89 lines
2.5 KiB
Nim
89 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: seq[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.} =
|
|
echo "progress! seqNumbers: ", seqNumbers
|
|
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:
|
|
if userSock.isClosed:
|
|
break
|
|
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()
|