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.
Files changed (181) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +70 -16
  3. data/lib/rubysl/socket.rb +201 -1396
  4. data/lib/rubysl/socket/ancillary_data.rb +56 -0
  5. data/lib/rubysl/socket/bsd.rb +28 -0
  6. data/lib/rubysl/socket/error.rb +67 -0
  7. data/lib/rubysl/socket/foreign.rb +324 -0
  8. data/lib/rubysl/socket/foreign/addrinfo.rb +10 -0
  9. data/lib/rubysl/socket/foreign/hostent.rb +36 -0
  10. data/lib/rubysl/socket/foreign/ifaddrs.rb +129 -0
  11. data/lib/rubysl/socket/foreign/iovec.rb +18 -0
  12. data/lib/rubysl/socket/foreign/linger.rb +41 -0
  13. data/lib/rubysl/socket/foreign/msghdr.rb +41 -0
  14. data/lib/rubysl/socket/foreign/servent.rb +17 -0
  15. data/lib/rubysl/socket/foreign/sockaddr.rb +21 -0
  16. data/lib/rubysl/socket/foreign/sockaddr_in.rb +25 -0
  17. data/lib/rubysl/socket/foreign/sockaddr_in6.rb +25 -0
  18. data/lib/rubysl/socket/foreign/sockaddr_un.rb +29 -0
  19. data/lib/rubysl/socket/ipv6.rb +38 -0
  20. data/lib/rubysl/socket/linux.rb +16 -0
  21. data/lib/rubysl/socket/socket_options.rb +84 -0
  22. data/lib/rubysl/socket/version.rb +1 -1
  23. data/lib/socket.rb +45 -1
  24. data/lib/socket/addrinfo.rb +453 -0
  25. data/lib/socket/ancillary_data.rb +114 -0
  26. data/lib/socket/basic_socket.rb +295 -0
  27. data/lib/socket/constants.rb +41 -0
  28. data/lib/socket/ifaddr.rb +29 -0
  29. data/lib/socket/ip_socket.rb +37 -0
  30. data/lib/socket/mri.rb +928 -0
  31. data/lib/socket/option.rb +96 -0
  32. data/lib/socket/socket.rb +353 -0
  33. data/lib/socket/socket_error.rb +2 -0
  34. data/lib/socket/tcp_server.rb +78 -0
  35. data/lib/socket/tcp_socket.rb +109 -0
  36. data/lib/socket/udp_socket.rb +73 -0
  37. data/lib/socket/unix_server.rb +35 -0
  38. data/lib/socket/unix_socket.rb +78 -0
  39. data/rubysl-socket.gemspec +15 -10
  40. metadata +78 -293
  41. data/.gitignore +0 -17
  42. data/.travis.yml +0 -9
  43. data/Gemfile +0 -4
  44. data/Rakefile +0 -1
  45. data/spec/addrinfo/afamily_spec.rb +0 -5
  46. data/spec/addrinfo/bind_spec.rb +0 -5
  47. data/spec/addrinfo/canonname_spec.rb +0 -5
  48. data/spec/addrinfo/connect_from_spec.rb +0 -5
  49. data/spec/addrinfo/connect_spec.rb +0 -5
  50. data/spec/addrinfo/connect_to_spec.rb +0 -5
  51. data/spec/addrinfo/family_addrinfo_spec.rb +0 -5
  52. data/spec/addrinfo/foreach_spec.rb +0 -5
  53. data/spec/addrinfo/getaddrinfo_spec.rb +0 -5
  54. data/spec/addrinfo/getnameinfo_spec.rb +0 -5
  55. data/spec/addrinfo/inspect_sockaddr_spec.rb +0 -5
  56. data/spec/addrinfo/inspect_spec.rb +0 -5
  57. data/spec/addrinfo/ip_address_spec.rb +0 -5
  58. data/spec/addrinfo/ip_port_spec.rb +0 -5
  59. data/spec/addrinfo/ip_spec.rb +0 -9
  60. data/spec/addrinfo/ip_unpack_spec.rb +0 -5
  61. data/spec/addrinfo/ipv4_loopback_spec.rb +0 -5
  62. data/spec/addrinfo/ipv4_multicast_spec.rb +0 -5
  63. data/spec/addrinfo/ipv4_private_spec.rb +0 -5
  64. data/spec/addrinfo/ipv4_spec.rb +0 -5
  65. data/spec/addrinfo/ipv6_linklocal_spec.rb +0 -5
  66. data/spec/addrinfo/ipv6_loopback_spec.rb +0 -5
  67. data/spec/addrinfo/ipv6_mc_global_spec.rb +0 -5
  68. data/spec/addrinfo/ipv6_mc_linklocal_spec.rb +0 -5
  69. data/spec/addrinfo/ipv6_mc_nodelocal_spec.rb +0 -5
  70. data/spec/addrinfo/ipv6_mc_orglocal_spec.rb +0 -5
  71. data/spec/addrinfo/ipv6_mc_sitelocal_spec.rb +0 -5
  72. data/spec/addrinfo/ipv6_multicast_spec.rb +0 -5
  73. data/spec/addrinfo/ipv6_sitelocal_spec.rb +0 -5
  74. data/spec/addrinfo/ipv6_spec.rb +0 -5
  75. data/spec/addrinfo/ipv6_to_ipv4_spec.rb +0 -5
  76. data/spec/addrinfo/ipv6_unspecified_spec.rb +0 -5
  77. data/spec/addrinfo/ipv6_v4compat_spec.rb +0 -5
  78. data/spec/addrinfo/ipv6_v4mapped_spec.rb +0 -5
  79. data/spec/addrinfo/listen_spec.rb +0 -5
  80. data/spec/addrinfo/marshal_dump_spec.rb +0 -5
  81. data/spec/addrinfo/marshal_load_spec.rb +0 -5
  82. data/spec/addrinfo/pfamily_spec.rb +0 -5
  83. data/spec/addrinfo/protocol_spec.rb +0 -5
  84. data/spec/addrinfo/socktype_spec.rb +0 -5
  85. data/spec/addrinfo/tcp_spec.rb +0 -5
  86. data/spec/addrinfo/to_s_spec.rb +0 -5
  87. data/spec/addrinfo/to_sockaddr_spec.rb +0 -5
  88. data/spec/addrinfo/udp_spec.rb +0 -5
  89. data/spec/addrinfo/unix_path_spec.rb +0 -5
  90. data/spec/addrinfo/unix_spec.rb +0 -9
  91. data/spec/basicsocket/close_read_spec.rb +0 -42
  92. data/spec/basicsocket/close_write_spec.rb +0 -42
  93. data/spec/basicsocket/do_not_reverse_lookup_spec.rb +0 -78
  94. data/spec/basicsocket/for_fd_spec.rb +0 -37
  95. data/spec/basicsocket/getpeername_spec.rb +0 -24
  96. data/spec/basicsocket/getsockname_spec.rb +0 -27
  97. data/spec/basicsocket/getsockopt_spec.rb +0 -54
  98. data/spec/basicsocket/ioctl_spec.rb +0 -22
  99. data/spec/basicsocket/recv_nonblock_spec.rb +0 -6
  100. data/spec/basicsocket/recv_spec.rb +0 -76
  101. data/spec/basicsocket/send_spec.rb +0 -81
  102. data/spec/basicsocket/setsockopt_spec.rb +0 -333
  103. data/spec/basicsocket/shutdown_spec.rb +0 -5
  104. data/spec/constants/constants_spec.rb +0 -63
  105. data/spec/fixtures/classes.rb +0 -174
  106. data/spec/fixtures/send_io.txt +0 -1
  107. data/spec/ipsocket/addr_spec.rb +0 -72
  108. data/spec/ipsocket/getaddress_spec.rb +0 -26
  109. data/spec/ipsocket/peeraddr_spec.rb +0 -79
  110. data/spec/ipsocket/recvfrom_spec.rb +0 -64
  111. data/spec/option/int_spec.rb +0 -27
  112. data/spec/option/linger_spec.rb +0 -52
  113. data/spec/option/new_spec.rb +0 -32
  114. data/spec/shared/pack_sockaddr.rb +0 -26
  115. data/spec/shared/partially_closable_sockets.rb +0 -13
  116. data/spec/shared/recv_nonblock.rb +0 -33
  117. data/spec/shared/socketpair.rb +0 -35
  118. data/spec/socket/accept_nonblock_spec.rb +0 -27
  119. data/spec/socket/accept_spec.rb +0 -1
  120. data/spec/socket/bind_spec.rb +0 -80
  121. data/spec/socket/connect_nonblock_spec.rb +0 -62
  122. data/spec/socket/connect_spec.rb +0 -1
  123. data/spec/socket/for_fd_spec.rb +0 -29
  124. data/spec/socket/getaddrinfo_spec.rb +0 -120
  125. data/spec/socket/gethostbyaddr_spec.rb +0 -1
  126. data/spec/socket/gethostbyname_spec.rb +0 -26
  127. data/spec/socket/gethostname_spec.rb +0 -9
  128. data/spec/socket/getnameinfo_spec.rb +0 -57
  129. data/spec/socket/getservbyname_spec.rb +0 -24
  130. data/spec/socket/listen_spec.rb +0 -21
  131. data/spec/socket/new_spec.rb +0 -109
  132. data/spec/socket/pack_sockaddr_in_spec.rb +0 -6
  133. data/spec/socket/pack_sockaddr_un_spec.rb +0 -6
  134. data/spec/socket/pair_spec.rb +0 -6
  135. data/spec/socket/recvfrom_nonblock_spec.rb +0 -1
  136. data/spec/socket/recvfrom_spec.rb +0 -1
  137. data/spec/socket/sockaddr_in_spec.rb +0 -6
  138. data/spec/socket/sockaddr_un_spec.rb +0 -6
  139. data/spec/socket/socket_spec.rb +0 -37
  140. data/spec/socket/socketpair_spec.rb +0 -6
  141. data/spec/socket/sysaccept_spec.rb +0 -1
  142. data/spec/socket/unpack_sockaddr_in_spec.rb +0 -16
  143. data/spec/socket/unpack_sockaddr_un_spec.rb +0 -2
  144. data/spec/tcpserver/accept_nonblock_spec.rb +0 -30
  145. data/spec/tcpserver/accept_spec.rb +0 -60
  146. data/spec/tcpserver/gets_spec.rb +0 -17
  147. data/spec/tcpserver/listen_spec.rb +0 -1
  148. data/spec/tcpserver/new_spec.rb +0 -88
  149. data/spec/tcpserver/output_spec.rb +0 -8
  150. data/spec/tcpserver/readpartial_spec.rb +0 -8
  151. data/spec/tcpserver/sysaccept_spec.rb +0 -1
  152. data/spec/tcpsocket/gethostbyname_spec.rb +0 -62
  153. data/spec/tcpsocket/new_spec.rb +0 -5
  154. data/spec/tcpsocket/open_spec.rb +0 -5
  155. data/spec/tcpsocket/partially_closable_spec.rb +0 -20
  156. data/spec/tcpsocket/recv_nonblock_spec.rb +0 -31
  157. data/spec/tcpsocket/setsockopt_spec.rb +0 -49
  158. data/spec/tcpsocket/shared/new.rb +0 -85
  159. data/spec/udpsocket/bind_spec.rb +0 -33
  160. data/spec/udpsocket/connect_spec.rb +0 -1
  161. data/spec/udpsocket/new_spec.rb +0 -1
  162. data/spec/udpsocket/open_spec.rb +0 -12
  163. data/spec/udpsocket/recvfrom_nonblock_spec.rb +0 -1
  164. data/spec/udpsocket/send_spec.rb +0 -57
  165. data/spec/unixserver/accept_nonblock_spec.rb +0 -33
  166. data/spec/unixserver/accept_spec.rb +0 -64
  167. data/spec/unixserver/for_fd_spec.rb +0 -32
  168. data/spec/unixserver/new_spec.rb +0 -5
  169. data/spec/unixserver/open_spec.rb +0 -25
  170. data/spec/unixserver/shared/new.rb +0 -23
  171. data/spec/unixsocket/addr_spec.rb +0 -37
  172. data/spec/unixsocket/new_spec.rb +0 -5
  173. data/spec/unixsocket/open_spec.rb +0 -26
  174. data/spec/unixsocket/pair_spec.rb +0 -38
  175. data/spec/unixsocket/partially_closable_spec.rb +0 -25
  176. data/spec/unixsocket/path_spec.rb +0 -29
  177. data/spec/unixsocket/peeraddr_spec.rb +0 -29
  178. data/spec/unixsocket/recv_io_spec.rb +0 -40
  179. data/spec/unixsocket/recvfrom_spec.rb +0 -48
  180. data/spec/unixsocket/send_io_spec.rb +0 -30
  181. 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
@@ -1,5 +1,5 @@
1
1
  module RubySL
2
2
  module Socket
3
- VERSION = "2.0.1"
3
+ VERSION = "2.1.0"
4
4
  end
5
5
  end
@@ -1 +1,45 @@
1
- require "rubysl/socket"
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