* ext/socket/rubysocket.h (cmsg_type_arg): declared.

(Init_ancdata): ditto.

* ext/socket/init.c (Init_socket_init): call Init_ancdata.

* ext/socket/constants.c (cmsg_type_arg): defined.

* ext/socket/depend: add dependency for ancdata.o.

* ext/socket/mkconstants.rb: generate scm_optname_to_int.
  more constants.

* ext/socket/extconf.rb: add ancdata.o.

* ext/socket/ancdata.c: new file.  new method
  BasicSocket#{sendmsg,sendmsg_nonblock,recvmsg,recvmsg_nonblock}



git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@21943 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
akr 2009-02-02 02:51:02 +00:00
parent c618d018d8
commit 61fc0c6cf4
10 changed files with 1259 additions and 0 deletions

View File

@ -1,3 +1,22 @@
Mon Feb 2 11:45:10 2009 Tanaka Akira <akr@fsij.org>
* ext/socket/rubysocket.h (cmsg_type_arg): declared.
(Init_ancdata): ditto.
* ext/socket/init.c (Init_socket_init): call Init_ancdata.
* ext/socket/constants.c (cmsg_type_arg): defined.
* ext/socket/depend: add dependency for ancdata.o.
* ext/socket/mkconstants.rb: generate scm_optname_to_int.
more constants.
* ext/socket/extconf.rb: add ancdata.o.
* ext/socket/ancdata.c: new file. new method
BasicSocket#{sendmsg,sendmsg_nonblock,recvmsg,recvmsg_nonblock}
Mon Feb 2 10:57:27 2009 NAKAMURA Usaku <usa@ruby-lang.org>
* win32/win32.c (open_dir_handle, rb_w32_opendir, move_to_next_entry,

View File

@ -21,6 +21,7 @@ socket/unixsocket.c
socket/unixserver.c
socket/socket.c
socket/option.c
socket/ancdata.c
socket/constants.c
socket/lib/socket.rb
stringio/stringio.c

1070
ext/socket/ancdata.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -92,6 +92,25 @@ shutdown_how_arg(VALUE how)
return constant_arg(how, shutdown_how_to_int, "unknown shutdown argument");
}
int
cmsg_type_arg(int level, VALUE optname)
{
switch (level) {
case SOL_SOCKET:
return constant_arg(optname, scm_optname_to_int, "unknown UNIX control message");
case IPPROTO_IP:
return constant_arg(optname, ip_optname_to_int, "unknown IP control message");
case IPPROTO_IPV6:
return constant_arg(optname, ipv6_optname_to_int, "unknown IPv6 control message");
case IPPROTO_TCP:
return constant_arg(optname, tcp_optname_to_int, "unknown TCP control message");
case IPPROTO_UDP:
return constant_arg(optname, udp_optname_to_int, "unknown UDP control message");
default:
return NUM2INT(optname);
}
}
static void
sock_define_const(const char *name, int value, VALUE mConst)
{

View File

@ -14,6 +14,7 @@ udpsocket.o: udpsocket.c $(SOCK_HEADERS)
unixsocket.o: unixsocket.c $(SOCK_HEADERS)
unixserver.o: unixserver.c $(SOCK_HEADERS)
option.o: option.c $(SOCK_HEADERS)
ancdata.o: ancdata.c $(SOCK_HEADERS)
raddrinfo.o: raddrinfo.c $(SOCK_HEADERS)
getnameinfo.o: getnameinfo.c $(arch_hdrdir)/ruby/config.h addrinfo.h sockport.h

View File

@ -255,6 +255,7 @@ $objs = [
"unixsocket.#{$OBJEXT}",
"unixserver.#{$OBJEXT}",
"option.#{$OBJEXT}",
"ancdata.#{$OBJEXT}",
"raddrinfo.#{$OBJEXT}"
]

View File

@ -520,6 +520,7 @@ Init_socket_init()
Init_unixsocket();
Init_unixserver();
Init_sockopt();
Init_ancdata();
Init_addrinfo();
Init_socket_constants();
}

View File

@ -249,6 +249,7 @@ def_name_to_int("ipv6_optname_to_int", /\AIPV6_/, "IPV6_", "IPPROTO_IPV6")
def_name_to_int("tcp_optname_to_int", /\ATCP_/, "TCP_")
def_name_to_int("udp_optname_to_int", /\AUDP_/, "UDP_")
def_name_to_int("shutdown_how_to_int", /\ASHUT_/, "SHUT_")
def_name_to_int("scm_optname_to_int", /\ASCM_/, "SCM_")
def_intern('intern_family', /\AAF_/)
def_intern('intern_protocol_family', /\APF_/)
@ -482,6 +483,35 @@ IP_DROP_MEMBERSHIP
IP_DEFAULT_MULTICAST_TTL
IP_DEFAULT_MULTICAST_LOOP
IP_MAX_MEMBERSHIPS
IP_ROUTER_ALERT
IP_PKTINFO
IP_PKTOPTIONS
IP_MTU_DISCOVER
IP_RECVERR
IP_RECVTOS
IP_MTU
IP_FREEBIND
IP_IPSEC_POLICY
IP_XFRM_POLICY
IP_PASSSEC
IP_PMTUDISC_DONT
IP_PMTUDISC_WANT
IP_PMTUDISC_DO
IP_UNBLOCK_SOURCE
IP_BLOCK_SOURCE
IP_ADD_SOURCE_MEMBERSHIP
IP_DROP_SOURCE_MEMBERSHIP
IP_MSFILTER
MCAST_JOIN_GROUP
MCAST_BLOCK_SOURCE
MCAST_UNBLOCK_SOURCE
MCAST_LEAVE_GROUP
MCAST_JOIN_SOURCE_GROUP
MCAST_LEAVE_SOURCE_GROUP
MCAST_MSFILTER
MCAST_EXCLUDE
MCAST_INCLUDE
SO_DEBUG
SO_REUSEADDR
@ -617,3 +647,6 @@ INET_ADDRSTRLEN
INET6_ADDRSTRLEN
SOMAXCONN
SCM_RIGHTS
SCM_CREDENTIALS

View File

@ -190,6 +190,7 @@ int socktype_arg(VALUE type);
int level_arg(VALUE level);
int optname_arg(int level, VALUE optname);
int shutdown_how_arg(VALUE how);
int cmsg_type_arg(int level, VALUE optname);
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);
@ -254,6 +255,7 @@ void Init_udpsocket(void);
void Init_unixsocket(void);
void Init_unixserver(void);
void Init_socket_constants(void);
void Init_ancdata(void);
void Init_addrinfo(void);
void Init_sockopt(void);
void Init_socket_init(void);

View File

@ -31,6 +31,118 @@ class TestUNIXSocket < Test::Unit::TestCase
end
end
def test_fd_passing_n
io_ary = []
return if !defined?(Socket::SCM_RIGHTS)
io_ary.concat IO.pipe
io_ary.concat IO.pipe
io_ary.concat IO.pipe
send_io_ary = []
io_ary.each {|io|
send_io_ary << io
UNIXSocket.pair {|s1, s2|
begin
ret = s1.sendmsg("\0", 0, nil, [Socket::SOL_SOCKET, Socket::SCM_RIGHTS,
send_io_ary.map {|io| io.fileno }.pack("i!*")])
rescue NotImplementedError
return
end
assert_equal(1, ret)
ret = s2.recvmsg
data, srcaddr, flags, *ctls = ret
recv_io_ary = []
ctls.each {|ctl|
next if ctl.level != Socket::SOL_SOCKET || ctl.type != Socket::SCM_RIGHTS
recv_io_ary.concat ctl.data.unpack("i!*").map {|fd| IO.new(fd) }
}
assert_equal(send_io_ary.length, recv_io_ary.length)
send_io_ary.length.times {|i|
assert_not_equal(send_io_ary[i].fileno, recv_io_ary[i].fileno)
assert(File.identical?(send_io_ary[i], recv_io_ary[i]))
}
}
}
ensure
io_ary.each {|io| io.close if !io.closed? }
end
def test_sendmsg
return if !defined?(Socket::SCM_RIGHTS)
IO.pipe {|r1, w|
UNIXSocket.pair {|s1, s2|
begin
ret = s1.sendmsg("\0", 0, nil, [Socket::SOL_SOCKET, Socket::SCM_RIGHTS, [r1.fileno].pack("i!")])
rescue NotImplementedError
return
end
assert_equal(1, ret)
r2 = s2.recv_io
begin
assert(File.identical?(r1, r2))
ensure
r2.close
end
}
}
end
def test_sendmsg_ancillarydata
return if !defined?(Socket::SCM_RIGHTS)
return if !defined?(Socket::AncillaryData)
IO.pipe {|r1, w|
UNIXSocket.pair {|s1, s2|
begin
ad = Socket::AncillaryData.int(:SOCKET, :RIGHTS, r1.fileno)
ret = s1.sendmsg("\0", 0, nil, ad)
rescue NotImplementedError
return
end
assert_equal(1, ret)
r2 = s2.recv_io
begin
assert(File.identical?(r1, r2))
ensure
r2.close
end
}
}
end
def test_recvmsg
return if !defined?(Socket::SCM_RIGHTS)
IO.pipe {|r1, w|
UNIXSocket.pair {|s1, s2|
s1.send_io(r1)
ret = s2.recvmsg
data, srcaddr, flags, *ctls = ret
assert_equal("\0", data)
if flags == nil
# struct msghdr is 4.3BSD style (msg_accrights field).
assert_instance_of(Array, ctls)
assert_equal(0, ctls.length)
else
# struct msghdr is POSIX/4.4BSD style (msg_control field).
assert_equal(0, flags & (Socket::MSG_TRUNC|Socket::MSG_CTRUNC))
assert_instance_of(AddrInfo, srcaddr)
assert_instance_of(Array, ctls)
assert_equal(1, ctls.length)
assert_instance_of(Socket::AncillaryData, ctls[0])
assert_equal(Socket::SOL_SOCKET, ctls[0].level)
assert_equal(Socket::SCM_RIGHTS, ctls[0].type)
assert_instance_of(String, ctls[0].data)
fd, rest = ctls[0].data.unpack("i!a*")
assert_equal("", rest)
r2 = IO.new(fd)
begin
assert(File.identical?(r1, r2))
ensure
r2.close
end
end
}
}
end
def bound_unix_socket(klass)
tmpfile = Tempfile.new("testrubysock")
path = tmpfile.path