summaryrefslogtreecommitdiff
path: root/Presence
diff options
context:
space:
mode:
Diffstat (limited to 'Presence')
-rw-r--r--Presence/XMPPServer.hs117
1 files changed, 79 insertions, 38 deletions
diff --git a/Presence/XMPPServer.hs b/Presence/XMPPServer.hs
index a9e7e336..45b89b3d 100644
--- a/Presence/XMPPServer.hs
+++ b/Presence/XMPPServer.hs
@@ -26,10 +26,11 @@ import Data.Conduit.Blaze (builderToByteStringFlush)
26import qualified Text.XML.Stream.Render as XML 26import qualified Text.XML.Stream.Render as XML
27import qualified Text.XML.Stream.Parse as XML 27import qualified Text.XML.Stream.Parse as XML
28import Data.XML.Types as XML 28import Data.XML.Types as XML
29import Data.Maybe (catMaybes,fromJust) 29import Data.Maybe (catMaybes,fromJust,isNothing)
30import Data.Monoid ( (<>) ) 30import Data.Monoid ( (<>) )
31import Data.Text (Text) 31import Data.Text (Text)
32import qualified Data.Text as Text (pack) 32import qualified Data.Text as Text (pack)
33import Data.Char (toUpper)
33 34
34import qualified Control.Concurrent.STM.UpdateStream as Slotted 35import qualified Control.Concurrent.STM.UpdateStream as Slotted
35import ControlMaybe 36import ControlMaybe
@@ -40,6 +41,8 @@ import Server
40peerport = 5269 41peerport = 5269
41clientport = 5222 42clientport = 5222
42 43
44my_uuid = "154ae29f-98f2-4af4-826d-a40c8a188574"
45
43 46
44-- TODO: http://xmpp.org/rfcs/rfc6120.html#rules-remote-error 47-- TODO: http://xmpp.org/rfcs/rfc6120.html#rules-remote-error
45-- client connection 48-- client connection
@@ -89,12 +92,27 @@ type FlagCommand = STM Bool
89type ReadCommand = IO (Maybe ByteString) 92type ReadCommand = IO (Maybe ByteString)
90type WriteCommand = ByteString -> IO Bool 93type WriteCommand = ByteString -> IO Bool
91 94
95{-
92data Stanza 96data Stanza
93 = UnrecognizedStanza { stanzaChan :: TChan (Maybe XML.Event) } 97 = UnrecognizedStanza { stanzaChan :: TChan (Maybe XML.Event) }
94 | PingStanza { stanzaId :: Maybe Text 98 | PingStanza { stanzaId :: Maybe Text
95 , stanzaChan :: TChan (Maybe XML.Event) } 99 , stanzaChan :: TChan (Maybe XML.Event) }
96 | PongStanza { -- stanzaId :: Maybe Text 100 | PongStanza { -- stanzaId :: Maybe Text
97 stanzaChan :: TChan (Maybe XML.Event) } 101 stanzaChan :: TChan (Maybe XML.Event) }
102-}
103
104data StanzaType = Unrecognized | Ping | Pong
105 deriving Show
106
107data Stanza = Stanza
108 { stanzaType :: StanzaType
109 , stanzaId :: Maybe Text
110 , stanzaTo :: Maybe Text
111 , stanzaFrom :: Maybe Text
112 , stanzaChan :: TChan XML.Event
113 , stanzaClosers :: TVar (Maybe [XML.Event])
114 , stanzaInterrupt :: TMVar ()
115 }
98 116
99copyToChannel f chan closer_stack = awaitForever copy 117copyToChannel f chan closer_stack = awaitForever copy
100 where 118 where
@@ -104,10 +122,10 @@ copyToChannel f chan closer_stack = awaitForever copy
104 EventBeginDocument {} -> do 122 EventBeginDocument {} -> do
105 let clsr = closerFor x 123 let clsr = closerFor x
106 liftIO . atomically $ 124 liftIO . atomically $
107 modifyTVar' closer_stack (clsr:) 125 modifyTVar' closer_stack (fmap (clsr:))
108 EventEndDocument {} -> do 126 EventEndDocument {} -> do
109 liftIO . atomically $ 127 liftIO . atomically $
110 modifyTVar' closer_stack (drop 1) 128 modifyTVar' closer_stack (fmap (drop 1))
111 _ -> return () 129 _ -> return ()
112 yield x 130 yield x
113 131
@@ -119,15 +137,12 @@ prettyPrint prefix xs =
119 =$= CB.lines 137 =$= CB.lines
120 $$ CL.mapM_ (wlogb . (prefix <>)) 138 $$ CL.mapM_ (wlogb . (prefix <>))
121 139
122grockStanzaIQGet :: Monad m => XML.Event -> NestingXML o m (Maybe (TChan (Maybe Event) -> Stanza)) 140grockStanzaIQGet :: Monad m => XML.Event -> NestingXML o m (Maybe StanzaType)
123grockStanzaIQGet stanza = do 141grockStanzaIQGet stanza = do
124 let mid = lookupAttrib "id" (tagAttrs stanza)
125 -- mfrom = lookupAttrib "from" (tagAttrs stanza)
126 mtag <- nextElement 142 mtag <- nextElement
127 flip (maybe $ return Nothing) mtag $ \tag -> do 143 flip (maybe $ return Nothing) mtag $ \tag -> do
128 case tagName tag of 144 case tagName tag of
129 "{urn:xmpp:ping}ping" -> do 145 "{urn:xmpp:ping}ping" -> return $ Just Ping
130 return $ Just (PingStanza mid)
131 _ -> return Nothing 146 _ -> return Nothing
132 147
133ioWriteChan c v = liftIO . atomically $ writeTChan c v 148ioWriteChan c v = liftIO . atomically $ writeTChan c v
@@ -146,33 +161,52 @@ xmppInbound k pingflag src stanzas output donevar = doNestingXML $ do
146 fix $ \loop -> do 161 fix $ \loop -> do
147 -- liftIO . wlog $ "waiting for stanza." 162 -- liftIO . wlog $ "waiting for stanza."
148 (chan,clsrs) <- liftIO . atomically $ 163 (chan,clsrs) <- liftIO . atomically $
149 liftM2 (,) newTChan (newTVar []) 164 liftM2 (,) newTChan (newTVar (Just []))
150 whenJust nextElement $ \stanza -> do 165 whenJust nextElement $ \stanzaTag -> do
151 stanza_lvl <- nesting 166 stanza_lvl <- nesting
152 liftIO . atomically $ do 167 liftIO . atomically $ do
153 writeTChan chan (Just stanza) 168 writeTChan chan stanzaTag
154 modifyTVar' clsrs (closerFor stanza:) 169 modifyTVar' clsrs (fmap (closerFor stanzaTag:))
155 copyToChannel Just chan clsrs =$= do 170 copyToChannel id chan clsrs =$= do
171 let mid = lookupAttrib "id" (tagAttrs stanzaTag)
172 mfrom = lookupAttrib "from" (tagAttrs stanzaTag)
173 mto = lookupAttrib "to" (tagAttrs stanzaTag)
156 dispatch <- 174 dispatch <-
157 case () of 175 case () of
158 _ | stanza `isServerIQOf` "get" -> grockStanzaIQGet stanza 176 _ | stanzaTag `isServerIQOf` "get" -> grockStanzaIQGet stanzaTag
159 _ -> return $ Just UnrecognizedStanza 177 _ -> return $ Just Unrecognized
160 flip (maybe $ return ()) dispatch $ \dispatch -> 178 flip (maybe $ return ()) dispatch $ \dispatch ->
161 case dispatch chan of 179 case dispatch of
162 d@(PingStanza {}) -> do 180 Ping -> do
163 let to = "todo" 181 let to = maybe "todo" id mto
164 from = "todo" 182 from = maybe "todo" id mfrom
165 let pong = peerPong (stanzaId d) to from 183 let pong = peerPong mid to from
166 liftIO $ wlog "got ping, sending pong..." 184 -- liftIO $ wlog "got ping, sending pong..."
167 pongChan <- liftIO $ atomically newTChan 185 pongChan <- liftIO $ atomically newTChan
168 ioWriteChan output (PongStanza pongChan) 186 pongClsrs <- liftIO $ atomically $ newTVar (Just [])
187 ioWriteChan output $ Stanza { stanzaType = Pong
188 , stanzaId = mid
189 , stanzaTo = mto
190 , stanzaFrom = mfrom
191 , stanzaChan = pongChan
192 , stanzaClosers = pongClsrs
193 , stanzaInterrupt = donevar
194 }
169 void . liftIO . forkIO $ do 195 void . liftIO . forkIO $ do
170 mapM_ (ioWriteChan pongChan . Just) pong 196 mapM_ (ioWriteChan pongChan) pong
171 ioWriteChan pongChan Nothing 197 liftIO . atomically $ writeTVar pongClsrs Nothing
172 liftIO $ wlog "finished pong stanza" 198 -- liftIO $ wlog "finished pong stanza"
173 disp -> ioWriteChan stanzas disp 199 stype -> ioWriteChan stanzas Stanza
200 { stanzaType = stype
201 , stanzaId = mid
202 , stanzaTo = mto
203 , stanzaFrom = mfrom
204 , stanzaChan = chan
205 , stanzaClosers = clsrs
206 , stanzaInterrupt = donevar
207 }
174 awaitCloser stanza_lvl 208 awaitCloser stanza_lvl
175 ioWriteChan chan Nothing 209 liftIO . atomically $ writeTVar clsrs Nothing
176 loop 210 loop
177 211
178 212
@@ -283,15 +317,20 @@ forkConnection k pingflag src snk stanzas = do
283 what <- atomically $ foldr1 orElse 317 what <- atomically $ foldr1 orElse
284 [readTChan output >>= \stanza -> return $ do 318 [readTChan output >>= \stanza -> return $ do
285 let xchan = stanzaChan stanza 319 let xchan = stanzaChan stanza
320 xfin = stanzaClosers stanza
286 fix $ \inner -> do 321 fix $ \inner -> do
287 what <- atomically $ orElse 322 what <- atomically $ foldr1 orElse
288 (readTChan xchan >>= \mxml -> return $ do 323 [readTChan xchan >>= \xml -> return $ do
289 case mxml of 324 atomically $ Slotted.push slots Nothing xml
290 Just xml -> do 325 inner
291 atomically $ Slotted.push slots Nothing xml 326 ,do mb <- readTVar xfin
292 inner 327 cempty <- isEmptyTChan xchan
293 Nothing -> loop) 328 if isNothing mb
294 (readTMVar rdone >> return (return ())) 329 then if cempty then return loop else retry
330 else retry -- todo: send closers
331 ,do isEmptyTChan xchan >>= check
332 readTMVar rdone
333 return (return ())]
295 what 334 what
296 ,do pingflag >>= check 335 ,do pingflag >>= check
297 return $ do 336 return $ do
@@ -303,7 +342,7 @@ forkConnection k pingflag src snk stanzas = do
303 mapM_ (atomically . Slotted.push slots (Just $ PingSlot)) 342 mapM_ (atomically . Slotted.push slots (Just $ PingSlot))
304 ping 343 ping
305 wlog "" 344 wlog ""
306 prettyPrint "P<- " ping 345 prettyPrint "P<-PING " ping
307 loop 346 loop
308 ,readTMVar rdone >> return (return ()) 347 ,readTMVar rdone >> return (return ())
309 ] 348 ]
@@ -363,9 +402,11 @@ monitor sv params = do
363 RequiresPing -> return () -- wlog $ tomsg k "RequiresPing" 402 RequiresPing -> return () -- wlog $ tomsg k "RequiresPing"
364 _ -> return () 403 _ -> return ()
365 , readTChan stanzas >>= \stanza -> return $ do 404 , readTChan stanzas >>= \stanza -> return $ do
366 xs <- readUntilNothing (stanzaChan stanza) 405 -- xs <- readUntilNothing (stanzaChan stanza)
406 xs <- chanContents (stanzaChan stanza)
407 let typ = Strict8.pack $ "P->"++(show (stanzaType stanza))++" "
367 wlog "" 408 wlog ""
368 prettyPrint "P-> " xs 409 prettyPrint typ xs
369 ] 410 ]
370 action 411 action
371 loop 412 loop