modules/sk/cd_socket.c
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- SK_cd_make
- SK_cd_free
- SK_cd_puts
- SK_cd_gets
- SK_cd_close
- SK_cd_printf
1 /***************************************
2 $Revision: 1.6 $
3
4 Socket module - cd_socket.c - basic read/write socket routines defined
5 in terms of connection data structures
6 with timeouts and storing information about
7 broken connections.
8
9 Status: NOT REVUED, TESTED
10
11 Design and implementation by Marek Bukowy.
12
13 ******************/ /******************
14 Copyright (c) 1999,2000,2001,2002 RIPE NCC
15
16 All Rights Reserved
17
18 Permission to use, copy, modify, and distribute this software and its
19 documentation for any purpose and without fee is hereby granted,
20 provided that the above copyright notice appear in all copies and that
21 both that copyright notice and this permission notice appear in
22 supporting documentation, and that the name of the author not be
23 used in advertising or publicity pertaining to distribution of the
24 software without specific, written prior permission.
25
26 THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
27 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
28 AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
29 DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
30 AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
31 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
32 ***************************************/
33
34 #include "rip.h"
35
36 /*+
37 * -------------------------------------------------------------------
38 * CD (connection data structure) varieties of the functions:
39 * broken connections get registered in the connection structure
40 * as side effects.
41 * by marek
42 * -----------------------------------------------------------------
43 +*/
44
45 /* SK_cd_make */
46 /*++++++++++++++++++++++++++++++++++++++
47
48 Construct a connection data given the socket or file descriptor.
49 Also performs the getpeername check and stores the IP in an allocated
50 string.
51
52 sk_conn_st *condat pointer to where the data is to be stored.
53
54 int sock The socket or file descriptor.
55
56 unsigned timeout Read timeout (used in SK_cd_gets) in seconds.
57 Value of 0 disables the timeout.
58 ++++++++++++++++++++++++++++++++++++++*/
59 void SK_cd_make(sk_conn_st *condat, int sock, unsigned timeout)
/* [<][>][^][v][top][bottom][index][help] */
60 {
61 memset(condat, 0, sizeof(sk_conn_st));
62
63 condat->sock = sock;
64
65 condat->ip = SK_getpeername(sock);
66 dieif(condat->ip == NULL);
67
68 SK_getpeerip(sock, &(condat->rIP));
69 condat->eIP = condat->rIP;
70
71 condat->rd_timeout.tv_sec = timeout;
72 }
73
74
75 /*++++++++++++++++++++++++++++++++++++++
76 Destroys the data allocated and anchored by the connection data structure.
77
78 sk_conn_st *condat Pointer to the connection data structure.
79
80 ++++++++++++++++++++++++++++++++++++++*/
81 void SK_cd_free(sk_conn_st *condat)
/* [<][>][^][v][top][bottom][index][help] */
82 {
83 UT_free(condat->ip);
84 }
85
86 /* SK_cd_puts() */
87 /*++++++++++++++++++++++++++++++++++++++
88
89 This function writes a character string out to a socket, unless
90 the connection is broken.
91
92 int SK_cd_puts Returns the total_count of bytes written,
93 or inverted error codes (negative numbers):
94 (- SK_DISCONNECT) on broken connection,
95 (- SK_INTERRUPT) on control-c received,
96 (- SK_TIMEOUT) on timeout.
97
98 sk_conn_st *condat Pointer to the connection data structure.
99
100 char *str The buffer to be written to the socket.
101
102 More:
103 if the connection structure has bad status for this connection
104 from previous calls, no write will be attempted.
105
106 +html+ <PRE>
107
108 Side Effects:
109 broken connections get registered in the connection structure
110
111 +html+ </PRE>
112
113 ++++++++++++++++++++++++++++++++++++++*/
114 int SK_cd_puts(sk_conn_st *condat, const char *str)
/* [<][>][^][v][top][bottom][index][help] */
115 {
116 int res;
117 struct timeval *ptm;
118
119 /* if we're not connected, return our status */
120 if (condat->rtc != 0) {
121 return (-condat->rtc);
122 }
123
124 /* bad design to use 0 to mean "infinity", but we'll keep it because
125 that's the current implementation - shane */
126 ptm = &condat->rd_timeout;
127 if ((ptm->tv_sec == 0) && (ptm->tv_usec == 0)) { /* if timeout 0,
128 do blocking I/O */
129 ptm = NULL;
130 }
131
132 /* use SK_puts() to do the actual work */
133 res = SK_puts(condat->sock, str, ptm);
134
135 /* if timed out (or some other error), then set the rtc variable */
136 if (res < 0) {
137 condat->rtc |= SK_DISCONNECT;
138 res = -SK_DISCONNECT;
139 }
140
141 /* return documented value */
142 return res;
143 } /* SK_cd_puts() */
144
145 /* SK_cd_gets() */
146 /*++++++++++++++++++++++++++++++++++++++
147
148 Read from a socket, until a linefeed character is received or the buffer
149 fills up to the maximum size "count". If the connection data has non-zero
150 timeout value for reading, it is used here between calls to read
151 the next 1 character.
152
153 int SK_cd_gets Returns the total_count of bytes read,
154 or inverted error codes (negative numbers):
155 (- SK_DISCONNECT) on broken connection,
156 (- SK_TIMEOUT) on timeout.
157
158 sk_conn_st *condat connection data
159
160 char *str The buffer to store the data received from
161 the socket.
162
163 size_t count size of the buffer.
164
165 More:
166 if the connection structure has bad status for this connection
167 from previous calls, no read will be attempted.
168
169 +html+ <PRE>
170 Author:
171 marek
172
173 Side Effects:
174 broken connections get registered in the connection structure.
175
176 +html+ </PRE>
177
178 ++++++++++++++++++++++++++++++++++++++*/
179 int SK_cd_gets(sk_conn_st *condat, char *str, size_t count)
/* [<][>][^][v][top][bottom][index][help] */
180 {
181 fd_set rset;
182 struct timeval *ptm = & condat->rd_timeout;
183 int readcount = 0;
184
185 memset( str, 0, count);
186 /* leave space for \0 */
187 count--;
188
189 FD_ZERO( &rset );
190 FD_SET( condat->sock, &rset );
191
192 if( ptm->tv_sec == 0 && ptm->tv_usec == 0) { /* if timeout undefined,
193 do blocking I/O */
194 ptm = NULL;
195 }
196
197 do {
198 char buf[2];
199 int sel = select( (condat->sock)+1, &rset, NULL, NULL, ptm);
200
201 if (sel < 0) {
202 /* unfortunate, but bad things happen to good sockets - SK */
203 ER_perror(FAC_SK, SK_SELECT, "(%d) %s", errno, strerror(errno));
204 break;
205 }
206
207 if( sel == 0 ) {
208 condat->rtc |= SK_TIMEOUT;
209 break;
210 }
211
212 else {
213 if(read( condat->sock, buf, 1) == 0 ) {
214 condat->rtc |= SK_DISCONNECT;
215 break;
216 }
217 str[readcount] = buf[0];
218 readcount++;
219 if( buf[0] == '\n' ) {
220 break;
221 }
222 }
223 } while( readcount < count );
224
225 return readcount;
226
227 } /* SK_cd_gets() */
228
229
230 /*++++++++++++++++++++++++++++++++++++++
231 Wrapper around the close(2) system call,
232
233 int SK_cd_close returns the error codes of close(2).
234
235 sk_conn_st *condat Pointer to the connection data structure.
236
237 +html+ <PRE>
238 Author:
239 marek
240 +html+ </PRE>
241 ++++++++++++++++++++++++++++++++++++++*/
242 int SK_cd_close(sk_conn_st *condat) {
/* [<][>][^][v][top][bottom][index][help] */
243 return SK_close(condat->sock);
244 } /* SK_cd_close() */
245
246
247 /* SK_cd_printf() */
248 /*++++++++++++++++++++++++++++++++++++++
249
250 Printf-like function to print to socket/file specified by connection
251 data structure. First writes the text to a temporary buffer, then
252 uses SK_cd_puts to print it. Maintains a 2K static buffer, and allocates
253 more memory if this is not enough.
254
255 int SK_cd_printf Returns the SK_cd_puts error code/return value.
256
257 sk_conn_st *condat Pointer to the connection data structure.
258
259 char *txt Format text to be written
260
261 ... more arguments (like printf)
262
263
264 +html+ <PRE>
265 Author:
266 marek
267 +html+ </PRE>
268 ++++++++++++++++++++++++++++++++++++++*/
269 int SK_cd_printf(sk_conn_st *condat, char *txt, ...)
/* [<][>][^][v][top][bottom][index][help] */
270 {
271 #define SKBUFLEN 2047
272 va_list ap;
273 char buffer[SKBUFLEN+1];
274 unsigned len;
275 char *newbuf = NULL;
276 char *finalbuf = buffer; /* points to where the text REALLY is */
277
278 /* vsnprintf returns the number of character it WOULD write if it could.
279 So we assume the buffer to be of adequate size for most cases,
280 and if it isn't, then we allocate to newbuf and call v*printf again
281 */
282 va_start(ap, txt);
283 len = vsnprintf(buffer, SKBUFLEN, txt, ap);
284 va_end(ap);
285
286 if( len > SKBUFLEN ) {
287 newbuf = (char *)UT_malloc(len+1);
288
289 va_start(ap, txt);
290 vsnprintf(newbuf, len, txt, ap);
291 va_end(ap);
292
293 finalbuf = newbuf;
294 }
295 /* terminate */
296 finalbuf[len] = 0;
297
298 /* reuse len */
299 len = SK_cd_puts(condat, finalbuf);
300
301 if(newbuf != NULL) {
302 UT_free(newbuf);
303 }
304
305 return len;
306 } /* SK_cd_printf() */