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

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

1/* 1/*
2 * poll.C: poll(2) socket engine. 2 * poll.C: poll(2) socket engine.
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: poll.C,v 1.3 2007/07/21 13:23:22 pippijn Exp $"; 8static char const rcsid[] = "$Id: poll.C,v 1.4 2007/08/28 17:08:12 pippijn Exp $";
9 9
10#include <sys/poll.h> 10#include <sys/poll.h>
11 11
12#include "atheme.h" 12#include "atheme.h"
13#include "internal.h" 13#include "internal.h"
14#include "datastream.h" 14#include "datastream.h"
15
16extern list_t connection_list; /* this lives in connection.c */
17 15
18/* 16/*
19 * linux does not provide POLLWRNORM by default, and we're not _XOPEN_SOURCE. 17 * linux does not provide POLLWRNORM by default, and we're not _XOPEN_SOURCE.
20 * so.... we have to do this crap below. 18 * so.... we have to do this crap below.
21 */ 19 */
24#endif 22#endif
25#ifndef POLLWRNORM 23#ifndef POLLWRNORM
26#define POLLWRNORM POLLOUT 24#define POLLWRNORM POLLOUT
27#endif 25#endif
28 26
29struct pollfd pollfds[FD_SETSIZE]; /* XXX We need a define indicating MAXCONN. */ 27pollfd pollfds[FD_SETSIZE]; /* XXX We need a define indicating MAXCONN. */
30 28
31/* 29/*
32 * init_socket_queues() 30 * init_socket_queues()
33 * 31 *
34 * inputs: 32 * inputs:
41 * when using select, we don't need to do anything here. 39 * when using select, we don't need to do anything here.
42 */ 40 */
43void 41void
44init_socket_queues (void) 42init_socket_queues (void)
45{ 43{
46 memset (&pollfds, 0, sizeof (struct pollfd) * FD_SETSIZE); 44 memset (&pollfds, 0, sizeof (pollfd) * FD_SETSIZE);
47} 45}
48 46
49/* 47/*
50 * update_poll_fds() 48 * update_poll_fds()
51 * 49 *
59 * registered sockets are prepared for the poll() loop. 57 * registered sockets are prepared for the poll() loop.
60 */ 58 */
61static void 59static void
62update_poll_fds (void) 60update_poll_fds (void)
63{ 61{
64 node_t *n; 62 connection_vector::iterator it = connlist.begin ();
65 connection_t *cptr; 63 connection_vector::iterator et = connlist.end ();
66 int slot = 0; 64 int slot = 0;
67 65
68 LIST_FOREACH (n, connection_list.head) 66 while (it != et)
69 { 67 {
70 cptr = static_cast<connection_t *> (n->data); 68 connection_t *cptr = *it;
71 69
72 cptr->pollslot = slot; 70 cptr->pollslot = slot;
73 71
74 if (CF_IS_CONNECTING (cptr) || sendq_nonempty (cptr)) 72 if (CF_IS_CONNECTING (cptr) || sendq_nonempty (cptr))
75 { 73 {
76 pollfds[slot].fd = cptr->fd; 74 pollfds[slot].fd = cptr->fd;
77 pollfds[slot].events |= POLLWRNORM; 75 pollfds[slot].events |= POLLWRNORM;
78 pollfds[slot].revents = 0; 76 pollfds[slot].revents = 0;
79 } 77 }
80 else 78 else
81 { 79 {
82 pollfds[slot].fd = cptr->fd; 80 pollfds[slot].fd = cptr->fd;
83 pollfds[slot].events |= POLLRDNORM; 81 pollfds[slot].events |= POLLRDNORM;
84 pollfds[slot].revents = 0; 82 pollfds[slot].revents = 0;
85 } 83 }
86 slot++; 84 slot++;
85 ++it;
87 } 86 }
88} 87}
89 88
90/* 89/*
91 * connection_select() 90 * connection_select()
92 * 91 *
101 */ 100 */
102void 101void
103connection_select (time_t delay) 102connection_select (time_t delay)
104{ 103{
105 int sr; 104 int sr;
106 node_t *n, *tn; 105 connection_vector::iterator it = connlist.begin ();
107 connection_t *cptr; 106 connection_vector::iterator et = connlist.end ();
108 int slot; 107 int slot;
109 108
110 update_poll_fds (); 109 update_poll_fds ();
111 110
112 if ((sr = poll (pollfds, connection_list.count, delay / 100)) > 0) 111 if ((sr = poll (pollfds, connlist.size (), delay / 100)) > 0)
113 { 112 {
114 /* Iterate twice, so we don't touch freed memory if 113 /* Iterate twice, so we don't touch freed memory if
115 * a connection is closed. 114 * a connection is closed.
116 * -- jilles */ 115 * -- jilles */
117 LIST_FOREACH_SAFE (n, tn, connection_list.head) 116 while (it != et)
118 { 117 {
119 cptr = static_cast<connection_t *> (n->data); 118 connection_t *cptr = *it;
119 ++it; // increment here or continue will cause an endless loop
120 slot = cptr->pollslot; 120 slot = cptr->pollslot;
121 121
122 if (pollfds[slot].revents == 0) 122 if (pollfds[slot].revents == 0)
123 continue; 123 continue;
124 124
125 if (pollfds[slot].revents & (POLLRDNORM | POLLIN | POLLHUP | POLLERR)) 125 if (pollfds[slot].revents & (POLLRDNORM | POLLIN | POLLHUP | POLLERR))
126 { 126 {
127 pollfds[slot].events &= ~(POLLRDNORM | POLLIN | POLLHUP | POLLERR); 127 pollfds[slot].events &= ~(POLLRDNORM | POLLIN | POLLHUP | POLLERR);
128 cptr->read_handler (cptr); 128 cptr->read_handler (cptr);
129 } 129 }
130 }
130 } 131
131 132 for (it = connlist.begin (), et = connlist.end (); it != et; ++it)
132 LIST_FOREACH_SAFE (n, tn, connection_list.head)
133 { 133 {
134 cptr = static_cast<connection_t *> (n->data); 134 connection_t *cptr = *it;
135 slot = cptr->pollslot; 135 slot = cptr->pollslot;
136 136
137 if (pollfds[slot].revents == 0) 137 if (pollfds[slot].revents == 0)
138 continue; 138 continue;
139 if (pollfds[slot].revents & (POLLWRNORM | POLLOUT | POLLHUP | POLLERR)) 139 if (pollfds[slot].revents & (POLLWRNORM | POLLOUT | POLLHUP | POLLERR))
140 { 140 {
141 pollfds[slot].events &= ~(POLLWRNORM | POLLOUT | POLLHUP | POLLERR); 141 pollfds[slot].events &= ~(POLLWRNORM | POLLOUT | POLLHUP | POLLERR);
142 if (CF_IS_CONNECTING (cptr)) 142 if (CF_IS_CONNECTING (cptr))
143 hook_call_event ("connected", cptr); 143 cptr->callback.connected (cptr);
144 else 144 else
145 cptr->write_handler (cptr); 145 cptr->write_handler (cptr);
146 } 146 }
147 }
147 } 148
148 149 for (it = connlist.begin (), et = connlist.end (); it != et; ++it)
149 LIST_FOREACH_SAFE (n, tn, connection_list.head)
150 { 150 {
151 cptr = static_cast<connection_t *> (n->data); 151 connection_t *cptr = *it;
152 if (cptr->flags & CF_DEAD) 152 if (cptr->flags & CF_DEAD)
153 connection_close (cptr); 153 connection_close (cptr);
154 } 154 }
155 } 155 }
156} 156}
157
158/* vim:cinoptions=>s,e0,n0,f0,{0,}0,^0,=s,ps,t0,c3,+s,(2s,us,)20,*30,gs,hs
159 * vim:ts=8
160 * vim:sw=8
161 * vim:noexpandtab
162 */

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines