test_drb が IPv4 射影アドレスが有効な環境でないと動かないこ
とに触発されて、setsockopt(IPPROTO_IPV6, IPV6_V6ONLY) を追加
して試そうと思ったのですが、TCPServer の場合はオブジェクトの
生成が終った時点で bind と listen が完了しているのでうまく行
きません。
そこで、Socket.new で作ったソケットを for_fd で TCPServer に
することを考えたのですが、もとのソケットが GC されないように
する必要があって、あまり使い勝手がよくないように思います。
そこで、IO を引数に取って内部に保存しておく IO::for_io (と
TCPServer#bind)があると次のようなことができて嬉しいのですが、
どうでしょう。
require 'socket'
include Socket::Constants
s = Socket.new(AF_INET6, SOCK_STREAM, 0)
svr = TCPServer.for_io(s)
svr.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
svr.setsockopt(IPPROTO_IPV6, IPV6_V6ONLY, 0)
svr.bind("::", 8080)
svr.listen(5)
while sock = svr.accept
p [ sock.addr, sock.peeraddr ]
sock.close
end
--
ごとうゆうぞう
Index: io.c
===================================================================
RCS file: /src/ruby/io.c,v
retrieving revision 1.240
diff -u -p -r1.240 io.c
--- io.c 9 Dec 2003 05:12:52 -0000 1.240
+++ io.c 9 Dec 2003 11:04:10 -0000
@@ -2943,6 +2943,17 @@ rb_io_s_for_fd(argc, argv, klass)
return io;
}
+static VALUE
+rb_io_s_for_io(klass, io)
+ VALUE klass;
+ VALUE io;
+{
+ VALUE fd = rb_funcall(io, rb_intern("fileno"), 0, 0);
+ VALUE ret = rb_io_s_for_fd(1, &fd, klass);
+ rb_iv_set(ret, "io", io);
+ return ret;
+}
+
static int binmode = 0;
static VALUE
@@ -4057,6 +4068,7 @@ Init_IO()
rb_define_singleton_method(rb_cIO, "open", rb_io_s_open, -1);
rb_define_singleton_method(rb_cIO, "sysopen", rb_io_s_sysopen, -1);
rb_define_singleton_method(rb_cIO, "for_fd", rb_io_s_for_fd, -1);
+ rb_define_singleton_method(rb_cIO, "for_io", rb_io_s_for_io, 1);
rb_define_singleton_method(rb_cIO, "popen", rb_io_s_popen, -1);
rb_define_singleton_method(rb_cIO, "foreach", rb_io_s_foreach, -1);
rb_define_singleton_method(rb_cIO, "readlines", rb_io_s_readlines, -1);
Index: ext/socket/socket.c
===================================================================
RCS file: /src/ruby/ext/socket/socket.c,v
retrieving revision 1.106
diff -u -p -r1.106 socket.c
--- ext/socket/socket.c 22 Nov 2003 03:59:33 -0000 1.106
+++ ext/socket/socket.c 9 Dec 2003 11:04:10 -0000
@@ -196,6 +196,18 @@ bsock_s_for_fd(klass, fd)
}
static VALUE
+bsock_s_for_io(klass, io)
+ VALUE klass, io;
+{
+ VALUE fd = rb_funcall(io, rb_intern("fileno"), 0, 0);
+ VALUE sock = bsock_s_for_fd(klass, fd);
+
+ rb_iv_set(sock, "io", io);
+
+ return sock;
+}
+
+static VALUE
bsock_shutdown(argc, argv, sock)
int argc;
VALUE *argv;
@@ -1347,15 +1359,16 @@ udp_connect(sock, host, port)
}
static VALUE
-udp_bind(sock, host, port)
+ip_bind(sock, host, port, sock_type)
VALUE sock, host, port;
+ int sock_type;
{
OpenFile *fptr;
struct addrinfo *res0, *res;
rb_secure(3);
GetOpenFile(sock, fptr);
- res0 = sock_addrinfo(host, port, SOCK_DGRAM, 0);
+ res0 = sock_addrinfo(host, port, sock_type, 0);
for (res = res0; res; res = res->ai_next) {
if (bind(fileno(fptr->f), res->ai_addr, res->ai_addrlen) < 0) {
continue;
@@ -1369,6 +1382,20 @@ udp_bind(sock, host, port)
}
static VALUE
+udp_bind(sock, host, port)
+ VALUE sock, host, port;
+{
+ return ip_bind(sock, host, port, SOCK_DGRAM);
+}
+
+static VALUE
+tcp_bind(sock, host, port)
+ VALUE sock, host, port;
+{
+ return ip_bind(sock, host, port, SOCK_STREAM);
+}
+
+static VALUE
udp_send(argc, argv, sock)
int argc;
VALUE *argv;
@@ -2375,6 +2402,7 @@ Init_socket()
rb_define_singleton_method(rb_cBasicSocket, "do_not_reverse_lookup=",
bsock_do_not_rev_lookup_set, 1);
rb_define_singleton_method(rb_cBasicSocket, "for_fd", bsock_s_for_fd, 1);
+ rb_define_singleton_method(rb_cBasicSocket, "for_io", bsock_s_for_io, 1);
rb_define_method(rb_cBasicSocket, "close_read", bsock_close_read, 0);
rb_define_method(rb_cBasicSocket, "close_write", bsock_close_write, 0);
@@ -2412,6 +2440,7 @@ Init_socket()
rb_define_method(rb_cTCPServer, "accept", tcp_accept, 0);
rb_define_method(rb_cTCPServer, "sysaccept", tcp_sysaccept, 0);
rb_define_method(rb_cTCPServer, "initialize", tcp_svr_init, -1);
+ rb_define_method(rb_cTCPServer, "bind", tcp_bind, 2);
rb_define_method(rb_cTCPServer, "listen", sock_listen, 1);
rb_cUDPSocket = rb_define_class("UDPSocket", rb_cIPSocket);
@@ -2608,6 +2637,11 @@ Init_socket()
#ifdef IPPROTO_MAX
sock_define_const("IPPROTO_MAX", IPPROTO_MAX);
#endif
+#ifdef IPPROTO_IPV6
+ sock_define_const("IPPROTO_IPV6", IPPROTO_IPV6);
+#else
+ sock_define_const("IPPROTO_IPV6", 41);
+#endif
/* Some port configuration */
#ifdef IPPORT_RESERVED
@@ -2704,6 +2738,9 @@ Init_socket()
#endif
#ifdef IP_MAX_MEMBERSHIPS
sock_define_const("IP_MAX_MEMBERSHIPS", IP_MAX_MEMBERSHIPS);
+#endif
+#ifdef IPV6_V6ONLY
+ sock_define_const("IPV6_V6ONLY", IPV6_V6ONLY);
#endif
#ifdef SO_DEBUG
sock_define_const("SO_DEBUG", SO_DEBUG);