diff --git a/apps/multiplatform/android/src/main/java/chat/simplex/app/SimplexApp.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/SimplexApp.kt index b6773ceb42..6adaa1d4e0 100644 --- a/apps/multiplatform/android/src/main/java/chat/simplex/app/SimplexApp.kt +++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/SimplexApp.kt @@ -37,7 +37,7 @@ import java.util.concurrent.TimeUnit const val TAG = "SIMPLEX" -class SimplexApp: Application(), LifecycleEventObserver, Configuration.Provider { +class SimplexApp: Application(), LifecycleEventObserver { val chatModel: ChatModel get() = chatController.chatModel @@ -391,9 +391,4 @@ class SimplexApp: Application(), LifecycleEventObserver, Configuration.Provider } } } - - // Fix for an exception: - // WorkManager is not initialized properly. You have explicitly disabled WorkManagerInitializer in your manifest, have not manually called WorkManager#initialize at this point, and your Application does not implement Configuration.Provider. - override val workManagerConfiguration: Configuration - get() = Configuration.Builder().build() } diff --git a/cabal.project b/cabal.project index 51b35e0db7..7fb9f6d353 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: f5e666ae4f41351d5d5ac416cd6fb1d5fadc8ab7 + tag: 309ef3766cc6b69e0c3aa0c140faab25383b732a source-repository-package type: git diff --git a/scripts/nix/sha256map.nix b/scripts/nix/sha256map.nix index ec230ee09e..52dd21e8cd 100644 --- a/scripts/nix/sha256map.nix +++ b/scripts/nix/sha256map.nix @@ -1,5 +1,5 @@ { - "https://github.com/simplex-chat/simplexmq.git"."f5e666ae4f41351d5d5ac416cd6fb1d5fadc8ab7" = "1cq9apm9vp40v4ck0wcbis4463q3cjd9fbx5511hhh6lah6llifc"; + "https://github.com/simplex-chat/simplexmq.git"."309ef3766cc6b69e0c3aa0c140faab25383b732a" = "1ch03kizvsq3m5jwravyil529mc0lcfwj43czb1nhykbg8yb3cjv"; "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 fa80a2e7ec..9157ac7509 100644 --- a/src/Simplex/Chat.hs +++ b/src/Simplex/Chat.hs @@ -106,7 +106,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 (..), SocksMode (SMAlways), defaultNetworkConfig) +import Simplex.Messaging.Client (NetworkConfig (..), ProxyClientError (..), SocksMode (SMAlways), defaultNetworkConfig, textToHostMode) import qualified Simplex.Messaging.Crypto as C import Simplex.Messaging.Crypto.File (CryptoFile (..), CryptoFileArgs (..)) import qualified Simplex.Messaging.Crypto.File as CF @@ -120,7 +120,7 @@ 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.Transport.Client (defaultSocksProxyWithAuth) import Simplex.Messaging.Util import Simplex.Messaging.Version import Simplex.RemoteControl.Invitation (RCInvitation (..), RCSignedInvitation (..)) @@ -342,11 +342,11 @@ newChatController userServers user' = useServers config protocol <$> withTransaction chatStore (`getProtocolServers` user') updateNetworkConfig :: NetworkConfig -> SimpleNetCfg -> NetworkConfig -updateNetworkConfig cfg SimpleNetCfg {socksProxy, socksMode, smpProxyMode_, smpProxyFallback_, tcpTimeout_, logTLSErrors} = +updateNetworkConfig cfg SimpleNetCfg {socksProxy, socksMode, hostMode, requiredHostMode, 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, socksMode, logTLSErrors} + in cfg3 {socksProxy, socksMode, hostMode, requiredHostMode, logTLSErrors} withChatLock :: String -> CM a -> CM a withChatLock name action = asks chatLock >>= \l -> withLock l name action @@ -8320,14 +8320,16 @@ chatCommandP = <|> ("yes" $> TMEEnableKeepTTL) <|> ("no" $> TMEDisableKeepTTL) netCfgP = do - socksProxy <- "socks=" *> ("off" $> Nothing <|> "on" $> Just defaultSocksProxy <|> Just <$> strP) + socksProxy <- "socks=" *> ("off" $> Nothing <|> "on" $> Just defaultSocksProxyWithAuth <|> Just <$> strP) socksMode <- " socks-mode=" *> strP <|> pure SMAlways + hostMode <- " host-mode=" *> (textToHostMode . safeDecodeUtf8 <$?> A.takeTill (== ' ')) <|> pure (defaultHostMode socksProxy) + requiredHostMode <- " required-host-mode" *> onOffP <|> pure False 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, socksMode, smpProxyMode_, smpProxyFallback_, tcpTimeout_, logTLSErrors} + pure $ SimpleNetCfg {socksProxy, socksMode, hostMode, requiredHostMode, 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 7dccbb663d..1e00172cea 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, withTransactionPriority) import Simplex.Messaging.Agent.Store.SQLite.DB (SlowQueryStats (..)) import qualified Simplex.Messaging.Agent.Store.SQLite.DB as DB -import Simplex.Messaging.Client (SMPProxyFallback (..), SMPProxyMode (..), SocksMode (..)) +import Simplex.Messaging.Client (HostMode (..), SMPProxyFallback (..), SMPProxyMode (..), SocksMode (..)) import qualified Simplex.Messaging.Crypto as C import Simplex.Messaging.Crypto.File (CryptoFile (..)) import qualified Simplex.Messaging.Crypto.File as CF @@ -87,7 +87,7 @@ import Simplex.Messaging.Parsers (defaultJSON, dropPrefix, enumJSON, parseAll, p import Simplex.Messaging.Protocol (AProtoServerWithAuth, AProtocolType (..), CorrId, NtfServer, ProtocolType (..), ProtocolTypeI, QueueId, SMPMsgMeta (..), SProtocolType, SubscriptionMode (..), UserProtocol, XFTPServer, userProtocol) import Simplex.Messaging.TMap (TMap) import Simplex.Messaging.Transport (TLS, simplexMQVersion) -import Simplex.Messaging.Transport.Client (SocksProxy, TransportHost) +import Simplex.Messaging.Transport.Client (SocksProxyWithAuth, TransportHost) import Simplex.Messaging.Util (allFinally, catchAllErrors, catchAllErrors', tryAllErrors, tryAllErrors', (<$$>)) import Simplex.RemoteControl.Client import Simplex.RemoteControl.Invitation (RCSignedInvitation, RCVerifiedInvitation) @@ -984,8 +984,10 @@ data AppFilePathsConfig = AppFilePathsConfig deriving (Show) data SimpleNetCfg = SimpleNetCfg - { socksProxy :: Maybe SocksProxy, + { socksProxy :: Maybe SocksProxyWithAuth, socksMode :: SocksMode, + hostMode :: HostMode, + requiredHostMode :: Bool, smpProxyMode_ :: Maybe SMPProxyMode, smpProxyFallback_ :: Maybe SMPProxyFallback, tcpTimeout_ :: Maybe Int, @@ -994,7 +996,7 @@ data SimpleNetCfg = SimpleNetCfg deriving (Show) defaultSimpleNetCfg :: SimpleNetCfg -defaultSimpleNetCfg = SimpleNetCfg Nothing SMAlways Nothing Nothing Nothing False +defaultSimpleNetCfg = SimpleNetCfg Nothing SMAlways HMOnionViaSocks True Nothing Nothing Nothing False data ContactSubStatus = ContactSubStatus { contact :: Contact, diff --git a/src/Simplex/Chat/Options.hs b/src/Simplex/Chat/Options.hs index 0b5961b042..cd44966cc2 100644 --- a/src/Simplex/Chat/Options.hs +++ b/src/Simplex/Chat/Options.hs @@ -13,6 +13,7 @@ module Simplex.Chat.Options coreChatOptsP, getChatOpts, protocolServersP, + defaultHostMode, ) where @@ -20,6 +21,7 @@ import Control.Logger.Simple (LogLevel (..)) import qualified Data.Attoparsec.ByteString.Char8 as A import Data.ByteArray (ScrubbedBytes) import qualified Data.ByteString.Char8 as B +import Data.Maybe (fromMaybe) import Data.Text (Text) import qualified Data.Text as T import Data.Text.Encoding (encodeUtf8) @@ -27,11 +29,11 @@ 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.Client (HostMode (..), SocksMode (..), textToHostMode) import Simplex.Messaging.Encoding.String import Simplex.Messaging.Parsers (parseAll) import Simplex.Messaging.Protocol (ProtoServerWithAuth, ProtocolTypeI, SMPServerWithAuth, XFTPServerWithAuth) -import Simplex.Messaging.Transport.Client (defaultSocksProxy) +import Simplex.Messaging.Transport.Client (SocksProxyWithAuth (..), SocksAuth (..), defaultSocksProxyWithAuth) import System.FilePath (combine) data ChatOpts = ChatOpts @@ -123,7 +125,7 @@ coreChatOptsP appDir defaultDbFileName = do <> value [] ) socksProxy <- - flag' (Just defaultSocksProxy) (short 'x' <> help "Use local SOCKS5 proxy at :9050") + flag' (Just defaultSocksProxyWithAuth) (short 'x' <> help "Use local SOCKS5 proxy at :9050") <|> option strParse ( long "socks-proxy" @@ -139,6 +141,19 @@ coreChatOptsP appDir defaultDbFileName = do <> help "Use SOCKS5 proxy: always (default), onion (with onion-only relays)" <> value SMAlways ) + hostMode_ <- + optional $ + option + parseHostMode + ( long "host-mode" + <> metavar "HOST_MODE" + <> help "Preferred server host type: onion (when SOCKS proxy with isolate-by-auth is used), public" + ) + requiredHostMode <- + switch + ( long "required-host-mode" + <> help "Refuse connection if preferred server host type is not available" + ) smpProxyMode_ <- optional $ option @@ -226,7 +241,17 @@ coreChatOptsP appDir defaultDbFileName = do dbKey, smpServers, xftpServers, - simpleNetCfg = SimpleNetCfg {socksProxy, socksMode, smpProxyMode_, smpProxyFallback_, tcpTimeout_ = Just $ useTcpTimeout socksProxy t, logTLSErrors}, + simpleNetCfg = + SimpleNetCfg + { socksProxy, + socksMode, + hostMode = fromMaybe (defaultHostMode socksProxy) hostMode_, + requiredHostMode, + smpProxyMode_, + smpProxyFallback_, + tcpTimeout_ = Just $ useTcpTimeout socksProxy t, + logTLSErrors + }, logLevel, logConnections = logConnections || logLevel <= CLLInfo, logServerHosts = logServerHosts || logLevel <= CLLInfo, @@ -240,6 +265,11 @@ coreChatOptsP appDir defaultDbFileName = do useTcpTimeout p t = 1000000 * if t > 0 then t else maybe 7 (const 15) p defaultDbFilePath = combine appDir defaultDbFileName +defaultHostMode :: Maybe SocksProxyWithAuth -> HostMode +defaultHostMode = \case + Just (SocksProxyWithAuth SocksIsolateByAuth _) -> HMOnionViaSocks; + _ -> HMPublic + chatOptsP :: FilePath -> FilePath -> Parser ChatOpts chatOptsP appDir defaultDbFileName = do coreOptions <- coreChatOptsP appDir defaultDbFileName @@ -360,6 +390,9 @@ parseProtocolServers = eitherReader $ parseAll protocolServersP . B.pack strParse :: StrEncoding a => ReadM a strParse = eitherReader $ parseAll strP . encodeUtf8 . T.pack +parseHostMode :: ReadM HostMode +parseHostMode = eitherReader $ textToHostMode . T.pack + parseServerPort :: ReadM (Maybe String) parseServerPort = eitherReader $ parseAll serverPortP . B.pack