Browse Source

remove IQResponseTimeout from IQResponse

IQResponseTimeout does not model an XMPP type but is instead an implementation specific signal that a user-set timeout has occured. Removing it keeps our representation closer to the defined protocol.

add IQSendError to keep the result of sendIQ' clear
master
Philipp Balzarek 12 years ago
parent
commit
da64e8758e
  1. 2
      source/Network/Xmpp/Concurrent.hs
  2. 8
      source/Network/Xmpp/Concurrent/IQ.hs
  3. 7
      source/Network/Xmpp/Concurrent/Types.hs
  4. 21
      source/Network/Xmpp/IM/Roster.hs
  5. 3
      source/Network/Xmpp/Types.hs

2
source/Network/Xmpp/Concurrent.hs

@ -117,7 +117,7 @@ handleIQ iqHands out sta = do
case Map.updateLookupWithKey (\_ _ -> Nothing) (iqID iq) byID of case Map.updateLookupWithKey (\_ _ -> Nothing) (iqID iq) byID of
(Nothing, _) -> return () -- We are not supposed to send an error. (Nothing, _) -> return () -- We are not supposed to send an error.
(Just tmvar, byID') -> do (Just tmvar, byID') -> do
let answer = either IQResponseError IQResponseResult iq let answer = Just $ either IQResponseError IQResponseResult iq
_ <- tryPutTMVar tmvar answer -- Don't block. _ <- tryPutTMVar tmvar answer -- Don't block.
writeTVar handlers (byNS, byID') writeTVar handlers (byNS, byID')
where where

8
source/Network/Xmpp/Concurrent/IQ.hs

@ -49,7 +49,7 @@ sendIQ timeOut to tp lang body session = do -- TODO: Add timeout
else return Nothing else return Nothing
where where
doTimeOut handlers iqid var = atomically $ do doTimeOut handlers iqid var = atomically $ do
p <- tryPutTMVar var IQResponseTimeout p <- tryPutTMVar var Nothing
when p $ do when p $ do
(byNS, byId) <- readTVar (iqHandlers session) (byNS, byId) <- readTVar (iqHandlers session)
writeTVar handlers (byNS, Map.delete iqid byId) writeTVar handlers (byNS, Map.delete iqid byId)
@ -62,11 +62,11 @@ sendIQ' :: Maybe Integer
-> Maybe LangTag -> Maybe LangTag
-> Element -> Element
-> Session -> Session
-> IO (Maybe IQResponse) -> IO (Either IQSendError IQResponse)
sendIQ' timeout to tp lang body session = do sendIQ' timeout to tp lang body session = do
ref <- sendIQ timeout to tp lang body session ref <- sendIQ timeout to tp lang body session
maybe (return Nothing) (fmap Just . atomically . takeTMVar) ref maybe (return $ Left IQSendError) (fmap (maybe (Left IQTimeOut) Right)
. atomically . takeTMVar) ref
-- | Retrieves an IQ listener channel. If the namespace/'IQRequestType' is not -- | Retrieves an IQ listener channel. If the namespace/'IQRequestType' is not
-- already handled, a new 'TChan' is created and returned as a 'Right' value. -- already handled, a new 'TChan' is created and returned as a 'Right' value.

7
source/Network/Xmpp/Concurrent/Types.hs

@ -97,7 +97,7 @@ data Session = Session
-- TMVars of and TMVars for expected IQ responses (the second Text represent a -- TMVars of and TMVars for expected IQ responses (the second Text represent a
-- stanza identifier. -- stanza identifier.
type IQHandlers = ( Map.Map (IQRequestType, Text) (TChan IQRequestTicket) type IQHandlers = ( Map.Map (IQRequestType, Text) (TChan IQRequestTicket)
, Map.Map Text (TMVar IQResponse) , Map.Map Text (TMVar (Maybe IQResponse))
) )
-- | Contains whether or not a reply has been sent, and the IQ request body to -- | Contains whether or not a reply has been sent, and the IQ request body to
@ -110,3 +110,8 @@ data IQRequestTicket = IQRequestTicket
-- but failed (e.g. there is a connection failure) -- but failed (e.g. there is a connection failure)
, iqRequestBody :: IQRequest , iqRequestBody :: IQRequest
} }
-- | Error that can occur during sendIQ'
data IQSendError = IQSendError -- There was an error sending the IQ stanza
| IQTimeOut -- No answer was received during the allotted time
deriving (Show, Eq)

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

@ -33,7 +33,7 @@ timeout = Just 3000000 -- 3 seconds
-- | Push a roster item to the server. The values for approved and ask are -- | Push a roster item to the server. The values for approved and ask are
-- ignored and all values for subsciption except "remove" are ignored -- ignored and all values for subsciption except "remove" are ignored
rosterPush :: Item -> Session -> IO (Maybe IQResponse) rosterPush :: Item -> Session -> IO (Either IQSendError IQResponse)
rosterPush item session = do rosterPush item session = do
let el = pickleElem xpQuery (Query Nothing [fromItem item]) let el = pickleElem xpQuery (Query Nothing [fromItem item])
sendIQ' timeout Nothing Set Nothing el session sendIQ' timeout Nothing Set Nothing el session
@ -45,7 +45,7 @@ rosterAdd :: Jid -- ^ JID of the item
-> Maybe Text -- ^ Name alias -> Maybe Text -- ^ Name alias
-> [Text] -- ^ Groups (duplicates will be removed) -> [Text] -- ^ Groups (duplicates will be removed)
-> Session -> Session
-> IO (Maybe IQResponse) -> IO (Either IQSendError IQResponse)
rosterAdd j n gs session = do rosterAdd j n gs session = do
let el = pickleElem xpQuery (Query Nothing let el = pickleElem xpQuery (Query Nothing
[QueryItem { qiApproved = Nothing [QueryItem { qiApproved = Nothing
@ -67,7 +67,7 @@ rosterRemove j sess = do
Just _ -> do Just _ -> do
res <- rosterPush (Item False False j Nothing Remove []) sess res <- rosterPush (Item False False j Nothing Remove []) sess
case res of case res of
Just (IQResponseResult IQResult{}) -> return True Right (IQResponseResult IQResult{}) -> return True
_ -> return False _ -> return False
-- | Retrieve the current Roster state -- | Retrieve the current Roster state
@ -82,7 +82,7 @@ initRoster session = do
else Nothing ) session else Nothing ) session
case mbRoster of case mbRoster of
Nothing -> errorM "Pontarius.Xmpp" Nothing -> errorM "Pontarius.Xmpp"
"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 -> StanzaHandler handleRoster :: TVar Roster -> StanzaHandler
@ -129,22 +129,19 @@ retrieveRoster mbOldRoster sess = do
(pickleElem xpQuery (Query version [])) (pickleElem xpQuery (Query version []))
sess sess
case res of case res of
Nothing -> do Left e -> do
errorM "Pontarius.Xmpp.Roster" "getRoster: sending stanza failed" errorM "Pontarius.Xmpp.Roster" $ "getRoster: " ++ show e
return Nothing return Nothing
Just (IQResponseResult (IQResult{iqResultPayload = Just ros})) Right (IQResponseResult (IQResult{iqResultPayload = Just ros}))
-> case unpickleElem xpQuery ros of -> case unpickleElem xpQuery ros of
Left _e -> do Left _e -> do
errorM "Pontarius.Xmpp.Roster" "getRoster: invalid query element" errorM "Pontarius.Xmpp.Roster" "getRoster: invalid query element"
return Nothing return Nothing
Right ros' -> return . Just $ toRoster ros' Right ros' -> return . Just $ toRoster ros'
Just (IQResponseResult (IQResult{iqResultPayload = Nothing})) -> do Right (IQResponseResult (IQResult{iqResultPayload = Nothing})) -> do
return mbOldRoster return mbOldRoster
-- sever indicated that no roster updates are necessary -- sever indicated that no roster updates are necessary
Just IQResponseTimeout -> do Right (IQResponseError e) -> do
errorM "Pontarius.Xmpp.Roster" "getRoster: request timed out"
return Nothing
Just (IQResponseError e) -> do
errorM "Pontarius.Xmpp.Roster" $ "getRoster: server returned error" errorM "Pontarius.Xmpp.Roster" $ "getRoster: server returned error"
++ show e ++ show e
return Nothing return Nothing

3
source/Network/Xmpp/Types.hs

@ -119,10 +119,9 @@ data IQRequest = IQRequest { iqRequestID :: !Text
data IQRequestType = Get | Set deriving (Eq, Ord, Read, Show) data IQRequestType = Get | Set deriving (Eq, Ord, Read, Show)
-- | A "response" Info/Query (IQ) stanza is either an 'IQError', an IQ stanza -- | A "response" Info/Query (IQ) stanza is either an 'IQError', an IQ stanza
-- of type "result" ('IQResult') or a Timeout. -- of type "result" ('IQResult')
data IQResponse = IQResponseError IQError data IQResponse = IQResponseError IQError
| IQResponseResult IQResult | IQResponseResult IQResult
| IQResponseTimeout
deriving Show deriving Show
-- | The (non-error) answer to an IQ request. -- | The (non-error) answer to an IQ request.

Loading…
Cancel
Save