diff options
-rw-r--r-- | TraversableT.hs | 22 | ||||
-rw-r--r-- | xmppServer.hs | 53 |
2 files changed, 65 insertions, 10 deletions
diff --git a/TraversableT.hs b/TraversableT.hs new file mode 100644 index 00000000..6446fcc9 --- /dev/null +++ b/TraversableT.hs | |||
@@ -0,0 +1,22 @@ | |||
1 | module TraversableT where | ||
2 | |||
3 | import Data.Traversable | ||
4 | import Control.Monad (join) | ||
5 | |||
6 | newtype TraversableT m t a = TraversableT { runTraversableT :: m (t a) } | ||
7 | |||
8 | instance (Monad m, Traversable t, Monad t) => Monad (TraversableT m t) where | ||
9 | return = TraversableT . return . return | ||
10 | m >>= k = TraversableT $ do | ||
11 | a <- runTraversableT m | ||
12 | b <- forM a $ runTraversableT . k | ||
13 | return (join b) | ||
14 | fail s = TraversableT $ return (fail s) | ||
15 | |||
16 | liftT :: Monad m => t a -> TraversableT m t a | ||
17 | liftT = TraversableT . return | ||
18 | |||
19 | liftMT :: m (t a) -> TraversableT m t a | ||
20 | liftMT = TraversableT | ||
21 | |||
22 | |||
diff --git a/xmppServer.hs b/xmppServer.hs index 606bd05e..0f2b7c89 100644 --- a/xmppServer.hs +++ b/xmppServer.hs | |||
@@ -30,10 +30,10 @@ import qualified Data.ByteString.Lazy.Char8 as L | |||
30 | import qualified ConfigFiles | 30 | import qualified ConfigFiles |
31 | import Data.Maybe (listToMaybe,mapMaybe) | 31 | import Data.Maybe (listToMaybe,mapMaybe) |
32 | 32 | ||
33 | import TraversableT | ||
33 | import UTmp (ProcessID,users) | 34 | import UTmp (ProcessID,users) |
34 | import LocalPeerCred | 35 | import LocalPeerCred |
35 | import XMPPServer | 36 | import XMPPServer |
36 | -- import Server | ||
37 | 37 | ||
38 | unsplitJID (n,h,r) = jid | 38 | unsplitJID (n,h,r) = jid |
39 | where | 39 | where |
@@ -50,8 +50,7 @@ splitJID bjid = | |||
50 | splitAll c bjid = take 1 xs0 ++ map (Text.drop 1) (drop 1 xs0) | 50 | splitAll c bjid = take 1 xs0 ++ map (Text.drop 1) (drop 1 xs0) |
51 | where xs0 = Text.groupBy (\x y-> y/=c) bjid | 51 | where xs0 = Text.groupBy (\x y-> y/=c) bjid |
52 | server = head ys | 52 | server = head ys |
53 | name | 53 | name = case xs of |
54 | = case xs of | ||
55 | (n:s:_) -> Just n | 54 | (n:s:_) -> Just n |
56 | (s:_) -> Nothing | 55 | (s:_) -> Nothing |
57 | rsrc = case ys of | 56 | rsrc = case ys of |
@@ -78,13 +77,22 @@ data ClientState = ClientState | |||
78 | } | 77 | } |
79 | 78 | ||
80 | 79 | ||
81 | data PresenceContainer = PresenceContainer | 80 | data LocalPresence = LocalPresence |
82 | { networkClients :: Map ConnectionKey ClientState | 81 | { networkClients :: Map ConnectionKey ClientState |
83 | -- TODO: loginClients | 82 | -- TODO: loginClients |
84 | } | 83 | } |
85 | 84 | ||
85 | data RemotePresence = RemotePresence | ||
86 | { resources :: Map Text () | ||
87 | -- , localSubscribers :: Map Text () | ||
88 | -- ^ subset of clientsByUser who should be | ||
89 | -- notified about this presence. | ||
90 | } | ||
91 | |||
92 | |||
93 | |||
86 | pcSingletonNetworkClient key client = | 94 | pcSingletonNetworkClient key client = |
87 | PresenceContainer | 95 | LocalPresence |
88 | { networkClients = Map.singleton key client | 96 | { networkClients = Map.singleton key client |
89 | } | 97 | } |
90 | 98 | ||
@@ -101,10 +109,10 @@ pcIsEmpty pc = Map.null (networkClients pc) | |||
101 | 109 | ||
102 | data PresenceState = PresenceState | 110 | data PresenceState = PresenceState |
103 | { clients :: TVar (Map ConnectionKey ClientState) | 111 | { clients :: TVar (Map ConnectionKey ClientState) |
104 | , clientsByUser :: TVar (Map Text PresenceContainer) | 112 | , clientsByUser :: TVar (Map Text LocalPresence) |
105 | , remotesByPeer :: TVar (Map ConnectionKey | 113 | , remotesByPeer :: TVar (Map ConnectionKey |
106 | (Map UserName | 114 | (Map UserName |
107 | (Map ResourceName ()))) | 115 | RemotePresence)) |
108 | , associatedPeers :: TVar (Map SockAddr ()) | 116 | , associatedPeers :: TVar (Map SockAddr ()) |
109 | , server :: TMVar XMPPServer | 117 | , server :: TMVar XMPPServer |
110 | , keyToChan :: TVar (Map ConnectionKey Conn) | 118 | , keyToChan :: TVar (Map ConnectionKey Conn) |
@@ -192,8 +200,11 @@ tellClientHisName state k = forClient state k fallback go | |||
192 | 200 | ||
193 | toMapUnit xs = Map.fromList $ map (,()) xs | 201 | toMapUnit xs = Map.fromList $ map (,()) xs |
194 | 202 | ||
195 | resolveAllPeers hosts = fmap (toMapUnit . concat) $ mapM (fmap (take 1) . resolvePeer) hosts | 203 | resolveAllPeers hosts = fmap (toMapUnit . concat) $ Prelude.mapM (fmap (take 1) . resolvePeer) hosts |
196 | 204 | ||
205 | rosterGetStuff | ||
206 | :: (L.ByteString -> IO [L.ByteString]) | ||
207 | -> PresenceState -> ConnectionKey -> IO [Text] | ||
197 | rosterGetStuff what state k = forClient state k (return []) | 208 | rosterGetStuff what state k = forClient state k (return []) |
198 | $ \client -> do | 209 | $ \client -> do |
199 | jids <- | 210 | jids <- |
@@ -221,7 +232,29 @@ rosterGetSubscribers = rosterGetStuff ConfigFiles.getSubscribers | |||
221 | data Conn = Conn { connChan :: TChan Stanza | 232 | data Conn = Conn { connChan :: TChan Stanza |
222 | , auxAddr :: SockAddr } | 233 | , auxAddr :: SockAddr } |
223 | 234 | ||
224 | sendProbesAndSlocitations state k chan = do | 235 | textAdapter what u = fmap (map lazyByteStringToText) |
236 | $ what (textToLazyByteString u) | ||
237 | |||
238 | getBuddies' :: Text -> IO [Text] | ||
239 | getBuddies' = textAdapter ConfigFiles.getBuddies | ||
240 | getSolicited' :: Text -> IO [Text] | ||
241 | getSolicited' = textAdapter ConfigFiles.getSolicited | ||
242 | |||
243 | sendProbesAndSolicitations state k chan = do | ||
244 | cbu <- atomically $ readTVar $ clientsByUser state | ||
245 | -- get all buddies & solicited matching k for all users | ||
246 | us <- runTraversableT $ do | ||
247 | user <- liftT $ Map.keys cbu | ||
248 | (isbud,getter) <- liftT [(True ,getBuddies' ) | ||
249 | ,(False,getSolicited')] | ||
250 | bud <- liftMT $ getter user | ||
251 | let (u,h,r) = splitJID bud | ||
252 | addr <- liftMT $ resolvePeer h | ||
253 | liftT $ guard (PeerKey addr == k) | ||
254 | return (isbud,u) | ||
255 | |||
256 | let _ = us :: [(Bool,Maybe UserName)] | ||
257 | -- send probes for buddies, solicitations for solicited. | ||
225 | return () | 258 | return () |
226 | 259 | ||
227 | newConn state k addr outchan = do | 260 | newConn state k addr outchan = do |
@@ -229,7 +262,7 @@ newConn state k addr outchan = do | |||
229 | $ Map.insert k Conn { connChan = outchan | 262 | $ Map.insert k Conn { connChan = outchan |
230 | , auxAddr = addr } | 263 | , auxAddr = addr } |
231 | when (isPeerKey k) | 264 | when (isPeerKey k) |
232 | $ sendProbesAndSlocitations state k outchan | 265 | $ sendProbesAndSolicitations state k outchan |
233 | 266 | ||
234 | eofConn state k = atomically $ modifyTVar' (keyToChan state) $ Map.delete k | 267 | eofConn state k = atomically $ modifyTVar' (keyToChan state) $ Map.delete k |
235 | 268 | ||