From 258ab3dd26d23ff9dc08760a311b4931fc090008 Mon Sep 17 00:00:00 2001 From: parham saremi <45370204+parhamsaremi@users.noreply.github.com> Date: Mon, 14 Nov 2022 13:51:56 +0330 Subject: [PATCH] Network: rework TorGuard exception handling (#49) Move TorGuard exception handling to a new module so that every time we want to handle a new type of exception, we won't be bothered by adding a lot of try/except expressions. While we're at it, we wrap IOException (necessary for fixing [1]). Fixes https://github.com/nblockchain/NOnion/issues/45 [1] https://github.com/nblockchain/geewallet/issues/184 --- NOnion/Network/TorGuard.fs | 98 +++++++++++++++++++++----------------- 1 file changed, 54 insertions(+), 44 deletions(-) diff --git a/NOnion/Network/TorGuard.fs b/NOnion/Network/TorGuard.fs index 4ffb5834..d32e9584 100644 --- a/NOnion/Network/TorGuard.fs +++ b/NOnion/Network/TorGuard.fs @@ -20,6 +20,27 @@ type internal GuardSendMessage = ReplyChannel: AsyncReplyChannel> } +module ExceptionUtil = + let RunGuardJobWithExceptionHandling<'T> job : Async<'T> = + async { + try + return! job + with + | exn -> + match FSharpUtil.FindException exn with + | Some authEx -> + return raise <| GuardConnectionFailedException authEx + | None -> + match FSharpUtil.FindException exn with + | Some socketEx -> + return raise <| GuardConnectionFailedException socketEx + | None -> + match FSharpUtil.FindException exn with + | Some ioEx -> + return raise <| GuardConnectionFailedException ioEx + | None -> return raise <| FSharpUtil.ReRaise exn + } + type TorGuard private (client: TcpClient, sslStream: SslStream) = let shutdownToken = new CancellationTokenSource() @@ -88,24 +109,23 @@ type TorGuard private (client: TcpClient, sslStream: SslStream) = async { let tcpClient = new TcpClient() - try - ipEndpoint.ToString() - |> sprintf "TorGuard: trying to connect to %s guard node" - |> TorLogger.Log + let innerConnectAsync(client: TcpClient) = + async { + ipEndpoint.ToString() + |> sprintf "TorGuard: trying to connect to %s guard node" + |> TorLogger.Log - do! - tcpClient.ConnectAsync(ipEndpoint.Address, ipEndpoint.Port) - |> Async.AwaitTask - |> FSharpUtil.WithTimeout Constants.GuardConnectionTimeout - - with - | exn -> - let socketExOpt = FSharpUtil.FindException exn + do! + client.ConnectAsync(ipEndpoint.Address, ipEndpoint.Port) + |> Async.AwaitTask + |> FSharpUtil.WithTimeout + Constants.GuardConnectionTimeout + } - match socketExOpt with - | None -> return raise <| FSharpUtil.ReRaise exn - | Some socketEx -> - return raise <| GuardConnectionFailedException socketEx + do! + ExceptionUtil.RunGuardJobWithExceptionHandling( + innerConnectAsync tcpClient + ) let sslStream = new SslStream( @@ -118,26 +138,20 @@ type TorGuard private (client: TcpClient, sslStream: SslStream) = |> sprintf "TorGuard: creating ssl connection to %s guard node" |> TorLogger.Log - try - do! - sslStream.AuthenticateAsClientAsync( - String.Empty, - null, - SslProtocols.Tls12, - false - ) - |> Async.AwaitTask - |> FSharpUtil.WithTimeout Constants.CircuitOperationTimeout - with - | exn -> - match FSharpUtil.FindException exn with - | Some authEx -> - return raise <| GuardConnectionFailedException authEx - | None -> - match FSharpUtil.FindException exn with - | Some socketEx -> - return raise <| GuardConnectionFailedException socketEx - | None -> return raise <| FSharpUtil.ReRaise exn + let innerAuthenticateAsClient(stream: SslStream) = + stream.AuthenticateAsClientAsync( + String.Empty, + null, + SslProtocols.Tls12, + false + ) + |> Async.AwaitTask + |> FSharpUtil.WithTimeout Constants.CircuitOperationTimeout + + do! + ExceptionUtil.RunGuardJobWithExceptionHandling( + innerAuthenticateAsClient sslStream + ) ipEndpoint.ToString() |> sprintf "TorGuard: ssl connection to %s guard node authenticated" @@ -296,14 +310,10 @@ type TorGuard private (client: TcpClient, sslStream: SslStream) = async { let! maybeCell = async { - try - return! self.ReceiveMessage() - with - | exn -> - match FSharpUtil.FindException exn - with - | Some _socketExn -> return None - | None -> return raise <| FSharpUtil.ReRaise exn + return! + ExceptionUtil.RunGuardJobWithExceptionHandling>( + self.ReceiveMessage() + ) } match maybeCell with