summaryrefslogtreecommitdiff
path: root/ext/socket
diff options
context:
space:
mode:
Diffstat (limited to 'ext/socket')
-rw-r--r--ext/socket/addrinfo.h36
-rw-r--r--ext/socket/ancdata.c297
-rw-r--r--ext/socket/basicsocket.c157
-rw-r--r--ext/socket/constants.c7
-rw-r--r--ext/socket/depend2940
-rw-r--r--ext/socket/extconf.rb58
-rw-r--r--ext/socket/getaddrinfo.c898
-rw-r--r--ext/socket/getnameinfo.c224
-rw-r--r--ext/socket/ifaddr.c13
-rw-r--r--ext/socket/init.c538
-rw-r--r--ext/socket/ipsocket.c1490
-rw-r--r--ext/socket/lib/socket.rb542
-rw-r--r--ext/socket/mkconstants.rb86
-rw-r--r--ext/socket/option.c102
-rw-r--r--ext/socket/raddrinfo.c1249
-rw-r--r--ext/socket/rubysocket.h184
-rw-r--r--ext/socket/socket.c742
-rw-r--r--ext/socket/sockssocket.c21
-rw-r--r--ext/socket/tcpserver.c26
-rw-r--r--ext/socket/tcpsocket.c63
-rw-r--r--ext/socket/udpsocket.c111
-rw-r--r--ext/socket/unixserver.c31
-rw-r--r--ext/socket/unixsocket.c182
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, &notification, 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
*