summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog8
-rw-r--r--ext/socket/mkconstants.rb6
-rw-r--r--ext/socket/socket.c30
-rw-r--r--test/socket/test_socket.rb4
4 files changed, 46 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index 8dd5b9f786..ff1ff1cdb5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+Fri Jan 2 01:15:11 2009 Tanaka Akira <akr@fsij.org>
+
+ * ext/socket/socket.c (level_arg): defined.
+ (bsock_setsockopt): use level_arg.
+ (bsock_getsockopt): ditto.
+
+ * ext/socket/mkconstants.rb: generate level_to_int.
+
Fri Jan 2 00:58:40 2009 Tanaka Akira <akr@fsij.org>
* ext/socket/socket.c (family_arg): accept symbols as well.
diff --git a/ext/socket/mkconstants.rb b/ext/socket/mkconstants.rb
index d3eac7f3f1..a4f7569f88 100644
--- a/ext/socket/mkconstants.rb
+++ b/ext/socket/mkconstants.rb
@@ -151,6 +151,12 @@ socktype_to_int(char *str, int len, int *valp)
<%= gen_name_to_int("str", "len", "valp", /\ASOCK_/) %>
}
+static int
+level_to_int(char *str, int len, int *valp)
+{
+<%= gen_name_to_int("str", "len", "valp", /\A(SOL_SOCKET\z|IPPROTO_)/) %>
+}
+
static char *
family_to_str(int val)
{
diff --git a/ext/socket/socket.c b/ext/socket/socket.c
index 7b7aa416ac..0c8b0a6296 100644
--- a/ext/socket/socket.c
+++ b/ext/socket/socket.c
@@ -294,6 +294,32 @@ socktype_arg(VALUE type)
return ret;
}
+static int
+level_arg(VALUE level)
+{
+ /* convert SOL_SOCKET, IPPROTO_TCP, etc. */
+ VALUE tmp;
+ char *ptr;
+ int ret;
+
+ if (SYMBOL_P(level)) {
+ level = rb_sym_to_s(level);
+ goto str;
+ }
+ else if (!NIL_P(tmp = rb_check_string_type(level))) {
+ level = tmp;
+ str:
+ rb_check_safe_obj(level);
+ ptr = RSTRING_PTR(level);
+ if (level_to_int(ptr, RSTRING_LEN(level), &ret) == -1)
+ rb_raise(rb_eSocket, "unknown protocol level %s", ptr);
+ }
+ else {
+ ret = NUM2INT(level);
+ }
+
+ return ret;
+}
static VALUE
init_sock(VALUE sock, int fd)
@@ -440,7 +466,7 @@ bsock_setsockopt(VALUE sock, VALUE lev, VALUE optname, VALUE val)
int vlen;
rb_secure(2);
- level = NUM2INT(lev);
+ level = level_arg(lev);
option = NUM2INT(optname);
switch (TYPE(val)) {
@@ -520,7 +546,7 @@ bsock_getsockopt(VALUE sock, VALUE lev, VALUE optname)
char *buf;
rb_io_t *fptr;
- level = NUM2INT(lev);
+ level = level_arg(lev);
option = NUM2INT(optname);
len = 256;
buf = ALLOCA_N(char,len);
diff --git a/test/socket/test_socket.rb b/test/socket/test_socket.rb
index 130b1f4390..af241c0236 100644
--- a/test/socket/test_socket.rb
+++ b/test/socket/test_socket.rb
@@ -16,6 +16,10 @@ class TestBasicSocket < Test::Unit::TestCase
inet_stream do |s|
n = s.getsockopt(Socket::SOL_SOCKET, Socket::SO_TYPE)
assert_equal([Socket::SOCK_STREAM].pack("i"), n)
+ n = s.getsockopt("SOL_SOCKET", Socket::SO_TYPE)
+ assert_equal([Socket::SOCK_STREAM].pack("i"), n)
+ n = s.getsockopt(:SOL_SOCKET, Socket::SO_TYPE)
+ assert_equal([Socket::SOCK_STREAM].pack("i"), n)
n = s.getsockopt(Socket::SOL_SOCKET, Socket::SO_ERROR)
assert_equal([0].pack("i"), n)
val = Object.new