ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/ermyth/src/poll.C
Revision: 1.6
Committed: Wed Sep 5 11:23:15 2007 UTC (16 years, 8 months ago) by pippijn
Content type: text/plain
Branch: MAIN
Changes since 1.5: +8 -8 lines
Log Message:
removed GPLed code and put license back to BSD

File Contents

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