rubysl-socket 1.0.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,5 @@
1
1
  module RubySL
2
2
  module Socket
3
- VERSION = "1.0.1"
3
+ VERSION = "2.0.0"
4
4
  end
5
5
  end
@@ -16,10 +16,9 @@ Gem::Specification.new do |spec|
16
16
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
17
17
  spec.require_paths = ["lib"]
18
18
 
19
- spec.required_ruby_version = "~> 1.8.7"
19
+ spec.required_ruby_version = "~> 2.0"
20
20
 
21
21
  spec.add_development_dependency "bundler", "~> 1.3"
22
22
  spec.add_development_dependency "rake", "~> 10.0"
23
23
  spec.add_development_dependency "mspec", "~> 1.5"
24
- spec.add_development_dependency "rubysl-prettyprint", "~> 1.0"
25
24
  end
@@ -1 +1,2 @@
1
+ require File.expand_path('../../../../spec_helper', __FILE__)
1
2
  require File.expand_path('../../fixtures/classes', __FILE__)
metadata CHANGED
@@ -1,71 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubysl-socket
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Shirai
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-06-17 00:00:00.000000000 Z
11
+ date: 2013-08-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ~>
18
18
  - !ruby/object:Gem::Version
19
19
  version: '1.3'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ~>
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.3'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ~>
32
32
  - !ruby/object:Gem::Version
33
33
  version: '10.0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ~>
39
39
  - !ruby/object:Gem::Version
40
40
  version: '10.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: mspec
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - "~>"
45
+ - - ~>
46
46
  - !ruby/object:Gem::Version
47
47
  version: '1.5'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - "~>"
52
+ - - ~>
53
53
  - !ruby/object:Gem::Version
54
54
  version: '1.5'
55
- - !ruby/object:Gem::Dependency
56
- name: rubysl-prettyprint
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: '1.0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: '1.0'
69
55
  description: Ruby standard library socket.
70
56
  email:
71
57
  - brixen@gmail.com
@@ -73,14 +59,13 @@ executables: []
73
59
  extensions: []
74
60
  extra_rdoc_files: []
75
61
  files:
76
- - ".gitignore"
77
- - ".travis.yml"
62
+ - .gitignore
63
+ - .travis.yml
78
64
  - Gemfile
79
65
  - LICENSE
80
66
  - README.md
81
67
  - Rakefile
82
68
  - lib/rubysl/socket.rb
83
- - lib/rubysl/socket/socket.rb
84
69
  - lib/rubysl/socket/version.rb
85
70
  - lib/socket.rb
86
71
  - rubysl-socket.gemspec
@@ -231,17 +216,17 @@ require_paths:
231
216
  - lib
232
217
  required_ruby_version: !ruby/object:Gem::Requirement
233
218
  requirements:
234
- - - "~>"
219
+ - - ~>
235
220
  - !ruby/object:Gem::Version
236
- version: 1.8.7
221
+ version: '2.0'
237
222
  required_rubygems_version: !ruby/object:Gem::Requirement
238
223
  requirements:
239
- - - ">="
224
+ - - '>='
240
225
  - !ruby/object:Gem::Version
241
226
  version: '0'
242
227
  requirements: []
243
228
  rubyforge_project:
244
- rubygems_version: 2.2.2
229
+ rubygems_version: 2.0.7
245
230
  signing_key:
246
231
  specification_version: 4
247
232
  summary: Ruby standard library socket.
@@ -1,1210 +0,0 @@
1
- require 'fcntl'
2
-
3
- class SocketError < StandardError
4
- end
5
-
6
- # @todo Socket#accept[_nonblock]
7
- # @todo UNIXServer#accept[_nonblock]
8
- # @todo UDPSocket#recvfrom
9
-
10
- class BasicSocket < IO
11
- FFI = Rubinius::FFI
12
-
13
- class << self
14
- def from_descriptor(fixnum)
15
- sock = allocate()
16
- sock.from_descriptor(fixnum)
17
- return sock
18
- end
19
-
20
- alias :for_fd :from_descriptor
21
- end
22
-
23
- def from_descriptor(fixnum)
24
- IO.setup self, fixnum, nil, true
25
- return self
26
- end
27
-
28
- def self.do_not_reverse_lookup=(setting)
29
- @no_reverse_lookup = setting
30
- end
31
-
32
- def self.do_not_reverse_lookup
33
- @no_reverse_lookup ? true : false
34
- end
35
-
36
- def getsockopt(level, optname)
37
- Socket::Foreign.getsockopt descriptor, level, optname
38
- end
39
-
40
- def setsockopt(level, optname, optval)
41
- optval = 1 if optval == true
42
- optval = 0 if optval == false
43
-
44
- error = 0
45
-
46
- case optval
47
- when Fixnum then
48
- FFI::MemoryPointer.new :socklen_t do |val|
49
- val.write_int optval
50
- error = Socket::Foreign.setsockopt(descriptor, level,
51
- optname, val,
52
- val.total)
53
- end
54
- when String then
55
- FFI::MemoryPointer.new optval.size do |val|
56
- val.write_string optval
57
- error = Socket::Foreign.setsockopt(descriptor, level,
58
- optname, val,
59
- optval.size)
60
- end
61
- else
62
- raise TypeError, "socket option should be a String, a Fixnum, true, or false"
63
- end
64
-
65
- Errno.handle "Unable to set socket option" unless error == 0
66
-
67
- return 0
68
- end
69
-
70
- def getsockname()
71
- return Socket::Foreign.getsockname(descriptor)
72
- end
73
-
74
- #
75
- # Obtain peername information for this socket.
76
- #
77
- # @see Socket.getpeername
78
- #
79
- def getpeername()
80
- Socket::Foreign.getpeername @descriptor
81
- end
82
-
83
- #
84
- #
85
- #
86
- def send(message, flags, to = nil)
87
- connect to if to
88
-
89
- bytes = message.length
90
- bytes_sent = 0
91
-
92
- FFI::MemoryPointer.new :char, bytes + 1 do |buffer|
93
- buffer.write_string message
94
- bytes_sent = Socket::Foreign.send(descriptor, buffer, bytes, flags)
95
- Errno.handle 'send(2)' if bytes_sent < 0
96
- end
97
-
98
- bytes_sent
99
- end
100
-
101
- def recvfrom(bytes_to_read, flags = 0)
102
- # FIXME 0 is knowledge from io.cpp
103
- return socket_recv(bytes_to_read, flags, 0)
104
- end
105
-
106
- def recv(bytes_to_read, flags = 0)
107
- # FIXME 0 is knowledge from io.cpp
108
- return socket_recv(bytes_to_read, flags, 0)
109
- end
110
-
111
- def close_read
112
- ensure_open
113
-
114
- # If we were only in readonly mode, close it all together
115
- if @mode & ACCMODE == RDONLY
116
- return close
117
- end
118
-
119
- # MRI doesn't check if shutdown worked, so we don't.
120
- Socket::Foreign.shutdown @descriptor, 0
121
-
122
- @mode = WRONLY
123
-
124
- nil
125
- end
126
-
127
- def close_write
128
- ensure_open
129
-
130
- # If we were only in writeonly mode, close it all together
131
- if @mode & ACCMODE == WRONLY
132
- return close
133
- end
134
-
135
- Socket::Foreign.shutdown @descriptor, 1
136
-
137
- # Mark it as read only
138
- @mode = RDONLY
139
-
140
- nil
141
- end
142
-
143
- #
144
- # Sets socket nonblocking and reads up to given number of bytes.
145
- #
146
- # @todo Should EWOULDBLOCK be passed unchanged? --rue
147
- #
148
- def recv_nonblock(bytes_to_read, flags = 0)
149
- fcntl Fcntl::F_SETFL, Fcntl::O_NONBLOCK
150
- socket_recv bytes_to_read, flags, 0
151
- rescue Errno::EWOULDBLOCK
152
- raise Errno::EAGAIN
153
- end
154
-
155
- def shutdown(how = 2)
156
- err = Socket::Foreign.shutdown @descriptor, how
157
- Errno.handle "shutdown" unless err == 0
158
- end
159
-
160
- end
161
-
162
- class Socket < BasicSocket
163
- FFI = Rubinius::FFI
164
-
165
- # @todo Is omitting empty-value constants reasonable? --rue
166
- module Constants
167
- all_valid = FFI.config_hash("socket").reject {|name, value| value.empty? }
168
-
169
- all_valid.each {|name, value| const_set name, Integer(value) }
170
-
171
- # MRI compat. socket is a pretty screwed up API. All the constants in Constants
172
- # must also be directly accessible on Socket itself. This means it's not enough
173
- # to include Constants into Socket, because Socket#const_defined? must be able
174
- # to see constants like AF_INET6 directly on Socket, but #const_defined? doesn't
175
- # check inherited constants. O_o
176
- #
177
- all_valid.each {|name, value| Socket.const_set name, Integer(value) }
178
-
179
-
180
- afamilies = all_valid.to_a.select { |name,| name =~ /^AF_/ }
181
- afamilies.map! {|name, value| [value.to_i, name] }
182
-
183
- pfamilies = all_valid.to_a.select { |name,| name =~ /^PF_/ }
184
- pfamilies.map! {|name, value| [value.to_i, name] }
185
-
186
- AF_TO_FAMILY = Hash[*afamilies.flatten]
187
- PF_TO_FAMILY = Hash[*pfamilies.flatten]
188
- end
189
-
190
- module Foreign
191
- extend FFI::Library
192
-
193
- class Addrinfo < FFI::Struct
194
- config("rbx.platform.addrinfo", :ai_flags, :ai_family, :ai_socktype,
195
- :ai_protocol, :ai_addrlen, :ai_addr, :ai_canonname, :ai_next)
196
- end
197
-
198
- attach_function :_bind, "bind", [:int, :pointer, :socklen_t], :int
199
- attach_function :_connect, "connect", [:int, :pointer, :socklen_t], :int
200
-
201
- attach_function :accept, [:int, :pointer, :pointer], :int
202
- attach_function :close, [:int], :int
203
- attach_function :shutdown, [:int, :int], :int
204
- attach_function :listen, [:int, :int], :int
205
- attach_function :socket, [:int, :int, :int], :int
206
- attach_function :send, [:int, :pointer, :size_t, :int], :int
207
- attach_function :recv, [:int, :pointer, :size_t, :int], :int
208
- attach_function :recvfrom, [:int, :pointer, :size_t, :int,
209
- :pointer, :pointer], :int
210
-
211
- attach_function :_getsockopt,
212
- "getsockopt", [:int, :int, :int, :pointer, :pointer], :int
213
- attach_function :_getaddrinfo,
214
- "getaddrinfo", [:string, :string, :pointer, :pointer], :int
215
-
216
- attach_function :gai_strerror, [:int], :string
217
- attach_function :setsockopt, [:int, :int, :int, :pointer, :socklen_t], :int
218
- attach_function :freeaddrinfo, [:pointer], :void
219
- attach_function :_getpeername, "getpeername", [:int, :pointer, :pointer], :int
220
- attach_function :_getsockname, "getsockname", [:int, :pointer, :pointer], :int
221
-
222
- attach_function :socketpair, [:int, :int, :int, :pointer], :int
223
-
224
- attach_function :gethostname, [:pointer, :size_t], :int
225
- attach_function :getservbyname, [:pointer, :pointer], :pointer
226
-
227
- attach_function :htons, [:uint16_t], :uint16_t
228
- attach_function :ntohs, [:uint16_t], :uint16_t
229
-
230
- attach_function :_getnameinfo,
231
- "getnameinfo", [:pointer, :socklen_t, :pointer, :socklen_t,
232
- :pointer, :socklen_t, :int], :int
233
-
234
- def self.bind(descriptor, sockaddr)
235
- FFI::MemoryPointer.new :char, sockaddr.length do |sockaddr_p|
236
- sockaddr_p.write_string sockaddr, sockaddr.length
237
-
238
- _bind descriptor, sockaddr_p, sockaddr.length
239
- end
240
- end
241
-
242
- def self.connect(descriptor, sockaddr)
243
- err = 0
244
- FFI::MemoryPointer.new :char, sockaddr.length do |sockaddr_p|
245
- sockaddr_p.write_string sockaddr, sockaddr.length
246
-
247
- err = _connect descriptor, sockaddr_p, sockaddr.length
248
- end
249
-
250
- err
251
- end
252
-
253
- def self.getsockopt(descriptor, level, optname)
254
- FFI::MemoryPointer.new 256 do |val| # HACK magic number
255
- FFI::MemoryPointer.new :socklen_t do |length|
256
- length.write_int 256 # HACK magic number
257
-
258
- err = _getsockopt descriptor, level, optname, val, length
259
-
260
- Errno.handle "Unable to get socket option" unless err == 0
261
-
262
- return val.read_string(length.read_int)
263
- end
264
- end
265
- end
266
-
267
- def self.getaddrinfo(host, service = nil, family = nil, socktype = nil, protocol = nil, flags = nil)
268
- hints = Addrinfo.new
269
- hints[:ai_family] = family || 0
270
- hints[:ai_socktype] = socktype || 0
271
- hints[:ai_protocol] = protocol || 0
272
- hints[:ai_flags] = flags || 0
273
-
274
- if host && (host.empty? || host == '<any>')
275
- host = "0.0.0.0"
276
- elsif host == '<broadcast>'
277
- host = '255.255.255.255'
278
- end
279
-
280
- res_p = FFI::MemoryPointer.new :pointer
281
-
282
- err = _getaddrinfo host, service, hints.pointer, res_p
283
-
284
- raise SocketError, gai_strerror(err) unless err == 0
285
-
286
- ptr = res_p.read_pointer
287
-
288
- return [] unless ptr
289
-
290
- res = Addrinfo.new ptr
291
-
292
- addrinfos = []
293
-
294
- while true
295
- addrinfo = []
296
- addrinfo << res[:ai_flags]
297
- addrinfo << res[:ai_family]
298
- addrinfo << res[:ai_socktype]
299
- addrinfo << res[:ai_protocol]
300
- addrinfo << res[:ai_addr].read_string(res[:ai_addrlen])
301
- addrinfo << res[:ai_canonname]
302
-
303
- addrinfos << addrinfo
304
-
305
- break unless res[:ai_next]
306
-
307
- res = Addrinfo.new res[:ai_next]
308
- end
309
-
310
- return addrinfos
311
- ensure
312
- hints.free if hints
313
-
314
- if res_p
315
- ptr = res_p.read_pointer
316
-
317
- # Be sure to feed a legit pointer to freeaddrinfo
318
- if ptr and !ptr.null?
319
- freeaddrinfo ptr
320
- end
321
- res_p.free
322
- end
323
- end
324
-
325
- def self.getaddress(host)
326
- addrinfos = getaddrinfo(host)
327
- unpack_sockaddr_in(addrinfos.first[4], false).first
328
- end
329
-
330
- def self.getnameinfo(sockaddr, flags = Socket::Constants::NI_NUMERICHOST | Socket::Constants::NI_NUMERICSERV,
331
- reverse_lookup = !BasicSocket.do_not_reverse_lookup)
332
- name_info = []
333
- value = nil
334
-
335
- FFI::MemoryPointer.new :char, sockaddr.length do |sockaddr_p|
336
- FFI::MemoryPointer.new :char, Socket::Constants::NI_MAXHOST do |node|
337
- FFI::MemoryPointer.new :char, Socket::Constants::NI_MAXSERV do |service|
338
- sockaddr_p.write_string sockaddr, sockaddr.length
339
-
340
- if reverse_lookup then
341
- err = _getnameinfo(sockaddr_p, sockaddr.length,
342
- node, Socket::Constants::NI_MAXHOST, nil, 0, 0)
343
-
344
- name_info[2] = node.read_string if err == 0
345
- end
346
-
347
- err = _getnameinfo(sockaddr_p, sockaddr.length,
348
- node, Socket::Constants::NI_MAXHOST,
349
- service, Socket::Constants::NI_MAXSERV,
350
- flags)
351
-
352
- unless err == 0 then
353
- raise SocketError, gai_strerror(err)
354
- end
355
-
356
- sa_family = SockAddr_In.new(sockaddr)[:sin_family]
357
-
358
- name_info[0] = Socket::Constants::AF_TO_FAMILY[sa_family]
359
- name_info[1] = service.read_string
360
- name_info[3] = node.read_string
361
- end
362
- end
363
- end
364
-
365
- name_info[2] = name_info[3] if name_info[2].nil?
366
- name_info
367
- end
368
-
369
- def self.getpeername(descriptor)
370
- FFI::MemoryPointer.new :char, 128 do |sockaddr_storage_p|
371
- FFI::MemoryPointer.new :socklen_t do |len_p|
372
- len_p.write_int 128
373
-
374
- err = _getpeername descriptor, sockaddr_storage_p, len_p
375
-
376
- Errno.handle 'getpeername(2)' unless err == 0
377
-
378
- sockaddr_storage_p.read_string len_p.read_int
379
- end
380
- end
381
- end
382
-
383
- def self.getsockname(descriptor)
384
- FFI::MemoryPointer.new :char, 128 do |sockaddr_storage_p|
385
- FFI::MemoryPointer.new :socklen_t do |len_p|
386
- len_p.write_int 128
387
-
388
- err = _getsockname descriptor, sockaddr_storage_p, len_p
389
-
390
- Errno.handle 'getsockname(2)' unless err == 0
391
-
392
- sockaddr_storage_p.read_string len_p.read_int
393
- end
394
- end
395
- end
396
-
397
- def self.pack_sockaddr_in(host, port, family, type, flags)
398
- hints = Addrinfo.new
399
- hints[:ai_family] = family
400
- hints[:ai_socktype] = type
401
- hints[:ai_flags] = flags
402
-
403
- if host && host.empty?
404
- host = "0.0.0.0"
405
- end
406
-
407
- res_p = FFI::MemoryPointer.new :pointer
408
-
409
- err = _getaddrinfo host, port.to_s, hints.pointer, res_p
410
-
411
- raise SocketError, gai_strerror(err) unless err == 0
412
-
413
- return [] if res_p.read_pointer.null?
414
-
415
- res = Addrinfo.new res_p.read_pointer
416
-
417
- return res[:ai_addr].read_string(res[:ai_addrlen])
418
-
419
- ensure
420
- hints.free if hints
421
-
422
- if res_p then
423
- ptr = res_p.read_pointer
424
-
425
- freeaddrinfo ptr if ptr and not ptr.null?
426
-
427
- res_p.free
428
- end
429
- end
430
-
431
- def self.unpack_sockaddr_in(sockaddr, reverse_lookup)
432
- family, port, host, ip = getnameinfo sockaddr, Socket::Constants::NI_NUMERICHOST | Socket::Constants::NI_NUMERICSERV, reverse_lookup
433
- # On some systems this doesn't fail for families other than AF_INET(6)
434
- # so we raise manually here.
435
- raise ArgumentError, 'not an AF_INET/AF_INET6 sockaddr' unless family =~ /AF_INET/
436
- return host, ip, port.to_i
437
- end
438
- end
439
-
440
- module ListenAndAccept
441
- include IO::Socketable
442
-
443
- def listen(backlog)
444
- backlog = Rubinius::Type.coerce_to backlog, Fixnum, :to_int
445
-
446
- err = Socket::Foreign.listen descriptor, backlog
447
-
448
- Errno.handle 'listen(2)' unless err == 0
449
-
450
- err
451
- end
452
-
453
- def accept
454
- return if closed?
455
-
456
- fd = super
457
-
458
- socket = self.class.superclass.allocate
459
- IO.setup socket, fd, nil, true
460
- socket
461
- end
462
-
463
- #
464
- # Set nonblocking and accept.
465
- #
466
- def accept_nonblock
467
- return if closed?
468
-
469
- fcntl(Fcntl::F_SETFL, Fcntl::O_NONBLOCK)
470
-
471
- fd = Socket::Foreign.accept descriptor, nil, nil
472
-
473
- Errno.handle 'accept(2)' if fd < 0
474
-
475
- # TCPServer -> TCPSocket etc. *sigh*
476
- socket = self.class.superclass.allocate
477
- IO.setup socket, fd, nil, true
478
- socket
479
- end
480
-
481
- def accept_nonblock2
482
- return if closed?
483
-
484
- fcntl(Fcntl::F_SETFL, Fcntl::O_NONBLOCK)
485
-
486
- fd = Socket::Foreign.accept descriptor, nil, nil
487
- if fd < 0
488
- return nil if FFI::Platform::POSIX.errno == Errno::EAGAIN::Errno
489
- Errno.handle 'accept(2)'
490
- end
491
-
492
- # TCPServer -> TCPSocket etc. *sigh*
493
- socket = self.class.superclass.allocate
494
- IO.setup socket, fd, nil, true
495
- socket
496
- end
497
- end
498
-
499
- include Socket::ListenAndAccept
500
-
501
- class SockAddr_In < FFI::Struct
502
- config("rbx.platform.sockaddr_in", :sin_family, :sin_port, :sin_addr, :sin_zero)
503
-
504
- def initialize(sockaddrin)
505
- @p = FFI::MemoryPointer.new sockaddrin.size
506
- @p.write_string(sockaddrin)
507
- super(@p)
508
- end
509
-
510
- def to_s
511
- @p.read_string(@p.total)
512
- end
513
-
514
- end
515
-
516
- # If we have the details to support unix sockets, do so.
517
- if FFI.config("sockaddr_un.sun_family.offset") and Socket::Constants.const_defined?(:AF_UNIX)
518
- class SockAddr_Un < FFI::Struct
519
- config("rbx.platform.sockaddr_un", :sun_family, :sun_path)
520
-
521
- def initialize(filename = nil)
522
- maxfnsize = self.size - (FFI.config("sockaddr_un.sun_family.size") + 1)
523
-
524
- if filename and filename.length > maxfnsize
525
- raise ArgumentError, "too long unix socket path (max: #{maxfnsize}bytes)"
526
- end
527
- @p = FFI::MemoryPointer.new self.size
528
- if filename
529
- @p.write_string( [Socket::AF_UNIX].pack("s") + filename )
530
- end
531
- super @p
532
- end
533
-
534
- def to_s
535
- @p.read_string self.size
536
- end
537
- end
538
- end
539
-
540
- def self.getaddrinfo(host, service, family = 0, socktype = 0,
541
- protocol = 0, flags = 0)
542
- if service
543
- if service.kind_of? Fixnum
544
- service = service.to_s
545
- else
546
- service = StringValue(service)
547
- end
548
- end
549
-
550
- addrinfos = Socket::Foreign.getaddrinfo(host, service, family, socktype,
551
- protocol, flags)
552
-
553
- addrinfos.map do |ai|
554
- addrinfo = []
555
- addrinfo << Socket::Constants::AF_TO_FAMILY[ai[1]]
556
-
557
- sockaddr = Foreign.unpack_sockaddr_in ai[4], !BasicSocket.do_not_reverse_lookup
558
-
559
- addrinfo << sockaddr.pop # port
560
- addrinfo.concat sockaddr # hosts
561
- addrinfo << ai[1]
562
- addrinfo << ai[2]
563
- addrinfo << ai[3]
564
- addrinfo
565
- end
566
- end
567
-
568
- def self.getnameinfo(sockaddr, flags = 0)
569
- port = nil
570
- host = nil
571
- family = Socket::AF_UNSPEC
572
- if sockaddr.is_a?(Array)
573
- if sockaddr.size == 3
574
- af = sockaddr[0]
575
- port = sockaddr[1]
576
- host = sockaddr[2]
577
- elsif sockaddr.size == 4
578
- af = sockaddr[0]
579
- port = sockaddr[1]
580
- host = sockaddr[3] || sockaddr[2]
581
- else
582
- raise ArgumentError, "array size should be 3 or 4, #{sockaddr.size} given"
583
- end
584
-
585
- if family == "AF_INET"
586
- family = Socket::AF_INET
587
- elsif family == "AF_INET6"
588
- family = Socket::AF_INET6
589
- end
590
- sockaddr = Socket::Foreign.pack_sockaddr_in(host, port, family, Socket::SOCK_DGRAM, 0)
591
- end
592
-
593
- family, port, host, ip = Socket::Foreign.getnameinfo(sockaddr, flags)
594
- [host, port]
595
- end
596
-
597
- def self.gethostname
598
- FFI::MemoryPointer.new :char, 1024 do |mp| #magic number 1024 comes from MRI
599
- Socket::Foreign.gethostname(mp, 1024) # same here
600
- return mp.read_string
601
- end
602
- end
603
-
604
- def self.gethostbyname(hostname)
605
- addrinfos = Socket.getaddrinfo(hostname, nil)
606
-
607
- hostname = addrinfos.first[2]
608
- family = addrinfos.first[4]
609
- addresses = []
610
- alternatives = []
611
- addrinfos.each do |a|
612
- alternatives << a[2] unless a[2] == hostname
613
- # transform addresses to packed strings
614
- if a[4] == family
615
- sockaddr = Socket.sockaddr_in(1, a[3])
616
- if family == AF_INET
617
- # IPv4 address
618
- offset = FFI.config("sockaddr_in.sin_addr.offset")
619
- size = FFI.config("sockaddr_in.sin_addr.size")
620
- addresses << sockaddr.slice(offset, size)
621
- elsif family == AF_INET6
622
- # Ipv6 address
623
- offset = FFI.config("sockaddr_in6.sin6_addr.offset")
624
- size = FFI.config("sockaddr_in6.sin6_addr.size")
625
- addresses << sockaddr.slice(offset, size)
626
- else
627
- addresses << a[3]
628
- end
629
- end
630
- end
631
-
632
- [hostname, alternatives.uniq, family] + addresses.uniq
633
- end
634
-
635
-
636
- class Servent < FFI::Struct
637
- config("rbx.platform.servent", :s_name, :s_aliases, :s_port, :s_proto)
638
-
639
- def initialize(data)
640
- @p = FFI::MemoryPointer.new data.size
641
- @p.write_string(data)
642
- super(@p)
643
- end
644
-
645
- def to_s
646
- @p.read_string(size)
647
- end
648
-
649
- end
650
-
651
- def self.getservbyname(service, proto='tcp')
652
- FFI::MemoryPointer.new :char, service.length + 1 do |svc|
653
- FFI::MemoryPointer.new :char, proto.length + 1 do |prot|
654
- svc.write_string(service + "\0")
655
- prot.write_string(proto + "\0")
656
- fn = Socket::Foreign.getservbyname(svc, prot)
657
-
658
- raise SocketError, "no such service #{service}/#{proto}" if fn.nil?
659
-
660
- s = Servent.new(fn.read_string(Servent.size))
661
- return Socket::Foreign.ntohs(s[:s_port])
662
- end
663
- end
664
- end
665
-
666
- def self.pack_sockaddr_in(port, host, type = Socket::SOCK_DGRAM, flags = 0)
667
- Socket::Foreign.pack_sockaddr_in host, port, Socket::AF_UNSPEC, type, flags
668
- end
669
-
670
- def self.unpack_sockaddr_in(sockaddr)
671
- host, address, port = Socket::Foreign.unpack_sockaddr_in sockaddr, false
672
-
673
- return [port, address]
674
- rescue SocketError => e
675
- if e.message =~ /ai_family not supported/ then # HACK platform specific?
676
- raise ArgumentError, 'not an AF_INET/AF_INET6 sockaddr'
677
- else
678
- raise e
679
- end
680
- end
681
-
682
- def self.socketpair(domain, type, protocol, klass=self)
683
- if domain.kind_of? String
684
- if domain.prefix? "AF_" or domain.prefix? "PF_"
685
- begin
686
- domain = Socket::Constants.const_get(domain)
687
- rescue NameError
688
- raise SocketError, "unknown socket domain #{domani}"
689
- end
690
- else
691
- raise SocketError, "unknown socket domain #{domani}"
692
- end
693
- end
694
-
695
- type = get_socket_type(type)
696
-
697
- FFI::MemoryPointer.new :int, 2 do |mp|
698
- Socket::Foreign.socketpair(domain, type, protocol, mp)
699
- fd0, fd1 = mp.read_array_of_int(2)
700
-
701
- [ klass.from_descriptor(fd0), klass.from_descriptor(fd1) ]
702
- end
703
- end
704
-
705
- class << self
706
- alias_method :sockaddr_in, :pack_sockaddr_in
707
- alias_method :pair, :socketpair
708
- end
709
-
710
- # Only define these methods if we support unix sockets
711
- if self.const_defined?(:SockAddr_Un)
712
- def self.pack_sockaddr_un(file)
713
- SockAddr_Un.new(file).to_s
714
- end
715
-
716
- def self.unpack_sockaddr_un(addr)
717
-
718
- if addr.length > FFI.config("sockaddr_un.sizeof")
719
- raise TypeError, "too long sockaddr_un - #{addr.length} longer than #{FFI.config("sockaddr_un.sizeof")}"
720
- end
721
-
722
- struct = SockAddr_Un.new
723
- struct.pointer.write_string(addr)
724
-
725
- struct[:sun_path]
726
- end
727
-
728
- class << self
729
- alias_method :sockaddr_un, :pack_sockaddr_un
730
- end
731
- end
732
-
733
- def initialize(family, socket_type, protocol)
734
- family = self.class.get_protocol_family family
735
- socket_type = self.class.get_socket_type socket_type
736
- descriptor = Socket::Foreign.socket family, socket_type, protocol
737
-
738
- Errno.handle 'socket(2)' if descriptor < 0
739
-
740
- IO.setup self, descriptor, nil, true
741
- end
742
-
743
- def bind(server_sockaddr)
744
- err = Socket::Foreign.bind(descriptor, server_sockaddr)
745
- Errno.handle 'bind(2)' unless err == 0
746
- err
747
- end
748
-
749
- # @todo Should this be closing the descriptor? --rue
750
- def connect(sockaddr, extra=nil)
751
- if extra
752
- sockaddr = Socket.pack_sockaddr_in sockaddr, extra
753
- else
754
- sockaddr = StringValue(sockaddr)
755
- end
756
-
757
- status = Socket::Foreign.connect descriptor, sockaddr
758
-
759
- if status < 0
760
- begin
761
- Errno.handle "connect(2)"
762
- rescue Errno::EISCONN
763
- return 0
764
- end
765
- end
766
-
767
- return 0
768
- end
769
-
770
- def connect_nonblock(sockaddr)
771
- fcntl(Fcntl::F_SETFL, Fcntl::O_NONBLOCK)
772
-
773
- status = Socket::Foreign.connect descriptor, StringValue(sockaddr)
774
- if status < 0
775
- Errno.handle "connect(2)"
776
- end
777
-
778
- return status
779
- end
780
-
781
- def self.get_protocol_family(family)
782
- case family
783
- when Fixnum
784
- return family
785
- when String
786
- # do nothing
787
- else
788
- family = StringValue(family)
789
- end
790
-
791
- return Socket::Constants.const_get family
792
- end
793
-
794
- def self.get_socket_type(type)
795
- if type.kind_of? String
796
- if type.prefix? "SOCK_"
797
- begin
798
- type = Socket::Constants.const_get(type)
799
- rescue NameError
800
- raise SocketError, "unknown socket type #{type}"
801
- end
802
- else
803
- raise SocketError, "unknown socket type #{type}"
804
- end
805
- elsif !type.kind_of? Integer
806
- raise Errno::EPROTONOSUPPORT, type.inspect
807
- end
808
-
809
- type
810
- end
811
- end
812
-
813
- class UNIXSocket < BasicSocket
814
- include IO::TransferIO
815
-
816
- # Coding to the lowest standard here.
817
- def recvfrom(bytes_read, flags = 0)
818
- # FIXME 2 is hardcoded knowledge from io.cpp
819
- socket_recv(bytes_read, flags, 2)
820
- end
821
-
822
- def initialize(path)
823
- @path = path
824
- unix_setup
825
- @path = "" # Client
826
- end
827
-
828
- def path
829
- unless @path
830
- sockaddr = Socket::Foreign.getsockname descriptor
831
- _, @path = sockaddr.unpack('SZ*')
832
- end
833
-
834
- return @path
835
- end
836
-
837
- def from_descriptor(fixnum)
838
- super
839
- @path = nil
840
- end
841
-
842
- def unix_setup(server = false)
843
- status = nil
844
- phase = 'socket(2)'
845
- sock = Socket::Foreign.socket Socket::Constants::AF_UNIX, Socket::Constants::SOCK_STREAM, 0
846
-
847
- Errno.handle phase if sock < 0
848
-
849
- IO.setup self, sock, 'r+', true
850
-
851
- sockaddr = Socket.pack_sockaddr_un(@path)
852
-
853
- if server then
854
- phase = 'bind(2)'
855
- status = Socket::Foreign.bind descriptor, sockaddr
856
- else
857
- phase = 'connect(2)'
858
- status = Socket::Foreign.connect descriptor, sockaddr
859
- end
860
-
861
- if status < 0 then
862
- close
863
- Errno.handle phase
864
- end
865
-
866
- if server then
867
- phase = 'listen(2)'
868
- status = Socket::Foreign.listen descriptor, 5
869
- if status < 0
870
- close
871
- Errno.handle phase
872
- end
873
- end
874
-
875
- return sock
876
- end
877
- private :unix_setup
878
-
879
- def addr
880
- sockaddr = Socket::Foreign.getsockname descriptor
881
- _, sock_path = sockaddr.unpack('SZ*')
882
- ["AF_UNIX", sock_path]
883
- end
884
-
885
- def peeraddr
886
- sockaddr = Socket::Foreign.getpeername descriptor
887
- _, sock_path = sockaddr.unpack('SZ*')
888
- ["AF_UNIX", sock_path]
889
- end
890
-
891
- def recv_io(klass=IO, mode=nil)
892
- begin
893
- fd = recv_fd
894
- rescue PrimitiveFailure
895
- raise SocketError, "file descriptor was not passed"
896
- end
897
-
898
- return fd unless klass
899
-
900
- if klass < BasicSocket
901
- klass.for_fd(fd)
902
- else
903
- klass.for_fd(fd, mode)
904
- end
905
- end
906
-
907
- class << self
908
- def socketpair(type=Socket::SOCK_STREAM, protocol=0)
909
- Socket.socketpair(Socket::PF_UNIX, type, protocol, self)
910
- end
911
-
912
- alias_method :pair, :socketpair
913
- end
914
-
915
- end
916
-
917
- class UNIXServer < UNIXSocket
918
-
919
- include Socket::ListenAndAccept
920
-
921
- def initialize(path)
922
- @path = path
923
- unix_setup(true)
924
- end
925
- end
926
-
927
- class IPSocket < BasicSocket
928
-
929
- def self.getaddress(host)
930
- Socket::Foreign.getaddress host
931
- end
932
-
933
- def addr
934
- sockaddr = Socket::Foreign.getsockname descriptor
935
-
936
- family, port, host, ip = Socket::Foreign.getnameinfo sockaddr
937
- [family, port.to_i, host, ip]
938
- end
939
-
940
- def peeraddr
941
- sockaddr = Socket::Foreign.getpeername descriptor
942
-
943
- family, port, host, ip = Socket::Foreign.getnameinfo sockaddr
944
- [family, port.to_i, host, ip]
945
- end
946
-
947
- def recvfrom(maxlen, flags = 0)
948
- # FIXME 1 is hardcoded knowledge from io.cpp
949
- flags = 0 if flags.nil?
950
- socket_recv maxlen, flags, 1
951
- end
952
-
953
- def recvfrom_nonblock(maxlen, flags = 0)
954
- # Set socket to non-blocking, if we can
955
- # Todo: Ensure this works in Windows! If not, I claim that's Fcntl's fault.
956
- fcntl(Fcntl::F_SETFL, Fcntl::O_NONBLOCK)
957
- flags = 0 if flags.nil?
958
- flags |= Socket::MSG_DONTWAIT
959
-
960
- # Wait until we have something to read
961
- # @todo Why? ^^ --rue
962
- IO.select([self])
963
- return recvfrom(maxlen, flags)
964
- end
965
- end
966
-
967
- class UDPSocket < IPSocket
968
- FFI = Rubinius::FFI
969
-
970
- def initialize(socktype = Socket::AF_INET)
971
- @socktype = socktype
972
- status = Socket::Foreign.socket @socktype,
973
- Socket::SOCK_DGRAM,
974
- Socket::IPPROTO_UDP
975
- Errno.handle 'socket(2)' if status < 0
976
-
977
- IO.setup self, status, nil, true
978
- end
979
-
980
- def bind(host, port)
981
- @host = host.to_s if host
982
- @port = port.to_s if port
983
-
984
- addrinfos = Socket::Foreign.getaddrinfo(@host,
985
- @port,
986
- @socktype,
987
- Socket::SOCK_DGRAM, 0,
988
- Socket::AI_PASSIVE)
989
-
990
- status = -1
991
-
992
- addrinfos.each do |addrinfo|
993
- flags, family, socket_type, protocol, sockaddr, canonname = addrinfo
994
-
995
- status = Socket::Foreign.bind descriptor, sockaddr
996
-
997
- break if status >= 0
998
- end
999
-
1000
- if status < 0
1001
- Errno.handle 'bind(2)'
1002
- end
1003
-
1004
- status
1005
- end
1006
-
1007
- def connect(host, port)
1008
- sockaddr = Socket::Foreign.pack_sockaddr_in host, port, @socktype, Socket::SOCK_DGRAM, 0
1009
-
1010
- syscall = 'connect(2)'
1011
- status = Socket::Foreign.connect descriptor, sockaddr
1012
-
1013
- if status < 0
1014
- Errno.handle syscall
1015
- end
1016
-
1017
- 0
1018
- end
1019
-
1020
- def send(message, flags, *to)
1021
- connect *to unless to.empty?
1022
-
1023
- bytes = message.length
1024
- bytes_sent = 0
1025
-
1026
- FFI::MemoryPointer.new :char, bytes + 1 do |buffer|
1027
- buffer.write_string message
1028
- bytes_sent = Socket::Foreign.send(descriptor, buffer, bytes, flags)
1029
- Errno.handle 'send(2)' if bytes_sent < 0
1030
- end
1031
-
1032
- bytes_sent
1033
- end
1034
-
1035
- def inspect
1036
- "#<#{self.class}:0x#{object_id.to_s(16)} #{@host}:#{@port}>"
1037
- end
1038
-
1039
- end
1040
-
1041
- class TCPSocket < IPSocket
1042
- FFI = Rubinius::FFI
1043
-
1044
- def self.gethostbyname(hostname)
1045
- addrinfos = Socket.getaddrinfo(hostname, nil)
1046
-
1047
- hostname = addrinfos.first[2]
1048
- family = addrinfos.first[4]
1049
- addresses = []
1050
- alternatives = []
1051
- addrinfos.each do |a|
1052
- alternatives << a[2] unless a[2] == hostname
1053
- addresses << a[3] if a[4] == family
1054
- end
1055
-
1056
- [hostname, alternatives.uniq, family] + addresses.uniq
1057
- end
1058
-
1059
- #
1060
- # @todo Is it correct to ignore the to? If not, does
1061
- # the socket need to be reconnected? --rue
1062
- #
1063
- def send(bytes_to_read, flags, to = nil)
1064
- super(bytes_to_read, flags)
1065
- end
1066
-
1067
-
1068
- def initialize(host, port, local_host=nil, local_service=nil)
1069
- @host = host
1070
- @port = port
1071
-
1072
- tcp_setup @host, @port, local_host, local_service
1073
- end
1074
-
1075
- def tcp_setup(remote_host, remote_service, local_host = nil,
1076
- local_service = nil, server = false)
1077
- status = nil
1078
- syscall = nil
1079
- remote_host = StringValue(remote_host) if remote_host
1080
- if remote_service
1081
- if remote_service.kind_of? Fixnum
1082
- remote_service = remote_service.to_s
1083
- else
1084
- remote_service = StringValue(remote_service)
1085
- end
1086
- end
1087
-
1088
- flags = server ? Socket::AI_PASSIVE : 0
1089
- @remote_addrinfo = Socket::Foreign.getaddrinfo(remote_host,
1090
- remote_service,
1091
- Socket::AF_UNSPEC,
1092
- Socket::SOCK_STREAM, 0,
1093
- flags)
1094
-
1095
- if server == false and (local_host or local_service)
1096
- local_host = local_host.to_s if local_host
1097
- local_service = local_service.to_s if local_service
1098
- @local_addrinfo = Socket::Foreign.getaddrinfo(local_host,
1099
- local_service,
1100
- Socket::AF_UNSPEC,
1101
- Socket::SOCK_STREAM, 0, 0)
1102
- end
1103
-
1104
- sock = nil
1105
-
1106
- @remote_addrinfo.each do |addrinfo|
1107
- flags, family, socket_type, protocol, sockaddr, canonname = addrinfo
1108
-
1109
- sock = Socket::Foreign.socket family, socket_type, protocol
1110
- syscall = 'socket(2)'
1111
-
1112
- next if sock < 0
1113
-
1114
- if server
1115
- FFI::MemoryPointer.new :socklen_t do |val|
1116
- val.write_int 1
1117
- level = Socket::Constants::SOL_SOCKET
1118
- optname = Socket::Constants::SO_REUSEADDR
1119
- error = Socket::Foreign.setsockopt(sock, level,
1120
- optname, val,
1121
- val.total)
1122
- # Don't check error because if this fails, we just continue
1123
- # anyway.
1124
- end
1125
-
1126
- status = Socket::Foreign.bind sock, sockaddr
1127
- syscall = 'bind(2)'
1128
- else
1129
- if @local_addrinfo
1130
- # Pick a local_addrinfo for the family and type of
1131
- # the remote side
1132
- li = @local_addrinfo.find do |i|
1133
- i[1] == family && i[2] == socket_type
1134
- end
1135
-
1136
- if li
1137
- status = Socket::Foreign.bind sock, li[4]
1138
- syscall = 'bind(2)'
1139
- else
1140
- status = 1
1141
- end
1142
- else
1143
- status = 1
1144
- end
1145
-
1146
- if status >= 0
1147
- status = Socket::Foreign.connect sock, sockaddr
1148
- syscall = 'connect(2)'
1149
- end
1150
- end
1151
-
1152
- if status < 0
1153
- Socket::Foreign.close sock
1154
- else
1155
- break
1156
- end
1157
- end
1158
-
1159
- if status < 0
1160
- Errno.handle syscall
1161
- end
1162
-
1163
- if server
1164
- err = Socket::Foreign.listen sock, 5
1165
- unless err == 0
1166
- Socket::Foreign.close sock
1167
- Errno.handle syscall
1168
- end
1169
- end
1170
-
1171
- # Only setup once we have found a socket we can use. Otherwise
1172
- # because we manually close a socket fd, we can create an IO fd
1173
- # alias condition which causes EBADF because when an IO is finalized
1174
- # and it's fd has been closed underneith it, we close someone elses
1175
- # fd!
1176
- IO.setup self, sock, nil, true
1177
- end
1178
- private :tcp_setup
1179
-
1180
- def from_descriptor(descriptor)
1181
- IO.setup self, descriptor, nil, true
1182
-
1183
- self
1184
- end
1185
- end
1186
-
1187
- class TCPServer < TCPSocket
1188
-
1189
- include Socket::ListenAndAccept
1190
-
1191
- def initialize(host, port = nil)
1192
- if Fixnum === host and port.nil? then
1193
- port = host
1194
- host = nil
1195
- end
1196
-
1197
- if String === host and port.nil? then
1198
- port = Integer(host)
1199
- host = nil
1200
- end
1201
-
1202
- port = StringValue port unless port.kind_of? Fixnum
1203
-
1204
- @host = host
1205
- @port = port
1206
-
1207
- tcp_setup @host, @port, nil, nil, true
1208
- end
1209
-
1210
- end