Module: RubySL::Socket

Defined in:
lib/rubysl/socket.rb,
lib/rubysl/socket/bsd.rb,
lib/rubysl/socket/ipv6.rb,
lib/rubysl/socket/error.rb,
lib/rubysl/socket/linux.rb,
lib/rubysl/socket/foreign.rb,
lib/rubysl/socket/version.rb,
lib/rubysl/socket/foreign/iovec.rb,
lib/rubysl/socket/ancillary_data.rb,
lib/rubysl/socket/foreign/linger.rb,
lib/rubysl/socket/foreign/msghdr.rb,
lib/rubysl/socket/socket_options.rb,
lib/rubysl/socket/foreign/hostent.rb,
lib/rubysl/socket/foreign/ifaddrs.rb,
lib/rubysl/socket/foreign/servent.rb,
lib/rubysl/socket/foreign/addrinfo.rb,
lib/rubysl/socket/foreign/sockaddr.rb,
lib/rubysl/socket/foreign/sockaddr_in.rb,
lib/rubysl/socket/foreign/sockaddr_un.rb,
lib/rubysl/socket/foreign/sockaddr_in6.rb

Defined Under Namespace

Modules: AncillaryData, Error, Foreign, IPv6, SocketOptions

Constant Summary collapse

VERSION =
"2.1.3"

Class Method Summary collapse

Class Method Details

.accept(source, new_class) ⇒ Object

Raises:

  • (IOError)


42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/rubysl/socket.rb', line 42

def self.accept(source, new_class)
  raise IOError, 'socket has been closed' if source.closed?

  sockaddr = sockaddr_class_for_socket(source).new

  begin
    fd = RubySL::Socket::Foreign.memory_pointer(:int) do |size_p|
      size_p.write_int(sockaddr.size)

      RubySL::Socket::Foreign
        .accept(source.descriptor, sockaddr.pointer, size_p)
    end

    Error.read_error('accept(2)', source) if fd < 0

    socket = new_class.allocate

    ::IO.setup(socket, fd, nil, true)
    socket.binmode

    socktype = source.getsockopt(:SOCKET, :TYPE).int
    addrinfo = Addrinfo.new(sockaddr.to_s, sockaddr.family, socktype)

    return socket, addrinfo
  ensure
    sockaddr.free
  end
end

.accept_nonblock(source, new_class) ⇒ Object



71
72
73
74
75
# File 'lib/rubysl/socket.rb', line 71

def self.accept_nonblock(source, new_class)
  source.fcntl(::Fcntl::F_SETFL, ::Fcntl::O_NONBLOCK)

  accept(source, new_class)
end

.address_family(family) ⇒ Object



139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/rubysl/socket.rb', line 139

def self.address_family(family)
  case family
  when Symbol, String
    f = family.to_s

    unless family_prefix?(f)
      f = 'AF_' + f
    end

    if ::Socket.const_defined?(f)
      ::Socket.const_get(f)
    else
      raise SocketError, "unknown socket domain: #{family}"
    end
  when Integer
    family
  when NilClass
    ::Socket::AF_UNSPEC
  else
    if family.respond_to?(:to_str)
      address_family(Rubinius::Type.coerce_to(family, String, :to_str))
    else
      raise SocketError, "unknown socket domain: #{family}"
    end
  end
end

.address_family_name(family_int) ⇒ Object



166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/rubysl/socket.rb', line 166

def self.address_family_name(family_int)
  # Both AF_LOCAL and AF_UNIX use value 1. CRuby seems to prefer AF_UNIX
  # over AF_LOCAL.
  if family_int == ::Socket::AF_UNIX && family_int == ::Socket::AF_LOCAL
    return 'AF_UNIX'
  end

  ::Socket.constants.grep(/^AF_/).each do |name|
    return name.to_s if ::Socket.const_get(name) == family_int
  end

  'AF_UNSPEC'
end

.address_info(method, socket, reverse_lookup = nil) ⇒ Object



286
287
288
289
290
291
292
293
294
295
296
297
298
# File 'lib/rubysl/socket.rb', line 286

def self.address_info(method, socket, reverse_lookup = nil)
  sockaddr = Foreign.__send__(method, socket.descriptor)

  reverse_lookup = convert_reverse_lookup(socket, reverse_lookup)

  options = ::Socket::Constants::NI_NUMERICHOST |
    ::Socket::Constants::NI_NUMERICSERV

  family, port, host, ip = Foreign
    .getnameinfo(sockaddr, options, reverse_lookup)

  [family, port.to_i, host, ip]
end

.aliases_for_hostname(hostname) ⇒ Object



15
16
17
18
19
# File 'lib/rubysl/socket.rb', line 15

def self.aliases_for_hostname(hostname)
  pointer = Foreign.gethostbyname(hostname)

  Foreign::Hostent.new(pointer).aliases
end

.bsd_support?Boolean

Returns:

  • (Boolean)


3
4
5
# File 'lib/rubysl/socket.rb', line 3

def self.bsd_support?
  Rubinius.bsd? || Rubinius.darwin?
end

.coerce_to_string(object) ⇒ Object



103
104
105
106
107
108
109
110
111
# File 'lib/rubysl/socket.rb', line 103

def self.coerce_to_string(object)
  if object.is_a?(String) or object.is_a?(Symbol)
    object.to_s
  elsif object.respond_to?(:to_str)
    Rubinius::Type.coerce_to(object, String, :to_str)
  else
    raise TypeError, "no implicit conversion of #{object.inspect} into Integer"
  end
end

.constant_pairsObject



99
100
101
# File 'lib/rubysl/socket.rb', line 99

def self.constant_pairs
  Rubinius::FFI.config_hash('socket').reject { |name, value| value.empty? }
end

.convert_reverse_lookup(socket = nil, reverse_lookup = nil) ⇒ Object



264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
# File 'lib/rubysl/socket.rb', line 264

def self.convert_reverse_lookup(socket = nil, reverse_lookup = nil)
  if reverse_lookup.nil?
    if socket
      reverse_lookup = !socket.do_not_reverse_lookup
    else
      reverse_lookup = !BasicSocket.do_not_reverse_lookup
    end

  elsif reverse_lookup == :hostname
    reverse_lookup = true

  elsif reverse_lookup == :numeric
    reverse_lookup = false

  elsif reverse_lookup != true and reverse_lookup != false
    raise ArgumentError,
      "invalid reverse_lookup flag: #{reverse_lookup.inspect}"
  end

  reverse_lookup
end

.family_for_sockaddr_in(sockaddr) ⇒ Object



86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/rubysl/socket.rb', line 86

def self.family_for_sockaddr_in(sockaddr)
  case sockaddr.bytesize
  when 28
    ::Socket::AF_INET6
  when 16
    ::Socket::AF_INET
  # UNIX socket addresses can have a variable size as sometimes any trailing
  # null bytes are stripped (e.g. when calling UNIXServer#getsockname).
  else
    ::Socket::AF_UNIX
  end
end

.family_prefix?(family) ⇒ Boolean

Returns:

  • (Boolean)


113
114
115
# File 'lib/rubysl/socket.rb', line 113

def self.family_prefix?(family)
  family.start_with?('AF_') || family.start_with?('PF_')
end

.linux_support?Boolean

Returns:

  • (Boolean)


7
8
9
# File 'lib/rubysl/socket.rb', line 7

def self.linux_support?
  Rubinius.linux?
end

.listen(source, backlog) ⇒ Object



77
78
79
80
81
82
83
84
# File 'lib/rubysl/socket.rb', line 77

def self.listen(source, backlog)
  backlog = Rubinius::Type.coerce_to(backlog, Fixnum, :to_int)
  err     = Foreign.listen(source.descriptor, backlog)

  Error.read_error('listen(2)', source) if err < 0

  0
end

.prefix_with(name, prefix) ⇒ Object



117
118
119
120
121
122
123
# File 'lib/rubysl/socket.rb', line 117

def self.prefix_with(name, prefix)
  unless name.start_with?(prefix)
    name = "#{prefix}#{name}"
  end

  name
end

.prefixed_socket_constant(name, prefix, &block) ⇒ Object



125
126
127
128
129
# File 'lib/rubysl/socket.rb', line 125

def self.prefixed_socket_constant(name, prefix, &block)
  prefixed = prefix_with(name, prefix)

  socket_constant(prefixed, &block)
end

.protocol_family(family) ⇒ Object



210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
# File 'lib/rubysl/socket.rb', line 210

def self.protocol_family(family)
  case family
  when Symbol, String
    f = family.to_s

    unless family_prefix?(f)
      f = 'PF_' + f
    end

    if ::Socket.const_defined?(f)
      ::Socket.const_get(f)
    else
      raise SocketError, "unknown socket domain: #{family}"
    end
  when Integer
    family
  when NilClass
    ::Socket::PF_UNSPEC
  else
    if family.respond_to?(:to_str)
      protocol_family(Rubinius::Type.coerce_to(family, String, :to_str))
    else
      raise SocketError, "unknown socket domain: #{family}"
    end
  end
end

.protocol_family_name(family_int) ⇒ Object



180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/rubysl/socket.rb', line 180

def self.protocol_family_name(family_int)
  # Both PF_LOCAL and PF_UNIX use value 1. CRuby seems to prefer PF_UNIX
  # over PF_LOCAL.
  if family_int == ::Socket::PF_UNIX && family_int == ::Socket::PF_LOCAL
    return 'PF_UNIX'
  end

  ::Socket.constants.grep(/^PF_/).each do |name|
    return name.to_s if ::Socket.const_get(name) == family_int
  end

  'PF_UNSPEC'
end

.protocol_name(family_int) ⇒ Object



194
195
196
197
198
199
200
# File 'lib/rubysl/socket.rb', line 194

def self.protocol_name(family_int)
  ::Socket.constants.grep(/^IPPROTO_/).each do |name|
    return name.to_s if ::Socket.const_get(name) == family_int
  end

  'IPPROTO_IP'
end

.shutdown_option(how) ⇒ Object



300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
# File 'lib/rubysl/socket.rb', line 300

def self.shutdown_option(how)
  case how
  when String, Symbol
    prefixed_socket_constant(how.to_s, 'SHUT_') do
      "unknown shutdown argument: #{how}"
    end
  when Fixnum
    if how == ::Socket::SHUT_RD or
      how == ::Socket::SHUT_WR or
      how == ::Socket::SHUT_RDWR
      how
    else
      raise ArgumentError,
        'argument should be :SHUT_RD, :SHUT_WR, or :SHUT_RDWR'
    end
  else
    if how.respond_to?(:to_str)
      shutdown_option(coerce_to_string(how))
    else
      raise TypeError,
        "no implicit conversion of #{how.class} into Integer"
    end
  end
end

.sockaddr_class_for_socket(socket) ⇒ Object



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/rubysl/socket.rb', line 21

def self.sockaddr_class_for_socket(socket)
  if socket.is_a?(::UNIXSocket)
    return Foreign::SockaddrUn
  end

  # Socket created using for example Socket.unix('foo')
  if socket.is_a?(::Socket) and
    socket.instance_variable_get(:@family) == ::Socket::AF_UNIX
    return Foreign::SockaddrUn
  end

  case address_info(:getsockname, socket)[0]
  when 'AF_INET6'
    Foreign::SockaddrIn6
  when 'AF_UNIX'
    Foreign::SockaddrUn
  else
    Foreign::SockaddrIn
  end
end

.socket_constant(name) ⇒ Object



131
132
133
134
135
136
137
# File 'lib/rubysl/socket.rb', line 131

def self.socket_constant(name)
  if ::Socket.const_defined?(name)
    ::Socket.const_get(name)
  else
    raise SocketError, yield
  end
end

.socket_type(type) ⇒ Object



237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
# File 'lib/rubysl/socket.rb', line 237

def self.socket_type(type)
  case type
  when Symbol, String
    t = type.to_s

    if t[0..4] != 'SOCK_'
      t = "SOCK_#{t}"
    end

    if ::Socket.const_defined?(t)
      ::Socket.const_get(t)
    else
      raise SocketError, "unknown socket type: #{type}"
    end
  when Integer
    type
  when NilClass
    0
  else
    if type.respond_to?(:to_str)
      socket_type(Rubinius::Type.coerce_to(type, String, :to_str))
    else
      raise SocketError, "unknown socket type: #{type}"
    end
  end
end

.socket_type_name(socktype) ⇒ Object



202
203
204
205
206
207
208
# File 'lib/rubysl/socket.rb', line 202

def self.socket_type_name(socktype)
  ::Socket.constants.grep(/^SOCK_/).each do |name|
    return name.to_s if ::Socket.const_get(name) == socktype
  end

  nil
end

.unix_socket_support?Boolean

Returns:

  • (Boolean)


11
12
13
# File 'lib/rubysl/socket.rb', line 11

def self.unix_socket_support?
  ::Socket::Constants.const_defined?(:AF_UNIX)
end