diff options
author | joe <joe@jerkface.net> | 2014-02-15 01:28:10 -0500 |
---|---|---|
committer | joe <joe@jerkface.net> | 2014-02-15 01:28:10 -0500 |
commit | 7e22f875d6e626a8a37f6e02423d4cc73004348d (patch) | |
tree | 558b65456eb27da779cb151279d303e2499f9826 /Presence/XMPPServer.hs | |
parent | 74def56dfa4e7361d12f27f09fb0f754109c23b5 (diff) |
Recongize stanza type BindResource
Diffstat (limited to 'Presence/XMPPServer.hs')
-rw-r--r-- | Presence/XMPPServer.hs | 137 |
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 | ||
104 | data StanzaType = Unrecognized | Ping | Pong | 104 | data StanzaType = Unrecognized | Ping | Pong | BindResource (Maybe Text) |
105 | deriving Show | 105 | deriving Show |
106 | 106 | ||
107 | data StanzaOrigin = LocalPeer | NetworkOrigin ConnectionKey | 107 | data 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 | } |
119 | dupStanza stanza = do | ||
120 | dupped <- dupTChan (stanzaChan stanza) | ||
121 | return stanza { stanzaChan = dupped } | ||
119 | 122 | ||
120 | copyToChannel f chan closer_stack = awaitForever copy | 123 | copyToChannel 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 | ||
141 | grockStanzaIQGet :: Monad m => XML.Event -> NestingXML o m (Maybe StanzaType) | 144 | grokStanzaIQGet :: Monad m => XML.Event -> NestingXML o m (Maybe StanzaType) |
142 | grockStanzaIQGet stanza = do | 145 | grokStanzaIQGet 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 | ||
152 | grokStanzaIQResult :: Monad m => XML.Event -> NestingXML o m (Maybe StanzaType) | ||
153 | grokStanzaIQResult stanza = do | ||
154 | mtag <- nextElement | ||
155 | flip (maybe $ return (Just Pong)) mtag $ \tag -> do | ||
156 | case tagName tag of | ||
157 | _ -> return Nothing | ||
158 | |||
159 | grokStanzaIQSet :: XML.Event -> NestingXML o IO (Maybe StanzaType) | ||
160 | grokStanzaIQSet 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 | {- | ||
176 | C->Unrecognized <iq | ||
177 | C->Unrecognized type="set" | ||
178 | C->Unrecognized id="purpleae62d88f" | ||
179 | C->Unrecognized xmlns="jabber:client"> | ||
180 | C->Unrecognized <bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"/> | ||
181 | C->Unrecognized </iq> | ||
182 | -} | ||
183 | |||
149 | ioWriteChan c v = liftIO . atomically $ writeTChan c v | 184 | ioWriteChan c v = liftIO . atomically $ writeTChan c v |
150 | 185 | ||
151 | 186 | ||
152 | grokStanza "jabber:server" stanzaTag = | 187 | grokStanza "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 | ||
157 | grokStanza "jabber:client" stanzaTag = | 193 | grokStanza "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 | ||
162 | xmppInbound :: ConnectionKey -> FlagCommand | 200 | xmppInbound :: 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 () |
168 | xmppInbound k pingflag src stanzas output donevar = doNestingXML $ do | 208 | xmppInbound 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 | ||
253 | greet' namespace host = | 307 | streamFeatures "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 | ] |
322 | streamFeatures "jabber:server" = | ||
323 | [] | ||
324 | |||
325 | |||
326 | greet' 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 | ||
277 | greet namespace = | 337 | greet namespace = |
278 | [ EventBeginDocument | 338 | [ EventBeginDocument |
@@ -320,13 +380,14 @@ makePong namespace mid to from = | |||
320 | ] | 380 | ] |
321 | 381 | ||
322 | 382 | ||
323 | forkConnection :: ConnectionKey | 383 | forkConnection :: 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) |
329 | forkConnection k pingflag src snk stanzas = do | 390 | forkConnection 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 | |||
478 | xmppServer = do | 543 | xmppServer = 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 |