|
|
@ -27,9 +27,10 @@ var IPPROTO_IP {.importc: "IPPROTO_IP", header: "<netinet/in.h>".}: cint |
|
|
|
var IP_TTL {.importc: "IP_TTL", header: "<netinet/in.h>".}: cint |
|
|
|
|
|
|
|
const Timeout = 3000 |
|
|
|
const InitiatorMaxSockCount = 1000 |
|
|
|
const ResponderMaxSockCount = 70 |
|
|
|
const MaxSockCount = max(InitiatorMaxSockCount, ResponderMaxSockCount) |
|
|
|
const InitiatorMaxOutPacketCount = 1000 |
|
|
|
const ResponderMaxOutPacketCount = 70 |
|
|
|
const MaxOutPacketCount = max(InitiatorMaxOutPacketCount, |
|
|
|
ResponderMaxOutPacketCount) |
|
|
|
|
|
|
|
proc srcPort(sock: AsyncSocket): Port = |
|
|
|
result = sock.getLocalAddr[1] |
|
|
@ -50,8 +51,8 @@ proc initPuncher*(sock: AsyncSocket, probedSrcPorts: seq[Port]): Puncher = |
|
|
|
# our NAT is of the evil symmetric type with random port allocation. We are |
|
|
|
# trying to help the other peer by allocating a lot of auxillary sockets |
|
|
|
# for punching more holes |
|
|
|
result.socks.setLen(MaxSockCount) |
|
|
|
for i in 1 .. MaxSockCount - 1: |
|
|
|
result.socks.setLen(MaxOutPacketCount) |
|
|
|
for i in 1 .. MaxOutPacketCount - 1: |
|
|
|
result.socks[i] = newAsyncSocket(sockType = SOCK_DGRAM, |
|
|
|
protocol = IPPROTO_UDP, buffered = false) |
|
|
|
result.socks[i].bindAddr(Port(0)) |
|
|
@ -64,20 +65,18 @@ proc punch(puncher: Puncher, peerIp: IpAddress, peerPort: Port, |
|
|
|
Future[Attempt] {.async.} = |
|
|
|
let punchFuture = newFuture[(AsyncSocket, Port)]("punch") |
|
|
|
let peerNatProps = getNatProperties(peerPort, peerProbedPorts) |
|
|
|
let maxOutPacketCount = if isInitiating: |
|
|
|
InitiatorMaxOutPacketCount |
|
|
|
else: |
|
|
|
ResponderMaxOutPacketCount |
|
|
|
var sockCount = 1 |
|
|
|
if puncher.natProps.natType == SymmetricRandom: |
|
|
|
# Our NAT is of the evil symmetric type with random port allocation. We are |
|
|
|
# trying to help the other peer by punching more holes using all our |
|
|
|
# sockets. |
|
|
|
if peerNatProps.natType == SymmetricRandom: |
|
|
|
# If the other peer is behind a SymmetricRandom NAT too we give up. |
|
|
|
# If both peers are behind a SymmetricRandom NAT we give up. |
|
|
|
raise newException(PunchHoleError, |
|
|
|
"both peers behind symmetric NAT with random port allocation") |
|
|
|
sockCount = if isInitiating: |
|
|
|
InitiatorMaxSockCount |
|
|
|
else: |
|
|
|
ResponderMaxSockCount |
|
|
|
let predictedDstPorts = predictPortRange(peerNatProps, sockCount.uint16) |
|
|
|
sockCount = maxOutPacketCount |
|
|
|
let predictedDstPorts = predictPortRange(peerNatProps, maxOutPacketCount.uint16) |
|
|
|
result = Attempt(dstIp: peerIp, dstPorts: predictedDstPorts, |
|
|
|
future: punchFuture) |
|
|
|
if puncher.attempts.contains(result): |
|
|
|