From 315d243b5198376c5034970b4895627b1480dd9b Mon Sep 17 00:00:00 2001 From: Esteban C Borsani Date: Wed, 18 Dec 2024 03:09:27 -0300 Subject: [PATCH] Propagate GoAway errors (#34) Close #16 --- src/hyperx/clientserver.nim | 33 +++++++++++++++++---------------- src/hyperx/errors.nim | 31 ++++++++++++++++++------------- 2 files changed, 35 insertions(+), 29 deletions(-) diff --git a/src/hyperx/clientserver.nim b/src/hyperx/clientserver.nim index 16223b9..0cc2998 100644 --- a/src/hyperx/clientserver.nim +++ b/src/hyperx/clientserver.nim @@ -142,7 +142,7 @@ type peerWindowUpdateSig: SignalAsync windowPending, windowProcessed: int windowUpdateSig: SignalAsync - error*: ref HyperxError # XXX HyperxConnError + error*: ref HyperxConnError when defined(hyperxStats): frmsSent: int frmsSentTyp: array[10, int] @@ -304,7 +304,7 @@ func hpackEncode*( client: ClientContext, payload: var seq[byte], # XXX var string name, value: openArray[char] -) {.raises: [HyperxError].} = +) {.raises: [HyperxConnError].} = ## headers must be added synchronously, no await in between, ## or else a table resize could occur in the meantime try: @@ -312,7 +312,7 @@ func hpackEncode*( except HpackError as err: debugInfo err.getStackTrace() debugInfo err.msg - raise newException(HyperxError, err.msg) + raise newConnError(err.msg) proc sendNaked(client: ClientContext, frm: Frame) {.async.} = debugInfo "===SENT===" @@ -334,7 +334,14 @@ proc sendNaked(client: ClientContext, frm: Frame) {.async.} = proc send(client: ClientContext, frm: Frame) {.async.} = try: await client.sendNaked(frm) - except HyperxConnError, OsError, SslError: + except HyperxConnError as err: + if client.isConnected: + debugInfo err.getStackTrace() + debugInfo err.msg + client.error = newError err + client.close() + raise err + except OsError, SslError: let err = getCurrentException() if client.isConnected: debugInfo err.getStackTrace() @@ -520,7 +527,7 @@ proc recvTask(client: ClientContext) {.async.} = debugInfo err.getStackTrace() debugInfo err.msg if client.isConnected: - client.error = newConnError(err.code) + client.error = newError err await client.sendSilently newGoAwayFrame( client.maxPeerStreamIdSeen, err.code ) @@ -614,7 +621,7 @@ proc consumeMainStream(client: ClientContext, frm: Frame) {.async.} = strm.pingSig.trigger() of frmtGoAway: client.isGracefulShutdown = true - client.error ?= newConnError frm.errCode() + client.error ?= newConnError(frm.errCode(), hyxRemoteErr) # streams are never created by ctServer, # so there are no streams to close if client.typ == ctClient: @@ -709,7 +716,7 @@ proc recvDispatcher(client: ClientContext) {.async.} = debugInfo err.getStackTrace() debugInfo err.msg if client.isConnected: - client.error = newConnError(err.code) + client.error = newError err await client.sendSilently newGoAwayFrame( client.maxPeerStreamIdSeen, err.code ) @@ -718,12 +725,6 @@ proc recvDispatcher(client: ClientContext) {.async.} = debugInfo getCurrentException().getStackTrace() debugInfo getCurrentException().msg doAssert false - except HyperxError as err: # XXX remove - if client.isConnected: - debugInfo err.getStackTrace() - debugInfo err.msg - client.error = err # XXX fix - raise err except CatchableError as err: debugInfo err.getStackTrace() debugInfo err.msg @@ -748,11 +749,11 @@ proc windowUpdateTask(client: ClientContext) {.async.} = await client.windowUpdateTaskNaked() except QueueClosedError: doAssert not client.isConnected - except HyperxError as err: + except HyperxConnError as err: if client.isConnected: debugInfo err.getStackTrace() debugInfo err.msg - client.error = err + client.error = newError err raise err except CatchableError as err: debugInfo err.getStackTrace() @@ -1029,7 +1030,7 @@ proc recvTask(strm: ClientStream) {.async.} = debugInfo err.msg connErr = true if client.isConnected: - client.error = newConnError(err.code) + client.error = newError err await client.sendSilently newGoAwayFrame( client.maxPeerStreamIdSeen, err.code ) diff --git a/src/hyperx/errors.nim b/src/hyperx/errors.nim index fd386d5..fdbfe00 100644 --- a/src/hyperx/errors.nim +++ b/src/hyperx/errors.nim @@ -51,35 +51,40 @@ type HyperxErrTyp* = enum hyxLocalErr, hyxRemoteErr HyperxError* = object of CatchableError - #typ*: HyperxErrTyp - #code*: HyperxErrCode - HyperxConnError* = object of HyperxError - code*: HyperxErrCode - HyperxStrmError* = object of HyperxError typ*: HyperxErrTyp code*: HyperxErrCode + HyperxConnError* = object of HyperxError + HyperxStrmError* = object of HyperxError ConnClosedError* = object of HyperxConnError GracefulShutdownError* = HyperxConnError QueueClosedError* = object of HyperxError func newConnClosedError*: ref ConnClosedError {.raises: [].} = - result = (ref ConnClosedError)(code: hyxUnknown, msg: "Connection Closed") + result = (ref ConnClosedError)(typ: hyxLocalErr, code: hyxInternalError, msg: "Connection Closed") func newConnError*(msg: string): ref HyperxConnError {.raises: [].} = - result = (ref HyperxConnError)(code: hyxInternalError, msg: msg) + result = (ref HyperxConnError)(typ: hyxLocalErr, code: hyxInternalError, msg: msg) -func newConnError*(errCode: HyperxErrCode): ref HyperxConnError {.raises: [].} = - result = (ref HyperxConnError)(code: errCode, msg: "Connection Error: " & $errCode) +func newConnError*( + errCode: HyperxErrCode, typ = hyxLocalErr +): ref HyperxConnError {.raises: [].} = + result = (ref HyperxConnError)( + typ: typ, code: errCode, msg: "Connection Error: " & $errCode + ) -func newConnError*(errCode: uint32): ref HyperxConnError {.raises: [].} = +func newConnError*( + errCode: uint32, typ = hyxLocalErr +): ref HyperxConnError {.raises: [].} = result = (ref HyperxConnError)( + typ: typ, code: errCode.toErrorCode, msg: "Connection Error: " & $errCode.toErrorCode ) -# XXX fix -func newError*(err: ref HyperxError): ref HyperxConnError {.raises: [].} = - result = (ref HyperxConnError)(code: hyxUnknown, msg: err.msg) +func newError*(err: ref HyperxConnError): ref HyperxConnError {.raises: [].} = + result = (ref HyperxConnError)( + typ: err.typ, code: err.code, msg: err.msg + ) func newStrmError*( errCode: HyperxErrCode, typ = hyxLocalErr