From: GOTOU Yuuzou Date: 2003-12-09T22:36:53+09:00 Subject: [ruby-dev:22195] IO::for_io and TCPServer#bind 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);