rubysl-socket 2.0.1 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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,16 @@
|
|
1
|
+
# This file is only available on Linux systems.
|
2
|
+
|
3
|
+
module RubySL
|
4
|
+
module Socket
|
5
|
+
module Foreign
|
6
|
+
def self.getpeereid(descriptor)
|
7
|
+
data = Foreign
|
8
|
+
.getsockopt(descriptor, ::Socket::SOL_SOCKET, ::Socket::SO_PEERCRED)
|
9
|
+
|
10
|
+
_, euid, egid = data.unpack('iii')
|
11
|
+
|
12
|
+
[euid, egid]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module RubySL
|
2
|
+
module Socket
|
3
|
+
module SocketOptions
|
4
|
+
def self.socket_level(level, family = nil)
|
5
|
+
if level.is_a?(Symbol) or level.is_a?(String)
|
6
|
+
if ::Socket.const_defined?(level)
|
7
|
+
::Socket.const_get(level)
|
8
|
+
else
|
9
|
+
if family and is_ip_family?(family)
|
10
|
+
ip_level_to_int(level)
|
11
|
+
elsif level.to_s == 'SOCKET'
|
12
|
+
::Socket::SOL_SOCKET
|
13
|
+
else
|
14
|
+
constant("IPPROTO", level)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
elsif level.respond_to?(:to_str)
|
18
|
+
socket_level(Socket.coerce_to_string(level), family)
|
19
|
+
else
|
20
|
+
level
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.socket_option(level, optname)
|
25
|
+
case optname
|
26
|
+
when Symbol, String
|
27
|
+
if ::Socket.const_defined?(optname)
|
28
|
+
::Socket.const_get(optname)
|
29
|
+
else
|
30
|
+
case level
|
31
|
+
when ::Socket::SOL_SOCKET
|
32
|
+
constant("SO", optname)
|
33
|
+
when ::Socket::IPPROTO_IP
|
34
|
+
constant("IP", optname)
|
35
|
+
when ::Socket::IPPROTO_TCP
|
36
|
+
constant("TCP", optname)
|
37
|
+
when ::Socket::IPPROTO_UDP
|
38
|
+
constant("UDP", optname)
|
39
|
+
when ::Socket.const_defined?(:IPPROTO_IPV6) && ::Socket::IPPROTO_IPV6
|
40
|
+
constant("IPV6", optname)
|
41
|
+
else
|
42
|
+
raise SocketError,
|
43
|
+
"Unsupported socket level option name: #{optname}"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
else
|
47
|
+
if optname.respond_to?(:to_str)
|
48
|
+
socket_option(level, Socket.coerce_to_string(optname))
|
49
|
+
else
|
50
|
+
optname
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.is_ip_family?(family)
|
56
|
+
family == "AF_INET" || family == "AF_INET6"
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.ip_level_to_int(level)
|
60
|
+
prefixes = ["IPPROTO", "SOL", "IPV6"]
|
61
|
+
|
62
|
+
prefixes.each do |prefix|
|
63
|
+
const = "#{prefix}_#{level}"
|
64
|
+
|
65
|
+
if ::Socket.const_defined?(const)
|
66
|
+
return ::Socket.const_get(const)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
nil
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.constant(prefix, suffix)
|
74
|
+
const = "#{prefix}_#{suffix}"
|
75
|
+
|
76
|
+
if ::Socket.const_defined?(const)
|
77
|
+
::Socket.const_get(const)
|
78
|
+
else
|
79
|
+
raise SocketError, "Undefined socket constant: #{const}"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
data/lib/socket.rb
CHANGED
@@ -1 +1,45 @@
|
|
1
|
-
require
|
1
|
+
require 'fcntl'
|
2
|
+
|
3
|
+
require 'rubysl/socket'
|
4
|
+
require 'rubysl/socket/version'
|
5
|
+
require 'rubysl/socket/socket_options'
|
6
|
+
|
7
|
+
require 'socket/socket_error'
|
8
|
+
require 'socket/basic_socket'
|
9
|
+
require 'socket/constants'
|
10
|
+
|
11
|
+
require 'rubysl/socket/foreign/addrinfo'
|
12
|
+
require 'rubysl/socket/foreign/linger'
|
13
|
+
require 'rubysl/socket/foreign/ifaddrs'
|
14
|
+
require 'rubysl/socket/foreign/sockaddr'
|
15
|
+
require 'rubysl/socket/foreign/sockaddr_in'
|
16
|
+
require 'rubysl/socket/foreign/sockaddr_in6'
|
17
|
+
|
18
|
+
if RubySL::Socket.unix_socket_support?
|
19
|
+
require 'rubysl/socket/foreign/sockaddr_un'
|
20
|
+
end
|
21
|
+
|
22
|
+
require 'rubysl/socket/foreign/iovec'
|
23
|
+
require 'rubysl/socket/foreign/msghdr'
|
24
|
+
require 'rubysl/socket/foreign/hostent'
|
25
|
+
require 'rubysl/socket/foreign/servent'
|
26
|
+
|
27
|
+
require 'rubysl/socket/ipv6'
|
28
|
+
require 'rubysl/socket/ancillary_data'
|
29
|
+
require 'rubysl/socket/foreign'
|
30
|
+
require 'rubysl/socket/error'
|
31
|
+
require 'rubysl/socket/bsd' if RubySL::Socket.bsd_support?
|
32
|
+
require 'rubysl/socket/linux' if RubySL::Socket.linux_support?
|
33
|
+
|
34
|
+
require 'socket/socket'
|
35
|
+
require 'socket/option'
|
36
|
+
require 'socket/ancillary_data'
|
37
|
+
require 'socket/mri'
|
38
|
+
require 'socket/unix_socket'
|
39
|
+
require 'socket/unix_server'
|
40
|
+
require 'socket/ip_socket'
|
41
|
+
require 'socket/udp_socket'
|
42
|
+
require 'socket/tcp_socket'
|
43
|
+
require 'socket/tcp_server'
|
44
|
+
require 'socket/addrinfo'
|
45
|
+
require 'socket/ifaddr'
|
@@ -0,0 +1,453 @@
|
|
1
|
+
class Addrinfo
|
2
|
+
attr_reader :afamily, :pfamily, :socktype, :protocol
|
3
|
+
|
4
|
+
attr_reader :canonname
|
5
|
+
|
6
|
+
def self.getaddrinfo(nodename, service, family = nil, socktype = nil,
|
7
|
+
protocol = nil, flags = nil)
|
8
|
+
|
9
|
+
raw = Socket
|
10
|
+
.getaddrinfo(nodename, service, family, socktype, protocol, flags)
|
11
|
+
|
12
|
+
raw.map do |pair|
|
13
|
+
lfamily, lport, lhost, laddress, _, lsocktype, lprotocol = pair
|
14
|
+
|
15
|
+
sockaddr = Socket.pack_sockaddr_in(lport, laddress)
|
16
|
+
addr = Addrinfo.new(sockaddr, lfamily, lsocktype, lprotocol)
|
17
|
+
|
18
|
+
if flags and flags | Socket::AI_CANONNAME
|
19
|
+
addr.instance_variable_set(:@canonname, lhost)
|
20
|
+
end
|
21
|
+
|
22
|
+
addr
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.ip(ip)
|
27
|
+
sockaddr = Socket.sockaddr_in(0, ip)
|
28
|
+
family = RubySL::Socket.family_for_sockaddr_in(sockaddr)
|
29
|
+
|
30
|
+
new(sockaddr, family)
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.tcp(ip, port)
|
34
|
+
sockaddr = Socket.sockaddr_in(port, ip)
|
35
|
+
pfamily = RubySL::Socket.family_for_sockaddr_in(sockaddr)
|
36
|
+
|
37
|
+
new(sockaddr, pfamily, Socket::SOCK_STREAM, Socket::IPPROTO_TCP)
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.udp(ip, port)
|
41
|
+
sockaddr = Socket.sockaddr_in(port, ip)
|
42
|
+
pfamily = RubySL::Socket.family_for_sockaddr_in(sockaddr)
|
43
|
+
|
44
|
+
new(sockaddr, pfamily, Socket::SOCK_DGRAM, Socket::IPPROTO_UDP)
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.unix(socket, socktype = nil)
|
48
|
+
socktype ||= Socket::SOCK_STREAM
|
49
|
+
|
50
|
+
new(Socket.pack_sockaddr_un(socket), Socket::PF_UNIX, socktype)
|
51
|
+
end
|
52
|
+
|
53
|
+
# Addrinfo#initialize has a bunch of checks that prevent us from setting
|
54
|
+
# certain address families (e.g. AF_PACKET). Meanwhile methods such as
|
55
|
+
# Socket.getifaddrs need to create Addrinfo instances with exactly those
|
56
|
+
# address families.
|
57
|
+
#
|
58
|
+
# Because modifying #initialize would break compatibility we have to define a
|
59
|
+
# separate new-like method that completely ignores #initialize. You can thank
|
60
|
+
# Ruby for being such a well designed language.
|
61
|
+
#
|
62
|
+
# For the sake of simplicity `family` **must** be a Fixnum, a String based
|
63
|
+
# address family is not supported.
|
64
|
+
def self.raw_with_family(family)
|
65
|
+
instance = allocate
|
66
|
+
|
67
|
+
instance.instance_variable_set(:@afamily, family)
|
68
|
+
|
69
|
+
instance
|
70
|
+
end
|
71
|
+
|
72
|
+
def initialize(sockaddr, pfamily = nil, socktype = 0, protocol = 0)
|
73
|
+
if sockaddr.kind_of?(Array)
|
74
|
+
@afamily = RubySL::Socket.address_family(sockaddr[0])
|
75
|
+
@ip_port = sockaddr[1]
|
76
|
+
@ip_address = sockaddr[3]
|
77
|
+
|
78
|
+
# When using AF_INET6 the protocol family can only be PF_INET6
|
79
|
+
if @afamily == Socket::AF_INET6 and !pfamily
|
80
|
+
pfamily = Socket::PF_INET6
|
81
|
+
end
|
82
|
+
else
|
83
|
+
if sockaddr.bytesize == RubySL::Socket::Foreign::SockaddrUn.size
|
84
|
+
@unix_path = Socket.unpack_sockaddr_un(sockaddr)
|
85
|
+
@afamily = Socket::AF_UNIX
|
86
|
+
else
|
87
|
+
@ip_port, @ip_address = Socket.unpack_sockaddr_in(sockaddr)
|
88
|
+
|
89
|
+
if sockaddr.bytesize == 28
|
90
|
+
@afamily = Socket::AF_INET6
|
91
|
+
else
|
92
|
+
@afamily = Socket::AF_INET
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
@pfamily ||= RubySL::Socket.protocol_family(pfamily)
|
98
|
+
|
99
|
+
@socktype = RubySL::Socket.socket_type(socktype || 0)
|
100
|
+
@protocol = protocol || 0
|
101
|
+
|
102
|
+
# Per MRI behaviour setting the protocol family should also set the address
|
103
|
+
# family, but only if the address and protocol families are compatible.
|
104
|
+
if @pfamily && @pfamily != 0
|
105
|
+
if @afamily == Socket::AF_INET6 and
|
106
|
+
@pfamily != Socket::PF_INET and
|
107
|
+
@pfamily != Socket::PF_INET6
|
108
|
+
raise SocketError, 'The given protocol and address families are incompatible'
|
109
|
+
end
|
110
|
+
|
111
|
+
@afamily = @pfamily
|
112
|
+
end
|
113
|
+
|
114
|
+
# MRI only checks this if "sockaddr" is an Array.
|
115
|
+
if sockaddr.kind_of?(Array)
|
116
|
+
if @afamily == Socket::AF_INET6
|
117
|
+
if Socket.sockaddr_in(0, @ip_address).bytesize != 28
|
118
|
+
raise SocketError, "Invalid IPv6 address: #{@ip_address.inspect}"
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
# Based on MRI's (re-)implementation of getaddrinfo()
|
124
|
+
if @afamily != Socket::AF_UNIX and
|
125
|
+
@afamily != Socket::AF_UNSPEC and
|
126
|
+
@afamily != Socket::AF_INET and
|
127
|
+
@afamily != Socket::AF_INET6
|
128
|
+
raise(
|
129
|
+
SocketError,
|
130
|
+
'Address family must be AF_UNIX, AF_INET, AF_INET6, PF_INET or PF_INET6'
|
131
|
+
)
|
132
|
+
end
|
133
|
+
|
134
|
+
# Per MRI this validation should only happen when "sockaddr" is an Array.
|
135
|
+
if sockaddr.is_a?(Array)
|
136
|
+
case @socktype
|
137
|
+
when 0, nil
|
138
|
+
if @protocol != 0 and @protocol != nil and @protocol != Socket::IPPROTO_UDP
|
139
|
+
raise SocketError, 'Socket protocol must be IPPROTO_UDP or left unset'
|
140
|
+
end
|
141
|
+
when Socket::SOCK_RAW
|
142
|
+
# nothing to do
|
143
|
+
when Socket::SOCK_DGRAM
|
144
|
+
if @protocol != Socket::IPPROTO_UDP and @protocol != 0
|
145
|
+
raise SocketError, 'Socket protocol must be IPPROTO_UDP or left unset'
|
146
|
+
end
|
147
|
+
when Socket::SOCK_STREAM
|
148
|
+
if @protocol != Socket::IPPROTO_TCP and @protocol != 0
|
149
|
+
raise SocketError, 'Socket protocol must be IPPROTO_TCP or left unset'
|
150
|
+
end
|
151
|
+
# Based on MRI behaviour, though MRI itself doesn't seem to explicitly
|
152
|
+
# handle this case (possibly handled by getaddrinfo()).
|
153
|
+
when Socket::SOCK_SEQPACKET
|
154
|
+
if @protocol != 0
|
155
|
+
raise SocketError, 'SOCK_SEQPACKET can not be used with an explicit protocol'
|
156
|
+
end
|
157
|
+
else
|
158
|
+
raise SocketError, 'Unsupported socket type'
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def unix?
|
164
|
+
@afamily == Socket::AF_UNIX
|
165
|
+
end
|
166
|
+
|
167
|
+
def ipv4?
|
168
|
+
@afamily == Socket::AF_INET
|
169
|
+
end
|
170
|
+
|
171
|
+
def ipv6?
|
172
|
+
@afamily == Socket::AF_INET6
|
173
|
+
end
|
174
|
+
|
175
|
+
def ip?
|
176
|
+
ipv4? || ipv6?
|
177
|
+
end
|
178
|
+
|
179
|
+
def ip_address
|
180
|
+
unless ip?
|
181
|
+
raise SocketError, 'An IPv4/IPv6 address is required'
|
182
|
+
end
|
183
|
+
|
184
|
+
@ip_address
|
185
|
+
end
|
186
|
+
|
187
|
+
def ip_port
|
188
|
+
unless ip?
|
189
|
+
raise SocketError, 'An IPv4/IPv6 address is required'
|
190
|
+
end
|
191
|
+
|
192
|
+
@ip_port
|
193
|
+
end
|
194
|
+
|
195
|
+
def unix_path
|
196
|
+
unless unix?
|
197
|
+
raise SocketError, 'The address family must be AF_UNIX'
|
198
|
+
end
|
199
|
+
|
200
|
+
@unix_path
|
201
|
+
end
|
202
|
+
|
203
|
+
def to_sockaddr
|
204
|
+
if unix?
|
205
|
+
Socket.sockaddr_un(@unix_path)
|
206
|
+
else
|
207
|
+
Socket.sockaddr_in(@ip_port.to_i, @ip_address.to_s)
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
alias_method :to_s, :to_sockaddr
|
212
|
+
|
213
|
+
def getnameinfo(flags = 0)
|
214
|
+
Socket.getnameinfo(to_sockaddr, flags)
|
215
|
+
end
|
216
|
+
|
217
|
+
def inspect_sockaddr
|
218
|
+
if ipv4?
|
219
|
+
if ip_port and ip_port != 0
|
220
|
+
"#{ip_address}:#{ip_port}"
|
221
|
+
elsif ip_address
|
222
|
+
ip_address.dup
|
223
|
+
else
|
224
|
+
'UNKNOWN'
|
225
|
+
end
|
226
|
+
elsif ipv6?
|
227
|
+
if ip_port and ip_port != 0
|
228
|
+
"[#{ip_address}]:#{ip_port}"
|
229
|
+
else
|
230
|
+
ip_address.dup
|
231
|
+
end
|
232
|
+
elsif unix?
|
233
|
+
if unix_path.start_with?(File::SEPARATOR)
|
234
|
+
unix_path.dup
|
235
|
+
else
|
236
|
+
"UNIX #{unix_path}"
|
237
|
+
end
|
238
|
+
else
|
239
|
+
RubySL::Socket.address_family_name(afamily)
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
def inspect
|
244
|
+
if socktype and socktype != 0
|
245
|
+
if ip?
|
246
|
+
case socktype
|
247
|
+
when Socket::SOCK_STREAM
|
248
|
+
suffix = 'TCP'
|
249
|
+
when Socket::SOCK_DGRAM
|
250
|
+
suffix = 'UDP'
|
251
|
+
else
|
252
|
+
suffix = RubySL::Socket.socket_type_name(socktype)
|
253
|
+
end
|
254
|
+
else
|
255
|
+
suffix = RubySL::Socket.socket_type_name(socktype)
|
256
|
+
end
|
257
|
+
|
258
|
+
"#<Addrinfo: #{inspect_sockaddr} #{suffix}>"
|
259
|
+
else
|
260
|
+
"#<Addrinfo: #{inspect_sockaddr}>"
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
def ip_unpack
|
265
|
+
unless ip?
|
266
|
+
raise SocketError, 'An IPv4/IPv6 address is required'
|
267
|
+
end
|
268
|
+
|
269
|
+
[ip_address, ip_port]
|
270
|
+
end
|
271
|
+
|
272
|
+
def ipv4_loopback?
|
273
|
+
return false unless ipv4?
|
274
|
+
|
275
|
+
RubySL::Socket::Foreign.inet_network(ip_address) & 0xff000000 == 0x7f000000
|
276
|
+
end
|
277
|
+
|
278
|
+
def ipv4_multicast?
|
279
|
+
return false unless ipv4?
|
280
|
+
|
281
|
+
RubySL::Socket::Foreign.inet_network(ip_address) & 0xf0000000 == 0xe0000000
|
282
|
+
end
|
283
|
+
|
284
|
+
def ipv4_private?
|
285
|
+
return false unless ipv4?
|
286
|
+
|
287
|
+
num = RubySL::Socket::Foreign.inet_network(ip_address)
|
288
|
+
|
289
|
+
num & 0xff000000 == 0x0a000000 ||
|
290
|
+
num & 0xfff00000 == 0xac100000 ||
|
291
|
+
num & 0xffff0000 == 0xc0a80000
|
292
|
+
end
|
293
|
+
|
294
|
+
def ipv6_loopback?
|
295
|
+
return false unless ipv6?
|
296
|
+
|
297
|
+
RubySL::Socket::Foreign.ip_to_bytes(afamily, ip_address) ==
|
298
|
+
RubySL::Socket::IPv6::LOOPBACK
|
299
|
+
end
|
300
|
+
|
301
|
+
def ipv6_linklocal?
|
302
|
+
return false unless ipv6?
|
303
|
+
|
304
|
+
bytes = RubySL::Socket::Foreign.ip_to_bytes(afamily, ip_address)
|
305
|
+
|
306
|
+
bytes[0] == 0xfe && bytes[1] >= 0x80
|
307
|
+
end
|
308
|
+
|
309
|
+
def ipv6_multicast?
|
310
|
+
return false unless ipv6?
|
311
|
+
|
312
|
+
bytes = RubySL::Socket::Foreign.ip_to_bytes(afamily, ip_address)
|
313
|
+
|
314
|
+
bytes[0] == 0xff
|
315
|
+
end
|
316
|
+
|
317
|
+
def ipv6_sitelocal?
|
318
|
+
return false unless ipv6?
|
319
|
+
|
320
|
+
bytes = RubySL::Socket::Foreign.ip_to_bytes(afamily, ip_address)
|
321
|
+
|
322
|
+
bytes[0] == 0xfe && bytes[1] >= 0xe0
|
323
|
+
end
|
324
|
+
|
325
|
+
def ipv6_mc_global?
|
326
|
+
return false unless ipv6?
|
327
|
+
|
328
|
+
bytes = RubySL::Socket::Foreign.ip_to_bytes(afamily, ip_address)
|
329
|
+
|
330
|
+
bytes[0] == 0xff && bytes[1] & 0xf == 0xe
|
331
|
+
end
|
332
|
+
|
333
|
+
def ipv6_mc_linklocal?
|
334
|
+
return false unless ipv6?
|
335
|
+
|
336
|
+
bytes = RubySL::Socket::Foreign.ip_to_bytes(afamily, ip_address)
|
337
|
+
|
338
|
+
bytes[0] == 0xff && bytes[1] & 0xf == 0x2
|
339
|
+
end
|
340
|
+
|
341
|
+
def ipv6_mc_nodelocal?
|
342
|
+
return false unless ipv6?
|
343
|
+
|
344
|
+
bytes = RubySL::Socket::Foreign.ip_to_bytes(afamily, ip_address)
|
345
|
+
|
346
|
+
bytes[0] == 0xff && bytes[1] & 0xf == 0x1
|
347
|
+
end
|
348
|
+
|
349
|
+
def ipv6_mc_orglocal?
|
350
|
+
return false unless ipv6?
|
351
|
+
|
352
|
+
bytes = RubySL::Socket::Foreign.ip_to_bytes(afamily, ip_address)
|
353
|
+
|
354
|
+
bytes[0] == 0xff && bytes[1] & 0xf == 0x8
|
355
|
+
end
|
356
|
+
|
357
|
+
def ipv6_mc_sitelocal?
|
358
|
+
return false unless ipv6?
|
359
|
+
|
360
|
+
bytes = RubySL::Socket::Foreign.ip_to_bytes(afamily, ip_address)
|
361
|
+
|
362
|
+
bytes[0] == 0xff && bytes[1] & 0xf == 0x5
|
363
|
+
end
|
364
|
+
|
365
|
+
def ipv6_to_ipv4
|
366
|
+
return unless ipv6?
|
367
|
+
|
368
|
+
bytes = RubySL::Socket::Foreign.ip_to_bytes(afamily, ip_address)
|
369
|
+
|
370
|
+
if RubySL::Socket::IPv6.ipv4_embedded?(bytes)
|
371
|
+
Addrinfo.ip(bytes.last(4).join('.'))
|
372
|
+
else
|
373
|
+
nil
|
374
|
+
end
|
375
|
+
end
|
376
|
+
|
377
|
+
def ipv6_unspecified?
|
378
|
+
return false unless ipv6?
|
379
|
+
|
380
|
+
bytes = RubySL::Socket::Foreign.ip_to_bytes(afamily, ip_address)
|
381
|
+
|
382
|
+
bytes == RubySL::Socket::IPv6::UNSPECIFIED
|
383
|
+
end
|
384
|
+
|
385
|
+
def ipv6_v4compat?
|
386
|
+
return false unless ipv6?
|
387
|
+
|
388
|
+
bytes = RubySL::Socket::Foreign.ip_to_bytes(afamily, ip_address)
|
389
|
+
|
390
|
+
RubySL::Socket::IPv6.ipv4_compatible?(bytes)
|
391
|
+
end
|
392
|
+
|
393
|
+
def ipv6_v4mapped?
|
394
|
+
return false unless ipv6?
|
395
|
+
|
396
|
+
bytes = RubySL::Socket::Foreign.ip_to_bytes(afamily, ip_address)
|
397
|
+
|
398
|
+
RubySL::Socket::IPv6.ipv4_mapped?(bytes)
|
399
|
+
end
|
400
|
+
|
401
|
+
def ipv6_unique_local?
|
402
|
+
return false unless ipv6?
|
403
|
+
|
404
|
+
bytes = RubySL::Socket::Foreign.ip_to_bytes(afamily, ip_address)
|
405
|
+
|
406
|
+
bytes[0] == 0xfc || bytes[0] == 0xfd
|
407
|
+
end
|
408
|
+
|
409
|
+
def marshal_dump
|
410
|
+
if unix?
|
411
|
+
address = unix_path
|
412
|
+
else
|
413
|
+
address = [ip_address, ip_port.to_s]
|
414
|
+
end
|
415
|
+
|
416
|
+
if unix?
|
417
|
+
protocol = 0
|
418
|
+
else
|
419
|
+
protocol = RubySL::Socket.protocol_name(self.protocol)
|
420
|
+
end
|
421
|
+
|
422
|
+
[
|
423
|
+
RubySL::Socket.address_family_name(afamily),
|
424
|
+
address,
|
425
|
+
RubySL::Socket.protocol_family_name(pfamily),
|
426
|
+
RubySL::Socket.socket_type_name(socktype),
|
427
|
+
protocol,
|
428
|
+
canonname
|
429
|
+
]
|
430
|
+
end
|
431
|
+
|
432
|
+
def marshal_load(array)
|
433
|
+
afamily, address, pfamily, socktype, protocol, canonname = array
|
434
|
+
|
435
|
+
@afamily = RubySL::Socket.address_family(afamily)
|
436
|
+
@pfamily = RubySL::Socket.protocol_family(pfamily)
|
437
|
+
@socktype = RubySL::Socket.socket_type(socktype)
|
438
|
+
|
439
|
+
if protocol and protocol != 0
|
440
|
+
@protocol = ::Socket.const_get(protocol)
|
441
|
+
else
|
442
|
+
@protocol = protocol
|
443
|
+
end
|
444
|
+
|
445
|
+
if unix?
|
446
|
+
@unix_path = address
|
447
|
+
else
|
448
|
+
@ip_address = address[0]
|
449
|
+
@ip_port = address[1].to_i
|
450
|
+
@canonname = canonname
|
451
|
+
end
|
452
|
+
end
|
453
|
+
end
|