More flexible definitions of Responders

This commit is contained in:
Zahary Karadjov 2019-06-03 20:05:45 +03:00
parent 1adad7f4da
commit a492e3c218
No known key found for this signature in database
GPG Key ID: C8936F8A3073D609
3 changed files with 34 additions and 14 deletions

View File

@ -23,6 +23,11 @@ template networkState*(connection: Peer, Protocol: type): untyped =
proc initProtocolState*[T](state: T, x: Peer|EthereumNode) {.gcsafe.} = discard
proc resolveFuture[MsgType](msg: pointer, future: FutureBase) {.gcsafe.} =
var f = Future[MsgType](future)
doAssert(not f.finished())
f.complete(cast[ptr MsgType](msg)[])
proc requestResolver[MsgType](msg: pointer, future: FutureBase) {.gcsafe.} =
var f = Future[Option[MsgType]](future)
if not f.finished:

View File

@ -17,9 +17,10 @@ type
timeoutParam*: NimNode
recIdent*: NimNode
recBody*: NimNode
userHandler*: NimNode
protocol*: P2PProtocol
response*: Message
userHandler*: NimNode
initResponderCall*: NimNode
Request* = ref object
queries*: seq[Message]
@ -93,6 +94,7 @@ type
# Code generators
implementMsg*: proc (msg: Message)
implementProtocolInit*: proc (protocol: P2PProtocol): NimNode
afterProtocolInit*: proc (protocol: P2PProtocol)
# Bound symbols to the back-end run-time types and procs
@ -213,6 +215,9 @@ proc init*(T: type P2PProtocol, backendFactory: BackendFactory,
outProcRegistrations: newStmtList())
result.backend = backendFactory(result)
assert(not result.backend.implementProtocolInit.isNil)
assert(not result.backend.ResponderType.isNil)
result.processProtocolBody body
if not result.backend.afterProtocolInit.isNil:
@ -312,6 +317,11 @@ proc ensureTimeoutParam(procDef: NimNode, timeouts: int64): NimNode =
proc hasReqId*(msg: Message): bool =
msg.protocol.useRequestIds and msg.kind in {msgRequest, msgResponse}
proc ResponderType(msg: Message): NimNode =
var resp = if msg.kind == msgRequest: msg.response else: msg
newTree(nnkBracketExpr,
msg.protocol.backend.ResponderType, resp.recIdent)
proc newMsg(protocol: P2PProtocol, kind: MessageKind, id: int,
procDef: NimNode, timeoutParam: NimNode = nil,
response: Message = nil): Message =
@ -354,16 +364,16 @@ proc newMsg(protocol: P2PProtocol, kind: MessageKind, id: int,
assert response != nil
let
peerParam = userHandler.params[1][0]
ResponderType = protocol.backend.ResponderType
ResponseRecord = response.recIdent
ResponderType = result.ResponderType
initResponderCall = newCall(ident"init", ResponderType, peerParam)
if protocol.useRequestIds:
initResponderCall.add reqIdVar
userHandler.addPreludeDefs quote do:
let `responseVar` = `ResponderType`[`ResponseRecord`](peer: `peerParam`,
reqId: `reqIdVar`)
else:
userHandler.addPreludeDefs quote do:
let `responseVar` = `ResponderType`[`ResponseRecord`](peer: `peerParam`)
let `responseVar` = `initResponderCall`
result.initResponderCall = initResponderCall
protocol.outRecvProcs.add userHandler
result.userHandler = userHandler
@ -418,12 +428,9 @@ proc createSendProc*(msg: Message,
# 1 to the correct strongly-typed ResponderType. The incoming procs still
# gets the normal Peer paramter.
let
ResponderTypeHead = msg.protocol.backend.ResponderType
ResponderType = newTree(nnkBracketExpr, ResponderTypeHead, msg.recIdent)
ResponderType = msg.ResponderType
sendProcName = msg.ident
assert ResponderTypeHead != nil
def[3][1][1] = ResponderType
# We create a helper that enables the `response.send()` syntax

View File

@ -45,9 +45,17 @@ var
template allProtocols*: auto = {.gcsafe.}: gProtocols
template devp2pInfo: auto = {.gcsafe.}: gDevp2pInfo
proc init*[MsgName](T: type ResponderWithId[MsgName],
peer: Peer, reqId: int): T =
T(peer: peer, reqId: reqId)
proc init*[MsgName](T: type ResponderWithoutId[MsgName], peer: Peer): T =
T(peer)
chronicles.formatIt(Peer): $(it.remote)
proc disconnect*(peer: Peer, reason: DisconnectionReason, notifyOtherPeer = false) {.gcsafe, async.}
proc disconnect*(peer: Peer, reason: DisconnectionReason,
notifyOtherPeer = false) {.gcsafe, async.}
template raisePeerDisconnected(msg: string, r: DisconnectionReason) =
var e = newException(PeerDisconnected, msg)