core: revert stop/close changes made for Windows (#3145)

* Revert "core: return error response when wrong passphrase is passed to start"

This reverts commit ea319313f1.

* Revert "core: support closing/re-opening store on chat stop/start (#3132)"

This reverts commit 3c7fc6b0ee.
This commit is contained in:
Evgeny Poberezkin 2023-09-29 11:14:10 +01:00 committed by GitHub
parent bc7baf560b
commit 1d34500fba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 42 additions and 87 deletions

View File

@ -516,8 +516,8 @@ object ChatController {
throw Exception("failed to delete the user ${r.responseType} ${r.details}") throw Exception("failed to delete the user ${r.responseType} ${r.details}")
} }
suspend fun apiStartChat(openDBWithKey: String? = null): Boolean { suspend fun apiStartChat(): Boolean {
val r = sendCmd(CC.StartChat(ChatCtrlCfg(subConns = true, enableExpireCIs = true, startXFTPWorkers = true, openDBWithKey = openDBWithKey))) val r = sendCmd(CC.StartChat(expire = true))
when (r) { when (r) {
is CR.ChatStarted -> return true is CR.ChatStarted -> return true
is CR.ChatRunning -> return false is CR.ChatRunning -> return false
@ -525,8 +525,8 @@ object ChatController {
} }
} }
suspend fun apiStopChat(closeStore: Boolean): Boolean { suspend fun apiStopChat(): Boolean {
val r = sendCmd(CC.ApiStopChat(closeStore)) val r = sendCmd(CC.ApiStopChat())
when (r) { when (r) {
is CR.ChatStopped -> return true is CR.ChatStopped -> return true
else -> throw Error("failed stopping chat: ${r.responseType} ${r.details}") else -> throw Error("failed stopping chat: ${r.responseType} ${r.details}")
@ -1834,8 +1834,8 @@ sealed class CC {
class ApiMuteUser(val userId: Long): CC() class ApiMuteUser(val userId: Long): CC()
class ApiUnmuteUser(val userId: Long): CC() class ApiUnmuteUser(val userId: Long): CC()
class ApiDeleteUser(val userId: Long, val delSMPQueues: Boolean, val viewPwd: String?): CC() class ApiDeleteUser(val userId: Long, val delSMPQueues: Boolean, val viewPwd: String?): CC()
class StartChat(val cfg: ChatCtrlCfg): CC() class StartChat(val expire: Boolean): CC()
class ApiStopChat(val closeStore: Boolean): CC() class ApiStopChat: CC()
class SetTempFolder(val tempFolder: String): CC() class SetTempFolder(val tempFolder: String): CC()
class SetFilesFolder(val filesFolder: String): CC() class SetFilesFolder(val filesFolder: String): CC()
class ApiSetXFTPConfig(val config: XFTPFileConfig?): CC() class ApiSetXFTPConfig(val config: XFTPFileConfig?): CC()
@ -1938,9 +1938,8 @@ sealed class CC {
is ApiMuteUser -> "/_mute user $userId" is ApiMuteUser -> "/_mute user $userId"
is ApiUnmuteUser -> "/_unmute user $userId" is ApiUnmuteUser -> "/_unmute user $userId"
is ApiDeleteUser -> "/_delete user $userId del_smp=${onOff(delSMPQueues)}${maybePwd(viewPwd)}" is ApiDeleteUser -> "/_delete user $userId del_smp=${onOff(delSMPQueues)}${maybePwd(viewPwd)}"
// is StartChat -> "/_start ${json.encodeToString(cfg)}" // this can be used with the new core is StartChat -> "/_start subscribe=on expire=${onOff(expire)} xftp=on"
is StartChat -> "/_start subscribe=on expire=${onOff(cfg.enableExpireCIs)} xftp=on" is ApiStopChat -> "/_stop"
is ApiStopChat -> if (closeStore) "/_stop close" else "/_stop"
is SetTempFolder -> "/_temp_folder $tempFolder" is SetTempFolder -> "/_temp_folder $tempFolder"
is SetFilesFolder -> "/_files_folder $filesFolder" is SetFilesFolder -> "/_files_folder $filesFolder"
is ApiSetXFTPConfig -> if (config != null) "/_xftp on ${json.encodeToString(config)}" else "/_xftp off" is ApiSetXFTPConfig -> if (config != null) "/_xftp on ${json.encodeToString(config)}" else "/_xftp off"
@ -2157,14 +2156,6 @@ sealed class CC {
} }
} }
@Serializable
data class ChatCtrlCfg (
val subConns: Boolean,
val enableExpireCIs: Boolean,
val startXFTPWorkers: Boolean,
val openDBWithKey: String?
)
@Serializable @Serializable
data class NewUser( data class NewUser(
val profile: Profile?, val profile: Profile?,

View File

@ -419,7 +419,7 @@ private fun stopChat(m: ChatModel) {
} }
suspend fun stopChatAsync(m: ChatModel) { suspend fun stopChatAsync(m: ChatModel) {
m.controller.apiStopChat(false) m.controller.apiStopChat()
m.chatRunning.value = false m.chatRunning.value = false
} }

View File

@ -9,7 +9,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: fda1284ae4b7c33cae2eb8ed0376a511aecc1d51 tag: 8d47f690838371bc848e4b31a4b09ef6bf67ccc5
source-repository-package source-repository-package
type: git type: git

View File

@ -1,5 +1,5 @@
{ {
"https://github.com/simplex-chat/simplexmq.git"."fda1284ae4b7c33cae2eb8ed0376a511aecc1d51" = "1gq7scv9z8x3xhzl914xr46na0kkrqd1i743xbw69lyx33kj9xb5"; "https://github.com/simplex-chat/simplexmq.git"."8d47f690838371bc848e4b31a4b09ef6bf67ccc5" = "1pwasv22ii3wy4xchaknlwczmy5ws7adx7gg2g58lxzrgdjm3650";
"https://github.com/simplex-chat/hs-socks.git"."a30cc7a79a08d8108316094f8f2f82a0c5e1ac51" = "0yasvnr7g91k76mjkamvzab2kvlb1g5pspjyjn2fr6v83swjhj38"; "https://github.com/simplex-chat/hs-socks.git"."a30cc7a79a08d8108316094f8f2f82a0c5e1ac51" = "0yasvnr7g91k76mjkamvzab2kvlb1g5pspjyjn2fr6v83swjhj38";
"https://github.com/kazu-yamamoto/http2.git"."b5a1b7200cf5bc7044af34ba325284271f6dff25" = "0dqb50j57an64nf4qcf5vcz4xkd1vzvghvf8bk529c1k30r9nfzb"; "https://github.com/kazu-yamamoto/http2.git"."b5a1b7200cf5bc7044af34ba325284271f6dff25" = "0dqb50j57an64nf4qcf5vcz4xkd1vzvghvf8bk529c1k30r9nfzb";
"https://github.com/simplex-chat/direct-sqlcipher.git"."f814ee68b16a9447fbb467ccc8f29bdd3546bfd9" = "0kiwhvml42g9anw4d2v0zd1fpc790pj9syg5x3ik4l97fnkbbwpp"; "https://github.com/simplex-chat/direct-sqlcipher.git"."f814ee68b16a9447fbb467ccc8f29bdd3546bfd9" = "0kiwhvml42g9anw4d2v0zd1fpc790pj9syg5x3ik4l97fnkbbwpp";

View File

@ -34,7 +34,6 @@ import qualified Data.ByteString.Base64 as B64
import Data.ByteString.Char8 (ByteString) import Data.ByteString.Char8 (ByteString)
import qualified Data.ByteString.Char8 as B import qualified Data.ByteString.Char8 as B
import Data.Char (isSpace, toLower) import Data.Char (isSpace, toLower)
import Data.Composition ((.:))
import Data.Constraint (Dict (..)) import Data.Constraint (Dict (..))
import Data.Either (fromRight, rights) import Data.Either (fromRight, rights)
import Data.Fixed (div') import Data.Fixed (div')
@ -84,7 +83,7 @@ import Simplex.Messaging.Agent.Client (AgentStatsKey (..), SubInfo (..), agentCl
import Simplex.Messaging.Agent.Env.SQLite (AgentConfig (..), InitialAgentServers (..), createAgentStore, defaultAgentConfig) import Simplex.Messaging.Agent.Env.SQLite (AgentConfig (..), InitialAgentServers (..), createAgentStore, defaultAgentConfig)
import Simplex.Messaging.Agent.Lock import Simplex.Messaging.Agent.Lock
import Simplex.Messaging.Agent.Protocol import Simplex.Messaging.Agent.Protocol
import Simplex.Messaging.Agent.Store.SQLite (MigrationConfirmation (..), MigrationError, SQLiteStore (dbNew), execSQL, upMigration, withConnection, closeSQLiteStore, openSQLiteStore) import Simplex.Messaging.Agent.Store.SQLite (MigrationConfirmation (..), MigrationError, SQLiteStore (dbNew), execSQL, upMigration, withConnection)
import Simplex.Messaging.Agent.Store.SQLite.DB (SlowQueryStats (..)) 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.DB as DB
import qualified Simplex.Messaging.Agent.Store.SQLite.Migrations as Migrations import qualified Simplex.Messaging.Agent.Store.SQLite.Migrations as Migrations
@ -218,8 +217,8 @@ newChatController ChatDatabase {chatStore, agentStore} user cfg@ChatConfig {agen
where where
configServers :: DefaultAgentServers configServers :: DefaultAgentServers
configServers = configServers =
let smp' = fromMaybe defaultServers.smp (nonEmpty smpServers) let smp' = fromMaybe (defaultServers.smp) (nonEmpty smpServers)
xftp' = fromMaybe defaultServers.xftp (nonEmpty xftpServers) xftp' = fromMaybe (defaultServers.xftp) (nonEmpty xftpServers)
in defaultServers {smp = smp', xftp = xftp', netCfg = networkConfig} in defaultServers {smp = smp', xftp = xftp', netCfg = networkConfig}
agentServers :: ChatConfig -> IO InitialAgentServers agentServers :: ChatConfig -> IO InitialAgentServers
agentServers config@ChatConfig {defaultServers = defServers@DefaultAgentServers {ntf, netCfg}} = do agentServers config@ChatConfig {defaultServers = defServers@DefaultAgentServers {ntf, netCfg}} = do
@ -252,7 +251,7 @@ cfgServers p s = case p of
startChatController :: forall m. ChatMonad' m => Bool -> Bool -> Bool -> m (Async ()) startChatController :: forall m. ChatMonad' m => Bool -> Bool -> Bool -> m (Async ())
startChatController subConns enableExpireCIs startXFTPWorkers = do startChatController subConns enableExpireCIs startXFTPWorkers = do
resumeAgentClient =<< asks smpAgent asks smpAgent >>= resumeAgentClient
unless subConns $ unless subConns $
chatWriteVar subscriptionMode SMOnlyCreate chatWriteVar subscriptionMode SMOnlyCreate
users <- fromRight [] <$> runExceptT (withStoreCtx' (Just "startChatController, getUsers") getUsers) users <- fromRight [] <$> runExceptT (withStoreCtx' (Just "startChatController, getUsers") getUsers)
@ -324,8 +323,8 @@ restoreCalls = do
calls <- asks currentCalls calls <- asks currentCalls
atomically $ writeTVar calls callsMap atomically $ writeTVar calls callsMap
stopChatController :: forall m. MonadUnliftIO m => ChatController -> Bool -> m () stopChatController :: forall m. MonadUnliftIO m => ChatController -> m ()
stopChatController ChatController {chatStore, smpAgent, agentAsync = s, sndFiles, rcvFiles, expireCIFlags} closeStore = do stopChatController ChatController {smpAgent, agentAsync = s, sndFiles, rcvFiles, expireCIFlags} = do
disconnectAgentClient smpAgent disconnectAgentClient smpAgent
readTVarIO s >>= mapM_ (\(a1, a2) -> uninterruptibleCancel a1 >> mapM_ uninterruptibleCancel a2) readTVarIO s >>= mapM_ (\(a1, a2) -> uninterruptibleCancel a1 >> mapM_ uninterruptibleCancel a2)
closeFiles sndFiles closeFiles sndFiles
@ -334,9 +333,6 @@ stopChatController ChatController {chatStore, smpAgent, agentAsync = s, sndFiles
keys <- M.keys <$> readTVar expireCIFlags keys <- M.keys <$> readTVar expireCIFlags
forM_ keys $ \k -> TM.insert k False expireCIFlags forM_ keys $ \k -> TM.insert k False expireCIFlags
writeTVar s Nothing writeTVar s Nothing
when closeStore $ liftIO $ do
closeSQLiteStore chatStore
closeSQLiteStore $ agentClientStore smpAgent
where where
closeFiles :: TVar (Map Int64 Handle) -> m () closeFiles :: TVar (Map Int64 Handle) -> m ()
closeFiles files = do closeFiles files = do
@ -466,19 +462,12 @@ processChatCommand = \case
checkDeleteChatUser user' checkDeleteChatUser user'
withChatLock "deleteUser" . procCmd $ deleteChatUser user' delSMPQueues withChatLock "deleteUser" . procCmd $ deleteChatUser user' delSMPQueues
DeleteUser uName delSMPQueues viewPwd_ -> withUserName uName $ \userId -> APIDeleteUser userId delSMPQueues viewPwd_ DeleteUser uName delSMPQueues viewPwd_ -> withUserName uName $ \userId -> APIDeleteUser userId delSMPQueues viewPwd_
APIStartChat ChatCtrlCfg {subConns, enableExpireCIs, startXFTPWorkers, openDBWithKey} -> withUser' $ \_ -> StartChat subConns enableExpireCIs startXFTPWorkers -> withUser' $ \_ ->
asks agentAsync >>= readTVarIO >>= \case asks agentAsync >>= readTVarIO >>= \case
Just _ -> pure CRChatRunning Just _ -> pure CRChatRunning
_ -> checkStoreNotChanged $ do _ -> checkStoreNotChanged $ startChatController subConns enableExpireCIs startXFTPWorkers $> CRChatStarted
forM_ openDBWithKey $ \(DBEncryptionKey dbKey) -> do APIStopChat -> do
ChatController {chatStore, smpAgent} <- ask ask >>= stopChatController
open chatStore dbKey
open (agentClientStore smpAgent) dbKey
startChatController subConns enableExpireCIs startXFTPWorkers $> CRChatStarted
where
open = handleDBError DBErrorOpen .: openSQLiteStore
APIStopChat closeStore -> do
ask >>= (`stopChatController` closeStore)
pure CRChatStopped pure CRChatStopped
APIActivateChat -> withUser $ \_ -> do APIActivateChat -> withUser $ \_ -> do
restoreCalls restoreCalls
@ -5411,9 +5400,9 @@ chatCommandP =
"/_delete user " *> (APIDeleteUser <$> A.decimal <* " del_smp=" <*> onOffP <*> optional (A.space *> jsonP)), "/_delete user " *> (APIDeleteUser <$> A.decimal <* " del_smp=" <*> onOffP <*> optional (A.space *> jsonP)),
"/delete user " *> (DeleteUser <$> displayName <*> pure True <*> optional (A.space *> pwdP)), "/delete user " *> (DeleteUser <$> displayName <*> pure True <*> optional (A.space *> pwdP)),
("/user" <|> "/u") $> ShowActiveUser, ("/user" <|> "/u") $> ShowActiveUser,
"/_start" *> (APIStartChat <$> ((A.space *> jsonP) <|> chatCtrlCfgP)), "/_start subscribe=" *> (StartChat <$> onOffP <* " expire=" <*> onOffP <* " xftp=" <*> onOffP),
"/_stop close" $> APIStopChat {closeStore = True}, "/_start" $> StartChat True True True,
"/_stop" $> APIStopChat False, "/_stop" $> APIStopChat,
"/_app activate" $> APIActivateChat, "/_app activate" $> APIActivateChat,
"/_app suspend " *> (APISuspendChat <$> A.decimal), "/_app suspend " *> (APISuspendChat <$> A.decimal),
"/_resubscribe all" $> ResubscribeAllConnections, "/_resubscribe all" $> ResubscribeAllConnections,
@ -5641,12 +5630,6 @@ chatCommandP =
] ]
where where
choice = A.choice . map (\p -> p <* A.takeWhile (== ' ') <* A.endOfInput) choice = A.choice . map (\p -> p <* A.takeWhile (== ' ') <* A.endOfInput)
chatCtrlCfgP = do
subConns <- (" subscribe=" *> onOffP) <|> pure True
enableExpireCIs <- (" expire=" *> onOffP) <|> pure True
startXFTPWorkers <- (" xftp=" *> onOffP) <|> pure True
openDBWithKey <- optional $ " key=" *> dbKeyP
pure ChatCtrlCfg {subConns, enableExpireCIs, startXFTPWorkers, openDBWithKey}
incognitoP = (A.space *> ("incognito" <|> "i")) $> True <|> pure False incognitoP = (A.space *> ("incognito" <|> "i")) $> True <|> pure False
incognitoOnOffP = (A.space *> "incognito=" *> onOffP) <|> pure False incognitoOnOffP = (A.space *> "incognito=" *> onOffP) <|> pure False
imagePrefix = (<>) <$> "data:" <*> ("image/png;base64," <|> "image/jpg;base64,") imagePrefix = (<>) <$> "data:" <*> ("image/png;base64," <|> "image/jpg;base64,")

View File

@ -9,7 +9,6 @@ module Simplex.Chat.Archive
importArchive, importArchive,
deleteStorage, deleteStorage,
sqlCipherExport, sqlCipherExport,
handleDBError,
) )
where where
@ -125,7 +124,7 @@ sqlCipherExport DBEncryptionConfig {currentKey = DBEncryptionKey key, newKey = D
checkFile `with` fs checkFile `with` fs
backup `with` fs backup `with` fs
(export chatDb chatEncrypted >> export agentDb agentEncrypted) (export chatDb chatEncrypted >> export agentDb agentEncrypted)
`catchChatError` \e -> tryChatError (restore `with` fs) >> throwError e `catchChatError` \e -> (restore `with` fs) >> throwError e
where where
action `with` StorageFiles {chatDb, agentDb} = action chatDb >> action agentDb action `with` StorageFiles {chatDb, agentDb} = action chatDb >> action agentDb
backup f = copyFile f (f <> ".bak") backup f = copyFile f (f <> ".bak")
@ -140,7 +139,17 @@ sqlCipherExport DBEncryptionConfig {currentKey = DBEncryptionKey key, newKey = D
withDB (`SQL.exec` testSQL) DBErrorOpen withDB (`SQL.exec` testSQL) DBErrorOpen
atomically $ writeTVar dbEnc $ not (null key') atomically $ writeTVar dbEnc $ not (null key')
where where
withDB a err = handleDBError err $ bracket (SQL.open $ T.pack f) SQL.close a withDB a err =
liftIO (bracket (SQL.open $ T.pack f) SQL.close a $> Nothing)
`catch` checkSQLError
`catch` (\(e :: SomeException) -> sqliteError' e)
>>= mapM_ (throwDBError . err)
where
checkSQLError e = case SQL.sqlError e of
SQL.ErrorNotADatabase -> pure $ Just SQLiteErrorNotADatabase
_ -> sqliteError' e
sqliteError' :: Show e => e -> m (Maybe SQLiteError)
sqliteError' = pure . Just . SQLiteError . show
exportSQL = exportSQL =
T.unlines $ T.unlines $
keySQL key keySQL key
@ -157,16 +166,3 @@ sqlCipherExport DBEncryptionConfig {currentKey = DBEncryptionKey key, newKey = D
"SELECT count(*) FROM sqlite_master;" "SELECT count(*) FROM sqlite_master;"
] ]
keySQL k = ["PRAGMA key = " <> sqlString k <> ";" | not (null k)] keySQL k = ["PRAGMA key = " <> sqlString k <> ";" | not (null k)]
handleDBError :: forall m. ChatMonad m => (SQLiteError -> DatabaseError) -> IO () -> m ()
handleDBError err a =
(liftIO a $> Nothing)
`catch` checkSQLError
`catch` (\(e :: SomeException) -> sqliteError' e)
>>= mapM_ (throwDBError . err)
where
checkSQLError e = case SQL.sqlError e of
SQL.ErrorNotADatabase -> pure $ Just SQLiteErrorNotADatabase
_ -> sqliteError' e
sqliteError' :: Show e => e -> m (Maybe SQLiteError)
sqliteError' = pure . Just . SQLiteError . show

View File

@ -221,8 +221,8 @@ data ChatCommand
| UnmuteUser | UnmuteUser
| APIDeleteUser UserId Bool (Maybe UserPwd) | APIDeleteUser UserId Bool (Maybe UserPwd)
| DeleteUser UserName Bool (Maybe UserPwd) | DeleteUser UserName Bool (Maybe UserPwd)
| APIStartChat ChatCtrlCfg | StartChat {subscribeConnections :: Bool, enableExpireChatItems :: Bool, startXFTPWorkers :: Bool}
| APIStopChat {closeStore :: Bool} | APIStopChat
| APIActivateChat | APIActivateChat
| APISuspendChat {suspendTimeout :: Int} | APISuspendChat {suspendTimeout :: Int}
| ResubscribeAllConnections | ResubscribeAllConnections
@ -621,14 +621,6 @@ instance ToJSON ChatResponse where
toJSON = J.genericToJSON . sumTypeJSON $ dropPrefix "CR" toJSON = J.genericToJSON . sumTypeJSON $ dropPrefix "CR"
toEncoding = J.genericToEncoding . sumTypeJSON $ dropPrefix "CR" toEncoding = J.genericToEncoding . sumTypeJSON $ dropPrefix "CR"
data ChatCtrlCfg = ChatCtrlCfg
{ subConns :: Bool,
enableExpireCIs :: Bool,
startXFTPWorkers :: Bool,
openDBWithKey :: Maybe DBEncryptionKey
}
deriving (Show, Generic, FromJSON)
newtype UserPwd = UserPwd {unUserPwd :: Text} newtype UserPwd = UserPwd {unUserPwd :: Text}
deriving (Eq, Show) deriving (Eq, Show)

View File

@ -1648,7 +1648,7 @@ viewChatError logLevel = \case
DBErrorEncrypted -> ["error: chat database is already encrypted"] DBErrorEncrypted -> ["error: chat database is already encrypted"]
DBErrorPlaintext -> ["error: chat database is not encrypted"] DBErrorPlaintext -> ["error: chat database is not encrypted"]
DBErrorExport e -> ["error encrypting database: " <> sqliteError' e] DBErrorExport e -> ["error encrypting database: " <> sqliteError' e]
DBErrorOpen e -> ["error opening database: " <> sqliteError' e] DBErrorOpen e -> ["error opening database after encryption: " <> sqliteError' e]
e -> ["chat database error: " <> sShow e] e -> ["chat database error: " <> sShow e]
ChatErrorAgent err entity_ -> case err of ChatErrorAgent err entity_ -> case err of
CMD PROHIBITED -> [withConnEntity <> "error: command is prohibited"] CMD PROHIBITED -> [withConnEntity <> "error: command is prohibited"]

View File

@ -49,7 +49,7 @@ extra-deps:
# - simplexmq-1.0.0@sha256:34b2004728ae396e3ae449cd090ba7410781e2b3cefc59259915f4ca5daa9ea8,8561 # - simplexmq-1.0.0@sha256:34b2004728ae396e3ae449cd090ba7410781e2b3cefc59259915f4ca5daa9ea8,8561
# - ../simplexmq # - ../simplexmq
- github: simplex-chat/simplexmq - github: simplex-chat/simplexmq
commit: fda1284ae4b7c33cae2eb8ed0376a511aecc1d51 commit: 8d47f690838371bc848e4b31a4b09ef6bf67ccc5
- github: kazu-yamamoto/http2 - github: kazu-yamamoto/http2
commit: b5a1b7200cf5bc7044af34ba325284271f6dff25 commit: b5a1b7200cf5bc7044af34ba325284271f6dff25
# - ../direct-sqlcipher # - ../direct-sqlcipher

View File

@ -171,7 +171,7 @@ startTestChat_ db cfg opts user = do
stopTestChat :: TestCC -> IO () stopTestChat :: TestCC -> IO ()
stopTestChat TestCC {chatController = cc, chatAsync, termAsync} = do stopTestChat TestCC {chatController = cc, chatAsync, termAsync} = do
stopChatController cc False stopChatController cc
uninterruptibleCancel termAsync uninterruptibleCancel termAsync
uninterruptibleCancel chatAsync uninterruptibleCancel chatAsync
threadDelay 200000 threadDelay 200000

View File

@ -992,17 +992,10 @@ testDatabaseEncryption tmp = do
alice ##> "/_start" alice ##> "/_start"
alice <## "chat started" alice <## "chat started"
testChatWorking alice bob testChatWorking alice bob
alice ##> "/_stop close" alice ##> "/_stop"
alice <## "chat stopped" alice <## "chat stopped"
alice ##> "/db key wrongkey nextkey" alice ##> "/db key wrongkey nextkey"
alice <## "error encrypting database: wrong passphrase or invalid database file" alice <## "error encrypting database: wrong passphrase or invalid database file"
alice ##> "/_start key=wrongkey"
alice <## "error opening database: wrong passphrase or invalid database file"
alice ##> "/_start key=mykey"
alice <## "chat started"
testChatWorking alice bob
alice ##> "/_stop close"
alice <## "chat stopped"
alice ##> "/db key mykey nextkey" alice ##> "/db key mykey nextkey"
alice <## "ok" alice <## "ok"
alice ##> "/_db encryption {\"currentKey\":\"nextkey\",\"newKey\":\"anotherkey\"}" alice ##> "/_db encryption {\"currentKey\":\"nextkey\",\"newKey\":\"anotherkey\"}"