diff options
-rw-r--r-- | Presence/main.hs | 65 |
1 files changed, 42 insertions, 23 deletions
diff --git a/Presence/main.hs b/Presence/main.hs index 9c11baae..f17b8340 100644 --- a/Presence/main.hs +++ b/Presence/main.hs | |||
@@ -57,28 +57,26 @@ import qualified Text.Show.ByteString as L | |||
57 | import Network.Socket (Family(AF_INET,AF_INET6)) | 57 | import Network.Socket (Family(AF_INET,AF_INET6)) |
58 | 58 | ||
59 | 59 | ||
60 | data UnixSession = UnixSession { | 60 | data ClientSession = ClientSession { |
61 | localhost :: Peer, -- ByteString, | 61 | localhost :: Peer, -- ByteString, |
62 | unix_uid :: (IORef (Maybe UserID)), | 62 | unix_uid :: (IORef (Maybe UserID)), |
63 | unix_resource :: (IORef (Maybe L.ByteString)), | 63 | unix_resource :: (IORef (Maybe L.ByteString)), |
64 | announced :: TVar (Set JID), | ||
65 | presence_state :: PresenceState | 64 | presence_state :: PresenceState |
66 | } | 65 | } |
67 | 66 | ||
68 | instance XMPPSession UnixSession where | 67 | instance XMPPSession ClientSession where |
69 | data XMPPClass UnixSession = UnixSessions PresenceState | 68 | data XMPPClass ClientSession = ClientSessions PresenceState |
70 | 69 | ||
71 | newSession (UnixSessions state) sock = do | 70 | newSession (ClientSessions state) sock = do |
72 | muid <- getLocalPeerCred sock | 71 | muid <- getLocalPeerCred sock |
73 | L.putStrLn $ "SESSION: open " <++> bshow muid | 72 | L.putStrLn $ "CLIENT SESSION: open " <++> bshow muid |
74 | uid_ref <- newIORef muid | 73 | uid_ref <- newIORef muid |
75 | res_ref <- newIORef Nothing | 74 | res_ref <- newIORef Nothing |
76 | jids <- newTVarIO Set.empty | 75 | return $ ClientSession (hostname state) uid_ref res_ref state |
77 | return $ UnixSession (hostname state) uid_ref res_ref jids state | ||
78 | 76 | ||
79 | setResource s resource = do | 77 | setResource s resource = do |
80 | writeIORef (unix_resource s) (Just resource) | 78 | writeIORef (unix_resource s) (Just resource) |
81 | L.putStrLn $ "SESSION: resource " <++> resource | 79 | L.putStrLn $ "CLIENT SESSION: resource " <++> resource |
82 | 80 | ||
83 | getJID s = do | 81 | getJID s = do |
84 | let host = localhost s | 82 | let host = localhost s |
@@ -94,14 +92,11 @@ instance XMPPSession UnixSession where | |||
94 | muid | 92 | muid |
95 | rsc <- readIORef (unix_resource s) | 93 | rsc <- readIORef (unix_resource s) |
96 | -- let jid = user <++> "@" <++> host <++?> "/" <++$> rsc | 94 | -- let jid = user <++> "@" <++> host <++?> "/" <++$> rsc |
97 | L.putStrLn $ "SESSION: jid " <++> L.show (JID (Just user) host rsc) | 95 | L.putStrLn $ "CLIENT SESSION: jid " <++> L.show (JID (Just user) host rsc) |
98 | return (JID (Just user) host rsc) | 96 | return (JID (Just user) host rsc) |
99 | 97 | ||
100 | closeSession session = do | 98 | closeSession session = do |
101 | L.putStrLn "SESSION: close" | 99 | L.putStrLn "CLIENT SESSION: close" |
102 | js <- fmap Set.toList (readTVarIO . announced $ session) | ||
103 | let offline jid = Presence jid Offline | ||
104 | forM_ js $ announcePresence session . offline | ||
105 | 100 | ||
106 | subscribe session Nothing = do | 101 | subscribe session Nothing = do |
107 | let tmvar = localSubscriber (presence_state session) | 102 | let tmvar = localSubscriber (presence_state session) |
@@ -110,10 +105,35 @@ instance XMPPSession UnixSession where | |||
110 | let tvar = subscriberMap (presence_state session) | 105 | let tvar = subscriberMap (presence_state session) |
111 | atomically $ subscribeToMap tvar jid | 106 | atomically $ subscribeToMap tvar jid |
112 | 107 | ||
108 | announcePresence _ _ = error "announcePresence on client session?" | ||
109 | |||
110 | |||
111 | data PeerSession = PeerSession { | ||
112 | announced :: TVar (Set JID), | ||
113 | peer_global :: PresenceState | ||
114 | } | ||
115 | instance XMPPSession PeerSession where | ||
116 | data XMPPClass PeerSession = PeerSessions PresenceState | ||
117 | |||
118 | setResource _ _ = error "setResource on peer session?" | ||
119 | getJID _ = error "getJID on peer session?" | ||
120 | subscribe _ _ = error "subscribe on peer session?" | ||
121 | |||
122 | newSession (PeerSessions state) sock = do | ||
123 | L.putStrLn $ "PEER SESSION: open" | ||
124 | jids <- newTVarIO Set.empty | ||
125 | return $ PeerSession jids state | ||
126 | |||
127 | closeSession session = do | ||
128 | L.putStrLn "PEER SESSION: close" | ||
129 | js <- fmap Set.toList (readTVarIO . announced $ session) | ||
130 | let offline jid = Presence jid Offline | ||
131 | forM_ js $ announcePresence session . offline | ||
132 | |||
113 | announcePresence session (Presence jid status) = do | 133 | announcePresence session (Presence jid status) = do |
114 | (greedy,subs) <- atomically $ do | 134 | (greedy,subs) <- atomically $ do |
115 | subs <- readTVar $ subscriberMap (presence_state session) | 135 | subs <- readTVar $ subscriberMap (peer_global session) |
116 | greedy <- fmap snd $ readTMVar $ localSubscriber (presence_state session) | 136 | greedy <- fmap snd $ readTMVar $ localSubscriber (peer_global session) |
117 | return (greedy,subs) | 137 | return (greedy,subs) |
118 | update_presence (Just greedy) (fmap snd subs) (Set.singleton jid) (const status) | 138 | update_presence (Just greedy) (fmap snd subs) (Set.singleton jid) (const status) |
119 | liftIO . atomically $ do | 139 | liftIO . atomically $ do |
@@ -123,7 +143,6 @@ instance XMPPSession UnixSession where | |||
123 | Offline -> Set.delete jid jids | 143 | Offline -> Set.delete jid jids |
124 | _ -> Set.insert jid jids | 144 | _ -> Set.insert jid jids |
125 | 145 | ||
126 | |||
127 | subscribeToChan tmvar = | 146 | subscribeToChan tmvar = |
128 | (do (cnt,chan) <- takeTMVar tmvar | 147 | (do (cnt,chan) <- takeTMVar tmvar |
129 | putTMVar tmvar (cnt+1,chan) | 148 | putTMVar tmvar (cnt+1,chan) |
@@ -229,16 +248,16 @@ instance XMPPConfig UnixConfig where | |||
229 | start :: Network.Socket.Family -> IO () | 248 | start :: Network.Socket.Family -> IO () |
230 | start ip4or6 = do | 249 | start ip4or6 = do |
231 | let host = LocalHost | 250 | let host = LocalHost |
232 | tracked <- newPresenceState host | 251 | global_state <- newPresenceState host |
233 | let dologin e = track_login host tracked e | 252 | let dologin e = track_login host global_state e |
234 | dologin :: t -> IO () | 253 | dologin :: t -> IO () |
235 | 254 | ||
236 | chan <- atomically $ subscribeToChan (localSubscriber tracked) | 255 | chan <- atomically $ subscribeToChan (localSubscriber global_state) |
237 | remotes <- forkIO $ seekRemotePeers UnixConfig chan | 256 | remotes <- forkIO $ seekRemotePeers UnixConfig chan |
238 | 257 | ||
239 | installHandler sigUSR1 (Catch (dologin (userError "signaled"))) Nothing | 258 | installHandler sigUSR1 (Catch (dologin (userError "signaled"))) Nothing |
240 | -- installHandler sigTERM (CatchOnce (dologin (userError "term signaled"))) Nothing | 259 | -- installHandler sigTERM (CatchOnce (dologin (userError "term signaled"))) Nothing |
241 | mtty <- monitorTTY (on_chvt tracked) | 260 | mtty <- monitorTTY (on_chvt global_state) |
242 | inotify <- initINotify | 261 | inotify <- initINotify |
243 | #ifndef NOUTMP | 262 | #ifndef NOUTMP |
244 | wd <- addWatch | 263 | wd <- addWatch |
@@ -247,8 +266,8 @@ start ip4or6 = do | |||
247 | utmp_file | 266 | utmp_file |
248 | dologin | 267 | dologin |
249 | #endif | 268 | #endif |
250 | clients <- listenForXmppClients ip4or6 (UnixSessions tracked) 5222 HNil | 269 | clients <- listenForXmppClients ip4or6 (ClientSessions global_state) 5222 HNil |
251 | peers <- listenForRemotePeers ip4or6 (UnixSessions tracked) 5269 HNil | 270 | peers <- listenForRemotePeers ip4or6 (PeerSessions global_state) 5269 HNil |
252 | 271 | ||
253 | threadDelay 1000 -- wait a moment to obtain current tty | 272 | threadDelay 1000 -- wait a moment to obtain current tty |
254 | dologin () | 273 | dologin () |