mirror of
https://github.com/simplex-chat/simplexmq.git
synced 2026-05-24 10:15:21 +00:00
make sending confirmation asynchronous (#327)
* make sending confirmation asynchronous * confirm first queue synchronously (on JOIN, and delete connection on failure), second queue asynchronously (from REPLY msg) * test to retry JOIN when the first attempt fails * process confirmation delivery errors
This commit is contained in:
committed by
GitHub
parent
7a611bed5a
commit
7a19ab224b
@@ -234,16 +234,20 @@ joinConn c connId (CRInvitationUri (ConnReqUriData _ agentVRange (qUri :| _)) e2
|
||||
(pk1, pk2, e2eSndParams) <- liftIO . CR.generateE2EParams $ version e2eRcvParams
|
||||
(_, rcDHRs) <- liftIO C.generateKeyPair'
|
||||
let rc = CR.initSndRatchet rcDHRr rcDHRs $ CR.x3dhSnd pk1 pk2 e2eRcvParams
|
||||
(sq, smpConf) <- newSndQueue qInfo cInfo
|
||||
sq <- newSndQueue qInfo
|
||||
g <- asks idsDrg
|
||||
let cData = ConnData {connId}
|
||||
connId' <- withStore $ \st -> do
|
||||
connId' <- createSndConn st g cData sq
|
||||
createRatchet st connId' rc
|
||||
pure connId'
|
||||
confirmQueue c connId' sq smpConf $ Just e2eSndParams
|
||||
void $ enqueueMessage c connId' sq HELLO
|
||||
pure connId'
|
||||
tryError (confirmQueue c connId' sq cInfo $ Just e2eSndParams) >>= \case
|
||||
Right _ -> do
|
||||
void $ enqueueMessage c connId' sq HELLO
|
||||
pure connId'
|
||||
Left e -> do
|
||||
withStore (`deleteConn` connId')
|
||||
throwError e
|
||||
_ -> throwError $ AGENT A_VERSION
|
||||
joinConn c connId (CRContactUri (ConnReqUriData _ agentVRange (qUri :| _))) cInfo =
|
||||
case ( qUri `compatibleVersion` SMP.smpClientVRange,
|
||||
@@ -337,12 +341,12 @@ enqueueMessage c connId sq aMessage = do
|
||||
internalTs <- liftIO getCurrentTime
|
||||
(internalId, internalSndId, prevMsgHash) <- withStore (`updateSndIds` connId)
|
||||
let privHeader = APrivHeader (unSndId internalSndId) prevMsgHash
|
||||
agentMessage = smpEncode $ AgentMessage privHeader aMessage
|
||||
internalHash = C.sha256Hash agentMessage
|
||||
|
||||
encAgentMessage <- agentRatchetEncrypt connId agentMessage e2eEncUserMsgLength
|
||||
agentMsg = AgentMessage privHeader aMessage
|
||||
agentMsgStr = smpEncode agentMsg
|
||||
internalHash = C.sha256Hash agentMsgStr
|
||||
encAgentMessage <- agentRatchetEncrypt connId agentMsgStr e2eEncUserMsgLength
|
||||
let msgBody = smpEncode $ AgentMsgEnvelope {agentVersion = smpAgentVersion, encAgentMessage}
|
||||
msgType = aMessageType aMessage
|
||||
msgType = agentMessageType agentMsg
|
||||
msgData = SndMsgData {internalId, internalSndId, internalTs, msgType, msgBody, internalHash, prevMsgHash}
|
||||
withStore $ \st -> createSndMsg st connId msgData
|
||||
pure internalId
|
||||
@@ -392,30 +396,38 @@ runSmpQueueMsgDelivery c@AgentClient {subQ} connId sq = do
|
||||
notify $ MERR mId (INTERNAL $ show e)
|
||||
Right (rq_, (msgType, msgBody, internalTs)) ->
|
||||
withRetryInterval ri $ \loop ->
|
||||
tryError (sendAgentMessage c sq msgBody) >>= \case
|
||||
tryError (send msgType c sq msgBody) >>= \case
|
||||
Left e -> do
|
||||
let err = if msgType == AM_CONN_INFO then ERR e else MERR mId e
|
||||
case e of
|
||||
SMP SMP.QUOTA -> loop
|
||||
SMP SMP.QUOTA -> case msgType of
|
||||
AM_CONN_INFO -> connError msgId NOT_AVAILABLE
|
||||
_ -> loop
|
||||
SMP SMP.AUTH -> case msgType of
|
||||
HELLO_ -> do
|
||||
AM_CONN_INFO -> connError msgId NOT_AVAILABLE
|
||||
AM_HELLO_ -> do
|
||||
helloTimeout <- asks $ helloTimeout . config
|
||||
currentTime <- liftIO getCurrentTime
|
||||
if diffUTCTime currentTime internalTs > helloTimeout
|
||||
then case rq_ of
|
||||
-- party initiating connection
|
||||
Just _ -> notifyDel msgId . ERR $ CONN NOT_AVAILABLE
|
||||
Just _ -> connError msgId NOT_AVAILABLE
|
||||
-- party joining connection
|
||||
_ -> notifyDel msgId . ERR $ CONN NOT_ACCEPTED
|
||||
_ -> connError msgId NOT_ACCEPTED
|
||||
else loop
|
||||
REPLY_ -> notifyDel msgId $ ERR e
|
||||
A_MSG_ -> notifyDel msgId $ MERR mId e
|
||||
SMP (SMP.CMD _) -> notifyDel msgId $ MERR mId e
|
||||
SMP SMP.LARGE_MSG -> notifyDel msgId $ MERR mId e
|
||||
SMP {} -> notify (MERR mId e) >> loop
|
||||
AM_REPLY_ -> notifyDel msgId $ ERR e
|
||||
AM_A_MSG_ -> notifyDel msgId $ MERR mId e
|
||||
SMP (SMP.CMD _) -> notifyDel msgId err
|
||||
SMP SMP.LARGE_MSG -> notifyDel msgId err
|
||||
SMP {} -> notify err >> loop
|
||||
_ -> loop
|
||||
Right () -> do
|
||||
case msgType of
|
||||
HELLO_ -> do
|
||||
AM_CONN_INFO -> do
|
||||
withStore $ \st -> setSndQueueStatus st sq Confirmed
|
||||
when (isJust rq_) $ withStore (`removeConfirmations` connId)
|
||||
void $ enqueueMessage c connId sq HELLO
|
||||
AM_HELLO_ -> do
|
||||
withStore $ \st -> setSndQueueStatus st sq Active
|
||||
case rq_ of
|
||||
-- party initiating connection
|
||||
@@ -424,16 +436,20 @@ runSmpQueueMsgDelivery c@AgentClient {subQ} connId sq = do
|
||||
notify CON
|
||||
-- party joining connection
|
||||
_ -> createReplyQueue c connId sq
|
||||
A_MSG_ -> notify $ SENT mId
|
||||
AM_A_MSG_ -> notify $ SENT mId
|
||||
_ -> pure ()
|
||||
delMsg msgId
|
||||
where
|
||||
send = \case
|
||||
AM_CONN_INFO -> sendConfirmation
|
||||
_ -> sendAgentMessage
|
||||
delMsg :: InternalId -> m ()
|
||||
delMsg msgId = withStore $ \st -> deleteMsg st connId msgId
|
||||
notify :: ACommand 'Agent -> m ()
|
||||
notify cmd = atomically $ writeTBQueue subQ ("", connId, cmd)
|
||||
notifyDel :: InternalId -> ACommand 'Agent -> m ()
|
||||
notifyDel msgId cmd = notify cmd >> delMsg msgId
|
||||
connError msgId = notifyDel msgId . ERR . CONN
|
||||
|
||||
ackMessage' :: forall m. AgentMonad m => AgentClient -> ConnId -> AgentMsgId -> m ()
|
||||
ackMessage' c connId msgId = do
|
||||
@@ -519,8 +535,9 @@ processSMPTransmission c@AgentClient {subQ} (srv, rId, cmd) = do
|
||||
(SMP.PHEmpty, AgentMsgEnvelope _ encAgentMsg) -> do
|
||||
agentMsgBody <- agentRatchetDecrypt connId encAgentMsg
|
||||
parseMessage agentMsgBody >>= \case
|
||||
AgentMessage APrivHeader {sndMsgId, prevMsgHash} aMessage -> do
|
||||
(msgId, msgMeta) <- agentClientMsg prevMsgHash sndMsgId (srvMsgId, systemToUTCTime srvTs) agentMsgBody aMessage
|
||||
agentMsg@(AgentMessage APrivHeader {sndMsgId, prevMsgHash} aMessage) -> do
|
||||
let msgType = agentMessageType agentMsg
|
||||
(msgId, msgMeta) <- agentClientMsg prevMsgHash sndMsgId (srvMsgId, systemToUTCTime srvTs) agentMsgBody msgType
|
||||
case aMessage of
|
||||
HELLO -> helloMsg >> ack >> withStore (\st -> deleteMsg st connId msgId)
|
||||
REPLY cReq -> replyMsg cReq >> ack >> withStore (\st -> deleteMsg st connId msgId)
|
||||
@@ -610,15 +627,13 @@ processSMPTransmission c@AgentClient {subQ} (srv, rId, cmd) = do
|
||||
case qInfo `proveCompatible` SMP.smpClientVRange of
|
||||
Nothing -> notify . ERR $ AGENT A_VERSION
|
||||
Just qInfo' -> do
|
||||
(sq, smpConf) <- newSndQueue qInfo' ownConnInfo
|
||||
sq <- newSndQueue qInfo'
|
||||
withStore $ \st -> upgradeRcvConnToDuplex st connId sq
|
||||
confirmQueue c connId sq smpConf Nothing
|
||||
withStore (`removeConfirmations` connId)
|
||||
void $ enqueueMessage c connId sq HELLO
|
||||
enqueueConfirmation c connId sq ownConnInfo Nothing
|
||||
_ -> prohibited
|
||||
|
||||
agentClientMsg :: PrevRcvMsgHash -> ExternalSndId -> (BrokerId, BrokerTs) -> MsgBody -> AMessage -> m (InternalId, MsgMeta)
|
||||
agentClientMsg externalPrevSndHash sndMsgId broker msgBody aMessage = do
|
||||
agentClientMsg :: PrevRcvMsgHash -> ExternalSndId -> (BrokerId, BrokerTs) -> MsgBody -> AgentMessageType -> m (InternalId, MsgMeta)
|
||||
agentClientMsg externalPrevSndHash sndMsgId broker msgBody msgType = do
|
||||
logServer "<--" c srv rId "MSG <MSG>"
|
||||
let internalHash = C.sha256Hash msgBody
|
||||
internalTs <- liftIO getCurrentTime
|
||||
@@ -626,7 +641,6 @@ processSMPTransmission c@AgentClient {subQ} (srv, rId, cmd) = do
|
||||
let integrity = checkMsgIntegrity prevExtSndId sndMsgId prevRcvMsgHash externalPrevSndHash
|
||||
recipient = (unId internalId, internalTs)
|
||||
msgMeta = MsgMeta {integrity, recipient, broker, sndMsgId}
|
||||
msgType = aMessageType aMessage
|
||||
rcvMsg = RcvMsgData {msgMeta, msgType, msgBody, internalRcvId, internalHash, externalPrevSndHash}
|
||||
withStore $ \st -> createRcvMsg st connId rcvMsg
|
||||
pure (internalId, msgMeta)
|
||||
@@ -651,8 +665,9 @@ processSMPTransmission c@AgentClient {subQ} (srv, rId, cmd) = do
|
||||
| internalPrevMsgHash /= receivedPrevMsgHash = MsgError MsgBadHash
|
||||
| otherwise = MsgError MsgDuplicate -- this case is not possible
|
||||
|
||||
confirmQueue :: forall m. AgentMonad m => AgentClient -> ConnId -> SndQueue -> SMPConfirmation -> Maybe (CR.E2ERatchetParams 'C.X448) -> m ()
|
||||
confirmQueue c connId sq SMPConfirmation {senderKey, e2ePubKey, connInfo} e2eEncryption = do
|
||||
confirmQueue :: forall m. AgentMonad m => AgentClient -> ConnId -> SndQueue -> ConnInfo -> Maybe (CR.E2ERatchetParams 'C.X448) -> m ()
|
||||
confirmQueue c connId sq connInfo e2eEncryption = do
|
||||
_ <- withStore (`updateSndIds` connId)
|
||||
msg <- mkConfirmation
|
||||
sendConfirmation c sq msg
|
||||
withStore $ \st -> setSndQueueStatus st sq Confirmed
|
||||
@@ -660,9 +675,27 @@ confirmQueue c connId sq SMPConfirmation {senderKey, e2ePubKey, connInfo} e2eEnc
|
||||
mkConfirmation :: m MsgBody
|
||||
mkConfirmation = do
|
||||
encConnInfo <- agentRatchetEncrypt connId (smpEncode $ AgentConnInfo connInfo) e2eEncConnInfoLength
|
||||
let agentEnvelope = AgentConfirmation {agentVersion = smpAgentVersion, e2eEncryption, encConnInfo}
|
||||
agentCbEncrypt sq (Just e2ePubKey) . smpEncode $
|
||||
SMP.ClientMessage (SMP.PHConfirmation senderKey) $ smpEncode agentEnvelope
|
||||
pure . smpEncode $ AgentConfirmation {agentVersion = smpAgentVersion, e2eEncryption, encConnInfo}
|
||||
|
||||
enqueueConfirmation :: forall m. AgentMonad m => AgentClient -> ConnId -> SndQueue -> ConnInfo -> Maybe (CR.E2ERatchetParams 'C.X448) -> m ()
|
||||
enqueueConfirmation c connId sq connInfo e2eEncryption = do
|
||||
resumeMsgDelivery c connId sq
|
||||
msgId <- storeConfirmation
|
||||
queuePendingMsgs c connId sq [msgId]
|
||||
where
|
||||
storeConfirmation :: m InternalId
|
||||
storeConfirmation = do
|
||||
internalTs <- liftIO getCurrentTime
|
||||
(internalId, internalSndId, prevMsgHash) <- withStore (`updateSndIds` connId)
|
||||
let agentMsg = AgentConnInfo connInfo
|
||||
agentMsgStr = smpEncode agentMsg
|
||||
internalHash = C.sha256Hash agentMsgStr
|
||||
encConnInfo <- agentRatchetEncrypt connId agentMsgStr e2eEncConnInfoLength
|
||||
let msgBody = smpEncode $ AgentConfirmation {agentVersion = smpAgentVersion, e2eEncryption, encConnInfo}
|
||||
msgType = agentMessageType agentMsg
|
||||
msgData = SndMsgData {internalId, internalSndId, internalTs, msgType, msgBody, internalHash, prevMsgHash}
|
||||
withStore $ \st -> createSndMsg st connId msgData
|
||||
pure internalId
|
||||
|
||||
-- encoded AgentMessage -> encoded EncAgentMessage
|
||||
agentRatchetEncrypt :: AgentMonad m => ConnId -> ByteString -> Int -> m ByteString
|
||||
@@ -684,27 +717,27 @@ agentRatchetDecrypt connId encAgentMsg = do
|
||||
notifyConnected :: AgentMonad m => AgentClient -> ConnId -> m ()
|
||||
notifyConnected c connId = atomically $ writeTBQueue (subQ c) ("", connId, CON)
|
||||
|
||||
newSndQueue :: (MonadUnliftIO m, MonadReader Env m) => Compatible SMPQueueInfo -> ConnInfo -> m (SndQueue, SMPConfirmation)
|
||||
newSndQueue qInfo cInfo =
|
||||
newSndQueue :: (MonadUnliftIO m, MonadReader Env m) => Compatible SMPQueueInfo -> m SndQueue
|
||||
newSndQueue qInfo =
|
||||
asks (cmdSignAlg . config) >>= \case
|
||||
C.SignAlg a -> newSndQueue_ a qInfo cInfo
|
||||
C.SignAlg a -> newSndQueue_ a qInfo
|
||||
|
||||
newSndQueue_ ::
|
||||
(C.SignatureAlgorithm a, C.AlgorithmI a, MonadUnliftIO m) =>
|
||||
C.SAlgorithm a ->
|
||||
Compatible SMPQueueInfo ->
|
||||
ConnInfo ->
|
||||
m (SndQueue, SMPConfirmation)
|
||||
newSndQueue_ a (Compatible (SMPQueueInfo _clientVersion smpServer senderId rcvE2ePubDhKey)) cInfo = do
|
||||
m SndQueue
|
||||
newSndQueue_ a (Compatible (SMPQueueInfo _clientVersion smpServer senderId rcvE2ePubDhKey)) = do
|
||||
-- this function assumes clientVersion is compatible - it was tested before
|
||||
(senderKey, sndPrivateKey) <- liftIO $ C.generateSignatureKeyPair a
|
||||
(sndPublicKey, sndPrivateKey) <- liftIO $ C.generateSignatureKeyPair a
|
||||
(e2ePubKey, e2ePrivKey) <- liftIO C.generateKeyPair'
|
||||
let sndQueue =
|
||||
SndQueue
|
||||
{ server = smpServer,
|
||||
sndId = senderId,
|
||||
sndPrivateKey,
|
||||
e2eDhSecret = C.dh' rcvE2ePubDhKey e2ePrivKey,
|
||||
status = New
|
||||
}
|
||||
pure (sndQueue, SMPConfirmation senderKey e2ePubKey cInfo)
|
||||
pure
|
||||
SndQueue
|
||||
{ server = smpServer,
|
||||
sndId = senderId,
|
||||
sndPublicKey = Just sndPublicKey,
|
||||
sndPrivateKey,
|
||||
e2eDhSecret = C.dh' rcvE2ePubDhKey e2ePrivKey,
|
||||
e2ePubKey = Just e2ePubKey,
|
||||
status = New
|
||||
}
|
||||
|
||||
@@ -381,11 +381,13 @@ showServer SMPServer {host, port} =
|
||||
logSecret :: ByteString -> ByteString
|
||||
logSecret bs = encode $ B.take 3 bs
|
||||
|
||||
-- TODO maybe package E2ERatchetParams into SMPConfirmation
|
||||
sendConfirmation :: forall m. AgentMonad m => AgentClient -> SndQueue -> ByteString -> m ()
|
||||
sendConfirmation c SndQueue {server, sndId} encConfirmation =
|
||||
withLogSMP_ c server sndId "SEND <CONF>" $ \smp ->
|
||||
liftSMP $ sendSMPMessage smp Nothing sndId encConfirmation
|
||||
sendConfirmation c sq@SndQueue {server, sndId, sndPublicKey = Just sndPublicKey, e2ePubKey = e2ePubKey@Just {}} agentConfirmation =
|
||||
withLogSMP_ c server sndId "SEND <CONF>" $ \smp -> do
|
||||
let clientMsg = SMP.ClientMessage (SMP.PHConfirmation sndPublicKey) agentConfirmation
|
||||
msg <- agentCbEncrypt sq e2ePubKey $ smpEncode clientMsg
|
||||
liftSMP $ sendSMPMessage smp Nothing sndId msg
|
||||
sendConfirmation _ _ _ = throwError $ INTERNAL "sendConfirmation called without snd_queue public key(s) in the database"
|
||||
|
||||
sendInvitation :: forall m. AgentMonad m => AgentClient -> Compatible SMPQueueInfo -> ConnectionRequestUri 'CMInvitation -> ConnInfo -> m ()
|
||||
sendInvitation c (Compatible SMPQueueInfo {smpServer, senderId, dhPublicKey}) connReq connInfo =
|
||||
|
||||
@@ -46,9 +46,9 @@ module Simplex.Messaging.Agent.Protocol
|
||||
SMPConfirmation (..),
|
||||
AgentMsgEnvelope (..),
|
||||
AgentMessage (..),
|
||||
AgentMessageType (..),
|
||||
APrivHeader (..),
|
||||
AMessage (..),
|
||||
AMsgType (..),
|
||||
SMPServer (..),
|
||||
SrvLoc (..),
|
||||
SMPQueueUri (..),
|
||||
@@ -89,7 +89,7 @@ module Simplex.Messaging.Agent.Protocol
|
||||
connModeT,
|
||||
serializeQueueStatus,
|
||||
queueStatusT,
|
||||
aMessageType,
|
||||
agentMessageType,
|
||||
|
||||
-- * TCP transport functions
|
||||
tPut,
|
||||
@@ -343,6 +343,31 @@ instance Encoding AgentMessage where
|
||||
'M' -> AgentMessage <$> smpP <*> smpP
|
||||
_ -> fail "bad AgentMessage"
|
||||
|
||||
data AgentMessageType = AM_CONN_INFO | AM_HELLO_ | AM_REPLY_ | AM_A_MSG_
|
||||
deriving (Eq, Show)
|
||||
|
||||
instance Encoding AgentMessageType where
|
||||
smpEncode = \case
|
||||
AM_CONN_INFO -> "C"
|
||||
AM_HELLO_ -> "H"
|
||||
AM_REPLY_ -> "R"
|
||||
AM_A_MSG_ -> "M"
|
||||
smpP =
|
||||
A.anyChar >>= \case
|
||||
'C' -> pure AM_CONN_INFO
|
||||
'H' -> pure AM_HELLO_
|
||||
'R' -> pure AM_REPLY_
|
||||
'M' -> pure AM_A_MSG_
|
||||
_ -> fail "bad AgentMessageType"
|
||||
|
||||
agentMessageType :: AgentMessage -> AgentMessageType
|
||||
agentMessageType = \case
|
||||
AgentConnInfo _ -> AM_CONN_INFO
|
||||
AgentMessage _ aMsg -> case aMsg of
|
||||
HELLO -> AM_HELLO_
|
||||
REPLY _ -> AM_REPLY_
|
||||
A_MSG _ -> AM_A_MSG_
|
||||
|
||||
data APrivHeader = APrivHeader
|
||||
{ -- | sequential ID assigned by the sending agent
|
||||
sndMsgId :: AgentMsgId,
|
||||
@@ -371,12 +396,6 @@ instance Encoding AMsgType where
|
||||
'M' -> pure A_MSG_
|
||||
_ -> fail "bad AMsgType"
|
||||
|
||||
aMessageType :: AMessage -> AMsgType
|
||||
aMessageType = \case
|
||||
HELLO -> HELLO_
|
||||
REPLY _ -> REPLY_
|
||||
A_MSG _ -> A_MSG_
|
||||
|
||||
-- | Messages sent between SMP agents once SMP queue is secured.
|
||||
--
|
||||
-- https://github.com/simplex-chat/simplexmq/blob/master/protocol/agent-protocol.md#messages-between-smp-agents
|
||||
@@ -705,7 +724,7 @@ data ConnectionErrorType
|
||||
SIMPLEX
|
||||
| -- | connection not accepted on join HELLO after timeout
|
||||
NOT_ACCEPTED
|
||||
| -- | connection not available on reply HELLO after timeout
|
||||
| -- | connection not available on reply confirmation/HELLO after timeout
|
||||
NOT_AVAILABLE
|
||||
deriving (Eq, Generic, Read, Show, Exception)
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ class Monad m => MonadAgentStore s m where
|
||||
createRcvMsg :: s -> ConnId -> RcvMsgData -> m ()
|
||||
updateSndIds :: s -> ConnId -> m (InternalId, InternalSndId, PrevSndMsgHash)
|
||||
createSndMsg :: s -> ConnId -> SndMsgData -> m ()
|
||||
getPendingMsgData :: s -> ConnId -> InternalId -> m (Maybe RcvQueue, (AMsgType, MsgBody, InternalTs))
|
||||
getPendingMsgData :: s -> ConnId -> InternalId -> m (Maybe RcvQueue, (AgentMessageType, MsgBody, InternalTs))
|
||||
getPendingMsgs :: s -> ConnId -> m [InternalId]
|
||||
checkRcvMsg :: s -> ConnId -> InternalId -> m ()
|
||||
deleteMsg :: s -> ConnId -> InternalId -> m ()
|
||||
@@ -102,8 +102,11 @@ data SndQueue = SndQueue
|
||||
{ server :: SMPServer,
|
||||
-- | sender queue ID
|
||||
sndId :: SMP.SenderId,
|
||||
-- | key used by the sender to sign transmissions
|
||||
-- | key pair used by the sender to sign transmissions
|
||||
sndPublicKey :: Maybe C.APublicVerifyKey,
|
||||
sndPrivateKey :: SndPrivateSignKey,
|
||||
-- | DH public key used to negotiate per-queue e2e encryption
|
||||
e2ePubKey :: Maybe C.PublicKeyX25519,
|
||||
-- | shared DH secret agreed for simple per-queue e2e encryption
|
||||
e2eDhSecret :: C.DhSecretX25519,
|
||||
-- | queue status
|
||||
@@ -221,7 +224,7 @@ type PrevSndMsgHash = MsgHash
|
||||
|
||||
data RcvMsgData = RcvMsgData
|
||||
{ msgMeta :: MsgMeta,
|
||||
msgType :: AMsgType,
|
||||
msgType :: AgentMessageType,
|
||||
msgBody :: MsgBody,
|
||||
internalRcvId :: InternalRcvId,
|
||||
internalHash :: MsgHash,
|
||||
@@ -232,7 +235,7 @@ data SndMsgData = SndMsgData
|
||||
{ internalId :: InternalId,
|
||||
internalSndId :: InternalSndId,
|
||||
internalTs :: InternalTs,
|
||||
msgType :: AMsgType,
|
||||
msgType :: AgentMessageType,
|
||||
msgBody :: MsgBody,
|
||||
internalHash :: MsgHash,
|
||||
prevMsgHash :: MsgHash
|
||||
|
||||
@@ -441,7 +441,7 @@ instance (MonadUnliftIO m, MonadError StoreError m) => MonadAgentStore SQLiteSto
|
||||
insertSndMsgDetails_ db connId sndMsgData
|
||||
updateHashSnd_ db connId sndMsgData
|
||||
|
||||
getPendingMsgData :: SQLiteStore -> ConnId -> InternalId -> m (Maybe RcvQueue, (AMsgType, MsgBody, InternalTs))
|
||||
getPendingMsgData :: SQLiteStore -> ConnId -> InternalId -> m (Maybe RcvQueue, (AgentMessageType, MsgBody, InternalTs))
|
||||
getPendingMsgData st connId msgId =
|
||||
liftIOEither . withTransaction st $ \db -> runExceptT $ do
|
||||
rq_ <- liftIO $ getRcvQueueByConnId_ db connId
|
||||
@@ -566,9 +566,9 @@ instance ToField InternalId where toField (InternalId x) = toField x
|
||||
|
||||
instance FromField InternalId where fromField x = InternalId <$> fromField x
|
||||
|
||||
instance ToField AMsgType where toField = toField . smpEncode
|
||||
instance ToField AgentMessageType where toField = toField . smpEncode
|
||||
|
||||
instance FromField AMsgType where fromField = blobFieldParser smpP
|
||||
instance FromField AgentMessageType where fromField = blobFieldParser smpP
|
||||
|
||||
instance ToField MsgIntegrity where toField = toField . strEncode
|
||||
|
||||
@@ -656,46 +656,25 @@ upsertServer_ dbConn SMPServer {host, port, keyHash} = do
|
||||
|
||||
insertRcvQueue_ :: DB.Connection -> ConnId -> RcvQueue -> IO ()
|
||||
insertRcvQueue_ dbConn connId RcvQueue {..} = do
|
||||
DB.executeNamed
|
||||
DB.execute
|
||||
dbConn
|
||||
[sql|
|
||||
INSERT INTO rcv_queues
|
||||
( host, port, rcv_id, conn_id, rcv_private_key, rcv_dh_secret, e2e_priv_key, e2e_dh_secret, snd_id, status)
|
||||
VALUES
|
||||
(:host,:port,:rcv_id,:conn_id,:rcv_private_key,:rcv_dh_secret,:e2e_priv_key,:e2e_dh_secret,:snd_id,:status);
|
||||
( host, port, rcv_id, conn_id, rcv_private_key, rcv_dh_secret, e2e_priv_key, e2e_dh_secret, snd_id, status) VALUES (?,?,?,?,?,?,?,?,?,?);
|
||||
|]
|
||||
[ ":host" := host server,
|
||||
":port" := port server,
|
||||
":rcv_id" := rcvId,
|
||||
":conn_id" := connId,
|
||||
":rcv_private_key" := rcvPrivateKey,
|
||||
":rcv_dh_secret" := rcvDhSecret,
|
||||
":e2e_priv_key" := e2ePrivKey,
|
||||
":e2e_dh_secret" := e2eDhSecret,
|
||||
":snd_id" := sndId,
|
||||
":status" := status
|
||||
]
|
||||
(host server, port server, rcvId, connId, rcvPrivateKey, rcvDhSecret, e2ePrivKey, e2eDhSecret, sndId, status)
|
||||
|
||||
-- * createSndConn helpers
|
||||
|
||||
insertSndQueue_ :: DB.Connection -> ConnId -> SndQueue -> IO ()
|
||||
insertSndQueue_ dbConn connId SndQueue {..} = do
|
||||
DB.executeNamed
|
||||
DB.execute
|
||||
dbConn
|
||||
[sql|
|
||||
INSERT INTO snd_queues
|
||||
( host, port, snd_id, conn_id, snd_private_key, e2e_dh_secret, status)
|
||||
VALUES
|
||||
(:host,:port,:snd_id,:conn_id,:snd_private_key,:e2e_dh_secret,:status);
|
||||
(host, port, snd_id, conn_id, snd_public_key, snd_private_key, e2e_pub_key, e2e_dh_secret, status) VALUES (?,?,?,?,?, ?,?, ?,?);
|
||||
|]
|
||||
[ ":host" := host server,
|
||||
":port" := port server,
|
||||
":snd_id" := sndId,
|
||||
":conn_id" := connId,
|
||||
":snd_private_key" := sndPrivateKey,
|
||||
":e2e_dh_secret" := e2eDhSecret,
|
||||
":status" := status
|
||||
]
|
||||
(host server, port server, sndId, connId, sndPublicKey, sndPrivateKey, e2ePubKey, e2eDhSecret, status)
|
||||
|
||||
-- * getConn helpers
|
||||
|
||||
@@ -746,16 +725,16 @@ getSndQueueByConnId_ dbConn connId =
|
||||
<$> DB.query
|
||||
dbConn
|
||||
[sql|
|
||||
SELECT s.key_hash, q.host, q.port, q.snd_id, q.snd_private_key, q.e2e_dh_secret, q.status
|
||||
SELECT s.key_hash, q.host, q.port, q.snd_id, q.snd_public_key, q.snd_private_key, q.e2e_pub_key, q.e2e_dh_secret, q.status
|
||||
FROM snd_queues q
|
||||
INNER JOIN servers s ON q.host = s.host AND q.port = s.port
|
||||
WHERE q.conn_id = ?;
|
||||
|]
|
||||
(Only connId)
|
||||
where
|
||||
sndQueue [(keyHash, host, port, sndId, sndPrivateKey, e2eDhSecret, status)] =
|
||||
sndQueue [(keyHash, host, port, sndId, sndPublicKey, sndPrivateKey, e2ePubKey, e2eDhSecret, status)] =
|
||||
let server = SMPServer host port keyHash
|
||||
in Just SndQueue {server, sndId, sndPrivateKey, e2eDhSecret, status}
|
||||
in Just SndQueue {server, sndId, sndPublicKey, sndPrivateKey, e2ePubKey, e2eDhSecret, status}
|
||||
sndQueue _ = Nothing
|
||||
|
||||
-- * updateRcvIds helpers
|
||||
|
||||
@@ -25,13 +25,15 @@ import qualified Database.SQLite.Simple as DB
|
||||
import Database.SQLite.Simple.QQ (sql)
|
||||
import qualified Database.SQLite3 as SQLite3
|
||||
import Simplex.Messaging.Agent.Store.SQLite.Migrations.M20220101_initial
|
||||
import Simplex.Messaging.Agent.Store.SQLite.Migrations.M20220301_snd_queue_keys
|
||||
|
||||
data Migration = Migration {name :: String, up :: Text}
|
||||
deriving (Show)
|
||||
|
||||
schemaMigrations :: [(String, Query)]
|
||||
schemaMigrations =
|
||||
[ ("20220101_initial", m20220101_initial)
|
||||
[ ("20220101_initial", m20220101_initial),
|
||||
("20220301_snd_queue_keys", m20220301_snd_queue_keys)
|
||||
]
|
||||
|
||||
-- | The list of migrations in ascending order by date
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
{-# LANGUAGE QuasiQuotes #-}
|
||||
|
||||
module Simplex.Messaging.Agent.Store.SQLite.Migrations.M20220301_snd_queue_keys where
|
||||
|
||||
import Database.SQLite.Simple (Query)
|
||||
import Database.SQLite.Simple.QQ (sql)
|
||||
|
||||
m20220301_snd_queue_keys :: Query
|
||||
m20220301_snd_queue_keys =
|
||||
[sql|
|
||||
ALTER TABLE snd_queues ADD COLUMN snd_public_key BLOB;
|
||||
ALTER TABLE snd_queues ADD COLUMN e2e_pub_key BLOB;
|
||||
|]
|
||||
Reference in New Issue
Block a user