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,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