Further simplifications

This commit is contained in:
Zahary Karadjov 2019-05-30 21:57:12 +03:00
parent c060c0fc5d
commit e177d17762
No known key found for this signature in database
GPG Key ID: C8936F8A3073D609
2 changed files with 44 additions and 97 deletions

View File

@ -68,7 +68,7 @@ type
peer*: Peer
stream*: P2PStream
Response*[MsgType] = distinct UntypedResponse
Responder*[MsgType] = distinct UntypedResponse
Bytes = seq[byte]
@ -82,6 +82,7 @@ type
const
defaultIncomingReqTimeout = 5000
defaultOutgoingReqTimeout = 10000
HandshakeTimeout = BreachOfProtocol
var
gProtocols: seq[ProtocolInfo]
@ -272,7 +273,7 @@ template getRecipient(peer: Peer): Peer =
template getRecipient(stream: P2PStream): P2PStream =
stream
template getRecipient(response: Response): Peer =
template getRecipient(response: Responder): Peer =
UntypedResponse(response).peer
proc initProtocol(name: string,
@ -329,7 +330,7 @@ proc p2pProtocolBackendImpl*(p: P2PProtocol): Backend =
Format = ident"SSZ"
Option = bindSym "Option"
UntypedResponse = bindSym "UntypedResponse"
Response = bindSym "Response"
Responder = bindSym "Responder"
DaemonAPI = bindSym "DaemonAPI"
P2PStream = ident "P2PStream"
# XXX: Binding the int type causes instantiation failure for some reason
@ -368,20 +369,21 @@ proc p2pProtocolBackendImpl*(p: P2PProtocol): Backend =
result.registerProtocol = bindSym "registerProtocol"
result.setEventHandlers = bindSym "setEventHandlers"
result.SerializationFormat = Format
result.ResponseType = Response
result.ResponderType = Responder
result.afterProtocolInit = proc (p: P2PProtocol) =
p.onPeerConnected.params.add newIdentDefs(ident"handshakeStream", P2PStream)
result.implementMsg = proc (p: P2PProtocol, msg: Message, resp: Message = nil) =
result.implementMsg = proc (msg: Message) =
let
n = msg.procDef
protocol = msg.protocol
msgId = newLit(msg.id)
msgIdent = n.name
msgName = $msgIdent
msgKind = msg.kind
msgRecName = msg.recIdent
responseRecord = if resp != nil: resp.recIdent else: nil
ResponseRecord = if msg.response != nil: msg.response.recIdent else: nil
userPragmas = n.pragma
var
@ -415,14 +417,14 @@ proc p2pProtocolBackendImpl*(p: P2PProtocol): Backend =
extraDefs = quote do:
# Jump through some hoops to work aroung
# https://github.com/nim-lang/Nim/issues/6248
let `response` = `Response`[`responseRecord`](
let `response` = `Responder`[`ResponseRecord`](
`UntypedResponse`(peer: `peer`, stream: `stream`))
# Resolve the Eth2Peer from the LibP2P data received in the thunk
userHandlerCall.add peerIdent
msg.userHandler.addPreludeDefs extraDefs
p.outRecvProcs.add msg.userHandler
protocol.outRecvProcs.add msg.userHandler
elif msgName == "status":
#awaitUserHandler = quote do:
@ -455,14 +457,11 @@ proc p2pProtocolBackendImpl*(p: P2PProtocol): Backend =
`awaitUserHandler`
`resolveNextMsgFutures`(`peerIdent`, get(`receivedMsg`))
for p in userPragmas:
thunkProc.addPragma p
p.outRecvProcs.add thunkProc
protocol.outRecvProcs.add thunkProc
var msgSendProc = n
let msgSendProcName = n.name
p.outSendProcs.add msgSendProc
protocol.outSendProcs.add msgSendProc
# TODO: check that the first param has the correct type
msgSendProc.params[1][0] = sendTo
@ -478,9 +477,9 @@ proc p2pProtocolBackendImpl*(p: P2PProtocol): Backend =
# from a certain request. Here we change the Peer parameter at position
# 1 to the correct strongly-typed ResponseType. The incoming procs still
# gets the normal Peer paramter.
let ResponseType = newTree(nnkBracketExpr, Response, msgRecName)
let ResponseType = newTree(nnkBracketExpr, Responder, msgRecName)
msgSendProc.params[1][1] = ResponseType
p.outSendProcs.add quote do:
protocol.outSendProcs.add quote do:
template send*(r: `ResponseType`, args: varargs[untyped]): auto =
`msgSendProcName`(r, args)
else: discard
@ -488,7 +487,7 @@ proc p2pProtocolBackendImpl*(p: P2PProtocol): Backend =
# We change the return type of the sending proc to a Future.
# If this is a request proc, the future will return the response record.
let rt = if msgKind != msgRequest: Void
else: newTree(nnkBracketExpr, Option, responseRecord)
else: newTree(nnkBracketExpr, Option, ResponseRecord)
msgSendProc.params[0] = newTree(nnkBracketExpr, ident("Future"), rt)
if msgKind == msgHandshake:
@ -516,7 +515,7 @@ proc p2pProtocolBackendImpl*(p: P2PProtocol): Backend =
return `getAst`(`handshakeImpl`(`msgRecName`, peer, stream, lazySendCall, timeout))
p.outSendProcs.add handshakeExchanger.def
protocol.outSendProcs.add handshakeExchanger.def
msgSendProc.params[1][1] = P2PStream
msgSendProc.name = ident rawSendProc
@ -553,7 +552,7 @@ proc p2pProtocolBackendImpl*(p: P2PProtocol): Backend =
if msgKind == msgRequest:
let timeout = msg.timeoutParam[0]
quote: `makeEth2Request`(`msgRecipient`, `msgProto`, `msgBytes`,
`responseRecord`, `timeout`)
`ResponseRecord`, `timeout`)
elif msgId.intVal == 0:
quote: `sendBytes`(`sendTo`, `msgBytes`)
else:
@ -568,9 +567,9 @@ proc p2pProtocolBackendImpl*(p: P2PProtocol): Backend =
`finalizeRequest`
return `sendCall`
p.outProcRegistrations.add(
protocol.outProcRegistrations.add(
newCall(registerMsg,
p.protocolInfoVar,
protocol.protocolInfoVar,
newLit(msgName),
thunkName,
msgProto,

View File

@ -34,7 +34,7 @@ type
CompressedMsgId = tuple
protocolIndex, msgId: int
ResponseWithId*[MsgType] = object
ResponderWithId*[MsgType] = object
peer*: Peer
id*: int
@ -411,15 +411,12 @@ proc prepareRequest(peer: Peer,
proc implementSendProcBody(sendProc: SendProc) =
let
msg = sendProc.msg
resultIdent = ident "result"
delayedWriteCursor = ident "delayedWriteCursor"
proc preludeGenerator(stream: NimNode): NimNode =
result = newStmtList()
if msg.kind == msgRequest:
let
reqId = ident "reqId"
appendPackedObject = bindSym "appendPackedObject"
requestMethodId = newLit(msg.id)
responseMethodId = newLit(msg.response.id)
peer = sendProc.peerParam
@ -428,7 +425,8 @@ proc implementSendProcBody(sendProc: SendProc) =
result.add quote do:
let `delayedWriteCursor` = `prepareRequest`(
`peer`, `protocol`, `requestMethodId`, `responseMethodId`, `stream`, `timeout`, `resultIdent`)
`peer`, `protocol`, `requestMethodId`, `responseMethodId`,
`stream`, `timeout`, `resultIdent`)
proc sendCallGenerator(peer, bytes: NimNode): NimNode =
let
@ -452,17 +450,13 @@ proc implementSendProcBody(sendProc: SendProc) =
proc p2pProtocolBackendImpl*(p: P2PProtocol): Backend =
let
resultIdent = ident "result"
Option = bindSym "Option"
# XXX: Binding the int type causes instantiation failure for some reason
# Int = bindSym "int"
Int = ident "int"
Peer = bindSym "Peer"
EthereumNode = bindSym "EthereumNode"
Format = bindSym "SSZ"
Response = bindSym "Response"
ResponseWithId = bindSym "ResponseWithId"
ResponderWithId = bindSym "ResponderWithId"
perProtocolMsgId = ident"perProtocolMsgId"
mount = bindSym "mount"
@ -474,9 +468,8 @@ proc p2pProtocolBackendImpl*(p: P2PProtocol): Backend =
nextMsg = bindSym "nextMsg"
initProtocol = bindSym "initProtocol"
registerMsg = bindSym "registerMsg"
handshakeImpl = bindSym "handshakeImpl"
peer = ident "peer"
reqId = ident "reqId"
stream = ident "stream"
protocol = ident "protocol"
response = ident "response"
@ -494,41 +487,17 @@ proc p2pProtocolBackendImpl*(p: P2PProtocol): Backend =
result.PeerType = Peer
result.NetworkType = EthereumNode
result.SerializationFormat = Format
result.ResponseType = ResponseWithId
result.implementMsg = proc (protocol: P2PProtocol, msg: Message) =
p.useRequestIds = true
result.ResponderType = ResponderWithId
result.implementMsg = proc (msg: Message) =
var
msgIdLit = newLit(msg.id)
msgRecName = msg.recIdent
msgKind = msg.kind
n = msg.procDef
responseMethodId = if msg.response != nil: msg.response.id else: -1
responseRecord = if msg.response != nil: msg.response.recIdent else: nil
msgIdent = n.name
msgIdent = msg.ident
msgName = $msgIdent
hasReqIds = msgKind in {msgRequest, msgResponse}
userPragmas = n.pragma
# variables used in the sending procs
msgRecipient = ident"msgRecipient"
rlpWriter = ident"writer"
paramsToWrite = newSeq[NimNode](0)
perPeerMsgIdVar = ident"perPeerMsgId"
##
## Augment user handler
##
if msg.userHandler != nil:
if msgKind == msgRequest:
msg.userHandler.params.insert(2, newIdentDefs(reqId, Int))
let peerParam = msg.userHandler.params[1][0]
let extraDefs = quote do:
let `response` = `ResponseWithId`[`responseRecord`](peer: `peerParam`, id: `reqId`)
msg.userHandler.addPreludeDefs extraDefs
protocol.outRecvProcs.add(msg.userHandler)
protocol = msg.protocol
##
## Implemenmt Thunk
@ -538,22 +507,25 @@ proc p2pProtocolBackendImpl*(p: P2PProtocol): Backend =
else:
newStmtList()
# variables used in the receiving procs
let callResolvedResponseFuture = if msgKind == msgResponse:
newCall(resolveResponseFuture, peer, msgIdLit, newCall("addr", receivedMsg), reqId)
let callResolvedResponseFuture = if msg.kind == msgResponse:
newCall(resolveResponseFuture, peer, msgIdLit, newCall("addr", receivedMsg), reqIdVar)
else:
newStmtList()
var userHandlerParams = @[peer]
if msg.kind == msgRequest:
userHandlerParams.add reqIdVar
let
awaitUserHandler = msg.genAwaitUserHandler(receivedMsg, peer, reqId)
thunkName = ident(msgName & "_thunk")
awaitUserHandler = msg.genAwaitUserHandler(receivedMsg, userHandlerParams)
var thunkProc = quote do:
proc `thunkName`(`peer`: `Peer`,
`stream`: `P2PStream`,
`reqId`: uint64,
`reqIdVar`: uint64,
`msgContents`: `ByteStreamVar`) {.async, gcsafe.} =
var `receivedMsg` = `mount`(`SSZ`, `msgContents`, `msgRecName`)
var `receivedMsg` = `mount`(`Format`, `msgContents`, `msgRecName`)
`traceMsg`
`awaitUserHandler`
`callResolvedResponseFuture`
@ -563,37 +535,13 @@ proc p2pProtocolBackendImpl*(p: P2PProtocol): Backend =
##
## Implement Senders and Handshake
##
var sendProc = createSendProc(msg, isRawSender = (msg.kind == msgHandshake))
var sendProc = msg.createSendProc(isRawSender = (msg.kind == msgHandshake))
implementSendProcBody sendProc
protocol.outSendProcs.add sendProc.allDefs
if msg.kind == msgHandshake:
var
rawSendProc = genSym(nskProc, msgName & "RawSend")
handshakeExchanger = createSendProc(msg, procType = nnkTemplateDef)
handshakeExchanger.def.params[0] = newTree(nnkBracketExpr, ident("Future"), msgRecName)
var
forwardCall = newCall(rawSendProc).appendAllParams(handshakeExchanger.def)
peerValue = forwardCall[1]
timeoutValue = msg.timeoutParam[0]
handshakeImpl = ident"handshakeImpl"
forwardCall[1] = peer
forwardCall.del(forwardCall.len - 1)
handshakeExchanger.def.body = quote do:
let `peer` = `peerValue`
let sendingFuture = `forwardCall`
`handshakeImpl`(`peer`,
sendingFuture,
`nextMsg`(`peer`, `msgRecName`),
`timeoutValue`)
sendProc.def.name = rawSendProc
protocol.outSendProcs.add handshakeExchanger.def
else:
implementSendProcBody sendProc
protocol.outSendProcs.add msg.genHandshakeTemplate(sendProc.def.name,
handshakeImpl, nextMsg)
protocol.outProcRegistrations.add(
newCall(registerMsg,