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