summaryrefslogtreecommitdiff
path: root/Presence/XMPPServer.hs
diff options
context:
space:
mode:
Diffstat (limited to 'Presence/XMPPServer.hs')
-rw-r--r--Presence/XMPPServer.hs61
1 files changed, 59 insertions, 2 deletions
diff --git a/Presence/XMPPServer.hs b/Presence/XMPPServer.hs
index 6e0f5c5f..7eb0fbc5 100644
--- a/Presence/XMPPServer.hs
+++ b/Presence/XMPPServer.hs
@@ -192,8 +192,10 @@ peerKeyToResolvedName k@(PeerKey { callBackAddress=addr }) = do
192 return $ maybe (peerKeyToText k) Text.pack mname 192 return $ maybe (peerKeyToText k) Text.pack mname
193 193
194 194
195wlog :: String -> IO ()
195wlog s = putStrLn s 196wlog s = putStrLn s
196 where _ = s :: String 197
198wlogb :: ByteString -> IO ()
197wlogb s = Strict8.putStrLn s 199wlogb s = Strict8.putStrLn s
198 200
199xmlStream :: ReadCommand -> WriteCommand -> ( Source IO XML.Event 201xmlStream :: ReadCommand -> WriteCommand -> ( Source IO XML.Event
@@ -226,10 +228,14 @@ type FlagCommand = STM Bool
226type ReadCommand = IO (Maybe ByteString) 228type ReadCommand = IO (Maybe ByteString)
227type WriteCommand = ByteString -> IO Bool 229type WriteCommand = ByteString -> IO Bool
228 230
231cloneStanza :: StanzaWrap (TChan a) -> STM (StanzaWrap (TChan a))
229cloneStanza stanza = do 232cloneStanza stanza = do
230 dupped <- cloneTChan (stanzaChan stanza) 233 dupped <- cloneTChan (stanzaChan stanza)
231 return stanza { stanzaChan = dupped } 234 return stanza { stanzaChan = dupped }
232 235
236copyToChannel
237 :: MonadIO m =>
238 (Event -> a) -> TChan a -> TVar (Maybe [Event]) -> ConduitM Event Event m ()
233copyToChannel f chan closer_stack = awaitForever copy 239copyToChannel f chan closer_stack = awaitForever copy
234 where 240 where
235 copy x = do 241 copy x = do
@@ -251,6 +257,7 @@ prettyPrint prefix =
251 =$= CB.lines 257 =$= CB.lines
252 =$ CL.mapM_ (wlogb . (prefix <>)) 258 =$ CL.mapM_ (wlogb . (prefix <>))
253 259
260swapNamespace :: Monad m => Text -> Text -> ConduitM Event Event m ()
254swapNamespace old new = awaitForever swapit 261swapNamespace old new = awaitForever swapit
255 where 262 where
256 swapit (EventBeginElement n as) | nameNamespace n==Just old = 263 swapit (EventBeginElement n as) | nameNamespace n==Just old =
@@ -259,6 +266,7 @@ swapNamespace old new = awaitForever swapit
259 yield $ EventEndElement (n { nameNamespace = Just new }) 266 yield $ EventEndElement (n { nameNamespace = Just new })
260 swapit x = yield x 267 swapit x = yield x
261 268
269fixHeaders :: Monad m => Stanza -> ConduitM Event Event m ()
262fixHeaders Stanza { stanzaTo=mto, stanzaFrom=mfrom } = do 270fixHeaders Stanza { stanzaTo=mto, stanzaFrom=mfrom } = do
263 x <- await 271 x <- await
264 maybe (return ()) f x 272 maybe (return ()) f x
@@ -272,6 +280,7 @@ fixHeaders Stanza { stanzaTo=mto, stanzaFrom=mfrom } = do
272 as'' = maybe as' (\from->attr "from" from:as') mfrom 280 as'' = maybe as' (\from->attr "from" from:as') mfrom
273 281
274 282
283sendModifiedStanzaToPeer :: Stanza -> TChan Stanza -> IO ()
275sendModifiedStanzaToPeer stanza chan = do 284sendModifiedStanzaToPeer stanza chan = do
276 (echan,clsrs,quitvar) <- conduitToChan c 285 (echan,clsrs,quitvar) <- conduitToChan c
277 ioWriteChan chan 286 ioWriteChan chan
@@ -283,6 +292,7 @@ sendModifiedStanzaToPeer stanza chan = do
283 where 292 where
284 c = stanzaToConduit stanza =$= swapNamespace "jabber:client" "jabber:server" =$= fixHeaders stanza 293 c = stanzaToConduit stanza =$= swapNamespace "jabber:client" "jabber:server" =$= fixHeaders stanza
285 294
295sendModifiedStanzaToClient :: Stanza -> TChan Stanza -> IO ()
286sendModifiedStanzaToClient stanza chan = do 296sendModifiedStanzaToClient stanza chan = do
287 (echan,clsrs,quitvar) <- conduitToChan c 297 (echan,clsrs,quitvar) <- conduitToChan c
288 ioWriteChan chan 298 ioWriteChan chan
@@ -295,6 +305,8 @@ sendModifiedStanzaToClient stanza chan = do
295 c = stanzaToConduit stanza =$= swapNamespace "jabber:server" "jabber:client" =$= fixHeaders stanza 305 c = stanzaToConduit stanza =$= swapNamespace "jabber:server" "jabber:client" =$= fixHeaders stanza
296 306
297-- id,to, and from are taken as-is from reply list 307-- id,to, and from are taken as-is from reply list
308-- todo: this should probably be restricted to IO monad
309sendReply :: (Functor m, MonadIO m) => TMVar () -> StanzaType -> [Event] -> TChan Stanza -> m ()
298sendReply donevar stype reply replychan = do 310sendReply donevar stype reply replychan = do
299 if null reply then return () 311 if null reply then return ()
300 else do 312 else do
@@ -363,8 +375,13 @@ C->Unrecognized <bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"/>
363C->Unrecognized </iq> 375C->Unrecognized </iq>
364-} 376-}
365 377
378ioWriteChan :: MonadIO m => TChan a -> a -> m ()
366ioWriteChan c v = liftIO . atomically $ writeTChan c v 379ioWriteChan c v = liftIO . atomically $ writeTChan c v
367 380
381parsePresenceStatus
382 :: ( MonadThrow m
383 , MonadIO m
384 ) => Text -> NestingXML o m (Maybe StanzaType)
368parsePresenceStatus ns = do 385parsePresenceStatus ns = do
369 386
370 let toStat "away" = Away 387 let toStat "away" = Away
@@ -399,6 +416,10 @@ parsePresenceStatus ns = do
399 , presencePriority = prio 416 , presencePriority = prio
400 , presenceStatus = status 417 , presenceStatus = status
401 } 418 }
419grokPresence
420 :: ( MonadThrow m
421 , MonadIO m
422 ) => Text -> XML.Event -> NestingXML o m (Maybe StanzaType)
402grokPresence ns stanzaTag = do 423grokPresence ns stanzaTag = do
403 let typ = lookupAttrib "type" (tagAttrs stanzaTag) 424 let typ = lookupAttrib "type" (tagAttrs stanzaTag)
404 case typ of 425 case typ of
@@ -413,6 +434,10 @@ grokPresence ns stanzaTag = do
413 Just "subscribe" -> return . Just $ PresenceRequestSubscription True 434 Just "subscribe" -> return . Just $ PresenceRequestSubscription True
414 _ -> return Nothing 435 _ -> return Nothing
415 436
437parseMessage
438 :: ( MonadThrow m
439 , MonadIO m
440 ) => Text -> XML.Event -> NestingXML o m StanzaType
416parseMessage ns stanza = do 441parseMessage ns stanza = do
417 let bodytag = Name { nameNamespace = Just ns 442 let bodytag = Name { nameNamespace = Just ns
418 , nameLocalName = "body" 443 , nameLocalName = "body"
@@ -462,11 +487,19 @@ parseMessage ns stanza = do
462 msgThread = if msgThreadContent th/="" then Just th else Nothing 487 msgThread = if msgThreadContent th/="" then Just th else Nothing
463 } 488 }
464 489
490grokMessage
491 :: ( MonadThrow m
492 , MonadIO m
493 ) => Text -> XML.Event -> NestingXML o m (Maybe StanzaType)
465grokMessage ns stanzaTag = do 494grokMessage ns stanzaTag = do
466 t <- parseMessage ns stanzaTag 495 t <- parseMessage ns stanzaTag
467 return $ Just t 496 return $ Just t
468 497
469grokStanza "jabber:server" stanzaTag = 498
499
500grokStanza
501 :: Text -> XML.Event -> NestingXML o IO (Maybe StanzaType)
502ggrokStanza "jabber:server" stanzaTag =
470 case () of 503 case () of
471 _ | stanzaTag `isServerIQOf` "get" -> grokStanzaIQGet stanzaTag 504 _ | stanzaTag `isServerIQOf` "get" -> grokStanzaIQGet stanzaTag
472 _ | stanzaTag `isServerIQOf` "result" -> grokStanzaIQResult stanzaTag 505 _ | stanzaTag `isServerIQOf` "result" -> grokStanzaIQResult stanzaTag
@@ -606,6 +639,7 @@ readUntilNothing ch = do
606 return (x:xs)) 639 return (x:xs))
607 x 640 x
608 641
642streamFeatures :: Text -> [XML.Event]
609streamFeatures "jabber:client" = 643streamFeatures "jabber:client" =
610 [ EventBeginElement (streamP "features") [] 644 [ EventBeginElement (streamP "features") []
611 , EventBeginElement "{urn:ietf:params:xml:ns:xmpp-bind}bind" [] 645 , EventBeginElement "{urn:ietf:params:xml:ns:xmpp-bind}bind" []
@@ -625,6 +659,7 @@ streamFeatures "jabber:server" =
625 [] 659 []
626 660
627 661
662greet' :: Text -> Text -> [XML.Event]
628greet' namespace host = 663greet' namespace host =
629 [ EventBeginDocument 664 [ EventBeginDocument
630 , EventBeginElement (streamP "stream") 665 , EventBeginElement (streamP "stream")
@@ -636,6 +671,7 @@ greet' namespace host =
636 ] 671 ]
637 ] ++ streamFeatures namespace 672 ] ++ streamFeatures namespace
638 673
674consid :: Maybe Text -> [(Name, [Content])] -> [(Name, [Content])]
639consid Nothing = id 675consid Nothing = id
640consid (Just sid) = (("id",[ContentText sid]):) 676consid (Just sid) = (("id",[ContentText sid]):)
641 677
@@ -644,6 +680,7 @@ data XMPPState
644 = PingSlot 680 = PingSlot
645 deriving (Eq,Ord) 681 deriving (Eq,Ord)
646 682
683mkname :: Text -> Text -> XML.Name
647mkname namespace name = (Name name (Just namespace) Nothing) 684mkname namespace name = (Name name (Just namespace) Nothing)
648 685
649makePing :: Text -> Maybe Text -> Text -> Text -> [XML.Event] 686makePing :: Text -> Maybe Text -> Text -> Text -> [XML.Event]
@@ -660,6 +697,7 @@ makePing namespace mid to from =
660 , EventEndElement "{urn:xmpp:ping}ping" 697 , EventEndElement "{urn:xmpp:ping}ping"
661 , EventEndElement $ mkname namespace "iq"] 698 , EventEndElement $ mkname namespace "iq"]
662 699
700makePong :: Text -> Maybe Text -> Text -> Text -> [XML.Event]
663makePong namespace mid to from = 701makePong namespace mid to from =
664 -- Note: similar to session reply 702 -- Note: similar to session reply
665 [ EventBeginElement (mkname namespace "iq") 703 [ EventBeginElement (mkname namespace "iq")
@@ -685,6 +723,7 @@ iq_bind_reply mid jid =
685 , EventEndElement "{jabber:client}iq" 723 , EventEndElement "{jabber:client}iq"
686 ] 724 ]
687 725
726iq_session_reply :: Maybe Text -> Text -> [XML.Event]
688iq_session_reply mid host = 727iq_session_reply mid host =
689 -- Note: similar to Pong 728 -- Note: similar to Pong
690 [ EventBeginElement "{jabber:client}iq" 729 [ EventBeginElement "{jabber:client}iq"
@@ -694,6 +733,7 @@ iq_session_reply mid host =
694 , EventEndElement "{jabber:client}iq" 733 , EventEndElement "{jabber:client}iq"
695 ] 734 ]
696 735
736iq_service_unavailable :: Maybe Text -> Text -> XML.Name -> [XML.Event]
697iq_service_unavailable mid host {- mjid -} req = 737iq_service_unavailable mid host {- mjid -} req =
698 [ EventBeginElement "{jabber:client}iq" 738 [ EventBeginElement "{jabber:client}iq"
699 (consid mid [("type",[ContentText "error"]) 739 (consid mid [("type",[ContentText "error"])
@@ -731,6 +771,7 @@ wrapStanzaList xs = do
731 mfrom = m >>= lookupAttrib "from" . tagAttrs 771 mfrom = m >>= lookupAttrib "from" . tagAttrs
732 mid = m >>= lookupAttrib "id" . tagAttrs 772 mid = m >>= lookupAttrib "id" . tagAttrs
733 773
774wrapStanzaConduit :: Monad m => StanzaWrap a -> ConduitM Event (Either (StanzaWrap Event) Event) m ()
734wrapStanzaConduit stanza = do 775wrapStanzaConduit stanza = do
735 mfirst <- await 776 mfirst <- await
736 flip (maybe $ return ()) mfirst $ \first -> do 777 flip (maybe $ return ()) mfirst $ \first -> do
@@ -749,6 +790,7 @@ greet namespace =
749 ] 790 ]
750-} 791-}
751 792
793goodbye :: [XML.Event]
752goodbye = 794goodbye =
753 [ EventEndElement (streamP "stream") 795 [ EventEndElement (streamP "stream")
754 , EventEndDocument 796 , EventEndDocument
@@ -888,6 +930,7 @@ data PeerState
888 | PeerConnected (TChan Stanza) 930 | PeerConnected (TChan Stanza)
889-} 931-}
890 932
933peerKey :: (Socket,SockAddr) -> IO (ConnectionKey,SockAddr)
891peerKey (sock,addr) = do 934peerKey (sock,addr) = do
892 peer <- 935 peer <-
893 sIsConnected sock >>= \c -> 936 sIsConnected sock >>= \c ->
@@ -896,6 +939,7 @@ peerKey (sock,addr) = do
896 laddr <- getSocketName sock 939 laddr <- getSocketName sock
897 return $ (PeerKey (peer `withPort` fromIntegral peerport),laddr) 940 return $ (PeerKey (peer `withPort` fromIntegral peerport),laddr)
898 941
942clientKey :: (Socket,SockAddr) -> IO (ConnectionKey,SockAddr)
899clientKey (sock,addr) = do 943clientKey (sock,addr) = do
900 paddr <- getPeerName sock 944 paddr <- getPeerName sock
901 return $ (ClientKey addr,paddr) 945 return $ (ClientKey addr,paddr)
@@ -934,6 +978,9 @@ xmlifyRosterItems solicited stype set = mapM_ item (Set.toList set)
934 else [] ) 978 else [] )
935 yield $ EventEndElement "{jabber:iq:roster}item" 979 yield $ EventEndElement "{jabber:iq:roster}item"
936 980
981conduitToChan
982 :: Conduit () IO Event
983 -> IO (TChan Event, TVar (Maybe [Event]), TMVar a)
937conduitToChan c = do 984conduitToChan c = do
938 chan <- atomically newTChan 985 chan <- atomically newTChan
939 clsrs <- atomically $ newTVar (Just []) 986 clsrs <- atomically $ newTVar (Just [])
@@ -943,6 +990,11 @@ conduitToChan c = do
943 atomically $ writeTVar clsrs Nothing 990 atomically $ writeTVar clsrs Nothing
944 return (chan,clsrs,quitvar) 991 return (chan,clsrs,quitvar)
945 992
993sendRoster ::
994 StanzaWrap a
995 -> XMPPServerParameters
996 -> TChan (StanzaWrap (TChan Event))
997 -> IO ()
946sendRoster query xmpp replyto = do 998sendRoster query xmpp replyto = do
947 let k = case stanzaOrigin query of 999 let k = case stanzaOrigin query of
948 NetworkOrigin k _ -> Just k 1000 NetworkOrigin k _ -> Just k
@@ -999,6 +1051,11 @@ socketFromKey sv k = do
999 -- Shouldnt happen anyway. 1051 -- Shouldnt happen anyway.
1000 Just cd -> return $ cdata cd 1052 Just cd -> return $ cdata cd
1001 1053
1054monitor ::
1055 Server ConnectionKey SockAddr
1056 -> ConnectionParameters ConnectionKey SockAddr
1057 -> XMPPServerParameters
1058 -> IO b
1002monitor sv params xmpp = do 1059monitor sv params xmpp = do
1003 chan <- return $ serverEvent sv 1060 chan <- return $ serverEvent sv
1004 stanzas <- atomically newTChan 1061 stanzas <- atomically newTChan