add timeouts

This commit is contained in:
Christian Ulrich 2020-08-27 00:03:14 +02:00
parent 0fe1b6ac06
commit 006ec73361
No known key found for this signature in database
GPG Key ID: 8241BE099775A097
1 changed files with 20 additions and 8 deletions

View File

@ -1,4 +1,4 @@
import asyncdispatch, asyncnet, strformat import asyncfutures, asyncdispatch, asyncnet, strformat
from net import IpAddress, Port, `$`, `==`, getPrimaryIPAddr, toSockAddr from net import IpAddress, Port, `$`, `==`, getPrimaryIPAddr, toSockAddr
from nativesockets import SockAddr, Sockaddr_storage, SockLen, setSockOptInt from nativesockets import SockAddr, Sockaddr_storage, SockLen, setSockOptInt
import asyncutils import asyncutils
@ -9,6 +9,8 @@ import raw_socket
var IPPROTO_IP {.importc: "IPPROTO_IP", header: "<netinet/in.h>".}: cint var IPPROTO_IP {.importc: "IPPROTO_IP", header: "<netinet/in.h>".}: cint
var IP_TTL {.importc: "IP_TTL", header: "<netinet/in.h>".}: cint var IP_TTL {.importc: "IP_TTL", header: "<netinet/in.h>".}: cint
const Timeout = 3000
type type
TcpSyniPuncher* = ref object TcpSyniPuncher* = ref object
srcIp: IpAddress srcIp: IpAddress
@ -157,22 +159,28 @@ proc connect*(puncher: TcpSyniPuncher,
asyncCheck puncher.captureAndResendAck(captureAckFd, injectAckFd) asyncCheck puncher.captureAndResendAck(captureAckFd, injectAckFd)
await puncher.addFirewallRules() await puncher.addFirewallRules()
try: try:
result = await puncher.connectParallel() let connectParallelFuture = puncher.connectParallel()
await connectParallelFuture or sleepAsync(Timeout)
await puncher.cleanup() await puncher.cleanup()
if connectParallelFuture.finished():
result = connectParallelFuture.read()
else:
raise newException(PunchHoleError, "timeout")
except OSError as e: except OSError as e:
raise newException(PunchHoleError, e.msg) raise newException(PunchHoleError, e.msg)
proc prepareAccept(puncher: TcpSyniPuncher) {.async.} = proc prepareAccept(puncher: TcpSyniPuncher) {.async.} =
# FIXME: timeouts
for dstPort in puncher.dstPorts: for dstPort in puncher.dstPorts:
try: try:
let sock = newAsyncSocket() let sock = newAsyncSocket()
sock.setSockOpt(OptReuseAddr, true) sock.setSockOpt(OptReuseAddr, true)
sock.getFd.setSockOptInt(IPPROTO_IP, IP_TTL, 2) sock.getFd.setSockOptInt(IPPROTO_IP, IP_TTL, 2)
sock.bindAddr(puncher.srcPort, $(puncher.srcIp)) sock.bindAddr(puncher.srcPort, $(puncher.srcIp))
await sock.connect($(puncher.dstIp), dstPort) let connectFuture = sock.connect($(puncher.dstIp), dstPort)
echo "connected during accept phase" await connectFuture or sleepAsync(Timeout)
sock.close() if connectFuture.finished():
echo "connected during accept phase"
sock.close()
except OSError: except OSError:
discard discard
@ -180,7 +188,6 @@ proc accept*(puncher: TcpSyniPuncher): Future[AsyncSocket] {.async.} =
await puncher.prepareAccept() await puncher.prepareAccept()
await puncher.addFirewallRules() await puncher.addFirewallRules()
try: try:
# FIXME: timeout
let rawFd = setupTcpInjectingSocket() let rawFd = setupTcpInjectingSocket()
for dstPort in puncher.dstPorts: for dstPort in puncher.dstPorts:
for seqNum in puncher.seqNums: for seqNum in puncher.seqNums:
@ -200,8 +207,13 @@ proc accept*(puncher: TcpSyniPuncher): Future[AsyncSocket] {.async.} =
sock.bindAddr(puncher.srcPort, $(puncher.srcIp)) sock.bindAddr(puncher.srcPort, $(puncher.srcIp))
sock.listen() sock.listen()
echo &"accepting connections from {puncher.dstIp}:{puncher.dstPorts[0].int}" echo &"accepting connections from {puncher.dstIp}:{puncher.dstPorts[0].int}"
result = await sock.accept() let acceptFuture = sock.accept()
await acceptFuture or sleepAsync(Timeout)
await puncher.cleanup() await puncher.cleanup()
if acceptFuture.finished():
result = acceptFuture.read()
else:
raise newException(PunchHoleError, "timeout")
except OSError as e: except OSError as e:
echo &"accepting connections from {puncher.dstIP}:{puncher.dstPorts[0].int} failed: ", e.msg echo &"accepting connections from {puncher.dstIP}:{puncher.dstPorts[0].int} failed: ", e.msg
await puncher.cleanup() await puncher.cleanup()