separating message structures and encoding

This commit is contained in:
Csaba Kiraly 2022-02-16 12:58:04 +01:00
parent b6943d3382
commit 043f195e19
3 changed files with 136 additions and 126 deletions

View File

@ -12,97 +12,14 @@ import
stew/byteutils, # toBytes
../eth/p2p/discoveryv5/[protocol, node],
libp2p/routing_record,
libp2p/protobuf/minprotobuf
./providers_messages,
./providers_encoding
type
ProvidersProtocol* = ref object
providers: Table[NodeId, seq[PeerRecord]]
discovery*: protocol.Protocol
AddProviderMessage* = object
cId: NodeId
prov: PeerRecord
GetProvidersMessage* = object
cId: NodeId
ProvidersMessage* = object
total: uint32
provs: seq[PeerRecord]
func getField*(pb: ProtoBuffer, field: int,
nid: var NodeId): ProtoResult[bool] {.inline.} =
## Read ``NodeId`` from ProtoBuf's message and validate it
var buffer: seq[byte]
let res = ? pb.getField(field, buffer)
if not(res):
ok(false)
else:
nid = readUintBE[256](buffer)
ok(true)
func write*(pb: var ProtoBuffer, field: int, nid: NodeId) =
## Write NodeId value ``nodeid`` to object ``pb`` using ProtoBuf's encoding.
write(pb, field, nid.toBytesBE())
func getField*(pb: ProtoBuffer, field: int,
pr: var PeerRecord): ProtoResult[bool] {.inline.} =
## Read ``NodeId`` from ProtoBuf's message and validate it
var buffer: seq[byte]
let res = ? pb.getField(field, buffer)
if not(res):
ok(false)
else:
let res2 = PeerRecord.decode(buffer)
if res2.isOk():
pr = res2.get()
ok(true)
else:
err(ProtoError.IncorrectBlob)
func write*(pb: var ProtoBuffer, field: int, pr: PeerRecord) =
## Write PeerRecord value ``pr`` to object ``pb`` using ProtoBuf's encoding.
write(pb, field, pr.encode())
proc getRepeatedField*(pb: ProtoBuffer, field: int,
value: var seq[PeerRecord]): ProtoResult[bool] {.
inline.} =
var items: seq[seq[byte]]
value.setLen(0)
let res = ? pb.getRepeatedField(field, items)
if not(res):
ok(false)
else:
for item in items:
let ma = PeerRecord.decode(item)
if ma.isOk():
value.add(ma.get())
else:
value.setLen(0)
return err(ProtoError.IncorrectBlob)
ok(true)
proc decode*(
T: typedesc[AddProviderMessage],
buffer: openArray[byte]): Result[AddProviderMessage, ProtoError] =
let pb = initProtoBuffer(buffer)
var msg = AddProviderMessage()
? pb.getRequiredField(1, msg.cId)
? pb.getRequiredField(2, msg.prov)
ok(msg)
proc encode*(msg: AddProviderMessage): seq[byte] =
var pb = initProtoBuffer()
pb.write(1, msg.cId)
pb.write(2, msg.prov)
pb.finish()
pb.buffer
proc addProviderLocal(p: ProvidersProtocol, cId: NodeId, prov: PeerRecord) =
trace "adding provider to local db", n=p.discovery.localNode, cId, prov
p.providers.mgetOrPut(cId, @[]).add(prov)
@ -149,47 +66,6 @@ proc addProvider*(p: ProvidersProtocol, cId: NodeId, pr: PeerRecord): Future[seq
const
protoIdGetProviders = "GP".toBytes()
proc decode*(
T: typedesc[GetProvidersMessage],
buffer: openArray[byte]): Result[GetProvidersMessage, ProtoError] =
let pb = initProtoBuffer(buffer)
var msg = GetProvidersMessage()
? pb.getRequiredField(1, msg.cId)
ok(msg)
proc encode*(msg: GetProvidersMessage): seq[byte] =
var pb = initProtoBuffer()
pb.write(1, msg.cId)
pb.finish()
pb.buffer
proc decode*(
T: typedesc[ProvidersMessage],
buffer: openArray[byte]): Result[ProvidersMessage, ProtoError] =
let pb = initProtoBuffer(buffer)
var msg = ProvidersMessage()
? pb.getRequiredField(1, msg.total)
discard ? pb.getRepeatedField(2, msg.provs)
ok(msg)
proc encode*(msg: ProvidersMessage): seq[byte] =
var pb = initProtoBuffer()
pb.write(1, msg.total)
for prov in msg.provs:
pb.write(2, prov)
pb.finish()
pb.buffer
proc sendGetProviders(p: ProvidersProtocol, dst: Node,
cId: NodeId): Future[ProvidersMessage]
{.async.} =

119
dht/providers_encoding.nim Normal file
View File

@ -0,0 +1,119 @@
import
../eth/p2p/discoveryv5/[node],
libp2p/routing_record,
libp2p/protobuf/minprotobuf,
./providers_messages
func getField*(pb: ProtoBuffer, field: int,
nid: var NodeId): ProtoResult[bool] {.inline.} =
## Read ``NodeId`` from ProtoBuf's message and validate it
var buffer: seq[byte]
let res = ? pb.getField(field, buffer)
if not(res):
ok(false)
else:
nid = readUintBE[256](buffer)
ok(true)
func write*(pb: var ProtoBuffer, field: int, nid: NodeId) =
## Write NodeId value ``nodeid`` to object ``pb`` using ProtoBuf's encoding.
write(pb, field, nid.toBytesBE())
func getField*(pb: ProtoBuffer, field: int,
pr: var PeerRecord): ProtoResult[bool] {.inline.} =
## Read ``NodeId`` from ProtoBuf's message and validate it
var buffer: seq[byte]
let res = ? pb.getField(field, buffer)
if not(res):
ok(false)
else:
let res2 = PeerRecord.decode(buffer)
if res2.isOk():
pr = res2.get()
ok(true)
else:
err(ProtoError.IncorrectBlob)
func write*(pb: var ProtoBuffer, field: int, pr: PeerRecord) =
## Write PeerRecord value ``pr`` to object ``pb`` using ProtoBuf's encoding.
write(pb, field, pr.encode())
proc getRepeatedField*(pb: ProtoBuffer, field: int,
value: var seq[PeerRecord]): ProtoResult[bool] {.
inline.} =
var items: seq[seq[byte]]
value.setLen(0)
let res = ? pb.getRepeatedField(field, items)
if not(res):
ok(false)
else:
for item in items:
let ma = PeerRecord.decode(item)
if ma.isOk():
value.add(ma.get())
else:
value.setLen(0)
return err(ProtoError.IncorrectBlob)
ok(true)
proc decode*(
T: typedesc[AddProviderMessage],
buffer: openArray[byte]): Result[AddProviderMessage, ProtoError] =
let pb = initProtoBuffer(buffer)
var msg = AddProviderMessage()
? pb.getRequiredField(1, msg.cId)
? pb.getRequiredField(2, msg.prov)
ok(msg)
proc encode*(msg: AddProviderMessage): seq[byte] =
var pb = initProtoBuffer()
pb.write(1, msg.cId)
pb.write(2, msg.prov)
pb.finish()
pb.buffer
proc decode*(
T: typedesc[GetProvidersMessage],
buffer: openArray[byte]): Result[GetProvidersMessage, ProtoError] =
let pb = initProtoBuffer(buffer)
var msg = GetProvidersMessage()
? pb.getRequiredField(1, msg.cId)
ok(msg)
proc encode*(msg: GetProvidersMessage): seq[byte] =
var pb = initProtoBuffer()
pb.write(1, msg.cId)
pb.finish()
pb.buffer
proc decode*(
T: typedesc[ProvidersMessage],
buffer: openArray[byte]): Result[ProvidersMessage, ProtoError] =
let pb = initProtoBuffer(buffer)
var msg = ProvidersMessage()
? pb.getRequiredField(1, msg.total)
discard ? pb.getRepeatedField(2, msg.provs)
ok(msg)
proc encode*(msg: ProvidersMessage): seq[byte] =
var pb = initProtoBuffer()
pb.write(1, msg.total)
for prov in msg.provs:
pb.write(2, prov)
pb.finish()
pb.buffer

View File

@ -0,0 +1,15 @@
import
../eth/p2p/discoveryv5/[node],
libp2p/routing_record
type
AddProviderMessage* = object
cId*: NodeId
prov*: PeerRecord
GetProvidersMessage* = object
cId*: NodeId
ProvidersMessage* = object
total*: uint32
provs*: seq[PeerRecord]