mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-06-07 06:42:35 +00:00
cli: options for private message routing and fallback mode (#4256)
* cli: options for private message routing and fallback mode * remove short options * fix tests * encoding * fix
This commit is contained in:
committed by
GitHub
parent
c52e5349db
commit
ef30fcf5e2
@@ -75,6 +75,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 (SMPProxyMode (..), SMPProxyFallback (..))
|
||||
import qualified Simplex.Messaging.Crypto as C
|
||||
import Simplex.Messaging.Crypto.File (CryptoFile (..))
|
||||
import qualified Simplex.Messaging.Crypto.File as CF
|
||||
@@ -86,7 +87,7 @@ import Simplex.Messaging.Protocol (AProtoServerWithAuth, AProtocolType (..), Cor
|
||||
import Simplex.Messaging.Server.QueueStore.QueueInfo
|
||||
import Simplex.Messaging.TMap (TMap)
|
||||
import Simplex.Messaging.Transport (TLS, simplexMQVersion)
|
||||
import Simplex.Messaging.Transport.Client (TransportHost)
|
||||
import Simplex.Messaging.Transport.Client (SocksProxy, TransportHost)
|
||||
import Simplex.Messaging.Util (allFinally, catchAllErrors, catchAllErrors', tryAllErrors, tryAllErrors', (<$$>))
|
||||
import Simplex.RemoteControl.Client
|
||||
import Simplex.RemoteControl.Invitation (RCSignedInvitation, RCVerifiedInvitation)
|
||||
@@ -351,6 +352,7 @@ data ChatCommand
|
||||
| GetChatItemTTL
|
||||
| APISetNetworkConfig NetworkConfig
|
||||
| APIGetNetworkConfig
|
||||
| SetNetworkConfig SimpleNetCfg
|
||||
| APISetNetworkInfo UserNetworkInfo
|
||||
| ReconnectAllServers
|
||||
| APISetChatSettings ChatRef ChatSettings
|
||||
@@ -961,6 +963,18 @@ data AppFilePathsConfig = AppFilePathsConfig
|
||||
}
|
||||
deriving (Show)
|
||||
|
||||
data SimpleNetCfg = SimpleNetCfg
|
||||
{ socksProxy :: Maybe SocksProxy,
|
||||
smpProxyMode_ :: Maybe SMPProxyMode,
|
||||
smpProxyFallback_ :: Maybe SMPProxyFallback,
|
||||
tcpTimeout_ :: Maybe Int,
|
||||
logTLSErrors :: Bool
|
||||
}
|
||||
deriving (Show)
|
||||
|
||||
defaultSimpleNetCfg :: SimpleNetCfg
|
||||
defaultSimpleNetCfg = SimpleNetCfg Nothing Nothing Nothing Nothing False
|
||||
|
||||
data ContactSubStatus = ContactSubStatus
|
||||
{ contact :: Contact,
|
||||
contactError :: Maybe ChatError
|
||||
|
||||
@@ -48,7 +48,6 @@ import Simplex.Chat.Types
|
||||
import Simplex.Messaging.Agent.Client (agentClientStore)
|
||||
import Simplex.Messaging.Agent.Env.SQLite (createAgentStore)
|
||||
import Simplex.Messaging.Agent.Store.SQLite (MigrationConfirmation (..), MigrationError, closeSQLiteStore, reopenSQLiteStore)
|
||||
import Simplex.Messaging.Client (defaultNetworkConfig)
|
||||
import qualified Simplex.Messaging.Crypto as C
|
||||
import Simplex.Messaging.Encoding.String
|
||||
import Simplex.Messaging.Parsers (defaultJSON, dropPrefix, sumTypeJSON)
|
||||
@@ -192,7 +191,7 @@ mobileChatOpts dbFilePrefix =
|
||||
dbKey = "", -- for API database is already opened, and the key in options is not used
|
||||
smpServers = [],
|
||||
xftpServers = [],
|
||||
networkConfig = defaultNetworkConfig,
|
||||
simpleNetCfg = defaultSimpleNetCfg,
|
||||
logLevel = CLLImportant,
|
||||
logConnections = False,
|
||||
logServerHosts = True,
|
||||
|
||||
+29
-17
@@ -13,7 +13,6 @@ module Simplex.Chat.Options
|
||||
coreChatOptsP,
|
||||
getChatOpts,
|
||||
protocolServersP,
|
||||
fullNetworkConfig,
|
||||
)
|
||||
where
|
||||
|
||||
@@ -22,15 +21,17 @@ import qualified Data.Attoparsec.ByteString.Char8 as A
|
||||
import Data.ByteArray (ScrubbedBytes)
|
||||
import qualified Data.ByteString.Char8 as B
|
||||
import Data.Text (Text)
|
||||
import qualified Data.Text as T
|
||||
import Data.Text.Encoding (encodeUtf8)
|
||||
import Numeric.Natural (Natural)
|
||||
import Options.Applicative
|
||||
import Simplex.Chat.Controller (ChatLogLevel (..), updateStr, versionNumber, versionString)
|
||||
import Simplex.Chat.Controller (ChatLogLevel (..), SimpleNetCfg (..), updateStr, versionNumber, versionString)
|
||||
import Simplex.FileTransfer.Description (mb)
|
||||
import Simplex.Messaging.Client (NetworkConfig (..), defaultNetworkConfig)
|
||||
import Simplex.Messaging.Client (SMPProxyMode (..), SMPProxyFallback (..))
|
||||
import Simplex.Messaging.Encoding.String
|
||||
import Simplex.Messaging.Parsers (parseAll)
|
||||
import Simplex.Messaging.Protocol (ProtoServerWithAuth, ProtocolTypeI, SMPServerWithAuth, XFTPServerWithAuth)
|
||||
import Simplex.Messaging.Transport.Client (SocksProxy, defaultSocksProxy)
|
||||
import Simplex.Messaging.Transport.Client (defaultSocksProxy)
|
||||
import System.FilePath (combine)
|
||||
|
||||
data ChatOpts = ChatOpts
|
||||
@@ -55,7 +56,7 @@ data CoreChatOpts = CoreChatOpts
|
||||
dbKey :: ScrubbedBytes,
|
||||
smpServers :: [SMPServerWithAuth],
|
||||
xftpServers :: [XFTPServerWithAuth],
|
||||
networkConfig :: NetworkConfig,
|
||||
simpleNetCfg :: SimpleNetCfg,
|
||||
logLevel :: ChatLogLevel,
|
||||
logConnections :: Bool,
|
||||
logServerHosts :: Bool,
|
||||
@@ -123,18 +124,34 @@ coreChatOptsP appDir defaultDbFileName = do
|
||||
socksProxy <-
|
||||
flag' (Just defaultSocksProxy) (short 'x' <> help "Use local SOCKS5 proxy at :9050")
|
||||
<|> option
|
||||
parseSocksProxy
|
||||
strParse
|
||||
( long "socks-proxy"
|
||||
<> metavar "SOCKS5"
|
||||
<> help "Use SOCKS5 proxy at `ipv4:port` or `:port`"
|
||||
<> value Nothing
|
||||
)
|
||||
smpProxyMode_ <-
|
||||
optional $
|
||||
option
|
||||
strParse
|
||||
( long "smp-proxy"
|
||||
<> metavar "SMP_PROXY_MODE"
|
||||
<> help "Use private message routing: always, unknown, unprotected, never (default)"
|
||||
)
|
||||
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)"
|
||||
)
|
||||
t <-
|
||||
option
|
||||
auto
|
||||
( long "tcp-timeout"
|
||||
<> metavar "TIMEOUT"
|
||||
<> help "TCP timeout, seconds (default: 5/10 without/with SOCKS5 proxy)"
|
||||
<> help "TCP timeout, seconds (default: 7/15 without/with SOCKS5 proxy)"
|
||||
<> value 0
|
||||
)
|
||||
logLevel <-
|
||||
@@ -149,7 +166,7 @@ coreChatOptsP appDir defaultDbFileName = do
|
||||
logTLSErrors <-
|
||||
switch
|
||||
( long "log-tls-errors"
|
||||
<> help "Log TLS errors (also enabled with `-l debug`)"
|
||||
<> help "Log TLS errors"
|
||||
)
|
||||
logConnections <-
|
||||
switch
|
||||
@@ -194,7 +211,7 @@ coreChatOptsP appDir defaultDbFileName = do
|
||||
dbKey,
|
||||
smpServers,
|
||||
xftpServers,
|
||||
networkConfig = fullNetworkConfig socksProxy (useTcpTimeout socksProxy t) (logTLSErrors || logLevel == CLLDebug),
|
||||
simpleNetCfg = SimpleNetCfg {socksProxy, smpProxyMode_, smpProxyFallback_, tcpTimeout_ = Just $ useTcpTimeout socksProxy t, logTLSErrors},
|
||||
logLevel,
|
||||
logConnections = logConnections || logLevel <= CLLInfo,
|
||||
logServerHosts = logServerHosts || logLevel <= CLLInfo,
|
||||
@@ -204,7 +221,7 @@ coreChatOptsP appDir defaultDbFileName = do
|
||||
highlyAvailable
|
||||
}
|
||||
where
|
||||
useTcpTimeout p t = 1000000 * if t > 0 then t else maybe 5 (const 10) p
|
||||
useTcpTimeout p t = 1000000 * if t > 0 then t else maybe 7 (const 15) p
|
||||
defaultDbFilePath = combine appDir defaultDbFileName
|
||||
|
||||
chatOptsP :: FilePath -> FilePath -> Parser ChatOpts
|
||||
@@ -321,16 +338,11 @@ chatOptsP appDir defaultDbFileName = do
|
||||
maintenance
|
||||
}
|
||||
|
||||
fullNetworkConfig :: Maybe SocksProxy -> Int -> Bool -> NetworkConfig
|
||||
fullNetworkConfig socksProxy tcpTimeout logTLSErrors =
|
||||
let tcpConnectTimeout = (tcpTimeout * 3) `div` 2
|
||||
in defaultNetworkConfig {socksProxy, tcpTimeout, tcpConnectTimeout, logTLSErrors}
|
||||
|
||||
parseProtocolServers :: ProtocolTypeI p => ReadM [ProtoServerWithAuth p]
|
||||
parseProtocolServers = eitherReader $ parseAll protocolServersP . B.pack
|
||||
|
||||
parseSocksProxy :: ReadM (Maybe SocksProxy)
|
||||
parseSocksProxy = eitherReader $ parseAll strP . B.pack
|
||||
strParse :: StrEncoding a => ReadM a
|
||||
strParse = eitherReader $ parseAll strP . encodeUtf8 . T.pack
|
||||
|
||||
parseServerPort :: ReadM (Maybe String)
|
||||
parseServerPort = eitherReader $ parseAll serverPortP . B.pack
|
||||
|
||||
@@ -6,15 +6,16 @@ module Simplex.Chat.Terminal.Main where
|
||||
import Control.Concurrent (forkIO, threadDelay)
|
||||
import Control.Concurrent.STM
|
||||
import Control.Monad
|
||||
import Data.Maybe (fromMaybe)
|
||||
import Data.Time.Clock (getCurrentTime)
|
||||
import Data.Time.LocalTime (getCurrentTimeZone)
|
||||
import Network.Socket
|
||||
import Simplex.Chat.Controller (ChatConfig, ChatController (..), ChatResponse (..), currentRemoteHost, versionNumber, versionString)
|
||||
import Simplex.Chat.Controller (ChatConfig, ChatController (..), ChatResponse (..), SimpleNetCfg (..), currentRemoteHost, versionNumber, versionString)
|
||||
import Simplex.Chat.Core
|
||||
import Simplex.Chat.Options
|
||||
import Simplex.Chat.Terminal
|
||||
import Simplex.Chat.View (serializeChatResponse)
|
||||
import Simplex.Messaging.Client (NetworkConfig (..))
|
||||
import Simplex.Chat.View (serializeChatResponse, smpProxyModeStr)
|
||||
import Simplex.Messaging.Client (NetworkConfig (..), defaultNetworkConfig)
|
||||
import System.Directory (getAppUserDataDirectory)
|
||||
import System.Exit (exitFailure)
|
||||
import System.Terminal (withTerminal)
|
||||
@@ -51,7 +52,7 @@ simplexChatCLI cfg server_ = do
|
||||
putStrLn $ serializeChatResponse (rh, Just user) ts tz rh r
|
||||
|
||||
welcome :: ChatOpts -> IO ()
|
||||
welcome ChatOpts {coreOptions = CoreChatOpts {dbFilePrefix, networkConfig}} =
|
||||
welcome ChatOpts {coreOptions = CoreChatOpts {dbFilePrefix, simpleNetCfg = SimpleNetCfg {socksProxy, smpProxyMode_, smpProxyFallback_}}} =
|
||||
mapM_
|
||||
putStrLn
|
||||
[ versionString versionNumber,
|
||||
@@ -59,6 +60,9 @@ welcome ChatOpts {coreOptions = CoreChatOpts {dbFilePrefix, networkConfig}} =
|
||||
maybe
|
||||
"direct network connection - use `/network` command or `-x` CLI option to connect via SOCKS5 at :9050"
|
||||
(("using SOCKS5 proxy " <>) . show)
|
||||
(socksProxy networkConfig),
|
||||
socksProxy,
|
||||
smpProxyModeStr
|
||||
(fromMaybe (smpProxyMode defaultNetworkConfig) smpProxyMode_)
|
||||
(fromMaybe (smpProxyFallback defaultNetworkConfig) smpProxyFallback_),
|
||||
"type \"/help\" or \"/h\" for usage info"
|
||||
]
|
||||
|
||||
@@ -55,6 +55,7 @@ import Simplex.Messaging.Agent.Client (ProtocolTestFailure (..), ProtocolTestSte
|
||||
import Simplex.Messaging.Agent.Env.SQLite (NetworkConfig (..))
|
||||
import Simplex.Messaging.Agent.Protocol
|
||||
import Simplex.Messaging.Agent.Store.SQLite.DB (SlowQueryStats (..))
|
||||
import Simplex.Messaging.Client (SMPProxyMode (..), SMPProxyFallback)
|
||||
import qualified Simplex.Messaging.Crypto as C
|
||||
import Simplex.Messaging.Crypto.File (CryptoFile (..), CryptoFileArgs (..))
|
||||
import qualified Simplex.Messaging.Crypto.Ratchet as CR
|
||||
@@ -64,7 +65,7 @@ import Simplex.Messaging.Parsers (dropPrefix, taggedObjectJSON)
|
||||
import Simplex.Messaging.Protocol (AProtoServerWithAuth (..), AProtocolType, ProtoServerWithAuth, ProtocolServer (..), ProtocolTypeI, SProtocolType (..))
|
||||
import qualified Simplex.Messaging.Protocol as SMP
|
||||
import Simplex.Messaging.Transport.Client (TransportHost (..))
|
||||
import Simplex.Messaging.Util (tshow)
|
||||
import Simplex.Messaging.Util (bshow, safeDecodeUtf8, tshow)
|
||||
import Simplex.Messaging.Version hiding (version)
|
||||
import Simplex.RemoteControl.Types (RCCtrlAddress (..))
|
||||
import System.Console.ANSI.Types
|
||||
@@ -1213,12 +1214,17 @@ viewChatItemTTL = \case
|
||||
deletedAfter ttlStr = ["old messages are set to be deleted after: " <> ttlStr]
|
||||
|
||||
viewNetworkConfig :: NetworkConfig -> [StyledString]
|
||||
viewNetworkConfig NetworkConfig {socksProxy, tcpTimeout} =
|
||||
viewNetworkConfig NetworkConfig {socksProxy, tcpTimeout, smpProxyMode, smpProxyFallback} =
|
||||
[ plain $ maybe "direct network connection" (("using SOCKS5 proxy " <>) . show) socksProxy,
|
||||
"TCP timeout: " <> sShow tcpTimeout,
|
||||
"use " <> highlight' "/network socks=<on/off/[ipv4]:port>[ timeout=<seconds>]" <> " to change settings"
|
||||
plain $ smpProxyModeStr smpProxyMode smpProxyFallback,
|
||||
"use " <> highlight' "/network socks=<on/off/[ipv4]:port>[ timeout=<seconds>][ smp-proxy=always/unknown/unprotected/never][ smp-proxy-fallback=no/protected/yes]" <> " to change settings"
|
||||
]
|
||||
|
||||
smpProxyModeStr :: SMPProxyMode -> SMPProxyFallback -> String
|
||||
smpProxyModeStr SPMNever _ = "private message routing disabled."
|
||||
smpProxyModeStr mode fallback = T.unpack $ safeDecodeUtf8 $ "private message routing mode: " <> strEncode mode <> ", fallback: " <> strEncode fallback
|
||||
|
||||
viewContactInfo :: Contact -> Maybe ConnectionStats -> Maybe Profile -> [StyledString]
|
||||
viewContactInfo ct@Contact {contactId, profile = LocalProfile {localAlias, contactLink}, activeConn, uiThemes, customData} stats incognitoProfile =
|
||||
["contact ID: " <> sShow contactId]
|
||||
|
||||
Reference in New Issue
Block a user