remote: fix deadlocked client when server rejects its cert (#897)

* remote: detect tls errors sooner to prevent deadlocks

* remove redundant error checking

* cleanup
This commit is contained in:
Alexander Bondarenko authored and GitHub committed 2023-11-17 10:37:32 +00:00
1 parent 3b348a463c
commit c501f4f9cc
2 files changed
+19 -8

No files matched your search

@@ -6,6 +6,7 @@ module Simplex.Messaging.Transport.Buffer where
import Control.Concurrent.STM
import qualified Control.Exception as E
import Control.Monad (forM_)
import Data.ByteString.Char8 (ByteString)
import qualified Data.ByteString.Char8 as B
import GHC.IO.Exception (IOErrorType (..), IOException (..), ioException)
@@ -28,6 +29,14 @@ withBufferLock TBuffer {getLock} =
(atomically $ takeTMVar getLock)
(atomically $ putTMVar getLock ())
-- | Attempt to read some bytes, appending it to the existing buffer
peekBuffered :: TBuffer -> Int -> IO ByteString -> IO (ByteString, Maybe ByteString)
peekBuffered tb@TBuffer {buffer} t getChunk = withBufferLock tb $ do
old <- readTVarIO buffer
next_ <- timeout t getChunk
forM_ next_ $ \next -> atomically $ writeTVar buffer $! old <> next
pure (old, next_)
getBuffered :: TBuffer -> Int -> Maybe Int -> IO ByteString -> IO ByteString
getBuffered tb@TBuffer {buffer} n t_ getChunk = withBufferLock tb $ do
b <- readChunks True =<< readTVarIO buffer
+10 -8
View File
@@ -54,7 +54,8 @@ import qualified Simplex.Messaging.Crypto.Lazy as LC
import Simplex.Messaging.Crypto.SNTRUP761
import Simplex.Messaging.Crypto.SNTRUP761.Bindings
import Simplex.Messaging.Encoding
import Simplex.Messaging.Transport (TLS (tlsUniq), cGet, cPut)
import Simplex.Messaging.Transport (TLS (..), cGet, cPut)
import Simplex.Messaging.Transport.Buffer (peekBuffered)
import Simplex.Messaging.Transport.Client (TransportClientConfig (..), TransportHost, defaultTransportClientConfig, runTransportClient)
import Simplex.Messaging.Transport.Credentials (genCredentials, tlsCredentials)
import Simplex.Messaging.Util
@@ -273,13 +274,14 @@ connectRCCtrl_ drg pairing'@RCCtrlPairing {caKey, caCert} inv@RCInvitation {ca,
TLS.Credentials (creds : _) -> pure $ Just creds
_ -> throwError $ RCEInternal "genTLSCredentials must generate credentials"
let clientConfig = defaultTransportClientConfig {clientCredentials}
liftIO . runTransportClient clientConfig Nothing host (show port) (Just ca) $ \tls ->
void . runExceptT $ do
logDebug "Got TLS connection"
r' <- newEmptyTMVarIO
whenM (atomically $ tryPutTMVar r $ Right (tlsUniq tls, tls, r')) $ do
logDebug "Waiting for session confirmation"
whenM (atomically $ readTMVar confirmSession) (runSession tls r') `putRCError` r'
runTransportClient clientConfig Nothing host (show port) (Just ca) $ \tls@TLS {tlsBuffer, tlsContext} -> do
-- pump socket to detect connection problems
liftIO $ peekBuffered tlsBuffer 100000 (TLS.recvData tlsContext) >>= logDebug . tshow -- should normally be ("", Nothing) here
logDebug "Got TLS connection"
r' <- newEmptyTMVarIO
whenM (atomically $ tryPutTMVar r $ Right (tlsUniq tls, tls, r')) $ do
logDebug "Waiting for session confirmation"
whenM (atomically $ readTMVar confirmSession) $ runSession tls r' `putRCError` r'
where
runSession tls r' = do
(sharedKey, kemPrivKey, hostEncHello) <- prepareHostHello drg pairing' inv hostAppInfo