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.2 $
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 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 #include "sk.h"
34 #include "stubs.h"
35 #include "memwrap.h"
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 wr_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 Author:
108 marek
109
110 Side Effects:
111 broken connections get registered in the connection structure
112
113 +html+ </PRE>
114
115 ++++++++++++++++++++++++++++++++++++++*/
116 int SK_cd_puts(sk_conn_st *condat, const char *str)
/* [<][>][^][v][top][bottom][index][help] */
117 {
118 int res;
119
120 if( condat->rtc != 0 ) {
121 return (-condat->rtc);
122 }
123
124 res = SK_puts(condat->sock, str);
125
126 if( res < 0 ){
127 /* set the corresponding rtc flag */
128 condat->rtc |= (-res);
129
130 switch( - res ) {
131 /* dont know what to do and how to log */
132 case SK_DISCONNECT:
133 case SK_INTERRUPT:
134 /*("Thread received a control-c\n");*/
135 case SK_TIMEOUT:
136 /*("Reading timed out\n");*/
137 break;
138 default:
139 /* unexpected error code. bail out */
140 die;
141 }
142 }
143 return res;
144 } /* SK_cd_puts() */
145
146 /* SK_cd_gets() */
147 /*++++++++++++++++++++++++++++++++++++++
148
149 Read from a socket, until a linefeed character is received or the buffer
150 fills up to the maximum size "count". If the connection data has non-zero
151 timeout value for reading, it is used here between calls to read
152 the next 1 character.
153
154 int SK_cd_gets Returns the total_count of bytes read,
155 or inverted error codes (negative numbers):
156 (- SK_DISCONNECT) on broken connection,
157 (- SK_TIMEOUT) on timeout.
158
159 sk_conn_st *condat connection data
160
161 char *str The buffer to store the data received from
162 the socket.
163
164 size_t count size of the buffer.
165
166 More:
167 if the connection structure has bad status for this connection
168 from previous calls, no read will be attempted.
169
170 +html+ <PRE>
171 Author:
172 marek
173
174 Side Effects:
175 broken connections get registered in the connection structure.
176
177 +html+ </PRE>
178
179 ++++++++++++++++++++++++++++++++++++++*/
180 int SK_cd_gets(sk_conn_st *condat, char *str, size_t count)
/* [<][>][^][v][top][bottom][index][help] */
181 {
182 fd_set rset;
183 struct timeval *ptm = & condat->rd_timeout;
184 int readcount = 0;
185
186 memset( str, 0, count);
187 /* leave space for \0 */
188 count--;
189
190 FD_ZERO( &rset );
191 FD_SET( condat->sock, &rset );
192
193 if( ptm->tv_sec == 0 && ptm->tv_usec == 0) { /* if timeout undefined,
194 do blocking I/O */
195 ptm = NULL;
196 }
197
198 do {
199 char buf[2];
200 int sel = select( (condat->sock)+1, &rset, NULL, NULL, ptm);
201 int ern = errno;
202
203 dieif(sel < 0); /* we don't expect problems */
204
205 if( sel == 0 ) {
206 condat->rtc |= SK_TIMEOUT;
207 break;
208 }
209
210 else {
211 if(read( condat->sock, buf, 1) == 0 ) {
212 condat->rtc |= SK_DISCONNECT;
213 break;
214 }
215 str[readcount] = buf[0];
216 readcount++;
217 if( buf[0] == '\n' ) {
218 break;
219 }
220 }
221 } while( readcount < count );
222
223 return readcount;
224
225 } /* SK_cd_gets() */
226
227
228 /*++++++++++++++++++++++++++++++++++++++
229 Wrapper around the close(2) system call,
230
231 int SK_cd_close returns the error codes of close(2).
232
233 sk_conn_st *condat Pointer to the connection data structure.
234
235 +html+ <PRE>
236 Author:
237 marek
238 +html+ </PRE>
239 ++++++++++++++++++++++++++++++++++++++*/
240 int SK_cd_close(sk_conn_st *condat) {
/* [<][>][^][v][top][bottom][index][help] */
241 return SK_close(condat->sock);
242 } /* SK_cd_close() */
243
244
245 /* SK_cd_printf() */
246 /*++++++++++++++++++++++++++++++++++++++
247
248 Printf-like function to print to socket/file specified by connection
249 data structure. First writes the text to a temporary buffer, then
250 uses SK_cd_puts to print it. Maintains a 2K static buffer, and allocates
251 more memory if this is not enough.
252
253 int SK_cd_printf Returns the SK_cd_puts error code/return value.
254
255 sk_conn_st *condat Pointer to the connection data structure.
256
257 char *txt Format text to be written
258
259 ... more arguments (like printf)
260
261
262 +html+ <PRE>
263 Author:
264 marek
265 +html+ </PRE>
266 ++++++++++++++++++++++++++++++++++++++*/
267 int SK_cd_printf(sk_conn_st *condat, char *txt, ...)
/* [<][>][^][v][top][bottom][index][help] */
268 {
269 #define SKBUFLEN 2047
270 va_list ap;
271 char buffer[SKBUFLEN+1];
272 unsigned len;
273 char *newbuf = NULL;
274 char *finalbuf = buffer; /* points to where the text REALLY is */
275
276 /* vsnprintf returns the number of character it WOULD write if it could.
277 So we assume the buffer to be of adequate size for most cases,
278 and if it isn't, then we allocate to newbuf and call v*printf again
279 */
280 va_start(ap, txt);
281 len = vsnprintf(buffer, SKBUFLEN, txt, ap);
282 va_end(ap);
283
284 if( len > SKBUFLEN ) {
285 dieif(!NOERR(wr_malloc( (void **)& newbuf, len+1)));
286
287 va_start(ap, txt);
288 vsnprintf(newbuf, len, txt, ap);
289 va_end(ap);
290
291 finalbuf = newbuf;
292 }
293 /* terminate */
294 finalbuf[len] = 0;
295
296 /* reuse len */
297 len = SK_cd_puts(condat, finalbuf);
298
299 if(newbuf != NULL) {
300 wr_free(newbuf);
301 }
302
303 return len;
304 } /* SK_cd_printf() */