From 664daa540aa05e097f2fc012cff8f35b8dc9f037 Mon Sep 17 00:00:00 2001
From: Philipp Balzarek
Date: Tue, 12 Nov 2013 17:18:59 +0100
Subject: [PATCH] add timeout parameter to sendIQ'
---
pontarius-xmpp.cabal | 1 +
source/Network/Xmpp/Concurrent/IQ.hs | 26 ++++++++++++++------------
source/Network/Xmpp/IM/Roster.hs | 14 +++++++++-----
3 files changed, 24 insertions(+), 17 deletions(-)
diff --git a/pontarius-xmpp.cabal b/pontarius-xmpp.cabal
index 046fc86..7d54ba2 100644
--- a/pontarius-xmpp.cabal
+++ b/pontarius-xmpp.cabal
@@ -67,6 +67,7 @@ Library
, tls >=1.1.3
, tls-extra >=0.6.0
, transformers >=0.2.2.0
+ , unbounded-delays >=0.1
, void >=0.5.5
, xml-types >=0.3.1
, xml-conduit >=1.1.0.7
diff --git a/source/Network/Xmpp/Concurrent/IQ.hs b/source/Network/Xmpp/Concurrent/IQ.hs
index 2204493..9055875 100644
--- a/source/Network/Xmpp/Concurrent/IQ.hs
+++ b/source/Network/Xmpp/Concurrent/IQ.hs
@@ -1,8 +1,10 @@
{-# OPTIONS_HADDOCK hide #-}
module Network.Xmpp.Concurrent.IQ where
-import Control.Concurrent (forkIO, threadDelay)
+import Control.Concurrent (forkIO)
+import Control.Concurrent.Thread.Delay (delay)
import Control.Concurrent.STM
+
import Control.Monad
import qualified Data.Map as Map
@@ -16,17 +18,17 @@ import Network.Xmpp.Types
-- | Sends an IQ, returns Just a 'TMVar' that will be filled with the first
-- inbound IQ with a matching ID that has type @result@ or @error@ or Nothing if
-- the stanza could not be sent
-sendIQ :: Maybe Int -- ^ Timeout . When the timeout is reached the response
- -- TMVar will be filled with 'IQResponseTimeout' and the id
- -- is removed from the list of IQ handlers. 'Nothing'
- -- deactivates the timeout
+sendIQ :: Maybe Integer -- ^ Timeout . When the timeout is reached the response
+ -- TMVar will be filled with 'IQResponseTimeout' and the
+ -- id is removed from the list of IQ handlers. 'Nothing'
+ -- deactivates the timeout
-> Maybe Jid -- ^ Recipient (to)
-> IQRequestType -- ^ IQ type (@Get@ or @Set@)
-> Maybe LangTag -- ^ Language tag of the payload (@Nothing@ for
-- default)
-> Element -- ^ The IQ body (there has to be exactly one)
-> Session
- -> IO (Maybe (TMVar IQResponse))
+ -> IO (Maybe (TMVar (Maybe IQResponse)))
sendIQ timeOut to tp lang body session = do -- TODO: Add timeout
newId <- idGenerator session
ref <- atomically $ do
@@ -41,7 +43,7 @@ sendIQ timeOut to tp lang body session = do -- TODO: Add timeout
case timeOut of
Nothing -> return ()
Just t -> void . forkIO $ do
- threadDelay t
+ delay t
doTimeOut (iqHandlers session) newId ref
return $ Just ref
else return Nothing
@@ -53,16 +55,16 @@ sendIQ timeOut to tp lang body session = do -- TODO: Add timeout
writeTVar handlers (byNS, Map.delete iqid byId)
return ()
-
--- | Like 'sendIQ', but waits for the answer IQ. Times out after 30 seconds
-sendIQ' :: Maybe Jid
+-- | Like 'sendIQ', but waits for the answer IQ.
+sendIQ' :: Maybe Integer
+ -> Maybe Jid
-> IQRequestType
-> Maybe LangTag
-> Element
-> Session
-> IO (Maybe IQResponse)
-sendIQ' to tp lang body session = do
- ref <- sendIQ (Just 30000000) to tp lang body session
+sendIQ' timeout to tp lang body session = do
+ ref <- sendIQ timeout to tp lang body session
maybe (return Nothing) (fmap Just . atomically . takeTMVar) ref
diff --git a/source/Network/Xmpp/IM/Roster.hs b/source/Network/Xmpp/IM/Roster.hs
index e0f4425..5e1a8aa 100644
--- a/source/Network/Xmpp/IM/Roster.hs
+++ b/source/Network/Xmpp/IM/Roster.hs
@@ -27,12 +27,16 @@ import Network.Xmpp.IM.Roster.Types
import Network.Xmpp.Marshal
import Network.Xmpp.Types
+-- | Timeout to use with IQ requests
+timeout :: Maybe Integer
+timeout = Just 3000000 -- 3 seconds
+
-- | Push a roster item to the server. The values for approved and ask are
-- ignored and all values for subsciption except "remove" are ignored
rosterPush :: Item -> Session -> IO (Maybe IQResponse)
rosterPush item session = do
let el = pickleElem xpQuery (Query Nothing [fromItem item])
- sendIQ' Nothing Set Nothing el session
+ sendIQ' timeout Nothing Set Nothing el session
-- | Add or update an item to the roster.
--
@@ -51,7 +55,7 @@ rosterAdd j n gs session = do
, qiSubscription = Nothing
, qiGroups = nub gs
}])
- sendIQ' Nothing Set Nothing el session
+ sendIQ' timeout Nothing Set Nothing el session
-- | Remove an item from the roster. Return True when the item is sucessfully
-- removed or if it wasn't in the roster to begin with.
@@ -121,9 +125,9 @@ retrieveRoster mbOldRoster sess = do
Nothing -> Just ""
Just oldRoster -> ver oldRoster
else Nothing
- res <- sendIQ' Nothing Get Nothing
- (pickleElem xpQuery (Query version []))
- sess
+ res <- sendIQ' timeout Nothing Get Nothing
+ (pickleElem xpQuery (Query version []))
+ sess
case res of
Nothing -> do
errorM "Pontarius.Xmpp.Roster" "getRoster: sending stanza failed"