diff options
Diffstat (limited to 'ext/socket')
| -rw-r--r-- | ext/socket/addrinfo.h | 36 | ||||
| -rw-r--r-- | ext/socket/ancdata.c | 297 | ||||
| -rw-r--r-- | ext/socket/basicsocket.c | 157 | ||||
| -rw-r--r-- | ext/socket/constants.c | 7 | ||||
| -rw-r--r-- | ext/socket/depend | 2940 | ||||
| -rw-r--r-- | ext/socket/extconf.rb | 58 | ||||
| -rw-r--r-- | ext/socket/getaddrinfo.c | 898 | ||||
| -rw-r--r-- | ext/socket/getnameinfo.c | 224 | ||||
| -rw-r--r-- | ext/socket/ifaddr.c | 13 | ||||
| -rw-r--r-- | ext/socket/init.c | 538 | ||||
| -rw-r--r-- | ext/socket/ipsocket.c | 1490 | ||||
| -rw-r--r-- | ext/socket/lib/socket.rb | 542 | ||||
| -rw-r--r-- | ext/socket/mkconstants.rb | 86 | ||||
| -rw-r--r-- | ext/socket/option.c | 102 | ||||
| -rw-r--r-- | ext/socket/raddrinfo.c | 1249 | ||||
| -rw-r--r-- | ext/socket/rubysocket.h | 184 | ||||
| -rw-r--r-- | ext/socket/socket.c | 742 | ||||
| -rw-r--r-- | ext/socket/sockssocket.c | 21 | ||||
| -rw-r--r-- | ext/socket/tcpserver.c | 26 | ||||
| -rw-r--r-- | ext/socket/tcpsocket.c | 63 | ||||
| -rw-r--r-- | ext/socket/udpsocket.c | 111 | ||||
| -rw-r--r-- | ext/socket/unixserver.c | 31 | ||||
| -rw-r--r-- | ext/socket/unixsocket.c | 182 |
23 files changed, 7740 insertions, 2257 deletions
diff --git a/ext/socket/addrinfo.h b/ext/socket/addrinfo.h index f0b977d79c..eb9eb8ae0e 100644 --- a/ext/socket/addrinfo.h +++ b/ext/socket/addrinfo.h @@ -129,14 +129,14 @@ #ifndef HAVE_TYPE_STRUCT_ADDRINFO struct addrinfo { - int ai_flags; /* AI_PASSIVE, AI_CANONNAME */ - int ai_family; /* PF_xxx */ - int ai_socktype; /* SOCK_xxx */ - int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */ - size_t ai_addrlen; /* length of ai_addr */ - char *ai_canonname; /* canonical name for hostname */ - struct sockaddr *ai_addr; /* binary address */ - struct addrinfo *ai_next; /* next structure in linked list */ + int ai_flags; /* AI_PASSIVE, AI_CANONNAME */ + int ai_family; /* PF_xxx */ + int ai_socktype; /* SOCK_xxx */ + int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */ + size_t ai_addrlen; /* length of ai_addr */ + char *ai_canonname; /* canonical name for hostname */ + struct sockaddr *ai_addr; /* binary address */ + struct addrinfo *ai_next; /* next structure in linked list */ }; #endif @@ -158,18 +158,18 @@ struct addrinfo { #endif extern int getaddrinfo __P(( - const char *hostname, const char *servname, - const struct addrinfo *hints, - struct addrinfo **res)); + const char *hostname, const char *servname, + const struct addrinfo *hints, + struct addrinfo **res)); extern int getnameinfo __P(( - const struct sockaddr *sa, - socklen_t salen, - char *host, - socklen_t hostlen, - char *serv, - socklen_t servlen, - int flags)); + const struct sockaddr *sa, + socklen_t salen, + char *host, + socklen_t hostlen, + char *serv, + socklen_t servlen, + int flags)); extern void freehostent __P((struct hostent *)); extern void freeaddrinfo __P((struct addrinfo *)); diff --git a/ext/socket/ancdata.c b/ext/socket/ancdata.c index 69c766e6fd..f1e9e42524 100644 --- a/ext/socket/ancdata.c +++ b/ext/socket/ancdata.c @@ -2,7 +2,6 @@ #include <time.h> -int rsock_cmsg_cloexec_state = -1; /* <0: unknown, 0: ignored, >0: working */ static VALUE sym_wait_readable, sym_wait_writable; #if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL) @@ -89,9 +88,9 @@ ancillary_initialize(VALUE self, VALUE vfamily, VALUE vlevel, VALUE vtype, VALUE static VALUE ancdata_new(int family, int level, int type, VALUE data) { - NEWOBJ_OF(obj, struct RObject, rb_cAncillaryData, T_OBJECT); + VALUE obj = rb_obj_alloc(rb_cAncillaryData); StringValue(data); - ancillary_initialize((VALUE)obj, INT2NUM(family), INT2NUM(level), INT2NUM(type), data); + ancillary_initialize(obj, INT2NUM(family), INT2NUM(level), INT2NUM(type), data); return (VALUE)obj; } @@ -334,11 +333,11 @@ ancillary_timestamp(VALUE self) if (level == SOL_SOCKET && type == SCM_BINTIME && RSTRING_LEN(data) == sizeof(struct bintime)) { struct bintime bt; - VALUE d, timev; + VALUE d, timev; memcpy((char*)&bt, RSTRING_PTR(data), sizeof(bt)); - d = ULL2NUM(0x100000000ULL); - d = mul(d,d); - timev = add(TIMET2NUM(bt.sec), quo(ULL2NUM(bt.frac), d)); + d = ULL2NUM(0x100000000ULL); + d = mul(d,d); + timev = add(TIMET2NUM(bt.sec), quo(ULL2NUM(bt.frac), d)); result = rb_time_num_new(timev, Qnil); } # endif @@ -698,7 +697,7 @@ anc_inspect_passcred_credentials(int level, int type, VALUE data, VALUE ret) struct ucred cred; memcpy(&cred, RSTRING_PTR(data), sizeof(struct ucred)); rb_str_catf(ret, " pid=%u uid=%u gid=%u", cred.pid, cred.uid, cred.gid); - rb_str_cat2(ret, " (ucred)"); + rb_str_cat2(ret, " (ucred)"); return 1; } else { @@ -713,7 +712,7 @@ static int anc_inspect_socket_creds(int level, int type, VALUE data, VALUE ret) { if (level != SOL_SOCKET && type != SCM_CREDS) - return 0; + return 0; /* * FreeBSD has struct cmsgcred and struct sockcred. @@ -728,46 +727,46 @@ anc_inspect_socket_creds(int level, int type, VALUE data, VALUE ret) #if defined(HAVE_TYPE_STRUCT_CMSGCRED) /* FreeBSD */ if (RSTRING_LEN(data) == sizeof(struct cmsgcred)) { - struct cmsgcred cred; + struct cmsgcred cred; memcpy(&cred, RSTRING_PTR(data), sizeof(struct cmsgcred)); rb_str_catf(ret, " pid=%u", cred.cmcred_pid); rb_str_catf(ret, " uid=%u", cred.cmcred_uid); rb_str_catf(ret, " euid=%u", cred.cmcred_euid); rb_str_catf(ret, " gid=%u", cred.cmcred_gid); - if (cred.cmcred_ngroups) { - int i; - const char *sep = " groups="; - for (i = 0; i < cred.cmcred_ngroups; i++) { - rb_str_catf(ret, "%s%u", sep, cred.cmcred_groups[i]); - sep = ","; - } - } - rb_str_cat2(ret, " (cmsgcred)"); + if (cred.cmcred_ngroups) { + int i; + const char *sep = " groups="; + for (i = 0; i < cred.cmcred_ngroups; i++) { + rb_str_catf(ret, "%s%u", sep, cred.cmcred_groups[i]); + sep = ","; + } + } + rb_str_cat2(ret, " (cmsgcred)"); return 1; } #endif #if defined(HAVE_TYPE_STRUCT_SOCKCRED) /* FreeBSD, NetBSD */ if ((size_t)RSTRING_LEN(data) >= SOCKCREDSIZE(0)) { - struct sockcred cred0, *cred; + struct sockcred cred0, *cred; memcpy(&cred0, RSTRING_PTR(data), SOCKCREDSIZE(0)); - if ((size_t)RSTRING_LEN(data) == SOCKCREDSIZE(cred0.sc_ngroups)) { - cred = (struct sockcred *)ALLOCA_N(char, SOCKCREDSIZE(cred0.sc_ngroups)); - memcpy(cred, RSTRING_PTR(data), SOCKCREDSIZE(cred0.sc_ngroups)); - rb_str_catf(ret, " uid=%u", cred->sc_uid); - rb_str_catf(ret, " euid=%u", cred->sc_euid); - rb_str_catf(ret, " gid=%u", cred->sc_gid); - rb_str_catf(ret, " egid=%u", cred->sc_egid); - if (cred0.sc_ngroups) { - int i; - const char *sep = " groups="; - for (i = 0; i < cred0.sc_ngroups; i++) { - rb_str_catf(ret, "%s%u", sep, cred->sc_groups[i]); - sep = ","; - } - } - rb_str_cat2(ret, " (sockcred)"); - return 1; - } + if ((size_t)RSTRING_LEN(data) == SOCKCREDSIZE(cred0.sc_ngroups)) { + cred = (struct sockcred *)ALLOCA_N(char, SOCKCREDSIZE(cred0.sc_ngroups)); + memcpy(cred, RSTRING_PTR(data), SOCKCREDSIZE(cred0.sc_ngroups)); + rb_str_catf(ret, " uid=%u", cred->sc_uid); + rb_str_catf(ret, " euid=%u", cred->sc_euid); + rb_str_catf(ret, " gid=%u", cred->sc_gid); + rb_str_catf(ret, " egid=%u", cred->sc_egid); + if (cred0.sc_ngroups) { + int i; + const char *sep = " groups="; + for (i = 0; i < cred0.sc_ngroups; i++) { + rb_str_catf(ret, "%s%u", sep, cred->sc_groups[i]); + sep = ","; + } + } + rb_str_cat2(ret, " (sockcred)"); + return 1; + } } #endif return 0; @@ -852,6 +851,12 @@ anc_inspect_ipv6_pktinfo(int level, int type, VALUE data, VALUE ret) } #endif +#ifdef HAVE_GMTIME_R +# define LOCALTIME(time, tm) localtime_r(&(time), &(tm)) +#else +# define LOCALTIME(time, tm) ((tm) = *localtime(&(time))) +#endif + #if defined(SCM_TIMESTAMP) /* GNU/Linux, FreeBSD, NetBSD, OpenBSD, MacOS X, Solaris */ static int inspect_timeval_as_abstime(int level, int optname, VALUE data, VALUE ret) @@ -863,7 +868,7 @@ inspect_timeval_as_abstime(int level, int optname, VALUE data, VALUE ret) char buf[32]; memcpy((char*)&tv, RSTRING_PTR(data), sizeof(tv)); time = tv.tv_sec; - tm = *localtime(&time); + LOCALTIME(time, tm); strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &tm); rb_str_catf(ret, " %s.%06ld", buf, (long)tv.tv_usec); return 1; @@ -883,7 +888,7 @@ inspect_timespec_as_abstime(int level, int optname, VALUE data, VALUE ret) struct tm tm; char buf[32]; memcpy((char*)&ts, RSTRING_PTR(data), sizeof(ts)); - tm = *localtime(&ts.tv_sec); + LOCALTIME(ts.tv_sec, tm); strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &tm); rb_str_catf(ret, " %s.%09ld", buf, (long)ts.tv_nsec); return 1; @@ -901,37 +906,37 @@ inspect_bintime_as_abstime(int level, int optname, VALUE data, VALUE ret) if (RSTRING_LEN(data) == sizeof(struct bintime)) { struct bintime bt; struct tm tm; - uint64_t frac_h, frac_l; - uint64_t scale_h, scale_l; - uint64_t tmp1, tmp2; - uint64_t res_h, res_l; + uint64_t frac_h, frac_l; + uint64_t scale_h, scale_l; + uint64_t tmp1, tmp2; + uint64_t res_h, res_l; char buf[32]; memcpy((char*)&bt, RSTRING_PTR(data), sizeof(bt)); - tm = *localtime(&bt.sec); + LOCALTIME(bt.sec, tm); strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &tm); - /* res_h = frac * 10**19 / 2**64 */ + /* res_h = frac * 10**19 / 2**64 */ - frac_h = bt.frac >> 32; - frac_l = bt.frac & 0xffffffff; + frac_h = bt.frac >> 32; + frac_l = bt.frac & 0xffffffff; - scale_h = 0x8ac72304; /* 0x8ac7230489e80000 == 10**19 */ - scale_l = 0x89e80000; + scale_h = 0x8ac72304; /* 0x8ac7230489e80000 == 10**19 */ + scale_l = 0x89e80000; - res_h = frac_h * scale_h; - res_l = frac_l * scale_l; + res_h = frac_h * scale_h; + res_l = frac_l * scale_l; - tmp1 = frac_h * scale_l; - res_h += tmp1 >> 32; - tmp2 = res_l; - res_l += tmp1 & 0xffffffff; - if (res_l < tmp2) res_h++; + tmp1 = frac_h * scale_l; + res_h += tmp1 >> 32; + tmp2 = res_l; + res_l += tmp1 & 0xffffffff; + if (res_l < tmp2) res_h++; - tmp1 = frac_l * scale_h; - res_h += tmp1 >> 32; - tmp2 = res_l; - res_l += tmp1 & 0xffffffff; - if (res_l < tmp2) res_h++; + tmp1 = frac_l * scale_h; + res_h += tmp1 >> 32; + tmp2 = res_l; + res_l += tmp1 & 0xffffffff; + if (res_l < tmp2) res_h++; rb_str_catf(ret, " %s.%019"PRIu64, buf, res_h); return 1; @@ -1131,8 +1136,8 @@ rb_sendmsg(int fd, const struct msghdr *msg, int flags) static VALUE bsock_sendmsg_internal(VALUE sock, VALUE data, VALUE vflags, - VALUE dest_sockaddr, VALUE controls, VALUE ex, - int nonblock) + VALUE dest_sockaddr, VALUE controls, VALUE ex, + int nonblock) { rb_io_t *fptr; struct msghdr mh; @@ -1155,15 +1160,15 @@ bsock_sendmsg_internal(VALUE sock, VALUE data, VALUE vflags, tmp = rb_str_tmp_frozen_acquire(data); if (!RB_TYPE_P(controls, T_ARRAY)) { - controls = rb_ary_new(); + controls = rb_ary_new(); } controls_num = RARRAY_LENINT(controls); if (controls_num) { #if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL) - int i; - size_t last_pad = 0; - const VALUE *controls_ptr = RARRAY_CONST_PTR(controls); + int i; + size_t last_pad = 0; + const VALUE *controls_ptr = RARRAY_CONST_PTR(controls); #if defined(__NetBSD__) int last_level = 0; int last_type = 0; @@ -1210,9 +1215,9 @@ bsock_sendmsg_internal(VALUE sock, VALUE data, VALUE vflags, last_level = cmh.cmsg_level; last_type = cmh.cmsg_type; #endif - last_pad = cspace - cmh.cmsg_len; + last_pad = cspace - cmh.cmsg_len; } - if (last_pad) { + if (last_pad) { /* * This code removes the last padding from msg_controllen. * @@ -1237,10 +1242,10 @@ bsock_sendmsg_internal(VALUE sock, VALUE data, VALUE vflags, if (last_level == SOL_SOCKET && last_type == SCM_RIGHTS) rb_str_set_len(controls_str, RSTRING_LEN(controls_str)-last_pad); #endif - } - RB_GC_GUARD(controls); + } + RB_GC_GUARD(controls); #else - rb_raise(rb_eNotImpError, "control message for sendmsg is unimplemented"); + rb_raise(rb_eNotImpError, "control message for sendmsg is unimplemented"); #endif } @@ -1251,7 +1256,7 @@ bsock_sendmsg_internal(VALUE sock, VALUE data, VALUE vflags, #endif if (!NIL_P(dest_sockaddr)) - SockAddrStringValue(dest_sockaddr); + SockAddrStringValue(dest_sockaddr); rb_io_check_closed(fptr); @@ -1279,20 +1284,20 @@ bsock_sendmsg_internal(VALUE sock, VALUE data, VALUE vflags, ss = rb_sendmsg(fptr->fd, &mh, flags); if (ss == -1) { - int e; - if (!nonblock && rb_io_wait_writable(fptr->fd)) { + int e; + if (!nonblock && rb_io_maybe_wait_writable(errno, fptr->self, RUBY_IO_TIMEOUT_DEFAULT)) { rb_io_check_closed(fptr); goto retry; } - e = errno; - if (nonblock && (e == EWOULDBLOCK || e == EAGAIN)) { - if (ex == Qfalse) { - return sym_wait_writable; - } - rb_readwrite_syserr_fail(RB_IO_WAIT_WRITABLE, e, - "sendmsg(2) would block"); - } - rb_syserr_fail(e, "sendmsg(2)"); + e = errno; + if (nonblock && (e == EWOULDBLOCK || e == EAGAIN)) { + if (ex == Qfalse) { + return sym_wait_writable; + } + rb_readwrite_syserr_fail(RB_IO_WAIT_WRITABLE, e, + "sendmsg(2) would block"); + } + rb_syserr_fail(e, "sendmsg(2)"); } #if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL) RB_GC_GUARD(controls_str); @@ -1306,20 +1311,20 @@ bsock_sendmsg_internal(VALUE sock, VALUE data, VALUE vflags, #if defined(HAVE_SENDMSG) VALUE rsock_bsock_sendmsg(VALUE sock, VALUE data, VALUE flags, VALUE dest_sockaddr, - VALUE controls) + VALUE controls) { return bsock_sendmsg_internal(sock, data, flags, dest_sockaddr, controls, - Qtrue, 0); + Qtrue, 0); } #endif #if defined(HAVE_SENDMSG) VALUE rsock_bsock_sendmsg_nonblock(VALUE sock, VALUE data, VALUE flags, - VALUE dest_sockaddr, VALUE controls, VALUE ex) + VALUE dest_sockaddr, VALUE controls, VALUE ex) { return bsock_sendmsg_internal(sock, data, flags, dest_sockaddr, - controls, ex, 1); + controls, ex, 1); } #endif @@ -1417,22 +1422,19 @@ make_io_for_unix_rights(VALUE ctl, struct cmsghdr *cmh, char *msg_end) { if (cmh->cmsg_level == SOL_SOCKET && cmh->cmsg_type == SCM_RIGHTS) { int *fdp, *end; - VALUE ary = rb_ary_new(); - rb_ivar_set(ctl, rb_intern("unix_rights"), ary); + VALUE ary = rb_ary_new(); + rb_ivar_set(ctl, rb_intern("unix_rights"), ary); fdp = (int *)CMSG_DATA(cmh); end = (int *)((char *)cmh + cmh->cmsg_len); while ((char *)fdp + sizeof(int) <= (char *)end && - (char *)fdp + sizeof(int) <= msg_end) { + (char *)fdp + sizeof(int) <= msg_end) { int fd = *fdp; struct stat stbuf; VALUE io; if (fstat(fd, &stbuf) == -1) rb_raise(rb_eSocket, "invalid fd in SCM_RIGHTS"); rb_update_max_fd(fd); - if (rsock_cmsg_cloexec_state < 0) - rsock_cmsg_cloexec_state = rsock_detect_cloexec(fd); - if (rsock_cmsg_cloexec_state == 0 || fd <= 2) - rb_maygvl_fd_fix_cloexec(fd); + rb_maygvl_fd_fix_cloexec(fd); if (S_ISSOCK(stbuf.st_mode)) io = rsock_init_sock(rb_obj_alloc(rb_cSocket), fd); else @@ -1441,15 +1443,15 @@ make_io_for_unix_rights(VALUE ctl, struct cmsghdr *cmh, char *msg_end) rb_ary_push(ary, io); fdp++; } - OBJ_FREEZE(ary); + OBJ_FREEZE(ary); } } #endif static VALUE bsock_recvmsg_internal(VALUE sock, - VALUE vmaxdatlen, VALUE vflags, VALUE vmaxctllen, - VALUE scm_rights, VALUE ex, int nonblock) + VALUE vmaxdatlen, VALUE vflags, VALUE vmaxctllen, + VALUE scm_rights, VALUE ex, int nonblock) { rb_io_t *fptr; int grow_buffer; @@ -1503,28 +1505,28 @@ bsock_recvmsg_internal(VALUE sock, #if !defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL) if (grow_buffer) { - int socktype; - socklen_t optlen = (socklen_t)sizeof(socktype); + int socktype; + socklen_t optlen = (socklen_t)sizeof(socktype); if (getsockopt(fptr->fd, SOL_SOCKET, SO_TYPE, (void*)&socktype, &optlen) == -1) { - rb_sys_fail("getsockopt(SO_TYPE)"); - } - if (socktype == SOCK_STREAM) - grow_buffer = 0; + rb_sys_fail("getsockopt(SO_TYPE)"); + } + if (socktype == SOCK_STREAM) + grow_buffer = 0; } #endif retry: if (NIL_P(dat_str)) - dat_str = rb_str_tmp_new(maxdatlen); + dat_str = rb_str_tmp_new(maxdatlen); else - rb_str_resize(dat_str, maxdatlen); + rb_str_resize(dat_str, maxdatlen); datbuf = RSTRING_PTR(dat_str); #if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL) if (NIL_P(ctl_str)) - ctl_str = rb_str_tmp_new(maxctllen); + ctl_str = rb_str_tmp_new(maxctllen); else - rb_str_resize(ctl_str, maxctllen); + rb_str_resize(ctl_str, maxctllen); ctlbuf = RSTRING_PTR(ctl_str); #endif @@ -1553,21 +1555,25 @@ bsock_recvmsg_internal(VALUE sock, ss = rb_recvmsg(fptr->fd, &mh, flags); + if (ss == 0 && !rsock_is_dgram(fptr)) { + return Qnil; + } + if (ss == -1) { - int e; - if (!nonblock && rb_io_wait_readable(fptr->fd)) { + int e; + if (!nonblock && rb_io_maybe_wait_readable(errno, fptr->self, RUBY_IO_TIMEOUT_DEFAULT)) { rb_io_check_closed(fptr); goto retry; } - e = errno; - if (nonblock && (e == EWOULDBLOCK || e == EAGAIN)) { + e = errno; + if (nonblock && (e == EWOULDBLOCK || e == EAGAIN)) { if (ex == Qfalse) { return sym_wait_readable; } - rb_readwrite_syserr_fail(RB_IO_WAIT_READABLE, e, "recvmsg(2) would block"); + rb_readwrite_syserr_fail(RB_IO_WAIT_READABLE, e, "recvmsg(2) would block"); } #if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL) - if (!gc_done && (e == EMFILE || e == EMSGSIZE)) { + if (!gc_done && (e == EMFILE || e == EMSGSIZE)) { /* * When SCM_RIGHTS hit the file descriptors limit: * - Linux 2.6.18 causes success with MSG_CTRUNC @@ -1577,24 +1583,24 @@ bsock_recvmsg_internal(VALUE sock, gc_and_retry: rb_gc(); gc_done = 1; - goto retry; + goto retry; } #else - if (NIL_P(vmaxdatlen) && grow_buffer && e == EMSGSIZE) - ss = (ssize_t)iov.iov_len; - else + if (NIL_P(vmaxdatlen) && grow_buffer && e == EMSGSIZE) + ss = (ssize_t)iov.iov_len; + else #endif - rb_syserr_fail(e, "recvmsg(2)"); + rb_syserr_fail(e, "recvmsg(2)"); } if (grow_buffer) { - int grown = 0; - if (NIL_P(vmaxdatlen) && ss != -1 && ss == (ssize_t)iov.iov_len) { + int grown = 0; + if (NIL_P(vmaxdatlen) && ss != -1 && ss == (ssize_t)iov.iov_len) { if (SIZE_MAX/2 < maxdatlen) rb_raise(rb_eArgError, "max data length too big"); - maxdatlen *= 2; - grown = 1; - } + maxdatlen *= 2; + grown = 1; + } #if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL) if (NIL_P(vmaxctllen) && (mh.msg_flags & MSG_CTRUNC)) { #define BIG_ENOUGH_SPACE 65536 @@ -1603,9 +1609,9 @@ bsock_recvmsg_internal(VALUE sock, /* there are big space bug truncated. * file descriptors limit? */ if (!gc_done) { - rsock_discard_cmsg_resource(&mh, (flags & MSG_PEEK) != 0); + rsock_discard_cmsg_resource(&mh, (flags & MSG_PEEK) != 0); goto gc_and_retry; - } + } } else { if (SIZE_MAX/2 < maxctllen) @@ -1614,13 +1620,13 @@ bsock_recvmsg_internal(VALUE sock, grown = 1; } #undef BIG_ENOUGH_SPACE - } + } #endif - if (grown) { + if (grown) { rsock_discard_cmsg_resource(&mh, (flags & MSG_PEEK) != 0); - goto retry; - } - else { + goto retry; + } + else { grow_buffer = 0; if (flags != orig_flags) { rsock_discard_cmsg_resource(&mh, (flags & MSG_PEEK) != 0); @@ -1631,36 +1637,35 @@ bsock_recvmsg_internal(VALUE sock, } if (NIL_P(dat_str)) - dat_str = rb_tainted_str_new(datbuf, ss); + dat_str = rb_str_new(datbuf, ss); else { rb_str_resize(dat_str, ss); - OBJ_TAINT(dat_str); - rb_obj_reveal(dat_str, rb_cString); + rb_obj_reveal(dat_str, rb_cString); } - ret = rb_ary_new3(3, dat_str, - rsock_io_socket_addrinfo(sock, mh.msg_name, mh.msg_namelen), #if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL) - INT2NUM(mh.msg_flags) + VALUE msg_flags = INT2NUM(mh.msg_flags); #else - Qnil + VALUE msg_flags = Qnil; #endif - ); + ret = rb_ary_new3(3, dat_str, + rsock_io_socket_addrinfo(sock, mh.msg_name, mh.msg_namelen), + msg_flags); #if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL) family = rsock_getfamily(fptr); if (mh.msg_controllen) { - char *msg_end = (char *)mh.msg_control + mh.msg_controllen; + char *msg_end = (char *)mh.msg_control + mh.msg_controllen; for (cmh = CMSG_FIRSTHDR(&mh); cmh != NULL; cmh = CMSG_NXTHDR(&mh, cmh)) { VALUE ctl; - char *ctl_end; + char *ctl_end; size_t clen; if (cmh->cmsg_len == 0) { rb_raise(rb_eTypeError, "invalid control message (cmsg_len == 0)"); } ctl_end = (char*)cmh + cmh->cmsg_len; - clen = (ctl_end <= msg_end ? ctl_end : msg_end) - (char*)CMSG_DATA(cmh); - ctl = ancdata_new(family, cmh->cmsg_level, cmh->cmsg_type, rb_tainted_str_new((char*)CMSG_DATA(cmh), clen)); + clen = (ctl_end <= msg_end ? ctl_end : msg_end) - (char*)CMSG_DATA(cmh); + ctl = ancdata_new(family, cmh->cmsg_level, cmh->cmsg_type, rb_str_new((char*)CMSG_DATA(cmh), clen)); if (request_scm_rights) make_io_for_unix_rights(ctl, cmh, msg_end); else @@ -1678,7 +1683,7 @@ bsock_recvmsg_internal(VALUE sock, #if defined(HAVE_RECVMSG) VALUE rsock_bsock_recvmsg(VALUE sock, VALUE dlen, VALUE flags, VALUE clen, - VALUE scm_rights) + VALUE scm_rights) { VALUE ex = Qtrue; return bsock_recvmsg_internal(sock, dlen, flags, clen, scm_rights, ex, 0); @@ -1688,7 +1693,7 @@ rsock_bsock_recvmsg(VALUE sock, VALUE dlen, VALUE flags, VALUE clen, #if defined(HAVE_RECVMSG) VALUE rsock_bsock_recvmsg_nonblock(VALUE sock, VALUE dlen, VALUE flags, VALUE clen, - VALUE scm_rights, VALUE ex) + VALUE scm_rights, VALUE ex) { return bsock_recvmsg_internal(sock, dlen, flags, clen, scm_rights, ex, 1); } diff --git a/ext/socket/basicsocket.c b/ext/socket/basicsocket.c index 1371672850..2fcae8eb54 100644 --- a/ext/socket/basicsocket.c +++ b/ext/socket/basicsocket.c @@ -10,6 +10,28 @@ #include "rubysocket.h" +#ifdef _WIN32 +#define is_socket(fd) rb_w32_is_socket(fd) +#else +static int +is_socket(int fd) +{ + struct stat sbuf; + + if (fstat(fd, &sbuf) < 0) + rb_sys_fail("fstat(2)"); + return S_ISSOCK(sbuf.st_mode); +} +#endif + +static void +rsock_validate_descriptor(int descriptor) +{ + if (!is_socket(descriptor) || rb_reserved_fd_p(descriptor)) { + rb_syserr_fail(EBADF, "not a socket file descriptor"); + } +} + /* * call-seq: * BasicSocket.for_fd(fd) => basicsocket @@ -22,10 +44,14 @@ * */ static VALUE -bsock_s_for_fd(VALUE klass, VALUE fd) +bsock_s_for_fd(VALUE klass, VALUE _descriptor) { rb_io_t *fptr; - VALUE sock = rsock_init_sock(rb_obj_alloc(klass), NUM2INT(fd)); + + int descriptor = RB_NUM2INT(_descriptor); + rsock_validate_descriptor(descriptor); + + VALUE sock = rsock_init_sock(rb_obj_alloc(klass), descriptor); GetOpenFile(sock, fptr); @@ -68,16 +94,16 @@ bsock_shutdown(int argc, VALUE *argv, VALUE sock) rb_scan_args(argc, argv, "01", &howto); if (howto == Qnil) - how = SHUT_RDWR; + how = SHUT_RDWR; else { - how = rsock_shutdown_how_arg(howto); + how = rsock_shutdown_how_arg(howto); if (how != SHUT_WR && how != SHUT_RD && how != SHUT_RDWR) { - rb_raise(rb_eArgError, "`how' should be either :SHUT_RD, :SHUT_WR, :SHUT_RDWR"); - } + rb_raise(rb_eArgError, "`how' should be either :SHUT_RD, :SHUT_WR, :SHUT_RDWR"); + } } GetOpenFile(sock, fptr); if (shutdown(fptr->fd, how) == -1) - rb_sys_fail("shutdown(2)"); + rb_sys_fail("shutdown(2)"); return INT2FIX(0); } @@ -98,9 +124,9 @@ bsock_close_read(VALUE sock) rb_io_t *fptr; GetOpenFile(sock, fptr); - shutdown(fptr->fd, 0); + shutdown(fptr->fd, SHUT_RD); if (!(fptr->mode & FMODE_WRITABLE)) { - return rb_io_close(sock); + return rb_io_close(sock); } fptr->mode &= ~FMODE_READABLE; @@ -129,9 +155,9 @@ bsock_close_write(VALUE sock) GetOpenFile(sock, fptr); if (!(fptr->mode & FMODE_READABLE)) { - return rb_io_close(sock); + return rb_io_close(sock); } - shutdown(fptr->fd, 1); + shutdown(fptr->fd, SHUT_WR); fptr->mode &= ~FMODE_WRITABLE; return Qnil; @@ -220,21 +246,21 @@ bsock_setsockopt(int argc, VALUE *argv, VALUE sock) switch (TYPE(val)) { case T_FIXNUM: - i = FIX2INT(val); - goto numval; + i = FIX2INT(val); + goto numval; case T_FALSE: - i = 0; - goto numval; + i = 0; + goto numval; case T_TRUE: - i = 1; + i = 1; numval: - v = (char*)&i; vlen = (int)sizeof(i); - break; + v = (char*)&i; vlen = (int)sizeof(i); + break; default: - StringValue(val); - v = RSTRING_PTR(val); - vlen = RSTRING_SOCKLEN(val); - break; + StringValue(val); + v = RSTRING_PTR(val); + vlen = RSTRING_SOCKLEN(val); + break; } rb_io_check_closed(fptr); @@ -280,7 +306,7 @@ bsock_setsockopt(int argc, VALUE *argv, VALUE sock) * ipttl = sock.getsockopt(:IP, :TTL).int * * optval = sock.getsockopt(Socket::IPPROTO_IP, Socket::IP_TTL) - * ipttl = optval.unpack("i")[0] + * ipttl = optval.unpack1("i") * * Option values may be structs. Decoding them can be complex as it involves * examining your system headers to determine the correct definition. An @@ -331,7 +357,7 @@ bsock_getsockopt(VALUE sock, VALUE lev, VALUE optname) rb_io_check_closed(fptr); if (getsockopt(fptr->fd, level, option, buf, &len) < 0) - rsock_sys_fail_path("getsockopt(2)", fptr->pathv); + rsock_sys_fail_path("getsockopt(2)", fptr->pathv); return rsock_sockopt_new(family, level, option, rb_str_new(buf, len)); } @@ -359,7 +385,7 @@ bsock_getsockname(VALUE sock) GetOpenFile(sock, fptr); if (getsockname(fptr->fd, &buf.addr, &len) < 0) - rb_sys_fail("getsockname(2)"); + rb_sys_fail("getsockname(2)"); if (len0 < len) len = len0; return rb_str_new((char*)&buf, len); } @@ -390,7 +416,7 @@ bsock_getpeername(VALUE sock) GetOpenFile(sock, fptr); if (getpeername(fptr->fd, &buf.addr, &len) < 0) - rb_sys_fail("getpeername(2)"); + rb_sys_fail("getpeername(2)"); if (len0 < len) len = len0; return rb_str_new((char*)&buf, len); } @@ -427,7 +453,7 @@ bsock_getpeereid(VALUE self) gid_t egid; GetOpenFile(self, fptr); if (getpeereid(fptr->fd, &euid, &egid) == -1) - rb_sys_fail("getpeereid(3)"); + rb_sys_fail("getpeereid(3)"); return rb_assoc_new(UIDT2NUM(euid), GIDT2NUM(egid)); #elif defined(SO_PEERCRED) /* GNU/Linux */ rb_io_t *fptr; @@ -435,7 +461,7 @@ bsock_getpeereid(VALUE self) socklen_t len = sizeof(cred); GetOpenFile(self, fptr); if (getsockopt(fptr->fd, SOL_SOCKET, SO_PEERCRED, &cred, &len) == -1) - rb_sys_fail("getsockopt(SO_PEERCRED)"); + rb_sys_fail("getsockopt(SO_PEERCRED)"); return rb_assoc_new(UIDT2NUM(cred.uid), GIDT2NUM(cred.gid)); #elif defined(HAVE_GETPEERUCRED) /* Solaris */ rb_io_t *fptr; @@ -443,7 +469,7 @@ bsock_getpeereid(VALUE self) VALUE ret; GetOpenFile(self, fptr); if (getpeerucred(fptr->fd, &uc) == -1) - rb_sys_fail("getpeerucred(3C)"); + rb_sys_fail("getpeerucred(3C)"); ret = rb_assoc_new(UIDT2NUM(ucred_geteuid(uc)), GIDT2NUM(ucred_getegid(uc))); ucred_free(uc); return ret; @@ -480,7 +506,7 @@ bsock_local_address(VALUE sock) GetOpenFile(sock, fptr); if (getsockname(fptr->fd, &buf.addr, &len) < 0) - rb_sys_fail("getsockname(2)"); + rb_sys_fail("getsockname(2)"); if (len0 < len) len = len0; return rsock_fd_socket_addrinfo(fptr->fd, &buf.addr, len); } @@ -514,7 +540,7 @@ bsock_remote_address(VALUE sock) GetOpenFile(sock, fptr); if (getpeername(fptr->fd, &buf.addr, &len) < 0) - rb_sys_fail("getpeername(2)"); + rb_sys_fail("getpeername(2)"); if (len0 < len) len = len0; return rsock_fd_socket_addrinfo(fptr->fd, &buf.addr, len); } @@ -537,12 +563,11 @@ bsock_remote_address(VALUE sock) * } */ VALUE -rsock_bsock_send(int argc, VALUE *argv, VALUE sock) +rsock_bsock_send(int argc, VALUE *argv, VALUE socket) { struct rsock_send_arg arg; VALUE flags, to; rb_io_t *fptr; - ssize_t n; rb_blocking_function_t *func; const char *funcname; @@ -550,28 +575,38 @@ rsock_bsock_send(int argc, VALUE *argv, VALUE sock) StringValue(arg.mesg); if (!NIL_P(to)) { - SockAddrStringValue(to); - to = rb_str_new4(to); - arg.to = (struct sockaddr *)RSTRING_PTR(to); - arg.tolen = RSTRING_SOCKLEN(to); - func = rsock_sendto_blocking; - funcname = "sendto(2)"; + SockAddrStringValue(to); + to = rb_str_new4(to); + arg.to = (struct sockaddr *)RSTRING_PTR(to); + arg.tolen = RSTRING_SOCKLEN(to); + func = rsock_sendto_blocking; + funcname = "sendto(2)"; } else { - func = rsock_send_blocking; - funcname = "send(2)"; + func = rsock_send_blocking; + funcname = "send(2)"; } - GetOpenFile(sock, fptr); + + RB_IO_POINTER(socket, fptr); + arg.fd = fptr->fd; arg.flags = NUM2INT(flags); - while (rsock_maybe_fd_writable(arg.fd), - (n = (ssize_t)BLOCKING_REGION_FD(func, &arg)) < 0) { - if (rb_io_wait_writable(arg.fd)) { - continue; - } - rb_sys_fail(funcname); + + while (true) { +#ifdef RSOCK_WAIT_BEFORE_BLOCKING + rb_io_wait(socket, RB_INT2NUM(RUBY_IO_WRITABLE), Qnil); +#endif + + ssize_t n = (ssize_t)rb_io_blocking_region(fptr, func, &arg); + + if (n >= 0) return SSIZET2NUM(n); + + if (rb_io_maybe_wait_writable(errno, socket, RUBY_IO_TIMEOUT_DEFAULT)) { + continue; + } + + rb_sys_fail(funcname); } - return SSIZET2NUM(n); } /* @@ -621,10 +656,10 @@ bsock_do_not_reverse_lookup_set(VALUE sock, VALUE state) GetOpenFile(sock, fptr); if (RTEST(state)) { - fptr->mode |= FMODE_NOREVLOOKUP; + fptr->mode |= FMODE_NOREVLOOKUP; } else { - fptr->mode &= ~FMODE_NOREVLOOKUP; + fptr->mode &= ~FMODE_NOREVLOOKUP; } return sock; } @@ -672,7 +707,7 @@ bsock_recv_nonblock(VALUE sock, VALUE len, VALUE flg, VALUE str, VALUE ex) * BasicSocket.do_not_reverse_lookup #=> false */ static VALUE -bsock_do_not_rev_lookup(void) +bsock_do_not_rev_lookup(VALUE _) { return rsock_do_not_reverse_lookup?Qtrue:Qfalse; } @@ -712,9 +747,9 @@ rsock_init_basicsocket(void) rb_undef_method(rb_cBasicSocket, "initialize"); rb_define_singleton_method(rb_cBasicSocket, "do_not_reverse_lookup", - bsock_do_not_rev_lookup, 0); + bsock_do_not_rev_lookup, 0); rb_define_singleton_method(rb_cBasicSocket, "do_not_reverse_lookup=", - bsock_do_not_rev_lookup_set, 1); + bsock_do_not_rev_lookup_set, 1); rb_define_singleton_method(rb_cBasicSocket, "for_fd", bsock_s_for_fd, 1); rb_define_method(rb_cBasicSocket, "close_read", bsock_close_read, 0); @@ -735,23 +770,23 @@ rsock_init_basicsocket(void) /* for ext/socket/lib/socket.rb use only: */ rb_define_private_method(rb_cBasicSocket, - "__recv_nonblock", bsock_recv_nonblock, 4); + "__recv_nonblock", bsock_recv_nonblock, 4); #if MSG_DONTWAIT_RELIABLE rb_define_private_method(rb_cBasicSocket, - "__read_nonblock", rsock_read_nonblock, 3); + "__read_nonblock", rsock_read_nonblock, 3); rb_define_private_method(rb_cBasicSocket, - "__write_nonblock", rsock_write_nonblock, 2); + "__write_nonblock", rsock_write_nonblock, 2); #endif /* in ancdata.c */ rb_define_private_method(rb_cBasicSocket, "__sendmsg", - rsock_bsock_sendmsg, 4); + rsock_bsock_sendmsg, 4); rb_define_private_method(rb_cBasicSocket, "__sendmsg_nonblock", - rsock_bsock_sendmsg_nonblock, 5); + rsock_bsock_sendmsg_nonblock, 5); rb_define_private_method(rb_cBasicSocket, "__recvmsg", - rsock_bsock_recvmsg, 4); + rsock_bsock_recvmsg, 4); rb_define_private_method(rb_cBasicSocket, "__recvmsg_nonblock", - rsock_bsock_recvmsg_nonblock, 5); + rsock_bsock_recvmsg_nonblock, 5); } diff --git a/ext/socket/constants.c b/ext/socket/constants.c index 6fc862777e..1213f2ae17 100644 --- a/ext/socket/constants.c +++ b/ext/socket/constants.c @@ -26,15 +26,14 @@ constant_arg(VALUE arg, int (*str_to_int)(const char*, long, int*), const char * goto str; } else if (!NIL_P(tmp = rb_check_string_type(arg))) { - arg = tmp; + arg = tmp; str: - rb_check_safe_obj(arg); ptr = RSTRING_PTR(arg); if (str_to_int(ptr, RSTRING_LEN(arg), &ret) == -1) - rb_raise(rb_eSocket, "%s: %s", errmsg, ptr); + rb_raise(rb_eSocket, "%s: %s", errmsg, ptr); } else { - ret = NUM2INT(arg); + ret = NUM2INT(arg); } return ret; } diff --git a/ext/socket/depend b/ext/socket/depend index e958b3dc5d..77f6239a3d 100644 --- a/ext/socket/depend +++ b/ext/socket/depend @@ -12,12 +12,172 @@ constdefs.c: constdefs.h # AUTOGENERATED DEPENDENCIES START ancdata.o: $(RUBY_EXTCONF_H) ancdata.o: $(arch_hdrdir)/ruby/config.h -ancdata.o: $(hdrdir)/ruby.h ancdata.o: $(hdrdir)/ruby/assert.h +ancdata.o: $(hdrdir)/ruby/atomic.h ancdata.o: $(hdrdir)/ruby/backward.h +ancdata.o: $(hdrdir)/ruby/backward/2/assume.h +ancdata.o: $(hdrdir)/ruby/backward/2/attributes.h +ancdata.o: $(hdrdir)/ruby/backward/2/bool.h +ancdata.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h +ancdata.o: $(hdrdir)/ruby/backward/2/inttypes.h +ancdata.o: $(hdrdir)/ruby/backward/2/limits.h +ancdata.o: $(hdrdir)/ruby/backward/2/long_long.h +ancdata.o: $(hdrdir)/ruby/backward/2/stdalign.h +ancdata.o: $(hdrdir)/ruby/backward/2/stdarg.h ancdata.o: $(hdrdir)/ruby/defines.h ancdata.o: $(hdrdir)/ruby/encoding.h +ancdata.o: $(hdrdir)/ruby/fiber/scheduler.h ancdata.o: $(hdrdir)/ruby/intern.h +ancdata.o: $(hdrdir)/ruby/internal/abi.h +ancdata.o: $(hdrdir)/ruby/internal/anyargs.h +ancdata.o: $(hdrdir)/ruby/internal/arithmetic.h +ancdata.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ancdata.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ancdata.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ancdata.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ancdata.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ancdata.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ancdata.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ancdata.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ancdata.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ancdata.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ancdata.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ancdata.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ancdata.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ancdata.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ancdata.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ancdata.o: $(hdrdir)/ruby/internal/assume.h +ancdata.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ancdata.o: $(hdrdir)/ruby/internal/attr/artificial.h +ancdata.o: $(hdrdir)/ruby/internal/attr/cold.h +ancdata.o: $(hdrdir)/ruby/internal/attr/const.h +ancdata.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ancdata.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ancdata.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ancdata.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ancdata.o: $(hdrdir)/ruby/internal/attr/error.h +ancdata.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ancdata.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ancdata.o: $(hdrdir)/ruby/internal/attr/format.h +ancdata.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ancdata.o: $(hdrdir)/ruby/internal/attr/noalias.h +ancdata.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ancdata.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ancdata.o: $(hdrdir)/ruby/internal/attr/noinline.h +ancdata.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ancdata.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ancdata.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +ancdata.o: $(hdrdir)/ruby/internal/attr/pure.h +ancdata.o: $(hdrdir)/ruby/internal/attr/restrict.h +ancdata.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ancdata.o: $(hdrdir)/ruby/internal/attr/warning.h +ancdata.o: $(hdrdir)/ruby/internal/attr/weakref.h +ancdata.o: $(hdrdir)/ruby/internal/cast.h +ancdata.o: $(hdrdir)/ruby/internal/compiler_is.h +ancdata.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ancdata.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ancdata.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ancdata.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ancdata.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ancdata.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ancdata.o: $(hdrdir)/ruby/internal/compiler_since.h +ancdata.o: $(hdrdir)/ruby/internal/config.h +ancdata.o: $(hdrdir)/ruby/internal/constant_p.h +ancdata.o: $(hdrdir)/ruby/internal/core.h +ancdata.o: $(hdrdir)/ruby/internal/core/rarray.h +ancdata.o: $(hdrdir)/ruby/internal/core/rbasic.h +ancdata.o: $(hdrdir)/ruby/internal/core/rbignum.h +ancdata.o: $(hdrdir)/ruby/internal/core/rclass.h +ancdata.o: $(hdrdir)/ruby/internal/core/rdata.h +ancdata.o: $(hdrdir)/ruby/internal/core/rfile.h +ancdata.o: $(hdrdir)/ruby/internal/core/rhash.h +ancdata.o: $(hdrdir)/ruby/internal/core/robject.h +ancdata.o: $(hdrdir)/ruby/internal/core/rregexp.h +ancdata.o: $(hdrdir)/ruby/internal/core/rstring.h +ancdata.o: $(hdrdir)/ruby/internal/core/rstruct.h +ancdata.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ancdata.o: $(hdrdir)/ruby/internal/ctype.h +ancdata.o: $(hdrdir)/ruby/internal/dllexport.h +ancdata.o: $(hdrdir)/ruby/internal/dosish.h +ancdata.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ancdata.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ancdata.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ancdata.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ancdata.o: $(hdrdir)/ruby/internal/encoding/re.h +ancdata.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ancdata.o: $(hdrdir)/ruby/internal/encoding/string.h +ancdata.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ancdata.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ancdata.o: $(hdrdir)/ruby/internal/error.h +ancdata.o: $(hdrdir)/ruby/internal/eval.h +ancdata.o: $(hdrdir)/ruby/internal/event.h +ancdata.o: $(hdrdir)/ruby/internal/fl_type.h +ancdata.o: $(hdrdir)/ruby/internal/gc.h +ancdata.o: $(hdrdir)/ruby/internal/glob.h +ancdata.o: $(hdrdir)/ruby/internal/globals.h +ancdata.o: $(hdrdir)/ruby/internal/has/attribute.h +ancdata.o: $(hdrdir)/ruby/internal/has/builtin.h +ancdata.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ancdata.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ancdata.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ancdata.o: $(hdrdir)/ruby/internal/has/extension.h +ancdata.o: $(hdrdir)/ruby/internal/has/feature.h +ancdata.o: $(hdrdir)/ruby/internal/has/warning.h +ancdata.o: $(hdrdir)/ruby/internal/intern/array.h +ancdata.o: $(hdrdir)/ruby/internal/intern/bignum.h +ancdata.o: $(hdrdir)/ruby/internal/intern/class.h +ancdata.o: $(hdrdir)/ruby/internal/intern/compar.h +ancdata.o: $(hdrdir)/ruby/internal/intern/complex.h +ancdata.o: $(hdrdir)/ruby/internal/intern/cont.h +ancdata.o: $(hdrdir)/ruby/internal/intern/dir.h +ancdata.o: $(hdrdir)/ruby/internal/intern/enum.h +ancdata.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ancdata.o: $(hdrdir)/ruby/internal/intern/error.h +ancdata.o: $(hdrdir)/ruby/internal/intern/eval.h +ancdata.o: $(hdrdir)/ruby/internal/intern/file.h +ancdata.o: $(hdrdir)/ruby/internal/intern/hash.h +ancdata.o: $(hdrdir)/ruby/internal/intern/io.h +ancdata.o: $(hdrdir)/ruby/internal/intern/load.h +ancdata.o: $(hdrdir)/ruby/internal/intern/marshal.h +ancdata.o: $(hdrdir)/ruby/internal/intern/numeric.h +ancdata.o: $(hdrdir)/ruby/internal/intern/object.h +ancdata.o: $(hdrdir)/ruby/internal/intern/parse.h +ancdata.o: $(hdrdir)/ruby/internal/intern/proc.h +ancdata.o: $(hdrdir)/ruby/internal/intern/process.h +ancdata.o: $(hdrdir)/ruby/internal/intern/random.h +ancdata.o: $(hdrdir)/ruby/internal/intern/range.h +ancdata.o: $(hdrdir)/ruby/internal/intern/rational.h +ancdata.o: $(hdrdir)/ruby/internal/intern/re.h +ancdata.o: $(hdrdir)/ruby/internal/intern/ruby.h +ancdata.o: $(hdrdir)/ruby/internal/intern/select.h +ancdata.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ancdata.o: $(hdrdir)/ruby/internal/intern/set.h +ancdata.o: $(hdrdir)/ruby/internal/intern/signal.h +ancdata.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ancdata.o: $(hdrdir)/ruby/internal/intern/string.h +ancdata.o: $(hdrdir)/ruby/internal/intern/struct.h +ancdata.o: $(hdrdir)/ruby/internal/intern/thread.h +ancdata.o: $(hdrdir)/ruby/internal/intern/time.h +ancdata.o: $(hdrdir)/ruby/internal/intern/variable.h +ancdata.o: $(hdrdir)/ruby/internal/intern/vm.h +ancdata.o: $(hdrdir)/ruby/internal/interpreter.h +ancdata.o: $(hdrdir)/ruby/internal/iterator.h +ancdata.o: $(hdrdir)/ruby/internal/memory.h +ancdata.o: $(hdrdir)/ruby/internal/method.h +ancdata.o: $(hdrdir)/ruby/internal/module.h +ancdata.o: $(hdrdir)/ruby/internal/newobj.h +ancdata.o: $(hdrdir)/ruby/internal/scan_args.h +ancdata.o: $(hdrdir)/ruby/internal/special_consts.h +ancdata.o: $(hdrdir)/ruby/internal/static_assert.h +ancdata.o: $(hdrdir)/ruby/internal/stdalign.h +ancdata.o: $(hdrdir)/ruby/internal/stdbool.h +ancdata.o: $(hdrdir)/ruby/internal/stdckdint.h +ancdata.o: $(hdrdir)/ruby/internal/symbol.h +ancdata.o: $(hdrdir)/ruby/internal/value.h +ancdata.o: $(hdrdir)/ruby/internal/value_type.h +ancdata.o: $(hdrdir)/ruby/internal/variable.h +ancdata.o: $(hdrdir)/ruby/internal/warning_push.h +ancdata.o: $(hdrdir)/ruby/internal/xmalloc.h ancdata.o: $(hdrdir)/ruby/io.h ancdata.o: $(hdrdir)/ruby/missing.h ancdata.o: $(hdrdir)/ruby/onigmo.h @@ -26,20 +186,214 @@ ancdata.o: $(hdrdir)/ruby/ruby.h ancdata.o: $(hdrdir)/ruby/st.h ancdata.o: $(hdrdir)/ruby/subst.h ancdata.o: $(hdrdir)/ruby/thread.h +ancdata.o: $(hdrdir)/ruby/thread_native.h ancdata.o: $(hdrdir)/ruby/util.h +ancdata.o: $(hdrdir)/ruby/version.h +ancdata.o: $(top_srcdir)/ccan/check_type/check_type.h +ancdata.o: $(top_srcdir)/ccan/container_of/container_of.h +ancdata.o: $(top_srcdir)/ccan/list/list.h +ancdata.o: $(top_srcdir)/ccan/str/str.h +ancdata.o: $(top_srcdir)/encindex.h +ancdata.o: $(top_srcdir)/id_table.h ancdata.o: $(top_srcdir)/internal.h +ancdata.o: $(top_srcdir)/internal/array.h +ancdata.o: $(top_srcdir)/internal/basic_operators.h +ancdata.o: $(top_srcdir)/internal/box.h +ancdata.o: $(top_srcdir)/internal/compilers.h +ancdata.o: $(top_srcdir)/internal/error.h +ancdata.o: $(top_srcdir)/internal/gc.h +ancdata.o: $(top_srcdir)/internal/imemo.h +ancdata.o: $(top_srcdir)/internal/io.h +ancdata.o: $(top_srcdir)/internal/sanitizers.h +ancdata.o: $(top_srcdir)/internal/serial.h +ancdata.o: $(top_srcdir)/internal/set_table.h +ancdata.o: $(top_srcdir)/internal/static_assert.h +ancdata.o: $(top_srcdir)/internal/string.h +ancdata.o: $(top_srcdir)/internal/thread.h +ancdata.o: $(top_srcdir)/internal/vm.h +ancdata.o: $(top_srcdir)/internal/warnings.h +ancdata.o: $(top_srcdir)/method.h +ancdata.o: $(top_srcdir)/node.h +ancdata.o: $(top_srcdir)/ruby_assert.h +ancdata.o: $(top_srcdir)/ruby_atomic.h +ancdata.o: $(top_srcdir)/rubyparser.h +ancdata.o: $(top_srcdir)/shape.h +ancdata.o: $(top_srcdir)/thread_pthread.h +ancdata.o: $(top_srcdir)/vm_core.h +ancdata.o: $(top_srcdir)/vm_opts.h ancdata.o: ancdata.c ancdata.o: constdefs.h ancdata.o: rubysocket.h ancdata.o: sockport.h +ancdata.o: {$(VPATH)}id.h basicsocket.o: $(RUBY_EXTCONF_H) basicsocket.o: $(arch_hdrdir)/ruby/config.h -basicsocket.o: $(hdrdir)/ruby.h basicsocket.o: $(hdrdir)/ruby/assert.h +basicsocket.o: $(hdrdir)/ruby/atomic.h basicsocket.o: $(hdrdir)/ruby/backward.h +basicsocket.o: $(hdrdir)/ruby/backward/2/assume.h +basicsocket.o: $(hdrdir)/ruby/backward/2/attributes.h +basicsocket.o: $(hdrdir)/ruby/backward/2/bool.h +basicsocket.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h +basicsocket.o: $(hdrdir)/ruby/backward/2/inttypes.h +basicsocket.o: $(hdrdir)/ruby/backward/2/limits.h +basicsocket.o: $(hdrdir)/ruby/backward/2/long_long.h +basicsocket.o: $(hdrdir)/ruby/backward/2/stdalign.h +basicsocket.o: $(hdrdir)/ruby/backward/2/stdarg.h basicsocket.o: $(hdrdir)/ruby/defines.h basicsocket.o: $(hdrdir)/ruby/encoding.h +basicsocket.o: $(hdrdir)/ruby/fiber/scheduler.h basicsocket.o: $(hdrdir)/ruby/intern.h +basicsocket.o: $(hdrdir)/ruby/internal/abi.h +basicsocket.o: $(hdrdir)/ruby/internal/anyargs.h +basicsocket.o: $(hdrdir)/ruby/internal/arithmetic.h +basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/char.h +basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/double.h +basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/int.h +basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/long.h +basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/short.h +basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +basicsocket.o: $(hdrdir)/ruby/internal/assume.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/artificial.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/cold.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/const.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/constexpr.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/deprecated.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/error.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/forceinline.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/format.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/noalias.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/noexcept.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/noinline.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/nonnull.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/noreturn.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/pure.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/restrict.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/warning.h +basicsocket.o: $(hdrdir)/ruby/internal/attr/weakref.h +basicsocket.o: $(hdrdir)/ruby/internal/cast.h +basicsocket.o: $(hdrdir)/ruby/internal/compiler_is.h +basicsocket.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +basicsocket.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +basicsocket.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +basicsocket.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +basicsocket.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +basicsocket.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +basicsocket.o: $(hdrdir)/ruby/internal/compiler_since.h +basicsocket.o: $(hdrdir)/ruby/internal/config.h +basicsocket.o: $(hdrdir)/ruby/internal/constant_p.h +basicsocket.o: $(hdrdir)/ruby/internal/core.h +basicsocket.o: $(hdrdir)/ruby/internal/core/rarray.h +basicsocket.o: $(hdrdir)/ruby/internal/core/rbasic.h +basicsocket.o: $(hdrdir)/ruby/internal/core/rbignum.h +basicsocket.o: $(hdrdir)/ruby/internal/core/rclass.h +basicsocket.o: $(hdrdir)/ruby/internal/core/rdata.h +basicsocket.o: $(hdrdir)/ruby/internal/core/rfile.h +basicsocket.o: $(hdrdir)/ruby/internal/core/rhash.h +basicsocket.o: $(hdrdir)/ruby/internal/core/robject.h +basicsocket.o: $(hdrdir)/ruby/internal/core/rregexp.h +basicsocket.o: $(hdrdir)/ruby/internal/core/rstring.h +basicsocket.o: $(hdrdir)/ruby/internal/core/rstruct.h +basicsocket.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +basicsocket.o: $(hdrdir)/ruby/internal/ctype.h +basicsocket.o: $(hdrdir)/ruby/internal/dllexport.h +basicsocket.o: $(hdrdir)/ruby/internal/dosish.h +basicsocket.o: $(hdrdir)/ruby/internal/encoding/coderange.h +basicsocket.o: $(hdrdir)/ruby/internal/encoding/ctype.h +basicsocket.o: $(hdrdir)/ruby/internal/encoding/encoding.h +basicsocket.o: $(hdrdir)/ruby/internal/encoding/pathname.h +basicsocket.o: $(hdrdir)/ruby/internal/encoding/re.h +basicsocket.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +basicsocket.o: $(hdrdir)/ruby/internal/encoding/string.h +basicsocket.o: $(hdrdir)/ruby/internal/encoding/symbol.h +basicsocket.o: $(hdrdir)/ruby/internal/encoding/transcode.h +basicsocket.o: $(hdrdir)/ruby/internal/error.h +basicsocket.o: $(hdrdir)/ruby/internal/eval.h +basicsocket.o: $(hdrdir)/ruby/internal/event.h +basicsocket.o: $(hdrdir)/ruby/internal/fl_type.h +basicsocket.o: $(hdrdir)/ruby/internal/gc.h +basicsocket.o: $(hdrdir)/ruby/internal/glob.h +basicsocket.o: $(hdrdir)/ruby/internal/globals.h +basicsocket.o: $(hdrdir)/ruby/internal/has/attribute.h +basicsocket.o: $(hdrdir)/ruby/internal/has/builtin.h +basicsocket.o: $(hdrdir)/ruby/internal/has/c_attribute.h +basicsocket.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +basicsocket.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +basicsocket.o: $(hdrdir)/ruby/internal/has/extension.h +basicsocket.o: $(hdrdir)/ruby/internal/has/feature.h +basicsocket.o: $(hdrdir)/ruby/internal/has/warning.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/array.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/bignum.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/class.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/compar.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/complex.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/cont.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/dir.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/enum.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/enumerator.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/error.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/eval.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/file.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/hash.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/io.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/load.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/marshal.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/numeric.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/object.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/parse.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/proc.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/process.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/random.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/range.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/rational.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/re.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/ruby.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/select.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/set.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/signal.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/sprintf.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/string.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/struct.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/thread.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/time.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/variable.h +basicsocket.o: $(hdrdir)/ruby/internal/intern/vm.h +basicsocket.o: $(hdrdir)/ruby/internal/interpreter.h +basicsocket.o: $(hdrdir)/ruby/internal/iterator.h +basicsocket.o: $(hdrdir)/ruby/internal/memory.h +basicsocket.o: $(hdrdir)/ruby/internal/method.h +basicsocket.o: $(hdrdir)/ruby/internal/module.h +basicsocket.o: $(hdrdir)/ruby/internal/newobj.h +basicsocket.o: $(hdrdir)/ruby/internal/scan_args.h +basicsocket.o: $(hdrdir)/ruby/internal/special_consts.h +basicsocket.o: $(hdrdir)/ruby/internal/static_assert.h +basicsocket.o: $(hdrdir)/ruby/internal/stdalign.h +basicsocket.o: $(hdrdir)/ruby/internal/stdbool.h +basicsocket.o: $(hdrdir)/ruby/internal/stdckdint.h +basicsocket.o: $(hdrdir)/ruby/internal/symbol.h +basicsocket.o: $(hdrdir)/ruby/internal/value.h +basicsocket.o: $(hdrdir)/ruby/internal/value_type.h +basicsocket.o: $(hdrdir)/ruby/internal/variable.h +basicsocket.o: $(hdrdir)/ruby/internal/warning_push.h +basicsocket.o: $(hdrdir)/ruby/internal/xmalloc.h basicsocket.o: $(hdrdir)/ruby/io.h basicsocket.o: $(hdrdir)/ruby/missing.h basicsocket.o: $(hdrdir)/ruby/onigmo.h @@ -48,20 +402,214 @@ basicsocket.o: $(hdrdir)/ruby/ruby.h basicsocket.o: $(hdrdir)/ruby/st.h basicsocket.o: $(hdrdir)/ruby/subst.h basicsocket.o: $(hdrdir)/ruby/thread.h +basicsocket.o: $(hdrdir)/ruby/thread_native.h basicsocket.o: $(hdrdir)/ruby/util.h +basicsocket.o: $(hdrdir)/ruby/version.h +basicsocket.o: $(top_srcdir)/ccan/check_type/check_type.h +basicsocket.o: $(top_srcdir)/ccan/container_of/container_of.h +basicsocket.o: $(top_srcdir)/ccan/list/list.h +basicsocket.o: $(top_srcdir)/ccan/str/str.h +basicsocket.o: $(top_srcdir)/encindex.h +basicsocket.o: $(top_srcdir)/id_table.h basicsocket.o: $(top_srcdir)/internal.h +basicsocket.o: $(top_srcdir)/internal/array.h +basicsocket.o: $(top_srcdir)/internal/basic_operators.h +basicsocket.o: $(top_srcdir)/internal/box.h +basicsocket.o: $(top_srcdir)/internal/compilers.h +basicsocket.o: $(top_srcdir)/internal/error.h +basicsocket.o: $(top_srcdir)/internal/gc.h +basicsocket.o: $(top_srcdir)/internal/imemo.h +basicsocket.o: $(top_srcdir)/internal/io.h +basicsocket.o: $(top_srcdir)/internal/sanitizers.h +basicsocket.o: $(top_srcdir)/internal/serial.h +basicsocket.o: $(top_srcdir)/internal/set_table.h +basicsocket.o: $(top_srcdir)/internal/static_assert.h +basicsocket.o: $(top_srcdir)/internal/string.h +basicsocket.o: $(top_srcdir)/internal/thread.h +basicsocket.o: $(top_srcdir)/internal/vm.h +basicsocket.o: $(top_srcdir)/internal/warnings.h +basicsocket.o: $(top_srcdir)/method.h +basicsocket.o: $(top_srcdir)/node.h +basicsocket.o: $(top_srcdir)/ruby_assert.h +basicsocket.o: $(top_srcdir)/ruby_atomic.h +basicsocket.o: $(top_srcdir)/rubyparser.h +basicsocket.o: $(top_srcdir)/shape.h +basicsocket.o: $(top_srcdir)/thread_pthread.h +basicsocket.o: $(top_srcdir)/vm_core.h +basicsocket.o: $(top_srcdir)/vm_opts.h basicsocket.o: basicsocket.c basicsocket.o: constdefs.h basicsocket.o: rubysocket.h basicsocket.o: sockport.h +basicsocket.o: {$(VPATH)}id.h constants.o: $(RUBY_EXTCONF_H) constants.o: $(arch_hdrdir)/ruby/config.h -constants.o: $(hdrdir)/ruby.h constants.o: $(hdrdir)/ruby/assert.h +constants.o: $(hdrdir)/ruby/atomic.h constants.o: $(hdrdir)/ruby/backward.h +constants.o: $(hdrdir)/ruby/backward/2/assume.h +constants.o: $(hdrdir)/ruby/backward/2/attributes.h +constants.o: $(hdrdir)/ruby/backward/2/bool.h +constants.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h +constants.o: $(hdrdir)/ruby/backward/2/inttypes.h +constants.o: $(hdrdir)/ruby/backward/2/limits.h +constants.o: $(hdrdir)/ruby/backward/2/long_long.h +constants.o: $(hdrdir)/ruby/backward/2/stdalign.h +constants.o: $(hdrdir)/ruby/backward/2/stdarg.h constants.o: $(hdrdir)/ruby/defines.h constants.o: $(hdrdir)/ruby/encoding.h +constants.o: $(hdrdir)/ruby/fiber/scheduler.h constants.o: $(hdrdir)/ruby/intern.h +constants.o: $(hdrdir)/ruby/internal/abi.h +constants.o: $(hdrdir)/ruby/internal/anyargs.h +constants.o: $(hdrdir)/ruby/internal/arithmetic.h +constants.o: $(hdrdir)/ruby/internal/arithmetic/char.h +constants.o: $(hdrdir)/ruby/internal/arithmetic/double.h +constants.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +constants.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +constants.o: $(hdrdir)/ruby/internal/arithmetic/int.h +constants.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +constants.o: $(hdrdir)/ruby/internal/arithmetic/long.h +constants.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +constants.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +constants.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +constants.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +constants.o: $(hdrdir)/ruby/internal/arithmetic/short.h +constants.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +constants.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +constants.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +constants.o: $(hdrdir)/ruby/internal/assume.h +constants.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +constants.o: $(hdrdir)/ruby/internal/attr/artificial.h +constants.o: $(hdrdir)/ruby/internal/attr/cold.h +constants.o: $(hdrdir)/ruby/internal/attr/const.h +constants.o: $(hdrdir)/ruby/internal/attr/constexpr.h +constants.o: $(hdrdir)/ruby/internal/attr/deprecated.h +constants.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +constants.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +constants.o: $(hdrdir)/ruby/internal/attr/error.h +constants.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +constants.o: $(hdrdir)/ruby/internal/attr/forceinline.h +constants.o: $(hdrdir)/ruby/internal/attr/format.h +constants.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +constants.o: $(hdrdir)/ruby/internal/attr/noalias.h +constants.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +constants.o: $(hdrdir)/ruby/internal/attr/noexcept.h +constants.o: $(hdrdir)/ruby/internal/attr/noinline.h +constants.o: $(hdrdir)/ruby/internal/attr/nonnull.h +constants.o: $(hdrdir)/ruby/internal/attr/noreturn.h +constants.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +constants.o: $(hdrdir)/ruby/internal/attr/pure.h +constants.o: $(hdrdir)/ruby/internal/attr/restrict.h +constants.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +constants.o: $(hdrdir)/ruby/internal/attr/warning.h +constants.o: $(hdrdir)/ruby/internal/attr/weakref.h +constants.o: $(hdrdir)/ruby/internal/cast.h +constants.o: $(hdrdir)/ruby/internal/compiler_is.h +constants.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +constants.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +constants.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +constants.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +constants.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +constants.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +constants.o: $(hdrdir)/ruby/internal/compiler_since.h +constants.o: $(hdrdir)/ruby/internal/config.h +constants.o: $(hdrdir)/ruby/internal/constant_p.h +constants.o: $(hdrdir)/ruby/internal/core.h +constants.o: $(hdrdir)/ruby/internal/core/rarray.h +constants.o: $(hdrdir)/ruby/internal/core/rbasic.h +constants.o: $(hdrdir)/ruby/internal/core/rbignum.h +constants.o: $(hdrdir)/ruby/internal/core/rclass.h +constants.o: $(hdrdir)/ruby/internal/core/rdata.h +constants.o: $(hdrdir)/ruby/internal/core/rfile.h +constants.o: $(hdrdir)/ruby/internal/core/rhash.h +constants.o: $(hdrdir)/ruby/internal/core/robject.h +constants.o: $(hdrdir)/ruby/internal/core/rregexp.h +constants.o: $(hdrdir)/ruby/internal/core/rstring.h +constants.o: $(hdrdir)/ruby/internal/core/rstruct.h +constants.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +constants.o: $(hdrdir)/ruby/internal/ctype.h +constants.o: $(hdrdir)/ruby/internal/dllexport.h +constants.o: $(hdrdir)/ruby/internal/dosish.h +constants.o: $(hdrdir)/ruby/internal/encoding/coderange.h +constants.o: $(hdrdir)/ruby/internal/encoding/ctype.h +constants.o: $(hdrdir)/ruby/internal/encoding/encoding.h +constants.o: $(hdrdir)/ruby/internal/encoding/pathname.h +constants.o: $(hdrdir)/ruby/internal/encoding/re.h +constants.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +constants.o: $(hdrdir)/ruby/internal/encoding/string.h +constants.o: $(hdrdir)/ruby/internal/encoding/symbol.h +constants.o: $(hdrdir)/ruby/internal/encoding/transcode.h +constants.o: $(hdrdir)/ruby/internal/error.h +constants.o: $(hdrdir)/ruby/internal/eval.h +constants.o: $(hdrdir)/ruby/internal/event.h +constants.o: $(hdrdir)/ruby/internal/fl_type.h +constants.o: $(hdrdir)/ruby/internal/gc.h +constants.o: $(hdrdir)/ruby/internal/glob.h +constants.o: $(hdrdir)/ruby/internal/globals.h +constants.o: $(hdrdir)/ruby/internal/has/attribute.h +constants.o: $(hdrdir)/ruby/internal/has/builtin.h +constants.o: $(hdrdir)/ruby/internal/has/c_attribute.h +constants.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +constants.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +constants.o: $(hdrdir)/ruby/internal/has/extension.h +constants.o: $(hdrdir)/ruby/internal/has/feature.h +constants.o: $(hdrdir)/ruby/internal/has/warning.h +constants.o: $(hdrdir)/ruby/internal/intern/array.h +constants.o: $(hdrdir)/ruby/internal/intern/bignum.h +constants.o: $(hdrdir)/ruby/internal/intern/class.h +constants.o: $(hdrdir)/ruby/internal/intern/compar.h +constants.o: $(hdrdir)/ruby/internal/intern/complex.h +constants.o: $(hdrdir)/ruby/internal/intern/cont.h +constants.o: $(hdrdir)/ruby/internal/intern/dir.h +constants.o: $(hdrdir)/ruby/internal/intern/enum.h +constants.o: $(hdrdir)/ruby/internal/intern/enumerator.h +constants.o: $(hdrdir)/ruby/internal/intern/error.h +constants.o: $(hdrdir)/ruby/internal/intern/eval.h +constants.o: $(hdrdir)/ruby/internal/intern/file.h +constants.o: $(hdrdir)/ruby/internal/intern/hash.h +constants.o: $(hdrdir)/ruby/internal/intern/io.h +constants.o: $(hdrdir)/ruby/internal/intern/load.h +constants.o: $(hdrdir)/ruby/internal/intern/marshal.h +constants.o: $(hdrdir)/ruby/internal/intern/numeric.h +constants.o: $(hdrdir)/ruby/internal/intern/object.h +constants.o: $(hdrdir)/ruby/internal/intern/parse.h +constants.o: $(hdrdir)/ruby/internal/intern/proc.h +constants.o: $(hdrdir)/ruby/internal/intern/process.h +constants.o: $(hdrdir)/ruby/internal/intern/random.h +constants.o: $(hdrdir)/ruby/internal/intern/range.h +constants.o: $(hdrdir)/ruby/internal/intern/rational.h +constants.o: $(hdrdir)/ruby/internal/intern/re.h +constants.o: $(hdrdir)/ruby/internal/intern/ruby.h +constants.o: $(hdrdir)/ruby/internal/intern/select.h +constants.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +constants.o: $(hdrdir)/ruby/internal/intern/set.h +constants.o: $(hdrdir)/ruby/internal/intern/signal.h +constants.o: $(hdrdir)/ruby/internal/intern/sprintf.h +constants.o: $(hdrdir)/ruby/internal/intern/string.h +constants.o: $(hdrdir)/ruby/internal/intern/struct.h +constants.o: $(hdrdir)/ruby/internal/intern/thread.h +constants.o: $(hdrdir)/ruby/internal/intern/time.h +constants.o: $(hdrdir)/ruby/internal/intern/variable.h +constants.o: $(hdrdir)/ruby/internal/intern/vm.h +constants.o: $(hdrdir)/ruby/internal/interpreter.h +constants.o: $(hdrdir)/ruby/internal/iterator.h +constants.o: $(hdrdir)/ruby/internal/memory.h +constants.o: $(hdrdir)/ruby/internal/method.h +constants.o: $(hdrdir)/ruby/internal/module.h +constants.o: $(hdrdir)/ruby/internal/newobj.h +constants.o: $(hdrdir)/ruby/internal/scan_args.h +constants.o: $(hdrdir)/ruby/internal/special_consts.h +constants.o: $(hdrdir)/ruby/internal/static_assert.h +constants.o: $(hdrdir)/ruby/internal/stdalign.h +constants.o: $(hdrdir)/ruby/internal/stdbool.h +constants.o: $(hdrdir)/ruby/internal/stdckdint.h +constants.o: $(hdrdir)/ruby/internal/symbol.h +constants.o: $(hdrdir)/ruby/internal/value.h +constants.o: $(hdrdir)/ruby/internal/value_type.h +constants.o: $(hdrdir)/ruby/internal/variable.h +constants.o: $(hdrdir)/ruby/internal/warning_push.h +constants.o: $(hdrdir)/ruby/internal/xmalloc.h constants.o: $(hdrdir)/ruby/io.h constants.o: $(hdrdir)/ruby/missing.h constants.o: $(hdrdir)/ruby/onigmo.h @@ -70,21 +618,215 @@ constants.o: $(hdrdir)/ruby/ruby.h constants.o: $(hdrdir)/ruby/st.h constants.o: $(hdrdir)/ruby/subst.h constants.o: $(hdrdir)/ruby/thread.h +constants.o: $(hdrdir)/ruby/thread_native.h constants.o: $(hdrdir)/ruby/util.h +constants.o: $(hdrdir)/ruby/version.h +constants.o: $(top_srcdir)/ccan/check_type/check_type.h +constants.o: $(top_srcdir)/ccan/container_of/container_of.h +constants.o: $(top_srcdir)/ccan/list/list.h +constants.o: $(top_srcdir)/ccan/str/str.h +constants.o: $(top_srcdir)/encindex.h +constants.o: $(top_srcdir)/id_table.h constants.o: $(top_srcdir)/internal.h +constants.o: $(top_srcdir)/internal/array.h +constants.o: $(top_srcdir)/internal/basic_operators.h +constants.o: $(top_srcdir)/internal/box.h +constants.o: $(top_srcdir)/internal/compilers.h +constants.o: $(top_srcdir)/internal/error.h +constants.o: $(top_srcdir)/internal/gc.h +constants.o: $(top_srcdir)/internal/imemo.h +constants.o: $(top_srcdir)/internal/io.h +constants.o: $(top_srcdir)/internal/sanitizers.h +constants.o: $(top_srcdir)/internal/serial.h +constants.o: $(top_srcdir)/internal/set_table.h +constants.o: $(top_srcdir)/internal/static_assert.h +constants.o: $(top_srcdir)/internal/string.h +constants.o: $(top_srcdir)/internal/thread.h +constants.o: $(top_srcdir)/internal/vm.h +constants.o: $(top_srcdir)/internal/warnings.h +constants.o: $(top_srcdir)/method.h +constants.o: $(top_srcdir)/node.h +constants.o: $(top_srcdir)/ruby_assert.h +constants.o: $(top_srcdir)/ruby_atomic.h +constants.o: $(top_srcdir)/rubyparser.h +constants.o: $(top_srcdir)/shape.h +constants.o: $(top_srcdir)/thread_pthread.h +constants.o: $(top_srcdir)/vm_core.h +constants.o: $(top_srcdir)/vm_opts.h constants.o: constants.c constants.o: constdefs.c constants.o: constdefs.h constants.o: rubysocket.h constants.o: sockport.h +constants.o: {$(VPATH)}id.h ifaddr.o: $(RUBY_EXTCONF_H) ifaddr.o: $(arch_hdrdir)/ruby/config.h -ifaddr.o: $(hdrdir)/ruby.h ifaddr.o: $(hdrdir)/ruby/assert.h +ifaddr.o: $(hdrdir)/ruby/atomic.h ifaddr.o: $(hdrdir)/ruby/backward.h +ifaddr.o: $(hdrdir)/ruby/backward/2/assume.h +ifaddr.o: $(hdrdir)/ruby/backward/2/attributes.h +ifaddr.o: $(hdrdir)/ruby/backward/2/bool.h +ifaddr.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h +ifaddr.o: $(hdrdir)/ruby/backward/2/inttypes.h +ifaddr.o: $(hdrdir)/ruby/backward/2/limits.h +ifaddr.o: $(hdrdir)/ruby/backward/2/long_long.h +ifaddr.o: $(hdrdir)/ruby/backward/2/stdalign.h +ifaddr.o: $(hdrdir)/ruby/backward/2/stdarg.h ifaddr.o: $(hdrdir)/ruby/defines.h ifaddr.o: $(hdrdir)/ruby/encoding.h +ifaddr.o: $(hdrdir)/ruby/fiber/scheduler.h ifaddr.o: $(hdrdir)/ruby/intern.h +ifaddr.o: $(hdrdir)/ruby/internal/abi.h +ifaddr.o: $(hdrdir)/ruby/internal/anyargs.h +ifaddr.o: $(hdrdir)/ruby/internal/arithmetic.h +ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ifaddr.o: $(hdrdir)/ruby/internal/assume.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/artificial.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/cold.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/const.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/error.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/format.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/noalias.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/noinline.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/pure.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/restrict.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/warning.h +ifaddr.o: $(hdrdir)/ruby/internal/attr/weakref.h +ifaddr.o: $(hdrdir)/ruby/internal/cast.h +ifaddr.o: $(hdrdir)/ruby/internal/compiler_is.h +ifaddr.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ifaddr.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ifaddr.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ifaddr.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ifaddr.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ifaddr.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ifaddr.o: $(hdrdir)/ruby/internal/compiler_since.h +ifaddr.o: $(hdrdir)/ruby/internal/config.h +ifaddr.o: $(hdrdir)/ruby/internal/constant_p.h +ifaddr.o: $(hdrdir)/ruby/internal/core.h +ifaddr.o: $(hdrdir)/ruby/internal/core/rarray.h +ifaddr.o: $(hdrdir)/ruby/internal/core/rbasic.h +ifaddr.o: $(hdrdir)/ruby/internal/core/rbignum.h +ifaddr.o: $(hdrdir)/ruby/internal/core/rclass.h +ifaddr.o: $(hdrdir)/ruby/internal/core/rdata.h +ifaddr.o: $(hdrdir)/ruby/internal/core/rfile.h +ifaddr.o: $(hdrdir)/ruby/internal/core/rhash.h +ifaddr.o: $(hdrdir)/ruby/internal/core/robject.h +ifaddr.o: $(hdrdir)/ruby/internal/core/rregexp.h +ifaddr.o: $(hdrdir)/ruby/internal/core/rstring.h +ifaddr.o: $(hdrdir)/ruby/internal/core/rstruct.h +ifaddr.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ifaddr.o: $(hdrdir)/ruby/internal/ctype.h +ifaddr.o: $(hdrdir)/ruby/internal/dllexport.h +ifaddr.o: $(hdrdir)/ruby/internal/dosish.h +ifaddr.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ifaddr.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ifaddr.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ifaddr.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ifaddr.o: $(hdrdir)/ruby/internal/encoding/re.h +ifaddr.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ifaddr.o: $(hdrdir)/ruby/internal/encoding/string.h +ifaddr.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ifaddr.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ifaddr.o: $(hdrdir)/ruby/internal/error.h +ifaddr.o: $(hdrdir)/ruby/internal/eval.h +ifaddr.o: $(hdrdir)/ruby/internal/event.h +ifaddr.o: $(hdrdir)/ruby/internal/fl_type.h +ifaddr.o: $(hdrdir)/ruby/internal/gc.h +ifaddr.o: $(hdrdir)/ruby/internal/glob.h +ifaddr.o: $(hdrdir)/ruby/internal/globals.h +ifaddr.o: $(hdrdir)/ruby/internal/has/attribute.h +ifaddr.o: $(hdrdir)/ruby/internal/has/builtin.h +ifaddr.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ifaddr.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ifaddr.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ifaddr.o: $(hdrdir)/ruby/internal/has/extension.h +ifaddr.o: $(hdrdir)/ruby/internal/has/feature.h +ifaddr.o: $(hdrdir)/ruby/internal/has/warning.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/array.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/bignum.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/class.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/compar.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/complex.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/cont.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/dir.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/enum.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/error.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/eval.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/file.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/hash.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/io.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/load.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/marshal.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/numeric.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/object.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/parse.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/proc.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/process.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/random.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/range.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/rational.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/re.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/ruby.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/select.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/set.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/signal.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/string.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/struct.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/thread.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/time.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/variable.h +ifaddr.o: $(hdrdir)/ruby/internal/intern/vm.h +ifaddr.o: $(hdrdir)/ruby/internal/interpreter.h +ifaddr.o: $(hdrdir)/ruby/internal/iterator.h +ifaddr.o: $(hdrdir)/ruby/internal/memory.h +ifaddr.o: $(hdrdir)/ruby/internal/method.h +ifaddr.o: $(hdrdir)/ruby/internal/module.h +ifaddr.o: $(hdrdir)/ruby/internal/newobj.h +ifaddr.o: $(hdrdir)/ruby/internal/scan_args.h +ifaddr.o: $(hdrdir)/ruby/internal/special_consts.h +ifaddr.o: $(hdrdir)/ruby/internal/static_assert.h +ifaddr.o: $(hdrdir)/ruby/internal/stdalign.h +ifaddr.o: $(hdrdir)/ruby/internal/stdbool.h +ifaddr.o: $(hdrdir)/ruby/internal/stdckdint.h +ifaddr.o: $(hdrdir)/ruby/internal/symbol.h +ifaddr.o: $(hdrdir)/ruby/internal/value.h +ifaddr.o: $(hdrdir)/ruby/internal/value_type.h +ifaddr.o: $(hdrdir)/ruby/internal/variable.h +ifaddr.o: $(hdrdir)/ruby/internal/warning_push.h +ifaddr.o: $(hdrdir)/ruby/internal/xmalloc.h ifaddr.o: $(hdrdir)/ruby/io.h ifaddr.o: $(hdrdir)/ruby/missing.h ifaddr.o: $(hdrdir)/ruby/onigmo.h @@ -93,20 +835,214 @@ ifaddr.o: $(hdrdir)/ruby/ruby.h ifaddr.o: $(hdrdir)/ruby/st.h ifaddr.o: $(hdrdir)/ruby/subst.h ifaddr.o: $(hdrdir)/ruby/thread.h +ifaddr.o: $(hdrdir)/ruby/thread_native.h ifaddr.o: $(hdrdir)/ruby/util.h +ifaddr.o: $(hdrdir)/ruby/version.h +ifaddr.o: $(top_srcdir)/ccan/check_type/check_type.h +ifaddr.o: $(top_srcdir)/ccan/container_of/container_of.h +ifaddr.o: $(top_srcdir)/ccan/list/list.h +ifaddr.o: $(top_srcdir)/ccan/str/str.h +ifaddr.o: $(top_srcdir)/encindex.h +ifaddr.o: $(top_srcdir)/id_table.h ifaddr.o: $(top_srcdir)/internal.h +ifaddr.o: $(top_srcdir)/internal/array.h +ifaddr.o: $(top_srcdir)/internal/basic_operators.h +ifaddr.o: $(top_srcdir)/internal/box.h +ifaddr.o: $(top_srcdir)/internal/compilers.h +ifaddr.o: $(top_srcdir)/internal/error.h +ifaddr.o: $(top_srcdir)/internal/gc.h +ifaddr.o: $(top_srcdir)/internal/imemo.h +ifaddr.o: $(top_srcdir)/internal/io.h +ifaddr.o: $(top_srcdir)/internal/sanitizers.h +ifaddr.o: $(top_srcdir)/internal/serial.h +ifaddr.o: $(top_srcdir)/internal/set_table.h +ifaddr.o: $(top_srcdir)/internal/static_assert.h +ifaddr.o: $(top_srcdir)/internal/string.h +ifaddr.o: $(top_srcdir)/internal/thread.h +ifaddr.o: $(top_srcdir)/internal/vm.h +ifaddr.o: $(top_srcdir)/internal/warnings.h +ifaddr.o: $(top_srcdir)/method.h +ifaddr.o: $(top_srcdir)/node.h +ifaddr.o: $(top_srcdir)/ruby_assert.h +ifaddr.o: $(top_srcdir)/ruby_atomic.h +ifaddr.o: $(top_srcdir)/rubyparser.h +ifaddr.o: $(top_srcdir)/shape.h +ifaddr.o: $(top_srcdir)/thread_pthread.h +ifaddr.o: $(top_srcdir)/vm_core.h +ifaddr.o: $(top_srcdir)/vm_opts.h ifaddr.o: constdefs.h ifaddr.o: ifaddr.c ifaddr.o: rubysocket.h ifaddr.o: sockport.h +ifaddr.o: {$(VPATH)}id.h init.o: $(RUBY_EXTCONF_H) init.o: $(arch_hdrdir)/ruby/config.h -init.o: $(hdrdir)/ruby.h init.o: $(hdrdir)/ruby/assert.h +init.o: $(hdrdir)/ruby/atomic.h init.o: $(hdrdir)/ruby/backward.h +init.o: $(hdrdir)/ruby/backward/2/assume.h +init.o: $(hdrdir)/ruby/backward/2/attributes.h +init.o: $(hdrdir)/ruby/backward/2/bool.h +init.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h +init.o: $(hdrdir)/ruby/backward/2/inttypes.h +init.o: $(hdrdir)/ruby/backward/2/limits.h +init.o: $(hdrdir)/ruby/backward/2/long_long.h +init.o: $(hdrdir)/ruby/backward/2/stdalign.h +init.o: $(hdrdir)/ruby/backward/2/stdarg.h init.o: $(hdrdir)/ruby/defines.h init.o: $(hdrdir)/ruby/encoding.h +init.o: $(hdrdir)/ruby/fiber/scheduler.h init.o: $(hdrdir)/ruby/intern.h +init.o: $(hdrdir)/ruby/internal/abi.h +init.o: $(hdrdir)/ruby/internal/anyargs.h +init.o: $(hdrdir)/ruby/internal/arithmetic.h +init.o: $(hdrdir)/ruby/internal/arithmetic/char.h +init.o: $(hdrdir)/ruby/internal/arithmetic/double.h +init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +init.o: $(hdrdir)/ruby/internal/arithmetic/int.h +init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +init.o: $(hdrdir)/ruby/internal/arithmetic/long.h +init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +init.o: $(hdrdir)/ruby/internal/arithmetic/short.h +init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +init.o: $(hdrdir)/ruby/internal/assume.h +init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +init.o: $(hdrdir)/ruby/internal/attr/artificial.h +init.o: $(hdrdir)/ruby/internal/attr/cold.h +init.o: $(hdrdir)/ruby/internal/attr/const.h +init.o: $(hdrdir)/ruby/internal/attr/constexpr.h +init.o: $(hdrdir)/ruby/internal/attr/deprecated.h +init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +init.o: $(hdrdir)/ruby/internal/attr/error.h +init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +init.o: $(hdrdir)/ruby/internal/attr/forceinline.h +init.o: $(hdrdir)/ruby/internal/attr/format.h +init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +init.o: $(hdrdir)/ruby/internal/attr/noalias.h +init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +init.o: $(hdrdir)/ruby/internal/attr/noexcept.h +init.o: $(hdrdir)/ruby/internal/attr/noinline.h +init.o: $(hdrdir)/ruby/internal/attr/nonnull.h +init.o: $(hdrdir)/ruby/internal/attr/noreturn.h +init.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +init.o: $(hdrdir)/ruby/internal/attr/pure.h +init.o: $(hdrdir)/ruby/internal/attr/restrict.h +init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +init.o: $(hdrdir)/ruby/internal/attr/warning.h +init.o: $(hdrdir)/ruby/internal/attr/weakref.h +init.o: $(hdrdir)/ruby/internal/cast.h +init.o: $(hdrdir)/ruby/internal/compiler_is.h +init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +init.o: $(hdrdir)/ruby/internal/compiler_since.h +init.o: $(hdrdir)/ruby/internal/config.h +init.o: $(hdrdir)/ruby/internal/constant_p.h +init.o: $(hdrdir)/ruby/internal/core.h +init.o: $(hdrdir)/ruby/internal/core/rarray.h +init.o: $(hdrdir)/ruby/internal/core/rbasic.h +init.o: $(hdrdir)/ruby/internal/core/rbignum.h +init.o: $(hdrdir)/ruby/internal/core/rclass.h +init.o: $(hdrdir)/ruby/internal/core/rdata.h +init.o: $(hdrdir)/ruby/internal/core/rfile.h +init.o: $(hdrdir)/ruby/internal/core/rhash.h +init.o: $(hdrdir)/ruby/internal/core/robject.h +init.o: $(hdrdir)/ruby/internal/core/rregexp.h +init.o: $(hdrdir)/ruby/internal/core/rstring.h +init.o: $(hdrdir)/ruby/internal/core/rstruct.h +init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +init.o: $(hdrdir)/ruby/internal/ctype.h +init.o: $(hdrdir)/ruby/internal/dllexport.h +init.o: $(hdrdir)/ruby/internal/dosish.h +init.o: $(hdrdir)/ruby/internal/encoding/coderange.h +init.o: $(hdrdir)/ruby/internal/encoding/ctype.h +init.o: $(hdrdir)/ruby/internal/encoding/encoding.h +init.o: $(hdrdir)/ruby/internal/encoding/pathname.h +init.o: $(hdrdir)/ruby/internal/encoding/re.h +init.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +init.o: $(hdrdir)/ruby/internal/encoding/string.h +init.o: $(hdrdir)/ruby/internal/encoding/symbol.h +init.o: $(hdrdir)/ruby/internal/encoding/transcode.h +init.o: $(hdrdir)/ruby/internal/error.h +init.o: $(hdrdir)/ruby/internal/eval.h +init.o: $(hdrdir)/ruby/internal/event.h +init.o: $(hdrdir)/ruby/internal/fl_type.h +init.o: $(hdrdir)/ruby/internal/gc.h +init.o: $(hdrdir)/ruby/internal/glob.h +init.o: $(hdrdir)/ruby/internal/globals.h +init.o: $(hdrdir)/ruby/internal/has/attribute.h +init.o: $(hdrdir)/ruby/internal/has/builtin.h +init.o: $(hdrdir)/ruby/internal/has/c_attribute.h +init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +init.o: $(hdrdir)/ruby/internal/has/extension.h +init.o: $(hdrdir)/ruby/internal/has/feature.h +init.o: $(hdrdir)/ruby/internal/has/warning.h +init.o: $(hdrdir)/ruby/internal/intern/array.h +init.o: $(hdrdir)/ruby/internal/intern/bignum.h +init.o: $(hdrdir)/ruby/internal/intern/class.h +init.o: $(hdrdir)/ruby/internal/intern/compar.h +init.o: $(hdrdir)/ruby/internal/intern/complex.h +init.o: $(hdrdir)/ruby/internal/intern/cont.h +init.o: $(hdrdir)/ruby/internal/intern/dir.h +init.o: $(hdrdir)/ruby/internal/intern/enum.h +init.o: $(hdrdir)/ruby/internal/intern/enumerator.h +init.o: $(hdrdir)/ruby/internal/intern/error.h +init.o: $(hdrdir)/ruby/internal/intern/eval.h +init.o: $(hdrdir)/ruby/internal/intern/file.h +init.o: $(hdrdir)/ruby/internal/intern/hash.h +init.o: $(hdrdir)/ruby/internal/intern/io.h +init.o: $(hdrdir)/ruby/internal/intern/load.h +init.o: $(hdrdir)/ruby/internal/intern/marshal.h +init.o: $(hdrdir)/ruby/internal/intern/numeric.h +init.o: $(hdrdir)/ruby/internal/intern/object.h +init.o: $(hdrdir)/ruby/internal/intern/parse.h +init.o: $(hdrdir)/ruby/internal/intern/proc.h +init.o: $(hdrdir)/ruby/internal/intern/process.h +init.o: $(hdrdir)/ruby/internal/intern/random.h +init.o: $(hdrdir)/ruby/internal/intern/range.h +init.o: $(hdrdir)/ruby/internal/intern/rational.h +init.o: $(hdrdir)/ruby/internal/intern/re.h +init.o: $(hdrdir)/ruby/internal/intern/ruby.h +init.o: $(hdrdir)/ruby/internal/intern/select.h +init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +init.o: $(hdrdir)/ruby/internal/intern/set.h +init.o: $(hdrdir)/ruby/internal/intern/signal.h +init.o: $(hdrdir)/ruby/internal/intern/sprintf.h +init.o: $(hdrdir)/ruby/internal/intern/string.h +init.o: $(hdrdir)/ruby/internal/intern/struct.h +init.o: $(hdrdir)/ruby/internal/intern/thread.h +init.o: $(hdrdir)/ruby/internal/intern/time.h +init.o: $(hdrdir)/ruby/internal/intern/variable.h +init.o: $(hdrdir)/ruby/internal/intern/vm.h +init.o: $(hdrdir)/ruby/internal/interpreter.h +init.o: $(hdrdir)/ruby/internal/iterator.h +init.o: $(hdrdir)/ruby/internal/memory.h +init.o: $(hdrdir)/ruby/internal/method.h +init.o: $(hdrdir)/ruby/internal/module.h +init.o: $(hdrdir)/ruby/internal/newobj.h +init.o: $(hdrdir)/ruby/internal/scan_args.h +init.o: $(hdrdir)/ruby/internal/special_consts.h +init.o: $(hdrdir)/ruby/internal/static_assert.h +init.o: $(hdrdir)/ruby/internal/stdalign.h +init.o: $(hdrdir)/ruby/internal/stdbool.h +init.o: $(hdrdir)/ruby/internal/stdckdint.h +init.o: $(hdrdir)/ruby/internal/symbol.h +init.o: $(hdrdir)/ruby/internal/value.h +init.o: $(hdrdir)/ruby/internal/value_type.h +init.o: $(hdrdir)/ruby/internal/variable.h +init.o: $(hdrdir)/ruby/internal/warning_push.h +init.o: $(hdrdir)/ruby/internal/xmalloc.h init.o: $(hdrdir)/ruby/io.h init.o: $(hdrdir)/ruby/missing.h init.o: $(hdrdir)/ruby/onigmo.h @@ -115,20 +1051,214 @@ init.o: $(hdrdir)/ruby/ruby.h init.o: $(hdrdir)/ruby/st.h init.o: $(hdrdir)/ruby/subst.h init.o: $(hdrdir)/ruby/thread.h +init.o: $(hdrdir)/ruby/thread_native.h init.o: $(hdrdir)/ruby/util.h +init.o: $(hdrdir)/ruby/version.h +init.o: $(top_srcdir)/ccan/check_type/check_type.h +init.o: $(top_srcdir)/ccan/container_of/container_of.h +init.o: $(top_srcdir)/ccan/list/list.h +init.o: $(top_srcdir)/ccan/str/str.h +init.o: $(top_srcdir)/encindex.h +init.o: $(top_srcdir)/id_table.h init.o: $(top_srcdir)/internal.h +init.o: $(top_srcdir)/internal/array.h +init.o: $(top_srcdir)/internal/basic_operators.h +init.o: $(top_srcdir)/internal/box.h +init.o: $(top_srcdir)/internal/compilers.h +init.o: $(top_srcdir)/internal/error.h +init.o: $(top_srcdir)/internal/gc.h +init.o: $(top_srcdir)/internal/imemo.h +init.o: $(top_srcdir)/internal/io.h +init.o: $(top_srcdir)/internal/sanitizers.h +init.o: $(top_srcdir)/internal/serial.h +init.o: $(top_srcdir)/internal/set_table.h +init.o: $(top_srcdir)/internal/static_assert.h +init.o: $(top_srcdir)/internal/string.h +init.o: $(top_srcdir)/internal/thread.h +init.o: $(top_srcdir)/internal/vm.h +init.o: $(top_srcdir)/internal/warnings.h +init.o: $(top_srcdir)/method.h +init.o: $(top_srcdir)/node.h +init.o: $(top_srcdir)/ruby_assert.h +init.o: $(top_srcdir)/ruby_atomic.h +init.o: $(top_srcdir)/rubyparser.h +init.o: $(top_srcdir)/shape.h +init.o: $(top_srcdir)/thread_pthread.h +init.o: $(top_srcdir)/vm_core.h +init.o: $(top_srcdir)/vm_opts.h init.o: constdefs.h init.o: init.c init.o: rubysocket.h init.o: sockport.h +init.o: {$(VPATH)}id.h ipsocket.o: $(RUBY_EXTCONF_H) ipsocket.o: $(arch_hdrdir)/ruby/config.h -ipsocket.o: $(hdrdir)/ruby.h ipsocket.o: $(hdrdir)/ruby/assert.h +ipsocket.o: $(hdrdir)/ruby/atomic.h ipsocket.o: $(hdrdir)/ruby/backward.h +ipsocket.o: $(hdrdir)/ruby/backward/2/assume.h +ipsocket.o: $(hdrdir)/ruby/backward/2/attributes.h +ipsocket.o: $(hdrdir)/ruby/backward/2/bool.h +ipsocket.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h +ipsocket.o: $(hdrdir)/ruby/backward/2/inttypes.h +ipsocket.o: $(hdrdir)/ruby/backward/2/limits.h +ipsocket.o: $(hdrdir)/ruby/backward/2/long_long.h +ipsocket.o: $(hdrdir)/ruby/backward/2/stdalign.h +ipsocket.o: $(hdrdir)/ruby/backward/2/stdarg.h ipsocket.o: $(hdrdir)/ruby/defines.h ipsocket.o: $(hdrdir)/ruby/encoding.h +ipsocket.o: $(hdrdir)/ruby/fiber/scheduler.h ipsocket.o: $(hdrdir)/ruby/intern.h +ipsocket.o: $(hdrdir)/ruby/internal/abi.h +ipsocket.o: $(hdrdir)/ruby/internal/anyargs.h +ipsocket.o: $(hdrdir)/ruby/internal/arithmetic.h +ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/char.h +ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/double.h +ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/int.h +ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/long.h +ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/short.h +ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +ipsocket.o: $(hdrdir)/ruby/internal/assume.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/artificial.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/cold.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/const.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/constexpr.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/deprecated.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/error.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/forceinline.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/format.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/noalias.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/noexcept.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/noinline.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/nonnull.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/noreturn.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/pure.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/restrict.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/warning.h +ipsocket.o: $(hdrdir)/ruby/internal/attr/weakref.h +ipsocket.o: $(hdrdir)/ruby/internal/cast.h +ipsocket.o: $(hdrdir)/ruby/internal/compiler_is.h +ipsocket.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +ipsocket.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +ipsocket.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +ipsocket.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +ipsocket.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +ipsocket.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +ipsocket.o: $(hdrdir)/ruby/internal/compiler_since.h +ipsocket.o: $(hdrdir)/ruby/internal/config.h +ipsocket.o: $(hdrdir)/ruby/internal/constant_p.h +ipsocket.o: $(hdrdir)/ruby/internal/core.h +ipsocket.o: $(hdrdir)/ruby/internal/core/rarray.h +ipsocket.o: $(hdrdir)/ruby/internal/core/rbasic.h +ipsocket.o: $(hdrdir)/ruby/internal/core/rbignum.h +ipsocket.o: $(hdrdir)/ruby/internal/core/rclass.h +ipsocket.o: $(hdrdir)/ruby/internal/core/rdata.h +ipsocket.o: $(hdrdir)/ruby/internal/core/rfile.h +ipsocket.o: $(hdrdir)/ruby/internal/core/rhash.h +ipsocket.o: $(hdrdir)/ruby/internal/core/robject.h +ipsocket.o: $(hdrdir)/ruby/internal/core/rregexp.h +ipsocket.o: $(hdrdir)/ruby/internal/core/rstring.h +ipsocket.o: $(hdrdir)/ruby/internal/core/rstruct.h +ipsocket.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +ipsocket.o: $(hdrdir)/ruby/internal/ctype.h +ipsocket.o: $(hdrdir)/ruby/internal/dllexport.h +ipsocket.o: $(hdrdir)/ruby/internal/dosish.h +ipsocket.o: $(hdrdir)/ruby/internal/encoding/coderange.h +ipsocket.o: $(hdrdir)/ruby/internal/encoding/ctype.h +ipsocket.o: $(hdrdir)/ruby/internal/encoding/encoding.h +ipsocket.o: $(hdrdir)/ruby/internal/encoding/pathname.h +ipsocket.o: $(hdrdir)/ruby/internal/encoding/re.h +ipsocket.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +ipsocket.o: $(hdrdir)/ruby/internal/encoding/string.h +ipsocket.o: $(hdrdir)/ruby/internal/encoding/symbol.h +ipsocket.o: $(hdrdir)/ruby/internal/encoding/transcode.h +ipsocket.o: $(hdrdir)/ruby/internal/error.h +ipsocket.o: $(hdrdir)/ruby/internal/eval.h +ipsocket.o: $(hdrdir)/ruby/internal/event.h +ipsocket.o: $(hdrdir)/ruby/internal/fl_type.h +ipsocket.o: $(hdrdir)/ruby/internal/gc.h +ipsocket.o: $(hdrdir)/ruby/internal/glob.h +ipsocket.o: $(hdrdir)/ruby/internal/globals.h +ipsocket.o: $(hdrdir)/ruby/internal/has/attribute.h +ipsocket.o: $(hdrdir)/ruby/internal/has/builtin.h +ipsocket.o: $(hdrdir)/ruby/internal/has/c_attribute.h +ipsocket.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +ipsocket.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +ipsocket.o: $(hdrdir)/ruby/internal/has/extension.h +ipsocket.o: $(hdrdir)/ruby/internal/has/feature.h +ipsocket.o: $(hdrdir)/ruby/internal/has/warning.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/array.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/bignum.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/class.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/compar.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/complex.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/cont.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/dir.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/enum.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/enumerator.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/error.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/eval.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/file.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/hash.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/io.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/load.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/marshal.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/numeric.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/object.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/parse.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/proc.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/process.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/random.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/range.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/rational.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/re.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/ruby.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/select.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/set.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/signal.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/sprintf.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/string.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/struct.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/thread.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/time.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/variable.h +ipsocket.o: $(hdrdir)/ruby/internal/intern/vm.h +ipsocket.o: $(hdrdir)/ruby/internal/interpreter.h +ipsocket.o: $(hdrdir)/ruby/internal/iterator.h +ipsocket.o: $(hdrdir)/ruby/internal/memory.h +ipsocket.o: $(hdrdir)/ruby/internal/method.h +ipsocket.o: $(hdrdir)/ruby/internal/module.h +ipsocket.o: $(hdrdir)/ruby/internal/newobj.h +ipsocket.o: $(hdrdir)/ruby/internal/scan_args.h +ipsocket.o: $(hdrdir)/ruby/internal/special_consts.h +ipsocket.o: $(hdrdir)/ruby/internal/static_assert.h +ipsocket.o: $(hdrdir)/ruby/internal/stdalign.h +ipsocket.o: $(hdrdir)/ruby/internal/stdbool.h +ipsocket.o: $(hdrdir)/ruby/internal/stdckdint.h +ipsocket.o: $(hdrdir)/ruby/internal/symbol.h +ipsocket.o: $(hdrdir)/ruby/internal/value.h +ipsocket.o: $(hdrdir)/ruby/internal/value_type.h +ipsocket.o: $(hdrdir)/ruby/internal/variable.h +ipsocket.o: $(hdrdir)/ruby/internal/warning_push.h +ipsocket.o: $(hdrdir)/ruby/internal/xmalloc.h ipsocket.o: $(hdrdir)/ruby/io.h ipsocket.o: $(hdrdir)/ruby/missing.h ipsocket.o: $(hdrdir)/ruby/onigmo.h @@ -137,20 +1267,214 @@ ipsocket.o: $(hdrdir)/ruby/ruby.h ipsocket.o: $(hdrdir)/ruby/st.h ipsocket.o: $(hdrdir)/ruby/subst.h ipsocket.o: $(hdrdir)/ruby/thread.h +ipsocket.o: $(hdrdir)/ruby/thread_native.h ipsocket.o: $(hdrdir)/ruby/util.h +ipsocket.o: $(hdrdir)/ruby/version.h +ipsocket.o: $(top_srcdir)/ccan/check_type/check_type.h +ipsocket.o: $(top_srcdir)/ccan/container_of/container_of.h +ipsocket.o: $(top_srcdir)/ccan/list/list.h +ipsocket.o: $(top_srcdir)/ccan/str/str.h +ipsocket.o: $(top_srcdir)/encindex.h +ipsocket.o: $(top_srcdir)/id_table.h ipsocket.o: $(top_srcdir)/internal.h +ipsocket.o: $(top_srcdir)/internal/array.h +ipsocket.o: $(top_srcdir)/internal/basic_operators.h +ipsocket.o: $(top_srcdir)/internal/box.h +ipsocket.o: $(top_srcdir)/internal/compilers.h +ipsocket.o: $(top_srcdir)/internal/error.h +ipsocket.o: $(top_srcdir)/internal/gc.h +ipsocket.o: $(top_srcdir)/internal/imemo.h +ipsocket.o: $(top_srcdir)/internal/io.h +ipsocket.o: $(top_srcdir)/internal/sanitizers.h +ipsocket.o: $(top_srcdir)/internal/serial.h +ipsocket.o: $(top_srcdir)/internal/set_table.h +ipsocket.o: $(top_srcdir)/internal/static_assert.h +ipsocket.o: $(top_srcdir)/internal/string.h +ipsocket.o: $(top_srcdir)/internal/thread.h +ipsocket.o: $(top_srcdir)/internal/vm.h +ipsocket.o: $(top_srcdir)/internal/warnings.h +ipsocket.o: $(top_srcdir)/method.h +ipsocket.o: $(top_srcdir)/node.h +ipsocket.o: $(top_srcdir)/ruby_assert.h +ipsocket.o: $(top_srcdir)/ruby_atomic.h +ipsocket.o: $(top_srcdir)/rubyparser.h +ipsocket.o: $(top_srcdir)/shape.h +ipsocket.o: $(top_srcdir)/thread_pthread.h +ipsocket.o: $(top_srcdir)/vm_core.h +ipsocket.o: $(top_srcdir)/vm_opts.h ipsocket.o: constdefs.h ipsocket.o: ipsocket.c ipsocket.o: rubysocket.h ipsocket.o: sockport.h +ipsocket.o: {$(VPATH)}id.h option.o: $(RUBY_EXTCONF_H) option.o: $(arch_hdrdir)/ruby/config.h -option.o: $(hdrdir)/ruby.h option.o: $(hdrdir)/ruby/assert.h +option.o: $(hdrdir)/ruby/atomic.h option.o: $(hdrdir)/ruby/backward.h +option.o: $(hdrdir)/ruby/backward/2/assume.h +option.o: $(hdrdir)/ruby/backward/2/attributes.h +option.o: $(hdrdir)/ruby/backward/2/bool.h +option.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h +option.o: $(hdrdir)/ruby/backward/2/inttypes.h +option.o: $(hdrdir)/ruby/backward/2/limits.h +option.o: $(hdrdir)/ruby/backward/2/long_long.h +option.o: $(hdrdir)/ruby/backward/2/stdalign.h +option.o: $(hdrdir)/ruby/backward/2/stdarg.h option.o: $(hdrdir)/ruby/defines.h option.o: $(hdrdir)/ruby/encoding.h +option.o: $(hdrdir)/ruby/fiber/scheduler.h option.o: $(hdrdir)/ruby/intern.h +option.o: $(hdrdir)/ruby/internal/abi.h +option.o: $(hdrdir)/ruby/internal/anyargs.h +option.o: $(hdrdir)/ruby/internal/arithmetic.h +option.o: $(hdrdir)/ruby/internal/arithmetic/char.h +option.o: $(hdrdir)/ruby/internal/arithmetic/double.h +option.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +option.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +option.o: $(hdrdir)/ruby/internal/arithmetic/int.h +option.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +option.o: $(hdrdir)/ruby/internal/arithmetic/long.h +option.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +option.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +option.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +option.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +option.o: $(hdrdir)/ruby/internal/arithmetic/short.h +option.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +option.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +option.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +option.o: $(hdrdir)/ruby/internal/assume.h +option.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +option.o: $(hdrdir)/ruby/internal/attr/artificial.h +option.o: $(hdrdir)/ruby/internal/attr/cold.h +option.o: $(hdrdir)/ruby/internal/attr/const.h +option.o: $(hdrdir)/ruby/internal/attr/constexpr.h +option.o: $(hdrdir)/ruby/internal/attr/deprecated.h +option.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +option.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +option.o: $(hdrdir)/ruby/internal/attr/error.h +option.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +option.o: $(hdrdir)/ruby/internal/attr/forceinline.h +option.o: $(hdrdir)/ruby/internal/attr/format.h +option.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +option.o: $(hdrdir)/ruby/internal/attr/noalias.h +option.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +option.o: $(hdrdir)/ruby/internal/attr/noexcept.h +option.o: $(hdrdir)/ruby/internal/attr/noinline.h +option.o: $(hdrdir)/ruby/internal/attr/nonnull.h +option.o: $(hdrdir)/ruby/internal/attr/noreturn.h +option.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +option.o: $(hdrdir)/ruby/internal/attr/pure.h +option.o: $(hdrdir)/ruby/internal/attr/restrict.h +option.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +option.o: $(hdrdir)/ruby/internal/attr/warning.h +option.o: $(hdrdir)/ruby/internal/attr/weakref.h +option.o: $(hdrdir)/ruby/internal/cast.h +option.o: $(hdrdir)/ruby/internal/compiler_is.h +option.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +option.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +option.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +option.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +option.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +option.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +option.o: $(hdrdir)/ruby/internal/compiler_since.h +option.o: $(hdrdir)/ruby/internal/config.h +option.o: $(hdrdir)/ruby/internal/constant_p.h +option.o: $(hdrdir)/ruby/internal/core.h +option.o: $(hdrdir)/ruby/internal/core/rarray.h +option.o: $(hdrdir)/ruby/internal/core/rbasic.h +option.o: $(hdrdir)/ruby/internal/core/rbignum.h +option.o: $(hdrdir)/ruby/internal/core/rclass.h +option.o: $(hdrdir)/ruby/internal/core/rdata.h +option.o: $(hdrdir)/ruby/internal/core/rfile.h +option.o: $(hdrdir)/ruby/internal/core/rhash.h +option.o: $(hdrdir)/ruby/internal/core/robject.h +option.o: $(hdrdir)/ruby/internal/core/rregexp.h +option.o: $(hdrdir)/ruby/internal/core/rstring.h +option.o: $(hdrdir)/ruby/internal/core/rstruct.h +option.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +option.o: $(hdrdir)/ruby/internal/ctype.h +option.o: $(hdrdir)/ruby/internal/dllexport.h +option.o: $(hdrdir)/ruby/internal/dosish.h +option.o: $(hdrdir)/ruby/internal/encoding/coderange.h +option.o: $(hdrdir)/ruby/internal/encoding/ctype.h +option.o: $(hdrdir)/ruby/internal/encoding/encoding.h +option.o: $(hdrdir)/ruby/internal/encoding/pathname.h +option.o: $(hdrdir)/ruby/internal/encoding/re.h +option.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +option.o: $(hdrdir)/ruby/internal/encoding/string.h +option.o: $(hdrdir)/ruby/internal/encoding/symbol.h +option.o: $(hdrdir)/ruby/internal/encoding/transcode.h +option.o: $(hdrdir)/ruby/internal/error.h +option.o: $(hdrdir)/ruby/internal/eval.h +option.o: $(hdrdir)/ruby/internal/event.h +option.o: $(hdrdir)/ruby/internal/fl_type.h +option.o: $(hdrdir)/ruby/internal/gc.h +option.o: $(hdrdir)/ruby/internal/glob.h +option.o: $(hdrdir)/ruby/internal/globals.h +option.o: $(hdrdir)/ruby/internal/has/attribute.h +option.o: $(hdrdir)/ruby/internal/has/builtin.h +option.o: $(hdrdir)/ruby/internal/has/c_attribute.h +option.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +option.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +option.o: $(hdrdir)/ruby/internal/has/extension.h +option.o: $(hdrdir)/ruby/internal/has/feature.h +option.o: $(hdrdir)/ruby/internal/has/warning.h +option.o: $(hdrdir)/ruby/internal/intern/array.h +option.o: $(hdrdir)/ruby/internal/intern/bignum.h +option.o: $(hdrdir)/ruby/internal/intern/class.h +option.o: $(hdrdir)/ruby/internal/intern/compar.h +option.o: $(hdrdir)/ruby/internal/intern/complex.h +option.o: $(hdrdir)/ruby/internal/intern/cont.h +option.o: $(hdrdir)/ruby/internal/intern/dir.h +option.o: $(hdrdir)/ruby/internal/intern/enum.h +option.o: $(hdrdir)/ruby/internal/intern/enumerator.h +option.o: $(hdrdir)/ruby/internal/intern/error.h +option.o: $(hdrdir)/ruby/internal/intern/eval.h +option.o: $(hdrdir)/ruby/internal/intern/file.h +option.o: $(hdrdir)/ruby/internal/intern/hash.h +option.o: $(hdrdir)/ruby/internal/intern/io.h +option.o: $(hdrdir)/ruby/internal/intern/load.h +option.o: $(hdrdir)/ruby/internal/intern/marshal.h +option.o: $(hdrdir)/ruby/internal/intern/numeric.h +option.o: $(hdrdir)/ruby/internal/intern/object.h +option.o: $(hdrdir)/ruby/internal/intern/parse.h +option.o: $(hdrdir)/ruby/internal/intern/proc.h +option.o: $(hdrdir)/ruby/internal/intern/process.h +option.o: $(hdrdir)/ruby/internal/intern/random.h +option.o: $(hdrdir)/ruby/internal/intern/range.h +option.o: $(hdrdir)/ruby/internal/intern/rational.h +option.o: $(hdrdir)/ruby/internal/intern/re.h +option.o: $(hdrdir)/ruby/internal/intern/ruby.h +option.o: $(hdrdir)/ruby/internal/intern/select.h +option.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +option.o: $(hdrdir)/ruby/internal/intern/set.h +option.o: $(hdrdir)/ruby/internal/intern/signal.h +option.o: $(hdrdir)/ruby/internal/intern/sprintf.h +option.o: $(hdrdir)/ruby/internal/intern/string.h +option.o: $(hdrdir)/ruby/internal/intern/struct.h +option.o: $(hdrdir)/ruby/internal/intern/thread.h +option.o: $(hdrdir)/ruby/internal/intern/time.h +option.o: $(hdrdir)/ruby/internal/intern/variable.h +option.o: $(hdrdir)/ruby/internal/intern/vm.h +option.o: $(hdrdir)/ruby/internal/interpreter.h +option.o: $(hdrdir)/ruby/internal/iterator.h +option.o: $(hdrdir)/ruby/internal/memory.h +option.o: $(hdrdir)/ruby/internal/method.h +option.o: $(hdrdir)/ruby/internal/module.h +option.o: $(hdrdir)/ruby/internal/newobj.h +option.o: $(hdrdir)/ruby/internal/scan_args.h +option.o: $(hdrdir)/ruby/internal/special_consts.h +option.o: $(hdrdir)/ruby/internal/static_assert.h +option.o: $(hdrdir)/ruby/internal/stdalign.h +option.o: $(hdrdir)/ruby/internal/stdbool.h +option.o: $(hdrdir)/ruby/internal/stdckdint.h +option.o: $(hdrdir)/ruby/internal/symbol.h +option.o: $(hdrdir)/ruby/internal/value.h +option.o: $(hdrdir)/ruby/internal/value_type.h +option.o: $(hdrdir)/ruby/internal/variable.h +option.o: $(hdrdir)/ruby/internal/warning_push.h +option.o: $(hdrdir)/ruby/internal/xmalloc.h option.o: $(hdrdir)/ruby/io.h option.o: $(hdrdir)/ruby/missing.h option.o: $(hdrdir)/ruby/onigmo.h @@ -159,20 +1483,214 @@ option.o: $(hdrdir)/ruby/ruby.h option.o: $(hdrdir)/ruby/st.h option.o: $(hdrdir)/ruby/subst.h option.o: $(hdrdir)/ruby/thread.h +option.o: $(hdrdir)/ruby/thread_native.h option.o: $(hdrdir)/ruby/util.h +option.o: $(hdrdir)/ruby/version.h +option.o: $(top_srcdir)/ccan/check_type/check_type.h +option.o: $(top_srcdir)/ccan/container_of/container_of.h +option.o: $(top_srcdir)/ccan/list/list.h +option.o: $(top_srcdir)/ccan/str/str.h +option.o: $(top_srcdir)/encindex.h +option.o: $(top_srcdir)/id_table.h option.o: $(top_srcdir)/internal.h +option.o: $(top_srcdir)/internal/array.h +option.o: $(top_srcdir)/internal/basic_operators.h +option.o: $(top_srcdir)/internal/box.h +option.o: $(top_srcdir)/internal/compilers.h +option.o: $(top_srcdir)/internal/error.h +option.o: $(top_srcdir)/internal/gc.h +option.o: $(top_srcdir)/internal/imemo.h +option.o: $(top_srcdir)/internal/io.h +option.o: $(top_srcdir)/internal/sanitizers.h +option.o: $(top_srcdir)/internal/serial.h +option.o: $(top_srcdir)/internal/set_table.h +option.o: $(top_srcdir)/internal/static_assert.h +option.o: $(top_srcdir)/internal/string.h +option.o: $(top_srcdir)/internal/thread.h +option.o: $(top_srcdir)/internal/vm.h +option.o: $(top_srcdir)/internal/warnings.h +option.o: $(top_srcdir)/method.h +option.o: $(top_srcdir)/node.h +option.o: $(top_srcdir)/ruby_assert.h +option.o: $(top_srcdir)/ruby_atomic.h +option.o: $(top_srcdir)/rubyparser.h +option.o: $(top_srcdir)/shape.h +option.o: $(top_srcdir)/thread_pthread.h +option.o: $(top_srcdir)/vm_core.h +option.o: $(top_srcdir)/vm_opts.h option.o: constdefs.h option.o: option.c option.o: rubysocket.h option.o: sockport.h +option.o: {$(VPATH)}id.h raddrinfo.o: $(RUBY_EXTCONF_H) raddrinfo.o: $(arch_hdrdir)/ruby/config.h -raddrinfo.o: $(hdrdir)/ruby.h raddrinfo.o: $(hdrdir)/ruby/assert.h +raddrinfo.o: $(hdrdir)/ruby/atomic.h raddrinfo.o: $(hdrdir)/ruby/backward.h +raddrinfo.o: $(hdrdir)/ruby/backward/2/assume.h +raddrinfo.o: $(hdrdir)/ruby/backward/2/attributes.h +raddrinfo.o: $(hdrdir)/ruby/backward/2/bool.h +raddrinfo.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h +raddrinfo.o: $(hdrdir)/ruby/backward/2/inttypes.h +raddrinfo.o: $(hdrdir)/ruby/backward/2/limits.h +raddrinfo.o: $(hdrdir)/ruby/backward/2/long_long.h +raddrinfo.o: $(hdrdir)/ruby/backward/2/stdalign.h +raddrinfo.o: $(hdrdir)/ruby/backward/2/stdarg.h raddrinfo.o: $(hdrdir)/ruby/defines.h raddrinfo.o: $(hdrdir)/ruby/encoding.h +raddrinfo.o: $(hdrdir)/ruby/fiber/scheduler.h raddrinfo.o: $(hdrdir)/ruby/intern.h +raddrinfo.o: $(hdrdir)/ruby/internal/abi.h +raddrinfo.o: $(hdrdir)/ruby/internal/anyargs.h +raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic.h +raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/char.h +raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/double.h +raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/int.h +raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/long.h +raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/short.h +raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +raddrinfo.o: $(hdrdir)/ruby/internal/assume.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/artificial.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/cold.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/const.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/constexpr.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/deprecated.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/error.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/forceinline.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/format.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/noalias.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/noexcept.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/noinline.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/nonnull.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/noreturn.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/pure.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/restrict.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/warning.h +raddrinfo.o: $(hdrdir)/ruby/internal/attr/weakref.h +raddrinfo.o: $(hdrdir)/ruby/internal/cast.h +raddrinfo.o: $(hdrdir)/ruby/internal/compiler_is.h +raddrinfo.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +raddrinfo.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +raddrinfo.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +raddrinfo.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +raddrinfo.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +raddrinfo.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +raddrinfo.o: $(hdrdir)/ruby/internal/compiler_since.h +raddrinfo.o: $(hdrdir)/ruby/internal/config.h +raddrinfo.o: $(hdrdir)/ruby/internal/constant_p.h +raddrinfo.o: $(hdrdir)/ruby/internal/core.h +raddrinfo.o: $(hdrdir)/ruby/internal/core/rarray.h +raddrinfo.o: $(hdrdir)/ruby/internal/core/rbasic.h +raddrinfo.o: $(hdrdir)/ruby/internal/core/rbignum.h +raddrinfo.o: $(hdrdir)/ruby/internal/core/rclass.h +raddrinfo.o: $(hdrdir)/ruby/internal/core/rdata.h +raddrinfo.o: $(hdrdir)/ruby/internal/core/rfile.h +raddrinfo.o: $(hdrdir)/ruby/internal/core/rhash.h +raddrinfo.o: $(hdrdir)/ruby/internal/core/robject.h +raddrinfo.o: $(hdrdir)/ruby/internal/core/rregexp.h +raddrinfo.o: $(hdrdir)/ruby/internal/core/rstring.h +raddrinfo.o: $(hdrdir)/ruby/internal/core/rstruct.h +raddrinfo.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +raddrinfo.o: $(hdrdir)/ruby/internal/ctype.h +raddrinfo.o: $(hdrdir)/ruby/internal/dllexport.h +raddrinfo.o: $(hdrdir)/ruby/internal/dosish.h +raddrinfo.o: $(hdrdir)/ruby/internal/encoding/coderange.h +raddrinfo.o: $(hdrdir)/ruby/internal/encoding/ctype.h +raddrinfo.o: $(hdrdir)/ruby/internal/encoding/encoding.h +raddrinfo.o: $(hdrdir)/ruby/internal/encoding/pathname.h +raddrinfo.o: $(hdrdir)/ruby/internal/encoding/re.h +raddrinfo.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +raddrinfo.o: $(hdrdir)/ruby/internal/encoding/string.h +raddrinfo.o: $(hdrdir)/ruby/internal/encoding/symbol.h +raddrinfo.o: $(hdrdir)/ruby/internal/encoding/transcode.h +raddrinfo.o: $(hdrdir)/ruby/internal/error.h +raddrinfo.o: $(hdrdir)/ruby/internal/eval.h +raddrinfo.o: $(hdrdir)/ruby/internal/event.h +raddrinfo.o: $(hdrdir)/ruby/internal/fl_type.h +raddrinfo.o: $(hdrdir)/ruby/internal/gc.h +raddrinfo.o: $(hdrdir)/ruby/internal/glob.h +raddrinfo.o: $(hdrdir)/ruby/internal/globals.h +raddrinfo.o: $(hdrdir)/ruby/internal/has/attribute.h +raddrinfo.o: $(hdrdir)/ruby/internal/has/builtin.h +raddrinfo.o: $(hdrdir)/ruby/internal/has/c_attribute.h +raddrinfo.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +raddrinfo.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +raddrinfo.o: $(hdrdir)/ruby/internal/has/extension.h +raddrinfo.o: $(hdrdir)/ruby/internal/has/feature.h +raddrinfo.o: $(hdrdir)/ruby/internal/has/warning.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/array.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/bignum.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/class.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/compar.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/complex.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/cont.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/dir.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/enum.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/enumerator.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/error.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/eval.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/file.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/hash.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/io.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/load.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/marshal.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/numeric.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/object.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/parse.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/proc.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/process.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/random.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/range.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/rational.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/re.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/ruby.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/select.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/set.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/signal.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/sprintf.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/string.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/struct.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/thread.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/time.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/variable.h +raddrinfo.o: $(hdrdir)/ruby/internal/intern/vm.h +raddrinfo.o: $(hdrdir)/ruby/internal/interpreter.h +raddrinfo.o: $(hdrdir)/ruby/internal/iterator.h +raddrinfo.o: $(hdrdir)/ruby/internal/memory.h +raddrinfo.o: $(hdrdir)/ruby/internal/method.h +raddrinfo.o: $(hdrdir)/ruby/internal/module.h +raddrinfo.o: $(hdrdir)/ruby/internal/newobj.h +raddrinfo.o: $(hdrdir)/ruby/internal/scan_args.h +raddrinfo.o: $(hdrdir)/ruby/internal/special_consts.h +raddrinfo.o: $(hdrdir)/ruby/internal/static_assert.h +raddrinfo.o: $(hdrdir)/ruby/internal/stdalign.h +raddrinfo.o: $(hdrdir)/ruby/internal/stdbool.h +raddrinfo.o: $(hdrdir)/ruby/internal/stdckdint.h +raddrinfo.o: $(hdrdir)/ruby/internal/symbol.h +raddrinfo.o: $(hdrdir)/ruby/internal/value.h +raddrinfo.o: $(hdrdir)/ruby/internal/value_type.h +raddrinfo.o: $(hdrdir)/ruby/internal/variable.h +raddrinfo.o: $(hdrdir)/ruby/internal/warning_push.h +raddrinfo.o: $(hdrdir)/ruby/internal/xmalloc.h raddrinfo.o: $(hdrdir)/ruby/io.h raddrinfo.o: $(hdrdir)/ruby/missing.h raddrinfo.o: $(hdrdir)/ruby/onigmo.h @@ -181,20 +1699,214 @@ raddrinfo.o: $(hdrdir)/ruby/ruby.h raddrinfo.o: $(hdrdir)/ruby/st.h raddrinfo.o: $(hdrdir)/ruby/subst.h raddrinfo.o: $(hdrdir)/ruby/thread.h +raddrinfo.o: $(hdrdir)/ruby/thread_native.h raddrinfo.o: $(hdrdir)/ruby/util.h +raddrinfo.o: $(hdrdir)/ruby/version.h +raddrinfo.o: $(top_srcdir)/ccan/check_type/check_type.h +raddrinfo.o: $(top_srcdir)/ccan/container_of/container_of.h +raddrinfo.o: $(top_srcdir)/ccan/list/list.h +raddrinfo.o: $(top_srcdir)/ccan/str/str.h +raddrinfo.o: $(top_srcdir)/encindex.h +raddrinfo.o: $(top_srcdir)/id_table.h raddrinfo.o: $(top_srcdir)/internal.h +raddrinfo.o: $(top_srcdir)/internal/array.h +raddrinfo.o: $(top_srcdir)/internal/basic_operators.h +raddrinfo.o: $(top_srcdir)/internal/box.h +raddrinfo.o: $(top_srcdir)/internal/compilers.h +raddrinfo.o: $(top_srcdir)/internal/error.h +raddrinfo.o: $(top_srcdir)/internal/gc.h +raddrinfo.o: $(top_srcdir)/internal/imemo.h +raddrinfo.o: $(top_srcdir)/internal/io.h +raddrinfo.o: $(top_srcdir)/internal/sanitizers.h +raddrinfo.o: $(top_srcdir)/internal/serial.h +raddrinfo.o: $(top_srcdir)/internal/set_table.h +raddrinfo.o: $(top_srcdir)/internal/static_assert.h +raddrinfo.o: $(top_srcdir)/internal/string.h +raddrinfo.o: $(top_srcdir)/internal/thread.h +raddrinfo.o: $(top_srcdir)/internal/vm.h +raddrinfo.o: $(top_srcdir)/internal/warnings.h +raddrinfo.o: $(top_srcdir)/method.h +raddrinfo.o: $(top_srcdir)/node.h +raddrinfo.o: $(top_srcdir)/ruby_assert.h +raddrinfo.o: $(top_srcdir)/ruby_atomic.h +raddrinfo.o: $(top_srcdir)/rubyparser.h +raddrinfo.o: $(top_srcdir)/shape.h +raddrinfo.o: $(top_srcdir)/thread_pthread.h +raddrinfo.o: $(top_srcdir)/vm_core.h +raddrinfo.o: $(top_srcdir)/vm_opts.h raddrinfo.o: constdefs.h raddrinfo.o: raddrinfo.c raddrinfo.o: rubysocket.h raddrinfo.o: sockport.h +raddrinfo.o: {$(VPATH)}id.h socket.o: $(RUBY_EXTCONF_H) socket.o: $(arch_hdrdir)/ruby/config.h -socket.o: $(hdrdir)/ruby.h socket.o: $(hdrdir)/ruby/assert.h +socket.o: $(hdrdir)/ruby/atomic.h socket.o: $(hdrdir)/ruby/backward.h +socket.o: $(hdrdir)/ruby/backward/2/assume.h +socket.o: $(hdrdir)/ruby/backward/2/attributes.h +socket.o: $(hdrdir)/ruby/backward/2/bool.h +socket.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h +socket.o: $(hdrdir)/ruby/backward/2/inttypes.h +socket.o: $(hdrdir)/ruby/backward/2/limits.h +socket.o: $(hdrdir)/ruby/backward/2/long_long.h +socket.o: $(hdrdir)/ruby/backward/2/stdalign.h +socket.o: $(hdrdir)/ruby/backward/2/stdarg.h socket.o: $(hdrdir)/ruby/defines.h socket.o: $(hdrdir)/ruby/encoding.h +socket.o: $(hdrdir)/ruby/fiber/scheduler.h socket.o: $(hdrdir)/ruby/intern.h +socket.o: $(hdrdir)/ruby/internal/abi.h +socket.o: $(hdrdir)/ruby/internal/anyargs.h +socket.o: $(hdrdir)/ruby/internal/arithmetic.h +socket.o: $(hdrdir)/ruby/internal/arithmetic/char.h +socket.o: $(hdrdir)/ruby/internal/arithmetic/double.h +socket.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +socket.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +socket.o: $(hdrdir)/ruby/internal/arithmetic/int.h +socket.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +socket.o: $(hdrdir)/ruby/internal/arithmetic/long.h +socket.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +socket.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +socket.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +socket.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +socket.o: $(hdrdir)/ruby/internal/arithmetic/short.h +socket.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +socket.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +socket.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +socket.o: $(hdrdir)/ruby/internal/assume.h +socket.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +socket.o: $(hdrdir)/ruby/internal/attr/artificial.h +socket.o: $(hdrdir)/ruby/internal/attr/cold.h +socket.o: $(hdrdir)/ruby/internal/attr/const.h +socket.o: $(hdrdir)/ruby/internal/attr/constexpr.h +socket.o: $(hdrdir)/ruby/internal/attr/deprecated.h +socket.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +socket.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +socket.o: $(hdrdir)/ruby/internal/attr/error.h +socket.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +socket.o: $(hdrdir)/ruby/internal/attr/forceinline.h +socket.o: $(hdrdir)/ruby/internal/attr/format.h +socket.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +socket.o: $(hdrdir)/ruby/internal/attr/noalias.h +socket.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +socket.o: $(hdrdir)/ruby/internal/attr/noexcept.h +socket.o: $(hdrdir)/ruby/internal/attr/noinline.h +socket.o: $(hdrdir)/ruby/internal/attr/nonnull.h +socket.o: $(hdrdir)/ruby/internal/attr/noreturn.h +socket.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +socket.o: $(hdrdir)/ruby/internal/attr/pure.h +socket.o: $(hdrdir)/ruby/internal/attr/restrict.h +socket.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +socket.o: $(hdrdir)/ruby/internal/attr/warning.h +socket.o: $(hdrdir)/ruby/internal/attr/weakref.h +socket.o: $(hdrdir)/ruby/internal/cast.h +socket.o: $(hdrdir)/ruby/internal/compiler_is.h +socket.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +socket.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +socket.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +socket.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +socket.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +socket.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +socket.o: $(hdrdir)/ruby/internal/compiler_since.h +socket.o: $(hdrdir)/ruby/internal/config.h +socket.o: $(hdrdir)/ruby/internal/constant_p.h +socket.o: $(hdrdir)/ruby/internal/core.h +socket.o: $(hdrdir)/ruby/internal/core/rarray.h +socket.o: $(hdrdir)/ruby/internal/core/rbasic.h +socket.o: $(hdrdir)/ruby/internal/core/rbignum.h +socket.o: $(hdrdir)/ruby/internal/core/rclass.h +socket.o: $(hdrdir)/ruby/internal/core/rdata.h +socket.o: $(hdrdir)/ruby/internal/core/rfile.h +socket.o: $(hdrdir)/ruby/internal/core/rhash.h +socket.o: $(hdrdir)/ruby/internal/core/robject.h +socket.o: $(hdrdir)/ruby/internal/core/rregexp.h +socket.o: $(hdrdir)/ruby/internal/core/rstring.h +socket.o: $(hdrdir)/ruby/internal/core/rstruct.h +socket.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +socket.o: $(hdrdir)/ruby/internal/ctype.h +socket.o: $(hdrdir)/ruby/internal/dllexport.h +socket.o: $(hdrdir)/ruby/internal/dosish.h +socket.o: $(hdrdir)/ruby/internal/encoding/coderange.h +socket.o: $(hdrdir)/ruby/internal/encoding/ctype.h +socket.o: $(hdrdir)/ruby/internal/encoding/encoding.h +socket.o: $(hdrdir)/ruby/internal/encoding/pathname.h +socket.o: $(hdrdir)/ruby/internal/encoding/re.h +socket.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +socket.o: $(hdrdir)/ruby/internal/encoding/string.h +socket.o: $(hdrdir)/ruby/internal/encoding/symbol.h +socket.o: $(hdrdir)/ruby/internal/encoding/transcode.h +socket.o: $(hdrdir)/ruby/internal/error.h +socket.o: $(hdrdir)/ruby/internal/eval.h +socket.o: $(hdrdir)/ruby/internal/event.h +socket.o: $(hdrdir)/ruby/internal/fl_type.h +socket.o: $(hdrdir)/ruby/internal/gc.h +socket.o: $(hdrdir)/ruby/internal/glob.h +socket.o: $(hdrdir)/ruby/internal/globals.h +socket.o: $(hdrdir)/ruby/internal/has/attribute.h +socket.o: $(hdrdir)/ruby/internal/has/builtin.h +socket.o: $(hdrdir)/ruby/internal/has/c_attribute.h +socket.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +socket.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +socket.o: $(hdrdir)/ruby/internal/has/extension.h +socket.o: $(hdrdir)/ruby/internal/has/feature.h +socket.o: $(hdrdir)/ruby/internal/has/warning.h +socket.o: $(hdrdir)/ruby/internal/intern/array.h +socket.o: $(hdrdir)/ruby/internal/intern/bignum.h +socket.o: $(hdrdir)/ruby/internal/intern/class.h +socket.o: $(hdrdir)/ruby/internal/intern/compar.h +socket.o: $(hdrdir)/ruby/internal/intern/complex.h +socket.o: $(hdrdir)/ruby/internal/intern/cont.h +socket.o: $(hdrdir)/ruby/internal/intern/dir.h +socket.o: $(hdrdir)/ruby/internal/intern/enum.h +socket.o: $(hdrdir)/ruby/internal/intern/enumerator.h +socket.o: $(hdrdir)/ruby/internal/intern/error.h +socket.o: $(hdrdir)/ruby/internal/intern/eval.h +socket.o: $(hdrdir)/ruby/internal/intern/file.h +socket.o: $(hdrdir)/ruby/internal/intern/hash.h +socket.o: $(hdrdir)/ruby/internal/intern/io.h +socket.o: $(hdrdir)/ruby/internal/intern/load.h +socket.o: $(hdrdir)/ruby/internal/intern/marshal.h +socket.o: $(hdrdir)/ruby/internal/intern/numeric.h +socket.o: $(hdrdir)/ruby/internal/intern/object.h +socket.o: $(hdrdir)/ruby/internal/intern/parse.h +socket.o: $(hdrdir)/ruby/internal/intern/proc.h +socket.o: $(hdrdir)/ruby/internal/intern/process.h +socket.o: $(hdrdir)/ruby/internal/intern/random.h +socket.o: $(hdrdir)/ruby/internal/intern/range.h +socket.o: $(hdrdir)/ruby/internal/intern/rational.h +socket.o: $(hdrdir)/ruby/internal/intern/re.h +socket.o: $(hdrdir)/ruby/internal/intern/ruby.h +socket.o: $(hdrdir)/ruby/internal/intern/select.h +socket.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +socket.o: $(hdrdir)/ruby/internal/intern/set.h +socket.o: $(hdrdir)/ruby/internal/intern/signal.h +socket.o: $(hdrdir)/ruby/internal/intern/sprintf.h +socket.o: $(hdrdir)/ruby/internal/intern/string.h +socket.o: $(hdrdir)/ruby/internal/intern/struct.h +socket.o: $(hdrdir)/ruby/internal/intern/thread.h +socket.o: $(hdrdir)/ruby/internal/intern/time.h +socket.o: $(hdrdir)/ruby/internal/intern/variable.h +socket.o: $(hdrdir)/ruby/internal/intern/vm.h +socket.o: $(hdrdir)/ruby/internal/interpreter.h +socket.o: $(hdrdir)/ruby/internal/iterator.h +socket.o: $(hdrdir)/ruby/internal/memory.h +socket.o: $(hdrdir)/ruby/internal/method.h +socket.o: $(hdrdir)/ruby/internal/module.h +socket.o: $(hdrdir)/ruby/internal/newobj.h +socket.o: $(hdrdir)/ruby/internal/scan_args.h +socket.o: $(hdrdir)/ruby/internal/special_consts.h +socket.o: $(hdrdir)/ruby/internal/static_assert.h +socket.o: $(hdrdir)/ruby/internal/stdalign.h +socket.o: $(hdrdir)/ruby/internal/stdbool.h +socket.o: $(hdrdir)/ruby/internal/stdckdint.h +socket.o: $(hdrdir)/ruby/internal/symbol.h +socket.o: $(hdrdir)/ruby/internal/value.h +socket.o: $(hdrdir)/ruby/internal/value_type.h +socket.o: $(hdrdir)/ruby/internal/variable.h +socket.o: $(hdrdir)/ruby/internal/warning_push.h +socket.o: $(hdrdir)/ruby/internal/xmalloc.h socket.o: $(hdrdir)/ruby/io.h socket.o: $(hdrdir)/ruby/missing.h socket.o: $(hdrdir)/ruby/onigmo.h @@ -203,20 +1915,214 @@ socket.o: $(hdrdir)/ruby/ruby.h socket.o: $(hdrdir)/ruby/st.h socket.o: $(hdrdir)/ruby/subst.h socket.o: $(hdrdir)/ruby/thread.h +socket.o: $(hdrdir)/ruby/thread_native.h socket.o: $(hdrdir)/ruby/util.h +socket.o: $(hdrdir)/ruby/version.h +socket.o: $(top_srcdir)/ccan/check_type/check_type.h +socket.o: $(top_srcdir)/ccan/container_of/container_of.h +socket.o: $(top_srcdir)/ccan/list/list.h +socket.o: $(top_srcdir)/ccan/str/str.h +socket.o: $(top_srcdir)/encindex.h +socket.o: $(top_srcdir)/id_table.h socket.o: $(top_srcdir)/internal.h +socket.o: $(top_srcdir)/internal/array.h +socket.o: $(top_srcdir)/internal/basic_operators.h +socket.o: $(top_srcdir)/internal/box.h +socket.o: $(top_srcdir)/internal/compilers.h +socket.o: $(top_srcdir)/internal/error.h +socket.o: $(top_srcdir)/internal/gc.h +socket.o: $(top_srcdir)/internal/imemo.h +socket.o: $(top_srcdir)/internal/io.h +socket.o: $(top_srcdir)/internal/sanitizers.h +socket.o: $(top_srcdir)/internal/serial.h +socket.o: $(top_srcdir)/internal/set_table.h +socket.o: $(top_srcdir)/internal/static_assert.h +socket.o: $(top_srcdir)/internal/string.h +socket.o: $(top_srcdir)/internal/thread.h +socket.o: $(top_srcdir)/internal/vm.h +socket.o: $(top_srcdir)/internal/warnings.h +socket.o: $(top_srcdir)/method.h +socket.o: $(top_srcdir)/node.h +socket.o: $(top_srcdir)/ruby_assert.h +socket.o: $(top_srcdir)/ruby_atomic.h +socket.o: $(top_srcdir)/rubyparser.h +socket.o: $(top_srcdir)/shape.h +socket.o: $(top_srcdir)/thread_pthread.h +socket.o: $(top_srcdir)/vm_core.h +socket.o: $(top_srcdir)/vm_opts.h socket.o: constdefs.h socket.o: rubysocket.h socket.o: socket.c socket.o: sockport.h +socket.o: {$(VPATH)}id.h sockssocket.o: $(RUBY_EXTCONF_H) sockssocket.o: $(arch_hdrdir)/ruby/config.h -sockssocket.o: $(hdrdir)/ruby.h sockssocket.o: $(hdrdir)/ruby/assert.h +sockssocket.o: $(hdrdir)/ruby/atomic.h sockssocket.o: $(hdrdir)/ruby/backward.h +sockssocket.o: $(hdrdir)/ruby/backward/2/assume.h +sockssocket.o: $(hdrdir)/ruby/backward/2/attributes.h +sockssocket.o: $(hdrdir)/ruby/backward/2/bool.h +sockssocket.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h +sockssocket.o: $(hdrdir)/ruby/backward/2/inttypes.h +sockssocket.o: $(hdrdir)/ruby/backward/2/limits.h +sockssocket.o: $(hdrdir)/ruby/backward/2/long_long.h +sockssocket.o: $(hdrdir)/ruby/backward/2/stdalign.h +sockssocket.o: $(hdrdir)/ruby/backward/2/stdarg.h sockssocket.o: $(hdrdir)/ruby/defines.h sockssocket.o: $(hdrdir)/ruby/encoding.h +sockssocket.o: $(hdrdir)/ruby/fiber/scheduler.h sockssocket.o: $(hdrdir)/ruby/intern.h +sockssocket.o: $(hdrdir)/ruby/internal/abi.h +sockssocket.o: $(hdrdir)/ruby/internal/anyargs.h +sockssocket.o: $(hdrdir)/ruby/internal/arithmetic.h +sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/char.h +sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/double.h +sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/int.h +sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/long.h +sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/short.h +sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +sockssocket.o: $(hdrdir)/ruby/internal/assume.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/artificial.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/cold.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/const.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/constexpr.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/deprecated.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/error.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/forceinline.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/format.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/noalias.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/noexcept.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/noinline.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/nonnull.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/noreturn.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/pure.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/restrict.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/warning.h +sockssocket.o: $(hdrdir)/ruby/internal/attr/weakref.h +sockssocket.o: $(hdrdir)/ruby/internal/cast.h +sockssocket.o: $(hdrdir)/ruby/internal/compiler_is.h +sockssocket.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +sockssocket.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +sockssocket.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +sockssocket.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +sockssocket.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +sockssocket.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +sockssocket.o: $(hdrdir)/ruby/internal/compiler_since.h +sockssocket.o: $(hdrdir)/ruby/internal/config.h +sockssocket.o: $(hdrdir)/ruby/internal/constant_p.h +sockssocket.o: $(hdrdir)/ruby/internal/core.h +sockssocket.o: $(hdrdir)/ruby/internal/core/rarray.h +sockssocket.o: $(hdrdir)/ruby/internal/core/rbasic.h +sockssocket.o: $(hdrdir)/ruby/internal/core/rbignum.h +sockssocket.o: $(hdrdir)/ruby/internal/core/rclass.h +sockssocket.o: $(hdrdir)/ruby/internal/core/rdata.h +sockssocket.o: $(hdrdir)/ruby/internal/core/rfile.h +sockssocket.o: $(hdrdir)/ruby/internal/core/rhash.h +sockssocket.o: $(hdrdir)/ruby/internal/core/robject.h +sockssocket.o: $(hdrdir)/ruby/internal/core/rregexp.h +sockssocket.o: $(hdrdir)/ruby/internal/core/rstring.h +sockssocket.o: $(hdrdir)/ruby/internal/core/rstruct.h +sockssocket.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +sockssocket.o: $(hdrdir)/ruby/internal/ctype.h +sockssocket.o: $(hdrdir)/ruby/internal/dllexport.h +sockssocket.o: $(hdrdir)/ruby/internal/dosish.h +sockssocket.o: $(hdrdir)/ruby/internal/encoding/coderange.h +sockssocket.o: $(hdrdir)/ruby/internal/encoding/ctype.h +sockssocket.o: $(hdrdir)/ruby/internal/encoding/encoding.h +sockssocket.o: $(hdrdir)/ruby/internal/encoding/pathname.h +sockssocket.o: $(hdrdir)/ruby/internal/encoding/re.h +sockssocket.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +sockssocket.o: $(hdrdir)/ruby/internal/encoding/string.h +sockssocket.o: $(hdrdir)/ruby/internal/encoding/symbol.h +sockssocket.o: $(hdrdir)/ruby/internal/encoding/transcode.h +sockssocket.o: $(hdrdir)/ruby/internal/error.h +sockssocket.o: $(hdrdir)/ruby/internal/eval.h +sockssocket.o: $(hdrdir)/ruby/internal/event.h +sockssocket.o: $(hdrdir)/ruby/internal/fl_type.h +sockssocket.o: $(hdrdir)/ruby/internal/gc.h +sockssocket.o: $(hdrdir)/ruby/internal/glob.h +sockssocket.o: $(hdrdir)/ruby/internal/globals.h +sockssocket.o: $(hdrdir)/ruby/internal/has/attribute.h +sockssocket.o: $(hdrdir)/ruby/internal/has/builtin.h +sockssocket.o: $(hdrdir)/ruby/internal/has/c_attribute.h +sockssocket.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +sockssocket.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +sockssocket.o: $(hdrdir)/ruby/internal/has/extension.h +sockssocket.o: $(hdrdir)/ruby/internal/has/feature.h +sockssocket.o: $(hdrdir)/ruby/internal/has/warning.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/array.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/bignum.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/class.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/compar.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/complex.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/cont.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/dir.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/enum.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/enumerator.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/error.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/eval.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/file.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/hash.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/io.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/load.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/marshal.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/numeric.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/object.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/parse.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/proc.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/process.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/random.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/range.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/rational.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/re.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/ruby.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/select.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/set.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/signal.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/sprintf.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/string.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/struct.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/thread.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/time.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/variable.h +sockssocket.o: $(hdrdir)/ruby/internal/intern/vm.h +sockssocket.o: $(hdrdir)/ruby/internal/interpreter.h +sockssocket.o: $(hdrdir)/ruby/internal/iterator.h +sockssocket.o: $(hdrdir)/ruby/internal/memory.h +sockssocket.o: $(hdrdir)/ruby/internal/method.h +sockssocket.o: $(hdrdir)/ruby/internal/module.h +sockssocket.o: $(hdrdir)/ruby/internal/newobj.h +sockssocket.o: $(hdrdir)/ruby/internal/scan_args.h +sockssocket.o: $(hdrdir)/ruby/internal/special_consts.h +sockssocket.o: $(hdrdir)/ruby/internal/static_assert.h +sockssocket.o: $(hdrdir)/ruby/internal/stdalign.h +sockssocket.o: $(hdrdir)/ruby/internal/stdbool.h +sockssocket.o: $(hdrdir)/ruby/internal/stdckdint.h +sockssocket.o: $(hdrdir)/ruby/internal/symbol.h +sockssocket.o: $(hdrdir)/ruby/internal/value.h +sockssocket.o: $(hdrdir)/ruby/internal/value_type.h +sockssocket.o: $(hdrdir)/ruby/internal/variable.h +sockssocket.o: $(hdrdir)/ruby/internal/warning_push.h +sockssocket.o: $(hdrdir)/ruby/internal/xmalloc.h sockssocket.o: $(hdrdir)/ruby/io.h sockssocket.o: $(hdrdir)/ruby/missing.h sockssocket.o: $(hdrdir)/ruby/onigmo.h @@ -225,20 +2131,214 @@ sockssocket.o: $(hdrdir)/ruby/ruby.h sockssocket.o: $(hdrdir)/ruby/st.h sockssocket.o: $(hdrdir)/ruby/subst.h sockssocket.o: $(hdrdir)/ruby/thread.h +sockssocket.o: $(hdrdir)/ruby/thread_native.h sockssocket.o: $(hdrdir)/ruby/util.h +sockssocket.o: $(hdrdir)/ruby/version.h +sockssocket.o: $(top_srcdir)/ccan/check_type/check_type.h +sockssocket.o: $(top_srcdir)/ccan/container_of/container_of.h +sockssocket.o: $(top_srcdir)/ccan/list/list.h +sockssocket.o: $(top_srcdir)/ccan/str/str.h +sockssocket.o: $(top_srcdir)/encindex.h +sockssocket.o: $(top_srcdir)/id_table.h sockssocket.o: $(top_srcdir)/internal.h +sockssocket.o: $(top_srcdir)/internal/array.h +sockssocket.o: $(top_srcdir)/internal/basic_operators.h +sockssocket.o: $(top_srcdir)/internal/box.h +sockssocket.o: $(top_srcdir)/internal/compilers.h +sockssocket.o: $(top_srcdir)/internal/error.h +sockssocket.o: $(top_srcdir)/internal/gc.h +sockssocket.o: $(top_srcdir)/internal/imemo.h +sockssocket.o: $(top_srcdir)/internal/io.h +sockssocket.o: $(top_srcdir)/internal/sanitizers.h +sockssocket.o: $(top_srcdir)/internal/serial.h +sockssocket.o: $(top_srcdir)/internal/set_table.h +sockssocket.o: $(top_srcdir)/internal/static_assert.h +sockssocket.o: $(top_srcdir)/internal/string.h +sockssocket.o: $(top_srcdir)/internal/thread.h +sockssocket.o: $(top_srcdir)/internal/vm.h +sockssocket.o: $(top_srcdir)/internal/warnings.h +sockssocket.o: $(top_srcdir)/method.h +sockssocket.o: $(top_srcdir)/node.h +sockssocket.o: $(top_srcdir)/ruby_assert.h +sockssocket.o: $(top_srcdir)/ruby_atomic.h +sockssocket.o: $(top_srcdir)/rubyparser.h +sockssocket.o: $(top_srcdir)/shape.h +sockssocket.o: $(top_srcdir)/thread_pthread.h +sockssocket.o: $(top_srcdir)/vm_core.h +sockssocket.o: $(top_srcdir)/vm_opts.h sockssocket.o: constdefs.h sockssocket.o: rubysocket.h sockssocket.o: sockport.h sockssocket.o: sockssocket.c +sockssocket.o: {$(VPATH)}id.h tcpserver.o: $(RUBY_EXTCONF_H) tcpserver.o: $(arch_hdrdir)/ruby/config.h -tcpserver.o: $(hdrdir)/ruby.h tcpserver.o: $(hdrdir)/ruby/assert.h +tcpserver.o: $(hdrdir)/ruby/atomic.h tcpserver.o: $(hdrdir)/ruby/backward.h +tcpserver.o: $(hdrdir)/ruby/backward/2/assume.h +tcpserver.o: $(hdrdir)/ruby/backward/2/attributes.h +tcpserver.o: $(hdrdir)/ruby/backward/2/bool.h +tcpserver.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h +tcpserver.o: $(hdrdir)/ruby/backward/2/inttypes.h +tcpserver.o: $(hdrdir)/ruby/backward/2/limits.h +tcpserver.o: $(hdrdir)/ruby/backward/2/long_long.h +tcpserver.o: $(hdrdir)/ruby/backward/2/stdalign.h +tcpserver.o: $(hdrdir)/ruby/backward/2/stdarg.h tcpserver.o: $(hdrdir)/ruby/defines.h tcpserver.o: $(hdrdir)/ruby/encoding.h +tcpserver.o: $(hdrdir)/ruby/fiber/scheduler.h tcpserver.o: $(hdrdir)/ruby/intern.h +tcpserver.o: $(hdrdir)/ruby/internal/abi.h +tcpserver.o: $(hdrdir)/ruby/internal/anyargs.h +tcpserver.o: $(hdrdir)/ruby/internal/arithmetic.h +tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/char.h +tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/double.h +tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/int.h +tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/long.h +tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/short.h +tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +tcpserver.o: $(hdrdir)/ruby/internal/assume.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/artificial.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/cold.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/const.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/constexpr.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/deprecated.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/error.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/forceinline.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/format.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/noalias.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/noexcept.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/noinline.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/nonnull.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/noreturn.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/pure.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/restrict.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/warning.h +tcpserver.o: $(hdrdir)/ruby/internal/attr/weakref.h +tcpserver.o: $(hdrdir)/ruby/internal/cast.h +tcpserver.o: $(hdrdir)/ruby/internal/compiler_is.h +tcpserver.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +tcpserver.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +tcpserver.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +tcpserver.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +tcpserver.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +tcpserver.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +tcpserver.o: $(hdrdir)/ruby/internal/compiler_since.h +tcpserver.o: $(hdrdir)/ruby/internal/config.h +tcpserver.o: $(hdrdir)/ruby/internal/constant_p.h +tcpserver.o: $(hdrdir)/ruby/internal/core.h +tcpserver.o: $(hdrdir)/ruby/internal/core/rarray.h +tcpserver.o: $(hdrdir)/ruby/internal/core/rbasic.h +tcpserver.o: $(hdrdir)/ruby/internal/core/rbignum.h +tcpserver.o: $(hdrdir)/ruby/internal/core/rclass.h +tcpserver.o: $(hdrdir)/ruby/internal/core/rdata.h +tcpserver.o: $(hdrdir)/ruby/internal/core/rfile.h +tcpserver.o: $(hdrdir)/ruby/internal/core/rhash.h +tcpserver.o: $(hdrdir)/ruby/internal/core/robject.h +tcpserver.o: $(hdrdir)/ruby/internal/core/rregexp.h +tcpserver.o: $(hdrdir)/ruby/internal/core/rstring.h +tcpserver.o: $(hdrdir)/ruby/internal/core/rstruct.h +tcpserver.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +tcpserver.o: $(hdrdir)/ruby/internal/ctype.h +tcpserver.o: $(hdrdir)/ruby/internal/dllexport.h +tcpserver.o: $(hdrdir)/ruby/internal/dosish.h +tcpserver.o: $(hdrdir)/ruby/internal/encoding/coderange.h +tcpserver.o: $(hdrdir)/ruby/internal/encoding/ctype.h +tcpserver.o: $(hdrdir)/ruby/internal/encoding/encoding.h +tcpserver.o: $(hdrdir)/ruby/internal/encoding/pathname.h +tcpserver.o: $(hdrdir)/ruby/internal/encoding/re.h +tcpserver.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +tcpserver.o: $(hdrdir)/ruby/internal/encoding/string.h +tcpserver.o: $(hdrdir)/ruby/internal/encoding/symbol.h +tcpserver.o: $(hdrdir)/ruby/internal/encoding/transcode.h +tcpserver.o: $(hdrdir)/ruby/internal/error.h +tcpserver.o: $(hdrdir)/ruby/internal/eval.h +tcpserver.o: $(hdrdir)/ruby/internal/event.h +tcpserver.o: $(hdrdir)/ruby/internal/fl_type.h +tcpserver.o: $(hdrdir)/ruby/internal/gc.h +tcpserver.o: $(hdrdir)/ruby/internal/glob.h +tcpserver.o: $(hdrdir)/ruby/internal/globals.h +tcpserver.o: $(hdrdir)/ruby/internal/has/attribute.h +tcpserver.o: $(hdrdir)/ruby/internal/has/builtin.h +tcpserver.o: $(hdrdir)/ruby/internal/has/c_attribute.h +tcpserver.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +tcpserver.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +tcpserver.o: $(hdrdir)/ruby/internal/has/extension.h +tcpserver.o: $(hdrdir)/ruby/internal/has/feature.h +tcpserver.o: $(hdrdir)/ruby/internal/has/warning.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/array.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/bignum.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/class.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/compar.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/complex.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/cont.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/dir.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/enum.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/enumerator.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/error.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/eval.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/file.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/hash.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/io.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/load.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/marshal.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/numeric.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/object.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/parse.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/proc.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/process.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/random.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/range.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/rational.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/re.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/ruby.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/select.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/set.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/signal.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/sprintf.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/string.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/struct.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/thread.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/time.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/variable.h +tcpserver.o: $(hdrdir)/ruby/internal/intern/vm.h +tcpserver.o: $(hdrdir)/ruby/internal/interpreter.h +tcpserver.o: $(hdrdir)/ruby/internal/iterator.h +tcpserver.o: $(hdrdir)/ruby/internal/memory.h +tcpserver.o: $(hdrdir)/ruby/internal/method.h +tcpserver.o: $(hdrdir)/ruby/internal/module.h +tcpserver.o: $(hdrdir)/ruby/internal/newobj.h +tcpserver.o: $(hdrdir)/ruby/internal/scan_args.h +tcpserver.o: $(hdrdir)/ruby/internal/special_consts.h +tcpserver.o: $(hdrdir)/ruby/internal/static_assert.h +tcpserver.o: $(hdrdir)/ruby/internal/stdalign.h +tcpserver.o: $(hdrdir)/ruby/internal/stdbool.h +tcpserver.o: $(hdrdir)/ruby/internal/stdckdint.h +tcpserver.o: $(hdrdir)/ruby/internal/symbol.h +tcpserver.o: $(hdrdir)/ruby/internal/value.h +tcpserver.o: $(hdrdir)/ruby/internal/value_type.h +tcpserver.o: $(hdrdir)/ruby/internal/variable.h +tcpserver.o: $(hdrdir)/ruby/internal/warning_push.h +tcpserver.o: $(hdrdir)/ruby/internal/xmalloc.h tcpserver.o: $(hdrdir)/ruby/io.h tcpserver.o: $(hdrdir)/ruby/missing.h tcpserver.o: $(hdrdir)/ruby/onigmo.h @@ -247,20 +2347,214 @@ tcpserver.o: $(hdrdir)/ruby/ruby.h tcpserver.o: $(hdrdir)/ruby/st.h tcpserver.o: $(hdrdir)/ruby/subst.h tcpserver.o: $(hdrdir)/ruby/thread.h +tcpserver.o: $(hdrdir)/ruby/thread_native.h tcpserver.o: $(hdrdir)/ruby/util.h +tcpserver.o: $(hdrdir)/ruby/version.h +tcpserver.o: $(top_srcdir)/ccan/check_type/check_type.h +tcpserver.o: $(top_srcdir)/ccan/container_of/container_of.h +tcpserver.o: $(top_srcdir)/ccan/list/list.h +tcpserver.o: $(top_srcdir)/ccan/str/str.h +tcpserver.o: $(top_srcdir)/encindex.h +tcpserver.o: $(top_srcdir)/id_table.h tcpserver.o: $(top_srcdir)/internal.h +tcpserver.o: $(top_srcdir)/internal/array.h +tcpserver.o: $(top_srcdir)/internal/basic_operators.h +tcpserver.o: $(top_srcdir)/internal/box.h +tcpserver.o: $(top_srcdir)/internal/compilers.h +tcpserver.o: $(top_srcdir)/internal/error.h +tcpserver.o: $(top_srcdir)/internal/gc.h +tcpserver.o: $(top_srcdir)/internal/imemo.h +tcpserver.o: $(top_srcdir)/internal/io.h +tcpserver.o: $(top_srcdir)/internal/sanitizers.h +tcpserver.o: $(top_srcdir)/internal/serial.h +tcpserver.o: $(top_srcdir)/internal/set_table.h +tcpserver.o: $(top_srcdir)/internal/static_assert.h +tcpserver.o: $(top_srcdir)/internal/string.h +tcpserver.o: $(top_srcdir)/internal/thread.h +tcpserver.o: $(top_srcdir)/internal/vm.h +tcpserver.o: $(top_srcdir)/internal/warnings.h +tcpserver.o: $(top_srcdir)/method.h +tcpserver.o: $(top_srcdir)/node.h +tcpserver.o: $(top_srcdir)/ruby_assert.h +tcpserver.o: $(top_srcdir)/ruby_atomic.h +tcpserver.o: $(top_srcdir)/rubyparser.h +tcpserver.o: $(top_srcdir)/shape.h +tcpserver.o: $(top_srcdir)/thread_pthread.h +tcpserver.o: $(top_srcdir)/vm_core.h +tcpserver.o: $(top_srcdir)/vm_opts.h tcpserver.o: constdefs.h tcpserver.o: rubysocket.h tcpserver.o: sockport.h tcpserver.o: tcpserver.c +tcpserver.o: {$(VPATH)}id.h tcpsocket.o: $(RUBY_EXTCONF_H) tcpsocket.o: $(arch_hdrdir)/ruby/config.h -tcpsocket.o: $(hdrdir)/ruby.h tcpsocket.o: $(hdrdir)/ruby/assert.h +tcpsocket.o: $(hdrdir)/ruby/atomic.h tcpsocket.o: $(hdrdir)/ruby/backward.h +tcpsocket.o: $(hdrdir)/ruby/backward/2/assume.h +tcpsocket.o: $(hdrdir)/ruby/backward/2/attributes.h +tcpsocket.o: $(hdrdir)/ruby/backward/2/bool.h +tcpsocket.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h +tcpsocket.o: $(hdrdir)/ruby/backward/2/inttypes.h +tcpsocket.o: $(hdrdir)/ruby/backward/2/limits.h +tcpsocket.o: $(hdrdir)/ruby/backward/2/long_long.h +tcpsocket.o: $(hdrdir)/ruby/backward/2/stdalign.h +tcpsocket.o: $(hdrdir)/ruby/backward/2/stdarg.h tcpsocket.o: $(hdrdir)/ruby/defines.h tcpsocket.o: $(hdrdir)/ruby/encoding.h +tcpsocket.o: $(hdrdir)/ruby/fiber/scheduler.h tcpsocket.o: $(hdrdir)/ruby/intern.h +tcpsocket.o: $(hdrdir)/ruby/internal/abi.h +tcpsocket.o: $(hdrdir)/ruby/internal/anyargs.h +tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic.h +tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/char.h +tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/double.h +tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/int.h +tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/long.h +tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/short.h +tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +tcpsocket.o: $(hdrdir)/ruby/internal/assume.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/artificial.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/cold.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/const.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/constexpr.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/deprecated.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/error.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/forceinline.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/format.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/noalias.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/noexcept.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/noinline.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/nonnull.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/noreturn.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/pure.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/restrict.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/warning.h +tcpsocket.o: $(hdrdir)/ruby/internal/attr/weakref.h +tcpsocket.o: $(hdrdir)/ruby/internal/cast.h +tcpsocket.o: $(hdrdir)/ruby/internal/compiler_is.h +tcpsocket.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +tcpsocket.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +tcpsocket.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +tcpsocket.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +tcpsocket.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +tcpsocket.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +tcpsocket.o: $(hdrdir)/ruby/internal/compiler_since.h +tcpsocket.o: $(hdrdir)/ruby/internal/config.h +tcpsocket.o: $(hdrdir)/ruby/internal/constant_p.h +tcpsocket.o: $(hdrdir)/ruby/internal/core.h +tcpsocket.o: $(hdrdir)/ruby/internal/core/rarray.h +tcpsocket.o: $(hdrdir)/ruby/internal/core/rbasic.h +tcpsocket.o: $(hdrdir)/ruby/internal/core/rbignum.h +tcpsocket.o: $(hdrdir)/ruby/internal/core/rclass.h +tcpsocket.o: $(hdrdir)/ruby/internal/core/rdata.h +tcpsocket.o: $(hdrdir)/ruby/internal/core/rfile.h +tcpsocket.o: $(hdrdir)/ruby/internal/core/rhash.h +tcpsocket.o: $(hdrdir)/ruby/internal/core/robject.h +tcpsocket.o: $(hdrdir)/ruby/internal/core/rregexp.h +tcpsocket.o: $(hdrdir)/ruby/internal/core/rstring.h +tcpsocket.o: $(hdrdir)/ruby/internal/core/rstruct.h +tcpsocket.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +tcpsocket.o: $(hdrdir)/ruby/internal/ctype.h +tcpsocket.o: $(hdrdir)/ruby/internal/dllexport.h +tcpsocket.o: $(hdrdir)/ruby/internal/dosish.h +tcpsocket.o: $(hdrdir)/ruby/internal/encoding/coderange.h +tcpsocket.o: $(hdrdir)/ruby/internal/encoding/ctype.h +tcpsocket.o: $(hdrdir)/ruby/internal/encoding/encoding.h +tcpsocket.o: $(hdrdir)/ruby/internal/encoding/pathname.h +tcpsocket.o: $(hdrdir)/ruby/internal/encoding/re.h +tcpsocket.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +tcpsocket.o: $(hdrdir)/ruby/internal/encoding/string.h +tcpsocket.o: $(hdrdir)/ruby/internal/encoding/symbol.h +tcpsocket.o: $(hdrdir)/ruby/internal/encoding/transcode.h +tcpsocket.o: $(hdrdir)/ruby/internal/error.h +tcpsocket.o: $(hdrdir)/ruby/internal/eval.h +tcpsocket.o: $(hdrdir)/ruby/internal/event.h +tcpsocket.o: $(hdrdir)/ruby/internal/fl_type.h +tcpsocket.o: $(hdrdir)/ruby/internal/gc.h +tcpsocket.o: $(hdrdir)/ruby/internal/glob.h +tcpsocket.o: $(hdrdir)/ruby/internal/globals.h +tcpsocket.o: $(hdrdir)/ruby/internal/has/attribute.h +tcpsocket.o: $(hdrdir)/ruby/internal/has/builtin.h +tcpsocket.o: $(hdrdir)/ruby/internal/has/c_attribute.h +tcpsocket.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +tcpsocket.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +tcpsocket.o: $(hdrdir)/ruby/internal/has/extension.h +tcpsocket.o: $(hdrdir)/ruby/internal/has/feature.h +tcpsocket.o: $(hdrdir)/ruby/internal/has/warning.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/array.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/bignum.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/class.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/compar.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/complex.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/cont.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/dir.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/enum.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/enumerator.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/error.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/eval.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/file.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/hash.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/io.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/load.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/marshal.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/numeric.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/object.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/parse.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/proc.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/process.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/random.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/range.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/rational.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/re.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/ruby.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/select.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/set.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/signal.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/sprintf.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/string.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/struct.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/thread.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/time.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/variable.h +tcpsocket.o: $(hdrdir)/ruby/internal/intern/vm.h +tcpsocket.o: $(hdrdir)/ruby/internal/interpreter.h +tcpsocket.o: $(hdrdir)/ruby/internal/iterator.h +tcpsocket.o: $(hdrdir)/ruby/internal/memory.h +tcpsocket.o: $(hdrdir)/ruby/internal/method.h +tcpsocket.o: $(hdrdir)/ruby/internal/module.h +tcpsocket.o: $(hdrdir)/ruby/internal/newobj.h +tcpsocket.o: $(hdrdir)/ruby/internal/scan_args.h +tcpsocket.o: $(hdrdir)/ruby/internal/special_consts.h +tcpsocket.o: $(hdrdir)/ruby/internal/static_assert.h +tcpsocket.o: $(hdrdir)/ruby/internal/stdalign.h +tcpsocket.o: $(hdrdir)/ruby/internal/stdbool.h +tcpsocket.o: $(hdrdir)/ruby/internal/stdckdint.h +tcpsocket.o: $(hdrdir)/ruby/internal/symbol.h +tcpsocket.o: $(hdrdir)/ruby/internal/value.h +tcpsocket.o: $(hdrdir)/ruby/internal/value_type.h +tcpsocket.o: $(hdrdir)/ruby/internal/variable.h +tcpsocket.o: $(hdrdir)/ruby/internal/warning_push.h +tcpsocket.o: $(hdrdir)/ruby/internal/xmalloc.h tcpsocket.o: $(hdrdir)/ruby/io.h tcpsocket.o: $(hdrdir)/ruby/missing.h tcpsocket.o: $(hdrdir)/ruby/onigmo.h @@ -269,20 +2563,214 @@ tcpsocket.o: $(hdrdir)/ruby/ruby.h tcpsocket.o: $(hdrdir)/ruby/st.h tcpsocket.o: $(hdrdir)/ruby/subst.h tcpsocket.o: $(hdrdir)/ruby/thread.h +tcpsocket.o: $(hdrdir)/ruby/thread_native.h tcpsocket.o: $(hdrdir)/ruby/util.h +tcpsocket.o: $(hdrdir)/ruby/version.h +tcpsocket.o: $(top_srcdir)/ccan/check_type/check_type.h +tcpsocket.o: $(top_srcdir)/ccan/container_of/container_of.h +tcpsocket.o: $(top_srcdir)/ccan/list/list.h +tcpsocket.o: $(top_srcdir)/ccan/str/str.h +tcpsocket.o: $(top_srcdir)/encindex.h +tcpsocket.o: $(top_srcdir)/id_table.h tcpsocket.o: $(top_srcdir)/internal.h +tcpsocket.o: $(top_srcdir)/internal/array.h +tcpsocket.o: $(top_srcdir)/internal/basic_operators.h +tcpsocket.o: $(top_srcdir)/internal/box.h +tcpsocket.o: $(top_srcdir)/internal/compilers.h +tcpsocket.o: $(top_srcdir)/internal/error.h +tcpsocket.o: $(top_srcdir)/internal/gc.h +tcpsocket.o: $(top_srcdir)/internal/imemo.h +tcpsocket.o: $(top_srcdir)/internal/io.h +tcpsocket.o: $(top_srcdir)/internal/sanitizers.h +tcpsocket.o: $(top_srcdir)/internal/serial.h +tcpsocket.o: $(top_srcdir)/internal/set_table.h +tcpsocket.o: $(top_srcdir)/internal/static_assert.h +tcpsocket.o: $(top_srcdir)/internal/string.h +tcpsocket.o: $(top_srcdir)/internal/thread.h +tcpsocket.o: $(top_srcdir)/internal/vm.h +tcpsocket.o: $(top_srcdir)/internal/warnings.h +tcpsocket.o: $(top_srcdir)/method.h +tcpsocket.o: $(top_srcdir)/node.h +tcpsocket.o: $(top_srcdir)/ruby_assert.h +tcpsocket.o: $(top_srcdir)/ruby_atomic.h +tcpsocket.o: $(top_srcdir)/rubyparser.h +tcpsocket.o: $(top_srcdir)/shape.h +tcpsocket.o: $(top_srcdir)/thread_pthread.h +tcpsocket.o: $(top_srcdir)/vm_core.h +tcpsocket.o: $(top_srcdir)/vm_opts.h tcpsocket.o: constdefs.h tcpsocket.o: rubysocket.h tcpsocket.o: sockport.h tcpsocket.o: tcpsocket.c +tcpsocket.o: {$(VPATH)}id.h udpsocket.o: $(RUBY_EXTCONF_H) udpsocket.o: $(arch_hdrdir)/ruby/config.h -udpsocket.o: $(hdrdir)/ruby.h udpsocket.o: $(hdrdir)/ruby/assert.h +udpsocket.o: $(hdrdir)/ruby/atomic.h udpsocket.o: $(hdrdir)/ruby/backward.h +udpsocket.o: $(hdrdir)/ruby/backward/2/assume.h +udpsocket.o: $(hdrdir)/ruby/backward/2/attributes.h +udpsocket.o: $(hdrdir)/ruby/backward/2/bool.h +udpsocket.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h +udpsocket.o: $(hdrdir)/ruby/backward/2/inttypes.h +udpsocket.o: $(hdrdir)/ruby/backward/2/limits.h +udpsocket.o: $(hdrdir)/ruby/backward/2/long_long.h +udpsocket.o: $(hdrdir)/ruby/backward/2/stdalign.h +udpsocket.o: $(hdrdir)/ruby/backward/2/stdarg.h udpsocket.o: $(hdrdir)/ruby/defines.h udpsocket.o: $(hdrdir)/ruby/encoding.h +udpsocket.o: $(hdrdir)/ruby/fiber/scheduler.h udpsocket.o: $(hdrdir)/ruby/intern.h +udpsocket.o: $(hdrdir)/ruby/internal/abi.h +udpsocket.o: $(hdrdir)/ruby/internal/anyargs.h +udpsocket.o: $(hdrdir)/ruby/internal/arithmetic.h +udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/char.h +udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/double.h +udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/int.h +udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/long.h +udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/short.h +udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +udpsocket.o: $(hdrdir)/ruby/internal/assume.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/artificial.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/cold.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/const.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/constexpr.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/deprecated.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/error.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/forceinline.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/format.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/noalias.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/noexcept.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/noinline.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/nonnull.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/noreturn.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/pure.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/restrict.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/warning.h +udpsocket.o: $(hdrdir)/ruby/internal/attr/weakref.h +udpsocket.o: $(hdrdir)/ruby/internal/cast.h +udpsocket.o: $(hdrdir)/ruby/internal/compiler_is.h +udpsocket.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +udpsocket.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +udpsocket.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +udpsocket.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +udpsocket.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +udpsocket.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +udpsocket.o: $(hdrdir)/ruby/internal/compiler_since.h +udpsocket.o: $(hdrdir)/ruby/internal/config.h +udpsocket.o: $(hdrdir)/ruby/internal/constant_p.h +udpsocket.o: $(hdrdir)/ruby/internal/core.h +udpsocket.o: $(hdrdir)/ruby/internal/core/rarray.h +udpsocket.o: $(hdrdir)/ruby/internal/core/rbasic.h +udpsocket.o: $(hdrdir)/ruby/internal/core/rbignum.h +udpsocket.o: $(hdrdir)/ruby/internal/core/rclass.h +udpsocket.o: $(hdrdir)/ruby/internal/core/rdata.h +udpsocket.o: $(hdrdir)/ruby/internal/core/rfile.h +udpsocket.o: $(hdrdir)/ruby/internal/core/rhash.h +udpsocket.o: $(hdrdir)/ruby/internal/core/robject.h +udpsocket.o: $(hdrdir)/ruby/internal/core/rregexp.h +udpsocket.o: $(hdrdir)/ruby/internal/core/rstring.h +udpsocket.o: $(hdrdir)/ruby/internal/core/rstruct.h +udpsocket.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +udpsocket.o: $(hdrdir)/ruby/internal/ctype.h +udpsocket.o: $(hdrdir)/ruby/internal/dllexport.h +udpsocket.o: $(hdrdir)/ruby/internal/dosish.h +udpsocket.o: $(hdrdir)/ruby/internal/encoding/coderange.h +udpsocket.o: $(hdrdir)/ruby/internal/encoding/ctype.h +udpsocket.o: $(hdrdir)/ruby/internal/encoding/encoding.h +udpsocket.o: $(hdrdir)/ruby/internal/encoding/pathname.h +udpsocket.o: $(hdrdir)/ruby/internal/encoding/re.h +udpsocket.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +udpsocket.o: $(hdrdir)/ruby/internal/encoding/string.h +udpsocket.o: $(hdrdir)/ruby/internal/encoding/symbol.h +udpsocket.o: $(hdrdir)/ruby/internal/encoding/transcode.h +udpsocket.o: $(hdrdir)/ruby/internal/error.h +udpsocket.o: $(hdrdir)/ruby/internal/eval.h +udpsocket.o: $(hdrdir)/ruby/internal/event.h +udpsocket.o: $(hdrdir)/ruby/internal/fl_type.h +udpsocket.o: $(hdrdir)/ruby/internal/gc.h +udpsocket.o: $(hdrdir)/ruby/internal/glob.h +udpsocket.o: $(hdrdir)/ruby/internal/globals.h +udpsocket.o: $(hdrdir)/ruby/internal/has/attribute.h +udpsocket.o: $(hdrdir)/ruby/internal/has/builtin.h +udpsocket.o: $(hdrdir)/ruby/internal/has/c_attribute.h +udpsocket.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +udpsocket.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +udpsocket.o: $(hdrdir)/ruby/internal/has/extension.h +udpsocket.o: $(hdrdir)/ruby/internal/has/feature.h +udpsocket.o: $(hdrdir)/ruby/internal/has/warning.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/array.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/bignum.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/class.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/compar.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/complex.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/cont.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/dir.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/enum.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/enumerator.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/error.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/eval.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/file.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/hash.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/io.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/load.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/marshal.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/numeric.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/object.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/parse.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/proc.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/process.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/random.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/range.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/rational.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/re.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/ruby.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/select.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/set.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/signal.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/sprintf.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/string.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/struct.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/thread.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/time.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/variable.h +udpsocket.o: $(hdrdir)/ruby/internal/intern/vm.h +udpsocket.o: $(hdrdir)/ruby/internal/interpreter.h +udpsocket.o: $(hdrdir)/ruby/internal/iterator.h +udpsocket.o: $(hdrdir)/ruby/internal/memory.h +udpsocket.o: $(hdrdir)/ruby/internal/method.h +udpsocket.o: $(hdrdir)/ruby/internal/module.h +udpsocket.o: $(hdrdir)/ruby/internal/newobj.h +udpsocket.o: $(hdrdir)/ruby/internal/scan_args.h +udpsocket.o: $(hdrdir)/ruby/internal/special_consts.h +udpsocket.o: $(hdrdir)/ruby/internal/static_assert.h +udpsocket.o: $(hdrdir)/ruby/internal/stdalign.h +udpsocket.o: $(hdrdir)/ruby/internal/stdbool.h +udpsocket.o: $(hdrdir)/ruby/internal/stdckdint.h +udpsocket.o: $(hdrdir)/ruby/internal/symbol.h +udpsocket.o: $(hdrdir)/ruby/internal/value.h +udpsocket.o: $(hdrdir)/ruby/internal/value_type.h +udpsocket.o: $(hdrdir)/ruby/internal/variable.h +udpsocket.o: $(hdrdir)/ruby/internal/warning_push.h +udpsocket.o: $(hdrdir)/ruby/internal/xmalloc.h udpsocket.o: $(hdrdir)/ruby/io.h udpsocket.o: $(hdrdir)/ruby/missing.h udpsocket.o: $(hdrdir)/ruby/onigmo.h @@ -291,20 +2779,214 @@ udpsocket.o: $(hdrdir)/ruby/ruby.h udpsocket.o: $(hdrdir)/ruby/st.h udpsocket.o: $(hdrdir)/ruby/subst.h udpsocket.o: $(hdrdir)/ruby/thread.h +udpsocket.o: $(hdrdir)/ruby/thread_native.h udpsocket.o: $(hdrdir)/ruby/util.h +udpsocket.o: $(hdrdir)/ruby/version.h +udpsocket.o: $(top_srcdir)/ccan/check_type/check_type.h +udpsocket.o: $(top_srcdir)/ccan/container_of/container_of.h +udpsocket.o: $(top_srcdir)/ccan/list/list.h +udpsocket.o: $(top_srcdir)/ccan/str/str.h +udpsocket.o: $(top_srcdir)/encindex.h +udpsocket.o: $(top_srcdir)/id_table.h udpsocket.o: $(top_srcdir)/internal.h +udpsocket.o: $(top_srcdir)/internal/array.h +udpsocket.o: $(top_srcdir)/internal/basic_operators.h +udpsocket.o: $(top_srcdir)/internal/box.h +udpsocket.o: $(top_srcdir)/internal/compilers.h +udpsocket.o: $(top_srcdir)/internal/error.h +udpsocket.o: $(top_srcdir)/internal/gc.h +udpsocket.o: $(top_srcdir)/internal/imemo.h +udpsocket.o: $(top_srcdir)/internal/io.h +udpsocket.o: $(top_srcdir)/internal/sanitizers.h +udpsocket.o: $(top_srcdir)/internal/serial.h +udpsocket.o: $(top_srcdir)/internal/set_table.h +udpsocket.o: $(top_srcdir)/internal/static_assert.h +udpsocket.o: $(top_srcdir)/internal/string.h +udpsocket.o: $(top_srcdir)/internal/thread.h +udpsocket.o: $(top_srcdir)/internal/vm.h +udpsocket.o: $(top_srcdir)/internal/warnings.h +udpsocket.o: $(top_srcdir)/method.h +udpsocket.o: $(top_srcdir)/node.h +udpsocket.o: $(top_srcdir)/ruby_assert.h +udpsocket.o: $(top_srcdir)/ruby_atomic.h +udpsocket.o: $(top_srcdir)/rubyparser.h +udpsocket.o: $(top_srcdir)/shape.h +udpsocket.o: $(top_srcdir)/thread_pthread.h +udpsocket.o: $(top_srcdir)/vm_core.h +udpsocket.o: $(top_srcdir)/vm_opts.h udpsocket.o: constdefs.h udpsocket.o: rubysocket.h udpsocket.o: sockport.h udpsocket.o: udpsocket.c +udpsocket.o: {$(VPATH)}id.h unixserver.o: $(RUBY_EXTCONF_H) unixserver.o: $(arch_hdrdir)/ruby/config.h -unixserver.o: $(hdrdir)/ruby.h unixserver.o: $(hdrdir)/ruby/assert.h +unixserver.o: $(hdrdir)/ruby/atomic.h unixserver.o: $(hdrdir)/ruby/backward.h +unixserver.o: $(hdrdir)/ruby/backward/2/assume.h +unixserver.o: $(hdrdir)/ruby/backward/2/attributes.h +unixserver.o: $(hdrdir)/ruby/backward/2/bool.h +unixserver.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h +unixserver.o: $(hdrdir)/ruby/backward/2/inttypes.h +unixserver.o: $(hdrdir)/ruby/backward/2/limits.h +unixserver.o: $(hdrdir)/ruby/backward/2/long_long.h +unixserver.o: $(hdrdir)/ruby/backward/2/stdalign.h +unixserver.o: $(hdrdir)/ruby/backward/2/stdarg.h unixserver.o: $(hdrdir)/ruby/defines.h unixserver.o: $(hdrdir)/ruby/encoding.h +unixserver.o: $(hdrdir)/ruby/fiber/scheduler.h unixserver.o: $(hdrdir)/ruby/intern.h +unixserver.o: $(hdrdir)/ruby/internal/abi.h +unixserver.o: $(hdrdir)/ruby/internal/anyargs.h +unixserver.o: $(hdrdir)/ruby/internal/arithmetic.h +unixserver.o: $(hdrdir)/ruby/internal/arithmetic/char.h +unixserver.o: $(hdrdir)/ruby/internal/arithmetic/double.h +unixserver.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +unixserver.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +unixserver.o: $(hdrdir)/ruby/internal/arithmetic/int.h +unixserver.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +unixserver.o: $(hdrdir)/ruby/internal/arithmetic/long.h +unixserver.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +unixserver.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +unixserver.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +unixserver.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +unixserver.o: $(hdrdir)/ruby/internal/arithmetic/short.h +unixserver.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +unixserver.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +unixserver.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +unixserver.o: $(hdrdir)/ruby/internal/assume.h +unixserver.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +unixserver.o: $(hdrdir)/ruby/internal/attr/artificial.h +unixserver.o: $(hdrdir)/ruby/internal/attr/cold.h +unixserver.o: $(hdrdir)/ruby/internal/attr/const.h +unixserver.o: $(hdrdir)/ruby/internal/attr/constexpr.h +unixserver.o: $(hdrdir)/ruby/internal/attr/deprecated.h +unixserver.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +unixserver.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +unixserver.o: $(hdrdir)/ruby/internal/attr/error.h +unixserver.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +unixserver.o: $(hdrdir)/ruby/internal/attr/forceinline.h +unixserver.o: $(hdrdir)/ruby/internal/attr/format.h +unixserver.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +unixserver.o: $(hdrdir)/ruby/internal/attr/noalias.h +unixserver.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +unixserver.o: $(hdrdir)/ruby/internal/attr/noexcept.h +unixserver.o: $(hdrdir)/ruby/internal/attr/noinline.h +unixserver.o: $(hdrdir)/ruby/internal/attr/nonnull.h +unixserver.o: $(hdrdir)/ruby/internal/attr/noreturn.h +unixserver.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +unixserver.o: $(hdrdir)/ruby/internal/attr/pure.h +unixserver.o: $(hdrdir)/ruby/internal/attr/restrict.h +unixserver.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +unixserver.o: $(hdrdir)/ruby/internal/attr/warning.h +unixserver.o: $(hdrdir)/ruby/internal/attr/weakref.h +unixserver.o: $(hdrdir)/ruby/internal/cast.h +unixserver.o: $(hdrdir)/ruby/internal/compiler_is.h +unixserver.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +unixserver.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +unixserver.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +unixserver.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +unixserver.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +unixserver.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +unixserver.o: $(hdrdir)/ruby/internal/compiler_since.h +unixserver.o: $(hdrdir)/ruby/internal/config.h +unixserver.o: $(hdrdir)/ruby/internal/constant_p.h +unixserver.o: $(hdrdir)/ruby/internal/core.h +unixserver.o: $(hdrdir)/ruby/internal/core/rarray.h +unixserver.o: $(hdrdir)/ruby/internal/core/rbasic.h +unixserver.o: $(hdrdir)/ruby/internal/core/rbignum.h +unixserver.o: $(hdrdir)/ruby/internal/core/rclass.h +unixserver.o: $(hdrdir)/ruby/internal/core/rdata.h +unixserver.o: $(hdrdir)/ruby/internal/core/rfile.h +unixserver.o: $(hdrdir)/ruby/internal/core/rhash.h +unixserver.o: $(hdrdir)/ruby/internal/core/robject.h +unixserver.o: $(hdrdir)/ruby/internal/core/rregexp.h +unixserver.o: $(hdrdir)/ruby/internal/core/rstring.h +unixserver.o: $(hdrdir)/ruby/internal/core/rstruct.h +unixserver.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +unixserver.o: $(hdrdir)/ruby/internal/ctype.h +unixserver.o: $(hdrdir)/ruby/internal/dllexport.h +unixserver.o: $(hdrdir)/ruby/internal/dosish.h +unixserver.o: $(hdrdir)/ruby/internal/encoding/coderange.h +unixserver.o: $(hdrdir)/ruby/internal/encoding/ctype.h +unixserver.o: $(hdrdir)/ruby/internal/encoding/encoding.h +unixserver.o: $(hdrdir)/ruby/internal/encoding/pathname.h +unixserver.o: $(hdrdir)/ruby/internal/encoding/re.h +unixserver.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +unixserver.o: $(hdrdir)/ruby/internal/encoding/string.h +unixserver.o: $(hdrdir)/ruby/internal/encoding/symbol.h +unixserver.o: $(hdrdir)/ruby/internal/encoding/transcode.h +unixserver.o: $(hdrdir)/ruby/internal/error.h +unixserver.o: $(hdrdir)/ruby/internal/eval.h +unixserver.o: $(hdrdir)/ruby/internal/event.h +unixserver.o: $(hdrdir)/ruby/internal/fl_type.h +unixserver.o: $(hdrdir)/ruby/internal/gc.h +unixserver.o: $(hdrdir)/ruby/internal/glob.h +unixserver.o: $(hdrdir)/ruby/internal/globals.h +unixserver.o: $(hdrdir)/ruby/internal/has/attribute.h +unixserver.o: $(hdrdir)/ruby/internal/has/builtin.h +unixserver.o: $(hdrdir)/ruby/internal/has/c_attribute.h +unixserver.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +unixserver.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +unixserver.o: $(hdrdir)/ruby/internal/has/extension.h +unixserver.o: $(hdrdir)/ruby/internal/has/feature.h +unixserver.o: $(hdrdir)/ruby/internal/has/warning.h +unixserver.o: $(hdrdir)/ruby/internal/intern/array.h +unixserver.o: $(hdrdir)/ruby/internal/intern/bignum.h +unixserver.o: $(hdrdir)/ruby/internal/intern/class.h +unixserver.o: $(hdrdir)/ruby/internal/intern/compar.h +unixserver.o: $(hdrdir)/ruby/internal/intern/complex.h +unixserver.o: $(hdrdir)/ruby/internal/intern/cont.h +unixserver.o: $(hdrdir)/ruby/internal/intern/dir.h +unixserver.o: $(hdrdir)/ruby/internal/intern/enum.h +unixserver.o: $(hdrdir)/ruby/internal/intern/enumerator.h +unixserver.o: $(hdrdir)/ruby/internal/intern/error.h +unixserver.o: $(hdrdir)/ruby/internal/intern/eval.h +unixserver.o: $(hdrdir)/ruby/internal/intern/file.h +unixserver.o: $(hdrdir)/ruby/internal/intern/hash.h +unixserver.o: $(hdrdir)/ruby/internal/intern/io.h +unixserver.o: $(hdrdir)/ruby/internal/intern/load.h +unixserver.o: $(hdrdir)/ruby/internal/intern/marshal.h +unixserver.o: $(hdrdir)/ruby/internal/intern/numeric.h +unixserver.o: $(hdrdir)/ruby/internal/intern/object.h +unixserver.o: $(hdrdir)/ruby/internal/intern/parse.h +unixserver.o: $(hdrdir)/ruby/internal/intern/proc.h +unixserver.o: $(hdrdir)/ruby/internal/intern/process.h +unixserver.o: $(hdrdir)/ruby/internal/intern/random.h +unixserver.o: $(hdrdir)/ruby/internal/intern/range.h +unixserver.o: $(hdrdir)/ruby/internal/intern/rational.h +unixserver.o: $(hdrdir)/ruby/internal/intern/re.h +unixserver.o: $(hdrdir)/ruby/internal/intern/ruby.h +unixserver.o: $(hdrdir)/ruby/internal/intern/select.h +unixserver.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +unixserver.o: $(hdrdir)/ruby/internal/intern/set.h +unixserver.o: $(hdrdir)/ruby/internal/intern/signal.h +unixserver.o: $(hdrdir)/ruby/internal/intern/sprintf.h +unixserver.o: $(hdrdir)/ruby/internal/intern/string.h +unixserver.o: $(hdrdir)/ruby/internal/intern/struct.h +unixserver.o: $(hdrdir)/ruby/internal/intern/thread.h +unixserver.o: $(hdrdir)/ruby/internal/intern/time.h +unixserver.o: $(hdrdir)/ruby/internal/intern/variable.h +unixserver.o: $(hdrdir)/ruby/internal/intern/vm.h +unixserver.o: $(hdrdir)/ruby/internal/interpreter.h +unixserver.o: $(hdrdir)/ruby/internal/iterator.h +unixserver.o: $(hdrdir)/ruby/internal/memory.h +unixserver.o: $(hdrdir)/ruby/internal/method.h +unixserver.o: $(hdrdir)/ruby/internal/module.h +unixserver.o: $(hdrdir)/ruby/internal/newobj.h +unixserver.o: $(hdrdir)/ruby/internal/scan_args.h +unixserver.o: $(hdrdir)/ruby/internal/special_consts.h +unixserver.o: $(hdrdir)/ruby/internal/static_assert.h +unixserver.o: $(hdrdir)/ruby/internal/stdalign.h +unixserver.o: $(hdrdir)/ruby/internal/stdbool.h +unixserver.o: $(hdrdir)/ruby/internal/stdckdint.h +unixserver.o: $(hdrdir)/ruby/internal/symbol.h +unixserver.o: $(hdrdir)/ruby/internal/value.h +unixserver.o: $(hdrdir)/ruby/internal/value_type.h +unixserver.o: $(hdrdir)/ruby/internal/variable.h +unixserver.o: $(hdrdir)/ruby/internal/warning_push.h +unixserver.o: $(hdrdir)/ruby/internal/xmalloc.h unixserver.o: $(hdrdir)/ruby/io.h unixserver.o: $(hdrdir)/ruby/missing.h unixserver.o: $(hdrdir)/ruby/onigmo.h @@ -313,20 +2995,214 @@ unixserver.o: $(hdrdir)/ruby/ruby.h unixserver.o: $(hdrdir)/ruby/st.h unixserver.o: $(hdrdir)/ruby/subst.h unixserver.o: $(hdrdir)/ruby/thread.h +unixserver.o: $(hdrdir)/ruby/thread_native.h unixserver.o: $(hdrdir)/ruby/util.h +unixserver.o: $(hdrdir)/ruby/version.h +unixserver.o: $(top_srcdir)/ccan/check_type/check_type.h +unixserver.o: $(top_srcdir)/ccan/container_of/container_of.h +unixserver.o: $(top_srcdir)/ccan/list/list.h +unixserver.o: $(top_srcdir)/ccan/str/str.h +unixserver.o: $(top_srcdir)/encindex.h +unixserver.o: $(top_srcdir)/id_table.h unixserver.o: $(top_srcdir)/internal.h +unixserver.o: $(top_srcdir)/internal/array.h +unixserver.o: $(top_srcdir)/internal/basic_operators.h +unixserver.o: $(top_srcdir)/internal/box.h +unixserver.o: $(top_srcdir)/internal/compilers.h +unixserver.o: $(top_srcdir)/internal/error.h +unixserver.o: $(top_srcdir)/internal/gc.h +unixserver.o: $(top_srcdir)/internal/imemo.h +unixserver.o: $(top_srcdir)/internal/io.h +unixserver.o: $(top_srcdir)/internal/sanitizers.h +unixserver.o: $(top_srcdir)/internal/serial.h +unixserver.o: $(top_srcdir)/internal/set_table.h +unixserver.o: $(top_srcdir)/internal/static_assert.h +unixserver.o: $(top_srcdir)/internal/string.h +unixserver.o: $(top_srcdir)/internal/thread.h +unixserver.o: $(top_srcdir)/internal/vm.h +unixserver.o: $(top_srcdir)/internal/warnings.h +unixserver.o: $(top_srcdir)/method.h +unixserver.o: $(top_srcdir)/node.h +unixserver.o: $(top_srcdir)/ruby_assert.h +unixserver.o: $(top_srcdir)/ruby_atomic.h +unixserver.o: $(top_srcdir)/rubyparser.h +unixserver.o: $(top_srcdir)/shape.h +unixserver.o: $(top_srcdir)/thread_pthread.h +unixserver.o: $(top_srcdir)/vm_core.h +unixserver.o: $(top_srcdir)/vm_opts.h unixserver.o: constdefs.h unixserver.o: rubysocket.h unixserver.o: sockport.h unixserver.o: unixserver.c +unixserver.o: {$(VPATH)}id.h unixsocket.o: $(RUBY_EXTCONF_H) unixsocket.o: $(arch_hdrdir)/ruby/config.h -unixsocket.o: $(hdrdir)/ruby.h unixsocket.o: $(hdrdir)/ruby/assert.h +unixsocket.o: $(hdrdir)/ruby/atomic.h unixsocket.o: $(hdrdir)/ruby/backward.h +unixsocket.o: $(hdrdir)/ruby/backward/2/assume.h +unixsocket.o: $(hdrdir)/ruby/backward/2/attributes.h +unixsocket.o: $(hdrdir)/ruby/backward/2/bool.h +unixsocket.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h +unixsocket.o: $(hdrdir)/ruby/backward/2/inttypes.h +unixsocket.o: $(hdrdir)/ruby/backward/2/limits.h +unixsocket.o: $(hdrdir)/ruby/backward/2/long_long.h +unixsocket.o: $(hdrdir)/ruby/backward/2/stdalign.h +unixsocket.o: $(hdrdir)/ruby/backward/2/stdarg.h unixsocket.o: $(hdrdir)/ruby/defines.h unixsocket.o: $(hdrdir)/ruby/encoding.h +unixsocket.o: $(hdrdir)/ruby/fiber/scheduler.h unixsocket.o: $(hdrdir)/ruby/intern.h +unixsocket.o: $(hdrdir)/ruby/internal/abi.h +unixsocket.o: $(hdrdir)/ruby/internal/anyargs.h +unixsocket.o: $(hdrdir)/ruby/internal/arithmetic.h +unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/char.h +unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/double.h +unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/int.h +unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/long.h +unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/short.h +unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +unixsocket.o: $(hdrdir)/ruby/internal/assume.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/artificial.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/cold.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/const.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/constexpr.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/deprecated.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/error.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/forceinline.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/format.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/noalias.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/noexcept.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/noinline.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/nonnull.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/noreturn.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/pure.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/restrict.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/warning.h +unixsocket.o: $(hdrdir)/ruby/internal/attr/weakref.h +unixsocket.o: $(hdrdir)/ruby/internal/cast.h +unixsocket.o: $(hdrdir)/ruby/internal/compiler_is.h +unixsocket.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +unixsocket.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +unixsocket.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +unixsocket.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +unixsocket.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +unixsocket.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +unixsocket.o: $(hdrdir)/ruby/internal/compiler_since.h +unixsocket.o: $(hdrdir)/ruby/internal/config.h +unixsocket.o: $(hdrdir)/ruby/internal/constant_p.h +unixsocket.o: $(hdrdir)/ruby/internal/core.h +unixsocket.o: $(hdrdir)/ruby/internal/core/rarray.h +unixsocket.o: $(hdrdir)/ruby/internal/core/rbasic.h +unixsocket.o: $(hdrdir)/ruby/internal/core/rbignum.h +unixsocket.o: $(hdrdir)/ruby/internal/core/rclass.h +unixsocket.o: $(hdrdir)/ruby/internal/core/rdata.h +unixsocket.o: $(hdrdir)/ruby/internal/core/rfile.h +unixsocket.o: $(hdrdir)/ruby/internal/core/rhash.h +unixsocket.o: $(hdrdir)/ruby/internal/core/robject.h +unixsocket.o: $(hdrdir)/ruby/internal/core/rregexp.h +unixsocket.o: $(hdrdir)/ruby/internal/core/rstring.h +unixsocket.o: $(hdrdir)/ruby/internal/core/rstruct.h +unixsocket.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +unixsocket.o: $(hdrdir)/ruby/internal/ctype.h +unixsocket.o: $(hdrdir)/ruby/internal/dllexport.h +unixsocket.o: $(hdrdir)/ruby/internal/dosish.h +unixsocket.o: $(hdrdir)/ruby/internal/encoding/coderange.h +unixsocket.o: $(hdrdir)/ruby/internal/encoding/ctype.h +unixsocket.o: $(hdrdir)/ruby/internal/encoding/encoding.h +unixsocket.o: $(hdrdir)/ruby/internal/encoding/pathname.h +unixsocket.o: $(hdrdir)/ruby/internal/encoding/re.h +unixsocket.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +unixsocket.o: $(hdrdir)/ruby/internal/encoding/string.h +unixsocket.o: $(hdrdir)/ruby/internal/encoding/symbol.h +unixsocket.o: $(hdrdir)/ruby/internal/encoding/transcode.h +unixsocket.o: $(hdrdir)/ruby/internal/error.h +unixsocket.o: $(hdrdir)/ruby/internal/eval.h +unixsocket.o: $(hdrdir)/ruby/internal/event.h +unixsocket.o: $(hdrdir)/ruby/internal/fl_type.h +unixsocket.o: $(hdrdir)/ruby/internal/gc.h +unixsocket.o: $(hdrdir)/ruby/internal/glob.h +unixsocket.o: $(hdrdir)/ruby/internal/globals.h +unixsocket.o: $(hdrdir)/ruby/internal/has/attribute.h +unixsocket.o: $(hdrdir)/ruby/internal/has/builtin.h +unixsocket.o: $(hdrdir)/ruby/internal/has/c_attribute.h +unixsocket.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +unixsocket.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +unixsocket.o: $(hdrdir)/ruby/internal/has/extension.h +unixsocket.o: $(hdrdir)/ruby/internal/has/feature.h +unixsocket.o: $(hdrdir)/ruby/internal/has/warning.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/array.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/bignum.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/class.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/compar.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/complex.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/cont.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/dir.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/enum.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/enumerator.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/error.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/eval.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/file.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/hash.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/io.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/load.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/marshal.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/numeric.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/object.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/parse.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/proc.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/process.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/random.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/range.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/rational.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/re.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/ruby.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/select.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/set.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/signal.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/sprintf.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/string.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/struct.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/thread.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/time.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/variable.h +unixsocket.o: $(hdrdir)/ruby/internal/intern/vm.h +unixsocket.o: $(hdrdir)/ruby/internal/interpreter.h +unixsocket.o: $(hdrdir)/ruby/internal/iterator.h +unixsocket.o: $(hdrdir)/ruby/internal/memory.h +unixsocket.o: $(hdrdir)/ruby/internal/method.h +unixsocket.o: $(hdrdir)/ruby/internal/module.h +unixsocket.o: $(hdrdir)/ruby/internal/newobj.h +unixsocket.o: $(hdrdir)/ruby/internal/scan_args.h +unixsocket.o: $(hdrdir)/ruby/internal/special_consts.h +unixsocket.o: $(hdrdir)/ruby/internal/static_assert.h +unixsocket.o: $(hdrdir)/ruby/internal/stdalign.h +unixsocket.o: $(hdrdir)/ruby/internal/stdbool.h +unixsocket.o: $(hdrdir)/ruby/internal/stdckdint.h +unixsocket.o: $(hdrdir)/ruby/internal/symbol.h +unixsocket.o: $(hdrdir)/ruby/internal/value.h +unixsocket.o: $(hdrdir)/ruby/internal/value_type.h +unixsocket.o: $(hdrdir)/ruby/internal/variable.h +unixsocket.o: $(hdrdir)/ruby/internal/warning_push.h +unixsocket.o: $(hdrdir)/ruby/internal/xmalloc.h unixsocket.o: $(hdrdir)/ruby/io.h unixsocket.o: $(hdrdir)/ruby/missing.h unixsocket.o: $(hdrdir)/ruby/onigmo.h @@ -335,10 +3211,44 @@ unixsocket.o: $(hdrdir)/ruby/ruby.h unixsocket.o: $(hdrdir)/ruby/st.h unixsocket.o: $(hdrdir)/ruby/subst.h unixsocket.o: $(hdrdir)/ruby/thread.h +unixsocket.o: $(hdrdir)/ruby/thread_native.h unixsocket.o: $(hdrdir)/ruby/util.h +unixsocket.o: $(hdrdir)/ruby/version.h +unixsocket.o: $(top_srcdir)/ccan/check_type/check_type.h +unixsocket.o: $(top_srcdir)/ccan/container_of/container_of.h +unixsocket.o: $(top_srcdir)/ccan/list/list.h +unixsocket.o: $(top_srcdir)/ccan/str/str.h +unixsocket.o: $(top_srcdir)/encindex.h +unixsocket.o: $(top_srcdir)/id_table.h unixsocket.o: $(top_srcdir)/internal.h +unixsocket.o: $(top_srcdir)/internal/array.h +unixsocket.o: $(top_srcdir)/internal/basic_operators.h +unixsocket.o: $(top_srcdir)/internal/box.h +unixsocket.o: $(top_srcdir)/internal/compilers.h +unixsocket.o: $(top_srcdir)/internal/error.h +unixsocket.o: $(top_srcdir)/internal/gc.h +unixsocket.o: $(top_srcdir)/internal/imemo.h +unixsocket.o: $(top_srcdir)/internal/io.h +unixsocket.o: $(top_srcdir)/internal/sanitizers.h +unixsocket.o: $(top_srcdir)/internal/serial.h +unixsocket.o: $(top_srcdir)/internal/set_table.h +unixsocket.o: $(top_srcdir)/internal/static_assert.h +unixsocket.o: $(top_srcdir)/internal/string.h +unixsocket.o: $(top_srcdir)/internal/thread.h +unixsocket.o: $(top_srcdir)/internal/vm.h +unixsocket.o: $(top_srcdir)/internal/warnings.h +unixsocket.o: $(top_srcdir)/method.h +unixsocket.o: $(top_srcdir)/node.h +unixsocket.o: $(top_srcdir)/ruby_assert.h +unixsocket.o: $(top_srcdir)/ruby_atomic.h +unixsocket.o: $(top_srcdir)/rubyparser.h +unixsocket.o: $(top_srcdir)/shape.h +unixsocket.o: $(top_srcdir)/thread_pthread.h +unixsocket.o: $(top_srcdir)/vm_core.h +unixsocket.o: $(top_srcdir)/vm_opts.h unixsocket.o: constdefs.h unixsocket.o: rubysocket.h unixsocket.o: sockport.h unixsocket.o: unixsocket.c +unixsocket.o: {$(VPATH)}id.h # AUTOGENERATED DEPENDENCIES END diff --git a/ext/socket/extconf.rb b/ext/socket/extconf.rb index 0cc8a88d5c..a814e21c3a 100644 --- a/ext/socket/extconf.rb +++ b/ext/socket/extconf.rb @@ -316,6 +316,7 @@ end netpacket/packet.h net/ethernet.h sys/un.h + afunix.h ifaddrs.h sys/ioctl.h sys/sockio.h @@ -326,6 +327,8 @@ end net/if_dl.h arpa/nameser.h resolv.h + pthread.h + sched.h ].each {|h| if have_header(h, headers) headers << h @@ -346,10 +349,22 @@ have_type("struct sockaddr_storage", headers) have_type("struct addrinfo", headers) -if have_type("socklen_t", headers) - if try_static_assert("sizeof(socklen_t) >= sizeof(long)", headers) - $defs << "-DRSTRING_SOCKLEN=(socklen_t)RSTRING_LEN" +def check_socklen(headers) + def (fmt = "none").%(x) + x || self + end + s = checking_for("RSTRING_SOCKLEN", fmt) do + if try_static_assert("sizeof(socklen_t) >= sizeof(long)", headers) + "RSTRING_LEN" + else + "RSTRING_LENINT" + end end + $defs << "-DRSTRING_SOCKLEN=(socklen_t)"+s +end + +if have_type("socklen_t", headers) + check_socklen(headers) end have_type("struct in_pktinfo", headers) {|src| @@ -484,6 +499,9 @@ EOF have_func("getpeerucred(0, (ucred_t **)NULL)", headers) # SunOS have_func_decl = proc do |name, headers| + # check if there is a declaration of <name> by trying to declare + # both "int <name>(void)" and "void <name>(void)" + # (at least one attempt should fail if there is a declaration) if !checking_for("declaration of #{name}()") {!%w[int void].all? {|ret| try_compile(<<EOF)}} #{cpp_include(headers)} #{ret} #{name}(void); @@ -492,10 +510,10 @@ EOF end end if have_func('if_indextoname(0, "")', headers) - have_func_decl["if_indextoname"] + have_func_decl["if_indextoname", headers] end if have_func('if_nametoindex("")', headers) - have_func_decl["if_nametoindex"] + have_func_decl["if_nametoindex", headers] end have_func("hsterror", headers) @@ -548,7 +566,7 @@ EOS end if !have_macro("IPPROTO_IPV6", headers) && have_const("IPPROTO_IPV6", headers) - IO.read(File.join(File.dirname(__FILE__), "mkconstants.rb")).sub(/\A.*^__END__$/m, '').split(/\r?\n/).grep(/\AIPPROTO_\w*/){$&}.each {|name| + File.read(File.join(File.dirname(__FILE__), "mkconstants.rb")).sub(/\A.*^__END__$/m, '').split(/\r?\n/).grep(/\AIPPROTO_\w*/){$&}.each {|name| have_const(name, headers) unless $defs.include?("-DHAVE_CONST_#{name.upcase}") } end @@ -646,18 +664,26 @@ EOS if enable_config("socks", ENV["SOCKS_SERVER"]) if have_library("socks5", "SOCKSinit") $defs << "-DSOCKS5" << "-DSOCKS" - elsif have_library("socks", "Rconnect") + elsif have_library("socksd", "Rconnect") || have_library("socks", "Rconnect") $defs << "-DSOCKS" end end hdr = "netinet6/in6.h" - if /darwin/ =~ RUBY_PLATFORM and !try_compile(<<"SRC", nil, :werror=>true) + /darwin/ =~ RUBY_PLATFORM and + checking_for("if apple's #{hdr} needs s6_addr patch") {!try_compile(<<"SRC", nil, :werror=>true)} and #include <netinet/in.h> int t(struct in6_addr *addr) {return IN6_IS_ADDR_UNSPECIFIED(addr);} SRC - print "fixing apple's netinet6/in6.h ..."; $stdout.flush - in6 = File.read("/usr/include/#{hdr}") + checking_for("fixing apple's #{hdr}", "%s") do + file = xpopen(%w"clang -include netinet/in.h -E -xc -", in: IO::NULL) do |f| + re = %r[^# *\d+ *"(.*/netinet/in\.h)"] + Logging.message " grep(#{re})\n" + f.read[re, 1] + end + Logging.message "Substitute from #{file}\n" + + in6 = File.read(file) if in6.gsub!(/\*\(const\s+__uint32_t\s+\*\)\(const\s+void\s+\*\)\(&(\(\w+\))->s6_addr\[(\d+)\]\)/) do i, r = $2.to_i.divmod(4) if r.zero? @@ -667,13 +693,19 @@ SRC end end FileUtils.mkdir_p(File.dirname(hdr)) - open(hdr, "w") {|f| f.write(in6)} + File.write(hdr, in6) $distcleanfiles << hdr $distcleandirs << File.dirname(hdr) - puts "done" + "done" else - puts "not needed" + "not needed" end end + + have_func("pthread_create") + have_func("pthread_detach") + have_func("pthread_attr_setdetachstate") + + $VPATH << '$(topdir)' << '$(top_srcdir)' create_makefile("socket") end diff --git a/ext/socket/getaddrinfo.c b/ext/socket/getaddrinfo.c index ce6dc40478..9a65490b1d 100644 --- a/ext/socket/getaddrinfo.c +++ b/ext/socket/getaddrinfo.c @@ -62,9 +62,6 @@ #endif #include <unistd.h> #else -#if defined(_MSC_VER) && _MSC_VER <= 1200 -#include <windows.h> -#endif #include <winsock2.h> #include <ws2tcpip.h> #include <io.h> @@ -98,42 +95,42 @@ static struct in6_addr faith_prefix = IN6ADDR_ANY_INIT; static const char in_addrany[] = { 0, 0, 0, 0 }; static const char in6_addrany[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static const char in_loopback[] = { 127, 0, 0, 1 }; static const char in6_loopback[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; struct sockinet { - u_char si_len; - u_char si_family; - u_short si_port; + u_char si_len; + u_char si_family; + u_short si_port; }; static const struct afd { - int a_af; - int a_addrlen; - int a_socklen; - int a_off; - const char *a_addrany; - const char *a_loopback; + int a_af; + int a_addrlen; + int a_socklen; + int a_off; + const char *a_addrany; + const char *a_loopback; } afdl [] = { #ifdef INET6 #define N_INET6 0 - {PF_INET6, sizeof(struct in6_addr), - sizeof(struct sockaddr_in6), - offsetof(struct sockaddr_in6, sin6_addr), - in6_addrany, in6_loopback}, + {PF_INET6, sizeof(struct in6_addr), + sizeof(struct sockaddr_in6), + offsetof(struct sockaddr_in6, sin6_addr), + in6_addrany, in6_loopback}, #define N_INET 1 #else #define N_INET 0 #endif - {PF_INET, sizeof(struct in_addr), - sizeof(struct sockaddr_in), - offsetof(struct sockaddr_in, sin_addr), - in_addrany, in_loopback}, - {0, 0, 0, 0, NULL, NULL}, + {PF_INET, sizeof(struct in_addr), + sizeof(struct sockaddr_in), + offsetof(struct sockaddr_in, sin_addr), + in_addrany, in_loopback}, + {0, 0, 0, 0, NULL, NULL}, }; #ifdef INET6 @@ -143,58 +140,56 @@ static const struct afd { #endif static int get_name __P((const char *, const struct afd *, - struct addrinfo **, char *, struct addrinfo *, - int)); + struct addrinfo **, char *, struct addrinfo *, + int)); static int get_addr __P((const char *, int, struct addrinfo **, - struct addrinfo *, int)); + struct addrinfo *, int)); static int str_isnumber __P((const char *)); #ifndef HAVE_GAI_STRERROR static const char *const ai_errlist[] = { - "success.", - "address family for hostname not supported.", /* EAI_ADDRFAMILY */ - "temporary failure in name resolution.", /* EAI_AGAIN */ - "invalid value for ai_flags.", /* EAI_BADFLAGS */ - "non-recoverable failure in name resolution.", /* EAI_FAIL */ - "ai_family not supported.", /* EAI_FAMILY */ - "memory allocation failure.", /* EAI_MEMORY */ - "no address associated with hostname.", /* EAI_NODATA */ - "hostname nor servname provided, or not known.",/* EAI_NONAME */ - "servname not supported for ai_socktype.", /* EAI_SERVICE */ - "ai_socktype not supported.", /* EAI_SOCKTYPE */ - "system error returned in errno.", /* EAI_SYSTEM */ - "invalid value for hints.", /* EAI_BADHINTS */ - "resolved protocol is unknown.", /* EAI_PROTOCOL */ - "unknown error.", /* EAI_MAX */ + "success.", + "address family for hostname not supported.", /* EAI_ADDRFAMILY */ + "temporary failure in name resolution.", /* EAI_AGAIN */ + "invalid value for ai_flags.", /* EAI_BADFLAGS */ + "non-recoverable failure in name resolution.", /* EAI_FAIL */ + "ai_family not supported.", /* EAI_FAMILY */ + "memory allocation failure.", /* EAI_MEMORY */ + "no address associated with hostname.", /* EAI_NODATA */ + "hostname nor servname provided, or not known.",/* EAI_NONAME */ + "servname not supported for ai_socktype.", /* EAI_SERVICE */ + "ai_socktype not supported.", /* EAI_SOCKTYPE */ + "system error returned in errno.", /* EAI_SYSTEM */ + "invalid value for hints.", /* EAI_BADHINTS */ + "resolved protocol is unknown.", /* EAI_PROTOCOL */ + "unknown error.", /* EAI_MAX */ }; #endif #define GET_CANONNAME(ai, str) \ if (pai->ai_flags & AI_CANONNAME) {\ - if (((ai)->ai_canonname = (char *)malloc(strlen(str) + 1)) != NULL) {\ - strcpy((ai)->ai_canonname, (str));\ - } else {\ - error = EAI_MEMORY;\ - goto free;\ - }\ + if (((ai)->ai_canonname = strdup(str)) == NULL) {\ + error = EAI_MEMORY;\ + goto free;\ + }\ } #define GET_AI(ai, afd, addr, port) {\ - char *p;\ - if (((ai) = (struct addrinfo *)malloc(sizeof(struct addrinfo) +\ - ((afd)->a_socklen)))\ - == NULL) {\ - error = EAI_MEMORY;\ - goto free;\ - }\ - memcpy((ai), pai, sizeof(struct addrinfo));\ - (ai)->ai_addr = (struct sockaddr *)((ai) + 1);\ - (ai)->ai_family = (afd)->a_af;\ - (ai)->ai_addrlen = (afd)->a_socklen;\ - INIT_SOCKADDR((ai)->ai_addr, (afd)->a_af, (afd)->a_socklen);\ - ((struct sockinet *)(ai)->ai_addr)->si_port = (port);\ - p = (char *)((ai)->ai_addr);\ - memcpy(p + (afd)->a_off, (addr), (afd)->a_addrlen);\ + char *p;\ + if (((ai) = (struct addrinfo *)malloc(sizeof(struct addrinfo) +\ + ((afd)->a_socklen)))\ + == NULL) {\ + error = EAI_MEMORY;\ + goto free;\ + }\ + memcpy((ai), pai, sizeof(struct addrinfo));\ + (ai)->ai_addr = (struct sockaddr *)((ai) + 1);\ + (ai)->ai_family = (afd)->a_af;\ + (ai)->ai_addrlen = (afd)->a_socklen;\ + INIT_SOCKADDR((ai)->ai_addr, (afd)->a_af, (afd)->a_socklen);\ + ((struct sockinet *)(ai)->ai_addr)->si_port = (port);\ + p = (char *)((ai)->ai_addr);\ + memcpy(p + (afd)->a_off, (addr), (afd)->a_addrlen);\ } #define ERR(err) { error = (err); goto bad; } @@ -206,36 +201,35 @@ const char * gai_strerror(int ecode) { - if (ecode < 0 || ecode > EAI_MAX) - ecode = EAI_MAX; - return (char *)ai_errlist[ecode]; + if (ecode < 0 || ecode > EAI_MAX) + ecode = EAI_MAX; + return (char *)ai_errlist[ecode]; } #endif void freeaddrinfo(struct addrinfo *ai) { - struct addrinfo *next; - - do { - next = ai->ai_next; - if (ai->ai_canonname) - free(ai->ai_canonname); - /* no need to free(ai->ai_addr) */ - free(ai); - } while ((ai = next) != NULL); + struct addrinfo *next; + + do { + next = ai->ai_next; + free(ai->ai_canonname); + /* no need to free(ai->ai_addr) */ + free(ai); + } while ((ai = next) != NULL); } static int str_isnumber(const char *p) { - char *q = (char *)p; - while (*q) { - if (! isdigit(*q)) - return NO; - q++; - } - return YES; + char *q = (char *)p; + while (*q) { + if (! isdigit(*q)) + return NO; + q++; + } + return YES; } #ifndef HAVE_INET_PTON @@ -243,435 +237,435 @@ str_isnumber(const char *p) static int inet_pton(int af, const char *hostname, void *pton) { - struct in_addr in; + struct in_addr in; #ifdef HAVE_INET_ATON - if (!inet_aton(hostname, &in)) - return 0; + if (!inet_aton(hostname, &in)) + return 0; #else - int d1, d2, d3, d4; - char ch; - - if (sscanf(hostname, "%d.%d.%d.%d%c", &d1, &d2, &d3, &d4, &ch) == 4 && - 0 <= d1 && d1 <= 255 && 0 <= d2 && d2 <= 255 && - 0 <= d3 && d3 <= 255 && 0 <= d4 && d4 <= 255) { - in.s_addr = htonl( - ((long) d1 << 24) | ((long) d2 << 16) | - ((long) d3 << 8) | ((long) d4 << 0)); - } - else { - return 0; - } -#endif - memcpy(pton, &in, sizeof(in)); - return 1; + int d1, d2, d3, d4; + char ch; + + if (sscanf(hostname, "%d.%d.%d.%d%c", &d1, &d2, &d3, &d4, &ch) == 4 && + 0 <= d1 && d1 <= 255 && 0 <= d2 && d2 <= 255 && + 0 <= d3 && d3 <= 255 && 0 <= d4 && d4 <= 255) { + in.s_addr = htonl( + ((long) d1 << 24) | ((long) d2 << 16) | + ((long) d3 << 8) | ((long) d4 << 0)); + } + else { + return 0; + } +#endif + memcpy(pton, &in, sizeof(in)); + return 1; } #endif int getaddrinfo(const char *hostname, const char *servname, const struct addrinfo *hints, struct addrinfo **res) { - struct addrinfo sentinel; - struct addrinfo *top = NULL; - struct addrinfo *cur; - int i, error = 0; - char pton[PTON_MAX]; - struct addrinfo ai; - struct addrinfo *pai; - u_short port; + struct addrinfo sentinel; + struct addrinfo *top = NULL; + struct addrinfo *cur; + int i, error = 0; + char pton[PTON_MAX]; + struct addrinfo ai; + struct addrinfo *pai; + u_short port; #ifdef FAITH - static int firsttime = 1; - - if (firsttime) { - /* translator hack */ - { - char *q = getenv("GAI"); - if (q && inet_pton(AF_INET6, q, &faith_prefix) == 1) - translate = YES; - } - firsttime = 0; - } -#endif - - /* initialize file static vars */ - sentinel.ai_next = NULL; - cur = &sentinel; - pai = &ai; - pai->ai_flags = 0; - pai->ai_family = PF_UNSPEC; - pai->ai_socktype = ANY; - pai->ai_protocol = ANY; - pai->ai_addrlen = 0; - pai->ai_canonname = NULL; - pai->ai_addr = NULL; - pai->ai_next = NULL; - port = ANY; - - if (hostname == NULL && servname == NULL) - return EAI_NONAME; - if (hints) { - /* error check for hints */ - if (hints->ai_addrlen || hints->ai_canonname || - hints->ai_addr || hints->ai_next) - ERR(EAI_BADHINTS); /* xxx */ - if (hints->ai_flags & ~AI_MASK) - ERR(EAI_BADFLAGS); - switch (hints->ai_family) { - case PF_UNSPEC: - case PF_INET: + static int firsttime = 1; + + if (firsttime) { + /* translator hack */ + { + char *q = getenv("GAI"); + if (q && inet_pton(AF_INET6, q, &faith_prefix) == 1) + translate = YES; + } + firsttime = 0; + } +#endif + + /* initialize file static vars */ + sentinel.ai_next = NULL; + cur = &sentinel; + pai = &ai; + pai->ai_flags = 0; + pai->ai_family = PF_UNSPEC; + pai->ai_socktype = ANY; + pai->ai_protocol = ANY; + pai->ai_addrlen = 0; + pai->ai_canonname = NULL; + pai->ai_addr = NULL; + pai->ai_next = NULL; + port = ANY; + + if (hostname == NULL && servname == NULL) + return EAI_NONAME; + if (hints) { + /* error check for hints */ + if (hints->ai_addrlen || hints->ai_canonname || + hints->ai_addr || hints->ai_next) + ERR(EAI_BADHINTS); /* xxx */ + if (hints->ai_flags & ~AI_MASK) + ERR(EAI_BADFLAGS); + switch (hints->ai_family) { + case PF_UNSPEC: + case PF_INET: #ifdef INET6 - case PF_INET6: -#endif - break; - default: - ERR(EAI_FAMILY); - } - memcpy(pai, hints, sizeof(*pai)); - switch (pai->ai_socktype) { - case ANY: - switch (pai->ai_protocol) { - case ANY: - break; - case IPPROTO_UDP: - pai->ai_socktype = SOCK_DGRAM; - break; - case IPPROTO_TCP: - pai->ai_socktype = SOCK_STREAM; - break; - default: + case PF_INET6: +#endif + break; + default: + ERR(EAI_FAMILY); + } + memcpy(pai, hints, sizeof(*pai)); + switch (pai->ai_socktype) { + case ANY: + switch (pai->ai_protocol) { + case ANY: + break; + case IPPROTO_UDP: + pai->ai_socktype = SOCK_DGRAM; + break; + case IPPROTO_TCP: + pai->ai_socktype = SOCK_STREAM; + break; + default: #if defined(SOCK_RAW) - pai->ai_socktype = SOCK_RAW; + pai->ai_socktype = SOCK_RAW; #endif - break; - } - break; + break; + } + break; #if defined(SOCK_RAW) - case SOCK_RAW: - break; -#endif - case SOCK_DGRAM: - if (pai->ai_protocol != IPPROTO_UDP && - pai->ai_protocol != ANY) - ERR(EAI_BADHINTS); /*xxx*/ - pai->ai_protocol = IPPROTO_UDP; - break; - case SOCK_STREAM: - if (pai->ai_protocol != IPPROTO_TCP && - pai->ai_protocol != ANY) - ERR(EAI_BADHINTS); /*xxx*/ - pai->ai_protocol = IPPROTO_TCP; - break; - default: - ERR(EAI_SOCKTYPE); - break; - } - } - - /* - * service port - */ - if (servname) { - if (str_isnumber(servname)) { - if (pai->ai_socktype == ANY) { - /* caller accept *ANY* socktype */ - pai->ai_socktype = SOCK_DGRAM; - pai->ai_protocol = IPPROTO_UDP; - } - port = htons((unsigned short)atoi(servname)); + case SOCK_RAW: + break; +#endif + case SOCK_DGRAM: + if (pai->ai_protocol != IPPROTO_UDP && + pai->ai_protocol != ANY) + ERR(EAI_BADHINTS); /*xxx*/ + pai->ai_protocol = IPPROTO_UDP; + break; + case SOCK_STREAM: + if (pai->ai_protocol != IPPROTO_TCP && + pai->ai_protocol != ANY) + ERR(EAI_BADHINTS); /*xxx*/ + pai->ai_protocol = IPPROTO_TCP; + break; + default: + ERR(EAI_SOCKTYPE); + break; + } + } + + /* + * service port + */ + if (servname) { + if (str_isnumber(servname)) { + if (pai->ai_socktype == ANY) { + /* caller accept *ANY* socktype */ + pai->ai_socktype = SOCK_DGRAM; + pai->ai_protocol = IPPROTO_UDP; + } + port = htons((unsigned short)atoi(servname)); } else if (pai->ai_flags & AI_NUMERICSERV) { ERR(EAI_NONAME); - } else { - struct servent *sp; - const char *proto; - - proto = NULL; - switch (pai->ai_socktype) { - case ANY: - proto = NULL; - break; - case SOCK_DGRAM: - proto = "udp"; - break; - case SOCK_STREAM: - proto = "tcp"; - break; - default: - fprintf(stderr, "panic!\n"); - break; - } - if ((sp = getservbyname((char*)servname, proto)) == NULL) - ERR(EAI_SERVICE); - port = sp->s_port; - if (pai->ai_socktype == ANY) - if (strcmp(sp->s_proto, "udp") == 0) { - pai->ai_socktype = SOCK_DGRAM; - pai->ai_protocol = IPPROTO_UDP; - } else if (strcmp(sp->s_proto, "tcp") == 0) { - pai->ai_socktype = SOCK_STREAM; - pai->ai_protocol = IPPROTO_TCP; - } else - ERR(EAI_PROTOCOL); /*xxx*/ - } - } - - /* - * hostname == NULL. - * passive socket -> anyaddr (0.0.0.0 or ::) - * non-passive socket -> localhost (127.0.0.1 or ::1) - */ - if (hostname == NULL) { - const struct afd *afd; - int s; - - for (afd = &afdl[0]; afd->a_af; afd++) { - if (!(pai->ai_family == PF_UNSPEC - || pai->ai_family == afd->a_af)) { - continue; - } - - /* - * filter out AFs that are not supported by the kernel - * XXX errno? - */ - s = socket(afd->a_af, SOCK_DGRAM, 0); - if (s < 0) - continue; - - close(s); - - if (pai->ai_flags & AI_PASSIVE) { - GET_AI(cur->ai_next, afd, afd->a_addrany, port); - /* xxx meaningless? - * GET_CANONNAME(cur->ai_next, "anyaddr"); - */ - } else { - GET_AI(cur->ai_next, afd, afd->a_loopback, - port); - /* xxx meaningless? - * GET_CANONNAME(cur->ai_next, "localhost"); - */ - } - cur = cur->ai_next; - } - top = sentinel.ai_next; - if (top) - goto good; - else - ERR(EAI_FAMILY); - } - - /* hostname as numeric name */ - for (i = 0; afdl[i].a_af; i++) { - if (inet_pton(afdl[i].a_af, hostname, pton)) { - u_long v4a; + } else { + struct servent *sp; + const char *proto; + + proto = NULL; + switch (pai->ai_socktype) { + case ANY: + proto = NULL; + break; + case SOCK_DGRAM: + proto = "udp"; + break; + case SOCK_STREAM: + proto = "tcp"; + break; + default: + fprintf(stderr, "panic!\n"); + break; + } + if ((sp = getservbyname((char*)servname, proto)) == NULL) + ERR(EAI_SERVICE); + port = sp->s_port; + if (pai->ai_socktype == ANY) + if (strcmp(sp->s_proto, "udp") == 0) { + pai->ai_socktype = SOCK_DGRAM; + pai->ai_protocol = IPPROTO_UDP; + } else if (strcmp(sp->s_proto, "tcp") == 0) { + pai->ai_socktype = SOCK_STREAM; + pai->ai_protocol = IPPROTO_TCP; + } else + ERR(EAI_PROTOCOL); /*xxx*/ + } + } + + /* + * hostname == NULL. + * passive socket -> anyaddr (0.0.0.0 or ::) + * non-passive socket -> localhost (127.0.0.1 or ::1) + */ + if (hostname == NULL) { + const struct afd *afd; + int s; + + for (afd = &afdl[0]; afd->a_af; afd++) { + if (!(pai->ai_family == PF_UNSPEC + || pai->ai_family == afd->a_af)) { + continue; + } + + /* + * filter out AFs that are not supported by the kernel + * XXX errno? + */ + s = socket(afd->a_af, SOCK_DGRAM, 0); + if (s < 0) + continue; + + close(s); + + if (pai->ai_flags & AI_PASSIVE) { + GET_AI(cur->ai_next, afd, afd->a_addrany, port); + /* xxx meaningless? + * GET_CANONNAME(cur->ai_next, "anyaddr"); + */ + } else { + GET_AI(cur->ai_next, afd, afd->a_loopback, + port); + /* xxx meaningless? + * GET_CANONNAME(cur->ai_next, "localhost"); + */ + } + cur = cur->ai_next; + } + top = sentinel.ai_next; + if (top) + goto good; + else + ERR(EAI_FAMILY); + } + + /* hostname as numeric name */ + for (i = 0; afdl[i].a_af; i++) { + if (inet_pton(afdl[i].a_af, hostname, pton)) { + u_long v4a; #ifdef INET6 - u_char pfx; -#endif - - switch (afdl[i].a_af) { - case AF_INET: - v4a = ((struct in_addr *)pton)->s_addr; - if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a)) - pai->ai_flags &= ~AI_CANONNAME; - v4a >>= IN_CLASSA_NSHIFT; - if (v4a == 0 || v4a == IN_LOOPBACKNET) - pai->ai_flags &= ~AI_CANONNAME; - break; + u_char pfx; +#endif + + switch (afdl[i].a_af) { + case AF_INET: + v4a = ((struct in_addr *)pton)->s_addr; + if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a)) + pai->ai_flags &= ~AI_CANONNAME; + v4a >>= IN_CLASSA_NSHIFT; + if (v4a == 0 || v4a == IN_LOOPBACKNET) + pai->ai_flags &= ~AI_CANONNAME; + break; #ifdef INET6 - case AF_INET6: - pfx = ((struct in6_addr *)pton)->s6_addr[0]; - if (pfx == 0 || pfx == 0xfe || pfx == 0xff) - pai->ai_flags &= ~AI_CANONNAME; - break; -#endif - } - - if (pai->ai_family == afdl[i].a_af || - pai->ai_family == PF_UNSPEC) { - if (! (pai->ai_flags & AI_CANONNAME)) { - GET_AI(top, &afdl[i], pton, port); - goto good; - } - /* - * if AI_CANONNAME and if reverse lookup - * fail, return ai anyway to pacify - * calling application. - * - * XXX getaddrinfo() is a name->address - * translation function, and it looks strange - * that we do addr->name translation here. - */ - get_name(pton, &afdl[i], &top, pton, pai, port); - goto good; - } else - ERR(EAI_FAMILY); /*xxx*/ - } - } - - if (pai->ai_flags & AI_NUMERICHOST) - ERR(EAI_NONAME); - - /* hostname as alphabetical name */ - error = get_addr(hostname, pai->ai_family, &top, pai, port); - if (error == 0) { - if (top) { + case AF_INET6: + pfx = ((struct in6_addr *)pton)->s6_addr[0]; + if (pfx == 0 || pfx == 0xfe || pfx == 0xff) + pai->ai_flags &= ~AI_CANONNAME; + break; +#endif + } + + if (pai->ai_family == afdl[i].a_af || + pai->ai_family == PF_UNSPEC) { + if (! (pai->ai_flags & AI_CANONNAME)) { + GET_AI(top, &afdl[i], pton, port); + goto good; + } + /* + * if AI_CANONNAME and if reverse lookup + * fail, return ai anyway to pacify + * calling application. + * + * XXX getaddrinfo() is a name->address + * translation function, and it looks strange + * that we do addr->name translation here. + */ + get_name(pton, &afdl[i], &top, pton, pai, port); + goto good; + } else + ERR(EAI_FAMILY); /*xxx*/ + } + } + + if (pai->ai_flags & AI_NUMERICHOST) + ERR(EAI_NONAME); + + /* hostname as alphabetical name */ + error = get_addr(hostname, pai->ai_family, &top, pai, port); + if (error == 0) { + if (top) { good: - *res = top; - return SUCCESS; - } else - error = EAI_FAIL; - } + *res = top; + return SUCCESS; + } else + error = EAI_FAIL; + } free: - if (top) - freeaddrinfo(top); + if (top) + freeaddrinfo(top); bad: - *res = NULL; - return error; + *res = NULL; + return error; } static int get_name(const char *addr, const struct afd *afd, struct addrinfo **res, char *numaddr, struct addrinfo *pai, int port0) { - u_short port = port0 & 0xffff; - struct hostent *hp; - struct addrinfo *cur; - int error = 0; + u_short port = port0 & 0xffff; + struct hostent *hp; + struct addrinfo *cur; + int error = 0; #ifdef INET6 - int h_error; + int h_error; #endif #ifdef INET6 - hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error); + hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error); #else - hp = gethostbyaddr((char*)addr, afd->a_addrlen, AF_INET); + hp = gethostbyaddr((char*)addr, afd->a_addrlen, AF_INET); #endif - if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) { - GET_AI(cur, afd, hp->h_addr_list[0], port); - GET_CANONNAME(cur, hp->h_name); - } else - GET_AI(cur, afd, numaddr, port); + if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) { + GET_AI(cur, afd, hp->h_addr_list[0], port); + GET_CANONNAME(cur, hp->h_name); + } else + GET_AI(cur, afd, numaddr, port); #ifdef INET6 - if (hp) - freehostent(hp); + if (hp) + freehostent(hp); #endif - *res = cur; - return SUCCESS; + *res = cur; + return SUCCESS; free: - if (cur) - freeaddrinfo(cur); + if (cur) + freeaddrinfo(cur); #ifdef INET6 - if (hp) - freehostent(hp); + if (hp) + freehostent(hp); #endif /* bad: */ - *res = NULL; - return error; + *res = NULL; + return error; } static int get_addr(const char *hostname, int af, struct addrinfo **res, struct addrinfo *pai, int port0) { - u_short port = port0 & 0xffff; - struct addrinfo sentinel; - struct hostent *hp; - struct addrinfo *top, *cur; - const struct afd *afd; - int i, error = 0, h_error; - char *ap; - - top = NULL; - sentinel.ai_next = NULL; - cur = &sentinel; + u_short port = port0 & 0xffff; + struct addrinfo sentinel; + struct hostent *hp; + struct addrinfo *top, *cur; + const struct afd *afd; + int i, error = 0, h_error; + char *ap; + + top = NULL; + sentinel.ai_next = NULL; + cur = &sentinel; #ifdef INET6 - if (af == AF_UNSPEC) { - hp = getipnodebyname(hostname, AF_INET6, - AI_ADDRCONFIG|AI_ALL|AI_V4MAPPED, &h_error); - } else - hp = getipnodebyname(hostname, af, AI_ADDRCONFIG, &h_error); + if (af == AF_UNSPEC) { + hp = getipnodebyname(hostname, AF_INET6, + AI_ADDRCONFIG|AI_ALL|AI_V4MAPPED, &h_error); + } else + hp = getipnodebyname(hostname, af, AI_ADDRCONFIG, &h_error); #else - if (strlen(hostname) >= NI_MAXHOST) ERR(EAI_NODATA); - hp = gethostbyname((char*)hostname); - h_error = h_errno; -#endif - if (hp == NULL) { - switch (h_error) { - case HOST_NOT_FOUND: - case NO_DATA: - error = EAI_NODATA; - break; - case TRY_AGAIN: - error = EAI_AGAIN; - break; - case NO_RECOVERY: - default: - error = EAI_FAIL; - break; - } - goto bad; - } - - if ((hp->h_name == NULL) || (hp->h_name[0] == 0) || - (hp->h_addr_list[0] == NULL)) - ERR(EAI_FAIL); - - for (i = 0; (ap = hp->h_addr_list[i]) != NULL; i++) { - switch (af) { + if (strlen(hostname) >= NI_MAXHOST) ERR(EAI_NODATA); + hp = gethostbyname((char*)hostname); + h_error = h_errno; +#endif + if (hp == NULL) { + switch (h_error) { + case HOST_NOT_FOUND: + case NO_DATA: + error = EAI_NODATA; + break; + case TRY_AGAIN: + error = EAI_AGAIN; + break; + case NO_RECOVERY: + default: + error = EAI_FAIL; + break; + } + goto bad; + } + + if ((hp->h_name == NULL) || (hp->h_name[0] == 0) || + (hp->h_addr_list[0] == NULL)) + ERR(EAI_FAIL); + + for (i = 0; (ap = hp->h_addr_list[i]) != NULL; i++) { + switch (af) { #ifdef INET6 - case AF_INET6: - afd = &afdl[N_INET6]; - break; + case AF_INET6: + afd = &afdl[N_INET6]; + break; #endif #ifndef INET6 - default: /* AF_UNSPEC */ + default: /* AF_UNSPEC */ #endif - case AF_INET: - afd = &afdl[N_INET]; - break; + case AF_INET: + afd = &afdl[N_INET]; + break; #ifdef INET6 - default: /* AF_UNSPEC */ - if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) { - ap += sizeof(struct in6_addr) - - sizeof(struct in_addr); - afd = &afdl[N_INET]; - } else - afd = &afdl[N_INET6]; - break; -#endif - } + default: /* AF_UNSPEC */ + if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) { + ap += sizeof(struct in6_addr) - + sizeof(struct in_addr); + afd = &afdl[N_INET]; + } else + afd = &afdl[N_INET6]; + break; +#endif + } #ifdef FAITH - if (translate && afd->a_af == AF_INET) { - struct in6_addr *in6; - - GET_AI(cur->ai_next, &afdl[N_INET6], ap, port); - in6 = &((struct sockaddr_in6 *)cur->ai_next->ai_addr)->sin6_addr; - memcpy(&in6->s6_addr, &faith_prefix, - sizeof(struct in6_addr) - sizeof(struct in_addr)); - memcpy(&in6->s6_addr + sizeof(struct in_addr), ap, - sizeof(struct in_addr)); - } else + if (translate && afd->a_af == AF_INET) { + struct in6_addr *in6; + + GET_AI(cur->ai_next, &afdl[N_INET6], ap, port); + in6 = &((struct sockaddr_in6 *)cur->ai_next->ai_addr)->sin6_addr; + memcpy(&in6->s6_addr, &faith_prefix, + sizeof(struct in6_addr) - sizeof(struct in_addr)); + memcpy(&in6->s6_addr + sizeof(struct in_addr), ap, + sizeof(struct in_addr)); + } else #endif /* FAITH */ - GET_AI(cur->ai_next, afd, ap, port); - if (cur == &sentinel) { - top = cur->ai_next; - GET_CANONNAME(top, hp->h_name); - } - cur = cur->ai_next; - } + GET_AI(cur->ai_next, afd, ap, port); + if (cur == &sentinel) { + top = cur->ai_next; + GET_CANONNAME(top, hp->h_name); + } + cur = cur->ai_next; + } #ifdef INET6 - freehostent(hp); + freehostent(hp); #endif - *res = top; - return SUCCESS; + *res = top; + return SUCCESS; free: - if (top) - freeaddrinfo(top); + if (top) + freeaddrinfo(top); #ifdef INET6 - if (hp) - freehostent(hp); + if (hp) + freehostent(hp); #endif bad: - *res = NULL; - return error; + *res = NULL; + return error; } diff --git a/ext/socket/getnameinfo.c b/ext/socket/getnameinfo.c index 94a5eb9439..98da8c1647 100644 --- a/ext/socket/getnameinfo.c +++ b/ext/socket/getnameinfo.c @@ -55,9 +55,6 @@ #endif #endif #ifdef _WIN32 -#if defined(_MSC_VER) && _MSC_VER <= 1200 -#include <windows.h> -#endif #include <winsock2.h> #include <ws2tcpip.h> #define snprintf _snprintf @@ -84,30 +81,30 @@ typedef int socklen_t; #define NO 0 struct sockinet { - u_char si_len; - u_char si_family; - u_short si_port; + u_char si_len; + u_char si_family; + u_short si_port; }; static struct afd { - int a_af; - int a_addrlen; - int a_socklen; - int a_off; + int a_af; + int a_addrlen; + int a_socklen; + int a_off; } afdl [] = { #ifdef INET6 #define N_INET6 0 - {PF_INET6, sizeof(struct in6_addr), - sizeof(struct sockaddr_in6), - offsetof(struct sockaddr_in6, sin6_addr)}, + {PF_INET6, sizeof(struct in6_addr), + sizeof(struct sockaddr_in6), + offsetof(struct sockaddr_in6, sin6_addr)}, #define N_INET 1 #else #define N_INET 0 #endif - {PF_INET, sizeof(struct in_addr), - sizeof(struct sockaddr_in), - offsetof(struct sockaddr_in, sin_addr)}, - {0, 0, 0, 0}, + {PF_INET, sizeof(struct in_addr), + sizeof(struct sockaddr_in), + offsetof(struct sockaddr_in, sin_addr)}, + {0, 0, 0, 0}, }; #define ENI_NOSOCKET 0 @@ -121,123 +118,118 @@ static struct afd { int getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, socklen_t hostlen, char *serv, socklen_t servlen, int flags) { - struct afd *afd; - struct hostent *hp; - u_short port; - int family, len, i; - char *addr, *p; - u_long v4a; + struct afd *afd; + struct hostent *hp; + u_short port; + int family, len, i; + char *addr, *p; + u_long v4a; #ifdef INET6 - u_char pfx; + u_char pfx; #endif - int h_error; - char numserv[512]; - char numaddr[512]; + int h_error; + char numserv[512]; + char numaddr[512]; - if (sa == NULL) - return ENI_NOSOCKET; + if (sa == NULL) + return ENI_NOSOCKET; - if (!VALIDATE_SOCKLEN(sa, salen)) return ENI_SALEN; + if (!VALIDATE_SOCKLEN(sa, salen)) return ENI_SALEN; len = salen; - family = sa->sa_family; - for (i = 0; afdl[i].a_af; i++) - if (afdl[i].a_af == family) { - afd = &afdl[i]; - goto found; - } - return ENI_FAMILY; + family = sa->sa_family; + for (i = 0; afdl[i].a_af; i++) + if (afdl[i].a_af == family) { + afd = &afdl[i]; + goto found; + } + return ENI_FAMILY; found: - if (len != afd->a_socklen) return ENI_SALEN; - - port = ((struct sockinet *)sa)->si_port; /* network byte order */ - addr = (char *)sa + afd->a_off; - - if (serv == NULL || servlen == 0) { - /* what we should do? */ - } else if (flags & NI_NUMERICSERV) { - snprintf(numserv, sizeof(numserv), "%d", ntohs(port)); - if (strlen(numserv) + 1 > servlen) - return ENI_MEMORY; - strcpy(serv, numserv); - } else { + if (len != afd->a_socklen) return ENI_SALEN; + + port = ((struct sockinet *)sa)->si_port; /* network byte order */ + addr = (char *)sa + afd->a_off; + + if (serv == NULL || servlen == 0) { + /* what we should do? */ + } else if (flags & NI_NUMERICSERV) { + snprintf(numserv, sizeof(numserv), "%d", ntohs(port)); + if (strlcpy(serv, numserv, servlen) >= servlen) + return ENI_MEMORY; + } else { #if defined(HAVE_GETSERVBYPORT) - struct servent *sp = getservbyport(port, (flags & NI_DGRAM) ? "udp" : "tcp"); - if (sp) { - if (strlen(sp->s_name) + 1 > servlen) - return ENI_MEMORY; - strcpy(serv, sp->s_name); - } else - return ENI_NOSERVNAME; + struct servent *sp = getservbyport(port, (flags & NI_DGRAM) ? "udp" : "tcp"); + if (sp) { + if (strlcpy(serv, sp->s_name, servlen) >= servlen) + return ENI_MEMORY; + } else + return ENI_NOSERVNAME; #else - return ENI_NOSERVNAME; -#endif - } - - switch (sa->sa_family) { - case AF_INET: - v4a = ntohl(((struct sockaddr_in *)sa)->sin_addr.s_addr); - if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a)) - flags |= NI_NUMERICHOST; - v4a >>= IN_CLASSA_NSHIFT; - if (v4a == 0) - flags |= NI_NUMERICHOST; - break; + return ENI_NOSERVNAME; +#endif + } + + switch (sa->sa_family) { + case AF_INET: + v4a = ntohl(((struct sockaddr_in *)sa)->sin_addr.s_addr); + if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a)) + flags |= NI_NUMERICHOST; + v4a >>= IN_CLASSA_NSHIFT; + if (v4a == 0) + flags |= NI_NUMERICHOST; + break; #ifdef INET6 - case AF_INET6: + case AF_INET6: #ifdef HAVE_ADDR8 - pfx = ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr8[0]; + pfx = ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr8[0]; #else - pfx = ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr[0]; -#endif - if (pfx == 0 || pfx == 0xfe || pfx == 0xff) - flags |= NI_NUMERICHOST; - break; -#endif - } - if (host == NULL || hostlen == 0) { - /* what should we do? */ - } else if (flags & NI_NUMERICHOST) { - if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr)) - == NULL) - return ENI_SYSTEM; - if (strlen(numaddr) > hostlen) - return ENI_MEMORY; - strcpy(host, numaddr); - } else { + pfx = ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr[0]; +#endif + if (pfx == 0 || pfx == 0xfe || pfx == 0xff) + flags |= NI_NUMERICHOST; + break; +#endif + } + if (host == NULL || hostlen == 0) { + /* what should we do? */ + } else if (flags & NI_NUMERICHOST) { + if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr)) + == NULL) + return ENI_SYSTEM; + if (strlcpy(host, numaddr, hostlen) >= hostlen) + return ENI_MEMORY; + } else { #ifdef INET6 - hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error); + hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error); #else - hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af); - h_error = h_errno; + hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af); + h_error = h_errno; #endif - if (hp) { - if (flags & NI_NOFQDN) { - p = strchr(hp->h_name, '.'); - if (p) *p = '\0'; - } - if (strlen(hp->h_name) + 1 > hostlen) { + if (hp) { + if (flags & NI_NOFQDN) { + p = strchr(hp->h_name, '.'); + if (p) *p = '\0'; + } + if (strlcpy(host, hp->h_name, hostlen) >= hostlen) { #ifdef INET6 - freehostent(hp); + freehostent(hp); #endif - return ENI_MEMORY; - } - strcpy(host, hp->h_name); + return ENI_MEMORY; + } #ifdef INET6 - freehostent(hp); -#endif - } else { - if (flags & NI_NAMEREQD) - return ENI_NOHOSTNAME; - if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr)) - == NULL) - return ENI_NOHOSTNAME; - if (strlen(numaddr) > hostlen) - return ENI_MEMORY; - strcpy(host, numaddr); - } - } - return SUCCESS; + freehostent(hp); +#endif + } else { + if (flags & NI_NAMEREQD) + return ENI_NOHOSTNAME; + if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr)) + == NULL) + return ENI_NOHOSTNAME; + if (strlcpy(host, numaddr, hostlen) >= hostlen) + return ENI_MEMORY; + } + } + return SUCCESS; } diff --git a/ext/socket/ifaddr.c b/ext/socket/ifaddr.c index 26aa0c8082..3596c40a11 100644 --- a/ext/socket/ifaddr.c +++ b/ext/socket/ifaddr.c @@ -104,7 +104,7 @@ rsock_getifaddrs(void) rb_sys_fail("getifaddrs"); if (!ifaddrs) { - return rb_ary_new(); + return rb_ary_new(); } numifaddrs = 0; @@ -128,9 +128,9 @@ rsock_getifaddrs(void) result = rb_ary_new2(numifaddrs); rb_ary_push(result, addr); for (i = 1; i < numifaddrs; i++) { - addr = TypedData_Wrap_Struct(rb_cSockIfaddr, &ifaddr_type, &root->ary[i]); - root->refcount++; - rb_ary_push(result, addr); + addr = TypedData_Wrap_Struct(rb_cSockIfaddr, &ifaddr_type, &root->ary[i]); + root->refcount++; + rb_ary_push(result, addr); } return result; @@ -177,6 +177,8 @@ ifaddr_ifindex(VALUE self) * ifaddr.flags => integer * * Returns the flags of _ifaddr_. + * + * The value is bitwise-or of Socket::IFF_* constants such as Socket::IFF_LOOPBACK. */ static VALUE @@ -459,7 +461,8 @@ rsock_init_sockifaddr(void) * * Socket::Ifaddr represents a result of getifaddrs() function. */ - rb_cSockIfaddr = rb_define_class_under(rb_cSocket, "Ifaddr", rb_cData); + rb_cSockIfaddr = rb_define_class_under(rb_cSocket, "Ifaddr", rb_cObject); + rb_undef_alloc_func(rb_cSockIfaddr); rb_define_method(rb_cSockIfaddr, "inspect", ifaddr_inspect, 0); rb_define_method(rb_cSockIfaddr, "name", ifaddr_name, 0); rb_define_method(rb_cSockIfaddr, "ifindex", ifaddr_ifindex, 0); diff --git a/ext/socket/init.c b/ext/socket/init.c index 44d1506973..b761d601c3 100644 --- a/ext/socket/init.c +++ b/ext/socket/init.c @@ -27,6 +27,7 @@ VALUE rb_cSocket; VALUE rb_cAddrinfo; VALUE rb_eSocket; +VALUE rb_eResolution; #ifdef SOCKS VALUE rb_cSOCKSSocket; @@ -34,39 +35,30 @@ VALUE rb_cSOCKSSocket; int rsock_do_not_reverse_lookup = 1; static VALUE sym_wait_readable; +static ID id_error_code; void -rsock_raise_socket_error(const char *reason, int error) +rsock_raise_resolution_error(const char *reason, int error) { #ifdef EAI_SYSTEM int e; if (error == EAI_SYSTEM && (e = errno) != 0) - rb_syserr_fail(e, reason); + rb_syserr_fail(e, reason); #endif #ifdef _WIN32 rb_encoding *enc = rb_default_internal_encoding(); VALUE msg = rb_sprintf("%s: ", reason); if (!enc) enc = rb_default_internal_encoding(); rb_str_concat(msg, rb_w32_conv_from_wchar(gai_strerrorW(error), enc)); - rb_exc_raise(rb_exc_new_str(rb_eSocket, msg)); #else - rb_raise(rb_eSocket, "%s: %s", reason, gai_strerror(error)); + VALUE msg = rb_sprintf("%s: %s", reason, gai_strerror(error)); #endif -} - -#ifdef _WIN32 -#define is_socket(fd) rb_w32_is_socket(fd) -#else -static int -is_socket(int fd) -{ - struct stat sbuf; - if (fstat(fd, &sbuf) < 0) - rb_sys_fail("fstat(2)"); - return S_ISSOCK(sbuf.st_mode); + StringValue(msg); + VALUE self = rb_class_new_instance(1, &msg, rb_eResolution); + rb_ivar_set(self, id_error_code, INT2NUM(error)); + rb_exc_raise(self); } -#endif #if defined __APPLE__ # define do_write_retry(code) do {ret = code;} while (ret == -1 && errno == EPROTOTYPE) @@ -79,17 +71,13 @@ rsock_init_sock(VALUE sock, int fd) { rb_io_t *fp; - if (!is_socket(fd) || rb_reserved_fd_p(fd)) { - rb_syserr_fail(EBADF, "not a socket file descriptor"); - } - rb_update_max_fd(fd); MakeOpenFile(sock, fp); fp->fd = fd; fp->mode = FMODE_READWRITE|FMODE_DUPLEX; rb_io_ascii8bit_binmode(sock); if (rsock_do_not_reverse_lookup) { - fp->mode |= FMODE_NOREVLOOKUP; + fp->mode |= FMODE_NOREVLOOKUP; } rb_io_synchronized(fp); @@ -103,7 +91,7 @@ rsock_sendto_blocking(void *data) VALUE mesg = arg->mesg; ssize_t ret; do_write_retry(sendto(arg->fd, RSTRING_PTR(mesg), RSTRING_LEN(mesg), - arg->flags, arg->to, arg->tolen)); + arg->flags, arg->to, arg->tolen)); return (VALUE)ret; } @@ -114,13 +102,15 @@ rsock_send_blocking(void *data) VALUE mesg = arg->mesg; ssize_t ret; do_write_retry(send(arg->fd, RSTRING_PTR(mesg), RSTRING_LEN(mesg), - arg->flags)); + arg->flags)); return (VALUE)ret; } struct recvfrom_arg { + rb_io_t *fptr; int fd, flags; VALUE str; + size_t length; socklen_t alen; union_sockaddr buf; }; @@ -131,10 +121,12 @@ recvfrom_blocking(void *data) struct recvfrom_arg *arg = data; socklen_t len0 = arg->alen; ssize_t ret; - ret = recvfrom(arg->fd, RSTRING_PTR(arg->str), RSTRING_LEN(arg->str), + ret = recvfrom(arg->fd, RSTRING_PTR(arg->str), arg->length, arg->flags, &arg->buf.addr, &arg->alen); + if (ret != -1 && len0 < arg->alen) arg->alen = len0; + return (VALUE)ret; } @@ -143,16 +135,15 @@ rsock_strbuf(VALUE str, long buflen) { long len; - if (NIL_P(str)) return rb_tainted_str_new(0, buflen); + if (NIL_P(str)) return rb_str_new(0, buflen); StringValue(str); len = RSTRING_LEN(str); if (len >= buflen) { - rb_str_modify(str); + rb_str_modify(str); } else { - rb_str_modify_expand(str, buflen - len); + rb_str_modify_expand(str, buflen - len); } - rb_str_set_len(str, buflen); return str; } @@ -161,11 +152,23 @@ recvfrom_locktmp(VALUE v) { struct recvfrom_arg *arg = (struct recvfrom_arg *)v; - return rb_thread_io_blocking_region(recvfrom_blocking, arg, arg->fd); + return rb_io_blocking_region(arg->fptr, recvfrom_blocking, arg); +} + +int +rsock_is_dgram(rb_io_t *fptr) +{ + int socktype; + socklen_t optlen = (socklen_t)sizeof(socktype); + int ret = getsockopt(fptr->fd, SOL_SOCKET, SO_TYPE, (void*)&socktype, &optlen); + if (ret == -1) { + rb_sys_fail("getsockopt(SO_TYPE)"); + } + return socktype == SOCK_DGRAM; } VALUE -rsock_s_recvfrom(VALUE sock, int argc, VALUE *argv, enum sock_recv_type from) +rsock_s_recvfrom(VALUE socket, int argc, VALUE *argv, enum sock_recv_type from) { rb_io_t *fptr; VALUE str; @@ -176,60 +179,75 @@ rsock_s_recvfrom(VALUE sock, int argc, VALUE *argv, enum sock_recv_type from) rb_scan_args(argc, argv, "12", &len, &flg, &str); - if (flg == Qnil) arg.flags = 0; - else arg.flags = NUM2INT(flg); + if (flg == Qnil) + arg.flags = 0; + else + arg.flags = NUM2INT(flg); + buflen = NUM2INT(len); str = rsock_strbuf(str, buflen); - GetOpenFile(sock, fptr); + RB_IO_POINTER(socket, fptr); + if (rb_io_read_pending(fptr)) { - rb_raise(rb_eIOError, "recv for buffered IO"); + rb_raise(rb_eIOError, "recv for buffered IO"); } + + arg.fptr = fptr; arg.fd = fptr->fd; arg.alen = (socklen_t)sizeof(arg.buf); arg.str = str; + arg.length = buflen; - while (rb_io_check_closed(fptr), - rsock_maybe_wait_fd(arg.fd), - (slen = (long)rb_str_locktmp_ensure(str, recvfrom_locktmp, - (VALUE)&arg)) < 0) { - if (!rb_io_wait_readable(fptr->fd)) { - rb_sys_fail("recvfrom(2)"); + while (true) { + rb_io_check_closed(fptr); + +#ifdef RSOCK_WAIT_BEFORE_BLOCKING + rb_io_wait(fptr->self, RB_INT2NUM(RUBY_IO_READABLE), Qnil); +#endif + + rb_str_locktmp(str); + slen = (long)rb_ensure(recvfrom_locktmp, (VALUE)&arg, rb_str_unlocktmp, str); + + if (slen == 0 && !rsock_is_dgram(fptr)) { + return Qnil; } - } + if (slen >= 0) break; - if (slen != RSTRING_LEN(str)) { - rb_str_set_len(str, slen); + if (!rb_io_maybe_wait_readable(errno, socket, RUBY_IO_TIMEOUT_DEFAULT)) + rb_sys_fail("recvfrom(2)"); } - rb_obj_taint(str); + + /* Resize the string to the amount of data received */ + rb_str_set_len(str, slen); switch (from) { case RECV_RECV: - return str; + return str; case RECV_IP: #if 0 - if (arg.alen != sizeof(struct sockaddr_in)) { - rb_raise(rb_eTypeError, "sockaddr size differs - should not happen"); - } + if (arg.alen != sizeof(struct sockaddr_in)) { + rb_raise(rb_eTypeError, "sockaddr size differs - should not happen"); + } #endif - if (arg.alen && arg.alen != sizeof(arg.buf)) /* OSX doesn't return a from result for connection-oriented sockets */ - return rb_assoc_new(str, rsock_ipaddr(&arg.buf.addr, arg.alen, fptr->mode & FMODE_NOREVLOOKUP)); - else - return rb_assoc_new(str, Qnil); + if (arg.alen && arg.alen != sizeof(arg.buf)) /* OSX doesn't return a from result for connection-oriented sockets */ + return rb_assoc_new(str, rsock_ipaddr(&arg.buf.addr, arg.alen, fptr->mode & FMODE_NOREVLOOKUP)); + else + return rb_assoc_new(str, Qnil); -#ifdef HAVE_SYS_UN_H +#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN case RECV_UNIX: return rb_assoc_new(str, rsock_unixaddr(&arg.buf.un, arg.alen)); #endif case RECV_SOCKET: - return rb_assoc_new(str, rsock_io_socket_addrinfo(sock, &arg.buf.addr, arg.alen)); + return rb_assoc_new(str, rsock_io_socket_addrinfo(socket, &arg.buf.addr, arg.alen)); default: - rb_bug("rsock_s_recvfrom called with bad value"); + rb_bug("rsock_s_recvfrom called with bad value"); } } VALUE rsock_s_recvfrom_nonblock(VALUE sock, VALUE len, VALUE flg, VALUE str, - VALUE ex, enum sock_recv_type from) + VALUE ex, enum sock_recv_type from) { rb_io_t *fptr; union_sockaddr buf; @@ -252,37 +270,40 @@ rsock_s_recvfrom_nonblock(VALUE sock, VALUE len, VALUE flg, VALUE str, GetOpenFile(sock, fptr); if (rb_io_read_pending(fptr)) { - rb_raise(rb_eIOError, "recvfrom for buffered IO"); + rb_raise(rb_eIOError, "recvfrom for buffered IO"); } fd = fptr->fd; rb_io_check_closed(fptr); if (!MSG_DONTWAIT_RELIABLE) - rb_io_set_nonblock(fptr); + rb_io_set_nonblock(fptr); len0 = alen; slen = recvfrom(fd, RSTRING_PTR(str), buflen, flags, &buf.addr, &alen); if (slen != -1 && len0 < alen) alen = len0; + if (slen == 0 && !rsock_is_dgram(fptr)) { + return Qnil; + } + if (slen < 0) { - int e = errno; - switch (e) { - case EAGAIN: + int e = errno; + switch (e) { + case EAGAIN: #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN - case EWOULDBLOCK: + case EWOULDBLOCK: #endif if (ex == Qfalse) - return sym_wait_readable; + return sym_wait_readable; rb_readwrite_syserr_fail(RB_IO_WAIT_READABLE, e, "recvfrom(2) would block"); - } - rb_syserr_fail(e, "recvfrom(2)"); + } + rb_syserr_fail(e, "recvfrom(2)"); } if (slen != RSTRING_LEN(str)) { - rb_str_set_len(str, slen); + rb_str_set_len(str, slen); } - rb_obj_taint(str); switch (from) { case RECV_RECV: return str; @@ -329,37 +350,34 @@ rsock_read_nonblock(VALUE sock, VALUE length, VALUE buf, VALUE ex) VALUE str = rsock_strbuf(buf, len); char *ptr; - OBJ_TAINT(str); GetOpenFile(sock, fptr); if (len == 0) { - return str; + rb_str_set_len(str, 0); + return str; } ptr = RSTRING_PTR(str); n = read_buffered_data(ptr, len, fptr); if (n <= 0) { - n = (long)recv(fptr->fd, ptr, len, MSG_DONTWAIT); - if (n < 0) { - int e = errno; - if ((e == EWOULDBLOCK || e == EAGAIN)) { - if (ex == Qfalse) return sym_wait_readable; - rb_readwrite_syserr_fail(RB_IO_WAIT_READABLE, - e, "read would block"); - } - rb_syserr_fail_path(e, fptr->pathv); - } + n = (long)recv(fptr->fd, ptr, len, MSG_DONTWAIT); + if (n < 0) { + int e = errno; + if ((e == EWOULDBLOCK || e == EAGAIN)) { + if (ex == Qfalse) return sym_wait_readable; + rb_readwrite_syserr_fail(RB_IO_WAIT_READABLE, + e, "read would block"); + } + rb_syserr_fail_path(e, fptr->pathv); + } } - if (len != n) { - rb_str_modify(str); - rb_str_set_len(str, n); - if (str != buf) { - rb_str_resize(str, n); - } + if (n != RSTRING_LEN(str)) { + rb_str_modify(str); + rb_str_set_len(str, n); } if (n == 0) { - if (ex == Qfalse) return Qnil; - rb_eof_error(); + if (ex == Qfalse) return Qnil; + rb_eof_error(); } return str; @@ -373,7 +391,7 @@ rsock_write_nonblock(VALUE sock, VALUE str, VALUE ex) long n; if (!RB_TYPE_P(str, T_STRING)) - str = rb_obj_as_string(str); + str = rb_obj_as_string(str); sock = rb_io_get_write_io(sock); GetOpenFile(sock, fptr); @@ -385,7 +403,7 @@ rsock_write_nonblock(VALUE sock, VALUE str, VALUE ex) * are not userspace-buffered in Ruby by default. */ if (fptr->wbuf.len > 0) { - rb_io_flush(sock); + rb_io_flush(sock); } #ifdef __APPLE__ @@ -393,103 +411,49 @@ rsock_write_nonblock(VALUE sock, VALUE str, VALUE ex) #endif n = (long)send(fptr->fd, RSTRING_PTR(str), RSTRING_LEN(str), MSG_DONTWAIT); if (n < 0) { - int e = errno; + int e = errno; #ifdef __APPLE__ - if (e == EPROTOTYPE) { - goto again; - } -#endif - if (e == EWOULDBLOCK || e == EAGAIN) { - if (ex == Qfalse) return sym_wait_writable; - rb_readwrite_syserr_fail(RB_IO_WAIT_WRITABLE, e, - "write would block"); - } - rb_syserr_fail_path(e, fptr->pathv); + if (e == EPROTOTYPE) { + goto again; + } +#endif + if (e == EWOULDBLOCK || e == EAGAIN) { + if (ex == Qfalse) return sym_wait_writable; + rb_readwrite_syserr_fail(RB_IO_WAIT_WRITABLE, e, + "write would block"); + } + rb_syserr_fail_path(e, fptr->pathv); } return LONG2FIX(n); } #endif /* MSG_DONTWAIT_RELIABLE */ -/* returns true if SOCK_CLOEXEC is supported */ -int rsock_detect_cloexec(int fd) +static int +rsock_socket0(int domain, int type, int proto) { #ifdef SOCK_CLOEXEC - int flags = fcntl(fd, F_GETFD); - - if (flags == -1) - rb_bug("rsock_detect_cloexec: fcntl(%d, F_GETFD) failed: %s", fd, strerror(errno)); + type |= SOCK_CLOEXEC; +#endif - if (flags & FD_CLOEXEC) - return 1; +#ifdef SOCK_NONBLOCK + type |= SOCK_NONBLOCK; #endif - return 0; -} -#ifdef SOCK_CLOEXEC -static int -rsock_socket0(int domain, int type, int proto) -{ - int ret; - static int cloexec_state = -1; /* <0: unknown, 0: ignored, >0: working */ - - if (cloexec_state > 0) { /* common path, if SOCK_CLOEXEC is defined */ - ret = socket(domain, type|SOCK_CLOEXEC|RSOCK_NONBLOCK_DEFAULT, proto); - if (ret >= 0) { - if (ret <= 2) - goto fix_cloexec; - goto update_max_fd; - } - } - else if (cloexec_state < 0) { /* usually runs once only for detection */ - ret = socket(domain, type|SOCK_CLOEXEC|RSOCK_NONBLOCK_DEFAULT, proto); - if (ret >= 0) { - cloexec_state = rsock_detect_cloexec(ret); - if (cloexec_state == 0 || ret <= 2) - goto fix_cloexec; - goto update_max_fd; - } - else if (ret == -1 && errno == EINVAL) { - /* SOCK_CLOEXEC is available since Linux 2.6.27. Linux 2.6.18 fails with EINVAL */ - ret = socket(domain, type, proto); - if (ret != -1) { - cloexec_state = 0; - /* fall through to fix_cloexec */ - } - } - } - else { /* cloexec_state == 0 */ - ret = socket(domain, type, proto); - } - if (ret == -1) + int result = socket(domain, type, proto); + + if (result == -1) return -1; -fix_cloexec: - rb_maygvl_fd_fix_cloexec(ret); - if (RSOCK_NONBLOCK_DEFAULT) { - rsock_make_fd_nonblock(ret); - } -update_max_fd: - rb_update_max_fd(ret); - return ret; -} -#else /* !SOCK_CLOEXEC */ -static int -rsock_socket0(int domain, int type, int proto) -{ - int ret = socket(domain, type, proto); + rb_fd_fix_cloexec(result); - if (ret == -1) - return -1; - rb_fd_fix_cloexec(ret); - if (RSOCK_NONBLOCK_DEFAULT) { - rsock_make_fd_nonblock(ret); - } +#ifndef SOCK_NONBLOCK + rsock_make_fd_nonblock(result); +#endif - return ret; + return result; } -#endif /* !SOCK_CLOEXEC */ int rsock_socket(int domain, int type, int proto) @@ -498,9 +462,9 @@ rsock_socket(int domain, int type, int proto) fd = rsock_socket0(domain, type, proto); if (fd < 0) { - if (rb_gc_for_fd(errno)) { - fd = rsock_socket0(domain, type, proto); - } + if (rb_gc_for_fd(errno)) { + fd = rsock_socket0(domain, type, proto); + } } if (0 <= fd) rb_update_max_fd(fd); @@ -509,10 +473,11 @@ rsock_socket(int domain, int type, int proto) /* emulate blocking connect behavior on EINTR or non-blocking socket */ static int -wait_connectable(int fd) +wait_connectable(VALUE self, VALUE timeout, const struct sockaddr *sockaddr, int len) { - int sockerr, revents; + int sockerr; socklen_t sockerrlen; + int fd = rb_io_descriptor(self); sockerrlen = (socklen_t)sizeof(sockerr); if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&sockerr, &sockerrlen) < 0) @@ -546,7 +511,16 @@ wait_connectable(int fd) * * Note: rb_wait_for_single_fd already retries on EINTR/ERESTART */ - revents = rb_wait_for_single_fd(fd, RB_WAITFD_IN|RB_WAITFD_OUT, NULL); + VALUE result = rb_io_wait(self, RB_INT2NUM(RUBY_IO_READABLE|RUBY_IO_WRITABLE), timeout); + + if (result == Qfalse) { + VALUE rai = rsock_addrinfo_new((struct sockaddr *)sockaddr, len, PF_UNSPEC, 0, 0, Qnil, Qnil); + VALUE addr_str = rsock_addrinfo_inspect_sockaddr(rai); + VALUE message = rb_sprintf("user specified timeout for %" PRIsVALUE, addr_str); + rb_raise(rb_eIOTimeoutError, "%" PRIsVALUE, message); + } + + int revents = RB_NUM2INT(result); if (revents < 0) return -1; @@ -557,10 +531,10 @@ wait_connectable(int fd) switch (sockerr) { case 0: - /* - * be defensive in case some platforms set SO_ERROR on the original, - * interrupted connect() - */ + /* + * be defensive in case some platforms set SO_ERROR on the original, + * interrupted connect() + */ case EINTR: #ifdef ERESTART case ERESTART: @@ -575,7 +549,7 @@ wait_connectable(int fd) #ifdef EISCONN case EISCONN: #endif - return 0; /* success */ + return 0; /* success */ default: /* likely (but not limited to): ECONNREFUSED, ETIMEDOUT, EHOSTUNREACH */ errno = sockerr; @@ -608,19 +582,19 @@ socks_connect_blocking(void *data) #endif int -rsock_connect(int fd, const struct sockaddr *sockaddr, int len, int socks) +rsock_connect(VALUE self, const struct sockaddr *sockaddr, int len, int socks, VALUE timeout) { - int status; + int descriptor = rb_io_descriptor(self); rb_blocking_function_t *func = connect_blocking; - struct connect_arg arg; + struct connect_arg arg = {.fd = descriptor, .sockaddr = sockaddr, .len = len}; + + rb_io_t *fptr; + RB_IO_POINTER(self, fptr); - arg.fd = fd; - arg.sockaddr = sockaddr; - arg.len = len; #if defined(SOCKS) && !defined(SOCKS5) if (socks) func = socks_connect_blocking; #endif - status = (int)BLOCKING_REGION_FD(func, &arg); + int status = (int)rb_io_blocking_region(fptr, func, &arg); if (status < 0) { switch (errno) { @@ -632,7 +606,7 @@ rsock_connect(int fd, const struct sockaddr *sockaddr, int len, int socks) #ifdef EINPROGRESS case EINPROGRESS: #endif - return wait_connectable(fd); + return wait_connectable(self, timeout, sockaddr, len); } } return status; @@ -641,6 +615,10 @@ rsock_connect(int fd, const struct sockaddr *sockaddr, int len, int socks) void rsock_make_fd_nonblock(int fd) { +#ifdef _WIN32 + return; +#endif + int flags; #ifdef F_GETFL flags = fcntl(fd, F_GETFL); @@ -657,81 +635,59 @@ rsock_make_fd_nonblock(int fd) } static int -cloexec_accept(int socket, struct sockaddr *address, socklen_t *address_len, - int nonblock) +cloexec_accept(int socket, struct sockaddr *address, socklen_t *address_len) { - int ret; socklen_t len0 = 0; -#ifdef HAVE_ACCEPT4 - static int try_accept4 = 1; -#endif - if (RSOCK_NONBLOCK_DEFAULT) { - nonblock = 1; - } if (address_len) len0 = *address_len; + #ifdef HAVE_ACCEPT4 - if (try_accept4) { - int flags = 0; -#ifdef SOCK_CLOEXEC - flags |= SOCK_CLOEXEC; -#endif + int flags = SOCK_CLOEXEC; + #ifdef SOCK_NONBLOCK - if (nonblock) { - flags |= SOCK_NONBLOCK; - } + flags |= SOCK_NONBLOCK; #endif - ret = accept4(socket, address, address_len, flags); - /* accept4 is available since Linux 2.6.28, glibc 2.10. */ - if (ret != -1) { - if (ret <= 2) - rb_maygvl_fd_fix_cloexec(ret); + + int result = accept4(socket, address, address_len, flags); + if (result == -1) return -1; + #ifndef SOCK_NONBLOCK - if (nonblock) { - rsock_make_fd_nonblock(ret); - } + rsock_make_fd_nonblock(result); #endif - if (address_len && len0 < *address_len) *address_len = len0; - return ret; - } - if (errno != ENOSYS) { - return -1; - } - try_accept4 = 0; - } +#else + int result = accept(socket, address, address_len); + if (result == -1) return -1; + + rb_maygvl_fd_fix_cloexec(result); + rsock_make_fd_nonblock(result); #endif - ret = accept(socket, address, address_len); - if (ret == -1) return -1; + if (address_len && len0 < *address_len) *address_len = len0; - rb_maygvl_fd_fix_cloexec(ret); - if (nonblock) { - rsock_make_fd_nonblock(ret); - } - return ret; + return result; } VALUE rsock_s_accept_nonblock(VALUE klass, VALUE ex, rb_io_t *fptr, - struct sockaddr *sockaddr, socklen_t *len) + struct sockaddr *sockaddr, socklen_t *len) { int fd2; rb_io_set_nonblock(fptr); - fd2 = cloexec_accept(fptr->fd, (struct sockaddr*)sockaddr, len, 1); + fd2 = cloexec_accept(fptr->fd, (struct sockaddr*)sockaddr, len); if (fd2 < 0) { - int e = errno; - switch (e) { - case EAGAIN: + int e = errno; + switch (e) { + case EAGAIN: #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN - case EWOULDBLOCK: + case EWOULDBLOCK: #endif - case ECONNABORTED: + case ECONNABORTED: #if defined EPROTO - case EPROTO: + case EPROTO: #endif if (ex == Qfalse) - return sym_wait_readable; + return sym_wait_readable; rb_readwrite_syserr_fail(RB_IO_WAIT_READABLE, e, "accept(2) would block"); - } + } rb_syserr_fail(e, "accept(2)"); } rb_update_max_fd(fd2); @@ -748,42 +704,53 @@ static VALUE accept_blocking(void *data) { struct accept_arg *arg = data; - return (VALUE)cloexec_accept(arg->fd, arg->sockaddr, arg->len, 0); + return (VALUE)cloexec_accept(arg->fd, arg->sockaddr, arg->len); } VALUE -rsock_s_accept(VALUE klass, int fd, struct sockaddr *sockaddr, socklen_t *len) +rsock_s_accept(VALUE klass, VALUE io, struct sockaddr *sockaddr, socklen_t *len) { - int fd2; - int retry = 0; - struct accept_arg arg; + rb_io_t *fptr = NULL; + RB_IO_POINTER(io, fptr); + + struct accept_arg accept_arg = { + .fd = fptr->fd, + .sockaddr = sockaddr, + .len = len + }; + + int retry = 0, peer; - arg.fd = fd; - arg.sockaddr = sockaddr; - arg.len = len; retry: - rsock_maybe_wait_fd(fd); - fd2 = (int)BLOCKING_REGION_FD(accept_blocking, &arg); - if (fd2 < 0) { - int e = errno; - switch (e) { - case EMFILE: - case ENFILE: - case ENOMEM: - if (retry) break; - rb_gc(); - retry = 1; - goto retry; - default: - if (!rb_io_wait_readable(fd)) break; - retry = 0; - goto retry; - } - rb_syserr_fail(e, "accept(2)"); +#ifdef RSOCK_WAIT_BEFORE_BLOCKING + rb_io_wait(fptr->self, RB_INT2NUM(RUBY_IO_READABLE), Qnil); +#endif + peer = (int)rb_io_blocking_region(fptr, accept_blocking, &accept_arg); + if (peer < 0) { + int error = errno; + + switch (error) { + case EMFILE: + case ENFILE: + case ENOMEM: + if (retry) break; + rb_gc(); + retry = 1; + goto retry; + default: + if (!rb_io_maybe_wait_readable(error, io, RUBY_IO_TIMEOUT_DEFAULT)) break; + retry = 0; + goto retry; + } + + rb_syserr_fail(error, "accept(2)"); } - rb_update_max_fd(fd2); - if (!klass) return INT2NUM(fd2); - return rsock_init_sock(rb_obj_alloc(klass), fd2); + + rb_update_max_fd(peer); + + if (!klass) return INT2NUM(peer); + + return rsock_init_sock(rb_obj_alloc(klass), peer); } int @@ -796,11 +763,11 @@ rsock_getfamily(rb_io_t *fptr) if (cached) { switch (cached) { #ifdef AF_UNIX - case FMODE_UNIX: return AF_UNIX; + case FMODE_UNIX: return AF_UNIX; #endif - case FMODE_INET: return AF_INET; - case FMODE_INET6: return AF_INET6; - } + case FMODE_INET: return AF_INET; + case FMODE_INET6: return AF_INET6; + } } ss.addr.sa_family = AF_UNSPEC; @@ -818,6 +785,28 @@ rsock_getfamily(rb_io_t *fptr) return ss.addr.sa_family; } +/* + * call-seq: + * error_code -> integer + * + * Returns the raw error code indicating the cause of the hostname resolution failure. + * + * begin + * Addrinfo.getaddrinfo("ruby-lang.org", nil) + * rescue Socket::ResolutionError => e + * if e.error_code == Socket::EAI_AGAIN + * puts "Temporary failure in name resolution." + * end + * end + * + * Note that error codes depend on the operating system. + */ +static VALUE +sock_resolv_error_code(VALUE self) +{ + return rb_attr_get(self, id_error_code); +} + void rsock_init_socket_init(void) { @@ -825,6 +814,11 @@ rsock_init_socket_init(void) * SocketError is the error class for socket. */ rb_eSocket = rb_define_class("SocketError", rb_eStandardError); + /* + * Socket::ResolutionError is the error class for hostname resolution. + */ + rb_eResolution = rb_define_class_under(rb_cSocket, "ResolutionError", rb_eSocket); + rb_define_method(rb_eResolution, "error_code", sock_resolv_error_code, 0); rsock_init_ipsocket(); rsock_init_tcpsocket(); rsock_init_tcpserver(); @@ -838,6 +832,8 @@ rsock_init_socket_init(void) rsock_init_sockifaddr(); rsock_init_socket_constants(); + id_error_code = rb_intern_const("error_code"); + #undef rb_intern sym_wait_readable = ID2SYM(rb_intern("wait_readable")); diff --git a/ext/socket/ipsocket.c b/ext/socket/ipsocket.c index f214d852ae..931a1a629c 100644 --- a/ext/socket/ipsocket.c +++ b/ext/socket/ipsocket.c @@ -9,62 +9,103 @@ ************************************************/ #include "rubysocket.h" +#include <stdio.h> struct inetsock_arg { - VALUE sock; + VALUE self; + VALUE io; + struct { - VALUE host, serv; - struct rb_addrinfo *res; + VALUE host, serv; + struct rb_addrinfo *res; } remote, local; int type; - int fd; + VALUE resolv_timeout; + VALUE connect_timeout; + VALUE open_timeout; }; +void +rsock_raise_user_specified_timeout(struct addrinfo *ai, VALUE host, VALUE port) +{ + VALUE message; + + if (ai && ai->ai_addr) { + VALUE rai = rsock_addrinfo_new((struct sockaddr *)ai->ai_addr, (socklen_t)ai->ai_addrlen, PF_UNSPEC, 0, 0, Qnil, Qnil); + VALUE addr_str = rsock_addrinfo_inspect_sockaddr(rai); + message = rb_sprintf("user specified timeout for %" PRIsVALUE, addr_str); + } else { + message = rb_sprintf("user specified timeout for %" PRIsVALUE " port %" PRIsVALUE, host, port); + } + + rb_raise(rb_eIOTimeoutError, "%" PRIsVALUE, message); +} + static VALUE -inetsock_cleanup(struct inetsock_arg *arg) +inetsock_cleanup(VALUE v) { + struct inetsock_arg *arg = (void *)v; if (arg->remote.res) { - rb_freeaddrinfo(arg->remote.res); - arg->remote.res = 0; + rb_freeaddrinfo(arg->remote.res); + arg->remote.res = 0; } if (arg->local.res) { - rb_freeaddrinfo(arg->local.res); - arg->local.res = 0; + rb_freeaddrinfo(arg->local.res); + arg->local.res = 0; } - if (arg->fd >= 0) { - close(arg->fd); + if (arg->io != Qnil) { + rb_io_close(arg->io); + arg->io = Qnil; } return Qnil; } static VALUE -init_inetsock_internal(struct inetsock_arg *arg) +current_clocktime(void) +{ + VALUE clock_monotnic_const = rb_const_get(rb_mProcess, rb_intern("CLOCK_MONOTONIC")); + return rb_funcall(rb_mProcess, rb_intern("clock_gettime"), 1, clock_monotnic_const); +} + +static VALUE +init_inetsock_internal(VALUE v) { + struct inetsock_arg *arg = (void *)v; int error = 0; int type = arg->type; struct addrinfo *res, *lres; - int fd, status = 0, local = 0; + int status = 0, local = 0; int family = AF_UNSPEC; const char *syscall = 0; + VALUE resolv_timeout = arg->resolv_timeout; + VALUE connect_timeout = arg->connect_timeout; + VALUE open_timeout = arg->open_timeout; + VALUE timeout; + VALUE starts_at; + + timeout = NIL_P(open_timeout) ? resolv_timeout : open_timeout; + starts_at = current_clocktime(); arg->remote.res = rsock_addrinfo(arg->remote.host, arg->remote.serv, - family, SOCK_STREAM, - (type == INET_SERVER) ? AI_PASSIVE : 0); + family, SOCK_STREAM, + (type == INET_SERVER) ? AI_PASSIVE : 0, timeout); + /* * Maybe also accept a local address */ if (type != INET_SERVER && (!NIL_P(arg->local.host) || !NIL_P(arg->local.serv))) { - arg->local.res = rsock_addrinfo(arg->local.host, arg->local.serv, - family, SOCK_STREAM, 0); + arg->local.res = rsock_addrinfo(arg->local.host, arg->local.serv, + family, SOCK_STREAM, 0, timeout); } - arg->fd = fd = -1; + VALUE io = Qnil; + for (res = arg->remote.res->ai; res; res = res->ai_next) { #if !defined(INET6) && defined(AF_INET6) - if (res->ai_family == AF_INET6) - continue; + if (res->ai_family == AF_INET6) + continue; #endif lres = NULL; if (arg->local.res) { @@ -80,85 +121,110 @@ init_inetsock_internal(struct inetsock_arg *arg) lres = arg->local.res->ai; } } - status = rsock_socket(res->ai_family,res->ai_socktype,res->ai_protocol); - syscall = "socket(2)"; - fd = status; - if (fd < 0) { - error = errno; - continue; - } - arg->fd = fd; - if (type == INET_SERVER) { + status = rsock_socket(res->ai_family,res->ai_socktype,res->ai_protocol); + syscall = "socket(2)"; + if (status < 0) { + error = errno; + continue; + } + + int fd = status; + io = arg->io = rsock_init_sock(arg->self, fd); + + if (type == INET_SERVER) { #if !defined(_WIN32) && !defined(__CYGWIN__) - status = 1; - setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, - (char*)&status, (socklen_t)sizeof(status)); + status = 1; + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, + (char*)&status, (socklen_t)sizeof(status)); #endif - status = bind(fd, res->ai_addr, res->ai_addrlen); - syscall = "bind(2)"; - } - else { - if (lres) { + status = bind(fd, res->ai_addr, res->ai_addrlen); + syscall = "bind(2)"; + } + else { + if (lres) { #if !defined(_WIN32) && !defined(__CYGWIN__) status = 1; setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&status, (socklen_t)sizeof(status)); #endif - status = bind(fd, lres->ai_addr, lres->ai_addrlen); - local = status; - syscall = "bind(2)"; - } - - if (status >= 0) { - status = rsock_connect(fd, res->ai_addr, res->ai_addrlen, - (type == INET_SOCKS)); - syscall = "connect(2)"; - } - } - - if (status < 0) { - error = errno; - close(fd); - arg->fd = fd = -1; - continue; - } else - break; + status = bind(fd, lres->ai_addr, lres->ai_addrlen); + local = status; + syscall = "bind(2)"; + } + + if (NIL_P(open_timeout)) { + timeout = connect_timeout; + } else { + VALUE elapsed = rb_funcall(current_clocktime(), '-', 1, starts_at); + timeout = rb_funcall(open_timeout, '-', 1, elapsed); + if (rb_funcall(timeout, '<', 1, INT2FIX(0)) == Qtrue) { + rsock_raise_user_specified_timeout(res, arg->remote.host, arg->remote.serv); + } + } + + if (status >= 0) { + status = rsock_connect(io, res->ai_addr, res->ai_addrlen, (type == INET_SOCKS), timeout); + syscall = "connect(2)"; + } + } + + if (status < 0) { + error = errno; + arg->io = Qnil; + rb_io_close(io); + io = Qnil; + continue; + } else { + break; + } } + if (status < 0) { - VALUE host, port; + VALUE host, port; - if (local < 0) { - host = arg->local.host; - port = arg->local.serv; - } else { - host = arg->remote.host; - port = arg->remote.serv; - } + if (local < 0) { + host = arg->local.host; + port = arg->local.serv; + } else { + host = arg->remote.host; + port = arg->remote.serv; + } - rsock_syserr_fail_host_port(error, syscall, host, port); + rsock_syserr_fail_host_port(error, syscall, host, port); } - arg->fd = -1; + // Don't close the socket in `inetsock_cleanup` if we are returning it: + arg->io = Qnil; - if (type == INET_SERVER) { - status = listen(fd, SOMAXCONN); - if (status < 0) { - error = errno; - close(fd); - rb_syserr_fail(error, "listen(2)"); - } + if (type == INET_SERVER && io != Qnil) { + status = listen(rb_io_descriptor(io), SOMAXCONN); + if (status < 0) { + error = errno; + rb_io_close(io); + rb_syserr_fail(error, "listen(2)"); + } } /* create new instance */ - return rsock_init_sock(arg->sock, fd); + return io; } +#if FAST_FALLBACK_INIT_INETSOCK_IMPL == 0 + VALUE -rsock_init_inetsock(VALUE sock, VALUE remote_host, VALUE remote_serv, - VALUE local_host, VALUE local_serv, int type) +rsock_init_inetsock( + VALUE self, VALUE remote_host, VALUE remote_serv, + VALUE local_host, VALUE local_serv, int type, + VALUE resolv_timeout, VALUE connect_timeout, VALUE open_timeout, + VALUE _fast_fallback, VALUE _test_mode_settings) { + if (!NIL_P(open_timeout) && (!NIL_P(resolv_timeout) || !NIL_P(connect_timeout))) { + rb_raise(rb_eArgError, "Cannot specify open_timeout along with connect_timeout or resolv_timeout"); + } + struct inetsock_arg arg; - arg.sock = sock; + arg.self = self; + arg.io = Qnil; arg.remote.host = remote_host; arg.remote.serv = remote_serv; arg.remote.res = 0; @@ -166,11 +232,1205 @@ rsock_init_inetsock(VALUE sock, VALUE remote_host, VALUE remote_serv, arg.local.serv = local_serv; arg.local.res = 0; arg.type = type; - arg.fd = -1; + arg.resolv_timeout = resolv_timeout; + arg.connect_timeout = connect_timeout; + arg.open_timeout = open_timeout; return rb_ensure(init_inetsock_internal, (VALUE)&arg, - inetsock_cleanup, (VALUE)&arg); + inetsock_cleanup, (VALUE)&arg); +} + +#elif FAST_FALLBACK_INIT_INETSOCK_IMPL == 1 + +#define IPV6_ENTRY_POS 0 +#define IPV4_ENTRY_POS 1 +#define RESOLUTION_ERROR 0 +#define SYSCALL_ERROR 1 + +static int +is_specified_ip_address(const char *hostname) +{ + if (!hostname) return false; + + struct in_addr ipv4addr; + struct in6_addr ipv6addr; + + return (inet_pton(AF_INET6, hostname, &ipv6addr) == 1 || + inet_pton(AF_INET, hostname, &ipv4addr) == 1); +} + +static int +is_local_port_fixed(const char *portp) +{ + if (!portp) return 0; + + char *endp; + errno = 0; + long port = strtol(portp, &endp, 10); + + if (endp == portp) return 0; + if (errno == ERANGE) return 0; + + return port > 0; +} + +struct fast_fallback_inetsock_arg +{ + VALUE self; + VALUE io; + + struct { + VALUE host, serv; + struct rb_addrinfo *res; + } remote, local; + int type; + VALUE resolv_timeout; + VALUE connect_timeout; + VALUE open_timeout; + + const char *hostp, *portp; + int *families; + int family_size; + int additional_flags; + struct fast_fallback_getaddrinfo_entry *getaddrinfo_entries[2]; + struct fast_fallback_getaddrinfo_shared *getaddrinfo_shared; + rb_fdset_t readfds, writefds; + int wait; + int connection_attempt_fds_size; + int *connection_attempt_fds; + VALUE test_mode_settings; +}; + +static struct fast_fallback_getaddrinfo_shared * +allocate_fast_fallback_getaddrinfo_shared(int family_size) +{ + struct fast_fallback_getaddrinfo_shared *shared; + + shared = (struct fast_fallback_getaddrinfo_shared *)calloc( + 1, + sizeof(struct fast_fallback_getaddrinfo_shared) + (family_size == 1 ? 0 : 2) * sizeof(struct fast_fallback_getaddrinfo_entry) + ); + + return shared; +} + +static void +allocate_fast_fallback_getaddrinfo_hints(struct addrinfo *hints, int family, int remote_addrinfo_hints, int additional_flags) +{ + MEMZERO(hints, struct addrinfo, 1); + hints->ai_family = family; + hints->ai_socktype = SOCK_STREAM; + hints->ai_protocol = IPPROTO_TCP; + hints->ai_flags = remote_addrinfo_hints; + hints->ai_flags |= additional_flags; +} + +static int* +allocate_connection_attempt_fds(int additional_capacity) +{ + int *fds = (int *)malloc(additional_capacity * sizeof(int)); + if (!fds) rb_syserr_fail(errno, "malloc(3)"); + for (int i = 0; i < additional_capacity; i++) fds[i] = -1; + return fds; +} + +static int +reallocate_connection_attempt_fds(int **fds, int current_capacity, int additional_capacity) +{ + int new_capacity = current_capacity + additional_capacity; + int *new_fds; + + new_fds = realloc(*fds, new_capacity * sizeof(int)); + if (new_fds == NULL) { + rb_syserr_fail(errno, "realloc(3)"); + } + *fds = new_fds; + + for (int i = current_capacity; i < new_capacity; i++) (*fds)[i] = -1; + return new_capacity; +} + +struct hostname_resolution_result +{ + struct addrinfo *ai; + int finished; + int has_error; +}; + +struct hostname_resolution_store +{ + struct hostname_resolution_result v6; + struct hostname_resolution_result v4; + int is_all_finished; +}; + +static int +any_addrinfos(struct hostname_resolution_store *resolution_store) +{ + return resolution_store->v6.ai || resolution_store->v4.ai; +} + +static struct timespec +current_clocktime_ts(void) +{ + struct timespec ts; + if ((clock_gettime(CLOCK_MONOTONIC, &ts)) < 0) { + rb_syserr_fail(errno, "clock_gettime(2)"); + } + return ts; +} + +static void +set_timeout_tv(struct timeval *tv, long ms, struct timespec from) +{ + long sec = ms / 1000; + long nsec = (ms % 1000) * 1000000; + long result_sec = from.tv_sec + sec; + long result_nsec = from.tv_nsec + nsec; + + result_sec += result_nsec / 1000000000; + result_nsec = result_nsec % 1000000000; + + tv->tv_sec = result_sec; + tv->tv_usec = (int)(result_nsec / 1000); +} + +static struct timeval +add_ts_to_tv(struct timeval tv, struct timespec ts) +{ + long ts_usec = ts.tv_nsec / 1000; + tv.tv_sec += ts.tv_sec; + tv.tv_usec += ts_usec; + + if (tv.tv_usec >= 1000000) { + tv.tv_sec += tv.tv_usec / 1000000; + tv.tv_usec = tv.tv_usec % 1000000; + } + + return tv; +} + +static VALUE +tv_to_seconds(struct timeval *timeout) { + if (timeout == NULL) return Qnil; + + double seconds = (double)timeout->tv_sec + (double)timeout->tv_usec / 1000000.0; + + return DBL2NUM(seconds); +} + +static int +is_infinity(struct timeval tv) +{ + // { -1, -1 } as infinity + return tv.tv_sec == -1 || tv.tv_usec == -1; +} + +static int +is_timeout_tv(struct timeval *timeout_tv, struct timespec now) { + if (!timeout_tv) return false; + if (timeout_tv->tv_sec == -1 && timeout_tv->tv_usec == -1) return false; + + struct timespec ts; + ts.tv_sec = timeout_tv->tv_sec; + ts.tv_nsec = timeout_tv->tv_usec * 1000; + + if (now.tv_sec > ts.tv_sec) return true; + if (now.tv_sec == ts.tv_sec && now.tv_nsec >= ts.tv_nsec) return true; + return false; +} + +static struct timeval * +select_expires_at( + struct hostname_resolution_store *resolution_store, + struct timeval *resolution_delay, + struct timeval *connection_attempt_delay, + struct timeval *user_specified_resolv_timeout_at, + struct timeval *user_specified_connect_timeout_at, + struct timeval *user_specified_open_timeout_at) +{ + if (any_addrinfos(resolution_store)) { + struct timeval *delay; + delay = resolution_delay ? resolution_delay : connection_attempt_delay; + + if (user_specified_open_timeout_at && + timercmp(user_specified_open_timeout_at, delay, <)) { + return user_specified_open_timeout_at; + } + return delay; + } + + if (user_specified_open_timeout_at) return user_specified_open_timeout_at; + + struct timeval *timeout = NULL; + + if (user_specified_resolv_timeout_at) { + if (is_infinity(*user_specified_resolv_timeout_at)) return NULL; + timeout = user_specified_resolv_timeout_at; + } + + if (user_specified_connect_timeout_at) { + if (is_infinity(*user_specified_connect_timeout_at)) return NULL; + if (!timeout || timercmp(user_specified_connect_timeout_at, timeout, >)) { + return user_specified_connect_timeout_at; + } + } + + return timeout; } +static struct timeval +tv_to_timeout(struct timeval *ends_at, struct timespec now) +{ + struct timeval delay; + struct timespec expires_at; + expires_at.tv_sec = ends_at->tv_sec; + expires_at.tv_nsec = ends_at->tv_usec * 1000; + + struct timespec diff; + diff.tv_sec = expires_at.tv_sec - now.tv_sec; + + if (expires_at.tv_nsec >= now.tv_nsec) { + diff.tv_nsec = expires_at.tv_nsec - now.tv_nsec; + } else { + diff.tv_sec -= 1; + diff.tv_nsec = (1000000000 + expires_at.tv_nsec) - now.tv_nsec; + } + + delay.tv_sec = diff.tv_sec; + delay.tv_usec = (int)diff.tv_nsec / 1000; + + return delay; +} + +static struct addrinfo * +pick_addrinfo(struct hostname_resolution_store *resolution_store, int last_family) +{ + int priority_on_v6[2] = { AF_INET6, AF_INET }; + int priority_on_v4[2] = { AF_INET, AF_INET6 }; + int *precedences = last_family == AF_INET6 ? priority_on_v4 : priority_on_v6; + struct addrinfo *selected_ai = NULL; + + for (int i = 0; i < 2; i++) { + if (precedences[i] == AF_INET6) { + selected_ai = resolution_store->v6.ai; + if (selected_ai) { + resolution_store->v6.ai = selected_ai->ai_next; + break; + } + } else { + selected_ai = resolution_store->v4.ai; + if (selected_ai) { + resolution_store->v4.ai = selected_ai->ai_next; + break; + } + } + } + return selected_ai; +} + +static void +socket_nonblock_set(int fd) +{ + int flags = fcntl(fd, F_GETFL); + + if (flags < 0) rb_syserr_fail(errno, "fcntl(2)"); + if ((flags & O_NONBLOCK) != 0) return; + + flags |= O_NONBLOCK; + + if (fcntl(fd, F_SETFL, flags) < 0) rb_syserr_fail(errno, "fcntl(2)"); + return; +} + +static int +in_progress_fds(int fds_size) +{ + return fds_size > 0; +} + +static void +remove_connection_attempt_fd(int *fds, int *fds_size, int removing_fd) +{ + int i, j; + + for (i = 0; i < *fds_size; i++) { + if (fds[i] != removing_fd) continue; + + for (j = i; j < *fds_size - 1; j++) { + fds[j] = fds[j + 1]; + } + + (*fds_size)--; + fds[*fds_size] = -1; + break; + } +} + +struct fast_fallback_error +{ + int type; + int ecode; +}; + +static VALUE +init_fast_fallback_inetsock_internal(VALUE v) +{ + struct fast_fallback_inetsock_arg *arg = (void *)v; + VALUE io = arg->io; + VALUE resolv_timeout = arg->resolv_timeout; + VALUE connect_timeout = arg->connect_timeout; + VALUE open_timeout = arg->open_timeout; + VALUE test_mode_settings = arg->test_mode_settings; + struct addrinfo *remote_ai = NULL, *local_ai = NULL; + int connected_fd = -1, status = 0, local_status = 0; + int remote_addrinfo_hints = 0; + struct fast_fallback_error last_error = { 0, 0 }; + const char *syscall = 0; + VALUE host, serv; + + #ifdef HAVE_CONST_AI_ADDRCONFIG + remote_addrinfo_hints |= AI_ADDRCONFIG; + #endif + + pthread_t threads[arg->family_size]; + char resolved_type[2]; + ssize_t resolved_type_size; + int hostname_resolution_waiter = -1, hostname_resolution_notifier = -1; + int pipefd[2]; + + int nfds = 0; + struct timeval *ends_at = NULL; + struct timeval delay = (struct timeval){ -1, -1 }; + struct timeval *delay_p = NULL; + + struct hostname_resolution_store resolution_store; + resolution_store.is_all_finished = false; + resolution_store.v6.ai = NULL; + resolution_store.v6.finished = false; + resolution_store.v6.has_error = false; + resolution_store.v4.ai = NULL; + resolution_store.v4.finished = false; + resolution_store.v4.has_error = false; + + int last_family = 0; + int additional_capacity = 10; + int current_capacity = additional_capacity; + arg->connection_attempt_fds = allocate_connection_attempt_fds(additional_capacity); + arg->connection_attempt_fds_size = 0; + + struct timeval resolution_delay_storage; + struct timeval *resolution_delay_expires_at = NULL; + struct timeval connection_attempt_delay_strage; + struct timeval *connection_attempt_delay_expires_at = NULL; + struct timeval user_specified_resolv_timeout_storage; + struct timeval *user_specified_resolv_timeout_at = NULL; + struct timeval user_specified_connect_timeout_storage; + struct timeval *user_specified_connect_timeout_at = NULL; + struct timeval user_specified_open_timeout_storage; + struct timeval *user_specified_open_timeout_at = NULL; + struct timespec now = current_clocktime_ts(); + VALUE starts_at = current_clocktime(); + + if (!NIL_P(open_timeout)) { + struct timeval open_timeout_tv = rb_time_interval(open_timeout); + user_specified_open_timeout_storage = add_ts_to_tv(open_timeout_tv, now); + user_specified_open_timeout_at = &user_specified_open_timeout_storage; + } + + /* start of hostname resolution */ + if (arg->family_size == 1) { + arg->wait = -1; + arg->getaddrinfo_shared = NULL; + + int family = arg->families[0]; + VALUE t = NIL_P(open_timeout) ? resolv_timeout : open_timeout; + + arg->remote.res = rsock_addrinfo( + arg->remote.host, + arg->remote.serv, + family, + SOCK_STREAM, + 0, + t + ); + + if (family == AF_INET6) { + resolution_store.v6.ai = arg->remote.res->ai; + resolution_store.v6.finished = true; + resolution_store.v4.finished = true; + } else if (family == AF_INET) { + resolution_store.v4.ai = arg->remote.res->ai; + resolution_store.v4.finished = true; + resolution_store.v6.finished = true; + } + resolution_store.is_all_finished = true; + } else { + if (pipe(pipefd) != 0) rb_syserr_fail(errno, "pipe(2)"); + hostname_resolution_waiter = pipefd[0]; + int waiter_flags = fcntl(hostname_resolution_waiter, F_GETFL, 0); + if (waiter_flags < 0) rb_syserr_fail(errno, "fcntl(2)"); + if ((fcntl(hostname_resolution_waiter, F_SETFL, waiter_flags | O_NONBLOCK)) < 0) { + rb_syserr_fail(errno, "fcntl(2)"); + } + arg->wait = hostname_resolution_waiter; + hostname_resolution_notifier = pipefd[1]; + + arg->getaddrinfo_shared = allocate_fast_fallback_getaddrinfo_shared(arg->family_size); + if (!arg->getaddrinfo_shared) rb_syserr_fail(errno, "calloc(3)"); + + rb_nativethread_lock_initialize(&arg->getaddrinfo_shared->lock); + arg->getaddrinfo_shared->notify = hostname_resolution_notifier; + + arg->getaddrinfo_shared->node = arg->hostp ? ruby_strdup(arg->hostp) : NULL; + arg->getaddrinfo_shared->service = arg->portp ? ruby_strdup(arg->portp) : NULL; + arg->getaddrinfo_shared->refcount = arg->family_size + 1; + + for (int i = 0; i < arg->family_size; i++) { + arg->getaddrinfo_entries[i] = &arg->getaddrinfo_shared->getaddrinfo_entries[i]; + arg->getaddrinfo_entries[i]->shared = arg->getaddrinfo_shared; + + struct addrinfo getaddrinfo_hints[arg->family_size]; + + allocate_fast_fallback_getaddrinfo_hints( + &getaddrinfo_hints[i], + arg->families[i], + remote_addrinfo_hints, + arg->additional_flags + ); + + arg->getaddrinfo_entries[i]->hints = getaddrinfo_hints[i]; + arg->getaddrinfo_entries[i]->ai = NULL; + arg->getaddrinfo_entries[i]->family = arg->families[i]; + arg->getaddrinfo_entries[i]->refcount = 2; + arg->getaddrinfo_entries[i]->has_syserr = false; + arg->getaddrinfo_entries[i]->test_sleep_ms = 0; + arg->getaddrinfo_entries[i]->test_ecode = 0; + + /* for testing HEv2 */ + if (!NIL_P(test_mode_settings) && RB_TYPE_P(test_mode_settings, T_HASH)) { + const char *family_sym = arg->families[i] == AF_INET6 ? "ipv6" : "ipv4"; + + VALUE test_delay_setting = rb_hash_aref(test_mode_settings, ID2SYM(rb_intern("delay"))); + if (!NIL_P(test_delay_setting)) { + VALUE rb_test_delay_ms = rb_hash_aref(test_delay_setting, ID2SYM(rb_intern(family_sym))); + long test_delay_ms = NIL_P(rb_test_delay_ms) ? 0 : rb_test_delay_ms; + arg->getaddrinfo_entries[i]->test_sleep_ms = test_delay_ms; + } + + VALUE test_error_setting = rb_hash_aref(test_mode_settings, ID2SYM(rb_intern("error"))); + if (!NIL_P(test_error_setting)) { + VALUE rb_test_ecode = rb_hash_aref(test_error_setting, ID2SYM(rb_intern(family_sym))); + if (!NIL_P(rb_test_ecode)) { + arg->getaddrinfo_entries[i]->test_ecode = NUM2INT(rb_test_ecode); + } + } + } + + if (raddrinfo_pthread_create(&threads[i], fork_safe_do_fast_fallback_getaddrinfo, arg->getaddrinfo_entries[i]) != 0) { + rsock_raise_resolution_error("getaddrinfo(3)", EAI_AGAIN); + } + } + + if (NIL_P(resolv_timeout)) { + user_specified_resolv_timeout_storage = (struct timeval){ -1, -1 }; + } else { + struct timeval resolv_timeout_tv = rb_time_interval(resolv_timeout); + user_specified_resolv_timeout_storage = add_ts_to_tv(resolv_timeout_tv, now); + } + user_specified_resolv_timeout_at = &user_specified_resolv_timeout_storage; + } + + while (true) { + /* start of connection */ + if (any_addrinfos(&resolution_store) && + !resolution_delay_expires_at && + !connection_attempt_delay_expires_at) { + while ((remote_ai = pick_addrinfo(&resolution_store, last_family))) { + int fd = -1; + + #if !defined(INET6) && defined(AF_INET6) + if (remote_ai->ai_family == AF_INET6) { + if (any_addrinfos(&resolution_store)) continue; + if (!in_progress_fds(arg->connection_attempt_fds_size)) break; + if (resolution_store.is_all_finished) break; + + if (local_status < 0) { + host = arg->local.host; + serv = arg->local.serv; + } else { + host = arg->remote.host; + serv = arg->remote.serv; + } + if (last_error.type == RESOLUTION_ERROR) { + rsock_raise_resolution_error(syscall, last_error.ecode); + } else { + rsock_syserr_fail_host_port(last_error.ecode, syscall, host, serv); + } + } + #endif + + local_ai = NULL; + + if (arg->local.res) { + for (local_ai = arg->local.res->ai; local_ai; local_ai = local_ai->ai_next) { + if (local_ai->ai_family == remote_ai->ai_family) break; + } + if (!local_ai) { + if (any_addrinfos(&resolution_store)) continue; + if (in_progress_fds(arg->connection_attempt_fds_size)) break; + if (!resolution_store.is_all_finished) break; + + /* Use a different family local address if no choice, this + * will cause EAFNOSUPPORT. */ + rsock_syserr_fail_host_port(EAFNOSUPPORT, syscall, arg->local.host, arg->local.serv); + } + } + + status = rsock_socket(remote_ai->ai_family, remote_ai->ai_socktype, remote_ai->ai_protocol); + syscall = "socket(2)"; + + if (status < 0) { + last_error.type = SYSCALL_ERROR; + last_error.ecode = errno; + + if (any_addrinfos(&resolution_store)) continue; + if (in_progress_fds(arg->connection_attempt_fds_size)) break; + if (!resolution_store.is_all_finished) break; + + if (local_status < 0) { + host = arg->local.host; + serv = arg->local.serv; + } else { + host = arg->remote.host; + serv = arg->remote.serv; + } + if (last_error.type == RESOLUTION_ERROR) { + rsock_raise_resolution_error(syscall, last_error.ecode); + } else { + rsock_syserr_fail_host_port(last_error.ecode, syscall, host, serv); + } + } + + fd = status; + + if (local_ai) { + #if !defined(_WIN32) && !defined(__CYGWIN__) + status = 1; + if ((setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&status, (socklen_t)sizeof(status))) < 0) { + rb_syserr_fail(errno, "setsockopt(2)"); + } + #endif + status = bind(fd, local_ai->ai_addr, local_ai->ai_addrlen); + local_status = status; + syscall = "bind(2)"; + + if (status < 0) { + last_error.type = SYSCALL_ERROR; + last_error.ecode = errno; + close(fd); + + if (any_addrinfos(&resolution_store)) continue; + if (in_progress_fds(arg->connection_attempt_fds_size)) break; + if (!resolution_store.is_all_finished) break; + + if (local_status < 0) { + host = arg->local.host; + serv = arg->local.serv; + } else { + host = arg->remote.host; + serv = arg->remote.serv; + } + if (last_error.type == RESOLUTION_ERROR) { + rsock_raise_resolution_error(syscall, last_error.ecode); + } else { + rsock_syserr_fail_host_port(last_error.ecode, syscall, host, serv); + } + } + } + + syscall = "connect(2)"; + + if (any_addrinfos(&resolution_store) || + in_progress_fds(arg->connection_attempt_fds_size) || + !resolution_store.is_all_finished) { + socket_nonblock_set(fd); + status = connect(fd, remote_ai->ai_addr, remote_ai->ai_addrlen); + last_family = remote_ai->ai_family; + } else { + VALUE timeout = Qnil; + + if (!NIL_P(open_timeout)) { + VALUE elapsed = rb_funcall(current_clocktime(), '-', 1, starts_at); + timeout = rb_funcall(open_timeout, '-', 1, elapsed); + + if (rb_funcall(timeout, '<', 1, INT2FIX(0)) == Qtrue) { + rsock_raise_user_specified_timeout(NULL, arg->remote.host, arg->remote.serv); + } + } + if (NIL_P(timeout)) { + if (!NIL_P(connect_timeout)) { + user_specified_connect_timeout_storage = rb_time_interval(connect_timeout); + user_specified_connect_timeout_at = &user_specified_connect_timeout_storage; + } + timeout = + (user_specified_connect_timeout_at && is_infinity(*user_specified_connect_timeout_at)) ? + Qnil : tv_to_seconds(user_specified_connect_timeout_at); + } + + io = arg->io = rsock_init_sock(arg->self, fd); + status = rsock_connect(io, remote_ai->ai_addr, remote_ai->ai_addrlen, 0, timeout); + } + + if (status == 0) { + connected_fd = fd; + break; + } + + if (errno == EINPROGRESS) { + if (current_capacity == arg->connection_attempt_fds_size) { + current_capacity = reallocate_connection_attempt_fds( + &arg->connection_attempt_fds, + current_capacity, + additional_capacity + ); + } + arg->connection_attempt_fds[arg->connection_attempt_fds_size] = fd; + (arg->connection_attempt_fds_size)++; + + set_timeout_tv(&connection_attempt_delay_strage, 250, now); + connection_attempt_delay_expires_at = &connection_attempt_delay_strage; + + if (!any_addrinfos(&resolution_store)) { + if (NIL_P(connect_timeout)) { + user_specified_connect_timeout_storage = (struct timeval){ -1, -1 }; + } else { + struct timeval connect_timeout_tv = rb_time_interval(connect_timeout); + user_specified_connect_timeout_storage = add_ts_to_tv(connect_timeout_tv, now); + } + user_specified_connect_timeout_at = &user_specified_connect_timeout_storage; + } + + break; + } + + last_error.type = SYSCALL_ERROR; + last_error.ecode = errno; + + if (NIL_P(io)) { + close(fd); + } else { + rb_io_close(io); + } + + if (any_addrinfos(&resolution_store)) continue; + if (in_progress_fds(arg->connection_attempt_fds_size)) break; + if (!resolution_store.is_all_finished) break; + + if (local_status < 0) { + host = arg->local.host; + serv = arg->local.serv; + } else { + host = arg->remote.host; + serv = arg->remote.serv; + } + if (last_error.type == RESOLUTION_ERROR) { + rsock_raise_resolution_error(syscall, last_error.ecode); + } else { + rsock_syserr_fail_host_port(last_error.ecode, syscall, host, serv); + } + } + } + + if (connected_fd >= 0) break; + + ends_at = select_expires_at( + &resolution_store, + resolution_delay_expires_at, + connection_attempt_delay_expires_at, + user_specified_resolv_timeout_at, + user_specified_connect_timeout_at, + user_specified_open_timeout_at + ); + if (ends_at) { + delay = tv_to_timeout(ends_at, now); + delay_p = &delay; + } else { + if (((resolution_store.v6.finished && !resolution_store.v4.finished) || + (resolution_store.v4.finished && !resolution_store.v6.finished)) && + !any_addrinfos(&resolution_store) && + !in_progress_fds(arg->connection_attempt_fds_size)) { + /* A limited timeout is introduced to prevent select(2) from hanging when it is exclusively + * waiting for name resolution and write(2) failure occurs in a child thread. */ + delay.tv_sec = 0; + delay.tv_usec = 50000; + delay_p = &delay; + } else { + delay_p = NULL; + } + } + + nfds = 0; + rb_fd_zero(&arg->writefds); + if (in_progress_fds(arg->connection_attempt_fds_size)) { + int n = 0; + for (int i = 0; i < arg->connection_attempt_fds_size; i++) { + int cfd = arg->connection_attempt_fds[i]; + if (cfd < 0) continue; + if (cfd > n) n = cfd; + rb_fd_set(cfd, &arg->writefds); + } + if (n > 0) n++; + nfds = n; + } + + rb_fd_zero(&arg->readfds); + if (arg->family_size > 1) { + rb_fd_set(hostname_resolution_waiter, &arg->readfds); + + if ((hostname_resolution_waiter + 1) > nfds) { + nfds = hostname_resolution_waiter + 1; + } + } + + status = rb_thread_fd_select(nfds, &arg->readfds, &arg->writefds, NULL, delay_p); + + now = current_clocktime_ts(); + if (is_timeout_tv(resolution_delay_expires_at, now)) { + resolution_delay_expires_at = NULL; + } + if (is_timeout_tv(connection_attempt_delay_expires_at, now)) { + connection_attempt_delay_expires_at = NULL; + } + + if (status < 0 && (errno && errno != EINTR)) rb_syserr_fail(errno, "select(2)"); + + if (status > 0) { + /* check for connection */ + if (in_progress_fds(arg->connection_attempt_fds_size)) { + for (int i = 0; i < arg->connection_attempt_fds_size; i++) { + int fd = arg->connection_attempt_fds[i]; + if (fd < 0 || !rb_fd_isset(fd, &arg->writefds)) continue; + + int err; + socklen_t len = sizeof(err); + + status = getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &len); + + if (status < 0) { + last_error.type = SYSCALL_ERROR; + last_error.ecode = errno; + close(fd); + + if (any_addrinfos(&resolution_store)) continue; + if (in_progress_fds(arg->connection_attempt_fds_size)) break; + if (!resolution_store.is_all_finished) break; + + if (local_status < 0) { + host = arg->local.host; + serv = arg->local.serv; + } else { + host = arg->remote.host; + serv = arg->remote.serv; + } + if (last_error.type == RESOLUTION_ERROR) { + rsock_raise_resolution_error(syscall, last_error.ecode); + } else { + rsock_syserr_fail_host_port(last_error.ecode, syscall, host, serv); + } + } + + if (err == 0) { /* success */ + remove_connection_attempt_fd( + arg->connection_attempt_fds, + &arg->connection_attempt_fds_size, + fd + ); + connected_fd = fd; + break; + } else { /* fail */ + close(fd); + remove_connection_attempt_fd( + arg->connection_attempt_fds, + &arg->connection_attempt_fds_size, + fd + ); + last_error.type = SYSCALL_ERROR; + last_error.ecode = err; + } + } + + if (connected_fd >= 0) break; + + if (!in_progress_fds(arg->connection_attempt_fds_size)) { + if (!any_addrinfos(&resolution_store) && resolution_store.is_all_finished) { + if (local_status < 0) { + host = arg->local.host; + serv = arg->local.serv; + } else { + host = arg->remote.host; + serv = arg->remote.serv; + } + if (last_error.type == RESOLUTION_ERROR) { + rsock_raise_resolution_error(syscall, last_error.ecode); + } else { + rsock_syserr_fail_host_port(last_error.ecode, syscall, host, serv); + } + } + connection_attempt_delay_expires_at = NULL; + user_specified_connect_timeout_at = NULL; + } + } + + /* check for hostname resolution */ + if (!resolution_store.is_all_finished && rb_fd_isset(hostname_resolution_waiter, &arg->readfds)) { + while (true) { + resolved_type_size = read( + hostname_resolution_waiter, + resolved_type, + sizeof(resolved_type) - 1 + ); + + if (resolved_type_size > 0) { + resolved_type[resolved_type_size] = '\0'; + + if (resolved_type[0] == IPV6_HOSTNAME_RESOLVED) { + resolution_store.v6.finished = true; + + if (arg->getaddrinfo_entries[IPV6_ENTRY_POS]->err && + arg->getaddrinfo_entries[IPV6_ENTRY_POS]->err != EAI_ADDRFAMILY) { + if (!resolution_store.v4.finished || resolution_store.v4.has_error) { + last_error.type = RESOLUTION_ERROR; + last_error.ecode = arg->getaddrinfo_entries[IPV6_ENTRY_POS]->err; + syscall = "getaddrinfo(3)"; + } + resolution_store.v6.has_error = true; + } else { + resolution_store.v6.ai = arg->getaddrinfo_entries[IPV6_ENTRY_POS]->ai; + } + if (resolution_store.v4.finished) { + resolution_store.is_all_finished = true; + resolution_delay_expires_at = NULL; + user_specified_resolv_timeout_at = NULL; + break; + } + } else if (resolved_type[0] == IPV4_HOSTNAME_RESOLVED) { + resolution_store.v4.finished = true; + + if (arg->getaddrinfo_entries[IPV4_ENTRY_POS]->err) { + if (!resolution_store.v6.finished || resolution_store.v6.has_error) { + last_error.type = RESOLUTION_ERROR; + last_error.ecode = arg->getaddrinfo_entries[IPV4_ENTRY_POS]->err; + syscall = "getaddrinfo(3)"; + } + resolution_store.v4.has_error = true; + } else { + resolution_store.v4.ai = arg->getaddrinfo_entries[IPV4_ENTRY_POS]->ai; + } + + if (resolution_store.v6.finished) { + resolution_store.is_all_finished = true; + resolution_delay_expires_at = NULL; + user_specified_resolv_timeout_at = NULL; + break; + } + } else { + /* Retry to read from hostname_resolution_waiter */ + } + } else if (resolved_type_size < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) { + errno = 0; + break; + } else { + /* Retry to read from hostname_resolution_waiter */ + } + + if (!resolution_store.v6.finished && + resolution_store.v4.finished && + !resolution_store.v4.has_error) { + set_timeout_tv(&resolution_delay_storage, 50, now); + resolution_delay_expires_at = &resolution_delay_storage; + } + } + } + + status = 0; + } + + /* For cases where write(2) fails in child threads */ + if (!resolution_store.is_all_finished) { + if (!resolution_store.v6.finished && arg->getaddrinfo_entries[IPV6_ENTRY_POS]->has_syserr) { + resolution_store.v6.finished = true; + + if (arg->getaddrinfo_entries[IPV6_ENTRY_POS]->err) { + if (!resolution_store.v4.finished || resolution_store.v4.has_error) { + last_error.type = RESOLUTION_ERROR; + last_error.ecode = arg->getaddrinfo_entries[IPV6_ENTRY_POS]->err; + syscall = "getaddrinfo(3)"; + } + resolution_store.v6.has_error = true; + } else { + resolution_store.v6.ai = arg->getaddrinfo_entries[IPV6_ENTRY_POS]->ai; + } + + if (resolution_store.v4.finished) { + resolution_store.is_all_finished = true; + resolution_delay_expires_at = NULL; + user_specified_resolv_timeout_at = NULL; + } + } + if (!resolution_store.v4.finished && arg->getaddrinfo_entries[IPV4_ENTRY_POS]->has_syserr) { + resolution_store.v4.finished = true; + + if (arg->getaddrinfo_entries[IPV4_ENTRY_POS]->err) { + if (!resolution_store.v6.finished || resolution_store.v6.has_error) { + last_error.type = RESOLUTION_ERROR; + last_error.ecode = arg->getaddrinfo_entries[IPV4_ENTRY_POS]->err; + syscall = "getaddrinfo(3)"; + } + resolution_store.v4.has_error = true; + } else { + resolution_store.v4.ai = arg->getaddrinfo_entries[IPV4_ENTRY_POS]->ai; + } + + if (resolution_store.v6.finished) { + resolution_store.is_all_finished = true; + resolution_delay_expires_at = NULL; + user_specified_resolv_timeout_at = NULL; + } else { + set_timeout_tv(&resolution_delay_storage, 50, now); + resolution_delay_expires_at = &resolution_delay_storage; + } + } + } + + if (is_timeout_tv(user_specified_open_timeout_at, now)) { + rsock_raise_user_specified_timeout(NULL, arg->remote.host, arg->remote.serv); + } + + if (!any_addrinfos(&resolution_store)) { + if (!in_progress_fds(arg->connection_attempt_fds_size) && + resolution_store.is_all_finished) { + if (local_status < 0) { + host = arg->local.host; + serv = arg->local.serv; + } else { + host = arg->remote.host; + serv = arg->remote.serv; + } + if (last_error.type == RESOLUTION_ERROR) { + rsock_raise_resolution_error(syscall, last_error.ecode); + } else { + rsock_syserr_fail_host_port(last_error.ecode, syscall, host, serv); + } + } + + if ((is_timeout_tv(user_specified_resolv_timeout_at, now) || + resolution_store.is_all_finished) && + (is_timeout_tv(user_specified_connect_timeout_at, now) || + !in_progress_fds(arg->connection_attempt_fds_size))) { + rsock_raise_user_specified_timeout(NULL, arg->remote.host, arg->remote.serv); + } + } + } + + if (NIL_P(arg->io)) { + /* create new instance */ + arg->io = rsock_init_sock(arg->self, connected_fd); + } + + return arg->io; +} + +static VALUE +fast_fallback_inetsock_cleanup(VALUE v) +{ + struct fast_fallback_inetsock_arg *arg = (void *)v; + struct fast_fallback_getaddrinfo_shared *getaddrinfo_shared = arg->getaddrinfo_shared; + + if (arg->remote.res) { + rb_freeaddrinfo(arg->remote.res); + arg->remote.res = 0; + } + if (arg->local.res) { + rb_freeaddrinfo(arg->local.res); + arg->local.res = 0; + } + + if (arg->wait != -1) close(arg->wait); + + if (getaddrinfo_shared) { + if (getaddrinfo_shared->notify != -1) close(getaddrinfo_shared->notify); + getaddrinfo_shared->notify = -1; + + int shared_need_free = 0; + struct addrinfo *ais[arg->family_size]; + for (int i = 0; i < arg->family_size; i++) ais[i] = NULL; + + rb_nativethread_lock_lock(&getaddrinfo_shared->lock); + { + for (int i = 0; i < arg->family_size; i++) { + struct fast_fallback_getaddrinfo_entry *getaddrinfo_entry = arg->getaddrinfo_entries[i]; + + if (!getaddrinfo_entry) continue; + + if (--(getaddrinfo_entry->refcount) == 0) { + ais[i] = getaddrinfo_entry->ai; + getaddrinfo_entry->ai = NULL; + } + } + if (--(getaddrinfo_shared->refcount) == 0) { + shared_need_free = 1; + } + } + rb_nativethread_lock_unlock(&getaddrinfo_shared->lock); + + for (int i = 0; i < arg->family_size; i++) { + if (ais[i]) freeaddrinfo(ais[i]); + } + if (getaddrinfo_shared && shared_need_free) { + free_fast_fallback_getaddrinfo_shared(&getaddrinfo_shared); + } + } + + int connection_attempt_fd; + + for (int i = 0; i < arg->connection_attempt_fds_size; i++) { + connection_attempt_fd = arg->connection_attempt_fds[i]; + + if (connection_attempt_fd >= 0) { + int error = 0; + socklen_t len = sizeof(error); + getsockopt(connection_attempt_fd, SOL_SOCKET, SO_ERROR, &error, &len); + if (error == 0) shutdown(connection_attempt_fd, SHUT_RDWR); + close(connection_attempt_fd); + } + } + + if (arg->readfds.fdset) rb_fd_term(&arg->readfds); + if (arg->writefds.fdset) rb_fd_term(&arg->writefds); + + if (arg->connection_attempt_fds) { + free(arg->connection_attempt_fds); + arg->connection_attempt_fds = NULL; + } + + return Qnil; +} + +VALUE +rsock_init_inetsock( + VALUE self, VALUE remote_host, VALUE remote_serv, + VALUE local_host, VALUE local_serv, int type, + VALUE resolv_timeout, VALUE connect_timeout, VALUE open_timeout, + VALUE fast_fallback, VALUE test_mode_settings) +{ + if (!NIL_P(open_timeout) && (!NIL_P(resolv_timeout) || !NIL_P(connect_timeout))) { + rb_raise(rb_eArgError, "Cannot specify open_timeout along with connect_timeout or resolv_timeout"); + } + + if (type == INET_CLIENT && FAST_FALLBACK_INIT_INETSOCK_IMPL == 1 && RTEST(fast_fallback)) { + struct rb_addrinfo *local_res = NULL; + char *hostp, *portp, *local_portp; + char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV], local_pbuf[NI_MAXSERV]; + int additional_flags = 0; + int local_flags = 0; + hostp = raddrinfo_host_str(remote_host, hbuf, sizeof(hbuf), &additional_flags); + portp = raddrinfo_port_str(remote_serv, pbuf, sizeof(pbuf), &additional_flags); + local_portp = raddrinfo_port_str(local_serv, local_pbuf, sizeof(local_pbuf), &local_flags); + + if (!is_specified_ip_address(hostp) && !is_local_port_fixed(local_portp)) { + int target_families[2] = { 0, 0 }; + int resolving_family_size = 0; + + /* + * Maybe also accept a local address + */ + if (!NIL_P(local_host) || !NIL_P(local_serv)) { + VALUE t = NIL_P(open_timeout) ? resolv_timeout : open_timeout; + local_res = rsock_addrinfo( + local_host, + local_serv, + AF_UNSPEC, + SOCK_STREAM, + 0, + t + ); + + struct addrinfo *tmp_p = local_res->ai; + for (; tmp_p != NULL; tmp_p = tmp_p->ai_next) { + if (target_families[0] == 0 && tmp_p->ai_family == AF_INET6) { + target_families[0] = AF_INET6; + resolving_family_size++; + } + if (target_families[1] == 0 && tmp_p->ai_family == AF_INET) { + target_families[1] = AF_INET; + resolving_family_size++; + } + } + } else { + resolving_family_size = 2; + target_families[0] = AF_INET6; + target_families[1] = AF_INET; + } + + struct fast_fallback_inetsock_arg fast_fallback_arg; + memset(&fast_fallback_arg, 0, sizeof(fast_fallback_arg)); + + fast_fallback_arg.self = self; + fast_fallback_arg.io = Qnil; + fast_fallback_arg.remote.host = remote_host; + fast_fallback_arg.remote.serv = remote_serv; + fast_fallback_arg.remote.res = 0; + fast_fallback_arg.local.host = local_host; + fast_fallback_arg.local.serv = local_serv; + fast_fallback_arg.local.res = local_res; + fast_fallback_arg.type = type; + fast_fallback_arg.resolv_timeout = resolv_timeout; + fast_fallback_arg.connect_timeout = connect_timeout; + fast_fallback_arg.open_timeout = open_timeout; + fast_fallback_arg.hostp = hostp; + fast_fallback_arg.portp = portp; + fast_fallback_arg.additional_flags = additional_flags; + + int resolving_families[resolving_family_size]; + int resolving_family_index = 0; + for (int i = 0; 2 > i; i++) { + if (target_families[i] != 0) { + resolving_families[resolving_family_index] = target_families[i]; + resolving_family_index++; + } + } + fast_fallback_arg.families = resolving_families; + fast_fallback_arg.family_size = resolving_family_size; + fast_fallback_arg.test_mode_settings = test_mode_settings; + + rb_fd_init(&fast_fallback_arg.readfds); + rb_fd_init(&fast_fallback_arg.writefds); + + return rb_ensure(init_fast_fallback_inetsock_internal, (VALUE)&fast_fallback_arg, + fast_fallback_inetsock_cleanup, (VALUE)&fast_fallback_arg); + } + } + + struct inetsock_arg arg; + arg.self = self; + arg.io = Qnil; + arg.remote.host = remote_host; + arg.remote.serv = remote_serv; + arg.remote.res = 0; + arg.local.host = local_host; + arg.local.serv = local_serv; + arg.local.res = 0; + arg.type = type; + arg.resolv_timeout = resolv_timeout; + arg.connect_timeout = connect_timeout; + arg.open_timeout = open_timeout; + + return rb_ensure(init_inetsock_internal, (VALUE)&arg, + inetsock_cleanup, (VALUE)&arg); +} + +#endif + static ID id_numeric, id_hostname; int @@ -184,11 +1444,11 @@ rsock_revlookup_flag(VALUE revlookup, int *norevlookup) case Qfalse: return_norevlookup(1); case Qnil: break; default: - Check_Type(revlookup, T_SYMBOL); - id = SYM2ID(revlookup); - if (id == id_numeric) return_norevlookup(1); - if (id == id_hostname) return_norevlookup(0); - rb_raise(rb_eArgError, "invalid reverse_lookup flag: :%s", rb_id2name(id)); + Check_Type(revlookup, T_SYMBOL); + id = SYM2ID(revlookup); + if (id == id_numeric) return_norevlookup(1); + if (id == id_hostname) return_norevlookup(0); + rb_raise(rb_eArgError, "invalid reverse_lookup flag: :%s", rb_id2name(id)); } return 0; #undef return_norevlookup @@ -209,24 +1469,24 @@ ip_inspect(VALUE sock) socklen_t len = (socklen_t)sizeof addr; ID id; if (fptr && fptr->fd >= 0 && - getsockname(fptr->fd, &addr.addr, &len) >= 0 && - (id = rsock_intern_family(addr.addr.sa_family)) != 0) { - VALUE family = rb_id2str(id); - char hbuf[1024], pbuf[1024]; - long slen = RSTRING_LEN(str); - const char last = (slen > 1 && RSTRING_PTR(str)[slen - 1] == '>') ? - (--slen, '>') : 0; - str = rb_str_subseq(str, 0, slen); - rb_str_cat_cstr(str, ", "); - rb_str_append(str, family); - if (!rb_getnameinfo(&addr.addr, len, hbuf, sizeof(hbuf), - pbuf, sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV)) { - rb_str_cat_cstr(str, ", "); - rb_str_cat_cstr(str, hbuf); - rb_str_cat_cstr(str, ", "); - rb_str_cat_cstr(str, pbuf); - } - if (last) rb_str_cat(str, &last, 1); + getsockname(fptr->fd, &addr.addr, &len) >= 0 && + (id = rsock_intern_family(addr.addr.sa_family)) != 0) { + VALUE family = rb_id2str(id); + char hbuf[1024], pbuf[1024]; + long slen = RSTRING_LEN(str); + const char last = (slen > 1 && RSTRING_PTR(str)[slen - 1] == '>') ? + (--slen, '>') : 0; + str = rb_str_subseq(str, 0, slen); + rb_str_cat_cstr(str, ", "); + rb_str_append(str, family); + if (!rb_getnameinfo(&addr.addr, len, hbuf, sizeof(hbuf), + pbuf, sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV)) { + rb_str_cat_cstr(str, ", "); + rb_str_cat_cstr(str, hbuf); + rb_str_cat_cstr(str, ", "); + rb_str_cat_cstr(str, pbuf); + } + if (last) rb_str_cat(str, &last, 1); } return str; } @@ -241,7 +1501,7 @@ ip_inspect(VALUE sock) * If +reverse_lookup+ is +true+ or +:hostname+, * hostname is obtained from numeric_address using reverse lookup. * Or if it is +false+, or +:numeric+, - * hostname is same as numeric_address. + * hostname is the same as numeric_address. * Or if it is +nil+ or omitted, obeys to +ipsocket.do_not_reverse_lookup+. * See +Socket.getaddrinfo+ also. * @@ -257,17 +1517,14 @@ ip_inspect(VALUE sock) static VALUE ip_addr(int argc, VALUE *argv, VALUE sock) { - rb_io_t *fptr; union_sockaddr addr; socklen_t len = (socklen_t)sizeof addr; int norevlookup; - GetOpenFile(sock, fptr); - if (argc < 1 || !rsock_revlookup_flag(argv[0], &norevlookup)) - norevlookup = fptr->mode & FMODE_NOREVLOOKUP; - if (getsockname(fptr->fd, &addr.addr, &len) < 0) - rb_sys_fail("getsockname(2)"); + norevlookup = rb_io_mode(sock) & FMODE_NOREVLOOKUP; + if (getsockname(rb_io_descriptor(sock), &addr.addr, &len) < 0) + rb_sys_fail("getsockname(2)"); return rsock_ipaddr(&addr.addr, len, norevlookup); } @@ -282,7 +1539,7 @@ ip_addr(int argc, VALUE *argv, VALUE sock) * If +reverse_lookup+ is +true+ or +:hostname+, * hostname is obtained from numeric_address using reverse lookup. * Or if it is +false+, or +:numeric+, - * hostname is same as numeric_address. + * hostname is the same as numeric_address. * Or if it is +nil+ or omitted, obeys to +ipsocket.do_not_reverse_lookup+. * See +Socket.getaddrinfo+ also. * @@ -298,17 +1555,14 @@ ip_addr(int argc, VALUE *argv, VALUE sock) static VALUE ip_peeraddr(int argc, VALUE *argv, VALUE sock) { - rb_io_t *fptr; union_sockaddr addr; socklen_t len = (socklen_t)sizeof addr; int norevlookup; - GetOpenFile(sock, fptr); - if (argc < 1 || !rsock_revlookup_flag(argv[0], &norevlookup)) - norevlookup = fptr->mode & FMODE_NOREVLOOKUP; - if (getpeername(fptr->fd, &addr.addr, &len) < 0) - rb_sys_fail("getpeername(2)"); + norevlookup = rb_io_mode(sock) & FMODE_NOREVLOOKUP; + if (getpeername(rb_io_descriptor(sock), &addr.addr, &len) < 0) + rb_sys_fail("getpeername(2)"); return rsock_ipaddr(&addr.addr, len, norevlookup); } @@ -324,7 +1578,7 @@ ip_peeraddr(int argc, VALUE *argv, VALUE sock) * * _flags_ should be a bitwise OR of Socket::MSG_* constants. * - * ipaddr is same as IPSocket#{peeraddr,addr}. + * ipaddr is the same as IPSocket#{peeraddr,addr}. * * u1 = UDPSocket.new * u1.bind("127.0.0.1", 4913) @@ -355,7 +1609,7 @@ static VALUE ip_s_getaddress(VALUE obj, VALUE host) { union_sockaddr addr; - struct rb_addrinfo *res = rsock_addrinfo(host, Qnil, AF_UNSPEC, SOCK_STREAM, 0); + struct rb_addrinfo *res = rsock_addrinfo(host, Qnil, AF_UNSPEC, SOCK_STREAM, 0, Qnil); socklen_t len = res->ai->ai_addrlen; /* just take the first one */ diff --git a/ext/socket/lib/socket.rb b/ext/socket/lib/socket.rb index 4ed2df23e6..36fcceaee9 100644 --- a/ext/socket/lib/socket.rb +++ b/ext/socket/lib/socket.rb @@ -1,7 +1,11 @@ # frozen_string_literal: true require 'socket.so' -require 'io/wait' + +unless IO.method_defined?(:wait_writable, false) + # It's only required on older Rubies < v3.2: + require 'io/wait' +end class Addrinfo # creates an Addrinfo object from the arguments. @@ -58,7 +62,7 @@ class Addrinfo break when :wait_writable sock.wait_writable(timeout) or - raise Errno::ETIMEDOUT, 'user specified timeout' + raise Errno::ETIMEDOUT, "user specified timeout for #{self.ip_address}:#{self.ip_port}" end while true else sock.connect(self) @@ -197,7 +201,7 @@ class Addrinfo sock = Socket.new(self.pfamily, self.socktype, self.protocol) begin sock.ipv6only! if self.ipv6? - sock.setsockopt(:SOCKET, :REUSEADDR, 1) + sock.setsockopt(:SOCKET, :REUSEADDR, 1) unless self.pfamily == Socket::PF_UNIX sock.bind(self) sock.listen(backlog) rescue Exception @@ -223,8 +227,8 @@ class Addrinfo # # #<Addrinfo: [::1]:80 TCP (:80)> # # #<Addrinfo: [::1]:80 UDP (:80)> # - def self.foreach(nodename, service, family=nil, socktype=nil, protocol=nil, flags=nil, &block) - Addrinfo.getaddrinfo(nodename, service, family, socktype, protocol, flags).each(&block) + def self.foreach(nodename, service, family=nil, socktype=nil, protocol=nil, flags=nil, timeout: nil, &block) + Addrinfo.getaddrinfo(nodename, service, family, socktype, protocol, flags, timeout: timeout).each(&block) end end @@ -329,9 +333,10 @@ class BasicSocket < IO # _flags_ is zero or more of the +MSG_+ options. # The result, _mesg_, is the data received. # - # When recvfrom(2) returns 0, Socket#recv_nonblock returns - # an empty string as data. - # The meaning depends on the socket: EOF on TCP, empty packet on UDP, etc. + # When recvfrom(2) returns 0, Socket#recv_nonblock returns nil. + # In most cases it means the connection was closed, but for UDP connections + # it may mean an empty packet was received, as the underlying API makes + # it impossible to distinguish these two cases. # # === Parameters # * +maxlen+ - the number of bytes to receive from the socket @@ -476,9 +481,10 @@ class Socket < BasicSocket # The second element, _sender_addrinfo_, contains protocol-specific address # information of the sender. # - # When recvfrom(2) returns 0, Socket#recvfrom_nonblock returns - # an empty string as data. - # The meaning depends on the socket: EOF on TCP, empty packet on UDP, etc. + # When recvfrom(2) returns 0, Socket#recv_nonblock returns nil. + # In most cases it means the connection was closed, but for UDP connections + # it may mean an empty packet was received, as the underlying API makes + # it impossible to distinguish these two cases. # # === Parameters # * +maxlen+ - the maximum number of bytes to receive from the socket @@ -593,19 +599,54 @@ class Socket < BasicSocket __accept_nonblock(exception) end + # :stopdoc: + RESOLUTION_DELAY = 0.05 + private_constant :RESOLUTION_DELAY + + CONNECTION_ATTEMPT_DELAY = 0.25 + private_constant :CONNECTION_ATTEMPT_DELAY + + ADDRESS_FAMILIES = { + ipv6: Socket::AF_INET6, + ipv4: Socket::AF_INET + }.freeze + private_constant :ADDRESS_FAMILIES + + HOSTNAME_RESOLUTION_QUEUE_UPDATED = 0 + private_constant :HOSTNAME_RESOLUTION_QUEUE_UPDATED + + IPV6_ADDRESS_FORMAT = /\A(?i:(?:(?:[0-9A-F]{1,4}:){7}(?:[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){6}(?:[0-9A-F]{1,4}|:(?:[0-9A-F]{1,4}:){1,5}[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){5}(?:(?::[0-9A-F]{1,4}){1,2}|:(?:[0-9A-F]{1,4}:){1,4}[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){4}(?:(?::[0-9A-F]{1,4}){1,3}|:(?:[0-9A-F]{1,4}:){1,3}[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){3}(?:(?::[0-9A-F]{1,4}){1,4}|:(?:[0-9A-F]{1,4}:){1,2}[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){2}(?:(?::[0-9A-F]{1,4}){1,5}|:(?:[0-9A-F]{1,4}:)[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){1}(?:(?::[0-9A-F]{1,4}){1,6}|:(?:[0-9A-F]{1,4}:){0,5}[0-9A-F]{1,4}|:)|(?:::(?:[0-9A-F]{1,4}:){0,7}[0-9A-F]{1,4}|::)))(?:%.+)?\z/ + private_constant :IPV6_ADDRESS_FORMAT + # :startdoc: + # :call-seq: # Socket.tcp(host, port, local_host=nil, local_port=nil, [opts]) {|socket| ... } # Socket.tcp(host, port, local_host=nil, local_port=nil, [opts]) # # creates a new socket object connected to host:port using TCP/IP. # + # Starting from Ruby 3.4, this method operates according to the + # Happy Eyeballs Version 2 ({RFC 8305}[https://datatracker.ietf.org/doc/html/rfc8305]) + # algorithm by default. + # + # For details on Happy Eyeballs Version 2, + # see {Socket.tcp_fast_fallback=}[rdoc-ref:Socket.tcp_fast_fallback=]. + # + # To make it behave the same as in Ruby 3.3 and earlier, + # explicitly specify the option fast_fallback:false. + # Or, setting Socket.tcp_fast_fallback=false will disable + # Happy Eyeballs Version 2 not only for this method but for all Socket globally. + # # If local_host:local_port is given, # the socket is bound to it. # # The optional last argument _opts_ is options represented by a hash. # _opts_ may have following options: # - # [:connect_timeout] specify the timeout in seconds. + # [:resolv_timeout] Specifies the timeout in seconds from when the hostname resolution starts. + # [:connect_timeout] This method sequentially attempts connecting to all candidate destination addresses.<br>The +connect_timeout+ specifies the timeout in seconds from the start of the connection attempt to the last candidate.<br>By default, all connection attempts continue until the timeout occurs.<br>When +fast_fallback:false+ is explicitly specified,<br>a timeout is set for each connection attempt and any connection attempt that exceeds its timeout will be canceled. + # [:open_timeout] Specifies the timeout in seconds from the start of the method execution.<br>If this timeout is reached while there are still addresses that have not yet been attempted for connection, no further attempts will be made.<br>If this option is specified together with other timeout options, an +ArgumentError+ will be raised. + # [:fast_fallback] Enables the Happy Eyeballs Version 2 algorithm (enabled by default). # # If a block is given, the block is called with the socket. # The value of the block is returned. @@ -618,17 +659,296 @@ class Socket < BasicSocket # sock.close_write # puts sock.read # } - # - def self.tcp(host, port, local_host = nil, local_port = nil, connect_timeout: nil) # :yield: socket + def self.tcp(host, port, local_host = nil, local_port = nil, connect_timeout: nil, resolv_timeout: nil, open_timeout: nil, fast_fallback: tcp_fast_fallback, &) # :yield: socket + if open_timeout && (connect_timeout || resolv_timeout) + raise ArgumentError, "Cannot specify open_timeout along with connect_timeout or resolv_timeout" + end + + sock = if fast_fallback && !(host && ip_address?(host)) && !(local_port && local_port.to_i != 0) + tcp_with_fast_fallback(host, port, local_host, local_port, connect_timeout:, resolv_timeout:, open_timeout:) + else + tcp_without_fast_fallback(host, port, local_host, local_port, connect_timeout:, resolv_timeout:, open_timeout:) + end + + if block_given? + begin + yield sock + ensure + sock.close + end + else + sock + end + end + + # :stopdoc: + def self.tcp_with_fast_fallback(host, port, local_host = nil, local_port = nil, connect_timeout: nil, resolv_timeout: nil, open_timeout: nil) + if local_host || local_port + local_addrinfos = Addrinfo.getaddrinfo(local_host, local_port, nil, :STREAM, timeout: open_timeout || resolv_timeout) + resolving_family_names = local_addrinfos.map { |lai| ADDRESS_FAMILIES.key(lai.afamily) }.uniq + else + local_addrinfos = [] + resolving_family_names = ADDRESS_FAMILIES.keys + end + + hostname_resolution_threads = [] + resolution_store = HostnameResolutionStore.new(resolving_family_names) + connecting_sockets = {} + is_windows_environment ||= (RUBY_PLATFORM =~ /mswin|mingw|cygwin/) + + now = current_clock_time + starts_at = now + resolution_delay_expires_at = nil + connection_attempt_delay_expires_at = nil + user_specified_connect_timeout_at = nil + user_specified_open_timeout_at = open_timeout ? now + open_timeout : nil + last_error = nil + last_error_from_thread = false + + if resolving_family_names.size == 1 + family_name = resolving_family_names.first + addrinfos = Addrinfo.getaddrinfo(host, port, ADDRESS_FAMILIES[:family_name], :STREAM, timeout: open_timeout || resolv_timeout) + resolution_store.add_resolved(family_name, addrinfos) + hostname_resolution_result = nil + hostname_resolution_notifier = nil + user_specified_resolv_timeout_at = nil + else + hostname_resolution_result = HostnameResolutionResult.new(resolving_family_names.size) + hostname_resolution_notifier = hostname_resolution_result.notifier + + hostname_resolution_threads.concat( + resolving_family_names.map { |family| + thread_args = [family, host, port, hostname_resolution_result] + thread = Thread.new(*thread_args) { |*thread_args| resolve_hostname(*thread_args) } + Thread.pass + thread + } + ) + user_specified_resolv_timeout_at = resolv_timeout ? now + resolv_timeout : Float::INFINITY + end + + loop do + if resolution_store.any_addrinfos? && + !resolution_delay_expires_at && + !connection_attempt_delay_expires_at + while (addrinfo = resolution_store.get_addrinfo) + if local_addrinfos.any? + local_addrinfo = local_addrinfos.find { |lai| lai.afamily == addrinfo.afamily } + + if local_addrinfo.nil? + if resolution_store.any_addrinfos? + # Try other Addrinfo in next "while" + next + elsif connecting_sockets.any? || resolution_store.any_unresolved_family? + # Exit this "while" and wait for connections to be established or hostname resolution in next loop + # Or exit this "while" and wait for hostname resolution in next loop + break + else + raise SocketError.new 'no appropriate local address' + end + end + end + + begin + if resolution_store.any_addrinfos? || + connecting_sockets.any? || + resolution_store.any_unresolved_family? + socket = Socket.new(addrinfo.pfamily, addrinfo.socktype, addrinfo.protocol) + socket.bind(local_addrinfo) if local_addrinfo + result = socket.connect_nonblock(addrinfo, exception: false) + else + timeout = + if open_timeout + t = open_timeout - (current_clock_time - starts_at) + t.negative? ? 0 : t + else + connect_timeout + end + result = socket = local_addrinfo ? + addrinfo.connect_from(local_addrinfo, timeout:) : + addrinfo.connect(timeout:) + end + + if result == :wait_writable + connection_attempt_delay_expires_at = now + CONNECTION_ATTEMPT_DELAY + if resolution_store.empty_addrinfos? + user_specified_connect_timeout_at = connect_timeout ? now + connect_timeout : Float::INFINITY + end + + connecting_sockets[socket] = addrinfo + break + else + return socket # connection established + end + rescue SystemCallError => e + socket&.close + last_error = e + + if resolution_store.any_addrinfos? + # Try other Addrinfo in next "while" + next + elsif connecting_sockets.any? || resolution_store.any_unresolved_family? + # Exit this "while" and wait for connections to be established or hostname resolution in next loop + # Or exit this "while" and wait for hostname resolution in next loop + break + else + raise last_error + end + end + end + end + + ends_at = + if resolution_store.any_addrinfos? + [(resolution_delay_expires_at || connection_attempt_delay_expires_at), + user_specified_open_timeout_at].compact.min + elsif user_specified_open_timeout_at + user_specified_open_timeout_at + else + [user_specified_resolv_timeout_at, user_specified_connect_timeout_at].compact.max + end + + hostname_resolved, writable_sockets, except_sockets = IO.select( + hostname_resolution_notifier, + connecting_sockets.keys, + # Use errorfds to wait for non-blocking connect failures on Windows + is_windows_environment ? connecting_sockets.keys : nil, + second_to_timeout(current_clock_time, ends_at), + ) + now = current_clock_time + resolution_delay_expires_at = nil if expired?(now, resolution_delay_expires_at) + connection_attempt_delay_expires_at = nil if expired?(now, connection_attempt_delay_expires_at) + + if writable_sockets&.any? + while (writable_socket = writable_sockets.pop) + is_connected = is_windows_environment || ( + sockopt = writable_socket.getsockopt(Socket::SOL_SOCKET, Socket::SO_ERROR) + sockopt.int.zero? + ) + + if is_connected + connecting_sockets.delete writable_socket + return writable_socket + else + failed_ai = connecting_sockets.delete writable_socket + writable_socket.close + ip_address = failed_ai.ipv6? ? "[#{failed_ai.ip_address}]" : failed_ai.ip_address + last_error = SystemCallError.new("connect(2) for #{ip_address}:#{failed_ai.ip_port}", sockopt.int) + + if writable_sockets.any? || connecting_sockets.any? + # Try other writable socket in next "while" + # Or exit this "while" and wait for connections to be established or hostname resolution in next loop + elsif resolution_store.any_addrinfos? || resolution_store.any_unresolved_family? + # Exit this "while" and try other connection attempt + # Or exit this "while" and wait for hostname resolution in next loop + connection_attempt_delay_expires_at = nil + user_specified_connect_timeout_at = nil + else + raise last_error + end + end + end + end + + if except_sockets&.any? + except_sockets.each do |except_socket| + failed_ai = connecting_sockets.delete except_socket + sockopt = except_socket.getsockopt(Socket::SOL_SOCKET, Socket::SO_ERROR) + except_socket.close + ip_address = failed_ai.ipv6? ? "[#{failed_ai.ip_address}]" : failed_ai.ip_address + last_error = SystemCallError.new("connect(2) for #{ip_address}:#{failed_ai.ip_port}", sockopt.int) + + if except_sockets.any? || connecting_sockets.any? + # Cleanup other except socket in next "each" + # Or exit this "while" and wait for connections to be established or hostname resolution in next loop + elsif resolution_store.any_addrinfos? || resolution_store.any_unresolved_family? + # Exit this "while" and try other connection attempt + # Or exit this "while" and wait for hostname resolution in next loop + connection_attempt_delay_expires_at = nil + user_specified_connect_timeout_at = nil + else + raise last_error + end + end + end + + if hostname_resolved&.any? + while (family_and_result = hostname_resolution_result.get) + family_name, result = family_and_result + + if result.is_a? Exception + resolution_store.add_error(family_name, result) + + unless (Socket.const_defined?(:EAI_ADDRFAMILY)) && + (result.is_a?(Socket::ResolutionError)) && + (result.error_code == Socket::EAI_ADDRFAMILY) + other = family_name == :ipv6 ? :ipv4 : :ipv6 + if !resolution_store.resolved?(other) || !resolution_store.resolved_successfully?(other) + last_error = result + last_error_from_thread = true + end + end + else + resolution_store.add_resolved(family_name, result) + end + end + + if resolution_store.resolved?(:ipv4) + if resolution_store.resolved?(:ipv6) + hostname_resolution_notifier = nil + resolution_delay_expires_at = nil + user_specified_resolv_timeout_at = nil + elsif resolution_store.resolved_successfully?(:ipv4) + resolution_delay_expires_at = now + RESOLUTION_DELAY + end + end + end + + if expired?(now, user_specified_open_timeout_at) + raise(IO::TimeoutError, "user specified timeout for #{host}:#{port}") + end + + if resolution_store.empty_addrinfos? + if connecting_sockets.empty? && resolution_store.resolved_all_families? + if last_error_from_thread + raise last_error.class, last_error.message, cause: last_error + else + raise last_error + end + end + + if (expired?(now, user_specified_resolv_timeout_at) || resolution_store.resolved_all_families?) && + (expired?(now, user_specified_connect_timeout_at) || connecting_sockets.empty?) + raise(IO::TimeoutError, "user specified timeout for #{host}:#{port}") + end + end + end + ensure + hostname_resolution_threads.each do |thread| + thread.exit + end + + hostname_resolution_result&.close + + connecting_sockets.each_key do |connecting_socket| + connecting_socket.close + end + end + private_class_method :tcp_with_fast_fallback + + def self.tcp_without_fast_fallback(host, port, local_host, local_port, connect_timeout:, resolv_timeout:, open_timeout:) last_error = nil ret = nil local_addr_list = nil if local_host != nil || local_port != nil - local_addr_list = Addrinfo.getaddrinfo(local_host, local_port, nil, :STREAM, nil) + local_addr_list = Addrinfo.getaddrinfo(local_host, local_port, nil, :STREAM, nil, timeout: open_timeout || resolv_timeout) end - Addrinfo.foreach(host, port, nil, :STREAM) {|ai| + timeout = open_timeout ? open_timeout : resolv_timeout + starts_at = current_clock_time + + Addrinfo.foreach(host, port, nil, :STREAM, timeout:) {|ai| if local_addr_list local_addr = local_addr_list.find {|local_ai| local_ai.afamily == ai.afamily } next unless local_addr @@ -636,9 +956,17 @@ class Socket < BasicSocket local_addr = nil end begin + timeout = + if open_timeout + t = open_timeout - (current_clock_time - starts_at) + t.negative? ? 0 : t + else + connect_timeout + end + sock = local_addr ? - ai.connect_from(local_addr, timeout: connect_timeout) : - ai.connect(timeout: connect_timeout) + ai.connect_from(local_addr, timeout:) : + ai.connect(timeout:) rescue SystemCallError last_error = $! next @@ -653,18 +981,150 @@ class Socket < BasicSocket raise SocketError, "no appropriate local address" end end - if block_given? - begin - yield ret - ensure - ret.close + + ret + end + private_class_method :tcp_without_fast_fallback + + def self.ip_address?(hostname) + hostname.match?(IPV6_ADDRESS_FORMAT) || hostname.match?(/\A([0-9]{1,3}\.){3}[0-9]{1,3}\z/) + end + private_class_method :ip_address? + + def self.resolve_hostname(family, host, port, hostname_resolution_result) + begin + resolved_addrinfos = Addrinfo.getaddrinfo(host, port, ADDRESS_FAMILIES[family], :STREAM) + hostname_resolution_result.add(family, resolved_addrinfos) + rescue => e + hostname_resolution_result.add(family, e) + end + end + private_class_method :resolve_hostname + + def self.current_clock_time + Process.clock_gettime(Process::CLOCK_MONOTONIC) + end + private_class_method :current_clock_time + + def self.second_to_timeout(started_at, ends_at) + return nil if ends_at == Float::INFINITY || ends_at.nil? + + remaining = (ends_at - started_at) + remaining.negative? ? 0 : remaining + end + private_class_method :second_to_timeout + + def self.expired?(started_at, ends_at) + second_to_timeout(started_at, ends_at)&.zero? + end + private_class_method :expired? + + class HostnameResolutionResult + def initialize(size) + @size = size + @taken_count = 0 + @rpipe, @wpipe = IO.pipe + @results = [] + @mutex = Mutex.new + end + + def notifier + [@rpipe] + end + + def add(family, result) + @mutex.synchronize do + @results.push [family, result] + @wpipe.putc HOSTNAME_RESOLUTION_QUEUE_UPDATED end - else - ret + end + + def get + return nil if @results.empty? + + res = nil + + @mutex.synchronize do + @rpipe.getbyte + res = @results.shift + end + + @taken_count += 1 + close if @taken_count == @size + res + end + + def close + @rpipe.close + @wpipe.close end end + private_constant :HostnameResolutionResult + + class HostnameResolutionStore + PRIORITY_ON_V6 = [:ipv6, :ipv4].freeze + PRIORITY_ON_V4 = [:ipv4, :ipv6].freeze + + def initialize(family_names) + @family_names = family_names + @addrinfo_dict = {} + @error_dict = {} + @last_family = nil + end + + def add_resolved(family_name, addrinfos) + @addrinfo_dict[family_name] = addrinfos + end + + def add_error(family_name, error) + @addrinfo_dict[family_name] = [] + @error_dict[family_name] = error + end + + def get_addrinfo + precedences = + case @last_family + when :ipv4, nil then PRIORITY_ON_V6 + when :ipv6 then PRIORITY_ON_V4 + end + + precedences.each do |family_name| + addrinfo = @addrinfo_dict[family_name]&.shift + next unless addrinfo + + @last_family = family_name + return addrinfo + end + + nil + end + + def empty_addrinfos? + @addrinfo_dict.all? { |_, addrinfos| addrinfos.empty? } + end + + def any_addrinfos? + !empty_addrinfos? + end + + def resolved?(family) + @addrinfo_dict.has_key? family + end + + def resolved_successfully?(family) + resolved?(family) && !@error_dict[family] + end + + def resolved_all_families? + (@family_names - @addrinfo_dict.keys).empty? + end + + def any_unresolved_family? + !resolved_all_families? + end + end + private_constant :HostnameResolutionStore - # :stopdoc: def self.ip_sockets_port0(ai_list, reuseaddr) sockets = [] begin @@ -697,9 +1157,7 @@ class Socket < BasicSocket end sockets end - class << self - private :ip_sockets_port0 - end + private_class_method :ip_sockets_port0 def self.tcp_server_sockets_port0(host) ai_list = Addrinfo.getaddrinfo(host, 0, nil, :STREAM, nil, Socket::AI_PASSIVE) @@ -1127,13 +1585,18 @@ class Socket < BasicSocket end end - class << self - private - - def unix_socket_abstract_name?(path) - /linux/ =~ RUBY_PLATFORM && /\A(\0|\z)/ =~ path + # :stopdoc: + if RUBY_PLATFORM.include?("linux") + def self.unix_socket_abstract_name?(path) + path.empty? or path.start_with?("\0") + end + else + def self.unix_socket_abstract_name?(path) + false end end + private_class_method :unix_socket_abstract_name? + # :startdoc: # creates a UNIX socket server on _path_. # It calls the block for each socket accepted. @@ -1173,7 +1636,7 @@ class Socket < BasicSocket # Returns 0 if successful, otherwise an exception is raised. # # === Parameter - # # +remote_sockaddr+ - the +struct+ sockaddr contained in a string or Addrinfo object + # * +remote_sockaddr+ - the +struct+ sockaddr contained in a string or Addrinfo object # # === Example: # # Pull down Google's web page @@ -1208,7 +1671,7 @@ class Socket < BasicSocket # return the symbol +:wait_writable+ instead. # # === See - # # Socket#connect + # * Socket#connect def connect_nonblock(addr, exception: true) __connect_nonblock(addr, exception) end @@ -1225,9 +1688,10 @@ class UDPSocket < IPSocket # The first element of the results, _mesg_, is the data received. # The second element, _sender_inet_addr_, is an array to represent the sender address. # - # When recvfrom(2) returns 0, - # Socket#recvfrom_nonblock returns an empty string as data. - # It means an empty packet. + # When recvfrom(2) returns 0, Socket#recv_nonblock returns nil. + # In most cases it means the connection was closed, but it may also mean + # an empty packet was received, as the underlying API makes + # it impossible to distinguish these two cases. # # === Parameters # * +maxlen+ - the number of bytes to receive from the socket diff --git a/ext/socket/mkconstants.rb b/ext/socket/mkconstants.rb index 620a5f60ff..4271e40cd8 100644 --- a/ext/socket/mkconstants.rb +++ b/ext/socket/mkconstants.rb @@ -51,7 +51,10 @@ DATA.each_line {|s| next end h[name] = default_value - COMMENTS[name] = comment + if comment + # Stop unintentional references + COMMENTS[name] = comment.gsub(/\b(Data|Kernel|Process|Set|Socket|Time)\b/, '\\\\\\&') + end } DEFS = h.to_a @@ -73,15 +76,11 @@ def each_name(pat) } end -erb_new = lambda do |src, safe, trim| - if ERB.instance_method(:initialize).parameters.assoc(:key) # Ruby 2.6+ - ERB.new(src, trim_mode: trim) - else - ERB.new(src, safe, trim) - end +erb_new = lambda do |src, trim| + ERB.new(src, trim_mode: trim) end -erb_new.call(<<'EOS', nil, '%').def_method(Object, "gen_const_decls") +erb_new.call(<<'EOS', '%').def_method(Object, "gen_const_decls") % each_const {|guard, name, default_value| #if !defined(<%=name%>) # if defined(HAVE_CONST_<%=name.upcase%>) @@ -95,7 +94,7 @@ erb_new.call(<<'EOS', nil, '%').def_method(Object, "gen_const_decls") % } EOS -erb_new.call(<<'EOS', nil, '%').def_method(Object, "gen_const_defs_in_guard(name, default_value)") +erb_new.call(<<'EOS', '%').def_method(Object, "gen_const_defs_in_guard(name, default_value)") #if defined(<%=name%>) /* <%= COMMENTS[name] %> */ rb_define_const(rb_cSocket, <%=c_str name%>, INTEGER2NUM(<%=name%>)); @@ -104,7 +103,7 @@ erb_new.call(<<'EOS', nil, '%').def_method(Object, "gen_const_defs_in_guard(name #endif EOS -erb_new.call(<<'EOS', nil, '%').def_method(Object, "gen_const_defs") +erb_new.call(<<'EOS', '%').def_method(Object, "gen_const_defs") % each_const {|guard, name, default_value| % if guard #if <%=guard%> @@ -154,7 +153,7 @@ def each_names_with_len(pat, prefix_optional=nil) } end -erb_new.call(<<'EOS', nil, '%').def_method(Object, "gen_name_to_int_decl(funcname, pat, prefix_optional, guard=nil)") +erb_new.call(<<'EOS', '%').def_method(Object, "gen_name_to_int_decl(funcname, pat, prefix_optional, guard=nil)") %if guard #ifdef <%=guard%> int <%=funcname%>(const char *str, long len, int *valp); @@ -164,7 +163,7 @@ int <%=funcname%>(const char *str, long len, int *valp); %end EOS -erb_new.call(<<'EOS', nil, '%').def_method(Object, "gen_name_to_int_func_in_guard(funcname, pat, prefix_optional, guard=nil)") +erb_new.call(<<'EOS', '%').def_method(Object, "gen_name_to_int_func_in_guard(funcname, pat, prefix_optional, guard=nil)") int <%=funcname%>(const char *str, long len, int *valp) { @@ -186,7 +185,7 @@ int } EOS -erb_new.call(<<'EOS', nil, '%').def_method(Object, "gen_name_to_int_func(funcname, pat, prefix_optional, guard=nil)") +erb_new.call(<<'EOS', '%').def_method(Object, "gen_name_to_int_func(funcname, pat, prefix_optional, guard=nil)") %if guard #ifdef <%=guard%> <%=gen_name_to_int_func_in_guard(funcname, pat, prefix_optional, guard)%> @@ -215,7 +214,7 @@ def reverse_each_name_with_prefix_optional(pat, prefix_pat) end end -erb_new.call(<<'EOS', nil, '%').def_method(Object, "gen_int_to_name_hash(hash_var, pat, prefix_pat)") +erb_new.call(<<'EOS', '%').def_method(Object, "gen_int_to_name_hash(hash_var, pat, prefix_pat)") <%=hash_var%> = st_init_numtable(); % reverse_each_name_with_prefix_optional(pat, prefix_pat) {|n,s| #ifdef <%=n%> @@ -224,7 +223,7 @@ erb_new.call(<<'EOS', nil, '%').def_method(Object, "gen_int_to_name_hash(hash_va % } EOS -erb_new.call(<<'EOS', nil, '%').def_method(Object, "gen_int_to_name_func(func_name, hash_var)") +erb_new.call(<<'EOS', '%').def_method(Object, "gen_int_to_name_func(func_name, hash_var)") ID <%=func_name%>(int val) { @@ -235,7 +234,7 @@ ID } EOS -erb_new.call(<<'EOS', nil, '%').def_method(Object, "gen_int_to_name_decl(func_name, hash_var)") +erb_new.call(<<'EOS', '%').def_method(Object, "gen_int_to_name_decl(func_name, hash_var)") ID <%=func_name%>(int val); EOS @@ -284,7 +283,7 @@ def_intern('rsock_intern_udp_optname', /\AUDP_/, "UDP_") def_intern('rsock_intern_scm_optname', /\ASCM_/, "SCM_") def_intern('rsock_intern_local_optname', /\ALOCAL_/, "LOCAL_") -result = erb_new.call(<<'EOS', nil, '%').result(binding) +result = erb_new.call(<<'EOS', '%').result(binding) /* autogenerated file */ <%= INTERN_DEFS.map {|vardef, gen_hash, decl, func| vardef }.join("\n") %> @@ -327,7 +326,7 @@ init_constants(void) EOS -header_result = erb_new.call(<<'EOS', nil, '%').result(binding) +header_result = erb_new.call(<<'EOS', '%').result(binding) /* autogenerated file */ <%= gen_const_decls %> <%= NAME_TO_INT_DEFS.map {|decl, func| decl }.join("\n") %> @@ -358,6 +357,8 @@ SOCK_RAW nil A raw socket provides low-level access for direct access or impleme SOCK_RDM nil A reliable datagram socket provides reliable delivery of messages SOCK_SEQPACKET nil A sequential packet socket provides sequenced, reliable two-way connection for datagrams SOCK_PACKET nil Device-level packet access +SOCK_NONBLOCK nil Set the O_NONBLOCK file status flag on the open file description (see open(2)) referred to by the new file descriptor. +SOCK_CLOEXEC nil Set the close-on-exec (FD_CLOEXEC) flag on the new file descriptor. AF_UNSPEC nil Unspecified protocol, any supported address family PF_UNSPEC nil Unspecified protocol, any supported address family @@ -397,6 +398,8 @@ AF_SNA nil IBM SNA protocol PF_SNA nil IBM SNA protocol AF_DEC nil DECnet protocol PF_DEC nil DECnet protocol +AF_DECnet nil DECnet protocol +PF_DECnet nil DECnet protocol AF_DLI nil DEC Direct Data Link Interface protocol PF_DLI nil DEC Direct Data Link Interface protocol AF_LAT nil Local Area Transport protocol @@ -419,8 +422,8 @@ AF_ISDN nil Integrated Services Digital Network PF_ISDN nil Integrated Services Digital Network AF_NATM nil Native ATM access PF_NATM nil Native ATM access -AF_SYSTEM -PF_SYSTEM +AF_SYSTEM nil Kernel event messages +PF_SYSTEM nil Kernel event messages AF_NETBIOS nil NetBIOS PF_NETBIOS nil NetBIOS AF_PPP nil Point-to-Point Protocol @@ -436,9 +439,36 @@ PF_PACKET nil Direct link-layer access AF_E164 nil CCITT (ITU-T) E.164 recommendation PF_XTP nil eXpress Transfer Protocol -PF_RTIP -PF_PIP -PF_KEY +PF_RTIP nil Help Identify RTIP packets +PF_PIP nil Help Identify PIP packets +AF_KEY nil Key management protocol, originally developed for usage with IPsec +PF_KEY nil Key management protocol, originally developed for usage with IPsec +AF_NETLINK nil Kernel user interface device +PF_NETLINK nil Kernel user interface device +AF_RDS nil Reliable Datagram Sockets (RDS) protocol +PF_RDS nil Reliable Datagram Sockets (RDS) protocol +AF_PPPOX nil Generic PPP transport layer, for setting up L2 tunnels (L2TP and PPPoE) +PF_PPPOX nil Generic PPP transport layer, for setting up L2 tunnels (L2TP and PPPoE) +AF_LLC nil Logical link control (IEEE 802.2 LLC) protocol +PF_LLC nil Logical link control (IEEE 802.2 LLC) protocol +AF_IB nil InfiniBand native addressing +PF_IB nil InfiniBand native addressing +AF_MPLS nil Multiprotocol Label Switching +PF_MPLS nil Multiprotocol Label Switching +AF_CAN nil Controller Area Network automotive bus protocol +PF_CAN nil Controller Area Network automotive bus protocol +AF_TIPC nil TIPC, "cluster domain sockets" protocol +PF_TIPC nil TIPC, "cluster domain sockets" protocol +AF_BLUETOOTH nil Bluetooth low-level socket protocol +PF_BLUETOOTH nil Bluetooth low-level socket protocol +AF_ALG nil Interface to kernel crypto API +PF_ALG nil Interface to kernel crypto API +AF_VSOCK nil VSOCK (originally "VMWare VSockets") protocol for hypervisor-guest communication +PF_VSOCK nil VSOCK (originally "VMWare VSockets") protocol for hypervisor-guest communication +AF_KCM nil KCM (kernel connection multiplexor) interface +PF_KCM nil KCM (kernel connection multiplexor) interface +AF_XDP nil XDP (express data path) interface +PF_XDP nil XDP (express data path) interface MSG_OOB nil Process out-of-band data MSG_PEEK nil Peek at incoming message @@ -595,6 +625,7 @@ SO_SNDTIMEO nil Send timeout SO_ACCEPTCONN nil Socket has had listen() called on it SO_USELOOPBACK nil Bypass hardware when possible SO_ACCEPTFILTER nil There is an accept filter +SO_USER_COOKIE nil Setting an identifier for ipfw purpose mainly SO_DONTTRUNC nil Retain unread data SO_WANTMORE nil Give a hint when more data is ready SO_WANTOOBFLAG nil OOB data is wanted in MSG_FLAG on receive @@ -630,6 +661,11 @@ SO_SELECT_ERR_QUEUE nil Make select() detect socket error queue with err SO_BUSY_POLL nil Set the threshold in microseconds for low latency polling (Linux 3.11) SO_MAX_PACING_RATE nil Cap the rate computed by transport layer. [bytes per second] (Linux 3.13) SO_BPF_EXTENSIONS nil Query supported BPF extensions (Linux 3.14) +SO_SETFIB nil Set the associated routing table for the socket (FreeBSD) +SO_RTABLE nil Set the routing table for this socket (OpenBSD) +SO_INCOMING_CPU nil Receive the cpu attached to the socket (Linux 3.19) +SO_INCOMING_NAPI_ID nil Receive the napi ID attached to a RX queue (Linux 4.12) +SO_CONNECT_TIME nil Returns the number of seconds a socket has been connected. This option is only valid for connection-oriented protocols (Windows) SOPRI_INTERACTIVE nil Interactive socket priority SOPRI_NORMAL nil Normal socket priority @@ -639,9 +675,11 @@ IPX_TYPE TCP_NODELAY nil Don't delay sending to coalesce packets TCP_MAXSEG nil Set maximum segment size +TCP_CONNECTION_INFO nil Retrieve information about this socket (macOS) TCP_CORK nil Don't send partial frames (Linux 2.2, glibc 2.2) TCP_DEFER_ACCEPT nil Don't notify a listening socket until data is ready (Linux 2.4, glibc 2.2) TCP_INFO nil Retrieve information about this socket (Linux 2.4, glibc 2.2) +TCP_KEEPALIVE nil Idle time before keepalive probes are sent (macOS) TCP_KEEPCNT nil Maximum number of keepalive probes allowed before dropping a connection (Linux 2.4, glibc 2.2) TCP_KEEPIDLE nil Idle time before keepalive probes are sent (Linux 2.4, glibc 2.2) TCP_KEEPINTVL nil Time between keepalive probes (Linux 2.4, glibc 2.2) @@ -707,6 +745,7 @@ SHUT_RDWR 2 Shut down the both sides of the socket IPV6_JOIN_GROUP nil Join a group membership IPV6_LEAVE_GROUP nil Leave a group membership +IPV6_MTU_DISCOVER nil Path MTU discovery IPV6_MULTICAST_HOPS nil IP6 multicast hops IPV6_MULTICAST_IF nil IP6 multicast interface IPV6_MULTICAST_LOOP nil IP6 multicast loopback @@ -721,6 +760,7 @@ IPV6_NEXTHOP nil Next hop address IPV6_PATHMTU nil Retrieve current path MTU IPV6_PKTINFO nil Receive packet information with datagram IPV6_RECVDSTOPTS nil Receive all IP6 options for response +IPV6_RECVERR nil Enable extended reliable error message passing IPV6_RECVHOPLIMIT nil Receive hop limit with datagram IPV6_RECVHOPOPTS nil Receive hop-by-hop options IPV6_RECVPKTINFO nil Receive destination IP address and incoming interface diff --git a/ext/socket/option.c b/ext/socket/option.c index 5ad44cdcd8..0d818d0c70 100644 --- a/ext/socket/option.c +++ b/ext/socket/option.c @@ -31,7 +31,7 @@ VALUE rb_cSockOpt; ((len) == (size) ? \ (void)0 : \ rb_raise(rb_eTypeError, "size differ. expected as "#size"=%d but %ld", \ - (int)size, (long)(len))) + (int)size, (long)(len))) static VALUE sockopt_pack_byte(VALUE value) @@ -106,9 +106,9 @@ sockopt_initialize(VALUE self, VALUE vfamily, VALUE vlevel, VALUE voptname, VALU VALUE rsock_sockopt_new(int family, int level, int optname, VALUE data) { - NEWOBJ_OF(obj, struct RObject, rb_cSockOpt, T_OBJECT); + VALUE obj = rb_obj_alloc(rb_cSockOpt); StringValue(data); - sockopt_initialize((VALUE)obj, INT2NUM(family), INT2NUM(level), INT2NUM(optname), data); + sockopt_initialize(obj, INT2NUM(family), INT2NUM(level), INT2NUM(optname), data); return (VALUE)obj; } @@ -309,7 +309,7 @@ sockopt_bool(VALUE self) StringValue(data); len = RSTRING_LEN(data); if (len == 1) { - return *RSTRING_PTR(data) == 0 ? Qfalse : Qtrue; + return *RSTRING_PTR(data) == 0 ? Qfalse : Qtrue; } check_size(len, sizeof(int)); memcpy((char*)&i, RSTRING_PTR(data), len); @@ -420,7 +420,7 @@ sockopt_ipv4_multicast_loop(VALUE self) #if defined(IPPROTO_IP) && defined(IP_MULTICAST_LOOP) if (family == AF_INET && level == IPPROTO_IP && optname == IP_MULTICAST_LOOP) { - return XCAT(sockopt_,TYPE_IP_MULTICAST_LOOP)(self); + return XCAT(sockopt_,TYPE_IP_MULTICAST_LOOP)(self); } #endif rb_raise(rb_eTypeError, "ipv4_multicast_loop socket option expected"); @@ -471,7 +471,7 @@ sockopt_ipv4_multicast_ttl(VALUE self) #if defined(IPPROTO_IP) && defined(IP_MULTICAST_TTL) if (family == AF_INET && level == IPPROTO_IP && optname == IP_MULTICAST_TTL) { - return XCAT(sockopt_,TYPE_IP_MULTICAST_TTL)(self); + return XCAT(sockopt_,TYPE_IP_MULTICAST_TTL)(self); } #endif rb_raise(rb_eTypeError, "ipv4_multicast_ttl socket option expected"); @@ -657,8 +657,8 @@ inet_ntop(int af, const void *addr, char *numaddr, size_t numaddr_len) #else unsigned long x = ntohl(*(unsigned long*)addr); snprintf(numaddr, numaddr_len, "%d.%d.%d.%d", - (int) (x>>24) & 0xff, (int) (x>>16) & 0xff, - (int) (x>> 8) & 0xff, (int) (x>> 0) & 0xff); + (int) (x>>24) & 0xff, (int) (x>>16) & 0xff, + (int) (x>> 8) & 0xff, (int) (x>> 0) & 0xff); #endif return numaddr; } @@ -670,10 +670,10 @@ rb_if_indextoname(const char *succ_prefix, const char *fail_prefix, unsigned int { #if defined(HAVE_IF_INDEXTONAME) char ifbuf[IFNAMSIZ]; - if (if_indextoname(ifindex, ifbuf) == NULL) - return snprintf(buf, len, "%s%u", fail_prefix, ifindex); - else + if (if_indextoname(ifindex, ifbuf)) return snprintf(buf, len, "%s%s", succ_prefix, ifbuf); + else + return snprintf(buf, len, "%s%u", fail_prefix, ifindex); #else # ifndef IFNAMSIZ # define IFNAMSIZ (sizeof(unsigned int)*3+1) @@ -1059,16 +1059,16 @@ inspect_tcp_info(int level, int optname, VALUE data, VALUE ret) rb_str_catf(ret, " fackets=%u", s.tcpi_fackets); #endif #ifdef HAVE_STRUCT_TCP_INFO_TCPI_LAST_DATA_SENT - inspect_tcpi_last_data_sent(ret, s.tcpi_last_data_sent); + inspect_tcpi_last_data_sent(ret, s.tcpi_last_data_sent); #endif #ifdef HAVE_STRUCT_TCP_INFO_TCPI_LAST_ACK_SENT - inspect_tcpi_last_ack_sent(ret, s.tcpi_last_ack_sent); + inspect_tcpi_last_ack_sent(ret, s.tcpi_last_ack_sent); #endif #ifdef HAVE_STRUCT_TCP_INFO_TCPI_LAST_DATA_RECV - inspect_tcpi_last_data_recv(ret, s.tcpi_last_data_recv); + inspect_tcpi_last_data_recv(ret, s.tcpi_last_data_recv); #endif #ifdef HAVE_STRUCT_TCP_INFO_TCPI_LAST_ACK_RECV - inspect_tcpi_last_ack_recv(ret, s.tcpi_last_ack_recv); + inspect_tcpi_last_ack_recv(ret, s.tcpi_last_ack_recv); #endif #ifdef HAVE_STRUCT_TCP_INFO_TCPI_PMTU rb_str_catf(ret, " pmtu=%u", s.tcpi_pmtu); @@ -1077,10 +1077,10 @@ inspect_tcp_info(int level, int optname, VALUE data, VALUE ret) rb_str_catf(ret, " rcv_ssthresh=%u", s.tcpi_rcv_ssthresh); #endif #ifdef HAVE_STRUCT_TCP_INFO_TCPI_RTT - inspect_tcpi_rtt(ret, s.tcpi_rtt); + inspect_tcpi_rtt(ret, s.tcpi_rtt); #endif #ifdef HAVE_STRUCT_TCP_INFO_TCPI_RTTVAR - inspect_tcpi_rttvar(ret, s.tcpi_rttvar); + inspect_tcpi_rttvar(ret, s.tcpi_rttvar); #endif #ifdef HAVE_STRUCT_TCP_INFO_TCPI_SND_SSTHRESH rb_str_catf(ret, " snd_ssthresh=%u", s.tcpi_snd_ssthresh); @@ -1150,7 +1150,7 @@ inspect_peercred(int level, int optname, VALUE data, VALUE ret) RUBY_SOCK_PEERCRED cred; memcpy(&cred, RSTRING_PTR(data), sizeof(RUBY_SOCK_PEERCRED)); rb_str_catf(ret, " pid=%u euid=%u egid=%u", - (unsigned)cred.pid, (unsigned)cred.uid, (unsigned)cred.gid); + (unsigned)cred.pid, (unsigned)cred.uid, (unsigned)cred.gid); rb_str_cat2(ret, " (ucred)"); return 1; } @@ -1171,14 +1171,14 @@ inspect_local_peercred(int level, int optname, VALUE data, VALUE ret) return 0; rb_str_catf(ret, " version=%u", cred.cr_version); rb_str_catf(ret, " euid=%u", cred.cr_uid); - if (cred.cr_ngroups) { - int i; - const char *sep = " groups="; - for (i = 0; i < cred.cr_ngroups; i++) { - rb_str_catf(ret, "%s%u", sep, cred.cr_groups[i]); - sep = ","; - } - } + if (cred.cr_ngroups) { + int i; + const char *sep = " groups="; + for (i = 0; i < cred.cr_ngroups; i++) { + rb_str_catf(ret, "%s%u", sep, cred.cr_groups[i]); + sep = ","; + } + } rb_str_cat2(ret, " (xucred)"); return 1; } @@ -1216,42 +1216,42 @@ sockopt_inspect(VALUE self) family_id = rsock_intern_family_noprefix(family); if (family_id) - rb_str_catf(ret, " %s", rb_id2name(family_id)); + rb_str_catf(ret, " %s", rb_id2name(family_id)); else rb_str_catf(ret, " family:%d", family); if (level == SOL_SOCKET) { rb_str_cat2(ret, " SOCKET"); - optname_id = rsock_intern_so_optname(optname); - if (optname_id) - rb_str_catf(ret, " %s", rb_id2name(optname_id)); - else - rb_str_catf(ret, " optname:%d", optname); + optname_id = rsock_intern_so_optname(optname); + if (optname_id) + rb_str_catf(ret, " %s", rb_id2name(optname_id)); + else + rb_str_catf(ret, " optname:%d", optname); } -#ifdef HAVE_SYS_UN_H +#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN else if (family == AF_UNIX) { - rb_str_catf(ret, " level:%d", level); + rb_str_catf(ret, " level:%d", level); - optname_id = rsock_intern_local_optname(optname); - if (optname_id) - rb_str_catf(ret, " %s", rb_id2name(optname_id)); - else - rb_str_catf(ret, " optname:%d", optname); + optname_id = rsock_intern_local_optname(optname); + if (optname_id) + rb_str_catf(ret, " %s", rb_id2name(optname_id)); + else + rb_str_catf(ret, " optname:%d", optname); } #endif else if (IS_IP_FAMILY(family)) { - level_id = rsock_intern_iplevel(level); - if (level_id) - rb_str_catf(ret, " %s", rb_id2name(level_id)); - else - rb_str_catf(ret, " level:%d", level); - - v = optname_to_sym(level, optname); - if (SYMBOL_P(v)) - rb_str_catf(ret, " %"PRIsVALUE, rb_sym2str(v)); - else - rb_str_catf(ret, " optname:%d", optname); + level_id = rsock_intern_iplevel(level); + if (level_id) + rb_str_catf(ret, " %s", rb_id2name(level_id)); + else + rb_str_catf(ret, " level:%d", level); + + v = optname_to_sym(level, optname); + if (SYMBOL_P(v)) + rb_str_catf(ret, " %"PRIsVALUE, rb_sym2str(v)); + else + rb_str_catf(ret, " optname:%d", optname); } else { rb_str_catf(ret, " level:%d", level); @@ -1393,7 +1393,7 @@ sockopt_inspect(VALUE self) } break; -#ifdef HAVE_SYS_UN_H +#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN case AF_UNIX: switch (level) { case 0: diff --git a/ext/socket/raddrinfo.c b/ext/socket/raddrinfo.c index 1054d0440d..6cdf5c6abc 100644 --- a/ext/socket/raddrinfo.c +++ b/ext/socket/raddrinfo.c @@ -10,6 +10,22 @@ #include "rubysocket.h" +// GETADDRINFO_IMPL == 0 : call getaddrinfo/getnameinfo directly +// GETADDRINFO_IMPL == 1 : call getaddrinfo/getnameinfo without gvl (but uncancellable) +// GETADDRINFO_IMPL == 2 : call getaddrinfo/getnameinfo in a dedicated pthread +// (and if the call is interrupted, the pthread is detached) + +#ifndef GETADDRINFO_IMPL +# ifdef GETADDRINFO_EMU +# define GETADDRINFO_IMPL 0 +# elif !defined(HAVE_PTHREAD_CREATE) || !defined(HAVE_PTHREAD_DETACH) || defined(__MINGW32__) || defined(__MINGW64__) +# define GETADDRINFO_IMPL 1 +# else +# define GETADDRINFO_IMPL 2 +# include "ruby/thread_native.h" +# endif +#endif + #if defined(INET6) && (defined(LOOKUP_ORDER_HACK_INET) || defined(LOOKUP_ORDER_HACK_INET6)) #define LOOKUP_ORDERS (sizeof(lookup_order_table) / sizeof(lookup_order_table[0])) static const int lookup_order_table[] = { @@ -24,28 +40,28 @@ static const int lookup_order_table[] = { static int ruby_getaddrinfo(const char *nodename, const char *servname, - const struct addrinfo *hints, struct addrinfo **res) + const struct addrinfo *hints, struct addrinfo **res) { struct addrinfo tmp_hints; int i, af, error; if (hints->ai_family != PF_UNSPEC) { - return getaddrinfo(nodename, servname, hints, res); + return getaddrinfo(nodename, servname, hints, res); } for (i = 0; i < LOOKUP_ORDERS; i++) { - af = lookup_order_table[i]; - MEMCPY(&tmp_hints, hints, struct addrinfo, 1); - tmp_hints.ai_family = af; - error = getaddrinfo(nodename, servname, &tmp_hints, res); - if (error) { - if (tmp_hints.ai_family == PF_UNSPEC) { - break; - } - } - else { - break; - } + af = lookup_order_table[i]; + MEMCPY(&tmp_hints, hints, struct addrinfo, 1); + tmp_hints.ai_family = af; + error = getaddrinfo(nodename, servname, &tmp_hints, res); + if (error) { + if (tmp_hints.ai_family == PF_UNSPEC) { + break; + } + } + else { + break; + } } return error; @@ -56,17 +72,17 @@ ruby_getaddrinfo(const char *nodename, const char *servname, #if defined(_AIX) static int ruby_getaddrinfo__aix(const char *nodename, const char *servname, - const struct addrinfo *hints, struct addrinfo **res) + const struct addrinfo *hints, struct addrinfo **res) { int error = getaddrinfo(nodename, servname, hints, res); struct addrinfo *r; if (error) - return error; + return error; for (r = *res; r != NULL; r = r->ai_next) { - if (r->ai_addr->sa_family == 0) - r->ai_addr->sa_family = r->ai_family; - if (r->ai_addr->sa_len == 0) - r->ai_addr->sa_len = r->ai_addrlen; + if (r->ai_addr->sa_family == 0) + r->ai_addr->sa_family = r->ai_family; + if (r->ai_addr->sa_len == 0) + r->ai_addr->sa_len = r->ai_addrlen; } return 0; } @@ -74,21 +90,21 @@ ruby_getaddrinfo__aix(const char *nodename, const char *servname, #define getaddrinfo(node,serv,hints,res) ruby_getaddrinfo__aix((node),(serv),(hints),(res)) static int ruby_getnameinfo__aix(const struct sockaddr *sa, size_t salen, - char *host, size_t hostlen, - char *serv, size_t servlen, int flags) + char *host, size_t hostlen, + char *serv, size_t servlen, int flags) { struct sockaddr_in6 *sa6; u_int32_t *a6; if (sa->sa_family == AF_INET6) { - sa6 = (struct sockaddr_in6 *)sa; - a6 = sa6->sin6_addr.u6_addr.u6_addr32; + sa6 = (struct sockaddr_in6 *)sa; + a6 = sa6->sin6_addr.u6_addr.u6_addr32; - if (a6[0] == 0 && a6[1] == 0 && a6[2] == 0 && a6[3] == 0) { - strncpy(host, "::", hostlen); - snprintf(serv, servlen, "%d", sa6->sin6_port); - return 0; - } + if (a6[0] == 0 && a6[1] == 0 && a6[2] == 0 && a6[3] == 0) { + strncpy(host, "::", hostlen); + snprintf(serv, servlen, "%d", sa6->sin6_port); + return 0; + } } return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags); } @@ -102,7 +118,7 @@ static int str_is_number(const char *); #if defined(__APPLE__) static int ruby_getaddrinfo__darwin(const char *nodename, const char *servname, - const struct addrinfo *hints, struct addrinfo **res) + const struct addrinfo *hints, struct addrinfo **res) { /* fix [ruby-core:29427] */ const char *tmp_servname; @@ -112,12 +128,12 @@ ruby_getaddrinfo__darwin(const char *nodename, const char *servname, tmp_servname = servname; MEMCPY(&tmp_hints, hints, struct addrinfo, 1); if (nodename && servname) { - if (str_is_number(tmp_servname) && atoi(servname) == 0) { - tmp_servname = NULL; + if (str_is_number(tmp_servname) && atoi(servname) == 0) { + tmp_servname = NULL; #ifdef AI_NUMERICSERV - if (tmp_hints.ai_flags) tmp_hints.ai_flags &= ~AI_NUMERICSERV; + if (tmp_hints.ai_flags) tmp_hints.ai_flags &= ~AI_NUMERICSERV; #endif - } + } } error = getaddrinfo(nodename, tmp_servname, &tmp_hints, res); @@ -173,32 +189,6 @@ parse_numeric_port(const char *service, int *portp) } #endif -#ifndef GETADDRINFO_EMU -struct getaddrinfo_arg -{ - const char *node; - const char *service; - const struct addrinfo *hints; - struct addrinfo **res; -}; - -static void * -nogvl_getaddrinfo(void *arg) -{ - int ret; - struct getaddrinfo_arg *ptr = arg; - ret = getaddrinfo(ptr->node, ptr->service, ptr->hints, ptr->res); -#ifdef __linux__ - /* On Linux (mainly Ubuntu 13.04) /etc/nsswitch.conf has mdns4 and - * it cause getaddrinfo to return EAI_SYSTEM/ENOENT. [ruby-list:49420] - */ - if (ret == EAI_SYSTEM && errno == ENOENT) - ret = EAI_NONAME; -#endif - return (void *)(VALUE)ret; -} -#endif - static int numeric_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, @@ -212,15 +202,15 @@ numeric_getaddrinfo(const char *node, const char *service, int port; if (node && parse_numeric_port(service, &port)) { - static const struct { - int socktype; - int protocol; - } list[] = { - { SOCK_STREAM, IPPROTO_TCP }, - { SOCK_DGRAM, IPPROTO_UDP }, - { SOCK_RAW, 0 } - }; - struct addrinfo *ai = NULL; + static const struct { + int socktype; + int protocol; + } list[] = { + { SOCK_STREAM, IPPROTO_TCP }, + { SOCK_DGRAM, IPPROTO_UDP }, + { SOCK_RAW, 0 } + }; + struct addrinfo *ai = NULL; int hint_family = hints ? hints->ai_family : PF_UNSPEC; int hint_socktype = hints ? hints->ai_socktype : 0; int hint_protocol = hints ? hints->ai_protocol : 0; @@ -284,59 +274,372 @@ numeric_getaddrinfo(const char *node, const char *service, return EAI_FAIL; } -int -rb_getaddrinfo(const char *node, const char *service, - const struct addrinfo *hints, - struct rb_addrinfo **res) +void +rb_freeaddrinfo(struct rb_addrinfo *ai) +{ + if (!ai->allocated_by_malloc) { + if (ai->ai) freeaddrinfo(ai->ai); + } + else { + struct addrinfo *ai1, *ai2; + ai1 = ai->ai; + while (ai1) { + ai2 = ai1->ai_next; + xfree(ai1->ai_addr); + xfree(ai1); + ai1 = ai2; + } + } + xfree(ai); +} + +static int +rsock_value_timeout_to_msec(VALUE timeout) +{ + double seconds = NUM2DBL(timeout); + if (seconds < 0) rb_raise(rb_eArgError, "timeout must not be negative"); + + double msec = seconds * 1000.0; + if (msec > UINT_MAX) rb_raise(rb_eArgError, "timeout too large"); + + return (unsigned int)(msec + 0.5); +} + +#if GETADDRINFO_IMPL == 0 + +static int +rb_getaddrinfo(const char *hostp, const char *portp, const struct addrinfo *hints, struct addrinfo **ai, int _timeout) +{ + return getaddrinfo(hostp, portp, hints, ai); +} + +#elif GETADDRINFO_IMPL == 1 + +struct getaddrinfo_arg +{ + const char *node; + const char *service; + const struct addrinfo *hints; + struct addrinfo **res; +}; + +static void * +nogvl_getaddrinfo(void *arg) { - struct addrinfo *ai; int ret; - int allocated_by_malloc = 0; + struct getaddrinfo_arg *ptr = arg; + ret = getaddrinfo(ptr->node, ptr->service, ptr->hints, ptr->res); +#ifdef __linux__ + /* On Linux (mainly Ubuntu 13.04) /etc/nsswitch.conf has mdns4 and + * it cause getaddrinfo to return EAI_SYSTEM/ENOENT. [ruby-list:49420] + */ + if (ret == EAI_SYSTEM && errno == ENOENT) + ret = EAI_NONAME; +#endif + return (void *)(VALUE)ret; +} + +static void * +fork_safe_getaddrinfo(void *arg) +{ + return rb_thread_prevent_fork(nogvl_getaddrinfo, arg); +} + +static int +rb_getaddrinfo(const char *hostp, const char *portp, const struct addrinfo *hints, struct addrinfo **ai, int _timeout) +{ + struct getaddrinfo_arg arg; + MEMZERO(&arg, struct getaddrinfo_arg, 1); + arg.node = hostp; + arg.service = portp; + arg.hints = hints; + arg.res = ai; + return (int)(VALUE)rb_thread_call_without_gvl(fork_safe_getaddrinfo, &arg, RUBY_UBF_IO, 0); +} + +#elif GETADDRINFO_IMPL == 2 + +struct getaddrinfo_arg +{ + char *node, *service; + struct addrinfo hints; + struct addrinfo *ai; + int err, gai_errno, refcount, done, cancelled, timedout; + rb_nativethread_lock_t lock; + rb_nativethread_cond_t cond; + int timeout; +}; + +static struct getaddrinfo_arg * +allocate_getaddrinfo_arg(const char *hostp, const char *portp, const struct addrinfo *hints, int timeout) +{ + size_t hostp_offset = sizeof(struct getaddrinfo_arg); + size_t portp_offset = hostp_offset + (hostp ? strlen(hostp) + 1 : 0); + size_t bufsize = portp_offset + (portp ? strlen(portp) + 1 : 0); - ret = numeric_getaddrinfo(node, service, hints, &ai); - if (ret == 0) - allocated_by_malloc = 1; + char *buf = malloc(bufsize); + if (!buf) { + rb_gc(); + buf = malloc(bufsize); + if (!buf) return NULL; + } + struct getaddrinfo_arg *arg = (struct getaddrinfo_arg *)buf; + + if (hostp) { + arg->node = buf + hostp_offset; + memcpy(arg->node, hostp, portp_offset - hostp_offset); + } else { -#ifdef GETADDRINFO_EMU - ret = getaddrinfo(node, service, hints, &ai); -#else - struct getaddrinfo_arg arg; - MEMZERO(&arg, struct getaddrinfo_arg, 1); - arg.node = node; - arg.service = service; - arg.hints = hints; - arg.res = &ai; - ret = (int)(VALUE)rb_thread_call_without_gvl(nogvl_getaddrinfo, &arg, RUBY_UBF_IO, 0); + arg->node = NULL; + } + + if (portp) { + arg->service = buf + portp_offset; + memcpy(arg->service, portp, bufsize - portp_offset); + } + else { + arg->service = NULL; + } + + arg->hints = *hints; + arg->ai = NULL; + + arg->refcount = 2; + arg->done = arg->cancelled = arg->timedout = 0; + arg->timeout = timeout; + + rb_nativethread_lock_initialize(&arg->lock); + rb_native_cond_initialize(&arg->cond); + + return arg; +} + +static void +free_getaddrinfo_arg(struct getaddrinfo_arg *arg) +{ + rb_native_cond_destroy(&arg->cond); + rb_nativethread_lock_destroy(&arg->lock); + free(arg); +} + +static void * +do_getaddrinfo(void *ptr) +{ + struct getaddrinfo_arg *arg = (struct getaddrinfo_arg *)ptr; + + int err, gai_errno; + err = getaddrinfo(arg->node, arg->service, &arg->hints, &arg->ai); + gai_errno = errno; +#ifdef __linux__ + /* On Linux (mainly Ubuntu 13.04) /etc/nsswitch.conf has mdns4 and + * it cause getaddrinfo to return EAI_SYSTEM/ENOENT. [ruby-list:49420] + */ + if (err == EAI_SYSTEM && errno == ENOENT) + err = EAI_NONAME; #endif + + int need_free = 0; + rb_nativethread_lock_lock(&arg->lock); + { + arg->err = err; + arg->gai_errno = gai_errno; + if (arg->cancelled) { + if (arg->ai) freeaddrinfo(arg->ai); + } + else { + arg->done = 1; + rb_native_cond_signal(&arg->cond); + } + if (--arg->refcount == 0) need_free = 1; } + rb_nativethread_lock_unlock(&arg->lock); + + if (need_free) free_getaddrinfo_arg(arg); + return 0; +} + +static void * +wait_getaddrinfo(void *ptr) +{ + struct getaddrinfo_arg *arg = (struct getaddrinfo_arg *)ptr; + rb_nativethread_lock_lock(&arg->lock); + while (!arg->done && !arg->cancelled) { + long msec = arg->timeout; + if (msec == 0) { + arg->cancelled = 1; + arg->timedout = 1; + } else if (msec > 0) { + rb_native_cond_timedwait(&arg->cond, &arg->lock, msec); + if (!arg->done) { + arg->cancelled = 1; + arg->timedout = 1; + } + } else { + rb_native_cond_wait(&arg->cond, &arg->lock); + } + } + rb_nativethread_lock_unlock(&arg->lock); + return 0; +} + +static void +cancel_getaddrinfo(void *ptr) +{ + struct getaddrinfo_arg *arg = (struct getaddrinfo_arg *)ptr; + rb_nativethread_lock_lock(&arg->lock); + { + arg->cancelled = 1; + rb_native_cond_signal(&arg->cond); + } + rb_nativethread_lock_unlock(&arg->lock); +} + +int +raddrinfo_pthread_create(pthread_t *th, void *(*start_routine) (void *), void *arg) +{ + int limit = 3, ret; + int saved_errno; +#ifdef HAVE_PTHREAD_ATTR_SETDETACHSTATE + pthread_attr_t attr; + pthread_attr_t *attr_p = &attr; + int err; + int init_retries = 0; + int init_retries_max = 3; +retry_attr_init: + if ((err = pthread_attr_init(attr_p)) != 0) { + if (err == ENOMEM && init_retries < init_retries_max) { + init_retries++; + rb_gc(); + goto retry_attr_init; + } + return err; + } + if ((err = pthread_attr_setdetachstate(attr_p, PTHREAD_CREATE_DETACHED)) != 0) { + saved_errno = errno; + pthread_attr_destroy(attr_p); + errno = saved_errno; + return err; // EINVAL - shouldn't happen + } +#else + pthread_attr_t *attr_p = NULL; +#endif + do { + // It is said that pthread_create may fail spuriously, so we follow the JDK and retry several times. + // + // https://bugs.openjdk.org/browse/JDK-8268605 + // https://github.com/openjdk/jdk/commit/e35005d5ce383ddd108096a3079b17cb0bcf76f1 + ret = pthread_create(th, attr_p, start_routine, arg); + } while (ret == EAGAIN && limit-- > 0); +#ifdef HAVE_PTHREAD_ATTR_SETDETACHSTATE + saved_errno = errno; + pthread_attr_destroy(attr_p); + if (ret != 0) { + errno = saved_errno; + } +#else if (ret == 0) { - *res = (struct rb_addrinfo *)xmalloc(sizeof(struct rb_addrinfo)); - (*res)->allocated_by_malloc = allocated_by_malloc; - (*res)->ai = ai; + pthread_detach(th); // this can race with shutdown routine of thread in some glibc versions } +#endif return ret; } -void -rb_freeaddrinfo(struct rb_addrinfo *ai) +static void * +fork_safe_do_getaddrinfo(void *ptr) { - if (!ai->allocated_by_malloc) - freeaddrinfo(ai->ai); - else { - struct addrinfo *ai1, *ai2; - ai1 = ai->ai; - while (ai1) { - ai2 = ai1->ai_next; - xfree(ai1->ai_addr); - xfree(ai1); - ai1 = ai2; + return rb_thread_prevent_fork(do_getaddrinfo, ptr); +} + +static int +rb_getaddrinfo(const char *hostp, const char *portp, const struct addrinfo *hints, struct addrinfo **ai, int timeout) +{ + int retry; + struct getaddrinfo_arg *arg; + int err = 0, gai_errno = 0, timedout = 0; + +start: + retry = 0; + + arg = allocate_getaddrinfo_arg(hostp, portp, hints, timeout); + if (!arg) { + return EAI_MEMORY; + } + + pthread_t th; + if (raddrinfo_pthread_create(&th, fork_safe_do_getaddrinfo, arg) != 0) { + int err = errno; + free_getaddrinfo_arg(arg); + errno = err; + return EAI_SYSTEM; + } + + rb_thread_call_without_gvl2(wait_getaddrinfo, arg, cancel_getaddrinfo, arg); + + int need_free = 0; + rb_nativethread_lock_lock(&arg->lock); + { + if (arg->done) { + err = arg->err; + gai_errno = arg->gai_errno; + if (err == 0) *ai = arg->ai; + } + else if (arg->cancelled) { + retry = 1; + timedout = arg->timedout; + } + else { + // If already interrupted, rb_thread_call_without_gvl2 may return without calling wait_getaddrinfo. + // In this case, it could be !arg->done && !arg->cancelled. + arg->cancelled = 1; // to make do_getaddrinfo call freeaddrinfo + retry = 1; } + if (--arg->refcount == 0) need_free = 1; } - xfree(ai); + rb_nativethread_lock_unlock(&arg->lock); + + if (need_free) free_getaddrinfo_arg(arg); + + if (timedout) { + if (arg->ai) { + rsock_raise_user_specified_timeout(arg->ai, Qnil, Qnil); + } else { + VALUE host = rb_str_new_cstr(hostp); + VALUE port = rb_str_new_cstr(portp); + rsock_raise_user_specified_timeout(NULL, host, port); + } + } + + // If the current thread is interrupted by asynchronous exception, the following raises the exception. + // But if the current thread is interrupted by timer thread, the following returns; we need to manually retry. + rb_thread_check_ints(); + if (retry) goto start; + + /* Because errno is threadlocal, the errno value we got from the call to getaddrinfo() in the thread + * (in case of EAI_SYSTEM return value) is not propagated to the caller of _this_ function. Set errno + * explicitly, as round-tripped through struct getaddrinfo_arg, to deal with that */ + if (gai_errno) errno = gai_errno; + return err; } -#ifndef GETADDRINFO_EMU +#endif + +#define GETNAMEINFO_WONT_BLOCK(host, serv, flags) \ + ((!(host) || ((flags) & NI_NUMERICHOST)) && \ + (!(serv) || ((flags) & NI_NUMERICSERV))) + +#if GETADDRINFO_IMPL == 0 + +int +rb_getnameinfo(const struct sockaddr *sa, socklen_t salen, + char *host, size_t hostlen, + char *serv, size_t servlen, int flags) +{ + return getnameinfo(sa, salen, host, (socklen_t)hostlen, serv, (socklen_t)servlen, flags); +} + +#elif GETADDRINFO_IMPL == 1 + struct getnameinfo_arg { const struct sockaddr *sa; @@ -353,20 +656,19 @@ nogvl_getnameinfo(void *arg) { struct getnameinfo_arg *ptr = arg; return (void *)(VALUE)getnameinfo(ptr->sa, ptr->salen, - ptr->host, (socklen_t)ptr->hostlen, - ptr->serv, (socklen_t)ptr->servlen, - ptr->flags); + ptr->host, (socklen_t)ptr->hostlen, + ptr->serv, (socklen_t)ptr->servlen, + ptr->flags); } -#endif - int rb_getnameinfo(const struct sockaddr *sa, socklen_t salen, - char *host, size_t hostlen, - char *serv, size_t servlen, int flags) + char *host, size_t hostlen, + char *serv, size_t servlen, int flags) { -#ifdef GETADDRINFO_EMU - return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags); -#else + if (GETNAMEINFO_WONT_BLOCK(host, serv, flags)) { + return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags); + } + struct getnameinfo_arg arg; int ret; arg.sa = sa; @@ -378,17 +680,190 @@ rb_getnameinfo(const struct sockaddr *sa, socklen_t salen, arg.flags = flags; ret = (int)(VALUE)rb_thread_call_without_gvl(nogvl_getnameinfo, &arg, RUBY_UBF_IO, 0); return ret; -#endif +} + +#elif GETADDRINFO_IMPL == 2 + +struct getnameinfo_arg +{ + struct sockaddr *sa; + socklen_t salen; + int flags; + char *host; + size_t hostlen; + char *serv; + size_t servlen; + int err, gni_errno, refcount, done, cancelled; + rb_nativethread_lock_t lock; + rb_nativethread_cond_t cond; +}; + +static struct getnameinfo_arg * +allocate_getnameinfo_arg(const struct sockaddr *sa, socklen_t salen, size_t hostlen, size_t servlen, int flags) +{ + size_t sa_offset = sizeof(struct getnameinfo_arg); + size_t host_offset = sa_offset + salen; + size_t serv_offset = host_offset + hostlen; + size_t bufsize = serv_offset + servlen; + + char *buf = malloc(bufsize); + if (!buf) { + rb_gc(); + buf = malloc(bufsize); + if (!buf) return NULL; + } + struct getnameinfo_arg *arg = (struct getnameinfo_arg *)buf; + + arg->sa = (struct sockaddr *)(buf + sa_offset); + memcpy(arg->sa, sa, salen); + arg->salen = salen; + arg->host = buf + host_offset; + arg->hostlen = hostlen; + arg->serv = buf + serv_offset; + arg->servlen = servlen; + arg->flags = flags; + + arg->refcount = 2; + arg->done = arg->cancelled = 0; + + rb_nativethread_lock_initialize(&arg->lock); + rb_native_cond_initialize(&arg->cond); + + return arg; } static void +free_getnameinfo_arg(struct getnameinfo_arg *arg) +{ + rb_native_cond_destroy(&arg->cond); + rb_nativethread_lock_destroy(&arg->lock); + + free(arg); +} + +static void * +do_getnameinfo(void *ptr) +{ + struct getnameinfo_arg *arg = (struct getnameinfo_arg *)ptr; + + int err, gni_errno; + err = getnameinfo(arg->sa, arg->salen, arg->host, (socklen_t)arg->hostlen, arg->serv, (socklen_t)arg->servlen, arg->flags); + gni_errno = errno; + + int need_free = 0; + rb_nativethread_lock_lock(&arg->lock); + arg->err = err; + arg->gni_errno = gni_errno; + if (!arg->cancelled) { + arg->done = 1; + rb_native_cond_signal(&arg->cond); + } + if (--arg->refcount == 0) need_free = 1; + rb_nativethread_lock_unlock(&arg->lock); + + if (need_free) free_getnameinfo_arg(arg); + + return 0; +} + +static void * +wait_getnameinfo(void *ptr) +{ + struct getnameinfo_arg *arg = (struct getnameinfo_arg *)ptr; + rb_nativethread_lock_lock(&arg->lock); + while (!arg->done && !arg->cancelled) { + rb_native_cond_wait(&arg->cond, &arg->lock); + } + rb_nativethread_lock_unlock(&arg->lock); + return 0; +} + +static void +cancel_getnameinfo(void *ptr) +{ + struct getnameinfo_arg *arg = (struct getnameinfo_arg *)ptr; + rb_nativethread_lock_lock(&arg->lock); + arg->cancelled = 1; + rb_native_cond_signal(&arg->cond); + rb_nativethread_lock_unlock(&arg->lock); +} + +int +rb_getnameinfo(const struct sockaddr *sa, socklen_t salen, + char *host, size_t hostlen, + char *serv, size_t servlen, int flags) +{ + int retry; + struct getnameinfo_arg *arg; + int err = 0, gni_errno = 0; + + if (GETNAMEINFO_WONT_BLOCK(host, serv, flags)) { + return getnameinfo(sa, salen, host, (socklen_t)hostlen, serv, (socklen_t)servlen, flags); + } + +start: + retry = 0; + + arg = allocate_getnameinfo_arg(sa, salen, hostlen, servlen, flags); + if (!arg) { + return EAI_MEMORY; + } + + pthread_t th; + if (raddrinfo_pthread_create(&th, do_getnameinfo, arg) != 0) { + int err = errno; + free_getnameinfo_arg(arg); + errno = err; + return EAI_SYSTEM; + } + + rb_thread_call_without_gvl2(wait_getnameinfo, arg, cancel_getnameinfo, arg); + + int need_free = 0; + rb_nativethread_lock_lock(&arg->lock); + if (arg->done) { + err = arg->err; + gni_errno = arg->gni_errno; + if (err == 0) { + if (host) memcpy(host, arg->host, hostlen); + if (serv) memcpy(serv, arg->serv, servlen); + } + } + else if (arg->cancelled) { + retry = 1; + } + else { + // If already interrupted, rb_thread_call_without_gvl2 may return without calling wait_getnameinfo. + // In this case, it could be !arg->done && !arg->cancelled. + arg->cancelled = 1; + retry = 1; + } + if (--arg->refcount == 0) need_free = 1; + rb_nativethread_lock_unlock(&arg->lock); + + if (need_free) free_getnameinfo_arg(arg); + + // If the current thread is interrupted by asynchronous exception, the following raises the exception. + // But if the current thread is interrupted by timer thread, the following returns; we need to manually retry. + rb_thread_check_ints(); + if (retry) goto start; + + /* Make sure we copy the thread-local errno value from the getnameinfo thread back to this thread, so + * calling code sees the correct errno */ + if (gni_errno) errno = gni_errno; + return err; +} + +#endif + +static void make_ipaddr0(struct sockaddr *addr, socklen_t addrlen, char *buf, size_t buflen) { int error; error = rb_getnameinfo(addr, addrlen, buf, buflen, NULL, 0, NI_NUMERICHOST); if (error) { - rsock_raise_socket_error("getnameinfo", error); + rsock_raise_resolution_error("getnameinfo", error); } } @@ -429,13 +904,9 @@ str_is_number(const char *p) #define str_equal(ptr, len, name) \ ((ptr)[0] == name[0] && \ rb_strlen_lit(name) == (len) && memcmp(ptr, name, len) == 0) -#define SafeStringValueCStr(v) do {\ - StringValueCStr(v);\ - rb_check_safe_obj(v);\ -} while(0) -static char* -host_str(VALUE host, char *hbuf, size_t hbuflen, int *flags_ptr) +char* +raddrinfo_host_str(VALUE host, char *hbuf, size_t hbuflen, int *flags_ptr) { if (NIL_P(host)) { return NULL; @@ -451,7 +922,7 @@ host_str(VALUE host, char *hbuf, size_t hbuflen, int *flags_ptr) const char *name; size_t len; - SafeStringValueCStr(host); + StringValueCStr(host); RSTRING_GETMEM(host, name, len); if (!len || str_equal(name, len, "<any>")) { make_inetaddr(INADDR_ANY, hbuf, hbuflen); @@ -473,8 +944,8 @@ host_str(VALUE host, char *hbuf, size_t hbuflen, int *flags_ptr) } } -static char* -port_str(VALUE port, char *pbuf, size_t pbuflen, int *flags_ptr) +char* +raddrinfo_port_str(VALUE port, char *pbuf, size_t pbuflen, int *flags_ptr) { if (NIL_P(port)) { return 0; @@ -490,7 +961,7 @@ port_str(VALUE port, char *pbuf, size_t pbuflen, int *flags_ptr) const char *serv; size_t len; - SafeStringValueCStr(port); + StringValueCStr(port); RSTRING_GETMEM(port, serv, len); if (len >= pbuflen) { rb_raise(rb_eArgError, "service name too long (%"PRIuSIZE")", @@ -502,29 +973,107 @@ port_str(VALUE port, char *pbuf, size_t pbuflen, int *flags_ptr) } } +static int +rb_scheduler_getaddrinfo(VALUE scheduler, VALUE host, const char *service, + const struct addrinfo *hints, struct rb_addrinfo **res) +{ + int error, res_allocated = 0, _additional_flags = 0; + long i, len; + struct addrinfo *ai, *ai_tail = NULL; + char *hostp; + char _hbuf[NI_MAXHOST]; + VALUE ip_addresses_array, ip_address; + + ip_addresses_array = rb_fiber_scheduler_address_resolve(scheduler, host); + + if (ip_addresses_array == Qundef) { + // Returns EAI_FAIL if the scheduler hook is not implemented: + return EAI_FAIL; + } else if (ip_addresses_array == Qnil) { + len = 0; + } else { + len = RARRAY_LEN(ip_addresses_array); + } + + for(i=0; i<len; i++) { + ip_address = rb_ary_entry(ip_addresses_array, i); + hostp = raddrinfo_host_str(ip_address, _hbuf, sizeof(_hbuf), &_additional_flags); + error = numeric_getaddrinfo(hostp, service, hints, &ai); + if (error == 0) { + if (!res_allocated) { + res_allocated = 1; + *res = (struct rb_addrinfo *)xmalloc(sizeof(struct rb_addrinfo)); + (*res)->allocated_by_malloc = 1; + (*res)->ai = ai; + ai_tail = ai; + } else { + while (ai_tail->ai_next) { + ai_tail = ai_tail->ai_next; + } + ai_tail->ai_next = ai; + ai_tail = ai; + } + } + } + + if (res_allocated) { // At least one valid result. + return 0; + } else { + return EAI_NONAME; + } +} + struct rb_addrinfo* -rsock_getaddrinfo(VALUE host, VALUE port, struct addrinfo *hints, int socktype_hack) +rsock_getaddrinfo(VALUE host, VALUE port, struct addrinfo *hints, int socktype_hack, VALUE timeout) { struct rb_addrinfo* res = NULL; + struct addrinfo *ai; char *hostp, *portp; - int error; + int error = 0; char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV]; int additional_flags = 0; - hostp = host_str(host, hbuf, sizeof(hbuf), &additional_flags); - portp = port_str(port, pbuf, sizeof(pbuf), &additional_flags); + hostp = raddrinfo_host_str(host, hbuf, sizeof(hbuf), &additional_flags); + portp = raddrinfo_port_str(port, pbuf, sizeof(pbuf), &additional_flags); if (socktype_hack && hints->ai_socktype == 0 && str_is_number(portp)) { hints->ai_socktype = SOCK_DGRAM; } hints->ai_flags |= additional_flags; - error = rb_getaddrinfo(hostp, portp, hints, &res); + error = numeric_getaddrinfo(hostp, portp, hints, &ai); + if (error == 0) { + res = (struct rb_addrinfo *)xmalloc(sizeof(struct rb_addrinfo)); + res->allocated_by_malloc = 1; + res->ai = ai; + } else { + VALUE scheduler = rb_fiber_scheduler_current(); + int resolved = 0; + + if (scheduler != Qnil && hostp && !(hints->ai_flags & AI_NUMERICHOST)) { + error = rb_scheduler_getaddrinfo(scheduler, host, portp, hints, &res); + + if (error != EAI_FAIL) { + resolved = 1; + } + } + + if (!resolved) { + int t = NIL_P(timeout) ? -1 : rsock_value_timeout_to_msec(timeout); + error = rb_getaddrinfo(hostp, portp, hints, &ai, t); + if (error == 0) { + res = (struct rb_addrinfo *)xmalloc(sizeof(struct rb_addrinfo)); + res->allocated_by_malloc = 0; + res->ai = ai; + } + } + } + if (error) { if (hostp && hostp[strlen(hostp)-1] == '\n') { rb_raise(rb_eSocket, "newline at the end of hostname"); } - rsock_raise_socket_error("getaddrinfo", error); + rsock_raise_resolution_error("getaddrinfo", error); } return res; @@ -538,13 +1087,13 @@ rsock_fd_family(int fd) if (fd < 0 || getsockname(fd, &sa, &sa_len) != 0 || (size_t)sa_len < offsetof(struct sockaddr, sa_family) + sizeof(sa.sa_family)) { - return AF_UNSPEC; + return AF_UNSPEC; } return sa.sa_family; } struct rb_addrinfo* -rsock_addrinfo(VALUE host, VALUE port, int family, int socktype, int flags) +rsock_addrinfo(VALUE host, VALUE port, int family, int socktype, int flags, VALUE timeout) { struct addrinfo hints; @@ -552,7 +1101,7 @@ rsock_addrinfo(VALUE host, VALUE port, int family, int socktype, int flags) hints.ai_family = family; hints.ai_socktype = socktype; hints.ai_flags = flags; - return rsock_getaddrinfo(host, port, &hints, 1); + return rsock_getaddrinfo(host, port, &hints, 1, timeout); } VALUE @@ -569,8 +1118,7 @@ rsock_ipaddr(struct sockaddr *sockaddr, socklen_t sockaddrlen, int norevlookup) family = rb_str_dup(rb_id2str(id)); } else { - sprintf(pbuf, "unknown:%d", sockaddr->sa_family); - family = rb_str_new2(pbuf); + family = rb_sprintf("unknown:%d", sockaddr->sa_family); } addr1 = Qnil; @@ -584,7 +1132,7 @@ rsock_ipaddr(struct sockaddr *sockaddr, socklen_t sockaddrlen, int norevlookup) error = rb_getnameinfo(sockaddr, sockaddrlen, hbuf, sizeof(hbuf), pbuf, sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV); if (error) { - rsock_raise_socket_error("getnameinfo", error); + rsock_raise_resolution_error("getnameinfo", error); } addr2 = rb_str_new2(hbuf); if (addr1 == Qnil) { @@ -596,17 +1144,22 @@ rsock_ipaddr(struct sockaddr *sockaddr, socklen_t sockaddrlen, int norevlookup) return ary; } -#ifdef HAVE_SYS_UN_H -VALUE -rsock_unixpath_str(struct sockaddr_un *sockaddr, socklen_t len) +#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN +static long +unixsocket_len(const struct sockaddr_un *su, socklen_t socklen) { - char *s, *e; - s = sockaddr->sun_path; - e = (char *)sockaddr + len; + const char *s = su->sun_path, *e = (const char*)su + socklen; while (s < e && *(e-1) == '\0') e--; - if (s <= e) - return rb_str_new(s, e-s); + return e - s; +} + +VALUE +rsock_unixpath_str(struct sockaddr_un *sockaddr, socklen_t len) +{ + long n = unixsocket_len(sockaddr, len); + if (n >= 0) + return rb_str_new(sockaddr->sun_path, n); else return rb_str_new2(""); } @@ -623,19 +1176,19 @@ rsock_unix_sockaddr_len(VALUE path) { #ifdef __linux__ if (RSTRING_LEN(path) == 0) { - /* autobind; see unix(7) for details. */ - return (socklen_t) sizeof(sa_family_t); + /* autobind; see unix(7) for details. */ + return (socklen_t) sizeof(sa_family_t); } else if (RSTRING_PTR(path)[0] == '\0') { - /* abstract namespace; see unix(7) for details. */ + /* abstract namespace; see unix(7) for details. */ if (SOCKLEN_MAX - offsetof(struct sockaddr_un, sun_path) < (size_t)RSTRING_LEN(path)) rb_raise(rb_eArgError, "Linux abstract socket too long"); - return (socklen_t) offsetof(struct sockaddr_un, sun_path) + - RSTRING_SOCKLEN(path); + return (socklen_t) offsetof(struct sockaddr_un, sun_path) + + RSTRING_SOCKLEN(path); } else { #endif - return (socklen_t) sizeof(struct sockaddr_un); + return (socklen_t) sizeof(struct sockaddr_un); #ifdef __linux__ } #endif @@ -649,8 +1202,9 @@ struct hostent_arg { }; static VALUE -make_hostent_internal(struct hostent_arg *arg) +make_hostent_internal(VALUE v) { + struct hostent_arg *arg = (void *)v; VALUE host = arg->host; struct addrinfo* addr = arg->addr->ai; VALUE (*ipaddr)(struct sockaddr*, socklen_t) = arg->ipaddr; @@ -667,12 +1221,12 @@ make_hostent_internal(struct hostent_arg *arg) hostp = addr->ai_canonname; } else { - hostp = host_str(host, hbuf, sizeof(hbuf), NULL); + hostp = raddrinfo_host_str(host, hbuf, sizeof(hbuf), NULL); } rb_ary_push(ary, rb_str_new2(hostp)); if (addr->ai_canonname && strlen(addr->ai_canonname) < NI_MAXHOST && - (h = gethostbyname(addr->ai_canonname))) { + (h = gethostbyname(addr->ai_canonname))) { names = rb_ary_new(); if (h->h_aliases != NULL) { for (pch = h->h_aliases; *pch; pch++) { @@ -741,6 +1295,7 @@ addrinfo_memsize(const void *ptr) static const rb_data_type_t addrinfo_type = { "socket/addrinfo", {addrinfo_mark, addrinfo_free, addrinfo_memsize,}, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_FROZEN_SHAREABLE | RUBY_TYPED_WB_PROTECTED, }; static VALUE @@ -778,7 +1333,7 @@ alloc_addrinfo(void) } static void -init_addrinfo(rb_addrinfo_t *rai, struct sockaddr *sa, socklen_t len, +init_addrinfo(VALUE self, rb_addrinfo_t *rai, struct sockaddr *sa, socklen_t len, int pfamily, int socktype, int protocol, VALUE canonname, VALUE inspectname) { @@ -790,8 +1345,8 @@ init_addrinfo(rb_addrinfo_t *rai, struct sockaddr *sa, socklen_t len, rai->pfamily = pfamily; rai->socktype = socktype; rai->protocol = protocol; - rai->canonname = canonname; - rai->inspectname = inspectname; + RB_OBJ_WRITE(self, &rai->canonname, canonname); + RB_OBJ_WRITE(self, &rai->inspectname, inspectname); } VALUE @@ -804,14 +1359,14 @@ rsock_addrinfo_new(struct sockaddr *addr, socklen_t len, a = addrinfo_s_allocate(rb_cAddrinfo); DATA_PTR(a) = rai = alloc_addrinfo(); - init_addrinfo(rai, addr, len, family, socktype, protocol, canonname, inspectname); + init_addrinfo(a, rai, addr, len, family, socktype, protocol, canonname, inspectname); return a; } static struct rb_addrinfo * call_getaddrinfo(VALUE node, VALUE service, VALUE family, VALUE socktype, VALUE protocol, VALUE flags, - int socktype_hack) + int socktype_hack, VALUE timeout) { struct addrinfo hints; struct rb_addrinfo *res; @@ -820,39 +1375,40 @@ call_getaddrinfo(VALUE node, VALUE service, hints.ai_family = NIL_P(family) ? PF_UNSPEC : rsock_family_arg(family); if (!NIL_P(socktype)) { - hints.ai_socktype = rsock_socktype_arg(socktype); + hints.ai_socktype = rsock_socktype_arg(socktype); } if (!NIL_P(protocol)) { - hints.ai_protocol = NUM2INT(protocol); + hints.ai_protocol = NUM2INT(protocol); } if (!NIL_P(flags)) { - hints.ai_flags = NUM2INT(flags); + hints.ai_flags = NUM2INT(flags); } - res = rsock_getaddrinfo(node, service, &hints, socktype_hack); + + res = rsock_getaddrinfo(node, service, &hints, socktype_hack, timeout); if (res == NULL) - rb_raise(rb_eSocket, "host not found"); + rb_raise(rb_eSocket, "host not found"); return res; } static VALUE make_inspectname(VALUE node, VALUE service, struct addrinfo *res); static void -init_addrinfo_getaddrinfo(rb_addrinfo_t *rai, VALUE node, VALUE service, +init_addrinfo_getaddrinfo(VALUE self, rb_addrinfo_t *rai, VALUE node, VALUE service, VALUE family, VALUE socktype, VALUE protocol, VALUE flags, VALUE inspectnode, VALUE inspectservice) { - struct rb_addrinfo *res = call_getaddrinfo(node, service, family, socktype, protocol, flags, 1); + struct rb_addrinfo *res = call_getaddrinfo(node, service, family, socktype, protocol, flags, 1, Qnil); VALUE canonname; VALUE inspectname = rb_str_equal(node, inspectnode) ? Qnil : make_inspectname(inspectnode, inspectservice, res->ai); canonname = Qnil; if (res->ai->ai_canonname) { - canonname = rb_tainted_str_new_cstr(res->ai->ai_canonname); + canonname = rb_str_new_cstr(res->ai->ai_canonname); OBJ_FREEZE(canonname); } - init_addrinfo(rai, res->ai->ai_addr, res->ai->ai_addrlen, + init_addrinfo(self, rai, res->ai->ai_addr, res->ai->ai_addrlen, NUM2INT(family), NUM2INT(socktype), NUM2INT(protocol), canonname, inspectname); @@ -898,8 +1454,6 @@ make_inspectname(VALUE node, VALUE service, struct addrinfo *res) rb_str_catf(inspectname, ":%d", FIX2INT(service)); } if (!NIL_P(inspectname)) { - OBJ_INFECT(inspectname, node); - OBJ_INFECT(inspectname, service); OBJ_FREEZE(inspectname); } return inspectname; @@ -912,13 +1466,13 @@ addrinfo_firstonly_new(VALUE node, VALUE service, VALUE family, VALUE socktype, VALUE canonname; VALUE inspectname; - struct rb_addrinfo *res = call_getaddrinfo(node, service, family, socktype, protocol, flags, 0); + struct rb_addrinfo *res = call_getaddrinfo(node, service, family, socktype, protocol, flags, 0, Qnil); inspectname = make_inspectname(node, service, res->ai); canonname = Qnil; if (res->ai->ai_canonname) { - canonname = rb_tainted_str_new_cstr(res->ai->ai_canonname); + canonname = rb_str_new_cstr(res->ai->ai_canonname); OBJ_FREEZE(canonname); } @@ -932,13 +1486,13 @@ addrinfo_firstonly_new(VALUE node, VALUE service, VALUE family, VALUE socktype, } static VALUE -addrinfo_list_new(VALUE node, VALUE service, VALUE family, VALUE socktype, VALUE protocol, VALUE flags) +addrinfo_list_new(VALUE node, VALUE service, VALUE family, VALUE socktype, VALUE protocol, VALUE flags, VALUE timeout) { VALUE ret; struct addrinfo *r; VALUE inspectname; - struct rb_addrinfo *res = call_getaddrinfo(node, service, family, socktype, protocol, flags, 0); + struct rb_addrinfo *res = call_getaddrinfo(node, service, family, socktype, protocol, flags, 0, timeout); inspectname = make_inspectname(node, service, res->ai); @@ -948,7 +1502,7 @@ addrinfo_list_new(VALUE node, VALUE service, VALUE family, VALUE socktype, VALUE VALUE canonname = Qnil; if (r->ai_canonname) { - canonname = rb_tainted_str_new_cstr(r->ai_canonname); + canonname = rb_str_new_cstr(r->ai_canonname); OBJ_FREEZE(canonname); } @@ -964,9 +1518,9 @@ addrinfo_list_new(VALUE node, VALUE service, VALUE family, VALUE socktype, VALUE } -#ifdef HAVE_SYS_UN_H +#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN static void -init_unix_addrinfo(rb_addrinfo_t *rai, VALUE path, int socktype) +init_unix_addrinfo(VALUE self, rb_addrinfo_t *rai, VALUE path, int socktype) { struct sockaddr_un un; socklen_t len; @@ -982,8 +1536,14 @@ init_unix_addrinfo(rb_addrinfo_t *rai, VALUE path, int socktype) memcpy((void*)&un.sun_path, RSTRING_PTR(path), RSTRING_LEN(path)); len = rsock_unix_sockaddr_len(path); - init_addrinfo(rai, (struct sockaddr *)&un, len, - PF_UNIX, socktype, 0, Qnil, Qnil); + init_addrinfo(self, rai, (struct sockaddr *)&un, len, + PF_UNIX, socktype, 0, Qnil, Qnil); +} + +static long +rai_unixsocket_len(const rb_addrinfo_t *rai) +{ + return unixsocket_len(&rai->addr.un, rai->sockaddr_len); } #endif @@ -1005,13 +1565,13 @@ init_unix_addrinfo(rb_addrinfo_t *rai, VALUE path, int socktype) * Socket.sockaddr_in or Socket.unpack_sockaddr_un. * * sockaddr examples: - * - ["AF_INET", 46102, "localhost.localdomain", "127.0.0.1"] - * - ["AF_INET6", 42304, "ip6-localhost", "::1"] - * - ["AF_UNIX", "/tmp/sock"] - * - Socket.sockaddr_in("smtp", "2001:DB8::1") - * - Socket.sockaddr_in(80, "172.18.22.42") - * - Socket.sockaddr_in(80, "www.ruby-lang.org") - * - Socket.sockaddr_un("/tmp/sock") + * - <code>["AF_INET", 46102, "localhost.localdomain", "127.0.0.1"]</code> + * - <code>["AF_INET6", 42304, "ip6-localhost", "::1"]</code> + * - <code>["AF_UNIX", "/tmp/sock"]</code> + * - <code>Socket.sockaddr_in("smtp", "2001:DB8::1")</code> + * - <code>Socket.sockaddr_in(80, "172.18.22.42")</code> + * - <code>Socket.sockaddr_in(80, "www.ruby-lang.org")</code> + * - <code>Socket.sockaddr_un("/tmp/sock")</code> * * In an AF_INET/AF_INET6 sockaddr array, the 4th element, * numeric IP address, is used to construct socket address in the Addrinfo instance. @@ -1059,7 +1619,7 @@ addrinfo_initialize(int argc, VALUE *argv, VALUE self) int af; StringValue(afamily); if (rsock_family_to_int(RSTRING_PTR(afamily), RSTRING_LEN(afamily), &af) == -1) - rb_raise(rb_eSocket, "unknown address family: %s", StringValueCStr(afamily)); + rb_raise(rb_eSocket, "unknown address family: %s", StringValueCStr(afamily)); switch (af) { case AF_INET: /* ["AF_INET", 46102, "localhost.localdomain", "127.0.0.1"] */ #ifdef INET6 @@ -1080,19 +1640,19 @@ addrinfo_initialize(int argc, VALUE *argv, VALUE self) flags |= AI_NUMERICSERV; #endif - init_addrinfo_getaddrinfo(rai, numericnode, service, + init_addrinfo_getaddrinfo(self, rai, numericnode, service, INT2NUM(i_pfamily ? i_pfamily : af), INT2NUM(i_socktype), INT2NUM(i_protocol), INT2NUM(flags), nodename, service); break; } -#ifdef HAVE_SYS_UN_H +#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN case AF_UNIX: /* ["AF_UNIX", "/tmp/sock"] */ { VALUE path = rb_ary_entry(sockaddr_ary, 1); StringValue(path); - init_unix_addrinfo(rai, path, SOCK_STREAM); + init_unix_addrinfo(self, rai, path, SOCK_STREAM); break; } #endif @@ -1105,7 +1665,7 @@ addrinfo_initialize(int argc, VALUE *argv, VALUE self) StringValue(sockaddr_arg); sockaddr_ptr = (struct sockaddr *)RSTRING_PTR(sockaddr_arg); sockaddr_len = RSTRING_SOCKLEN(sockaddr_arg); - init_addrinfo(rai, sockaddr_ptr, sockaddr_len, + init_addrinfo(self, rai, sockaddr_ptr, sockaddr_len, i_pfamily, i_socktype, i_protocol, canonname, inspectname); } @@ -1149,45 +1709,45 @@ rsock_inspect_sockaddr(struct sockaddr *sockaddr_arg, socklen_t socklen, VALUE r else { switch (sockaddr->addr.sa_family) { case AF_UNSPEC: - { - rb_str_cat2(ret, "UNSPEC"); + { + rb_str_cat2(ret, "UNSPEC"); break; - } + } case AF_INET: { struct sockaddr_in *addr; int port; - addr = &sockaddr->in; - if ((socklen_t)(((char*)&addr->sin_addr)-(char*)addr+0+1) <= socklen) - rb_str_catf(ret, "%d", ((unsigned char*)&addr->sin_addr)[0]); - else - rb_str_cat2(ret, "?"); - if ((socklen_t)(((char*)&addr->sin_addr)-(char*)addr+1+1) <= socklen) - rb_str_catf(ret, ".%d", ((unsigned char*)&addr->sin_addr)[1]); - else - rb_str_cat2(ret, ".?"); - if ((socklen_t)(((char*)&addr->sin_addr)-(char*)addr+2+1) <= socklen) - rb_str_catf(ret, ".%d", ((unsigned char*)&addr->sin_addr)[2]); - else - rb_str_cat2(ret, ".?"); - if ((socklen_t)(((char*)&addr->sin_addr)-(char*)addr+3+1) <= socklen) - rb_str_catf(ret, ".%d", ((unsigned char*)&addr->sin_addr)[3]); - else - rb_str_cat2(ret, ".?"); - - if ((socklen_t)(((char*)&addr->sin_port)-(char*)addr+(int)sizeof(addr->sin_port)) < socklen) { - port = ntohs(addr->sin_port); - if (port) - rb_str_catf(ret, ":%d", port); - } - else { - rb_str_cat2(ret, ":?"); - } - if ((socklen_t)sizeof(struct sockaddr_in) != socklen) - rb_str_catf(ret, " (%d bytes for %d bytes sockaddr_in)", - (int)socklen, - (int)sizeof(struct sockaddr_in)); + addr = &sockaddr->in; + if ((socklen_t)(((char*)&addr->sin_addr)-(char*)addr+0+1) <= socklen) + rb_str_catf(ret, "%d", ((unsigned char*)&addr->sin_addr)[0]); + else + rb_str_cat2(ret, "?"); + if ((socklen_t)(((char*)&addr->sin_addr)-(char*)addr+1+1) <= socklen) + rb_str_catf(ret, ".%d", ((unsigned char*)&addr->sin_addr)[1]); + else + rb_str_cat2(ret, ".?"); + if ((socklen_t)(((char*)&addr->sin_addr)-(char*)addr+2+1) <= socklen) + rb_str_catf(ret, ".%d", ((unsigned char*)&addr->sin_addr)[2]); + else + rb_str_cat2(ret, ".?"); + if ((socklen_t)(((char*)&addr->sin_addr)-(char*)addr+3+1) <= socklen) + rb_str_catf(ret, ".%d", ((unsigned char*)&addr->sin_addr)[3]); + else + rb_str_cat2(ret, ".?"); + + if ((socklen_t)(((char*)&addr->sin_port)-(char*)addr+(int)sizeof(addr->sin_port)) < socklen) { + port = ntohs(addr->sin_port); + if (port) + rb_str_catf(ret, ":%d", port); + } + else { + rb_str_cat2(ret, ":?"); + } + if ((socklen_t)sizeof(struct sockaddr_in) != socklen) + rb_str_catf(ret, " (%d bytes for %d bytes sockaddr_in)", + (int)socklen, + (int)sizeof(struct sockaddr_in)); break; } @@ -1207,11 +1767,11 @@ rsock_inspect_sockaddr(struct sockaddr *sockaddr_arg, socklen_t socklen, VALUE r * RFC 4007: IPv6 Scoped Address Architecture * draft-ietf-ipv6-scope-api-00.txt: Scoped Address Extensions to the IPv6 Basic Socket API */ - error = getnameinfo(&sockaddr->addr, socklen, - hbuf, (socklen_t)sizeof(hbuf), NULL, 0, - NI_NUMERICHOST|NI_NUMERICSERV); + error = rb_getnameinfo(&sockaddr->addr, socklen, + hbuf, (socklen_t)sizeof(hbuf), NULL, 0, + NI_NUMERICHOST|NI_NUMERICSERV); if (error) { - rsock_raise_socket_error("getnameinfo", error); + rsock_raise_resolution_error("getnameinfo", error); } if (addr->sin6_port == 0) { rb_str_cat2(ret, hbuf); @@ -1227,21 +1787,20 @@ rsock_inspect_sockaddr(struct sockaddr *sockaddr_arg, socklen_t socklen, VALUE r } #endif -#ifdef HAVE_SYS_UN_H +#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN case AF_UNIX: { struct sockaddr_un *addr = &sockaddr->un; char *p, *s, *e; + long len = unixsocket_len(addr, socklen); s = addr->sun_path; - e = (char*)addr + socklen; - while (s < e && *(e-1) == '\0') - e--; - if (e < s) + if (len < 0) rb_str_cat2(ret, "too-short-AF_UNIX-sockaddr"); - else if (s == e) + else if (len == 0) rb_str_cat2(ret, "empty-path-AF_UNIX-sockaddr"); else { int printable_only = 1; + e = s + len; p = s; while (p < e) { printable_only = printable_only && ISPRINT(*p) && !ISSPACE(*p); @@ -1339,20 +1898,20 @@ rsock_inspect_sockaddr(struct sockaddr *sockaddr_arg, socklen_t socklen, VALUE r #endif #if defined(AF_LINK) && defined(HAVE_TYPE_STRUCT_SOCKADDR_DL) - /* AF_LINK is defined in 4.4BSD derivations since Net2. - link_ntoa is also defined at Net2. + /* AF_LINK is defined in 4.4BSD derivations since Net2. + link_ntoa is also defined at Net2. However Debian GNU/kFreeBSD defines AF_LINK but don't have link_ntoa. */ case AF_LINK: - { - /* - * Simple implementation using link_ntoa(): - * This doesn't work on Debian GNU/kFreeBSD 6.0.7 (squeeze). + { + /* + * Simple implementation using link_ntoa(): + * This doesn't work on Debian GNU/kFreeBSD 6.0.7 (squeeze). * Also, the format is bit different. - * - * rb_str_catf(ret, "LINK %s", link_ntoa(&sockaddr->dl)); - * break; - */ + * + * rb_str_catf(ret, "LINK %s", link_ntoa(&sockaddr->dl)); + * break; + */ struct sockaddr_dl *addr = &sockaddr->dl; char *np = NULL, *ap = NULL, *endp; int nlen = 0, alen = 0; @@ -1379,14 +1938,14 @@ rsock_inspect_sockaddr(struct sockaddr *sockaddr_arg, socklen_t socklen, VALUE r alen = (int)(endp - ap); } - CATSEP; + CATSEP; if (np) rb_str_catf(ret, "%.*s", nlen, np); else rb_str_cat2(ret, "?"); if (ap && 0 < alen) { - CATSEP; + CATSEP; for (i = 0; i < alen; i++) rb_str_catf(ret, "%s%02x", i == 0 ? "" : ":", (unsigned char)ap[i]); } @@ -1397,10 +1956,10 @@ rsock_inspect_sockaddr(struct sockaddr *sockaddr_arg, socklen_t socklen, VALUE r /* longer length is possible behavior because struct sockaddr_dl has "minimum work area, can be larger" as the last field. * cf. Net2:/usr/src/sys/net/if_dl.h. */ socklen < (socklen_t)(offsetof(struct sockaddr_dl, sdl_data) + addr->sdl_nlen + addr->sdl_alen + addr->sdl_slen)) { - CATSEP; + CATSEP; rb_str_catf(ret, "(%d bytes for %d bytes sockaddr_dl)", (int)socklen, (int)sizeof(struct sockaddr_dl)); - } + } rb_str_cat2(ret, "]"); #undef CATSEP @@ -1564,16 +2123,10 @@ addrinfo_mdump(VALUE self) afamily = rb_id2str(id); switch(afamily_int) { -#ifdef HAVE_SYS_UN_H +#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN case AF_UNIX: { - struct sockaddr_un *su = &rai->addr.un; - char *s, *e; - s = su->sun_path; - e = (char*)su + rai->sockaddr_len; - while (s < e && *(e-1) == '\0') - e--; - sockaddr = rb_str_new(s, e-s); + sockaddr = rb_str_new(rai->addr.un.sun_path, rai_unixsocket_len(rai)); break; } #endif @@ -1582,11 +2135,11 @@ addrinfo_mdump(VALUE self) { char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV]; int error; - error = getnameinfo(&rai->addr.addr, rai->sockaddr_len, - hbuf, (socklen_t)sizeof(hbuf), pbuf, (socklen_t)sizeof(pbuf), - NI_NUMERICHOST|NI_NUMERICSERV); + error = rb_getnameinfo(&rai->addr.addr, rai->sockaddr_len, + hbuf, (socklen_t)sizeof(hbuf), pbuf, (socklen_t)sizeof(pbuf), + NI_NUMERICHOST|NI_NUMERICSERV); if (error) { - rsock_raise_socket_error("getnameinfo", error); + rsock_raise_resolution_error("getnameinfo", error); } sockaddr = rb_assoc_new(rb_str_new_cstr(hbuf), rb_str_new_cstr(pbuf)); break; @@ -1663,7 +2216,7 @@ addrinfo_mload(VALUE self, VALUE ary) v = rb_ary_entry(ary, 1); switch(afamily) { -#ifdef HAVE_SYS_UN_H +#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN case AF_UNIX: { struct sockaddr_un uaddr; @@ -1691,7 +2244,7 @@ addrinfo_mload(VALUE self, VALUE ary) #endif res = call_getaddrinfo(rb_ary_entry(pair, 0), rb_ary_entry(pair, 1), INT2NUM(pfamily), INT2NUM(socktype), INT2NUM(protocol), - INT2NUM(flags), 1); + INT2NUM(flags), 1, Qnil); len = res->ai->ai_addrlen; memcpy(&ss, res->ai->ai_addr, res->ai->ai_addrlen); @@ -1701,7 +2254,7 @@ addrinfo_mload(VALUE self, VALUE ary) } DATA_PTR(self) = rai = alloc_addrinfo(); - init_addrinfo(rai, &ss.addr, len, + init_addrinfo(self, rai, &ss.addr, len, pfamily, socktype, protocol, canonname, inspectname); return self; @@ -1788,7 +2341,6 @@ addrinfo_to_sockaddr(VALUE self) rb_addrinfo_t *rai = get_addrinfo(self); VALUE ret; ret = rb_str_new((char*)&rai->addr, rai->sockaddr_len); - OBJ_INFECT(ret, self); return ret; } @@ -1796,7 +2348,7 @@ addrinfo_to_sockaddr(VALUE self) * call-seq: * addrinfo.canonname => string or nil * - * returns the canonical name as an string. + * returns the canonical name as a string. * * nil is returned if no canonical name. * @@ -1929,11 +2481,11 @@ addrinfo_getnameinfo(int argc, VALUE *argv, VALUE self) if (rai->socktype == SOCK_DGRAM) flags |= NI_DGRAM; - error = getnameinfo(&rai->addr.addr, rai->sockaddr_len, - hbuf, (socklen_t)sizeof(hbuf), pbuf, (socklen_t)sizeof(pbuf), - flags); + error = rb_getnameinfo(&rai->addr.addr, rai->sockaddr_len, + hbuf, (socklen_t)sizeof(hbuf), pbuf, (socklen_t)sizeof(pbuf), + flags); if (error) { - rsock_raise_socket_error("getnameinfo", error); + rsock_raise_resolution_error("getnameinfo", error); } return rb_assoc_new(rb_str_new2(hbuf), rb_str_new2(pbuf)); @@ -1957,7 +2509,7 @@ addrinfo_ip_unpack(VALUE self) VALUE ret, portstr; if (!IS_IP_FAMILY(family)) - rb_raise(rb_eSocket, "need IPv4 or IPv6 address"); + rb_raise(rb_eSocket, "need IPv4 or IPv6 address"); vflags = INT2NUM(NI_NUMERICHOST|NI_NUMERICSERV); ret = addrinfo_getnameinfo(1, &vflags, self); @@ -1984,7 +2536,7 @@ addrinfo_ip_address(VALUE self) VALUE ret; if (!IS_IP_FAMILY(family)) - rb_raise(rb_eSocket, "need IPv4 or IPv6 address"); + rb_raise(rb_eSocket, "need IPv4 or IPv6 address"); vflags = INT2NUM(NI_NUMERICHOST|NI_NUMERICSERV); ret = addrinfo_getnameinfo(1, &vflags, self); @@ -2010,9 +2562,9 @@ addrinfo_ip_port(VALUE self) if (!IS_IP_FAMILY(family)) { bad_family: #ifdef AF_INET6 - rb_raise(rb_eSocket, "need IPv4 or IPv6 address"); + rb_raise(rb_eSocket, "need IPv4 or IPv6 address"); #else - rb_raise(rb_eSocket, "need IPv4 address"); + rb_raise(rb_eSocket, "need IPv4 address"); #endif } @@ -2032,7 +2584,7 @@ addrinfo_ip_port(VALUE self) #endif default: - goto bad_family; + goto bad_family; } return INT2NUM(port); @@ -2140,7 +2692,7 @@ addrinfo_ipv6_multicast_p(VALUE self) } /* - * Returns true for IPv6 link local address (ff80::/10). + * Returns true for IPv6 link local address (fe80::/10). * It returns false otherwise. */ static VALUE @@ -2152,7 +2704,7 @@ addrinfo_ipv6_linklocal_p(VALUE self) } /* - * Returns true for IPv6 site local address (ffc0::/10). + * Returns true for IPv6 site local address (fec0::/10). * It returns false otherwise. */ static VALUE @@ -2292,7 +2844,7 @@ addrinfo_ipv6_to_ipv4(VALUE self) #endif -#ifdef HAVE_SYS_UN_H +#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN /* * call-seq: * addrinfo.unix_path => path @@ -2307,28 +2859,27 @@ addrinfo_unix_path(VALUE self) rb_addrinfo_t *rai = get_addrinfo(self); int family = ai_get_afamily(rai); struct sockaddr_un *addr; - char *s, *e; + long n; if (family != AF_UNIX) - rb_raise(rb_eSocket, "need AF_UNIX address"); + rb_raise(rb_eSocket, "need AF_UNIX address"); addr = &rai->addr.un; - s = addr->sun_path; - e = (char*)addr + rai->sockaddr_len; - if (e < s) + n = rai_unixsocket_len(rai); + if (n < 0) rb_raise(rb_eSocket, "too short AF_UNIX address: %"PRIuSIZE" bytes given for minimum %"PRIuSIZE" bytes.", - (size_t)rai->sockaddr_len, (size_t)(s - (char *)addr)); - if (addr->sun_path + sizeof(addr->sun_path) < e) + (size_t)rai->sockaddr_len, offsetof(struct sockaddr_un, sun_path)); + if ((long)sizeof(addr->sun_path) < n) rb_raise(rb_eSocket, "too long AF_UNIX path (%"PRIuSIZE" bytes given but %"PRIuSIZE" bytes max)", - (size_t)(e - addr->sun_path), sizeof(addr->sun_path)); - while (s < e && *(e-1) == '\0') - e--; - return rb_str_new(s, e-s); + (size_t)n, sizeof(addr->sun_path)); + return rb_str_new(addr->sun_path, n); } #endif +static ID id_timeout; + /* * call-seq: * Addrinfo.getaddrinfo(nodename, service, family, socktype, protocol, flags) => [addrinfo, ...] @@ -2375,10 +2926,16 @@ addrinfo_unix_path(VALUE self) static VALUE addrinfo_s_getaddrinfo(int argc, VALUE *argv, VALUE self) { - VALUE node, service, family, socktype, protocol, flags; + VALUE node, service, family, socktype, protocol, flags, opts, timeout; - rb_scan_args(argc, argv, "24", &node, &service, &family, &socktype, &protocol, &flags); - return addrinfo_list_new(node, service, family, socktype, protocol, flags); + rb_scan_args(argc, argv, "24:", &node, &service, &family, &socktype, + &protocol, &flags, &opts); + rb_get_kwargs(opts, &id_timeout, 0, 1, &timeout); + if (timeout == Qundef) { + timeout = Qnil; + } + + return addrinfo_list_new(node, service, family, socktype, protocol, flags, timeout); } /* @@ -2435,7 +2992,7 @@ addrinfo_s_udp(VALUE self, VALUE host, VALUE port) INT2NUM(PF_UNSPEC), INT2NUM(SOCK_DGRAM), INT2NUM(IPPROTO_UDP), INT2FIX(0)); } -#ifdef HAVE_SYS_UN_H +#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN /* * call-seq: @@ -2465,8 +3022,7 @@ addrinfo_s_unix(int argc, VALUE *argv, VALUE self) addr = addrinfo_s_allocate(rb_cAddrinfo); DATA_PTR(addr) = rai = alloc_addrinfo(); - init_unix_addrinfo(rai, path, socktype); - OBJ_INFECT(addr, path); + init_unix_addrinfo(self, rai, path, socktype); return addr; } @@ -2553,17 +3109,112 @@ rsock_io_socket_addrinfo(VALUE io, struct sockaddr *addr, socklen_t len) UNREACHABLE_RETURN(Qnil); } +#if FAST_FALLBACK_INIT_INETSOCK_IMPL == 1 + +void +free_fast_fallback_getaddrinfo_shared(struct fast_fallback_getaddrinfo_shared **shared) +{ + xfree((*shared)->node); + (*shared)->node = NULL; + xfree((*shared)->service); + (*shared)->service = NULL; + rb_nativethread_lock_destroy(&(*shared)->lock); + free(*shared); + *shared = NULL; +} + +static void * +do_fast_fallback_getaddrinfo(void *ptr) +{ + struct fast_fallback_getaddrinfo_entry *entry = (struct fast_fallback_getaddrinfo_entry *)ptr; + struct fast_fallback_getaddrinfo_shared *shared = entry->shared; + int err = 0, shared_need_free = 0; + struct addrinfo *ai = NULL; + + sigset_t set; + sigemptyset(&set); + sigaddset(&set, SIGPIPE); + pthread_sigmask(SIG_BLOCK, &set, NULL); + + err = numeric_getaddrinfo(shared->node, shared->service, &entry->hints, &entry->ai); + + if (err != 0) { + err = getaddrinfo(shared->node, shared->service, &entry->hints, &entry->ai); + #ifdef __linux__ + /* On Linux (mainly Ubuntu 13.04) /etc/nsswitch.conf has mdns4 and + * it cause getaddrinfo to return EAI_SYSTEM/ENOENT. [ruby-list:49420] + */ + if (err == EAI_SYSTEM && errno == ENOENT) + err = EAI_NONAME; + #endif + } + + /* for testing HEv2 */ + if (entry->test_sleep_ms > 0) { + struct timespec sleep_ts; + sleep_ts.tv_sec = entry->test_sleep_ms / 1000; + sleep_ts.tv_nsec = (entry->test_sleep_ms % 1000) * 1000000L; + if (sleep_ts.tv_nsec >= 1000000000L) { + sleep_ts.tv_sec += sleep_ts.tv_nsec / 1000000000L; + sleep_ts.tv_nsec = sleep_ts.tv_nsec % 1000000000L; + } + nanosleep(&sleep_ts, NULL); + } + if (entry->test_ecode != 0) { + err = entry->test_ecode; + if (entry->ai) { + freeaddrinfo(entry->ai); + entry->ai = NULL; + } + } + + rb_nativethread_lock_lock(&shared->lock); + { + entry->err = err; + const char notification = entry->family == AF_INET6 ? + IPV6_HOSTNAME_RESOLVED : IPV4_HOSTNAME_RESOLVED; + + if (shared->notify != -1 && (write(shared->notify, ¬ification, 1)) < 0) { + entry->err = errno; + entry->has_syserr = true; + } + if (--(entry->refcount) == 0) { + ai = entry->ai; + entry->ai = NULL; + } + if (--(shared->refcount) == 0) shared_need_free = 1; + } + rb_nativethread_lock_unlock(&shared->lock); + + if (ai) freeaddrinfo(ai); + if (shared_need_free && shared) { + free_fast_fallback_getaddrinfo_shared(&shared); + } + + return 0; +} + +void * +fork_safe_do_fast_fallback_getaddrinfo(void *ptr) +{ + return rb_thread_prevent_fork(do_fast_fallback_getaddrinfo, ptr); +} + +#endif + /* * Addrinfo class */ void rsock_init_addrinfo(void) { + id_timeout = rb_intern("timeout"); + /* * The Addrinfo class maps <tt>struct addrinfo</tt> to ruby. This * structure identifies an Internet host and a service. */ - rb_cAddrinfo = rb_define_class("Addrinfo", rb_cData); + rb_cAddrinfo = rb_define_class("Addrinfo", rb_cObject); rb_define_alloc_func(rb_cAddrinfo, addrinfo_s_allocate); rb_define_method(rb_cAddrinfo, "initialize", addrinfo_initialize, -1); rb_define_method(rb_cAddrinfo, "inspect", addrinfo_inspect, 0); @@ -2572,7 +3223,7 @@ rsock_init_addrinfo(void) rb_define_singleton_method(rb_cAddrinfo, "ip", addrinfo_s_ip, 1); rb_define_singleton_method(rb_cAddrinfo, "tcp", addrinfo_s_tcp, 2); rb_define_singleton_method(rb_cAddrinfo, "udp", addrinfo_s_udp, 2); -#ifdef HAVE_SYS_UN_H +#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN rb_define_singleton_method(rb_cAddrinfo, "unix", addrinfo_s_unix, -1); #endif @@ -2613,7 +3264,7 @@ rsock_init_addrinfo(void) rb_define_method(rb_cAddrinfo, "ipv6_to_ipv4", addrinfo_ipv6_to_ipv4, 0); #endif -#ifdef HAVE_SYS_UN_H +#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN rb_define_method(rb_cAddrinfo, "unix_path", addrinfo_unix_path, 0); #endif diff --git a/ext/socket/rubysocket.h b/ext/socket/rubysocket.h index 0ce77a5f6e..2ec3ab335a 100644 --- a/ext/socket/rubysocket.h +++ b/ext/socket/rubysocket.h @@ -1,12 +1,22 @@ #ifndef RUBY_SOCKET_H #define RUBY_SOCKET_H 1 -#include "ruby/ruby.h" -#include "ruby/io.h" -#include "ruby/thread.h" -#include "ruby/util.h" -#include "internal.h" +#include "ruby/config.h" +#include RUBY_EXTCONF_H + +#if defined(__sun) || defined(_AIX) +/* (Recent?) Solaris' <nfs/nfs.h> have conflicting definition of T_DATA. Let + * us honour system definition by undefining ours. + * + * See also [ruby-core:4261] + */ +# include "ruby/ruby.h" +# undef T_DATA +#endif + +#include <errno.h> #include <stdio.h> + #include <sys/types.h> #include <sys/stat.h> @@ -23,16 +33,14 @@ #endif #ifdef _WIN32 +# include <winsock2.h> +# include <ws2tcpip.h> +# include <mswsock.h> +# include <iphlpapi.h> # if defined(_MSC_VER) # undef HAVE_TYPE_STRUCT_SOCKADDR_DL # endif -/* - * FIXME: failures if we make nonblocking the default - * [ruby-core:89973] [ruby-core:89976] [ruby-core:89977] [Bug #14968] - */ -# define RSOCK_NONBLOCK_DEFAULT (0) #else -# define RSOCK_NONBLOCK_DEFAULT (0) # include <sys/socket.h> # include <netinet/in.h> # ifdef HAVE_NETINET_IN_SYSTM_H @@ -56,16 +64,20 @@ #ifdef HAVE_NETPACKET_PACKET_H # include <netpacket/packet.h> #endif + #ifdef HAVE_NET_ETHERNET_H # include <net/ethernet.h> #endif -#include <errno.h> - #ifdef HAVE_SYS_UN_H # include <sys/un.h> #endif +#ifdef HAVE_AFUNIX_H +// Windows doesn't have sys/un.h, but it does have afunix.h just to be special: +# include <afunix.h> +#endif + #if defined(HAVE_FCNTL) # ifdef HAVE_SYS_SELECT_H # include <sys/select.h> @@ -87,12 +99,15 @@ # endif # include <ifaddrs.h> #endif + #ifdef HAVE_SYS_IOCTL_H # include <sys/ioctl.h> #endif + #ifdef HAVE_SYS_SOCKIO_H # include <sys/sockio.h> #endif + #ifdef HAVE_NET_IF_H # include <net/if.h> #endif @@ -100,16 +115,42 @@ #ifdef HAVE_SYS_PARAM_H # include <sys/param.h> #endif + #ifdef HAVE_SYS_UCRED_H # include <sys/ucred.h> #endif + #ifdef HAVE_UCRED_H # include <ucred.h> #endif + #ifdef HAVE_NET_IF_DL_H # include <net/if_dl.h> #endif +#ifdef SOCKS5 +# include <socks.h> +#endif + +#ifndef HAVE_GETADDRINFO +# include "addrinfo.h" +#endif + +#include "internal.h" +#include "internal/array.h" +#include "internal/compilers.h" +#include "internal/error.h" +#include "internal/gc.h" +#include "internal/io.h" +#include "internal/thread.h" +#include "internal/vm.h" +#include "ruby/io.h" +#include "ruby/ruby.h" +#include "ruby/thread.h" +#include "ruby/util.h" +#include "sockport.h" +#include "ruby/fiber/scheduler.h" + #ifndef HAVE_TYPE_SOCKLEN_T typedef int socklen_t; #endif @@ -143,11 +184,6 @@ unsigned int if_nametoindex(const char *); */ #define pseudo_AF_FTIP pseudo_AF_RTIP -#ifndef HAVE_GETADDRINFO -# include "addrinfo.h" -#endif - -#include "sockport.h" #ifndef NI_MAXHOST # define NI_MAXHOST 1025 @@ -229,7 +265,6 @@ typedef union { #define INET_SOCKS 2 extern int rsock_do_not_reverse_lookup; -extern int rsock_cmsg_cloexec_state; #define FMODE_NOREVLOOKUP 0x100 /* common socket families only */ @@ -243,7 +278,7 @@ extern VALUE rb_cIPSocket; extern VALUE rb_cTCPSocket; extern VALUE rb_cTCPServer; extern VALUE rb_cUDPSocket; -#ifdef HAVE_SYS_UN_H +#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN extern VALUE rb_cUNIXSocket; extern VALUE rb_cUNIXServer; #endif @@ -252,21 +287,18 @@ extern VALUE rb_cAddrinfo; extern VALUE rb_cSockOpt; extern VALUE rb_eSocket; +extern VALUE rb_eResolution; #ifdef SOCKS extern VALUE rb_cSOCKSSocket; -# ifdef SOCKS5 -# include <socks.h> -# else -void SOCKSinit(); -int Rconnect(); +# ifndef SOCKS5 +void SOCKSinit(char *); +int Rconnect(int, const struct sockaddr *, socklen_t); # endif #endif #include "constdefs.h" -#define BLOCKING_REGION_FD(func, arg) (long)rb_thread_io_blocking_region((func), (arg), (arg)->fd) - #define SockAddrStringValue(v) rsock_sockaddr_string_value(&(v)) #define SockAddrStringValuePtr(v) rsock_sockaddr_string_value_ptr(&(v)) #define SockAddrStringValueWithAddrinfo(v, rai_ret) rsock_sockaddr_string_value_with_addrinfo(&(v), &(rai_ret)) @@ -276,7 +308,7 @@ VALUE rsock_sockaddr_string_value_with_addrinfo(volatile VALUE *v, VALUE *ai_ret VALUE rb_check_sockaddr_string_type(VALUE); -NORETURN(void rsock_raise_socket_error(const char *, int)); +NORETURN(void rsock_raise_resolution_error(const char *, int)); int rsock_family_arg(VALUE domain); int rsock_socktype_arg(VALUE type); @@ -291,13 +323,13 @@ struct rb_addrinfo { struct addrinfo *ai; int allocated_by_malloc; }; -int rb_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct rb_addrinfo **res); void rb_freeaddrinfo(struct rb_addrinfo *ai); VALUE rsock_freeaddrinfo(VALUE arg); int rb_getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags); int rsock_fd_family(int fd); -struct rb_addrinfo *rsock_addrinfo(VALUE host, VALUE port, int family, int socktype, int flags); -struct rb_addrinfo *rsock_getaddrinfo(VALUE host, VALUE port, struct addrinfo *hints, int socktype_hack); +struct rb_addrinfo *rsock_addrinfo(VALUE host, VALUE port, int family, int socktype, int flags, VALUE timeout); +struct rb_addrinfo *rsock_getaddrinfo(VALUE host, VALUE port, struct addrinfo *hints, int socktype_hack, VALUE timeout); + VALUE rsock_fd_socket_addrinfo(int fd, struct sockaddr *addr, socklen_t len); VALUE rsock_io_socket_addrinfo(VALUE io, struct sockaddr *addr, socklen_t len); @@ -313,7 +345,7 @@ VALUE rsock_sockaddr_obj(struct sockaddr *addr, socklen_t len); int rsock_revlookup_flag(VALUE revlookup, int *norevlookup); -#ifdef HAVE_SYS_UN_H +#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN VALUE rsock_unixpath_str(struct sockaddr_un *sockaddr, socklen_t len); VALUE rsock_unixaddr(struct sockaddr_un *sockaddr, socklen_t len); socklen_t rsock_unix_sockaddr_len(VALUE path); @@ -323,7 +355,7 @@ int rsock_socket(int domain, int type, int proto); int rsock_detect_cloexec(int fd); VALUE rsock_init_sock(VALUE sock, int fd); VALUE rsock_sock_s_socketpair(int argc, VALUE *argv, VALUE klass); -VALUE rsock_init_inetsock(VALUE sock, VALUE remote_host, VALUE remote_serv, VALUE local_host, VALUE local_serv, int type); +VALUE rsock_init_inetsock(VALUE sock, VALUE remote_host, VALUE remote_serv, VALUE local_host, VALUE local_serv, int type, VALUE resolv_timeout, VALUE connect_timeout, VALUE open_timeout, VALUE fast_fallback, VALUE test_mode_settings); VALUE rsock_init_unixsock(VALUE sock, VALUE path, int server); struct rsock_send_arg { @@ -345,23 +377,23 @@ enum sock_recv_type { }; VALUE rsock_s_recvfrom_nonblock(VALUE sock, VALUE len, VALUE flg, VALUE str, - VALUE ex, enum sock_recv_type from); + VALUE ex, enum sock_recv_type from); VALUE rsock_s_recvfrom(VALUE sock, int argc, VALUE *argv, enum sock_recv_type from); -int rsock_connect(int fd, const struct sockaddr *sockaddr, int len, int socks); +int rsock_connect(VALUE self, const struct sockaddr *sockaddr, int len, int socks, VALUE timeout); -VALUE rsock_s_accept(VALUE klass, int fd, struct sockaddr *sockaddr, socklen_t *len); +VALUE rsock_s_accept(VALUE klass, VALUE io, struct sockaddr *sockaddr, socklen_t *len); VALUE rsock_s_accept_nonblock(VALUE klass, VALUE ex, rb_io_t *fptr, - struct sockaddr *sockaddr, socklen_t *len); + struct sockaddr *sockaddr, socklen_t *len); VALUE rsock_sock_listen(VALUE sock, VALUE log); VALUE rsock_sockopt_new(int family, int level, int optname, VALUE data); #if defined(HAVE_SENDMSG) VALUE rsock_bsock_sendmsg(VALUE sock, VALUE data, VALUE flags, - VALUE dest_sockaddr, VALUE controls); + VALUE dest_sockaddr, VALUE controls); VALUE rsock_bsock_sendmsg_nonblock(VALUE sock, VALUE data, VALUE flags, - VALUE dest_sockaddr, VALUE controls, VALUE ex); + VALUE dest_sockaddr, VALUE controls, VALUE ex); #else #define rsock_bsock_sendmsg rb_f_notimplement #define rsock_bsock_sendmsg_nonblock rb_f_notimplement @@ -369,9 +401,9 @@ VALUE rsock_bsock_sendmsg_nonblock(VALUE sock, VALUE data, VALUE flags, #if defined(HAVE_RECVMSG) VALUE rsock_bsock_recvmsg(VALUE sock, VALUE dlen, VALUE clen, VALUE flags, - VALUE scm_rights); + VALUE scm_rights); VALUE rsock_bsock_recvmsg_nonblock(VALUE sock, VALUE dlen, VALUE clen, - VALUE flags, VALUE scm_rights, VALUE ex); + VALUE flags, VALUE scm_rights, VALUE ex); ssize_t rsock_recvmsg(int socket, struct msghdr *message, int flags); #else #define rsock_bsock_recvmsg rb_f_notimplement @@ -382,6 +414,47 @@ ssize_t rsock_recvmsg(int socket, struct msghdr *message, int flags); void rsock_discard_cmsg_resource(struct msghdr *mh, int msg_peek_p); #endif +char *raddrinfo_host_str(VALUE host, char *hbuf, size_t hbuflen, int *flags_ptr); +char *raddrinfo_port_str(VALUE port, char *pbuf, size_t pbuflen, int *flags_ptr); + +#ifndef FAST_FALLBACK_INIT_INETSOCK_IMPL +# if !defined(HAVE_PTHREAD_CREATE) || !defined(HAVE_PTHREAD_DETACH) || defined(__MINGW32__) || defined(__MINGW64__) +# define FAST_FALLBACK_INIT_INETSOCK_IMPL 0 +# else +# include "ruby/thread_native.h" +# define FAST_FALLBACK_INIT_INETSOCK_IMPL 1 +# define IPV6_HOSTNAME_RESOLVED '1' +# define IPV4_HOSTNAME_RESOLVED '2' +# define SELECT_CANCELLED '3' + +struct fast_fallback_getaddrinfo_entry +{ + int family, err, refcount; + struct addrinfo hints; + struct addrinfo *ai; + struct fast_fallback_getaddrinfo_shared *shared; + int has_syserr; + long test_sleep_ms; + int test_ecode; +}; + +struct fast_fallback_getaddrinfo_shared +{ + int notify, refcount; + char *node, *service; + rb_nativethread_lock_t lock; + struct fast_fallback_getaddrinfo_entry getaddrinfo_entries[FLEX_ARY_LEN]; +}; + +int raddrinfo_pthread_create(pthread_t *th, void *(*start_routine) (void *), void *arg); +void *fork_safe_do_fast_fallback_getaddrinfo(void *ptr); +void free_fast_fallback_getaddrinfo_entry(struct fast_fallback_getaddrinfo_entry **entry); +void free_fast_fallback_getaddrinfo_shared(struct fast_fallback_getaddrinfo_shared **shared); +# endif +#endif + +NORETURN(void rsock_raise_user_specified_timeout(struct addrinfo *ai, VALUE host, VALUE port)); + void rsock_init_basicsocket(void); void rsock_init_ipsocket(void); void rsock_init_tcpsocket(void); @@ -409,30 +482,17 @@ NORETURN(void rsock_sys_fail_sockaddr(const char *, struct sockaddr *addr, sockl NORETURN(void rsock_sys_fail_raddrinfo(const char *, VALUE rai)); NORETURN(void rsock_sys_fail_raddrinfo_or_sockaddr(const char *, VALUE addr, VALUE rai)); -/* - * It is safe on Linux to attempt using a socket without waiting on it in - * all cases. For some syscalls (e.g. accept/accept4), blocking on the - * syscall instead of relying on select/poll allows the kernel to use - * "wake-one" behavior and avoid the thundering herd problem. - * This is likely safe on all other *nix-like systems, so this safe list - * can be expanded by interested parties. - */ -#if defined(__linux__) -static inline int rsock_maybe_fd_writable(int fd) { return 1; } -static inline void rsock_maybe_wait_fd(int fd) { } -# ifdef MSG_DONTWAIT -# define MSG_DONTWAIT_RELIABLE 1 -# endif -#else /* some systems (mswin/mingw) need these. ref: r36946 */ -# define rsock_maybe_fd_writable(fd) rb_thread_fd_writable((fd)) -# define rsock_maybe_wait_fd(fd) rb_thread_wait_fd((fd)) +#if defined(__MINGW32__) || defined(_WIN32) +#define RSOCK_WAIT_BEFORE_BLOCKING #endif /* * some OSes may support MSG_DONTWAIT inconsistently depending on socket * type, we only expect Linux to support it consistently for all socket types. */ -#ifndef MSG_DONTWAIT_RELIABLE +#if defined(MSG_DONTWAIT) && defined(__linux__) +# define MSG_DONTWAIT_RELIABLE 1 +#else # define MSG_DONTWAIT_RELIABLE 0 #endif @@ -441,12 +501,14 @@ VALUE rsock_write_nonblock(VALUE sock, VALUE buf, VALUE ex); void rsock_make_fd_nonblock(int fd); +int rsock_is_dgram(rb_io_t *fptr); + +extern ID tcp_fast_fallback; + #if !defined HAVE_INET_NTOP && ! defined _WIN32 const char *inet_ntop(int, const void *, char *, size_t); #elif defined __MINGW32__ # define inet_ntop(f,a,n,l) rb_w32_inet_ntop(f,a,n,l) -#elif defined _MSC_VER && RUBY_MSVCRT_VERSION < 90 -const char *WSAAPI inet_ntop(int, const void *, char *, size_t); #endif #endif diff --git a/ext/socket/socket.c b/ext/socket/socket.c index 0059595e1b..a8e5ae8119 100644 --- a/ext/socket/socket.c +++ b/ext/socket/socket.c @@ -14,6 +14,8 @@ static VALUE sym_wait_writable; static VALUE sock_s_unpack_sockaddr_in(VALUE, VALUE); +ID tcp_fast_fallback; + void rsock_sys_fail_host_port(const char *mesg, VALUE host, VALUE port) { @@ -26,7 +28,11 @@ rsock_syserr_fail_host_port(int err, const char *mesg, VALUE host, VALUE port) VALUE message; message = rb_sprintf("%s for %+"PRIsVALUE" port % "PRIsVALUE"", - mesg, host, port); + mesg, host, port); + + if (err == ETIMEDOUT) { + rb_exc_raise(rb_exc_new3(rb_eIOTimeoutError, message)); + } rb_syserr_fail_str(err, message); } @@ -43,11 +49,11 @@ rsock_syserr_fail_path(int err, const char *mesg, VALUE path) VALUE message; if (RB_TYPE_P(path, T_STRING)) { - message = rb_sprintf("%s for % "PRIsVALUE"", mesg, path); - rb_syserr_fail_str(err, message); + message = rb_sprintf("%s for % "PRIsVALUE"", mesg, path); + rb_syserr_fail_str(err, message); } else { - rb_syserr_fail(err, mesg); + rb_syserr_fail(err, mesg); } } @@ -96,12 +102,12 @@ rsock_syserr_fail_raddrinfo_or_sockaddr(int err, const char *mesg, VALUE addr, V if (NIL_P(rai)) { StringValue(addr); - rsock_syserr_fail_sockaddr(err, mesg, + rsock_syserr_fail_sockaddr(err, mesg, (struct sockaddr *)RSTRING_PTR(addr), (socklen_t)RSTRING_LEN(addr)); /* overflow should be checked already */ } else - rsock_syserr_fail_raddrinfo(err, mesg, rai); + rsock_syserr_fail_raddrinfo(err, mesg, rai); } static void @@ -168,93 +174,47 @@ pair_yield(VALUE pair) #endif #if defined HAVE_SOCKETPAIR - -#ifdef SOCK_CLOEXEC static int -rsock_socketpair0(int domain, int type, int protocol, int sv[2]) +rsock_socketpair0(int domain, int type, int protocol, int descriptors[2]) { - int ret; - static int cloexec_state = -1; /* <0: unknown, 0: ignored, >0: working */ - static const int default_flags = SOCK_CLOEXEC|RSOCK_NONBLOCK_DEFAULT; +#ifdef SOCK_CLOEXEC + type |= SOCK_CLOEXEC; +#endif - if (cloexec_state > 0) { /* common path, if SOCK_CLOEXEC is defined */ - ret = socketpair(domain, type|default_flags, protocol, sv); - if (ret == 0 && (sv[0] <= 2 || sv[1] <= 2)) { - goto fix_cloexec; /* highly unlikely */ - } - goto update_max_fd; - } - else if (cloexec_state < 0) { /* usually runs once only for detection */ - ret = socketpair(domain, type|default_flags, protocol, sv); - if (ret == 0) { - cloexec_state = rsock_detect_cloexec(sv[0]); - if ((cloexec_state == 0) || (sv[0] <= 2 || sv[1] <= 2)) - goto fix_cloexec; - goto update_max_fd; - } - else if (ret == -1 && errno == EINVAL) { - /* SOCK_CLOEXEC is available since Linux 2.6.27. Linux 2.6.18 fails with EINVAL */ - ret = socketpair(domain, type, protocol, sv); - if (ret != -1) { - /* The reason of EINVAL may be other than SOCK_CLOEXEC. - * So disable SOCK_CLOEXEC only if socketpair() succeeds without SOCK_CLOEXEC. - * Ex. Socket.pair(:UNIX, 0xff) fails with EINVAL. - */ - cloexec_state = 0; - } - } - } - else { /* cloexec_state == 0 */ - ret = socketpair(domain, type, protocol, sv); - } - if (ret == -1) { - return -1; - } +#ifdef SOCK_NONBLOCK + type |= SOCK_NONBLOCK; +#endif -fix_cloexec: - rb_maygvl_fd_fix_cloexec(sv[0]); - rb_maygvl_fd_fix_cloexec(sv[1]); - if (RSOCK_NONBLOCK_DEFAULT) { - rsock_make_fd_nonblock(sv[0]); - rsock_make_fd_nonblock(sv[1]); - } + int result = socketpair(domain, type, protocol, descriptors); -update_max_fd: - rb_update_max_fd(sv[0]); - rb_update_max_fd(sv[1]); + if (result == -1) + return -1; - return ret; -} -#else /* !SOCK_CLOEXEC */ -static int -rsock_socketpair0(int domain, int type, int protocol, int sv[2]) -{ - int ret = socketpair(domain, type, protocol, sv); +#ifndef SOCK_CLOEXEC + rb_fd_fix_cloexec(descriptors[0]); + rb_fd_fix_cloexec(descriptors[1]); +#endif - if (ret == -1) - return -1; +#ifndef SOCK_NONBLOCK + rsock_make_fd_nonblock(descriptors[0]); + rsock_make_fd_nonblock(descriptors[1]); +#endif - rb_fd_fix_cloexec(sv[0]); - rb_fd_fix_cloexec(sv[1]); - if (RSOCK_NONBLOCK_DEFAULT) { - rsock_make_fd_nonblock(sv[0]); - rsock_make_fd_nonblock(sv[1]); - } - return ret; + return result; } -#endif /* !SOCK_CLOEXEC */ static int -rsock_socketpair(int domain, int type, int protocol, int sv[2]) +rsock_socketpair(int domain, int type, int protocol, int descriptors[2]) { - int ret; + int result; - ret = rsock_socketpair0(domain, type, protocol, sv); - if (ret < 0 && rb_gc_for_fd(errno)) { - ret = rsock_socketpair0(domain, type, protocol, sv); + result = rsock_socketpair0(domain, type, protocol, descriptors); + + if (result < 0 && rb_gc_for_fd(errno)) { + result = rsock_socketpair0(domain, type, protocol, descriptors); } - return ret; + return result; } /* @@ -302,7 +262,7 @@ rsock_sock_s_socketpair(int argc, VALUE *argv, VALUE klass) p = NUM2INT(protocol); ret = rsock_socketpair(d, t, p, sp); if (ret < 0) { - rb_sys_fail("socketpair(2)"); + rb_sys_fail("socketpair(2)"); } s1 = rsock_init_sock(rb_obj_alloc(klass), sp[0]); @@ -376,7 +336,7 @@ rsock_sock_s_socketpair(int argc, VALUE *argv, VALUE klass) * * Errno::EOPNOTSUPP - the calling +socket+ is listening and cannot be connected * * Errno::EPROTOTYPE - the _sockaddr_ has a different type than the socket * bound to the specified peer address - * * Errno::ETIMEDOUT - the attempt to connect time out before a connection + * * Errno::ETIMEDOUT - the attempt to connect timed out before a connection * was made. * * On unix-based systems if the address family of the calling +socket+ is @@ -417,7 +377,7 @@ rsock_sock_s_socketpair(int argc, VALUE *argv, VALUE klass) * * Errno::EHOSTUNREACH - no route to the network is present * * Errno::ENOBUFS - no buffer space is available * * Errno::ENOTSOCK - the +socket+ argument does not refer to a socket - * * Errno::ETIMEDOUT - the attempt to connect time out before a connection + * * Errno::ETIMEDOUT - the attempt to connect timed out before a connection * was made. * * Errno::EWOULDBLOCK - the socket is marked as nonblocking and the * connection cannot be completed immediately @@ -429,22 +389,20 @@ rsock_sock_s_socketpair(int argc, VALUE *argv, VALUE klass) * * connect function in Microsoft's Winsock functions reference */ static VALUE -sock_connect(VALUE sock, VALUE addr) +sock_connect(VALUE self, VALUE addr) { VALUE rai; - rb_io_t *fptr; - int fd, n; SockAddrStringValueWithAddrinfo(addr, rai); addr = rb_str_new4(addr); - GetOpenFile(sock, fptr); - fd = fptr->fd; - n = rsock_connect(fd, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_SOCKLEN(addr), 0); - if (n < 0) { - rsock_sys_fail_raddrinfo_or_sockaddr("connect(2)", addr, rai); + + int result = rsock_connect(self, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_SOCKLEN(addr), 0, RUBY_IO_TIMEOUT_DEFAULT); + + if (result < 0) { + rsock_sys_fail_raddrinfo_or_sockaddr("connect(2)", addr, rai); } - return INT2FIX(n); + return INT2FIX(result); } /* :nodoc: */ @@ -461,19 +419,19 @@ sock_connect_nonblock(VALUE sock, VALUE addr, VALUE ex) rb_io_set_nonblock(fptr); n = connect(fptr->fd, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_SOCKLEN(addr)); if (n < 0) { - int e = errno; - if (e == EINPROGRESS) { + int e = errno; + if (e == EINPROGRESS) { if (ex == Qfalse) { return sym_wait_writable; } rb_readwrite_syserr_fail(RB_IO_WAIT_WRITABLE, e, "connect(2) would block"); - } - if (e == EISCONN) { + } + if (e == EISCONN) { if (ex == Qfalse) { return INT2FIX(0); } - } - rsock_syserr_fail_raddrinfo_or_sockaddr(e, "connect(2)", addr, rai); + } + rsock_syserr_fail_raddrinfo_or_sockaddr(e, "connect(2)", addr, rai); } return INT2FIX(n); @@ -574,7 +532,7 @@ sock_bind(VALUE sock, VALUE addr) SockAddrStringValueWithAddrinfo(addr, rai); GetOpenFile(sock, fptr); if (bind(fptr->fd, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_SOCKLEN(addr)) < 0) - rsock_sys_fail_raddrinfo_or_sockaddr("bind(2)", addr, rai); + rsock_sys_fail_raddrinfo_or_sockaddr("bind(2)", addr, rai); return INT2FIX(0); } @@ -658,7 +616,7 @@ rsock_sock_listen(VALUE sock, VALUE log) backlog = NUM2INT(log); GetOpenFile(sock, fptr); if (listen(fptr->fd, backlog) < 0) - rb_sys_fail("listen(2)"); + rb_sys_fail("listen(2)"); return INT2FIX(0); } @@ -796,17 +754,14 @@ sock_recvfrom_nonblock(VALUE sock, VALUE len, VALUE flg, VALUE str, VALUE ex) * */ static VALUE -sock_accept(VALUE sock) +sock_accept(VALUE server) { - rb_io_t *fptr; - VALUE sock2; - union_sockaddr buf; - socklen_t len = (socklen_t)sizeof buf; + union_sockaddr buffer; + socklen_t length = (socklen_t)sizeof(buffer); - GetOpenFile(sock, fptr); - sock2 = rsock_s_accept(rb_cSocket,fptr->fd,&buf.addr,&len); + VALUE peer = rsock_s_accept(rb_cSocket, server, &buffer.addr, &length); - return rb_assoc_new(sock2, rsock_io_socket_addrinfo(sock2, &buf.addr, len)); + return rb_assoc_new(peer, rsock_io_socket_addrinfo(peer, &buffer.addr, length)); } /* :nodoc: */ @@ -823,7 +778,7 @@ sock_accept_nonblock(VALUE sock, VALUE ex) sock2 = rsock_s_accept_nonblock(rb_cSocket, ex, fptr, addr, &len); if (SYMBOL_P(sock2)) /* :wait_readable */ - return sock2; + return sock2; return rb_assoc_new(sock2, rsock_io_socket_addrinfo(sock2, &buf.addr, len)); } @@ -866,17 +821,14 @@ sock_accept_nonblock(VALUE sock, VALUE ex) * * Socket#accept */ static VALUE -sock_sysaccept(VALUE sock) +sock_sysaccept(VALUE server) { - rb_io_t *fptr; - VALUE sock2; - union_sockaddr buf; - socklen_t len = (socklen_t)sizeof buf; + union_sockaddr buffer; + socklen_t length = (socklen_t)sizeof(buffer); - GetOpenFile(sock, fptr); - sock2 = rsock_s_accept(0,fptr->fd,&buf.addr,&len); + VALUE peer = rsock_s_accept(0, server, &buffer.addr, &length); - return rb_assoc_new(sock2, rsock_io_socket_addrinfo(sock2, &buf.addr, len)); + return rb_assoc_new(peer, rsock_io_socket_addrinfo(peer, &buffer.addr, length)); } #ifdef HAVE_GETHOSTNAME @@ -907,19 +859,19 @@ sock_gethostname(VALUE obj) name = rb_str_new(0, len); while (gethostname(RSTRING_PTR(name), len) < 0) { - int e = errno; - switch (e) { - case ENAMETOOLONG: + int e = errno; + switch (e) { + case ENAMETOOLONG: #ifdef __linux__ - case EINVAL: - /* glibc before version 2.1 uses EINVAL instead of ENAMETOOLONG */ + case EINVAL: + /* glibc before version 2.1 uses EINVAL instead of ENAMETOOLONG */ #endif - break; - default: - rb_syserr_fail(e, "gethostname(3)"); - } - rb_str_modify_expand(name, len); - len += len; + break; + default: + rb_syserr_fail(e, "gethostname(3)"); + } + rb_str_modify_expand(name, len); + len += len; } rb_str_resize(name, strlen(RSTRING_PTR(name))); return name; @@ -949,18 +901,18 @@ make_addrinfo(struct rb_addrinfo *res0, int norevlookup) struct addrinfo *res; if (res0 == NULL) { - rb_raise(rb_eSocket, "host not found"); + rb_raise(rb_eSocket, "host not found"); } base = rb_ary_new(); for (res = res0->ai; res; res = res->ai_next) { - ary = rsock_ipaddr(res->ai_addr, res->ai_addrlen, norevlookup); - if (res->ai_canonname) { - RARRAY_ASET(ary, 2, rb_str_new2(res->ai_canonname)); - } - rb_ary_push(ary, INT2FIX(res->ai_family)); - rb_ary_push(ary, INT2FIX(res->ai_socktype)); - rb_ary_push(ary, INT2FIX(res->ai_protocol)); - rb_ary_push(base, ary); + ary = rsock_ipaddr(res->ai_addr, res->ai_addrlen, norevlookup); + if (res->ai_canonname) { + RARRAY_ASET(ary, 2, rb_str_new2(res->ai_canonname)); + } + rb_ary_push(ary, INT2FIX(res->ai_family)); + rb_ary_push(ary, INT2FIX(res->ai_socktype)); + rb_ary_push(ary, INT2FIX(res->ai_protocol)); + rb_ary_push(base, ary); } return base; } @@ -972,18 +924,18 @@ sock_sockaddr(struct sockaddr *addr, socklen_t len) switch (addr->sa_family) { case AF_INET: - ptr = (char*)&((struct sockaddr_in*)addr)->sin_addr.s_addr; - len = (socklen_t)sizeof(((struct sockaddr_in*)addr)->sin_addr.s_addr); - break; + ptr = (char*)&((struct sockaddr_in*)addr)->sin_addr.s_addr; + len = (socklen_t)sizeof(((struct sockaddr_in*)addr)->sin_addr.s_addr); + break; #ifdef AF_INET6 case AF_INET6: - ptr = (char*)&((struct sockaddr_in6*)addr)->sin6_addr.s6_addr; - len = (socklen_t)sizeof(((struct sockaddr_in6*)addr)->sin6_addr.s6_addr); - break; + ptr = (char*)&((struct sockaddr_in6*)addr)->sin6_addr.s6_addr; + len = (socklen_t)sizeof(((struct sockaddr_in6*)addr)->sin6_addr.s6_addr); + break; #endif default: rb_raise(rb_eSocket, "unknown socket family:%d", addr->sa_family); - break; + break; } return rb_str_new(ptr, len); } @@ -1011,8 +963,9 @@ sock_sockaddr(struct sockaddr *addr, socklen_t len) static VALUE sock_s_gethostbyname(VALUE obj, VALUE host) { + rb_warn("Socket.gethostbyname is deprecated; use Addrinfo.getaddrinfo instead."); struct rb_addrinfo *res = - rsock_addrinfo(host, Qnil, AF_UNSPEC, SOCK_STREAM, AI_CANONNAME); + rsock_addrinfo(host, Qnil, AF_UNSPEC, SOCK_STREAM, AI_CANONNAME, Qnil); return rsock_make_hostent(host, res, sock_sockaddr); } @@ -1042,7 +995,7 @@ sock_s_gethostbyname(VALUE obj, VALUE host) * */ static VALUE -sock_s_gethostbyaddr(int argc, VALUE *argv) +sock_s_gethostbyaddr(int argc, VALUE *argv, VALUE _) { VALUE addr, family; struct hostent *h; @@ -1050,23 +1003,25 @@ sock_s_gethostbyaddr(int argc, VALUE *argv) VALUE ary, names; int t = AF_INET; + rb_warn("Socket.gethostbyaddr is deprecated; use Addrinfo#getnameinfo instead."); + rb_scan_args(argc, argv, "11", &addr, &family); StringValue(addr); if (!NIL_P(family)) { - t = rsock_family_arg(family); + t = rsock_family_arg(family); } #ifdef AF_INET6 else if (RSTRING_LEN(addr) == 16) { - t = AF_INET6; + t = AF_INET6; } #endif h = gethostbyaddr(RSTRING_PTR(addr), RSTRING_SOCKLEN(addr), t); if (h == NULL) { #ifdef HAVE_HSTRERROR - extern int h_errno; - rb_raise(rb_eSocket, "%s", (char*)hstrerror(h_errno)); + extern int h_errno; + rb_raise(rb_eSocket, "%s", (char*)hstrerror(h_errno)); #else - rb_raise(rb_eSocket, "host not found"); + rb_raise(rb_eSocket, "host not found"); #endif } ary = rb_ary_new(); @@ -1074,14 +1029,14 @@ sock_s_gethostbyaddr(int argc, VALUE *argv) names = rb_ary_new(); rb_ary_push(ary, names); if (h->h_aliases != NULL) { - for (pch = h->h_aliases; *pch; pch++) { - rb_ary_push(names, rb_str_new2(*pch)); - } + for (pch = h->h_aliases; *pch; pch++) { + rb_ary_push(names, rb_str_new2(*pch)); + } } rb_ary_push(ary, INT2NUM(h->h_addrtype)); #ifdef h_addr for (pch = h->h_addr_list; *pch; pch++) { - rb_ary_push(ary, rb_str_new(*pch, h->h_length)); + rb_ary_push(ary, rb_str_new(*pch, h->h_length)); } #else rb_ary_push(ary, rb_str_new(h->h_addr, h->h_length)); @@ -1104,7 +1059,7 @@ sock_s_gethostbyaddr(int argc, VALUE *argv) * Socket.getservbyname("syslog", "udp") #=> 514 */ static VALUE -sock_s_getservbyname(int argc, VALUE *argv) +sock_s_getservbyname(int argc, VALUE *argv, VALUE _) { VALUE service, proto; struct servent *sp; @@ -1118,15 +1073,15 @@ sock_s_getservbyname(int argc, VALUE *argv) if (!NIL_P(proto)) protoname = StringValueCStr(proto); sp = getservbyname(servicename, protoname); if (sp) { - port = ntohs(sp->s_port); + port = ntohs(sp->s_port); } else { - char *end; + char *end; - port = STRTOUL(servicename, &end, 0); - if (*end != '\0') { - rb_raise(rb_eSocket, "no such service %s/%s", servicename, protoname); - } + port = STRTOUL(servicename, &end, 0); + if (*end != '\0') { + rb_raise(rb_eSocket, "no such service %s/%s", servicename, protoname); + } } return INT2FIX(port); } @@ -1145,7 +1100,7 @@ sock_s_getservbyname(int argc, VALUE *argv) * */ static VALUE -sock_s_getservbyport(int argc, VALUE *argv) +sock_s_getservbyport(int argc, VALUE *argv, VALUE _) { VALUE port, proto; struct servent *sp; @@ -1155,16 +1110,16 @@ sock_s_getservbyport(int argc, VALUE *argv) rb_scan_args(argc, argv, "11", &port, &proto); portnum = NUM2LONG(port); if (portnum != (uint16_t)portnum) { - const char *s = portnum > 0 ? "big" : "small"; - rb_raise(rb_eRangeError, "integer %ld too %s to convert into `int16_t'", portnum, s); + const char *s = portnum > 0 ? "big" : "small"; + rb_raise(rb_eRangeError, "integer %ld too %s to convert into `int16_t'", portnum, s); } if (!NIL_P(proto)) protoname = StringValueCStr(proto); sp = getservbyport((int)htons((uint16_t)portnum), protoname); if (!sp) { - rb_raise(rb_eSocket, "no such service for port %d/%s", (int)portnum, protoname); + rb_raise(rb_eSocket, "no such service for port %d/%s", (int)portnum, protoname); } - return rb_tainted_str_new2(sp->s_name); + return rb_str_new2(sp->s_name); } /* @@ -1197,13 +1152,13 @@ sock_s_getservbyport(int argc, VALUE *argv) * be one of below. If _reverse_lookup_ is omitted, the default value is +nil+. * * +true+, +:hostname+: hostname is obtained from numeric address using reverse lookup, which may take a time. - * +false+, +:numeric+: hostname is same as numeric address. + * +false+, +:numeric+: hostname is the same as numeric address. * +nil+: obey to the current +do_not_reverse_lookup+ flag. * * If Addrinfo object is preferred, use Addrinfo.getaddrinfo. */ static VALUE -sock_s_getaddrinfo(int argc, VALUE *argv) +sock_s_getaddrinfo(int argc, VALUE *argv, VALUE _) { VALUE host, port, family, socktype, protocol, flags, ret, revlookup; struct addrinfo hints; @@ -1216,18 +1171,19 @@ sock_s_getaddrinfo(int argc, VALUE *argv) hints.ai_family = NIL_P(family) ? PF_UNSPEC : rsock_family_arg(family); if (!NIL_P(socktype)) { - hints.ai_socktype = rsock_socktype_arg(socktype); + hints.ai_socktype = rsock_socktype_arg(socktype); } if (!NIL_P(protocol)) { - hints.ai_protocol = NUM2INT(protocol); + hints.ai_protocol = NUM2INT(protocol); } if (!NIL_P(flags)) { - hints.ai_flags = NUM2INT(flags); + hints.ai_flags = NUM2INT(flags); } if (NIL_P(revlookup) || !rsock_revlookup_flag(revlookup, &norevlookup)) { - norevlookup = rsock_do_not_reverse_lookup; + norevlookup = rsock_do_not_reverse_lookup; } - res = rsock_getaddrinfo(host, port, &hints, 0); + + res = rsock_getaddrinfo(host, port, &hints, 0, Qnil); ret = make_addrinfo(res, norevlookup); rb_freeaddrinfo(res); @@ -1257,10 +1213,9 @@ sock_s_getaddrinfo(int argc, VALUE *argv) * If Addrinfo object is preferred, use Addrinfo#getnameinfo. */ static VALUE -sock_s_getnameinfo(int argc, VALUE *argv) +sock_s_getnameinfo(int argc, VALUE *argv, VALUE _) { VALUE sa, af = Qnil, host = Qnil, port = Qnil, flags, tmp; - char *hptr, *pptr; char hbuf[1024], pbuf[1024]; int fl; struct rb_addrinfo *res = NULL; @@ -1275,120 +1230,90 @@ sock_s_getnameinfo(int argc, VALUE *argv) fl = 0; if (!NIL_P(flags)) { - fl = NUM2INT(flags); + fl = NUM2INT(flags); } tmp = rb_check_sockaddr_string_type(sa); if (!NIL_P(tmp)) { - sa = tmp; - if (sizeof(ss) < (size_t)RSTRING_LEN(sa)) { - rb_raise(rb_eTypeError, "sockaddr length too big"); - } - memcpy(&ss, RSTRING_PTR(sa), RSTRING_LEN(sa)); + sa = tmp; + if (sizeof(ss) < (size_t)RSTRING_LEN(sa)) { + rb_raise(rb_eTypeError, "sockaddr length too big"); + } + memcpy(&ss, RSTRING_PTR(sa), RSTRING_LEN(sa)); if (!VALIDATE_SOCKLEN(&ss.addr, RSTRING_LEN(sa))) { - rb_raise(rb_eTypeError, "sockaddr size differs - should not happen"); - } - sap = &ss.addr; + rb_raise(rb_eTypeError, "sockaddr size differs - should not happen"); + } + sap = &ss.addr; salen = RSTRING_SOCKLEN(sa); - goto call_nameinfo; + goto call_nameinfo; } tmp = rb_check_array_type(sa); if (!NIL_P(tmp)) { - sa = tmp; - MEMZERO(&hints, struct addrinfo, 1); - if (RARRAY_LEN(sa) == 3) { - af = RARRAY_AREF(sa, 0); - port = RARRAY_AREF(sa, 1); - host = RARRAY_AREF(sa, 2); - } - else if (RARRAY_LEN(sa) >= 4) { - af = RARRAY_AREF(sa, 0); - port = RARRAY_AREF(sa, 1); - host = RARRAY_AREF(sa, 3); - if (NIL_P(host)) { - host = RARRAY_AREF(sa, 2); - } - else { - /* - * 4th element holds numeric form, don't resolve. - * see rsock_ipaddr(). - */ + sa = tmp; + MEMZERO(&hints, struct addrinfo, 1); + if (RARRAY_LEN(sa) == 3) { + af = RARRAY_AREF(sa, 0); + port = RARRAY_AREF(sa, 1); + host = RARRAY_AREF(sa, 2); + } + else if (RARRAY_LEN(sa) >= 4) { + af = RARRAY_AREF(sa, 0); + port = RARRAY_AREF(sa, 1); + host = RARRAY_AREF(sa, 3); + if (NIL_P(host)) { + host = RARRAY_AREF(sa, 2); + } + else { + /* + * 4th element holds numeric form, don't resolve. + * see rsock_ipaddr(). + */ #ifdef AI_NUMERICHOST /* AIX 4.3.3 doesn't have AI_NUMERICHOST. */ - hints.ai_flags |= AI_NUMERICHOST; + hints.ai_flags |= AI_NUMERICHOST; #endif - } - } - else { - rb_raise(rb_eArgError, "array size should be 3 or 4, %ld given", - RARRAY_LEN(sa)); - } - /* host */ - if (NIL_P(host)) { - hptr = NULL; - } - else { - strncpy(hbuf, StringValueCStr(host), sizeof(hbuf)); - hbuf[sizeof(hbuf) - 1] = '\0'; - hptr = hbuf; - } - /* port */ - if (NIL_P(port)) { - strcpy(pbuf, "0"); - pptr = NULL; - } - else if (FIXNUM_P(port)) { - snprintf(pbuf, sizeof(pbuf), "%ld", NUM2LONG(port)); - pptr = pbuf; - } - else { - strncpy(pbuf, StringValueCStr(port), sizeof(pbuf)); - pbuf[sizeof(pbuf) - 1] = '\0'; - pptr = pbuf; - } - hints.ai_socktype = (fl & NI_DGRAM) ? SOCK_DGRAM : SOCK_STREAM; - /* af */ + } + } + else { + rb_raise(rb_eArgError, "array size should be 3 or 4, %ld given", + RARRAY_LEN(sa)); + } + hints.ai_socktype = (fl & NI_DGRAM) ? SOCK_DGRAM : SOCK_STREAM; + /* af */ hints.ai_family = NIL_P(af) ? PF_UNSPEC : rsock_family_arg(af); - error = rb_getaddrinfo(hptr, pptr, &hints, &res); - if (error) goto error_exit_addr; - sap = res->ai->ai_addr; + res = rsock_getaddrinfo(host, port, &hints, 0, Qnil); + sap = res->ai->ai_addr; salen = res->ai->ai_addrlen; } else { - rb_raise(rb_eTypeError, "expecting String or Array"); + rb_raise(rb_eTypeError, "expecting String or Array"); } call_nameinfo: error = rb_getnameinfo(sap, salen, hbuf, sizeof(hbuf), - pbuf, sizeof(pbuf), fl); + pbuf, sizeof(pbuf), fl); if (error) goto error_exit_name; if (res) { - for (r = res->ai->ai_next; r; r = r->ai_next) { - char hbuf2[1024], pbuf2[1024]; + for (r = res->ai->ai_next; r; r = r->ai_next) { + char hbuf2[1024], pbuf2[1024]; - sap = r->ai_addr; + sap = r->ai_addr; salen = r->ai_addrlen; - error = rb_getnameinfo(sap, salen, hbuf2, sizeof(hbuf2), - pbuf2, sizeof(pbuf2), fl); - if (error) goto error_exit_name; - if (strcmp(hbuf, hbuf2) != 0|| strcmp(pbuf, pbuf2) != 0) { - rb_freeaddrinfo(res); - rb_raise(rb_eSocket, "sockaddr resolved to multiple nodename"); - } - } - rb_freeaddrinfo(res); + error = rb_getnameinfo(sap, salen, hbuf2, sizeof(hbuf2), + pbuf2, sizeof(pbuf2), fl); + if (error) goto error_exit_name; + if (strcmp(hbuf, hbuf2) != 0|| strcmp(pbuf, pbuf2) != 0) { + rb_freeaddrinfo(res); + rb_raise(rb_eSocket, "sockaddr resolved to multiple nodename"); + } + } + rb_freeaddrinfo(res); } return rb_assoc_new(rb_str_new2(hbuf), rb_str_new2(pbuf)); - error_exit_addr: - saved_errno = errno; - if (res) rb_freeaddrinfo(res); - errno = saved_errno; - rsock_raise_socket_error("getaddrinfo", error); - error_exit_name: saved_errno = errno; if (res) rb_freeaddrinfo(res); errno = saved_errno; - rsock_raise_socket_error("getnameinfo", error); + rsock_raise_resolution_error("getnameinfo", error); UNREACHABLE_RETURN(Qnil); } @@ -1410,12 +1335,10 @@ sock_s_getnameinfo(int argc, VALUE *argv) static VALUE sock_s_pack_sockaddr_in(VALUE self, VALUE port, VALUE host) { - struct rb_addrinfo *res = rsock_addrinfo(host, port, AF_UNSPEC, 0, 0); + struct rb_addrinfo *res = rsock_addrinfo(host, port, AF_UNSPEC, 0, 0, Qnil); VALUE addr = rb_str_new((char*)res->ai->ai_addr, res->ai->ai_addrlen); rb_freeaddrinfo(res); - OBJ_INFECT(addr, port); - OBJ_INFECT(addr, host); return addr; } @@ -1457,11 +1380,10 @@ sock_s_unpack_sockaddr_in(VALUE self, VALUE addr) #endif } host = rsock_make_ipaddr((struct sockaddr*)sockaddr, RSTRING_SOCKLEN(addr)); - OBJ_INFECT(host, addr); return rb_assoc_new(INT2NUM(ntohs(sockaddr->sin_port)), host); } -#ifdef HAVE_SYS_UN_H +#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN /* * call-seq: @@ -1487,7 +1409,6 @@ sock_s_pack_sockaddr_un(VALUE self, VALUE path) } memcpy(sockaddr.sun_path, RSTRING_PTR(path), RSTRING_LEN(path)); addr = rb_str_new((char*)&sockaddr, rsock_unix_sockaddr_len(path)); - OBJ_INFECT(addr, path); return addr; } @@ -1520,11 +1441,10 @@ sock_s_unpack_sockaddr_un(VALUE self, VALUE addr) rb_raise(rb_eArgError, "not an AF_UNIX sockaddr"); } if (sizeof(struct sockaddr_un) < (size_t)RSTRING_LEN(addr)) { - rb_raise(rb_eTypeError, "too long sockaddr_un - %ld longer than %d", - RSTRING_LEN(addr), (int)sizeof(struct sockaddr_un)); + rb_raise(rb_eTypeError, "too long sockaddr_un - %ld longer than %d", + RSTRING_LEN(addr), (int)sizeof(struct sockaddr_un)); } path = rsock_unixpath_str(sockaddr, RSTRING_SOCKLEN(addr)); - OBJ_INFECT(path, addr); return path; } #endif @@ -1551,7 +1471,7 @@ sockaddr_len(struct sockaddr *addr) return (socklen_t)sizeof(struct sockaddr_in6); #endif -#ifdef HAVE_SYS_UN_H +#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN case AF_UNIX: return (socklen_t)sizeof(struct sockaddr_un); #endif @@ -1586,19 +1506,19 @@ sockaddr_obj(struct sockaddr *addr, socklen_t len) #if defined(__KAME__) && defined(AF_INET6) if (addr->sa_family == AF_INET6) { - /* KAME uses the 2nd 16bit word of link local IPv6 address as interface index internally */ + /* KAME uses the 2nd 16bit word of link local IPv6 address as interface index internally */ /* http://orange.kame.net/dev/cvsweb.cgi/kame/IMPLEMENTATION */ - /* convert fe80:1::1 to fe80::1%1 */ + /* convert fe80:1::1 to fe80::1%1 */ len = (socklen_t)sizeof(struct sockaddr_in6); - memcpy(&addr6, addr, len); - addr = (struct sockaddr *)&addr6; - if (IN6_IS_ADDR_LINKLOCAL(&addr6.sin6_addr) && - addr6.sin6_scope_id == 0 && - (addr6.sin6_addr.s6_addr[2] || addr6.sin6_addr.s6_addr[3])) { - addr6.sin6_scope_id = (addr6.sin6_addr.s6_addr[2] << 8) | addr6.sin6_addr.s6_addr[3]; - addr6.sin6_addr.s6_addr[2] = 0; - addr6.sin6_addr.s6_addr[3] = 0; - } + memcpy(&addr6, addr, len); + addr = (struct sockaddr *)&addr6; + if (IN6_IS_ADDR_LINKLOCAL(&addr6.sin6_addr) && + addr6.sin6_scope_id == 0 && + (addr6.sin6_addr.s6_addr[2] || addr6.sin6_addr.s6_addr[3])) { + addr6.sin6_scope_id = (addr6.sin6_addr.s6_addr[2] << 8) | addr6.sin6_addr.s6_addr[3]; + addr6.sin6_addr.s6_addr[2] = 0; + addr6.sin6_addr.s6_addr[3] = 0; + } } #endif @@ -1613,7 +1533,7 @@ rsock_sockaddr_obj(struct sockaddr *addr, socklen_t len) #endif -#if defined(HAVE_GETIFADDRS) || (defined(SIOCGLIFCONF) && defined(SIOCGLIFNUM) && !defined(__hpux)) || defined(SIOCGIFCONF) || defined(_WIN32) +#if defined(HAVE_GETIFADDRS) || (defined(SIOCGLIFCONF) && defined(SIOCGLIFNUM)) || defined(SIOCGIFCONF) || defined(_WIN32) /* * call-seq: * Socket.ip_address_list => array @@ -1674,9 +1594,8 @@ socket_s_ip_address_list(VALUE self) freeifaddrs(ifp); return list; -#elif defined(SIOCGLIFCONF) && defined(SIOCGLIFNUM) && !defined(__hpux) +#elif defined(SIOCGLIFCONF) && defined(SIOCGLIFNUM) /* Solaris if_tcp(7P) */ - /* HP-UX has SIOCGLIFCONF too. But it uses different struct */ int fd = -1; int ret; struct lifnum ln; @@ -1697,8 +1616,8 @@ socket_s_ip_address_list(VALUE self) ret = ioctl(fd, SIOCGLIFNUM, &ln); if (ret == -1) { - reason = "SIOCGLIFNUM"; - goto finish; + reason = "SIOCGLIFNUM"; + goto finish; } memset(&lc, 0, sizeof(lc)); @@ -1709,13 +1628,13 @@ socket_s_ip_address_list(VALUE self) ret = ioctl(fd, SIOCGLIFCONF, &lc); if (ret == -1) { - reason = "SIOCGLIFCONF"; - goto finish; + reason = "SIOCGLIFCONF"; + goto finish; } list = rb_ary_new(); for (i = 0; i < ln.lifn_count; i++) { - struct lifreq *req = &lc.lifc_req[i]; + struct lifreq *req = &lc.lifc_req[i]; if (IS_IP_FAMILY(req->lifr_addr.ss_family)) { if (req->lifr_addr.ss_family == AF_INET6 && IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)(&req->lifr_addr))->sin6_addr) && @@ -1735,14 +1654,13 @@ socket_s_ip_address_list(VALUE self) finish: save_errno = errno; - if (lc.lifc_buf != NULL) - xfree(lc.lifc_req); + xfree(lc.lifc_req); if (fd != -1) - close(fd); + close(fd); errno = save_errno; if (reason) - rb_syserr_fail(save_errno, reason); + rb_syserr_fail(save_errno, reason); return list; #elif defined(SIOCGIFCONF) @@ -1780,17 +1698,17 @@ socket_s_ip_address_list(VALUE self) /* fprintf(stderr, "conf.ifc_len: %d\n", conf.ifc_len); */ if (bufsize - EXTRA_SPACE < conf.ifc_len) { - if (bufsize < conf.ifc_len) { - /* NetBSD returns required size for all interfaces. */ - bufsize = conf.ifc_len + EXTRA_SPACE; - } - else { - bufsize = bufsize << 1; - } - if (buf == initbuf) - buf = NULL; - buf = xrealloc(buf, bufsize); - goto retry; + if (bufsize < conf.ifc_len) { + /* NetBSD returns required size for all interfaces. */ + bufsize = conf.ifc_len + EXTRA_SPACE; + } + else { + bufsize = bufsize << 1; + } + if (buf == initbuf) + buf = NULL; + buf = xrealloc(buf, bufsize); + goto retry; } close(fd); @@ -1799,10 +1717,10 @@ socket_s_ip_address_list(VALUE self) list = rb_ary_new(); req = conf.ifc_req; while ((char*)req < (char*)conf.ifc_req + conf.ifc_len) { - struct sockaddr *addr = &req->ifr_addr; + struct sockaddr *addr = &req->ifr_addr; if (IS_IP_FAMILY(addr->sa_family)) { - rb_ary_push(list, sockaddr_obj(addr, sockaddr_len(addr))); - } + rb_ary_push(list, sockaddr_obj(addr, sockaddr_len(addr))); + } #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN # ifndef _SIZEOF_ADDR_IFREQ # define _SIZEOF_ADDR_IFREQ(r) \ @@ -1811,9 +1729,9 @@ socket_s_ip_address_list(VALUE self) (r).ifr_addr.sa_len - sizeof(struct sockaddr) : \ 0)) # endif - req = (struct ifreq *)((char*)req + _SIZEOF_ADDR_IFREQ(*req)); + req = (struct ifreq *)((char*)req + _SIZEOF_ADDR_IFREQ(*req)); #else - req = (struct ifreq *)((char*)req + sizeof(struct ifreq)); + req = (struct ifreq *)((char*)req + sizeof(struct ifreq)); #endif } @@ -1823,57 +1741,57 @@ socket_s_ip_address_list(VALUE self) if (buf != initbuf) xfree(buf); if (fd != -1) - close(fd); + close(fd); errno = save_errno; if (reason) - rb_syserr_fail(save_errno, reason); + rb_syserr_fail(save_errno, reason); return list; #undef EXTRA_SPACE #elif defined(_WIN32) typedef struct ip_adapter_unicast_address_st { - unsigned LONG_LONG dummy0; - struct ip_adapter_unicast_address_st *Next; - struct { - struct sockaddr *lpSockaddr; - int iSockaddrLength; - } Address; - int dummy1; - int dummy2; - int dummy3; - long dummy4; - long dummy5; - long dummy6; + unsigned LONG_LONG dummy0; + struct ip_adapter_unicast_address_st *Next; + struct { + struct sockaddr *lpSockaddr; + int iSockaddrLength; + } Address; + int dummy1; + int dummy2; + int dummy3; + long dummy4; + long dummy5; + long dummy6; } ip_adapter_unicast_address_t; typedef struct ip_adapter_anycast_address_st { - unsigned LONG_LONG dummy0; - struct ip_adapter_anycast_address_st *Next; - struct { - struct sockaddr *lpSockaddr; - int iSockaddrLength; - } Address; + unsigned LONG_LONG dummy0; + struct ip_adapter_anycast_address_st *Next; + struct { + struct sockaddr *lpSockaddr; + int iSockaddrLength; + } Address; } ip_adapter_anycast_address_t; typedef struct ip_adapter_addresses_st { - unsigned LONG_LONG dummy0; - struct ip_adapter_addresses_st *Next; - void *dummy1; - ip_adapter_unicast_address_t *FirstUnicastAddress; - ip_adapter_anycast_address_t *FirstAnycastAddress; - void *dummy2; - void *dummy3; - void *dummy4; - void *dummy5; - void *dummy6; - BYTE dummy7[8]; - DWORD dummy8; - DWORD dummy9; - DWORD dummy10; - DWORD IfType; - int OperStatus; - DWORD dummy12; - DWORD dummy13[16]; - void *dummy14; + unsigned LONG_LONG dummy0; + struct ip_adapter_addresses_st *Next; + void *dummy1; + ip_adapter_unicast_address_t *FirstUnicastAddress; + ip_adapter_anycast_address_t *FirstAnycastAddress; + void *dummy2; + void *dummy3; + void *dummy4; + void *dummy5; + void *dummy6; + BYTE dummy7[8]; + DWORD dummy8; + DWORD dummy9; + DWORD dummy10; + DWORD IfType; + int OperStatus; + DWORD dummy12; + DWORD dummy13[16]; + void *dummy14; } ip_adapter_addresses_t; typedef ULONG (WINAPI *GetAdaptersAddresses_t)(ULONG, ULONG, PVOID, ip_adapter_addresses_t *, PULONG); HMODULE h; @@ -1885,49 +1803,49 @@ socket_s_ip_address_list(VALUE self) h = LoadLibrary("iphlpapi.dll"); if (!h) - rb_notimplement(); + rb_notimplement(); pGetAdaptersAddresses = (GetAdaptersAddresses_t)GetProcAddress(h, "GetAdaptersAddresses"); if (!pGetAdaptersAddresses) { - FreeLibrary(h); - rb_notimplement(); + FreeLibrary(h); + rb_notimplement(); } ret = pGetAdaptersAddresses(AF_UNSPEC, 0, NULL, NULL, &len); if (ret != ERROR_SUCCESS && ret != ERROR_BUFFER_OVERFLOW) { - errno = rb_w32_map_errno(ret); - FreeLibrary(h); - rb_sys_fail("GetAdaptersAddresses"); + errno = rb_w32_map_errno(ret); + FreeLibrary(h); + rb_sys_fail("GetAdaptersAddresses"); } adapters = (ip_adapter_addresses_t *)ALLOCA_N(BYTE, len); ret = pGetAdaptersAddresses(AF_UNSPEC, 0, NULL, adapters, &len); if (ret != ERROR_SUCCESS) { - errno = rb_w32_map_errno(ret); - FreeLibrary(h); - rb_sys_fail("GetAdaptersAddresses"); + errno = rb_w32_map_errno(ret); + FreeLibrary(h); + rb_sys_fail("GetAdaptersAddresses"); } list = rb_ary_new(); for (; adapters; adapters = adapters->Next) { - ip_adapter_unicast_address_t *uni; - ip_adapter_anycast_address_t *any; - if (adapters->OperStatus != 1) /* 1 means IfOperStatusUp */ - continue; - for (uni = adapters->FirstUnicastAddress; uni; uni = uni->Next) { + ip_adapter_unicast_address_t *uni; + ip_adapter_anycast_address_t *any; + if (adapters->OperStatus != 1) /* 1 means IfOperStatusUp */ + continue; + for (uni = adapters->FirstUnicastAddress; uni; uni = uni->Next) { #ifndef INET6 - if (uni->Address.lpSockaddr->sa_family == AF_INET) + if (uni->Address.lpSockaddr->sa_family == AF_INET) #else - if (IS_IP_FAMILY(uni->Address.lpSockaddr->sa_family)) + if (IS_IP_FAMILY(uni->Address.lpSockaddr->sa_family)) #endif - rb_ary_push(list, sockaddr_obj(uni->Address.lpSockaddr, uni->Address.iSockaddrLength)); - } - for (any = adapters->FirstAnycastAddress; any; any = any->Next) { + rb_ary_push(list, sockaddr_obj(uni->Address.lpSockaddr, uni->Address.iSockaddrLength)); + } + for (any = adapters->FirstAnycastAddress; any; any = any->Next) { #ifndef INET6 - if (any->Address.lpSockaddr->sa_family == AF_INET) + if (any->Address.lpSockaddr->sa_family == AF_INET) #else - if (IS_IP_FAMILY(any->Address.lpSockaddr->sa_family)) + if (IS_IP_FAMILY(any->Address.lpSockaddr->sa_family)) #endif - rb_ary_push(list, sockaddr_obj(any->Address.lpSockaddr, any->Address.iSockaddrLength)); - } + rb_ary_push(list, sockaddr_obj(any->Address.lpSockaddr, any->Address.iSockaddrLength)); + } } FreeLibrary(h); @@ -1938,9 +1856,72 @@ socket_s_ip_address_list(VALUE self) #define socket_s_ip_address_list rb_f_notimplement #endif +/* + * call-seq: + * Socket.tcp_fast_fallback -> true or false + * + * Returns whether Happy Eyeballs Version 2 ({RFC 8305}[https://datatracker.ietf.org/doc/html/rfc8305]), + * which is provided starting from Ruby 3.4 when using TCPSocket.new and Socket.tcp, + * is enabled or disabled. + * + * If true, it is enabled for TCPSocket.new and Socket.tcp. + * (Note: Happy Eyeballs Version 2 is not provided when using TCPSocket.new on Windows.) + * + * If false, Happy Eyeballs Version 2 is disabled. + * + * For details on Happy Eyeballs Version 2, + * see {Socket.tcp_fast_fallback=}[rdoc-ref:Socket.tcp_fast_fallback=]. + */ +VALUE socket_s_tcp_fast_fallback(VALUE self) { + return rb_ivar_get(rb_cSocket, tcp_fast_fallback); +} + +/* + * call-seq: + * Socket.tcp_fast_fallback= -> true or false + * + * Enable or disable Happy Eyeballs Version 2 ({RFC 8305}[https://datatracker.ietf.org/doc/html/rfc8305]) + * globally, which is provided starting from Ruby 3.4 when using TCPSocket.new and Socket.tcp. + * + * When set to true, the feature is enabled for both `TCPSocket.new` and `Socket.tcp`. + * (Note: This feature is not available when using TCPSocket.new on Windows.) + * + * When set to false, the behavior reverts to that of Ruby 3.3 or earlier. + * + * The default value is true if no value is explicitly set by calling this method. + * However, when the environment variable RUBY_TCP_NO_FAST_FALLBACK=1 is set, + * the default is false. + * + * To control the setting on a per-method basis, use the fast_fallback keyword argument for each method. + * + * === Happy Eyeballs Version 2 + * Happy Eyeballs Version 2 ({RFC 8305}[https://datatracker.ietf.org/doc/html/rfc8305]) + * is an algorithm designed to improve client socket connectivity.<br> + * It aims for more reliable and efficient connections by performing hostname resolution + * and connection attempts in parallel, instead of serially. + * + * Starting from Ruby 3.4, this method operates as follows with this algorithm: + * + * 1. Start resolving both IPv6 and IPv4 addresses concurrently. + * 2. Start connecting to the one of the addresses that are obtained first.<br>If IPv4 addresses are obtained first, + * the method waits 50 ms for IPv6 name resolution to prioritize IPv6 connections. + * 3. After starting a connection attempt, wait 250 ms for the connection to be established.<br> + * If no connection is established within this time, a new connection is started every 250 ms<br> + * until a connection is established or there are no more candidate addresses.<br> + * (Although RFC 8305 strictly specifies sorting addresses,<br> + * this method only alternates between IPv6 / IPv4 addresses due to the performance concerns) + * 4. Once a connection is established, all remaining connection attempts are canceled. + */ +VALUE socket_s_tcp_fast_fallback_set(VALUE self, VALUE value) { + rb_ivar_set(rb_cSocket, tcp_fast_fallback, value); + return value; +} + void Init_socket(void) { + rb_ext_ractor_safe(true); + rsock_init_basicsocket(); /* @@ -2064,12 +2045,22 @@ Init_socket(void) rsock_init_socket_init(); + const char *tcp_no_fast_fallback_config = getenv("RUBY_TCP_NO_FAST_FALLBACK"); + VALUE fast_fallback_default; + if (tcp_no_fast_fallback_config == NULL || strcmp(tcp_no_fast_fallback_config, "0") == 0) { + fast_fallback_default = Qtrue; + } else { + fast_fallback_default = Qfalse; + } + tcp_fast_fallback = rb_intern_const("tcp_fast_fallback"); + rb_ivar_set(rb_cSocket, tcp_fast_fallback, fast_fallback_default); + rb_define_method(rb_cSocket, "initialize", sock_initialize, -1); rb_define_method(rb_cSocket, "connect", sock_connect, 1); /* for ext/socket/lib/socket.rb use only: */ rb_define_private_method(rb_cSocket, - "__connect_nonblock", sock_connect_nonblock, 2); + "__connect_nonblock", sock_connect_nonblock, 2); rb_define_method(rb_cSocket, "bind", sock_bind, 1); rb_define_method(rb_cSocket, "listen", rsock_sock_listen, 1); @@ -2077,7 +2068,7 @@ Init_socket(void) /* for ext/socket/lib/socket.rb use only: */ rb_define_private_method(rb_cSocket, - "__accept_nonblock", sock_accept_nonblock, 1); + "__accept_nonblock", sock_accept_nonblock, 1); rb_define_method(rb_cSocket, "sysaccept", sock_sysaccept, 0); @@ -2085,7 +2076,7 @@ Init_socket(void) /* for ext/socket/lib/socket.rb use only: */ rb_define_private_method(rb_cSocket, - "__recvfrom_nonblock", sock_recvfrom_nonblock, 4); + "__recvfrom_nonblock", sock_recvfrom_nonblock, 4); rb_define_singleton_method(rb_cSocket, "socketpair", rsock_sock_s_socketpair, -1); rb_define_singleton_method(rb_cSocket, "pair", rsock_sock_s_socketpair, -1); @@ -2099,7 +2090,7 @@ Init_socket(void) rb_define_singleton_method(rb_cSocket, "sockaddr_in", sock_s_pack_sockaddr_in, 2); rb_define_singleton_method(rb_cSocket, "pack_sockaddr_in", sock_s_pack_sockaddr_in, 2); rb_define_singleton_method(rb_cSocket, "unpack_sockaddr_in", sock_s_unpack_sockaddr_in, 1); -#ifdef HAVE_SYS_UN_H +#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN rb_define_singleton_method(rb_cSocket, "sockaddr_un", sock_s_pack_sockaddr_un, 1); rb_define_singleton_method(rb_cSocket, "pack_sockaddr_un", sock_s_pack_sockaddr_un, 1); rb_define_singleton_method(rb_cSocket, "unpack_sockaddr_un", sock_s_unpack_sockaddr_un, 1); @@ -2107,6 +2098,9 @@ Init_socket(void) rb_define_singleton_method(rb_cSocket, "ip_address_list", socket_s_ip_address_list, 0); + rb_define_singleton_method(rb_cSocket, "tcp_fast_fallback", socket_s_tcp_fast_fallback, 0); + rb_define_singleton_method(rb_cSocket, "tcp_fast_fallback=", socket_s_tcp_fast_fallback_set, 1); + #undef rb_intern sym_wait_writable = ID2SYM(rb_intern("wait_writable")); } diff --git a/ext/socket/sockssocket.c b/ext/socket/sockssocket.c index 81f77a67c5..30860ea257 100644 --- a/ext/socket/sockssocket.c +++ b/ext/socket/sockssocket.c @@ -13,22 +13,29 @@ #ifdef SOCKS /* * call-seq: - * SOCKSSocket.new(host, serv) => socket + * SOCKSSocket.new(host, port) => socket * - * Opens a SOCKS connection to +host+ via the SOCKS server +serv+. + * Opens a SOCKS connection to +host+ via the SOCKS server. + * + * The SOCKS server configuration varies by implementation + * + * When using the Dante libsocks/libsocksd implementation it is configured as SOCKS_SERVER env var. + * + * See: https://manpages.debian.org/testing/dante-client/socksify.1.en.html for full env variable support. * */ static VALUE -socks_init(VALUE sock, VALUE host, VALUE serv) +socks_init(VALUE sock, VALUE host, VALUE port) { static int init = 0; if (init == 0) { - SOCKSinit("ruby"); - init = 1; + char progname[] = "ruby"; + SOCKSinit(progname); + init = 1; } - return rsock_init_inetsock(sock, host, serv, Qnil, Qnil, INET_SOCKS); + return rsock_init_inetsock(sock, host, port, Qnil, Qnil, INET_SOCKS, Qnil, Qnil, Qnil, Qfalse, Qnil); } #ifdef SOCKS5 @@ -42,7 +49,7 @@ socks_s_close(VALUE sock) rb_io_t *fptr; GetOpenFile(sock, fptr); - shutdown(fptr->fd, 2); + shutdown(fptr->fd, SHUT_RDWR); return rb_io_close(sock); } #endif diff --git a/ext/socket/tcpserver.c b/ext/socket/tcpserver.c index 1bbb31adcf..0069f3c703 100644 --- a/ext/socket/tcpserver.c +++ b/ext/socket/tcpserver.c @@ -36,7 +36,7 @@ tcp_svr_init(int argc, VALUE *argv, VALUE sock) VALUE hostname, port; rb_scan_args(argc, argv, "011", &hostname, &port); - return rsock_init_inetsock(sock, hostname, port, Qnil, Qnil, INET_SERVER); + return rsock_init_inetsock(sock, hostname, port, Qnil, Qnil, INET_SERVER, Qnil, Qnil, Qnil, Qfalse, Qnil); } /* @@ -53,15 +53,12 @@ tcp_svr_init(int argc, VALUE *argv, VALUE sock) * */ static VALUE -tcp_accept(VALUE sock) +tcp_accept(VALUE server) { - rb_io_t *fptr; - union_sockaddr from; - socklen_t fromlen; + union_sockaddr buffer; + socklen_t length = sizeof(buffer); - GetOpenFile(sock, fptr); - fromlen = (socklen_t)sizeof(from); - return rsock_s_accept(rb_cTCPSocket, fptr->fd, &from.addr, &fromlen); + return rsock_s_accept(rb_cTCPSocket, server, &buffer.addr, &length); } /* :nodoc: */ @@ -91,15 +88,12 @@ tcp_accept_nonblock(VALUE sock, VALUE ex) * */ static VALUE -tcp_sysaccept(VALUE sock) +tcp_sysaccept(VALUE server) { - rb_io_t *fptr; - union_sockaddr from; - socklen_t fromlen; + union_sockaddr buffer; + socklen_t length = sizeof(buffer); - GetOpenFile(sock, fptr); - fromlen = (socklen_t)sizeof(from); - return rsock_s_accept(0, fptr->fd, &from.addr, &fromlen); + return rsock_s_accept(0, server, &buffer.addr, &length); } void @@ -139,7 +133,7 @@ rsock_init_tcpserver(void) rb_cTCPServer = rb_define_class("TCPServer", rb_cTCPSocket); rb_define_method(rb_cTCPServer, "accept", tcp_accept, 0); rb_define_private_method(rb_cTCPServer, - "__accept_nonblock", tcp_accept_nonblock, 1); + "__accept_nonblock", tcp_accept_nonblock, 1); rb_define_method(rb_cTCPServer, "sysaccept", tcp_sysaccept, 0); rb_define_method(rb_cTCPServer, "initialize", tcp_svr_init, -1); rb_define_method(rb_cTCPServer, "listen", rsock_sock_listen, 1); /* in socket.c */ diff --git a/ext/socket/tcpsocket.c b/ext/socket/tcpsocket.c index 29a3eda45f..7ce536e0af 100644 --- a/ext/socket/tcpsocket.c +++ b/ext/socket/tcpsocket.c @@ -12,23 +12,75 @@ /* * call-seq: - * TCPSocket.new(remote_host, remote_port, local_host=nil, local_port=nil) + * TCPSocket.new(remote_host, remote_port, local_host=nil, local_port=nil, resolv_timeout: nil, connect_timeout: nil, open_timeout: nil, fast_fallback: true) * * Opens a TCP connection to +remote_host+ on +remote_port+. If +local_host+ * and +local_port+ are specified, then those parameters are used on the local * end to establish the connection. + * + * Starting from Ruby 3.4, this method operates according to the + * Happy Eyeballs Version 2 ({RFC 8305}[https://datatracker.ietf.org/doc/html/rfc8305]) + * algorithm by default, except on Windows. + * + * For details on Happy Eyeballs Version 2, + * see {Socket.tcp_fast_fallback=}[rdoc-ref:Socket.tcp_fast_fallback=]. + * + * To make it behave the same as in Ruby 3.3 and earlier, + * explicitly specify the option fast_fallback:false. + * Or, setting Socket.tcp_fast_fallback=false will disable + * Happy Eyeballs Version 2 not only for this method but for all Socket globally. + * + * When using TCPSocket.new on Windows, Happy Eyeballs Version 2 is not provided, + * and it behaves the same as in Ruby 3.3 and earlier. + * + * [:resolv_timeout] Specifies the timeout in seconds from when the hostname resolution starts. + * [:connect_timeout] This method sequentially attempts connecting to all candidate destination addresses.<br>The +connect_timeout+ specifies the timeout in seconds from the start of the connection attempt to the last candidate.<br>By default, all connection attempts continue until the timeout occurs.<br>When +fast_fallback:false+ is explicitly specified,<br>a timeout is set for each connection attempt and any connection attempt that exceeds its timeout will be canceled. + * [:open_timeout] Specifies the timeout in seconds from the start of the method execution.<br>If this timeout is reached while there are still addresses that have not yet been attempted for connection, no further attempts will be made.<br>If this option is specified together with other timeout options, an +ArgumentError+ will be raised. + * [:fast_fallback] Enables the Happy Eyeballs Version 2 algorithm (enabled by default). */ static VALUE tcp_init(int argc, VALUE *argv, VALUE sock) { VALUE remote_host, remote_serv; VALUE local_host, local_serv; + VALUE opt; + static ID keyword_ids[5]; + VALUE kwargs[5]; + VALUE resolv_timeout = Qnil; + VALUE connect_timeout = Qnil; + VALUE open_timeout = Qnil; + VALUE fast_fallback = Qnil; + VALUE test_mode_settings = Qnil; + + if (!keyword_ids[0]) { + CONST_ID(keyword_ids[0], "resolv_timeout"); + CONST_ID(keyword_ids[1], "connect_timeout"); + CONST_ID(keyword_ids[2], "open_timeout"); + CONST_ID(keyword_ids[3], "fast_fallback"); + CONST_ID(keyword_ids[4], "test_mode_settings"); + } + + rb_scan_args(argc, argv, "22:", &remote_host, &remote_serv, + &local_host, &local_serv, &opt); + + if (!NIL_P(opt)) { + rb_get_kwargs(opt, keyword_ids, 0, 5, kwargs); + if (kwargs[0] != Qundef) { resolv_timeout = kwargs[0]; } + if (kwargs[1] != Qundef) { connect_timeout = kwargs[1]; } + if (kwargs[2] != Qundef) { open_timeout = kwargs[2]; } + if (kwargs[3] != Qundef) { fast_fallback = kwargs[3]; } + if (kwargs[4] != Qundef) { test_mode_settings = kwargs[4]; } + } - rb_scan_args(argc, argv, "22", &remote_host, &remote_serv, - &local_host, &local_serv); + if (fast_fallback == Qnil) { + fast_fallback = rb_ivar_get(rb_cSocket, tcp_fast_fallback); + if (fast_fallback == Qnil) fast_fallback = Qtrue; + } return rsock_init_inetsock(sock, remote_host, remote_serv, - local_host, local_serv, INET_CLIENT); + local_host, local_serv, INET_CLIENT, + resolv_timeout, connect_timeout, open_timeout, + fast_fallback, test_mode_settings); } static VALUE @@ -59,8 +111,9 @@ tcp_sockaddr(struct sockaddr *addr, socklen_t len) static VALUE tcp_s_gethostbyname(VALUE obj, VALUE host) { + rb_warn("TCPSocket.gethostbyname is deprecated; use Addrinfo.getaddrinfo instead."); struct rb_addrinfo *res = - rsock_addrinfo(host, Qnil, AF_UNSPEC, SOCK_STREAM, AI_CANONNAME); + rsock_addrinfo(host, Qnil, AF_UNSPEC, SOCK_STREAM, AI_CANONNAME, Qnil); return rsock_make_hostent(host, res, tcp_sockaddr); } diff --git a/ext/socket/udpsocket.c b/ext/socket/udpsocket.c index c2e273c2a3..b2bc925538 100644 --- a/ext/socket/udpsocket.c +++ b/ext/socket/udpsocket.c @@ -33,11 +33,11 @@ udp_init(int argc, VALUE *argv, VALUE sock) int fd; if (rb_scan_args(argc, argv, "01", &arg) == 1) { - family = rsock_family_arg(arg); + family = rsock_family_arg(arg); } fd = rsock_socket(family, SOCK_DGRAM, 0); if (fd < 0) { - rb_sys_fail("socket(2) - udp"); + rb_sys_fail("socket(2) - udp"); } return rsock_init_sock(sock, fd); @@ -45,23 +45,20 @@ udp_init(int argc, VALUE *argv, VALUE sock) struct udp_arg { + VALUE io; struct rb_addrinfo *res; - rb_io_t *fptr; }; static VALUE -udp_connect_internal(struct udp_arg *arg) +udp_connect_internal(VALUE v) { - rb_io_t *fptr; - int fd; + struct udp_arg *arg = (void *)v; struct addrinfo *res; - rb_io_check_closed(fptr = arg->fptr); - fd = fptr->fd; for (res = arg->res->ai; res; res = res->ai_next) { - if (rsock_connect(fd, res->ai_addr, res->ai_addrlen, 0) >= 0) { - return Qtrue; - } + if (rsock_connect(arg->io, res->ai_addr, res->ai_addrlen, 0, RUBY_IO_TIMEOUT_DEFAULT) >= 0) { + return Qtrue; + } } return Qfalse; } @@ -83,33 +80,34 @@ udp_connect_internal(struct udp_arg *arg) * */ static VALUE -udp_connect(VALUE sock, VALUE host, VALUE port) +udp_connect(VALUE self, VALUE host, VALUE port) { - struct udp_arg arg; - VALUE ret; + struct udp_arg arg = {.io = self}; + + arg.res = rsock_addrinfo(host, port, rsock_fd_family(rb_io_descriptor(self)), SOCK_DGRAM, 0, Qnil); + + int result = (int)rb_ensure(udp_connect_internal, (VALUE)&arg, rsock_freeaddrinfo, (VALUE)arg.res); + if (!result) { + rsock_sys_fail_host_port("connect(2)", host, port); + } - GetOpenFile(sock, arg.fptr); - arg.res = rsock_addrinfo(host, port, rsock_fd_family(arg.fptr->fd), SOCK_DGRAM, 0); - ret = rb_ensure(udp_connect_internal, (VALUE)&arg, - rsock_freeaddrinfo, (VALUE)arg.res); - if (!ret) rsock_sys_fail_host_port("connect(2)", host, port); return INT2FIX(0); } static VALUE -udp_bind_internal(struct udp_arg *arg) +udp_bind_internal(VALUE v) { - rb_io_t *fptr; - int fd; + struct udp_arg *arg = (void *)v; struct addrinfo *res; - rb_io_check_closed(fptr = arg->fptr); - fd = fptr->fd; + rb_io_t *fptr; + RB_IO_POINTER(arg->io, fptr); + for (res = arg->res->ai; res; res = res->ai_next) { - if (bind(fd, res->ai_addr, res->ai_addrlen) < 0) { - continue; - } - return Qtrue; + if (bind(fptr->fd, res->ai_addr, res->ai_addrlen) < 0) { + continue; + } + return Qtrue; } return Qfalse; } @@ -127,46 +125,51 @@ udp_bind_internal(struct udp_arg *arg) * */ static VALUE -udp_bind(VALUE sock, VALUE host, VALUE port) +udp_bind(VALUE self, VALUE host, VALUE port) { - struct udp_arg arg; - VALUE ret; + struct udp_arg arg = {.io = self}; + + arg.res = rsock_addrinfo(host, port, rsock_fd_family(rb_io_descriptor(self)), SOCK_DGRAM, 0, Qnil); + + VALUE result = rb_ensure(udp_bind_internal, (VALUE)&arg, rsock_freeaddrinfo, (VALUE)arg.res); + if (!result) { + rsock_sys_fail_host_port("bind(2)", host, port); + } - GetOpenFile(sock, arg.fptr); - arg.res = rsock_addrinfo(host, port, rsock_fd_family(arg.fptr->fd), SOCK_DGRAM, 0); - ret = rb_ensure(udp_bind_internal, (VALUE)&arg, - rsock_freeaddrinfo, (VALUE)arg.res); - if (!ret) rsock_sys_fail_host_port("bind(2)", host, port); return INT2FIX(0); } struct udp_send_arg { - struct rb_addrinfo *res; rb_io_t *fptr; + struct rb_addrinfo *res; struct rsock_send_arg sarg; }; static VALUE -udp_send_internal(struct udp_send_arg *arg) +udp_send_internal(VALUE v) { + struct udp_send_arg *arg = (void *)v; rb_io_t *fptr; - int n; struct addrinfo *res; rb_io_check_closed(fptr = arg->fptr); for (res = arg->res->ai; res; res = res->ai_next) { retry: - arg->sarg.fd = fptr->fd; - arg->sarg.to = res->ai_addr; - arg->sarg.tolen = res->ai_addrlen; - rsock_maybe_fd_writable(arg->sarg.fd); - n = (int)BLOCKING_REGION_FD(rsock_sendto_blocking, &arg->sarg); - if (n >= 0) { - return INT2FIX(n); - } - if (rb_io_wait_writable(fptr->fd)) { - goto retry; - } + arg->sarg.fd = fptr->fd; + arg->sarg.to = res->ai_addr; + arg->sarg.tolen = res->ai_addrlen; + +#ifdef RSOCK_WAIT_BEFORE_BLOCKING + rb_io_wait(fptr->self, RB_INT2NUM(RUBY_IO_WRITABLE), Qnil); +#endif + + ssize_t n = (ssize_t)rb_io_blocking_region(fptr, rsock_sendto_blocking, &arg->sarg); + + if (n >= 0) return RB_SSIZE2NUM(n); + + if (rb_io_maybe_wait_writable(errno, fptr->self, RUBY_IO_TIMEOUT_DEFAULT)) { + goto retry; + } } return Qfalse; } @@ -201,7 +204,7 @@ udp_send(int argc, VALUE *argv, VALUE sock) VALUE ret; if (argc == 2 || argc == 3) { - return rsock_bsock_send(argc, argv, sock); + return rsock_bsock_send(argc, argv, sock); } rb_scan_args(argc, argv, "4", &arg.sarg.mesg, &flags, &host, &port); @@ -209,9 +212,9 @@ udp_send(int argc, VALUE *argv, VALUE sock) GetOpenFile(sock, arg.fptr); arg.sarg.fd = arg.fptr->fd; arg.sarg.flags = NUM2INT(flags); - arg.res = rsock_addrinfo(host, port, rsock_fd_family(arg.fptr->fd), SOCK_DGRAM, 0); + arg.res = rsock_addrinfo(host, port, rsock_fd_family(arg.fptr->fd), SOCK_DGRAM, 0, Qnil); ret = rb_ensure(udp_send_internal, (VALUE)&arg, - rsock_freeaddrinfo, (VALUE)arg.res); + rsock_freeaddrinfo, (VALUE)arg.res); if (!ret) rsock_sys_fail_host_port("sendto(2)", host, port); return ret; } @@ -240,5 +243,5 @@ rsock_init_udpsocket(void) /* for ext/socket/lib/socket.rb use only: */ rb_define_private_method(rb_cUDPSocket, - "__recvfrom_nonblock", udp_recvfrom_nonblock, 4); + "__recvfrom_nonblock", udp_recvfrom_nonblock, 4); } diff --git a/ext/socket/unixserver.c b/ext/socket/unixserver.c index b1f2a38547..0ea5ac083c 100644 --- a/ext/socket/unixserver.c +++ b/ext/socket/unixserver.c @@ -10,7 +10,7 @@ #include "rubysocket.h" -#ifdef HAVE_SYS_UN_H +#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN /* * call-seq: * UNIXServer.new(path) => unixserver @@ -47,16 +47,12 @@ unix_svr_init(VALUE sock, VALUE path) * */ static VALUE -unix_accept(VALUE sock) +unix_accept(VALUE server) { - rb_io_t *fptr; - struct sockaddr_un from; - socklen_t fromlen; + struct sockaddr_un buffer; + socklen_t length = sizeof(buffer); - GetOpenFile(sock, fptr); - fromlen = (socklen_t)sizeof(struct sockaddr_un); - return rsock_s_accept(rb_cUNIXSocket, fptr->fd, - (struct sockaddr*)&from, &fromlen); + return rsock_s_accept(rb_cUNIXSocket, server, (struct sockaddr*)&buffer, &length); } /* :nodoc: */ @@ -70,7 +66,7 @@ unix_accept_nonblock(VALUE sock, VALUE ex) GetOpenFile(sock, fptr); fromlen = (socklen_t)sizeof(from); return rsock_s_accept_nonblock(rb_cUNIXSocket, ex, fptr, - (struct sockaddr *)&from, &fromlen); + (struct sockaddr *)&from, &fromlen); } /* @@ -92,15 +88,12 @@ unix_accept_nonblock(VALUE sock, VALUE ex) * */ static VALUE -unix_sysaccept(VALUE sock) +unix_sysaccept(VALUE server) { - rb_io_t *fptr; - struct sockaddr_un from; - socklen_t fromlen; + struct sockaddr_un buffer; + socklen_t length = sizeof(buffer); - GetOpenFile(sock, fptr); - fromlen = (socklen_t)sizeof(struct sockaddr_un); - return rsock_s_accept(0, fptr->fd, (struct sockaddr*)&from, &fromlen); + return rsock_s_accept(0, server, (struct sockaddr*)&buffer, &length); } #endif @@ -108,7 +101,7 @@ unix_sysaccept(VALUE sock) void rsock_init_unixserver(void) { -#ifdef HAVE_SYS_UN_H +#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN /* * Document-class: UNIXServer < UNIXSocket * @@ -120,7 +113,7 @@ rsock_init_unixserver(void) rb_define_method(rb_cUNIXServer, "accept", unix_accept, 0); rb_define_private_method(rb_cUNIXServer, - "__accept_nonblock", unix_accept_nonblock, 1); + "__accept_nonblock", unix_accept_nonblock, 1); rb_define_method(rb_cUNIXServer, "sysaccept", unix_sysaccept, 0); rb_define_method(rb_cUNIXServer, "listen", rsock_sock_listen, 1); /* in socket.c */ diff --git a/ext/socket/unixsocket.c b/ext/socket/unixsocket.c index 8bdfc84575..2ec9376074 100644 --- a/ext/socket/unixsocket.c +++ b/ext/socket/unixsocket.c @@ -10,19 +10,18 @@ #include "rubysocket.h" -#ifdef HAVE_SYS_UN_H +#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN struct unixsock_arg { struct sockaddr_un *sockaddr; socklen_t sockaddrlen; - int fd; + VALUE io; }; static VALUE unixsock_connect_internal(VALUE a) { struct unixsock_arg *arg = (struct unixsock_arg *)a; - return (VALUE)rsock_connect(arg->fd, (struct sockaddr*)arg->sockaddr, - arg->sockaddrlen, 0); + return (VALUE)rsock_connect(arg->io, (struct sockaddr*)arg->sockaddr, arg->sockaddrlen, 0, RUBY_IO_TIMEOUT_DEFAULT); } static VALUE @@ -39,16 +38,20 @@ unixsock_path_value(VALUE path) #endif if (isstr) { if (RSTRING_LEN(name) == 0 || RSTRING_PTR(name)[0] == '\0') { - rb_check_safe_obj(name); return name; /* ignore encoding */ } } #endif - return rb_get_path(path); + path = rb_get_path(path); +#ifdef _WIN32 + /* UNIXSocket requires UTF-8 per spec. */ + path = rb_str_export_to_enc(path, rb_utf8_encoding()); +#endif + return path; } VALUE -rsock_init_unixsock(VALUE sock, VALUE path, int server) +rsock_init_unixsock(VALUE self, VALUE path, int server) { struct sockaddr_un sockaddr; socklen_t sockaddrlen; @@ -67,46 +70,49 @@ rsock_init_unixsock(VALUE sock, VALUE path, int server) fd = rsock_socket(AF_UNIX, SOCK_STREAM, 0); if (fd < 0) { - rsock_sys_fail_path("socket(2)", path); + rsock_sys_fail_path("socket(2)", path); } + VALUE io = rsock_init_sock(self, fd); + RB_IO_POINTER(io, fptr); + if (server) { status = bind(fd, (struct sockaddr*)&sockaddr, sockaddrlen); } else { - int prot; - struct unixsock_arg arg; - arg.sockaddr = &sockaddr; - arg.sockaddrlen = sockaddrlen; - arg.fd = fd; - status = (int)rb_protect(unixsock_connect_internal, (VALUE)&arg, &prot); - if (prot) { - close(fd); - rb_jump_tag(prot); - } + int error_tag; + struct unixsock_arg arg; + arg.sockaddr = &sockaddr; + arg.sockaddrlen = sockaddrlen; + arg.io = io; + + status = (int)rb_protect(unixsock_connect_internal, (VALUE)&arg, &error_tag); + + if (error_tag) { + rb_io_close(io); + rb_jump_tag(error_tag); + } } if (status < 0) { - int e = errno; - close(fd); - rsock_syserr_fail_path(e, "connect(2)", path); + int e = errno; + rb_io_close(io); + rsock_syserr_fail_path(e, "connect(2)", path); } if (server) { - if (listen(fd, SOMAXCONN) < 0) { - int e = errno; - close(fd); - rsock_syserr_fail_path(e, "listen(2)", path); - } + if (listen(fd, SOMAXCONN) < 0) { + int e = errno; + rb_io_close(io); + rsock_syserr_fail_path(e, "listen(2)", path); + } } - rsock_init_sock(sock, fd); if (server) { - GetOpenFile(sock, fptr); fptr->pathv = rb_str_new_frozen(path); } - return sock; + return io; } /* @@ -122,9 +128,9 @@ rsock_init_unixsock(VALUE sock, VALUE path, int server) * */ static VALUE -unix_init(VALUE sock, VALUE path) +unix_init(VALUE self, VALUE path) { - return rsock_init_unixsock(sock, path, 0); + return rsock_init_unixsock(self, path, 0); } /* @@ -144,13 +150,13 @@ unix_path(VALUE sock) GetOpenFile(sock, fptr); if (NIL_P(fptr->pathv)) { - struct sockaddr_un addr; - socklen_t len = (socklen_t)sizeof(addr); - socklen_t len0 = len; - if (getsockname(fptr->fd, (struct sockaddr*)&addr, &len) < 0) + struct sockaddr_un addr; + socklen_t len = (socklen_t)sizeof(addr); + socklen_t len0 = len; + if (getsockname(fptr->fd, (struct sockaddr*)&addr, &len) < 0) rsock_sys_fail_path("getsockname(2)", fptr->pathv); if (len0 < len) len = len0; - fptr->pathv = rb_obj_freeze(rsock_unixpath_str(&addr, len)); + fptr->pathv = rb_obj_freeze(rsock_unixpath_str(&addr, len)); } return rb_str_dup(fptr->pathv); } @@ -241,21 +247,21 @@ unix_send_io(VALUE sock, VALUE val) #if FD_PASSING_BY_MSG_CONTROL union { - struct cmsghdr hdr; - char pad[sizeof(struct cmsghdr)+8+sizeof(int)+8]; + struct cmsghdr hdr; + char pad[sizeof(struct cmsghdr)+8+sizeof(int)+8]; } cmsg; #endif if (rb_obj_is_kind_of(val, rb_cIO)) { rb_io_t *valfptr; - GetOpenFile(val, valfptr); - fd = valfptr->fd; + GetOpenFile(val, valfptr); + fd = valfptr->fd; } else if (FIXNUM_P(val)) { fd = FIX2INT(val); } else { - rb_raise(rb_eTypeError, "neither IO nor file descriptor"); + rb_raise(rb_eTypeError, "neither IO nor file descriptor"); } GetOpenFile(sock, fptr); @@ -285,9 +291,9 @@ unix_send_io(VALUE sock, VALUE val) #endif arg.fd = fptr->fd; - while ((int)BLOCKING_REGION_FD(sendmsg_blocking, &arg) == -1) { - if (!rb_io_wait_writable(arg.fd)) - rsock_sys_fail_path("sendmsg(2)", fptr->pathv); + while ((int)rb_io_blocking_region(fptr, sendmsg_blocking, &arg) == -1) { + if (!rb_io_wait_writable(arg.fd)) + rsock_sys_fail_path("sendmsg(2)", fptr->pathv); } return Qnil; @@ -349,16 +355,16 @@ unix_recv_io(int argc, VALUE *argv, VALUE sock) int fd; #if FD_PASSING_BY_MSG_CONTROL union { - struct cmsghdr hdr; - char pad[sizeof(struct cmsghdr)+8+sizeof(int)+8]; + struct cmsghdr hdr; + char pad[sizeof(struct cmsghdr)+8+sizeof(int)+8]; } cmsg; #endif rb_scan_args(argc, argv, "02", &klass, &mode); if (argc == 0) - klass = rb_cIO; + klass = rb_cIO; if (argc <= 1) - mode = Qnil; + mode = Qnil; retry: GetOpenFile(sock, fptr); @@ -387,7 +393,7 @@ retry: #endif arg.fd = fptr->fd; - while ((int)BLOCKING_REGION_FD(recvmsg_blocking, &arg) == -1) { + while ((int)rb_io_blocking_region(fptr, recvmsg_blocking, &arg) == -1) { int e = errno; if (e == EMSGSIZE && !(gc_reason & GC_REASON_EMSGSIZE)) { /* FreeBSD gets here when we're out of FDs */ @@ -401,8 +407,8 @@ retry: rb_gc_for_fd(e); goto retry; } - if (!rb_io_wait_readable(arg.fd)) - rsock_syserr_fail_path(e, "recvmsg(2)", fptr->pathv); + if (!rb_io_wait_readable(arg.fd)) + rsock_syserr_fail_path(e, "recvmsg(2)", fptr->pathv); } #if FD_PASSING_BY_MSG_CONTROL @@ -413,41 +419,41 @@ retry: rb_gc_for_fd(EMFILE); goto retry; } - rb_raise(rb_eSocket, - "file descriptor was not passed (msg_controllen=%d smaller than sizeof(struct cmsghdr)=%d)", - (int)arg.msg.msg_controllen, (int)sizeof(struct cmsghdr)); + rb_raise(rb_eSocket, + "file descriptor was not passed (msg_controllen=%d smaller than sizeof(struct cmsghdr)=%d)", + (int)arg.msg.msg_controllen, (int)sizeof(struct cmsghdr)); } if (cmsg.hdr.cmsg_level != SOL_SOCKET) { - rb_raise(rb_eSocket, - "file descriptor was not passed (cmsg_level=%d, %d expected)", - cmsg.hdr.cmsg_level, SOL_SOCKET); + rb_raise(rb_eSocket, + "file descriptor was not passed (cmsg_level=%d, %d expected)", + cmsg.hdr.cmsg_level, SOL_SOCKET); } if (cmsg.hdr.cmsg_type != SCM_RIGHTS) { - rb_raise(rb_eSocket, - "file descriptor was not passed (cmsg_type=%d, %d expected)", - cmsg.hdr.cmsg_type, SCM_RIGHTS); + rb_raise(rb_eSocket, + "file descriptor was not passed (cmsg_type=%d, %d expected)", + cmsg.hdr.cmsg_type, SCM_RIGHTS); } if (arg.msg.msg_controllen < (socklen_t)CMSG_LEN(sizeof(int))) { - rb_raise(rb_eSocket, - "file descriptor was not passed (msg_controllen=%d smaller than CMSG_LEN(sizeof(int))=%d)", - (int)arg.msg.msg_controllen, (int)CMSG_LEN(sizeof(int))); + rb_raise(rb_eSocket, + "file descriptor was not passed (msg_controllen=%d smaller than CMSG_LEN(sizeof(int))=%d)", + (int)arg.msg.msg_controllen, (int)CMSG_LEN(sizeof(int))); } if ((socklen_t)CMSG_SPACE(sizeof(int)) < arg.msg.msg_controllen) { - rb_raise(rb_eSocket, - "file descriptor was not passed (msg_controllen=%d bigger than CMSG_SPACE(sizeof(int))=%d)", - (int)arg.msg.msg_controllen, (int)CMSG_SPACE(sizeof(int))); + rb_raise(rb_eSocket, + "file descriptor was not passed (msg_controllen=%d bigger than CMSG_SPACE(sizeof(int))=%d)", + (int)arg.msg.msg_controllen, (int)CMSG_SPACE(sizeof(int))); } if (cmsg.hdr.cmsg_len != CMSG_LEN(sizeof(int))) { - rsock_discard_cmsg_resource(&arg.msg, 0); - rb_raise(rb_eSocket, - "file descriptor was not passed (cmsg_len=%d, %d expected)", - (int)cmsg.hdr.cmsg_len, (int)CMSG_LEN(sizeof(int))); + rsock_discard_cmsg_resource(&arg.msg, 0); + rb_raise(rb_eSocket, + "file descriptor was not passed (cmsg_len=%d, %d expected)", + (int)cmsg.hdr.cmsg_len, (int)CMSG_LEN(sizeof(int))); } #else if (arg.msg.msg_accrightslen != sizeof(fd)) { - rb_raise(rb_eSocket, - "file descriptor was not passed (accrightslen=%d, %d expected)", - arg.msg.msg_accrightslen, (int)sizeof(fd)); + rb_raise(rb_eSocket, + "file descriptor was not passed (accrightslen=%d, %d expected)", + arg.msg.msg_accrightslen, (int)sizeof(fd)); } #endif @@ -456,22 +462,18 @@ retry: #endif rb_update_max_fd(fd); - - if (rsock_cmsg_cloexec_state < 0) - rsock_cmsg_cloexec_state = rsock_detect_cloexec(fd); - if (rsock_cmsg_cloexec_state == 0 || fd <= 2) - rb_maygvl_fd_fix_cloexec(fd); + rb_maygvl_fd_fix_cloexec(fd); if (klass == Qnil) - return INT2FIX(fd); + return INT2FIX(fd); else { - ID for_fd; - int ff_argc; - VALUE ff_argv[2]; - CONST_ID(for_fd, "for_fd"); - ff_argc = mode == Qnil ? 1 : 2; - ff_argv[0] = INT2FIX(fd); - ff_argv[1] = mode; + ID for_fd; + int ff_argc; + VALUE ff_argv[2]; + CONST_ID(for_fd, "for_fd"); + ff_argc = mode == Qnil ? 1 : 2; + ff_argv[0] = INT2FIX(fd); + ff_argv[1] = mode; return rb_funcallv(klass, for_fd, ff_argc, ff_argv); } } @@ -541,7 +543,7 @@ unix_peeraddr(VALUE sock) * * Creates a pair of sockets connected to each other. * - * _socktype_ should be a socket type such as: :STREAM, :DGRAM, :RAW, etc. + * _type_ should be a socket type such as: :STREAM, :DGRAM, :RAW, etc. * * _protocol_ should be a protocol defined in the domain. * 0 is default protocol for the domain. @@ -561,9 +563,9 @@ unix_s_socketpair(int argc, VALUE *argv, VALUE klass) domain = INT2FIX(PF_UNIX); rb_scan_args(argc, argv, "02", &type, &protocol); if (argc == 0) - type = INT2FIX(SOCK_STREAM); + type = INT2FIX(SOCK_STREAM); if (argc <= 1) - protocol = INT2FIX(0); + protocol = INT2FIX(0); args[0] = domain; args[1] = type; @@ -576,7 +578,7 @@ unix_s_socketpair(int argc, VALUE *argv, VALUE klass) void rsock_init_unixsocket(void) { -#ifdef HAVE_SYS_UN_H +#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN /* * Document-class: UNIXSocket < BasicSocket * |
