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