From 93e371d40110732a30ed9760c658a40179de5eec Mon Sep 17 00:00:00 2001 From: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com> Date: Fri, 10 May 2024 12:49:57 +0400 Subject: [PATCH 01/13] core: delivery path --- cabal.project | 2 +- scripts/nix/sha256map.nix | 2 +- src/Simplex/Chat.hs | 15 +++++++++++---- tests/ChatClient.hs | 7 ++++++- 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/cabal.project b/cabal.project index aef1672c3d..1813d95976 100644 --- a/cabal.project +++ b/cabal.project @@ -12,7 +12,7 @@ constraints: zip +disable-bzip2 +disable-zstd source-repository-package type: git location: https://github.com/simplex-chat/simplexmq.git - tag: b40654c95dd4b00764f60bc3c35bc4e64b550cf1 + tag: 7a02debcf63c32e3f8c4d83649690dfccc500778 source-repository-package type: git diff --git a/scripts/nix/sha256map.nix b/scripts/nix/sha256map.nix index 2841b811d1..00f45328cb 100644 --- a/scripts/nix/sha256map.nix +++ b/scripts/nix/sha256map.nix @@ -1,5 +1,5 @@ { - "https://github.com/simplex-chat/simplexmq.git"."b40654c95dd4b00764f60bc3c35bc4e64b550cf1" = "1yq3azgb43n42bxr7k1gcld4w54f3y6jn327bs56mvxz8pa0jvvq"; + "https://github.com/simplex-chat/simplexmq.git"."7a02debcf63c32e3f8c4d83649690dfccc500778" = "1jk5hlhbw3w8imyaqzm0f3q5nqid5ggsj5qvhxdmrlrp8axm3b8h"; "https://github.com/simplex-chat/hs-socks.git"."a30cc7a79a08d8108316094f8f2f82a0c5e1ac51" = "0yasvnr7g91k76mjkamvzab2kvlb1g5pspjyjn2fr6v83swjhj38"; "https://github.com/simplex-chat/direct-sqlcipher.git"."f814ee68b16a9447fbb467ccc8f29bdd3546bfd9" = "1ql13f4kfwkbaq7nygkxgw84213i0zm7c1a8hwvramayxl38dq5d"; "https://github.com/simplex-chat/sqlcipher-simple.git"."a46bd361a19376c5211f1058908fc0ae6bf42446" = "1z0r78d8f0812kxbgsm735qf6xx8lvaz27k1a0b4a2m0sshpd5gl"; diff --git a/src/Simplex/Chat.hs b/src/Simplex/Chat.hs index d56e731246..9cb853c1e8 100644 --- a/src/Simplex/Chat.hs +++ b/src/Simplex/Chat.hs @@ -3872,7 +3872,7 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = withAckMessage' agentConnId meta $ void $ saveDirectRcvMSG conn meta msgBody - SENT msgId -> + SENT msgId _deliveryPath -> sentMsgDeliveryEvent conn msgId OK -> -- [async agent commands] continuation on receiving OK @@ -4005,7 +4005,7 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = notifyMemberConnected gInfo m $ Just ct let connectedIncognito = contactConnIncognito ct || incognitoMembership gInfo when (memberCategory m == GCPreMember) $ probeMatchingContactsAndMembers ct connectedIncognito True - SENT msgId -> do + SENT msgId deliveryPath -> do sentMsgDeliveryEvent conn msgId checkSndInlineFTComplete conn msgId updateDirectItemStatus ct conn msgId $ CISSndSent SSPComplete @@ -4043,6 +4043,10 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = OK -> -- [async agent commands] continuation on receiving OK when (corrId /= "") $ withCompletedCommand conn agentMsg $ \_cmdData -> pure () + MWARN msgId err -> do + -- updateDirectItemStatus (agentWarnToItemStatus) + -- toView + pure () MERR msgId err -> do updateDirectItemStatus ct conn msgId $ agentErrToItemStatus err toView $ CRChatError (Just user) (ChatErrorAgent err $ Just connEntity) @@ -4387,7 +4391,7 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = RCVD msgMeta msgRcpt -> withAckMessage' agentConnId msgMeta $ groupMsgReceived gInfo m conn msgMeta msgRcpt - SENT msgId -> do + SENT msgId deliveryPath -> do sentMsgDeliveryEvent conn msgId checkSndInlineFTComplete conn msgId updateGroupItemStatus gInfo m conn msgId $ CISSndSent SSPComplete @@ -4426,6 +4430,9 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = OK -> -- [async agent commands] continuation on receiving OK when (corrId /= "") $ withCompletedCommand conn agentMsg $ \_cmdData -> pure () + MWARN msgId err -> do + -- updateGroupItemErrorStatus (agentWarnToItemStatus) + pure () MERR msgId err -> do withStore' $ \db -> updateGroupItemErrorStatus db msgId (groupMemberId' m) $ agentErrToItemStatus err -- group errors are silenced to reduce load on UI event log @@ -4493,7 +4500,7 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = updateDirectCIFileStatus db vr user fileId $ CIFSSndTransfer 0 1 toView $ CRSndFileStart user ci ft sendFileChunk user ft - SENT msgId -> do + SENT msgId _deliveryPath -> do withStore' $ \db -> updateSndFileChunkSent db ft msgId unless (fileStatus == FSCancelled) $ sendFileChunk user ft MERR _ err -> do diff --git a/tests/ChatClient.hs b/tests/ChatClient.hs index 4897a3b3d3..2bcd52ab3f 100644 --- a/tests/ChatClient.hs +++ b/tests/ChatClient.hs @@ -37,6 +37,7 @@ import Simplex.Chat.Types import Simplex.FileTransfer.Description (kb, mb) import Simplex.FileTransfer.Server (runXFTPServerBlocking) import Simplex.FileTransfer.Server.Env (XFTPServerConfig (..), defaultFileExpiration) +import Simplex.FileTransfer.Transport (supportedFileServerVRange) import Simplex.Messaging.Agent (disposeAgentClient) import Simplex.Messaging.Agent.Env.SQLite import Simplex.Messaging.Agent.Protocol (currentSMPAgentVersion, duplexHandshakeSMPAgentVersion, pqdrSMPAgentVersion, supportedSMPAgentVRange) @@ -44,6 +45,7 @@ import Simplex.Messaging.Agent.RetryInterval import Simplex.Messaging.Agent.Store.SQLite (MigrationConfirmation (..), closeSQLiteStore) import qualified Simplex.Messaging.Agent.Store.SQLite.DB as DB import Simplex.Messaging.Client (ProtocolClientConfig (..), defaultNetworkConfig) +import Simplex.Messaging.Client.Agent (defaultSMPClientAgentConfig) import Simplex.Messaging.Crypto.Ratchet (supportedE2EEncryptVRange) import qualified Simplex.Messaging.Crypto.Ratchet as CR import Simplex.Messaging.Server (runSMPServerBlocking) @@ -427,7 +429,9 @@ serverCfg = smpServerVRange = supportedServerSMPRelayVRange, transportConfig = defaultTransportServerConfig, smpHandshakeTimeout = 1000000, - controlPort = Nothing + controlPort = Nothing, + smpAgentCfg = defaultSMPClientAgentConfig, + allowSMPProxy = False } withSmpServer :: IO () -> IO () @@ -458,6 +462,7 @@ xftpServerConfig = caCertificateFile = "tests/fixtures/tls/ca.crt", privateKeyFile = "tests/fixtures/tls/server.key", certificateFile = "tests/fixtures/tls/server.crt", + xftpServerVRange = supportedFileServerVRange, logStatsInterval = Nothing, logStatsStartTime = 0, serverStatsLogFile = "tests/tmp/xftp-server-stats.daily.log", From 7c15367443c5ac4f96c7176d908b8ee15863e1ba Mon Sep 17 00:00:00 2001 From: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com> Date: Fri, 10 May 2024 14:46:33 +0400 Subject: [PATCH 02/13] update simplexmq --- cabal.project | 2 +- scripts/nix/sha256map.nix | 2 +- src/Simplex/Chat.hs | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cabal.project b/cabal.project index 1813d95976..983ff0b906 100644 --- a/cabal.project +++ b/cabal.project @@ -12,7 +12,7 @@ constraints: zip +disable-bzip2 +disable-zstd source-repository-package type: git location: https://github.com/simplex-chat/simplexmq.git - tag: 7a02debcf63c32e3f8c4d83649690dfccc500778 + tag: b7afb725fd5cdfde67a82303535aea0367121023 source-repository-package type: git diff --git a/scripts/nix/sha256map.nix b/scripts/nix/sha256map.nix index 00f45328cb..3d3ae870fc 100644 --- a/scripts/nix/sha256map.nix +++ b/scripts/nix/sha256map.nix @@ -1,5 +1,5 @@ { - "https://github.com/simplex-chat/simplexmq.git"."7a02debcf63c32e3f8c4d83649690dfccc500778" = "1jk5hlhbw3w8imyaqzm0f3q5nqid5ggsj5qvhxdmrlrp8axm3b8h"; + "https://github.com/simplex-chat/simplexmq.git"."b7afb725fd5cdfde67a82303535aea0367121023" = "0fh67l1ikjw0q0p9b4zc25c4nrwvfc11k8853ia70h9ji316l9s3"; "https://github.com/simplex-chat/hs-socks.git"."a30cc7a79a08d8108316094f8f2f82a0c5e1ac51" = "0yasvnr7g91k76mjkamvzab2kvlb1g5pspjyjn2fr6v83swjhj38"; "https://github.com/simplex-chat/direct-sqlcipher.git"."f814ee68b16a9447fbb467ccc8f29bdd3546bfd9" = "1ql13f4kfwkbaq7nygkxgw84213i0zm7c1a8hwvramayxl38dq5d"; "https://github.com/simplex-chat/sqlcipher-simple.git"."a46bd361a19376c5211f1058908fc0ae6bf42446" = "1z0r78d8f0812kxbgsm735qf6xx8lvaz27k1a0b4a2m0sshpd5gl"; diff --git a/src/Simplex/Chat.hs b/src/Simplex/Chat.hs index 9cb853c1e8..6a2ac39230 100644 --- a/src/Simplex/Chat.hs +++ b/src/Simplex/Chat.hs @@ -3872,7 +3872,7 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = withAckMessage' agentConnId meta $ void $ saveDirectRcvMSG conn meta msgBody - SENT msgId _deliveryPath -> + SENT msgId _proxy -> sentMsgDeliveryEvent conn msgId OK -> -- [async agent commands] continuation on receiving OK @@ -4005,7 +4005,7 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = notifyMemberConnected gInfo m $ Just ct let connectedIncognito = contactConnIncognito ct || incognitoMembership gInfo when (memberCategory m == GCPreMember) $ probeMatchingContactsAndMembers ct connectedIncognito True - SENT msgId deliveryPath -> do + SENT msgId proxy -> do sentMsgDeliveryEvent conn msgId checkSndInlineFTComplete conn msgId updateDirectItemStatus ct conn msgId $ CISSndSent SSPComplete @@ -4391,7 +4391,7 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = RCVD msgMeta msgRcpt -> withAckMessage' agentConnId msgMeta $ groupMsgReceived gInfo m conn msgMeta msgRcpt - SENT msgId deliveryPath -> do + SENT msgId proxy -> do sentMsgDeliveryEvent conn msgId checkSndInlineFTComplete conn msgId updateGroupItemStatus gInfo m conn msgId $ CISSndSent SSPComplete @@ -4500,7 +4500,7 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = updateDirectCIFileStatus db vr user fileId $ CIFSSndTransfer 0 1 toView $ CRSndFileStart user ci ft sendFileChunk user ft - SENT msgId _deliveryPath -> do + SENT msgId _proxy -> do withStore' $ \db -> updateSndFileChunkSent db ft msgId unless (fileStatus == FSCancelled) $ sendFileChunk user ft MERR _ err -> do From 5be44678404cb3ad537a83d78e71c33a70c7e45d Mon Sep 17 00:00:00 2001 From: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com> Date: Fri, 10 May 2024 18:26:01 +0400 Subject: [PATCH 03/13] via proxy snd flags --- simplex-chat.cabal | 1 + src/Simplex/Chat.hs | 18 ++++---- src/Simplex/Chat/Messages.hs | 11 +++-- .../M20240510_chat_items_via_proxy.hs | 20 +++++++++ src/Simplex/Chat/Migrations/chat_schema.sql | 5 ++- src/Simplex/Chat/Store/Messages.hs | 42 +++++++++++++------ src/Simplex/Chat/Store/Migrations.hs | 4 +- 7 files changed, 76 insertions(+), 25 deletions(-) create mode 100644 src/Simplex/Chat/Migrations/M20240510_chat_items_via_proxy.hs diff --git a/simplex-chat.cabal b/simplex-chat.cabal index f59d490cc4..a04949328e 100644 --- a/simplex-chat.cabal +++ b/simplex-chat.cabal @@ -142,6 +142,7 @@ library Simplex.Chat.Migrations.M20240324_custom_data Simplex.Chat.Migrations.M20240402_item_forwarded Simplex.Chat.Migrations.M20240430_ui_theme + Simplex.Chat.Migrations.M20240510_chat_items_via_proxy Simplex.Chat.Mobile Simplex.Chat.Mobile.File Simplex.Chat.Mobile.Shared diff --git a/src/Simplex/Chat.hs b/src/Simplex/Chat.hs index 6a2ac39230..a2f0bca5f2 100644 --- a/src/Simplex/Chat.hs +++ b/src/Simplex/Chat.hs @@ -701,7 +701,7 @@ processChatCommand' vr = \case (SCTGroup, SMDSnd) -> do withStore' (`getGroupSndStatuses` itemId) >>= \case [] -> pure Nothing - memStatuses -> pure $ Just $ map (uncurry MemberDeliveryStatus) memStatuses + memStatuses -> pure $ Just $ map (\(x,y,z) -> MemberDeliveryStatus x y z) memStatuses _ -> pure Nothing forwardedFromChatItem <- getForwardedFromItem user ci pure $ CRChatItemInfo user aci ChatItemInfo {itemVersions, memberDeliveryStatuses, forwardedFromChatItem} @@ -4008,7 +4008,10 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = SENT msgId proxy -> do sentMsgDeliveryEvent conn msgId checkSndInlineFTComplete conn msgId - updateDirectItemStatus ct conn msgId $ CISSndSent SSPComplete + ci_ <- withStore $ \db -> do + ci_ <- updateDirectItemStatus' db ct conn msgId (CISSndSent SSPComplete) + forM ci_ $ \ci -> liftIO $ setDirectSndChatItemViaProxy db user ct ci (isJust proxy) + forM_ ci_ $ \ci -> toView $ CRChatItemStatusUpdated user (AChatItem SCTDirect SMDSnd (DirectChat ct) ci) SWITCH qd phase cStats -> do toView $ CRContactSwitch user ct (SwitchProgress qd phase cStats) when (phase `elem` [SPStarted, SPCompleted]) $ case qd of @@ -4394,7 +4397,7 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = SENT msgId proxy -> do sentMsgDeliveryEvent conn msgId checkSndInlineFTComplete conn msgId - updateGroupItemStatus gInfo m conn msgId $ CISSndSent SSPComplete + updateGroupItemStatus gInfo m conn msgId (CISSndSent SSPComplete) (Just $ isJust proxy) SWITCH qd phase cStats -> do toView $ CRGroupMemberSwitch user gInfo m (SwitchProgress qd phase cStats) when (phase `elem` [SPStarted, SPCompleted]) $ case qd of @@ -6043,7 +6046,7 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = checkIntegrityCreateItem (CDGroupRcv gInfo m) msgMeta `catchChatError` \_ -> pure () forM_ msgRcpts $ \MsgReceipt {agentMsgId, msgRcptStatus} -> do withStore' $ \db -> updateSndMsgDeliveryStatus db connId agentMsgId $ MDSSndRcvd msgRcptStatus - updateGroupItemStatus gInfo m conn agentMsgId $ CISSndRcvd msgRcptStatus SSPComplete + updateGroupItemStatus gInfo m conn agentMsgId (CISSndRcvd msgRcptStatus SSPComplete) Nothing updateDirectItemsStatus :: Contact -> Connection -> [AgentMsgId] -> CIStatus 'MDSnd -> CM () updateDirectItemsStatus ct conn msgIds newStatus = do @@ -6080,11 +6083,12 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = | otherwise -> updateGroupSndStatus db itemId groupMemberId newStatus $> True _ -> pure False - updateGroupItemStatus :: GroupInfo -> GroupMember -> Connection -> AgentMsgId -> CIStatus 'MDSnd -> CM () - updateGroupItemStatus gInfo@GroupInfo {groupId} GroupMember {groupMemberId} Connection {connId} msgId newMemStatus = + updateGroupItemStatus :: GroupInfo -> GroupMember -> Connection -> AgentMsgId -> CIStatus 'MDSnd -> Maybe Bool -> CM () + updateGroupItemStatus gInfo@GroupInfo {groupId} GroupMember {groupMemberId} Connection {connId} msgId newMemStatus viaProxy_ = withStore' (\db -> getGroupChatItemByAgentMsgId db user groupId connId msgId) >>= \case Just (CChatItem SMDSnd ChatItem {meta = CIMeta {itemStatus = CISSndRcvd _ SSPComplete}}) -> pure () Just (CChatItem SMDSnd ChatItem {meta = CIMeta {itemId, itemStatus}}) -> do + forM_ viaProxy_ $ \viaProxy -> withStore' $ \db -> setGroupSndViaProxy db itemId groupMemberId viaProxy memStatusChanged <- updateGroupMemSndStatus itemId groupMemberId newMemStatus when memStatusChanged $ do memStatusCounts <- withStore' (`getGroupSndStatusCounts` itemId) @@ -6707,7 +6711,7 @@ mkChatItem :: (ChatTypeI c, MsgDirectionI d) => ChatDirection c d -> ChatItemId mkChatItem cd ciId content file quotedItem sharedMsgId itemForwarded itemTimed live itemTs forwardedByMember currentTs = let itemText = ciContentToText content itemStatus = ciCreateStatus content - meta = mkCIMeta ciId content itemText itemStatus sharedMsgId itemForwarded Nothing False itemTimed (justTrue live) currentTs itemTs forwardedByMember currentTs currentTs + meta = mkCIMeta ciId content itemText itemStatus Nothing sharedMsgId itemForwarded Nothing False itemTimed (justTrue live) currentTs itemTs forwardedByMember currentTs currentTs in ChatItem {chatDir = toCIDirection cd, meta, content, formattedText = parseMaybeMarkdownList itemText, quotedItem, reactions = [], file} deleteDirectCI :: MsgDirectionI d => User -> Contact -> ChatItem 'CTDirect d -> Bool -> Bool -> CM ChatResponse diff --git a/src/Simplex/Chat/Messages.hs b/src/Simplex/Chat/Messages.hs index a6d5761b5f..50ee141a48 100644 --- a/src/Simplex/Chat/Messages.hs +++ b/src/Simplex/Chat/Messages.hs @@ -338,6 +338,7 @@ data CIMeta (c :: ChatType) (d :: MsgDirection) = CIMeta itemTs :: ChatItemTs, itemText :: Text, itemStatus :: CIStatus d, + sentViaProxy :: Maybe Bool, itemSharedMsgId :: Maybe SharedMsgId, itemForwarded :: Maybe CIForwardedFrom, itemDeleted :: Maybe (CIDeleted c), @@ -352,8 +353,8 @@ data CIMeta (c :: ChatType) (d :: MsgDirection) = CIMeta } deriving (Show) -mkCIMeta :: forall c d. ChatTypeI c => ChatItemId -> CIContent d -> Text -> CIStatus d -> Maybe SharedMsgId -> Maybe CIForwardedFrom -> Maybe (CIDeleted c) -> Bool -> Maybe CITimed -> Maybe Bool -> UTCTime -> ChatItemTs -> Maybe GroupMemberId -> UTCTime -> UTCTime -> CIMeta c d -mkCIMeta itemId itemContent itemText itemStatus itemSharedMsgId itemForwarded itemDeleted itemEdited itemTimed itemLive currentTs itemTs forwardedByMember createdAt updatedAt = +mkCIMeta :: forall c d. ChatTypeI c => ChatItemId -> CIContent d -> Text -> CIStatus d -> Maybe Bool -> Maybe SharedMsgId -> Maybe CIForwardedFrom -> Maybe (CIDeleted c) -> Bool -> Maybe CITimed -> Maybe Bool -> UTCTime -> ChatItemTs -> Maybe GroupMemberId -> UTCTime -> UTCTime -> CIMeta c d +mkCIMeta itemId itemContent itemText itemStatus sentViaProxy itemSharedMsgId itemForwarded itemDeleted itemEdited itemTimed itemLive currentTs itemTs forwardedByMember createdAt updatedAt = let deletable = case itemContent of CISndMsgContent _ -> case chatTypeI @c of @@ -361,7 +362,7 @@ mkCIMeta itemId itemContent itemText itemStatus itemSharedMsgId itemForwarded it _ -> diffUTCTime currentTs itemTs < nominalDay && isNothing itemDeleted _ -> False editable = deletable && isNothing itemForwarded - in CIMeta {itemId, itemTs, itemText, itemStatus, itemSharedMsgId, itemForwarded, itemDeleted, itemEdited, itemTimed, itemLive, deletable, editable, forwardedByMember, createdAt, updatedAt} + in CIMeta {itemId, itemTs, itemText, itemStatus, sentViaProxy, itemSharedMsgId, itemForwarded, itemDeleted, itemEdited, itemTimed, itemLive, deletable, editable, forwardedByMember, createdAt, updatedAt} dummyMeta :: ChatItemId -> UTCTime -> Text -> CIMeta c 'MDSnd dummyMeta itemId ts itemText = @@ -370,6 +371,7 @@ dummyMeta itemId ts itemText = itemTs = ts, itemText, itemStatus = CISSndNew, + sentViaProxy = Nothing, itemSharedMsgId = Nothing, itemForwarded = Nothing, itemDeleted = Nothing, @@ -1063,7 +1065,8 @@ mkItemVersion ChatItem {content, meta} = version <$> ciMsgContent content data MemberDeliveryStatus = MemberDeliveryStatus { groupMemberId :: GroupMemberId, - memberDeliveryStatus :: CIStatus 'MDSnd + memberDeliveryStatus :: CIStatus 'MDSnd, + sentViaProxy :: Maybe Bool } deriving (Eq, Show) diff --git a/src/Simplex/Chat/Migrations/M20240510_chat_items_via_proxy.hs b/src/Simplex/Chat/Migrations/M20240510_chat_items_via_proxy.hs new file mode 100644 index 0000000000..3c32034344 --- /dev/null +++ b/src/Simplex/Chat/Migrations/M20240510_chat_items_via_proxy.hs @@ -0,0 +1,20 @@ +{-# LANGUAGE QuasiQuotes #-} + +module Simplex.Chat.Migrations.M20240510_chat_items_via_proxy where + +import Database.SQLite.Simple (Query) +import Database.SQLite.Simple.QQ (sql) + +m20240510_chat_items_via_proxy :: Query +m20240510_chat_items_via_proxy = + [sql| +ALTER TABLE chat_items ADD COLUMN via_proxy INTEGER; +ALTER TABLE group_snd_item_statuses ADD COLUMN via_proxy INTEGER; +|] + +down_m20240510_chat_items_via_proxy :: Query +down_m20240510_chat_items_via_proxy = + [sql| +ALTER TABLE chat_items DROP COLUMN via_proxy; +ALTER TABLE group_snd_item_statuses DROP COLUMN via_proxy; +|] diff --git a/src/Simplex/Chat/Migrations/chat_schema.sql b/src/Simplex/Chat/Migrations/chat_schema.sql index f2f94d019c..fd917443a8 100644 --- a/src/Simplex/Chat/Migrations/chat_schema.sql +++ b/src/Simplex/Chat/Migrations/chat_schema.sql @@ -391,7 +391,8 @@ CREATE TABLE chat_items( fwd_from_msg_dir INTEGER, fwd_from_contact_id INTEGER REFERENCES contacts ON DELETE SET NULL, fwd_from_group_id INTEGER REFERENCES groups ON DELETE SET NULL, - fwd_from_chat_item_id INTEGER REFERENCES chat_items ON DELETE SET NULL + fwd_from_chat_item_id INTEGER REFERENCES chat_items ON DELETE SET NULL, + via_proxy INTEGER ); CREATE TABLE chat_item_messages( chat_item_id INTEGER NOT NULL REFERENCES chat_items ON DELETE CASCADE, @@ -502,6 +503,8 @@ CREATE TABLE group_snd_item_statuses( group_snd_item_status TEXT NOT NULL, created_at TEXT NOT NULL DEFAULT(datetime('now')), updated_at TEXT NOT NULL DEFAULT(datetime('now')) + , + via_proxy INTEGER ); CREATE TABLE IF NOT EXISTS "sent_probes"( sent_probe_id INTEGER PRIMARY KEY, diff --git a/src/Simplex/Chat/Store/Messages.hs b/src/Simplex/Chat/Store/Messages.hs index 8163bd336c..b006e67dae 100644 --- a/src/Simplex/Chat/Store/Messages.hs +++ b/src/Simplex/Chat/Store/Messages.hs @@ -95,6 +95,7 @@ module Simplex.Chat.Store.Messages lookupChatItemByFileId, getChatItemByGroupId, updateDirectChatItemStatus, + setDirectSndChatItemViaProxy, getTimedItems, getChatItemTTL, setChatItemTTL, @@ -108,6 +109,7 @@ module Simplex.Chat.Store.Messages createGroupSndStatus, getGroupSndStatus, updateGroupSndStatus, + setGroupSndViaProxy, getGroupSndStatuses, getGroupSndStatusCounts, getGroupHistoryItems, @@ -806,7 +808,7 @@ getLocalChatPreview_ db user (LocalChatPD _ noteFolderId lastItemId_ stats) = do -- this function can be changed so it never fails, not only avoid failure on invalid json toLocalChatItem :: UTCTime -> ChatItemRow -> Either StoreError (CChatItem 'CTLocal) -toLocalChatItem currentTs ((itemId, itemTs, AMsgDirection msgDir, itemContentText, itemText, itemStatus, sharedMsgId) :. (itemDeleted, deletedTs, itemEdited, createdAt, updatedAt) :. forwardedFromRow :. (timedTTL, timedDeleteAt, itemLive) :. (fileId_, fileName_, fileSize_, filePath, fileKey, fileNonce, fileStatus_, fileProtocol_)) = +toLocalChatItem currentTs ((itemId, itemTs, AMsgDirection msgDir, itemContentText, itemText, itemStatus, sentViaProxy, sharedMsgId) :. (itemDeleted, deletedTs, itemEdited, createdAt, updatedAt) :. forwardedFromRow :. (timedTTL, timedDeleteAt, itemLive) :. (fileId_, fileName_, fileSize_, filePath, fileKey, fileNonce, fileStatus_, fileProtocol_)) = chatItem $ fromRight invalid $ dbParseACIContent itemContentText where invalid = ACIContent msgDir $ CIInvalidJSON itemContentText @@ -839,7 +841,7 @@ toLocalChatItem currentTs ((itemId, itemTs, AMsgDirection msgDir, itemContentTex _ -> Just (CIDeleted @CTLocal deletedTs) itemEdited' = fromMaybe False itemEdited itemForwarded = toCIForwardedFrom forwardedFromRow - in mkCIMeta itemId content itemText status sharedMsgId itemForwarded itemDeleted' itemEdited' ciTimed itemLive currentTs itemTs Nothing createdAt updatedAt + in mkCIMeta itemId content itemText status sentViaProxy sharedMsgId itemForwarded itemDeleted' itemEdited' ciTimed itemLive currentTs itemTs Nothing createdAt updatedAt ciTimed :: Maybe CITimed ciTimed = timedTTL >>= \ttl -> Just CITimed {ttl, deleteAt = timedDeleteAt} @@ -1407,7 +1409,7 @@ type ChatItemModeRow = (Maybe Int, Maybe UTCTime, Maybe Bool) type ChatItemForwardedFromRow = (Maybe CIForwardedFromTag, Maybe Text, Maybe MsgDirection, Maybe Int64, Maybe Int64, Maybe Int64) type ChatItemRow = - (Int64, ChatItemTs, AMsgDirection, Text, Text, ACIStatus, Maybe SharedMsgId) + (Int64, ChatItemTs, AMsgDirection, Text, Text, ACIStatus, Maybe Bool, Maybe SharedMsgId) :. (Int, Maybe UTCTime, Maybe Bool, UTCTime, UTCTime) :. ChatItemForwardedFromRow :. ChatItemModeRow @@ -1426,7 +1428,7 @@ toQuote (quotedItemId, quotedSharedMsgId, quotedSentAt, quotedMsgContent, _) dir -- this function can be changed so it never fails, not only avoid failure on invalid json toDirectChatItem :: UTCTime -> ChatItemRow :. QuoteRow -> Either StoreError (CChatItem 'CTDirect) -toDirectChatItem currentTs (((itemId, itemTs, AMsgDirection msgDir, itemContentText, itemText, itemStatus, sharedMsgId) :. (itemDeleted, deletedTs, itemEdited, createdAt, updatedAt) :. forwardedFromRow :. (timedTTL, timedDeleteAt, itemLive) :. (fileId_, fileName_, fileSize_, filePath, fileKey, fileNonce, fileStatus_, fileProtocol_)) :. quoteRow) = +toDirectChatItem currentTs (((itemId, itemTs, AMsgDirection msgDir, itemContentText, itemText, itemStatus, sentViaProxy, sharedMsgId) :. (itemDeleted, deletedTs, itemEdited, createdAt, updatedAt) :. forwardedFromRow :. (timedTTL, timedDeleteAt, itemLive) :. (fileId_, fileName_, fileSize_, filePath, fileKey, fileNonce, fileStatus_, fileProtocol_)) :. quoteRow) = chatItem $ fromRight invalid $ dbParseACIContent itemContentText where invalid = ACIContent msgDir $ CIInvalidJSON itemContentText @@ -1459,7 +1461,7 @@ toDirectChatItem currentTs (((itemId, itemTs, AMsgDirection msgDir, itemContentT _ -> Just (CIDeleted @CTDirect deletedTs) itemEdited' = fromMaybe False itemEdited itemForwarded = toCIForwardedFrom forwardedFromRow - in mkCIMeta itemId content itemText status sharedMsgId itemForwarded itemDeleted' itemEdited' ciTimed itemLive currentTs itemTs Nothing createdAt updatedAt + in mkCIMeta itemId content itemText status sentViaProxy sharedMsgId itemForwarded itemDeleted' itemEdited' ciTimed itemLive currentTs itemTs Nothing createdAt updatedAt ciTimed :: Maybe CITimed ciTimed = timedTTL >>= \ttl -> Just CITimed {ttl, deleteAt = timedDeleteAt} @@ -1483,7 +1485,7 @@ toGroupQuote qr@(_, _, _, _, quotedSent) quotedMember_ = toQuote qr $ direction -- this function can be changed so it never fails, not only avoid failure on invalid json toGroupChatItem :: UTCTime -> Int64 -> ChatItemRow :. Only (Maybe GroupMemberId) :. MaybeGroupMemberRow :. GroupQuoteRow :. MaybeGroupMemberRow -> Either StoreError (CChatItem 'CTGroup) -toGroupChatItem currentTs userContactId (((itemId, itemTs, AMsgDirection msgDir, itemContentText, itemText, itemStatus, sharedMsgId) :. (itemDeleted, deletedTs, itemEdited, createdAt, updatedAt) :. forwardedFromRow :. (timedTTL, timedDeleteAt, itemLive) :. (fileId_, fileName_, fileSize_, filePath, fileKey, fileNonce, fileStatus_, fileProtocol_)) :. Only forwardedByMember :. memberRow_ :. (quoteRow :. quotedMemberRow_) :. deletedByGroupMemberRow_) = do +toGroupChatItem currentTs userContactId (((itemId, itemTs, AMsgDirection msgDir, itemContentText, itemText, itemStatus, sentViaProxy, sharedMsgId) :. (itemDeleted, deletedTs, itemEdited, createdAt, updatedAt) :. forwardedFromRow :. (timedTTL, timedDeleteAt, itemLive) :. (fileId_, fileName_, fileSize_, filePath, fileKey, fileNonce, fileStatus_, fileProtocol_)) :. Only forwardedByMember :. memberRow_ :. (quoteRow :. quotedMemberRow_) :. deletedByGroupMemberRow_) = do chatItem $ fromRight invalid $ dbParseACIContent itemContentText where member_ = toMaybeGroupMember userContactId memberRow_ @@ -1521,7 +1523,7 @@ toGroupChatItem currentTs userContactId (((itemId, itemTs, AMsgDirection msgDir, _ -> Just (maybe (CIDeleted @CTGroup deletedTs) (CIModerated deletedTs) deletedByGroupMember_) itemEdited' = fromMaybe False itemEdited itemForwarded = toCIForwardedFrom forwardedFromRow - in mkCIMeta itemId content itemText status sharedMsgId itemForwarded itemDeleted' itemEdited' ciTimed itemLive currentTs itemTs forwardedByMember createdAt updatedAt + in mkCIMeta itemId content itemText status sentViaProxy sharedMsgId itemForwarded itemDeleted' itemEdited' ciTimed itemLive currentTs itemTs forwardedByMember createdAt updatedAt ciTimed :: Maybe CITimed ciTimed = timedTTL >>= \ttl -> Just CITimed {ttl, deleteAt = timedDeleteAt} @@ -1600,6 +1602,11 @@ updateDirectChatItemStatus db user@User {userId} ct@Contact {contactId} itemId i liftIO $ DB.execute db "UPDATE chat_items SET item_status = ?, updated_at = ? WHERE user_id = ? AND contact_id = ? AND chat_item_id = ?" (itemStatus, currentTs, userId, contactId, itemId) pure ci {meta = (meta ci) {itemStatus}} +setDirectSndChatItemViaProxy :: DB.Connection -> User -> Contact -> ChatItem 'CTDirect 'MDSnd -> Bool -> IO (ChatItem 'CTDirect 'MDSnd) +setDirectSndChatItemViaProxy db User {userId} Contact {contactId} ci viaProxy = do + DB.execute db "UPDATE chat_items SET via_proxy = ? WHERE user_id = ? AND contact_id = ? AND chat_item_id = ?" (viaProxy, userId, contactId, chatItemId' ci) + pure ci {meta = (meta ci) {sentViaProxy = Just viaProxy}} + updateDirectChatItem :: MsgDirectionI d => DB.Connection -> User -> Contact -> ChatItemId -> CIContent d -> Bool -> Bool -> Maybe CITimed -> Maybe MessageId -> ExceptT StoreError IO (ChatItem 'CTDirect d) updateDirectChatItem db user ct@Contact {contactId} itemId newContent edited live timed_ msgId_ = do ci <- liftEither . correctDir =<< getDirectCIWithReactions db user ct itemId @@ -1758,7 +1765,7 @@ getDirectChatItem db User {userId} contactId itemId = ExceptT $ do [sql| SELECT -- ChatItem - i.chat_item_id, i.item_ts, i.item_sent, i.item_content, i.item_text, i.item_status, i.shared_msg_id, + i.chat_item_id, i.item_ts, i.item_sent, i.item_content, i.item_text, i.item_status, i.via_proxy, i.shared_msg_id, i.item_deleted, i.item_deleted_ts, i.item_edited, i.created_at, i.updated_at, i.fwd_from_tag, i.fwd_from_chat_name, i.fwd_from_msg_dir, i.fwd_from_contact_id, i.fwd_from_group_id, i.fwd_from_chat_item_id, i.timed_ttl, i.timed_delete_at, i.item_live, @@ -2001,7 +2008,7 @@ getGroupChatItem db User {userId, userContactId} groupId itemId = ExceptT $ do [sql| SELECT -- ChatItem - i.chat_item_id, i.item_ts, i.item_sent, i.item_content, i.item_text, i.item_status, i.shared_msg_id, + i.chat_item_id, i.item_ts, i.item_sent, i.item_content, i.item_text, i.item_status, i.via_proxy, i.shared_msg_id, i.item_deleted, i.item_deleted_ts, i.item_edited, i.created_at, i.updated_at, i.fwd_from_tag, i.fwd_from_chat_name, i.fwd_from_msg_dir, i.fwd_from_contact_id, i.fwd_from_group_id, i.fwd_from_chat_item_id, i.timed_ttl, i.timed_delete_at, i.item_live, @@ -2105,7 +2112,7 @@ getLocalChatItem db User {userId} folderId itemId = ExceptT $ do [sql| SELECT -- ChatItem - i.chat_item_id, i.item_ts, i.item_sent, i.item_content, i.item_text, i.item_status, i.shared_msg_id, + i.chat_item_id, i.item_ts, i.item_sent, i.item_content, i.item_text, i.item_status, i.via_proxy, i.shared_msg_id, i.item_deleted, i.item_deleted_ts, i.item_edited, i.created_at, i.updated_at, i.fwd_from_tag, i.fwd_from_chat_name, i.fwd_from_msg_dir, i.fwd_from_contact_id, i.fwd_from_group_id, i.fwd_from_chat_item_id, i.timed_ttl, i.timed_delete_at, i.item_live, @@ -2538,12 +2545,23 @@ updateGroupSndStatus db itemId memberId status = do |] (status, currentTs, itemId, memberId) -getGroupSndStatuses :: DB.Connection -> ChatItemId -> IO [(GroupMemberId, CIStatus 'MDSnd)] +setGroupSndViaProxy :: DB.Connection -> ChatItemId -> GroupMemberId -> Bool -> IO () +setGroupSndViaProxy db itemId memberId viaProxy = + DB.execute + db + [sql| + UPDATE group_snd_item_statuses + SET via_proxy = ? + WHERE chat_item_id = ? AND group_member_id = ? + |] + (viaProxy, itemId, memberId) + +getGroupSndStatuses :: DB.Connection -> ChatItemId -> IO [(GroupMemberId, CIStatus 'MDSnd, Maybe Bool)] getGroupSndStatuses db itemId = DB.query db [sql| - SELECT group_member_id, group_snd_item_status + SELECT group_member_id, group_snd_item_status, via_proxy FROM group_snd_item_statuses WHERE chat_item_id = ? |] diff --git a/src/Simplex/Chat/Store/Migrations.hs b/src/Simplex/Chat/Store/Migrations.hs index 2b44778272..43b0729e47 100644 --- a/src/Simplex/Chat/Store/Migrations.hs +++ b/src/Simplex/Chat/Store/Migrations.hs @@ -106,6 +106,7 @@ import Simplex.Chat.Migrations.M20240313_drop_agent_ack_cmd_id import Simplex.Chat.Migrations.M20240324_custom_data import Simplex.Chat.Migrations.M20240402_item_forwarded import Simplex.Chat.Migrations.M20240430_ui_theme +import Simplex.Chat.Migrations.M20240510_chat_items_via_proxy import Simplex.Messaging.Agent.Store.SQLite.Migrations (Migration (..)) schemaMigrations :: [(String, Query, Maybe Query)] @@ -211,7 +212,8 @@ schemaMigrations = ("20240313_drop_agent_ack_cmd_id", m20240313_drop_agent_ack_cmd_id, Just down_m20240313_drop_agent_ack_cmd_id), ("20240324_custom_data", m20240324_custom_data, Just down_m20240324_custom_data), ("20240402_item_forwarded", m20240402_item_forwarded, Just down_m20240402_item_forwarded), - ("20240430_ui_theme", m20240430_ui_theme, Just down_m20240430_ui_theme) + ("20240430_ui_theme", m20240430_ui_theme, Just down_m20240430_ui_theme), + ("20240510_chat_items_via_proxy", m20240510_chat_items_via_proxy, Just down_m20240510_chat_items_via_proxy) ] -- | The list of migrations in ascending order by date From d670b269fd1871b81c5a655684151c322ac55f92 Mon Sep 17 00:00:00 2001 From: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com> Date: Fri, 10 May 2024 18:54:37 +0400 Subject: [PATCH 04/13] error statuses --- src/Simplex/Chat.hs | 31 +++++++++------ src/Simplex/Chat/Messages.hs | 73 ++++++++++++++++++++++++++++++++++-- 2 files changed, 89 insertions(+), 15 deletions(-) diff --git a/src/Simplex/Chat.hs b/src/Simplex/Chat.hs index a2f0bca5f2..6b7061af5a 100644 --- a/src/Simplex/Chat.hs +++ b/src/Simplex/Chat.hs @@ -99,7 +99,7 @@ import Simplex.Messaging.Agent.Store.SQLite (MigrationConfirmation (..), Migrati import Simplex.Messaging.Agent.Store.SQLite.DB (SlowQueryStats (..)) import qualified Simplex.Messaging.Agent.Store.SQLite.DB as DB import qualified Simplex.Messaging.Agent.Store.SQLite.Migrations as Migrations -import Simplex.Messaging.Client (defaultNetworkConfig) +import Simplex.Messaging.Client (ProxyClientError (..), defaultNetworkConfig) import qualified Simplex.Messaging.Crypto as C import Simplex.Messaging.Crypto.File (CryptoFile (..), CryptoFileArgs (..)) import qualified Simplex.Messaging.Crypto.File as CF @@ -112,6 +112,7 @@ import Simplex.Messaging.Protocol (AProtoServerWithAuth (..), AProtocolType (..) import qualified Simplex.Messaging.Protocol as SMP import Simplex.Messaging.ServiceScheme (ServiceScheme (..)) import qualified Simplex.Messaging.TMap as TM +import Simplex.Messaging.Transport (TransportError (..)) import Simplex.Messaging.Transport.Client (defaultSocksProxy) import Simplex.Messaging.Util import Simplex.Messaging.Version @@ -701,7 +702,7 @@ processChatCommand' vr = \case (SCTGroup, SMDSnd) -> do withStore' (`getGroupSndStatuses` itemId) >>= \case [] -> pure Nothing - memStatuses -> pure $ Just $ map (\(x,y,z) -> MemberDeliveryStatus x y z) memStatuses + memStatuses -> pure $ Just $ map (\(x, y, z) -> MemberDeliveryStatus x y z) memStatuses _ -> pure Nothing forwardedFromChatItem <- getForwardedFromItem user ci pure $ CRChatItemInfo user aci ChatItemInfo {itemVersions, memberDeliveryStatuses, forwardedFromChatItem} @@ -4046,10 +4047,8 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = OK -> -- [async agent commands] continuation on receiving OK when (corrId /= "") $ withCompletedCommand conn agentMsg $ \_cmdData -> pure () - MWARN msgId err -> do - -- updateDirectItemStatus (agentWarnToItemStatus) - -- toView - pure () + MWARN msgId err -> + updateDirectItemStatus ct conn msgId $ agentWarnToItemStatus err MERR msgId err -> do updateDirectItemStatus ct conn msgId $ agentErrToItemStatus err toView $ CRChatError (Just user) (ChatErrorAgent err $ Just connEntity) @@ -4433,9 +4432,8 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = OK -> -- [async agent commands] continuation on receiving OK when (corrId /= "") $ withCompletedCommand conn agentMsg $ \_cmdData -> pure () - MWARN msgId err -> do - -- updateGroupItemErrorStatus (agentWarnToItemStatus) - pure () + MWARN msgId err -> + withStore' $ \db -> updateGroupItemErrorStatus db msgId (groupMemberId' m) $ agentWarnToItemStatus err MERR msgId err -> do withStore' $ \db -> updateGroupItemErrorStatus db msgId (groupMemberId' m) $ agentErrToItemStatus err -- group errors are silenced to reduce load on UI event log @@ -4716,8 +4714,19 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = withStore' $ \db -> updateSndMsgDeliveryStatus db connId msgId MDSSndSent agentErrToItemStatus :: AgentErrorType -> CIStatus 'MDSnd - agentErrToItemStatus (SMP AUTH) = CISSndErrorAuth - agentErrToItemStatus err = CISSndError . T.unpack . safeDecodeUtf8 $ strEncode err + agentErrToItemStatus (SMP AUTH) = CISSndDeliveryError SDEAuth + agentErrToItemStatus (SMP QUOTA) = CISSndDeliveryError SDEQuota + agentErrToItemStatus err = CISSndDeliveryError . SDEOther . T.unpack . safeDecodeUtf8 $ strEncode err + + -- see MWARN, serverHostError in agent + agentWarnToItemStatus :: AgentErrorType -> CIStatus 'MDSnd + agentWarnToItemStatus (BROKER _ HOST) = CISSndDeliveryWarning SDWBrokerHost + agentWarnToItemStatus (BROKER _ (SMP.TRANSPORT TEVersion)) = CISSndDeliveryWarning SDWBrokerTransportVersion + agentWarnToItemStatus (SMP (SMP.PROXY (SMP.BROKER HOST))) = CISSndDeliveryWarning SDWProxyHost + agentWarnToItemStatus (SMP (SMP.PROXY (SMP.BROKER (SMP.TRANSPORT TEVersion)))) = CISSndDeliveryWarning SDWProxyTransportVersion + agentWarnToItemStatus (AP.PROXY _ _ (ProxyProtocolError (SMP.PROXY (SMP.BROKER HOST)))) = CISSndDeliveryWarning SDWProxyBrokerHost + agentWarnToItemStatus (AP.PROXY _ _ (ProxyProtocolError (SMP.PROXY (SMP.BROKER (SMP.TRANSPORT TEVersion))))) = CISSndDeliveryWarning SDWProxyBrokerTransportVersion + agentWarnToItemStatus err = CISSndDeliveryWarning . SDWOther . T.unpack . safeDecodeUtf8 $ strEncode err badRcvFileChunk :: RcvFileTransfer -> String -> CM () badRcvFileChunk ft err = diff --git a/src/Simplex/Chat/Messages.hs b/src/Simplex/Chat/Messages.hs index 50ee141a48..3f9e7a7018 100644 --- a/src/Simplex/Chat/Messages.hs +++ b/src/Simplex/Chat/Messages.hs @@ -678,8 +678,10 @@ data CIStatus (d :: MsgDirection) where CISSndNew :: CIStatus 'MDSnd CISSndSent :: SndCIStatusProgress -> CIStatus 'MDSnd CISSndRcvd :: MsgReceiptStatus -> SndCIStatusProgress -> CIStatus 'MDSnd - CISSndErrorAuth :: CIStatus 'MDSnd - CISSndError :: String -> CIStatus 'MDSnd + CISSndErrorAuth :: CIStatus 'MDSnd -- deprecated + CISSndError :: String -> CIStatus 'MDSnd -- deprecated + CISSndDeliveryError :: SndDeliveryError -> CIStatus 'MDSnd + CISSndDeliveryWarning :: SndDeliveryWarning -> CIStatus 'MDSnd CISRcvNew :: CIStatus 'MDRcv CISRcvRead :: CIStatus 'MDRcv CISInvalid :: Text -> CIStatus 'MDSnd @@ -699,6 +701,8 @@ instance MsgDirectionI d => StrEncoding (CIStatus d) where CISSndRcvd msgRcptStatus sndProgress -> "snd_rcvd " <> strEncode msgRcptStatus <> " " <> strEncode sndProgress CISSndErrorAuth -> "snd_error_auth" CISSndError e -> "snd_error " <> encodeUtf8 (T.pack e) + CISSndDeliveryError sde -> "snd_delivery_error " <> strEncode sde + CISSndDeliveryWarning sdw -> "snd_delivery_warning " <> strEncode sdw CISRcvNew -> "rcv_new" CISRcvRead -> "rcv_read" CISInvalid {} -> "invalid" @@ -717,16 +721,69 @@ instance StrEncoding ACIStatus where "snd_rcvd" -> ACIStatus SMDSnd <$> (CISSndRcvd <$> (A.space *> strP) <*> ((A.space *> strP) <|> pure SSPComplete)) "snd_error_auth" -> pure $ ACIStatus SMDSnd CISSndErrorAuth "snd_error" -> ACIStatus SMDSnd . CISSndError . T.unpack . safeDecodeUtf8 <$> (A.space *> A.takeByteString) + "snd_delivery_error" -> ACIStatus SMDSnd . CISSndDeliveryError <$> (A.space *> strP) + "snd_delivery_warning" -> ACIStatus SMDSnd . CISSndDeliveryWarning <$> (A.space *> strP) "rcv_new" -> pure $ ACIStatus SMDRcv CISRcvNew "rcv_read" -> pure $ ACIStatus SMDRcv CISRcvRead _ -> fail "bad status" +data SndDeliveryError + = SDEAuth + | SDEQuota + | SDEOther String + deriving (Eq, Show) + +instance StrEncoding SndDeliveryError where + strEncode = \case + SDEAuth -> "sde_auth" + SDEQuota -> "sde_quota" + SDEOther e -> "sde_other " <> encodeUtf8 (T.pack e) + strP = + A.takeWhile1 (/= ' ') >>= \case + "sde_auth" -> pure SDEAuth + "sde_quota" -> pure SDEQuota + "snd_other" -> SDEOther . T.unpack . safeDecodeUtf8 <$> (A.space *> A.takeByteString) + _ -> fail "bad SndDeliveryError" + +-- see MWARN, serverHostError in agent +data SndDeliveryWarning + = SDWBrokerHost + | SDWBrokerTransportVersion + | SDWProxyHost + | SDWProxyTransportVersion + | SDWProxyBrokerHost + | SDWProxyBrokerTransportVersion + | SDWOther String + deriving (Eq, Show) + +instance StrEncoding SndDeliveryWarning where + strEncode = \case + SDWBrokerHost -> "sdw_broker_host" + SDWBrokerTransportVersion -> "sdw_broker_transport_version" + SDWProxyHost -> "sdw_proxy_host" + SDWProxyTransportVersion -> "sdw_proxy_transport_version" + SDWProxyBrokerHost -> "sdw_proxy_broker_host" + SDWProxyBrokerTransportVersion -> "sdw_proxy_broker_transport_version" + SDWOther e -> "sdw_other " <> encodeUtf8 (T.pack e) + strP = + A.takeWhile1 (/= ' ') >>= \case + "sdw_broker_host" -> pure SDWBrokerHost + "sdw_broker_transport_version" -> pure SDWBrokerTransportVersion + "sdw_proxy_host" -> pure SDWProxyHost + "sdw_proxy_transport_version" -> pure SDWProxyTransportVersion + "sdw_proxy_broker_host" -> pure SDWProxyBrokerHost + "sdw_proxy_broker_transport_version" -> pure SDWProxyBrokerTransportVersion + "sdw_other" -> SDWOther . T.unpack . safeDecodeUtf8 <$> (A.space *> A.takeByteString) + _ -> fail "bad SndDeliveryWarning" + data JSONCIStatus = JCISSndNew | JCISSndSent {sndProgress :: SndCIStatusProgress} | JCISSndRcvd {msgRcptStatus :: MsgReceiptStatus, sndProgress :: SndCIStatusProgress} - | JCISSndErrorAuth - | JCISSndError {agentError :: String} + | JCISSndErrorAuth -- deprecated + | JCISSndError {agentError :: String} -- deprecated + | JCISSndDeliveryError {sndDeliveryError :: SndDeliveryError} + | JCISSndDeliveryWarning {sndDeliveryWarning :: SndDeliveryWarning} | JCISRcvNew | JCISRcvRead | JCISInvalid {text :: Text} @@ -739,6 +796,8 @@ jsonCIStatus = \case CISSndRcvd msgRcptStatus sndProgress -> JCISSndRcvd msgRcptStatus sndProgress CISSndErrorAuth -> JCISSndErrorAuth CISSndError e -> JCISSndError e + CISSndDeliveryError sde -> JCISSndDeliveryError sde + CISSndDeliveryWarning sdw -> JCISSndDeliveryWarning sdw CISRcvNew -> JCISRcvNew CISRcvRead -> JCISRcvRead CISInvalid text -> JCISInvalid text @@ -750,6 +809,8 @@ jsonACIStatus = \case JCISSndRcvd msgRcptStatus sndProgress -> ACIStatus SMDSnd $ CISSndRcvd msgRcptStatus sndProgress JCISSndErrorAuth -> ACIStatus SMDSnd CISSndErrorAuth JCISSndError e -> ACIStatus SMDSnd $ CISSndError e + JCISSndDeliveryError sde -> ACIStatus SMDSnd $ CISSndDeliveryError sde + JCISSndDeliveryWarning sdw -> ACIStatus SMDSnd $ CISSndDeliveryWarning sdw JCISRcvNew -> ACIStatus SMDRcv CISRcvNew JCISRcvRead -> ACIStatus SMDRcv CISRcvRead JCISInvalid text -> ACIStatus SMDSnd $ CISInvalid text @@ -1104,6 +1165,10 @@ $(JQ.deriveJSON defaultJSON ''CITimed) $(JQ.deriveJSON (enumJSON $ dropPrefix "SSP") ''SndCIStatusProgress) +$(JQ.deriveJSON (sumTypeJSON $ dropPrefix "SDE") ''SndDeliveryError) + +$(JQ.deriveJSON (sumTypeJSON $ dropPrefix "SDW") ''SndDeliveryWarning) + $(JQ.deriveJSON (sumTypeJSON $ dropPrefix "JCIS") ''JSONCIStatus) instance MsgDirectionI d => FromJSON (CIStatus d) where From 0e09a2ca080c84380a29d9e4d0fe4457285c9edc Mon Sep 17 00:00:00 2001 From: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com> Date: Mon, 13 May 2024 19:05:55 +0400 Subject: [PATCH 05/13] rework errors --- src/Simplex/Chat.hs | 41 ++++++------ src/Simplex/Chat/Messages.hs | 120 +++++++++++++++++------------------ 2 files changed, 81 insertions(+), 80 deletions(-) diff --git a/src/Simplex/Chat.hs b/src/Simplex/Chat.hs index aa2026840e..c385f9928a 100644 --- a/src/Simplex/Chat.hs +++ b/src/Simplex/Chat.hs @@ -4067,14 +4067,14 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = -- [async agent commands] continuation on receiving OK when (corrId /= "") $ withCompletedCommand conn agentMsg $ \_cmdData -> pure () MWARN msgId err -> - updateDirectItemStatus ct conn msgId $ agentWarnToItemStatus err + updateDirectItemStatus ct conn msgId (CISSndWarning $ agentErrToSndErr err) MERR msgId err -> do - updateDirectItemStatus ct conn msgId $ agentErrToItemStatus err + updateDirectItemStatus ct conn msgId (CISSndError $ agentErrToSndErr err) toView $ CRChatError (Just user) (ChatErrorAgent err $ Just connEntity) incAuthErrCounter connEntity conn err MERRS msgIds err -> do -- error cannot be AUTH error here - updateDirectItemsStatus ct conn (L.toList msgIds) $ agentErrToItemStatus err + updateDirectItemsStatus ct conn (L.toList msgIds) (CISSndError $ agentErrToSndErr err) toView $ CRChatError (Just user) (ChatErrorAgent err $ Just connEntity) ERR err -> do toView $ CRChatError (Just user) (ChatErrorAgent err $ Just connEntity) @@ -4452,14 +4452,14 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = -- [async agent commands] continuation on receiving OK when (corrId /= "") $ withCompletedCommand conn agentMsg $ \_cmdData -> pure () MWARN msgId err -> - withStore' $ \db -> updateGroupItemErrorStatus db msgId (groupMemberId' m) $ agentWarnToItemStatus err + withStore' $ \db -> updateGroupItemErrorStatus db msgId (groupMemberId' m) (CISSndWarning $ agentErrToSndErr err) MERR msgId err -> do - withStore' $ \db -> updateGroupItemErrorStatus db msgId (groupMemberId' m) $ agentErrToItemStatus err + withStore' $ \db -> updateGroupItemErrorStatus db msgId (groupMemberId' m) (CISSndError $ agentErrToSndErr err) -- group errors are silenced to reduce load on UI event log -- toView $ CRChatError (Just user) (ChatErrorAgent err $ Just connEntity) incAuthErrCounter connEntity conn err MERRS msgIds err -> do - let newStatus = agentErrToItemStatus err + let newStatus = CISSndError $ agentErrToSndErr err -- error cannot be AUTH error here withStore' $ \db -> forM_ msgIds $ \msgId -> updateGroupItemErrorStatus db msgId (groupMemberId' m) newStatus `catchAll_` pure () @@ -4732,20 +4732,21 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = sentMsgDeliveryEvent Connection {connId} msgId = withStore' $ \db -> updateSndMsgDeliveryStatus db connId msgId MDSSndSent - agentErrToItemStatus :: AgentErrorType -> CIStatus 'MDSnd - agentErrToItemStatus (SMP _ AUTH) = CISSndDeliveryError SDEAuth - agentErrToItemStatus (SMP _ QUOTA) = CISSndDeliveryError SDEQuota - agentErrToItemStatus err = CISSndDeliveryError . SDEOther . T.unpack . safeDecodeUtf8 $ strEncode err - - -- see MWARN, serverHostError in agent - agentWarnToItemStatus :: AgentErrorType -> CIStatus 'MDSnd - agentWarnToItemStatus (BROKER _ HOST) = CISSndDeliveryWarning SDWBrokerHost - agentWarnToItemStatus (BROKER _ (SMP.TRANSPORT TEVersion)) = CISSndDeliveryWarning SDWBrokerTransportVersion - agentWarnToItemStatus (SMP _ (SMP.PROXY (SMP.BROKER HOST))) = CISSndDeliveryWarning SDWProxyHost - agentWarnToItemStatus (SMP _ (SMP.PROXY (SMP.BROKER (SMP.TRANSPORT TEVersion)))) = CISSndDeliveryWarning SDWProxyTransportVersion - agentWarnToItemStatus (AP.PROXY _ _ (ProxyProtocolError (SMP.PROXY (SMP.BROKER HOST)))) = CISSndDeliveryWarning SDWProxyBrokerHost - agentWarnToItemStatus (AP.PROXY _ _ (ProxyProtocolError (SMP.PROXY (SMP.BROKER (SMP.TRANSPORT TEVersion))))) = CISSndDeliveryWarning SDWProxyBrokerTransportVersion - agentWarnToItemStatus err = CISSndDeliveryWarning . SDWOther . T.unpack . safeDecodeUtf8 $ strEncode err + agentErrToSndErr :: AgentErrorType -> SndError + agentErrToSndErr (SMP _ AUTH) = SndErrAuth + agentErrToSndErr (SMP _ QUOTA) = SndErrQuota + agentErrToSndErr (BROKER _ NETWORK) = SndErrExpired + agentErrToSndErr (BROKER _ TIMEOUT) = SndErrExpired + agentErrToSndErr (BROKER _ e) = SndErrRelay $ brokerHostError e + agentErrToSndErr (SMP proxySrv (SMP.PROXY (SMP.BROKER e))) = SndErrProxy proxySrv $ brokerHostError e + agentErrToSndErr (AP.PROXY proxySrv _ (ProxyProtocolError (SMP.PROXY (SMP.BROKER e)))) = SndErrProxyRelay proxySrv $ brokerHostError e + agentErrToSndErr err = SndErrOther . T.unpack . safeDecodeUtf8 $ strEncode err + + brokerHostError :: BrokerErrorType -> SrvError + brokerHostError e = case e of + HOST -> SrvErrHost + SMP.TRANSPORT TEVersion -> SrvErrVersion + _ -> SrvErrOther . T.unpack . safeDecodeUtf8 $ strEncode e badRcvFileChunk :: RcvFileTransfer -> String -> CM () badRcvFileChunk ft err = diff --git a/src/Simplex/Chat/Messages.hs b/src/Simplex/Chat/Messages.hs index 08f5984779..6fee58c5cb 100644 --- a/src/Simplex/Chat/Messages.hs +++ b/src/Simplex/Chat/Messages.hs @@ -686,9 +686,9 @@ data CIStatus (d :: MsgDirection) where CISSndSent :: SndCIStatusProgress -> CIStatus 'MDSnd CISSndRcvd :: MsgReceiptStatus -> SndCIStatusProgress -> CIStatus 'MDSnd CISSndErrorAuth :: CIStatus 'MDSnd -- deprecated - CISSndError :: String -> CIStatus 'MDSnd -- deprecated - CISSndDeliveryError :: SndDeliveryError -> CIStatus 'MDSnd - CISSndDeliveryWarning :: SndDeliveryWarning -> CIStatus 'MDSnd + -- CISSndError :: String -> CIStatus 'MDSnd -- deprecated + CISSndError :: SndError -> CIStatus 'MDSnd + CISSndWarning :: SndError -> CIStatus 'MDSnd CISRcvNew :: CIStatus 'MDRcv CISRcvRead :: CIStatus 'MDRcv CISInvalid :: Text -> CIStatus 'MDSnd @@ -707,9 +707,9 @@ instance MsgDirectionI d => StrEncoding (CIStatus d) where CISSndSent sndProgress -> "snd_sent " <> strEncode sndProgress CISSndRcvd msgRcptStatus sndProgress -> "snd_rcvd " <> strEncode msgRcptStatus <> " " <> strEncode sndProgress CISSndErrorAuth -> "snd_error_auth" - CISSndError e -> "snd_error " <> encodeUtf8 (T.pack e) - CISSndDeliveryError sde -> "snd_delivery_error " <> strEncode sde - CISSndDeliveryWarning sdw -> "snd_delivery_warning " <> strEncode sdw + -- CISSndError e -> "snd_error " <> encodeUtf8 (T.pack e) -- deprecated + CISSndError sndErr -> "snd_error " <> strEncode sndErr + CISSndWarning sndErr -> "snd_warning " <> strEncode sndErr CISRcvNew -> "rcv_new" CISRcvRead -> "rcv_read" CISInvalid {} -> "invalid" @@ -727,70 +727,72 @@ instance StrEncoding ACIStatus where "snd_sent" -> ACIStatus SMDSnd . CISSndSent <$> ((A.space *> strP) <|> pure SSPComplete) "snd_rcvd" -> ACIStatus SMDSnd <$> (CISSndRcvd <$> (A.space *> strP) <*> ((A.space *> strP) <|> pure SSPComplete)) "snd_error_auth" -> pure $ ACIStatus SMDSnd CISSndErrorAuth - "snd_error" -> ACIStatus SMDSnd . CISSndError . T.unpack . safeDecodeUtf8 <$> (A.space *> A.takeByteString) - "snd_delivery_error" -> ACIStatus SMDSnd . CISSndDeliveryError <$> (A.space *> strP) - "snd_delivery_warning" -> ACIStatus SMDSnd . CISSndDeliveryWarning <$> (A.space *> strP) + "snd_error" -> + ACIStatus SMDSnd . CISSndError + <$> ( (A.space *> strP) + <|> (SndErrOther . T.unpack . safeDecodeUtf8 <$> (A.space *> A.takeByteString)) -- deprecated + ) + "snd_warning" -> ACIStatus SMDSnd . CISSndWarning <$> (A.space *> strP) "rcv_new" -> pure $ ACIStatus SMDRcv CISRcvNew "rcv_read" -> pure $ ACIStatus SMDRcv CISRcvRead _ -> fail "bad status" -data SndDeliveryError - = SDEAuth - | SDEQuota - | SDEOther String +-- see serverHostError in agent +data SndError + = SndErrAuth + | SndErrQuota + | SndErrExpired -- TIMEOUT/NETWORK errors + | SndErrRelay SrvError -- BROKER errors (other than TIMEOUT/NETWORK) + | SndErrProxy String SrvError -- SMP PROXY errors, String is proxy server + | SndErrProxyRelay String SrvError -- PROXY BROKER errors, String is proxy server + | SndErrOther String -- other errors, String is error deriving (Eq, Show) -instance StrEncoding SndDeliveryError where +data SrvError + = SrvErrHost + | SrvErrVersion + | SrvErrOther String + deriving (Eq, Show) + +instance StrEncoding SndError where strEncode = \case - SDEAuth -> "sde_auth" - SDEQuota -> "sde_quota" - SDEOther e -> "sde_other " <> encodeUtf8 (T.pack e) + SndErrAuth -> "auth" + SndErrQuota -> "quota" + SndErrExpired -> "expired" + SndErrRelay srvErr -> "relay " <> strEncode srvErr + SndErrProxy proxy srvErr -> "proxy " <> encodeUtf8 (T.pack proxy) <> " " <> strEncode srvErr + SndErrProxyRelay proxy srvErr -> "proxy_relay " <> encodeUtf8 (T.pack proxy) <> " " <> strEncode srvErr + SndErrOther e -> "other " <> encodeUtf8 (T.pack e) strP = A.takeWhile1 (/= ' ') >>= \case - "sde_auth" -> pure SDEAuth - "sde_quota" -> pure SDEQuota - "snd_other" -> SDEOther . T.unpack . safeDecodeUtf8 <$> (A.space *> A.takeByteString) - _ -> fail "bad SndDeliveryError" - --- see MWARN, serverHostError in agent -data SndDeliveryWarning - = SDWBrokerHost - | SDWBrokerTransportVersion - | SDWProxyHost - | SDWProxyTransportVersion - | SDWProxyBrokerHost - | SDWProxyBrokerTransportVersion - | SDWOther String - deriving (Eq, Show) - -instance StrEncoding SndDeliveryWarning where + "auth" -> pure SndErrAuth + "quota" -> pure SndErrQuota + "expired" -> pure SndErrExpired + "relay" -> SndErrRelay <$> (A.space *> strP) + "proxy" -> SndErrProxy . T.unpack . safeDecodeUtf8 <$> (A.space *> A.takeWhile1 (/= ' ') <* A.space) <*> strP + "proxy_relay" -> SndErrProxyRelay . T.unpack . safeDecodeUtf8 <$> (A.space *> A.takeWhile1 (/= ' ') <* A.space) <*> strP + "other" -> SndErrOther . T.unpack . safeDecodeUtf8 <$> (A.space *> A.takeByteString) + _ -> fail "bad SndError" + +instance StrEncoding SrvError where strEncode = \case - SDWBrokerHost -> "sdw_broker_host" - SDWBrokerTransportVersion -> "sdw_broker_transport_version" - SDWProxyHost -> "sdw_proxy_host" - SDWProxyTransportVersion -> "sdw_proxy_transport_version" - SDWProxyBrokerHost -> "sdw_proxy_broker_host" - SDWProxyBrokerTransportVersion -> "sdw_proxy_broker_transport_version" - SDWOther e -> "sdw_other " <> encodeUtf8 (T.pack e) + SrvErrHost -> "host" + SrvErrVersion -> "version" + SrvErrOther e -> "other " <> encodeUtf8 (T.pack e) strP = A.takeWhile1 (/= ' ') >>= \case - "sdw_broker_host" -> pure SDWBrokerHost - "sdw_broker_transport_version" -> pure SDWBrokerTransportVersion - "sdw_proxy_host" -> pure SDWProxyHost - "sdw_proxy_transport_version" -> pure SDWProxyTransportVersion - "sdw_proxy_broker_host" -> pure SDWProxyBrokerHost - "sdw_proxy_broker_transport_version" -> pure SDWProxyBrokerTransportVersion - "sdw_other" -> SDWOther . T.unpack . safeDecodeUtf8 <$> (A.space *> A.takeByteString) - _ -> fail "bad SndDeliveryWarning" + "host" -> pure SrvErrHost + "version" -> pure SrvErrVersion + "other" -> SrvErrOther . T.unpack . safeDecodeUtf8 <$> (A.space *> A.takeByteString) + _ -> fail "bad SrvError" data JSONCIStatus = JCISSndNew | JCISSndSent {sndProgress :: SndCIStatusProgress} | JCISSndRcvd {msgRcptStatus :: MsgReceiptStatus, sndProgress :: SndCIStatusProgress} | JCISSndErrorAuth -- deprecated - | JCISSndError {agentError :: String} -- deprecated - | JCISSndDeliveryError {sndDeliveryError :: SndDeliveryError} - | JCISSndDeliveryWarning {sndDeliveryWarning :: SndDeliveryWarning} + | JCISSndError {agentError :: SndError} + | JCISSndWarning {agentError :: SndError} | JCISRcvNew | JCISRcvRead | JCISInvalid {text :: Text} @@ -802,9 +804,8 @@ jsonCIStatus = \case CISSndSent sndProgress -> JCISSndSent sndProgress CISSndRcvd msgRcptStatus sndProgress -> JCISSndRcvd msgRcptStatus sndProgress CISSndErrorAuth -> JCISSndErrorAuth - CISSndError e -> JCISSndError e - CISSndDeliveryError sde -> JCISSndDeliveryError sde - CISSndDeliveryWarning sdw -> JCISSndDeliveryWarning sdw + CISSndError sndErr -> JCISSndError sndErr + CISSndWarning sndErr -> JCISSndWarning sndErr CISRcvNew -> JCISRcvNew CISRcvRead -> JCISRcvRead CISInvalid text -> JCISInvalid text @@ -815,9 +816,8 @@ jsonACIStatus = \case JCISSndSent sndProgress -> ACIStatus SMDSnd $ CISSndSent sndProgress JCISSndRcvd msgRcptStatus sndProgress -> ACIStatus SMDSnd $ CISSndRcvd msgRcptStatus sndProgress JCISSndErrorAuth -> ACIStatus SMDSnd CISSndErrorAuth - JCISSndError e -> ACIStatus SMDSnd $ CISSndError e - JCISSndDeliveryError sde -> ACIStatus SMDSnd $ CISSndDeliveryError sde - JCISSndDeliveryWarning sdw -> ACIStatus SMDSnd $ CISSndDeliveryWarning sdw + JCISSndError sndErr -> ACIStatus SMDSnd $ CISSndError sndErr + JCISSndWarning sndErr -> ACIStatus SMDSnd $ CISSndWarning sndErr JCISRcvNew -> ACIStatus SMDRcv CISRcvNew JCISRcvRead -> ACIStatus SMDRcv CISRcvRead JCISInvalid text -> ACIStatus SMDSnd $ CISInvalid text @@ -1172,9 +1172,9 @@ $(JQ.deriveJSON defaultJSON ''CITimed) $(JQ.deriveJSON (enumJSON $ dropPrefix "SSP") ''SndCIStatusProgress) -$(JQ.deriveJSON (sumTypeJSON $ dropPrefix "SDE") ''SndDeliveryError) +$(JQ.deriveJSON (sumTypeJSON $ dropPrefix "SrvErr") ''SrvError) -$(JQ.deriveJSON (sumTypeJSON $ dropPrefix "SDW") ''SndDeliveryWarning) +$(JQ.deriveJSON (sumTypeJSON $ dropPrefix "SndErr") ''SndError) $(JQ.deriveJSON (sumTypeJSON $ dropPrefix "JCIS") ''JSONCIStatus) From 592d4dc1a7b6499f804f9d546aa695b91d06f50d Mon Sep 17 00:00:00 2001 From: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com> Date: Mon, 13 May 2024 19:14:56 +0400 Subject: [PATCH 06/13] proxy expired errors --- src/Simplex/Chat.hs | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/Simplex/Chat.hs b/src/Simplex/Chat.hs index c385f9928a..2432b45c3a 100644 --- a/src/Simplex/Chat.hs +++ b/src/Simplex/Chat.hs @@ -4735,18 +4735,22 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = agentErrToSndErr :: AgentErrorType -> SndError agentErrToSndErr (SMP _ AUTH) = SndErrAuth agentErrToSndErr (SMP _ QUOTA) = SndErrQuota - agentErrToSndErr (BROKER _ NETWORK) = SndErrExpired - agentErrToSndErr (BROKER _ TIMEOUT) = SndErrExpired - agentErrToSndErr (BROKER _ e) = SndErrRelay $ brokerHostError e - agentErrToSndErr (SMP proxySrv (SMP.PROXY (SMP.BROKER e))) = SndErrProxy proxySrv $ brokerHostError e - agentErrToSndErr (AP.PROXY proxySrv _ (ProxyProtocolError (SMP.PROXY (SMP.BROKER e)))) = SndErrProxyRelay proxySrv $ brokerHostError e + agentErrToSndErr (BROKER _ e) = brokerError e SndErrRelay + agentErrToSndErr (SMP proxySrv (SMP.PROXY (SMP.BROKER e))) = brokerError e $ SndErrProxy proxySrv + agentErrToSndErr (AP.PROXY proxySrv _ (ProxyProtocolError (SMP.PROXY (SMP.BROKER e)))) = brokerError e $ SndErrProxyRelay proxySrv agentErrToSndErr err = SndErrOther . T.unpack . safeDecodeUtf8 $ strEncode err - brokerHostError :: BrokerErrorType -> SrvError - brokerHostError e = case e of - HOST -> SrvErrHost - SMP.TRANSPORT TEVersion -> SrvErrVersion - _ -> SrvErrOther . T.unpack . safeDecodeUtf8 $ strEncode e + brokerError :: BrokerErrorType -> (SrvError -> SndError) -> SndError + brokerError e wrapErr = case e of + NETWORK -> SndErrExpired + TIMEOUT -> SndErrExpired + _ -> wrapErr brokerHostError + where + brokerHostError :: SrvError + brokerHostError = case e of + HOST -> SrvErrHost + SMP.TRANSPORT TEVersion -> SrvErrVersion + _ -> SrvErrOther . T.unpack . safeDecodeUtf8 $ strEncode e badRcvFileChunk :: RcvFileTransfer -> String -> CM () badRcvFileChunk ft err = From 60181127fe1fac34f4dca1d2db9769ab7bc3d93e Mon Sep 17 00:00:00 2001 From: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com> Date: Mon, 13 May 2024 20:57:35 +0400 Subject: [PATCH 07/13] corrections --- src/Simplex/Chat.hs | 4 ++-- src/Simplex/Chat/Messages.hs | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Simplex/Chat.hs b/src/Simplex/Chat.hs index 2432b45c3a..792a88a14c 100644 --- a/src/Simplex/Chat.hs +++ b/src/Simplex/Chat.hs @@ -4738,7 +4738,7 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = agentErrToSndErr (BROKER _ e) = brokerError e SndErrRelay agentErrToSndErr (SMP proxySrv (SMP.PROXY (SMP.BROKER e))) = brokerError e $ SndErrProxy proxySrv agentErrToSndErr (AP.PROXY proxySrv _ (ProxyProtocolError (SMP.PROXY (SMP.BROKER e)))) = brokerError e $ SndErrProxyRelay proxySrv - agentErrToSndErr err = SndErrOther . T.unpack . safeDecodeUtf8 $ strEncode err + agentErrToSndErr err = SndErrOther . safeDecodeUtf8 $ strEncode err brokerError :: BrokerErrorType -> (SrvError -> SndError) -> SndError brokerError e wrapErr = case e of @@ -4750,7 +4750,7 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = brokerHostError = case e of HOST -> SrvErrHost SMP.TRANSPORT TEVersion -> SrvErrVersion - _ -> SrvErrOther . T.unpack . safeDecodeUtf8 $ strEncode e + _ -> SrvErrOther . safeDecodeUtf8 $ strEncode e badRcvFileChunk :: RcvFileTransfer -> String -> CM () badRcvFileChunk ft err = diff --git a/src/Simplex/Chat/Messages.hs b/src/Simplex/Chat/Messages.hs index 6fee58c5cb..084fadcce7 100644 --- a/src/Simplex/Chat/Messages.hs +++ b/src/Simplex/Chat/Messages.hs @@ -730,7 +730,7 @@ instance StrEncoding ACIStatus where "snd_error" -> ACIStatus SMDSnd . CISSndError <$> ( (A.space *> strP) - <|> (SndErrOther . T.unpack . safeDecodeUtf8 <$> (A.space *> A.takeByteString)) -- deprecated + <|> (SndErrOther . safeDecodeUtf8 <$> (A.space *> A.takeByteString)) -- deprecated ) "snd_warning" -> ACIStatus SMDSnd . CISSndWarning <$> (A.space *> strP) "rcv_new" -> pure $ ACIStatus SMDRcv CISRcvNew @@ -745,13 +745,13 @@ data SndError | SndErrRelay SrvError -- BROKER errors (other than TIMEOUT/NETWORK) | SndErrProxy String SrvError -- SMP PROXY errors, String is proxy server | SndErrProxyRelay String SrvError -- PROXY BROKER errors, String is proxy server - | SndErrOther String -- other errors, String is error + | SndErrOther Text -- other errors deriving (Eq, Show) data SrvError = SrvErrHost | SrvErrVersion - | SrvErrOther String + | SrvErrOther Text deriving (Eq, Show) instance StrEncoding SndError where @@ -762,7 +762,7 @@ instance StrEncoding SndError where SndErrRelay srvErr -> "relay " <> strEncode srvErr SndErrProxy proxy srvErr -> "proxy " <> encodeUtf8 (T.pack proxy) <> " " <> strEncode srvErr SndErrProxyRelay proxy srvErr -> "proxy_relay " <> encodeUtf8 (T.pack proxy) <> " " <> strEncode srvErr - SndErrOther e -> "other " <> encodeUtf8 (T.pack e) + SndErrOther e -> "other " <> encodeUtf8 e strP = A.takeWhile1 (/= ' ') >>= \case "auth" -> pure SndErrAuth @@ -771,19 +771,19 @@ instance StrEncoding SndError where "relay" -> SndErrRelay <$> (A.space *> strP) "proxy" -> SndErrProxy . T.unpack . safeDecodeUtf8 <$> (A.space *> A.takeWhile1 (/= ' ') <* A.space) <*> strP "proxy_relay" -> SndErrProxyRelay . T.unpack . safeDecodeUtf8 <$> (A.space *> A.takeWhile1 (/= ' ') <* A.space) <*> strP - "other" -> SndErrOther . T.unpack . safeDecodeUtf8 <$> (A.space *> A.takeByteString) + "other" -> SndErrOther . safeDecodeUtf8 <$> (A.space *> A.takeByteString) _ -> fail "bad SndError" instance StrEncoding SrvError where strEncode = \case SrvErrHost -> "host" SrvErrVersion -> "version" - SrvErrOther e -> "other " <> encodeUtf8 (T.pack e) + SrvErrOther e -> "other " <> encodeUtf8 e strP = A.takeWhile1 (/= ' ') >>= \case "host" -> pure SrvErrHost "version" -> pure SrvErrVersion - "other" -> SrvErrOther . T.unpack . safeDecodeUtf8 <$> (A.space *> A.takeByteString) + "other" -> SrvErrOther . safeDecodeUtf8 <$> (A.space *> A.takeByteString) _ -> fail "bad SrvError" data JSONCIStatus From ba0e93f028300223f67c7be971a1b4c4a2c9f3a7 Mon Sep 17 00:00:00 2001 From: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com> Date: Mon, 13 May 2024 21:16:27 +0400 Subject: [PATCH 08/13] move backwards compatibile parser to new type --- src/Simplex/Chat/Messages.hs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/Simplex/Chat/Messages.hs b/src/Simplex/Chat/Messages.hs index 084fadcce7..830c58329b 100644 --- a/src/Simplex/Chat/Messages.hs +++ b/src/Simplex/Chat/Messages.hs @@ -727,11 +727,7 @@ instance StrEncoding ACIStatus where "snd_sent" -> ACIStatus SMDSnd . CISSndSent <$> ((A.space *> strP) <|> pure SSPComplete) "snd_rcvd" -> ACIStatus SMDSnd <$> (CISSndRcvd <$> (A.space *> strP) <*> ((A.space *> strP) <|> pure SSPComplete)) "snd_error_auth" -> pure $ ACIStatus SMDSnd CISSndErrorAuth - "snd_error" -> - ACIStatus SMDSnd . CISSndError - <$> ( (A.space *> strP) - <|> (SndErrOther . safeDecodeUtf8 <$> (A.space *> A.takeByteString)) -- deprecated - ) + "snd_error" -> ACIStatus SMDSnd . CISSndError <$> (A.space *> strP) "snd_warning" -> ACIStatus SMDSnd . CISSndWarning <$> (A.space *> strP) "rcv_new" -> pure $ ACIStatus SMDRcv CISRcvNew "rcv_read" -> pure $ ACIStatus SMDRcv CISRcvRead @@ -772,7 +768,7 @@ instance StrEncoding SndError where "proxy" -> SndErrProxy . T.unpack . safeDecodeUtf8 <$> (A.space *> A.takeWhile1 (/= ' ') <* A.space) <*> strP "proxy_relay" -> SndErrProxyRelay . T.unpack . safeDecodeUtf8 <$> (A.space *> A.takeWhile1 (/= ' ') <* A.space) <*> strP "other" -> SndErrOther . safeDecodeUtf8 <$> (A.space *> A.takeByteString) - _ -> fail "bad SndError" + s -> SndErrOther . safeDecodeUtf8 . (s <>) <$> A.takeByteString -- for deprecated CISSndError instance StrEncoding SrvError where strEncode = \case From 7286f61f24fe02c7321f88cceb6c1e3baf0b7bd3 Mon Sep 17 00:00:00 2001 From: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com> Date: Tue, 14 May 2024 10:53:00 +0400 Subject: [PATCH 09/13] update simplexmq --- cabal.project | 2 +- scripts/nix/sha256map.nix | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cabal.project b/cabal.project index d4809ac9bb..a2d08f2fbe 100644 --- a/cabal.project +++ b/cabal.project @@ -12,7 +12,7 @@ constraints: zip +disable-bzip2 +disable-zstd source-repository-package type: git location: https://github.com/simplex-chat/simplexmq.git - tag: c4c983348f099eafb1f16b44b80840b6de070e4d + tag: 00a2dde727d5e71b1fd14c59f57f285a01667cda source-repository-package type: git diff --git a/scripts/nix/sha256map.nix b/scripts/nix/sha256map.nix index b74dc7348e..793f67f79b 100644 --- a/scripts/nix/sha256map.nix +++ b/scripts/nix/sha256map.nix @@ -1,5 +1,5 @@ { - "https://github.com/simplex-chat/simplexmq.git"."c4c983348f099eafb1f16b44b80840b6de070e4d" = "1h6q2yjxjar1j6l89dwin0qdxrgzr7lsyvg9gz98piz4bz49fsb4"; + "https://github.com/simplex-chat/simplexmq.git"."00a2dde727d5e71b1fd14c59f57f285a01667cda" = "12h8i2j3sd208l9l8xiwrpby3p116wipsmrr0wpdxac3g1qgpfrs"; "https://github.com/simplex-chat/hs-socks.git"."a30cc7a79a08d8108316094f8f2f82a0c5e1ac51" = "0yasvnr7g91k76mjkamvzab2kvlb1g5pspjyjn2fr6v83swjhj38"; "https://github.com/simplex-chat/direct-sqlcipher.git"."f814ee68b16a9447fbb467ccc8f29bdd3546bfd9" = "1ql13f4kfwkbaq7nygkxgw84213i0zm7c1a8hwvramayxl38dq5d"; "https://github.com/simplex-chat/sqlcipher-simple.git"."a46bd361a19376c5211f1058908fc0ae6bf42446" = "1z0r78d8f0812kxbgsm735qf6xx8lvaz27k1a0b4a2m0sshpd5gl"; From e9fb68db792b72fa8c246dd042f259fb3acc15b0 Mon Sep 17 00:00:00 2001 From: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com> Date: Tue, 14 May 2024 12:35:54 +0400 Subject: [PATCH 10/13] names --- src/Simplex/Chat/Messages.hs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Simplex/Chat/Messages.hs b/src/Simplex/Chat/Messages.hs index 830c58329b..f32c9e3a25 100644 --- a/src/Simplex/Chat/Messages.hs +++ b/src/Simplex/Chat/Messages.hs @@ -738,16 +738,16 @@ data SndError = SndErrAuth | SndErrQuota | SndErrExpired -- TIMEOUT/NETWORK errors - | SndErrRelay SrvError -- BROKER errors (other than TIMEOUT/NETWORK) - | SndErrProxy String SrvError -- SMP PROXY errors, String is proxy server - | SndErrProxyRelay String SrvError -- PROXY BROKER errors, String is proxy server - | SndErrOther Text -- other errors + | SndErrRelay {srvError :: SrvError} -- BROKER errors (other than TIMEOUT/NETWORK) + | SndErrProxy {proxyServer :: String, srvError :: SrvError} -- SMP PROXY errors + | SndErrProxyRelay {proxyServer :: String, srvError :: SrvError} -- PROXY BROKER errors + | SndErrOther {sndError :: Text} -- other errors deriving (Eq, Show) data SrvError = SrvErrHost | SrvErrVersion - | SrvErrOther Text + | SrvErrOther {srvError :: Text} deriving (Eq, Show) instance StrEncoding SndError where From ac6ded3bd09199e1b6648ece8f7cdee6b7b6a6e5 Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin Date: Tue, 14 May 2024 12:26:15 +0100 Subject: [PATCH 11/13] refactor, style --- src/Simplex/Chat.hs | 44 ++++++++++++++++-------------------- src/Simplex/Chat/Messages.hs | 4 +--- 2 files changed, 21 insertions(+), 27 deletions(-) diff --git a/src/Simplex/Chat.hs b/src/Simplex/Chat.hs index 2b0760b7a9..2c204e6180 100644 --- a/src/Simplex/Chat.hs +++ b/src/Simplex/Chat.hs @@ -4072,14 +4072,14 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = -- [async agent commands] continuation on receiving OK when (corrId /= "") $ withCompletedCommand conn agentMsg $ \_cmdData -> pure () MWARN msgId err -> - updateDirectItemStatus ct conn msgId (CISSndWarning $ agentErrToSndErr err) + updateDirectItemStatus ct conn msgId (CISSndWarning $ agentSndError err) MERR msgId err -> do - updateDirectItemStatus ct conn msgId (CISSndError $ agentErrToSndErr err) + updateDirectItemStatus ct conn msgId (CISSndError $ agentSndError err) toView $ CRChatError (Just user) (ChatErrorAgent err $ Just connEntity) incAuthErrCounter connEntity conn err MERRS msgIds err -> do -- error cannot be AUTH error here - updateDirectItemsStatus ct conn (L.toList msgIds) (CISSndError $ agentErrToSndErr err) + updateDirectItemsStatus ct conn (L.toList msgIds) (CISSndError $ agentSndError err) toView $ CRChatError (Just user) (ChatErrorAgent err $ Just connEntity) ERR err -> do toView $ CRChatError (Just user) (ChatErrorAgent err $ Just connEntity) @@ -4457,14 +4457,14 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = -- [async agent commands] continuation on receiving OK when (corrId /= "") $ withCompletedCommand conn agentMsg $ \_cmdData -> pure () MWARN msgId err -> - withStore' $ \db -> updateGroupItemErrorStatus db msgId (groupMemberId' m) (CISSndWarning $ agentErrToSndErr err) + withStore' $ \db -> updateGroupItemErrorStatus db msgId (groupMemberId' m) (CISSndWarning $ agentSndError err) MERR msgId err -> do - withStore' $ \db -> updateGroupItemErrorStatus db msgId (groupMemberId' m) (CISSndError $ agentErrToSndErr err) + withStore' $ \db -> updateGroupItemErrorStatus db msgId (groupMemberId' m) (CISSndError $ agentSndError err) -- group errors are silenced to reduce load on UI event log -- toView $ CRChatError (Just user) (ChatErrorAgent err $ Just connEntity) incAuthErrCounter connEntity conn err MERRS msgIds err -> do - let newStatus = CISSndError $ agentErrToSndErr err + let newStatus = CISSndError $ agentSndError err -- error cannot be AUTH error here withStore' $ \db -> forM_ msgIds $ \msgId -> updateGroupItemErrorStatus db msgId (groupMemberId' m) newStatus `catchAll_` pure () @@ -4737,25 +4737,21 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = sentMsgDeliveryEvent Connection {connId} msgId = withStore' $ \db -> updateSndMsgDeliveryStatus db connId msgId MDSSndSent - agentErrToSndErr :: AgentErrorType -> SndError - agentErrToSndErr (SMP _ AUTH) = SndErrAuth - agentErrToSndErr (SMP _ QUOTA) = SndErrQuota - agentErrToSndErr (BROKER _ e) = brokerError e SndErrRelay - agentErrToSndErr (SMP proxySrv (SMP.PROXY (SMP.BROKER e))) = brokerError e $ SndErrProxy proxySrv - agentErrToSndErr (AP.PROXY proxySrv _ (ProxyProtocolError (SMP.PROXY (SMP.BROKER e)))) = brokerError e $ SndErrProxyRelay proxySrv - agentErrToSndErr err = SndErrOther . safeDecodeUtf8 $ strEncode err - - brokerError :: BrokerErrorType -> (SrvError -> SndError) -> SndError - brokerError e wrapErr = case e of - NETWORK -> SndErrExpired - TIMEOUT -> SndErrExpired - _ -> wrapErr brokerHostError + agentSndError :: AgentErrorType -> SndError + agentSndError = \case + SMP _ AUTH -> SndErrAuth + SMP _ QUOTA -> SndErrQuota + BROKER _ e -> brokerError SndErrRelay e + SMP proxySrv (SMP.PROXY (SMP.BROKER e)) -> brokerError (SndErrProxy proxySrv) e + AP.PROXY proxySrv _ (ProxyProtocolError (SMP.PROXY (SMP.BROKER e))) -> brokerError (SndErrProxyRelay proxySrv) e + e -> SndErrOther . safeDecodeUtf8 $ strEncode e where - brokerHostError :: SrvError - brokerHostError = case e of - HOST -> SrvErrHost - SMP.TRANSPORT TEVersion -> SrvErrVersion - _ -> SrvErrOther . safeDecodeUtf8 $ strEncode e + brokerError srvErr = \case + NETWORK -> SndErrExpired + TIMEOUT -> SndErrExpired + HOST -> srvErr SrvErrHost + SMP.TRANSPORT TEVersion -> srvErr SrvErrVersion + e -> srvErr . SrvErrOther . safeDecodeUtf8 $ strEncode e badRcvFileChunk :: RcvFileTransfer -> String -> CM () badRcvFileChunk ft err = diff --git a/src/Simplex/Chat/Messages.hs b/src/Simplex/Chat/Messages.hs index f32c9e3a25..068e2250f9 100644 --- a/src/Simplex/Chat/Messages.hs +++ b/src/Simplex/Chat/Messages.hs @@ -686,7 +686,6 @@ data CIStatus (d :: MsgDirection) where CISSndSent :: SndCIStatusProgress -> CIStatus 'MDSnd CISSndRcvd :: MsgReceiptStatus -> SndCIStatusProgress -> CIStatus 'MDSnd CISSndErrorAuth :: CIStatus 'MDSnd -- deprecated - -- CISSndError :: String -> CIStatus 'MDSnd -- deprecated CISSndError :: SndError -> CIStatus 'MDSnd CISSndWarning :: SndError -> CIStatus 'MDSnd CISRcvNew :: CIStatus 'MDRcv @@ -707,7 +706,6 @@ instance MsgDirectionI d => StrEncoding (CIStatus d) where CISSndSent sndProgress -> "snd_sent " <> strEncode sndProgress CISSndRcvd msgRcptStatus sndProgress -> "snd_rcvd " <> strEncode msgRcptStatus <> " " <> strEncode sndProgress CISSndErrorAuth -> "snd_error_auth" - -- CISSndError e -> "snd_error " <> encodeUtf8 (T.pack e) -- deprecated CISSndError sndErr -> "snd_error " <> strEncode sndErr CISSndWarning sndErr -> "snd_warning " <> strEncode sndErr CISRcvNew -> "rcv_new" @@ -768,7 +766,7 @@ instance StrEncoding SndError where "proxy" -> SndErrProxy . T.unpack . safeDecodeUtf8 <$> (A.space *> A.takeWhile1 (/= ' ') <* A.space) <*> strP "proxy_relay" -> SndErrProxyRelay . T.unpack . safeDecodeUtf8 <$> (A.space *> A.takeWhile1 (/= ' ') <* A.space) <*> strP "other" -> SndErrOther . safeDecodeUtf8 <$> (A.space *> A.takeByteString) - s -> SndErrOther . safeDecodeUtf8 . (s <>) <$> A.takeByteString -- for deprecated CISSndError + s -> SndErrOther . safeDecodeUtf8 . (s <>) <$> A.takeByteString -- for backward compatibility with `CISSndError String` instance StrEncoding SrvError where strEncode = \case From 70fec230f5fb8a735af3dbf02ff71257f3ddd48a Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin Date: Tue, 14 May 2024 22:29:04 +0100 Subject: [PATCH 12/13] simplexmq --- cabal.project | 2 +- scripts/nix/sha256map.nix | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cabal.project b/cabal.project index a2d08f2fbe..7ff4fa4a10 100644 --- a/cabal.project +++ b/cabal.project @@ -12,7 +12,7 @@ constraints: zip +disable-bzip2 +disable-zstd source-repository-package type: git location: https://github.com/simplex-chat/simplexmq.git - tag: 00a2dde727d5e71b1fd14c59f57f285a01667cda + tag: 2d2cc86bd82a5c604901ae813a6cbcc21f3e2024 source-repository-package type: git diff --git a/scripts/nix/sha256map.nix b/scripts/nix/sha256map.nix index 793f67f79b..6ac9ac1a99 100644 --- a/scripts/nix/sha256map.nix +++ b/scripts/nix/sha256map.nix @@ -1,5 +1,5 @@ { - "https://github.com/simplex-chat/simplexmq.git"."00a2dde727d5e71b1fd14c59f57f285a01667cda" = "12h8i2j3sd208l9l8xiwrpby3p116wipsmrr0wpdxac3g1qgpfrs"; + "https://github.com/simplex-chat/simplexmq.git"."2d2cc86bd82a5c604901ae813a6cbcc21f3e2024" = "0gny4qywp2hda9fqs5gm3zkr8vd4jriy3iqp7ap7bwc12is6n8zw"; "https://github.com/simplex-chat/hs-socks.git"."a30cc7a79a08d8108316094f8f2f82a0c5e1ac51" = "0yasvnr7g91k76mjkamvzab2kvlb1g5pspjyjn2fr6v83swjhj38"; "https://github.com/simplex-chat/direct-sqlcipher.git"."f814ee68b16a9447fbb467ccc8f29bdd3546bfd9" = "1ql13f4kfwkbaq7nygkxgw84213i0zm7c1a8hwvramayxl38dq5d"; "https://github.com/simplex-chat/sqlcipher-simple.git"."a46bd361a19376c5211f1058908fc0ae6bf42446" = "1z0r78d8f0812kxbgsm735qf6xx8lvaz27k1a0b4a2m0sshpd5gl"; From 9d0a5467e9ccccc1f1538331f35516f432fe7e74 Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin Date: Tue, 14 May 2024 23:07:48 +0100 Subject: [PATCH 13/13] refactor --- src/Simplex/Chat.hs | 5 +---- src/Simplex/Chat/Messages.hs | 3 ++- src/Simplex/Chat/Store/Messages.hs | 22 +++++++++++++--------- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/Simplex/Chat.hs b/src/Simplex/Chat.hs index 2c204e6180..f2f6fb2783 100644 --- a/src/Simplex/Chat.hs +++ b/src/Simplex/Chat.hs @@ -700,10 +700,7 @@ processChatCommand' vr = \case (,) <$> getAChatItem db vr user chatRef itemId <*> liftIO (getChatItemVersions db itemId) let itemVersions = if null versions then maybeToList $ mkItemVersion ci else versions memberDeliveryStatuses <- case (cType, dir) of - (SCTGroup, SMDSnd) -> do - withStore' (`getGroupSndStatuses` itemId) >>= \case - [] -> pure Nothing - memStatuses -> pure $ Just $ map (\(x, y, z) -> MemberDeliveryStatus x y z) memStatuses + (SCTGroup, SMDSnd) -> L.nonEmpty <$> withStore' (`getGroupSndStatuses` itemId) _ -> pure Nothing forwardedFromChatItem <- getForwardedFromItem user ci pure $ CRChatItemInfo user aci ChatItemInfo {itemVersions, memberDeliveryStatuses, forwardedFromChatItem} diff --git a/src/Simplex/Chat/Messages.hs b/src/Simplex/Chat/Messages.hs index 068e2250f9..83417efa59 100644 --- a/src/Simplex/Chat/Messages.hs +++ b/src/Simplex/Chat/Messages.hs @@ -29,6 +29,7 @@ import qualified Data.ByteString.Lazy.Char8 as LB import Data.Char (isSpace) import Data.Int (Int64) import Data.Kind (Constraint) +import Data.List.NonEmpty (NonEmpty) import Data.Maybe (fromMaybe, isJust, isNothing) import Data.Text (Text) import qualified Data.Text as T @@ -1098,7 +1099,7 @@ instance TextEncoding CIForwardedFromTag where data ChatItemInfo = ChatItemInfo { itemVersions :: [ChatItemVersion], - memberDeliveryStatuses :: Maybe [MemberDeliveryStatus], + memberDeliveryStatuses :: Maybe (NonEmpty MemberDeliveryStatus), forwardedFromChatItem :: Maybe AChatItem } deriving (Show) diff --git a/src/Simplex/Chat/Store/Messages.hs b/src/Simplex/Chat/Store/Messages.hs index c78eaada7d..b0a0495c16 100644 --- a/src/Simplex/Chat/Store/Messages.hs +++ b/src/Simplex/Chat/Store/Messages.hs @@ -2556,16 +2556,20 @@ setGroupSndViaProxy db itemId memberId viaProxy = |] (viaProxy, itemId, memberId) -getGroupSndStatuses :: DB.Connection -> ChatItemId -> IO [(GroupMemberId, CIStatus 'MDSnd, Maybe Bool)] +getGroupSndStatuses :: DB.Connection -> ChatItemId -> IO [MemberDeliveryStatus] getGroupSndStatuses db itemId = - DB.query - db - [sql| - SELECT group_member_id, group_snd_item_status, via_proxy - FROM group_snd_item_statuses - WHERE chat_item_id = ? - |] - (Only itemId) + map memStatus + <$> DB.query + db + [sql| + SELECT group_member_id, group_snd_item_status, via_proxy + FROM group_snd_item_statuses + WHERE chat_item_id = ? + |] + (Only itemId) + where + memStatus (groupMemberId, memberDeliveryStatus, sentViaProxy) = + MemberDeliveryStatus {groupMemberId, memberDeliveryStatus, sentViaProxy} getGroupSndStatusCounts :: DB.Connection -> ChatItemId -> IO [(CIStatus 'MDSnd, Int)] getGroupSndStatusCounts db itemId =