implement primitive probing of the rendezvous server's public IP and provide it to LAN clients
This commit is contained in:
parent
32ecd8074c
commit
4f64b7be53
|
@ -1,9 +1,9 @@
|
|||
import asyncdispatch, asyncnet, os, strformat, strutils, tables
|
||||
from net import IpAddress, Port, `$`
|
||||
import asyncdispatch, asyncnet, os, sequtils, strformat, strutils, tables
|
||||
from nativesockets import htonl
|
||||
from net import IpAddress, Port, getPrimaryIPAddr, parseIpAddress, `$`
|
||||
import ../../asyncutils
|
||||
import ../../message
|
||||
|
||||
# TODO: we need to find out our own external IP and return it to clients who
|
||||
# connect from our LAN
|
||||
import ../../network_interface
|
||||
|
||||
type
|
||||
Client = object
|
||||
|
@ -25,12 +25,49 @@ type
|
|||
recipient: string
|
||||
data: string
|
||||
|
||||
proc isPrivateIp(ip: IpAddress): bool =
|
||||
const ranges: array[5, tuple[first: IpAddress, last: IpAddress]] =
|
||||
[(parseIpAddress("10.0.0.0"), parseIpAddress("10.255.255.255")),
|
||||
(parseIpAddress("172.16.0.0"), parseIpAddress("172.31.255.255")),
|
||||
(parseIpAddress("192.168.0.0"), parseIpAddress("192.168.255.255")),
|
||||
(parseIpAddress("169.254.0.0"), parseIpAddress("169.254.255.255")),
|
||||
(parseIpAddress("127.0.0.0"), parseIpAddress("127.255.255.255"))]
|
||||
for r in ranges:
|
||||
let ipScalar = htonl(cast[uint32](ip.address_v4))
|
||||
if ipScalar > htonl(cast[uint32](r.first.address_v4)) and
|
||||
ipScalar < htonl(cast[uint32](r.last.address_v4)):
|
||||
return true
|
||||
return false
|
||||
|
||||
proc isInNetwork(ip: IpAddress, iface: NetworkInterface): bool =
|
||||
let ipScalar = htonl(cast[uint32](ip.address_v4))
|
||||
let ifaceIpScalar = htonl(cast[uint32](iface.ipAddress.address_v4))
|
||||
let netmaskScalar = htonl(cast[uint32](iface.netmask.address_v4))
|
||||
(ipScalar and netmaskScalar) == (ifaceIpScalar and netmaskScalar)
|
||||
|
||||
proc probePublicIp(): Future[IpAddress] {.async.} =
|
||||
let output = await asyncExecCmd("ping -R -c 1 -s 1 -n 193.0.14.129")
|
||||
let ipLines = output.splitLines()
|
||||
.filter(proc(l: string): bool = l.startsWith("\t") or l.startsWith("RR:"))
|
||||
.map(proc(l: string): string = l.strip(true, false, {'R', ':', '\t', ' '}))
|
||||
for line in ipLines:
|
||||
let ipAddr = parseIpAddress(line)
|
||||
if not isPrivateIp(ipAddr):
|
||||
return ipAddr
|
||||
block:
|
||||
raise newException(OSError, "cannot probe public IP address")
|
||||
|
||||
proc removeClient(clients: TableRef[string, Client], peerId: string) =
|
||||
if peerId.len > 0: clients.del(peerId)
|
||||
|
||||
proc processClient(client: AsyncSocket, clients: TableRef[string, Client]) {.async.} =
|
||||
let (address, port) = client.getPeerAddr
|
||||
await client.send(&"notify-endpoint|{address}|{port.int}\n")
|
||||
proc processClient(client: AsyncSocket,
|
||||
clients: TableRef[string, Client]) {.async.} =
|
||||
let (address, port) = client.getPeerAddr()
|
||||
var ipAddr = parseIpAddress(address)
|
||||
if ipAddr.isPrivateIp() and
|
||||
ipAddr.isInNetwork(fromIpAddress(getPrimaryIPAddr(ipAddr))):
|
||||
ipAddr = await probePublicIp()
|
||||
await client.send(&"notify-endpoint|{ipAddr}|{port.int}\n")
|
||||
var id = ""
|
||||
var peerId = ""
|
||||
while true:
|
||||
|
|
Loading…
Reference in New Issue