From 0972735d219b9588e3edd895f0002df47617b524 Mon Sep 17 00:00:00 2001 From: Parham Saremi Date: Wed, 9 Nov 2022 16:53:54 +0330 Subject: [PATCH] Network: clean TorGuard exception handling 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. This code is 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 33bf4a45..bdfc1c63 100644 --- a/NOnion/Network/TorGuard.fs +++ b/NOnion/Network/TorGuard.fs @@ -20,6 +20,27 @@ type internal GuardSendMessage = ReplyChannel: AsyncReplyChannel> } +module ExceptionUtil = + let RunGuardJobWIthExceptionHandlling<'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 innetConnectAsync(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.RunGuardJobWIthExceptionHandlling( + innetConnectAsync 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.RunGuardJobWIthExceptionHandlling( + 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.RunGuardJobWIthExceptionHandlling>( + self.ReceiveMessage() + ) } match maybeCell with