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, 9 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

# User Rev Content
1 pippijn 1.1 /*
2     * poll.C: poll(2) socket engine.
3 pippijn 1.7 *
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 pippijn 1.2 * Rights to this code are documented in doc/pod/license.pod.
10 pippijn 1.4 * Copyright © 2005-2007 Atheme Project (http://www.atheme.org)
11 pippijn 1.1 */
12    
13 pippijn 1.7 static char const rcsid[] = "$Id: poll.C,v 1.6 2007-09-05 11:23:15 pippijn Exp $";
14 pippijn 1.1
15     #include <sys/poll.h>
16    
17     #include "atheme.h"
18     #include "internal.h"
19     #include "datastream.h"
20 pippijn 1.5 #include "connection.h"
21 pippijn 1.1
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 pippijn 1.4 pollfd pollfds[FD_SETSIZE]; /* XXX We need a define indicating MAXCONN. */
34 pippijn 1.1
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 pippijn 1.4 memset (&pollfds, 0, sizeof (pollfd) * FD_SETSIZE);
51 pippijn 1.1 }
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 pippijn 1.6 connection_t::list_type::iterator it = connection_t::list.begin ();
69     connection_t::list_type::iterator et = connection_t::list.end ();
70 pippijn 1.1 int slot = 0;
71    
72 pippijn 1.4 while (it != et)
73     {
74     connection_t *cptr = *it;
75    
76     cptr->pollslot = slot;
77    
78 pippijn 1.5 if (cptr->is_connecting () || sendq_nonempty (cptr))
79 pippijn 1.4 {
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 pippijn 1.1 }
94    
95     /*
96 pippijn 1.5 * connection_t::select()
97 pippijn 1.1 *
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 pippijn 1.5 connection_t::select (time_t delay)
109 pippijn 1.1 {
110     int sr;
111 pippijn 1.6 connection_t::list_type::iterator it = connection_t::list.begin ();
112     connection_t::list_type::iterator et = connection_t::list.end ();
113 pippijn 1.1 int slot;
114    
115     update_poll_fds ();
116    
117 pippijn 1.6 if ((sr = poll (pollfds, connection_t::list.size (), delay / 100)) > 0)
118 pippijn 1.1 {
119     /* Iterate twice, so we don't touch freed memory if
120     * a connection is closed.
121     * -- jilles */
122 pippijn 1.4 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 pippijn 1.6 for (it = connection_t::list.begin (), et = connection_t::list.end (); it != et; ++it)
139 pippijn 1.4 {
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 pippijn 1.5 if (cptr->is_connecting ())
149 pippijn 1.4 cptr->callback.connected (cptr);
150     else
151     cptr->write_handler (cptr);
152     }
153     }
154    
155 pippijn 1.6 for (it = connection_t::list.begin (), et = connection_t::list.end (); it != et; ++it)
156 pippijn 1.4 {
157     connection_t *cptr = *it;
158     if (cptr->flags & CF_DEAD)
159 pippijn 1.5 cptr->close ();
160 pippijn 1.4 }
161 pippijn 1.1 }
162     }