diff --git a/cabal.project b/cabal.project index bcaf9f2abd..cc63f998af 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: e56bd0b47b22781f9b5936e3b8a9d51cc3f9e8d5 + tag: 784d36d691381290e72884cc30c59ce646166134 source-repository-package type: git diff --git a/scripts/nix/sha256map.nix b/scripts/nix/sha256map.nix index 195589ae83..a50762d6ff 100644 --- a/scripts/nix/sha256map.nix +++ b/scripts/nix/sha256map.nix @@ -1,5 +1,5 @@ { - "https://github.com/simplex-chat/simplexmq.git"."e56bd0b47b22781f9b5936e3b8a9d51cc3f9e8d5" = "11ghsddgyrlnddxqvvb0xlqvnnhnnsbixz1kg01x3gd6vpdqkz47"; + "https://github.com/simplex-chat/simplexmq.git"."784d36d691381290e72884cc30c59ce646166134" = "17qg39xfsn8fxajylpggxwb916013m1xgpz1kpd4qfy5rdpn6gp3"; "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 8f5295705b..d31c2cdeca 100644 --- a/src/Simplex/Chat.hs +++ b/src/Simplex/Chat.hs @@ -103,7 +103,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 (NetworkConfig (..), ProxyClientError (..), defaultNetworkConfig) +import Simplex.Messaging.Client (NetworkConfig (..), ProxyClientError (..), SocksMode (SMAlways), defaultNetworkConfig) import qualified Simplex.Messaging.Crypto as C import Simplex.Messaging.Crypto.File (CryptoFile (..), CryptoFileArgs (..)) import qualified Simplex.Messaging.Crypto.File as CF @@ -314,10 +314,10 @@ newChatController where configServers :: DefaultAgentServers configServers = - let DefaultAgentServers {smp = defSmp, xftp = defXftp} = defaultServers + let DefaultAgentServers {smp = defSmp, xftp = defXftp, netCfg} = defaultServers smp' = maybe defSmp (L.map enabledServerCfg) (nonEmpty smpServers) xftp' = maybe defXftp (L.map enabledServerCfg) (nonEmpty xftpServers) - in defaultServers {smp = smp', xftp = xftp', netCfg = updateNetworkConfig defaultNetworkConfig simpleNetCfg} + in defaultServers {smp = smp', xftp = xftp', netCfg = updateNetworkConfig netCfg simpleNetCfg} agentServers :: ChatConfig -> IO InitialAgentServers agentServers config@ChatConfig {defaultServers = defServers@DefaultAgentServers {ntf, netCfg}} = do users <- withTransaction chatStore getUsers @@ -336,11 +336,11 @@ newChatController userServers user' = useServers config protocol <$> withTransaction chatStore (`getProtocolServers` user') updateNetworkConfig :: NetworkConfig -> SimpleNetCfg -> NetworkConfig -updateNetworkConfig cfg SimpleNetCfg {socksProxy, smpProxyMode_, smpProxyFallback_, tcpTimeout_, logTLSErrors} = +updateNetworkConfig cfg SimpleNetCfg {socksProxy, socksMode, smpProxyMode_, smpProxyFallback_, tcpTimeout_, logTLSErrors} = let cfg1 = maybe cfg (\smpProxyMode -> cfg {smpProxyMode}) smpProxyMode_ cfg2 = maybe cfg1 (\smpProxyFallback -> cfg1 {smpProxyFallback}) smpProxyFallback_ cfg3 = maybe cfg2 (\tcpTimeout -> cfg2 {tcpTimeout, tcpConnectTimeout = (tcpTimeout * 3) `div` 2}) tcpTimeout_ - in cfg3 {socksProxy, logTLSErrors} + in cfg3 {socksProxy, socksMode, logTLSErrors} withChatLock :: String -> CM a -> CM a withChatLock name action = asks chatLock >>= \l -> withLock l name action @@ -1360,9 +1360,9 @@ processChatCommand' vr = \case APISetNetworkConfig cfg -> withUser' $ \_ -> lift (withAgent' (`setNetworkConfig` cfg)) >> ok_ APIGetNetworkConfig -> withUser' $ \_ -> CRNetworkConfig <$> lift getNetworkConfig - SetNetworkConfig netCfg -> do - cfg <- lift getNetworkConfig - void . processChatCommand $ APISetNetworkConfig $ updateNetworkConfig cfg netCfg + SetNetworkConfig simpleNetCfg -> do + cfg <- (`updateNetworkConfig` simpleNetCfg) <$> lift getNetworkConfig + void . processChatCommand $ APISetNetworkConfig cfg pure $ CRNetworkConfig cfg APISetNetworkInfo info -> lift (withAgent' (`setUserNetworkInfo` info)) >> ok_ ReconnectAllServers -> withUser' $ \_ -> lift (withAgent' reconnectAllServers) >> ok_ @@ -7770,12 +7770,13 @@ chatCommandP = <|> ("no" $> TMEDisableKeepTTL) netCfgP = do socksProxy <- "socks=" *> ("off" $> Nothing <|> "on" $> Just defaultSocksProxy <|> Just <$> strP) + socksMode <- " socks-mode=" *> strP <|> pure SMAlways smpProxyMode_ <- optional $ " smp-proxy=" *> strP smpProxyFallback_ <- optional $ " smp-proxy-fallback=" *> strP t_ <- optional $ " timeout=" *> A.decimal logTLSErrors <- " log=" *> onOffP <|> pure False let tcpTimeout_ = (1000000 *) <$> t_ - pure $ SimpleNetCfg {socksProxy, smpProxyMode_, smpProxyFallback_, tcpTimeout_, logTLSErrors} + pure $ SimpleNetCfg {socksProxy, socksMode, smpProxyMode_, smpProxyFallback_, tcpTimeout_, logTLSErrors} dbKeyP = nonEmptyKey <$?> strP nonEmptyKey k@(DBEncryptionKey s) = if BA.null s then Left "empty key" else Right k dbEncryptionConfig currentKey newKey = DBEncryptionConfig {currentKey, newKey, keepKey = Just False} diff --git a/src/Simplex/Chat/Controller.hs b/src/Simplex/Chat/Controller.hs index 6c127264d2..e08c8a287a 100644 --- a/src/Simplex/Chat/Controller.hs +++ b/src/Simplex/Chat/Controller.hs @@ -76,7 +76,7 @@ import Simplex.Messaging.Agent.Protocol import Simplex.Messaging.Agent.Store.SQLite (MigrationConfirmation, SQLiteStore, UpMigration, withTransaction) import Simplex.Messaging.Agent.Store.SQLite.DB (SlowQueryStats (..)) import qualified Simplex.Messaging.Agent.Store.SQLite.DB as DB -import Simplex.Messaging.Client (SMPProxyFallback (..), SMPProxyMode (..)) +import Simplex.Messaging.Client (SMPProxyFallback (..), SMPProxyMode (..), SocksMode (..)) import qualified Simplex.Messaging.Crypto as C import Simplex.Messaging.Crypto.File (CryptoFile (..)) import qualified Simplex.Messaging.Crypto.File as CF @@ -966,6 +966,7 @@ data AppFilePathsConfig = AppFilePathsConfig data SimpleNetCfg = SimpleNetCfg { socksProxy :: Maybe SocksProxy, + socksMode :: SocksMode, smpProxyMode_ :: Maybe SMPProxyMode, smpProxyFallback_ :: Maybe SMPProxyFallback, tcpTimeout_ :: Maybe Int, @@ -974,7 +975,7 @@ data SimpleNetCfg = SimpleNetCfg deriving (Show) defaultSimpleNetCfg :: SimpleNetCfg -defaultSimpleNetCfg = SimpleNetCfg Nothing Nothing Nothing Nothing False +defaultSimpleNetCfg = SimpleNetCfg Nothing SMAlways Nothing Nothing Nothing False data ContactSubStatus = ContactSubStatus { contact :: Contact, diff --git a/src/Simplex/Chat/Options.hs b/src/Simplex/Chat/Options.hs index 14e5603976..0b5961b042 100644 --- a/src/Simplex/Chat/Options.hs +++ b/src/Simplex/Chat/Options.hs @@ -27,6 +27,7 @@ import Numeric.Natural (Natural) import Options.Applicative import Simplex.Chat.Controller (ChatLogLevel (..), SimpleNetCfg (..), updateStr, versionNumber, versionString) import Simplex.FileTransfer.Description (mb) +import Simplex.Messaging.Client (SocksMode (..)) import Simplex.Messaging.Encoding.String import Simplex.Messaging.Parsers (parseAll) import Simplex.Messaging.Protocol (ProtoServerWithAuth, ProtocolTypeI, SMPServerWithAuth, XFTPServerWithAuth) @@ -130,21 +131,29 @@ coreChatOptsP appDir defaultDbFileName = do <> help "Use SOCKS5 proxy at `ipv4:port` or `:port`" <> value Nothing ) + socksMode <- + option + strParse + ( long "socks-mode" + <> metavar "SOCKS_MODE" + <> help "Use SOCKS5 proxy: always (default), onion (with onion-only relays)" + <> value SMAlways + ) smpProxyMode_ <- optional $ option strParse ( long "smp-proxy" <> metavar "SMP_PROXY_MODE" - <> help "Use private message routing: always, unknown, unprotected, never (default)" - ) + <> help "Use private message routing: always, unknown (default), unprotected, never" + ) smpProxyFallback_ <- optional $ option strParse ( long "smp-proxy-fallback" <> metavar "SMP_PROXY_FALLBACK_MODE" - <> help "Allow downgrade and connect directly: no, [when IP address is] protected, yes (default)" + <> help "Allow downgrade and connect directly: no, [when IP address is] protected (default), yes" ) t <- option @@ -217,7 +226,7 @@ coreChatOptsP appDir defaultDbFileName = do dbKey, smpServers, xftpServers, - simpleNetCfg = SimpleNetCfg {socksProxy, smpProxyMode_, smpProxyFallback_, tcpTimeout_ = Just $ useTcpTimeout socksProxy t, logTLSErrors}, + simpleNetCfg = SimpleNetCfg {socksProxy, socksMode, smpProxyMode_, smpProxyFallback_, tcpTimeout_ = Just $ useTcpTimeout socksProxy t, logTLSErrors}, logLevel, logConnections = logConnections || logLevel <= CLLInfo, logServerHosts = logServerHosts || logLevel <= CLLInfo, diff --git a/src/Simplex/Chat/Terminal.hs b/src/Simplex/Chat/Terminal.hs index ca9b2edb65..eb11bb0205 100644 --- a/src/Simplex/Chat/Terminal.hs +++ b/src/Simplex/Chat/Terminal.hs @@ -22,7 +22,7 @@ import Simplex.Chat.Terminal.Input import Simplex.Chat.Terminal.Output import Simplex.FileTransfer.Client.Presets (defaultXFTPServers) import Simplex.Messaging.Agent.Env.SQLite (presetServerCfg) -import Simplex.Messaging.Client (defaultNetworkConfig) +import Simplex.Messaging.Client (NetworkConfig (..), SMPProxyFallback (..), SMPProxyMode (..), defaultNetworkConfig) import Simplex.Messaging.Util (raceAny_) import System.IO (hFlush, hSetEcho, stdin, stdout) @@ -41,7 +41,11 @@ terminalChatConfig = ], ntf = ["ntf://FB-Uop7RTaZZEG0ZLD2CIaTjsPh-Fw0zFAnb7QyA8Ks=@ntf2.simplex.im,ntg7jdjy2i3qbib3sykiho3enekwiaqg3icctliqhtqcg6jmoh6cxiad.onion"], xftp = L.map (presetServerCfg True) defaultXFTPServers, - netCfg = defaultNetworkConfig + netCfg = + defaultNetworkConfig + { smpProxyMode = SPMUnknown, + smpProxyFallback = SPFAllowProtected + } }, deviceNameForRemote = "SimpleX CLI" } diff --git a/src/Simplex/Chat/Terminal/Main.hs b/src/Simplex/Chat/Terminal/Main.hs index 3e7d933669..5d684d7283 100644 --- a/src/Simplex/Chat/Terminal/Main.hs +++ b/src/Simplex/Chat/Terminal/Main.hs @@ -10,12 +10,12 @@ import Data.Maybe (fromMaybe) import Data.Time.Clock (getCurrentTime) import Data.Time.LocalTime (getCurrentTimeZone) import Network.Socket -import Simplex.Chat.Controller (ChatConfig, ChatController (..), ChatResponse (..), SimpleNetCfg (..), currentRemoteHost, versionNumber, versionString) +import Simplex.Chat.Controller (ChatConfig (..), ChatController (..), ChatResponse (..), DefaultAgentServers (DefaultAgentServers, netCfg), SimpleNetCfg (..), currentRemoteHost, versionNumber, versionString) import Simplex.Chat.Core import Simplex.Chat.Options import Simplex.Chat.Terminal import Simplex.Chat.View (serializeChatResponse, smpProxyModeStr) -import Simplex.Messaging.Client (NetworkConfig (..), defaultNetworkConfig) +import Simplex.Messaging.Client (NetworkConfig (..), SocksMode (..)) import System.Directory (getAppUserDataDirectory) import System.Exit (exitFailure) import System.Terminal (withTerminal) @@ -33,7 +33,7 @@ simplexChatCLI cfg server_ = do else simplexChatCore cfg opts $ runCommand opts where runCLI opts = do - welcome opts + welcome cfg opts t <- withTerminal pure simplexChatTerminal cfg opts t runCommand ChatOpts {chatCmd, chatCmdLog, chatCmdDelay} user cc = do @@ -51,18 +51,18 @@ simplexChatCLI cfg server_ = do rh <- readTVarIO $ currentRemoteHost cc putStrLn $ serializeChatResponse (rh, Just user) ts tz rh r -welcome :: ChatOpts -> IO () -welcome ChatOpts {coreOptions = CoreChatOpts {dbFilePrefix, simpleNetCfg = SimpleNetCfg {socksProxy, smpProxyMode_, smpProxyFallback_}}} = +welcome :: ChatConfig -> ChatOpts -> IO () +welcome ChatConfig {defaultServers = DefaultAgentServers {netCfg}} ChatOpts {coreOptions = CoreChatOpts {dbFilePrefix, simpleNetCfg = SimpleNetCfg {socksProxy, socksMode, smpProxyMode_, smpProxyFallback_}}} = mapM_ putStrLn [ versionString versionNumber, "db: " <> dbFilePrefix <> "_chat.db, " <> dbFilePrefix <> "_agent.db", maybe "direct network connection - use `/network` command or `-x` CLI option to connect via SOCKS5 at :9050" - (("using SOCKS5 proxy " <>) . show) + ((\sp -> "using SOCKS5 proxy " <> sp <> if socksMode == SMOnion then " for onion servers ONLY." else " for ALL servers.") . show) socksProxy, smpProxyModeStr - (fromMaybe (smpProxyMode defaultNetworkConfig) smpProxyMode_) - (fromMaybe (smpProxyFallback defaultNetworkConfig) smpProxyFallback_), + (fromMaybe (smpProxyMode netCfg) smpProxyMode_) + (fromMaybe (smpProxyFallback netCfg) smpProxyFallback_), "type \"/help\" or \"/h\" for usage info" ] diff --git a/src/Simplex/Chat/View.hs b/src/Simplex/Chat/View.hs index 4dffa41dea..b0d3032ed3 100644 --- a/src/Simplex/Chat/View.hs +++ b/src/Simplex/Chat/View.hs @@ -55,7 +55,7 @@ import Simplex.Messaging.Agent.Client (ProtocolTestFailure (..), ProtocolTestSte import Simplex.Messaging.Agent.Env.SQLite (NetworkConfig (..), ServerCfg (..)) import Simplex.Messaging.Agent.Protocol import Simplex.Messaging.Agent.Store.SQLite.DB (SlowQueryStats (..)) -import Simplex.Messaging.Client (SMPProxyFallback, SMPProxyMode (..)) +import Simplex.Messaging.Client (SMPProxyFallback, SMPProxyMode (..), SocksMode (..)) import qualified Simplex.Messaging.Crypto as C import Simplex.Messaging.Crypto.File (CryptoFile (..), CryptoFileArgs (..)) import qualified Simplex.Messaging.Crypto.Ratchet as CR @@ -1217,11 +1217,11 @@ viewChatItemTTL = \case deletedAfter ttlStr = ["old messages are set to be deleted after: " <> ttlStr] viewNetworkConfig :: NetworkConfig -> [StyledString] -viewNetworkConfig NetworkConfig {socksProxy, tcpTimeout, smpProxyMode, smpProxyFallback} = - [ plain $ maybe "direct network connection" (("using SOCKS5 proxy " <>) . show) socksProxy, +viewNetworkConfig NetworkConfig {socksProxy, socksMode, tcpTimeout, smpProxyMode, smpProxyFallback} = + [ plain $ maybe "direct network connection" ((\sp -> "using SOCKS5 proxy " <> sp <> if socksMode == SMOnion then " for onion servers ONLY." else " for ALL servers.") . show) socksProxy, "TCP timeout: " <> sShow tcpTimeout, plain $ smpProxyModeStr smpProxyMode smpProxyFallback, - "use " <> highlight' "/network socks=[ timeout=][ smp-proxy=always/unknown/unprotected/never][ smp-proxy-fallback=no/protected/yes]" <> " to change settings" + "use " <> highlight' "/network socks=[ socks-mode=always/onion][ smp-proxy=always/unknown/unprotected/never][ smp-proxy-fallback=no/protected/yes][ timeout=]" <> " to change settings" ] smpProxyModeStr :: SMPProxyMode -> SMPProxyFallback -> String