summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Presence/XMPPServer.hs8
-rw-r--r--presence.cabal1
-rwxr-xr-xt2
-rw-r--r--xmppServer.hs68
4 files changed, 63 insertions, 16 deletions
diff --git a/Presence/XMPPServer.hs b/Presence/XMPPServer.hs
index aae5e97a..f029810d 100644
--- a/Presence/XMPPServer.hs
+++ b/Presence/XMPPServer.hs
@@ -68,6 +68,7 @@ import qualified Data.Set as Set
68import qualified System.Random 68import qualified System.Random
69import qualified Network.BSD as BSD 69import qualified Network.BSD as BSD
70import Data.Void (Void) 70import Data.Void (Void)
71import System.Endian (toBE32)
71 72
72import GetHostByAddr (getHostByAddr) 73import GetHostByAddr (getHostByAddr)
73import qualified Control.Concurrent.STM.UpdateStream as Slotted 74import qualified Control.Concurrent.STM.UpdateStream as Slotted
@@ -254,10 +255,15 @@ peerKeyToResolvedNames :: ConnectionKey -> IO [Text]
254peerKeyToResolvedNames k@(ClientKey { localAddress=addr }) = return [] 255peerKeyToResolvedNames k@(ClientKey { localAddress=addr }) = return []
255peerKeyToResolvedNames k@(PeerKey { callBackAddress=addr }) = do 256peerKeyToResolvedNames k@(PeerKey { callBackAddress=addr }) = do
256 handleIO_ (return []) $ do 257 handleIO_ (return []) $ do
257 ent <- getHostByAddr addr -- AF_UNSPEC addr 258 ent <- getHostByAddr (unmap6mapped4 addr) -- AF_UNSPEC addr
258 let names = BSD.hostName ent : BSD.hostAliases ent 259 let names = BSD.hostName ent : BSD.hostAliases ent
259 return $ map Text.pack $ nub names 260 return $ map Text.pack $ nub names
260 261
262unmap6mapped4 addr@(SockAddrInet6 port _ (0,0,0xFFFF,a) _) =
263 SockAddrInet port (toBE32 a)
264unmap6mapped4 addr = addr
265
266
261 267
262wlog :: String -> IO () 268wlog :: String -> IO ()
263wlog s = putStrLn s >> hFlush stdout 269wlog s = putStrLn s >> hFlush stdout
diff --git a/presence.cabal b/presence.cabal
index 30081d17..aaa5603a 100644
--- a/presence.cabal
+++ b/presence.cabal
@@ -26,4 +26,5 @@ executable presence
26 c-sources: Presence/monitortty.c 26 c-sources: Presence/monitortty.c
27 hs-source-dirs: . Presence 27 hs-source-dirs: . Presence
28 ghc-prof-options: -DNOUTMP 28 ghc-prof-options: -DNOUTMP
29 ghc-options: -O2 -fwarn-unused-binds -threaded
29 30
diff --git a/t b/t
index 6b7abba5..22b21361 100755
--- a/t
+++ b/t
@@ -1,5 +1,5 @@
1#!/bin/bash 1#!/bin/bash
2args="-fwarn-unused-imports -rtsopts -DRENDERFLUSH -optP-include -optPdist/build/autogen/cabal_macros.h" 2args="-threaded -fwarn-unused-imports -rtsopts -DRENDERFLUSH -optP-include -optPdist/build/autogen/cabal_macros.h"
3 3
4root=${0%/*} 4root=${0%/*}
5cd "$root" 5cd "$root"
diff --git a/xmppServer.hs b/xmppServer.hs
index 598ffe72..3752218a 100644
--- a/xmppServer.hs
+++ b/xmppServer.hs
@@ -1,6 +1,7 @@
1{-# LANGUAGE OverloadedStrings #-} 1{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE TupleSections #-} 2{-# LANGUAGE TupleSections #-}
3import System.Posix.Signals 3import System.Posix.Signals
4import Control.Concurrent (threadDelay,forkIO,forkOS,killThread,throwTo)
4import Control.Concurrent.STM 5import Control.Concurrent.STM
5import Control.Concurrent.STM.TMVar 6import Control.Concurrent.STM.TMVar
6import Control.Monad.Trans.Resource (runResourceT) 7import Control.Monad.Trans.Resource (runResourceT)
@@ -146,10 +147,31 @@ make6mapped4 addr@(SockAddrInet port a) = SockAddrInet6 port 0 (0,0,0xFFFF,fromB
146 147
147resolvePeer :: Text -> IO [SockAddr] 148resolvePeer :: Text -> IO [SockAddr]
148resolvePeer addrtext = do 149resolvePeer addrtext = do
149 fmap (map $ make6mapped4 . addrAddress) $ 150 r <- atomically newEmptyTMVar
150 getAddrInfo (Just $ defaultHints { addrFlags = [ AI_CANONNAME, AI_V4MAPPED ]}) 151 mvar <- atomically newEmptyTMVar
152 rt <- forkOS $ resolver r mvar
153 tt <- forkIO $ timer r rt
154 atomically $ putTMVar mvar tt
155 atomically $ readTMVar r
156 where
157 resolver r mvar = do
158 xs <- handle (\e -> let _ = isDoesNotExistError e in return [])
159 $ do fmap (map $ make6mapped4 . addrAddress) $
160 getAddrInfo (Just $ defaultHints { addrFlags = [ AI_CANONNAME, AI_V4MAPPED ]})
151 (Just $ Text.unpack $ strip_brackets addrtext) 161 (Just $ Text.unpack $ strip_brackets addrtext)
152 (Just "5269") 162 (Just "5269")
163 did <- atomically $ tryPutTMVar r xs
164 when did $ do
165 tt <- atomically $ readTMVar mvar
166 throwTo tt (ErrorCall "Interrupted delay")
167 return ()
168 timer r rt = do
169 handle (\(ErrorCall _)-> return ()) $ do
170 threadDelay 1000000
171 did <- atomically $ tryPutTMVar r []
172 when did $ do
173 putStrLn $ "timeout resolving: "++show addrtext
174 killThread rt
153 175
154strip_brackets s = 176strip_brackets s =
155 case Text.uncons s of 177 case Text.uncons s of
@@ -388,12 +410,14 @@ rewriteJIDForClient laddr jid = do
388 else peerKeyToResolvedName (PeerKey addr) 410 else peerKeyToResolvedName (PeerKey addr)
389 return (mine,(n,h',r)) 411 return (mine,(n,h',r))
390 412
413sameAddress laddr addr = laddr `withPort` 0 == addr `withPort` 0
414
391multiplyJIDForClient :: SockAddr -> Text -> IO (Bool,[(Maybe Text,Text,Maybe Text)]) 415multiplyJIDForClient :: SockAddr -> Text -> IO (Bool,[(Maybe Text,Text,Maybe Text)])
392multiplyJIDForClient laddr jid = do 416multiplyJIDForClient laddr jid = do
393 let (n,h,r) = splitJID jid 417 let (n,h,r) = splitJID jid
394 maddr <- parseAddress (strip_brackets h) 418 maddr <- parseAddress (strip_brackets h)
395 flip (maybe $ return (False,[(n,ip6literal h,r)])) maddr $ \addr -> do 419 flip (maybe $ return (False,[(n,ip6literal h,r)])) maddr $ \addr -> do
396 let mine = laddr `withPort` 0 == addr `withPort` 0 420 let mine = sameAddress laddr addr
397 names <- if mine then fmap (:[]) textHostName 421 names <- if mine then fmap (:[]) textHostName
398 else peerKeyToResolvedNames (PeerKey addr) 422 else peerKeyToResolvedNames (PeerKey addr)
399 return (mine,map (\h' -> (n,h',r)) names) 423 return (mine,map (\h' -> (n,h',r)) names)
@@ -529,10 +553,11 @@ informClientPresence state k stanza = do
529 553
530informPeerPresence state k stanza = do 554informPeerPresence state k stanza = do
531 -- Presence must indicate full JID with resource... 555 -- Presence must indicate full JID with resource...
532 putStrLn $ "xmppInformPeerPresence checking from address..." 556 putStrLn $ "xmppInformPeerPresence checking from address..."
533 flip (maybe $ return ()) (stanzaFrom stanza) $ \from -> do 557 flip (maybe $ return ()) (stanzaFrom stanza) $ \from -> do
534 let (muser,h,mresource) = splitJID from 558 let (muser,h,mresource) = splitJID from
535 flip (maybe $ return ()) mresource $ \resource -> do 559 putStrLn $ "xmppInformPeerPresence from = " ++ show from
560 -- flip (maybe $ return ()) mresource $ \resource -> do
536 flip (maybe $ return ()) muser $ \user -> do 561 flip (maybe $ return ()) muser $ \user -> do
537 562
538 clients <- atomically $ do 563 clients <- atomically $ do
@@ -542,13 +567,25 @@ informPeerPresence state k stanza = do
542 let umap = maybe Map.empty id $ Map.lookup k rbp 567 let umap = maybe Map.empty id $ Map.lookup k rbp
543 rp = case (presenceShow $ stanzaType stanza) of 568 rp = case (presenceShow $ stanzaType stanza) of
544 Offline -> 569 Offline ->
545 maybe (Map.empty) 570 maybe Map.empty
546 (Map.delete resource . resources) 571 (\resource ->
547 $ Map.lookup user umap 572 maybe (Map.empty)
548 _ -> maybe (Map.singleton resource stanza) 573 (Map.delete resource . resources)
549 (Map.insert resource stanza . resources ) 574 $ Map.lookup user umap)
550 $ Map.lookup user umap 575 mresource
576
577 _ ->maybe Map.empty
578 (\resource ->
579 maybe (Map.singleton resource stanza)
580 (Map.insert resource stanza . resources )
581 $ Map.lookup user umap)
582 mresource
551 umap' = Map.insert user (RemotePresence rp) umap 583 umap' = Map.insert user (RemotePresence rp) umap
584
585 flip (maybe $ return []) (case presenceShow $ stanzaType stanza of
586 Offline -> Just ()
587 _ -> mresource >> Just ())
588 $ \_ -> do
552 writeTVar (remotesByPeer state) $ Map.insert k umap' rbp 589 writeTVar (remotesByPeer state) $ Map.insert k umap' rbp
553 -- TODO: Store or delete the stanza (remotesByPeer) 590 -- TODO: Store or delete the stanza (remotesByPeer)
554 591
@@ -565,11 +602,13 @@ informPeerPresence state k stanza = do
565 -- For now, all "available" clients (available = sent initial presence) 602 -- For now, all "available" clients (available = sent initial presence)
566 is_avail <- atomically $ clientIsAvailable client 603 is_avail <- atomically $ clientIsAvailable client
567 when is_avail $ do 604 when is_avail $ do
605 putStrLn $ "reversing for client: " ++ show from
568 froms <- do 606 froms <- do
569 let ClientKey laddr = ck 607 let ClientKey laddr = ck
570 (_,trip) <- multiplyJIDForClient laddr from 608 (_,trip) <- multiplyJIDForClient laddr from
571 return (map unsplitJID trip) 609 return (map unsplitJID trip)
572 putStrLn $ "sending to client: " ++ show (stanzaType stanza) 610
611 putStrLn $ "sending to client: " ++ show (stanzaType stanza,froms)
573 forM_ froms $ \from' -> do 612 forM_ froms $ \from' -> do
574 dup <- cloneStanza stanza 613 dup <- cloneStanza stanza
575 sendModifiedStanzaToClient (dup { stanzaFrom=Just from' }) 614 sendModifiedStanzaToClient (dup { stanzaFrom=Just from' })
@@ -802,11 +841,12 @@ peerSubscriptionRequest state fail k stanza chan = do
802 841
803 -- TODO: if peer-connection is to self, then auto-approve local user. 842 -- TODO: if peer-connection is to self, then auto-approve local user.
804 843
805 -- Catch exception in case the user does not exist
806 handle (\e -> let _ = isDoesNotExistError e in fail) $ do
807 -- add from-address to to's pending 844 -- add from-address to to's pending
808 addrs <- resolvePeer from_h 845 addrs <- resolvePeer from_h
809 846
847 -- Catch exception in case the user does not exist
848 if null addrs then fail else do
849
810 let from' = unsplitJID fromtup 850 let from' = unsplitJID fromtup
811 851
812 already_pending <- 852 already_pending <-