punchd/punchd.nim

85 lines
2.5 KiB
Nim

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]
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")
asyncCheck handleUsers(unixSocket)
runForever()
when isMainModule:
main()