From 61c5f0dda920ce604a741781899d6a7f2a7cc866 Mon Sep 17 00:00:00 2001
From: Philipp Balzarek
Date: Wed, 23 Oct 2013 14:19:17 +0200
Subject: [PATCH] make stanza handler plugins more flexible
stanza handlers used to return a Boolean value to indicate whether stanza processing should continue. Now the return lists of stanzas instead. This facilitates plugins that transform stranzas (e.g. encryption)
---
source/Network/Xmpp/Concurrent.hs | 17 +++++++----------
source/Network/Xmpp/IM/Roster.hs | 12 ++++++------
source/Network/Xmpp/Types.hs | 4 ++--
3 files changed, 15 insertions(+), 18 deletions(-)
diff --git a/source/Network/Xmpp/Concurrent.hs b/source/Network/Xmpp/Concurrent.hs
index 4e4ca13..8bf20ba 100644
--- a/source/Network/Xmpp/Concurrent.hs
+++ b/source/Network/Xmpp/Concurrent.hs
@@ -52,24 +52,21 @@ runHandlers :: WriteSemaphore -> [StanzaHandler] -> Stanza -> IO ()
runHandlers _ [] _ = return ()
runHandlers sem (h:hands) sta = do
res <- h sem sta
- case res of
- True -> runHandlers sem hands sta
- False -> return ()
+ forM_ res (runHandlers sem hands)
toChan :: TChan Stanza -> StanzaHandler
toChan stanzaC _ sta = do
atomically $ writeTChan stanzaC sta
- return True
-
+ return [sta]
handleIQ :: TVar IQHandlers
-> StanzaHandler
handleIQ iqHands writeSem sta = do
case sta of
- IQRequestS i -> handleIQRequest iqHands i >> return False
- IQResultS i -> handleIQResponse iqHands (Right i) >> return False
- IQErrorS i -> handleIQResponse iqHands (Left i) >> return False
- _ -> return True
+ IQRequestS i -> handleIQRequest iqHands i >> return []
+ IQResultS i -> handleIQResponse iqHands (Right i) >> return []
+ IQErrorS i -> handleIQResponse iqHands (Left i) >> return []
+ _ -> return [sta]
where
-- If the IQ request has a namespace, send it through the appropriate channel.
handleIQRequest :: TVar IQHandlers -> IQRequest -> IO ()
@@ -141,7 +138,7 @@ newSession stream config realm mbSasl = runErrorT $ do
ros <- liftIO . newTVarIO $ Roster Nothing Map.empty
rew <- lift $ newTVarIO 60
let rosterH = if (enableRoster config) then handleRoster ros
- else \ _ _ -> return True
+ else \ _ sta -> return [sta]
let stanzaHandler = runHandlers writeSem
$ Prelude.concat [ [ toChan stanzaChan ]
, extraStanzaHandlers
diff --git a/source/Network/Xmpp/IM/Roster.hs b/source/Network/Xmpp/IM/Roster.hs
index 358531b..f71ef91 100644
--- a/source/Network/Xmpp/IM/Roster.hs
+++ b/source/Network/Xmpp/IM/Roster.hs
@@ -81,26 +81,26 @@ initRoster session = do
"Server did not return a roster"
Just roster -> atomically $ writeTVar (rosterRef session) roster
-handleRoster :: TVar Roster -> WriteSemaphore -> Stanza -> IO Bool
+handleRoster :: TVar Roster -> WriteSemaphore -> Stanza -> IO [Stanza]
handleRoster ref sem sta = case sta of
IQRequestS (iqr@IQRequest{iqRequestPayload =
iqb@Element{elementName = en}})
| nameNamespace en == Just "jabber:iq:roster" -> do
case iqRequestFrom iqr of
- Just _from -> return True -- Don't handle roster pushes from
- -- unauthorized sources
+ Just _from -> return [sta] -- Don't handle roster pushes from
+ -- unauthorized sources
Nothing -> case unpickleElem xpQuery iqb of
Right Query{ queryVer = v
, queryItems = [update]
} -> do
handleUpdate v update
_ <- writeStanza sem $ result iqr
- return False
+ return []
_ -> do
errorM "Pontarius.Xmpp" "Invalid roster query"
_ <- writeStanza sem $ badRequest iqr
- return False
- _ -> return True
+ return []
+ _ -> return [sta]
where
handleUpdate v' update = atomically $ modifyTVar ref $ \(Roster v is) ->
Roster (v' `mplus` v) $ case qiSubscription update of
diff --git a/source/Network/Xmpp/Types.hs b/source/Network/Xmpp/Types.hs
index e342dd6..811dd4d 100644
--- a/source/Network/Xmpp/Types.hs
+++ b/source/Network/Xmpp/Types.hs
@@ -756,7 +756,7 @@ instance Read Jid where
#if WITH_TEMPLATE_HASKELL
-- | Constructs a @Jid@ value at compile time.
---
+--
-- Syntax:
-- @
-- [jidQ|localpart\@domainpart/resourcepart|]
@@ -1037,7 +1037,7 @@ instance Default StreamConfiguration where
type StanzaHandler = TMVar (BS.ByteString -> IO Bool) -- ^ outgoing stanza
-> Stanza -- ^ stanza to handle
- -> IO Bool -- ^ True when processing should continue
+ -> IO [Stanza] -- ^ modified stanzas (if any)
-- | How the client should behave in regards to TLS.
data TlsBehaviour = RequireTls -- ^ Require the use of TLS; disconnect if it's