96 lines
3.1 KiB
Nim
96 lines
3.1 KiB
Nim
# Nim-LibP2P
|
|
# Copyright (c) 2023 Status Research & Development GmbH
|
|
# Licensed under either of
|
|
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
|
|
# * MIT license ([LICENSE-MIT](LICENSE-MIT))
|
|
# at your option.
|
|
# This file may not be copied, modified, or distributed except according to
|
|
# those terms.
|
|
|
|
{.used.}
|
|
|
|
when (NimMajor, NimMinor) < (1, 4):
|
|
{.push raises: [Defect].}
|
|
else:
|
|
{.push raises: [].}
|
|
|
|
import tables
|
|
import chronos, stew/[byteutils, endians2, shims/net]
|
|
import ../../libp2p/[stream/connection,
|
|
protocols/connectivity/relay/utils,
|
|
transports/tcptransport,
|
|
transports/tortransport,
|
|
upgrademngrs/upgrade,
|
|
multiaddress,
|
|
errors,
|
|
builders]
|
|
|
|
type
|
|
TorServerStub* = ref object of RootObj
|
|
tcpTransport: TcpTransport
|
|
addrTable: Table[string, string]
|
|
|
|
proc new*(
|
|
T: typedesc[TorServerStub]): T {.public.} =
|
|
|
|
T(
|
|
tcpTransport: TcpTransport.new(flags = {ReuseAddr}, upgrade = Upgrade()),
|
|
addrTable: initTable[string, string]())
|
|
|
|
proc registerAddr*(self: TorServerStub, key: string, val: string) =
|
|
self.addrTable[key] = val
|
|
|
|
proc start*(self: TorServerStub, address: TransportAddress) {.async.} =
|
|
let ma = @[MultiAddress.init(address).tryGet()]
|
|
|
|
await self.tcpTransport.start(ma)
|
|
|
|
var msg = newSeq[byte](3)
|
|
while self.tcpTransport.running:
|
|
let connSrc = await self.tcpTransport.accept()
|
|
await connSrc.readExactly(addr msg[0], 3)
|
|
|
|
await connSrc.write(@[05'u8, 00])
|
|
|
|
msg = newSeq[byte](4)
|
|
await connSrc.readExactly(addr msg[0], 4)
|
|
let atyp = msg[3]
|
|
let address = case atyp:
|
|
of Socks5AddressType.IPv4.byte:
|
|
let n = 4 + 2 # +2 bytes for the port
|
|
msg = newSeq[byte](n)
|
|
await connSrc.readExactly(addr msg[0], n)
|
|
var ip: array[4, byte]
|
|
for i, e in msg[0..^3]:
|
|
ip[i] = e
|
|
$(ipv4(ip)) & ":" & $(Port(fromBytesBE(uint16, msg[^2..^1])))
|
|
of Socks5AddressType.IPv6.byte:
|
|
let n = 16 + 2 # +2 bytes for the port
|
|
msg = newSeq[byte](n) # +2 bytes for the port
|
|
await connSrc.readExactly(addr msg[0], n)
|
|
var ip: array[16, byte]
|
|
for i, e in msg[0..^3]:
|
|
ip[i] = e
|
|
$(ipv6(ip)) & ":" & $(Port(fromBytesBE(uint16, msg[^2..^1])))
|
|
of Socks5AddressType.FQDN.byte:
|
|
await connSrc.readExactly(addr msg[0], 1)
|
|
let n = int(uint8.fromBytes(msg[0..0])) + 2 # +2 bytes for the port
|
|
msg = newSeq[byte](n)
|
|
await connSrc.readExactly(addr msg[0], n)
|
|
string.fromBytes(msg[0..^3]) & ":" & $(Port(fromBytesBE(uint16, msg[^2..^1])))
|
|
else:
|
|
raise newException(LPError, "Address not supported")
|
|
|
|
let tcpIpAddr = self.addrTable[$(address)]
|
|
|
|
await connSrc.write(@[05'u8, 00, 00, 01, 00, 00, 00, 00, 00, 00])
|
|
|
|
let connDst = await self.tcpTransport.dial("", MultiAddress.init(tcpIpAddr).tryGet())
|
|
|
|
await bridge(connSrc, connDst)
|
|
await allFutures(connSrc.close(), connDst.close())
|
|
|
|
|
|
proc stop*(self: TorServerStub) {.async.} =
|
|
await self.tcpTransport.stop()
|