summaryrefslogtreecommitdiff
path: root/Presence/XMPPServer.hs
diff options
context:
space:
mode:
authorjoe <joe@jerkface.net>2014-02-15 01:28:10 -0500
committerjoe <joe@jerkface.net>2014-02-15 01:28:10 -0500
commit7e22f875d6e626a8a37f6e02423d4cc73004348d (patch)
tree558b65456eb27da779cb151279d303e2499f9826 /Presence/XMPPServer.hs
parent74def56dfa4e7361d12f27f09fb0f754109c23b5 (diff)
Recongize stanza type BindResource
Diffstat (limited to 'Presence/XMPPServer.hs')
-rw-r--r--Presence/XMPPServer.hs137
1 files changed, 101 insertions, 36 deletions
diff --git a/Presence/XMPPServer.hs b/Presence/XMPPServer.hs
index 92f59061..8afc3245 100644
--- a/Presence/XMPPServer.hs
+++ b/Presence/XMPPServer.hs
@@ -101,7 +101,7 @@ data Stanza
101 stanzaChan :: TChan (Maybe XML.Event) } 101 stanzaChan :: TChan (Maybe XML.Event) }
102-} 102-}
103 103
104data StanzaType = Unrecognized | Ping | Pong 104data StanzaType = Unrecognized | Ping | Pong | BindResource (Maybe Text)
105 deriving Show 105 deriving Show
106 106
107data StanzaOrigin = LocalPeer | NetworkOrigin ConnectionKey 107data StanzaOrigin = LocalPeer | NetworkOrigin ConnectionKey
@@ -116,6 +116,9 @@ data Stanza = Stanza
116 , stanzaInterrupt :: TMVar () 116 , stanzaInterrupt :: TMVar ()
117 , stanzaOrigin :: StanzaOrigin 117 , stanzaOrigin :: StanzaOrigin
118 } 118 }
119dupStanza stanza = do
120 dupped <- dupTChan (stanzaChan stanza)
121 return stanza { stanzaChan = dupped }
119 122
120copyToChannel f chan closer_stack = awaitForever copy 123copyToChannel f chan closer_stack = awaitForever copy
121 where 124 where
@@ -138,34 +141,71 @@ prettyPrint prefix =
138 =$= CB.lines 141 =$= CB.lines
139 =$ CL.mapM_ (wlogb . (prefix <>)) 142 =$ CL.mapM_ (wlogb . (prefix <>))
140 143
141grockStanzaIQGet :: Monad m => XML.Event -> NestingXML o m (Maybe StanzaType) 144grokStanzaIQGet :: Monad m => XML.Event -> NestingXML o m (Maybe StanzaType)
142grockStanzaIQGet stanza = do 145grokStanzaIQGet stanza = do
143 mtag <- nextElement 146 mtag <- nextElement
144 flip (maybe $ return Nothing) mtag $ \tag -> do 147 flip (maybe $ return Nothing) mtag $ \tag -> do
145 case tagName tag of 148 case tagName tag of
146 "{urn:xmpp:ping}ping" -> return $ Just Ping 149 "{urn:xmpp:ping}ping" -> return $ Just Ping
147 _ -> return Nothing 150 _ -> return Nothing
148 151
152grokStanzaIQResult :: Monad m => XML.Event -> NestingXML o m (Maybe StanzaType)
153grokStanzaIQResult stanza = do
154 mtag <- nextElement
155 flip (maybe $ return (Just Pong)) mtag $ \tag -> do
156 case tagName tag of
157 _ -> return Nothing
158
159grokStanzaIQSet :: XML.Event -> NestingXML o IO (Maybe StanzaType)
160grokStanzaIQSet stanza = do
161 mtag <- nextElement
162 flip (maybe $ return Nothing) mtag $ \tag -> do
163 case tagName tag of
164 "{urn:ietf:params:xml:ns:xmpp-bind}bind" -> do
165 mchild <- nextElement
166 case fmap tagName mchild of
167 Just "{urn:ietf:params:xml:ns:xmpp-bind}resource" -> do
168 rsc <- XML.content -- TODO: MonadThrow???
169 return . Just $ BindResource (Just rsc)
170 Just _ -> return Nothing
171 Nothing -> return . Just $ BindResource Nothing
172 _ -> return Nothing
173
174
175{-
176C->Unrecognized <iq
177C->Unrecognized type="set"
178C->Unrecognized id="purpleae62d88f"
179C->Unrecognized xmlns="jabber:client">
180C->Unrecognized <bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"/>
181C->Unrecognized </iq>
182-}
183
149ioWriteChan c v = liftIO . atomically $ writeTChan c v 184ioWriteChan c v = liftIO . atomically $ writeTChan c v
150 185
151 186
152grokStanza "jabber:server" stanzaTag = 187grokStanza "jabber:server" stanzaTag =
153 case () of 188 case () of
154 _ | stanzaTag `isServerIQOf` "get" -> grockStanzaIQGet stanzaTag 189 _ | stanzaTag `isServerIQOf` "get" -> grokStanzaIQGet stanzaTag
190 _ | stanzaTag `isServerIQOf` "result" -> grokStanzaIQResult stanzaTag
155 _ -> return $ Just Unrecognized 191 _ -> return $ Just Unrecognized
156 192
157grokStanza "jabber:client" stanzaTag = 193grokStanza "jabber:client" stanzaTag =
158 case () of 194 case () of
159 _ | stanzaTag `isClientIQOf` "get" -> grockStanzaIQGet stanzaTag 195 _ | stanzaTag `isClientIQOf` "get" -> grokStanzaIQGet stanzaTag
196 _ | stanzaTag `isClientIQOf` "set" -> grokStanzaIQSet stanzaTag
197 _ | stanzaTag `isClientIQOf` "result" -> grokStanzaIQResult stanzaTag
160 _ -> return $ Just Unrecognized 198 _ -> return $ Just Unrecognized
161 199
162xmppInbound :: ConnectionKey -> FlagCommand 200xmppInbound :: Server ConnectionKey
201 -> ConnectionKey
202 -> FlagCommand
163 -> Source IO XML.Event 203 -> Source IO XML.Event
164 -> TChan Stanza 204 -> TChan Stanza
165 -> TChan Stanza 205 -> TChan Stanza
166 -> TMVar () 206 -> TMVar ()
167 -> Sink XML.Event IO () 207 -> Sink XML.Event IO ()
168xmppInbound k pingflag src stanzas output donevar = doNestingXML $ do 208xmppInbound sv k pingflag src stanzas output donevar = doNestingXML $ do
169 let namespace = case k of 209 let namespace = case k of
170 ClientKey {} -> "jabber:client" 210 ClientKey {} -> "jabber:client"
171 PeerKey {} -> "jabber:server" 211 PeerKey {} -> "jabber:server"
@@ -198,21 +238,35 @@ xmppInbound k pingflag src stanzas output donevar = doNestingXML $ do
198 from = maybe "todo" id mfrom 238 from = maybe "todo" id mfrom
199 let pong = makePong namespace mid to from 239 let pong = makePong namespace mid to from
200 -- liftIO $ wlog "got ping, sending pong..." 240 -- liftIO $ wlog "got ping, sending pong..."
201 pongChan <- liftIO $ atomically newTChan 241 pongStanza <- liftIO . atomically $ do
202 pongClsrs <- liftIO $ atomically $ newTVar (Just []) 242 pongChan <- newTChan
203 ioWriteChan output $ Stanza { stanzaType = Pong 243 pongClsrs <- newTVar (Just [])
204 , stanzaId = mid 244 return Stanza { stanzaType = Pong
205 , stanzaTo = mto 245 , stanzaId = mid
206 , stanzaFrom = mfrom 246 , stanzaTo = mto
207 , stanzaChan = pongChan 247 , stanzaFrom = mfrom
208 , stanzaClosers = pongClsrs 248 , stanzaChan = pongChan
209 , stanzaInterrupt = donevar 249 , stanzaClosers = pongClsrs
210 , stanzaOrigin = LocalPeer 250 , stanzaInterrupt = donevar
211 } 251 , stanzaOrigin = LocalPeer
252 }
253 ioWriteChan output pongStanza
212 void . liftIO . forkIO $ do 254 void . liftIO . forkIO $ do
213 mapM_ (ioWriteChan pongChan) pong 255 mapM_ (ioWriteChan $ stanzaChan pongStanza) pong
214 liftIO . atomically $ writeTVar pongClsrs Nothing 256 liftIO . atomically $ writeTVar (stanzaClosers pongStanza) Nothing
215 -- liftIO $ wlog "finished pong stanza" 257 -- liftIO $ wlog "finished pong stanza"
258
259 -- TODO: Remove this, it is only to generate a debug print
260 ioWriteChan stanzas Stanza
261 { stanzaType = Ping
262 , stanzaId = mid
263 , stanzaTo = mto
264 , stanzaFrom = mfrom
265 , stanzaChan = chan
266 , stanzaClosers = clsrs
267 , stanzaInterrupt = donevar
268 , stanzaOrigin = NetworkOrigin k
269 }
216 stype -> ioWriteChan stanzas Stanza 270 stype -> ioWriteChan stanzas Stanza
217 { stanzaType = stype 271 { stanzaType = stype
218 , stanzaId = mid 272 , stanzaId = mid
@@ -250,16 +304,8 @@ readUntilNothing ch = do
250 return (x:xs)) 304 return (x:xs))
251 x 305 x
252 306
253greet' namespace host = 307streamFeatures "jabber:client" =
254 [ EventBeginDocument 308 [ EventBeginElement (streamP "features") []
255 , EventBeginElement (streamP "stream")
256 [("from",[ContentText host])
257 ,("id",[ContentText "someid"])
258 ,("xmlns",[ContentText namespace])
259 ,("xmlns:stream",[ContentText "http://etherx.jabber.org/streams"])
260 ,("version",[ContentText "1.0"])
261 ]
262 , EventBeginElement (streamP "features") []
263 , EventBeginElement "{urn:ietf:params:xml:ns:xmpp-bind}bind" [] 309 , EventBeginElement "{urn:ietf:params:xml:ns:xmpp-bind}bind" []
264 , EventEndElement "{urn:ietf:params:xml:ns:xmpp-bind}bind" 310 , EventEndElement "{urn:ietf:params:xml:ns:xmpp-bind}bind"
265 311
@@ -273,6 +319,20 @@ greet' namespace host =
273 319
274 , EventEndElement (streamP "features") 320 , EventEndElement (streamP "features")
275 ] 321 ]
322streamFeatures "jabber:server" =
323 []
324
325
326greet' namespace host =
327 [ EventBeginDocument
328 , EventBeginElement (streamP "stream")
329 [("from",[ContentText host])
330 ,("id",[ContentText "someid"])
331 ,("xmlns",[ContentText namespace])
332 ,("xmlns:stream",[ContentText "http://etherx.jabber.org/streams"])
333 ,("version",[ContentText "1.0"])
334 ]
335 ] ++ streamFeatures namespace
276 336
277greet namespace = 337greet namespace =
278 [ EventBeginDocument 338 [ EventBeginDocument
@@ -320,13 +380,14 @@ makePong namespace mid to from =
320 ] 380 ]
321 381
322 382
323forkConnection :: ConnectionKey 383forkConnection :: Server ConnectionKey
384 -> ConnectionKey
324 -> FlagCommand 385 -> FlagCommand
325 -> Source IO XML.Event 386 -> Source IO XML.Event
326 -> Sink (Flush XML.Event) IO () 387 -> Sink (Flush XML.Event) IO ()
327 -> TChan Stanza 388 -> TChan Stanza
328 -> IO (TChan Stanza) 389 -> IO (TChan Stanza)
329forkConnection k pingflag src snk stanzas = do 390forkConnection sv k pingflag src snk stanzas = do
330 let namespace = case k of 391 let namespace = case k of
331 ClientKey {} -> "jabber:client" 392 ClientKey {} -> "jabber:client"
332 PeerKey {} -> "jabber:server" 393 PeerKey {} -> "jabber:server"
@@ -361,6 +422,10 @@ forkConnection k pingflag src snk stanzas = do
361 fix $ \loop -> do 422 fix $ \loop -> do
362 what <- atomically $ foldr1 orElse 423 what <- atomically $ foldr1 orElse
363 [readTChan output >>= \stanza -> return $ do 424 [readTChan output >>= \stanza -> return $ do
425 dup <- atomically $ dupStanza stanza
426 stanzaToConduit dup $$ prettyPrint $ case k of
427 ClientKey {} -> "C<-" <> bshow (stanzaType dup) <> " "
428 PeerKey {} -> "P<-" <> bshow (stanzaType dup) <> " "
364 stanzaToConduit stanza 429 stanzaToConduit stanza
365 $$ awaitForever 430 $$ awaitForever
366 $ liftIO . atomically . Slotted.push slots Nothing 431 $ liftIO . atomically . Slotted.push slots Nothing
@@ -385,7 +450,7 @@ forkConnection k pingflag src snk stanzas = do
385 wlog $ "end pre-queue fork: " ++ show k 450 wlog $ "end pre-queue fork: " ++ show k
386 forkIO $ do 451 forkIO $ do
387 -- src $$ awaitForever (lift . putStrLn . takeWhile (/=' ') . show) 452 -- src $$ awaitForever (lift . putStrLn . takeWhile (/=' ') . show)
388 src $$ xmppInbound k pingflag src stanzas output rdone 453 src $$ xmppInbound sv k pingflag src stanzas output rdone
389 atomically $ putTMVar rdone () 454 atomically $ putTMVar rdone ()
390 wlog $ "end reader fork: " ++ show k 455 wlog $ "end reader fork: " ++ show k
391 return output 456 return output
@@ -446,7 +511,7 @@ monitor sv params = do
446 Connection pingflag conread conwrite -> do 511 Connection pingflag conread conwrite -> do
447 wlog $ tomsg k "Connection" 512 wlog $ tomsg k "Connection"
448 let (xsrc,xsnk) = xmlStream conread conwrite 513 let (xsrc,xsnk) = xmlStream conread conwrite
449 forkConnection k pingflag xsrc xsnk stanzas 514 forkConnection sv k pingflag xsrc xsnk stanzas
450 return () 515 return ()
451 ConnectFailure addr -> do 516 ConnectFailure addr -> do
452 wlog $ tomsg k "ConnectFailure" 517 wlog $ tomsg k "ConnectFailure"
@@ -478,8 +543,8 @@ xmppServer :: (MonadResource m, MonadIO m) => m (Server ConnectionKey,Connection
478xmppServer = do 543xmppServer = do
479 sv <- server 544 sv <- server
480 let peer_params = (connectionDefaults peerKey) 545 let peer_params = (connectionDefaults peerKey)
481 { pingInterval = 5000 546 { pingInterval = 15000
482 , timeout = 1000 547 , timeout = 2000
483 , duplex = False } 548 , duplex = False }
484 client_params = (connectionDefaults clientKey) 549 client_params = (connectionDefaults clientKey)
485 { pingInterval = 0 550 { pingInterval = 0