rubysl-socket 2.0.1 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +70 -16
- data/lib/rubysl/socket.rb +201 -1396
- data/lib/rubysl/socket/ancillary_data.rb +56 -0
- data/lib/rubysl/socket/bsd.rb +28 -0
- data/lib/rubysl/socket/error.rb +67 -0
- data/lib/rubysl/socket/foreign.rb +324 -0
- data/lib/rubysl/socket/foreign/addrinfo.rb +10 -0
- data/lib/rubysl/socket/foreign/hostent.rb +36 -0
- data/lib/rubysl/socket/foreign/ifaddrs.rb +129 -0
- data/lib/rubysl/socket/foreign/iovec.rb +18 -0
- data/lib/rubysl/socket/foreign/linger.rb +41 -0
- data/lib/rubysl/socket/foreign/msghdr.rb +41 -0
- data/lib/rubysl/socket/foreign/servent.rb +17 -0
- data/lib/rubysl/socket/foreign/sockaddr.rb +21 -0
- data/lib/rubysl/socket/foreign/sockaddr_in.rb +25 -0
- data/lib/rubysl/socket/foreign/sockaddr_in6.rb +25 -0
- data/lib/rubysl/socket/foreign/sockaddr_un.rb +29 -0
- data/lib/rubysl/socket/ipv6.rb +38 -0
- data/lib/rubysl/socket/linux.rb +16 -0
- data/lib/rubysl/socket/socket_options.rb +84 -0
- data/lib/rubysl/socket/version.rb +1 -1
- data/lib/socket.rb +45 -1
- data/lib/socket/addrinfo.rb +453 -0
- data/lib/socket/ancillary_data.rb +114 -0
- data/lib/socket/basic_socket.rb +295 -0
- data/lib/socket/constants.rb +41 -0
- data/lib/socket/ifaddr.rb +29 -0
- data/lib/socket/ip_socket.rb +37 -0
- data/lib/socket/mri.rb +928 -0
- data/lib/socket/option.rb +96 -0
- data/lib/socket/socket.rb +353 -0
- data/lib/socket/socket_error.rb +2 -0
- data/lib/socket/tcp_server.rb +78 -0
- data/lib/socket/tcp_socket.rb +109 -0
- data/lib/socket/udp_socket.rb +73 -0
- data/lib/socket/unix_server.rb +35 -0
- data/lib/socket/unix_socket.rb +78 -0
- data/rubysl-socket.gemspec +15 -10
- metadata +78 -293
- data/.gitignore +0 -17
- data/.travis.yml +0 -9
- data/Gemfile +0 -4
- data/Rakefile +0 -1
- data/spec/addrinfo/afamily_spec.rb +0 -5
- data/spec/addrinfo/bind_spec.rb +0 -5
- data/spec/addrinfo/canonname_spec.rb +0 -5
- data/spec/addrinfo/connect_from_spec.rb +0 -5
- data/spec/addrinfo/connect_spec.rb +0 -5
- data/spec/addrinfo/connect_to_spec.rb +0 -5
- data/spec/addrinfo/family_addrinfo_spec.rb +0 -5
- data/spec/addrinfo/foreach_spec.rb +0 -5
- data/spec/addrinfo/getaddrinfo_spec.rb +0 -5
- data/spec/addrinfo/getnameinfo_spec.rb +0 -5
- data/spec/addrinfo/inspect_sockaddr_spec.rb +0 -5
- data/spec/addrinfo/inspect_spec.rb +0 -5
- data/spec/addrinfo/ip_address_spec.rb +0 -5
- data/spec/addrinfo/ip_port_spec.rb +0 -5
- data/spec/addrinfo/ip_spec.rb +0 -9
- data/spec/addrinfo/ip_unpack_spec.rb +0 -5
- data/spec/addrinfo/ipv4_loopback_spec.rb +0 -5
- data/spec/addrinfo/ipv4_multicast_spec.rb +0 -5
- data/spec/addrinfo/ipv4_private_spec.rb +0 -5
- data/spec/addrinfo/ipv4_spec.rb +0 -5
- data/spec/addrinfo/ipv6_linklocal_spec.rb +0 -5
- data/spec/addrinfo/ipv6_loopback_spec.rb +0 -5
- data/spec/addrinfo/ipv6_mc_global_spec.rb +0 -5
- data/spec/addrinfo/ipv6_mc_linklocal_spec.rb +0 -5
- data/spec/addrinfo/ipv6_mc_nodelocal_spec.rb +0 -5
- data/spec/addrinfo/ipv6_mc_orglocal_spec.rb +0 -5
- data/spec/addrinfo/ipv6_mc_sitelocal_spec.rb +0 -5
- data/spec/addrinfo/ipv6_multicast_spec.rb +0 -5
- data/spec/addrinfo/ipv6_sitelocal_spec.rb +0 -5
- data/spec/addrinfo/ipv6_spec.rb +0 -5
- data/spec/addrinfo/ipv6_to_ipv4_spec.rb +0 -5
- data/spec/addrinfo/ipv6_unspecified_spec.rb +0 -5
- data/spec/addrinfo/ipv6_v4compat_spec.rb +0 -5
- data/spec/addrinfo/ipv6_v4mapped_spec.rb +0 -5
- data/spec/addrinfo/listen_spec.rb +0 -5
- data/spec/addrinfo/marshal_dump_spec.rb +0 -5
- data/spec/addrinfo/marshal_load_spec.rb +0 -5
- data/spec/addrinfo/pfamily_spec.rb +0 -5
- data/spec/addrinfo/protocol_spec.rb +0 -5
- data/spec/addrinfo/socktype_spec.rb +0 -5
- data/spec/addrinfo/tcp_spec.rb +0 -5
- data/spec/addrinfo/to_s_spec.rb +0 -5
- data/spec/addrinfo/to_sockaddr_spec.rb +0 -5
- data/spec/addrinfo/udp_spec.rb +0 -5
- data/spec/addrinfo/unix_path_spec.rb +0 -5
- data/spec/addrinfo/unix_spec.rb +0 -9
- data/spec/basicsocket/close_read_spec.rb +0 -42
- data/spec/basicsocket/close_write_spec.rb +0 -42
- data/spec/basicsocket/do_not_reverse_lookup_spec.rb +0 -78
- data/spec/basicsocket/for_fd_spec.rb +0 -37
- data/spec/basicsocket/getpeername_spec.rb +0 -24
- data/spec/basicsocket/getsockname_spec.rb +0 -27
- data/spec/basicsocket/getsockopt_spec.rb +0 -54
- data/spec/basicsocket/ioctl_spec.rb +0 -22
- data/spec/basicsocket/recv_nonblock_spec.rb +0 -6
- data/spec/basicsocket/recv_spec.rb +0 -76
- data/spec/basicsocket/send_spec.rb +0 -81
- data/spec/basicsocket/setsockopt_spec.rb +0 -333
- data/spec/basicsocket/shutdown_spec.rb +0 -5
- data/spec/constants/constants_spec.rb +0 -63
- data/spec/fixtures/classes.rb +0 -174
- data/spec/fixtures/send_io.txt +0 -1
- data/spec/ipsocket/addr_spec.rb +0 -72
- data/spec/ipsocket/getaddress_spec.rb +0 -26
- data/spec/ipsocket/peeraddr_spec.rb +0 -79
- data/spec/ipsocket/recvfrom_spec.rb +0 -64
- data/spec/option/int_spec.rb +0 -27
- data/spec/option/linger_spec.rb +0 -52
- data/spec/option/new_spec.rb +0 -32
- data/spec/shared/pack_sockaddr.rb +0 -26
- data/spec/shared/partially_closable_sockets.rb +0 -13
- data/spec/shared/recv_nonblock.rb +0 -33
- data/spec/shared/socketpair.rb +0 -35
- data/spec/socket/accept_nonblock_spec.rb +0 -27
- data/spec/socket/accept_spec.rb +0 -1
- data/spec/socket/bind_spec.rb +0 -80
- data/spec/socket/connect_nonblock_spec.rb +0 -62
- data/spec/socket/connect_spec.rb +0 -1
- data/spec/socket/for_fd_spec.rb +0 -29
- data/spec/socket/getaddrinfo_spec.rb +0 -120
- data/spec/socket/gethostbyaddr_spec.rb +0 -1
- data/spec/socket/gethostbyname_spec.rb +0 -26
- data/spec/socket/gethostname_spec.rb +0 -9
- data/spec/socket/getnameinfo_spec.rb +0 -57
- data/spec/socket/getservbyname_spec.rb +0 -24
- data/spec/socket/listen_spec.rb +0 -21
- data/spec/socket/new_spec.rb +0 -109
- data/spec/socket/pack_sockaddr_in_spec.rb +0 -6
- data/spec/socket/pack_sockaddr_un_spec.rb +0 -6
- data/spec/socket/pair_spec.rb +0 -6
- data/spec/socket/recvfrom_nonblock_spec.rb +0 -1
- data/spec/socket/recvfrom_spec.rb +0 -1
- data/spec/socket/sockaddr_in_spec.rb +0 -6
- data/spec/socket/sockaddr_un_spec.rb +0 -6
- data/spec/socket/socket_spec.rb +0 -37
- data/spec/socket/socketpair_spec.rb +0 -6
- data/spec/socket/sysaccept_spec.rb +0 -1
- data/spec/socket/unpack_sockaddr_in_spec.rb +0 -16
- data/spec/socket/unpack_sockaddr_un_spec.rb +0 -2
- data/spec/tcpserver/accept_nonblock_spec.rb +0 -30
- data/spec/tcpserver/accept_spec.rb +0 -60
- data/spec/tcpserver/gets_spec.rb +0 -17
- data/spec/tcpserver/listen_spec.rb +0 -1
- data/spec/tcpserver/new_spec.rb +0 -88
- data/spec/tcpserver/output_spec.rb +0 -8
- data/spec/tcpserver/readpartial_spec.rb +0 -8
- data/spec/tcpserver/sysaccept_spec.rb +0 -1
- data/spec/tcpsocket/gethostbyname_spec.rb +0 -62
- data/spec/tcpsocket/new_spec.rb +0 -5
- data/spec/tcpsocket/open_spec.rb +0 -5
- data/spec/tcpsocket/partially_closable_spec.rb +0 -20
- data/spec/tcpsocket/recv_nonblock_spec.rb +0 -31
- data/spec/tcpsocket/setsockopt_spec.rb +0 -49
- data/spec/tcpsocket/shared/new.rb +0 -85
- data/spec/udpsocket/bind_spec.rb +0 -33
- data/spec/udpsocket/connect_spec.rb +0 -1
- data/spec/udpsocket/new_spec.rb +0 -1
- data/spec/udpsocket/open_spec.rb +0 -12
- data/spec/udpsocket/recvfrom_nonblock_spec.rb +0 -1
- data/spec/udpsocket/send_spec.rb +0 -57
- data/spec/unixserver/accept_nonblock_spec.rb +0 -33
- data/spec/unixserver/accept_spec.rb +0 -64
- data/spec/unixserver/for_fd_spec.rb +0 -32
- data/spec/unixserver/new_spec.rb +0 -5
- data/spec/unixserver/open_spec.rb +0 -25
- data/spec/unixserver/shared/new.rb +0 -23
- data/spec/unixsocket/addr_spec.rb +0 -37
- data/spec/unixsocket/new_spec.rb +0 -5
- data/spec/unixsocket/open_spec.rb +0 -26
- data/spec/unixsocket/pair_spec.rb +0 -38
- data/spec/unixsocket/partially_closable_spec.rb +0 -25
- data/spec/unixsocket/path_spec.rb +0 -29
- data/spec/unixsocket/peeraddr_spec.rb +0 -29
- data/spec/unixsocket/recv_io_spec.rb +0 -40
- data/spec/unixsocket/recvfrom_spec.rb +0 -48
- data/spec/unixsocket/send_io_spec.rb +0 -30
- data/spec/unixsocket/shared/new.rb +0 -25
@@ -0,0 +1,56 @@
|
|
1
|
+
module RubySL
|
2
|
+
module Socket
|
3
|
+
module AncillaryData
|
4
|
+
LEVEL_PREFIXES = {
|
5
|
+
::Socket::SOL_SOCKET => %w{SCM_ UNIX},
|
6
|
+
::Socket::IPPROTO_IP => %w{IP_ IP},
|
7
|
+
::Socket::IPPROTO_IPV6 => %w{IPV6_ IPV6},
|
8
|
+
::Socket::IPPROTO_TCP => %w{TCP_ TCP},
|
9
|
+
::Socket::IPPROTO_UDP => %w{UDP_ UDP}
|
10
|
+
}
|
11
|
+
|
12
|
+
def self.level(raw_level)
|
13
|
+
if raw_level.is_a?(Fixnum)
|
14
|
+
raw_level
|
15
|
+
else
|
16
|
+
level = Socket.coerce_to_string(raw_level)
|
17
|
+
|
18
|
+
if level == 'SOL_SOCKET' or level == 'SOCKET'
|
19
|
+
::Socket::SOL_SOCKET
|
20
|
+
|
21
|
+
# Translates "TCP" into "IPPROTO_TCP", "UDP" into "IPPROTO_UDP", etc.
|
22
|
+
else
|
23
|
+
Socket.prefixed_socket_constant(level, 'IPPROTO_') do
|
24
|
+
"unknown protocol level: #{level}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.type(family, level, raw_type)
|
31
|
+
if raw_type.is_a?(Fixnum)
|
32
|
+
raw_type
|
33
|
+
else
|
34
|
+
type = Socket.coerce_to_string(raw_type)
|
35
|
+
|
36
|
+
if family == ::Socket::AF_INET or family == ::Socket::AF_INET6
|
37
|
+
prefix, label = LEVEL_PREFIXES[level]
|
38
|
+
else
|
39
|
+
prefix, label = LEVEL_PREFIXES[::Socket::SOL_SOCKET]
|
40
|
+
end
|
41
|
+
|
42
|
+
# Translates "RIGHTS" into "SCM_RIGHTS", "CORK" into "TCP_CORK" (when
|
43
|
+
# the level is IPPROTO_TCP), etc.
|
44
|
+
if prefix and label
|
45
|
+
Socket.prefixed_socket_constant(type, prefix) do
|
46
|
+
"Unknown #{label} control message: #{type}"
|
47
|
+
end
|
48
|
+
else
|
49
|
+
raise TypeError,
|
50
|
+
"no implicit conversion of #{type.class} into Integer"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# This file is only available on BSD/Darwin systems.
|
2
|
+
|
3
|
+
module RubySL
|
4
|
+
module Socket
|
5
|
+
module Foreign
|
6
|
+
attach_function :_getpeereid,
|
7
|
+
:getpeereid, [:int, :pointer, :pointer], :int
|
8
|
+
|
9
|
+
def self.getpeereid(descriptor)
|
10
|
+
euid = Foreign.memory_pointer(:int)
|
11
|
+
egid = Foreign.memory_pointer(:int)
|
12
|
+
|
13
|
+
begin
|
14
|
+
res = _getpeereid(descriptor, euid, egid)
|
15
|
+
|
16
|
+
if res == 0
|
17
|
+
[euid.read_int, egid.read_int]
|
18
|
+
else
|
19
|
+
Errno.handle('getpeereid(3)')
|
20
|
+
end
|
21
|
+
ensure
|
22
|
+
euid.free
|
23
|
+
egid.free
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module RubySL
|
2
|
+
module Socket
|
3
|
+
module Error
|
4
|
+
def self.write_error(message, socket)
|
5
|
+
if nonblocking?(socket)
|
6
|
+
write_nonblock(message)
|
7
|
+
else
|
8
|
+
Errno.handle(message)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.read_error(message, socket)
|
13
|
+
if nonblocking?(socket)
|
14
|
+
read_nonblock(message)
|
15
|
+
else
|
16
|
+
Errno.handle(message)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Handles an error for a non-blocking read operation.
|
21
|
+
def self.read_nonblock(message)
|
22
|
+
wrap_read_nonblock { Errno.handle(message) }
|
23
|
+
end
|
24
|
+
|
25
|
+
# Handles an error for a non-blocking write operation.
|
26
|
+
def self.write_nonblock(message)
|
27
|
+
wrap_write_nonblock { Errno.handle(message) }
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.wrap_read_nonblock
|
31
|
+
yield
|
32
|
+
rescue Errno::EAGAIN => err
|
33
|
+
raise_wrapped_error(err, IO::EAGAINWaitReadable)
|
34
|
+
rescue Errno::EWOULDBLOCK => err
|
35
|
+
raise_wrapped_error(err, IO::EWOULDBLOCKWaitReadable)
|
36
|
+
rescue Errno::EINPROGRESS => err
|
37
|
+
raise_wrapped_error(err, IO::EINPROGRESSWaitReadable)
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.wrap_write_nonblock
|
41
|
+
yield
|
42
|
+
rescue Errno::EAGAIN => err
|
43
|
+
raise_wrapped_error(err, IO::EAGAINWaitWritable)
|
44
|
+
rescue Errno::EWOULDBLOCK => err
|
45
|
+
raise_wrapped_error(err, IO::EWOULDBLOCKWaitWritable)
|
46
|
+
rescue Errno::EINPROGRESS => err
|
47
|
+
raise_wrapped_error(err, IO::EINPROGRESSWaitWritable)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Wraps the error given in `original` in an instance of `error_class`.
|
51
|
+
#
|
52
|
+
# This can be used to wrap e.g. an Errno::EAGAIN error in an
|
53
|
+
# IO::EAGAINWaitReadable instance.
|
54
|
+
def self.raise_wrapped_error(original, error_class)
|
55
|
+
error = error_class.new(original.message)
|
56
|
+
|
57
|
+
error.set_backtrace(original.backtrace)
|
58
|
+
|
59
|
+
raise error
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.nonblocking?(socket)
|
63
|
+
socket.fcntl(::Fcntl::F_GETFL) & ::Fcntl::O_NONBLOCK > 0
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,324 @@
|
|
1
|
+
module RubySL
|
2
|
+
module Socket
|
3
|
+
module Foreign
|
4
|
+
extend Rubinius::FFI::Library
|
5
|
+
|
6
|
+
SIZEOF_INT = Rubinius::FFI.type_size(:int)
|
7
|
+
|
8
|
+
attach_function :_bind, :bind, [:int, :pointer, :socklen_t], :int
|
9
|
+
attach_function :_connect, :connect, [:int, :pointer, :socklen_t], :int
|
10
|
+
|
11
|
+
attach_function :accept, [:int, :pointer, :pointer], :int
|
12
|
+
attach_function :close, [:int], :int
|
13
|
+
attach_function :shutdown, [:int, :int], :int
|
14
|
+
attach_function :listen, [:int, :int], :int
|
15
|
+
attach_function :socket, [:int, :int, :int], :int
|
16
|
+
attach_function :send, [:int, :pointer, :size_t, :int], :ssize_t
|
17
|
+
|
18
|
+
attach_function :sendto,
|
19
|
+
[:int, :pointer, :size_t, :int, :pointer, :socklen_t], :ssize_t
|
20
|
+
|
21
|
+
attach_function :recv, [:int, :pointer, :size_t, :int], :ssize_t
|
22
|
+
attach_function :recvmsg, :recvmsg, [:int, :pointer, :int], :ssize_t
|
23
|
+
attach_function :sendmsg, :sendmsg, [:int, :pointer, :int], :ssize_t
|
24
|
+
|
25
|
+
attach_function :recvfrom,
|
26
|
+
[:int, :pointer, :size_t, :int, :pointer, :pointer], :int
|
27
|
+
|
28
|
+
attach_function :_getsockopt,
|
29
|
+
:getsockopt, [:int, :int, :int, :pointer, :pointer], :int
|
30
|
+
|
31
|
+
attach_function :_getaddrinfo,
|
32
|
+
:getaddrinfo, [:string, :string, :pointer, :pointer], :int
|
33
|
+
|
34
|
+
attach_function :gai_strerror, [:int], :string
|
35
|
+
|
36
|
+
attach_function :setsockopt,
|
37
|
+
[:int, :int, :int, :pointer, :socklen_t], :int
|
38
|
+
|
39
|
+
attach_function :freeaddrinfo, [:pointer], :void
|
40
|
+
|
41
|
+
attach_function :_getpeername,
|
42
|
+
:getpeername, [:int, :pointer, :pointer], :int
|
43
|
+
|
44
|
+
attach_function :_getsockname,
|
45
|
+
:getsockname, [:int, :pointer, :pointer], :int
|
46
|
+
|
47
|
+
attach_function :_socketpair,
|
48
|
+
:socketpair, [:int, :int, :int, :pointer], :int
|
49
|
+
|
50
|
+
attach_function :gethostname, [:pointer, :size_t], :int
|
51
|
+
attach_function :getservbyname, [:string, :string], :pointer
|
52
|
+
attach_function :getservbyport, [:int, :string], :pointer
|
53
|
+
attach_function :gethostbyname, [:string], :pointer
|
54
|
+
attach_function :gethostbyaddr, [:pointer, :socklen_t, :int], :pointer
|
55
|
+
|
56
|
+
attach_function :htons, [:uint16_t], :uint16_t
|
57
|
+
attach_function :ntohs, [:uint16_t], :uint16_t
|
58
|
+
|
59
|
+
attach_function :inet_network, [:string], :uint32_t
|
60
|
+
attach_function :inet_pton, [:int, :string, :pointer], :int
|
61
|
+
|
62
|
+
attach_function :_getnameinfo,
|
63
|
+
:getnameinfo,
|
64
|
+
[:pointer, :socklen_t, :pointer, :socklen_t, :pointer, :socklen_t, :int],
|
65
|
+
:int
|
66
|
+
|
67
|
+
attach_function :getifaddrs, [:pointer], :int
|
68
|
+
attach_function :freeifaddrs, [:pointer], :void
|
69
|
+
|
70
|
+
def self.bind(descriptor, sockaddr)
|
71
|
+
memory_pointer(:char, sockaddr.bytesize) do |sockaddr_p|
|
72
|
+
sockaddr_p.write_string(sockaddr, sockaddr.bytesize)
|
73
|
+
|
74
|
+
_bind(descriptor, sockaddr_p, sockaddr.bytesize)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.connect(descriptor, sockaddr)
|
79
|
+
sockaddr = Socket.coerce_to_string(sockaddr)
|
80
|
+
|
81
|
+
memory_pointer(:char, sockaddr.bytesize) do |sockaddr_p|
|
82
|
+
sockaddr_p.write_string(sockaddr, sockaddr.bytesize)
|
83
|
+
|
84
|
+
_connect(descriptor, sockaddr_p, sockaddr.bytesize)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def self.getsockopt(descriptor, level, optname)
|
89
|
+
memory_pointer(256) do |val|
|
90
|
+
memory_pointer(:socklen_t) do |length|
|
91
|
+
length.write_int(256)
|
92
|
+
|
93
|
+
err = _getsockopt(descriptor, level, optname, val, length)
|
94
|
+
|
95
|
+
Errno.handle('Unable to get socket option') unless err == 0
|
96
|
+
|
97
|
+
return val.read_string(length.read_int)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def self.getaddrinfo(host, service = nil, family = nil, socktype = nil,
|
103
|
+
protocol = nil, flags = nil)
|
104
|
+
hints = Addrinfo.new
|
105
|
+
|
106
|
+
hints[:ai_family] = family || 0
|
107
|
+
hints[:ai_socktype] = socktype || 0
|
108
|
+
hints[:ai_protocol] = protocol || 0
|
109
|
+
hints[:ai_flags] = flags || 0
|
110
|
+
|
111
|
+
res_p = memory_pointer(:pointer)
|
112
|
+
err = _getaddrinfo(host, service, hints.pointer, res_p)
|
113
|
+
|
114
|
+
raise SocketError, gai_strerror(err) unless err == 0
|
115
|
+
|
116
|
+
ptr = res_p.read_pointer
|
117
|
+
|
118
|
+
return [] unless ptr
|
119
|
+
|
120
|
+
res = Addrinfo.new(ptr)
|
121
|
+
|
122
|
+
addrinfos = []
|
123
|
+
|
124
|
+
while true
|
125
|
+
addrinfo = []
|
126
|
+
addrinfo << res[:ai_flags]
|
127
|
+
addrinfo << res[:ai_family]
|
128
|
+
addrinfo << res[:ai_socktype]
|
129
|
+
addrinfo << res[:ai_protocol]
|
130
|
+
addrinfo << res[:ai_addr].read_string(res[:ai_addrlen])
|
131
|
+
addrinfo << res[:ai_canonname]
|
132
|
+
|
133
|
+
addrinfos << addrinfo
|
134
|
+
|
135
|
+
break unless res[:ai_next]
|
136
|
+
|
137
|
+
res = Addrinfo.new(res[:ai_next])
|
138
|
+
end
|
139
|
+
|
140
|
+
return addrinfos
|
141
|
+
ensure
|
142
|
+
hints.free if hints
|
143
|
+
|
144
|
+
if res_p
|
145
|
+
ptr = res_p.read_pointer
|
146
|
+
|
147
|
+
# Be sure to feed a legit pointer to freeaddrinfo
|
148
|
+
freeaddrinfo(ptr) if ptr && !ptr.null?
|
149
|
+
|
150
|
+
res_p.free
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def self.getaddress(host)
|
155
|
+
addrinfos = getaddrinfo(host)
|
156
|
+
|
157
|
+
unpack_sockaddr_in(addrinfos.first[4], false).first
|
158
|
+
end
|
159
|
+
|
160
|
+
def self.getnameinfo(sockaddr, flags = ::Socket::NI_NUMERICHOST | ::Socket::NI_NUMERICSERV,
|
161
|
+
reverse_lookup = !BasicSocket.do_not_reverse_lookup)
|
162
|
+
name_info = []
|
163
|
+
|
164
|
+
char_pointer(sockaddr.bytesize) do |sockaddr_p|
|
165
|
+
char_pointer(::Socket::NI_MAXHOST) do |node|
|
166
|
+
char_pointer(::Socket::NI_MAXSERV) do |service|
|
167
|
+
sockaddr_p.write_string(sockaddr, sockaddr.bytesize)
|
168
|
+
|
169
|
+
if reverse_lookup
|
170
|
+
err = _getnameinfo(sockaddr_p, sockaddr.bytesize, node,
|
171
|
+
::Socket::NI_MAXHOST, nil, 0, 0)
|
172
|
+
|
173
|
+
name_info[2] = node.read_string if err == 0
|
174
|
+
end
|
175
|
+
|
176
|
+
err = _getnameinfo(sockaddr_p, sockaddr.bytesize, node,
|
177
|
+
::Socket::NI_MAXHOST, service,
|
178
|
+
::Socket::NI_MAXSERV, flags)
|
179
|
+
|
180
|
+
raise SocketError, gai_strerror(err) unless err == 0
|
181
|
+
|
182
|
+
sa_family = SockaddrIn.with_sockaddr(sockaddr)[:sin_family]
|
183
|
+
|
184
|
+
name_info[0] = ::Socket::Constants::AF_TO_FAMILY[sa_family]
|
185
|
+
name_info[1] = service.read_string
|
186
|
+
name_info[3] = node.read_string
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
name_info[2] = name_info[3] unless name_info[2]
|
192
|
+
|
193
|
+
name_info
|
194
|
+
end
|
195
|
+
|
196
|
+
def self.getpeername(descriptor)
|
197
|
+
memory_pointer(:char, 128) do |sockaddr_storage_p|
|
198
|
+
memory_pointer(:socklen_t) do |len_p|
|
199
|
+
len_p.write_int(128)
|
200
|
+
|
201
|
+
err = _getpeername(descriptor, sockaddr_storage_p, len_p)
|
202
|
+
|
203
|
+
Errno.handle('getpeername(2)') unless err == 0
|
204
|
+
|
205
|
+
sockaddr_storage_p.read_string(len_p.read_int)
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
def self.getsockname(descriptor)
|
211
|
+
memory_pointer(:char, 128) do |sockaddr_storage_p|
|
212
|
+
memory_pointer(:socklen_t) do |len_p|
|
213
|
+
len_p.write_int(128)
|
214
|
+
|
215
|
+
err = _getsockname(descriptor, sockaddr_storage_p, len_p)
|
216
|
+
|
217
|
+
Errno.handle('getsockname(2)') unless err == 0
|
218
|
+
|
219
|
+
sockaddr_storage_p.read_string(len_p.read_int)
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
def self.pack_sockaddr_in(host, port, family = ::Socket::AF_UNSPEC,
|
225
|
+
type = 0, flags = 0)
|
226
|
+
hints = Addrinfo.new
|
227
|
+
|
228
|
+
hints[:ai_family] = family
|
229
|
+
hints[:ai_socktype] = type
|
230
|
+
hints[:ai_flags] = flags
|
231
|
+
|
232
|
+
if host and host.empty?
|
233
|
+
host = "0.0.0.0"
|
234
|
+
end
|
235
|
+
|
236
|
+
res_p = memory_pointer(:pointer)
|
237
|
+
|
238
|
+
err = _getaddrinfo(host, port.to_s, hints.pointer, res_p)
|
239
|
+
|
240
|
+
raise SocketError, gai_strerror(err) unless err == 0
|
241
|
+
|
242
|
+
return [] if res_p.read_pointer.null?
|
243
|
+
|
244
|
+
res = Addrinfo.new(res_p.read_pointer)
|
245
|
+
|
246
|
+
return res[:ai_addr].read_string(res[:ai_addrlen])
|
247
|
+
ensure
|
248
|
+
hints.free if hints
|
249
|
+
|
250
|
+
if res_p
|
251
|
+
ptr = res_p.read_pointer
|
252
|
+
|
253
|
+
freeaddrinfo(ptr) if ptr && !ptr.null?
|
254
|
+
|
255
|
+
res_p.free
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
def self.unpack_sockaddr_in(sockaddr, reverse_lookup)
|
260
|
+
family, port, host, ip = getnameinfo(
|
261
|
+
sockaddr,
|
262
|
+
::Socket::NI_NUMERICHOST | ::Socket::NI_NUMERICSERV,
|
263
|
+
reverse_lookup
|
264
|
+
)
|
265
|
+
|
266
|
+
# On some systems this doesn't fail for families other than AF_INET(6)
|
267
|
+
# so we raise manually here.
|
268
|
+
unless family =~ /AF_INET/
|
269
|
+
raise ArgumentError, 'not an AF_INET/AF_INET6 sockaddr'
|
270
|
+
end
|
271
|
+
|
272
|
+
return host, ip, port.to_i
|
273
|
+
end
|
274
|
+
|
275
|
+
def self.getpeereid(*)
|
276
|
+
raise NotImplementedError,
|
277
|
+
'getpeereid() is not supported on this platform'
|
278
|
+
end
|
279
|
+
|
280
|
+
def self.socketpair(family, type, protocol)
|
281
|
+
memory_pointer(:int, 2) do |pointer|
|
282
|
+
_socketpair(family, type, protocol, pointer)
|
283
|
+
|
284
|
+
pointer.read_array_of_int(2)
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
def self.char_pointer(length, &block)
|
289
|
+
memory_pointer(:char, length, &block)
|
290
|
+
end
|
291
|
+
|
292
|
+
def self.memory_pointer(*args, &block)
|
293
|
+
Rubinius::FFI::MemoryPointer.new(*args, &block)
|
294
|
+
end
|
295
|
+
|
296
|
+
def self.pointers_of_type(current, type)
|
297
|
+
pointers = []
|
298
|
+
size = Rubinius::FFI.type_size(type)
|
299
|
+
pointer = current.read_pointer
|
300
|
+
|
301
|
+
until pointer.null?
|
302
|
+
pointers << pointer
|
303
|
+
|
304
|
+
current = current + size
|
305
|
+
pointer = current.read_pointer
|
306
|
+
end
|
307
|
+
|
308
|
+
pointers
|
309
|
+
end
|
310
|
+
|
311
|
+
def self.ip_to_bytes(family, address)
|
312
|
+
size = 16
|
313
|
+
|
314
|
+
memory_pointer(:pointer, size) do |pointer|
|
315
|
+
status = inet_pton(family, address, pointer)
|
316
|
+
|
317
|
+
Errno.handle('inet_pton()') if status < 1
|
318
|
+
|
319
|
+
pointer.get_array_of_uchar(0, size)
|
320
|
+
end
|
321
|
+
end
|
322
|
+
end
|
323
|
+
end
|
324
|
+
end
|