From 393d60edf335fd50d14b984782bc20913289de0e Mon Sep 17 00:00:00 2001 From: Parham Saremi Date: Tue, 15 Nov 2022 12:48:12 +0330 Subject: [PATCH] Backend(LN): catch NOnionException TorOperations Catch the NOnionException after Retrys have finished and the problem still exists. We catch the exception and return an error. Fixes https://github.com/nblockchain/geewallet/issues/181 Fixes https://github.com/nblockchain/geewallet/issues/182 --- .../UtxoCoin/Lightning/Network.fs | 55 +++++++++++++------ src/GWallet.Backend/UtxoCoin/TorOperations.fs | 16 ++++-- 2 files changed, 49 insertions(+), 22 deletions(-) diff --git a/src/GWallet.Backend/UtxoCoin/Lightning/Network.fs b/src/GWallet.Backend/UtxoCoin/Lightning/Network.fs index 7f7ecc29d..ba6f13655 100644 --- a/src/GWallet.Backend/UtxoCoin/Lightning/Network.fs +++ b/src/GWallet.Backend/UtxoCoin/Lightning/Network.fs @@ -10,6 +10,7 @@ open NBitcoin open DotNetLightning.Peer open DotNetLightning.Utils open ResultUtils.Portability +open NOnion open NOnion.Network open NOnion.Directory open NOnion.Services @@ -35,9 +36,13 @@ type PeerDisconnectedError = member internal self.PossibleBug = not self.Abruptly +type TCPError = + | NOnionError of NOnionException + | SocketError of seq + type HandshakeError = - | TcpConnect of seq - | TcpAccept of seq + | TcpConnect of TCPError + | TcpAccept of TCPError | DisconnectedOnAct1 of PeerDisconnectedError | InvalidAct1 of PeerError | DisconnectedOnAct2 of PeerDisconnectedError @@ -48,11 +53,21 @@ type HandshakeError = member self.Message = match self with | TcpConnect errs -> - let messages = Seq.map (fun (err: SocketException) -> err.Message) errs - SPrintF1 "TCP connection failed: %s" (String.concat "; " messages) + match errs with + | TCPError.NOnionError err -> + let message = err.Message + SPrintF1 "TCP connection failed: %s" message + | TCPError.SocketError errs -> + let messages = Seq.map (fun (err: SocketException) -> err.Message) errs + SPrintF1 "TCP connection failed: %s" (String.concat "; " messages) | TcpAccept errs -> - let messages = Seq.map (fun (err: SocketException) -> err.Message) errs - SPrintF1 "TCP accept failed: %s" (String.concat "; " messages) + match errs with + | TCPError.NOnionError err -> + let message = err.Message + SPrintF1 "TCP accept failed: %s" message + | TCPError.SocketError errs -> + let messages = Seq.map (fun (err: SocketException) -> err.Message) errs + SPrintF1 "TCP accept failed: %s" (String.concat "; " messages) | DisconnectedOnAct1 err -> SPrintF1 "Peer disconnected before starting handshake: %s" (err :> IErrorMsg).Message | InvalidAct1 err -> @@ -331,7 +346,7 @@ type internal TransportStream = static member private TcpTransportConnect (localEndPointOpt: Option) (remoteEndPoint: IPEndPoint) - : Async>> = async { + : Async> = async { let client = new TcpClient (remoteEndPoint.AddressFamily) match localEndPointOpt with | Some localEndPoint -> @@ -351,12 +366,12 @@ type internal TransportStream = with | ex -> client.Close() - let socketExceptions = FindSingleException ex - return Error socketExceptions + let socketExceptions = FindSingleException ex + return Error (TCPError.SocketError socketExceptions) } static member private AcceptAny (listener: IncomingConnectionMethod) - : Async>> = async { + : Async> = async { try match listener with | IncomingConnectionMethod.Tcp tcpListener -> @@ -368,7 +383,7 @@ type internal TransportStream = with | ex -> let socketExceptions = FindSingleException ex - return Error socketExceptions + return Error (TCPError.SocketError socketExceptions) } static member private ConnectHandshake (client: TransportClientType) @@ -419,23 +434,27 @@ type internal TransportStream = static member private TorTransportConnect (nonionEndPoint: NOnionEndPoint) - : Async>> = + : Async> = async { let! directory = TorOperations.GetTorDirectory() try - let! torClient = TorOperations.TorConnect directory nonionEndPoint.Url - Infrastructure.LogDebug <| SPrintF1 "Connected %s" nonionEndPoint.Url - return Ok torClient + let! maybeTorClient = TorOperations.TorConnect directory nonionEndPoint.Url + match maybeTorClient with + | Ok torClient -> + Infrastructure.LogDebug <| SPrintF1 "Connected %s" nonionEndPoint.Url + return Ok torClient + | Error ex -> + return Error (TCPError.NOnionError ex) with | ex -> let socketExceptions = FindSingleException ex - return Error socketExceptions + return Error (TCPError.SocketError socketExceptions) } static member private TransportConnect (localEndPointOpt: Option) (node: NodeIdentifier) - : Async>> = + : Async> = async { match node with | NodeIdentifier.TcpEndPoint remoteEndPoint -> @@ -470,7 +489,7 @@ type internal TransportStream = : Async> = async { let! clientRes = TransportStream.AcceptAny transportListener.Listener match clientRes with - | Error socketError -> return Error <| TcpAccept socketError + | Error tcpError -> return Error <| TcpAccept tcpError | Ok client -> let nodeSecret = transportListener.NodeMasterPrivKey.NodeSecret() let nodeSecretKey = nodeSecret.RawKey() diff --git a/src/GWallet.Backend/UtxoCoin/TorOperations.fs b/src/GWallet.Backend/UtxoCoin/TorOperations.fs index 91d0dc516..d2407b424 100644 --- a/src/GWallet.Backend/UtxoCoin/TorOperations.fs +++ b/src/GWallet.Backend/UtxoCoin/TorOperations.fs @@ -6,6 +6,7 @@ open System.Net open System.Text.RegularExpressions open System.Diagnostics +open ResultUtils.Portability open NOnion open NOnion.Directory open NOnion.Services @@ -110,11 +111,18 @@ module internal TorOperations = Config.TOR_CONNECTION_RETRY_COUNT } - let internal TorConnect directory url = + let internal TorConnect directory url: + Async> = async { - return! FSharpUtil.Retry - (fun _ -> TorServiceClient.Connect directory url) - Config.TOR_CONNECTION_RETRY_COUNT + try + let! connectedServiceClient = + FSharpUtil.Retry + (fun _ -> TorServiceClient.Connect directory url) + Config.TOR_CONNECTION_RETRY_COUNT + return Ok connectedServiceClient + with + | :? NOnionException as ex -> + return Error ex } let internal ExtractServerListFromGithub() : List<(string*string)> =