]> jfr.im git - irc/rqf/shadowircd.git/blob - libratbox/src/ports.c
Fix up grammar in ShadowIRCd MOTD for great good!
[irc/rqf/shadowircd.git] / libratbox / src / ports.c
1 /*
2 * ircd-ratbox: A slightly useful ircd.
3 * ports.c: Solaris ports compatible network routines.
4 *
5 * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
6 * Copyright (C) 1996-2002 Hybrid Development Team
7 * Copyright (C) 2001 Adrian Chadd <adrian@creative.net.au>
8 * Copyright (C) 2002-2004,2008 ircd-ratbox development team
9 * Copyright (C) 2005 Edward Brocklesby.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
24 * USA
25 *
26 */
27
28 #include <libratbox_config.h>
29 #include <ratbox_lib.h>
30 #include <commio-int.h>
31 #include <event-int.h>
32 #if defined(HAVE_PORT_H) && (HAVE_PORT_CREATE)
33
34 #include <port.h>
35
36 #define PE_LENGTH 128
37
38 static int pe;
39 static struct timespec zero_timespec;
40
41 static port_event_t *pelst; /* port buffer */
42 static int pemax; /* max structs to buffer */
43
44 int
45 rb_setup_fd_ports(rb_fde_t *F)
46 {
47 return 0;
48 }
49
50 /*
51 * rb_init_netio
52 *
53 * This is a needed exported function which will be called to initialise
54 * the network loop code.
55 */
56
57 int
58 rb_init_netio_ports(void)
59 {
60 if((pe = port_create()) < 0)
61 {
62 return errno;
63 }
64 pemax = getdtablesize();
65 pelst = rb_malloc(sizeof(port_event_t) * pemax);
66 zero_timespec.tv_sec = 0;
67 zero_timespec.tv_nsec = 0;
68 rb_set_time();
69 return 0;
70 }
71
72 /*
73 * rb_setselect
74 *
75 * This is a needed exported function which will be called to register
76 * and deregister interest in a pending IO state for a given FD.
77 */
78 void
79 rb_setselect_ports(rb_fde_t *F, unsigned int type, PF * handler, void *client_data)
80 {
81 lrb_assert(IsFDOpen(F));
82 int old_flags = F->pflags;
83
84 if(type & RB_SELECT_READ)
85 {
86 F->read_handler = handler;
87 F->read_data = client_data;
88 }
89 if(type & RB_SELECT_WRITE)
90 {
91 F->write_handler = handler;
92 F->write_data = client_data;
93 }
94 F->pflags = 0;
95
96 if(F->read_handler != NULL)
97 F->pflags = POLLIN;
98 if(F->write_handler != NULL)
99 F->pflags |= POLLOUT;
100
101 if(old_flags == 0 && F->pflags == 0)
102 return;
103 else if(F->pflags <= 0)
104 {
105 port_dissociate(pe, PORT_SOURCE_FD, F->fd);
106 return;
107 }
108
109 port_associate(pe, PORT_SOURCE_FD, F->fd, F->pflags, F);
110
111 }
112
113 /*
114 * rb_select
115 *
116 * Called to do the new-style IO, courtesy of squid (like most of this
117 * new IO code). This routine handles the stuff we've hidden in
118 * rb_setselect and fd_table[] and calls callbacks for IO ready
119 * events.
120 */
121
122 int
123 rb_select_ports(long delay)
124 {
125 int i, fd;
126 int nget = 1;
127 struct timespec poll_time;
128 struct timespec *p = NULL;
129 struct ev_entry *ev;
130
131 if(delay >= 0)
132 {
133 poll_time.tv_sec = delay / 1000;
134 poll_time.tv_nsec = (delay % 1000) * 1000000;
135 p = &poll_time;
136 }
137
138
139 i = port_getn(pe, pelst, pemax, &nget, p);
140 rb_set_time();
141
142 if(i == -1)
143 return RB_OK;
144
145 for(i = 0; i < nget; i++)
146 {
147 if(pelst[i].portev_source == PORT_SOURCE_FD)
148 {
149 fd = pelst[i].portev_object;
150 PF *hdl = NULL;
151 rb_fde_t *F = pelst[i].portev_user;
152 if((pelst[i].portev_events & (POLLIN | POLLHUP | POLLERR)) && (hdl = F->read_handler))
153 {
154 F->read_handler = NULL;
155 hdl(F, F->read_data);
156 }
157 if((pelst[i].portev_events & (POLLOUT | POLLHUP | POLLERR)) && (hdl = F->write_handler))
158 {
159 F->write_handler = NULL;
160 hdl(F, F->write_data);
161 }
162 } else if(pelst[i].portev_source == PORT_SOURCE_TIMER)
163 {
164 ev = (struct ev_entry *)pelst[i].portev_user;
165 rb_run_event(ev);
166 }
167 }
168 return RB_OK;
169 }
170
171 int
172 rb_ports_supports_event(void)
173 {
174 return 1;
175 };
176
177 void
178 rb_ports_init_event(void)
179 {
180 return;
181 }
182
183 int
184 rb_ports_sched_event(struct ev_entry *event, int when)
185 {
186 timer_t *id;
187 struct sigevent ev;
188 port_notify_t not;
189 struct itimerspec ts;
190
191 event->comm_ptr = rb_malloc(sizeof(timer_t));
192 id = event->comm_ptr;
193
194 memset(&ev, 0, sizeof(ev));
195 ev.sigev_notify = SIGEV_PORT;
196 ev.sigev_value.sival_ptr = &not;
197
198 memset(&not, 0, sizeof(not));
199 not.portnfy_port = pe;
200 not.portnfy_user = event;
201
202 if(timer_create(CLOCK_REALTIME, &ev, id) < 0)
203 {
204 rb_lib_log("timer_create: %s\n", strerror(errno));
205 return 0;
206 }
207
208 memset(&ts, 0, sizeof(ts));
209 ts.it_value.tv_sec = when;
210 ts.it_value.tv_nsec = 0;
211 if(event->frequency != 0)
212 ts.it_interval = ts.it_value;
213
214 if(timer_settime(*id, 0, &ts, NULL) < 0)
215 {
216 rb_lib_log("timer_settime: %s\n", strerror(errno));
217 return 0;
218 }
219 return 1;
220 }
221
222 void
223 rb_ports_unsched_event(struct ev_entry *event)
224 {
225 timer_delete(*((timer_t *) event->comm_ptr));
226 rb_free(event->comm_ptr);
227 event->comm_ptr = NULL;
228 }
229 #else /* ports not supported */
230
231 int
232 rb_ports_supports_event(void)
233 {
234 errno = ENOSYS;
235 return 0;
236 }
237
238 void
239 rb_ports_init_event(void)
240 {
241 return;
242 }
243
244 int
245 rb_ports_sched_event(struct ev_entry *event, int when)
246 {
247 errno = ENOSYS;
248 return -1;
249 }
250
251 void
252 rb_ports_unsched_event(struct ev_entry *event)
253 {
254 return;
255 }
256
257 int
258 rb_init_netio_ports(void)
259 {
260 return ENOSYS;
261 }
262
263 void
264 rb_setselect_ports(rb_fde_t *F, unsigned int type, PF * handler, void *client_data)
265 {
266 errno = ENOSYS;
267 return;
268 }
269
270 int
271 rb_select_ports(long delay)
272 {
273 errno = ENOSYS;
274 return -1;
275 }
276
277 int
278 rb_setup_fd_ports(rb_fde_t *F)
279 {
280 errno = ENOSYS;
281 return -1;
282 }
283
284
285 #endif