Skip to content

Commit

Permalink
TryCatch util (#38)
Browse files Browse the repository at this point in the history
  • Loading branch information
nitely authored Dec 22, 2024
1 parent 7efdeb5 commit d076c6c
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 67 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,4 @@ examples/dataStream
examples/tlsServer
config.nims
out
patches
5 changes: 1 addition & 4 deletions src/hyperx/client.nim
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,11 @@ proc defaultSslContext(): SslContext {.raises: [HyperxConnError].} =
when not defined(hyperxTest):
proc newMySocket(ssl: bool): MyAsyncSocket {.raises: [HyperxConnError].} =
result = nil
try:
tryCatch:
result = newAsyncSocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, buffered = true)
doAssert result != nil
if ssl:
wrapSocket(defaultSslContext(), result)
except CatchableError as err:
debugErr2 err
raise newConnError(err.msg, err)

proc newClient*(
hostname: string,
Expand Down
39 changes: 8 additions & 31 deletions src/hyperx/clientserver.nim
Original file line number Diff line number Diff line change
Expand Up @@ -72,23 +72,12 @@ proc defaultSslContext*(
# protSSLv23 will disable all protocols
# lower than the min protocol defined
# in openssl.config, usually +TLSv1.2
result = nil
try:
result = newContext(
protSSLv23,
verifyMode = CVerifyPeer,
certFile = certFile,
keyFile = keyFile
)
except CatchableError as err:
debugErr2 err
raise newConnError(err.msg, err)
except Defect as err:
raise err
except Exception as err:
debugErr2 err
# workaround for newContext raising Exception
raise newException(Defect, err.msg, err)
result = tryCatch newContext(
protSSLv23,
verifyMode = CVerifyPeer,
certFile = certFile,
keyFile = keyFile
)
doAssert result != nil, "failure to initialize the SSL context"
# https://httpwg.org/specs/rfc9113.html#tls12features
const ctxOps = SSL_OP_ALL or
Expand Down Expand Up @@ -180,15 +169,7 @@ proc close*(client: ClientContext) {.raises: [HyperxConnError].} =
return
client.isConnected = false
try:
client.sock.close()
except CatchableError as err:
debugErr2 err
raise newConnError(err.msg, err)
except Defect as err:
raise err
except Exception as err:
debugErr2 err
raise newException(Defect, err.msg, err)
tryCatch client.sock.close()
finally:
client.recvMsgs.close()
client.streamOpenedMsgs.close()
Expand Down Expand Up @@ -741,11 +722,7 @@ proc windowUpdateTask(client: ClientContext) {.async.} =
client.close()

proc connect(client: ClientContext) {.async.} =
try:
await client.sock.connect(client.hostname, client.port)
except OsError as err:
debugErr2 err
raise newConnError(err.msg, err)
tryCatch await client.sock.connect(client.hostname, client.port)

proc failSilently(f: Future[void]) {.async.} =
## Be careful when wrapping non {.async.} procs,
Expand Down
29 changes: 5 additions & 24 deletions src/hyperx/server.nim
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,11 @@ when not defined(hyperxTest):
keyFile = ""
): MyAsyncSocket {.raises: [HyperxConnError].} =
result = nil
try:
tryCatch:
result = newAsyncSocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, buffered = true)
doAssert result != nil
if ssl:
wrapSocket(defaultSslContext(certFile, keyFile), result)
except CatchableError as err:
debugErr2 err
raise newConnError(err.msg, err)

type
ServerContext* = ref object
Expand Down Expand Up @@ -99,34 +96,21 @@ proc close*(server: ServerContext) {.raises: [HyperxConnError].} =
if not server.isConnected:
return
server.isConnected = false
try:
server.sock.close()
except CatchableError as err:
debugErr2 err
raise newConnError(err.msg, err)
except Defect as err:
raise err
except Exception as err:
debugErr2 err
raise newException(Defect, err.msg, err)
tryCatch server.sock.close()

proc listen(server: ServerContext) {.raises: [HyperxConnError].} =
try:
tryCatch:
server.sock.setSockOpt(OptReuseAddr, true)
server.sock.setSockOpt(OptReusePort, true)
server.sock.setSockOpt(OptNoDelay, true, level = IPPROTO_TCP.cint)
server.sock.bindAddr server.port
server.sock.listen()
except OSError, ValueError:
let err = getCurrentException()
debugErr2 err
raise newConnError(err.msg, err)

# XXX dont allow receive push promise

# XXX limit number of active clients
proc recvClient*(server: ServerContext): Future[ClientContext] {.async.} =
try:
tryCatch:
# note OptNoDelay is inherited from server.sock
let sock = await server.sock.accept()
if server.sock.isSsl:
Expand All @@ -135,10 +119,7 @@ proc recvClient*(server: ServerContext): Future[ClientContext] {.async.} =
wrapConnectedSocket(
sslContext, sock, handshakeAsServer, server.hostname
)
result = newClient(ctServer, sock, server.hostname)
except CatchableError as err:
debugErr2 err
raise newConnError(err.msg, err)
return newClient(ctServer, sock, server.hostname)

template with*(server: ServerContext, body: untyped): untyped =
try:
Expand Down
34 changes: 26 additions & 8 deletions src/hyperx/utils.nim
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,22 @@ template raisesAssertion*(exp: untyped): untyped =

template untrackExceptions*(body: untyped): untyped =
## workaround for API errors in Nim's stdlib
{.line: instantiationInfo(fullPaths = true).}:
try:
body
except Defect as err:
raise err # raise original error
except Exception as err:
debugErr err
raise newException(Defect, err.msg, err)
try:
body
except Defect as err:
raise err # raise original error
except Exception as err:
debugErr err
raise newException(Defect, err.msg, err)

template tryCatch*(body: untyped): untyped =
try:
body
except Defect as err:
raise err
except Exception as err:
debugErr2 err
raise newConnError(err.msg, err)

func add*(s: var seq[byte], ss: openArray[char]) {.raises: [].} =
let L = s.len
Expand Down Expand Up @@ -241,6 +249,16 @@ when isMainModule:
except AssertionDefect:
raised = true
doAssert raised
block:
raisesAssertion(tryCatch(doAssert false))
block:
try:
tryCatch:
raise newException(ValueError, "foo")
doAssert false
except HyperxConnError as err:
doAssert err.msg == "foo"
doAssert err.parent.msg == "foo"
block content_len:
doAssert contentLen(newSeq[byte]()) == -1
doAssert contentLen(":foo: abc\r\n".toBytes) == -1
Expand Down

0 comments on commit d076c6c

Please sign in to comment.