mirror of
https://github.com/status-im/nim-eth.git
synced 2025-02-11 13:36:29 +00:00
* Add initial impl of utp over udp * Add more comments * Add licenses and push declarations * Add tests to nimble task * Pr comments Use better random generator Raise assert error in case of buffer io exception
62 lines
2.2 KiB
Nim
62 lines
2.2 KiB
Nim
# Copyright (c) 2020-2021 Status Research & Development GmbH
|
|
# Licensed and distributed under either of
|
|
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
|
|
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
|
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
|
|
|
{.push raises: [Defect].}
|
|
|
|
import
|
|
chronos, chronicles, bearssl,
|
|
./packets,
|
|
../keys
|
|
|
|
logScope:
|
|
topics = "utp"
|
|
|
|
type
|
|
# For now utp protocol is tied to udp transport, but ultimatly we would like to
|
|
# abstract underlying transport to be able to run utp over udp, discoveryv5 or
|
|
# maybe some test transport
|
|
UtpProtocol* = ref object
|
|
transport: DatagramTransport
|
|
rng*: ref BrHmacDrbgContext
|
|
|
|
UtpSocket* = ref object
|
|
|
|
# TODO not implemented
|
|
# for now just log incoming packets
|
|
proc processPacket(p: Packet) =
|
|
notice "Received packet ", packet = p
|
|
|
|
# Connect to provided address
|
|
# Reference implementation: https://github.com/bittorrent/libutp/blob/master/utp_internal.cpp#L2732
|
|
# TODO not implemented
|
|
proc connectTo*(p: UtpProtocol, address: TransportAddress): Future[UtpSocket] {.async.} =
|
|
let packet = synPacket(p.rng[], randUint16(p.rng[]), 1048576)
|
|
notice "Sending packet", packet = packet
|
|
let packetEncoded = encodePacket(packet)
|
|
await p.transport.sendTo(address, packetEncoded)
|
|
return UtpSocket()
|
|
|
|
proc processDatagram(transp: DatagramTransport, raddr: TransportAddress):
|
|
Future[void] {.async.} =
|
|
# TODO: should we use `peekMessage()` to avoid allocation?
|
|
let buf = try: transp.getMessage()
|
|
except TransportOsError as e:
|
|
# This is likely to be local network connection issues.
|
|
return
|
|
|
|
let dec = decodePacket(buf)
|
|
if (dec.isOk()):
|
|
processPacket(dec.get())
|
|
else:
|
|
warn "failed to decode packet from address", address = raddr
|
|
|
|
proc new*(T: type UtpProtocol, address: TransportAddress, rng = newRng()): UtpProtocol {.raises: [Defect, CatchableError].} =
|
|
let ta = newDatagramTransport(processDatagram, local = address)
|
|
UtpProtocol(transport: ta, rng: rng)
|
|
|
|
proc closeWait*(p: UtpProtocol): Future[void] =
|
|
p.transport.closeWait()
|