Compare commits

...

1 Commits

Author SHA1 Message Date
Evgeny Poberezkin c418e91970 core: move DRG state to IORefs 2024-08-29 11:45:28 +01:00
15 changed files with 45 additions and 42 deletions
+1 -1
View File
@@ -12,7 +12,7 @@ constraints: zip +disable-bzip2 +disable-zstd
source-repository-package source-repository-package
type: git type: git
location: https://github.com/simplex-chat/simplexmq.git location: https://github.com/simplex-chat/simplexmq.git
tag: 56986f82c89b04beae84a61208db8b55eb0098e3 tag: f940ce234ebc3831c3bbedb3fc653907cdb7a064
source-repository-package source-repository-package
type: git type: git
+1 -1
View File
@@ -1,5 +1,5 @@
{ {
"https://github.com/simplex-chat/simplexmq.git"."56986f82c89b04beae84a61208db8b55eb0098e3" = "0vqvdnm560xrfq7kjsghdbpk67vn4hcdpp58dfqgh9l2c9f79bin"; "https://github.com/simplex-chat/simplexmq.git"."f940ce234ebc3831c3bbedb3fc653907cdb7a064" = "16y4ix3v7sd8qd1qfrxk0nshvh0p1a415y2sw5am2jhx0mjr8w1q";
"https://github.com/simplex-chat/hs-socks.git"."a30cc7a79a08d8108316094f8f2f82a0c5e1ac51" = "0yasvnr7g91k76mjkamvzab2kvlb1g5pspjyjn2fr6v83swjhj38"; "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/direct-sqlcipher.git"."f814ee68b16a9447fbb467ccc8f29bdd3546bfd9" = "1ql13f4kfwkbaq7nygkxgw84213i0zm7c1a8hwvramayxl38dq5d";
"https://github.com/simplex-chat/sqlcipher-simple.git"."a46bd361a19376c5211f1058908fc0ae6bf42446" = "1z0r78d8f0812kxbgsm735qf6xx8lvaz27k1a0b4a2m0sshpd5gl"; "https://github.com/simplex-chat/sqlcipher-simple.git"."a46bd361a19376c5211f1058908fc0ae6bf42446" = "1z0r78d8f0812kxbgsm735qf6xx8lvaz27k1a0b4a2m0sshpd5gl";
+9 -8
View File
@@ -40,6 +40,7 @@ import Data.Either (fromRight, lefts, partitionEithers, rights)
import Data.Fixed (div') import Data.Fixed (div')
import Data.Functor (($>)) import Data.Functor (($>))
import Data.Functor.Identity import Data.Functor.Identity
import Data.IORef (IORef)
import Data.Int (Int64) import Data.Int (Int64)
import Data.List (find, foldl', isSuffixOf, mapAccumL, partition, sortOn) import Data.List (find, foldl', isSuffixOf, mapAccumL, partition, sortOn)
import Data.List.NonEmpty (NonEmpty (..), nonEmpty, toList, (<|)) import Data.List.NonEmpty (NonEmpty (..), nonEmpty, toList, (<|))
@@ -1057,7 +1058,7 @@ processChatCommand' vr = \case
fsNewPath <- liftIO $ filesFolder `uniqueCombine` fileName fsNewPath <- liftIO $ filesFolder `uniqueCombine` fileName
liftIO $ B.writeFile fsNewPath "" -- create empty file liftIO $ B.writeFile fsNewPath "" -- create empty file
encrypt <- chatReadVar encryptLocalFiles encrypt <- chatReadVar encryptLocalFiles
cfArgs <- if encrypt then Just <$> (atomically . CF.randomArgs =<< asks random) else pure Nothing cfArgs <- if encrypt then Just <$> (liftIO . CF.randomArgs =<< asks random) else pure Nothing
let toCF = CryptoFile fsNewPath cfArgs let toCF = CryptoFile fsNewPath cfArgs
-- to keep forwarded file in case original is deleted -- to keep forwarded file in case original is deleted
liftIOEither $ runExceptT $ withExceptT (ChatError . CEInternalError . show) $ copyCryptoFile (fromCF {filePath = fsFromPath} :: CryptoFile) toCF liftIOEither $ runExceptT $ withExceptT (ChatError . CEInternalError . show) $ copyCryptoFile (fromCF {filePath = fsFromPath} :: CryptoFile) toCF
@@ -1264,9 +1265,9 @@ processChatCommand' vr = \case
calls <- asks currentCalls calls <- asks currentCalls
withContactLock "sendCallInvitation" contactId $ do withContactLock "sendCallInvitation" contactId $ do
g <- asks random g <- asks random
callId <- atomically $ CallId <$> C.randomBytes 16 g callId <- liftIO $ CallId <$> C.randomBytes 16 g
callUUID <- UUID.toText <$> liftIO V4.nextRandom callUUID <- UUID.toText <$> liftIO V4.nextRandom
dhKeyPair <- atomically $ if encryptedCall callType then Just <$> C.generateKeyPair g else pure Nothing dhKeyPair <- liftIO $ if encryptedCall callType then Just <$> C.generateKeyPair g else pure Nothing
let invitation = CallInvitation {callType, callDhPubKey = fst <$> dhKeyPair} let invitation = CallInvitation {callType, callDhPubKey = fst <$> dhKeyPair}
callState = CallInvitationSent {localCallType = callType, localDhPrivKey = snd <$> dhKeyPair} callState = CallInvitationSent {localCallType = callType, localDhPrivKey = snd <$> dhKeyPair}
(msg, _) <- sendDirectContactMessage user ct (XCallInv callId invitation) (msg, _) <- sendDirectContactMessage user ct (XCallInv callId invitation)
@@ -2234,7 +2235,7 @@ processChatCommand' vr = \case
SetFileToReceive fileId userApprovedRelays encrypted_ -> withUser $ \_ -> do SetFileToReceive fileId userApprovedRelays encrypted_ -> withUser $ \_ -> do
withFileLock "setFileToReceive" fileId . procCmd $ do withFileLock "setFileToReceive" fileId . procCmd $ do
encrypt <- (`fromMaybe` encrypted_) <$> chatReadVar encryptLocalFiles encrypt <- (`fromMaybe` encrypted_) <$> chatReadVar encryptLocalFiles
cfArgs <- if encrypt then Just <$> (atomically . CF.randomArgs =<< asks random) else pure Nothing cfArgs <- if encrypt then Just <$> (liftIO . CF.randomArgs =<< asks random) else pure Nothing
withStore' $ \db -> setRcvFileToReceive db fileId userApprovedRelays cfArgs withStore' $ \db -> setRcvFileToReceive db fileId userApprovedRelays cfArgs
ok_ ok_
CancelFile fileId -> withUser $ \user@User {userId} -> CancelFile fileId -> withUser $ \user@User {userId} ->
@@ -2719,7 +2720,7 @@ processChatCommand' vr = \case
forM_ (timed_ >>= timedDeleteAt') $ forM_ (timed_ >>= timedDeleteAt') $
startProximateTimedItemThread user (ChatRef CTDirect contactId, chatItemId' ci) startProximateTimedItemThread user (ChatRef CTDirect contactId, chatItemId' ci)
drgRandomBytes :: Int -> CM ByteString drgRandomBytes :: Int -> CM ByteString
drgRandomBytes n = asks random >>= atomically . C.randomBytes n drgRandomBytes n = asks random >>= liftIO . C.randomBytes n
privateGetUser :: UserId -> CM User privateGetUser :: UserId -> CM User
privateGetUser userId = privateGetUser userId =
tryChatError (withStore (`getUser` userId)) >>= \case tryChatError (withStore (`getUser` userId)) >>= \case
@@ -3244,7 +3245,7 @@ toFSFilePath f =
setFileToEncrypt :: RcvFileTransfer -> CM RcvFileTransfer setFileToEncrypt :: RcvFileTransfer -> CM RcvFileTransfer
setFileToEncrypt ft@RcvFileTransfer {fileId} = do setFileToEncrypt ft@RcvFileTransfer {fileId} = do
cfArgs <- atomically . CF.randomArgs =<< asks random cfArgs <- liftIO . CF.randomArgs =<< asks random
withStore' $ \db -> setFileCryptoArgs db fileId cfArgs withStore' $ \db -> setFileCryptoArgs db fileId cfArgs
pure (ft :: RcvFileTransfer) {cryptoArgs = Just cfArgs} pure (ft :: RcvFileTransfer) {cryptoArgs = Just cfArgs}
@@ -5956,7 +5957,7 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
if featureAllowed SCFCalls forContact ct if featureAllowed SCFCalls forContact ct
then do then do
g <- asks random g <- asks random
dhKeyPair <- atomically $ if encryptedCall callType then Just <$> C.generateKeyPair g else pure Nothing dhKeyPair <- liftIO $ if encryptedCall callType then Just <$> C.generateKeyPair g else pure Nothing
ci <- saveCallItem CISCallPending ci <- saveCallItem CISCallPending
callUUID <- UUID.toText <$> liftIO V4.nextRandom callUUID <- UUID.toText <$> liftIO V4.nextRandom
let sharedKey = C.Key . C.dhBytes' <$> (C.dh' <$> callDhPubKey <*> (snd <$> dhKeyPair)) let sharedKey = C.Key . C.dhBytes' <$> (C.dh' <$> callDhPubKey <*> (snd <$> dhKeyPair))
@@ -6875,7 +6876,7 @@ createSndMessages idsEvents = do
vr <- chatVersionRange' vr <- chatVersionRange'
withStoreBatch $ \db -> fmap (createMsg db g vr) idsEvents withStoreBatch $ \db -> fmap (createMsg db g vr) idsEvents
where where
createMsg :: DB.Connection -> TVar ChaChaDRG -> VersionRangeChat -> (ConnOrGroupId, ChatMsgEvent e) -> IO (Either ChatError SndMessage) createMsg :: DB.Connection -> IORef ChaChaDRG -> VersionRangeChat -> (ConnOrGroupId, ChatMsgEvent e) -> IO (Either ChatError SndMessage)
createMsg db g vr (connOrGroupId, evnt) = runExceptT $ do createMsg db g vr (connOrGroupId, evnt) = runExceptT $ do
withExceptT ChatErrorStore $ createNewSndMessage db g connOrGroupId evnt encodeMessage withExceptT ChatErrorStore $ createNewSndMessage db g connOrGroupId evnt encodeMessage
where where
+2 -1
View File
@@ -36,6 +36,7 @@ import Data.ByteString.Char8 (ByteString)
import qualified Data.ByteString.Char8 as B import qualified Data.ByteString.Char8 as B
import Data.Char (ord) import Data.Char (ord)
import Data.Constraint (Dict (..)) import Data.Constraint (Dict (..))
import Data.IORef (IORef)
import Data.Int (Int64) import Data.Int (Int64)
import Data.List.NonEmpty (NonEmpty) import Data.List.NonEmpty (NonEmpty)
import Data.Map.Strict (Map) import Data.Map.Strict (Map)
@@ -209,7 +210,7 @@ data ChatController = ChatController
agentAsync :: TVar (Maybe (Async (), Maybe (Async ()))), agentAsync :: TVar (Maybe (Async (), Maybe (Async ()))),
chatStore :: SQLiteStore, chatStore :: SQLiteStore,
chatStoreChanged :: TVar Bool, -- if True, chat should be fully restarted chatStoreChanged :: TVar Bool, -- if True, chat should be fully restarted
random :: TVar ChaChaDRG, random :: IORef ChaChaDRG,
eventSeq :: TVar Int, eventSeq :: TVar Int,
inputQ :: TBQueue String, inputQ :: TBQueue String,
outputQ :: TBQueue (Maybe CorrId, Maybe RemoteHostId, ChatResponse), outputQ :: TBQueue (Maybe CorrId, Maybe RemoteHostId, ChatResponse),
+3 -3
View File
@@ -42,7 +42,7 @@ import qualified Simplex.Messaging.Crypto.File as CF
import Simplex.Messaging.Encoding.String import Simplex.Messaging.Encoding.String
import Simplex.Messaging.Parsers (dropPrefix, sumTypeJSON) import Simplex.Messaging.Parsers (dropPrefix, sumTypeJSON)
import Simplex.Messaging.Util (catchAll) import Simplex.Messaging.Util (catchAll)
import UnliftIO (Handle, IOMode (..), atomically, withFile) import UnliftIO (Handle, IOMode (..), withFile)
data WriteFileResult data WriteFileResult
= WFResult {cryptoArgs :: CryptoFileArgs} = WFResult {cryptoArgs :: CryptoFileArgs}
@@ -60,7 +60,7 @@ cChatWriteFile cc cPath ptr len = do
chatWriteFile :: ChatController -> FilePath -> ByteString -> IO WriteFileResult chatWriteFile :: ChatController -> FilePath -> ByteString -> IO WriteFileResult
chatWriteFile ChatController {random} path s = do chatWriteFile ChatController {random} path s = do
cfArgs <- atomically $ CF.randomArgs random cfArgs <- CF.randomArgs random
let file = CryptoFile path $ Just cfArgs let file = CryptoFile path $ Just cfArgs
either WFError (\_ -> WFResult cfArgs) either WFError (\_ -> WFResult cfArgs)
<$> runCatchExceptT (withExceptT show $ CF.writeFile file $ LB.fromStrict s) <$> runCatchExceptT (withExceptT show $ CF.writeFile file $ LB.fromStrict s)
@@ -104,7 +104,7 @@ chatEncryptFile ChatController {random} fromPath toPath =
either WFError WFResult <$> runCatchExceptT encrypt either WFError WFResult <$> runCatchExceptT encrypt
where where
encrypt = do encrypt = do
cfArgs <- atomically $ CF.randomArgs random cfArgs <- liftIO $ CF.randomArgs random
encryptFile fromPath toPath cfArgs encryptFile fromPath toPath cfArgs
pure cfArgs pure cfArgs
+1 -2
View File
@@ -26,7 +26,6 @@ import Foreign.StablePtr
import Simplex.Chat.Controller (ChatController (..)) import Simplex.Chat.Controller (ChatController (..))
import Simplex.Chat.Mobile.Shared import Simplex.Chat.Mobile.Shared
import qualified Simplex.Messaging.Crypto as C import qualified Simplex.Messaging.Crypto as C
import UnliftIO (atomically)
cChatEncryptMedia :: StablePtr ChatController -> CString -> Ptr Word8 -> CInt -> IO CString cChatEncryptMedia :: StablePtr ChatController -> CString -> Ptr Word8 -> CInt -> IO CString
cChatEncryptMedia = cTransformMedia . chatEncryptMedia cChatEncryptMedia = cTransformMedia . chatEncryptMedia
@@ -48,7 +47,7 @@ chatEncryptMedia cc keyStr frame = do
ChatController {random} <- liftIO $ deRefStablePtr cc ChatController {random} <- liftIO $ deRefStablePtr cc
len <- checkFrameLen frame len <- checkFrameLen frame
key <- decodeKey keyStr key <- decodeKey keyStr
iv <- atomically $ C.randomGCMIV random iv <- liftIO $ C.randomGCMIV random
(tag, frame') <- withExceptT show $ C.encryptAESNoPad key iv $ B.take len frame (tag, frame') <- withExceptT show $ C.encryptAESNoPad key iv $ B.take len frame
pure $ frame' <> BA.convert (C.unAuthTag tag) <> C.unGCMIV iv pure $ frame' <> BA.convert (C.unAuthTag tag) <> C.unGCMIV iv
+1 -1
View File
@@ -352,7 +352,7 @@ storeRemoteFile rhId encrypted_ localPath = do
tmpDir <- lift getChatTempDirectory tmpDir <- lift getChatTempDirectory
createDirectoryIfMissing True tmpDir createDirectoryIfMissing True tmpDir
tmpFile <- liftIO $ tmpDir `uniqueCombine` takeFileName localPath tmpFile <- liftIO $ tmpDir `uniqueCombine` takeFileName localPath
cfArgs <- atomically . CF.randomArgs =<< asks random cfArgs <- liftIO . CF.randomArgs =<< asks random
liftError (ChatError . CEFileWrite tmpFile) $ encryptFile localPath tmpFile cfArgs liftError (ChatError . CEFileWrite tmpFile) $ encryptFile localPath tmpFile cfArgs
pure $ CryptoFile tmpFile $ Just cfArgs pure $ CryptoFile tmpFile $ Just cfArgs
+1 -1
View File
@@ -24,7 +24,7 @@ type EncryptedFile = ((Handle, Word32), C.CbNonce, LC.SbState)
prepareEncryptedFile :: RemoteCrypto -> (Handle, Word32) -> ExceptT RemoteProtocolError IO EncryptedFile prepareEncryptedFile :: RemoteCrypto -> (Handle, Word32) -> ExceptT RemoteProtocolError IO EncryptedFile
prepareEncryptedFile RemoteCrypto {drg, hybridKey} f = do prepareEncryptedFile RemoteCrypto {drg, hybridKey} f = do
nonce <- atomically $ C.randomCbNonce drg nonce <- liftIO $ C.randomCbNonce drg
sbState <- liftEitherWith (const $ PRERemoteControl RCEEncrypt) $ LC.kcbInit hybridKey nonce sbState <- liftEitherWith (const $ PRERemoteControl RCEEncrypt) $ LC.kcbInit hybridKey nonce
pure (f, nonce, sbState) pure (f, nonce, sbState)
+2 -1
View File
@@ -16,6 +16,7 @@ import Control.Exception (Exception)
import Crypto.Random (ChaChaDRG) import Crypto.Random (ChaChaDRG)
import qualified Data.Aeson.TH as J import qualified Data.Aeson.TH as J
import Data.ByteString (ByteString) import Data.ByteString (ByteString)
import Data.IORef (IORef)
import Data.Int (Int64) import Data.Int (Int64)
import Data.Text (Text) import Data.Text (Text)
import Data.Word (Word16) import Data.Word (Word16)
@@ -40,7 +41,7 @@ data RemoteHostClient = RemoteHostClient
} }
data RemoteCrypto = RemoteCrypto data RemoteCrypto = RemoteCrypto
{ drg :: TVar ChaChaDRG, { drg :: IORef ChaChaDRG,
counter :: TVar Int64, counter :: TVar Int64,
sessionCode :: ByteString, sessionCode :: ByteString,
hybridKey :: KEMHybridSecret, hybridKey :: KEMHybridSecret,
+6 -6
View File
@@ -127,6 +127,7 @@ import Control.Monad.IO.Class
import Crypto.Random (ChaChaDRG) import Crypto.Random (ChaChaDRG)
import Data.Bifunctor (second) import Data.Bifunctor (second)
import Data.Either (rights) import Data.Either (rights)
import Data.IORef (IORef)
import Data.Int (Int64) import Data.Int (Int64)
import Data.List (partition, sortOn) import Data.List (partition, sortOn)
import Data.Maybe (catMaybes, fromMaybe, isJust, isNothing) import Data.Maybe (catMaybes, fromMaybe, isJust, isNothing)
@@ -151,7 +152,6 @@ import Simplex.Messaging.Crypto.Ratchet (pattern PQEncOff, pattern PQSupportOff)
import Simplex.Messaging.Protocol (SubscriptionMode (..)) import Simplex.Messaging.Protocol (SubscriptionMode (..))
import Simplex.Messaging.Util (eitherToMaybe, ($>>=), (<$$>)) import Simplex.Messaging.Util (eitherToMaybe, ($>>=), (<$$>))
import Simplex.Messaging.Version import Simplex.Messaging.Version
import UnliftIO.STM
type GroupInfoRow = (Int64, GroupName, GroupName, Text, Maybe Text, Maybe ImageData, Maybe ProfileId, Maybe MsgFilter, Maybe Bool, Bool, Maybe GroupPreferences) :. (UTCTime, UTCTime, Maybe UTCTime, Maybe UTCTime, Maybe UIThemeEntityOverrides, Maybe CustomData) :. GroupMemberRow type GroupInfoRow = (Int64, GroupName, GroupName, Text, Maybe Text, Maybe ImageData, Maybe ProfileId, Maybe MsgFilter, Maybe Bool, Bool, Maybe GroupPreferences) :. (UTCTime, UTCTime, Maybe UTCTime, Maybe UTCTime, Maybe UIThemeEntityOverrides, Maybe CustomData) :. GroupMemberRow
@@ -311,7 +311,7 @@ getGroupAndMember db User {userId, userContactId} groupMemberId vr =
in (groupInfo, (member :: GroupMember) {activeConn = toMaybeConnection vr connRow}) in (groupInfo, (member :: GroupMember) {activeConn = toMaybeConnection vr connRow})
-- | creates completely new group with a single member - the current user -- | creates completely new group with a single member - the current user
createNewGroup :: DB.Connection -> VersionRangeChat -> TVar ChaChaDRG -> User -> GroupProfile -> Maybe Profile -> ExceptT StoreError IO GroupInfo createNewGroup :: DB.Connection -> VersionRangeChat -> IORef ChaChaDRG -> User -> GroupProfile -> Maybe Profile -> ExceptT StoreError IO GroupInfo
createNewGroup db vr gVar user@User {userId} groupProfile incognitoProfile = ExceptT $ do createNewGroup db vr gVar user@User {userId} groupProfile incognitoProfile = ExceptT $ do
let GroupProfile {displayName, fullName, description, image, groupPreferences} = groupProfile let GroupProfile {displayName, fullName, description, image, groupPreferences} = groupProfile
fullGroupPreferences = mergeGroupPreferences groupPreferences fullGroupPreferences = mergeGroupPreferences groupPreferences
@@ -798,7 +798,7 @@ getGroupInvitation db vr user groupId =
firstRow fromOnly (SEGroupNotFound groupId) $ firstRow fromOnly (SEGroupNotFound groupId) $
DB.query db "SELECT g.inv_queue_info FROM groups g WHERE g.group_id = ? AND g.user_id = ?" (groupId, userId) DB.query db "SELECT g.inv_queue_info FROM groups g WHERE g.group_id = ? AND g.user_id = ?" (groupId, userId)
createNewContactMember :: DB.Connection -> TVar ChaChaDRG -> User -> GroupInfo -> Contact -> GroupMemberRole -> ConnId -> ConnReqInvitation -> SubscriptionMode -> ExceptT StoreError IO GroupMember createNewContactMember :: DB.Connection -> IORef ChaChaDRG -> User -> GroupInfo -> Contact -> GroupMemberRole -> ConnId -> ConnReqInvitation -> SubscriptionMode -> ExceptT StoreError IO GroupMember
createNewContactMember _ _ _ _ Contact {localDisplayName, activeConn = Nothing} _ _ _ _ = throwError $ SEContactNotReady localDisplayName createNewContactMember _ _ _ _ Contact {localDisplayName, activeConn = Nothing} _ _ _ _ = throwError $ SEContactNotReady localDisplayName
createNewContactMember db gVar User {userId, userContactId} GroupInfo {groupId, membership} Contact {contactId, localDisplayName, profile, activeConn = Just Connection {connChatVersion, peerChatVRange}} memberRole agentConnId connRequest subMode = createNewContactMember db gVar User {userId, userContactId} GroupInfo {groupId, membership} Contact {contactId, localDisplayName, profile, activeConn = Just Connection {connChatVersion, peerChatVRange}} memberRole agentConnId connRequest subMode =
createWithRandomId gVar $ \memId -> do createWithRandomId gVar $ \memId -> do
@@ -847,7 +847,7 @@ createNewContactMember db gVar User {userId, userContactId} GroupInfo {groupId,
:. (minV, maxV) :. (minV, maxV)
) )
createNewContactMemberAsync :: DB.Connection -> TVar ChaChaDRG -> User -> GroupInfo -> Contact -> GroupMemberRole -> (CommandId, ConnId) -> VersionChat -> VersionRangeChat -> SubscriptionMode -> ExceptT StoreError IO () createNewContactMemberAsync :: DB.Connection -> IORef ChaChaDRG -> User -> GroupInfo -> Contact -> GroupMemberRole -> (CommandId, ConnId) -> VersionChat -> VersionRangeChat -> SubscriptionMode -> ExceptT StoreError IO ()
createNewContactMemberAsync db gVar user@User {userId, userContactId} GroupInfo {groupId, membership} Contact {contactId, localDisplayName, profile} memberRole (cmdId, agentConnId) chatV peerChatVRange subMode = createNewContactMemberAsync db gVar user@User {userId, userContactId} GroupInfo {groupId, membership} Contact {contactId, localDisplayName, profile} memberRole (cmdId, agentConnId) chatV peerChatVRange subMode =
createWithRandomId gVar $ \memId -> do createWithRandomId gVar $ \memId -> do
createdAt <- liftIO getCurrentTime createdAt <- liftIO getCurrentTime
@@ -872,7 +872,7 @@ createNewContactMemberAsync db gVar user@User {userId, userContactId} GroupInfo
:. (minV, maxV) :. (minV, maxV)
) )
createAcceptedMember :: DB.Connection -> TVar ChaChaDRG -> User -> GroupInfo -> UserContactRequest -> GroupMemberRole -> ExceptT StoreError IO (GroupMemberId, MemberId) createAcceptedMember :: DB.Connection -> IORef ChaChaDRG -> User -> GroupInfo -> UserContactRequest -> GroupMemberRole -> ExceptT StoreError IO (GroupMemberId, MemberId)
createAcceptedMember createAcceptedMember
db db
gVar gVar
@@ -1544,7 +1544,7 @@ getMatchingMemberContacts db vr user@User {userId} GroupMember {memberProfile =
AND p.display_name = ? AND p.full_name = ? AND p.display_name = ? AND p.full_name = ?
|] |]
createSentProbe :: DB.Connection -> TVar ChaChaDRG -> UserId -> ContactOrMember -> ExceptT StoreError IO (Probe, Int64) createSentProbe :: DB.Connection -> IORef ChaChaDRG -> UserId -> ContactOrMember -> ExceptT StoreError IO (Probe, Int64)
createSentProbe db gVar userId to = createSentProbe db gVar userId to =
createWithRandomBytes 32 gVar $ \probe -> do createWithRandomBytes 32 gVar $ \probe -> do
currentTs <- getCurrentTime currentTs <- getCurrentTime
+2 -1
View File
@@ -124,6 +124,7 @@ import Crypto.Random (ChaChaDRG)
import Data.Bifunctor (first) import Data.Bifunctor (first)
import Data.ByteString.Char8 (ByteString) import Data.ByteString.Char8 (ByteString)
import Data.Either (fromRight, rights) import Data.Either (fromRight, rights)
import Data.IORef (IORef)
import Data.Int (Int64) import Data.Int (Int64)
import Data.List (sortBy) import Data.List (sortBy)
import Data.Maybe (fromMaybe, isJust, mapMaybe) import Data.Maybe (fromMaybe, isJust, mapMaybe)
@@ -176,7 +177,7 @@ deleteGroupChatItemsMessages db User {userId} GroupInfo {groupId} = do
DB.execute db "DELETE FROM chat_item_reactions WHERE group_id = ?" (Only groupId) DB.execute db "DELETE FROM chat_item_reactions WHERE group_id = ?" (Only groupId)
DB.execute db "DELETE FROM chat_items WHERE user_id = ? AND group_id = ?" (userId, groupId) DB.execute db "DELETE FROM chat_items WHERE user_id = ? AND group_id = ?" (userId, groupId)
createNewSndMessage :: MsgEncodingI e => DB.Connection -> TVar ChaChaDRG -> ConnOrGroupId -> ChatMsgEvent e -> (SharedMsgId -> EncodedChatMessage) -> ExceptT StoreError IO SndMessage createNewSndMessage :: MsgEncodingI e => DB.Connection -> IORef ChaChaDRG -> ConnOrGroupId -> ChatMsgEvent e -> (SharedMsgId -> EncodedChatMessage) -> ExceptT StoreError IO SndMessage
createNewSndMessage db gVar connOrGroupId chatMsgEvent encodeMessage = createNewSndMessage db gVar connOrGroupId chatMsgEvent encodeMessage =
createWithRandomId' gVar $ \sharedMsgId -> createWithRandomId' gVar $ \sharedMsgId ->
case encodeMessage (SharedMsgId sharedMsgId) of case encodeMessage (SharedMsgId sharedMsgId) of
+7 -7
View File
@@ -20,6 +20,7 @@ import Crypto.Random (ChaChaDRG)
import qualified Data.Aeson.TH as J import qualified Data.Aeson.TH as J
import qualified Data.ByteString.Base64 as B64 import qualified Data.ByteString.Base64 as B64
import Data.ByteString.Char8 (ByteString) import Data.ByteString.Char8 (ByteString)
import Data.IORef (IORef)
import Data.Int (Int64) import Data.Int (Int64)
import Data.Maybe (fromMaybe, isJust, listToMaybe) import Data.Maybe (fromMaybe, isJust, listToMaybe)
import Data.Text (Text) import Data.Text (Text)
@@ -44,7 +45,6 @@ import Simplex.Messaging.Parsers (dropPrefix, sumTypeJSON)
import Simplex.Messaging.Protocol (SubscriptionMode (..)) import Simplex.Messaging.Protocol (SubscriptionMode (..))
import Simplex.Messaging.Util (allFinally) import Simplex.Messaging.Util (allFinally)
import Simplex.Messaging.Version import Simplex.Messaging.Version
import UnliftIO.STM
data ChatLockEntity data ChatLockEntity
= CLInvitation ByteString = CLInvitation ByteString
@@ -488,16 +488,16 @@ withLocalDisplayName db userId displayName action = getLdnSuffix >>= (`tryCreate
|] |]
(ldn, displayName, ldnSuffix, userId, ts, ts) (ldn, displayName, ldnSuffix, userId, ts, ts)
createWithRandomId :: forall a. TVar ChaChaDRG -> (ByteString -> IO a) -> ExceptT StoreError IO a createWithRandomId :: forall a. IORef ChaChaDRG -> (ByteString -> IO a) -> ExceptT StoreError IO a
createWithRandomId = createWithRandomBytes 12 createWithRandomId = createWithRandomBytes 12
createWithRandomId' :: forall a. TVar ChaChaDRG -> (ByteString -> IO (Either StoreError a)) -> ExceptT StoreError IO a createWithRandomId' :: forall a. IORef ChaChaDRG -> (ByteString -> IO (Either StoreError a)) -> ExceptT StoreError IO a
createWithRandomId' = createWithRandomBytes' 12 createWithRandomId' = createWithRandomBytes' 12
createWithRandomBytes :: forall a. Int -> TVar ChaChaDRG -> (ByteString -> IO a) -> ExceptT StoreError IO a createWithRandomBytes :: forall a. Int -> IORef ChaChaDRG -> (ByteString -> IO a) -> ExceptT StoreError IO a
createWithRandomBytes size gVar create = createWithRandomBytes' size gVar (fmap Right . create) createWithRandomBytes size gVar create = createWithRandomBytes' size gVar (fmap Right . create)
createWithRandomBytes' :: forall a. Int -> TVar ChaChaDRG -> (ByteString -> IO (Either StoreError a)) -> ExceptT StoreError IO a createWithRandomBytes' :: forall a. Int -> IORef ChaChaDRG -> (ByteString -> IO (Either StoreError a)) -> ExceptT StoreError IO a
createWithRandomBytes' size gVar create = tryCreate 3 createWithRandomBytes' size gVar create = tryCreate 3
where where
tryCreate :: Int -> ExceptT StoreError IO a tryCreate :: Int -> ExceptT StoreError IO a
@@ -510,8 +510,8 @@ createWithRandomBytes' size gVar create = tryCreate 3
| SQL.sqlError e == SQL.ErrorConstraint -> tryCreate (n - 1) | SQL.sqlError e == SQL.ErrorConstraint -> tryCreate (n - 1)
| otherwise -> throwError . SEInternalError $ show e | otherwise -> throwError . SEInternalError $ show e
encodedRandomBytes :: TVar ChaChaDRG -> Int -> IO ByteString encodedRandomBytes :: IORef ChaChaDRG -> Int -> IO ByteString
encodedRandomBytes gVar n = atomically $ B64.encode <$> C.randomBytes n gVar encodedRandomBytes gVar n = B64.encode <$> C.randomBytes n gVar
assertNotUser :: DB.Connection -> User -> Contact -> ExceptT StoreError IO () assertNotUser :: DB.Connection -> User -> Contact -> ExceptT StoreError IO ()
assertNotUser db User {userId} Contact {contactId, localDisplayName} = do assertNotUser db User {userId} Contact {contactId, localDisplayName} = do
+1
View File
@@ -442,6 +442,7 @@ smpServerCfg =
logStatsStartTime = 0, logStatsStartTime = 0,
serverStatsLogFile = "tests/smp-server-stats.daily.log", serverStatsLogFile = "tests/smp-server-stats.daily.log",
serverStatsBackupFile = Nothing, serverStatsBackupFile = Nothing,
pendingENDInterval = 500000,
smpServerVRange = supportedServerSMPRelayVRange, smpServerVRange = supportedServerSMPRelayVRange,
transportConfig = defaultTransportServerConfig {alpn = Just supportedSMPHandshakes}, transportConfig = defaultTransportServerConfig {alpn = Just supportedSMPHandshakes},
smpHandshakeTimeout = 1000000, smpHandshakeTimeout = 1000000,
+2 -2
View File
@@ -216,7 +216,7 @@ sndRcvImg pqEnc enabled (cc1, msg, v1) (cc2, v2) = do
name1 <- userName cc1 name1 <- userName cc1
name2 <- userName cc2 name2 <- userName cc2
g <- C.newRandom g <- C.newRandom
img <- atomically $ B64.encode <$> C.randomBytes lrgLen g img <- B64.encode <$> C.randomBytes lrgLen g
cc1 `send` ("/_send @2 json {\"msgContent\":{\"type\":\"image\",\"text\":\"" <> msg <> "\",\"image\":\"" <> B.unpack img <> "\"}}") cc1 `send` ("/_send @2 json {\"msgContent\":{\"type\":\"image\",\"text\":\"" <> msg <> "\",\"image\":\"" <> B.unpack img <> "\"}}")
cc1 .<## "}}" cc1 .<## "}}"
cc1 <### ([ConsoleString (name2 <> ": quantum resistant end-to-end encryption enabled") | enabled] <> [WithTime ("@" <> name2 <> " " <> msg)]) cc1 <### ([ConsoleString (name2 <> ": quantum resistant end-to-end encryption enabled") | enabled] <> [WithTime ("@" <> name2 <> " " <> msg)])
@@ -231,7 +231,7 @@ sndRcvImg pqEnc enabled (cc1, msg, v1) (cc2, v2) = do
genProfileImg :: IO ByteString genProfileImg :: IO ByteString
genProfileImg = do genProfileImg = do
g <- C.newRandom g <- C.newRandom
atomically $ B64.encode <$> C.randomBytes lrgLen g B64.encode <$> C.randomBytes lrgLen g
where where
lrgLen = maxEncodedInfoLength * 3 `div` 4 - 420 lrgLen = maxEncodedInfoLength * 3 `div` 4 - 420
+6 -7
View File
@@ -8,7 +8,6 @@
module MobileTests where module MobileTests where
import ChatTests.Utils import ChatTests.Utils
import Control.Concurrent.STM
import Control.Monad.Except import Control.Monad.Except
import Data.Aeson (FromJSON) import Data.Aeson (FromJSON)
import qualified Data.Aeson as J import qualified Data.Aeson as J
@@ -232,8 +231,8 @@ testMediaApi :: HasCallStack => FilePath -> IO ()
testMediaApi tmp = do testMediaApi tmp = do
Right c@ChatController {random = g} <- chatMigrateInit (tmp </> "1") "" "yesUp" Right c@ChatController {random = g} <- chatMigrateInit (tmp </> "1") "" "yesUp"
cc <- newStablePtr c cc <- newStablePtr c
key <- atomically $ C.randomBytes 32 g key <- C.randomBytes 32 g
frame <- atomically $ C.randomBytes 100 g frame <- C.randomBytes 100 g
let keyStr = strEncode key let keyStr = strEncode key
reserved = B.replicate (C.authTagSize + C.gcmIVSize) 0 reserved = B.replicate (C.authTagSize + C.gcmIVSize) 0
frame' = frame <> reserved frame' = frame <> reserved
@@ -246,8 +245,8 @@ testMediaCApi :: HasCallStack => FilePath -> IO ()
testMediaCApi tmp = do testMediaCApi tmp = do
Right c@ChatController {random = g} <- chatMigrateInit (tmp </> "1") "" "yesUp" Right c@ChatController {random = g} <- chatMigrateInit (tmp </> "1") "" "yesUp"
cc <- newStablePtr c cc <- newStablePtr c
key <- atomically $ C.randomBytes 32 g key <- C.randomBytes 32 g
frame <- atomically $ C.randomBytes 100 g frame <- C.randomBytes 100 g
let keyStr = strEncode key let keyStr = strEncode key
reserved = B.replicate (C.authTagSize + C.gcmIVSize) 0 reserved = B.replicate (C.authTagSize + C.gcmIVSize) 0
frame' = frame <> reserved frame' = frame <> reserved
@@ -300,7 +299,7 @@ testMissingFileCApi :: FilePath -> IO ()
testMissingFileCApi tmp = do testMissingFileCApi tmp = do
let path = tmp </> "missing_file" let path = tmp </> "missing_file"
cPath <- newCString path cPath <- newCString path
CFArgs key nonce <- atomically . CF.randomArgs =<< C.newRandom CFArgs key nonce <- CF.randomArgs =<< C.newRandom
cKey <- encodedCString key cKey <- encodedCString key
cNonce <- encodedCString nonce cNonce <- encodedCString nonce
ptr <- cChatReadFile cPath cKey cNonce ptr <- cChatReadFile cPath cKey cNonce
@@ -337,7 +336,7 @@ testMissingFileEncryptionCApi tmp = do
r <- peekCAString =<< cChatEncryptFile cc cFromPath cToPath r <- peekCAString =<< cChatEncryptFile cc cFromPath cToPath
Just (WFError err) <- jDecode r Just (WFError err) <- jDecode r
err `shouldContain` fromPath err `shouldContain` fromPath
CFArgs key nonce <- atomically . CF.randomArgs =<< C.newRandom CFArgs key nonce <- CF.randomArgs =<< C.newRandom
cKey <- encodedCString key cKey <- encodedCString key
cNonce <- encodedCString nonce cNonce <- encodedCString nonce
let toPath' = tmp </> "missing_file.decrypted.pdf" let toPath' = tmp </> "missing_file.decrypted.pdf"