libp2p-dht/libp2pdht/private/eth/p2p/discoveryv5/messages.nim

152 lines
4.2 KiB
Nim

# codex-dht - Codex DHT
# Copyright (c) 2022 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.
#
## Discovery v5 Protocol Messages as specified at
## https://github.com/ethereum/devp2p/blob/master/discv5/discv5-wire.md#protocol-messages
## These messages get protobuf encoded, while in the spec they get RLP encoded.
##
{.push raises: [Defect].}
import
std/[hashes, net],
bearssl/rand,
./spr,
./node,
../../../../dht/providers_messages,
../../../../dht/value_messages
export providers_messages
export value_messages
type
MessageKind* {.pure.} = enum
# TODO This is needed only to make Nim 1.2.6 happy
# Without it, the `MessageKind` type cannot be used as
# a discriminator in case objects.
unused = 0x00
ping = 0x01
pong = 0x02
findNode = 0x03
nodes = 0x04
talkReq = 0x05
talkResp = 0x06
regTopic = 0x07
ticket = 0x08
regConfirmation = 0x09
topicQuery = 0x0A
addProvider = 0x0B
getProviders = 0x0C
providers = 0x0D
addValue = 0x0E
getValue = 0x0F
respValue = 0x10
findNodeFast = 0x83
RequestId* = object
id*: seq[byte]
PingMessage* = object
sprSeq*: uint64
PongMessage* = object
sprSeq*: uint64
ip*: IpAddress
port*: uint16
FindNodeMessage* = object
distances*: seq[uint16]
FindNodeFastMessage* = object
target*: NodeId
NodesMessage* = object
total*: uint32
sprs*: seq[SignedPeerRecord]
TalkReqMessage* = object
protocol*: seq[byte]
request*: seq[byte]
TalkRespMessage* = object
response*: seq[byte]
# Not implemented, specification is not final here.
RegTopicMessage* = object
TicketMessage* = object
RegConfirmationMessage* = object
TopicQueryMessage* = object
SomeMessage* = PingMessage or PongMessage or FindNodeMessage or NodesMessage or
TalkReqMessage or TalkRespMessage or AddProviderMessage or GetProvidersMessage or
ProvidersMessage or FindNodeFastMessage or
AddValueMessage or GetValueMessage or ValueMessage
Message* = object
reqId*: RequestId
case kind*: MessageKind
of ping:
ping*: PingMessage
of pong:
pong*: PongMessage
of findNode:
findNode*: FindNodeMessage
of findNodeFast:
findNodeFast*: FindNodeFastMessage
of nodes:
nodes*: NodesMessage
of talkReq:
talkReq*: TalkReqMessage
of talkResp:
talkResp*: TalkRespMessage
of regTopic:
regtopic*: RegTopicMessage
of ticket:
ticket*: TicketMessage
of regConfirmation:
regConfirmation*: RegConfirmationMessage
of topicQuery:
topicQuery*: TopicQueryMessage
of addProvider:
addProvider*: AddProviderMessage
of getProviders:
getProviders*: GetProvidersMessage
of providers:
provs*: ProvidersMessage
of addValue:
addValue*: AddValueMessage
of getValue:
getValue*: GetValueMessage
of respValue:
value*: ValueMessage
else:
discard
template messageKind*(T: typedesc[SomeMessage]): MessageKind =
when T is PingMessage: MessageKind.ping
elif T is PongMessage: MessageKind.pong
elif T is FindNodeMessage: MessageKind.findNode
elif T is FindNodeFastMessage: MessageKind.findNodeFast
elif T is NodesMessage: MessageKind.nodes
elif T is TalkReqMessage: MessageKind.talkReq
elif T is TalkRespMessage: MessageKind.talkResp
elif T is AddProviderMessage: MessageKind.addProvider
elif T is GetProvidersMessage: MessageKind.getProviders
elif T is ProvidersMessage: MessageKind.providers
elif T is AddValueMessage: MessageKind.addValue
elif T is GetValueMessage: MessageKind.getValue
elif T is ValueMessage: MessageKind.respValue
proc hash*(reqId: RequestId): Hash =
hash(reqId.id)
proc init*(T: type RequestId, rng: var HmacDrbgContext): T =
var reqId = RequestId(id: newSeq[byte](8)) # RequestId must be <= 8 bytes
hmacDrbgGenerate(rng, reqId.id)
reqId