diff options
Diffstat (limited to 'Presence')
-rw-r--r-- | Presence/XMPPServer.hs | 56 |
1 files changed, 48 insertions, 8 deletions
diff --git a/Presence/XMPPServer.hs b/Presence/XMPPServer.hs index af986645..eb680002 100644 --- a/Presence/XMPPServer.hs +++ b/Presence/XMPPServer.hs | |||
@@ -14,6 +14,7 @@ module XMPPServer | |||
14 | , peerKeyToText | 14 | , peerKeyToText |
15 | , peerKeyToResolvedName | 15 | , peerKeyToResolvedName |
16 | , addrToText | 16 | , addrToText |
17 | , sendModifiedStanzaToPeer | ||
17 | ) where | 18 | ) where |
18 | import Debug.Trace | 19 | import Debug.Trace |
19 | import Control.Monad.Trans.Resource (runResourceT) | 20 | import Control.Monad.Trans.Resource (runResourceT) |
@@ -245,6 +246,38 @@ prettyPrint prefix = | |||
245 | =$= CB.lines | 246 | =$= CB.lines |
246 | =$ CL.mapM_ (wlogb . (prefix <>)) | 247 | =$ CL.mapM_ (wlogb . (prefix <>)) |
247 | 248 | ||
249 | swapNamespace old new = awaitForever swapit | ||
250 | where | ||
251 | swapit (EventBeginElement n as) | nameNamespace n==Just old = | ||
252 | yield $ EventBeginElement (n { nameNamespace = Just new }) as | ||
253 | swapit (EventEndElement n) | nameNamespace n==Just old = | ||
254 | yield $ EventEndElement (n { nameNamespace = Just new }) | ||
255 | swapit x = yield x | ||
256 | |||
257 | fixHeaders Stanza { stanzaTo=mto, stanzaFrom=mfrom } = do | ||
258 | x <- await | ||
259 | maybe (return ()) f x | ||
260 | where | ||
261 | f (EventBeginElement n as) = do yield $ EventBeginElement n (update as) | ||
262 | awaitForever yield | ||
263 | f x = yield x >> awaitForever yield | ||
264 | update as = as'' | ||
265 | where | ||
266 | as' = maybe as (\to->attr "to" to:as) mto | ||
267 | as'' = maybe as' (\from->attr "from" from:as') mfrom | ||
268 | |||
269 | |||
270 | sendModifiedStanzaToPeer stanza chan = do | ||
271 | (echan,clsrs,quitvar) <- conduitToChan c | ||
272 | ioWriteChan chan | ||
273 | stanza { stanzaChan = echan | ||
274 | , stanzaClosers = clsrs | ||
275 | , stanzaInterrupt = quitvar | ||
276 | -- TODO id? origin? | ||
277 | } | ||
278 | where | ||
279 | c = stanzaToConduit stanza =$= swapNamespace "jabber:client" "jabber:server" =$= fixHeaders stanza | ||
280 | |||
248 | -- id,to, and from are taken as-is from reply list | 281 | -- id,to, and from are taken as-is from reply list |
249 | sendReply donevar stype reply replychan = do | 282 | sendReply donevar stype reply replychan = do |
250 | if null reply then return () | 283 | if null reply then return () |
@@ -802,6 +835,15 @@ xmlifyRosterItems solicited stype set = mapM_ item (Set.toList set) | |||
802 | else [] ) | 835 | else [] ) |
803 | yield $ EventEndElement "{jabber:iq:roster}item" | 836 | yield $ EventEndElement "{jabber:iq:roster}item" |
804 | 837 | ||
838 | conduitToChan c = do | ||
839 | chan <- atomically newTChan | ||
840 | clsrs <- atomically $ newTVar (Just []) | ||
841 | quitvar <- atomically $ newEmptyTMVar | ||
842 | forkIO $ do | ||
843 | c =$= copyToChannel id chan clsrs $$ awaitForever (const $ return ()) | ||
844 | atomically $ writeTVar clsrs Nothing | ||
845 | return (chan,clsrs,quitvar) | ||
846 | |||
805 | sendRoster query xmpp replyto = do | 847 | sendRoster query xmpp replyto = do |
806 | let k = case stanzaOrigin query of | 848 | let k = case stanzaOrigin query of |
807 | NetworkOrigin k _ -> Just k | 849 | NetworkOrigin k _ -> Just k |
@@ -834,12 +876,7 @@ sendRoster query xmpp replyto = do | |||
834 | xmlifyRosterItems solicited "none" subnone | 876 | xmlifyRosterItems solicited "none" subnone |
835 | yield $ EventEndElement "{jabber:iq:roster}query" | 877 | yield $ EventEndElement "{jabber:iq:roster}query" |
836 | yield $ EventEndElement "{jabber:client}iq" | 878 | yield $ EventEndElement "{jabber:client}iq" |
837 | chan <- atomically newTChan | 879 | (chan,clsrs,quitvar) <- conduitToChan roster |
838 | clsrs <- atomically $ newTVar (Just []) | ||
839 | quitvar <- atomically $ newEmptyTMVar | ||
840 | forkIO $ do | ||
841 | roster =$= copyToChannel id chan clsrs $$ awaitForever (const $ return ()) | ||
842 | atomically $ writeTVar clsrs Nothing | ||
843 | ioWriteChan replyto | 880 | ioWriteChan replyto |
844 | Stanza { stanzaType = Roster | 881 | Stanza { stanzaType = Roster |
845 | , stanzaId = (stanzaId query) | 882 | , stanzaId = (stanzaId query) |
@@ -904,7 +941,8 @@ monitor sv params xmpp = do | |||
904 | sendRoster stanza xmpp replyto | 941 | sendRoster stanza xmpp replyto |
905 | xmppSubscribeToRoster xmpp k | 942 | xmppSubscribeToRoster xmpp k |
906 | Message {} -> do | 943 | Message {} -> do |
907 | let fail = return () -- todo | 944 | let fail = wlog $ "Failed delivery id="++show (stanzaId stanza) -- TODO |
945 | stanza2 <- atomically $ cloneStanza stanza | ||
908 | xmppDeliverMessage xmpp fail stanza | 946 | xmppDeliverMessage xmpp fail stanza |
909 | PresenceStatus {} -> do | 947 | PresenceStatus {} -> do |
910 | xmppInformClientPresence xmpp k stanza | 948 | xmppInformClientPresence xmpp k stanza |
@@ -914,13 +952,15 @@ monitor sv params xmpp = do | |||
914 | sendReply quitVar Error reply replyto | 952 | sendReply quitVar Error reply replyto |
915 | _ -> return () | 953 | _ -> return () |
916 | _ -> return () | 954 | _ -> return () |
955 | -- We need to clone in the case the stanza is passed on as for Message. | ||
956 | dup <- atomically $ cloneStanza stanza | ||
917 | let typ = Strict8.pack $ c ++ "->"++(concat . take 1 . words $ show (stanzaType stanza))++" " | 957 | let typ = Strict8.pack $ c ++ "->"++(concat . take 1 . words $ show (stanzaType stanza))++" " |
918 | c = case stanzaOrigin stanza of | 958 | c = case stanzaOrigin stanza of |
919 | LocalPeer -> "*" | 959 | LocalPeer -> "*" |
920 | NetworkOrigin (ClientKey {}) _ -> "C" | 960 | NetworkOrigin (ClientKey {}) _ -> "C" |
921 | NetworkOrigin (PeerKey {}) _ -> "P" | 961 | NetworkOrigin (PeerKey {}) _ -> "P" |
922 | wlog "" | 962 | wlog "" |
923 | stanzaToConduit stanza $$ prettyPrint typ | 963 | stanzaToConduit dup $$ prettyPrint typ |
924 | 964 | ||
925 | ] | 965 | ] |
926 | action | 966 | action |