mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* 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:
parent
c618d018d8
commit
61fc0c6cf4
10 changed files with 1259 additions and 0 deletions
19
ChangeLog
19
ChangeLog
|
@ -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,
|
||||
|
|
|
@ -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
1070
ext/socket/ancdata.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -255,6 +255,7 @@ $objs = [
|
|||
"unixsocket.#{$OBJEXT}",
|
||||
"unixserver.#{$OBJEXT}",
|
||||
"option.#{$OBJEXT}",
|
||||
"ancdata.#{$OBJEXT}",
|
||||
"raddrinfo.#{$OBJEXT}"
|
||||
]
|
||||
|
||||
|
|
|
@ -520,6 +520,7 @@ Init_socket_init()
|
|||
Init_unixsocket();
|
||||
Init_unixserver();
|
||||
Init_sockopt();
|
||||
Init_ancdata();
|
||||
Init_addrinfo();
|
||||
Init_socket_constants();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue