ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/ermyth/src/connection.C
(Generate patch)

Comparing cvsroot/ermyth/src/connection.C (file contents):
Revision 1.3 by pippijn, Sat Jul 21 13:23:21 2007 UTC vs.
Revision 1.4 by pippijn, Tue Aug 28 17:08:12 2007 UTC

1/* 1/*
2 * connection.C: Connection and I/O management 2 * connection.C: Connection and I/O management
3 * Rights to this code are documented in doc/pod/license.pod. 3 * Rights to this code are documented in doc/pod/license.pod.
4 * 4 *
5 * Copyright © 2005-2007 Atheme Project (http://www.atheme.org) 5 * Copyright © 2005-2007 Atheme Project (http://www.atheme.org)
6 */ 6 */
7 7
8static char const rcsid[] = "$Id: connection.C,v 1.3 2007/07/21 13:23:21 pippijn Exp $"; 8static char const rcsid[] = "$Id: connection.C,v 1.4 2007/08/28 17:08:12 pippijn Exp $";
9 9
10#include "atheme.h" 10#include "atheme.h"
11#include "internal.h" 11#include "internal.h"
12#include "datastream.h" 12#include "datastream.h"
13 13
14#if 0 14connection_vector connlist;
15static BlockHeap *sa_heap; 15connection_t::callbacks connection_t::callback;
16static BlockHeap *connection_heap;
17#endif
18
19list_t connection_list;
20 16
21void 17void
22init_netio (void) 18init_netio (void)
23{ 19{
24#if 0 20#if 0
25 connection_heap = BlockHeapCreate (sizeof (connection_t), 16); 21 connection_heap = BlockHeapCreate (sizeof (connection_t), 16);
26 sa_heap = BlockHeapCreate (sizeof (struct sockaddr_in), 16); 22 sa_heap = BlockHeapCreate (sizeof (struct sockaddr_in), 16);
27
28 if (!connection_heap || !sa_heap)
29 {
30 slog (LG_INFO, "init_netio(): blockheap failure");
31 exit (EXIT_FAILURE);
32 }
33#endif 23#endif
34} 24}
35 25
36static int 26static int
37socket_setnonblocking (int sck) 27socket_setnonblocking (int sck)
59 * 49 *
60 * side effects: 50 * side effects:
61 * a connection is added to the socket queue. 51 * a connection is added to the socket queue.
62 */ 52 */
63connection_t * 53connection_t *
64connection_add (const char *name, int fd, unsigned int flags, void (*read_handler) (connection_t *), void (*write_handler) (connection_t *)) 54connection_add (char const * const name, int fd, unsigned int flags, void (*read_handler) (connection_t *), void (*write_handler) (connection_t *))
65{ 55{
66 connection_t *cptr; 56 connection_t *cptr;
67 57
68 if ((cptr = connection_find (fd))) 58 if ((cptr = connection_find (fd)))
69 { 59 {
70 slog (LG_DEBUG, "connection_add(): connection %d is already registered as %s", fd, cptr->name); 60 slog (LG_DEBUG, "connection_add(): connection %d is already registered as %s", fd, cptr->name);
71 return NULL; 61 return NULL;
72 } 62 }
73 63
74 slog (LG_DEBUG, "connection_add(): adding connection '%s', fd=%d", name, fd); 64 slog (LG_DEBUG, "connection_add(): adding connection '%s', fd = %d", name, fd);
75 65
76 cptr = new connection_t; 66 cptr = new connection_t;
77 67
78 cptr->fd = fd; 68 cptr->fd = fd;
79 cptr->pollslot = -1; 69 cptr->pollslot = -1;
92 getpeername (cptr->fd, &cptr->saddr, &cptr->saddr_size); 82 getpeername (cptr->fd, &cptr->saddr, &cptr->saddr_size);
93 cptr->sa = (struct sockaddr_in *) &cptr->saddr; 83 cptr->sa = (struct sockaddr_in *) &cptr->saddr;
94 84
95 inet_ntop (AF_INET, &cptr->sa->sin_addr, cptr->hbuf, BUFSIZE); 85 inet_ntop (AF_INET, &cptr->sa->sin_addr, cptr->hbuf, BUFSIZE);
96 86
97 node_add (cptr, node_create (), &connection_list); 87 connlist.insert (cptr);
98 88
99 return cptr; 89 return cptr;
100} 90}
101 91
102/* 92/*
113 */ 103 */
114connection_t * 104connection_t *
115connection_find (int fd) 105connection_find (int fd)
116{ 106{
117 connection_t *cptr; 107 connection_t *cptr;
118 node_t *nptr; 108 connection_vector::iterator it = connlist.begin ();
109 connection_vector::iterator et = connlist.end ();
119 110
120 LIST_FOREACH (nptr, connection_list.head) 111 while (it != et)
121 { 112 {
122 cptr = static_cast<connection_t *> (nptr->data); 113 cptr = *it;
123 114
124 if (cptr->fd == fd) 115 if (cptr->fd == fd)
125 return cptr; 116 return cptr;
117
118 ++it;
126 } 119 }
127 120
128 return NULL; 121 return NULL;
129} 122}
130 123
131/* 124/*
141 * none 134 * none
142 */ 135 */
143int 136int
144connection_count (void) 137connection_count (void)
145{ 138{
146 return LIST_LENGTH (&connection_list); 139 return connlist.size ();
147} 140}
148 141
149/* 142/*
150 * connection_close() 143 * connection_close()
151 * 144 *
159 * the connection is closed. 152 * the connection is closed.
160 */ 153 */
161void 154void
162connection_close (connection_t *cptr) 155connection_close (connection_t *cptr)
163{ 156{
164 node_t *nptr; 157 connection_vector::iterator it;
165 int errno1, errno2; 158 int errno1, errno2;
166#ifdef SO_ERROR 159#ifdef SO_ERROR
167 socklen_t len = sizeof (errno2); 160 socklen_t len = sizeof (errno2);
168#endif 161#endif
169 162
170 if (!cptr) 163 it = connlist.find (cptr);
171 { 164 if (it == connlist.end ())
172 slog (LG_DEBUG, "connection_close(): no connection to close!");
173 return;
174 }
175
176 nptr = node_find (cptr, &connection_list);
177 if (!nptr)
178 { 165 {
179 slog (LG_DEBUG, "connection_close(): connection %p is not registered!", cptr); 166 slog (LG_DEBUG, "connection_close(): connection %p is not registered!", cptr);
180 return; 167 return;
181 } 168 }
182 169
183 errno1 = errno; 170 errno1 = errno;
184#ifdef SO_ERROR 171#ifdef SO_ERROR
185 if (!getsockopt (cptr->fd, SOL_SOCKET, SO_ERROR, (char *) &errno2, (socklen_t *) & len)) 172 if (!getsockopt (cptr->fd, SOL_SOCKET, SO_ERROR, (char *) &errno2, (socklen_t *) &len))
186 { 173 {
187 if (errno2 != 0) 174 if (errno2 != 0)
188 errno1 = errno2; 175 errno1 = errno2;
189 } 176 }
190#endif 177#endif
196 cptr->close_handler (cptr); 183 cptr->close_handler (cptr);
197 184
198 /* close the fd */ 185 /* close the fd */
199 close (cptr->fd); 186 close (cptr->fd);
200 187
201 node_del (nptr, &connection_list); 188 connlist.erase (cptr);
202 node_free (nptr);
203 189
204 sendqrecvq_free (cptr); 190 sendqrecvq_free (cptr);
205 191
206 delete cptr; 192 delete cptr;
207} 193}
229 * close_handler called 215 * close_handler called
230 */ 216 */
231void 217void
232connection_close_soon (connection_t *cptr) 218connection_close_soon (connection_t *cptr)
233{ 219{
234 if (cptr == NULL)
235 return;
236 cptr->flags |= CF_DEAD; 220 cptr->flags |= CF_DEAD;
237 /* these two cannot be NULL */ 221 /* these two cannot be NULL */
238 cptr->read_handler = empty_handler; 222 cptr->read_handler = empty_handler;
239 cptr->write_handler = empty_handler; 223 cptr->write_handler = empty_handler;
240 cptr->recvq_handler = NULL; 224 cptr->recvq_handler = NULL;
258 * for all connections accepted on this listener 242 * for all connections accepted on this listener
259 */ 243 */
260void 244void
261connection_close_soon_children (connection_t *cptr) 245connection_close_soon_children (connection_t *cptr)
262{ 246{
263 node_t *n; 247 connection_vector::iterator it = connlist.begin ();
248 connection_vector::iterator et = connlist.end ();
264 connection_t *cptr2; 249 connection_t *cptr2;
265 250
266 if (cptr == NULL) 251 return_if_fail (cptr != NULL);
267 return;
268 252
269 if (CF_IS_LISTENING (cptr)) 253 if (CF_IS_LISTENING (cptr))
270 { 254 {
271 LIST_FOREACH (n, connection_list.head) 255 while (it != et)
272 { 256 {
273 cptr2 = static_cast<connection_t *> (n->data); 257 cptr2 = *it;
274 if (cptr2->listener == cptr) 258 if (cptr2->listener == cptr)
275 connection_close_soon (cptr2); 259 connection_close_soon (cptr2);
260 ++it;
276 } 261 }
277 } 262 }
263
278 connection_close_soon (cptr); 264 connection_close_soon (cptr);
279} 265}
280 266
281/* 267/*
282 * connection_close_all() 268 * connection_close_all()
291 * connection_close() called on all registered connections 277 * connection_close() called on all registered connections
292 */ 278 */
293void 279void
294connection_close_all (void) 280connection_close_all (void)
295{ 281{
296 node_t *n, *tn; 282 while (!connlist.empty ())
297 connection_t *cptr;
298
299 LIST_FOREACH_SAFE (n, tn, connection_list.head)
300 {
301 cptr = static_cast<connection_t *> (n->data);
302 connection_close (cptr); 283 connection_close (connlist.back ());
303 }
304} 284}
305 285
306/* 286/*
307 * connection_open_tcp() 287 * connection_open_tcp()
308 * 288 *
316 * side effects: 296 * side effects:
317 * a TCP/IP connection is opened to the host, 297 * a TCP/IP connection is opened to the host,
318 * and interest is registered in read/write events. 298 * and interest is registered in read/write events.
319 */ 299 */
320connection_t * 300connection_t *
321connection_open_tcp (char *host, char *vhost, unsigned int port, void (*read_handler) (connection_t *), void (*write_handler) (connection_t *)) 301connection_open_tcp (char const * const host, char const * const vhost, unsigned int port, void (*read_handler) (connection_t *), void (*write_handler) (connection_t *))
322{ 302{
323 connection_t *cptr; 303 connection_t *cptr;
324 char buf[BUFSIZE]; 304 char buf[BUFSIZE];
325 struct hostent *hp; 305 struct hostent *hp;
326 struct sockaddr_in sa; 306 struct sockaddr_in sa;
333 slog (LG_ERROR, "connection_open_tcp(): unable to create socket."); 313 slog (LG_ERROR, "connection_open_tcp(): unable to create socket.");
334 return NULL; 314 return NULL;
335 } 315 }
336 316
337 /* Has the highest fd gotten any higher yet? */ 317 /* Has the highest fd gotten any higher yet? */
338 if (s > claro_state.maxfd) 318 if (s > system_state.maxfd)
339 claro_state.maxfd = s; 319 system_state.maxfd = s;
340 320
341 snprintf (buf, BUFSIZE, "tcp connection: %s", host); 321 snprintf (buf, BUFSIZE, "tcp connection: %s", host);
342 322
343 if (vhost) 323 if (vhost)
344 { 324 {
407 * side effects: 387 * side effects:
408 * a TCP/IP connection is opened to the host, 388 * a TCP/IP connection is opened to the host,
409 * and interest is registered in read/write events. 389 * and interest is registered in read/write events.
410 */ 390 */
411connection_t * 391connection_t *
412connection_open_listener_tcp (char *host, unsigned int port, void (*read_handler) (connection_t *)) 392connection_open_listener_tcp (char const * const host, unsigned int port, void (*read_handler) (connection_t *))
413{ 393{
414 connection_t *cptr; 394 connection_t *cptr;
415 char buf[BUFSIZE]; 395 char buf[BUFSIZE];
416 struct hostent *hp; 396 struct hostent *hp;
417 struct sockaddr_in sa; 397 struct sockaddr_in sa;
424 slog (LG_ERROR, "connection_open_listener_tcp(): unable to create socket."); 404 slog (LG_ERROR, "connection_open_listener_tcp(): unable to create socket.");
425 return NULL; 405 return NULL;
426 } 406 }
427 407
428 /* Has the highest fd gotten any higher yet? */ 408 /* Has the highest fd gotten any higher yet? */
429 if (s > claro_state.maxfd) 409 if (s > system_state.maxfd)
430 claro_state.maxfd = s; 410 system_state.maxfd = s;
431 411
432 snprintf (buf, BUFSIZE, "listener: %s[%d]", host, port); 412 snprintf (buf, BUFSIZE, "listener: %s[%d]", host, port);
433 413
434 memset (&sa, 0, sizeof (sa)); 414 memset (&sa, 0, sizeof (sa));
435 sa.sin_family = AF_INET; 415 sa.sin_family = AF_INET;
496 slog (LG_INFO, "connection_accept_tcp(): accept failed"); 476 slog (LG_INFO, "connection_accept_tcp(): accept failed");
497 return NULL; 477 return NULL;
498 } 478 }
499 479
500 /* Has the highest fd gotten any higher yet? */ 480 /* Has the highest fd gotten any higher yet? */
501 if (s > claro_state.maxfd) 481 if (s > system_state.maxfd)
502 claro_state.maxfd = s; 482 system_state.maxfd = s;
503 483
504 socket_setnonblocking (s); 484 socket_setnonblocking (s);
505 485
506 strlcpy (buf, "incoming connection", BUFSIZE); 486 strlcpy (buf, "incoming connection", BUFSIZE);
507 newptr = connection_add (buf, s, 0, read_handler, write_handler); 487 newptr = connection_add (buf, s, 0, read_handler, write_handler);
540 * 520 *
541 * side effects: 521 * side effects:
542 * callback function is called with a series of lines 522 * callback function is called with a series of lines
543 */ 523 */
544void 524void
545connection_stats (void (*stats_cb) (const char *, void *), void *privdata) 525connection_stats (void (*stats_cb) (char const * const , void *), void *privdata)
546{ 526{
547 node_t *n;
548 char buf[160]; 527 char buf[160];
549 char buf2[20]; 528 char buf2[20];
529 connection_vector::iterator it = connlist.begin ();
530 connection_vector::iterator et = connlist.end ();
550 531
551 LIST_FOREACH (n, connection_list.head) 532 while (it != et)
552 { 533 {
553 connection_t *c = (connection_t *) n->data; 534 connection_t *c = *it;
554 535
555 snprintf (buf, sizeof buf, "fd %-3d desc '%s'", c->fd, c->flags & CF_UPLINK ? "uplink" : c->flags & CF_LISTENING ? "listener" : "misc"); 536 snprintf (buf, sizeof buf, "fd %-3d desc '%s'", c->fd, c->flags & CF_UPLINK ? "uplink" : c->flags & CF_LISTENING ? "listener" : "misc");
556 if (c->listener != NULL) 537 if (c->listener != NULL)
557 { 538 {
558 snprintf (buf2, sizeof buf2, " listener %d", c->listener->fd); 539 snprintf (buf2, sizeof buf2, " listener %d", c->listener->fd);
559 strlcat (buf, buf2, sizeof buf); 540 strlcat (buf, buf2, sizeof buf);
560 } 541 }
561 if (c->flags & (CF_CONNECTING | CF_DEAD | CF_NONEWLINE | CF_SEND_EOF | CF_SEND_DEAD)) 542 if (c->flags & (CF_CONNECTING | CF_DEAD | CF_NONEWLINE | CF_SEND_EOF | CF_SEND_DEAD))
562 { 543 {
563 strlcat (buf, " status", sizeof buf); 544 strlcat (buf, " status", sizeof buf);
564 if (c->flags & CF_CONNECTING) 545 if (c->flags & CF_CONNECTING)
565 strlcat (buf, " connecting", sizeof buf); 546 strlcat (buf, " connecting", sizeof buf);
566 if (c->flags & CF_DEAD) 547 if (c->flags & CF_DEAD)
567 strlcat (buf, " dead", sizeof buf); 548 strlcat (buf, " dead", sizeof buf);
568 if (c->flags & CF_NONEWLINE) 549 if (c->flags & CF_NONEWLINE)
569 strlcat (buf, " nonewline", sizeof buf); 550 strlcat (buf, " nonewline", sizeof buf);
570 if (c->flags & CF_SEND_DEAD) 551 if (c->flags & CF_SEND_DEAD)
571 strlcat (buf, " send_dead", sizeof buf); 552 strlcat (buf, " send_dead", sizeof buf);
572 else if (c->flags & CF_SEND_EOF) 553 else if (c->flags & CF_SEND_EOF)
573 strlcat (buf, " send_eof", sizeof buf); 554 strlcat (buf, " send_eof", sizeof buf);
574 } 555 }
575 stats_cb (buf, privdata); 556 stats_cb (buf, privdata);
557
558 ++it;
576 } 559 }
577} 560}
578 561
579/* 562/*
580 * connection_write() 563 * connection_write()
581 * 564 *
622void 605void
623connection_write_raw (connection_t *to, char *data) 606connection_write_raw (connection_t *to, char *data)
624{ 607{
625 sendq_add (to, data, strlen (data)); 608 sendq_add (to, data, strlen (data));
626} 609}
627
628/* vim:cinoptions=>s,e0,n0,f0,{0,}0,^0,=s,ps,t0,c3,+s,(2s,us,)20,*30,gs,hs
629 * vim:ts=8
630 * vim:sw=8
631 * vim:noexpandtab
632 */

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines