96 lines
2.8 KiB
Nim
96 lines
2.8 KiB
Nim
import
|
|
net,
|
|
asyncnet,
|
|
asyncdispatch,
|
|
asyncutils,
|
|
punch
|
|
|
|
from strutils import format, join
|
|
from nativesockets import setSockOptInt
|
|
from os import paramCount, paramStr
|
|
|
|
var IPPROTO_IP {.importc: "IPPROTO_IP", header: "<netinet/in.h>".}: cint
|
|
var IP_TTL {.importc: "IP_TTL", header: "<netinet/in.h>".}: cint
|
|
|
|
proc usage() =
|
|
echo("Usage: $# client|server".format(paramStr(0)))
|
|
|
|
proc processInput(client: AsyncSocket) {.async.} =
|
|
while true:
|
|
let input = await asyncReadline()
|
|
await client.send(input & "\c\L")
|
|
|
|
proc connectAsClient(clientAddress: string,
|
|
clientPort: Port,
|
|
serverAddress: string,
|
|
serverPort: Port) {.async.} =
|
|
var client = newAsyncSocket()
|
|
client.setSockOpt(OptReuseAddr, true)
|
|
client.getFd().setSockOptInt(IPPROTO_IP, IP_TTL, 2)
|
|
client.bindAddr(clientPort, clientAddress)
|
|
try:
|
|
echo "trying to connect"
|
|
await client.connect(serverAddress, serverPort)
|
|
let (address, port) = client.getPeerAddr()
|
|
echo("connected to $#:$#!".format(address, port.uint16))
|
|
asyncCheck processInput(client)
|
|
while true:
|
|
let line = await client.recvLine()
|
|
if line.len == 0: break
|
|
echo("server responded: $#".format(line))
|
|
except OSError as e:
|
|
echo("Error: $#".format(e.msg))
|
|
|
|
proc processClient(client: AsyncSocket) {.async.} =
|
|
while true:
|
|
let line = await client.recvLine()
|
|
if line.len == 0: break
|
|
echo("client sent message: $#".format(line))
|
|
await client.send(line & "\c\L")
|
|
|
|
proc runServer(serverAddress: string,
|
|
serverPort: Port,
|
|
clientAddress: string,
|
|
clientPort: Port) {.async.} =
|
|
var server = newAsyncSocket()
|
|
server.setSockOpt(OptReuseAddr, true)
|
|
server.bindAddr(serverPort)
|
|
server.listen()
|
|
echo("listening on port $#".format(serverPort.uint16))
|
|
while true:
|
|
let client = await server.accept()
|
|
let (address, port) = client.getPeerAddr()
|
|
echo("client $#:$# connected!".format(address, port.uint16()))
|
|
asyncCheck processClient(client)
|
|
|
|
proc main() =
|
|
if paramCount() != 1:
|
|
usage()
|
|
return
|
|
let serverAddress = "176.95.209.87"
|
|
let serverPort = Port(80)
|
|
let clientAddress = $getPrimaryIPAddr(parseIpAddress(serverAddress))
|
|
let clientPort = Port(1234)
|
|
case paramStr(1)
|
|
of "client":
|
|
asyncCheck punchHoleAsClient(clientAddress, clientPort, serverAddress, serverPort)
|
|
asyncCheck connectAsClient(clientAddress, clientPort, serverAddress, serverPort)
|
|
try:
|
|
runForever()
|
|
except NetworkInterfaceError as e:
|
|
echo(e.msg)
|
|
except PunchHoleError as e:
|
|
echo(e.msg)
|
|
of "server":
|
|
asyncCheck runServer(serverAddress, serverPort, clientAddress, clientPort)
|
|
try:
|
|
runForever()
|
|
except ValueError:
|
|
echo "server got ValueError!"
|
|
discard
|
|
else:
|
|
usage()
|
|
|
|
when isMainModule:
|
|
main()
|