1 | class Addrinfo
|
---|
2 | def initialize(sockaddr, family=Socket::PF_UNSPEC, socktype=0, protocol=0)
|
---|
3 | @hostname = nil
|
---|
4 | if sockaddr.is_a? Array
|
---|
5 | sary = sockaddr
|
---|
6 | if sary[0] == 'AF_INET' || sary[0] == 'AF_INET6'
|
---|
7 | @sockaddr = Socket.sockaddr_in(sary[1], sary[3])
|
---|
8 | @hostname = sary[2]
|
---|
9 | elsif sary[0] == 'AF_UNIX'
|
---|
10 | @sockaddr = Socket.sockaddr_un(sary[1])
|
---|
11 | end
|
---|
12 | else
|
---|
13 | @sockaddr = sockaddr.dup
|
---|
14 | end
|
---|
15 | if family == Socket::PF_UNSPEC or family == nil
|
---|
16 | @family = Socket._sockaddr_family(@sockaddr)
|
---|
17 | else
|
---|
18 | @family = family
|
---|
19 | end
|
---|
20 | @socktype = socktype
|
---|
21 | @protocol = protocol
|
---|
22 | @canonname = nil
|
---|
23 | end
|
---|
24 |
|
---|
25 | def self.foreach(nodename, service, family=nil, socktype=nil, protocol=nil, flags=0, &block)
|
---|
26 | a = self.getaddrinfo(nodename, service, family, socktype, protocol, flags)
|
---|
27 | a.each { |ai| block.call(ai) }
|
---|
28 | a
|
---|
29 | end
|
---|
30 |
|
---|
31 | def self.ip(host)
|
---|
32 | Addrinfo.new(Socket.sockaddr_in(0, host))
|
---|
33 | end
|
---|
34 |
|
---|
35 | def self.tcp(host, port)
|
---|
36 | Addrinfo.getaddrinfo(host, port, nil, Socket::SOCK_STREAM, Socket::IPPROTO_TCP)[0]
|
---|
37 | end
|
---|
38 |
|
---|
39 | def self.udp(host, port)
|
---|
40 | Addrinfo.getaddrinfo(host, port, nil, Socket::SOCK_DGRAM, Socket::IPPROTO_UDP)[0]
|
---|
41 | end
|
---|
42 |
|
---|
43 | def self.unix(path, socktype=Socket::SOCK_STREAM)
|
---|
44 | Addrinfo.new(Socket.sockaddr_un(path), Socket::AF_UNIX, socktype)
|
---|
45 | end
|
---|
46 |
|
---|
47 | def afamily
|
---|
48 | @family
|
---|
49 | end
|
---|
50 |
|
---|
51 | #def bind
|
---|
52 |
|
---|
53 | attr_reader :canonname
|
---|
54 |
|
---|
55 | #def connect
|
---|
56 | #def connect_from
|
---|
57 | #def connect_to
|
---|
58 |
|
---|
59 | #def family_addrinfo(host, port=nil)
|
---|
60 | #def getnameinfo(flags=0)
|
---|
61 | # Socket.getnameinfo
|
---|
62 | #end
|
---|
63 |
|
---|
64 | def inspect
|
---|
65 | if ipv4? or ipv6?
|
---|
66 | if @protocol == Socket::IPPROTO_TCP or (@socktype == Socket::SOCK_STREAM and @protocol == 0)
|
---|
67 | proto = 'TCP'
|
---|
68 | elsif @protocol == Socket::IPPROTO_UDP or (@socktype == Socket::SOCK_DGRAM and @protocol == 0)
|
---|
69 | proto = 'UDP'
|
---|
70 | else
|
---|
71 | proto = '???'
|
---|
72 | end
|
---|
73 | "#<Addrinfo: #{inspect_sockaddr} #{proto}>"
|
---|
74 | else
|
---|
75 | "#<Addrinfo: #{self.unix_path} SOCK_STREAM>"
|
---|
76 | end
|
---|
77 | end
|
---|
78 |
|
---|
79 | def inspect_sockaddr
|
---|
80 | if ipv4?
|
---|
81 | a, p = ip_unpack
|
---|
82 | "#{a}:#{p}"
|
---|
83 | elsif ipv6?
|
---|
84 | a, p = ip_unpack
|
---|
85 | "[#{a}]:#{p}"
|
---|
86 | elsif unix?
|
---|
87 | unix_path
|
---|
88 | else
|
---|
89 | '???'
|
---|
90 | end
|
---|
91 | end
|
---|
92 |
|
---|
93 | def ip?
|
---|
94 | ipv4? or ipv6?
|
---|
95 | end
|
---|
96 |
|
---|
97 | def ip_address
|
---|
98 | ip_unpack[0]
|
---|
99 | end
|
---|
100 |
|
---|
101 | def ip_port
|
---|
102 | ip_unpack[1]
|
---|
103 | end
|
---|
104 |
|
---|
105 | def ip_unpack
|
---|
106 | h, p = getnameinfo(Socket::NI_NUMERICHOST|Socket::NI_NUMERICSERV)
|
---|
107 | [ h, p.to_i ]
|
---|
108 | end
|
---|
109 |
|
---|
110 | def ipv4?
|
---|
111 | @family == Socket::AF_INET
|
---|
112 | end
|
---|
113 |
|
---|
114 | #def ipv4_loopback?
|
---|
115 | #def ipv4_multicast?
|
---|
116 | #def ipv4_private?
|
---|
117 |
|
---|
118 | def ipv6?
|
---|
119 | @family == Socket::AF_INET6
|
---|
120 | end
|
---|
121 |
|
---|
122 | #def ipv6_loopback?
|
---|
123 | #def ipv6_mc_global?
|
---|
124 | #def ipv6_mc_linklocal?
|
---|
125 | #def ipv6_mc_nodelocal?
|
---|
126 | #def ipv6_mc_orilocal?
|
---|
127 | #def ipv6_mc_sitelocal?
|
---|
128 | #def ipv6_multicast?
|
---|
129 | #def ipv6_to_ipv4
|
---|
130 | #def ipv6_unspecified
|
---|
131 | #def ipv6_v4compat?
|
---|
132 | #def ipv6_v4mapped?
|
---|
133 | #def listen(backlog=5)
|
---|
134 |
|
---|
135 | def pfamily
|
---|
136 | @family
|
---|
137 | end
|
---|
138 |
|
---|
139 | attr_reader :protocol
|
---|
140 | attr_reader :socktype
|
---|
141 |
|
---|
142 | def _to_array
|
---|
143 | case @family
|
---|
144 | when Socket::AF_INET
|
---|
145 | s = "AF_INET"
|
---|
146 | when Socket::AF_INET6
|
---|
147 | s = "AF_INET6"
|
---|
148 | when Socket::AF_UNIX
|
---|
149 | s = "AF_UNIX"
|
---|
150 | else
|
---|
151 | s = "(unknown AF)"
|
---|
152 | end
|
---|
153 | addr, port = self.getnameinfo(Socket::NI_NUMERICHOST|Socket::NI_NUMERICSERV)
|
---|
154 | [ s, port.to_i, addr, addr ]
|
---|
155 | end
|
---|
156 |
|
---|
157 | def to_sockaddr
|
---|
158 | @sockaddr
|
---|
159 | end
|
---|
160 |
|
---|
161 | alias to_s to_sockaddr
|
---|
162 |
|
---|
163 | def unix?
|
---|
164 | @family == Socket::AF_UNIX
|
---|
165 | end
|
---|
166 | end
|
---|
167 |
|
---|
168 | class BasicSocket
|
---|
169 | @@do_not_reverse_lookup = true
|
---|
170 |
|
---|
171 | def self.do_not_reverse_lookup
|
---|
172 | @@do_not_reverse_lookup
|
---|
173 | end
|
---|
174 |
|
---|
175 | def self.do_not_reverse_lookup=(val)
|
---|
176 | @@do_not_reverse_lookup = val ? true : false
|
---|
177 | end
|
---|
178 |
|
---|
179 | def initialize(*args)
|
---|
180 | super(*args)
|
---|
181 | @do_not_reverse_lookup = @@do_not_reverse_lookup
|
---|
182 | end
|
---|
183 |
|
---|
184 | def self.for_fd(fd)
|
---|
185 | super(fd, "r+")
|
---|
186 | end
|
---|
187 |
|
---|
188 | #def connect_address
|
---|
189 |
|
---|
190 | def local_address
|
---|
191 | Addrinfo.new self.getsockname
|
---|
192 | end
|
---|
193 |
|
---|
194 | def recv_nonblock(maxlen, flags=0)
|
---|
195 | begin
|
---|
196 | _setnonblock(true)
|
---|
197 | recv(maxlen, flags)
|
---|
198 | ensure
|
---|
199 | _setnonblock(false)
|
---|
200 | end
|
---|
201 | end
|
---|
202 |
|
---|
203 | def remote_address
|
---|
204 | Addrinfo.new self.getpeername
|
---|
205 | end
|
---|
206 |
|
---|
207 | attr_accessor :do_not_reverse_lookup
|
---|
208 | end
|
---|
209 |
|
---|
210 | class IPSocket
|
---|
211 | def self.getaddress(host)
|
---|
212 | Addrinfo.ip(host).ip_address
|
---|
213 | end
|
---|
214 |
|
---|
215 | def addr
|
---|
216 | Addrinfo.new(self.getsockname)._to_array
|
---|
217 | end
|
---|
218 |
|
---|
219 | def peeraddr
|
---|
220 | Addrinfo.new(self.getpeername)._to_array
|
---|
221 | end
|
---|
222 |
|
---|
223 | def recvfrom(maxlen, flags=0)
|
---|
224 | msg, sa = _recvfrom(maxlen, flags)
|
---|
225 | [ msg, Addrinfo.new(sa)._to_array ]
|
---|
226 | end
|
---|
227 | end
|
---|
228 |
|
---|
229 | class TCPSocket
|
---|
230 | def initialize(host, service, local_host=nil, local_service=nil)
|
---|
231 | if @init_with_fd
|
---|
232 | super(host, service)
|
---|
233 | else
|
---|
234 | s = nil
|
---|
235 | e = SocketError
|
---|
236 | Addrinfo.foreach(host, service, nil, Socket::SOCK_STREAM, Socket::IPPROTO_TCP) do |ai|
|
---|
237 | begin
|
---|
238 | s = Socket._socket(ai.afamily, Socket::SOCK_STREAM, 0)
|
---|
239 | if local_host or local_service
|
---|
240 | local_host ||= (ai.afamily == Socket::AF_INET) ? "0.0.0.0" : "::"
|
---|
241 | local_service ||= "0"
|
---|
242 | bi = Addrinfo.getaddrinfo(local_host, local_service, ai.afamily, ai.socktype)[0]
|
---|
243 | Socket._bind(s, bi.to_sockaddr)
|
---|
244 | end
|
---|
245 | Socket._connect(s, ai.to_sockaddr)
|
---|
246 | super(s, "r+")
|
---|
247 | e = nil
|
---|
248 | break
|
---|
249 | rescue => e0
|
---|
250 | e = e0
|
---|
251 | end
|
---|
252 | end
|
---|
253 | if e != nil
|
---|
254 | raise e
|
---|
255 | end
|
---|
256 | end
|
---|
257 | end
|
---|
258 |
|
---|
259 | def self.new_with_prelude pre, *args
|
---|
260 | o = self._allocate
|
---|
261 | o.instance_eval(&pre)
|
---|
262 | o.initialize(*args)
|
---|
263 | o
|
---|
264 | end
|
---|
265 |
|
---|
266 | #def self.gethostbyname(host)
|
---|
267 | end
|
---|
268 |
|
---|
269 | class TCPServer
|
---|
270 | def initialize(host=nil, service)
|
---|
271 | ai = Addrinfo.getaddrinfo(host, service, nil, nil, nil, Socket::AI_PASSIVE)[0]
|
---|
272 | @init_with_fd = true
|
---|
273 | super(Socket._socket(ai.afamily, Socket::SOCK_STREAM, 0), "r+")
|
---|
274 | if Socket.const_defined?(:SO_REUSEADDR)
|
---|
275 | self.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, true)
|
---|
276 | end
|
---|
277 | Socket._bind(self.fileno, ai.to_sockaddr)
|
---|
278 | listen(5)
|
---|
279 | self
|
---|
280 | end
|
---|
281 |
|
---|
282 | def accept
|
---|
283 | fd = self.sysaccept
|
---|
284 | begin
|
---|
285 | proc = Proc.new { @init_with_fd = true }
|
---|
286 | TCPSocket.new_with_prelude(proc, fd, "r+")
|
---|
287 | rescue
|
---|
288 | IO._sysclose(fd) rescue nil
|
---|
289 | raise
|
---|
290 | end
|
---|
291 | end
|
---|
292 |
|
---|
293 | def accept_nonblock
|
---|
294 | begin
|
---|
295 | self._setnonblock(true)
|
---|
296 | self.accept
|
---|
297 | ensure
|
---|
298 | self._setnonblock(false)
|
---|
299 | end
|
---|
300 | end
|
---|
301 |
|
---|
302 | def listen(backlog)
|
---|
303 | Socket._listen(self.fileno, backlog)
|
---|
304 | 0
|
---|
305 | end
|
---|
306 |
|
---|
307 | def sysaccept
|
---|
308 | Socket._accept(self.fileno)[0]
|
---|
309 | end
|
---|
310 | end
|
---|
311 |
|
---|
312 | class UDPSocket
|
---|
313 | def initialize(af=Socket::AF_INET)
|
---|
314 | super(Socket._socket(af, Socket::SOCK_DGRAM, 0), "r+")
|
---|
315 | @af = af
|
---|
316 | self
|
---|
317 | end
|
---|
318 |
|
---|
319 | def bind(host, port)
|
---|
320 | Socket._bind(self.fileno, _sockaddr_in(port, host))
|
---|
321 | 0
|
---|
322 | end
|
---|
323 |
|
---|
324 | def connect(host, port)
|
---|
325 | Socket._connect(self.fileno, _sockaddr_in(port, host))
|
---|
326 | 0
|
---|
327 | end
|
---|
328 |
|
---|
329 | def recvfrom_nonblock(*args)
|
---|
330 | s = self
|
---|
331 | begin
|
---|
332 | self._setnonblock(true)
|
---|
333 | self.recvfrom(*args)
|
---|
334 | ensure
|
---|
335 | # XXX: self is a SystemcallException here! (should be bug)
|
---|
336 | s._setnonblock(false)
|
---|
337 | end
|
---|
338 | end
|
---|
339 |
|
---|
340 | def send(mesg, flags, host=nil, port=nil)
|
---|
341 | if port
|
---|
342 | super(mesg, flags, _sockaddr_in(port, host))
|
---|
343 | elsif host
|
---|
344 | super(mesg, flags, host)
|
---|
345 | else
|
---|
346 | super(mesg, flags)
|
---|
347 | end
|
---|
348 | end
|
---|
349 |
|
---|
350 | def _sockaddr_in(port, host)
|
---|
351 | ai = Addrinfo.getaddrinfo(host, port, @af, Socket::SOCK_DGRAM)[0]
|
---|
352 | ai.to_sockaddr
|
---|
353 | end
|
---|
354 | end
|
---|
355 |
|
---|
356 | class Socket
|
---|
357 | def initialize(domain, type, protocol=0)
|
---|
358 | super(Socket._socket(domain, type, protocol), "r+")
|
---|
359 | end
|
---|
360 |
|
---|
361 | #def self.accept_loop
|
---|
362 |
|
---|
363 | def self.getaddrinfo(nodename, servname, family=nil, socktype=nil, protocol=nil, flags=0)
|
---|
364 | Addrinfo.getaddrinfo(nodename, servname, family, socktype, protocol, flags).map { |ai|
|
---|
365 | ary = ai._to_array
|
---|
366 | ary[2] = nodename
|
---|
367 | ary[4] = ai.afamily
|
---|
368 | ary[5] = ai.socktype
|
---|
369 | ary[6] = ai.protocol
|
---|
370 | ary
|
---|
371 | }
|
---|
372 | end
|
---|
373 |
|
---|
374 | #def self.getnameinfo
|
---|
375 | #def self.ip_address_list
|
---|
376 |
|
---|
377 | def self.open(*args)
|
---|
378 | new(args)
|
---|
379 | end
|
---|
380 |
|
---|
381 | def self.sockaddr_in(port, host)
|
---|
382 | ai = Addrinfo.getaddrinfo(host, port, nil, Socket::SOCK_DGRAM)[0]
|
---|
383 | ai.to_sockaddr
|
---|
384 | end
|
---|
385 |
|
---|
386 | #def self.tcp
|
---|
387 | #def self.tcp_server_loop
|
---|
388 | #def self.tcp_server_sockets
|
---|
389 | #def self.udp_server_loop
|
---|
390 | #def self.udp_server_loop_on
|
---|
391 | #def self.udp_server_recv
|
---|
392 | #def self.udp_server_sockets
|
---|
393 | #def self.unix(path)
|
---|
394 | #def self.unix_server_loop
|
---|
395 | #def self.unix_server_socket
|
---|
396 |
|
---|
397 | def self.unpack_sockaddr_in(sa)
|
---|
398 | Addrinfo.new(sa).ip_unpack.reverse
|
---|
399 | end
|
---|
400 |
|
---|
401 | def self.unpack_sockaddr_un(sa)
|
---|
402 | Addrinfo.new(sa).unix_path
|
---|
403 | end
|
---|
404 |
|
---|
405 | class << self
|
---|
406 | alias pack_sockaddr_in sockaddr_in
|
---|
407 | alias pack_sockaddr_un sockaddr_un
|
---|
408 | alias pair socketpair
|
---|
409 | end
|
---|
410 |
|
---|
411 | def accept
|
---|
412 | fd, addr = self.sysaccept
|
---|
413 | [ Socket.for_fd(fd), addr ]
|
---|
414 | end
|
---|
415 |
|
---|
416 | def accept_nonblock
|
---|
417 | begin
|
---|
418 | self._setnonblock(true)
|
---|
419 | self.accept
|
---|
420 | ensure
|
---|
421 | self._setnonblock(false)
|
---|
422 | end
|
---|
423 | end
|
---|
424 |
|
---|
425 | def bind(sockaddr)
|
---|
426 | sockaddr = sockaddr.to_sockaddr if sockaddr.is_a? Addrinfo
|
---|
427 | Socket._bind(self.fileno, sockaddr)
|
---|
428 | 0
|
---|
429 | end
|
---|
430 |
|
---|
431 | def connect(sockaddr)
|
---|
432 | sockaddr = sockaddr.to_sockaddr if sockaddr.is_a? Addrinfo
|
---|
433 | Socket._connect(self.fileno, sockaddr)
|
---|
434 | 0
|
---|
435 | end
|
---|
436 |
|
---|
437 | def connect_nonblock(sockaddr)
|
---|
438 | begin
|
---|
439 | self._setnonblock(true)
|
---|
440 | self.connect(sockaddr)
|
---|
441 | ensure
|
---|
442 | self._setnonblock(false)
|
---|
443 | end
|
---|
444 | end
|
---|
445 |
|
---|
446 | #def ipv6only!
|
---|
447 |
|
---|
448 | def listen(backlog)
|
---|
449 | Socket._listen(self.fileno, backlog)
|
---|
450 | 0
|
---|
451 | end
|
---|
452 |
|
---|
453 | def recvfrom(maxlen, flags=0)
|
---|
454 | msg, sa = _recvfrom(maxlen, flags)
|
---|
455 | socktype = self.getsockopt(Socket::SOL_SOCKET, Socket::SO_TYPE).int
|
---|
456 | [ msg, Addrinfo.new(sa, Socket::PF_UNSPEC, socktype) ]
|
---|
457 | end
|
---|
458 |
|
---|
459 | def recvfrom_nonblock(*args)
|
---|
460 | begin
|
---|
461 | self._setnonblock(true)
|
---|
462 | self._recvfrom(*args)
|
---|
463 | ensure
|
---|
464 | self._setnonblock(false)
|
---|
465 | end
|
---|
466 | end
|
---|
467 |
|
---|
468 | def sysaccept
|
---|
469 | Socket._accept(self.fileno)[0]
|
---|
470 | end
|
---|
471 | end
|
---|
472 |
|
---|
473 | class UNIXSocket < BasicSocket
|
---|
474 | def initialize(path, &block)
|
---|
475 | if self.is_a? UNIXServer
|
---|
476 | super(path, "r")
|
---|
477 | else
|
---|
478 | super(Socket._socket(Socket::AF_UNIX, Socket::SOCK_STREAM, 0), "r+")
|
---|
479 | Socket._connect(self.fileno, Socket.sockaddr_un(path))
|
---|
480 |
|
---|
481 | if block_given?
|
---|
482 | begin
|
---|
483 | yield self
|
---|
484 | ensure
|
---|
485 | begin
|
---|
486 | self.close unless self.closed?
|
---|
487 | rescue StandardError
|
---|
488 | end
|
---|
489 | end
|
---|
490 | end
|
---|
491 | end
|
---|
492 | end
|
---|
493 |
|
---|
494 | def self.socketpair(type=Socket::SOCK_STREAM, protocol=0)
|
---|
495 | a = Socket.socketpair(Socket::AF_UNIX, type, protocol)
|
---|
496 | [ UNIXSocket.for_fd(a[0]), UNIXSocket.for_fd(a[1]) ]
|
---|
497 | end
|
---|
498 |
|
---|
499 | class << self
|
---|
500 | alias pair socketpair
|
---|
501 | end
|
---|
502 |
|
---|
503 | def addr
|
---|
504 | [ "AF_UNIX", path ]
|
---|
505 | end
|
---|
506 |
|
---|
507 | def path
|
---|
508 | Addrinfo.new(self.getsockname).unix_path
|
---|
509 | end
|
---|
510 |
|
---|
511 | def peeraddr
|
---|
512 | [ "AF_UNIX", Addrinfo.new(self.getpeername).unix_path ]
|
---|
513 | end
|
---|
514 |
|
---|
515 | #def recv_io
|
---|
516 |
|
---|
517 | def recvfrom(maxlen, flags=0)
|
---|
518 | msg, sa = _recvfrom(maxlen, flags)
|
---|
519 | path = (sa.size > 0) ? Addrinfo.new(sa).unix_path : ""
|
---|
520 | [ msg, [ "AF_UNIX", path ] ]
|
---|
521 | end
|
---|
522 |
|
---|
523 | #def send_io
|
---|
524 | end
|
---|
525 |
|
---|
526 | class UNIXServer < UNIXSocket
|
---|
527 | def initialize(path)
|
---|
528 | fd = Socket._socket(Socket::AF_UNIX, Socket::SOCK_STREAM, 0)
|
---|
529 | begin
|
---|
530 | super(fd)
|
---|
531 | Socket._bind(fd, Socket.pack_sockaddr_un(path))
|
---|
532 | self.listen(5)
|
---|
533 | rescue => e
|
---|
534 | IO._sysclose(fd) rescue nil
|
---|
535 | raise e
|
---|
536 | end
|
---|
537 |
|
---|
538 | if block_given?
|
---|
539 | begin
|
---|
540 | yield self
|
---|
541 | ensure
|
---|
542 | self.close rescue nil unless self.closed?
|
---|
543 | end
|
---|
544 | end
|
---|
545 | end
|
---|
546 |
|
---|
547 | def accept
|
---|
548 | fd = self.sysaccept
|
---|
549 | begin
|
---|
550 | sock = UNIXSocket.for_fd(fd)
|
---|
551 | rescue
|
---|
552 | IO._sysclose(fd) rescue nil
|
---|
553 | end
|
---|
554 | sock
|
---|
555 | end
|
---|
556 |
|
---|
557 | def accept_nonblock
|
---|
558 | begin
|
---|
559 | self._setnonblock(true)
|
---|
560 | self.accept
|
---|
561 | ensure
|
---|
562 | self._setnonblock(false)
|
---|
563 | end
|
---|
564 | end
|
---|
565 |
|
---|
566 | def listen(backlog)
|
---|
567 | Socket._listen(self.fileno, backlog)
|
---|
568 | 0
|
---|
569 | end
|
---|
570 |
|
---|
571 | def sysaccept
|
---|
572 | Socket._accept(self.fileno)[0]
|
---|
573 | end
|
---|
574 | end
|
---|
575 |
|
---|
576 | class Socket
|
---|
577 | include Constants
|
---|
578 | end
|
---|
579 |
|
---|
580 | class Socket
|
---|
581 | class Option
|
---|
582 | def initialize(family, level, optname, data)
|
---|
583 | @family = family
|
---|
584 | @level = level
|
---|
585 | @optname = optname
|
---|
586 | @data = data
|
---|
587 | end
|
---|
588 |
|
---|
589 | def self.bool(family, level, optname, bool)
|
---|
590 | self.new(family, level, optname, [(bool ? 1 : 0)].pack('i'))
|
---|
591 | end
|
---|
592 |
|
---|
593 | def self.int(family, level, optname, integer)
|
---|
594 | self.new(family, level, optname, [integer].pack('i'))
|
---|
595 | end
|
---|
596 |
|
---|
597 | #def self.linger(family, level, optname, integer)
|
---|
598 | #end
|
---|
599 |
|
---|
600 | attr_reader :data, :family, :level, :optname
|
---|
601 |
|
---|
602 | def bool
|
---|
603 | @data.unpack('i')[0] != 0
|
---|
604 | end
|
---|
605 |
|
---|
606 | def inspect
|
---|
607 | "#<Socket::Option: family:#{@family} level:#{@level} optname:#{@optname} #{@data.inspect}>"
|
---|
608 | end
|
---|
609 |
|
---|
610 | def int
|
---|
611 | @data.unpack('i')[0]
|
---|
612 | end
|
---|
613 |
|
---|
614 | def linger
|
---|
615 | raise NotImplementedError.new
|
---|
616 | end
|
---|
617 |
|
---|
618 | def unpack(template)
|
---|
619 | raise NotImplementedError.new
|
---|
620 | end
|
---|
621 | end
|
---|
622 | end
|
---|
623 |
|
---|
624 | class SocketError < StandardError; end
|
---|