ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/ermyth/src/poll.C
Revision: 1.7
Committed: Sun Sep 16 18:54:45 2007 UTC (16 years, 8 months ago) by pippijn
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.6: +7 -2 lines
Log Message:
#defines to enum

File Contents

# Content
1 /*
2 * poll.C: poll(2) socket engine.
3 *
4 * Copyright © 2007 Pippijn van Steenhoven / The Ermyth Team
5 * Rights to this code are as documented in COPYING.
6 *
7 *
8 * Portions of this file were derived from sources bearing the following license:
9 * Rights to this code are documented in doc/pod/license.pod.
10 * Copyright © 2005-2007 Atheme Project (http://www.atheme.org)
11 */
12
13 static char const rcsid[] = "$Id: poll.C,v 1.6 2007-09-05 11:23:15 pippijn Exp $";
14
15 #include <sys/poll.h>
16
17 #include "atheme.h"
18 #include "internal.h"
19 #include "datastream.h"
20 #include "connection.h"
21
22 /*
23 * linux does not provide POLLWRNORM by default, and we're not _XOPEN_SOURCE.
24 * so.... we have to do this crap below.
25 */
26 #ifndef POLLRDNORM
27 #define POLLRDNORM POLLIN
28 #endif
29 #ifndef POLLWRNORM
30 #define POLLWRNORM POLLOUT
31 #endif
32
33 pollfd pollfds[FD_SETSIZE]; /* XXX We need a define indicating MAXCONN. */
34
35 /*
36 * init_socket_queues()
37 *
38 * inputs:
39 * none
40 *
41 * outputs:
42 * none
43 *
44 * side effects:
45 * when using select, we don't need to do anything here.
46 */
47 void
48 init_socket_queues (void)
49 {
50 memset (&pollfds, 0, sizeof (pollfd) * FD_SETSIZE);
51 }
52
53 /*
54 * update_poll_fds()
55 *
56 * inputs:
57 * none
58 *
59 * outputs:
60 * none
61 *
62 * side effects:
63 * registered sockets are prepared for the poll() loop.
64 */
65 static void
66 update_poll_fds (void)
67 {
68 connection_t::list_type::iterator it = connection_t::list.begin ();
69 connection_t::list_type::iterator et = connection_t::list.end ();
70 int slot = 0;
71
72 while (it != et)
73 {
74 connection_t *cptr = *it;
75
76 cptr->pollslot = slot;
77
78 if (cptr->is_connecting () || sendq_nonempty (cptr))
79 {
80 pollfds[slot].fd = cptr->fd;
81 pollfds[slot].events |= POLLWRNORM;
82 pollfds[slot].revents = 0;
83 }
84 else
85 {
86 pollfds[slot].fd = cptr->fd;
87 pollfds[slot].events |= POLLRDNORM;
88 pollfds[slot].revents = 0;
89 }
90 slot++;
91 ++it;
92 }
93 }
94
95 /*
96 * connection_t::select()
97 *
98 * inputs:
99 * delay in microseconds
100 *
101 * outputs:
102 * none
103 *
104 * side effects:
105 * registered sockets and their associated handlers are acted on.
106 */
107 void
108 connection_t::select (time_t delay)
109 {
110 int sr;
111 connection_t::list_type::iterator it = connection_t::list.begin ();
112 connection_t::list_type::iterator et = connection_t::list.end ();
113 int slot;
114
115 update_poll_fds ();
116
117 if ((sr = poll (pollfds, connection_t::list.size (), delay / 100)) > 0)
118 {
119 /* Iterate twice, so we don't touch freed memory if
120 * a connection is closed.
121 * -- jilles */
122 while (it != et)
123 {
124 connection_t *cptr = *it;
125 ++it; // increment here or continue will cause an endless loop
126 slot = cptr->pollslot;
127
128 if (pollfds[slot].revents == 0)
129 continue;
130
131 if (pollfds[slot].revents & (POLLRDNORM | POLLIN | POLLHUP | POLLERR))
132 {
133 pollfds[slot].events &= ~(POLLRDNORM | POLLIN | POLLHUP | POLLERR);
134 cptr->read_handler (cptr);
135 }
136 }
137
138 for (it = connection_t::list.begin (), et = connection_t::list.end (); it != et; ++it)
139 {
140 connection_t *cptr = *it;
141 slot = cptr->pollslot;
142
143 if (pollfds[slot].revents == 0)
144 continue;
145 if (pollfds[slot].revents & (POLLWRNORM | POLLOUT | POLLHUP | POLLERR))
146 {
147 pollfds[slot].events &= ~(POLLWRNORM | POLLOUT | POLLHUP | POLLERR);
148 if (cptr->is_connecting ())
149 cptr->callback.connected (cptr);
150 else
151 cptr->write_handler (cptr);
152 }
153 }
154
155 for (it = connection_t::list.begin (), et = connection_t::list.end (); it != et; ++it)
156 {
157 connection_t *cptr = *it;
158 if (cptr->flags & CF_DEAD)
159 cptr->close ();
160 }
161 }
162 }