reinstate the original (and dangerous) autopush in C
[kgio.git] / ext / kgio / accept.c
blobc847c92ae48544d65bd996924d9f48f9ba8b1a87
1 /* ref: rubinius b2811f260de16d1e972462e27852470364608de5 */
2 #define RSTRING_MODIFIED 1
4 #include "kgio.h"
5 #include "missing_accept4.h"
6 #include "sock_for_fd.h"
7 #include "my_fileno.h"
8 #include "nonblock.h"
10 static VALUE localhost;
11 static VALUE cClientSocket;
12 static VALUE cKgio_Socket;
13 static VALUE mSocketMethods;
14 static VALUE iv_kgio_addr;
16 #if defined(__linux__) && defined(KGIO_WITHOUT_GVL)
17 static int accept4_flags = SOCK_CLOEXEC;
18 #else /* ! linux */
19 static int accept4_flags = SOCK_CLOEXEC | SOCK_NONBLOCK;
20 #endif /* ! linux */
22 struct accept_args {
23 int fd;
24 int flags;
25 struct sockaddr *addr;
26 socklen_t *addrlen;
27 VALUE accept_io;
28 VALUE accepted_class;
32 * Sets the default class for newly accepted sockets. This is
33 * legacy behavior, kgio_accept and kgio_tryaccept now take optional
34 * class arguments to override this value.
36 static VALUE set_accepted(VALUE klass, VALUE aclass)
38 VALUE tmp;
40 if (NIL_P(aclass))
41 aclass = cKgio_Socket;
43 tmp = rb_funcall(aclass, rb_intern("included_modules"), 0, 0);
44 tmp = rb_funcall(tmp, rb_intern("include?"), 1, mSocketMethods);
46 if (tmp != Qtrue)
47 rb_raise(rb_eTypeError,
48 "class must include Kgio::SocketMethods");
50 cClientSocket = aclass;
52 return aclass;
56 * Returns the default class for newly accepted sockets when kgio_accept
57 * or kgio_tryaccept are not passed arguments
59 static VALUE get_accepted(VALUE klass)
61 return cClientSocket;
65 * accept() wrapper that'll fall back on accept() if we were built on
66 * a system with accept4() but run on a system without accept4()
68 static VALUE xaccept(void *ptr)
70 struct accept_args *a = ptr;
71 int rv;
73 rv = accept_fn(a->fd, a->addr, a->addrlen, a->flags);
74 if (rv < 0 && errno == ENOSYS && accept_fn != my_accept4) {
75 accept_fn = my_accept4;
76 rv = accept_fn(a->fd, a->addr, a->addrlen, a->flags);
79 return (VALUE)rv;
82 #ifdef KGIO_WITHOUT_GVL
83 # include <time.h>
84 # include "blocking_io_region.h"
85 static int thread_accept(struct accept_args *a, int force_nonblock)
87 if (force_nonblock)
88 set_nonblocking(a->fd);
89 return (int)rb_thread_io_blocking_region(xaccept, a, a->fd);
92 #else /* ! KGIO_WITHOUT_GVL */
93 # include <rubysig.h>
94 static int thread_accept(struct accept_args *a, int force_nonblock)
96 int rv;
98 /* always use non-blocking accept() under 1.8 for green threads */
99 set_nonblocking(a->fd);
101 /* created sockets are always non-blocking under 1.8, too */
102 a->flags |= SOCK_NONBLOCK;
104 TRAP_BEG;
105 rv = (int)xaccept(a);
106 TRAP_END;
107 return rv;
109 #endif /* ! KGIO_WITHOUT_GVL */
111 static void
112 prepare_accept(struct accept_args *a, VALUE self, int argc, const VALUE *argv)
114 a->fd = my_fileno(self);
115 a->accept_io = self;
117 switch (argc) {
118 case 2:
119 a->flags = NUM2INT(argv[1]);
120 a->accepted_class = NIL_P(argv[0]) ? cClientSocket : argv[0];
121 return;
122 case 0: /* default, legacy behavior */
123 a->flags = accept4_flags;
124 a->accepted_class = cClientSocket;
125 return;
126 case 1:
127 a->flags = accept4_flags;
128 a->accepted_class = NIL_P(argv[0]) ? cClientSocket : argv[0];
129 return;
132 rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc);
135 static VALUE in_addr_set(VALUE io, struct sockaddr_storage *addr, socklen_t len)
137 VALUE host;
138 int host_len, rc;
139 char *host_ptr;
141 switch (addr->ss_family) {
142 case AF_INET:
143 host_len = (long)INET_ADDRSTRLEN;
144 break;
145 case AF_INET6:
146 host_len = (long)INET6_ADDRSTRLEN;
147 break;
148 default:
149 rb_raise(rb_eRuntimeError,
150 "unsupported address family: ss_family=%lu (socklen=%ld)",
151 (unsigned long)addr->ss_family, (long)len);
153 host = rb_str_new(NULL, host_len);
154 host_ptr = RSTRING_PTR(host);
155 rc = getnameinfo((struct sockaddr *)addr, len,
156 host_ptr, host_len, NULL, 0, NI_NUMERICHOST);
157 if (rc != 0)
158 rb_raise(rb_eRuntimeError, "getnameinfo: %s", gai_strerror(rc));
159 rb_str_set_len(host, strlen(host_ptr));
160 return rb_ivar_set(io, iv_kgio_addr, host);
163 #if defined(__linux__)
164 # define post_accept kgio_autopush_accept
165 #else
166 # define post_accept(a,b) for(;0;)
167 #endif
169 static VALUE
170 my_accept(struct accept_args *a, int force_nonblock)
172 int client_fd;
173 VALUE client_io;
174 int retried = 0;
176 retry:
177 client_fd = thread_accept(a, force_nonblock);
178 if (client_fd < 0) {
179 switch (errno) {
180 case EAGAIN:
181 if (force_nonblock)
182 return Qnil;
183 a->fd = my_fileno(a->accept_io);
184 errno = EAGAIN;
185 (void)rb_io_wait_readable(a->fd);
186 /* fall-through to EINTR case */
187 #ifdef ECONNABORTED
188 case ECONNABORTED:
189 #endif /* ECONNABORTED */
190 #ifdef EPROTO
191 case EPROTO:
192 #endif /* EPROTO */
193 case EINTR:
194 /* raise IOError if closed during sleep */
195 a->fd = my_fileno(a->accept_io);
196 goto retry;
197 case ENOMEM:
198 case EMFILE:
199 case ENFILE:
200 #ifdef ENOBUFS
201 case ENOBUFS:
202 #endif /* ENOBUFS */
203 if (!retried) {
204 retried = 1;
205 errno = 0;
206 rb_gc();
207 goto retry;
209 default:
210 rb_sys_fail("accept");
213 client_io = sock_for_fd(a->accepted_class, client_fd);
214 post_accept(a->accept_io, client_io);
216 if (a->addr)
217 in_addr_set(client_io,
218 (struct sockaddr_storage *)a->addr, *a->addrlen);
219 else
220 rb_ivar_set(client_io, iv_kgio_addr, localhost);
221 return client_io;
225 * call-seq:
227 * io.kgio_addr! => refreshes the given sock address
229 static VALUE addr_bang(VALUE io)
231 int fd = my_fileno(io);
232 struct sockaddr_storage addr;
233 socklen_t len = sizeof(struct sockaddr_storage);
235 if (getpeername(fd, (struct sockaddr *)&addr, &len) != 0)
236 rb_sys_fail("getpeername");
238 if (addr.ss_family == AF_UNIX)
239 return rb_ivar_set(io, iv_kgio_addr, localhost);
241 return in_addr_set(io, &addr, len);
245 * call-seq:
247 * server = Kgio::TCPServer.new('0.0.0.0', 80)
248 * server.kgio_tryaccept -> Kgio::Socket or nil
249 * server.kgio_tryaccept(klass = MySocket) -> MySocket or nil
250 * server.kgio_tryaccept(nil, flags) -> Kgio::Socket or nil
252 * Initiates a non-blocking accept and returns a generic Kgio::Socket
253 * object with the kgio_addr attribute set to the IP address of the
254 * connected client on success.
256 * Returns nil on EAGAIN, and raises on other errors.
258 * An optional +klass+ argument may be specified to override the
259 * Kgio::Socket-class on a successful return value.
261 * An optional +flags+ argument may also be specified.
262 * +flags+ is a bitmask that may contain any combination of:
264 * - Kgio::SOCK_CLOEXEC - close-on-exec flag (enabled by default)
265 * - Kgio::SOCK_NONBLOCK - non-blocking flag (unimportant)
267 static VALUE tcp_tryaccept(int argc, VALUE *argv, VALUE self)
269 struct sockaddr_storage addr;
270 socklen_t addrlen = sizeof(struct sockaddr_storage);
271 struct accept_args a;
273 a.addr = (struct sockaddr *)&addr;
274 a.addrlen = &addrlen;
275 prepare_accept(&a, self, argc, argv);
276 return my_accept(&a, 1);
280 * call-seq:
282 * server = Kgio::TCPServer.new('0.0.0.0', 80)
283 * server.kgio_accept -> Kgio::Socket or nil
284 * server.kgio_tryaccept -> Kgio::Socket or nil
285 * server.kgio_tryaccept(klass = MySocket) -> MySocket or nil
287 * Initiates a blocking accept and returns a generic Kgio::Socket
288 * object with the kgio_addr attribute set to the IP address of
289 * the client on success.
291 * On Ruby implementations using native threads, this can use a blocking
292 * accept(2) (or accept4(2)) system call to avoid thundering herds.
294 * An optional +klass+ argument may be specified to override the
295 * Kgio::Socket-class on a successful return value.
297 * An optional +flags+ argument may also be specified.
298 * +flags+ is a bitmask that may contain any combination of:
300 * - Kgio::SOCK_CLOEXEC - close-on-exec flag (enabled by default)
301 * - Kgio::SOCK_NONBLOCK - non-blocking flag (unimportant)
303 static VALUE tcp_accept(int argc, VALUE *argv, VALUE self)
305 struct sockaddr_storage addr;
306 socklen_t addrlen = sizeof(struct sockaddr_storage);
307 struct accept_args a;
309 a.addr = (struct sockaddr *)&addr;
310 a.addrlen = &addrlen;
311 prepare_accept(&a, self, argc, argv);
312 return my_accept(&a, 0);
316 * call-seq:
318 * server = Kgio::UNIXServer.new("/path/to/unix/socket")
319 * server.kgio_tryaccept -> Kgio::Socket or nil
320 * server.kgio_tryaccept(klass = MySocket) -> MySocket or nil
321 * server.kgio_tryaccept(nil, flags) -> Kgio::Socket or nil
323 * Initiates a non-blocking accept and returns a generic Kgio::Socket
324 * object with the kgio_addr attribute set (to the value of
325 * Kgio::LOCALHOST) on success.
327 * An optional +klass+ argument may be specified to override the
328 * Kgio::Socket-class on a successful return value.
330 * An optional +flags+ argument may also be specified.
331 * +flags+ is a bitmask that may contain any combination of:
333 * - Kgio::SOCK_CLOEXEC - close-on-exec flag (enabled by default)
334 * - Kgio::SOCK_NONBLOCK - non-blocking flag (unimportant)
336 static VALUE unix_tryaccept(int argc, VALUE *argv, VALUE self)
338 struct accept_args a;
340 a.addr = NULL;
341 a.addrlen = NULL;
342 prepare_accept(&a, self, argc, argv);
343 return my_accept(&a, 1);
347 * call-seq:
349 * server = Kgio::UNIXServer.new("/path/to/unix/socket")
350 * server.kgio_accept -> Kgio::Socket or nil
351 * server.kgio_accept(klass = MySocket) -> MySocket or nil
352 * server.kgio_accept(nil, flags) -> Kgio::Socket or nil
354 * Initiates a blocking accept and returns a generic Kgio::Socket
355 * object with the kgio_addr attribute set (to the value of
356 * Kgio::LOCALHOST) on success.
358 * On Ruby implementations using native threads, this can use a blocking
359 * accept(2) (or accept4(2)) system call to avoid thundering herds.
361 * An optional +klass+ argument may be specified to override the
362 * Kgio::Socket-class on a successful return value.
364 * An optional +flags+ argument may also be specified.
365 * +flags+ is a bitmask that may contain any combination of:
367 * - Kgio::SOCK_CLOEXEC - close-on-exec flag (enabled by default)
368 * - Kgio::SOCK_NONBLOCK - non-blocking flag (unimportant)
370 static VALUE unix_accept(int argc, VALUE *argv, VALUE self)
372 struct accept_args a;
374 a.addr = NULL;
375 a.addrlen = NULL;
376 prepare_accept(&a, self, argc, argv);
377 return my_accept(&a, 0);
381 * call-seq:
383 * Kgio.accept_cloexec? -> true or false
385 * Returns true if newly accepted Kgio::Sockets are created with the
386 * FD_CLOEXEC file descriptor flag, false if not.
388 * Deprecated, use the per-socket flags for kgio_*accept instead.
390 static VALUE get_cloexec(VALUE mod)
392 return (accept4_flags & SOCK_CLOEXEC) == SOCK_CLOEXEC ? Qtrue : Qfalse;
397 * call-seq:
399 * Kgio.accept_nonblock? -> true or false
401 * Returns true if newly accepted Kgio::Sockets are created with the
402 * O_NONBLOCK file status flag, false if not.
404 * Deprecated, use the per-socket flags for kgio_*accept instead.
406 static VALUE get_nonblock(VALUE mod)
408 return (accept4_flags & SOCK_NONBLOCK)==SOCK_NONBLOCK ? Qtrue : Qfalse;
412 * call-seq:
414 * Kgio.accept_cloexec = true
415 * Kgio.accept_cloexec = false
417 * Sets whether or not Kgio::Socket objects created by
418 * TCPServer#kgio_accept,
419 * TCPServer#kgio_tryaccept,
420 * UNIXServer#kgio_accept,
421 * and UNIXServer#kgio_tryaccept
422 * default to being created with the FD_CLOEXEC file descriptor flag.
424 * This is on by default, as there is little reason to deal to enable
425 * it for client sockets on a socket server.
427 * Deprecated, use the per-socket flags for kgio_*accept instead.
429 static VALUE set_cloexec(VALUE mod, VALUE boolean)
431 switch (TYPE(boolean)) {
432 case T_TRUE:
433 accept4_flags |= SOCK_CLOEXEC;
434 return boolean;
435 case T_FALSE:
436 accept4_flags &= ~SOCK_CLOEXEC;
437 return boolean;
439 rb_raise(rb_eTypeError, "not true or false");
440 return Qnil;
444 * call-seq:
446 * Kgio.accept_nonblock = true
447 * Kgio.accept_nonblock = false
449 * Sets whether or not Kgio::Socket objects created by
450 * TCPServer#kgio_accept,
451 * TCPServer#kgio_tryaccept,
452 * UNIXServer#kgio_accept,
453 * and UNIXServer#kgio_tryaccept
454 * are created with the O_NONBLOCK file status flag.
456 * This defaults to +false+ for GNU/Linux where MSG_DONTWAIT is
457 * available (and on newer GNU/Linux, accept4() may also set
458 * the non-blocking flag. This defaults to +true+ on non-GNU/Linux
459 * systems.
461 * This is always true on Ruby implementations using user-space threads.
463 * Deprecated, use the per-socket flags for kgio_*accept instead.
465 static VALUE set_nonblock(VALUE mod, VALUE boolean)
467 switch (TYPE(boolean)) {
468 case T_TRUE:
469 accept4_flags |= SOCK_NONBLOCK;
470 return boolean;
471 case T_FALSE:
472 accept4_flags &= ~SOCK_NONBLOCK;
473 return boolean;
475 rb_raise(rb_eTypeError, "not true or false");
476 return Qnil;
479 void init_kgio_accept(void)
481 VALUE cUNIXServer, cTCPServer;
482 VALUE mKgio = rb_define_module("Kgio");
485 * Maps to the SOCK_NONBLOCK constant in Linux for setting
486 * the non-blocking flag on newly accepted sockets. This is
487 * usually unnecessary as sockets are made non-blocking
488 * whenever non-blocking methods are used.
490 rb_define_const(mKgio, "SOCK_NONBLOCK", INT2NUM(SOCK_NONBLOCK));
493 * Maps to the SOCK_CLOEXEC constant in Linux for setting
494 * the close-on-exec flag on newly accepted descriptors. This
495 * is enabled by default, and there is usually no reason to
496 * disable close-on-exec for accepted sockets.
498 rb_define_const(mKgio, "SOCK_CLOEXEC", INT2NUM(SOCK_CLOEXEC));
500 localhost = rb_const_get(mKgio, rb_intern("LOCALHOST"));
501 cKgio_Socket = rb_const_get(mKgio, rb_intern("Socket"));
502 cClientSocket = cKgio_Socket;
503 mSocketMethods = rb_const_get(mKgio, rb_intern("SocketMethods"));
505 rb_define_method(mSocketMethods, "kgio_addr!", addr_bang, 0);
507 rb_define_singleton_method(mKgio, "accept_cloexec?", get_cloexec, 0);
508 rb_define_singleton_method(mKgio, "accept_cloexec=", set_cloexec, 1);
509 rb_define_singleton_method(mKgio, "accept_nonblock?", get_nonblock, 0);
510 rb_define_singleton_method(mKgio, "accept_nonblock=", set_nonblock, 1);
511 rb_define_singleton_method(mKgio, "accept_class=", set_accepted, 1);
512 rb_define_singleton_method(mKgio, "accept_class", get_accepted, 0);
515 * Document-class: Kgio::UNIXServer
517 * Kgio::UNIXServer should be used in place of the plain UNIXServer
518 * when kgio_accept and kgio_tryaccept methods are needed.
520 cUNIXServer = rb_const_get(rb_cObject, rb_intern("UNIXServer"));
521 cUNIXServer = rb_define_class_under(mKgio, "UNIXServer", cUNIXServer);
522 rb_define_method(cUNIXServer, "kgio_tryaccept", unix_tryaccept, -1);
523 rb_define_method(cUNIXServer, "kgio_accept", unix_accept, -1);
526 * Document-class: Kgio::TCPServer
528 * Kgio::TCPServer should be used in place of the plain TCPServer
529 * when kgio_accept and kgio_tryaccept methods are needed.
531 cTCPServer = rb_const_get(rb_cObject, rb_intern("TCPServer"));
532 cTCPServer = rb_define_class_under(mKgio, "TCPServer", cTCPServer);
534 rb_define_method(cTCPServer, "kgio_tryaccept", tcp_tryaccept, -1);
535 rb_define_method(cTCPServer, "kgio_accept", tcp_accept, -1);
536 init_sock_for_fd();
537 iv_kgio_addr = rb_intern("@kgio_addr");