Browse Source
added IQ answering mechanism improved error reporting un unpickling failures (will show offending element) general cleanupsmaster
7 changed files with 167 additions and 48 deletions
@ -0,0 +1,121 @@
@@ -0,0 +1,121 @@
|
||||
{-# LANGUAGE PackageImports, OverloadedStrings #-} |
||||
module Example where |
||||
|
||||
import Network.XMPP |
||||
import Control.Concurrent |
||||
import Control.Concurrent.STM |
||||
import Control.Monad |
||||
import Control.Monad.IO.Class |
||||
|
||||
import Data.Maybe |
||||
import Data.Text (Text) |
||||
import qualified Data.Text as Text |
||||
import Data.XML.Pickle |
||||
import Data.XML.Types |
||||
|
||||
import Network.XMPP.Pickle |
||||
|
||||
import System.Environment |
||||
|
||||
testUser1 :: JID |
||||
testUser1 = read "testuser1@species64739.dyndns.org/bot1" |
||||
|
||||
testUser2 :: JID |
||||
testUser2 = read "testuser2@species64739.dyndns.org/bot2" |
||||
|
||||
superviser :: JID |
||||
superviser = read "uart14@species64739.dyndns.org" |
||||
|
||||
|
||||
attXmpp :: STM a -> XMPPThread a |
||||
attXmpp = liftIO . atomically |
||||
|
||||
testNS :: Text |
||||
testNS = "xmpp:library:test" |
||||
|
||||
data Payload = Payload Int Bool Text deriving (Eq, Show) |
||||
|
||||
payloadP = xpWrap (\((counter,flag) , message) -> Payload counter flag message) |
||||
(\(Payload counter flag message) ->((counter,flag) , message)) $ |
||||
xpElem (Name "request" (Just testNS) Nothing) |
||||
(xpPair |
||||
(xpAttr "counter" xpPrim) |
||||
(xpAttr "flag" xpPrim) |
||||
) |
||||
(xpElemNodes (Name "message" (Just testNS) Nothing) |
||||
(xpContent xpId)) |
||||
|
||||
invertPayload (Payload count flag message) = Payload (count + 1) (not flag) (Text.reverse message) |
||||
|
||||
iqResponder = do |
||||
(free, chan) <- listenIQChan Get testNS |
||||
unless free $ liftIO $ putStrLn "Channel was already taken" |
||||
>> error "hanging up" |
||||
forever $ do |
||||
next@(iq,_) <- liftIO . atomically $ readTChan chan |
||||
let payload = unpickleElem payloadP $ iqBody iq |
||||
let answerPayload = invertPayload payload |
||||
let answerBody = pickleElem payloadP answerPayload |
||||
answerIQ next answerBody |
||||
|
||||
autoAccept :: XMPPThread () |
||||
autoAccept = forever $ do |
||||
st <- pullPresence |
||||
case st of |
||||
Presence from _ idq (Just Subscribe) _ _ _ _ -> |
||||
sendS . SPresence $ |
||||
Presence Nothing from idq (Just Subscribed) Nothing Nothing Nothing [] |
||||
_ -> return () |
||||
|
||||
sendUser txt = sendS . SMessage $ Message Nothing superviser Nothing Nothing Nothing |
||||
(Just (Text.pack txt)) Nothing [] |
||||
|
||||
|
||||
expect debug x y | x == y = debug "Ok." |
||||
| otherwise = do |
||||
let failMSG = "failed" ++ show x ++ " /= " ++ show y |
||||
debug failMSG |
||||
sendUser failMSG |
||||
|
||||
|
||||
|
||||
runMain :: (String -> STM ()) -> Int -> IO () |
||||
runMain debug number = do |
||||
let (we, them, active) = case number of |
||||
1 -> (testUser1, testUser2,True) |
||||
2 -> (testUser2, testUser1,False) |
||||
_ -> error "Need either 1 or 2" |
||||
sessionConnect "localhost" |
||||
"species64739.dyndns.org" |
||||
(fromJust $ node we) (resource we) $ do |
||||
let debug' = liftIO . atomically . debug . |
||||
(("Thread " ++ show number ++ ":") ++) |
||||
singleThreaded $ xmppSASL "pwd" |
||||
xmppThreadedBind (resource we) |
||||
singleThreaded $ xmppSession |
||||
sendS . SPresence $ Presence Nothing Nothing Nothing Nothing (Just Available) Nothing Nothing [] |
||||
forkXMPP autoAccept |
||||
forkXMPP iqResponder |
||||
-- sendS . SPresence $ Presence Nothing (Just them) Nothing (Just Subscribe) Nothing Nothing Nothing [] |
||||
let delay = if active then 1000000 else 5000000 |
||||
when active . void . forkXMPP . void . forM [1..10] $ \count -> do |
||||
let message = Text.pack . show $ node we |
||||
let payload = Payload count (even count) (Text.pack $ show count) |
||||
let body = pickleElem payloadP payload |
||||
answer <- sendIQ' (Just them) Get body |
||||
let answerPayload = unpickleElem payloadP (iqBody answer) |
||||
expect debug' (invertPayload payload) answerPayload |
||||
liftIO $ threadDelay delay |
||||
sendUser "All tests done" |
||||
liftIO . forever $ threadDelay 10000000 |
||||
return () |
||||
return () |
||||
|
||||
|
||||
main = do |
||||
out <- newTChanIO |
||||
forkIO . forever $ atomically (readTChan out) >>= putStrLn |
||||
let debugOut = writeTChan out |
||||
forkIO $ runMain debugOut 1 |
||||
runMain debugOut 2 |
||||
|
||||
Loading…
Reference in new issue