class Rendezvous::AcceptOrConnect
Constants
- ADDR_IN_USE_DELAY
- CONNECTION_TIMEOUT
- CONN_REFUSED_DELAY
Attributes
bind_addr[R]
bind_port[R]
dest_addr[R]
dest_port[R]
Public Class Methods
new(bind_port, bind_addr, dest_port, dest_addr)
click to toggle source
# File lib/rendezvous/socket/accept_or_connect.rb, line 14 def initialize(bind_port, bind_addr, dest_port, dest_addr) @bind_port = bind_port @bind_addr = bind_addr @dest_port = dest_port @dest_addr = dest_addr end
Public Instance Methods
new_socket()
click to toggle source
# File lib/rendezvous/socket/accept_or_connect.rb, line 21 def new_socket ::Socket.new(AF_INET, SOCK_STREAM, 0).tap do |s| s.setsockopt(SOL_SOCKET, SO_REUSEADDR, true) s.setsockopt(SOL_SOCKET, SO_REUSEPORT, true) if defined?(SO_REUSEPORT) s.bind(::Socket.sockaddr_in(bind_port, bind_addr)) end end
socket()
click to toggle source
# File lib/rendezvous/socket/accept_or_connect.rb, line 29 def socket Timeout::timeout(CONNECTION_TIMEOUT) { wait_for_accept_or_connect } end
wait_for_accept_or_connect()
click to toggle source
# File lib/rendezvous/socket/accept_or_connect.rb, line 35 def wait_for_accept_or_connect a_thread = Thread.new { # prefer connect over accept if RUBY_PLATFORM =~ /linux/ sleep 2 end s = new_socket s.listen(5) client_socket, addrinfo = s.accept Thread.current["socket"] = client_socket Thread.current["addrinfo"] = addrinfo Thread.current.exit } a_thread.abort_on_exception = true c_thread = Thread.new { begin s = new_socket sockaddr = ::Socket.sockaddr_in(dest_port, dest_addr) s.connect(sockaddr) Thread.current["socket"] = s Thread.current["addrinfo"] = Addrinfo.new(sockaddr) rescue Errno::ECONNREFUSED sleep CONN_REFUSED_DELAY retry rescue Errno::EADDRINUSE sleep ADDR_IN_USE_DELAY retry end Thread.current.exit } c_thread.abort_on_exception = true # wait while both a and c are alive while a_thread.alive? && c_thread.alive? sleep 0.1 end if a_thread.status == false # accept succeded Thread.kill(c_thread) [a_thread["socket"], a_thread["addrinfo"], :accept] elsif c_thread.status == false # connect succeded Thread.kill(a_thread) [c_thread["socket"], c_thread["addrinfo"], :connect] end end