mirror of
https://github.com/logos-storage/nim-json-rpc.git
synced 2026-01-07 16:13:07 +00:00
Fix freezes on *nix systems.
This commit is contained in:
parent
493583b7f4
commit
a56ad7dfcb
@ -11,6 +11,7 @@ type
|
|||||||
|
|
||||||
RpcHttpClient* = ref object of RpcClient
|
RpcHttpClient* = ref object of RpcClient
|
||||||
transp*: StreamTransport
|
transp*: StreamTransport
|
||||||
|
loop: Future[void]
|
||||||
addresses: seq[TransportAddress]
|
addresses: seq[TransportAddress]
|
||||||
options: HttpClientOptions
|
options: HttpClientOptions
|
||||||
|
|
||||||
@ -115,7 +116,7 @@ proc recvData(transp: StreamTransport): Future[string] {.async.} =
|
|||||||
error = true
|
error = true
|
||||||
|
|
||||||
if error or not transp.validateResponse(header):
|
if error or not transp.validateResponse(header):
|
||||||
transp.close()
|
await transp.closeWait()
|
||||||
result = ""
|
result = ""
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -155,7 +156,7 @@ proc recvData(transp: StreamTransport): Future[string] {.async.} =
|
|||||||
error = true
|
error = true
|
||||||
|
|
||||||
if error:
|
if error:
|
||||||
transp.close()
|
await transp.closeWait()
|
||||||
result = ""
|
result = ""
|
||||||
else:
|
else:
|
||||||
result = cast[string](buffer)
|
result = cast[string](buffer)
|
||||||
@ -188,7 +189,7 @@ proc call*(client: RpcHttpClient, name: string,
|
|||||||
if not res:
|
if not res:
|
||||||
debug "Failed to send message to RPC server",
|
debug "Failed to send message to RPC server",
|
||||||
address = client.transp.remoteAddress(), msg_len = len(value)
|
address = client.transp.remoteAddress(), msg_len = len(value)
|
||||||
client.transp.close()
|
await client.transp.closeWait()
|
||||||
raise newException(ValueError, "Transport error")
|
raise newException(ValueError, "Transport error")
|
||||||
else:
|
else:
|
||||||
debug "Message sent to RPC server", address = client.transp.remoteAddress(),
|
debug "Message sent to RPC server", address = client.transp.remoteAddress(),
|
||||||
@ -207,19 +208,28 @@ template call*(client: RpcHttpClient, name: string,
|
|||||||
|
|
||||||
proc processData(client: RpcHttpClient) {.async.} =
|
proc processData(client: RpcHttpClient) {.async.} =
|
||||||
while true:
|
while true:
|
||||||
var value = await client.transp.recvData()
|
while true:
|
||||||
if value == "":
|
var value = await client.transp.recvData()
|
||||||
break
|
debug "Returned from recvData()", address = client.transp.remoteAddress()
|
||||||
debug "Received response from RPC server",
|
if value == "":
|
||||||
address = client.transp.remoteAddress(),
|
debug "Empty response from RPC server",
|
||||||
msg_len = len(value)
|
address = client.transp.remoteAddress()
|
||||||
trace "Message", msg = value
|
break
|
||||||
client.processMessage(value)
|
debug "Received response from RPC server",
|
||||||
|
address = client.transp.remoteAddress(),
|
||||||
|
msg_len = len(value)
|
||||||
|
trace "Message", msg = value
|
||||||
|
client.processMessage(value)
|
||||||
|
|
||||||
# async loop reconnection and waiting
|
# async loop reconnection and waiting
|
||||||
client.transp = await connect(client.addresses[0])
|
try:
|
||||||
|
client.transp = await connect(client.addresses[0])
|
||||||
|
except:
|
||||||
|
debug "Could not establish new connection to RPC server",
|
||||||
|
address = client.addresses[0]
|
||||||
|
break
|
||||||
|
|
||||||
proc connect*(client: RpcHttpClient, address: string, port: Port) {.async.} =
|
proc connect*(client: RpcHttpClient, address: string, port: Port) {.async.} =
|
||||||
client.addresses = resolveTAddress(address, port)
|
client.addresses = resolveTAddress(address, port)
|
||||||
client.transp = await connect(client.addresses[0])
|
client.transp = await connect(client.addresses[0])
|
||||||
asyncCheck processData(client)
|
client.loop = processData(client)
|
||||||
|
|||||||
@ -4,6 +4,7 @@ type
|
|||||||
RpcSocketClient* = ref object of RpcClient
|
RpcSocketClient* = ref object of RpcClient
|
||||||
transport*: StreamTransport
|
transport*: StreamTransport
|
||||||
address*: TransportAddress
|
address*: TransportAddress
|
||||||
|
loop*: Future[void]
|
||||||
|
|
||||||
const defaultMaxRequestLength* = 1024 * 128
|
const defaultMaxRequestLength* = 1024 * 128
|
||||||
|
|
||||||
@ -32,18 +33,19 @@ proc call*(self: RpcSocketClient, name: string,
|
|||||||
|
|
||||||
proc processData(client: RpcSocketClient) {.async.} =
|
proc processData(client: RpcSocketClient) {.async.} =
|
||||||
while true:
|
while true:
|
||||||
var value = await client.transport.readLine(defaultMaxRequestLength)
|
while true:
|
||||||
if value == "":
|
var value = await client.transport.readLine(defaultMaxRequestLength)
|
||||||
# transmission ends
|
if value == "":
|
||||||
client.transport.close
|
# transmission ends
|
||||||
break
|
await client.transport.closeWait()
|
||||||
|
break
|
||||||
|
|
||||||
client.processMessage(value)
|
client.processMessage(value)
|
||||||
# async loop reconnection and waiting
|
# async loop reconnection and waiting
|
||||||
client.transport = await connect(client.address)
|
client.transport = await connect(client.address)
|
||||||
|
|
||||||
proc connect*(client: RpcSocketClient, address: string, port: Port) {.async.} =
|
proc connect*(client: RpcSocketClient, address: string, port: Port) {.async.} =
|
||||||
let addresses = resolveTAddress(address, port)
|
let addresses = resolveTAddress(address, port)
|
||||||
client.transport = await connect(addresses[0])
|
client.transport = await connect(addresses[0])
|
||||||
client.address = addresses[0]
|
client.address = addresses[0]
|
||||||
asyncCheck processData(client)
|
client.loop = processData(client)
|
||||||
|
|||||||
@ -104,7 +104,7 @@ proc processClient(server: StreamServer,
|
|||||||
debug "Timeout expired while receiving headers",
|
debug "Timeout expired while receiving headers",
|
||||||
address = transp.remoteAddress()
|
address = transp.remoteAddress()
|
||||||
let res = await transp.sendAnswer(HttpVersion11, Http408)
|
let res = await transp.sendAnswer(HttpVersion11, Http408)
|
||||||
transp.close()
|
await transp.closeWait()
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
let hlen = hlenfut.read()
|
let hlen = hlenfut.read()
|
||||||
@ -115,24 +115,29 @@ proc processClient(server: StreamServer,
|
|||||||
debug "Malformed header received",
|
debug "Malformed header received",
|
||||||
address = transp.remoteAddress()
|
address = transp.remoteAddress()
|
||||||
let res = await transp.sendAnswer(HttpVersion11, Http400)
|
let res = await transp.sendAnswer(HttpVersion11, Http400)
|
||||||
transp.close()
|
await transp.closeWait()
|
||||||
break
|
break
|
||||||
except TransportLimitError:
|
except TransportLimitError:
|
||||||
# size of headers exceeds `MaxHttpHeadersSize`
|
# size of headers exceeds `MaxHttpHeadersSize`
|
||||||
debug "Maximum size of headers limit reached",
|
debug "Maximum size of headers limit reached",
|
||||||
address = transp.remoteAddress()
|
address = transp.remoteAddress()
|
||||||
let res = await transp.sendAnswer(HttpVersion11, Http413)
|
let res = await transp.sendAnswer(HttpVersion11, Http413)
|
||||||
transp.close()
|
await transp.closeWait()
|
||||||
break
|
break
|
||||||
except TransportIncompleteError:
|
except TransportIncompleteError:
|
||||||
# remote peer disconnected
|
# remote peer disconnected
|
||||||
debug "Remote peer disconnected", address = transp.remoteAddress()
|
debug "Remote peer disconnected", address = transp.remoteAddress()
|
||||||
transp.close()
|
await transp.closeWait()
|
||||||
break
|
break
|
||||||
except TransportOsError:
|
except TransportOsError:
|
||||||
debug "Problems with networking", address = transp.remoteAddress(),
|
debug "Problems with networking", address = transp.remoteAddress(),
|
||||||
error = getCurrentExceptionMsg()
|
error = getCurrentExceptionMsg()
|
||||||
transp.close()
|
await transp.closeWait()
|
||||||
|
break
|
||||||
|
except:
|
||||||
|
debug "Unknown exception", address = transp.remoteAddress(),
|
||||||
|
error = getCurrentExceptionMsg()
|
||||||
|
await transp.closeWait()
|
||||||
break
|
break
|
||||||
|
|
||||||
let vres = await validateRequest(transp, header)
|
let vres = await validateRequest(transp, header)
|
||||||
@ -154,19 +159,19 @@ proc processClient(server: StreamServer,
|
|||||||
debug "Timeout expired while receiving request body",
|
debug "Timeout expired while receiving request body",
|
||||||
address = transp.remoteAddress()
|
address = transp.remoteAddress()
|
||||||
let res = await transp.sendAnswer(header.version, Http413)
|
let res = await transp.sendAnswer(header.version, Http413)
|
||||||
transp.close()
|
await transp.closeWait()
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
blenfut.read()
|
blenfut.read()
|
||||||
except TransportIncompleteError:
|
except TransportIncompleteError:
|
||||||
# remote peer disconnected
|
# remote peer disconnected
|
||||||
debug "Remote peer disconnected", address = transp.remoteAddress()
|
debug "Remote peer disconnected", address = transp.remoteAddress()
|
||||||
transp.close()
|
await transp.closeWait()
|
||||||
break
|
break
|
||||||
except TransportOsError:
|
except TransportOsError:
|
||||||
debug "Problems with networking", address = transp.remoteAddress(),
|
debug "Problems with networking", address = transp.remoteAddress(),
|
||||||
error = getCurrentExceptionMsg()
|
error = getCurrentExceptionMsg()
|
||||||
transp.close()
|
await transp.closeWait()
|
||||||
break
|
break
|
||||||
|
|
||||||
let future = rpc.route(cast[string](buffer))
|
let future = rpc.route(cast[string](buffer))
|
||||||
@ -177,30 +182,32 @@ proc processClient(server: StreamServer,
|
|||||||
address = transp.remoteAddress()
|
address = transp.remoteAddress()
|
||||||
let res = await transp.sendAnswer(header.version, Http503)
|
let res = await transp.sendAnswer(header.version, Http503)
|
||||||
if not res:
|
if not res:
|
||||||
transp.close()
|
await transp.closeWait()
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
var data = future.read()
|
var data = future.read()
|
||||||
let res = await transp.sendAnswer(header.version, Http200, data)
|
let res = await transp.sendAnswer(header.version, Http200, data)
|
||||||
info "RPC result has been sent", address = transp.remoteAddress()
|
info "RPC result has been sent", address = transp.remoteAddress()
|
||||||
if not res:
|
if not res:
|
||||||
transp.close()
|
await transp.closeWait()
|
||||||
break
|
break
|
||||||
elif vres == ErrorFailure:
|
elif vres == ErrorFailure:
|
||||||
debug "Remote peer disconnected", address = transp.remoteAddress()
|
debug "Remote peer disconnected", address = transp.remoteAddress()
|
||||||
transp.close()
|
await transp.closeWait()
|
||||||
break
|
break
|
||||||
|
|
||||||
if header.version in {HttpVersion09, HttpVersion10}:
|
if header.version in {HttpVersion09, HttpVersion10}:
|
||||||
debug "Disconnecting client", address = transp.remoteAddress()
|
debug "Disconnecting client", address = transp.remoteAddress()
|
||||||
transp.close()
|
await transp.closeWait()
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
if connection == "close":
|
if connection == "close":
|
||||||
debug "Disconnecting client", address = transp.remoteAddress()
|
debug "Disconnecting client", address = transp.remoteAddress()
|
||||||
transp.close()
|
await transp.closeWait()
|
||||||
break
|
break
|
||||||
|
|
||||||
|
info "Finished connection", address = transp.remoteAddress()
|
||||||
|
|
||||||
# Utility functions for setting up servers using stream transport addresses
|
# Utility functions for setting up servers using stream transport addresses
|
||||||
|
|
||||||
proc addStreamServer*(server: RpcHttpServer, address: TransportAddress) =
|
proc addStreamServer*(server: RpcHttpServer, address: TransportAddress) =
|
||||||
|
|||||||
@ -20,7 +20,7 @@ proc processClient(server: StreamServer, transport: StreamTransport) {.async, gc
|
|||||||
maxRequestLength = defaultMaxRequestLength
|
maxRequestLength = defaultMaxRequestLength
|
||||||
value = await transport.readLine(defaultMaxRequestLength)
|
value = await transport.readLine(defaultMaxRequestLength)
|
||||||
if value == "":
|
if value == "":
|
||||||
transport.close
|
await transport.closeWait()
|
||||||
break
|
break
|
||||||
|
|
||||||
debug "Processing message", address = transport.remoteAddress(), line = value
|
debug "Processing message", address = transport.remoteAddress(), line = value
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user