diff options
author | Joe Crayne <joe@jerkface.net> | 2018-11-05 05:54:00 -0500 |
---|---|---|
committer | Joe Crayne <joe@jerkface.net> | 2018-11-05 16:28:25 -0500 |
commit | dd9dad21a830e932ab873510c41ce1a098bc78b8 (patch) | |
tree | 9c8cd38ac353509c1330eecf38101a5ee10dead0 /Presence | |
parent | 361209738d454309bf93ed49d9343ea264b21fb8 (diff) |
Respond to XMPP discovery queries.
Diffstat (limited to 'Presence')
-rw-r--r-- | Presence/Stanza/Parse.hs | 8 | ||||
-rw-r--r-- | Presence/Stanza/Types.hs | 4 | ||||
-rw-r--r-- | Presence/XMPPServer.hs | 76 |
3 files changed, 78 insertions, 10 deletions
diff --git a/Presence/Stanza/Parse.hs b/Presence/Stanza/Parse.hs index e2a9efdd..af95530f 100644 --- a/Presence/Stanza/Parse.hs +++ b/Presence/Stanza/Parse.hs | |||
@@ -46,6 +46,10 @@ grokStanzaIQGet stanza = do | |||
46 | case tagName tag of | 46 | case tagName tag of |
47 | "{urn:xmpp:ping}ping" -> return Ping | 47 | "{urn:xmpp:ping}ping" -> return Ping |
48 | "{jabber:iq:roster}query" -> return RequestRoster | 48 | "{jabber:iq:roster}query" -> return RequestRoster |
49 | "{http://jabber.org/protocol/disco#items}query" | ||
50 | -> return RequestItems | ||
51 | "{http://jabber.org/protocol/disco#info}query" | ||
52 | -> return RequestInfo | ||
49 | name -> return $ UnrecognizedQuery name | 53 | name -> return $ UnrecognizedQuery name |
50 | 54 | ||
51 | grokStanzaIQResult :: XML.Event -> NestingXML o IO (Maybe StanzaType) | 55 | grokStanzaIQResult :: XML.Event -> NestingXML o IO (Maybe StanzaType) |
@@ -55,6 +59,10 @@ grokStanzaIQResult stanza = do | |||
55 | case tagName tag of | 59 | case tagName tag of |
56 | "{jabber:iq:version}query" | nameNamespace (tagName stanza)==Just "jabber:client" | 60 | "{jabber:iq:version}query" | nameNamespace (tagName stanza)==Just "jabber:client" |
57 | -> parseClientVersion | 61 | -> parseClientVersion |
62 | "{http://jabber.org/protocol/disco#items}query" | ||
63 | -> return $ Just Items | ||
64 | "{http://jabber.org/protocol/disco#info}query" | ||
65 | -> return $ Just Info | ||
58 | _ -> return Nothing | 66 | _ -> return Nothing |
59 | 67 | ||
60 | grokStanzaIQSet :: XML.Event -> NestingXML o IO (Maybe StanzaType) | 68 | grokStanzaIQSet :: XML.Event -> NestingXML o IO (Maybe StanzaType) |
diff --git a/Presence/Stanza/Types.hs b/Presence/Stanza/Types.hs index 6b402f4d..cbb156a0 100644 --- a/Presence/Stanza/Types.hs +++ b/Presence/Stanza/Types.hs | |||
@@ -34,6 +34,10 @@ data StanzaType | |||
34 | | Pong | 34 | | Pong |
35 | | RequestResource (Maybe Text) (Maybe Text) -- ^ Client's name for this host followed by client's requested resource id. | 35 | | RequestResource (Maybe Text) (Maybe Text) -- ^ Client's name for this host followed by client's requested resource id. |
36 | | SetResource | 36 | | SetResource |
37 | | RequestItems | ||
38 | | Items | ||
39 | | RequestInfo | ||
40 | | Info | ||
37 | | SessionRequest | 41 | | SessionRequest |
38 | | UnrecognizedQuery Name | 42 | | UnrecognizedQuery Name |
39 | | RequestRoster | 43 | | RequestRoster |
diff --git a/Presence/XMPPServer.hs b/Presence/XMPPServer.hs index f9938570..dcbc9bf5 100644 --- a/Presence/XMPPServer.hs +++ b/Presence/XMPPServer.hs | |||
@@ -1,9 +1,10 @@ | |||
1 | {-# LANGUAGE CPP #-} | 1 | {-# LANGUAGE CPP #-} |
2 | {-# LANGUAGE OverloadedStrings #-} | 2 | {-# LANGUAGE DoAndIfThenElse #-} |
3 | {-# LANGUAGE RankNTypes #-} | ||
4 | {-# LANGUAGE FlexibleInstances #-} -- instance for TChan Event | ||
5 | {-# LANGUAGE DoAndIfThenElse #-} | ||
6 | {-# LANGUAGE ExistentialQuantification #-} | 3 | {-# LANGUAGE ExistentialQuantification #-} |
4 | {-# LANGUAGE FlexibleInstances #-} | ||
5 | {-# LANGUAGE OverloadedStrings #-} | ||
6 | {-# LANGUAGE RankNTypes #-} | ||
7 | {-# LANGUAGE TupleSections #-} | ||
7 | module XMPPServer | 8 | module XMPPServer |
8 | ( xmppServer | 9 | ( xmppServer |
9 | , forkXmpp | 10 | , forkXmpp |
@@ -92,7 +93,7 @@ import Data.XML.Types as XML | |||
92 | import Data.Maybe | 93 | import Data.Maybe |
93 | import Data.Monoid ( (<>) ) | 94 | import Data.Monoid ( (<>) ) |
94 | import Data.Text (Text) | 95 | import Data.Text (Text) |
95 | import qualified Data.Text as Text (pack,unpack,intercalate,drop) | 96 | import qualified Data.Text as Text (pack,unpack,intercalate,drop,toLower) |
96 | import qualified Data.Map as Map | 97 | import qualified Data.Map as Map |
97 | import Data.Set (Set, (\\) ) | 98 | import Data.Set (Set, (\\) ) |
98 | import qualified Data.Set as Set | 99 | import qualified Data.Set as Set |
@@ -626,6 +627,40 @@ makePing namespace mid to from = | |||
626 | , EventEndElement "{urn:xmpp:ping}ping" | 627 | , EventEndElement "{urn:xmpp:ping}ping" |
627 | , EventEndElement $ mkname namespace "iq"] | 628 | , EventEndElement $ mkname namespace "iq"] |
628 | 629 | ||
630 | makeInfo :: Maybe Text -> Text -> Maybe Text -> [Event] | ||
631 | makeInfo mid from mto = concat | ||
632 | [ [ EventBeginElement "{jabber:client}iq" | ||
633 | $ consid mid $ maybe id (\to -> (("to", [ContentText to]) :)) mto | ||
634 | [("from", [ContentText from]) | ||
635 | ,("type", [ContentText "result"])] | ||
636 | , EventBeginElement "{http://jabber.org/protocol/disco#info}query" [] | ||
637 | , EventBeginElement "{http://jabber.org/protocol/disco#info}identity" | ||
638 | [("category",[ContentText "server"]) | ||
639 | ,("type",[ContentText "im"])] | ||
640 | , EventEndElement "{http://jabber.org/protocol/disco#info}identity" | ||
641 | , EventBeginElement "{http://jabber.org/protocol/disco#info}feature" | ||
642 | [("var",[ContentText "http://jabber.org/protocol/disco#info"])] | ||
643 | , EventEndElement "{http://jabber.org/protocol/disco#info}feature" ] | ||
644 | , [] -- todo | ||
645 | , [ EventEndElement "{http://jabber.org/protocol/disco#info}query" | ||
646 | , EventEndElement "{jabber:client}iq" ] | ||
647 | ] | ||
648 | |||
649 | makeItemList :: Maybe Text -> [(Text,Maybe Text)] -> Text -> Maybe Text -> [Event] | ||
650 | makeItemList mid items from mto = concat | ||
651 | [ [ EventBeginElement "{jabber:client}iq" | ||
652 | $ consid mid $ maybe id (\to -> (("to", [ContentText to]) :)) mto | ||
653 | [("from", [ContentText from]) | ||
654 | ,("type", [ContentText "result"])] | ||
655 | , EventBeginElement "{http://jabber.org/protocol/disco#items}query" []] | ||
656 | , do (jid,name) <- items | ||
657 | [ EventBeginElement "{http://jabber.org/protocol/disco#items}item" | ||
658 | $ maybe id (\n -> (("name", [ContentText n]) :)) name [ ("jid", [ContentText jid]) ], | ||
659 | EventEndElement "{http://jabber.org/protocol/disco#items}item" ] | ||
660 | , [ EventEndElement "{http://jabber.org/protocol/disco#items}query" | ||
661 | , EventEndElement "{jabber:client}iq" ] | ||
662 | ] | ||
663 | |||
629 | iq_bind_reply :: Maybe Text -> Text -> [XML.Event] | 664 | iq_bind_reply :: Maybe Text -> Text -> [XML.Event] |
630 | iq_bind_reply mid jid = | 665 | iq_bind_reply mid jid = |
631 | [ EventBeginElement "{jabber:client}iq" (consid mid [("type",[ContentText "result"])]) | 666 | [ EventBeginElement "{jabber:client}iq" (consid mid [("type",[ContentText "result"])]) |
@@ -908,7 +943,7 @@ forkConnection sv xmpp saddr cdta pingflag src snk stanzas pp_mvar = do | |||
908 | -- kwlog $ "queuing: "++show (isempty, stanzaId stanza) | 943 | -- kwlog $ "queuing: "++show (isempty, stanzaId stanza) |
909 | notping $ do | 944 | notping $ do |
910 | dup <- cloneStanza stanza | 945 | dup <- cloneStanza stanza |
911 | let typ = Strict8.pack $ c ++ "<-"++(concat . take 1 . words $ show (stanzaType dup))++" " | 946 | let typ = Strict8.pack $ c ++ "<-" ++ stanzaTypeString dup ++ " " |
912 | c = case auxAddr of | 947 | c = case auxAddr of |
913 | Right _ -> "C" | 948 | Right _ -> "C" |
914 | Left _ -> "P" | 949 | Left _ -> "P" |
@@ -1209,8 +1244,9 @@ monitor sv params xmpp = do | |||
1209 | -} | 1244 | -} |
1210 | dup <- cloneStanza stanza | 1245 | dup <- cloneStanza stanza |
1211 | 1246 | ||
1212 | forkIO $ do applyStanza sv quitVar xmpp stanza | 1247 | t <- forkIO $ do applyStanza sv quitVar xmpp stanza |
1213 | forwardStanza quitVar xmpp stanza | 1248 | forwardStanza quitVar xmpp stanza |
1249 | labelThread t $ "process." ++ stanzaTypeString stanza | ||
1214 | 1250 | ||
1215 | -- We need to clone in the case the stanza is passed on as for Message. | 1251 | -- We need to clone in the case the stanza is passed on as for Message. |
1216 | wantStanzas <- getVerbose XJabber | 1252 | wantStanzas <- getVerbose XJabber |
@@ -1221,7 +1257,7 @@ monitor sv params xmpp = do | |||
1221 | | (verbosity>=2) = f | 1257 | | (verbosity>=2) = f |
1222 | | otherwise = return () | 1258 | | otherwise = return () |
1223 | notping $ do | 1259 | notping $ do |
1224 | let typ = Strict8.pack $ c ++ "->"++(concat . take 1 . words $ show (stanzaType stanza))++" " | 1260 | let typ = Strict8.pack $ c ++ "->" ++ stanzaTypeString stanza ++ " " |
1225 | c = case stanzaOrigin stanza of | 1261 | c = case stanzaOrigin stanza of |
1226 | LocalPeer -> "*" | 1262 | LocalPeer -> "*" |
1227 | ClientOrigin {} -> "C" | 1263 | ClientOrigin {} -> "C" |
@@ -1238,6 +1274,9 @@ monitor sv params xmpp = do | |||
1238 | where | 1274 | where |
1239 | _ = str :: String | 1275 | _ = str :: String |
1240 | 1276 | ||
1277 | stanzaTypeString :: StanzaWrap a -> String | ||
1278 | stanzaTypeString stanza = concat . take 1 . words $ show (stanzaType stanza) | ||
1279 | |||
1241 | applyStanza :: Server PeerAddress ConnectionData releaseKey Event | 1280 | applyStanza :: Server PeerAddress ConnectionData releaseKey Event |
1242 | -> TMVar () | 1281 | -> TMVar () |
1243 | -> XMPPServerParameters | 1282 | -> XMPPServerParameters |
@@ -1298,6 +1337,23 @@ applyStanza sv quitVar xmpp stanza = case stanzaOrigin stanza of | |||
1298 | xmppClientInformSubscription xmpp fail k stanza | 1337 | xmppClientInformSubscription xmpp fail k stanza |
1299 | NotifyClientVersion name version -> do | 1338 | NotifyClientVersion name version -> do |
1300 | enableClientHacks name version replyto | 1339 | enableClientHacks name version replyto |
1340 | RequestInfo -> do | ||
1341 | -- TODO ItemNotFound | ||
1342 | me <- xmppTellMyNameToClient xmpp k | ||
1343 | if fmap Text.toLower (stanzaTo stanza) == Just (Text.toLower me) | ||
1344 | then | ||
1345 | let reply = makeInfo (stanzaId stanza) me (stanzaFrom stanza) | ||
1346 | in sendReply quitVar Info reply replyto | ||
1347 | else | ||
1348 | let query = "{http://jabber.org/protocol/disco#info}info" | ||
1349 | reply = iq_service_unavailable (stanzaId stanza) me query | ||
1350 | in sendReply quitVar (Error ServiceUnavailable (head reply)) reply replyto | ||
1351 | RequestItems -> do | ||
1352 | -- let query = "{http://jabber.org/protocol/disco#items}query" | ||
1353 | me <- xmppTellMyNameToClient xmpp k | ||
1354 | let items = [] | ||
1355 | reply = makeItemList (stanzaId stanza) items me (stanzaFrom stanza) | ||
1356 | sendReply quitVar Items reply replyto | ||
1301 | UnrecognizedQuery query -> do | 1357 | UnrecognizedQuery query -> do |
1302 | me <- xmppTellMyNameToClient xmpp k | 1358 | me <- xmppTellMyNameToClient xmpp k |
1303 | let reply = iq_service_unavailable (stanzaId stanza) me query | 1359 | let reply = iq_service_unavailable (stanzaId stanza) me query |