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 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.} = proc requestResolver[MsgType](msg: pointer, future: FutureBase) {.gcsafe.} =
var f = Future[Option[MsgType]](future) var f = Future[Option[MsgType]](future)
if not f.finished: if not f.finished:

View File

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

View File

@ -45,9 +45,17 @@ var
template allProtocols*: auto = {.gcsafe.}: gProtocols template allProtocols*: auto = {.gcsafe.}: gProtocols
template devp2pInfo: auto = {.gcsafe.}: gDevp2pInfo 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) 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) = template raisePeerDisconnected(msg: string, r: DisconnectionReason) =
var e = newException(PeerDisconnected, msg) var e = newException(PeerDisconnected, msg)