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,114 @@
1
+ class Socket < BasicSocket
2
+ class AncillaryData
3
+ attr_reader :family, :level, :type
4
+
5
+ def self.int(family, level, type, integer)
6
+ new(family, level, type, [integer].pack('I'))
7
+ end
8
+
9
+ def self.unix_rights(*ios)
10
+ descriptors = ios.map do |io|
11
+ unless io.is_a?(IO)
12
+ raise TypeError, "IO expected, got #{io.class} instead"
13
+ end
14
+
15
+ io.fileno
16
+ end
17
+
18
+ instance = new(:UNIX, :SOCKET, :RIGHTS, descriptors.pack('I*'))
19
+
20
+ # MRI sets this using a hidden instance variable ("unix_rights"). Because
21
+ # you can't set hidden instance variables from within Ruby we'll have to
22
+ # use a regular instance variable. Lets hope people don't mess with it.
23
+ instance.instance_variable_set(:@unix_rights, ios)
24
+
25
+ instance
26
+ end
27
+
28
+ def self.ip_pktinfo(addr, ifindex, spec_dst = nil)
29
+ spec_dst ||= addr
30
+
31
+ instance = new(:INET, :IP, :PKTINFO, '')
32
+ pkt_info = [
33
+ Addrinfo.ip(addr.ip_address),
34
+ ifindex,
35
+ Addrinfo.ip(spec_dst.ip_address)
36
+ ]
37
+
38
+ instance.instance_variable_set(:@ip_pktinfo, pkt_info)
39
+
40
+ instance
41
+ end
42
+
43
+ def self.ipv6_pktinfo(addr, ifindex)
44
+ instance = new(:INET6, :IPV6, :PKTINFO, '')
45
+ pkt_info = [Addrinfo.ip(addr.ip_address), ifindex]
46
+
47
+ instance.instance_variable_set(:@ipv6_pktinfo, pkt_info)
48
+
49
+ instance
50
+ end
51
+
52
+ def initialize(family, level, type, data)
53
+ @family = RubySL::Socket.address_family(family)
54
+ @data = RubySL::Socket.coerce_to_string(data)
55
+ @level = RubySL::Socket::AncillaryData.level(level)
56
+ @type = RubySL::Socket::AncillaryData.type(@family, @level, type)
57
+ end
58
+
59
+ def cmsg_is?(level, type)
60
+ level = RubySL::Socket::AncillaryData.level(level)
61
+ type = RubySL::Socket::AncillaryData.type(@family, level, type)
62
+
63
+ @level == level && @type == type
64
+ end
65
+
66
+ def int
67
+ unpacked = @data.unpack('I')[0]
68
+
69
+ unless unpacked
70
+ raise TypeError, 'data could not be unpacked into a Fixnum'
71
+ end
72
+
73
+ unpacked
74
+ end
75
+
76
+ def unix_rights
77
+ if @level != Socket::SOL_SOCKET or @type != Socket::SCM_RIGHTS
78
+ raise TypeError, 'SCM_RIGHTS ancillary data expected'
79
+ end
80
+
81
+ @unix_rights
82
+ end
83
+
84
+ def data
85
+ if @ip_pktinfo or @ipv6_pktinfo
86
+ raise NotImplementedError,
87
+ 'AncillaryData#data is not supported as its output depends on ' \
88
+ 'MRI specific internals, use #ip_pktinfo or #ipv6_pktinfo instead'
89
+ else
90
+ @data
91
+ end
92
+ end
93
+
94
+ def ip_pktinfo
95
+ addr, ifindex, spec = @ip_pktinfo
96
+
97
+ [addr.dup, ifindex, spec.dup]
98
+ end
99
+
100
+ def ipv6_pktinfo
101
+ addr, ifindex = @ipv6_pktinfo
102
+
103
+ [addr.dup, ifindex]
104
+ end
105
+
106
+ def ipv6_pktinfo_addr
107
+ ipv6_pktinfo[0]
108
+ end
109
+
110
+ def ipv6_pktinfo_ifindex
111
+ ipv6_pktinfo[1]
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,295 @@
1
+ class BasicSocket < IO
2
+ def self.for_fd(fixnum)
3
+ sock = allocate
4
+
5
+ IO.setup(sock, fixnum, nil, true)
6
+
7
+ sock
8
+ end
9
+
10
+ def self.do_not_reverse_lookup=(setting)
11
+ @no_reverse_lookup = setting
12
+ end
13
+
14
+ def self.do_not_reverse_lookup
15
+ @no_reverse_lookup = true unless defined?(@no_reverse_lookup)
16
+ @no_reverse_lookup
17
+ end
18
+
19
+ def do_not_reverse_lookup=(setting)
20
+ @no_reverse_lookup = setting
21
+ end
22
+
23
+ def do_not_reverse_lookup
24
+ @no_reverse_lookup
25
+ end
26
+
27
+ def getsockopt(level, optname)
28
+ sockname = RubySL::Socket::Foreign.getsockname(descriptor)
29
+ family = RubySL::Socket.family_for_sockaddr_in(sockname)
30
+ level = RubySL::Socket::SocketOptions.socket_level(level, family)
31
+ optname = RubySL::Socket::SocketOptions.socket_option(level, optname)
32
+ data = RubySL::Socket::Foreign.getsockopt(descriptor, level, optname)
33
+
34
+ Socket::Option.new(family, level, optname, data)
35
+ end
36
+
37
+ def setsockopt(level_or_option, optname = nil, optval = nil)
38
+ if level_or_option and optname and optval
39
+ if level_or_option.is_a?(Socket::Option)
40
+ raise TypeError,
41
+ 'expected the first argument to be a Fixnum, Symbol, or String'
42
+ end
43
+
44
+ level = level_or_option
45
+ elsif level_or_option.is_a?(Socket::Option)
46
+ raise(ArgumentError, 'given 2, expected 1') if optname
47
+
48
+ level = level_or_option.level
49
+ optname = level_or_option.optname
50
+ optval = level_or_option.data
51
+ else
52
+ raise TypeError,
53
+ 'expected the first argument to be a Fixnum, Symbol, String, or Socket::Option'
54
+ end
55
+
56
+ optval = 1 if optval == true
57
+ optval = 0 if optval == false
58
+
59
+ sockname = RubySL::Socket::Foreign.getsockname(descriptor)
60
+ family = RubySL::Socket.family_for_sockaddr_in(sockname)
61
+ level = RubySL::Socket::SocketOptions.socket_level(level, family)
62
+ optname = RubySL::Socket::SocketOptions.socket_option(level, optname)
63
+ error = 0
64
+
65
+ if optval.is_a?(Fixnum)
66
+ RubySL::Socket::Foreign.memory_pointer(:socklen_t) do |pointer|
67
+ pointer.write_int(optval)
68
+
69
+ error = RubySL::Socket::Foreign
70
+ .setsockopt(descriptor, level, optname, pointer, pointer.total)
71
+ end
72
+ elsif optval.is_a?(String)
73
+ RubySL::Socket::Foreign.memory_pointer(optval.bytesize) do |pointer|
74
+ pointer.write_string(optval)
75
+
76
+ error = RubySL::Socket::Foreign
77
+ .setsockopt(descriptor, level, optname, pointer, optval.bytesize)
78
+ end
79
+ else
80
+ raise TypeError, 'socket option should be a Fixnum, String, true, or false'
81
+ end
82
+
83
+ Errno.handle('unable to set socket option') if error < 0
84
+
85
+ 0
86
+ end
87
+
88
+ def getsockname
89
+ RubySL::Socket::Foreign.getsockname(descriptor)
90
+ end
91
+
92
+ def getpeername
93
+ RubySL::Socket::Foreign.getpeername(descriptor)
94
+ end
95
+
96
+ def send(message, flags, dest_sockaddr = nil)
97
+ bytes = message.bytesize
98
+ bytes_sent = 0
99
+
100
+ if dest_sockaddr.is_a?(Addrinfo)
101
+ dest_sockaddr = dest_sockaddr.to_sockaddr
102
+ end
103
+
104
+ RubySL::Socket::Foreign.char_pointer(bytes) do |buffer|
105
+ buffer.write_string(message)
106
+
107
+ if dest_sockaddr.is_a?(String)
108
+ addr = RubySL::Socket.sockaddr_class_for_socket(self)
109
+ .with_sockaddr(dest_sockaddr)
110
+
111
+ begin
112
+ bytes_sent = RubySL::Socket::Foreign
113
+ .sendto(descriptor, buffer, bytes, flags, addr, addr.size)
114
+ ensure
115
+ addr.free
116
+ end
117
+ else
118
+ bytes_sent = RubySL::Socket::Foreign
119
+ .send(descriptor, buffer, bytes, flags)
120
+ end
121
+ end
122
+
123
+ RubySL::Socket::Error.write_error('send(2)', self) if bytes_sent < 0
124
+
125
+ bytes_sent
126
+ end
127
+
128
+ def recv(bytes_to_read, flags = 0)
129
+ return socket_recv(bytes_to_read, flags, 0)
130
+ end
131
+
132
+ def recvmsg(max_msg_len = nil, flags = 0, *_)
133
+ socket_type = getsockopt(:SOCKET, :TYPE).int
134
+
135
+ if socket_type == Socket::SOCK_STREAM
136
+ grow_msg = false
137
+ else
138
+ grow_msg = max_msg_len.nil?
139
+ end
140
+
141
+ flags |= Socket::MSG_PEEK if grow_msg
142
+
143
+ msg_len = max_msg_len || 4096
144
+
145
+ loop do
146
+ msg_buffer = RubySL::Socket::Foreign.char_pointer(msg_len)
147
+ address = RubySL::Socket.sockaddr_class_for_socket(self).new
148
+ io_vec = RubySL::Socket::Foreign::Iovec.with_buffer(msg_buffer)
149
+ header = RubySL::Socket::Foreign::Msghdr.with_buffers(address, io_vec)
150
+
151
+ begin
152
+ need_more = false
153
+
154
+ msg_size = RubySL::Socket::Foreign
155
+ .recvmsg(descriptor, header.pointer, flags)
156
+
157
+ RubySL::Socket::Error.read_error('recvmsg(2)', self) if msg_size < 0
158
+
159
+ if grow_msg and header.message_truncated?
160
+ need_more = true
161
+ msg_len *= 2
162
+ end
163
+
164
+ next if need_more
165
+
166
+ # When a socket is actually connected the address structure is not used.
167
+ if header.address_size > 0
168
+ addr = Addrinfo.new(address.to_s, address.family, socket_type)
169
+ else
170
+ addr = Addrinfo.new([Socket::AF_UNSPEC], nil, socket_type)
171
+ end
172
+
173
+ return msg_buffer.read_string(msg_size), addr, header.flags
174
+ ensure
175
+ msg_buffer.free
176
+ address.free
177
+ io_vec.free
178
+ header.free
179
+ end
180
+ end
181
+
182
+ nil
183
+ end
184
+
185
+ def recvmsg_nonblock(max_msg_len = nil, flags = 0, *_)
186
+ fcntl(Fcntl::F_SETFL, Fcntl::O_NONBLOCK)
187
+
188
+ recvmsg(max_msg_len, flags | Socket::MSG_DONTWAIT)
189
+ end
190
+
191
+ def sendmsg(message, flags = 0, dest_sockaddr = nil, *_)
192
+ msg_buffer = RubySL::Socket::Foreign.char_pointer(message.bytesize)
193
+ io_vec = RubySL::Socket::Foreign::Iovec.with_buffer(msg_buffer)
194
+ header = RubySL::Socket::Foreign::Msghdr.new
195
+ address = nil
196
+
197
+ begin
198
+ msg_buffer.write_string(message)
199
+
200
+ header.message = io_vec
201
+
202
+ if dest_sockaddr.is_a?(Addrinfo)
203
+ dest_sockaddr = dest_sockaddr.to_sockaddr
204
+ end
205
+
206
+ if dest_sockaddr.is_a?(String)
207
+ address = RubySL::Socket::Foreign::SockaddrIn
208
+ .with_sockaddr(dest_sockaddr)
209
+
210
+ header.address = address
211
+ end
212
+
213
+ num_bytes = RubySL::Socket::Foreign
214
+ .sendmsg(descriptor, header.pointer, flags)
215
+
216
+ RubySL::Socket::Error.read_error('sendmsg(2)', self) if num_bytes < 0
217
+
218
+ num_bytes
219
+ ensure
220
+ address.free if address
221
+ header.free
222
+ io_vec.free
223
+ msg_buffer.free
224
+ end
225
+ end
226
+
227
+ def sendmsg_nonblock(message, flags = 0, dest_sockaddr = nil, *_)
228
+ fcntl(Fcntl::F_SETFL, Fcntl::O_NONBLOCK)
229
+
230
+ sendmsg(message, flags | Socket::MSG_DONTWAIT, dest_sockaddr)
231
+ end
232
+
233
+ def close_read
234
+ ensure_open
235
+
236
+ if @mode & ACCMODE == RDONLY
237
+ return close
238
+ end
239
+
240
+ RubySL::Socket::Foreign.shutdown(descriptor, 0)
241
+
242
+ @mode = WRONLY
243
+
244
+ nil
245
+ end
246
+
247
+ def close_write
248
+ ensure_open
249
+
250
+ if @mode & ACCMODE == WRONLY
251
+ return close
252
+ end
253
+
254
+ RubySL::Socket::Foreign.shutdown(descriptor, 1)
255
+
256
+ @mode = RDONLY
257
+
258
+ nil
259
+ end
260
+
261
+ def recv_nonblock(bytes_to_read, flags = 0)
262
+ fcntl(Fcntl::F_SETFL, Fcntl::O_NONBLOCK)
263
+
264
+ RubySL::Socket::Error.wrap_read_nonblock do
265
+ socket_recv(bytes_to_read, flags, 0)
266
+ end
267
+ end
268
+
269
+ def shutdown(how = Socket::SHUT_RDWR)
270
+ how = RubySL::Socket.shutdown_option(how)
271
+ err = RubySL::Socket::Foreign.shutdown(descriptor, how)
272
+
273
+ Errno.handle('shutdown(2)') unless err == 0
274
+
275
+ 0
276
+ end
277
+
278
+ # MRI defines this method in BasicSocket and stuffs all logic in it. Since
279
+ # inheriting classes behave differently we overwrite this method in said
280
+ # classes. The method here exists so that code such as the following still
281
+ # works: BasicSocket.method_defined?(:local_address).
282
+ def local_address
283
+ raise NotImplementedError,
284
+ 'This method must be implemented by classes inheriting from BasicSocket'
285
+ end
286
+
287
+ def remote_address
288
+ raise NotImplementedError,
289
+ 'This method must be implemented by classes inheriting from BasicSocket'
290
+ end
291
+
292
+ def getpeereid
293
+ RubySL::Socket::Foreign.getpeereid(descriptor)
294
+ end
295
+ end
@@ -0,0 +1,41 @@
1
+ class Socket < BasicSocket
2
+ module Constants
3
+ all_valid = RubySL::Socket.constant_pairs
4
+
5
+ all_valid.each {|name, value| const_set name, Integer(value) }
6
+
7
+ # MRI compat. socket is a pretty screwed up API. All the constants in Constants
8
+ # must also be directly accessible on Socket itself. This means it's not enough
9
+ # to include Constants into Socket, because Socket#const_defined? must be able
10
+ # to see constants like AF_INET6 directly on Socket, but #const_defined? doesn't
11
+ # check inherited constants. O_o
12
+ #
13
+ all_valid.each {|name, value| Socket.const_set name, Integer(value) }
14
+
15
+
16
+ afamilies = all_valid.to_a.select { |name,| name =~ /^AF_/ }
17
+ afamilies.map! {|name, value| [value.to_i, name] }
18
+
19
+ pfamilies = all_valid.to_a.select { |name,| name =~ /^PF_/ }
20
+ pfamilies.map! {|name, value| [value.to_i, name] }
21
+
22
+ AF_TO_FAMILY = Hash[*afamilies.flatten]
23
+ PF_TO_FAMILY = Hash[*pfamilies.flatten]
24
+
25
+ # MRI defines these constants manually, thus our FFI generators don't pick
26
+ # them up.
27
+ EAI_ADDRFAMILY = 1
28
+ EAI_NODATA = 7
29
+ IPPORT_USERRESERVED = 5000
30
+
31
+ # This constant is hidden behind a #ifdef __GNU on Linux, meaning it won't
32
+ # be available when using clang.
33
+ unless const_defined?(:SCM_CREDENTIALS)
34
+ SCM_CREDENTIALS = 2
35
+ end
36
+ end
37
+
38
+ [:EAI_ADDRFAMILY, :EAI_NODATA, :IPPORT_USERRESERVED, :SCM_CREDENTIALS].each do |const|
39
+ const_set(const, Constants.const_get(const))
40
+ end
41
+ end