summaryrefslogtreecommitdiff
path: root/Presence
diff options
context:
space:
mode:
Diffstat (limited to 'Presence')
-rw-r--r--Presence/ControlMaybe.hs4
-rw-r--r--Presence/XMPP.hs67
-rw-r--r--Presence/XMPPTypes.hs1
-rw-r--r--Presence/main.hs4
4 files changed, 65 insertions, 11 deletions
diff --git a/Presence/ControlMaybe.hs b/Presence/ControlMaybe.hs
index 37f6f93c..69a38f71 100644
--- a/Presence/ControlMaybe.hs
+++ b/Presence/ControlMaybe.hs
@@ -15,5 +15,9 @@ whenJust acn f = do
15catchIO_ :: IO a -> IO a -> IO a 15catchIO_ :: IO a -> IO a -> IO a
16catchIO_ a h = Exception.catch a (\(_ :: IOException) -> h) 16catchIO_ a h = Exception.catch a (\(_ :: IOException) -> h)
17 17
18catchIO :: IO a -> (IOException -> IO a) -> IO a
19catchIO body handler = Exception.catch body handler
20
18handleIO_ = flip catchIO_ 21handleIO_ = flip catchIO_
22handleIO = flip catchIO
19 23
diff --git a/Presence/XMPP.hs b/Presence/XMPP.hs
index 7b01711e..1520839e 100644
--- a/Presence/XMPP.hs
+++ b/Presence/XMPP.hs
@@ -62,6 +62,7 @@ import Control.Exception
62 , finally 62 , finally
63 , bracketOnError ) 63 , bracketOnError )
64import GHC.IO.Exception (IOException(..)) 64import GHC.IO.Exception (IOException(..))
65import System.IO.Error (isDoesNotExistError)
65import Control.Monad.IO.Class 66import Control.Monad.IO.Class
66import Control.Monad.Trans.Class 67import Control.Monad.Trans.Class
67import Control.Monad.Trans.Maybe 68import Control.Monad.Trans.Maybe
@@ -93,7 +94,11 @@ import GHC.Conc
93 , ThreadId 94 , ThreadId
94 ) 95 )
95 96
96data Commands = Send [XML.Event] | QuitThread 97data Commands =
98 Send [XML.Event]
99 | BoundToResource
100 | InterestedInRoster
101 | QuitThread
97 deriving Prelude.Show 102 deriving Prelude.Show
98 103
99getNamesForPeer :: Peer -> IO [ByteString] 104getNamesForPeer :: Peer -> IO [ByteString]
@@ -260,7 +265,9 @@ handleIQSetBind session cmdChan stanza_id = do
260 L.putStrLn $ "iq-set-bind-resource " <++> rsc 265 L.putStrLn $ "iq-set-bind-resource " <++> rsc
261 setResource session rsc 266 setResource session rsc
262 jid <- getJID session 267 jid <- getJID session
263 atomically $ writeTChan cmdChan (Send $ iq_bind_reply stanza_id (toStrict $ L.decodeUtf8 $ L.show jid) ) 268 atomically $ do
269 writeTChan cmdChan (Send $ iq_bind_reply stanza_id (toStrict $ L.decodeUtf8 $ L.show jid) )
270 writeTChan cmdChan BoundToResource
264 forCachedPresence session $ \presence -> do 271 forCachedPresence session $ \presence -> do
265 xs <- xmlifyPresenceForClient presence 272 xs <- xmlifyPresenceForClient presence
266 atomically . writeTChan cmdChan . Send $ xs 273 atomically . writeTChan cmdChan . Send $ xs
@@ -410,7 +417,9 @@ handleIQGet session cmdChan tag = do
410 -- ,(Name {nameLocalName = "type", nameNamespace = Nothing, namePrefix = Nothing}, 417 -- ,(Name {nameLocalName = "type", nameNamespace = Nothing, namePrefix = Nothing},
411 -- [ContentText "get"])] 418 -- [ContentText "get"])]
412 roster <- getRoster session stanza_id 419 roster <- getRoster session stanza_id
413 atomically . writeTChan cmdChan . Send $ roster 420 atomically $ do
421 writeTChan cmdChan InterestedInRoster
422 writeTChan cmdChan . Send $ roster
414 req -> unhandledGet req 423 req -> unhandledGet req
415 424
416 425
@@ -436,15 +445,17 @@ fromClient session cmdChan = doNestingXML $ do
436 whenJust nextElement $ \stanza -> do 445 whenJust nextElement $ \stanza -> do
437 stanza_lvl <- nesting 446 stanza_lvl <- nesting
438 447
448 liftIO . putStrLn $ "stanza: "++show stanza
449
439 let unhandledStanza = do 450 let unhandledStanza = do
440 xs <- gatherElement stanza Seq.empty 451 xs <- gatherElement stanza Seq.empty
441 prettyPrint "unhandled-C: " (toList xs) 452 prettyPrint "unhandled-C: " (toList xs)
442 case () of 453 case () of
443 _ | stanza `isIQOf` iqTypeSet -> handleIQSet session cmdChan stanza 454 _ | stanza `isIQOf` iqTypeSet -> handleIQSet session cmdChan stanza
444 _ | stanza `isIQOf` iqTypeGet -> handleIQGet session cmdChan stanza 455 _ | stanza `isIQOf` iqTypeGet -> handleIQGet session cmdChan stanza
445 _ | stanza `isPresenceOf` presenceTypeSubscribe 456 _ | stanza `isClientPresenceOf` presenceTypeSubscribe
446 -> clientRequestsSubscription session stanza 457 -> clientRequestsSubscription session cmdChan stanza
447 _ | stanza `isPresenceOf` presenceTypeSubscribed 458 _ | stanza `isClientPresenceOf` presenceTypeSubscribed
448 -> clientApprovesSubscription session stanza 459 -> clientApprovesSubscription session stanza
449 _ | otherwise -> unhandledStanza 460 _ | otherwise -> unhandledStanza
450 461
@@ -468,6 +479,7 @@ toClient pchan cmdChan = fix $ \loop -> do
468 case event of 479 case event of
469 Right QuitThread -> return () 480 Right QuitThread -> return ()
470 Right (Send xs) -> send xs >> loop 481 Right (Send xs) -> send xs >> loop
482 Right cmd -> liftIO (putStrLn $ "unhandled event: "++show cmd) >> loop
471 Left presence -> do 483 Left presence -> do
472 xs <- liftIO $ xmlifyPresenceForClient presence 484 xs <- liftIO $ xmlifyPresenceForClient presence
473 send xs 485 send xs
@@ -610,6 +622,12 @@ isPresenceOf (EventBeginElement name attrs) testType
610 = True 622 = True
611isPresenceOf _ _ = False 623isPresenceOf _ _ = False
612 624
625isClientPresenceOf (EventBeginElement name attrs) testType
626 | name=="{jabber:client}presence"
627 && matchAttribMaybe "type" testType attrs
628 = True
629isClientPresenceOf _ _ = False
630
613handlePresenceProbe session stanza = do 631handlePresenceProbe session stanza = do
614 withJust (lookupAttrib "to" (tagAttrs stanza)) $ \to -> do 632 withJust (lookupAttrib "to" (tagAttrs stanza)) $ \to -> do
615 -- withJust (lookupAttrib "from" (tagAttrs stanza)) $ \from -> do 633 -- withJust (lookupAttrib "from" (tagAttrs stanza)) $ \from -> do
@@ -638,7 +656,22 @@ subscribeToPresence subscribers peer_jid user = do
638 656
639bare (JID n host _) = JID n host Nothing 657bare (JID n host _) = JID n host Nothing
640 658
641clientRequestsSubscription session stanza = do 659presenceErrorRemoteNotFound iqid from to = return
660 [ EventBeginElement "{stream:client}presence"
661 ( case iqid of { Nothing -> id; Just iqid -> ( attr "id" iqid :) }
662 $ [ attr "from" to
663 , attr "type" "error"
664 ] )
665 , EventBeginElement "{stream:client}error"
666 [ attr "type" "modify"]
667 , EventBeginElement "{urn:ietf:params:xml:ns:xmpp-stanzas}remote-server-not-found"
668 []
669 , EventEndElement "{urn:ietf:params:xml:ns:xmpp-stanzas}remote-server-not-found"
670 , EventEndElement "{stream:client}error"
671 , EventEndElement "{stream:client}presence"
672 ]
673
674clientRequestsSubscription session cmdChan stanza = do
642 -- make bare jid 675 -- make bare jid
643 -- check local server and obey rules 3.1.3 of rfc 6121 676 -- check local server and obey rules 3.1.3 of rfc 6121
644 -- or forward to remote peer 677 -- or forward to remote peer
@@ -646,10 +679,22 @@ clientRequestsSubscription session stanza = do
646 -- if not bailed, 679 -- if not bailed,
647 -- add to solicited 680 -- add to solicited
648 -- do roster push with subscription=none ask=subscribe 681 -- do roster push with subscription=none ask=subscribe
649 liftIO $ putStrLn $ "CLIENT PRESENCE SUBSCRIBE " ++ show stanza 682 liftIO $ do
650 -- add solicited 683 putStrLn $ "CLIENT PRESENCE SUBSCRIBE " ++ show stanza
651 -- notify other clients 684 withJust (lookupAttrib "to" (tagAttrs stanza)) $ \to_str -> do
652 -- notify peer 685 let from = lookupAttrib "from" (tagAttrs stanza)
686 iqid = lookupAttrib "id" (tagAttrs stanza)
687 let handleError e | isDoesNotExistError e = do
688 putStrLn $ "remote-server-not-found"
689 r <- presenceErrorRemoteNotFound iqid from to_str
690 atomically $ writeTChan cmdChan (Send r)
691 handleError e = do
692 putStrLn $ "ERROR: "++ show e
693 handleIO handleError $ do
694 to_jid <- parseHostNameJID (L.fromChunks [S.encodeUtf8 to_str])
695 addSolicited session (L.fromChunks [S.encodeUtf8 to_str]) -- jid
696 putStrLn $ "added to solicited: " ++ show to_jid
697 -- TODO: create roster item and push to interested clients
653 return () 698 return ()
654 699
655peerRequestsSubsription session stanza = do 700peerRequestsSubsription session stanza = do
diff --git a/Presence/XMPPTypes.hs b/Presence/XMPPTypes.hs
index 747ceb0e..301f19fd 100644
--- a/Presence/XMPPTypes.hs
+++ b/Presence/XMPPTypes.hs
@@ -44,6 +44,7 @@ class JabberClientSession session where
44 getMyOthers :: session -> IO [ByteString] 44 getMyOthers :: session -> IO [ByteString]
45 getMyPending :: session -> IO [ByteString] 45 getMyPending :: session -> IO [ByteString]
46 getMySolicited :: session -> IO [ByteString] 46 getMySolicited :: session -> IO [ByteString]
47 addSolicited :: session -> ByteString -> IO ()
47 48
48class JabberPeerSession session where 49class JabberPeerSession session where
49 data XMPPPeerClass session 50 data XMPPPeerClass session
diff --git a/Presence/main.hs b/Presence/main.hs
index 0eae8677..bf4809a8 100644
--- a/Presence/main.hs
+++ b/Presence/main.hs
@@ -168,6 +168,10 @@ instance JabberClientSession ClientSession where
168 L.putStrLn $ "cached presence: " <++> bshow p 168 L.putStrLn $ "cached presence: " <++> bshow p
169 action p 169 action p
170 170
171 addSolicited s jid = do
172 user <- readIORef (unix_uid s) >>= getJabberUserForId
173 ConfigFiles.addSolicited user jid -- (L.show jid)
174
171 getMyBuddies s = do 175 getMyBuddies s = do
172 user <- readIORef (unix_uid s) >>= getJabberUserForId 176 user <- readIORef (unix_uid s) >>= getJabberUserForId
173 ConfigFiles.getBuddies user 177 ConfigFiles.getBuddies user