diff --git a/src/Simplex/FileTransfer/Agent.hs b/src/Simplex/FileTransfer/Agent.hs index a8b220327..959a45d5f 100644 --- a/src/Simplex/FileTransfer/Agent.hs +++ b/src/Simplex/FileTransfer/Agent.hs @@ -348,7 +348,7 @@ xftpDeleteRcvFiles' c rcvFileEntityIds = do batchFiles f rcvFiles = withStoreBatch' c $ \db -> map (\RcvFile {rcvFileId} -> f db rcvFileId) rcvFiles notify :: forall m e. (MonadIO m, AEntityI e) => AgentClient -> AEntityId -> AEvent e -> m () -notify c entId cmd = atomically $ writeTBQueue (subQ c) ("", entId, AEvt (sAEntity @e) cmd) +notify c entId cmd = liftIO $ notifyEvent c ("", entId, AEvt (sAEntity @e) cmd) xftpSendFile' :: AgentClient -> UserId -> CryptoFile -> Int -> AM SndFileId xftpSendFile' c userId file numRecipients = do diff --git a/src/Simplex/Messaging/Agent.hs b/src/Simplex/Messaging/Agent.hs index 03af68e87..ce8cceee8 100644 --- a/src/Simplex/Messaging/Agent.hs +++ b/src/Simplex/Messaging/Agent.hs @@ -256,12 +256,12 @@ import UnliftIO.STM type AE a = ExceptT AgentErrorType IO a -- | Creates an SMP agent client instance -getSMPAgentClient :: AgentConfig -> InitialAgentServers -> DBStore -> Bool -> AE AgentClient +getSMPAgentClient :: AgentConfig -> InitialAgentServers -> DBStore -> Bool -> (ATransmission -> IO ()) -> AE AgentClient getSMPAgentClient = getSMPAgentClient_ 1 {-# INLINE getSMPAgentClient #-} -getSMPAgentClient_ :: Int -> AgentConfig -> InitialAgentServers -> DBStore -> Bool -> AE AgentClient -getSMPAgentClient_ clientId cfg initServers@InitialAgentServers {smp, xftp, netCfg, useServices, presetServers} store backgroundMode = do +getSMPAgentClient_ :: Int -> AgentConfig -> InitialAgentServers -> DBStore -> Bool -> (ATransmission -> IO ()) -> AE AgentClient +getSMPAgentClient_ clientId cfg initServers@InitialAgentServers {smp, xftp, netCfg, useServices, presetServers} store backgroundMode processEvent = do -- This error should be prevented in the app when (any id useServices && sessionMode netCfg == TSMEntity) $ throwE $ CMD PROHIBITED "newAgentClient" liftIO $ newSMPAgentEnv cfg store >>= runReaderT runAgent @@ -272,7 +272,8 @@ getSMPAgentClient_ clientId cfg initServers@InitialAgentServers {smp, xftp, netC notices <- liftIO $ withTransaction store (`getClientNotices` presetServers) `catchAll_` pure [] env <- ask let processMsg c t = subscriber c t `runReaderT` env - c@AgentClient {acThread} <- liftIO $ newAgentClient clientId initServers currentTs notices processMsg env + c@AgentClient {acThread, generalQ} <- liftIO $ newAgentClient clientId initServers currentTs notices processEvent processMsg env + void $ liftIO $ forkIO $ connWorkerLoop c generalQ unless backgroundMode $ do t <- runAgentThreads c `forkFinally` const (liftIO $ disconnectAgentClient c) atomically . writeTVar acThread . Just =<< mkWeakThreadId t @@ -287,10 +288,10 @@ getSMPAgentClient_ clientId cfg initServers@InitialAgentServers {smp, xftp, netC run c "logServersStats" $ logServersStats c ] `E.finally` saveServersStats c - run AgentClient {subQ, acThread} name a = + run c'@AgentClient {acThread} name a = a `E.catchAny` \e -> whenM (isJust <$> readTVarIO acThread) $ do logError $ "Agent thread " <> name <> " crashed: " <> tshow e - atomically $ writeTBQueue subQ ("", "", AEvt SAEConn $ ERR $ CRITICAL True $ show e) + liftIO $ notifyEvent c' ("", "", AEvt SAEConn $ ERR $ CRITICAL True $ show e) logServersStats :: AgentClient -> AM' () logServersStats c = do @@ -303,19 +304,19 @@ logServersStats c = do liftIO $ threadDelay' int saveServersStats :: AgentClient -> AM' () -saveServersStats c@AgentClient {subQ, smpServersStats, xftpServersStats, ntfServersStats} = do +saveServersStats c@AgentClient {smpServersStats, xftpServersStats, ntfServersStats} = do sss <- mapM (liftIO . getAgentSMPServerStats) =<< readTVarIO smpServersStats xss <- mapM (liftIO . getAgentXFTPServerStats) =<< readTVarIO xftpServersStats nss <- mapM (liftIO . getAgentNtfServerStats) =<< readTVarIO ntfServersStats let stats = AgentPersistedServerStats {smpServersStats = sss, xftpServersStats = xss, ntfServersStats = OptionalMap nss} tryAllErrors' (withStore' c (`updateServersStats` stats)) >>= \case - Left e -> atomically $ writeTBQueue subQ ("", "", AEvt SAEConn $ ERR $ INTERNAL $ show e) + Left e -> liftIO $ notifyEvent c ("", "", AEvt SAEConn $ ERR $ INTERNAL $ show e) Right () -> pure () restoreServersStats :: AgentClient -> AM' () restoreServersStats c@AgentClient {smpServersStats, xftpServersStats, ntfServersStats, srvStatsStartedAt} = do tryAllErrors' (withStore c getServersStats) >>= \case - Left e -> atomically $ writeTBQueue (subQ c) ("", "", AEvt SAEConn $ ERR $ INTERNAL $ show e) + Left e -> liftIO $ notifyEvent c ("", "", AEvt SAEConn $ ERR $ INTERNAL $ show e) Right (startedAt, Nothing) -> atomically $ writeTVar srvStatsStartedAt startedAt Right (startedAt, Just AgentPersistedServerStats {smpServersStats = sss, xftpServersStats = xss, ntfServersStats = OptionalMap nss}) -> do atomically $ writeTVar srvStatsStartedAt startedAt @@ -820,8 +821,8 @@ deleteUser' c@AgentClient {smpServersStats, xftpServersStats} userId delSMPQueue lift $ saveServersStats c where delUser = - whenM (withStore' c (`deleteUserWithoutConns` userId)) . atomically $ - writeTBQueue (subQ c) ("", "", AEvt SAENone $ DEL_USER userId) + whenM (withStore' c (`deleteUserWithoutConns` userId)) . liftIO $ + notifyEvent c ("", "", AEvt SAENone $ DEL_USER userId) setUserService' :: AgentClient -> UserId -> Bool -> AM () setUserService' c userId enable = do @@ -1324,7 +1325,7 @@ startJoinInvitation c userId connId sq_ enableNtfs cReqUri pqSup = getSndRatchet db connId v >>= \case Right r -> pure $ Right $ snd r Left e -> do - nonBlockingWriteTBQueue (subQ c) ("", connId, AEvt SAEConn (ERR $ INTERNAL $ "no snd ratchet " <> show e)) + notifyEvent c ("", connId, AEvt SAEConn (ERR $ INTERNAL $ "no snd ratchet " <> show e)) runExceptT $ createRatchet_ db g maxSupported pqSupport e2eRcvParams pure (cData, sq, e2eSndParams, Nothing) _ -> do @@ -1418,7 +1419,7 @@ joinConnSrv c nm userId connId enableNtfs cReqUri@CRContactUri {} cInfo pqSup su getRatchetX3dhKeys db connId >>= \case Right keys -> pure $ CR.mkRcvE2ERatchetParams (maxVersion e2eVR) keys Left e -> do - nonBlockingWriteTBQueue (subQ c) ("", connId, AEvt SAEConn (ERR $ INTERNAL $ "no rcv ratchet " <> show e)) + notifyEvent c ("", connId, AEvt SAEConn (ERR $ INTERNAL $ "no rcv ratchet " <> show e)) let pqEnc = CR.initialPQEncryption False pqInitKeys (pk1, pk2, pKem, e2eRcvParams) <- liftIO $ CR.generateRcvE2EParams g (maxVersion e2eVR) pqEnc createRatchetX3dhKeys db connId pk1 pk2 pKem @@ -1430,7 +1431,7 @@ joinConnSrv c nm userId connId enableNtfs cReqUri@CRContactUri {} cInfo pqSup su delInvSL :: AgentClient -> ConnId -> SMPServerWithAuth -> SMP.LinkId -> AM () delInvSL c connId srv lnkId = withStore' c (\db -> deleteInvShortLink db (protoServer srv) lnkId) `catchE` \e -> - liftIO $ nonBlockingWriteTBQueue (subQ c) ("", connId, AEvt SAEConn (ERR $ INTERNAL $ "error deleting short link " <> show e)) + liftIO $ notifyEvent c ("", connId, AEvt SAEConn (ERR $ INTERNAL $ "error deleting short link " <> show e)) joinConnSrvAsync :: AgentClient -> UserId -> ConnId -> Bool -> ConnectionRequestUri c -> ConnInfo -> PQSupport -> SubscriptionMode -> SMPServerWithAuth -> AM SndQueueSecured joinConnSrvAsync c userId connId enableNtfs inv@CRInvitationUri {} cInfo pqSupport subMode srv = do @@ -1603,8 +1604,8 @@ subscribeConnections_ c conns = do notifyResultError rs = do let actual = M.size rs expected = length conns - when (actual /= expected) . atomically $ - writeTBQueue (subQ c) ("", "", AEvt SAEConn $ ERR $ INTERNAL $ "subscribeConnections result size: " <> show actual <> ", expected " <> show expected) + when (actual /= expected) . liftIO $ + notifyEvent c ("", "", AEvt SAEConn $ ERR $ INTERNAL $ "subscribeConnections result size: " <> show actual <> ", expected " <> show expected) subscribeAllConnections' :: AgentClient -> Bool -> Maybe UserId -> AM () subscribeAllConnections' c onlyNeeded activeUserId_ = handleErr $ do @@ -1651,7 +1652,7 @@ subscribeAllConnections' c onlyNeeded activeUserId_ = handleErr $ do Just SSErrorQueueCount {expectedQueueCount = n, subscribedQueueCount = n'} | n > 0 && n' == 0 -> unassocQueues _ -> pure True Left e -> do - atomically $ writeTBQueue (subQ c) ("", "", AEvt SAEConn $ ERR e) + liftIO $ notifyEvent c ("", "", AEvt SAEConn $ ERR e) if clientServiceError e then False <$ withStore' c (\db -> unassocUserServerRcvQueueSubs' db userId srv) else pure True @@ -1860,7 +1861,7 @@ getAsyncCmdWorker hasWork c connId server = data CommandCompletion = CCMoved | CCCompleted runCommandProcessing :: AgentClient -> ConnId -> Maybe SMPServer -> Worker -> AM () -runCommandProcessing c@AgentClient {subQ} connId server_ Worker {doWork} = do +runCommandProcessing c connId server_ Worker {doWork} = do ri <- asks $ messageRetryInterval . config -- different retry interval? forever $ do atomically $ endAgentOperation c AOSndNetwork @@ -1872,7 +1873,7 @@ runCommandProcessing c@AgentClient {subQ} connId server_ Worker {doWork} = do runProcessCmd ri cmd = do pending <- newTVarIO [] processCmd ri cmd pending - mapM_ (atomically . writeTBQueue subQ) . reverse =<< readTVarIO pending + mapM_ (liftIO . notifyEvent c) . reverse =<< readTVarIO pending processCmd :: RetryInterval -> PendingCommand -> TVar [ATransmission] -> AM () processCmd ri PendingCommand {cmdId, corrId, userId, command} pendingCmds = case command of AClientCommand cmd -> case cmd of @@ -2028,9 +2029,7 @@ runCommandProcessing c@AgentClient {subQ} connId server_ Worker {doWork} = do internalErr s = cmdError $ INTERNAL $ s <> ": " <> show (agentCommandTag command) cmdError e = notify (ERR e) >> withStore' c (`deleteCommand` cmdId) notify :: forall e. AEntityI e => AEvent e -> AM () - notify cmd = - let t = (corrId, connId, AEvt (sAEntity @e) cmd) - in atomically $ ifM (isFullTBQueue subQ) (modifyTVar' pendingCmds (t :)) (writeTBQueue subQ t) + notify cmd = atomically $ modifyTVar' pendingCmds ((corrId, connId, AEvt (sAEntity @e) cmd) :) -- ^ ^ ^ async command processing / enqueueMessages :: AgentClient -> ConnData -> NonEmpty SndQueue -> MsgFlags -> AMessage -> AM (AgentMsgId, PQEncryption) @@ -2163,7 +2162,7 @@ submitPendingMsg c sq = do void $ getDeliveryWorker True c sq runSmpQueueMsgDelivery :: AgentClient -> SndQueue -> (Worker, TMVar ()) -> AM () -runSmpQueueMsgDelivery c@AgentClient {subQ} sq@SndQueue {userId, connId, server, queueMode} (Worker {doWork}, qLock) = do +runSmpQueueMsgDelivery c sq@SndQueue {userId, connId, server, queueMode} (Worker {doWork}, qLock) = do AgentConfig {messageRetryInterval = ri, messageTimeout, helloTimeout, quotaExceededTimeout} <- asks config forever $ do atomically $ endAgentOperation c AOSndNetwork @@ -2331,7 +2330,7 @@ runSmpQueueMsgDelivery c@AgentClient {subQ} sq@SndQueue {userId, connId, server, delMsgKeep :: Bool -> InternalId -> AM () delMsgKeep keepForReceipt msgId = withStore' c $ \db -> deleteSndMsgDelivery db connId sq msgId keepForReceipt notify :: forall e. AEntityI e => AEvent e -> AM () - notify cmd = atomically $ writeTBQueue subQ ("", connId, AEvt (sAEntity @e) cmd) + notify cmd = liftIO $ notifyEvent c ("", connId, AEvt (sAEntity @e) cmd) notifyDel :: AEntityI e => InternalId -> AEvent e -> AM () notifyDel msgId cmd = notify cmd >> delMsg msgId connError msgId = notifyDel msgId . ERR . (`CONN` "") @@ -2353,7 +2352,7 @@ retrySndOp c loop = do withConnLockNotify :: AgentClient -> ConnId -> Text -> AM (Maybe ATransmission) -> AM () withConnLockNotify c connId name action = do t_ <- withConnLock c connId name action - forM_ t_ $ atomically . writeTBQueue (subQ c) + forM_ t_ $ liftIO . notifyEvent c ackMessage' :: AgentClient -> ConnId -> AgentMsgId -> Maybe MsgReceiptInfo -> AM () ackMessage' c connId msgId rcptInfo_ = withConnLockNotify c connId "ackMessage" $ do @@ -2570,7 +2569,7 @@ prepareDeleteConnections_ getConnections c waitDelivery connIds = do unsubNtfConnIds connIds' = do ns <- asks ntfSupervisor atomically $ writeTBQueue (ntfSubQ ns) (NSCDeleteSub, connIds') - notify = atomically . writeTBQueue (subQ c) + notify = liftIO . notifyEvent c deleteConnQueues :: AgentClient -> NetworkRequestMode -> Bool -> Bool -> [RcvQueue] -> AM' (Map ConnId (Either AgentErrorType ())) deleteConnQueues c nm waitDelivery ntf rqs = do @@ -2604,7 +2603,7 @@ deleteConnQueues c nm waitDelivery ntf rqs = do -- attempts and successes are counted in deleteQueues function atomically $ incSMPServerStat c userId server connDeleted pure ((rq, Right ()), Just (Just e)) - notify = when ntf . atomically . writeTBQueue (subQ c) + notify = when ntf . liftIO . notifyEvent c connResults :: [(RcvQueue, Either AgentErrorType ())] -> Map ConnId (Either AgentErrorType ()) connResults = M.map snd . foldl' addResult M.empty where @@ -2640,8 +2639,8 @@ deleteConnections_ getConnections ntf waitDelivery c nm connIds = do notifyResultError rs = do let actual = M.size rs expected = length connIds - when (actual /= expected) . atomically $ - writeTBQueue (subQ c) ("", "", AEvt SAEConn $ ERR $ INTERNAL $ "deleteConnections result size: " <> show actual <> ", expected " <> show expected) + when (actual /= expected) . liftIO $ + notifyEvent c ("", "", AEvt SAEConn $ ERR $ INTERNAL $ "deleteConnections result size: " <> show actual <> ", expected " <> show expected) getConnectionServers' :: AgentClient -> ConnId -> AM ConnectionStats getConnectionServers' c connId = do @@ -2941,23 +2940,23 @@ suspendAgent :: AgentClient -> Int -> IO () suspendAgent c 0 = do atomically $ writeTVar (agentState c) ASSuspended mapM_ suspend agentOperations + notifyEvent c ("", "", AEvt SAENone SUSPENDED) where suspend opSel = atomically $ modifyTVar' (opSel c) $ \s -> s {opSuspended = True} suspendAgent c@AgentClient {agentState = as} maxDelay = do - state <- - atomically $ do - writeTVar as ASSuspending - suspendOperation c AONtfNetwork $ pure () - suspendOperation c AORcvNetwork $ - suspendOperation c AOMsgDelivery $ - suspendSendingAndDatabase c - readTVar as + (state, suspended) <- atomically $ do + writeTVar as ASSuspending + void $ suspendOperation c AONtfNetwork $ pure False + suspended <- suspendOperation c AORcvNetwork $ + suspendOperation c AOMsgDelivery $ + suspendSendingAndDatabase c + (,suspended) <$> readTVar as + when suspended $ notifyEvent c ("", "", AEvt SAENone SUSPENDED) when (state == ASSuspending) . void . forkIO $ do threadDelay maxDelay - -- liftIO $ putStrLn "suspendAgent after timeout" - atomically . whenSuspending c $ do - -- unsafeIOToSTM $ putStrLn $ "in timeout: suspendSendingAndDatabase" + suspended' <- atomically . whenSuspendingB c $ suspendSendingAndDatabase c + when suspended' $ notifyEvent c ("", "", AEvt SAENone SUSPENDED) execAgentStoreSQL :: AgentClient -> Text -> AE [Text] execAgentStoreSQL c sql = withAgentEnv c $ withStore' c (`execSQL` sql) @@ -2983,16 +2982,16 @@ getNextSMPServer c userId = getNextServer c userId storageSrvs {-# INLINE getNextSMPServer #-} subscriber :: AgentClient -> ServerTransmissionBatch SMPVersion ErrorType BrokerMsg -> AM' () -subscriber c@AgentClient {subQ} t = run $ +subscriber c t = run $ agentOperationBracket c AORcvNetwork waitUntilActive $ processSMPTransmissions c t where run a = a `catchOwn` \e -> notify $ CRITICAL True $ "subscriber error: " <> show e - notify err = atomically $ writeTBQueue subQ ("", "", AEvt SAEConn $ ERR err) + notify err = liftIO $ notifyEvent c ("", "", AEvt SAEConn $ ERR err) cleanupManager :: AgentClient -> AM' () -cleanupManager c@AgentClient {subQ} = do +cleanupManager c = do AgentConfig {initialCleanupDelay, cleanupInterval = int, storedMsgDataTTL = ttl, cleanupBatchSize = limit} <- asks config liftIO $ threadDelay' initialCleanupDelay @@ -3060,7 +3059,7 @@ cleanupManager c@AgentClient {subQ} = do rcvFilesTTL <- asks $ rcvFilesTTL . config withStore' c (`deleteDeletedSndChunkReplicasExpired` rcvFilesTTL) notify :: forall e. AEntityI e => AEntityId -> AEvent e -> AM () - notify entId cmd = atomically $ writeTBQueue subQ ("", entId, AEvt (sAEntity @e) cmd) + notify entId cmd = liftIO $ notifyEvent c ("", entId, AEvt (sAEntity @e) cmd) data ACKd = ACKd | ACKPending @@ -3068,7 +3067,7 @@ data ACKd = ACKd | ACKPending -- It cannot be finally, as sometimes it needs to be ACK+DEL, -- and sometimes ACK has to be sent from the consumer. processSMPTransmissions :: AgentClient -> ServerTransmissionBatch SMPVersion ErrorType BrokerMsg -> AM' () -processSMPTransmissions c@AgentClient {subQ} (tSess@(userId, srv, _), THandleParams {thAuth, sessionId = sessId}, ts) = do +processSMPTransmissions c (tSess@(userId, srv, _), THandleParams {thAuth, sessionId = sessId}, ts) = do upConnIds <- newTVarIO [] serviceRQs <- newTVarIO ([] :: [RcvQueue]) forM_ ts $ \(entId, t) -> case t of @@ -3141,14 +3140,14 @@ processSMPTransmissions c@AgentClient {subQ} (tSess@(userId, srv, _), THandlePar (atomically $ putTMVar (clientNoticesLock c) ()) (processClientNotices c tSess [(rcvQueueSub rq, notice_)]) notify' :: forall e m. (AEntityI e, MonadIO m) => ConnId -> AEvent e -> m () - notify' connId msg = atomically $ writeTBQueue subQ ("", connId, AEvt (sAEntity @e) msg) + notify' connId msg = liftIO $ notifyEvent c ("", connId, AEvt (sAEntity @e) msg) notifyErr :: ConnId -> SMPClientError -> AM' () notifyErr connId = notify' connId . ERR . protocolClientError SMP (B.unpack $ strEncode srv) runProcessSMP :: RcvQueue -> Connection c -> ConnData -> BrokerMsg -> AM () runProcessSMP rq conn cData msg = do pending <- newTVarIO [] processSMP rq conn cData msg pending - mapM_ (atomically . writeTBQueue subQ) . reverse =<< readTVarIO pending + mapM_ (liftIO . notifyEvent c) . reverse =<< readTVarIO pending processSMP :: forall c. RcvQueue -> Connection c -> ConnData -> BrokerMsg -> TVar [ATransmission] -> AM () processSMP rq@RcvQueue {rcvId = rId, queueMode, e2ePrivKey, e2eDhSecret, status, smpClientVersion = agreedClientVerion} @@ -3355,9 +3354,7 @@ processSMPTransmissions c@AgentClient {subQ} (tSess@(userId, srv, _), THandlePar notify :: forall e m. (AEntityI e, MonadIO m) => AEvent e -> m () notify = notify_ connId notify_ :: forall e m. (AEntityI e, MonadIO m) => ConnId -> AEvent e -> m () - notify_ connId' msg = - let t = ("", connId', AEvt (sAEntity @e) msg) - in atomically $ ifM (isFullTBQueue subQ) (modifyTVar' pendingMsgs (t :)) (writeTBQueue subQ t) + notify_ connId' msg = atomically $ modifyTVar' pendingMsgs (("", connId', AEvt (sAEntity @e) msg) :) prohibited :: Text -> AM () prohibited s = do diff --git a/src/Simplex/Messaging/Agent/Client.hs b/src/Simplex/Messaging/Agent/Client.hs index e70004a56..30796bf4a 100644 --- a/src/Simplex/Messaging/Agent/Client.hs +++ b/src/Simplex/Messaging/Agent/Client.hs @@ -157,6 +157,7 @@ module Simplex.Messaging.Agent.Client suspendOperation, notifySuspended, whenSuspending, + whenSuspendingB, withStore, withStore', withStoreBatch, @@ -165,6 +166,8 @@ module Simplex.Messaging.Agent.Client storeError, notifySub, notifySub', + notifyEvent, + connWorkerLoop, userServers, pickServer, getNextServer, @@ -334,10 +337,20 @@ type NtfTransportSession = TransportSession NtfResponse type XFTPTransportSession = TransportSession FileResponse +data EventWorker = EventWorker + { eventQ :: TBQueue ATransmission, + workerThreadId :: Weak ThreadId + } + +type EventWorkerVar = SessionVar EventWorker + data AgentClient = AgentClient { acThread :: TVar (Maybe (Weak ThreadId)), active :: TVar Bool, - subQ :: TBQueue ATransmission, + processEvent :: ATransmission -> IO (), + generalQ :: TBQueue ATransmission, + connWorkers :: TMap ConnId EventWorkerVar, + connWorkerSeq :: TVar Int, processServerMsg :: AgentClient -> ServerTransmissionBatch SMPVersion ErrorType BrokerMsg -> IO (), smpServers :: TMap UserId (UserServers 'PSMP), smpClients :: TMap SMPTransportSession SMPClientVar, @@ -419,7 +432,8 @@ getAgentWorker' toW fromW name hasWork c@AgentClient {agentEnv} key ws work = do t <- liftIO getSystemTime let maxRestarts = maxWorkerRestartsPerMin $ config agentEnv -- worker may terminate because it was deleted from the map (getWorker returns Nothing), then it won't restart - restart <- atomically $ getWorker >>= maybe (pure False) (shouldRestart e_ (toW w) t maxRestarts) + (restart, notify_) <- atomically $ getWorker >>= maybe (pure (False, Nothing)) (shouldRestart e_ (toW w) t maxRestarts) + forM_ notify_ $ liftIO . notifyEvent c when restart runWork shouldRestart e_ Worker {workerId = wId, doWork, action, restarts} t maxRestarts w' | wId == workerId (toW w') = do @@ -427,24 +441,21 @@ getAgentWorker' toW fromW name hasWork c@AgentClient {agentEnv} key ws work = do isActive <- readTVar $ active c checkRestarts isActive $ updateRestartCount t rc | otherwise = - pure False -- there is a new worker in the map, no action + pure (False, Nothing) -- there is a new worker in the map, no action where checkRestarts isActive rc | isActive && restartCount rc < maxRestarts = do writeTVar restarts rc hasWorkToDo' doWork void $ tryPutTMVar action Nothing - notifyErr INTERNAL - pure True + pure (True, Just $ notifyMsg rc INTERNAL) | otherwise = do TM.delete key ws - when isActive $ notifyErr $ CRITICAL True - pure False - where - notifyErr err = do - let e = either ((", error: " <>) . show) (\_ -> ", no error") e_ - msg = "Worker " <> name <> " for " <> show key <> " terminated " <> show (restartCount rc) <> " times" <> e - writeTBQueue (subQ c) ("", "", AEvt SAEConn $ ERR $ err msg) + pure (False, if isActive then Just (notifyMsg rc $ CRITICAL True) else Nothing) + notifyMsg rc err = + let e = either ((", error: " <>) . show) (\_ -> ", no error") e_ + msg = "Worker " <> name <> " for " <> show key <> " terminated " <> show (restartCount rc) <> " times" <> e + in ("", "", AEvt SAEConn $ ERR $ err msg) newWorker :: AgentClient -> STM Worker newWorker c = do @@ -505,14 +516,16 @@ data UserNetworkType = UNNone | UNCellular | UNWifi | UNEthernet | UNOther deriving (Eq, Show) -- | Creates an SMP agent client instance that receives commands and sends responses via 'TBQueue's. -newAgentClient :: Int -> InitialAgentServers -> UTCTime -> Map (Maybe SMPServer) (Maybe SystemSeconds) -> (AgentClient -> ServerTransmissionBatch SMPVersion ErrorType BrokerMsg -> IO ()) -> Env -> IO AgentClient -newAgentClient clientId InitialAgentServers {smp, ntf, xftp, netCfg, useServices, presetDomains, presetServers} currentTs notices processServerMsg agentEnv = do +newAgentClient :: Int -> InitialAgentServers -> UTCTime -> Map (Maybe SMPServer) (Maybe SystemSeconds) -> (ATransmission -> IO ()) -> (AgentClient -> ServerTransmissionBatch SMPVersion ErrorType BrokerMsg -> IO ()) -> Env -> IO AgentClient +newAgentClient clientId InitialAgentServers {smp, ntf, xftp, netCfg, useServices, presetDomains, presetServers} currentTs notices processEvent processServerMsg agentEnv = do let cfg = config agentEnv qSize = tbqSize cfg proxySessTs <- newTVarIO =<< getCurrentTime acThread <- newTVarIO Nothing active <- newTVarIO True - subQ <- newTBQueueIO qSize + generalQ <- newTBQueueIO qSize + connWorkers <- TM.emptyIO + connWorkerSeq <- newTVarIO 0 smpServers <- newTVarIO $ M.map mkUserServers smp smpClients <- TM.emptyIO useClientServices <- newTVarIO useServices @@ -551,7 +564,10 @@ newAgentClient clientId InitialAgentServers {smp, ntf, xftp, netCfg, useServices AgentClient { acThread, active, - subQ, + processEvent, + generalQ, + connWorkers, + connWorkerSeq, processServerMsg, smpServers, smpClients, @@ -834,7 +850,7 @@ resubscribeSMPSession c@AgentClient {smpSubWorkers, workerSeq} tSess = do handleNotify = E.handleAny $ notifySub' c "" . ERR . INTERNAL . show notifySub' :: forall e m. (AEntityI e, MonadIO m) => AgentClient -> ConnId -> AEvent e -> m () -notifySub' c connId cmd = liftIO $ nonBlockingWriteTBQueue (subQ c) (B.empty, connId, AEvt (sAEntity @e) cmd) +notifySub' c connId cmd = liftIO $ notifyEvent c (B.empty, connId, AEvt (sAEntity @e) cmd) {-# INLINE notifySub' #-} notifySub :: MonadIO m => AgentClient -> AEvent 'AENone -> m () @@ -862,7 +878,7 @@ getNtfServerClient c@AgentClient {active, ntfClients, workerSeq, proxySessTs, pr clientDisconnected :: NtfClientVar -> NtfClient -> IO () clientDisconnected v client = do atomically $ removeSessVar v tSess ntfClients - atomically $ writeTBQueue (subQ c) ("", "", AEvt SAENone $ hostEvent DISCONNECT client) + notifyEvent c ("", "", AEvt SAENone $ hostEvent DISCONNECT client) logInfo . decodeUtf8 $ "Agent disconnected from " <> showServer srv getXFTPServerClient :: AgentClient -> XFTPTransportSession -> AM XFTPClient @@ -886,7 +902,7 @@ getXFTPServerClient c@AgentClient {active, xftpClients, workerSeq, proxySessTs, clientDisconnected :: XFTPClientVar -> XFTPClient -> IO () clientDisconnected v client = do atomically $ removeSessVar v tSess xftpClients - atomically $ writeTBQueue (subQ c) ("", "", AEvt SAENone $ hostEvent DISCONNECT client) + notifyEvent c ("", "", AEvt SAENone $ hostEvent DISCONNECT client) logInfo . decodeUtf8 $ "Agent disconnected from " <> showServer srv waitForProtocolClient :: @@ -925,7 +941,7 @@ newProtocolClient c tSess@(userId, srv, entityId_) clients connectClient v = Right client -> do logInfo . decodeUtf8 $ "Agent connected to " <> showServer srv <> " (user " <> bshow userId <> maybe "" (" for entity " <>) entityId_ <> ")" atomically $ putTMVar (sessionVar v) (Right client) - liftIO $ nonBlockingWriteTBQueue (subQ c) ("", "", AEvt SAENone $ hostEvent CONNECT client) + liftIO $ notifyEvent c ("", "", AEvt SAENone $ hostEvent CONNECT client) pure client Left e -> do ei <- asks $ persistErrorInterval . config @@ -1053,6 +1069,30 @@ withConnLock' _ "" _ = id withConnLock' AgentClient {connLocks} connId name = withLockMap connLocks connId name {-# INLINE withConnLock' #-} +notifyEvent :: AgentClient -> ATransmission -> IO () +notifyEvent c t@(_, connId, _) + | B.null connId = atomically $ writeTBQueue (generalQ c) t + | otherwise = do + q <- getOrCreateConnWorker c connId + atomically $ writeTBQueue q t + +getOrCreateConnWorker :: AgentClient -> ConnId -> IO (TBQueue ATransmission) +getOrCreateConnWorker c@AgentClient {connWorkers, connWorkerSeq} connId = do + ts <- getCurrentTime + atomically (getSessVar connWorkerSeq connId connWorkers ts) >>= \case + Left v -> do + q <- newTBQueueIO 64 + tId <- mkWeakThreadId =<< forkIO (connWorkerLoop c q) + atomically $ putTMVar (sessionVar v) EventWorker {eventQ = q, workerThreadId = tId} + pure q + Right v -> eventQ <$> atomically (readTMVar $ sessionVar v) + +connWorkerLoop :: AgentClient -> TBQueue ATransmission -> IO () +connWorkerLoop AgentClient {processEvent} q = forever $ do + t <- atomically $ readTBQueue q + processEvent t `E.catchAny` \e -> + logError $ "connWorkerLoop error: " <> tshow e + withInvLock :: AgentClient -> ByteString -> Text -> AM a -> AM a withInvLock c key name = ExceptT . withInvLock' c key name . runExceptT {-# INLINE withInvLock #-} @@ -1739,7 +1779,7 @@ resubscribeClientService c tSess@(userId, srv, _) serviceSub = r <$ withStore' c (\db -> removeRcvServiceAssocs db userId srv) _ -> pure r Left e -> do - atomically $ writeTBQueue (subQ c) ("", "", AEvt SAEConn $ ERR e) + liftIO $ notifyEvent c ("", "", AEvt SAEConn $ ERR e) when (clientServiceError e) $ do atomically $ SS.deleteServiceSub tSess $ currentSubs c unassocSubscribeQueues @@ -2265,7 +2305,7 @@ withWork_ c doWork getWork action = noWork = liftIO $ noWorkToDo doWork notifyErr err e = do logError $ "withWork_ error: " <> tshow e - atomically $ writeTBQueue (subQ c) ("", "", AEvt SAEConn $ ERR $ err $ show e) + liftIO $ notifyEvent c ("", "", AEvt SAEConn $ ERR $ err $ show e) withWorkItems :: (AnyStoreError e', MonadIO m) => AgentClient -> TMVar () -> ExceptT e m (Either e' [Either e' a]) -> (NonEmpty a -> ExceptT e m ()) -> ExceptT e m () withWorkItems c doWork getWork action = do @@ -2290,7 +2330,7 @@ withWorkItems c doWork getWork action = do noWork = liftIO $ noWorkToDo doWork notifyErr err e = do logError $ "withWorkItems error: " <> tshow e - atomically $ writeTBQueue (subQ c) ("", "", AEvt SAEConn $ ERR $ err $ show e) + liftIO $ notifyEvent c ("", "", AEvt SAEConn $ ERR $ err $ show e) noWorkToDo :: TMVar () -> IO () noWorkToDo = void . atomically . tryTakeTMVar @@ -2304,9 +2344,9 @@ hasWorkToDo' :: TMVar () -> STM () hasWorkToDo' = void . (`tryPutTMVar` ()) {-# INLINE hasWorkToDo' #-} -endAgentOperation :: AgentClient -> AgentOperation -> STM () +endAgentOperation :: AgentClient -> AgentOperation -> STM Bool endAgentOperation c op = endOperation c op $ case op of - AONtfNetwork -> pure () + AONtfNetwork -> pure False AORcvNetwork -> suspendOperation c AOMsgDelivery $ suspendSendingAndDatabase c @@ -2318,36 +2358,37 @@ endAgentOperation c op = endOperation c op $ case op of AODatabase -> notifySuspended c -suspendSendingAndDatabase :: AgentClient -> STM () +suspendSendingAndDatabase :: AgentClient -> STM Bool suspendSendingAndDatabase c = suspendOperation c AOSndNetwork $ suspendOperation c AODatabase $ notifySuspended c -suspendOperation :: AgentClient -> AgentOperation -> STM () -> STM () +suspendOperation :: AgentClient -> AgentOperation -> STM Bool -> STM Bool suspendOperation c op endedAction = do n <- stateTVar (agentOpSel op c) $ \s -> (opsInProgress s, s {opSuspended = True}) - -- unsafeIOToSTM $ putStrLn $ "suspendOperation_ " <> show op <> " " <> show n - when (n == 0) $ whenSuspending c endedAction + if n == 0 then whenSuspendingB c endedAction else pure False -notifySuspended :: AgentClient -> STM () +notifySuspended :: AgentClient -> STM Bool notifySuspended c = do - -- unsafeIOToSTM $ putStrLn "notifySuspended" - writeTBQueue (subQ c) ("", "", AEvt SAENone SUSPENDED) writeTVar (agentState c) ASSuspended + pure True -endOperation :: AgentClient -> AgentOperation -> STM () -> STM () +endOperation :: AgentClient -> AgentOperation -> STM Bool -> STM Bool endOperation c op endedAction = do (suspended, n) <- stateTVar (agentOpSel op c) $ \s -> let n = max 0 (opsInProgress s - 1) in ((opSuspended s, n), s {opsInProgress = n}) - -- unsafeIOToSTM $ putStrLn $ "endOperation: " <> show op <> " " <> show suspended <> " " <> show n - when (suspended && n == 0) $ whenSuspending c endedAction + if suspended && n == 0 then whenSuspendingB c endedAction else pure False whenSuspending :: AgentClient -> STM () -> STM () whenSuspending c = whenM ((== ASSuspending) <$> readTVar (agentState c)) {-# INLINE whenSuspending #-} +whenSuspendingB :: AgentClient -> STM Bool -> STM Bool +whenSuspendingB c action = + ifM ((== ASSuspending) <$> readTVar (agentState c)) action (pure False) + beginAgentOperation :: AgentClient -> AgentOperation -> STM () beginAgentOperation c op = do let opVar = agentOpSel op c @@ -2361,7 +2402,9 @@ agentOperationBracket :: MonadUnliftIO m => AgentClient -> AgentOperation -> (Ag agentOperationBracket c op check action = E.bracket (liftIO (check c) >> atomically (beginAgentOperation c op)) - (\_ -> atomically $ endAgentOperation c op) + (\_ -> do + suspended <- atomically $ endAgentOperation c op + when suspended $ liftIO $ notifyEvent c ("", "", AEvt SAENone SUSPENDED)) (const action) waitUntilForeground :: AgentClient -> IO () @@ -2834,9 +2877,9 @@ data ClientInfo deriving (Show) getAgentQueuesInfo :: AgentClient -> IO AgentQueuesInfo -getAgentQueuesInfo AgentClient {subQ, smpClients} = do +getAgentQueuesInfo AgentClient {smpClients} = do let msgQInfo = TBQueueInfo {qLength = 0, qFull = False} - subQInfo <- atomically $ getTBQueueInfo subQ + subQInfo = TBQueueInfo {qLength = 0, qFull = False} smpClientsMap <- readTVarIO smpClients let smpClientsMap' = M.mapKeys (decodeLatin1 . strEncode) smpClientsMap smpClientsQueues <- mapM getClientQueuesInfo smpClientsMap' diff --git a/src/Simplex/Messaging/Agent/NtfSubSupervisor.hs b/src/Simplex/Messaging/Agent/NtfSubSupervisor.hs index 06c9b4ca4..b66285acd 100644 --- a/src/Simplex/Messaging/Agent/NtfSubSupervisor.hs +++ b/src/Simplex/Messaging/Agent/NtfSubSupervisor.hs @@ -502,9 +502,9 @@ workerInternalError c connId internalErrStr = do -- TODO change error notifyInternalError :: MonadIO m => AgentClient -> ConnId -> String -> m () -notifyInternalError AgentClient {subQ} connId internalErrStr = do +notifyInternalError c connId internalErrStr = do logError $ T.pack internalErrStr - liftIO $ nonBlockingWriteTBQueue subQ ("", connId, AEvt SAEConn $ ERR $ INTERNAL internalErrStr) + liftIO $ notifyEvent c ("", connId, AEvt SAEConn $ ERR $ INTERNAL internalErrStr) notifyInternalError' :: MonadIO m => AgentClient -> String -> m () notifyInternalError' c = notifyInternalError c "" diff --git a/tests/AgentTests/FunctionalAPITests.hs b/tests/AgentTests/FunctionalAPITests.hs index fba0eac4a..87824d6f0 100644 --- a/tests/AgentTests/FunctionalAPITests.hs +++ b/tests/AgentTests/FunctionalAPITests.hs @@ -19,7 +19,8 @@ {-# OPTIONS_GHC -Wno-orphans #-} module AgentTests.FunctionalAPITests - ( functionalAPITests, + ( AgentClient (..), + functionalAPITests, testServerMatrix2, withAgentClientsCfg2, withAgentClientsCfgServers2, @@ -52,6 +53,11 @@ module AgentTests.FunctionalAPITests pattern Msg', pattern SENT, agentCfgVPrevPQ, + allowConnection, + ackMessage, + subscribeConnection, + deleteConnection, + disposeAgentClient, ) where @@ -82,10 +88,11 @@ import Data.Word (Word16) import GHC.Stack (withFrozenCallStack) import SMPAgentClient import SMPClient -import Simplex.Messaging.Agent hiding (acceptContact, createConnection, deleteConnection, deleteConnections, getConnShortLink, joinConnection, sendMessage, setConnShortLink, subscribeConnection, suspendConnection) +import Simplex.Messaging.Agent hiding (AgentClient, abortConnectionSwitch, acceptContact, ackMessage, ackMessageAsync, allowConnection, allowConnectionAsync, changeConnectionUser, createConnection, createConnectionAsync, createUser, deleteConnection, deleteConnectionAsync, deleteConnections, deleteConnectionsAsync, deleteUser, disposeAgentClient, foregroundAgent, getConnShortLink, getConnShortLinkAsync, getConnectionMessages, getConnectionRatchetAdHash, getConnectionServers, joinConnection, joinConnectionAsync, prepareConnectionLink, prepareConnectionToAccept, rejectContact, resubscribeConnections, sendMessage, sendMessagesB, setConnShortLink, setConnShortLinkAsync, setNetworkConfig, setUserNetworkInfo, subscribeAllConnections, subscribeClientServices, subscribeConnection, subscribeConnections, suspendAgent, suspendConnection, switchConnectionAsync, synchronizeRatchet, testProtocolServer) import qualified Simplex.Messaging.Agent as A -import Simplex.Messaging.Agent.Client (ProtocolTestFailure (..), ProtocolTestStep (..), ServerQueueInfo (..), UserNetworkInfo (..), UserNetworkType (..), waitForUserNetwork) -import Simplex.Messaging.Agent.Env.SQLite (AgentConfig (..), Env (..), InitialAgentServers (..), createAgentStore) +import Simplex.Messaging.Agent.Client (ProtocolTestFailure (..), ProtocolTestStep (..), ServerQueueInfo (..), UserNetworkInfo (..), UserNetworkType (..)) +import qualified Simplex.Messaging.Agent.Client as AC +import Simplex.Messaging.Agent.Env.SQLite (AgentConfig (..), Env (..), InitialAgentServers (..), ServerCfg (..), createAgentStore) import Simplex.Messaging.Agent.Protocol hiding (CON, CONF, INFO, REQ, SENT) import qualified Simplex.Messaging.Agent.Protocol as A import Simplex.Messaging.Agent.Store (Connection' (..), SomeConn' (..), StoredRcvQueue (..)) @@ -94,14 +101,14 @@ import Simplex.Messaging.Agent.Store.Common (DBStore (..), withTransaction) import Simplex.Messaging.Agent.Store.Interface import qualified Simplex.Messaging.Agent.Store.DB as DB import Simplex.Messaging.Agent.Store.Shared (MigrationConfig (..), MigrationConfirmation (..), MigrationError (..)) -import Simplex.Messaging.Client (pattern NRMInteractive, NetworkConfig (..), ProtocolClientConfig (..), TransportSessionMode (..), defaultClientConfig) +import Simplex.Messaging.Client (pattern NRMInteractive, NetworkConfig (..), NetworkRequestMode, ProtocolClientConfig (..), TransportSessionMode (..), defaultClientConfig) import qualified Simplex.Messaging.Crypto as C import Simplex.Messaging.Crypto.Ratchet (InitialKeys (..), PQEncryption (..), PQSupport (..), pattern IKPQOff, pattern IKPQOn, pattern PQEncOff, pattern PQEncOn, pattern PQSupportOff, pattern PQSupportOn) import qualified Simplex.Messaging.Crypto.Ratchet as CR import Simplex.Messaging.Encoding import Simplex.Messaging.Encoding.String import Simplex.Messaging.Notifications.Transport (NTFVersion, pattern VersionNTF) -import Simplex.Messaging.Protocol (BasicAuth, ErrorType (..), MsgBody, NetworkError (..), ProtocolServer (..), SubscriptionMode (..), initialSMPClientVersion, srvHostnamesSMPClientVersion, supportedSMPClientVRange) +import Simplex.Messaging.Protocol (BasicAuth, ErrorType (..), MsgBody, NetworkError (..), ProtocolServer (..), ProtocolType (..), SubscriptionMode (..), initialSMPClientVersion, srvHostnamesSMPClientVersion, supportedSMPClientVRange) import qualified Simplex.Messaging.Protocol as SMP import Simplex.Messaging.Protocol.Types import Simplex.Messaging.Server.Env.STM (AStoreType (..), ServerConfig (..), ServerStoreCfg (..), StorePaths (..)) @@ -138,6 +145,11 @@ import Simplex.Messaging.Server.QueueStore.Postgres.Migrations import Simplex.Messaging.Server.QueueStore.Types (QueueStoreClass (..)) #endif +data AgentClient = AgentClient + { client :: A.AgentClient, + subQ :: TBQueue ATransmission + } + type AEntityTransmission e = (ACorrId, ConnId, AEvent e) -- deriving instance Eq (ValidFileDescription p) @@ -183,8 +195,8 @@ pGet :: forall m. MonadIO m => AgentClient -> m ATransmission pGet c = pGet' c True pGet' :: forall m. MonadIO m => AgentClient -> Bool -> m ATransmission -pGet' c skipWarn = do - t@(_, _, AEvt _ cmd) <- atomically (readTBQueue $ subQ c) +pGet' c@AgentClient {subQ} skipWarn = do + t@(_, _, AEvt _ cmd) <- atomically (readTBQueue subQ) case cmd of CONNECT {} -> pGet c DISCONNECT {} -> pGet c @@ -284,41 +296,143 @@ inAnyOrder g rs = withFrozenCallStack $ do createConnection :: ConnectionModeI c => AgentClient -> UserId -> Bool -> SConnectionMode c -> Maybe CRClientData -> SubscriptionMode -> AE (ConnId, ConnectionRequestUri c) createConnection c userId enableNtfs cMode clientData subMode = do - (connId, CCLink cReq _) <- A.createConnection c NRMInteractive userId enableNtfs True cMode Nothing clientData IKPQOn subMode + (connId, CCLink cReq _) <- A.createConnection (client c) NRMInteractive userId enableNtfs True cMode Nothing clientData IKPQOn subMode pure (connId, cReq) joinConnection :: AgentClient -> UserId -> Bool -> ConnectionRequestUri c -> ConnInfo -> SubscriptionMode -> AE (ConnId, SndQueueSecured) joinConnection c userId enableNtfs cReq connInfo subMode = do - connId <- A.prepareConnectionToJoin c userId enableNtfs cReq PQSupportOn - sndSecure <- A.joinConnection c NRMInteractive userId connId enableNtfs cReq connInfo PQSupportOn subMode + connId <- A.prepareConnectionToJoin (client c) userId enableNtfs cReq PQSupportOn + sndSecure <- A.joinConnection (client c) NRMInteractive userId connId enableNtfs cReq connInfo PQSupportOn subMode pure (connId, sndSecure) acceptContact :: AgentClient -> UserId -> ConnId -> Bool -> ConfirmationId -> ConnInfo -> PQSupport -> SubscriptionMode -> AE SndQueueSecured -acceptContact c = A.acceptContact c NRMInteractive +acceptContact c = A.acceptContact (client c) NRMInteractive subscribeConnection :: AgentClient -> ConnId -> AE () -subscribeConnection c = void . A.subscribeConnection c +subscribeConnection c = void . A.subscribeConnection (client c) sendMessage :: AgentClient -> ConnId -> SMP.MsgFlags -> MsgBody -> AE AgentMsgId sendMessage c connId msgFlags msgBody = do - (msgId, pqEnc) <- A.sendMessage c connId PQEncOn msgFlags msgBody + (msgId, pqEnc) <- A.sendMessage (client c) connId PQEncOn msgFlags msgBody liftIO $ pqEnc `shouldBe` PQEncOn pure msgId deleteConnection :: AgentClient -> ConnId -> AE () -deleteConnection c = A.deleteConnection c NRMInteractive +deleteConnection c = A.deleteConnection (client c) NRMInteractive deleteConnections :: AgentClient -> [ConnId] -> AE (M.Map ConnId (Either AgentErrorType ())) -deleteConnections c = A.deleteConnections c NRMInteractive +deleteConnections c = A.deleteConnections (client c) NRMInteractive getConnShortLink :: AgentClient -> UserId -> ConnShortLink c -> AE (FixedLinkData c, ConnLinkData c) -getConnShortLink c = A.getConnShortLink c NRMInteractive +getConnShortLink c = A.getConnShortLink (client c) NRMInteractive setConnShortLink :: AgentClient -> ConnId -> SConnectionMode c -> UserConnLinkData c -> Maybe CRClientData -> AE (ConnShortLink c) -setConnShortLink c = A.setConnShortLink c NRMInteractive +setConnShortLink c = A.setConnShortLink (client c) NRMInteractive suspendConnection :: AgentClient -> ConnId -> AE () -suspendConnection c = A.suspendConnection c NRMInteractive +suspendConnection c = A.suspendConnection (client c) NRMInteractive + +allowConnection :: AgentClient -> ConnId -> ConfirmationId -> ConnInfo -> AE () +allowConnection c = A.allowConnection (client c) + +ackMessage :: AgentClient -> ConnId -> AgentMsgId -> Maybe MsgReceiptInfo -> AE () +ackMessage c = A.ackMessage (client c) + +ackMessageAsync :: AgentClient -> ACorrId -> ConnId -> AgentMsgId -> Maybe MsgReceiptInfo -> AE () +ackMessageAsync c = A.ackMessageAsync (client c) + +disposeAgentClient :: AgentClient -> IO () +disposeAgentClient = A.disposeAgentClient . client + +subscribeConnections :: AgentClient -> [ConnId] -> AE (M.Map ConnId (Either AgentErrorType ())) +subscribeConnections c = A.subscribeConnections (client c) + +switchConnectionAsync :: AgentClient -> ACorrId -> ConnId -> AE ConnectionStats +switchConnectionAsync c = A.switchConnectionAsync (client c) + +foregroundAgent :: AgentClient -> IO () +foregroundAgent = A.foregroundAgent . client + +suspendAgent :: AgentClient -> Int -> IO () +suspendAgent c = A.suspendAgent (client c) + +subscribeAllConnections :: AgentClient -> Bool -> Maybe UserId -> AE () +subscribeAllConnections c = A.subscribeAllConnections (client c) + +subscribeClientServices :: AgentClient -> UserId -> AE (M.Map SMPServer (Either AgentErrorType SMP.ServiceSubResult)) +subscribeClientServices c = A.subscribeClientServices (client c) + +deleteConnectionAsync :: AgentClient -> Bool -> ConnId -> AE () +deleteConnectionAsync c = A.deleteConnectionAsync (client c) + +deleteConnectionsAsync :: AgentClient -> Bool -> [ConnId] -> AE () +deleteConnectionsAsync c = A.deleteConnectionsAsync (client c) + +resubscribeConnections :: AgentClient -> [ConnId] -> AE (M.Map ConnId (Either AgentErrorType ())) +resubscribeConnections c = A.resubscribeConnections (client c) + +createUser :: AgentClient -> Bool -> NonEmpty (ServerCfg 'PSMP) -> NonEmpty (ServerCfg 'PXFTP) -> AE UserId +createUser c = A.createUser (client c) + +deleteUser :: AgentClient -> UserId -> Bool -> AE () +deleteUser c = A.deleteUser (client c) + +changeConnectionUser :: AgentClient -> UserId -> ConnId -> UserId -> AE () +changeConnectionUser c = A.changeConnectionUser (client c) + +rejectContact :: AgentClient -> ConfirmationId -> AE () +rejectContact c = A.rejectContact (client c) + +setConnShortLinkAsync :: AgentClient -> ACorrId -> ConnId -> UserConnLinkData 'CMContact -> Maybe CRClientData -> AE () +setConnShortLinkAsync c = A.setConnShortLinkAsync (client c) + +getConnShortLinkAsync :: AgentClient -> UserId -> ACorrId -> Maybe ConnId -> ConnShortLink 'CMContact -> AE ConnId +getConnShortLinkAsync c = A.getConnShortLinkAsync (client c) + +abortConnectionSwitch :: AgentClient -> ConnId -> AE ConnectionStats +abortConnectionSwitch c = A.abortConnectionSwitch (client c) + +synchronizeRatchet :: AgentClient -> ConnId -> PQSupport -> Bool -> AE ConnectionStats +synchronizeRatchet c = A.synchronizeRatchet (client c) + +setNetworkConfig :: AgentClient -> NetworkConfig -> AE () +setNetworkConfig c = A.setNetworkConfig (client c) + +setUserNetworkInfo :: AgentClient -> UserNetworkInfo -> IO () +setUserNetworkInfo c = A.setUserNetworkInfo (client c) + +getConnectionServers :: AgentClient -> ConnId -> AE ConnectionStats +getConnectionServers c = A.getConnectionServers (client c) + +prepareConnectionToAccept :: AgentClient -> UserId -> Bool -> ConfirmationId -> PQSupport -> AE ConnId +prepareConnectionToAccept c = A.prepareConnectionToAccept (client c) + +allowConnectionAsync :: AgentClient -> ACorrId -> ConnId -> ConfirmationId -> ConnInfo -> AE () +allowConnectionAsync c = A.allowConnectionAsync (client c) + +joinConnectionAsync :: AgentClient -> UserId -> ACorrId -> Maybe ConnId -> Bool -> ConnectionRequestUri c -> ConnInfo -> PQSupport -> SubscriptionMode -> AE ConnId +joinConnectionAsync c = A.joinConnectionAsync (client c) + +sendMessagesB :: AgentClient -> [Either AgentErrorType MsgReq] -> AE [Either AgentErrorType (AgentMsgId, PQEncryption)] +sendMessagesB c = A.sendMessagesB (client c) + +createConnectionAsync :: ConnectionModeI c => AgentClient -> UserId -> ACorrId -> Bool -> SConnectionMode c -> CR.InitialKeys -> SubscriptionMode -> AE ConnId +createConnectionAsync c = A.createConnectionAsync (client c) + +testProtocolServer :: SMP.ProtocolTypeI p => AgentClient -> NetworkRequestMode -> UserId -> SMP.ProtoServerWithAuth p -> IO (Maybe ProtocolTestFailure) +testProtocolServer c = A.testProtocolServer (client c) + +getConnectionRatchetAdHash :: AgentClient -> ConnId -> AE ByteString +getConnectionRatchetAdHash c = A.getConnectionRatchetAdHash (client c) + +getConnectionMessages :: AgentClient -> NonEmpty ConnMsgReq -> IO (NonEmpty (Either AgentErrorType (Maybe SMP.SMPMsgMeta))) +getConnectionMessages c = A.getConnectionMessages (client c) + +prepareConnectionLink :: AgentClient -> UserId -> C.KeyPairEd25519 -> ByteString -> Bool -> Maybe CRClientData -> AE (CreatedConnLink 'CMContact, PreparedLinkParams) +prepareConnectionLink c = A.prepareConnectionLink (client c) + +waitForUserNetwork :: AgentClient -> IO () +waitForUserNetwork = AC.waitForUserNetwork . client functionalAPITests :: (ASrvTransport, AStoreType) -> Spec functionalAPITests ps = do @@ -723,9 +837,9 @@ runAgentClientTest pqSupport sqSecured viaProxy alice bob baseId = runAgentClientTestPQ :: HasCallStack => SndQueueSecured -> Bool -> (AgentClient, InitialKeys) -> (AgentClient, PQSupport) -> AgentMsgId -> IO () runAgentClientTestPQ sqSecured viaProxy (alice, aPQ) (bob, bPQ) baseId = runRight_ $ do - (bobId, CCLink qInfo Nothing) <- A.createConnection alice NRMInteractive 1 True True SCMInvitation Nothing Nothing aPQ SMSubscribe - aliceId <- A.prepareConnectionToJoin bob 1 True qInfo bPQ - sqSecured' <- A.joinConnection bob NRMInteractive 1 aliceId True qInfo "bob's connInfo" bPQ SMSubscribe + (bobId, CCLink qInfo Nothing) <- A.createConnection (client alice) NRMInteractive 1 True True SCMInvitation Nothing Nothing aPQ SMSubscribe + aliceId <- A.prepareConnectionToJoin (client bob) 1 True qInfo bPQ + sqSecured' <- A.joinConnection (client bob) NRMInteractive 1 aliceId True qInfo "bob's connInfo" bPQ SMSubscribe liftIO $ sqSecured' `shouldBe` sqSecured ("", _, A.CONF confId pqSup' _ "bob's connInfo") <- get alice liftIO $ pqSup' `shouldBe` CR.connPQEncryption aPQ @@ -736,24 +850,24 @@ runAgentClientTestPQ sqSecured viaProxy (alice, aPQ) (bob, bPQ) baseId = get bob ##> ("", aliceId, A.CON pqEnc) -- message IDs 1 to 3 (or 1 to 4 in v1) get assigned to control messages, so first MSG is assigned ID 4 let proxySrv = if viaProxy then Just testSMPServer else Nothing - 1 <- msgId <$> A.sendMessage alice bobId pqEnc SMP.noMsgFlags "hello" + 1 <- msgId <$> A.sendMessage (client alice) bobId pqEnc SMP.noMsgFlags "hello" get alice ##> ("", bobId, A.SENT (baseId + 1) proxySrv) - 2 <- msgId <$> A.sendMessage alice bobId pqEnc SMP.noMsgFlags "how are you?" + 2 <- msgId <$> A.sendMessage (client alice) bobId pqEnc SMP.noMsgFlags "how are you?" get alice ##> ("", bobId, A.SENT (baseId + 2) proxySrv) get bob =##> \case ("", c, Msg' _ pq "hello") -> c == aliceId && pq == pqEnc; _ -> False ackMessage bob aliceId (baseId + 1) Nothing get bob =##> \case ("", c, Msg' _ pq "how are you?") -> c == aliceId && pq == pqEnc; _ -> False ackMessage bob aliceId (baseId + 2) Nothing - 3 <- msgId <$> A.sendMessage bob aliceId pqEnc SMP.noMsgFlags "hello too" + 3 <- msgId <$> A.sendMessage (client bob) aliceId pqEnc SMP.noMsgFlags "hello too" get bob ##> ("", aliceId, A.SENT (baseId + 3) proxySrv) - 4 <- msgId <$> A.sendMessage bob aliceId pqEnc SMP.noMsgFlags "message 1" + 4 <- msgId <$> A.sendMessage (client bob) aliceId pqEnc SMP.noMsgFlags "message 1" get bob ##> ("", aliceId, A.SENT (baseId + 4) proxySrv) get alice =##> \case ("", c, Msg' _ pq "hello too") -> c == bobId && pq == pqEnc; _ -> False ackMessage alice bobId (baseId + 3) Nothing get alice =##> \case ("", c, Msg' _ pq "message 1") -> c == bobId && pq == pqEnc; _ -> False ackMessage alice bobId (baseId + 4) Nothing suspendConnection alice bobId - 5 <- msgId <$> A.sendMessage bob aliceId pqEnc SMP.noMsgFlags "message 2" + 5 <- msgId <$> A.sendMessage (client bob) aliceId pqEnc SMP.noMsgFlags "message 2" get bob =##> \case ("", cId, MERR mId (SMP _ AUTH)) -> cId == aliceId && mId == (baseId + 5); _ -> False deleteConnection alice bobId liftIO $ noMessages alice "nothing else should be delivered to alice" @@ -771,7 +885,7 @@ runAgentClientStressTestOneWay n pqSupport sqSecured viaProxy alice bob baseId = message i = "message " <> bshow i concurrently_ ( forM_ ([1 .. n] :: [Int64]) $ \i -> do - mId <- msgId <$> A.sendMessage alice bobId pqEnc SMP.noMsgFlags (message i) + mId <- msgId <$> A.sendMessage (client alice) bobId pqEnc SMP.noMsgFlags (message i) liftIO $ do mId >= i `shouldBe` True let getEvent = @@ -817,7 +931,7 @@ runAgentClientStressTestConc n pqSupport sqSecured viaProxy alice bob _baseId = proxySrv = if viaProxy then Just testSMPServer else Nothing message i = "message " <> bshow i send :: AgentClient -> ConnId -> [Int64] -> ExceptT AgentErrorType IO () - send a bId = mapM_ $ \i -> void $ A.sendMessage a bId pqEnc SMP.noMsgFlags (message i) + send a bId = mapM_ $ \i -> void $ A.sendMessage (client a) bId pqEnc SMP.noMsgFlags (message i) receive :: AgentClient -> ConnId -> TVar AgentMsgId -> (Int64, Int64, Int64, Int64) -> ExceptT AgentErrorType IO () receive a bId mIdVar acc' = loop acc' >> liftIO drain where @@ -872,14 +986,14 @@ testEnablePQEncryption = -- switched to smaller envelopes (before reporting PQ encryption enabled) sml <- largeMsg g PQSupportOn -- fail because of message size - Left (A.CMD LARGE _) <- tryError $ A.sendMessage ca bId PQEncOn SMP.noMsgFlags lrg - (7, PQEncOff) <- A.sendMessage ca bId PQEncOn SMP.noMsgFlags sml + Left (A.CMD LARGE _) <- tryError $ A.sendMessage (client ca) bId PQEncOn SMP.noMsgFlags lrg + (7, PQEncOff) <- A.sendMessage (client ca) bId PQEncOn SMP.noMsgFlags sml get ca =##> \case ("", connId, SENT 7) -> connId == bId; _ -> False get cb =##> \case ("", connId, MsgErr' 6 MsgSkipped {} PQEncOff msg') -> connId == aId && msg' == sml; _ -> False ackMessage cb aId 6 Nothing -- -- fail in reply to sync IDss - Left (A.CMD LARGE _) <- tryError $ A.sendMessage cb aId PQEncOn SMP.noMsgFlags lrg - (8, PQEncOff) <- A.sendMessage cb aId PQEncOn SMP.noMsgFlags sml + Left (A.CMD LARGE _) <- tryError $ A.sendMessage (client cb) aId PQEncOn SMP.noMsgFlags lrg + (8, PQEncOff) <- A.sendMessage (client cb) aId PQEncOn SMP.noMsgFlags sml get cb =##> \case ("", connId, SENT 8) -> connId == aId; _ -> False get ca =##> \case ("", connId, MsgErr' 8 MsgSkipped {} PQEncOff msg') -> connId == bId && msg' == sml; _ -> False ackMessage ca bId 8 Nothing @@ -905,8 +1019,8 @@ testEnablePQEncryption = (b, 24, sml) \#>\ a (a, 25, sml) \#>\ b -- PQ encryption is now disabled, but support remained enabled, so we still cannot send larger messages - Left (A.CMD LARGE _) <- tryError $ A.sendMessage ca bId PQEncOff SMP.noMsgFlags (sml <> "123456") - Left (A.CMD LARGE _) <- tryError $ A.sendMessage cb aId PQEncOff SMP.noMsgFlags (sml <> "123456") + Left (A.CMD LARGE _) <- tryError $ A.sendMessage (client ca) bId PQEncOff SMP.noMsgFlags (sml <> "123456") + Left (A.CMD LARGE _) <- tryError $ A.sendMessage (client cb) aId PQEncOff SMP.noMsgFlags (sml <> "123456") pure () where (\#>\) = PQEncOff `sndRcv` PQEncOff @@ -916,7 +1030,7 @@ testEnablePQEncryption = sndRcv :: PQEncryption -> PQEncryption -> ((AgentClient, ConnId), AgentMsgId, MsgBody) -> (AgentClient, ConnId) -> ExceptT AgentErrorType IO () sndRcv pqEnc pqEnc' ((c1, id1), mId, msg) (c2, id2) = do - r <- A.sendMessage c1 id2 pqEnc' SMP.noMsgFlags msg + r <- A.sendMessage (client c1) id2 pqEnc' SMP.noMsgFlags msg liftIO $ r `shouldBe` (mId, pqEnc) get c1 =##> \case ("", connId, SENT mId') -> connId == id2 && mId' == mId; _ -> False get c2 =##> \case ("", connId, Msg' mId' pq msg') -> connId == id1 && mId' == mId && msg' == msg && pq == pqEnc; _ -> False @@ -952,13 +1066,13 @@ runAgentClientContactTest pqSupport sqSecured viaProxy alice bob baseId = runAgentClientContactTestPQ :: HasCallStack => SndQueueSecured -> Bool -> PQSupport -> (AgentClient, InitialKeys) -> (AgentClient, PQSupport) -> AgentMsgId -> IO () runAgentClientContactTestPQ sqSecured viaProxy reqPQSupport (alice, aPQ) (bob, bPQ) baseId = runRight_ $ do - (_, CCLink qInfo Nothing) <- A.createConnection alice NRMInteractive 1 True True SCMContact Nothing Nothing aPQ SMSubscribe - aliceId <- A.prepareConnectionToJoin bob 1 True qInfo bPQ - sqSecuredJoin <- A.joinConnection bob NRMInteractive 1 aliceId True qInfo "bob's connInfo" bPQ SMSubscribe + (_, CCLink qInfo Nothing) <- A.createConnection (client alice) NRMInteractive 1 True True SCMContact Nothing Nothing aPQ SMSubscribe + aliceId <- A.prepareConnectionToJoin (client bob) 1 True qInfo bPQ + sqSecuredJoin <- A.joinConnection (client bob) NRMInteractive 1 aliceId True qInfo "bob's connInfo" bPQ SMSubscribe liftIO $ sqSecuredJoin `shouldBe` False -- joining via contact address connection ("", _, A.REQ invId pqSup' _ "bob's connInfo") <- get alice liftIO $ pqSup' `shouldBe` reqPQSupport - bobId <- A.prepareConnectionToAccept alice 1 True invId (CR.connPQEncryption aPQ) + bobId <- prepareConnectionToAccept alice 1 True invId (CR.connPQEncryption aPQ) sqSecured' <- acceptContact alice 1 bobId True invId "alice's connInfo" (CR.connPQEncryption aPQ) SMSubscribe liftIO $ sqSecured' `shouldBe` sqSecured ("", _, A.CONF confId pqSup'' _ "alice's connInfo") <- get bob @@ -970,24 +1084,24 @@ runAgentClientContactTestPQ sqSecured viaProxy reqPQSupport (alice, aPQ) (bob, b get bob ##> ("", aliceId, A.CON pqEnc) -- message IDs 1 to 3 (or 1 to 4 in v1) get assigned to control messages, so first MSG is assigned ID 4 let proxySrv = if viaProxy then Just testSMPServer else Nothing - 1 <- msgId <$> A.sendMessage alice bobId pqEnc SMP.noMsgFlags "hello" + 1 <- msgId <$> A.sendMessage (client alice) bobId pqEnc SMP.noMsgFlags "hello" get alice ##> ("", bobId, A.SENT (baseId + 1) proxySrv) - 2 <- msgId <$> A.sendMessage alice bobId pqEnc SMP.noMsgFlags "how are you?" + 2 <- msgId <$> A.sendMessage (client alice) bobId pqEnc SMP.noMsgFlags "how are you?" get alice ##> ("", bobId, A.SENT (baseId + 2) proxySrv) get bob =##> \case ("", c, Msg' _ pq "hello") -> c == aliceId && pq == pqEnc; _ -> False ackMessage bob aliceId (baseId + 1) Nothing get bob =##> \case ("", c, Msg' _ pq "how are you?") -> c == aliceId && pq == pqEnc; _ -> False ackMessage bob aliceId (baseId + 2) Nothing - 3 <- msgId <$> A.sendMessage bob aliceId pqEnc SMP.noMsgFlags "hello too" + 3 <- msgId <$> A.sendMessage (client bob) aliceId pqEnc SMP.noMsgFlags "hello too" get bob ##> ("", aliceId, A.SENT (baseId + 3) proxySrv) - 4 <- msgId <$> A.sendMessage bob aliceId pqEnc SMP.noMsgFlags "message 1" + 4 <- msgId <$> A.sendMessage (client bob) aliceId pqEnc SMP.noMsgFlags "message 1" get bob ##> ("", aliceId, A.SENT (baseId + 4) proxySrv) get alice =##> \case ("", c, Msg' _ pq "hello too") -> c == bobId && pq == pqEnc; _ -> False ackMessage alice bobId (baseId + 3) Nothing get alice =##> \case ("", c, Msg' _ pq "message 1") -> c == bobId && pq == pqEnc; _ -> False ackMessage alice bobId (baseId + 4) Nothing suspendConnection alice bobId - 5 <- msgId <$> A.sendMessage bob aliceId pqEnc SMP.noMsgFlags "message 2" + 5 <- msgId <$> A.sendMessage (client bob) aliceId pqEnc SMP.noMsgFlags "message 2" get bob =##> \case ("", cId, MERR mId (SMP _ AUTH)) -> cId == aliceId && mId == (baseId + 5); _ -> False deleteConnection alice bobId liftIO $ noMessages alice "nothing else should be delivered to alice" @@ -996,7 +1110,7 @@ runAgentClientContactTestPQ sqSecured viaProxy reqPQSupport (alice, aPQ) (bob, b runAgentClientContactTestPQ3 :: HasCallStack => Bool -> (AgentClient, InitialKeys) -> (AgentClient, PQSupport) -> (AgentClient, PQSupport) -> AgentMsgId -> IO () runAgentClientContactTestPQ3 viaProxy (alice, aPQ) (bob, bPQ) (tom, tPQ) baseId = runRight_ $ do - (_, CCLink qInfo Nothing) <- A.createConnection alice NRMInteractive 1 True True SCMContact Nothing Nothing aPQ SMSubscribe + (_, CCLink qInfo Nothing) <- A.createConnection (client alice) NRMInteractive 1 True True SCMContact Nothing Nothing aPQ SMSubscribe (bAliceId, bobId, abPQEnc) <- connectViaContact bob bPQ qInfo sentMessages abPQEnc alice bobId bob bAliceId (tAliceId, tomId, atPQEnc) <- connectViaContact tom tPQ qInfo @@ -1004,12 +1118,12 @@ runAgentClientContactTestPQ3 viaProxy (alice, aPQ) (bob, bPQ) (tom, tPQ) baseId where msgId = subtract baseId . fst connectViaContact b pq qInfo = do - aId <- A.prepareConnectionToJoin b 1 True qInfo pq - sqSecuredJoin <- A.joinConnection b NRMInteractive 1 aId True qInfo "bob's connInfo" pq SMSubscribe + aId <- A.prepareConnectionToJoin (client b) 1 True qInfo pq + sqSecuredJoin <- A.joinConnection (client b) NRMInteractive 1 aId True qInfo "bob's connInfo" pq SMSubscribe liftIO $ sqSecuredJoin `shouldBe` False -- joining via contact address connection ("", _, A.REQ invId pqSup' _ "bob's connInfo") <- get alice liftIO $ pqSup' `shouldBe` PQSupportOn - bId <- A.prepareConnectionToAccept alice 1 True invId (CR.connPQEncryption aPQ) + bId <- prepareConnectionToAccept alice 1 True invId (CR.connPQEncryption aPQ) sqSecuredAccept <- acceptContact alice 1 bId True invId "alice's connInfo" (CR.connPQEncryption aPQ) SMSubscribe liftIO $ sqSecuredAccept `shouldBe` False -- agent cfg is v8 ("", _, A.CONF confId pqSup'' _ "alice's connInfo") <- get b @@ -1022,11 +1136,11 @@ runAgentClientContactTestPQ3 viaProxy (alice, aPQ) (bob, bPQ) (tom, tPQ) baseId pure (aId, bId, pqEnc) sentMessages pqEnc a bId b aId = do let proxySrv = if viaProxy then Just testSMPServer else Nothing - 1 <- msgId <$> A.sendMessage a bId pqEnc SMP.noMsgFlags "hello" + 1 <- msgId <$> A.sendMessage (client a) bId pqEnc SMP.noMsgFlags "hello" get a ##> ("", bId, A.SENT (baseId + 1) proxySrv) get b =##> \case ("", c, Msg' _ pq "hello") -> c == aId && pq == pqEnc; _ -> False ackMessage b aId (baseId + 1) Nothing - 2 <- msgId <$> A.sendMessage b aId pqEnc SMP.noMsgFlags "hello too" + 2 <- msgId <$> A.sendMessage (client b) aId pqEnc SMP.noMsgFlags "hello too" get b ##> ("", aId, A.SENT (baseId + 2) proxySrv) get a =##> \case ("", c, Msg' _ pq "hello too") -> c == bId && pq == pqEnc; _ -> False ackMessage a bId (baseId + 2) Nothing @@ -1049,9 +1163,9 @@ noMessages_ ingoreQCONT c err = tryGet `shouldReturn` () testRejectContactRequest :: HasCallStack => IO () testRejectContactRequest = withAgentClients2 $ \alice bob -> runRight_ $ do - (_addrConnId, CCLink qInfo Nothing) <- A.createConnection alice NRMInteractive 1 True True SCMContact Nothing Nothing IKPQOn SMSubscribe - aliceId <- A.prepareConnectionToJoin bob 1 True qInfo PQSupportOn - sqSecured <- A.joinConnection bob NRMInteractive 1 aliceId True qInfo "bob's connInfo" PQSupportOn SMSubscribe + (_addrConnId, CCLink qInfo Nothing) <- A.createConnection (client alice) NRMInteractive 1 True True SCMContact Nothing Nothing IKPQOn SMSubscribe + aliceId <- A.prepareConnectionToJoin (client bob) 1 True qInfo PQSupportOn + sqSecured <- A.joinConnection (client bob) NRMInteractive 1 aliceId True qInfo "bob's connInfo" PQSupportOn SMSubscribe liftIO $ sqSecured `shouldBe` False -- joining via contact address connection ("", _, A.REQ invId PQSupportOn _ "bob's connInfo") <- get alice rejectContact alice invId @@ -1063,8 +1177,8 @@ testUpdateConnectionUserId = (connId, qInfo) <- createConnection alice 1 True SCMInvitation Nothing SMSubscribe newUserId <- createUser alice False [noAuthSrvCfg testSMPServer] [noAuthSrvCfg testXFTPServer] _ <- changeConnectionUser alice 1 connId newUserId - aliceId <- A.prepareConnectionToJoin bob 1 True qInfo PQSupportOn - sqSecured' <- A.joinConnection bob NRMInteractive 1 aliceId True qInfo "bob's connInfo" PQSupportOn SMSubscribe + aliceId <- A.prepareConnectionToJoin (client bob) 1 True qInfo PQSupportOn + sqSecured' <- A.joinConnection (client bob) NRMInteractive 1 aliceId True qInfo "bob's connInfo" PQSupportOn SMSubscribe liftIO $ sqSecured' `shouldBe` True ("", _, A.CONF confId pqSup' _ "bob's connInfo") <- get alice liftIO $ pqSup' `shouldBe` PQSupportOn @@ -1085,10 +1199,10 @@ testAsyncInitiatingOffline = liftIO $ sqSecured `shouldBe` True -- send messages - msgId1 <- A.sendMessage bob aliceId PQEncOn SMP.noMsgFlags "can send 1" + msgId1 <- A.sendMessage (client bob) aliceId PQEncOn SMP.noMsgFlags "can send 1" liftIO $ msgId1 `shouldBe` (2, PQEncOff) get bob ##> ("", aliceId, SENT 2) - msgId2 <- A.sendMessage bob aliceId PQEncOn SMP.noMsgFlags "can send 2" + msgId2 <- A.sendMessage (client bob) aliceId PQEncOn SMP.noMsgFlags "can send 2" liftIO $ msgId2 `shouldBe` (3, PQEncOff) get bob ##> ("", aliceId, SENT 3) @@ -1222,15 +1336,15 @@ testInvitationErrors ps restart = do b <- getAgentB (bId, cReq) <- withServer1 ps $ runRight $ createConnection a 1 True SCMInvitation Nothing SMSubscribe ("", "", DOWN _ [_]) <- nGet a - aId <- runRight $ A.prepareConnectionToJoin b 1 True cReq PQSupportOn + aId <- runRight $ A.prepareConnectionToJoin (client b) 1 True cReq PQSupportOn -- fails to secure the queue on testPort - BROKER srv (NETWORK _) <- runLeft $ A.joinConnection b NRMInteractive 1 aId True cReq "bob's connInfo" PQSupportOn SMSubscribe + BROKER srv (NETWORK _) <- runLeft $ A.joinConnection (client b) NRMInteractive 1 aId True cReq "bob's connInfo" PQSupportOn SMSubscribe (testPort `isSuffixOf` srv) `shouldBe` True withServer1 ps $ do ("", "", UP _ [_]) <- nGet a let loopSecure = do -- secures the queue on testPort, but fails to create reply queue on testPort2 - BROKER srv2 (NETWORK _) <- runLeft $ A.joinConnection b NRMInteractive 1 aId True cReq "bob's connInfo" PQSupportOn SMSubscribe + BROKER srv2 (NETWORK _) <- runLeft $ A.joinConnection (client b) NRMInteractive 1 aId True cReq "bob's connInfo" PQSupportOn SMSubscribe unless (testPort2 `isSuffixOf` srv2) $ putStrLn "retrying secure" >> threadDelay 200000 >> loopSecure loopSecure ("", "", DOWN _ [_]) <- nGet a @@ -1238,7 +1352,7 @@ testInvitationErrors ps restart = do threadDelay 200000 let loopCreate = do -- creates the reply queue on testPort2, but fails to send it to testPort - BROKER srv' (NETWORK _) <- runLeft $ A.joinConnection b NRMInteractive 1 aId True cReq "bob's connInfo" PQSupportOn SMSubscribe + BROKER srv' (NETWORK _) <- runLeft $ A.joinConnection (client b) NRMInteractive 1 aId True cReq "bob's connInfo" PQSupportOn SMSubscribe unless (testPort `isSuffixOf` srv') $ putStrLn "retrying create" >> threadDelay 200000 >> loopCreate loopCreate restartAgentB restart b [aId] @@ -1247,7 +1361,7 @@ testInvitationErrors ps restart = do ("", "", UP _ [_]) <- nGet a threadDelay 200000 let loopConfirm n = - runExceptT (A.joinConnection b' NRMInteractive 1 aId True cReq "bob's connInfo" PQSupportOn SMSubscribe) >>= \case + runExceptT (A.joinConnection (client b') NRMInteractive 1 aId True cReq "bob's connInfo" PQSupportOn SMSubscribe) >>= \case Right True -> pure n Right r -> error $ "unexpected result " <> show r Left _ -> putStrLn "retrying confirm" >> threadDelay 200000 >> loopConfirm (n + 1) @@ -1292,14 +1406,14 @@ testContactErrors ps restart = do b <- getAgentB (contactId, cReq) <- withServer1 ps $ runRight $ createConnection a 1 True SCMContact Nothing SMSubscribe ("", "", DOWN _ [_]) <- nGet a - aId <- runRight $ A.prepareConnectionToJoin b 1 True cReq PQSupportOn + aId <- runRight $ A.prepareConnectionToJoin (client b) 1 True cReq PQSupportOn -- fails to create queue on testPort2 - BROKER srv2 (NETWORK _) <- runLeft $ A.joinConnection b NRMInteractive 1 aId True cReq "bob's connInfo" PQSupportOn SMSubscribe + BROKER srv2 (NETWORK _) <- runLeft $ A.joinConnection (client b) NRMInteractive 1 aId True cReq "bob's connInfo" PQSupportOn SMSubscribe (testPort2 `isSuffixOf` srv2) `shouldBe` True b' <- restartAgentB restart b [aId] let loopCreate2 = do -- creates the reply queue on testPort2, but fails to send invitation to testPort - BROKER srv' (NETWORK _) <- runLeft $ A.joinConnection b' NRMInteractive 1 aId True cReq "bob's connInfo" PQSupportOn SMSubscribe + BROKER srv' (NETWORK _) <- runLeft $ A.joinConnection (client b') NRMInteractive 1 aId True cReq "bob's connInfo" PQSupportOn SMSubscribe unless (testPort `isSuffixOf` srv') $ putStrLn "retrying create 2" >> threadDelay 200000 >> loopCreate2 b'' <- withServer2 ps $ do loopCreate2 @@ -1309,7 +1423,7 @@ testContactErrors ps restart = do ("", "", UP _ [_]) <- nGet a let loopSend = do -- sends the invitation to testPort - runExceptT (A.joinConnection b'' NRMInteractive 1 aId True cReq "bob's connInfo" PQSupportOn SMSubscribe) >>= \case + runExceptT (A.joinConnection (client b'') NRMInteractive 1 aId True cReq "bob's connInfo" PQSupportOn SMSubscribe) >>= \case Right False -> pure () Right r -> error $ "unexpected result " <> show r Left _ -> putStrLn "retrying send" >> threadDelay 200000 >> loopSend @@ -1317,7 +1431,7 @@ testContactErrors ps restart = do ("", _, A.REQ invId PQSupportOn _ "bob's connInfo") <- get a pure invId ("", "", DOWN _ [_]) <- nGet a - bId <- runRight $ A.prepareConnectionToAccept a 1 True invId PQSupportOn + bId <- runRight $ prepareConnectionToAccept a 1 True invId PQSupportOn withServer2 ps $ do ("", "", UP _ [_]) <- nGet b'' let loopSecure = do @@ -1376,7 +1490,7 @@ testInvitationShortLink viaProxy a b = withAgent 3 agentCfg initAgentServers testDB3 $ \c -> do let userData = UserLinkData "some user data" newLinkData = UserInvLinkData userData - (bId, CCLink connReq (Just shortLink)) <- runRight $ A.createConnection a NRMInteractive 1 True True SCMInvitation (Just newLinkData) Nothing CR.IKUsePQ SMSubscribe + (bId, CCLink connReq (Just shortLink)) <- runRight $ A.createConnection (client a) NRMInteractive 1 True True SCMInvitation (Just newLinkData) Nothing CR.IKUsePQ SMSubscribe (FixedLinkData {linkConnReq = connReq'}, connData') <- runRight $ getConnShortLink b 1 shortLink strDecode (strEncode shortLink) `shouldBe` Right shortLink connReq' `shouldBe` connReq @@ -1397,8 +1511,8 @@ testInvitationShortLink viaProxy a b = testJoinConn_ :: Bool -> Bool -> AgentClient -> ConnId -> AgentClient -> ConnectionRequestUri c -> ExceptT AgentErrorType IO () testJoinConn_ viaProxy sndSecure a bId b connReq = do - aId <- A.prepareConnectionToJoin b 1 True connReq PQSupportOn - sndSecure' <- A.joinConnection b NRMInteractive 1 aId True connReq "bob's connInfo" PQSupportOn SMSubscribe + aId <- A.prepareConnectionToJoin (client b) 1 True connReq PQSupportOn + sndSecure' <- A.joinConnection (client b) NRMInteractive 1 aId True connReq "bob's connInfo" PQSupportOn SMSubscribe liftIO $ sndSecure' `shouldBe` sndSecure ("", _, CONF confId _ "bob's connInfo") <- get a allowConnection a bId confId "alice's connInfo" @@ -1412,20 +1526,20 @@ testInvitationShortLinkPrev viaProxy sndSecure a b = runRight_ $ do let userData = UserLinkData "some user data" newLinkData = UserInvLinkData userData -- can't create short link with previous version - (bId, CCLink connReq Nothing) <- A.createConnection a NRMInteractive 1 True True SCMInvitation (Just newLinkData) Nothing CR.IKPQOn SMSubscribe + (bId, CCLink connReq Nothing) <- A.createConnection (client a) NRMInteractive 1 True True SCMInvitation (Just newLinkData) Nothing CR.IKPQOn SMSubscribe testJoinConn_ viaProxy sndSecure a bId b connReq testInvitationShortLinkAsync :: HasCallStack => Bool -> AgentClient -> AgentClient -> IO () testInvitationShortLinkAsync viaProxy a b = do let userData = UserLinkData "some user data" newLinkData = UserInvLinkData userData - (bId, CCLink connReq (Just shortLink)) <- runRight $ A.createConnection a NRMInteractive 1 True True SCMInvitation (Just newLinkData) Nothing CR.IKUsePQ SMSubscribe + (bId, CCLink connReq (Just shortLink)) <- runRight $ A.createConnection (client a) NRMInteractive 1 True True SCMInvitation (Just newLinkData) Nothing CR.IKUsePQ SMSubscribe (FixedLinkData {linkConnReq = connReq'}, connData') <- runRight $ getConnShortLink b 1 shortLink strDecode (strEncode shortLink) `shouldBe` Right shortLink connReq' `shouldBe` connReq linkUserData connData' `shouldBe` userData runRight $ do - aId <- A.joinConnectionAsync b 1 "123" Nothing True connReq "bob's connInfo" PQSupportOn SMSubscribe + aId <- A.joinConnectionAsync (client b) 1 "123" Nothing True connReq "bob's connInfo" PQSupportOn SMSubscribe get b =##> \case ("123", c, JOINED sndSecure) -> c == aId && sndSecure; _ -> False ("", _, CONF confId _ "bob's connInfo") <- get a allowConnection a bId confId "alice's connInfo" @@ -1446,7 +1560,7 @@ testContactShortLink viaProxy a b = let userData = UserLinkData "some user data" userCtData = UserContactData {direct = True, owners = [], relays = [], userData} newLinkData = UserContactLinkData userCtData - (contactId, CCLink connReq0 (Just shortLink)) <- runRight $ A.createConnection a NRMInteractive 1 True True SCMContact (Just newLinkData) Nothing CR.IKPQOn SMSubscribe + (contactId, CCLink connReq0 (Just shortLink)) <- runRight $ A.createConnection (client a) NRMInteractive 1 True True SCMContact (Just newLinkData) Nothing CR.IKPQOn SMSubscribe Right connReq <- pure $ smpDecode (smpEncode connReq0) (FixedLinkData {linkConnReq = connReq'}, ContactLinkData _ userCtData') <- runRight $ getConnShortLink b 1 shortLink strDecode (strEncode shortLink) `shouldBe` Right shortLink @@ -1464,7 +1578,7 @@ testContactShortLink viaProxy a b = (aId, sndSecure) <- joinConnection b 1 True connReq "bob's connInfo" SMSubscribe liftIO $ sndSecure `shouldBe` False ("", _, REQ invId _ "bob's connInfo") <- get a - bId <- A.prepareConnectionToAccept a 1 True invId PQSupportOn + bId <- prepareConnectionToAccept a 1 True invId PQSupportOn sndSecure' <- acceptContact a 1 bId True invId "alice's connInfo" PQSupportOn SMSubscribe liftIO $ sndSecure' `shouldBe` True ("", _, CONF confId _ "alice's connInfo") <- get b @@ -1486,14 +1600,14 @@ testContactShortLink viaProxy a b = shortLink2 <- runRight $ setConnShortLink a contactId SCMContact userLinkData' Nothing shortLink2 `shouldBe` shortLink -- delete short link - runRight_ $ deleteConnShortLink a NRMInteractive contactId SCMContact + runRight_ $ A.deleteConnShortLink (client a) NRMInteractive contactId SCMContact Left (SMP _ AUTH) <- runExceptT $ getConnShortLink c 1 shortLink pure () testAddContactShortLink :: HasCallStack => Bool -> AgentClient -> AgentClient -> IO () testAddContactShortLink viaProxy a b = withAgent 3 agentCfg initAgentServers testDB3 $ \c -> do - (contactId, CCLink connReq0 Nothing) <- runRight $ A.createConnection a NRMInteractive 1 True True SCMContact Nothing Nothing CR.IKPQOn SMSubscribe + (contactId, CCLink connReq0 Nothing) <- runRight $ A.createConnection (client a) NRMInteractive 1 True True SCMContact Nothing Nothing CR.IKPQOn SMSubscribe Right connReq <- pure $ smpDecode (smpEncode connReq0) -- let userData = UserLinkData "some user data" userCtData = UserContactData {direct = True, owners = [], relays = [], userData} @@ -1515,7 +1629,7 @@ testAddContactShortLink viaProxy a b = (aId, sndSecure) <- joinConnection b 1 True connReq "bob's connInfo" SMSubscribe liftIO $ sndSecure `shouldBe` False ("", _, REQ invId _ "bob's connInfo") <- get a - bId <- A.prepareConnectionToAccept a 1 True invId PQSupportOn + bId <- prepareConnectionToAccept a 1 True invId PQSupportOn sndSecure' <- acceptContact a 1 bId True invId "alice's connInfo" PQSupportOn SMSubscribe liftIO $ sndSecure' `shouldBe` True ("", _, CONF confId _ "alice's connInfo") <- get b @@ -1539,7 +1653,7 @@ testInvitationShortLinkRestart ps = withAgentClients2 $ \a b -> do let userData = UserLinkData "some user data" newLinkData = UserInvLinkData userData (bId, CCLink connReq (Just shortLink)) <- withSmpServer ps $ - runRight $ A.createConnection a NRMInteractive 1 True True SCMInvitation (Just newLinkData) Nothing CR.IKUsePQ SMOnlyCreate + runRight $ A.createConnection (client a) NRMInteractive 1 True True SCMInvitation (Just newLinkData) Nothing CR.IKUsePQ SMOnlyCreate withSmpServer ps $ do runRight_ $ subscribeConnection a bId (FixedLinkData {linkConnReq = connReq'}, connData') <- runRight $ getConnShortLink b 1 shortLink @@ -1553,7 +1667,7 @@ testContactShortLinkRestart ps = withAgentClients2 $ \a b -> do userCtData = UserContactData {direct = True, owners = [], relays = [], userData} newLinkData = UserContactLinkData userCtData (contactId, CCLink connReq0 (Just shortLink)) <- withSmpServer ps $ - runRight $ A.createConnection a NRMInteractive 1 True True SCMContact (Just newLinkData) Nothing CR.IKPQOn SMOnlyCreate + runRight $ A.createConnection (client a) NRMInteractive 1 True True SCMContact (Just newLinkData) Nothing CR.IKPQOn SMOnlyCreate Right connReq <- pure $ smpDecode (smpEncode connReq0) let updatedData = UserLinkData "updated user data" updatedCtData = UserContactData {direct = False, owners = [], relays = [relayLink1, relayLink2], userData = updatedData} @@ -1577,7 +1691,7 @@ testAddContactShortLinkRestart ps = withAgentClients2 $ \a b -> do userCtData = UserContactData {direct = True, owners = [], relays = [], userData} newLinkData = UserContactLinkData userCtData ((contactId, CCLink connReq0 Nothing), shortLink) <- withSmpServer ps $ runRight $ do - r@(contactId, _) <- A.createConnection a NRMInteractive 1 True True SCMContact Nothing Nothing CR.IKPQOn SMOnlyCreate + r@(contactId, _) <- A.createConnection (client a) NRMInteractive 1 True True SCMContact Nothing Nothing CR.IKPQOn SMOnlyCreate (r,) <$> setConnShortLink a contactId SCMContact newLinkData Nothing Right connReq <- pure $ smpDecode (smpEncode connReq0) let updatedData = UserLinkData "updated user data" @@ -1599,7 +1713,7 @@ testAddContactShortLinkRestart ps = withAgentClients2 $ \a b -> do testOldContactQueueShortLink :: HasCallStack => (ASrvTransport, AStoreType) -> IO () testOldContactQueueShortLink ps@(_, msType) = withAgentClients2 $ \a b -> do (contactId, CCLink connReq Nothing) <- withSmpServer ps $ runRight $ - A.createConnection a NRMInteractive 1 True True SCMContact Nothing Nothing CR.IKPQOn SMOnlyCreate + A.createConnection (client a) NRMInteractive 1 True True SCMContact Nothing Nothing CR.IKPQOn SMOnlyCreate -- make it an "old" queue let updateStoreLog f = replaceSubstringInFile f " queue_mode=C" "" #if defined(dbServerPostgres) @@ -1662,9 +1776,9 @@ testPrepareCreateConnectionLink ps = withSmpServer ps $ withAgentClients2 $ \a b linkEntId <- atomically $ C.randomBytes 32 g runRight $ do (ccLink@(CCLink connReq (Just shortLink)), preparedParams) <- - A.prepareConnectionLink a 1 rootKey linkEntId True Nothing + A.prepareConnectionLink (client a) 1 rootKey linkEntId True Nothing liftIO $ strDecode (strEncode shortLink) `shouldBe` Right shortLink - _ <- A.createConnectionForLink a NRMInteractive 1 True ccLink preparedParams userLinkData CR.IKPQOn SMSubscribe + _ <- A.createConnectionForLink (client a) NRMInteractive 1 True ccLink preparedParams userLinkData CR.IKPQOn SMSubscribe (FixedLinkData {linkConnReq = connReq', linkEntityId}, ContactLinkData _ userCtData') <- getConnShortLink b 1 shortLink liftIO $ Just linkEntId `shouldBe` linkEntityId Right connReqDecoded <- pure $ smpDecode (smpEncode connReq) @@ -1673,7 +1787,7 @@ testPrepareCreateConnectionLink ps = withSmpServer ps $ withAgentClients2 $ \a b (bId, sndSecure) <- joinConnection b 1 True connReq' "bob's connInfo" SMSubscribe liftIO $ sndSecure `shouldBe` False ("", _, REQ invId _ "bob's connInfo") <- get a - aId <- A.prepareConnectionToAccept a 1 True invId PQSupportOn + aId <- prepareConnectionToAccept a 1 True invId PQSupportOn sndSecure' <- acceptContact a 1 aId True invId "alice's connInfo" PQSupportOn SMSubscribe liftIO $ sndSecure' `shouldBe` True ("", _, CONF confId _ "alice's connInfo") <- get b @@ -2406,9 +2520,9 @@ makeConnectionForUsers = makeConnectionForUsers_ PQSupportOn True makeConnectionForUsers_ :: HasCallStack => PQSupport -> SndQueueSecured -> AgentClient -> UserId -> AgentClient -> UserId -> ExceptT AgentErrorType IO (ConnId, ConnId) makeConnectionForUsers_ pqSupport sqSecured alice aliceUserId bob bobUserId = do - (bobId, CCLink qInfo Nothing) <- A.createConnection alice NRMInteractive aliceUserId True True SCMInvitation Nothing Nothing (IKLinkPQ pqSupport) SMSubscribe - aliceId <- A.prepareConnectionToJoin bob bobUserId True qInfo pqSupport - sqSecured' <- A.joinConnection bob NRMInteractive bobUserId aliceId True qInfo "bob's connInfo" pqSupport SMSubscribe + (bobId, CCLink qInfo Nothing) <- A.createConnection (client alice) NRMInteractive aliceUserId True True SCMInvitation Nothing Nothing (IKLinkPQ pqSupport) SMSubscribe + aliceId <- A.prepareConnectionToJoin (client bob) bobUserId True qInfo pqSupport + sqSecured' <- A.joinConnection (client bob) NRMInteractive bobUserId aliceId True qInfo "bob's connInfo" pqSupport SMSubscribe liftIO $ sqSecured' `shouldBe` sqSecured ("", _, A.CONF confId pqSup' _ "bob's connInfo") <- get alice liftIO $ pqSup' `shouldBe` pqSupport @@ -2739,7 +2853,7 @@ testSetConnShortLinkAsync ps = withAgentClients2 $ \alice bob -> let userData = UserLinkData "test user data" userCtData = UserContactData {direct = True, owners = [], relays = [], userData} newLinkData = UserContactLinkData userCtData - (cId, CCLink qInfo (Just shortLink)) <- A.createConnection alice NRMInteractive 1 True True SCMContact (Just newLinkData) Nothing IKPQOn SMSubscribe + (cId, CCLink qInfo (Just shortLink)) <- A.createConnection (client alice) NRMInteractive 1 True True SCMContact (Just newLinkData) Nothing IKPQOn SMSubscribe -- verify initial link data (_, ContactLinkData _ userCtData') <- getConnShortLink bob 1 shortLink liftIO $ userCtData' `shouldBe` userCtData @@ -2757,7 +2871,7 @@ testSetConnShortLinkAsync ps = withAgentClients2 $ \alice bob -> -- complete connection via contact address (aliceId, _) <- joinConnection bob 1 True qInfo "bob's connInfo" SMSubscribe ("", _, REQ invId _ "bob's connInfo") <- get alice - bobId <- A.prepareConnectionToAccept alice 1 True invId PQSupportOn + bobId <- prepareConnectionToAccept alice 1 True invId PQSupportOn _ <- acceptContact alice 1 bobId True invId "alice's connInfo" PQSupportOn SMSubscribe ("", _, CONF confId _ "alice's connInfo") <- get bob allowConnection bob aliceId confId "bob's connInfo" @@ -2771,7 +2885,7 @@ testGetConnShortLinkAsync ps = withAgentClients2 $ \alice bob -> let userData = UserLinkData "test user data" userCtData = UserContactData {direct = True, owners = [], relays = [], userData} newLinkData = UserContactLinkData userCtData - (_, CCLink qInfo (Just shortLink)) <- A.createConnection alice NRMInteractive 1 True True SCMContact (Just newLinkData) Nothing IKPQOn SMSubscribe + (_, CCLink qInfo (Just shortLink)) <- A.createConnection (client alice) NRMInteractive 1 True True SCMContact (Just newLinkData) Nothing IKPQOn SMSubscribe -- get link data async - creates new connection for bob newId <- getConnShortLinkAsync bob 1 "1" Nothing shortLink ("1", newId', LDATA FixedLinkData {linkConnReq = qInfo'} (ContactLinkData _ userCtData')) <- get bob @@ -2785,7 +2899,7 @@ testGetConnShortLinkAsync ps = withAgentClients2 $ \alice bob -> liftIO $ aliceId' `shouldBe` aliceId -- complete connection ("", _, REQ invId _ "bob's connInfo") <- get alice - bobId <- A.prepareConnectionToAccept alice 1 True invId PQSupportOn + bobId <- prepareConnectionToAccept alice 1 True invId PQSupportOn _ <- acceptContact alice 1 bobId True invId "alice's connInfo" PQSupportOn SMSubscribe ("", _, CONF confId _ "alice's connInfo") <- get bob allowConnection bob aliceId confId "bob's connInfo" @@ -2812,7 +2926,7 @@ testAcceptContactAsync sqSecured alice bob baseId = (aliceId, sqSecuredJoin) <- joinConnection bob 1 True qInfo "bob's connInfo" SMSubscribe liftIO $ sqSecuredJoin `shouldBe` False -- joining via contact address connection ("", _, REQ invId _ "bob's connInfo") <- get alice - bobId <- acceptContactAsync alice 1 "1" True invId "alice's connInfo" PQSupportOn SMSubscribe + bobId <- A.acceptContactAsync (client alice) 1 "1" True invId "alice's connInfo" PQSupportOn SMSubscribe get alice =##> \case ("1", c, JOINED sqSecured') -> c == bobId && sqSecured' == sqSecured; _ -> False ("", _, CONF confId _ "alice's connInfo") <- get bob allowConnection bob aliceId confId "bob's connInfo" @@ -3670,12 +3784,12 @@ testDeliveryReceiptsVersion ps = do (aId, bId) <- makeConnection_ PQSupportOff False a b checkVersion a bId 3 checkVersion b aId 3 - (2, _) <- A.sendMessage a bId PQEncOff SMP.noMsgFlags "hello" + (2, _) <- A.sendMessage (client a) bId PQEncOff SMP.noMsgFlags "hello" get a ##> ("", bId, SENT 2) get b =##> \case ("", c, Msg' 2 PQEncOff "hello") -> c == aId; _ -> False ackMessage b aId 2 $ Just "" liftIO $ noMessages a "no delivery receipt (unsupported version)" - (3, _) <- A.sendMessage b aId PQEncOff SMP.noMsgFlags "hello too" + (3, _) <- A.sendMessage (client b) aId PQEncOff SMP.noMsgFlags "hello too" get b ##> ("", aId, SENT 3) get a =##> \case ("", c, Msg' 3 PQEncOff "hello too") -> c == bId; _ -> False ackMessage a bId 3 $ Just "" @@ -3693,19 +3807,19 @@ testDeliveryReceiptsVersion ps = do exchangeGreetingsMsgId_ PQEncOff 4 a' bId b' aId checkVersion a' bId 7 checkVersion b' aId 7 - (6, PQEncOff) <- A.sendMessage a' bId PQEncOn SMP.noMsgFlags "hello" + (6, PQEncOff) <- A.sendMessage (client a') bId PQEncOn SMP.noMsgFlags "hello" get a' ##> ("", bId, SENT 6) get b' =##> \case ("", c, Msg' 6 PQEncOff "hello") -> c == aId; _ -> False ackMessage b' aId 6 $ Just "" get a' =##> \case ("", c, Rcvd 6) -> c == bId; _ -> False ackMessage a' bId 7 Nothing - (8, PQEncOff) <- A.sendMessage b' aId PQEncOn SMP.noMsgFlags "hello too" + (8, PQEncOff) <- A.sendMessage (client b') aId PQEncOn SMP.noMsgFlags "hello too" get b' ##> ("", aId, SENT 8) get a' =##> \case ("", c, Msg' 8 PQEncOff "hello too") -> c == bId; _ -> False ackMessage a' bId 8 $ Just "" get b' =##> \case ("", c, Rcvd 8) -> c == aId; _ -> False ackMessage b' aId 9 Nothing - (10, _) <- A.sendMessage a' bId PQEncOn SMP.noMsgFlags "hello 2" + (10, _) <- A.sendMessage (client a') bId PQEncOn SMP.noMsgFlags "hello 2" get a' ##> ("", bId, SENT 10) get b' =##> \case ("", c, Msg' 10 PQEncOff "hello 2") -> c == aId; _ -> False ackMessage b' aId 10 $ Just "" @@ -3833,7 +3947,7 @@ testTwoUsers = withAgentClients2 $ \a b -> do exchangeGreetingsMsgId 6 a bId2' b aId2' where hasClients :: HasCallStack => AgentClient -> Int -> ExceptT AgentErrorType IO () - hasClients c n = liftIO $ M.size <$> readTVarIO (smpClients c) `shouldReturn` n + hasClients c n = liftIO $ M.size <$> readTVarIO (smpClients $ client c) `shouldReturn` n testClientServiceConnection :: HasCallStack => (ASrvTransport, AStoreType) -> IO () testClientServiceConnection ps = do @@ -4218,9 +4332,10 @@ testMigrateConnectionsToService ps = do getSMPAgentClient' :: Int -> AgentConfig -> InitialAgentServers -> String -> IO AgentClient getSMPAgentClient' clientId cfg' initServers dbPath = do Right st <- liftIO $ createStore dbPath - Right c <- runExceptT $ getSMPAgentClient_ clientId cfg' initServers st False + subQ <- newTBQueueIO 1024 + Right client <- runExceptT $ getSMPAgentClient_ clientId cfg' initServers st False (atomically . writeTBQueue subQ) when (dbNew st) $ insertUser st - pure c + pure AgentClient {client, subQ} #if defined(dbPostgres) createStore :: String -> IO (Either MigrationError DBStore) @@ -4361,7 +4476,7 @@ testServerQueueInfo = do checkEmptyQ alice bobId True checkEmptyQ bob aliceId True let msgId = 2 - (msgId', PQEncOn) <- A.sendMessage alice bobId PQEncOn SMP.noMsgFlags "hello" + (msgId', PQEncOn) <- A.sendMessage (client alice) bobId PQEncOn SMP.noMsgFlags "hello" liftIO $ msgId' `shouldBe` msgId get alice ##> ("", bobId, SENT msgId) liftIO $ threadDelay 200000 @@ -4373,17 +4488,17 @@ testServerQueueInfo = do ackMessage bob aliceId msgId Nothing liftIO $ threadDelay 200000 checkEmptyQ bob aliceId True - (msgId1, PQEncOn) <- A.sendMessage alice bobId PQEncOn SMP.noMsgFlags "hello 1" + (msgId1, PQEncOn) <- A.sendMessage (client alice) bobId PQEncOn SMP.noMsgFlags "hello 1" get alice ##> ("", bobId, SENT msgId1) Just _ <- checkMsgQ bob aliceId 1 - (msgId2, PQEncOn) <- A.sendMessage alice bobId PQEncOn SMP.noMsgFlags "hello 2" + (msgId2, PQEncOn) <- A.sendMessage (client alice) bobId PQEncOn SMP.noMsgFlags "hello 2" get alice ##> ("", bobId, SENT msgId2) - (msgId3, PQEncOn) <- A.sendMessage alice bobId PQEncOn SMP.noMsgFlags "hello 3" + (msgId3, PQEncOn) <- A.sendMessage (client alice) bobId PQEncOn SMP.noMsgFlags "hello 3" get alice ##> ("", bobId, SENT msgId3) - (msgId4, PQEncOn) <- A.sendMessage alice bobId PQEncOn SMP.noMsgFlags "hello 4" + (msgId4, PQEncOn) <- A.sendMessage (client alice) bobId PQEncOn SMP.noMsgFlags "hello 4" get alice ##> ("", bobId, SENT msgId4) Just _ <- checkMsgQ bob aliceId 4 - (msgId5, PQEncOn) <- A.sendMessage alice bobId PQEncOn SMP.noMsgFlags "hello: quota exceeded" + (msgId5, PQEncOn) <- A.sendMessage (client alice) bobId PQEncOn SMP.noMsgFlags "hello: quota exceeded" liftIO $ threadDelay 200000 Just _ <- checkMsgQ bob aliceId 5 get bob =##> \case ("", c, Msg' mId PQEncOn "hello 1") -> c == aliceId && mId == msgId1; _ -> False @@ -4418,7 +4533,7 @@ testServerQueueInfo = do liftIO $ isJust r `shouldBe` True pure r checkQ c cId qiSnd' qiSubThread_ qiSize' msgType_ = do - ServerQueueInfo {info = QueueInfo {qiSnd, qiNtf, qiSub, qiSize, qiMsg}} <- getConnectionQueueInfo c NRMInteractive cId + ServerQueueInfo {info = QueueInfo {qiSnd, qiNtf, qiSub, qiSize, qiMsg}} <- getConnectionQueueInfo (client c) NRMInteractive cId liftIO $ do qiSnd `shouldBe` qiSnd' qiNtf `shouldBe` False @@ -4432,7 +4547,7 @@ testClientNotice :: HasCallStack => (ASrvTransport, AStoreType) -> IO () testClientNotice ps = do withAgent 1 agentCfg initAgentServers testDB $ \c -> do (cId, _) <- withSmpServerStoreLogOn ps testPort $ \_ -> runRight $ - A.createConnection c NRMInteractive 1 True True SCMContact Nothing Nothing IKPQOn SMSubscribe + A.createConnection (client c) NRMInteractive 1 True True SCMContact Nothing Nothing IKPQOn SMSubscribe ("", "", DOWN _ [_]) <- nGet c addNotice c cId $ Just 1 @@ -4441,7 +4556,7 @@ testClientNotice ps = do subscribedWithErrors c 1 testNotice c True threadDelay 1000000 - runRight $ A.createConnection c NRMInteractive 1 True True SCMContact Nothing Nothing IKPQOn SMSubscribe + runRight $ A.createConnection (client c) NRMInteractive 1 True True SCMContact Nothing Nothing IKPQOn SMSubscribe ("", "", DOWN _ [_]) <- nGet c addNotice c cId' $ Just 1 @@ -4452,7 +4567,7 @@ testClientNotice ps = do threadDelay 1000000 testNotice c True threadDelay 1000000 - runRight $ A.createConnection c NRMInteractive 1 True True SCMContact Nothing Nothing IKPQOn SMSubscribe + runRight $ A.createConnection (client c) NRMInteractive 1 True True SCMContact Nothing Nothing IKPQOn SMSubscribe addNotice c cId'' $ Just 1 @@ -4464,7 +4579,7 @@ testClientNotice ps = do threadDelay 2000000 testNotice c True threadDelay 1000000 - runRight $ A.createConnection c NRMInteractive 1 True True SCMContact Nothing Nothing IKPQOn SMSubscribe + runRight $ A.createConnection (client c) NRMInteractive 1 True True SCMContact Nothing Nothing IKPQOn SMSubscribe ("", "", DOWN _ [_]) <- nGet c addNotice c cId3 Nothing @@ -4479,13 +4594,13 @@ testClientNotice ps = do withSmpServerStoreLogOn ps testPort $ \_ -> do runRight_ $ subscribeAllConnections c False Nothing subscribedWithErrors c 4 - void $ runRight $ A.createConnection c NRMInteractive 1 True True SCMContact Nothing Nothing IKPQOn SMSubscribe + void $ runRight $ A.createConnection (client c) NRMInteractive 1 True True SCMContact Nothing Nothing IKPQOn SMSubscribe where addNotice c cId ttl = logNotice c cId $ Just ClientNotice {ttl} removeNotice c cId = logNotice c cId Nothing logNotice :: AgentClient -> ConnId -> Maybe ClientNotice -> IO () logNotice c cId notice = do - Right (SomeConn _ (ContactConnection _ RcvQueue {rcvId})) <- withTransaction (store $ agentEnv c) (`getConn` cId) + Right (SomeConn _ (ContactConnection _ RcvQueue {rcvId})) <- withTransaction (store $ agentEnv $ client c) (`getConn` cId) withFile testStoreLogFile AppendMode $ \h -> B.hPutStrLn h $ strEncode $ BlockQueue rcvId $ SMP.BlockingInfo SMP.BRContent notice subscribedWithErrors c n = do ("", "", ERRS errs) <- nGet c @@ -4495,7 +4610,7 @@ testClientNotice ps = do r -> expectationFailure $ "unexpected event: " <> show r testNotice :: HasCallStack => AgentClient -> Bool -> IO () testNotice c willExpire = do - NOTICE "localhost" False expiresAt_ <- runLeft $ A.createConnection c NRMInteractive 1 True True SCMContact Nothing Nothing IKPQOn SMSubscribe + NOTICE "localhost" False expiresAt_ <- runLeft $ A.createConnection (client c) NRMInteractive 1 True True SCMContact Nothing Nothing IKPQOn SMSubscribe isJust expiresAt_ `shouldBe` willExpire noNetworkDelay :: AgentClient -> IO () @@ -4532,14 +4647,14 @@ exchangeGreetingsViaProxy viaProxy = exchangeGreetingsViaProxyMsgId_ viaProxy PQ exchangeGreetingsViaProxyMsgId_ :: HasCallStack => Bool -> PQEncryption -> Int64 -> Int64 -> AgentClient -> ConnId -> AgentClient -> ConnId -> ExceptT AgentErrorType IO () exchangeGreetingsViaProxyMsgId_ viaProxy pqEnc aMsgId bMsgId alice bobId bob aliceId = do - msgId1 <- A.sendMessage alice bobId pqEnc SMP.noMsgFlags "hello" + msgId1 <- A.sendMessage (client alice) bobId pqEnc SMP.noMsgFlags "hello" liftIO $ msgId1 `shouldBe` (aMsgId, pqEnc) get alice =##> \case ("", c, A.SENT mId srv_) -> c == bobId && mId == aMsgId && viaProxy == isJust srv_; _ -> False if aMsgId <= bMsgId then get bob =##> \case ("", c, Msg' mId pq "hello") -> c == aliceId && mId == bMsgId && pq == pqEnc; _ -> False else get bob =##> \case ("", c, MsgErr' mId (MsgSkipped 2 _) pq "hello") -> c == aliceId && mId == bMsgId && pq == pqEnc; _ -> False ackMessage bob aliceId bMsgId Nothing - msgId2 <- A.sendMessage bob aliceId pqEnc SMP.noMsgFlags "hello too" + msgId2 <- A.sendMessage (client bob) aliceId pqEnc SMP.noMsgFlags "hello too" let aMsgId' = aMsgId + 1 bMsgId' = bMsgId + 1 liftIO $ msgId2 `shouldBe` (bMsgId', pqEnc) diff --git a/tests/AgentTests/ServerChoice.hs b/tests/AgentTests/ServerChoice.hs index 8412c6761..4c00b1a5a 100644 --- a/tests/AgentTests/ServerChoice.hs +++ b/tests/AgentTests/ServerChoice.hs @@ -74,17 +74,17 @@ testChooseDifferentOperator = do c <- getSMPAgentClient' 1 agentCfg initServers testDB runRight_ $ do -- chooses the only operator with storage role - srv1 <- withAgentEnv c $ getNextServer c 1 storageSrvs [] + srv1 <- withAgentEnv (client c) $ getNextServer (client c) 1 storageSrvs [] liftIO $ srv1 == testOp1Srv1 || srv1 == testOp1Srv2 `shouldBe` True -- chooses another server for storage - srv2 <- withAgentEnv c $ getNextServer c 1 storageSrvs [protoServer testOp1Srv1] + srv2 <- withAgentEnv (client c) $ getNextServer (client c) 1 storageSrvs [protoServer testOp1Srv1] liftIO $ srv2 `shouldBe` testOp1Srv2 -- chooses another operator for proxy - srv3 <- withAgentEnv c $ getNextServer c 1 proxySrvs [protoServer srv1] + srv3 <- withAgentEnv (client c) $ getNextServer (client c) 1 proxySrvs [protoServer srv1] liftIO $ srv3 == testOp2Srv1 || srv3 == testOp2Srv2 `shouldBe` True -- chooses another operator for proxy - srv3' <- withAgentEnv c $ getNextServer c 1 proxySrvs [protoServer testOp1Srv1, protoServer testOp1Srv2] + srv3' <- withAgentEnv (client c) $ getNextServer (client c) 1 proxySrvs [protoServer testOp1Srv1, protoServer testOp1Srv2] liftIO $ srv3' == testOp2Srv1 || srv3' == testOp2Srv2 `shouldBe` True -- chooses any other server - srv4 <- withAgentEnv c $ getNextServer c 1 proxySrvs [protoServer testOp1Srv1, protoServer testOp2Srv1] + srv4 <- withAgentEnv (client c) $ getNextServer (client c) 1 proxySrvs [protoServer testOp1Srv1, protoServer testOp2Srv1] liftIO $ srv4 == testOp1Srv2 || srv4 == testOp2Srv2 `shouldBe` True diff --git a/tests/SMPProxyTests.hs b/tests/SMPProxyTests.hs index 1edc95766..c4e052980 100644 --- a/tests/SMPProxyTests.hs +++ b/tests/SMPProxyTests.hs @@ -27,7 +27,7 @@ import Data.Time.Clock (getCurrentTime) import SMPAgentClient import SMPClient import ServerTests (decryptMsgV3, sendRecv) -import Simplex.Messaging.Agent hiding (createConnection, joinConnection, sendMessage) +import Simplex.Messaging.Agent hiding (AgentClient, createConnection, joinConnection, sendMessage, allowConnection, ackMessage) import qualified Simplex.Messaging.Agent as A import Simplex.Messaging.Agent.Env.SQLite (AgentConfig (..), InitialAgentServers (..)) import Simplex.Messaging.Agent.Protocol hiding (CON, CONF, INFO, REQ) @@ -224,9 +224,9 @@ agentDeliverMessageViaProxy :: (C.AlgorithmI a, C.AuthAlgorithm a) => (NonEmpty agentDeliverMessageViaProxy aTestCfg@(aSrvs, _, aViaProxy) bTestCfg@(bSrvs, _, bViaProxy) alg msg1 msg2 baseId = withAgent 1 aCfg (servers aTestCfg) testDB $ \alice -> withAgent 2 aCfg (servers bTestCfg) testDB2 $ \bob -> runRight_ $ do - (bobId, CCLink qInfo Nothing) <- A.createConnection alice NRMInteractive 1 True True SCMInvitation Nothing Nothing CR.IKPQOn SMSubscribe - aliceId <- A.prepareConnectionToJoin bob 1 True qInfo PQSupportOn - sqSecured <- A.joinConnection bob NRMInteractive 1 aliceId True qInfo "bob's connInfo" PQSupportOn SMSubscribe + (bobId, CCLink qInfo Nothing) <- A.createConnection (client alice) NRMInteractive 1 True True SCMInvitation Nothing Nothing CR.IKPQOn SMSubscribe + aliceId <- A.prepareConnectionToJoin (client bob) 1 True qInfo PQSupportOn + sqSecured <- A.joinConnection (client bob) NRMInteractive 1 aliceId True qInfo "bob's connInfo" PQSupportOn SMSubscribe liftIO $ sqSecured `shouldBe` True ("", _, A.CONF confId pqSup' _ "bob's connInfo") <- get alice liftIO $ pqSup' `shouldBe` PQSupportOn @@ -237,18 +237,18 @@ agentDeliverMessageViaProxy aTestCfg@(aSrvs, _, aViaProxy) bTestCfg@(bSrvs, _, b get bob ##> ("", aliceId, A.CON pqEnc) -- message IDs 1 to 3 (or 1 to 4 in v1) get assigned to control messages, so first MSG is assigned ID 4 let aProxySrv = if aViaProxy then Just $ L.head aSrvs else Nothing - 1 <- msgId <$> A.sendMessage alice bobId pqEnc noMsgFlags msg1 + 1 <- msgId <$> A.sendMessage (client alice) bobId pqEnc noMsgFlags msg1 get alice ##> ("", bobId, A.SENT (baseId + 1) aProxySrv) - 2 <- msgId <$> A.sendMessage alice bobId pqEnc noMsgFlags msg2 + 2 <- msgId <$> A.sendMessage (client alice) bobId pqEnc noMsgFlags msg2 get alice ##> ("", bobId, A.SENT (baseId + 2) aProxySrv) get bob =##> \case ("", c, Msg' _ pq msg1') -> c == aliceId && pq == pqEnc && msg1 == msg1'; _ -> False ackMessage bob aliceId (baseId + 1) Nothing get bob =##> \case ("", c, Msg' _ pq msg2') -> c == aliceId && pq == pqEnc && msg2 == msg2'; _ -> False ackMessage bob aliceId (baseId + 2) Nothing let bProxySrv = if bViaProxy then Just $ L.head bSrvs else Nothing - 3 <- msgId <$> A.sendMessage bob aliceId pqEnc noMsgFlags msg1 + 3 <- msgId <$> A.sendMessage (client bob) aliceId pqEnc noMsgFlags msg1 get bob ##> ("", aliceId, A.SENT (baseId + 3) bProxySrv) - 4 <- msgId <$> A.sendMessage bob aliceId pqEnc noMsgFlags msg2 + 4 <- msgId <$> A.sendMessage (client bob) aliceId pqEnc noMsgFlags msg2 get bob ##> ("", aliceId, A.SENT (baseId + 4) bProxySrv) get alice =##> \case ("", c, Msg' _ pq msg1') -> c == bobId && pq == pqEnc && msg1 == msg1'; _ -> False ackMessage alice bobId (baseId + 3) Nothing @@ -280,9 +280,9 @@ agentDeliverMessagesViaProxyConc agentServers msgs = -- agent connections have to be set up in advance -- otherwise the CONF messages would get mixed with MSG prePair alice bob = do - (bobId, CCLink qInfo Nothing) <- runExceptT' $ A.createConnection alice NRMInteractive 1 True True SCMInvitation Nothing Nothing CR.IKPQOn SMSubscribe - aliceId <- runExceptT' $ A.prepareConnectionToJoin bob 1 True qInfo PQSupportOn - sqSecured <- runExceptT' $ A.joinConnection bob NRMInteractive 1 aliceId True qInfo "bob's connInfo" PQSupportOn SMSubscribe + (bobId, CCLink qInfo Nothing) <- runExceptT' $ A.createConnection (client alice) NRMInteractive 1 True True SCMInvitation Nothing Nothing CR.IKPQOn SMSubscribe + aliceId <- runExceptT' $ A.prepareConnectionToJoin (client bob) 1 True qInfo PQSupportOn + sqSecured <- runExceptT' $ A.joinConnection (client bob) NRMInteractive 1 aliceId True qInfo "bob's connInfo" PQSupportOn SMSubscribe liftIO $ sqSecured `shouldBe` True confId <- get alice >>= \case @@ -297,7 +297,7 @@ agentDeliverMessagesViaProxyConc agentServers msgs = pure (alice, bobId, bob, aliceId) -- stream messages in opposite directions, while getting deliveries and sending ACKs run (alice, bobId, bob, aliceId) = do - aSender <- async $ forM_ msgs $ runExceptT' . A.sendMessage alice bobId pqEnc noMsgFlags + aSender <- async $ forM_ msgs $ runExceptT' . A.sendMessage (client alice) bobId pqEnc noMsgFlags bRecipient <- async $ forever $ @@ -305,7 +305,7 @@ agentDeliverMessagesViaProxyConc agentServers msgs = ("", _, A.SENT _ _) -> pure () ("", _, Msg' mId' _ _) -> runExceptT' $ ackMessage alice bobId mId' Nothing huh -> fail (show huh) - bSender <- async $ forM_ msgs $ runExceptT' . A.sendMessage bob aliceId pqEnc noMsgFlags + bSender <- async $ forM_ msgs $ runExceptT' . A.sendMessage (client bob) aliceId pqEnc noMsgFlags aRecipient <- async $ forever $ @@ -331,9 +331,9 @@ agentViaProxyVersionError = withAgent 1 agentCfg (servers [SMPServer testHost testPort testKeyHash]) testDB $ \alice -> do Left (A.BROKER _ (TRANSPORT TEVersion)) <- withAgent 2 agentCfg (servers [SMPServer testHost2 testPort2 testKeyHash]) testDB2 $ \bob -> runExceptT $ do - (_bobId, CCLink qInfo Nothing) <- A.createConnection alice NRMInteractive 1 True True SCMInvitation Nothing Nothing CR.IKPQOn SMSubscribe - aliceId <- A.prepareConnectionToJoin bob 1 True qInfo PQSupportOn - A.joinConnection bob NRMInteractive 1 aliceId True qInfo "bob's connInfo" PQSupportOn SMSubscribe + (_bobId, CCLink qInfo Nothing) <- A.createConnection (client alice) NRMInteractive 1 True True SCMInvitation Nothing Nothing CR.IKPQOn SMSubscribe + aliceId <- A.prepareConnectionToJoin (client bob) 1 True qInfo PQSupportOn + A.joinConnection (client bob) NRMInteractive 1 aliceId True qInfo "bob's connInfo" PQSupportOn SMSubscribe pure () where servers srvs = (initAgentServersProxy_ SPMUnknown SPFProhibit) {smp = userServers srvs} @@ -351,9 +351,9 @@ agentViaProxyRetryOffline = do let pqEnc = CR.PQEncOn withServer $ \_ -> do (aliceId, bobId) <- withServer2 $ \_ -> runRight $ do - (bobId, CCLink qInfo Nothing) <- A.createConnection alice NRMInteractive 1 True True SCMInvitation Nothing Nothing CR.IKPQOn SMSubscribe - aliceId <- A.prepareConnectionToJoin bob 1 True qInfo PQSupportOn - sqSecured <- A.joinConnection bob NRMInteractive 1 aliceId True qInfo "bob's connInfo" PQSupportOn SMSubscribe + (bobId, CCLink qInfo Nothing) <- A.createConnection (client alice) NRMInteractive 1 True True SCMInvitation Nothing Nothing CR.IKPQOn SMSubscribe + aliceId <- A.prepareConnectionToJoin (client bob) 1 True qInfo PQSupportOn + sqSecured <- A.joinConnection (client bob) NRMInteractive 1 aliceId True qInfo "bob's connInfo" PQSupportOn SMSubscribe liftIO $ sqSecured `shouldBe` True ("", _, A.CONF confId pqSup' _ "bob's connInfo") <- get alice liftIO $ pqSup' `shouldBe` PQSupportOn @@ -361,18 +361,18 @@ agentViaProxyRetryOffline = do get alice ##> ("", bobId, A.CON pqEnc) get bob ##> ("", aliceId, A.INFO PQSupportOn "alice's connInfo") get bob ##> ("", aliceId, A.CON pqEnc) - 1 <- msgId <$> A.sendMessage alice bobId pqEnc noMsgFlags msg1 + 1 <- msgId <$> A.sendMessage (client alice) bobId pqEnc noMsgFlags msg1 get alice ##> ("", bobId, A.SENT (baseId + 1) aProxySrv) get bob =##> \case ("", c, Msg' _ pq msg1') -> c == aliceId && pq == pqEnc && msg1 == msg1'; _ -> False ackMessage bob aliceId (baseId + 1) Nothing - 2 <- msgId <$> A.sendMessage bob aliceId pqEnc noMsgFlags msg2 + 2 <- msgId <$> A.sendMessage (client bob) aliceId pqEnc noMsgFlags msg2 get bob ##> ("", aliceId, A.SENT (baseId + 2) bProxySrv) get alice =##> \case ("", c, Msg' _ pq msg2') -> c == bobId && pq == pqEnc && msg2 == msg2'; _ -> False ackMessage alice bobId (baseId + 2) Nothing pure (aliceId, bobId) runRight_ $ do -- destination relay down - 3 <- msgId <$> A.sendMessage alice bobId pqEnc noMsgFlags msg1 + 3 <- msgId <$> A.sendMessage (client alice) bobId pqEnc noMsgFlags msg1 bob `down` aliceId withServer2 $ \_ -> runRight_ $ do bob `up` aliceId @@ -381,7 +381,7 @@ agentViaProxyRetryOffline = do ackMessage bob aliceId (baseId + 3) Nothing runRight_ $ do -- proxy relay down - 4 <- msgId <$> A.sendMessage bob aliceId pqEnc noMsgFlags msg2 + 4 <- msgId <$> A.sendMessage (client bob) aliceId pqEnc noMsgFlags msg2 bob `down` aliceId withServer2 $ \_ -> do getInAnyOrder diff --git a/tests/XFTPAgent.hs b/tests/XFTPAgent.hs index af1d2f5c2..f03fe003d 100644 --- a/tests/XFTPAgent.hs +++ b/tests/XFTPAgent.hs @@ -10,7 +10,7 @@ module XFTPAgent where -import AgentTests.FunctionalAPITests (get, rfGet, runRight, runRight_, sfGet, withAgent) +import AgentTests.FunctionalAPITests (AgentClient (..), get, rfGet, runRight, runRight_, sfGet, withAgent) import Control.Logger.Simple import Control.Monad @@ -30,7 +30,7 @@ import Simplex.FileTransfer.Server.Env (AFStoreType, XFTPServerConfig (..)) import Simplex.FileTransfer.Server.Store (STMFileStore) import Simplex.FileTransfer.Transport (XFTPErrorType (AUTH)) import Simplex.FileTransfer.Types (RcvFileId, SndFileId) -import Simplex.Messaging.Agent (AgentClient, testProtocolServer, xftpDeleteRcvFile, xftpDeleteSndFileInternal, xftpDeleteSndFileRemote, xftpReceiveFile, xftpSendDescription, xftpSendFile, xftpStartWorkers) +import qualified Simplex.Messaging.Agent as A import Simplex.Messaging.Agent.Client (ProtocolTestFailure (..), ProtocolTestStep (..)) import Simplex.Messaging.Agent.Env.SQLite (AgentConfig, xftpCfg) import Simplex.Messaging.Agent.Protocol (AEvent (..), AgentErrorType (..), BrokerErrorType (..), noAuthSrv) @@ -99,7 +99,7 @@ testXFTPServerTest newFileBasicAuth srv = withXFTPServerCfg testXFTPServerConfig {newFileBasicAuth, xftpPort = xftpTestPort2} $ \_ -> -- initially passed server is not running withAgent 1 agentCfg initAgentServers testDB $ \a -> - testProtocolServer a NRMInteractive 1 srv + A.testProtocolServer (client a) NRMInteractive 1 srv rfProgress :: forall m. (HasCallStack, MonadIO m, MonadFail m) => AgentClient -> Int64 -> m () rfProgress c expected = loop 0 @@ -132,7 +132,7 @@ testXFTPAgentSendReceive = do -- send file, delete snd file internally (rfd1, rfd2) <- withAgent 1 agentCfg initAgentServers testDB $ \sndr -> runRight $ do (sfId, _, rfd1, rfd2) <- testSend sndr filePath - liftIO $ xftpDeleteSndFileInternal sndr sfId + liftIO $ A.xftpDeleteSndFileInternal (client sndr) sfId pure (rfd1, rfd2) -- receive file, delete rcv file testReceiveDelete 2 rfd1 filePath @@ -141,7 +141,7 @@ testXFTPAgentSendReceive = do testReceiveDelete clientId rfd originalFilePath = withAgent clientId agentCfg initAgentServers testDB2 $ \rcp -> do rfId <- runRight $ testReceive rcp rfd originalFilePath - xftpDeleteRcvFile rcp rfId + A.xftpDeleteRcvFile (client rcp) rfId testXFTPAgentSendReceiveEncrypted :: HasCallStack => AFStoreType -> IO () testXFTPAgentSendReceiveEncrypted = withXFTPServer $ do @@ -152,7 +152,7 @@ testXFTPAgentSendReceiveEncrypted = withXFTPServer $ do runRight_ $ CF.writeFile file s (rfd1, rfd2) <- withAgent 1 agentCfg initAgentServers testDB $ \sndr -> runRight $ do (sfId, _, rfd1, rfd2) <- testSendCF sndr file - liftIO $ xftpDeleteSndFileInternal sndr sfId + liftIO $ A.xftpDeleteSndFileInternal (client sndr) sfId pure (rfd1, rfd2) -- receive file, delete rcv file testReceiveDelete 2 rfd1 filePath g @@ -162,7 +162,7 @@ testXFTPAgentSendReceiveEncrypted = withXFTPServer $ do withAgent clientId agentCfg initAgentServers testDB2 $ \rcp -> do cfArgs <- atomically $ Just <$> CF.randomArgs g rfId <- runRight $ testReceiveCF rcp rfd cfArgs originalFilePath - xftpDeleteRcvFile rcp rfId + A.xftpDeleteRcvFile (client rcp) rfId testXFTPAgentSendReceiveRedirect :: HasCallStack => AFStoreType -> IO () testXFTPAgentSendReceiveRedirect = withXFTPServer $ do @@ -171,7 +171,7 @@ testXFTPAgentSendReceiveRedirect = withXFTPServer $ do let fileSize = mb 17 totalSize = fileSize + mb 1 withAgent 1 agentCfg initAgentServers testDB $ \sndr -> do - directFileId <- runRight $ xftpSendFile sndr 1 (CryptoFile filePathIn Nothing) 1 + directFileId <- runRight $ A.xftpSendFile (client sndr) 1 (CryptoFile filePathIn Nothing) 1 sfGet sndr `shouldReturn` ("", directFileId, SFPROG 4194304 totalSize) sfGet sndr `shouldReturn` ("", directFileId, SFPROG 8388608 totalSize) sfGet sndr `shouldReturn` ("", directFileId, SFPROG 12582912 totalSize) @@ -185,7 +185,7 @@ testXFTPAgentSendReceiveRedirect = withXFTPServer $ do testNoRedundancy vfdDirect - redirectFileId <- runRight $ xftpSendDescription sndr 1 vfdDirect 1 + redirectFileId <- runRight $ A.xftpSendDescription (client sndr) 1 vfdDirect 1 logInfo $ "File sent, sending redirect: " <> tshow redirectFileId sfGet sndr `shouldReturn` ("", redirectFileId, SFPROG 65536 65536) vfdRedirect@(ValidFileDescription fdRedirect) <- @@ -206,7 +206,7 @@ testXFTPAgentSendReceiveRedirect = withXFTPServer $ do withAgent 2 agentCfg initAgentServers testDB2 $ \rcp -> do FileDescriptionURI {description} <- either fail pure $ strDecode uri - rcvFileId <- runRight $ xftpReceiveFile rcp 1 description Nothing True + rcvFileId <- runRight $ A.xftpReceiveFile (client rcp) 1 description Nothing True rfGet rcp `shouldReturn` ("", rcvFileId, RFPROG 65536 totalSize) -- extra RFPROG before switching to real file rfGet rcp `shouldReturn` ("", rcvFileId, RFPROG 4194304 totalSize) rfGet rcp `shouldReturn` ("", rcvFileId, RFPROG 8388608 totalSize) @@ -228,7 +228,7 @@ testXFTPAgentSendReceiveNoRedirect = withXFTPServer $ do let fileSize = mb 5 filePathIn <- createRandomFile_ fileSize "testfile" withAgent 1 agentCfg initAgentServers testDB $ \sndr -> do - directFileId <- runRight $ xftpSendFile sndr 1 (CryptoFile filePathIn Nothing) 1 + directFileId <- runRight $ A.xftpSendFile (client sndr) 1 (CryptoFile filePathIn Nothing) 1 let totalSize = fileSize + mb 1 sfGet sndr `shouldReturn` ("", directFileId, SFPROG 4194304 totalSize) sfGet sndr `shouldReturn` ("", directFileId, SFPROG 5242880 totalSize) @@ -250,7 +250,7 @@ testXFTPAgentSendReceiveNoRedirect = withXFTPServer $ do FileDescriptionURI {description} <- either fail pure $ strDecode uri let ValidFileDescription FileDescription {redirect} = description redirect `shouldBe` Nothing - rcvFileId <- runRight $ xftpReceiveFile rcp 1 description Nothing True + rcvFileId <- runRight $ A.xftpReceiveFile (client rcp) 1 description Nothing True -- NO extra "RFPROG 65k 65k" before switching to real file rfGet rcp `shouldReturn` ("", rcvFileId, RFPROG 4194304 totalSize) rfGet rcp `shouldReturn` ("", rcvFileId, RFPROG 5242880 totalSize) @@ -286,10 +286,10 @@ testXFTPAgentSendReceiveMatrix = do filePath <- createRandomFile_ (kb 319 :: Integer) "testfile" rfd <- withAgent 1 sender initAgentServers testDB $ \sndr -> do (sfId, _, rfd1, _) <- runRight $ testSendCF' sndr (CF.plain filePath) (kb 320) - rfd1 <$ xftpDeleteSndFileInternal sndr sfId + rfd1 <$ A.xftpDeleteSndFileInternal (client sndr) sfId withAgent 2 receiver initAgentServers testDB2 $ \rcp -> do rfId <- runRight $ testReceiveCF' rcp rfd Nothing filePath (kb 320) - xftpDeleteRcvFile rcp rfId + A.xftpDeleteRcvFile (client rcp) rfId createRandomFile :: HasCallStack => IO FilePath createRandomFile = createRandomFile' "testfile" @@ -312,8 +312,8 @@ testSendCF sndr file = testSendCF' sndr file $ mb 18 testSendCF' :: HasCallStack => AgentClient -> CryptoFile -> Int64 -> ExceptT AgentErrorType IO (SndFileId, ValidFileDescription 'FSender, ValidFileDescription 'FRecipient, ValidFileDescription 'FRecipient) testSendCF' sndr file size = do - xftpStartWorkers sndr (Just senderFiles) - sfId <- xftpSendFile sndr 1 file 2 + A.xftpStartWorkers (client sndr) (Just senderFiles) + sfId <- A.xftpSendFile (client sndr) 1 file 2 sfProgress sndr size ("", sfId', SFDONE sndDescr [rfd1, rfd2]) <- sfGet sndr liftIO $ testNoRedundancy rfd1 @@ -330,7 +330,7 @@ testReceive rcp rfd = testReceiveCF rcp rfd Nothing testReceiveCF :: HasCallStack => AgentClient -> ValidFileDescription 'FRecipient -> Maybe CryptoFileArgs -> FilePath -> ExceptT AgentErrorType IO RcvFileId testReceiveCF rcp rfd cfArgs originalFilePath = do - xftpStartWorkers rcp (Just recipientFiles) + A.xftpStartWorkers (client rcp) (Just recipientFiles) testReceiveCF' rcp rfd cfArgs originalFilePath $ mb 18 testReceive' :: HasCallStack => AgentClient -> ValidFileDescription 'FRecipient -> FilePath -> ExceptT AgentErrorType IO RcvFileId @@ -338,7 +338,7 @@ testReceive' rcp rfd originalFilePath = testReceiveCF' rcp rfd Nothing originalF testReceiveCF' :: HasCallStack => AgentClient -> ValidFileDescription 'FRecipient -> Maybe CryptoFileArgs -> FilePath -> Int64 -> ExceptT AgentErrorType IO RcvFileId testReceiveCF' rcp rfd cfArgs originalFilePath size = do - rfId <- xftpReceiveFile rcp 1 rfd cfArgs True + rfId <- A.xftpReceiveFile (client rcp) 1 rfd cfArgs True rfProgress rcp size ("", rfId', RFDONE path) <- rfGet rcp liftIO $ do @@ -362,8 +362,8 @@ testXFTPAgentReceiveRestore = do -- receive file - should not succeed with server down rfId <- withAgent 2 agentCfg initAgentServers testDB2 $ \rcp -> runRight $ do - xftpStartWorkers rcp (Just recipientFiles) - rfId <- xftpReceiveFile rcp 1 rfd Nothing True + A.xftpStartWorkers (client rcp) (Just recipientFiles) + rfId <- A.xftpReceiveFile (client rcp) 1 rfd Nothing True liftIO $ timeout 300000 (get rcp) `shouldReturn` Nothing -- wait for worker attempt pure rfId @@ -374,7 +374,7 @@ testXFTPAgentReceiveRestore = do withXFTPServerStoreLogOn $ \_ -> -- receive file - should start downloading with server up withAgent 3 agentCfg initAgentServers testDB2 $ \rcp' -> do - runRight_ $ xftpStartWorkers rcp' (Just recipientFiles) + runRight_ $ A.xftpStartWorkers (client rcp') (Just recipientFiles) ("", rfId', RFPROG _ _) <- rfGet rcp' liftIO $ rfId' `shouldBe` rfId threadDelay 100000 @@ -382,7 +382,7 @@ testXFTPAgentReceiveRestore = do withXFTPServerStoreLogOn $ \_ -> -- receive file - should continue downloading with server up withAgent 4 agentCfg initAgentServers testDB2 $ \rcp' -> do - runRight_ $ xftpStartWorkers rcp' (Just recipientFiles) + runRight_ $ A.xftpStartWorkers (client rcp') (Just recipientFiles) rfProgress rcp' $ mb 18 ("", rfId', RFDONE path) <- rfGet rcp' liftIO $ do @@ -406,8 +406,8 @@ testXFTPAgentReceiveCleanup = withGlobalLogging logCfgNoLogs $ do -- receive file - should not succeed with server down rfId <- withAgent 2 agentCfg initAgentServers testDB2 $ \rcp -> runRight $ do - xftpStartWorkers rcp (Just recipientFiles) - rfId <- xftpReceiveFile rcp 1 rfd Nothing True + A.xftpStartWorkers (client rcp) (Just recipientFiles) + rfId <- A.xftpReceiveFile (client rcp) 1 rfd Nothing True liftIO $ timeout 300000 (get rcp) `shouldReturn` Nothing -- wait for worker attempt pure rfId @@ -418,7 +418,7 @@ testXFTPAgentReceiveCleanup = withGlobalLogging logCfgNoLogs $ do withXFTPServerThreadOn $ \_ -> -- receive file - should fail with AUTH error withAgent 3 agentCfg initAgentServers testDB2 $ \rcp' -> do - runRight_ $ xftpStartWorkers rcp' (Just recipientFiles) + runRight_ $ A.xftpStartWorkers (client rcp') (Just recipientFiles) ("", rfId', RFERR (XFTP "xftp://LcJUMfVhwD8yxjAiSaDzzGF3-kLG4Uh0Fl_ZIjrRwjI=@localhost:8000" AUTH)) <- rfGet rcp' rfId' `shouldBe` rfId @@ -431,8 +431,8 @@ testXFTPAgentSendRestore = withGlobalLogging logCfgNoLogs $ do -- send file - should not succeed with server down sfId <- withAgent 1 agentCfg initAgentServers testDB $ \sndr -> runRight $ do - xftpStartWorkers sndr (Just senderFiles) - sfId <- xftpSendFile sndr 1 (CF.plain filePath) 2 + A.xftpStartWorkers (client sndr) (Just senderFiles) + sfId <- A.xftpSendFile (client sndr) 1 (CF.plain filePath) 2 liftIO $ timeout 1000000 (get sndr) `shouldReturn` Nothing -- wait for worker to encrypt and attempt to create file pure sfId @@ -446,7 +446,7 @@ testXFTPAgentSendRestore = withGlobalLogging logCfgNoLogs $ do withXFTPServerStoreLogOn $ \_ -> -- send file - should start uploading with server up withAgent 2 agentCfg initAgentServers testDB $ \sndr' -> do - runRight_ $ xftpStartWorkers sndr' (Just senderFiles) + runRight_ $ A.xftpStartWorkers (client sndr') (Just senderFiles) ("", sfId', SFPROG _ _) <- sfGet sndr' liftIO $ sfId' `shouldBe` sfId @@ -455,7 +455,7 @@ testXFTPAgentSendRestore = withGlobalLogging logCfgNoLogs $ do withXFTPServerStoreLogOn $ \_ -> do -- send file - should continue uploading with server up rfd1 <- withAgent 3 agentCfg initAgentServers testDB $ \sndr' -> do - runRight_ $ xftpStartWorkers sndr' (Just senderFiles) + runRight_ $ A.xftpStartWorkers (client sndr') (Just senderFiles) sfProgress sndr' $ mb 18 ("", sfId', SFDONE _sndDescr [rfd1, rfd2]) <- sfGet sndr' liftIO $ testNoRedundancy rfd1 @@ -479,8 +479,8 @@ testXFTPAgentSendCleanup = withGlobalLogging logCfgNoLogs $ do sfId <- withXFTPServerStoreLogOn $ \_ -> -- send file withAgent 1 agentCfg initAgentServers testDB $ \sndr -> runRight $ do - xftpStartWorkers sndr (Just senderFiles) - sfId <- xftpSendFile sndr 1 (CF.plain filePath) 2 + A.xftpStartWorkers (client sndr) (Just senderFiles) + sfId <- A.xftpSendFile (client sndr) 1 (CF.plain filePath) 2 -- wait for progress events for 5 out of 6 chunks - at this point all chunks should be created on the server forM_ [1 .. 5 :: Integer] $ \_ -> do (_, _, SFPROG _ _) <- sfGet sndr @@ -497,7 +497,7 @@ testXFTPAgentSendCleanup = withGlobalLogging logCfgNoLogs $ do withXFTPServerThreadOn $ \_ -> -- send file - should fail with AUTH error withAgent 2 agentCfg initAgentServers testDB $ \sndr' -> do - runRight_ $ xftpStartWorkers sndr' (Just senderFiles) + runRight_ $ A.xftpStartWorkers (client sndr') (Just senderFiles) ("", sfId', SFERR (XFTP "xftp://LcJUMfVhwD8yxjAiSaDzzGF3-kLG4Uh0Fl_ZIjrRwjI=@localhost:8000" AUTH)) <- sfGet sndr' sfId' `shouldBe` sfId @@ -523,8 +523,8 @@ testXFTPAgentDelete = withGlobalLogging logCfgNoLogs . withXFTPServer test length <$> listDirectory xftpServerFiles `shouldReturn` 6 -- delete file - runRight_ $ xftpStartWorkers sndr (Just senderFiles) - xftpDeleteSndFileRemote sndr 1 sfId sndDescr + runRight_ $ A.xftpStartWorkers (client sndr) (Just senderFiles) + A.xftpDeleteSndFileRemote (client sndr) 1 sfId sndDescr Nothing <- 100000 `timeout` sfGet sndr pure () @@ -533,8 +533,8 @@ testXFTPAgentDelete = withGlobalLogging logCfgNoLogs . withXFTPServer test -- receive file - should fail with AUTH error withAgent 3 agentCfg initAgentServers testDB2 $ \rcp2 -> runRight $ do - xftpStartWorkers rcp2 (Just recipientFiles) - rfId <- xftpReceiveFile rcp2 1 rfd2 Nothing True + A.xftpStartWorkers (client rcp2) (Just recipientFiles) + rfId <- A.xftpReceiveFile (client rcp2) 1 rfd2 Nothing True ("", rfId', RFERR (XFTP "xftp://LcJUMfVhwD8yxjAiSaDzzGF3-kLG4Uh0Fl_ZIjrRwjI=@localhost:8000" AUTH)) <- rfGet rcp2 liftIO $ rfId' `shouldBe` rfId @@ -555,8 +555,8 @@ testXFTPAgentDeleteRestore = withGlobalLogging logCfgNoLogs $ do -- delete file - should not succeed with server down withAgent 3 agentCfg initAgentServers testDB $ \sndr -> do - runRight_ $ xftpStartWorkers sndr (Just senderFiles) - xftpDeleteSndFileRemote sndr 1 sfId sndDescr + runRight_ $ A.xftpStartWorkers (client sndr) (Just senderFiles) + A.xftpDeleteSndFileRemote (client sndr) 1 sfId sndDescr timeout 300000 (get sndr) `shouldReturn` Nothing -- wait for worker attempt threadDelay 300000 length <$> listDirectory xftpServerFiles `shouldReturn` 6 @@ -564,15 +564,15 @@ testXFTPAgentDeleteRestore = withGlobalLogging logCfgNoLogs $ do withXFTPServerStoreLogOn $ \_ -> do -- delete file - should succeed with server up withAgent 4 agentCfg initAgentServers testDB $ \sndr' -> do - runRight_ $ xftpStartWorkers sndr' (Just senderFiles) + runRight_ $ A.xftpStartWorkers (client sndr') (Just senderFiles) threadDelay 1000000 length <$> listDirectory xftpServerFiles `shouldReturn` 0 -- receive file - should fail with AUTH error withAgent 5 agentCfg initAgentServers testDB3 $ \rcp2 -> runRight $ do - xftpStartWorkers rcp2 (Just recipientFiles) - rfId <- xftpReceiveFile rcp2 1 rfd2 Nothing True + A.xftpStartWorkers (client rcp2) (Just recipientFiles) + rfId <- A.xftpReceiveFile (client rcp2) 1 rfd2 Nothing True ("", rfId', RFERR (XFTP "xftp://LcJUMfVhwD8yxjAiSaDzzGF3-kLG4Uh0Fl_ZIjrRwjI=@localhost:8000" AUTH)) <- rfGet rcp2 liftIO $ rfId' `shouldBe` rfId @@ -608,7 +608,7 @@ testXFTPAgentDeleteOnServer = withGlobalLogging logCfgNoLogs . withXFTPServer te runRight_ . void $ do -- receive file 1 again - rfId1 <- xftpReceiveFile rcp 1 rfd1_2 Nothing True + rfId1 <- A.xftpReceiveFile (client rcp) 1 rfd1_2 Nothing True ("", rfId1', RFERR (XFTP "xftp://LcJUMfVhwD8yxjAiSaDzzGF3-kLG4Uh0Fl_ZIjrRwjI=@localhost:8000" AUTH)) <- rfGet rcp liftIO $ rfId1 `shouldBe` rfId1' @@ -640,7 +640,7 @@ testXFTPAgentExpiredOnServer fsType = withGlobalLogging logCfgNoLogs $ -- receive file 1 again - should fail with AUTH error runRight $ do - rfId <- xftpReceiveFile rcp 1 rfd1_2 Nothing True + rfId <- A.xftpReceiveFile (client rcp) 1 rfd1_2 Nothing True ("", rfId', RFERR (XFTP "xftp://LcJUMfVhwD8yxjAiSaDzzGF3-kLG4Uh0Fl_ZIjrRwjI=@localhost:8000" AUTH)) <- rfGet rcp liftIO $ rfId' `shouldBe` rfId @@ -662,8 +662,8 @@ testXFTPAgentRequestAdditionalRecipientIDs = withXFTPServer $ do -- send file rfds <- withAgent 1 agentCfg initAgentServers testDB $ \sndr -> runRight $ do - xftpStartWorkers sndr (Just senderFiles) - sfId <- xftpSendFile sndr 1 (CF.plain filePath) 500 + A.xftpStartWorkers (client sndr) (Just senderFiles) + sfId <- A.xftpSendFile (client sndr) 1 (CF.plain filePath) 500 sfProgress sndr $ mb 18 ("", sfId', SFDONE _sndDescr rfds) <- sfGet sndr liftIO $ do @@ -685,4 +685,4 @@ testXFTPServerTest_ :: HasCallStack => XFTPServerWithAuth -> IO (Maybe ProtocolT testXFTPServerTest_ srv = -- initially passed server is not running withAgent 1 agentCfg initAgentServers testDB $ \a -> - testProtocolServer a NRMInteractive 1 srv + A.testProtocolServer (client a) NRMInteractive 1 srv diff --git a/tests/XFTPWebTests.hs b/tests/XFTPWebTests.hs index c9a98eef1..309d610ff 100644 --- a/tests/XFTPWebTests.hs +++ b/tests/XFTPWebTests.hs @@ -47,8 +47,8 @@ import Util import Simplex.FileTransfer.Server.Env (XFTPServerConfig) import Simplex.FileTransfer.Server.Store (STMFileStore) import XFTPClient (testXFTPServerConfigEd25519SNI, testXFTPServerConfigSNI, withXFTPServerCfg, xftpTestPort) -import AgentTests.FunctionalAPITests (rfGet, runRight, runRight_, sfGet, withAgent) -import Simplex.Messaging.Agent (AgentClient, xftpReceiveFile, xftpSendFile, xftpStartWorkers) +import AgentTests.FunctionalAPITests (AgentClient (..), rfGet, runRight, runRight_, sfGet, withAgent) +import qualified Simplex.Messaging.Agent as A import Simplex.Messaging.Agent.Protocol (AEvent (..)) import SMPAgentClient (agentCfg, initAgentServers, testDB) import XFTPCLI (recipientFiles, senderFiles, testBracket) @@ -3126,8 +3126,8 @@ tsUploadHaskellDownloadTest cfg caFile = do <> jsOut2 "Buffer.from(yaml)" "Buffer.from(originalData)" let vfd :: ValidFileDescription 'FRecipient = either error id $ strDecode yamlDesc withAgent 1 agentCfg initAgentServers testDB $ \rcp -> do - runRight_ $ xftpStartWorkers rcp (Just recipientFiles) - _ <- runRight $ xftpReceiveFile rcp 1 vfd Nothing True + runRight_ $ A.xftpStartWorkers (client rcp) (Just recipientFiles) + _ <- runRight $ A.xftpReceiveFile (client rcp) 1 vfd Nothing True rfProgress rcp 50000 (_, _, RFDONE outPath) <- rfGet rcp downloadedData <- B.readFile outPath @@ -3162,8 +3162,8 @@ tsUploadRedirectHaskellDownloadTest cfg caFile = do let vfd@(ValidFileDescription fd) :: ValidFileDescription 'FRecipient = either error id $ strDecode yamlDesc redirect fd `shouldSatisfy` (/= Nothing) withAgent 1 agentCfg initAgentServers testDB $ \rcp -> do - runRight_ $ xftpStartWorkers rcp (Just recipientFiles) - _ <- runRight $ xftpReceiveFile rcp 1 vfd Nothing True + runRight_ $ A.xftpStartWorkers (client rcp) (Just recipientFiles) + _ <- runRight $ A.xftpReceiveFile (client rcp) 1 vfd Nothing True outPath <- waitRfDone rcp downloadedData <- B.readFile outPath downloadedData `shouldBe` originalData @@ -3177,8 +3177,8 @@ haskellUploadTsDownloadTest cfg = do B.writeFile filePath originalData withXFTPServerCfg cfg $ \_ -> do vfd <- withAgent 1 agentCfg initAgentServers testDB $ \sndr -> do - runRight_ $ xftpStartWorkers sndr (Just senderFiles) - _ <- runRight $ xftpSendFile sndr 1 (CF.plain filePath) 1 + runRight_ $ A.xftpStartWorkers (client sndr) (Just senderFiles) + _ <- runRight $ A.xftpSendFile (client sndr) 1 (CF.plain filePath) 1 sfProgress sndr 50000 (_, _, SFDONE _ [rfd]) <- sfGet sndr pure rfd