summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Presence/ByteStringOperators.hs8
-rw-r--r--Presence/XMPPServer.hs61
-rw-r--r--Presence/main.hs22
3 files changed, 55 insertions, 36 deletions
diff --git a/Presence/ByteStringOperators.hs b/Presence/ByteStringOperators.hs
index 2815f05a..9e6cc938 100644
--- a/Presence/ByteStringOperators.hs
+++ b/Presence/ByteStringOperators.hs
@@ -2,6 +2,7 @@ module ByteStringOperators where
2 2
3import qualified Data.ByteString as S (ByteString) 3import qualified Data.ByteString as S (ByteString)
4import Data.ByteString.Lazy.Char8 as L 4import Data.ByteString.Lazy.Char8 as L
5import Control.Applicative
5 6
6-- These two were imported to provide an NFData instance. 7-- These two were imported to provide an NFData instance.
7import qualified Data.ByteString.Lazy.Internal as L (ByteString(..)) 8import qualified Data.ByteString.Lazy.Internal as L (ByteString(..))
@@ -21,6 +22,13 @@ infixr 5 <.++>
21infixr 5 <++> 22infixr 5 <++>
22infixr 5 <++.> 23infixr 5 <++.>
23 24
25a <++$> b = fmap (a<++>) b
26a <$++> b = fmap (<++>b) a
27a <$++$> b = liftA2 (<++>) a b
28infixr 6 <++$>
29infixr 6 <$++>
30infixr 6 <$++$>
31
24Nothing <?++> b = b 32Nothing <?++> b = b
25Just a <?++> b = a <++> b 33Just a <?++> b = a <++> b
26infixr 5 <?++> 34infixr 5 <?++>
diff --git a/Presence/XMPPServer.hs b/Presence/XMPPServer.hs
index 6d7841ff..6c0b609e 100644
--- a/Presence/XMPPServer.hs
+++ b/Presence/XMPPServer.hs
@@ -44,6 +44,9 @@ import Control.DeepSeq
44import Control.Concurrent.STM 44import Control.Concurrent.STM
45import Control.Concurrent 45import Control.Concurrent
46import Control.Exception 46import Control.Exception
47import Text.Show.ByteString as L
48import Data.Binary.Builder as B
49import Data.Binary.Put
47 50
48-- | Jabber ID (JID) datatype 51-- | Jabber ID (JID) datatype
49data JID = JID { name :: Maybe ByteString 52data JID = JID { name :: Maybe ByteString
@@ -52,8 +55,11 @@ data JID = JID { name :: Maybe ByteString
52 } 55 }
53 deriving (Ord,Eq) 56 deriving (Ord,Eq)
54 57
55instance Show JID where 58instance L.Show JID where
56 show (JID n s r ) = L.unpack $ fmap (<++>"@") n <?++> s <++?> fmap ("/"<++>) r 59 showp (JID n s r ) = putBuilder . B.fromLazyByteString $ n <$++> "@" <?++> s <++?> "/" <++$> r
60
61instance Prelude.Show JID where
62 show jid = L.unpack $ L.show jid
57 63
58instance NFData JID where 64instance NFData JID where
59 rnf v@(JID n s r) = n `seq` s `seq` r `seq` () 65 rnf v@(JID n s r) = n `seq` s `seq` r `seq` ()
@@ -63,13 +69,13 @@ jid user host rsrc = JID (Just user) host (Just rsrc)
63data JabberShow = Offline 69data JabberShow = Offline
64 | Away 70 | Away
65 | Available 71 | Available
66 deriving (Show,Enum,Ord,Eq,Read) 72 deriving (Prelude.Show,Enum,Ord,Eq,Read)
67 73
68data Presence = Presence JID JabberShow 74data Presence = Presence JID JabberShow
69 deriving Show 75 deriving Prelude.Show
70 76
71xmlifyPresence (Presence jid stat) = L.unlines 77xmlifyPresence (Presence jid stat) = L.unlines
72 [ "<presence from='" <++> bshow jid <++> "' " <++> typ stat <++> ">" 78 [ "<presence from='" <++> L.show jid <++> "' " <++> typ stat <++> ">"
73 , "<show>" <++> shw stat <++> "</show>" 79 , "<show>" <++> shw stat <++> "</show>"
74 , "</presence>" 80 , "</presence>"
75 ] 81 ]
@@ -88,7 +94,7 @@ class XMPPSession session where
88 data XMPPClass session 94 data XMPPClass session
89 newSession :: XMPPClass session -> Socket -> Handle -> IO session 95 newSession :: XMPPClass session -> Socket -> Handle -> IO session
90 setResource :: session -> ByteString -> IO () 96 setResource :: session -> ByteString -> IO ()
91 getJID :: session -> IO ByteString 97 getJID :: session -> IO JID
92 closeSession :: session -> IO () 98 closeSession :: session -> IO ()
93 subscribe :: session -> Maybe JID -> IO (TChan Presence) 99 subscribe :: session -> Maybe JID -> IO (TChan Presence)
94 100
@@ -114,15 +120,15 @@ greet host = L.unlines
114-- data TaggedXMPPSession s = TaggedXMPPSession s 120-- data TaggedXMPPSession s = TaggedXMPPSession s
115 121
116data Commands = Send ByteString 122data Commands = Send ByteString
117 deriving Show 123 deriving Prelude.Show
118 124
119startCon session_factory sock st = do 125startCon session_factory sock st = do
120 let h = hOccursFst st :: Handle 126 let h = hOccursFst st :: Handle
121 cred <- getLocalPeerCred sock 127 cred <- getLocalPeerCred sock
122 Prelude.putStrLn $ "PEER CRED: "++show cred 128 Prelude.putStrLn $ "PEER CRED: "++Prelude.show cred
123 pname <- getPeerName sock 129 pname <- getPeerName sock
124 session <- newSession session_factory sock h 130 session <- newSession session_factory sock h
125 Prelude.putStrLn $ "PEER NAME: "++show pname 131 Prelude.putStrLn $ "PEER NAME: "++Prelude.show pname
126 pchan <- subscribe session Nothing 132 pchan <- subscribe session Nothing
127 cmdChan <- atomically newTChan 133 cmdChan <- atomically newTChan
128 reader <- forkIO $ 134 reader <- forkIO $
@@ -150,9 +156,7 @@ startCon session_factory sock st = do
150 156
151iq_query_unavailable host id mjid xmlns kind = L.unlines $ 157iq_query_unavailable host id mjid xmlns kind = L.unlines $
152 [ "<iq type='error'" 158 [ "<iq type='error'"
153 , " from='" <++> host <++> "'" 159 , " from='" <++> host <++> "'" <++?> " to='" <++$> mjid <$++> "'"
154 , case mjid of Just jid -> " to='" <++> jid <++> "'"
155 Nothing -> ""
156 , " id='" <++> id <++> "'>" 160 , " id='" <++> id <++> "'>"
157 , " <" <++> kind <++> " xmlns='" <++> xmlns <++> "'/>" 161 , " <" <++> kind <++> " xmlns='" <++> xmlns <++> "'/>"
158 , " <error type='cancel'>" 162 , " <error type='cancel'>"
@@ -195,11 +199,10 @@ iq_session_reply host id = L.unlines $
195 , " /> " 199 , " /> "
196 ] 200 ]
197 201
202{-
198iqresult_info host id mjid = L.unlines $ 203iqresult_info host id mjid = L.unlines $
199 [ "<iq type='result'" 204 [ "<iq type='result'"
200 , " from='" <++> host <++> "'" 205 , " from='" <++> host <++> "'" <++?> " to='" <++$> mjid <$++> "'"
201 , case mjid of Just jid -> " to='" <++> jid <++> "'"
202 Nothing -> ""
203 , " id='" <++> id <++> "'>" 206 , " id='" <++> id <++> "'>"
204 , " <query xmlns='http://jabber.org/protocol/disco#info'>" 207 , " <query xmlns='http://jabber.org/protocol/disco#info'>"
205 , " <identity" 208 , " <identity"
@@ -211,10 +214,12 @@ iqresult_info host id mjid = L.unlines $
211 , " </query>" 214 , " </query>"
212 , "</iq>" 215 , "</iq>"
213 ] 216 ]
217-}
214 218
215iqresponse session host (Elem _ attrs content) = runMaybeT $ do 219iqresponse session host (Elem _ attrs content) = runMaybeT $ do
216 id <- MaybeT . return $ fmap pack (lookup (N "id") attrs >>= unattr) 220 id <- MaybeT . return $ fmap pack (lookup (N "id") attrs >>= unattr)
217 typ <- MaybeT . return $ fmap pack (lookup (N "type") attrs >>= unattr) 221 typ <- MaybeT . return $ fmap pack (lookup (N "type") attrs >>= unattr)
222 host <- fmap server $ getJID session
218 case typ of 223 case typ of
219 "set" -> do 224 "set" -> do
220 let string (CString _ s _) = [s] 225 let string (CString _ s _) = [s]
@@ -224,7 +229,7 @@ iqresponse session host (Elem _ attrs content) = runMaybeT $ do
224 liftIO $ do 229 liftIO $ do
225 setResource session rsrc 230 setResource session rsrc
226 jid <- getJID session 231 jid <- getJID session
227 return $ iq_bind_reply id jid ) 232 return $ iq_bind_reply id (L.show jid) )
228 (do 233 (do
229 guard (hasElem "session" content) 234 guard (hasElem "session" content)
230 return (iq_session_reply host id)) 235 return (iq_session_reply host id))
@@ -234,11 +239,11 @@ iqresponse session host (Elem _ attrs content) = runMaybeT $ do
234 xmlns <- MaybeT . return $ fmap pack $ listToMaybe . astring $ as 239 xmlns <- MaybeT . return $ fmap pack $ listToMaybe . astring $ as
235 let servicekind = case tag of { (N s) -> pack s ; _ -> "query" } 240 let servicekind = case tag of { (N s) -> pack s ; _ -> "query" }
236 case xmlns of 241 case xmlns of
237 "urn:xmpp:ping" -> do 242 "urn:xmpp:ping" ->
238 let to = case fmap pack (lookup (N "from") attrs >>= unattr) of 243 return $
239 Just jid -> "to='" <++> jid <++> "' " 244 "<iq from='" <++> host
240 Nothing -> "" 245 <++> ("' " <++?> "to='" <++$> fmap pack (lookup (N "from") attrs >>= unattr) <$++> "' ")
241 return $ "<iq from='" <++> host <++> "' " <++> to <++> "id='" <++> id <++> "' type='result'/>" 246 <++> "id='" <++> id <++> "' type='result'/>"
242 247
243 _ -> return (iq_query_unavailable host id Nothing xmlns servicekind) 248 _ -> return (iq_query_unavailable host id Nothing xmlns servicekind)
244 _ -> MaybeT (return Nothing) 249 _ -> MaybeT (return Nothing)
@@ -256,14 +261,14 @@ presence_response host (Elem _ attrs content) = do
256 261
257doCon st elem cont = do 262doCon st elem cont = do
258 let h = hOccursFst st :: Handle 263 let h = hOccursFst st :: Handle
259 host = "localhost"
260 (session,cmdChan) = hHead st 264 (session,cmdChan) = hHead st
261 hsend r = do 265 hsend r = do
262 atomically $ writeTChan cmdChan (Send r) 266 atomically $ writeTChan cmdChan (Send r)
263 -- hPutStrLn h r 267 -- hPutStrLn h r
264 L.putStrLn $ "\nOUT:\n" <++> r 268 L.putStrLn $ "\nOUT:\n" <++> r
265 269 host <- fmap server $ getJID session
266 putStrLn $ (show $ hang (text "\nIN:") 2 $ pp elem) ++ "\n" 270
271 putStrLn $ (Prelude.show $ hang (text "\nIN:") 2 $ pp elem) ++ "\n"
267 272
268 case elem of 273 case elem of
269 OpenTag _ -> 274 OpenTag _ ->
@@ -282,7 +287,7 @@ doCon st elem cont = do
282 287
283 cont () 288 cont ()
284 289
285instance Show Hax.ElemTag where 290instance Prelude.Show Hax.ElemTag where
286 show _ = "elemtag" 291 show _ = "elemtag"
287 292
288data XmppObject 293data XmppObject
@@ -290,10 +295,10 @@ data XmppObject
290 | ProcessingInstruction Hax.ProcessingInstruction 295 | ProcessingInstruction Hax.ProcessingInstruction
291 | OpenTag ElemTag 296 | OpenTag ElemTag
292 | CloseTag () 297 | CloseTag ()
293 deriving Show 298 deriving Prelude.Show
294 299
295pp (Element e) = PP.element e 300pp (Element e) = PP.element e
296pp o = fromString (show o) 301pp o = fromString (Prelude.show o)
297 302
298streamName = QN (Namespace {nsPrefix= "stream" , nsURI="http://etherx.jabber.org/streams" }) "stream" 303streamName = QN (Namespace {nsPrefix= "stream" , nsURI="http://etherx.jabber.org/streams" }) "stream"
299 304
@@ -349,3 +354,5 @@ listenForRemotePeers session_factory port st = do
349 dopkt 354 dopkt
350 start 355 start
351 356
357seekRemotePeers session_factory st = do
358 return ()
diff --git a/Presence/main.hs b/Presence/main.hs
index 86503a62..e416d7cc 100644
--- a/Presence/main.hs
+++ b/Presence/main.hs
@@ -46,6 +46,7 @@ import Data.ByteString.Lazy.Char8 as L (ByteString,putStrLn)
46import qualified Prelude 46import qualified Prelude
47import Prelude hiding (putStrLn) 47import Prelude hiding (putStrLn)
48import System.Environment 48import System.Environment
49import qualified Text.Show.ByteString as L
49 50
50 51
51data UnixSession = UnixSession { 52data UnixSession = UnixSession {
@@ -79,14 +80,19 @@ instance XMPPSession UnixSession where
79 ) 80 )
80 muid 81 muid
81 rsc <- readIORef (unix_resource s) 82 rsc <- readIORef (unix_resource s)
82 let suf = maybe "" ("/"<++>) rsc 83 -- let jid = user <++> "@" <++> host <++?> "/" <++$> rsc
83 jid = user <++> "@" <++> host <++> suf 84 L.putStrLn $ "SESSION: jid " <++> L.show (JID (Just user) host rsc)
84 L.putStrLn $ "SESSION: jid " <++> jid 85 return (JID (Just user) host rsc)
85 return jid
86 closeSession _ = L.putStrLn "SESSION: close" 86 closeSession _ = L.putStrLn "SESSION: close"
87 subscribe session Nothing = do 87 subscribe session Nothing = do
88 let tmvar = greedySubscriber (presence_state session) 88 let tmvar = greedySubscriber (presence_state session)
89 chan <- atomically $ 89 atomically $ subscribeToChan tmvar
90 subscribe session (Just jid) = do
91 let tvar = subscriberMap (presence_state session)
92 atomically $ subscribeToMap tvar jid
93
94
95subscribeToChan tmvar =
90 (do (cnt,chan) <- takeTMVar tmvar 96 (do (cnt,chan) <- takeTMVar tmvar
91 putTMVar tmvar (cnt+1,chan) 97 putTMVar tmvar (cnt+1,chan)
92 chan' <- dupTChan chan 98 chan' <- dupTChan chan
@@ -95,10 +101,8 @@ instance XMPPSession UnixSession where
95 (do chan <- newTChan 101 (do chan <- newTChan
96 putTMVar tmvar (1,chan) 102 putTMVar tmvar (1,chan)
97 return chan ) 103 return chan )
98 return chan 104
99 subscribe session (Just jid) = do 105subscribeToMap tvar jid = do
100 let tvar = subscriberMap (presence_state session)
101 atomically $ do
102 subs <- readTVar tvar 106 subs <- readTVar tvar
103 let mbchan = Map.lookup jid subs 107 let mbchan = Map.lookup jid subs
104 (chan,subs') <- 108 (chan,subs') <-