|
|
|
@ -26,10 +26,10 @@ import Network.Xmpp.Monad |
|
|
|
-- to interfere with existing consumers. |
|
|
|
-- to interfere with existing consumers. |
|
|
|
listenIQChan :: IQRequestType -- ^ Type of IQs to receive (@Get@ or @Set@) |
|
|
|
listenIQChan :: IQRequestType -- ^ Type of IQs to receive (@Get@ or @Set@) |
|
|
|
-> Text -- ^ Namespace of the child element |
|
|
|
-> Text -- ^ Namespace of the child element |
|
|
|
-> Session |
|
|
|
-> Chans |
|
|
|
-> IO (Either (TChan IQRequestTicket) (TChan IQRequestTicket)) |
|
|
|
-> IO (Either (TChan IQRequestTicket) (TChan IQRequestTicket)) |
|
|
|
listenIQChan tp ns session = do |
|
|
|
listenIQChan tp ns chans = do |
|
|
|
let handlers = iqHandlers session |
|
|
|
let handlers = iqHandlers chans |
|
|
|
atomically $ do |
|
|
|
atomically $ do |
|
|
|
(byNS, byID) <- readTVar handlers |
|
|
|
(byNS, byID) <- readTVar handlers |
|
|
|
iqCh <- newTChan |
|
|
|
iqCh <- newTChan |
|
|
|
@ -44,110 +44,110 @@ listenIQChan tp ns session = do |
|
|
|
Just iqCh' -> Left iqCh' |
|
|
|
Just iqCh' -> Left iqCh' |
|
|
|
|
|
|
|
|
|
|
|
-- | Get a duplicate of the stanza channel |
|
|
|
-- | Get a duplicate of the stanza channel |
|
|
|
getStanzaChan :: Session -> IO (TChan Stanza) |
|
|
|
getStanzaChan :: Chans -> IO (TChan Stanza) |
|
|
|
getStanzaChan session = atomically $ dupTChan (sShadow session) |
|
|
|
getStanzaChan chans = atomically $ dupTChan (sShadow chans) |
|
|
|
|
|
|
|
|
|
|
|
-- | Get the inbound stanza channel, duplicates from master if necessary. Please |
|
|
|
-- | Get the inbound stanza channel, duplicates from master if necessary. Please |
|
|
|
-- note that once duplicated it will keep filling up, call 'dropMessageChan' to |
|
|
|
-- note that once duplicated it will keep filling up, call 'dropMessageChan' to |
|
|
|
-- allow it to be garbage collected. |
|
|
|
-- allow it to be garbage collected. |
|
|
|
getMessageChan :: Session -> IO (TChan (Either MessageError Message)) |
|
|
|
getMessageChan :: Chans -> IO (TChan (Either MessageError Message)) |
|
|
|
getMessageChan session = do |
|
|
|
getMessageChan chans = do |
|
|
|
mCh <- readIORef $ messagesRef session |
|
|
|
mCh <- readIORef $ messagesRef chans |
|
|
|
case mCh of |
|
|
|
case mCh of |
|
|
|
Nothing -> do |
|
|
|
Nothing -> do |
|
|
|
mCh' <- atomically $ dupTChan (mShadow session) |
|
|
|
mCh' <- atomically $ dupTChan (mShadow chans) |
|
|
|
writeIORef (messagesRef session) (Just mCh') |
|
|
|
writeIORef (messagesRef chans) (Just mCh') |
|
|
|
return mCh' |
|
|
|
return mCh' |
|
|
|
Just mCh' -> return mCh' |
|
|
|
Just mCh' -> return mCh' |
|
|
|
|
|
|
|
|
|
|
|
-- | Analogous to 'getMessageChan'. |
|
|
|
-- | Analogous to 'getMessageChan'. |
|
|
|
getPresenceChan :: Session -> IO (TChan (Either PresenceError Presence)) |
|
|
|
getPresenceChan :: Chans -> IO (TChan (Either PresenceError Presence)) |
|
|
|
getPresenceChan session = do |
|
|
|
getPresenceChan chans = do |
|
|
|
pCh <- readIORef $ presenceRef session |
|
|
|
pCh <- readIORef $ presenceRef chans |
|
|
|
case pCh of |
|
|
|
case pCh of |
|
|
|
Nothing -> do |
|
|
|
Nothing -> do |
|
|
|
pCh' <- atomically $ dupTChan (pShadow session) |
|
|
|
pCh' <- atomically $ dupTChan (pShadow chans) |
|
|
|
writeIORef (presenceRef session) (Just pCh') |
|
|
|
writeIORef (presenceRef chans) (Just pCh') |
|
|
|
return pCh' |
|
|
|
return pCh' |
|
|
|
Just pCh' -> return pCh' |
|
|
|
Just pCh' -> return pCh' |
|
|
|
|
|
|
|
|
|
|
|
-- | Drop the local end of the inbound stanza channel from our context so it can |
|
|
|
-- | Drop the local end of the inbound stanza channel from our context so it can |
|
|
|
-- be GC-ed. |
|
|
|
-- be GC-ed. |
|
|
|
dropMessageChan :: Session -> IO () |
|
|
|
dropMessageChan :: Chans -> IO () |
|
|
|
dropMessageChan session = writeIORef (messagesRef session) Nothing |
|
|
|
dropMessageChan chans = writeIORef (messagesRef chans) Nothing |
|
|
|
|
|
|
|
|
|
|
|
-- | Analogous to 'dropMessageChan'. |
|
|
|
-- | Analogous to 'dropMessageChan'. |
|
|
|
dropPresenceChan :: Session -> IO () |
|
|
|
dropPresenceChan :: Chans -> IO () |
|
|
|
dropPresenceChan session = writeIORef (presenceRef session) Nothing |
|
|
|
dropPresenceChan chans = writeIORef (presenceRef chans) Nothing |
|
|
|
|
|
|
|
|
|
|
|
-- | Read an element from the inbound stanza channel, acquiring a copy of the |
|
|
|
-- | Read an element from the inbound stanza channel, acquiring a copy of the |
|
|
|
-- channel as necessary. |
|
|
|
-- channel as necessary. |
|
|
|
pullMessage :: Session -> IO (Either MessageError Message) |
|
|
|
pullMessage :: Chans -> IO (Either MessageError Message) |
|
|
|
pullMessage session = do |
|
|
|
pullMessage chans = do |
|
|
|
c <- getMessageChan session |
|
|
|
c <- getMessageChan chans |
|
|
|
atomically $ readTChan c |
|
|
|
atomically $ readTChan c |
|
|
|
|
|
|
|
|
|
|
|
-- | Read an element from the inbound stanza channel, acquiring a copy of the |
|
|
|
-- | Read an element from the inbound stanza channel, acquiring a copy of the |
|
|
|
-- channel as necessary. |
|
|
|
-- channel as necessary. |
|
|
|
pullPresence :: Session -> IO (Either PresenceError Presence) |
|
|
|
pullPresence :: Chans -> IO (Either PresenceError Presence) |
|
|
|
pullPresence session = do |
|
|
|
pullPresence chans = do |
|
|
|
c <- getPresenceChan session |
|
|
|
c <- getPresenceChan chans |
|
|
|
atomically $ readTChan c |
|
|
|
atomically $ readTChan c |
|
|
|
|
|
|
|
|
|
|
|
-- | Send a stanza to the server. |
|
|
|
-- | Send a stanza to the server. |
|
|
|
sendStanza :: Stanza -> Session -> IO () |
|
|
|
sendStanza :: Stanza -> Chans -> IO () |
|
|
|
sendStanza a session = atomically $ writeTChan (outCh session) a |
|
|
|
sendStanza a chans = atomically $ writeTChan (outCh chans) a |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- | Create a forked session object |
|
|
|
-- | Create a forked chans object |
|
|
|
forkSession :: Session -> IO Session |
|
|
|
forkChans :: Chans -> IO Chans |
|
|
|
forkSession session = do |
|
|
|
forkChans chans = do |
|
|
|
mCH' <- newIORef Nothing |
|
|
|
mCH' <- newIORef Nothing |
|
|
|
pCH' <- newIORef Nothing |
|
|
|
pCH' <- newIORef Nothing |
|
|
|
return $ session {messagesRef = mCH', presenceRef = pCH'} |
|
|
|
return $ chans {messagesRef = mCH', presenceRef = pCH'} |
|
|
|
|
|
|
|
|
|
|
|
-- | Pulls a message and returns it if the given predicate returns @True@. |
|
|
|
-- | Pulls a message and returns it if the given predicate returns @True@. |
|
|
|
filterMessages :: (MessageError -> Bool) |
|
|
|
filterMessages :: (MessageError -> Bool) |
|
|
|
-> (Message -> Bool) |
|
|
|
-> (Message -> Bool) |
|
|
|
-> Session -> IO (Either MessageError Message) |
|
|
|
-> Chans -> IO (Either MessageError Message) |
|
|
|
filterMessages f g session = do |
|
|
|
filterMessages f g chans = do |
|
|
|
s <- pullMessage session |
|
|
|
s <- pullMessage chans |
|
|
|
case s of |
|
|
|
case s of |
|
|
|
Left e | f e -> return $ Left e |
|
|
|
Left e | f e -> return $ Left e |
|
|
|
| otherwise -> filterMessages f g session |
|
|
|
| otherwise -> filterMessages f g chans |
|
|
|
Right m | g m -> return $ Right m |
|
|
|
Right m | g m -> return $ Right m |
|
|
|
| otherwise -> filterMessages f g session |
|
|
|
| otherwise -> filterMessages f g chans |
|
|
|
|
|
|
|
|
|
|
|
-- | Pulls a (non-error) message and returns it if the given predicate returns |
|
|
|
-- | Pulls a (non-error) message and returns it if the given predicate returns |
|
|
|
-- @True@. |
|
|
|
-- @True@. |
|
|
|
waitForMessage :: (Message -> Bool) -> Session -> IO Message |
|
|
|
waitForMessage :: (Message -> Bool) -> Chans -> IO Message |
|
|
|
waitForMessage f session = do |
|
|
|
waitForMessage f chans = do |
|
|
|
s <- pullMessage session |
|
|
|
s <- pullMessage chans |
|
|
|
case s of |
|
|
|
case s of |
|
|
|
Left _ -> waitForMessage f session |
|
|
|
Left _ -> waitForMessage f chans |
|
|
|
Right m | f m -> return m |
|
|
|
Right m | f m -> return m |
|
|
|
| otherwise -> waitForMessage f session |
|
|
|
| otherwise -> waitForMessage f chans |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- | Pulls an error message and returns it if the given predicate returns @True@. |
|
|
|
-- | Pulls an error message and returns it if the given predicate returns @True@. |
|
|
|
waitForMessageError :: (MessageError -> Bool) -> Session -> IO MessageError |
|
|
|
waitForMessageError :: (MessageError -> Bool) -> Chans -> IO MessageError |
|
|
|
waitForMessageError f session = do |
|
|
|
waitForMessageError f chans = do |
|
|
|
s <- pullMessage session |
|
|
|
s <- pullMessage chans |
|
|
|
case s of |
|
|
|
case s of |
|
|
|
Right _ -> waitForMessageError f session |
|
|
|
Right _ -> waitForMessageError f chans |
|
|
|
Left m | f m -> return m |
|
|
|
Left m | f m -> return m |
|
|
|
| otherwise -> waitForMessageError f session |
|
|
|
| otherwise -> waitForMessageError f chans |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- | Pulls a (non-error) presence and returns it if the given predicate returns |
|
|
|
-- | Pulls a (non-error) presence and returns it if the given predicate returns |
|
|
|
-- @True@. |
|
|
|
-- @True@. |
|
|
|
waitForPresence :: (Presence -> Bool) -> Session -> IO Presence |
|
|
|
waitForPresence :: (Presence -> Bool) -> Chans -> IO Presence |
|
|
|
waitForPresence f session = do |
|
|
|
waitForPresence f chans = do |
|
|
|
s <- pullPresence session |
|
|
|
s <- pullPresence chans |
|
|
|
case s of |
|
|
|
case s of |
|
|
|
Left _ -> waitForPresence f session |
|
|
|
Left _ -> waitForPresence f chans |
|
|
|
Right m | f m -> return m |
|
|
|
Right m | f m -> return m |
|
|
|
| otherwise -> waitForPresence f session |
|
|
|
| otherwise -> waitForPresence f chans |
|
|
|
|
|
|
|
|
|
|
|
-- TODO: Wait for presence error? |
|
|
|
-- TODO: Wait for presence error? |
|
|
|
|
|
|
|
|
|
|
|
@ -194,12 +194,12 @@ withConnection a session = do |
|
|
|
] |
|
|
|
] |
|
|
|
|
|
|
|
|
|
|
|
-- | Send a presence stanza. |
|
|
|
-- | Send a presence stanza. |
|
|
|
sendPresence :: Presence -> Session -> IO () |
|
|
|
sendPresence :: Presence -> Chans -> IO () |
|
|
|
sendPresence p session = sendStanza (PresenceS p) session |
|
|
|
sendPresence p chans = sendStanza (PresenceS p) chans |
|
|
|
|
|
|
|
|
|
|
|
-- | Send a message stanza. |
|
|
|
-- | Send a message stanza. |
|
|
|
sendMessage :: Message -> Session -> IO () |
|
|
|
sendMessage :: Message -> Chans -> IO () |
|
|
|
sendMessage m session = sendStanza (MessageS m) session |
|
|
|
sendMessage m chans = sendStanza (MessageS m) chans |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- | Executes a function to update the event handlers. |
|
|
|
-- | Executes a function to update the event handlers. |
|
|
|
|