import asyncdispatch, asyncnet, os, strformat, strutils from nativesockets import Domain, SockType, Protocol from net import IpAddress, Port, `$` import asyncutils import message import tcp_syni from strutils import format, join from nativesockets import setSockOptInt type # Requests TcpSyniConnect = object srcIp: IpAddress srcPorts: array[3, Port] dstIp: IpAddress dstPorts: array[3, Port] TcpSyniAccept = object dstIp: IpAddress dstPorts: array[3, Port] srcIp: IpAddress srcPorts: array[3, Port] seqNums: array[10, uint32] # FIXME: this should be a seq proc handleRequest(line: string, unixSock: AsyncSocket) {.async.} = var id: string var sock: AsyncSocket var puncher: TcpSyniPuncher try: let args = line.parseArgs(3) id = args[1] case args[0]: of "tcp-syni-connect": let req = parseMessage[TcpSyniConnect](args[2]) proc handleSeqNumbers(seqNumbers: seq[uint32]) {.async.} = let content = @["tcp-syni-accept", $req.srcIp, req.srcPorts.join(","), $req.dstIp, req.dstPorts.join(","), seqNumbers.join(",")].join("|") await unixSock.send(&"progress|{id}|{content}\n") puncher = await initPuncher(req.srcPorts[0], req.dstIp, req.dstPorts) sock = await puncher.connect(handleSeqNumbers) of "tcp-syni-accept": let req = parseMessage[TcpSyniAccept](args[2]) puncher = await initPuncher(req.srcPorts[0], req.dstIp, req.dstPorts, @(req.seqNums)) sock = await puncher.accept() else: raise newException(ValueError, "invalid request") let unixFd = unixSock.getFd.AsyncFD await unixFd.asyncSendMsg(&"ok|{id}\n", @[fromFd(sock.getFd.AsyncFD)]) await puncher.cleanup except PunchHoleError as e: await unixSock.send(&"error|{id}|{e.msg}\n") await puncher.cleanup except ValueError: unixSock.close proc handleRequests(userSock: AsyncSocket) {.async.} = while true: let line = await userSock.recvLine(maxLength = 400) if line.len == 0: break asyncCheck handleRequest(line, userSock) proc handleUsers(sock: AsyncSocket) {.async.} = while true: let user = await sock.accept() asyncCheck handleRequests(user) proc main() = removeFile("/tmp/punchd.socket") let unixSocket = newAsyncSocket(AF_UNIX, SOCK_STREAM, IPPROTO_IP) unixSocket.bindUnix("/tmp/punchd.socket") unixSocket.listen() asyncCheck handleUsers(unixSocket) runForever() when isMainModule: main()