diff --git a/dht/providers.nim b/dht/providers.nim index f796316..0719fe0 100644 --- a/dht/providers.nim +++ b/dht/providers.nim @@ -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.} = diff --git a/dht/providers_encoding.nim b/dht/providers_encoding.nim new file mode 100644 index 0000000..cb234f1 --- /dev/null +++ b/dht/providers_encoding.nim @@ -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 diff --git a/dht/providers_messages.nim b/dht/providers_messages.nim new file mode 100644 index 0000000..db59fd9 --- /dev/null +++ b/dht/providers_messages.nim @@ -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]