From 92746237a9b8c90f4cbccd833656c29e8a07857d Mon Sep 17 00:00:00 2001 From: Philipp Balzarek Date: Mon, 10 Jun 2013 13:16:54 +0200 Subject: [PATCH] check for roster versioning stream feature and disable roster versioning unless present --- source/Network/Xmpp/Concurrent/Basic.hs | 6 ++++++ source/Network/Xmpp/IM/Roster.hs | 18 +++++++++++++----- source/Network/Xmpp/Marshal.hs | 7 ++++--- source/Network/Xmpp/Stream.hs | 4 ++-- source/Network/Xmpp/Types.hs | 1 + 5 files changed, 26 insertions(+), 10 deletions(-) diff --git a/source/Network/Xmpp/Concurrent/Basic.hs b/source/Network/Xmpp/Concurrent/Basic.hs index 99623f9..b5d24d2 100644 --- a/source/Network/Xmpp/Concurrent/Basic.hs +++ b/source/Network/Xmpp/Concurrent/Basic.hs @@ -30,3 +30,9 @@ getJid :: Session -> IO (Maybe Jid) getJid Session{streamRef = st} = do s <- atomically $ readTMVar st withStream' (gets streamJid) s + +-- | Return the JID assigned to us by the server +getFeatures :: Session -> IO StreamFeatures +getFeatures Session{streamRef = st} = do + s <- atomically $ readTMVar st + withStream' (gets streamFeatures) s diff --git a/source/Network/Xmpp/IM/Roster.hs b/source/Network/Xmpp/IM/Roster.hs index de62bb0..2f0dacf 100644 --- a/source/Network/Xmpp/IM/Roster.hs +++ b/source/Network/Xmpp/IM/Roster.hs @@ -4,6 +4,7 @@ module Network.Xmpp.IM.Roster where +import Control.Applicative ((<$>)) import Control.Concurrent.STM import Control.Monad import Data.List (nub) @@ -14,11 +15,12 @@ import Data.XML.Pickle import Data.XML.Types import System.Log.Logger +import Network.Xmpp.Concurrent.Basic +import Network.Xmpp.Concurrent.IQ +import Network.Xmpp.Concurrent.Types import Network.Xmpp.IM.Roster.Types import Network.Xmpp.Marshal -import Network.Xmpp.Concurrent.Types import Network.Xmpp.Types -import Network.Xmpp.Concurrent.IQ -- | Push a roster item to the server. The values for approved and ask are -- ignored and all values for subsciption except "remove" are ignored @@ -107,9 +109,15 @@ handleRoster ref outC sta = case sta of IQResultS $ IQResult iqid Nothing from lang Nothing retrieveRoster :: Maybe Roster -> Session -> IO (Maybe Roster) -retrieveRoster oldRoster sess = do +retrieveRoster mbOldRoster sess = do + useVersioning <- rosterVer <$> getFeatures sess + let version = if useVersioning + then case mbOldRoster of + Nothing -> Just "" + Just oldRoster -> ver oldRoster + else Nothing res <- sendIQ' Nothing Get Nothing - (pickleElem xpQuery (Query (ver =<< oldRoster) [])) + (pickleElem xpQuery (Query version [])) sess case res of IQResponseResult (IQResult{iqResultPayload = Just ros}) @@ -119,7 +127,7 @@ retrieveRoster oldRoster sess = do return Nothing Right ros' -> return . Just $ toRoster ros' IQResponseResult (IQResult{iqResultPayload = Nothing}) -> do - return oldRoster + return mbOldRoster -- sever indicated that no roster updates are necessary IQResponseTimeout -> do errorM "Pontarius.Xmpp.Roster" "getRoster: request timed out" diff --git a/source/Network/Xmpp/Marshal.hs b/source/Network/Xmpp/Marshal.hs index ce68966..1a08d5f 100644 --- a/source/Network/Xmpp/Marshal.hs +++ b/source/Network/Xmpp/Marshal.hs @@ -250,17 +250,18 @@ xpStream = xpElemAttrs -- Pickler/Unpickler for the stream features - TLS, SASL, and the rest. xpStreamFeatures :: PU [Node] StreamFeatures xpStreamFeatures = ("xpStreamFeatures","") xpWrap - (\(tls, sasl, rest) -> StreamFeatures tls (mbl sasl) rest) - (\(StreamFeatures tls sasl rest) -> (tls, lmb sasl, rest)) + (\(tls, sasl, ver, rest) -> StreamFeatures tls (mbl sasl) ver rest) + (\(StreamFeatures tls sasl ver rest) -> (tls, lmb sasl, ver, rest)) (xpElemNodes (Name "features" (Just "http://etherx.jabber.org/streams") (Just "stream") ) - (xpTriple + (xp4Tuple (xpOption pickleTlsFeature) (xpOption pickleSaslFeature) + (xpElemExists "{urn:xmpp:features:rosterver}ver") (xpAll xpElemVerbatim) ) ) diff --git a/source/Network/Xmpp/Stream.hs b/source/Network/Xmpp/Stream.hs index c80a8d9..089514f 100644 --- a/source/Network/Xmpp/Stream.hs +++ b/source/Network/Xmpp/Stream.hs @@ -488,7 +488,7 @@ xmppNoStream = StreamState { streamConnectionState = Closed , streamHandle = zeroHandle , streamEventSource = zeroSource - , streamFeatures = StreamFeatures Nothing [] [] + , streamFeatures = StreamFeatures Nothing [] False [] , streamAddress = Nothing , streamFrom = Nothing , streamId = Nothing @@ -522,7 +522,7 @@ createStream realm config = do { streamConnectionState = Plain , streamHandle = hand , streamEventSource = eSource - , streamFeatures = StreamFeatures Nothing [] [] + , streamFeatures = StreamFeatures Nothing [] False [] , streamAddress = Just $ Text.pack realm , streamFrom = Nothing , streamId = Nothing diff --git a/source/Network/Xmpp/Types.hs b/source/Network/Xmpp/Types.hs index e87212e..67d2343 100644 --- a/source/Network/Xmpp/Types.hs +++ b/source/Network/Xmpp/Types.hs @@ -823,6 +823,7 @@ langTagParser = do data StreamFeatures = StreamFeatures { streamTls :: !(Maybe Bool) , streamSaslMechanisms :: ![Text.Text] + , rosterVer :: !Bool , streamOtherFeatures :: ![Element] -- TODO: All feature elements instead? } deriving Show