Ruby 2.7.0p0(2019-12-25revision647ee6f091eafcce70ffb75ddf7e121e192ab217)

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