1 /************************************************
2
3 init.c -
4
5 created at: Thu Mar 31 12:21:29 JST 1994
6
7 Copyright (C) 1993-2007 Yukihiro Matsumoto
8
9 ************************************************/
10
11 #include "rubysocket.h"
12
13 #ifdef _WIN32
14 VALUE rb_w32_conv_from_wchar(const WCHAR *wstr, rb_encoding *enc);
15 #endif
16
17 VALUE rb_cBasicSocket;
18 VALUE rb_cIPSocket;
19 VALUE rb_cTCPSocket;
20 VALUE rb_cTCPServer;
21 VALUE rb_cUDPSocket;
22 #ifdef AF_UNIX
23 VALUE rb_cUNIXSocket;
24 VALUE rb_cUNIXServer;
25 #endif
26 VALUE rb_cSocket;
27 VALUE rb_cAddrinfo;
28
29 VALUE rb_eSocket;
30
31 #ifdef SOCKS
32 VALUE rb_cSOCKSSocket;
33 #endif
34
35 int rsock_do_not_reverse_lookup = 1;
36 static VALUE sym_wait_readable;
37
38 void
rsock_raise_socket_error(const char * reason,int error)39 rsock_raise_socket_error(const char *reason, int error)
40 {
41 #ifdef EAI_SYSTEM
42 int e;
43 if (error == EAI_SYSTEM && (e = errno) != 0)
44 rb_syserr_fail(e, reason);
45 #endif
46 #ifdef _WIN32
47 rb_encoding *enc = rb_default_internal_encoding();
48 VALUE msg = rb_sprintf("%s: ", reason);
49 if (!enc) enc = rb_default_internal_encoding();
50 rb_str_concat(msg, rb_w32_conv_from_wchar(gai_strerrorW(error), enc));
51 rb_exc_raise(rb_exc_new_str(rb_eSocket, msg));
52 #else
53 rb_raise(rb_eSocket, "%s: %s", reason, gai_strerror(error));
54 #endif
55 }
56
57 #ifdef _WIN32
58 #define is_socket(fd) rb_w32_is_socket(fd)
59 #else
60 static int
is_socket(int fd)61 is_socket(int fd)
62 {
63 struct stat sbuf;
64
65 if (fstat(fd, &sbuf) < 0)
66 rb_sys_fail("fstat(2)");
67 return S_ISSOCK(sbuf.st_mode);
68 }
69 #endif
70
71 #if defined __APPLE__
72 # define do_write_retry(code) do {ret = code;} while (ret == -1 && errno == EPROTOTYPE)
73 #else
74 # define do_write_retry(code) ret = code
75 #endif
76
77 VALUE
rsock_init_sock(VALUE sock,int fd)78 rsock_init_sock(VALUE sock, int fd)
79 {
80 rb_io_t *fp;
81
82 if (!is_socket(fd) || rb_reserved_fd_p(fd)) {
83 rb_syserr_fail(EBADF, "not a socket file descriptor");
84 }
85
86 rb_update_max_fd(fd);
87 MakeOpenFile(sock, fp);
88 fp->fd = fd;
89 fp->mode = FMODE_READWRITE|FMODE_DUPLEX;
90 rb_io_ascii8bit_binmode(sock);
91 if (rsock_do_not_reverse_lookup) {
92 fp->mode |= FMODE_NOREVLOOKUP;
93 }
94 rb_io_synchronized(fp);
95
96 return sock;
97 }
98
99 VALUE
rsock_sendto_blocking(void * data)100 rsock_sendto_blocking(void *data)
101 {
102 struct rsock_send_arg *arg = data;
103 VALUE mesg = arg->mesg;
104 ssize_t ret;
105 do_write_retry(sendto(arg->fd, RSTRING_PTR(mesg), RSTRING_LEN(mesg),
106 arg->flags, arg->to, arg->tolen));
107 return (VALUE)ret;
108 }
109
110 VALUE
rsock_send_blocking(void * data)111 rsock_send_blocking(void *data)
112 {
113 struct rsock_send_arg *arg = data;
114 VALUE mesg = arg->mesg;
115 ssize_t ret;
116 do_write_retry(send(arg->fd, RSTRING_PTR(mesg), RSTRING_LEN(mesg),
117 arg->flags));
118 return (VALUE)ret;
119 }
120
121 struct recvfrom_arg {
122 int fd, flags;
123 VALUE str;
124 size_t length;
125 socklen_t alen;
126 union_sockaddr buf;
127 };
128
129 static VALUE
recvfrom_blocking(void * data)130 recvfrom_blocking(void *data)
131 {
132 struct recvfrom_arg *arg = data;
133 socklen_t len0 = arg->alen;
134 ssize_t ret;
135 ret = recvfrom(arg->fd, RSTRING_PTR(arg->str), arg->length,
136 arg->flags, &arg->buf.addr, &arg->alen);
137 if (ret != -1 && len0 < arg->alen)
138 arg->alen = len0;
139
140 return (VALUE)ret;
141 }
142
143 static VALUE
rsock_strbuf(VALUE str,long buflen)144 rsock_strbuf(VALUE str, long buflen)
145 {
146 long len;
147
148 if (NIL_P(str)) return rb_tainted_str_new(0, buflen);
149
150 StringValue(str);
151 len = RSTRING_LEN(str);
152 if (len >= buflen) {
153 rb_str_modify(str);
154 } else {
155 rb_str_modify_expand(str, buflen - len);
156 }
157 return str;
158 }
159
160 static VALUE
recvfrom_locktmp(VALUE v)161 recvfrom_locktmp(VALUE v)
162 {
163 struct recvfrom_arg *arg = (struct recvfrom_arg *)v;
164
165 return rb_thread_io_blocking_region(recvfrom_blocking, arg, arg->fd);
166 }
167
168 VALUE
rsock_s_recvfrom(VALUE sock,int argc,VALUE * argv,enum sock_recv_type from)169 rsock_s_recvfrom(VALUE sock, int argc, VALUE *argv, enum sock_recv_type from)
170 {
171 rb_io_t *fptr;
172 VALUE str;
173 struct recvfrom_arg arg;
174 VALUE len, flg;
175 long buflen;
176 long slen;
177
178 rb_scan_args(argc, argv, "12", &len, &flg, &str);
179
180 if (flg == Qnil) arg.flags = 0;
181 else arg.flags = NUM2INT(flg);
182 buflen = NUM2INT(len);
183 str = rsock_strbuf(str, buflen);
184
185 GetOpenFile(sock, fptr);
186 if (rb_io_read_pending(fptr)) {
187 rb_raise(rb_eIOError, "recv for buffered IO");
188 }
189 arg.fd = fptr->fd;
190 arg.alen = (socklen_t)sizeof(arg.buf);
191 arg.str = str;
192 arg.length = buflen;
193
194 while (rb_io_check_closed(fptr),
195 rsock_maybe_wait_fd(arg.fd),
196 (slen = (long)rb_str_locktmp_ensure(str, recvfrom_locktmp,
197 (VALUE)&arg)) < 0) {
198 if (!rb_io_wait_readable(fptr->fd)) {
199 rb_sys_fail("recvfrom(2)");
200 }
201 }
202
203 /* Resize the string to the amount of data received */
204 rb_str_set_len(str, slen);
205 rb_obj_taint(str);
206 switch (from) {
207 case RECV_RECV:
208 return str;
209 case RECV_IP:
210 #if 0
211 if (arg.alen != sizeof(struct sockaddr_in)) {
212 rb_raise(rb_eTypeError, "sockaddr size differs - should not happen");
213 }
214 #endif
215 if (arg.alen && arg.alen != sizeof(arg.buf)) /* OSX doesn't return a from result for connection-oriented sockets */
216 return rb_assoc_new(str, rsock_ipaddr(&arg.buf.addr, arg.alen, fptr->mode & FMODE_NOREVLOOKUP));
217 else
218 return rb_assoc_new(str, Qnil);
219
220 #ifdef HAVE_SYS_UN_H
221 case RECV_UNIX:
222 return rb_assoc_new(str, rsock_unixaddr(&arg.buf.un, arg.alen));
223 #endif
224 case RECV_SOCKET:
225 return rb_assoc_new(str, rsock_io_socket_addrinfo(sock, &arg.buf.addr, arg.alen));
226 default:
227 rb_bug("rsock_s_recvfrom called with bad value");
228 }
229 }
230
231 VALUE
rsock_s_recvfrom_nonblock(VALUE sock,VALUE len,VALUE flg,VALUE str,VALUE ex,enum sock_recv_type from)232 rsock_s_recvfrom_nonblock(VALUE sock, VALUE len, VALUE flg, VALUE str,
233 VALUE ex, enum sock_recv_type from)
234 {
235 rb_io_t *fptr;
236 union_sockaddr buf;
237 socklen_t alen = (socklen_t)sizeof buf;
238 long buflen;
239 long slen;
240 int fd, flags;
241 VALUE addr = Qnil;
242 socklen_t len0;
243
244 flags = NUM2INT(flg);
245 buflen = NUM2INT(len);
246 str = rsock_strbuf(str, buflen);
247
248 #ifdef MSG_DONTWAIT
249 /* MSG_DONTWAIT avoids the race condition between fcntl and recvfrom.
250 It is not portable, though. */
251 flags |= MSG_DONTWAIT;
252 #endif
253
254 GetOpenFile(sock, fptr);
255 if (rb_io_read_pending(fptr)) {
256 rb_raise(rb_eIOError, "recvfrom for buffered IO");
257 }
258 fd = fptr->fd;
259
260 rb_io_check_closed(fptr);
261
262 if (!MSG_DONTWAIT_RELIABLE)
263 rb_io_set_nonblock(fptr);
264
265 len0 = alen;
266 slen = recvfrom(fd, RSTRING_PTR(str), buflen, flags, &buf.addr, &alen);
267 if (slen != -1 && len0 < alen)
268 alen = len0;
269
270 if (slen < 0) {
271 int e = errno;
272 switch (e) {
273 case EAGAIN:
274 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
275 case EWOULDBLOCK:
276 #endif
277 if (ex == Qfalse)
278 return sym_wait_readable;
279 rb_readwrite_syserr_fail(RB_IO_WAIT_READABLE, e, "recvfrom(2) would block");
280 }
281 rb_syserr_fail(e, "recvfrom(2)");
282 }
283 if (slen != RSTRING_LEN(str)) {
284 rb_str_set_len(str, slen);
285 }
286 rb_obj_taint(str);
287 switch (from) {
288 case RECV_RECV:
289 return str;
290
291 case RECV_IP:
292 if (alen && alen != sizeof(buf)) /* connection-oriented socket may not return a from result */
293 addr = rsock_ipaddr(&buf.addr, alen, fptr->mode & FMODE_NOREVLOOKUP);
294 break;
295
296 case RECV_SOCKET:
297 addr = rsock_io_socket_addrinfo(sock, &buf.addr, alen);
298 break;
299
300 default:
301 rb_bug("rsock_s_recvfrom_nonblock called with bad value");
302 }
303 return rb_assoc_new(str, addr);
304 }
305
306 #if MSG_DONTWAIT_RELIABLE
307 static VALUE sym_wait_writable;
308
309 /* copied from io.c :< */
310 static long
read_buffered_data(char * ptr,long len,rb_io_t * fptr)311 read_buffered_data(char *ptr, long len, rb_io_t *fptr)
312 {
313 int n = fptr->rbuf.len;
314
315 if (n <= 0) return 0;
316 if (n > len) n = (int)len;
317 MEMMOVE(ptr, fptr->rbuf.ptr+fptr->rbuf.off, char, n);
318 fptr->rbuf.off += n;
319 fptr->rbuf.len -= n;
320 return n;
321 }
322
323 /* :nodoc: */
324 VALUE
rsock_read_nonblock(VALUE sock,VALUE length,VALUE buf,VALUE ex)325 rsock_read_nonblock(VALUE sock, VALUE length, VALUE buf, VALUE ex)
326 {
327 rb_io_t *fptr;
328 long n;
329 long len = NUM2LONG(length);
330 VALUE str = rsock_strbuf(buf, len);
331 char *ptr;
332
333 OBJ_TAINT(str);
334 GetOpenFile(sock, fptr);
335
336 if (len == 0) {
337 rb_str_set_len(str, 0);
338 return str;
339 }
340
341 ptr = RSTRING_PTR(str);
342 n = read_buffered_data(ptr, len, fptr);
343 if (n <= 0) {
344 n = (long)recv(fptr->fd, ptr, len, MSG_DONTWAIT);
345 if (n < 0) {
346 int e = errno;
347 if ((e == EWOULDBLOCK || e == EAGAIN)) {
348 if (ex == Qfalse) return sym_wait_readable;
349 rb_readwrite_syserr_fail(RB_IO_WAIT_READABLE,
350 e, "read would block");
351 }
352 rb_syserr_fail_path(e, fptr->pathv);
353 }
354 }
355 if (n != RSTRING_LEN(str)) {
356 rb_str_modify(str);
357 rb_str_set_len(str, n);
358 }
359 if (n == 0) {
360 if (ex == Qfalse) return Qnil;
361 rb_eof_error();
362 }
363
364 return str;
365 }
366
367 /* :nodoc: */
368 VALUE
rsock_write_nonblock(VALUE sock,VALUE str,VALUE ex)369 rsock_write_nonblock(VALUE sock, VALUE str, VALUE ex)
370 {
371 rb_io_t *fptr;
372 long n;
373
374 if (!RB_TYPE_P(str, T_STRING))
375 str = rb_obj_as_string(str);
376
377 sock = rb_io_get_write_io(sock);
378 GetOpenFile(sock, fptr);
379 rb_io_check_writable(fptr);
380
381 /*
382 * As with IO#write_nonblock, we may block if somebody is relying on
383 * buffered I/O; but nobody actually hits this because pipes and sockets
384 * are not userspace-buffered in Ruby by default.
385 */
386 if (fptr->wbuf.len > 0) {
387 rb_io_flush(sock);
388 }
389
390 #ifdef __APPLE__
391 again:
392 #endif
393 n = (long)send(fptr->fd, RSTRING_PTR(str), RSTRING_LEN(str), MSG_DONTWAIT);
394 if (n < 0) {
395 int e = errno;
396
397 #ifdef __APPLE__
398 if (e == EPROTOTYPE) {
399 goto again;
400 }
401 #endif
402 if (e == EWOULDBLOCK || e == EAGAIN) {
403 if (ex == Qfalse) return sym_wait_writable;
404 rb_readwrite_syserr_fail(RB_IO_WAIT_WRITABLE, e,
405 "write would block");
406 }
407 rb_syserr_fail_path(e, fptr->pathv);
408 }
409
410 return LONG2FIX(n);
411 }
412 #endif /* MSG_DONTWAIT_RELIABLE */
413
414 /* returns true if SOCK_CLOEXEC is supported */
rsock_detect_cloexec(int fd)415 int rsock_detect_cloexec(int fd)
416 {
417 #ifdef SOCK_CLOEXEC
418 int flags = fcntl(fd, F_GETFD);
419
420 if (flags == -1)
421 rb_bug("rsock_detect_cloexec: fcntl(%d, F_GETFD) failed: %s", fd, strerror(errno));
422
423 if (flags & FD_CLOEXEC)
424 return 1;
425 #endif
426 return 0;
427 }
428
429 #ifdef SOCK_CLOEXEC
430 static int
rsock_socket0(int domain,int type,int proto)431 rsock_socket0(int domain, int type, int proto)
432 {
433 int ret;
434 static int cloexec_state = -1; /* <0: unknown, 0: ignored, >0: working */
435
436 if (cloexec_state > 0) { /* common path, if SOCK_CLOEXEC is defined */
437 ret = socket(domain, type|SOCK_CLOEXEC|RSOCK_NONBLOCK_DEFAULT, proto);
438 if (ret >= 0) {
439 if (ret <= 2)
440 goto fix_cloexec;
441 goto update_max_fd;
442 }
443 }
444 else if (cloexec_state < 0) { /* usually runs once only for detection */
445 ret = socket(domain, type|SOCK_CLOEXEC|RSOCK_NONBLOCK_DEFAULT, proto);
446 if (ret >= 0) {
447 cloexec_state = rsock_detect_cloexec(ret);
448 if (cloexec_state == 0 || ret <= 2)
449 goto fix_cloexec;
450 goto update_max_fd;
451 }
452 else if (ret == -1 && errno == EINVAL) {
453 /* SOCK_CLOEXEC is available since Linux 2.6.27. Linux 2.6.18 fails with EINVAL */
454 ret = socket(domain, type, proto);
455 if (ret != -1) {
456 cloexec_state = 0;
457 /* fall through to fix_cloexec */
458 }
459 }
460 }
461 else { /* cloexec_state == 0 */
462 ret = socket(domain, type, proto);
463 }
464 if (ret == -1)
465 return -1;
466 fix_cloexec:
467 rb_maygvl_fd_fix_cloexec(ret);
468 if (RSOCK_NONBLOCK_DEFAULT) {
469 rsock_make_fd_nonblock(ret);
470 }
471 update_max_fd:
472 rb_update_max_fd(ret);
473
474 return ret;
475 }
476 #else /* !SOCK_CLOEXEC */
477 static int
rsock_socket0(int domain,int type,int proto)478 rsock_socket0(int domain, int type, int proto)
479 {
480 int ret = socket(domain, type, proto);
481
482 if (ret == -1)
483 return -1;
484 rb_fd_fix_cloexec(ret);
485 if (RSOCK_NONBLOCK_DEFAULT) {
486 rsock_make_fd_nonblock(ret);
487 }
488
489 return ret;
490 }
491 #endif /* !SOCK_CLOEXEC */
492
493 int
rsock_socket(int domain,int type,int proto)494 rsock_socket(int domain, int type, int proto)
495 {
496 int fd;
497
498 fd = rsock_socket0(domain, type, proto);
499 if (fd < 0) {
500 if (rb_gc_for_fd(errno)) {
501 fd = rsock_socket0(domain, type, proto);
502 }
503 }
504 if (0 <= fd)
505 rb_update_max_fd(fd);
506 return fd;
507 }
508
509 /* emulate blocking connect behavior on EINTR or non-blocking socket */
510 static int
wait_connectable(int fd)511 wait_connectable(int fd)
512 {
513 int sockerr, revents;
514 socklen_t sockerrlen;
515
516 sockerrlen = (socklen_t)sizeof(sockerr);
517 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&sockerr, &sockerrlen) < 0)
518 return -1;
519
520 /* necessary for non-blocking sockets (at least ECONNREFUSED) */
521 switch (sockerr) {
522 case 0:
523 break;
524 #ifdef EALREADY
525 case EALREADY:
526 #endif
527 #ifdef EISCONN
528 case EISCONN:
529 #endif
530 #ifdef ECONNREFUSED
531 case ECONNREFUSED:
532 #endif
533 #ifdef EHOSTUNREACH
534 case EHOSTUNREACH:
535 #endif
536 errno = sockerr;
537 return -1;
538 }
539
540 /*
541 * Stevens book says, successful finish turn on RB_WAITFD_OUT and
542 * failure finish turn on both RB_WAITFD_IN and RB_WAITFD_OUT.
543 * So it's enough to wait only RB_WAITFD_OUT and check the pending error
544 * by getsockopt().
545 *
546 * Note: rb_wait_for_single_fd already retries on EINTR/ERESTART
547 */
548 revents = rb_wait_for_single_fd(fd, RB_WAITFD_IN|RB_WAITFD_OUT, NULL);
549
550 if (revents < 0)
551 return -1;
552
553 sockerrlen = (socklen_t)sizeof(sockerr);
554 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&sockerr, &sockerrlen) < 0)
555 return -1;
556
557 switch (sockerr) {
558 case 0:
559 /*
560 * be defensive in case some platforms set SO_ERROR on the original,
561 * interrupted connect()
562 */
563 case EINTR:
564 #ifdef ERESTART
565 case ERESTART:
566 #endif
567 case EAGAIN:
568 #ifdef EINPROGRESS
569 case EINPROGRESS:
570 #endif
571 #ifdef EALREADY
572 case EALREADY:
573 #endif
574 #ifdef EISCONN
575 case EISCONN:
576 #endif
577 return 0; /* success */
578 default:
579 /* likely (but not limited to): ECONNREFUSED, ETIMEDOUT, EHOSTUNREACH */
580 errno = sockerr;
581 return -1;
582 }
583
584 return 0;
585 }
586
587 struct connect_arg {
588 int fd;
589 socklen_t len;
590 const struct sockaddr *sockaddr;
591 };
592
593 static VALUE
connect_blocking(void * data)594 connect_blocking(void *data)
595 {
596 struct connect_arg *arg = data;
597 return (VALUE)connect(arg->fd, arg->sockaddr, arg->len);
598 }
599
600 #if defined(SOCKS) && !defined(SOCKS5)
601 static VALUE
socks_connect_blocking(void * data)602 socks_connect_blocking(void *data)
603 {
604 struct connect_arg *arg = data;
605 return (VALUE)Rconnect(arg->fd, arg->sockaddr, arg->len);
606 }
607 #endif
608
609 int
rsock_connect(int fd,const struct sockaddr * sockaddr,int len,int socks)610 rsock_connect(int fd, const struct sockaddr *sockaddr, int len, int socks)
611 {
612 int status;
613 rb_blocking_function_t *func = connect_blocking;
614 struct connect_arg arg;
615
616 arg.fd = fd;
617 arg.sockaddr = sockaddr;
618 arg.len = len;
619 #if defined(SOCKS) && !defined(SOCKS5)
620 if (socks) func = socks_connect_blocking;
621 #endif
622 status = (int)BLOCKING_REGION_FD(func, &arg);
623
624 if (status < 0) {
625 switch (errno) {
626 case EINTR:
627 #ifdef ERESTART
628 case ERESTART:
629 #endif
630 case EAGAIN:
631 #ifdef EINPROGRESS
632 case EINPROGRESS:
633 #endif
634 return wait_connectable(fd);
635 }
636 }
637 return status;
638 }
639
640 void
rsock_make_fd_nonblock(int fd)641 rsock_make_fd_nonblock(int fd)
642 {
643 int flags;
644 #ifdef F_GETFL
645 flags = fcntl(fd, F_GETFL);
646 if (flags == -1) {
647 rb_sys_fail("fnctl(2)");
648 }
649 #else
650 flags = 0;
651 #endif
652 flags |= O_NONBLOCK;
653 if (fcntl(fd, F_SETFL, flags) == -1) {
654 rb_sys_fail("fnctl(2)");
655 }
656 }
657
658 static int
cloexec_accept(int socket,struct sockaddr * address,socklen_t * address_len,int nonblock)659 cloexec_accept(int socket, struct sockaddr *address, socklen_t *address_len,
660 int nonblock)
661 {
662 int ret;
663 socklen_t len0 = 0;
664 #ifdef HAVE_ACCEPT4
665 static int try_accept4 = 1;
666 #endif
667 if (RSOCK_NONBLOCK_DEFAULT) {
668 nonblock = 1;
669 }
670 if (address_len) len0 = *address_len;
671 #ifdef HAVE_ACCEPT4
672 if (try_accept4) {
673 int flags = 0;
674 #ifdef SOCK_CLOEXEC
675 flags |= SOCK_CLOEXEC;
676 #endif
677 #ifdef SOCK_NONBLOCK
678 if (nonblock) {
679 flags |= SOCK_NONBLOCK;
680 }
681 #endif
682 ret = accept4(socket, address, address_len, flags);
683 /* accept4 is available since Linux 2.6.28, glibc 2.10. */
684 if (ret != -1) {
685 if (ret <= 2)
686 rb_maygvl_fd_fix_cloexec(ret);
687 #ifndef SOCK_NONBLOCK
688 if (nonblock) {
689 rsock_make_fd_nonblock(ret);
690 }
691 #endif
692 if (address_len && len0 < *address_len) *address_len = len0;
693 return ret;
694 }
695 if (errno != ENOSYS) {
696 return -1;
697 }
698 try_accept4 = 0;
699 }
700 #endif
701 ret = accept(socket, address, address_len);
702 if (ret == -1) return -1;
703 if (address_len && len0 < *address_len) *address_len = len0;
704 rb_maygvl_fd_fix_cloexec(ret);
705 if (nonblock) {
706 rsock_make_fd_nonblock(ret);
707 }
708 return ret;
709 }
710
711 VALUE
rsock_s_accept_nonblock(VALUE klass,VALUE ex,rb_io_t * fptr,struct sockaddr * sockaddr,socklen_t * len)712 rsock_s_accept_nonblock(VALUE klass, VALUE ex, rb_io_t *fptr,
713 struct sockaddr *sockaddr, socklen_t *len)
714 {
715 int fd2;
716
717 rb_io_set_nonblock(fptr);
718 fd2 = cloexec_accept(fptr->fd, (struct sockaddr*)sockaddr, len, 1);
719 if (fd2 < 0) {
720 int e = errno;
721 switch (e) {
722 case EAGAIN:
723 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
724 case EWOULDBLOCK:
725 #endif
726 case ECONNABORTED:
727 #if defined EPROTO
728 case EPROTO:
729 #endif
730 if (ex == Qfalse)
731 return sym_wait_readable;
732 rb_readwrite_syserr_fail(RB_IO_WAIT_READABLE, e, "accept(2) would block");
733 }
734 rb_syserr_fail(e, "accept(2)");
735 }
736 rb_update_max_fd(fd2);
737 return rsock_init_sock(rb_obj_alloc(klass), fd2);
738 }
739
740 struct accept_arg {
741 int fd;
742 struct sockaddr *sockaddr;
743 socklen_t *len;
744 };
745
746 static VALUE
accept_blocking(void * data)747 accept_blocking(void *data)
748 {
749 struct accept_arg *arg = data;
750 return (VALUE)cloexec_accept(arg->fd, arg->sockaddr, arg->len, 0);
751 }
752
753 VALUE
rsock_s_accept(VALUE klass,int fd,struct sockaddr * sockaddr,socklen_t * len)754 rsock_s_accept(VALUE klass, int fd, struct sockaddr *sockaddr, socklen_t *len)
755 {
756 int fd2;
757 int retry = 0;
758 struct accept_arg arg;
759
760 arg.fd = fd;
761 arg.sockaddr = sockaddr;
762 arg.len = len;
763 retry:
764 rsock_maybe_wait_fd(fd);
765 fd2 = (int)BLOCKING_REGION_FD(accept_blocking, &arg);
766 if (fd2 < 0) {
767 int e = errno;
768 switch (e) {
769 case EMFILE:
770 case ENFILE:
771 case ENOMEM:
772 if (retry) break;
773 rb_gc();
774 retry = 1;
775 goto retry;
776 default:
777 if (!rb_io_wait_readable(fd)) break;
778 retry = 0;
779 goto retry;
780 }
781 rb_syserr_fail(e, "accept(2)");
782 }
783 rb_update_max_fd(fd2);
784 if (!klass) return INT2NUM(fd2);
785 return rsock_init_sock(rb_obj_alloc(klass), fd2);
786 }
787
788 int
rsock_getfamily(rb_io_t * fptr)789 rsock_getfamily(rb_io_t *fptr)
790 {
791 union_sockaddr ss;
792 socklen_t sslen = (socklen_t)sizeof(ss);
793 int cached = fptr->mode & FMODE_SOCK;
794
795 if (cached) {
796 switch (cached) {
797 #ifdef AF_UNIX
798 case FMODE_UNIX: return AF_UNIX;
799 #endif
800 case FMODE_INET: return AF_INET;
801 case FMODE_INET6: return AF_INET6;
802 }
803 }
804
805 ss.addr.sa_family = AF_UNSPEC;
806 if (getsockname(fptr->fd, &ss.addr, &sslen) < 0)
807 return AF_UNSPEC;
808
809 switch (ss.addr.sa_family) {
810 #ifdef AF_UNIX
811 case AF_UNIX: fptr->mode |= FMODE_UNIX; break;
812 #endif
813 case AF_INET: fptr->mode |= FMODE_INET; break;
814 case AF_INET6: fptr->mode |= FMODE_INET6; break;
815 }
816
817 return ss.addr.sa_family;
818 }
819
820 void
rsock_init_socket_init(void)821 rsock_init_socket_init(void)
822 {
823 /*
824 * SocketError is the error class for socket.
825 */
826 rb_eSocket = rb_define_class("SocketError", rb_eStandardError);
827 rsock_init_ipsocket();
828 rsock_init_tcpsocket();
829 rsock_init_tcpserver();
830 rsock_init_sockssocket();
831 rsock_init_udpsocket();
832 rsock_init_unixsocket();
833 rsock_init_unixserver();
834 rsock_init_sockopt();
835 rsock_init_ancdata();
836 rsock_init_addrinfo();
837 rsock_init_sockifaddr();
838 rsock_init_socket_constants();
839
840 #undef rb_intern
841 sym_wait_readable = ID2SYM(rb_intern("wait_readable"));
842
843 #if MSG_DONTWAIT_RELIABLE
844 sym_wait_writable = ID2SYM(rb_intern("wait_writable"));
845 #endif
846 }
847