summaryrefslogtreecommitdiff
path: root/Presence/XMPPServer.hs
diff options
context:
space:
mode:
Diffstat (limited to 'Presence/XMPPServer.hs')
-rw-r--r--Presence/XMPPServer.hs67
1 files changed, 50 insertions, 17 deletions
diff --git a/Presence/XMPPServer.hs b/Presence/XMPPServer.hs
index 591acad6..05b12b73 100644
--- a/Presence/XMPPServer.hs
+++ b/Presence/XMPPServer.hs
@@ -1,6 +1,7 @@
1{-# LANGUAGE OverloadedStrings #-} 1{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE ScopedTypeVariables #-} 2{-# LANGUAGE ScopedTypeVariables #-}
3{-# LANGUAGE ViewPatterns #-} 3{-# LANGUAGE ViewPatterns #-}
4{-# LANGUAGE TupleSections #-}
4module XMPPServer ( listenForXmppClients ) where 5module XMPPServer ( listenForXmppClients ) where
5 6
6import Data.HList.TypeEqGeneric1() 7import Data.HList.TypeEqGeneric1()
@@ -9,27 +10,25 @@ import ByteStringOperators
9 10
10import Server 11import Server
11import Data.ByteString.Lazy.Char8 as L 12import Data.ByteString.Lazy.Char8 as L
12 ( ByteString 13 ( hPutStrLn
13 , hPutStrLn
14 , unlines 14 , unlines
15 , pack 15 , pack
16 , unpack 16 , unpack )
17 , init )
18import qualified Data.ByteString.Lazy.Char8 as L 17import qualified Data.ByteString.Lazy.Char8 as L
19 ( putStrLn ) 18 ( putStrLn )
20import System.IO 19import System.IO
21 ( Handle 20 ( Handle
22 ) 21 )
23import Control.Concurrent (forkIO)
24import Control.Concurrent.Chan
25import Data.HList 22import Data.HList
26import AdaptServer 23import AdaptServer
27import Text.XML.HaXml.Lex (xmlLex) 24import Text.XML.HaXml.Lex (xmlLex)
28import Text.XML.HaXml.Parse (xmlParseWith,element,doctypedecl,processinginstruction,elemOpenTag,elemCloseTag) 25import Text.XML.HaXml.Parse (xmlParseWith,element,{-doctypedecl,-}processinginstruction,elemOpenTag,elemCloseTag)
29import Text.XML.HaXml.Types as Hax (ElemTag,QName(..),Namespace(..),Element(..),Content(..),AttValue(..)) 26import Text.XML.HaXml.Types as Hax (ElemTag,QName(..),Namespace(..),Element(..),Content(..),AttValue(..))
30import qualified Text.XML.HaXml.Types as Hax (Element)
31import Data.Maybe 27import Data.Maybe
32import Debug.Trace 28import Debug.Trace
29import Control.Arrow
30import LocalPeerCred
31import Network.Socket
33 32
34 33
35 34
@@ -51,17 +50,21 @@ greet host = L.unlines
51 , "</stream:features>" 50 , "</stream:features>"
52 ] 51 ]
53 52
54startCon st = do 53startCon sock st = do
55 let h = hOccursFst st :: Handle 54 let h = hOccursFst st :: Handle
55 cred <- getLocalPeerCred sock
56 Prelude.putStrLn $ "PEER CRED: "++show cred
57 pname <- getPeerName sock
58 Prelude.putStrLn $ "PEER NAME: "++show pname
56 return (ConnectionFinalizer (return ()) .*. st) 59 return (ConnectionFinalizer (return ()) .*. st)
57 60
58iq_query_unavailable host id mjid xmlns = L.unlines $ 61iq_query_unavailable host id mjid xmlns kind = L.unlines $
59 [ "<iq type='error'" 62 [ "<iq type='error'"
60 , " from='" <++> host <++> "'" 63 , " from='" <++> host <++> "'"
61 , case mjid of Just jid -> " to='" <++> jid <++> "'" 64 , case mjid of Just jid -> " to='" <++> jid <++> "'"
62 Nothing -> "" 65 Nothing -> ""
63 , " id='" <++> id <++> "'>" 66 , " id='" <++> id <++> "'>"
64 , " <query xmlns='" <++> xmlns <++> "'/>" 67 , " <" <++> kind <++> " xmlns='" <++> xmlns <++> "'/>"
65 , " <error type='cancel'>" 68 , " <error type='cancel'>"
66 , " <service-unavailable" 69 , " <service-unavailable"
67 , " xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>" 70 , " xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>"
@@ -71,6 +74,7 @@ iq_query_unavailable host id mjid xmlns = L.unlines $
71 74
72tagattrs tag content = Prelude.concatMap (\(CElem (Elem _ a _) _)->a) 75tagattrs tag content = Prelude.concatMap (\(CElem (Elem _ a _) _)->a)
73 $ Prelude.filter (bindElem tag) content 76 $ Prelude.filter (bindElem tag) content
77anytagattrs content = Prelude.concatMap (\(CElem (Elem n a _) _)->map (second (n,)) a) content
74 78
75bindElem tag (CElem (Elem (N n) _ _) _) | n==tag = True 79bindElem tag (CElem (Elem (N n) _ _) _) | n==tag = True
76bindElem _ _ = False 80bindElem _ _ = False
@@ -132,13 +136,37 @@ iqresponse host (Elem _ attrs content) = do
132 Just (iqresult host id Nothing)) 136 Just (iqresult host id Nothing))
133 137
134 "get" -> trace ("iq-get "++show (attrs,content)) $ do 138 "get" -> trace ("iq-get "++show (attrs,content)) $ do
135 xmlns <- fmap pack $ 139 (tag,as) <- lookup (N "xmlns") (anytagattrs content)
136 lookup (N "xmlns") (tagattrs "query" content) 140 xmlns <- fmap pack $ listToMaybe . astring $ as
137 >>= listToMaybe . astring 141 let servicekind = case tag of { (N s) -> pack s ; _ -> "query" }
138 Just (iq_query_unavailable host id Nothing xmlns) 142 case xmlns of
143 "urn:xmpp:ping" -> do
144 let to = case fmap pack (lookup (N "from") attrs >>= unattr) of
145 Just jid -> "to='" <++> jid <++> "' "
146 Nothing -> ""
147 Just $ "<iq from='" <++> host <++> "' " <++> to <++> "id='" <++> id <++> "' type='result'/>"
148
149 _ -> Just (iq_query_unavailable host id Nothing xmlns servicekind)
139 _ -> Nothing 150 _ -> Nothing
140 151
141 152-- <presence>
153-- <priority>1</priority>
154-- <c xmlns='http://jabber.org/protocol/caps'
155-- node='http://pidgin.im/'
156-- hash='sha-1' ver='lV6i//bt2U8Rm0REcX8h4F3Nk3M='
157-- ext='voice-v1 camera-v1 video-v1'/>
158-- <x xmlns='vcard-temp:x:update'/>
159-- </presence>
160
161presence_response host (Elem _ attrs content) = do
162 -- let id = fmap pack (lookup (N "id") attrs >>= unattr)
163 typ <- fmap pack (lookup (N "type") attrs >>= unattr)
164 case typ of
165 "subscribe" -> do
166 -- <presence to='guest@localhost' type='subscribe'/>
167 to <- fmap pack (lookup (N "to") attrs >>= unattr)
168 Just $ "<presence to='" <++> to <++> "' type='subscribed'/>"
169 _ -> Nothing
142 170
143doCon st elem cont = do 171doCon st elem cont = do
144 let h = hOccursFst st :: Handle 172 let h = hOccursFst st :: Handle
@@ -152,8 +180,13 @@ doCon st elem cont = do
152 hsend (greet host) 180 hsend (greet host)
153 Element e@(Elem (N "iq") _ _) -> 181 Element e@(Elem (N "iq") _ _) ->
154 case iqresponse host e of 182 case iqresponse host e of
155 Nothing -> trace "no respones" $ return () 183 Nothing -> trace "IGNORE: no response to <iq>" $ return ()
156 Just r -> hsend r 184 Just r -> hsend r
185 Element e@(Elem (N "presence") _ _) ->
186 case presence_response host e of
187 Nothing -> trace "IGNORE: no response to <presence>" $ return ()
188 Just r -> hsend r
189
157 _ -> return () -- putStrLn $ "unhandled: "++show v 190 _ -> return () -- putStrLn $ "unhandled: "++show v
158 191
159 putStrLn (show elem) 192 putStrLn (show elem)