mirror of
https://github.com/logos-storage/nim-json-rpc.git
synced 2026-05-18 16:39:27 +00:00
Re-enabled chronicles, extended RpcClientTransport, added stream servers
This commit is contained in:
parent
ce94ba8b41
commit
c162f24253
133
rpc/server.nim
133
rpc/server.nim
@ -1,16 +1,11 @@
|
|||||||
import json, tables, strutils, options, macros #, chronicles
|
import json, tables, strutils, options, macros, chronicles
|
||||||
import asyncdispatch2
|
import asyncdispatch2
|
||||||
import jsonmarshal
|
import jsonmarshal
|
||||||
|
|
||||||
export asyncdispatch2, json, jsonmarshal
|
export asyncdispatch2, json, jsonmarshal
|
||||||
|
|
||||||
# Temporarily disable logging
|
logScope:
|
||||||
macro debug(body: varargs[untyped]): untyped = newStmtList()
|
topics = "RpcServer"
|
||||||
macro info(body: varargs[untyped]): untyped = newStmtList()
|
|
||||||
macro error(body: varargs[untyped]): untyped = newStmtList()
|
|
||||||
|
|
||||||
#logScope:
|
|
||||||
# topics = "RpcServer"
|
|
||||||
|
|
||||||
type
|
type
|
||||||
RpcJsonError* = enum rjeInvalidJson, rjeVersionError, rjeNoMethod, rjeNoId
|
RpcJsonError* = enum rjeInvalidJson, rjeVersionError, rjeNoMethod, rjeNoId
|
||||||
@ -23,12 +18,17 @@ type
|
|||||||
RpcClientTransport* = concept t
|
RpcClientTransport* = concept t
|
||||||
t.write(var string) is Future[int]
|
t.write(var string) is Future[int]
|
||||||
t.readLine(int) is Future[string]
|
t.readLine(int) is Future[string]
|
||||||
|
t.close
|
||||||
|
t.remoteAddress() # Required for logging
|
||||||
|
t.localAddress()
|
||||||
|
|
||||||
RpcServerTransport* = concept t
|
RpcServerTransport* = concept t
|
||||||
t.start
|
t.start
|
||||||
t.stop
|
t.stop
|
||||||
t.close
|
t.close
|
||||||
|
|
||||||
|
RpcProcessClient* = proc (server: RpcServerTransport, client: RpcClientTransport): Future[void] {.gcsafe.}
|
||||||
|
|
||||||
RpcServer*[S: RpcServerTransport] = ref object
|
RpcServer*[S: RpcServerTransport] = ref object
|
||||||
servers*: seq[S]
|
servers*: seq[S]
|
||||||
procs*: TableRef[string, RpcProc]
|
procs*: TableRef[string, RpcProc]
|
||||||
@ -152,7 +152,7 @@ proc processClient*[S: RpcServerTransport, C: RpcClientTransport](server: S, cli
|
|||||||
client.close()
|
client.close()
|
||||||
break
|
break
|
||||||
|
|
||||||
debug "Processing client", addresss = client.remoteAddress(), line
|
debug "Processing client", address = client.remoteAddress(), line
|
||||||
|
|
||||||
let future = processMessage(rpc, client, line)
|
let future = processMessage(rpc, client, line)
|
||||||
yield future
|
yield future
|
||||||
@ -230,7 +230,11 @@ macro rpc*(server: RpcServer, path: string, body: untyped): untyped =
|
|||||||
var
|
var
|
||||||
setup = jsonToNim(parameters, paramsIdent)
|
setup = jsonToNim(parameters, paramsIdent)
|
||||||
procBody = if body.kind == nnkStmtList: body else: body.body
|
procBody = if body.kind == nnkStmtList: body else: body.body
|
||||||
|
errTrappedBody = quote do:
|
||||||
|
try:
|
||||||
|
`procBody`
|
||||||
|
except:
|
||||||
|
debug "Error occurred within RPC " & `path` & ": ", getCurrentExceptionMsg()
|
||||||
if parameters.hasReturnType:
|
if parameters.hasReturnType:
|
||||||
let returnType = parameters[0]
|
let returnType = parameters[0]
|
||||||
|
|
||||||
@ -238,7 +242,7 @@ macro rpc*(server: RpcServer, path: string, body: untyped): untyped =
|
|||||||
result.add(quote do:
|
result.add(quote do:
|
||||||
proc `doMain`(`paramsIdent`: JsonNode): Future[`returnType`] {.async.} =
|
proc `doMain`(`paramsIdent`: JsonNode): Future[`returnType`] {.async.} =
|
||||||
`setup`
|
`setup`
|
||||||
`procBody`
|
`errTrappedBody`
|
||||||
)
|
)
|
||||||
|
|
||||||
if returnType == ident"JsonNode":
|
if returnType == ident"JsonNode":
|
||||||
@ -257,7 +261,7 @@ macro rpc*(server: RpcServer, path: string, body: untyped): untyped =
|
|||||||
result.add(quote do:
|
result.add(quote do:
|
||||||
proc `procName`(`paramsIdent`: JsonNode): Future[JsonNode] {.async.} =
|
proc `procName`(`paramsIdent`: JsonNode): Future[JsonNode] {.async.} =
|
||||||
`setup`
|
`setup`
|
||||||
`procBody`
|
`errTrappedBody`
|
||||||
)
|
)
|
||||||
result.add( quote do:
|
result.add( quote do:
|
||||||
`server`.register(`path`, `procName`)
|
`server`.register(`path`, `procName`)
|
||||||
@ -266,4 +270,109 @@ macro rpc*(server: RpcServer, path: string, body: untyped): untyped =
|
|||||||
when defined(nimDumpRpcs):
|
when defined(nimDumpRpcs):
|
||||||
echo "\n", pathStr, ": ", result.repr
|
echo "\n", pathStr, ": ", result.repr
|
||||||
|
|
||||||
|
# Utility functions for setting up servers using transport addresses
|
||||||
|
|
||||||
|
proc addStreamServer*[T: RpcServer](server: T, address: TransportAddress, streamCallback: StreamCallback) =
|
||||||
|
try:
|
||||||
|
info "Creating server on ", address = $address
|
||||||
|
var transportServer = createStreamServer(address, streamCallback, {ReuseAddr}, udata = server)
|
||||||
|
server.servers.add(transportServer)
|
||||||
|
except:
|
||||||
|
error "Failed to create server", address = $address, message = getCurrentExceptionMsg()
|
||||||
|
|
||||||
|
if len(server.servers) == 0:
|
||||||
|
# Server was not bound, critical error.
|
||||||
|
raise newException(RpcBindError, "Unable to create server!")
|
||||||
|
|
||||||
|
proc addStreamServers*[T: RpcServer](server: T, addresses: openarray[TransportAddress], streamCallback: StreamCallback) =
|
||||||
|
for item in addresses:
|
||||||
|
server.addStreamServer(item, streamCallback)
|
||||||
|
|
||||||
|
proc addStreamServer*[T: RpcServer](server: T, address: string, streamCallback: StreamCallback) =
|
||||||
|
## Create new server and assign it to addresses ``addresses``.
|
||||||
|
var
|
||||||
|
tas4: seq[TransportAddress]
|
||||||
|
tas6: seq[TransportAddress]
|
||||||
|
added = 0
|
||||||
|
|
||||||
|
# Attempt to resolve `address` for IPv4 address space.
|
||||||
|
try:
|
||||||
|
tas4 = resolveTAddress(address, IpAddressFamily.IPv4)
|
||||||
|
except:
|
||||||
|
discard
|
||||||
|
|
||||||
|
# Attempt to resolve `address` for IPv6 address space.
|
||||||
|
try:
|
||||||
|
tas6 = resolveTAddress(address, IpAddressFamily.IPv6)
|
||||||
|
except:
|
||||||
|
discard
|
||||||
|
|
||||||
|
for r in tas4:
|
||||||
|
server.addStreamServer(r, streamCallback)
|
||||||
|
added.inc
|
||||||
|
for r in tas6:
|
||||||
|
server.addStreamServer(r, streamCallback)
|
||||||
|
added.inc
|
||||||
|
|
||||||
|
if added == 0:
|
||||||
|
# Addresses could not be resolved, critical error.
|
||||||
|
raise newException(RpcAddressUnresolvableError, "Unable to get address!")
|
||||||
|
|
||||||
|
proc addStreamServers*[T: RpcServer](server: T, addresses: openarray[string], streamCallback: StreamCallback) =
|
||||||
|
for address in addresses:
|
||||||
|
server.addStreamServer(address, streamCallback)
|
||||||
|
|
||||||
|
proc addStreamServer*[T: RpcServer](server: T, address: string, port: Port, streamCallback: StreamCallback) =
|
||||||
|
var
|
||||||
|
tas4: seq[TransportAddress]
|
||||||
|
tas6: seq[TransportAddress]
|
||||||
|
added = 0
|
||||||
|
|
||||||
|
# Attempt to resolve `address` for IPv4 address space.
|
||||||
|
try:
|
||||||
|
tas4 = resolveTAddress(address, port, IpAddressFamily.IPv4)
|
||||||
|
except:
|
||||||
|
discard
|
||||||
|
|
||||||
|
# Attempt to resolve `address` for IPv6 address space.
|
||||||
|
try:
|
||||||
|
tas6 = resolveTAddress(address, port, IpAddressFamily.IPv6)
|
||||||
|
except:
|
||||||
|
discard
|
||||||
|
|
||||||
|
if len(tas4) == 0 and len(tas6) == 0:
|
||||||
|
# Address was not resolved, critical error.
|
||||||
|
raise newException(RpcAddressUnresolvableError,
|
||||||
|
"Address " & address & " could not be resolved!")
|
||||||
|
|
||||||
|
for r in tas4:
|
||||||
|
server.addStreamServer(r, streamCallback)
|
||||||
|
added.inc
|
||||||
|
for r in tas6:
|
||||||
|
server.addStreamServer(r, streamCallback)
|
||||||
|
added.inc
|
||||||
|
|
||||||
|
if len(server.servers) == 0:
|
||||||
|
# Server was not bound, critical error.
|
||||||
|
raise newException(RpcBindError,
|
||||||
|
"Could not setup server on " & address & ":" & $int(port))
|
||||||
|
|
||||||
|
type RpcStreamServer* = RpcServer[StreamServer]
|
||||||
|
|
||||||
|
proc newRpcStreamServer*(addresses: openarray[TransportAddress]): RpcStreamServer =
|
||||||
|
## Create new server and assign it to addresses ``addresses``.
|
||||||
|
result = newRpcServer[StreamServer]()
|
||||||
|
result.addStreamServers(addresses, processClient)
|
||||||
|
|
||||||
|
proc newRpcStreamServer*(addresses: openarray[string]): RpcStreamServer =
|
||||||
|
## Create new server and assign it to addresses ``addresses``.
|
||||||
|
result = newRpcServer[StreamServer]()
|
||||||
|
result.addStreamServers(addresses, processClient)
|
||||||
|
|
||||||
|
proc newRpcStreamServer*(address = "localhost", port: Port = Port(8545)): RpcStreamServer =
|
||||||
|
# Create server on specified port
|
||||||
|
result = newRpcServer[StreamServer]()
|
||||||
|
result.addStreamServer(address, port, processClient)
|
||||||
|
|
||||||
|
|
||||||
# TODO: Allow cross checking between client signatures and server calls
|
# TODO: Allow cross checking between client signatures and server calls
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user