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.1 $
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 FD_ZERO( &rset );
188 FD_SET( condat->sock, &rset );
189
190 if( ptm->tv_sec == 0 && ptm->tv_usec == 0) { /* if timeout undefined,
191 do blocking I/O */
192 ptm = NULL;
193 }
194
195 do {
196 char buf[2];
197 int sel = select( (condat->sock)+1, &rset, NULL, NULL, ptm);
198 int ern = errno;
199
200 dieif(sel < 0); /* we don't expect problems */
201
202 if( sel == 0 ) {
203 condat->rtc |= SK_TIMEOUT;
204 break;
205 }
206
207 else {
208 if(read( condat->sock, buf, 1) == 0 ) {
209 condat->rtc |= SK_DISCONNECT;
210 break;
211 }
212 str[readcount] = buf[0];
213 readcount++;
214 if( buf[0] == '\n' ) {
215 break;
216 }
217 }
218 } while( readcount < count );
219
220 return readcount;
221
222 } /* SK_cd_gets() */
223
224
225 /*++++++++++++++++++++++++++++++++++++++
226 Wrapper around the close(2) system call,
227
228 int SK_cd_close returns the error codes of close(2).
229
230 sk_conn_st *condat Pointer to the connection data structure.
231
232 +html+ <PRE>
233 Author:
234 marek
235 +html+ </PRE>
236 ++++++++++++++++++++++++++++++++++++++*/
237 int SK_cd_close(sk_conn_st *condat) {
/* [<][>][^][v][top][bottom][index][help] */
238 return SK_close(condat->sock);
239 } /* SK_cd_close() */
240
241
242 /* SK_cd_printf() */
243 /*++++++++++++++++++++++++++++++++++++++
244
245 Printf-like function to print to socket/file specified by connection
246 data structure. First writes the text to a temporary buffer, then
247 uses SK_cd_puts to print it. Maintains a 2K static buffer, and allocates
248 more memory if this is not enough.
249
250 int SK_cd_printf Returns the SK_cd_puts error code/return value.
251
252 sk_conn_st *condat Pointer to the connection data structure.
253
254 char *txt Format text to be written
255
256 ... more arguments (like printf)
257
258
259 +html+ <PRE>
260 Author:
261 marek
262 +html+ </PRE>
263 ++++++++++++++++++++++++++++++++++++++*/
264 int SK_cd_printf(sk_conn_st *condat, char *txt, ...)
/* [<][>][^][v][top][bottom][index][help] */
265 {
266 #define SKBUFLEN 2047
267 va_list ap;
268 char buffer[SKBUFLEN+1];
269 unsigned len;
270 char *newbuf = NULL;
271 char *finalbuf = buffer; /* points to where the text REALLY is */
272
273 /* vsnprintf returns the number of character it WOULD write if it could.
274 So we assume the buffer to be of adequate size for most cases,
275 and if it isn't, then we allocate to newbuf and call v*printf again
276 */
277 va_start(ap, txt);
278 len = vsnprintf(buffer, SKBUFLEN, txt, ap);
279 va_end(ap);
280
281 if( len > SKBUFLEN ) {
282 dieif(!NOERR(wr_malloc( (void **)& newbuf, len+1)));
283
284 va_start(ap, txt);
285 vsnprintf(newbuf, len, txt, ap);
286 va_end(ap);
287
288 finalbuf = newbuf;
289 }
290 /* terminate */
291 finalbuf[len] = 0;
292
293 /* reuse len */
294 len = SK_cd_puts(condat, finalbuf);
295
296 if(newbuf != NULL) {
297 wr_free(newbuf);
298 }
299
300 return len;
301 } /* SK_cd_printf() */