2021-04-06 02:31:10 +05:30
|
|
|
import pkg/[chronos,
|
|
|
|
chronos/apps/http/httpserver,
|
|
|
|
chronos/timer,
|
|
|
|
chronicles,
|
|
|
|
httputils]
|
|
|
|
import strutils
|
|
|
|
|
|
|
|
const
|
|
|
|
HeaderSep = @[byte('\c'), byte('\L'), byte('\c'), byte('\L')]
|
2021-04-14 03:35:58 +05:30
|
|
|
HttpHeadersTimeout = timer.seconds(120) # timeout for receiving headers (120 sec)
|
|
|
|
MaxHttpHeadersSize = 8192 # maximum size of HTTP headers in octets
|
2021-04-06 02:31:10 +05:30
|
|
|
|
|
|
|
proc readHeaders*(rstream: AsyncStreamReader): Future[seq[byte]] {.async.} =
|
|
|
|
var buffer = newSeq[byte](MaxHttpHeadersSize)
|
|
|
|
var error = false
|
|
|
|
try:
|
|
|
|
let hlenfut = rstream.readUntil(
|
|
|
|
addr buffer[0], MaxHttpHeadersSize,
|
|
|
|
sep = HeaderSep)
|
|
|
|
let ores = await withTimeout(hlenfut, HttpHeadersTimeout)
|
|
|
|
if not ores:
|
|
|
|
# Timeout
|
|
|
|
debug "Timeout expired while receiving headers",
|
|
|
|
address = rstream.tsource.remoteAddress()
|
|
|
|
error = true
|
|
|
|
else:
|
|
|
|
let hlen = hlenfut.read()
|
|
|
|
buffer.setLen(hlen)
|
|
|
|
except AsyncStreamLimitError:
|
|
|
|
# size of headers exceeds `MaxHttpHeadersSize`
|
|
|
|
debug "Maximum size of headers limit reached",
|
|
|
|
address = rstream.tsource.remoteAddress()
|
|
|
|
error = true
|
|
|
|
except AsyncStreamIncompleteError:
|
|
|
|
# remote peer disconnected
|
|
|
|
debug "Remote peer disconnected", address = rstream.tsource.remoteAddress()
|
|
|
|
error = true
|
|
|
|
except AsyncStreamError as exc:
|
|
|
|
debug "Problems with networking", address = rstream.tsource.remoteAddress(),
|
|
|
|
error = exc.msg
|
|
|
|
error = true
|
|
|
|
|
|
|
|
if error:
|
|
|
|
buffer.setLen(0)
|
2021-04-14 03:35:58 +05:30
|
|
|
|
2021-04-06 02:31:10 +05:30
|
|
|
return buffer
|
|
|
|
|
2021-04-14 03:35:58 +05:30
|
|
|
proc closeWait*(wsStream : AsyncStream) {.async.} =
|
|
|
|
await allFutures(
|
|
|
|
wsStream.writer.tsource.closeWait(),
|
|
|
|
wsStream.reader.tsource.closeWait())
|
2021-04-06 02:31:10 +05:30
|
|
|
|
|
|
|
# TODO: Implement stream read and write wrapper.
|