[279] | 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) { |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 | return
|
---|
| 248 | rescue => e0
|
---|
| 249 | e = e0
|
---|
| 250 | end
|
---|
| 251 | }
|
---|
| 252 | raise e
|
---|
| 253 | end
|
---|
| 254 | end
|
---|
| 255 |
|
---|
| 256 | def self.new_with_prelude pre, *args
|
---|
| 257 | o = self._allocate
|
---|
| 258 | o.instance_eval(&pre)
|
---|
| 259 | o.initialize(*args)
|
---|
| 260 | o
|
---|
| 261 | end
|
---|
| 262 |
|
---|
| 263 | #def self.gethostbyname(host)
|
---|
| 264 | end
|
---|
| 265 |
|
---|
| 266 | class TCPServer
|
---|
| 267 | def initialize(host=nil, service)
|
---|
| 268 | ai = Addrinfo.getaddrinfo(host, service, nil, nil, nil, Socket::AI_PASSIVE)[0]
|
---|
| 269 | @init_with_fd = true
|
---|
| 270 | super(Socket._socket(ai.afamily, Socket::SOCK_STREAM, 0), "r+")
|
---|
| 271 | if Socket.const_defined?(:SO_REUSEADDR)
|
---|
| 272 | self.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, true)
|
---|
| 273 | end
|
---|
| 274 | Socket._bind(self.fileno, ai.to_sockaddr)
|
---|
| 275 | listen(5)
|
---|
| 276 | self
|
---|
| 277 | end
|
---|
| 278 |
|
---|
| 279 | def accept
|
---|
| 280 | fd = self.sysaccept
|
---|
| 281 | begin
|
---|
| 282 | proc = Proc.new { @init_with_fd = true }
|
---|
| 283 | TCPSocket.new_with_prelude(proc, fd, "r+")
|
---|
| 284 | rescue
|
---|
| 285 | IO._sysclose(fd) rescue nil
|
---|
| 286 | raise
|
---|
| 287 | end
|
---|
| 288 | end
|
---|
| 289 |
|
---|
| 290 | def accept_nonblock
|
---|
| 291 | begin
|
---|
| 292 | self._setnonblock(true)
|
---|
| 293 | self.accept
|
---|
| 294 | ensure
|
---|
| 295 | self._setnonblock(false)
|
---|
| 296 | end
|
---|
| 297 | end
|
---|
| 298 |
|
---|
| 299 | def listen(backlog)
|
---|
| 300 | Socket._listen(self.fileno, backlog)
|
---|
| 301 | 0
|
---|
| 302 | end
|
---|
| 303 |
|
---|
| 304 | def sysaccept
|
---|
| 305 | Socket._accept(self.fileno)[0]
|
---|
| 306 | end
|
---|
| 307 | end
|
---|
| 308 |
|
---|
| 309 | class UDPSocket
|
---|
| 310 | def initialize(af=Socket::AF_INET)
|
---|
| 311 | super(Socket._socket(af, Socket::SOCK_DGRAM, 0), "r+")
|
---|
| 312 | @af = af
|
---|
| 313 | self
|
---|
| 314 | end
|
---|
| 315 |
|
---|
| 316 | def bind(host, port)
|
---|
| 317 | Socket._bind(self.fileno, _sockaddr_in(port, host))
|
---|
| 318 | 0
|
---|
| 319 | end
|
---|
| 320 |
|
---|
| 321 | def connect(host, port)
|
---|
| 322 | Socket._connect(self.fileno, _sockaddr_in(port, host))
|
---|
| 323 | 0
|
---|
| 324 | end
|
---|
| 325 |
|
---|
| 326 | def recvfrom_nonblock(*args)
|
---|
| 327 | s = self
|
---|
| 328 | begin
|
---|
| 329 | self._setnonblock(true)
|
---|
| 330 | self.recvfrom(*args)
|
---|
| 331 | ensure
|
---|
| 332 | # XXX: self is a SystemcallException here! (should be bug)
|
---|
| 333 | s._setnonblock(false)
|
---|
| 334 | end
|
---|
| 335 | end
|
---|
| 336 |
|
---|
| 337 | def send(mesg, flags, host=nil, port=nil)
|
---|
| 338 | if port
|
---|
| 339 | super(mesg, flags, _sockaddr_in(port, host))
|
---|
| 340 | elsif host
|
---|
| 341 | super(mesg, flags, host)
|
---|
| 342 | else
|
---|
| 343 | super(mesg, flags)
|
---|
| 344 | end
|
---|
| 345 | end
|
---|
| 346 |
|
---|
| 347 | def _sockaddr_in(port, host)
|
---|
| 348 | ai = Addrinfo.getaddrinfo(host, port, @af, Socket::SOCK_DGRAM)[0]
|
---|
| 349 | ai.to_sockaddr
|
---|
| 350 | end
|
---|
| 351 | end
|
---|
| 352 |
|
---|
| 353 | class Socket
|
---|
| 354 | def initialize(domain, type, protocol=0)
|
---|
| 355 | super(Socket._socket(domain, type, protocol), "r+")
|
---|
| 356 | end
|
---|
| 357 |
|
---|
| 358 | #def self.accept_loop
|
---|
| 359 |
|
---|
| 360 | def self.getaddrinfo(nodename, servname, family=nil, socktype=nil, protocol=nil, flags=0)
|
---|
| 361 | Addrinfo.getaddrinfo(nodename, servname, family, socktype, protocol, flags).map { |ai|
|
---|
| 362 | ary = ai._to_array
|
---|
| 363 | ary[2] = nodename
|
---|
| 364 | ary[4] = ai.afamily
|
---|
| 365 | ary[5] = ai.socktype
|
---|
| 366 | ary[6] = ai.protocol
|
---|
| 367 | ary
|
---|
| 368 | }
|
---|
| 369 | end
|
---|
| 370 |
|
---|
| 371 | #def self.getnameinfo
|
---|
| 372 | #def self.ip_address_list
|
---|
| 373 |
|
---|
| 374 | def self.open(*args)
|
---|
| 375 | new(args)
|
---|
| 376 | end
|
---|
| 377 |
|
---|
| 378 | def self.sockaddr_in(port, host)
|
---|
| 379 | ai = Addrinfo.getaddrinfo(host, port, nil, Socket::SOCK_DGRAM)[0]
|
---|
| 380 | ai.to_sockaddr
|
---|
| 381 | end
|
---|
| 382 |
|
---|
| 383 | #def self.tcp
|
---|
| 384 | #def self.tcp_server_loop
|
---|
| 385 | #def self.tcp_server_sockets
|
---|
| 386 | #def self.udp_server_loop
|
---|
| 387 | #def self.udp_server_loop_on
|
---|
| 388 | #def self.udp_server_recv
|
---|
| 389 | #def self.udp_server_sockets
|
---|
| 390 | #def self.unix(path)
|
---|
| 391 | #def self.unix_server_loop
|
---|
| 392 | #def self.unix_server_socket
|
---|
| 393 |
|
---|
| 394 | def self.unpack_sockaddr_in(sa)
|
---|
| 395 | Addrinfo.new(sa).ip_unpack.reverse
|
---|
| 396 | end
|
---|
| 397 |
|
---|
| 398 | def self.unpack_sockaddr_un(sa)
|
---|
| 399 | Addrinfo.new(sa).unix_path
|
---|
| 400 | end
|
---|
| 401 |
|
---|
| 402 | class << self
|
---|
| 403 | alias pack_sockaddr_in sockaddr_in
|
---|
| 404 | alias pack_sockaddr_un sockaddr_un
|
---|
| 405 | alias pair socketpair
|
---|
| 406 | end
|
---|
| 407 |
|
---|
| 408 | def accept
|
---|
| 409 | fd, addr = self.sysaccept
|
---|
| 410 | [ Socket.for_fd(fd), addr ]
|
---|
| 411 | end
|
---|
| 412 |
|
---|
| 413 | def accept_nonblock
|
---|
| 414 | begin
|
---|
| 415 | self._setnonblock(true)
|
---|
| 416 | self.accept
|
---|
| 417 | ensure
|
---|
| 418 | self._setnonblock(false)
|
---|
| 419 | end
|
---|
| 420 | end
|
---|
| 421 |
|
---|
| 422 | def bind(sockaddr)
|
---|
| 423 | sockaddr = sockaddr.to_sockaddr if sockaddr.is_a? Addrinfo
|
---|
| 424 | Socket._bind(self.fileno, sockaddr)
|
---|
| 425 | 0
|
---|
| 426 | end
|
---|
| 427 |
|
---|
| 428 | def connect(sockaddr)
|
---|
| 429 | sockaddr = sockaddr.to_sockaddr if sockaddr.is_a? Addrinfo
|
---|
| 430 | Socket._connect(self.fileno, sockaddr)
|
---|
| 431 | 0
|
---|
| 432 | end
|
---|
| 433 |
|
---|
| 434 | def connect_nonblock(sockaddr)
|
---|
| 435 | begin
|
---|
| 436 | self._setnonblock(true)
|
---|
| 437 | self.connect(sockaddr)
|
---|
| 438 | ensure
|
---|
| 439 | self._setnonblock(false)
|
---|
| 440 | end
|
---|
| 441 | end
|
---|
| 442 |
|
---|
| 443 | #def ipv6only!
|
---|
| 444 |
|
---|
| 445 | def listen(backlog)
|
---|
| 446 | Socket._listen(self.fileno, backlog)
|
---|
| 447 | 0
|
---|
| 448 | end
|
---|
| 449 |
|
---|
| 450 | def recvfrom(maxlen, flags=0)
|
---|
| 451 | msg, sa = _recvfrom(maxlen, flags)
|
---|
| 452 | socktype = self.getsockopt(Socket::SOL_SOCKET, Socket::SO_TYPE).int
|
---|
| 453 | [ msg, Addrinfo.new(sa, Socket::PF_UNSPEC, socktype) ]
|
---|
| 454 | end
|
---|
| 455 |
|
---|
| 456 | def recvfrom_nonblock(*args)
|
---|
| 457 | begin
|
---|
| 458 | self._setnonblock(true)
|
---|
| 459 | self._recvfrom(*args)
|
---|
| 460 | ensure
|
---|
| 461 | self._setnonblock(false)
|
---|
| 462 | end
|
---|
| 463 | end
|
---|
| 464 |
|
---|
| 465 | def sysaccept
|
---|
| 466 | Socket._accept(self.fileno)[0]
|
---|
| 467 | end
|
---|
| 468 | end
|
---|
| 469 |
|
---|
| 470 | class UNIXSocket < BasicSocket
|
---|
| 471 | def initialize(path, &block)
|
---|
| 472 | if self.is_a? UNIXServer
|
---|
| 473 | super(path, "r")
|
---|
| 474 | else
|
---|
| 475 | super(Socket._socket(Socket::AF_UNIX, Socket::SOCK_STREAM, 0), "r+")
|
---|
| 476 | Socket._connect(self.fileno, Socket.sockaddr_un(path))
|
---|
| 477 |
|
---|
| 478 | if block_given?
|
---|
| 479 | begin
|
---|
| 480 | yield self
|
---|
| 481 | ensure
|
---|
| 482 | begin
|
---|
| 483 | self.close unless self.closed?
|
---|
| 484 | rescue StandardError
|
---|
| 485 | end
|
---|
| 486 | end
|
---|
| 487 | end
|
---|
| 488 | end
|
---|
| 489 | end
|
---|
| 490 |
|
---|
| 491 | def self.socketpair(type=Socket::SOCK_STREAM, protocol=0)
|
---|
| 492 | a = Socket.socketpair(Socket::AF_UNIX, type, protocol)
|
---|
| 493 | [ UNIXSocket.for_fd(a[0]), UNIXSocket.for_fd(a[1]) ]
|
---|
| 494 | end
|
---|
| 495 |
|
---|
| 496 | class << self
|
---|
| 497 | alias pair socketpair
|
---|
| 498 | end
|
---|
| 499 |
|
---|
| 500 | def addr
|
---|
| 501 | [ "AF_UNIX", path ]
|
---|
| 502 | end
|
---|
| 503 |
|
---|
| 504 | def path
|
---|
| 505 | Addrinfo.new(self.getsockname).unix_path
|
---|
| 506 | end
|
---|
| 507 |
|
---|
| 508 | def peeraddr
|
---|
| 509 | [ "AF_UNIX", Addrinfo.new(self.getpeername).unix_path ]
|
---|
| 510 | end
|
---|
| 511 |
|
---|
| 512 | #def recv_io
|
---|
| 513 |
|
---|
| 514 | def recvfrom(maxlen, flags=0)
|
---|
| 515 | msg, sa = _recvfrom(maxlen, flags)
|
---|
| 516 | path = (sa.size > 0) ? Addrinfo.new(sa).unix_path : ""
|
---|
| 517 | [ msg, [ "AF_UNIX", path ] ]
|
---|
| 518 | end
|
---|
| 519 |
|
---|
| 520 | #def send_io
|
---|
| 521 | end
|
---|
| 522 |
|
---|
| 523 | class UNIXServer < UNIXSocket
|
---|
| 524 | def initialize(path)
|
---|
| 525 | fd = Socket._socket(Socket::AF_UNIX, Socket::SOCK_STREAM, 0)
|
---|
| 526 | begin
|
---|
| 527 | super(fd)
|
---|
| 528 | Socket._bind(fd, Socket.pack_sockaddr_un(path))
|
---|
| 529 | self.listen(5)
|
---|
| 530 | rescue => e
|
---|
| 531 | IO._sysclose(fd) rescue nil
|
---|
| 532 | raise e
|
---|
| 533 | end
|
---|
| 534 |
|
---|
| 535 | if block_given?
|
---|
| 536 | begin
|
---|
| 537 | yield self
|
---|
| 538 | ensure
|
---|
| 539 | self.close rescue nil unless self.closed?
|
---|
| 540 | end
|
---|
| 541 | end
|
---|
| 542 | end
|
---|
| 543 |
|
---|
| 544 | def accept
|
---|
| 545 | fd = self.sysaccept
|
---|
| 546 | begin
|
---|
| 547 | sock = UNIXSocket.for_fd(fd)
|
---|
| 548 | rescue
|
---|
| 549 | IO._sysclose(fd) rescue nil
|
---|
| 550 | end
|
---|
| 551 | sock
|
---|
| 552 | end
|
---|
| 553 |
|
---|
| 554 | def accept_nonblock
|
---|
| 555 | begin
|
---|
| 556 | self._setnonblock(true)
|
---|
| 557 | self.accept
|
---|
| 558 | ensure
|
---|
| 559 | self._setnonblock(false)
|
---|
| 560 | end
|
---|
| 561 | end
|
---|
| 562 |
|
---|
| 563 | def listen(backlog)
|
---|
| 564 | Socket._listen(self.fileno, backlog)
|
---|
| 565 | 0
|
---|
| 566 | end
|
---|
| 567 |
|
---|
| 568 | def sysaccept
|
---|
| 569 | Socket._accept(self.fileno)[0]
|
---|
| 570 | end
|
---|
| 571 | end
|
---|
| 572 |
|
---|
| 573 | class Socket
|
---|
| 574 | include Constants
|
---|
| 575 | end
|
---|
| 576 |
|
---|
| 577 | class Socket
|
---|
| 578 | class Option
|
---|
| 579 | def initialize(family, level, optname, data)
|
---|
| 580 | @family = family
|
---|
| 581 | @level = level
|
---|
| 582 | @optname = optname
|
---|
| 583 | @data = data
|
---|
| 584 | end
|
---|
| 585 |
|
---|
| 586 | def self.bool(family, level, optname, bool)
|
---|
| 587 | self.new(family, level, optname, [(bool ? 1 : 0)].pack('i'))
|
---|
| 588 | end
|
---|
| 589 |
|
---|
| 590 | def self.int(family, level, optname, integer)
|
---|
| 591 | self.new(family, level, optname, [integer].pack('i'))
|
---|
| 592 | end
|
---|
| 593 |
|
---|
| 594 | #def self.linger(family, level, optname, integer)
|
---|
| 595 | #end
|
---|
| 596 |
|
---|
| 597 | attr_reader :data, :family, :level, :optname
|
---|
| 598 |
|
---|
| 599 | def bool
|
---|
| 600 | @data.unpack('i')[0] != 0
|
---|
| 601 | end
|
---|
| 602 |
|
---|
| 603 | def inspect
|
---|
| 604 | "#<Socket::Option: family:#{@family} level:#{@level} optname:#{@optname} #{@data.inspect}>"
|
---|
| 605 | end
|
---|
| 606 |
|
---|
| 607 | def int
|
---|
| 608 | @data.unpack('i')[0]
|
---|
| 609 | end
|
---|
| 610 |
|
---|
| 611 | def linger
|
---|
| 612 | raise NotImplementedError.new
|
---|
| 613 | end
|
---|
| 614 |
|
---|
| 615 | def unpack(template)
|
---|
| 616 | raise NotImplementedError.new
|
---|
| 617 | end
|
---|
| 618 | end
|
---|
| 619 | end
|
---|
| 620 |
|
---|
| 621 | class SocketError < StandardError; end
|
---|