1 /***********************************************************************
3 * event_tcp.c -- implementation of event-driven socket I/O.
5 * Copyright (C) 2001 Roaring Penguin Software Inc.
7 * This program may be distributed according to the terms of the GNU
8 * General Public License, version 2 or (at your option) any later version.
12 ***********************************************************************/
14 static char const RCSID
[] =
15 "$Id: event_tcp.c,v 1.1.48.1 2005/08/08 12:05:25 honor Exp $";
17 #include "event_tcp.h"
20 #include <sys/types.h>
25 static void free_state(EventTcpState
*state
);
27 typedef struct EventTcpConnectState_t
{
30 EventTcpConnectFunc f
;
32 } EventTcpConnectState
;
34 /**********************************************************************
35 * %FUNCTION: handle_accept
37 * es -- event selector
40 * data -- the accept callback function
44 * Calls accept; if a connection arrives, calls the accept callback
45 * function with connected descriptor
46 ***********************************************************************/
48 handle_accept(EventSelector
*es
,
56 EVENT_DEBUG(("tcp_handle_accept(es=%p, fd=%d, flags=%u, data=%p)\n", es
, fd
, flags
, data
));
57 conn
= accept(fd
, NULL
, NULL
);
59 f
= (EventTcpAcceptFunc
) data
;
64 /**********************************************************************
65 * %FUNCTION: handle_connect
67 * es -- event selector
70 * data -- the accept callback function
74 * Calls accept; if a connection arrives, calls the accept callback
75 * function with connected descriptor
76 ***********************************************************************/
78 handle_connect(EventSelector
*es
,
84 socklen_t len
= sizeof(error
);
85 EventTcpConnectState
*state
= (EventTcpConnectState
*) data
;
87 EVENT_DEBUG(("tcp_handle_connect(es=%p, fd=%d, flags=%u, data=%p)\n", es
, fd
, flags
, data
));
89 /* Cancel writable event */
90 Event_DelHandler(es
, state
->conn
);
94 if (flags
& EVENT_FLAG_TIMEOUT
) {
96 state
->f(es
, fd
, EVENT_TCP_FLAG_TIMEOUT
, state
->data
);
101 /* Check for pending error */
102 if (getsockopt(fd
, SOL_SOCKET
, SO_ERROR
, &error
, &len
) < 0) {
103 state
->f(es
, fd
, EVENT_TCP_FLAG_IOERROR
, state
->data
);
109 state
->f(es
, fd
, EVENT_TCP_FLAG_IOERROR
, state
->data
);
115 state
->f(es
, fd
, EVENT_TCP_FLAG_COMPLETE
, state
->data
);
119 /**********************************************************************
120 * %FUNCTION: EventTcp_CreateAcceptor
122 * es -- event selector
123 * socket -- listening socket
124 * f -- function to call when a connection is accepted
125 * data -- extra data to pass to f.
127 * An event handler on success, NULL on failure.
129 * Sets up an accepting socket and calls "f" whenever a new
130 * connection arrives.
131 ***********************************************************************/
133 EventTcp_CreateAcceptor(EventSelector
*es
,
135 EventTcpAcceptFunc f
)
139 EVENT_DEBUG(("EventTcp_CreateAcceptor(es=%p, socket=%d)\n", es
, socket
));
140 /* Make sure socket is non-blocking */
141 flags
= fcntl(socket
, F_GETFL
, 0);
145 if (fcntl(socket
, F_SETFL
, flags
| O_NONBLOCK
) == -1) {
149 return Event_AddHandler(es
, socket
, EVENT_FLAG_READABLE
,
150 handle_accept
, (void *) f
);
154 /**********************************************************************
155 * %FUNCTION: free_state
157 * state -- EventTcpState to free
161 * Frees all state associated with the TcpEvent.
162 ***********************************************************************/
164 free_state(EventTcpState
*state
)
167 EVENT_DEBUG(("tcp_free_state(state=%p)\n", state
));
168 if (state
->buf
) free(state
->buf
);
169 if (state
->eh
) Event_DelHandler(state
->es
, state
->eh
);
173 /**********************************************************************
174 * %FUNCTION: handle_readable
176 * es -- event selector
177 * fd -- the readable socket
179 * data -- the EventTcpState object
183 * Continues to fill buffer. Calls callback when done.
184 ***********************************************************************/
186 handle_readable(EventSelector
*es
,
191 EventTcpState
*state
= (EventTcpState
*) data
;
192 int done
= state
->cur
- state
->buf
;
193 int togo
= state
->len
- done
;
197 EVENT_DEBUG(("tcp_handle_readable(es=%p, fd=%d, flags=%u, data=%p)\n", es
, fd
, flags
, data
));
200 if (flags
& EVENT_FLAG_TIMEOUT
) {
202 (state
->f
)(es
, state
->socket
, state
->buf
, done
, EVENT_TCP_FLAG_TIMEOUT
,
207 if (state
->delim
< 0) {
208 /* Not looking for a delimiter */
209 /* togo had better not be zero here! */
210 nread
= read(fd
, state
->cur
, togo
);
212 /* Change connection reset to EOF if we have read at least
214 if (nread
< 0 && errno
== ECONNRESET
&& done
> 0) {
217 flag
= (nread
) ? EVENT_TCP_FLAG_IOERROR
: EVENT_TCP_FLAG_EOF
;
219 (state
->f
)(es
, state
->socket
, state
->buf
, done
, flag
, state
->data
);
225 if (done
>= state
->len
) {
227 (state
->f
)(es
, state
->socket
, state
->buf
, done
,
228 EVENT_TCP_FLAG_COMPLETE
, state
->data
);
233 /* Looking for a delimiter */
234 while ( (togo
> 0) && (nread
= read(fd
, state
->cur
, 1)) == 1) {
238 if (*(state
->cur
- 1) == state
->delim
) break;
242 /* Error or EOF -- check for EAGAIN */
243 if (nread
< 0 && errno
== EAGAIN
) return;
246 /* Some other error, or EOF, or delimiter, or read enough */
248 flag
= EVENT_TCP_FLAG_IOERROR
;
249 } else if (nread
== 0) {
250 flag
= EVENT_TCP_FLAG_EOF
;
252 flag
= EVENT_TCP_FLAG_COMPLETE
;
254 (state
->f
)(es
, state
->socket
, state
->buf
, done
, flag
, state
->data
);
260 /**********************************************************************
261 * %FUNCTION: handle_writeable
263 * es -- event selector
264 * fd -- the writeable socket
266 * data -- the EventTcpState object
270 * Continues to fill buffer. Calls callback when done.
271 ***********************************************************************/
273 handle_writeable(EventSelector
*es
,
278 EventTcpState
*state
= (EventTcpState
*) data
;
279 int done
= state
->cur
- state
->buf
;
280 int togo
= state
->len
- done
;
284 if (flags
& EVENT_FLAG_TIMEOUT
) {
287 (state
->f
)(es
, state
->socket
, state
->buf
, done
, EVENT_TCP_FLAG_TIMEOUT
,
296 /* togo had better not be zero here! */
297 n
= write(fd
, state
->cur
, togo
);
299 EVENT_DEBUG(("tcp_handle_writeable(es=%p, fd=%d, flags=%u, data=%p)\n", es
, fd
, flags
, data
));
303 (state
->f
)(es
, state
->socket
, state
->buf
, done
,
304 EVENT_TCP_FLAG_IOERROR
,
314 if (done
>= state
->len
) {
315 /* Written enough! */
317 (state
->f
)(es
, state
->socket
, state
->buf
, done
,
318 EVENT_TCP_FLAG_COMPLETE
, state
->data
);
328 /**********************************************************************
329 * %FUNCTION: EventTcp_ReadBuf
331 * es -- event selector
332 * socket -- socket to read from
333 * len -- maximum number of bytes to read
334 * delim -- delimiter at which to stop reading, or -1 if we should
335 * read exactly len bytes
336 * f -- function to call on EOF or when all bytes have been read
337 * timeout -- if non-zero, timeout in seconds after which we cancel
339 * data -- extra data to pass to function f.
341 * A new EventTcpState token or NULL on error
343 * Sets up a handler to fill a buffer from a socket.
344 ***********************************************************************/
346 EventTcp_ReadBuf(EventSelector
*es
,
350 EventTcpIOFinishedFunc f
,
354 EventTcpState
*state
;
358 EVENT_DEBUG(("EventTcp_ReadBuf(es=%p, socket=%d, len=%d, delim=%d, timeout=%d)\n", es
, socket
, len
, delim
, timeout
));
359 if (len
<= 0) return NULL
;
360 if (socket
< 0) return NULL
;
362 /* Make sure socket is non-blocking */
363 flags
= fcntl(socket
, F_GETFL
, 0);
367 if (fcntl(socket
, F_SETFL
, flags
| O_NONBLOCK
) == -1) {
371 state
= malloc(sizeof(EventTcpState
));
372 if (!state
) return NULL
;
374 memset(state
, 0, sizeof(EventTcpState
));
376 state
->socket
= socket
;
378 state
->buf
= malloc(len
);
384 state
->cur
= state
->buf
;
397 state
->eh
= Event_AddHandlerWithTimeout(es
, socket
, EVENT_FLAG_READABLE
,
405 state
->delim
= delim
;
406 EVENT_DEBUG(("EventTcp_ReadBuf() -> %p\n", state
));
411 /**********************************************************************
412 * %FUNCTION: EventTcp_WriteBuf
414 * es -- event selector
415 * socket -- socket to read from
416 * buf -- buffer to write
417 * len -- number of bytes to write
418 * f -- function to call on EOF or when all bytes have been read
419 * timeout -- timeout after which to cancel operation
420 * data -- extra data to pass to function f.
422 * A new EventTcpState token or NULL on error
424 * Sets up a handler to fill a buffer from a socket.
425 ***********************************************************************/
427 EventTcp_WriteBuf(EventSelector
*es
,
431 EventTcpIOFinishedFunc f
,
435 EventTcpState
*state
;
439 EVENT_DEBUG(("EventTcp_WriteBuf(es=%p, socket=%d, len=%d, timeout=%d)\n", es
, socket
, len
, timeout
));
440 if (len
<= 0) return NULL
;
441 if (socket
< 0) return NULL
;
443 /* Make sure socket is non-blocking */
444 flags
= fcntl(socket
, F_GETFL
, 0);
448 if (fcntl(socket
, F_SETFL
, flags
| O_NONBLOCK
) == -1) {
452 state
= malloc(sizeof(EventTcpState
));
453 if (!state
) return NULL
;
455 memset(state
, 0, sizeof(EventTcpState
));
457 state
->socket
= socket
;
459 state
->buf
= malloc(len
);
464 memcpy(state
->buf
, buf
, len
);
466 state
->cur
= state
->buf
;
479 state
->eh
= Event_AddHandlerWithTimeout(es
, socket
, EVENT_FLAG_WRITEABLE
,
489 EVENT_DEBUG(("EventTcp_WriteBuf() -> %p\n", state
));
493 /**********************************************************************
494 * %FUNCTION: EventTcp_Connect
496 * es -- event selector
497 * fd -- descriptor to connect
498 * addr -- address to connect to
499 * addrlen -- length of address
500 * f -- function to call with connected socket
501 * data -- extra data to pass to f
505 * Does a non-blocking connect on fd
506 ***********************************************************************/
508 EventTcp_Connect(EventSelector
*es
,
510 struct sockaddr
const *addr
,
512 EventTcpConnectFunc f
,
518 EventTcpConnectState
*state
;
521 /* Make sure socket is non-blocking */
522 flags
= fcntl(fd
, F_GETFL
, 0);
523 if (flags
== -1 || fcntl(fd
, F_SETFL
, flags
| O_NONBLOCK
) == -1) {
524 f(es
, fd
, EVENT_TCP_FLAG_IOERROR
, data
);
528 n
= connect(fd
, addr
, addrlen
);
530 if (errno
!= EINPROGRESS
) {
531 f(es
, fd
, EVENT_TCP_FLAG_IOERROR
, data
);
536 if (n
== 0) { /* Connect succeeded immediately */
537 f(es
, fd
, EVENT_TCP_FLAG_COMPLETE
, data
);
541 state
= malloc(sizeof(*state
));
543 f(es
, fd
, EVENT_TCP_FLAG_IOERROR
, data
);
558 state
->conn
= Event_AddHandlerWithTimeout(es
, fd
, EVENT_FLAG_WRITEABLE
,
563 f(es
, fd
, EVENT_TCP_FLAG_IOERROR
, data
);
568 /**********************************************************************
569 * %FUNCTION: EventTcp_CancelPending
571 * s -- an EventTcpState
575 * Cancels the pending event handler
576 ***********************************************************************/
578 EventTcp_CancelPending(EventTcpState
*s
)