Skip to content

Commit 7975814

Browse files
committed
server: support server roles and operators
1 parent a957693 commit 7975814

File tree

3 files changed

+77
-28
lines changed

3 files changed

+77
-28
lines changed

src/Simplex/Messaging/Agent.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -812,7 +812,7 @@ joinConn c userId connId hasNewConn enableNtfs cReq cInfo pqSupport subMode = do
812812
srv <- case cReq of
813813
CRInvitationUri ConnReqUriData {crSmpQueues = q :| _} _ ->
814814
getNextServer c userId [qServer q]
815-
_ -> getSMPServer c userId
815+
_ -> getSMPServer c userId -- TODO when connecting to contact address, also try gettings a different operator/server
816816
joinConnSrv c userId connId hasNewConn enableNtfs cReq cInfo pqSupport subMode srv
817817

818818
startJoinInvitation :: UserId -> ConnId -> Maybe SndQueue -> Bool -> ConnectionRequestUri 'CMInvitation -> PQSupport -> AM (ConnData, NewSndQueue, C.PublicKeyX25519, CR.Ratchet 'C.X448, CR.SndE2ERatchetParams 'C.X448)

src/Simplex/Messaging/Agent/Client.hs

Lines changed: 46 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ import qualified Data.ByteString.Base64 as B64
189189
import Data.ByteString.Char8 (ByteString)
190190
import qualified Data.ByteString.Char8 as B
191191
import Data.Either (isRight, partitionEithers)
192+
import qualified Data.Foldable as Foldable
192193
import Data.Functor (($>))
193194
import Data.Int (Int64)
194195
import Data.List (deleteFirstsBy, find, foldl', partition, (\\))
@@ -2033,34 +2034,63 @@ userServers c = case protocolTypeI @p of
20332034
SPXFTP -> xftpServers c
20342035
{-# INLINE userServers #-}
20352036

2036-
pickServer :: forall p. NonEmpty (ProtoServerWithAuth p) -> AM (ProtoServerWithAuth p)
2037+
pickServer :: forall p. NonEmpty (OperatorId, ProtoServerWithAuth p) -> AM (ProtoServerWithAuth p)
20372038
pickServer = \case
2038-
srv :| [] -> pure srv
2039+
(_, srv) :| [] -> pure srv
20392040
servers -> do
20402041
gen <- asks randomServer
2041-
atomically $ (servers L.!!) <$> stateTVar gen (randomR (0, L.length servers - 1))
2042+
atomically $ snd . (servers L.!!) <$> stateTVar gen (randomR (0, L.length servers - 1))
20422043

2043-
getNextServer :: forall p. (ProtocolTypeI p, UserProtocol p) => AgentClient -> UserId -> [ProtocolServer p] -> AM (ProtoServerWithAuth p)
2044-
getNextServer c userId usedSrvs = withUserServers c userId $ \srvs ->
2045-
case L.nonEmpty $ deleteFirstsBy sameSrvAddr' (L.toList srvs) (map noAuthSrv usedSrvs) of
2046-
Just srvs' -> pickServer srvs'
2047-
_ -> pickServer srvs
2044+
getNextServer ::
2045+
forall p. (ProtocolTypeI p, UserProtocol p) =>
2046+
AgentClient ->
2047+
UserId ->
2048+
(UserServers p -> NonEmpty (OperatorId, ProtoServerWithAuth p)) ->
2049+
Set TransportHost ->
2050+
AM (ProtoServerWithAuth p)
2051+
getNextServer c userId enabledSel usedHosts = withUserServers c userId enabledSel $ \srvs -> do
2052+
let (usedSrvs, unusedSrvs) = L.partition (isUsed . snd) srvs
2053+
usedOps :: Set OperatorId = foldl' (\s -> (`S.insert` s) . fst) S.empty usedSrvs
2054+
unusedOpSrvs = filter ((`S.notMember` usedOps) . fst) unusedSrvs
2055+
-- choose from: 1) servers of other operators, 2) other servers, 3) all servers
2056+
srvs' = fromMaybe srvs $ L.nonEmpty unusedOpSrvs <|> L.nonEmpty unusedSrvs
2057+
pickServer srvs'
2058+
where
2059+
isUsed (ProtoServerWithAuth ProtocolServer {host} _) = any (`S.member` usedHosts) host
20482060

2049-
withUserServers :: forall p a. (ProtocolTypeI p, UserProtocol p) => AgentClient -> UserId -> (NonEmpty (ProtoServerWithAuth p) -> AM a) -> AM a
2050-
withUserServers c userId action =
2061+
withUserServers ::
2062+
forall p a. (ProtocolTypeI p, UserProtocol p) =>
2063+
AgentClient ->
2064+
UserId ->
2065+
(UserServers p -> NonEmpty (OperatorId, ProtoServerWithAuth p)) ->
2066+
(NonEmpty (OperatorId, ProtoServerWithAuth p) -> AM a) ->
2067+
AM a
2068+
withUserServers c userId enabledSel action =
20512069
liftIO (TM.lookupIO userId $ userServers c) >>= \case
2052-
Just srvs -> action $ enabledSrvs srvs
2070+
Just srvs -> action $ enabledSel srvs
20532071
_ -> throwE $ INTERNAL "unknown userId - no user servers"
20542072

2055-
withNextSrv :: forall p a. (ProtocolTypeI p, UserProtocol p) => AgentClient -> UserId -> TVar [ProtocolServer p] -> [ProtocolServer p] -> (ProtoServerWithAuth p -> AM a) -> AM a
2056-
withNextSrv c userId usedSrvs initUsed action = do
2073+
withNextSrv ::
2074+
forall p a. (ProtocolTypeI p, UserProtocol p) =>
2075+
AgentClient ->
2076+
UserId ->
2077+
(UserServers p -> NonEmpty (OperatorId, ProtoServerWithAuth p)) ->
2078+
TVar (Set TransportHost) ->
2079+
Maybe (ProtocolServer p) ->
2080+
(ProtoServerWithAuth p -> AM a) ->
2081+
AM a
2082+
withNextSrv c userId enabledSel usedSrvs initUsed action = do
20572083
used <- readTVarIO usedSrvs
2058-
srvAuth@(ProtoServerWithAuth srv _) <- getNextServer c userId used
2084+
srvAuth@(ProtoServerWithAuth srv _) <- getNextServer c userId enabledSel used
20592085
srvs_ <- liftIO $ TM.lookupIO userId $ userServers c
2060-
let unused = maybe [] ((\\ used) . map protoServer . L.toList . enabledSrvs) srvs_
2061-
used' = if null unused then initUsed else srv : used
2086+
let unused = undefined -- maybe [] ((\\ used) . map (protoServer . snd) . L.toList . enabledSel) srvs_
2087+
used'
2088+
| null unused = maybe id addHosts initUsed S.empty
2089+
| otherwise = addHosts srv used
20622090
atomically $ writeTVar usedSrvs $! used'
20632091
action srvAuth
2092+
where
2093+
addHosts ProtocolServer {host} s = Foldable.foldl' (flip S.insert) s host
20642094

20652095
incSMPServerStat :: AgentClient -> UserId -> SMPServer -> (AgentSMPServerStats -> TVar Int) -> STM ()
20662096
incSMPServerStat c userId srv sel = incSMPServerStat' c userId srv sel 1

src/Simplex/Messaging/Agent/Env/SQLite.hs

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ module Simplex.Messaging.Agent.Env.SQLite
1717
AgentConfig (..),
1818
InitialAgentServers (..),
1919
ServerCfg (..),
20+
OperatorId,
2021
UserServers (..),
2122
NetworkConfig (..),
2223
presetServerCfg,
@@ -54,6 +55,8 @@ import Data.List.NonEmpty (NonEmpty)
5455
import qualified Data.List.NonEmpty as L
5556
import Data.Map.Strict (Map)
5657
import Data.Maybe (fromMaybe)
58+
import Data.Set (Set)
59+
import qualified Data.Set as S
5760
import Data.Time.Clock (NominalDiffTime, nominalDay)
5861
import Data.Time.Clock.System (SystemTime (..))
5962
import Data.Word (Word16)
@@ -71,10 +74,11 @@ import Simplex.Messaging.Notifications.Client (defaultNTFClientConfig)
7174
import Simplex.Messaging.Notifications.Transport (NTFVersion)
7275
import Simplex.Messaging.Notifications.Types
7376
import Simplex.Messaging.Parsers (defaultJSON)
74-
import Simplex.Messaging.Protocol (NtfServer, ProtoServerWithAuth, ProtocolServer, ProtocolType (..), ProtocolTypeI, VersionRangeSMPC, XFTPServer, supportedSMPClientVRange)
77+
import Simplex.Messaging.Protocol (NtfServer, ProtoServerWithAuth (..), ProtocolServer (..), ProtocolType (..), ProtocolTypeI, VersionRangeSMPC, XFTPServer, supportedSMPClientVRange)
7578
import Simplex.Messaging.TMap (TMap)
7679
import qualified Simplex.Messaging.TMap as TM
7780
import Simplex.Messaging.Transport (SMPVersion)
81+
import Simplex.Messaging.Transport.Client (TransportHost)
7882
import Simplex.Messaging.Util (allFinally, catchAllErrors, catchAllErrors', tryAllErrors, tryAllErrors')
7983
import System.Mem.Weak (Weak)
8084
import System.Random (StdGen, newStdGen)
@@ -94,29 +98,42 @@ data InitialAgentServers = InitialAgentServers
9498

9599
data ServerCfg p = ServerCfg
96100
{ server :: ProtoServerWithAuth p,
101+
operator :: OperatorId,
97102
preset :: Bool,
98103
tested :: Maybe Bool,
99-
enabled :: Bool
104+
enabled :: Bool,
105+
roles :: ServerRoles
100106
}
101107
deriving (Show)
102108

103-
enabledServerCfg :: ProtoServerWithAuth p -> ServerCfg p
104-
enabledServerCfg server = ServerCfg {server, preset = False, tested = Nothing, enabled = True}
109+
data ServerRoles = ServerRoles
110+
{ storage :: Bool,
111+
proxy :: Bool
112+
}
113+
deriving (Show)
114+
115+
enabledServerCfg :: ProtoServerWithAuth p -> OperatorId -> ServerCfg p
116+
enabledServerCfg server operator =
117+
ServerCfg {server, operator, preset = False, tested = Nothing, enabled = True, roles = ServerRoles True True}
105118

106-
presetServerCfg :: Bool -> ProtoServerWithAuth p -> ServerCfg p
107-
presetServerCfg enabled server = ServerCfg {server, preset = True, tested = Nothing, enabled}
119+
presetServerCfg :: Bool -> ServerRoles -> ProtoServerWithAuth p -> OperatorId -> ServerCfg p
120+
presetServerCfg enabled roles server operator =
121+
ServerCfg {server, operator, preset = True, tested = Nothing, enabled, roles}
108122

109123
data UserServers p = UserServers
110-
{ enabledSrvs :: NonEmpty (ProtoServerWithAuth p),
111-
knownSrvs :: NonEmpty (ProtocolServer p)
124+
{ storageSrvs :: NonEmpty (OperatorId, ProtoServerWithAuth p),
125+
proxySrvs :: NonEmpty (OperatorId, ProtoServerWithAuth p),
126+
knownHosts :: Set TransportHost
112127
}
113128

129+
type OperatorId = Int64
130+
114131
-- This function sets all servers as enabled in case all passed servers are disabled.
115132
mkUserServers :: NonEmpty (ServerCfg p) -> UserServers p
116-
mkUserServers srvs = UserServers {enabledSrvs, knownSrvs}
133+
mkUserServers srvs = UserServers {storageSrvs = filterSrvs storage, proxySrvs = filterSrvs proxy, knownHosts}
117134
where
118-
enabledSrvs = L.map (\ServerCfg {server} -> server) $ fromMaybe srvs $ L.nonEmpty $ L.filter (\ServerCfg {enabled} -> enabled) srvs
119-
knownSrvs = L.map (\ServerCfg {server = ProtoServerWithAuth srv _} -> srv) srvs
135+
filterSrvs role = L.map (\ServerCfg {operator, server} -> (operator, server)) $ fromMaybe srvs $ L.nonEmpty $ L.filter (\ServerCfg {enabled, roles} -> enabled && role roles) srvs
136+
knownHosts = S.unions $ L.map (\ServerCfg {server = ProtoServerWithAuth ProtocolServer {host} _} -> S.fromList $ L.toList host) srvs
120137

121138
data AgentConfig = AgentConfig
122139
{ tcpPort :: Maybe ServiceName,
@@ -333,6 +350,8 @@ updateRestartCount t (RestartCount minute count) = do
333350

334351
$(pure [])
335352

353+
$(JQ.deriveJSON defaultJSON ''ServerRoles)
354+
336355
instance ProtocolTypeI p => ToJSON (ServerCfg p) where
337356
toEncoding = $(JQ.mkToEncoding defaultJSON ''ServerCfg)
338357
toJSON = $(JQ.mkToJSON defaultJSON ''ServerCfg)

0 commit comments

Comments
 (0)