diff --git a/ChangeLog b/ChangeLog index b29db89671..bcd85c7392 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,29 @@ +Mon Feb 9 22:52:13 2009 Tanaka Akira + + * ext/socket/rubysocket.h (level_arg): add family argument. + (optname_arg): ditto. + (cmsg_type_arg): ditto. + (rb_sock_getfamily): declared. + + * ext/socket/constants.c (level_arg): add family argument. + (optname_arg): ditto. + (cmsg_type_arg): ditto. + + * ext/socket/init.c (rb_sock_getfamily): defined. + + * ext/socket/option.c (sockopt_initialize): give family for level_arg + and optname_arg. + (sockopt_s_int): ditto. + + * ext/socket/basicsocket.c (bsock_setsockopt): ditto. + (bsock_getsockopt): ditto. + + * ext/socket/ancdata.c (ancillary_initialize): ditto. + (ancillary_s_int): ditto. + (ancillary_cmsg_is_p): ditto. + (bsock_sendmsg_internal): ditto. + (bsock_recvmsg_internal): use rb_sock_getfamily. + Mon Feb 9 21:48:59 2009 Tanaka Akira * ext/socket/ancdata.c (ancillary_inspect): show address family. diff --git a/ext/socket/ancdata.c b/ext/socket/ancdata.c index 980ab84441..06ec546646 100644 --- a/ext/socket/ancdata.c +++ b/ext/socket/ancdata.c @@ -71,8 +71,8 @@ static VALUE ancillary_initialize(VALUE self, VALUE vfamily, VALUE vlevel, VALUE vtype, VALUE data) { int family = family_arg(vfamily); - int level = level_arg(vlevel); - int type = cmsg_type_arg(level, vtype); + int level = level_arg(family, vlevel); + int type = cmsg_type_arg(family, level, vtype); StringValue(data); rb_ivar_set(self, rb_intern("family"), INT2NUM(family)); rb_ivar_set(self, rb_intern("level"), INT2NUM(level)); @@ -190,8 +190,8 @@ static VALUE ancillary_s_int(VALUE klass, VALUE vfamily, VALUE vlevel, VALUE vtype, VALUE integer) { int family = family_arg(vfamily); - int level = level_arg(vlevel); - int type = cmsg_type_arg(level, vtype); + int level = level_arg(family, vlevel); + int type = cmsg_type_arg(family, level, vtype); int i = NUM2INT(integer); return ancdata_new(family, level, type, rb_str_new((char*)&i, sizeof(i))); } @@ -686,8 +686,9 @@ ancillary_inspect(VALUE self) static VALUE ancillary_cmsg_is_p(VALUE self, VALUE vlevel, VALUE vtype) { - int level = level_arg(vlevel); - int type = cmsg_type_arg(level, vtype); + int family = ancillary_family(self); + int level = level_arg(family, vlevel); + int type = cmsg_type_arg(family, level, vtype); if (ancillary_level(self) == level && ancillary_type(self) == type) @@ -736,8 +737,11 @@ bsock_sendmsg_internal(int argc, VALUE *argv, VALUE sock, int nonblock) #endif int flags; ssize_t ss; + int family; rb_secure(4); + GetOpenFile(sock, fptr); + family = rb_sock_getfamily(fptr->fd); data = vflags = dest_sockaddr = Qnil; controls_ptr = NULL; @@ -779,8 +783,8 @@ bsock_sendmsg_internal(int argc, VALUE *argv, VALUE sock, int nonblock) vtype = rb_funcall(elt, rb_intern("type"), 0); cdata = rb_funcall(elt, rb_intern("data"), 0); } - level = level_arg(vlevel); - type = cmsg_type_arg(level, vtype); + level = level_arg(family, vlevel); + type = cmsg_type_arg(family, level, vtype); StringValue(cdata); oldlen = RSTRING_LEN(controls_str); cspace = CMSG_SPACE(RSTRING_LEN(cdata)); @@ -810,7 +814,7 @@ bsock_sendmsg_internal(int argc, VALUE *argv, VALUE sock, int nonblock) if (!NIL_P(dest_sockaddr)) SockAddrStringValue(dest_sockaddr); - GetOpenFile(sock, fptr); + rb_io_check_closed(fptr); retry: memset(&mh, 0, sizeof(mh)); @@ -1093,15 +1097,13 @@ bsock_recvmsg_internal(int argc, VALUE *argv, VALUE sock, int nonblock) for (cmh = CMSG_FIRSTHDR(&mh); cmh != NULL; cmh = CMSG_NXTHDR(&mh, cmh)) { VALUE ctl; size_t clen; - struct sockaddr_storage ss; - socklen_t sslen = sizeof(ss); + int family; if (cmh->cmsg_len == 0) { rb_raise(rb_eIOError, "invalid control message (cmsg_len == 0)"); } - ss.ss_family = AF_UNSPEC; - getsockname(fptr->fd, (struct sockaddr*)&ss, &sslen); + family = rb_sock_getfamily(fptr->fd); clen = (char*)cmh + cmh->cmsg_len - (char*)CMSG_DATA(cmh); - ctl = ancdata_new(ss.ss_family, cmh->cmsg_level, cmh->cmsg_type, rb_tainted_str_new((char*)CMSG_DATA(cmh), clen)); + ctl = ancdata_new(family, cmh->cmsg_level, cmh->cmsg_type, rb_tainted_str_new((char*)CMSG_DATA(cmh), clen)); rb_ary_push(ret, ctl); } } diff --git a/ext/socket/basicsocket.c b/ext/socket/basicsocket.c index f6fb9f264a..7690fb60ef 100644 --- a/ext/socket/basicsocket.c +++ b/ext/socket/basicsocket.c @@ -195,7 +195,7 @@ static VALUE bsock_setsockopt(int argc, VALUE *argv, VALUE sock) { VALUE lev, optname, val; - int level, option; + int family, level, option; rb_io_t *fptr; int i; char *v; @@ -211,8 +211,10 @@ bsock_setsockopt(int argc, VALUE *argv, VALUE sock) } rb_secure(2); - level = level_arg(lev); - option = optname_arg(level, optname); + GetOpenFile(sock, fptr); + family = rb_sock_getfamily(fptr->fd); + level = level_arg(family, lev); + option = optname_arg(family, level, optname); switch (TYPE(val)) { case T_FIXNUM: @@ -235,7 +237,7 @@ bsock_setsockopt(int argc, VALUE *argv, VALUE sock) #define rb_sys_fail_path(path) rb_sys_fail(NIL_P(path) ? 0 : RSTRING_PTR(path)) - GetOpenFile(sock, fptr); + rb_io_check_closed(fptr); if (setsockopt(fptr->fd, level, option, v, vlen) < 0) rb_sys_fail_path(fptr->pathv); @@ -290,24 +292,21 @@ bsock_getsockopt(VALUE sock, VALUE lev, VALUE optname) socklen_t len; char *buf; rb_io_t *fptr; - struct sockaddr_storage ss; - socklen_t sslen = sizeof(ss); + int family; - level = level_arg(lev); - option = optname_arg(level, optname); + GetOpenFile(sock, fptr); + family = rb_sock_getfamily(fptr->fd); + level = level_arg(family, lev); + option = optname_arg(family, level, optname); len = 256; buf = ALLOCA_N(char,len); - GetOpenFile(sock, fptr); - - ss.ss_family = AF_UNSPEC; - if (getsockname(fptr->fd, (struct sockaddr*)&ss, &sslen) < 0) - rb_sys_fail("getsockname(2)"); + rb_io_check_closed(fptr); if (getsockopt(fptr->fd, level, option, buf, &len) < 0) rb_sys_fail_path(fptr->pathv); - return sockopt_new(ss.ss_family, level, option, rb_str_new(buf, len)); + return sockopt_new(family, level, option, rb_str_new(buf, len)); #else rb_notimplement(); #endif diff --git a/ext/socket/constants.c b/ext/socket/constants.c index bb817e70d9..3b7906f890 100644 --- a/ext/socket/constants.c +++ b/ext/socket/constants.c @@ -58,14 +58,14 @@ socktype_arg(VALUE type) } int -level_arg(VALUE level) +level_arg(int family, VALUE level) { /* convert SOL_SOCKET, IPPROTO_TCP, etc. */ return constant_arg(level, level_to_int, "unknown protocol level"); } int -optname_arg(int level, VALUE optname) +optname_arg(int family, int level, VALUE optname) { switch (level) { case SOL_SOCKET: @@ -93,23 +93,23 @@ shutdown_how_arg(VALUE how) } int -cmsg_type_arg(int level, VALUE optname) +cmsg_type_arg(int family, int level, VALUE type) { switch (level) { case SOL_SOCKET: - return constant_arg(optname, scm_optname_to_int, "unknown UNIX control message"); + return constant_arg(type, scm_optname_to_int, "unknown UNIX control message"); case IPPROTO_IP: - return constant_arg(optname, ip_optname_to_int, "unknown IP control message"); + return constant_arg(type, ip_optname_to_int, "unknown IP control message"); #ifdef INET6 case IPPROTO_IPV6: - return constant_arg(optname, ipv6_optname_to_int, "unknown IPv6 control message"); + return constant_arg(type, ipv6_optname_to_int, "unknown IPv6 control message"); #endif case IPPROTO_TCP: - return constant_arg(optname, tcp_optname_to_int, "unknown TCP control message"); + return constant_arg(type, tcp_optname_to_int, "unknown TCP control message"); case IPPROTO_UDP: - return constant_arg(optname, udp_optname_to_int, "unknown UDP control message"); + return constant_arg(type, udp_optname_to_int, "unknown UDP control message"); default: - return NUM2INT(optname); + return NUM2INT(type); } } diff --git a/ext/socket/init.c b/ext/socket/init.c index 484d27e279..f0e34d1fa8 100644 --- a/ext/socket/init.c +++ b/ext/socket/init.c @@ -505,6 +505,18 @@ s_accept(VALUE klass, int fd, struct sockaddr *sockaddr, socklen_t *len) return init_sock(rb_obj_alloc(klass), fd2); } +int rb_sock_getfamily(int sockfd) +{ + struct sockaddr_storage ss; + socklen_t sslen = sizeof(ss); + + ss.ss_family = AF_UNSPEC; + if (getsockname(sockfd, (struct sockaddr*)&ss, &sslen) < 0) + rb_sys_fail("getsockname(2)"); + + return ss.ss_family; +} + /* * SocketError is the error class for socket. */ diff --git a/ext/socket/option.c b/ext/socket/option.c index 900b99a591..e09cb79ae5 100644 --- a/ext/socket/option.c +++ b/ext/socket/option.c @@ -38,8 +38,8 @@ static VALUE sockopt_initialize(VALUE self, VALUE vfamily, VALUE vlevel, VALUE voptname, VALUE data) { int family = family_arg(vfamily); - int level = level_arg(vlevel); - int optname = optname_arg(level, voptname); + int level = level_arg(family, vlevel); + int optname = optname_arg(family, level, voptname); StringValue(data); rb_ivar_set(self, rb_intern("family"), INT2NUM(family)); rb_ivar_set(self, rb_intern("level"), INT2NUM(level)); @@ -133,8 +133,8 @@ static VALUE sockopt_s_int(VALUE klass, VALUE vfamily, VALUE vlevel, VALUE voptname, VALUE vint) { int family = family_arg(vfamily); - int level = level_arg(vlevel); - int optname = optname_arg(level, voptname); + int level = level_arg(family, vlevel); + int optname = optname_arg(family, level, voptname); int i = NUM2INT(vint); return sockopt_new(family, level, optname, rb_str_new((char*)&i, sizeof(i))); } diff --git a/ext/socket/rubysocket.h b/ext/socket/rubysocket.h index 9e3692f7f1..efd91f662e 100644 --- a/ext/socket/rubysocket.h +++ b/ext/socket/rubysocket.h @@ -194,10 +194,12 @@ NORETURN(void raise_socket_error(const char *, int)); int family_arg(VALUE domain); int socktype_arg(VALUE type); -int level_arg(VALUE level); -int optname_arg(int level, VALUE optname); +int level_arg(int family, VALUE level); +int optname_arg(int family, int level, VALUE optname); int shutdown_how_arg(VALUE how); -int cmsg_type_arg(int level, VALUE optname); +int cmsg_type_arg(int family, int level, VALUE type); + +int rb_sock_getfamily(int sockfd); int rb_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res); int rb_getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags);