diff options
Diffstat (limited to 'Presence')
-rw-r--r-- | Presence/XMPPServer.hs | 28 | ||||
-rw-r--r-- | Presence/main.hs | 63 |
2 files changed, 59 insertions, 32 deletions
diff --git a/Presence/XMPPServer.hs b/Presence/XMPPServer.hs index 044ed9e4..4a859bc9 100644 --- a/Presence/XMPPServer.hs +++ b/Presence/XMPPServer.hs | |||
@@ -40,6 +40,33 @@ import Network.Socket | |||
40 | import Data.String | 40 | import Data.String |
41 | import Control.Monad.Trans.Maybe | 41 | import Control.Monad.Trans.Maybe |
42 | import Control.Monad.IO.Class | 42 | import Control.Monad.IO.Class |
43 | import Control.DeepSeq | ||
44 | import Control.Concurrent.STM | ||
45 | |||
46 | -- | Jabber ID (JID) datatype | ||
47 | data JID = JID { name :: Maybe ByteString | ||
48 | , server :: ByteString | ||
49 | , resource :: Maybe ByteString | ||
50 | } | ||
51 | deriving (Ord,Eq) | ||
52 | |||
53 | instance Show JID where | ||
54 | show (JID n s r ) = L.unpack $ fmap (<++>"@") n <?++> s <++?> fmap ("/"<++>) r | ||
55 | |||
56 | instance NFData JID where | ||
57 | rnf v@(JID n s r) = n `seq` s `seq` r `seq` () | ||
58 | |||
59 | jid user host rsrc = JID (Just user) host (Just rsrc) | ||
60 | |||
61 | data JabberShow = Offline | ||
62 | | Away | ||
63 | | Available | ||
64 | deriving (Show,Enum,Ord,Eq,Read) | ||
65 | |||
66 | data Presence = Presence JID JabberShow | ||
67 | |||
68 | instance NFData Presence where | ||
69 | rnf (Presence jid stat) = rnf jid `seq` stat `seq` () | ||
43 | 70 | ||
44 | 71 | ||
45 | class XMPPSession session where | 72 | class XMPPSession session where |
@@ -48,6 +75,7 @@ class XMPPSession session where | |||
48 | setResource :: session -> ByteString -> IO () | 75 | setResource :: session -> ByteString -> IO () |
49 | getJID :: session -> IO ByteString | 76 | getJID :: session -> IO ByteString |
50 | closeSession :: session -> IO () | 77 | closeSession :: session -> IO () |
78 | subscribeToPresence :: session -> Maybe JID -> IO (TChan Presence) | ||
51 | 79 | ||
52 | 80 | ||
53 | greet host = L.unlines | 81 | greet host = L.unlines |
diff --git a/Presence/main.hs b/Presence/main.hs index 4168feca..78ca4363 100644 --- a/Presence/main.hs +++ b/Presence/main.hs | |||
@@ -37,7 +37,6 @@ import Data.Map as Map (Map) | |||
37 | 37 | ||
38 | import Control.Concurrent.STM | 38 | import Control.Concurrent.STM |
39 | import Control.Concurrent (threadDelay) | 39 | import Control.Concurrent (threadDelay) |
40 | import Control.DeepSeq | ||
41 | import Control.Monad.Trans.Maybe | 40 | import Control.Monad.Trans.Maybe |
42 | import Control.Monad.IO.Class | 41 | import Control.Monad.IO.Class |
43 | 42 | ||
@@ -48,34 +47,20 @@ import qualified Prelude | |||
48 | import Prelude hiding (putStrLn) | 47 | import Prelude hiding (putStrLn) |
49 | 48 | ||
50 | 49 | ||
51 | -- | Jabber ID (JID) datatype | ||
52 | data JID = JID { name :: Maybe ByteString | ||
53 | , server :: ByteString | ||
54 | , resource :: Maybe ByteString | ||
55 | } | ||
56 | deriving (Ord,Eq) | ||
57 | |||
58 | instance Show JID where | ||
59 | show (JID n s r ) = L.unpack $ fmap (<++>"@") n <?++> s <++?> fmap ("/"<++>) r | ||
60 | |||
61 | instance NFData JID where | ||
62 | rnf v@(JID n s r) = n `seq` s `seq` r `seq` () | ||
63 | |||
64 | jid user host rsrc = JID (Just user) host (Just rsrc) | ||
65 | |||
66 | data UnixSession = UnixSession { | 50 | data UnixSession = UnixSession { |
67 | unix_uid :: (IORef (Maybe UserID)), | 51 | unix_uid :: (IORef (Maybe UserID)), |
68 | unix_resource :: (IORef (Maybe L.ByteString)) | 52 | unix_resource :: (IORef (Maybe L.ByteString)), |
53 | presence_state :: PresenceState | ||
69 | } | 54 | } |
70 | 55 | ||
71 | instance XMPPSession UnixSession where | 56 | instance XMPPSession UnixSession where |
72 | data XMPPClass UnixSession = UnixSessions | 57 | data XMPPClass UnixSession = UnixSessions PresenceState |
73 | newSession _ sock handle = do | 58 | newSession (UnixSessions state) sock handle = do |
74 | muid <- getLocalPeerCred sock | 59 | muid <- getLocalPeerCred sock |
75 | L.putStrLn $ "SESSION: open " <++> bshow muid | 60 | L.putStrLn $ "SESSION: open " <++> bshow muid |
76 | uid_ref <- newIORef muid | 61 | uid_ref <- newIORef muid |
77 | res_ref <- newIORef Nothing | 62 | res_ref <- newIORef Nothing |
78 | return $ UnixSession uid_ref res_ref | 63 | return $ UnixSession uid_ref res_ref state |
79 | setResource s resource = do | 64 | setResource s resource = do |
80 | writeIORef (unix_resource s) (Just resource) | 65 | writeIORef (unix_resource s) (Just resource) |
81 | L.putStrLn $ "SESSION: resource " <++> resource | 66 | L.putStrLn $ "SESSION: resource " <++> resource |
@@ -97,17 +82,31 @@ instance XMPPSession UnixSession where | |||
97 | L.putStrLn $ "SESSION: jid " <++> jid | 82 | L.putStrLn $ "SESSION: jid " <++> jid |
98 | return jid | 83 | return jid |
99 | closeSession _ = L.putStrLn "SESSION: close" | 84 | closeSession _ = L.putStrLn "SESSION: close" |
100 | 85 | subscribeToPresence session Nothing = do | |
101 | data JabberShow = Offline | 86 | let tmvar = greedySubscriber (presence_state session) |
102 | | Away | 87 | chan <- atomically $ |
103 | | Available | 88 | (do (cnt,chan) <- takeTMVar tmvar |
104 | deriving (Show,Enum,Ord,Eq,Read) | 89 | putTMVar tmvar (cnt+1,chan) |
105 | 90 | return chan ) | |
106 | data Presence = Presence JID JabberShow | 91 | `orElse` |
107 | type MaybePresence = Maybe Presence | 92 | (do chan <- newTChan |
108 | 93 | putTMVar tmvar (1,chan) | |
109 | instance NFData Presence where | 94 | return chan ) |
110 | rnf (Presence jid stat) = rnf jid `seq` stat `seq` () | 95 | return chan |
96 | subscribeToPresence session (Just jid) = do | ||
97 | let tvar = subscriberMap (presence_state session) | ||
98 | atomically $ do | ||
99 | subs <- readTVar tvar | ||
100 | let mbchan = Map.lookup jid subs | ||
101 | (chan,subs') <- | ||
102 | do case mbchan of | ||
103 | Nothing -> do | ||
104 | newchan <- newTChan | ||
105 | return (newchan, Map.insert jid (1,newchan) subs) | ||
106 | Just (cnt,chan) -> do | ||
107 | return (chan, Map.insert jid (cnt+1,chan) subs) | ||
108 | writeTVar tvar subs' | ||
109 | return chan | ||
111 | 110 | ||
112 | matchResource tty jid = maybe Away (avail . (==tty)) $ resource jid | 111 | matchResource tty jid = maybe Away (avail . (==tty)) $ resource jid |
113 | where | 112 | where |
@@ -196,7 +195,7 @@ start = do | |||
196 | utmp_file | 195 | utmp_file |
197 | dologin | 196 | dologin |
198 | #endif | 197 | #endif |
199 | sock <- listenForXmppClients UnixSessions 5222 HNil | 198 | sock <- listenForXmppClients (UnixSessions tracked) 5222 HNil |
200 | 199 | ||
201 | threadDelay 1000 -- wait a moment to obtain current tty | 200 | threadDelay 1000 -- wait a moment to obtain current tty |
202 | dologin () | 201 | dologin () |