summaryrefslogtreecommitdiff
path: root/Presence
diff options
context:
space:
mode:
authorjoe <joe@jerkface.net>2013-07-01 00:48:20 -0400
committerjoe <joe@jerkface.net>2013-07-01 00:48:20 -0400
commitd0eb0e8d0db2fdd55511d8176467675816b0a179 (patch)
treecaf5e64b9ea780bb0354b55444d792ac2aa75ec4 /Presence
parentb70209c295681a89b64f7527a2ecae23d9bb9bc2 (diff)
fixed gatherElement bug (it was bypassing the NestingXML api)
Diffstat (limited to 'Presence')
-rw-r--r--Presence/XMPP.hs101
1 files changed, 31 insertions, 70 deletions
diff --git a/Presence/XMPP.hs b/Presence/XMPP.hs
index 36630bc7..2917d833 100644
--- a/Presence/XMPP.hs
+++ b/Presence/XMPP.hs
@@ -177,12 +177,12 @@ filterMapElement ret opentag empty = loop (empty `mplus` ret opentag) 1
177 177
178gatherElement :: 178gatherElement ::
179 (Monad m, MonadPlus mp) => 179 (Monad m, MonadPlus mp) =>
180 Event -> mp Event -> MaybeT (ConduitM Event o m) (mp Event) 180 Event -> mp Event -> NestingXML o m (mp Event)
181gatherElement opentag empty = loop (empty `mplus` return opentag) 1 181gatherElement opentag empty = loop (empty `mplus` return opentag) 1
182 where 182 where
183 loop ts 0 = return ts 183 loop ts 0 = return ts
184 loop ts cnt = do 184 loop ts cnt = do
185 tag <- mawait 185 maybeXML (return ts) $ \tag -> do
186 let ts' = mplus ts (return tag) 186 let ts' = mplus ts (return tag)
187 case () of 187 case () of
188 _ | eventIsEndElement tag -> loop ts' (cnt-1) 188 _ | eventIsEndElement tag -> loop ts' (cnt-1)
@@ -224,68 +224,6 @@ uncontent cs = head $ map getText cs
224 getText (ContentText x) = x 224 getText (ContentText x) = x
225 getText (ContentEntity x ) = x 225 getText (ContentEntity x ) = x
226 226
227-- doIQ :: MonadIO m => Event -> MaybeT (ConduitM Event o m) ()
228doIQ session cmdChan tag@(EventBeginElement name attrs) = do
229 (_,uncontent->iq_id) <- MaybeT . return $ find (\(n,v)->isId n) attrs
230 -- The 'id' attribute is REQUIRED for IQ stanzas.
231 -- todo: handle it's absence more gracefully
232 case (find (\(n,v)->isType n) attrs) of
233 Just (_,[ContentText "get"]) -> discard
234 Just (_,[ContentText "set"]) -> do
235 fix $ \iqsetloop -> do
236 setwhat <- mawait
237 liftIO (putStrLn $ "IQ-set " ++ show setwhat)
238 case setwhat of
239 bind@(EventBeginElement name attrs) | isBind name -> do
240 fix $ \again -> do
241 rscElem <- mawait
242 liftIO (putStrLn $ "IQ-set-bind " ++ show rscElem)
243 case rscElem of
244 bindchild@(EventBeginElement name _) | isResource name -> do
245 let isContent (EventContent (ContentText v)) = return v
246 isContent _ = mzero
247 xs <- filterMapElement isContent bindchild Nothing
248 case xs of
249 Just rsrc ->
250 liftIO $ do
251 setResource session (L.fromChunks [S.encodeUtf8 rsrc])
252 jid <- getJID session
253 atomically $ writeTChan cmdChan (Send $ iq_bind_reply iq_id (toStrict $ L.decodeUtf8 $ L.show jid) )
254 Nothing -> return () -- TODO: empty resource tag?
255 void $ gatherElement bind Nothing
256 bindchild@(EventBeginElement _ _) -> do
257 liftIO (putStrLn "unknown bind child")
258 gatherElement bindchild Nothing
259 void $ gatherElement bind Nothing
260 EventEndElement _ -> do
261 liftIO (putStrLn "empty bind")
262 -- TODO
263 -- A server that supports resource binding MUST be able to
264 -- generate a resource identifier on behalf of a client. A
265 -- resource identifier generated by the server MUST be unique
266 -- for that <node@domain>.
267 _ -> again
268 discard
269 req@(EventBeginElement name attrs) -> do
270 liftIO (putStrLn $ "IQ-set-unknown " ++ show req)
271 gatherElement req Nothing
272 discard
273 endtag@(EventEndElement _) -> do
274 liftIO (putStrLn $ "IQ-set-empty" ++ show endtag)
275 _ -> iqsetloop
276 Just (_,[ContentText "result"]) -> discard
277 Just (_,[ContentText "error"]) -> discard
278 Just _ -> discard -- error: type must be one of {get,set,result,error}
279 Nothing -> discard -- error: The 'type' attribute is REQUIRED for IQ stanzas.
280 where
281 isId n = n=="id"
282 isType n = n=="type"
283 isResource n = n=="{urn:ietf:params:xml:ns:xmpp-bind}resource"
284 isBind n = n=="{urn:ietf:params:xml:ns:xmpp-bind}bind"
285 discard = do
286 xs <- gatherElement tag Seq.empty
287 prettyPrint "client-in: ignoring iq:" (toList xs)
288
289withJust (Just x) f = f x 227withJust (Just x) f = f x
290withJust Nothing f = return () 228withJust Nothing f = return ()
291 229
@@ -391,7 +329,30 @@ handleIQGet session cmdChan tag = do
391 liftIO . atomically . writeTChan cmdChan . Send $ iq_service_unavailable host stanza_id Nothing req 329 liftIO . atomically . writeTChan cmdChan . Send $ iq_service_unavailable host stanza_id Nothing req
392 case tagName child of 330 case tagName child of
393 -- "{http://jabber.org/protocol/disco#items}query" -> liftIO $ putStrLn "iq-get-query-items" 331 -- "{http://jabber.org/protocol/disco#items}query" -> liftIO $ putStrLn "iq-get-query-items"
394 -- "{urn:xmpp:ping}ping" -> todo 332 {-
333 IN client:
334 <iq type="get" id="purple8f8224d6"
335 ><ping xmlns="urn:xmpp:ping"/></iq>
336
337
338 OUT client:
339 <iq from='blackbird' id='purple8f8224d6' type='result'/>
340 -}
341 "{urn:xmpp:ping}ping" -> liftIO $ do
342 putStrLn ("iq-ping: "++show (stanza_id,child))
343 let mjid = lookupAttrib "from" (tagAttrs tag)
344 L.putStrLn $ "PING! from=" <++> bshow mjid
345 let pong = [ EventBeginElement "{jabber:client}iq"
346 $ (case mjid of
347 Just jid -> (("to",[ContentText jid]):)
348 _ -> id)
349 [("type",[ContentText "result"])
350 ,("id",[ContentText stanza_id])
351 ,("from",[ContentText host])
352 ]
353 , EventEndElement "{jabber:client}iq"
354 ]
355 atomically . writeTChan cmdChan . Send $ pong
395 req -> unhandledGet req 356 req -> unhandledGet req
396 357
397 358
@@ -418,8 +379,8 @@ fromClient session cmdChan = doNestingXML $ do
418 stanza_lvl <- nesting 379 stanza_lvl <- nesting
419 380
420 let unhandledStanza = do 381 let unhandledStanza = do
421 mb <- lift . runMaybeT $ gatherElement stanza Seq.empty 382 xs <- gatherElement stanza Seq.empty
422 withJust mb $ \xs -> prettyPrint "C: " (toList xs) 383 prettyPrint "unhandled-C: " (toList xs)
423 case () of 384 case () of
424 _ | stanza `isIQOf` iqTypeSet -> handleIQSet session cmdChan stanza 385 _ | stanza `isIQOf` iqTypeSet -> handleIQSet session cmdChan stanza
425 _ | stanza `isIQOf` iqTypeGet -> handleIQGet session cmdChan stanza 386 _ | stanza `isIQOf` iqTypeGet -> handleIQGet session cmdChan stanza
@@ -612,11 +573,11 @@ fromPeer session = doNestingXML $ do
612 stanza_lvl <- nesting 573 stanza_lvl <- nesting
613 574
614 let unhandledStanza = do 575 let unhandledStanza = do
615 mb <- lift . runMaybeT $ gatherElement stanza Seq.empty 576 xs <- gatherElement stanza Seq.empty
616 withJust mb $ \xs -> prettyPrint "P: " (toList xs) 577 prettyPrint "P: " (toList xs)
617 case () of 578 case () of
618 _ | stanza `isPresenceOf` presenceTypeOnline 579 _ | stanza `isPresenceOf` presenceTypeOnline
619 -> log "peer online!" >> handlePeerPresence session stanza True 580 -> handlePeerPresence session stanza True
620 _ | stanza `isPresenceOf` presenceTypeOffline 581 _ | stanza `isPresenceOf` presenceTypeOffline
621 -> handlePeerPresence session stanza False 582 -> handlePeerPresence session stanza False
622 _ -> unhandledStanza 583 _ -> unhandledStanza