source: EcnlProtoTool/trunk/mrbgems/mruby-socket/mrblib/socket.rb@ 331

Last change on this file since 331 was 331, checked in by coas-nagasima, 6 years ago

prototoolに関連するプロジェクトをnewlibからmuslを使うよう変更・更新
ntshellをnewlibの下位の実装から、muslのsyscallの実装に変更・更新
以下のOSSをアップデート
・mruby-1.3.0
・musl-1.1.18
・onigmo-6.1.3
・tcc-0.9.27
以下のOSSを追加
・openssl-1.1.0e
・curl-7.57.0
・zlib-1.2.11
以下のmrbgemsを追加
・iij/mruby-digest
・iij/mruby-env
・iij/mruby-errno
・iij/mruby-iijson
・iij/mruby-ipaddr
・iij/mruby-mock
・iij/mruby-require
・iij/mruby-tls-openssl

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-ruby;charset=UTF-8
File size: 12.4 KB
Line 
1class 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
166end
167
168class 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
208end
209
210class 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
227end
228
229class 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)
267end
268
269class 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
310end
311
312class 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
354end
355
356class 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
471end
472
473class 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
524end
525
526class 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
574end
575
576class Socket
577 include Constants
578end
579
580class 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
622end
623
624class SocketError < StandardError; end
Note: See TracBrowser for help on using the repository browser.