Browse Source

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)
master
Philipp Balzarek 12 years ago
parent
commit
61c5f0dda9
  1. 17
      source/Network/Xmpp/Concurrent.hs
  2. 12
      source/Network/Xmpp/IM/Roster.hs
  3. 2
      source/Network/Xmpp/Types.hs

17
source/Network/Xmpp/Concurrent.hs

@ -52,24 +52,21 @@ runHandlers :: WriteSemaphore -> [StanzaHandler] -> Stanza -> IO ()
runHandlers _ [] _ = return () runHandlers _ [] _ = return ()
runHandlers sem (h:hands) sta = do runHandlers sem (h:hands) sta = do
res <- h sem sta res <- h sem sta
case res of forM_ res (runHandlers sem hands)
True -> runHandlers sem hands sta
False -> return ()
toChan :: TChan Stanza -> StanzaHandler toChan :: TChan Stanza -> StanzaHandler
toChan stanzaC _ sta = do toChan stanzaC _ sta = do
atomically $ writeTChan stanzaC sta atomically $ writeTChan stanzaC sta
return True return [sta]
handleIQ :: TVar IQHandlers handleIQ :: TVar IQHandlers
-> StanzaHandler -> StanzaHandler
handleIQ iqHands writeSem sta = do handleIQ iqHands writeSem sta = do
case sta of case sta of
IQRequestS i -> handleIQRequest iqHands i >> return False IQRequestS i -> handleIQRequest iqHands i >> return []
IQResultS i -> handleIQResponse iqHands (Right i) >> return False IQResultS i -> handleIQResponse iqHands (Right i) >> return []
IQErrorS i -> handleIQResponse iqHands (Left i) >> return False IQErrorS i -> handleIQResponse iqHands (Left i) >> return []
_ -> return True _ -> return [sta]
where where
-- If the IQ request has a namespace, send it through the appropriate channel. -- If the IQ request has a namespace, send it through the appropriate channel.
handleIQRequest :: TVar IQHandlers -> IQRequest -> IO () handleIQRequest :: TVar IQHandlers -> IQRequest -> IO ()
@ -141,7 +138,7 @@ newSession stream config realm mbSasl = runErrorT $ do
ros <- liftIO . newTVarIO $ Roster Nothing Map.empty ros <- liftIO . newTVarIO $ Roster Nothing Map.empty
rew <- lift $ newTVarIO 60 rew <- lift $ newTVarIO 60
let rosterH = if (enableRoster config) then handleRoster ros let rosterH = if (enableRoster config) then handleRoster ros
else \ _ _ -> return True else \ _ sta -> return [sta]
let stanzaHandler = runHandlers writeSem let stanzaHandler = runHandlers writeSem
$ Prelude.concat [ [ toChan stanzaChan ] $ Prelude.concat [ [ toChan stanzaChan ]
, extraStanzaHandlers , extraStanzaHandlers

12
source/Network/Xmpp/IM/Roster.hs

@ -81,26 +81,26 @@ initRoster session = do
"Server did not return a roster" "Server did not return a roster"
Just roster -> atomically $ writeTVar (rosterRef session) 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 handleRoster ref sem sta = case sta of
IQRequestS (iqr@IQRequest{iqRequestPayload = IQRequestS (iqr@IQRequest{iqRequestPayload =
iqb@Element{elementName = en}}) iqb@Element{elementName = en}})
| nameNamespace en == Just "jabber:iq:roster" -> do | nameNamespace en == Just "jabber:iq:roster" -> do
case iqRequestFrom iqr of case iqRequestFrom iqr of
Just _from -> return True -- Don't handle roster pushes from Just _from -> return [sta] -- Don't handle roster pushes from
-- unauthorized sources -- unauthorized sources
Nothing -> case unpickleElem xpQuery iqb of Nothing -> case unpickleElem xpQuery iqb of
Right Query{ queryVer = v Right Query{ queryVer = v
, queryItems = [update] , queryItems = [update]
} -> do } -> do
handleUpdate v update handleUpdate v update
_ <- writeStanza sem $ result iqr _ <- writeStanza sem $ result iqr
return False return []
_ -> do _ -> do
errorM "Pontarius.Xmpp" "Invalid roster query" errorM "Pontarius.Xmpp" "Invalid roster query"
_ <- writeStanza sem $ badRequest iqr _ <- writeStanza sem $ badRequest iqr
return False return []
_ -> return True _ -> return [sta]
where where
handleUpdate v' update = atomically $ modifyTVar ref $ \(Roster v is) -> handleUpdate v' update = atomically $ modifyTVar ref $ \(Roster v is) ->
Roster (v' `mplus` v) $ case qiSubscription update of Roster (v' `mplus` v) $ case qiSubscription update of

2
source/Network/Xmpp/Types.hs

@ -1037,7 +1037,7 @@ instance Default StreamConfiguration where
type StanzaHandler = TMVar (BS.ByteString -> IO Bool) -- ^ outgoing stanza type StanzaHandler = TMVar (BS.ByteString -> IO Bool) -- ^ outgoing stanza
-> Stanza -- ^ stanza to handle -> 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. -- | How the client should behave in regards to TLS.
data TlsBehaviour = RequireTls -- ^ Require the use of TLS; disconnect if it's data TlsBehaviour = RequireTls -- ^ Require the use of TLS; disconnect if it's

Loading…
Cancel
Save