summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog26
-rw-r--r--ext/socket/ancdata.c30
-rw-r--r--ext/socket/basicsocket.c27
-rw-r--r--ext/socket/constants.c18
-rw-r--r--ext/socket/init.c12
-rw-r--r--ext/socket/option.c8
-rw-r--r--ext/socket/rubysocket.h8
7 files changed, 85 insertions, 44 deletions
diff --git a/ChangeLog b/ChangeLog
index b29db89..bcd85c7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,29 @@
+Mon Feb 9 22:52:13 2009 Tanaka Akira <akr@fsij.org>
+
+ * 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 <akr@fsij.org>
* ext/socket/ancdata.c (ancillary_inspect): show address family.
diff --git a/ext/socket/ancdata.c b/ext/socket/ancdata.c
index 980ab84..06ec546 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 f6fb9f2..7690fb6 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 bb817e7..3b7906f 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 484d27e..f0e34d1 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 900b99a..e09cb79 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 9e3692f..efd91f6 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);