@@ -50,6 +50,7 @@ module Simplex.Messaging.Agent
5050 deleteUser ,
5151 setUserService ,
5252 connRequestPQSupport ,
53+ prepareConnectionToCreate ,
5354 createConnectionAsync ,
5455 setConnShortLinkAsync ,
5556 getConnShortLinkAsync ,
@@ -362,8 +363,14 @@ setUserService c = withAgentEnv c .: setUserService' c
362363{-# INLINE setUserService #-}
363364
364365-- | Create SMP agent connection (NEW command) asynchronously, synchronous response is new connection id
365- createConnectionAsync :: ConnectionModeI c => AgentClient -> UserId -> ACorrId -> Bool -> SConnectionMode c -> CR. InitialKeys -> SubscriptionMode -> AE ConnId
366- createConnectionAsync c userId aCorrId enableNtfs = withAgentEnv c .:. newConnAsync c userId aCorrId enableNtfs
366+ -- | Create SMP agent connection without queue (to be used with createConnectionAsync).
367+ prepareConnectionToCreate :: ConnectionModeI c => AgentClient -> UserId -> Bool -> SConnectionMode c -> PQSupport -> AE ConnId
368+ prepareConnectionToCreate c userId enableNtfs cMode pqSup = withAgentEnv c $ newConnNoQueues c userId enableNtfs cMode pqSup
369+ {-# INLINE prepareConnectionToCreate #-}
370+
371+ -- | Enqueue NEW command for a prepared connection.
372+ createConnectionAsync :: ConnectionModeI c => AgentClient -> ACorrId -> ConnId -> Bool -> SConnectionMode c -> CR. InitialKeys -> SubscriptionMode -> AE ()
373+ createConnectionAsync c aCorrId connId enableNtfs = withAgentEnv c .:. newConnAsync c aCorrId connId enableNtfs
367374{-# INLINE createConnectionAsync #-}
368375
369376-- | Create or update user's contact connection short link (LSET command) asynchronously, no synchronous response
@@ -376,20 +383,21 @@ getConnShortLinkAsync :: AgentClient -> UserId -> ACorrId -> Maybe ConnId -> Con
376383getConnShortLinkAsync c = withAgentEnv c .:: getConnShortLinkAsync' c
377384{-# INLINE getConnShortLinkAsync #-}
378385
379- -- | Join SMP agent connection ( JOIN command) asynchronously, synchronous response is new connection id .
380- -- If connId is provided (for contact URIs), it updates the existing connection record created by getConnShortLinkAsync.
381- joinConnectionAsync :: AgentClient -> UserId -> ACorrId -> Maybe ConnId -> Bool -> ConnectionRequestUri c -> ConnInfo -> PQSupport -> SubscriptionMode -> AE ConnId
382- joinConnectionAsync c userId aCorrId connId_ enableNtfs = withAgentEnv c .:: joinConnAsync c userId aCorrId connId_ enableNtfs
386+ -- | Enqueue JOIN command for a prepared connection.
387+ joinConnectionAsync :: ConnectionModeI c => AgentClient -> ACorrId -> Bool -> ConnId -> Bool -> ConnectionRequestUri c -> ConnInfo -> PQSupport -> SubscriptionMode -> AE ()
388+ joinConnectionAsync c aCorrId updateConn connId enableNtfs cReqUri cInfo pqSup subMode =
389+ withAgentEnv c $ joinConnAsync c aCorrId updateConn connId enableNtfs cReqUri cInfo pqSup subMode
383390{-# INLINE joinConnectionAsync #-}
384391
385392-- | Allow connection to continue after CONF notification (LET command), no synchronous response
386393allowConnectionAsync :: AgentClient -> ACorrId -> ConnId -> ConfirmationId -> ConnInfo -> AE ()
387394allowConnectionAsync c = withAgentEnv c .:: allowConnectionAsync' c
388395{-# INLINE allowConnectionAsync #-}
389396
390- -- | Accept contact after REQ notification (ACPT command) asynchronously, synchronous response is new connection id
391- acceptContactAsync :: AgentClient -> UserId -> ACorrId -> Bool -> ConfirmationId -> ConnInfo -> PQSupport -> SubscriptionMode -> AE ConnId
392- acceptContactAsync c userId aCorrId enableNtfs = withAgentEnv c .:: acceptContactAsync' c userId aCorrId enableNtfs
397+ -- | Accept contact after REQ notification (ACPT command) asynchronously, for a prepared connection.
398+ acceptContactAsync :: AgentClient -> ACorrId -> ConnId -> Bool -> ConfirmationId -> ConnInfo -> PQSupport -> SubscriptionMode -> AE ()
399+ acceptContactAsync c aCorrId connId enableNtfs invId ownConnInfo pqSupport subMode =
400+ withAgentEnv c $ acceptContactAsync' c aCorrId connId enableNtfs invId ownConnInfo pqSupport subMode
393401{-# INLINE acceptContactAsync #-}
394402
395403-- | Acknowledge message (ACK command) asynchronously, no synchronous response
@@ -842,11 +850,10 @@ setUserService' c userId enable = do
842850 unless ok $ throwE $ CMD PROHIBITED " setUserService"
843851 when (changed && not enable) $ withStore' c (`deleteClientServices` userId)
844852
845- newConnAsync :: ConnectionModeI c => AgentClient -> UserId -> ACorrId -> Bool -> SConnectionMode c -> CR. InitialKeys -> SubscriptionMode -> AM ConnId
846- newConnAsync c userId corrId enableNtfs cMode pqInitKeys subMode = do
847- connId <- newConnNoQueues c userId enableNtfs cMode (CR. connPQEncryption pqInitKeys)
853+ newConnAsync :: ConnectionModeI c => AgentClient -> ACorrId -> ConnId -> Bool -> SConnectionMode c -> CR. InitialKeys -> SubscriptionMode -> AM ()
854+ newConnAsync c corrId connId enableNtfs cMode pqInitKeys subMode =
848855 enqueueCommand c corrId connId Nothing $ AClientCommand $ NEW enableNtfs (ACM cMode) pqInitKeys subMode
849- pure connId
856+ {-# INLINE newConnAsync #-}
850857
851858newConnNoQueues :: AgentClient -> UserId -> Bool -> SConnectionMode c -> PQSupport -> AM ConnId
852859newConnNoQueues c userId enableNtfs cMode pqSupport = do
@@ -855,36 +862,20 @@ newConnNoQueues c userId enableNtfs cMode pqSupport = do
855862 let cData = ConnData {userId, connId = " " , connAgentVersion, enableNtfs, lastExternalSndId = 0 , deleted = False , ratchetSyncState = RSOk , pqSupport}
856863 withStore c $ \ db -> createNewConn db g cData cMode
857864
858- -- TODO [short links] TBC, but probably we will need async join for contact addresses as the contact will be created after user confirming the connection,
859- -- and join should retry, the same as 1-time invitation joins.
860- joinConnAsync :: AgentClient -> UserId -> ACorrId -> Maybe ConnId -> Bool -> ConnectionRequestUri c -> ConnInfo -> PQSupport -> SubscriptionMode -> AM ConnId
861- joinConnAsync c userId corrId connId_ enableNtfs cReqUri@ CRInvitationUri {} cInfo pqSup subMode = do
862- when (isJust connId_) $ throwE $ CMD PROHIBITED " joinConnAsync: connId not allowed for invitation URI"
863- withInvLock c (strEncode cReqUri) " joinConnAsync" $ do
864- lift (compatibleInvitationUri cReqUri) >>= \ case
865- Just (_, Compatible (CR. E2ERatchetParams v _ _ _), Compatible connAgentVersion) -> do
866- g <- asks random
867- let pqSupport = pqSup `CR.pqSupportAnd` versionPQSupport_ connAgentVersion (Just v)
868- cData = ConnData {userId, connId = " " , connAgentVersion, enableNtfs, lastExternalSndId = 0 , deleted = False , ratchetSyncState = RSOk , pqSupport}
869- connId <- withStore c $ \ db -> createNewConn db g cData SCMInvitation
870- enqueueCommand c corrId connId Nothing $ AClientCommand $ JOIN enableNtfs (ACR sConnectionMode cReqUri) pqSupport subMode cInfo
871- pure connId
872- Nothing -> throwE $ AGENT A_VERSION
873- joinConnAsync c userId corrId connId_ enableNtfs cReqUri@ (CRContactUri _) cInfo pqSup subMode = do
865+ joinConnAsync :: ConnectionModeI c => AgentClient -> ACorrId -> Bool -> ConnId -> Bool -> ConnectionRequestUri c -> ConnInfo -> PQSupport -> SubscriptionMode -> AM ()
866+ joinConnAsync c corrId updateConn connId enableNtfs cReqUri@ CRInvitationUri {} cInfo pqSup subMode =
867+ lift (compatibleInvitationUri cReqUri) >>= \ case
868+ Just (_, Compatible (CR. E2ERatchetParams v _ _ _), Compatible connAgentVersion) -> do
869+ let pqSupport = pqSup `CR.pqSupportAnd` versionPQSupport_ connAgentVersion (Just v)
870+ when updateConn $ withStore' c $ \ db -> updateNewConnJoin db connId connAgentVersion pqSupport enableNtfs
871+ enqueueCommand c corrId connId Nothing $ AClientCommand $ JOIN enableNtfs (ACR sConnectionMode cReqUri) pqSupport subMode cInfo
872+ Nothing -> throwE $ AGENT A_VERSION
873+ joinConnAsync c corrId updateConn connId enableNtfs cReqUri@ (CRContactUri _) cInfo pqSup subMode =
874874 lift (compatibleContactUri cReqUri) >>= \ case
875875 Just (_, Compatible connAgentVersion) -> do
876876 let pqSupport = pqSup `CR.pqSupportAnd` versionPQSupport_ connAgentVersion Nothing
877- connId <- case connId_ of
878- Just cId -> do
879- -- update connection record created by getConnShortLinkAsync
880- withStore' c $ \ db -> updateNewConnJoin db cId connAgentVersion pqSupport enableNtfs
881- pure cId
882- Nothing -> do
883- g <- asks random
884- let cData = ConnData {userId, connId = " " , connAgentVersion, enableNtfs, lastExternalSndId = 0 , deleted = False , ratchetSyncState = RSOk , pqSupport}
885- withStore c $ \ db -> createNewConn db g cData SCMInvitation
877+ when updateConn $ withStore' c $ \ db -> updateNewConnJoin db connId connAgentVersion pqSupport enableNtfs
886878 enqueueCommand c corrId connId Nothing $ AClientCommand $ JOIN enableNtfs (ACR sConnectionMode cReqUri) pqSupport subMode cInfo
887- pure connId
888879 Nothing -> throwE $ AGENT A_VERSION
889880
890881allowConnectionAsync' :: AgentClient -> ACorrId -> ConnId -> ConfirmationId -> ConnInfo -> AM ()
@@ -900,11 +891,11 @@ allowConnectionAsync' c corrId connId confId ownConnInfo =
900891-- and also it can't be triggered by user concurrently several times in a row. It could be improved similarly to
901892-- `acceptContact` by creating a new map for invitation locks and taking lock here, and removing `unacceptInvitation`
902893-- while marking invitation as accepted inside "lock level transaction" after successful `joinConnAsync`.
903- acceptContactAsync' :: AgentClient -> UserId -> ACorrId -> Bool -> InvitationId -> ConnInfo -> PQSupport -> SubscriptionMode -> AM ConnId
904- acceptContactAsync' c userId corrId enableNtfs invId ownConnInfo pqSupport subMode = do
894+ acceptContactAsync' :: AgentClient -> ACorrId -> ConnId -> Bool -> InvitationId -> ConnInfo -> PQSupport -> SubscriptionMode -> AM ()
895+ acceptContactAsync' c corrId connId enableNtfs invId ownConnInfo pqSupport subMode = do
905896 Invitation {connReq} <- withStore c $ \ db -> getInvitation db " acceptContactAsync'" invId
906897 withStore' c $ \ db -> acceptInvitation db invId ownConnInfo
907- joinConnAsync c userId corrId Nothing enableNtfs connReq ownConnInfo pqSupport subMode `catchAllErrors` \ err -> do
898+ joinConnAsync c corrId False connId enableNtfs connReq ownConnInfo pqSupport subMode `catchAllErrors` \ err -> do
908899 withStore' c (`unacceptInvitation` invId)
909900 throwE err
910901
0 commit comments