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:
Evgeny Poberezkin
2024-05-31 23:41:20 +01:00
committed by GitHub
parent c52e5349db
commit ef30fcf5e2
8 changed files with 95 additions and 43 deletions
+15 -1
View File
@@ -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
+1 -2
View File
@@ -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
View File
@@ -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
+9 -5
View File
@@ -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"
]
+9 -3
View File
@@ -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]