class Rendezvous::Socket::RendezvousSocket

Attributes

rendezvous_url[R]

Public Class Methods

new(rendezvous_url) click to toggle source
# File lib/rendezvous/socket.rb, line 19
def initialize(rendezvous_url)
  @rendezvous_url = rendezvous_url
end

Public Instance Methods

get_peer_endpoint(lport=0) click to toggle source

lport=0 causes OS to select a random high port

# File lib/rendezvous/socket.rb, line 52
def get_peer_endpoint(lport=0)
  log(step: :get_peer_endpoint) {
    response = Excon.get(rendezvous_url, reuseaddr: true)
    rhost, rport = response.body.split(":")
    [response.local_port, response.local_address, rport.to_i, rhost]
  }
end
log(args={}) { || ... } click to toggle source
# File lib/rendezvous/socket.rb, line 23
def log(args={})
  start = Time.now
  puts args.merge(at: :start)
  result = yield
  elapsed = Time.now - start
  puts args.merge(at: :finish, elapsed: elapsed)
  result
end
open() click to toggle source
# File lib/rendezvous/socket.rb, line 67
def open
  peer_socket(*get_peer_endpoint)
end
peer_socket(lport, lhost, rport, rhost) click to toggle source
# File lib/rendezvous/socket.rb, line 60
def peer_socket(lport, lhost, rport, rhost)
  log(step: :connect, lport: lport, rport: rport, rhost: rhost) {
    #punch_nat_nonblock(lport, rhost, rport)
    AcceptOrConnect.new(lport, lhost, rport, rhost).socket
  }
end
punch_nat_nonblock(lport, rhost, rport) click to toggle source
# File lib/rendezvous/socket.rb, line 32
def punch_nat_nonblock(lport, rhost, rport)
  log(step: :punch_nat) {
    #Thread.new do
      begin
        socket = CustomSocket.new
        # set ttl low enough so it crosses our nat but won't reach remote peer.
        socket.setsockopt(::Socket::IPPROTO_IP, ::Socket::IP_TTL, [2].pack("L"))
        socket.bind(lport)

        Timeout::timeout(0.3) do
          socket.connect(rhost,rport)
        end
      rescue Timeout::Error, Errno::ECONNREFUSED, Errno::EADDRNOTAVAIL
        socket.close
      end
  #end
  }
end