diff --git a/NOnion/Http/TorHttpClient.fs b/NOnion/Http/TorHttpClient.fs index e863ab00..8826833a 100644 --- a/NOnion/Http/TorHttpClient.fs +++ b/NOnion/Http/TorHttpClient.fs @@ -5,6 +5,8 @@ open System.Text open System.IO open System.IO.Compression +open Fsdk + open NOnion open NOnion.Network open NOnion.Utility @@ -49,10 +51,14 @@ type TorHttpClient(stream: TorStream, host: string) = use memStream = new MemoryStream() - do! + let! receiveAllResult = ReceiveAll memStream |> FSharpUtil.WithTimeout Constants.HttpGetResponseTimeout + match receiveAllResult with + | Some _ -> () + | None -> return raise <| TimeoutErrorException() + let httpResponse = memStream.ToArray() let header, body = @@ -143,10 +149,14 @@ type TorHttpClient(stream: TorStream, host: string) = use memStream = new MemoryStream() - do! + let! receiveAllResult = ReceiveAll memStream |> FSharpUtil.WithTimeout Constants.HttpPostResponseTimeout + match receiveAllResult with + | Some _ -> () + | None -> return raise <| TimeoutErrorException() + let httpResponse = memStream.ToArray() let header, body = diff --git a/NOnion/Network/TorCircuit.fs b/NOnion/Network/TorCircuit.fs index 57c9f691..ed3bdb51 100644 --- a/NOnion/Network/TorCircuit.fs +++ b/NOnion/Network/TorCircuit.fs @@ -11,6 +11,7 @@ open Org.BouncyCastle.Crypto.Parameters open Org.BouncyCastle.Crypto.Generators open Org.BouncyCastle.Security open FSharpx.Collections +open Fsdk open NOnion open NOnion.Cells @@ -1109,11 +1110,15 @@ and TorCircuit Constants.CircuitOperationTimeout.TotalMilliseconds |> int ) - return! + let! taskResult = completionTaskRes |> UnwrapResult |> Async.AwaitTask |> FSharpUtil.WithTimeout Constants.CircuitOperationTimeout + + match taskResult with + | Some result -> return result + | None -> return raise <| TimeoutErrorException() } member __.Extend(nodeDetail: CircuitNodeDetail) = @@ -1152,11 +1157,15 @@ and TorCircuit Constants.CircuitOperationTimeout.TotalMilliseconds |> int ) - return! + let! result = completionTaskRes |> UnwrapResult |> Async.AwaitTask |> FSharpUtil.WithTimeout Constants.CircuitOperationTimeout + + match result with + | Some _ -> () + | None -> return raise <| TimeoutErrorException() } member __.RegisterAsRendezvousPoint(cookie: array) = @@ -1173,11 +1182,15 @@ and TorCircuit ) - return! + let! result = completionTaskRes |> UnwrapResult |> Async.AwaitTask |> FSharpUtil.WithTimeout Constants.CircuitOperationTimeout + + match result with + | Some _ -> () + | None -> return raise <| TimeoutErrorException() } member self.ExtendAsync nodeDetail = @@ -1199,11 +1212,15 @@ and TorCircuit Constants.CircuitOperationTimeout.TotalMilliseconds |> int ) - return! + let! introduceResult = completionTaskRes |> UnwrapResult |> Async.AwaitTask |> FSharpUtil.WithTimeout Constants.CircuitOperationTimeout + + match introduceResult with + | Some result -> return result + | None -> return raise <| TimeoutErrorException() } member __.WaitingForRendezvousJoin @@ -1227,12 +1244,15 @@ and TorCircuit Constants.CircuitRendezvousTimeout.TotalMilliseconds |> int ) - return! + let! result = completionTaskRes |> UnwrapResult |> Async.AwaitTask |> FSharpUtil.WithTimeout Constants.CircuitRendezvousTimeout + match result with + | Some _ -> () + | None -> return raise <| TimeoutErrorException() } member __.Rendezvous diff --git a/NOnion/Network/TorGuard.fs b/NOnion/Network/TorGuard.fs index 5c1109cc..1384ebdb 100644 --- a/NOnion/Network/TorGuard.fs +++ b/NOnion/Network/TorGuard.fs @@ -117,11 +117,15 @@ type TorGuard private (client: TcpClient, sslStream: SslStream) = |> sprintf "TorGuard: trying to connect to %s guard node" |> TorLogger.Log - do! + let! taskResult = client.ConnectAsync(ipEndpoint.Address, ipEndpoint.Port) |> Async.AwaitTask |> FSharpUtil.WithTimeout Constants.GuardConnectionTimeout + + match taskResult with + | Some _ -> () + | None -> return raise <| TimeoutErrorException() } do! @@ -141,14 +145,22 @@ type TorGuard private (client: TcpClient, sslStream: SslStream) = |> TorLogger.Log let innerAuthenticateAsClient(stream: SslStream) = - stream.AuthenticateAsClientAsync( - String.Empty, - null, - SslProtocols.Tls12, - false - ) - |> Async.AwaitTask - |> FSharpUtil.WithTimeout Constants.CircuitOperationTimeout + async { + let! taskResult = + stream.AuthenticateAsClientAsync( + String.Empty, + null, + SslProtocols.Tls12, + false + ) + |> Async.AwaitTask + |> FSharpUtil.WithTimeout + Constants.CircuitOperationTimeout + + match taskResult with + | Some result -> return result + | None -> return raise <| TimeoutErrorException() + } do! ExceptionUtil.RunGuardJobWithExceptionHandling( @@ -352,46 +364,58 @@ type TorGuard private (client: TcpClient, sslStream: SslStream) = Async.Start(readFromStream(), shutdownToken.Token) member private self.Handshake() = - async { - TorLogger.Log "TorGuard: started handshake process" - - do! - self.Send - Constants.DefaultCircuitId - { - CellVersions.Versions = - Constants.SupportedProtocolVersion - } - - let! _version = self.ReceiveExpected() - let! _certs = self.ReceiveExpected() - //TODO: Client authentication isn't implemented yet! - do! self.ReceiveExpected() |> Async.Ignore - let! netInfo = self.ReceiveExpected() - let maybeOtherAddress = netInfo.MyAddresses |> Seq.tryHead + let handshakeTask = + async { + TorLogger.Log "TorGuard: started handshake process" - match maybeOtherAddress with - | None -> - return - raise - <| GuardConnectionFailedException( - "TorGuard.Handshake: problem in initializing the handshake process" - ) - | Some otherAddress -> do! self.Send Constants.DefaultCircuitId { - CellNetInfo.Time = - DateTimeUtils.ToUnixTimestamp DateTime.UtcNow - OtherAddress = otherAddress - MyAddresses = List.singleton netInfo.OtherAddress + CellVersions.Versions = + Constants.SupportedProtocolVersion } - TorLogger.Log "TorGuard: finished handshake process" - //TODO: do security checks on handshake data + let! _version = self.ReceiveExpected() + let! _certs = self.ReceiveExpected() + //TODO: Client authentication isn't implemented yet! + do! self.ReceiveExpected() |> Async.Ignore + let! netInfo = self.ReceiveExpected() + let maybeOtherAddress = netInfo.MyAddresses |> Seq.tryHead + + match maybeOtherAddress with + | None -> + return + raise + <| GuardConnectionFailedException( + "TorGuard.Handshake: problem in initializing the handshake process" + ) + | Some otherAddress -> + do! + self.Send + Constants.DefaultCircuitId + { + CellNetInfo.Time = + DateTimeUtils.ToUnixTimestamp + DateTime.UtcNow + OtherAddress = otherAddress + MyAddresses = + List.singleton netInfo.OtherAddress + } + + TorLogger.Log "TorGuard: finished handshake process" + //TODO: do security checks on handshake data + } + + async { + let! handshakeResult = + handshakeTask + |> FSharpUtil.WithTimeout Constants.CircuitOperationTimeout + + match handshakeResult with + | Some _ -> () + | None -> return raise <| TimeoutErrorException() } - |> FSharpUtil.WithTimeout Constants.CircuitOperationTimeout member internal __.RegisterCircuit(circuit: ITorCircuit) : uint16 = let rec createCircuitId(retry: int) = diff --git a/NOnion/Network/TorStream.fs b/NOnion/Network/TorStream.fs index e29866c1..9d1510da 100644 --- a/NOnion/Network/TorStream.fs +++ b/NOnion/Network/TorStream.fs @@ -5,6 +5,7 @@ open System.Threading.Tasks open System.Threading.Tasks.Dataflow open FSharpx.Collections +open Fsdk open NOnion open NOnion.Cells.Relay @@ -456,11 +457,15 @@ type TorStream(circuit: TorCircuit) = Constants.StreamCreationTimeout.TotalMilliseconds |> int ) - return! + let! teskResult = completionTaskRes |> UnwrapResult |> Async.AwaitTask |> FSharpUtil.WithTimeout Constants.StreamCreationTimeout + + match teskResult with + | Some result -> return result + | None -> return raise <| TimeoutErrorException() } member self.ConnectToDirectory() = diff --git a/NOnion/Utility/FSharpUtil.fs b/NOnion/Utility/FSharpUtil.fs index b5002f00..1ae482a9 100644 --- a/NOnion/Utility/FSharpUtil.fs +++ b/NOnion/Utility/FSharpUtil.fs @@ -9,15 +9,6 @@ open Fsdk open NOnion module FSharpUtil = - let WithTimeout (timeSpan: TimeSpan) (job: Async<'R>) : Async<'R> = - async { - let! result = FSharpUtil.WithTimeout timeSpan job - - match result with - | Some value -> return value - | None -> return raise <| TimeoutErrorException() - } - let Retry<'TEx when 'TEx :> Exception> (jobToRetry: Async) (maxRetryCount: int)