summaryrefslogtreecommitdiff
path: root/Presence
diff options
context:
space:
mode:
Diffstat (limited to 'Presence')
-rw-r--r--Presence/ConfigFiles.hs2
-rw-r--r--Presence/Presence.hs34
-rw-r--r--Presence/XMPPServer.hs26
3 files changed, 45 insertions, 17 deletions
diff --git a/Presence/ConfigFiles.hs b/Presence/ConfigFiles.hs
index d405bd8f..6354d841 100644
--- a/Presence/ConfigFiles.hs
+++ b/Presence/ConfigFiles.hs
@@ -30,7 +30,7 @@ subscriberFile = "subscribers"
30otherFile = "others" 30otherFile = "others"
31pendingFile = "pending" 31pendingFile = "pending"
32solicitedFile = "solicited" 32solicitedFile = "solicited"
33secretsFile = "secrets" 33secretsFile = "secret"
34 34
35 35
36configPath :: User -> Profile -> String -> IO String 36configPath :: User -> Profile -> String -> IO String
diff --git a/Presence/Presence.hs b/Presence/Presence.hs
index 97b9d5b8..198012de 100644
--- a/Presence/Presence.hs
+++ b/Presence/Presence.hs
@@ -5,7 +5,9 @@
5{-# LANGUAGE TupleSections #-} 5{-# LANGUAGE TupleSections #-}
6module Presence where 6module Presence where
7 7
8import System.Directory
8import System.Environment 9import System.Environment
10import System.IO.Error
9import System.Posix.Signals 11import System.Posix.Signals
10import Control.Concurrent (threadDelay,forkIO,forkOS,killThread,throwTo) 12import Control.Concurrent (threadDelay,forkIO,forkOS,killThread,throwTo)
11import Control.Concurrent.STM 13import Control.Concurrent.STM
@@ -15,6 +17,7 @@ import Control.Monad.Trans
15import Control.Monad.IO.Class (MonadIO, liftIO) 17import Control.Monad.IO.Class (MonadIO, liftIO)
16import Network.Socket ( SockAddr(..), PortNumber ) 18import Network.Socket ( SockAddr(..), PortNumber )
17import System.Endian (fromBE32) 19import System.Endian (fromBE32)
20import Data.Char
18import Data.List (nub, (\\), intersect, groupBy, sort, sortBy ) 21import Data.List (nub, (\\), intersect, groupBy, sort, sortBy )
19import Data.Ord (comparing ) 22import Data.Ord (comparing )
20import Data.Monoid ( (<>), Sum(..), getSum ) 23import Data.Monoid ( (<>), Sum(..), getSum )
@@ -46,6 +49,7 @@ import Crypto.Error
46#endif 49#endif
47import Crypto.PubKey.Curve25519 (SecretKey,toPublic) 50import Crypto.PubKey.Curve25519 (SecretKey,toPublic)
48import Text.Read (readMaybe) 51import Text.Read (readMaybe)
52import System.IO
49 53
50import LockedChan (LockedChan) 54import LockedChan (LockedChan)
51import TraversableT 55import TraversableT
@@ -57,7 +61,7 @@ import ConsoleWriter
57import ClientState 61import ClientState
58import Util 62import Util
59import qualified Connection 63import qualified Connection
60import Network.Tox.NodeId (id2key) 64import Network.Tox.NodeId (id2key,key2id)
61import Crypto.Tox (decodeSecret) 65import Crypto.Tox (decodeSecret)
62 66
63isPeerKey :: ConnectionKey -> Bool 67isPeerKey :: ConnectionKey -> Bool
@@ -124,11 +128,22 @@ newPresenceState cw toxman xmpp = atomically $ do
124 } 128 }
125 129
126 130
131nameForClient :: PresenceState -> ConnectionKey -> IO Text
132nameForClient state k = do
133 mc <- atomically $ do
134 cmap <- readTVar (clients state)
135 return $ Map.lookup k cmap
136 case mc of
137 Nothing -> textHostName
138 Just client -> case clientProfile client of
139 "." -> textHostName
140 profile -> return profile
141
127presenceHooks :: PresenceState -> Int -> Maybe PortNumber -> XMPPServerParameters 142presenceHooks :: PresenceState -> Int -> Maybe PortNumber -> XMPPServerParameters
128presenceHooks state verbosity mport = XMPPServerParameters 143presenceHooks state verbosity mport = XMPPServerParameters
129 { xmppChooseResourceName = chooseResourceName state 144 { xmppChooseResourceName = chooseResourceName state
130 , xmppTellClientHisName = tellClientHisName state 145 , xmppTellClientHisName = tellClientHisName state
131 , xmppTellMyNameToClient = textHostName 146 , xmppTellMyNameToClient = nameForClient state
132 , xmppTellMyNameToPeer = \addr -> return $ addrToText addr 147 , xmppTellMyNameToPeer = \addr -> return $ addrToText addr
133 , xmppTellPeerHisName = return . peerKeyToText 148 , xmppTellPeerHisName = return . peerKeyToText
134 , xmppTellClientNameOfPeer = flip peerKeyToResolvedName 149 , xmppTellClientNameOfPeer = flip peerKeyToResolvedName
@@ -212,22 +227,29 @@ chooseResourceName state k addr clientsNameForMe desired = do
212 status <- atomically $ newTVar Nothing 227 status <- atomically $ newTVar Nothing
213 flgs <- atomically $ newTVar 0 228 flgs <- atomically $ newTVar 0
214 profile <- fmap (fromMaybe ".") 229 profile <- fmap (fromMaybe ".")
215 $ forM ((,) <$> clientsNameForMe <*> toxManager state) $ \(wanted_profile,toxman) -> 230 $ forM ((,) <$> clientsNameForMe <*> toxManager state) $ \(wanted_profile0,toxman) ->
216 case Text.splitAt 43 wanted_profile of 231 case Text.splitAt 43 wanted_profile0 of
217 (pub,".tox") -> do 232 (pub,".tox") -> do
218 -- TODO: Tox key profile. 233 cdir <- ConfigFiles.configPath (L.fromChunks [Text.encodeUtf8 user]) "." ""
234 cfs <- map Text.pack <$> listDirectory cdir `catchIOError` (\e -> return [])
235 let profiles = filter (\f -> Text.toLower f == Text.toLower wanted_profile0) cfs
236 -- hPutStrLn stderr $ "Toxmpp profile " ++ show (user,wanted_profile0,profiles,cfs)
237 let wanted_profile = head $ profiles ++ [wanted_profile0]
219 secs <- configText ConfigFiles.getSecrets user wanted_profile 238 secs <- configText ConfigFiles.getSecrets user wanted_profile
220 case secs of 239 case secs of
221 sec:_ | Just s <- decodeSecret (Text.encodeUtf8 sec) 240 sec:_ | Just s <- decodeSecret (Text.encodeUtf8 sec)
222 , Just (toPublic s) == fmap id2key (readMaybe $ Text.unpack pub) 241 , map toLower (show $ key2id $ toPublic s) == map toLower (Text.unpack pub)
223 -> do activateAccount toxman k wanted_profile s 242 -> do activateAccount toxman k wanted_profile s
243 hPutStrLn stderr $ "loaded tox secret " ++ show sec
224 return wanted_profile 244 return wanted_profile
225 _ -> do 245 _ -> do
226 -- XXX: We should probably fail to connect when an 246 -- XXX: We should probably fail to connect when an
227 -- invalid Tox profile is used. For now, we'll 247 -- invalid Tox profile is used. For now, we'll
228 -- fall back to the Unix account login. 248 -- fall back to the Unix account login.
249 hPutStrLn stderr "failed to find tox secret"
229 return "." 250 return "."
230 ("*.tox","") -> do 251 ("*.tox","") -> do
252 hPutStrLn stderr $ "TODO: Match single tox key profile or generate first."
231 -- TODO: Match single tox key profile or generate first. 253 -- TODO: Match single tox key profile or generate first.
232 _todo 254 _todo
233 _ -> return "." 255 _ -> return "."
diff --git a/Presence/XMPPServer.hs b/Presence/XMPPServer.hs
index c9132d0f..bc5e88da 100644
--- a/Presence/XMPPServer.hs
+++ b/Presence/XMPPServer.hs
@@ -89,6 +89,7 @@ import System.Endian (toBE32)
89import Control.Applicative 89import Control.Applicative
90import System.IO 90import System.IO
91import qualified Connection 91import qualified Connection
92import Util
92 93
93peerport :: PortNumber 94peerport :: PortNumber
94peerport = 5269 95peerport = 5269
@@ -182,9 +183,12 @@ data XMPPServerParameters =
182 { -- | Called when a client requests a resource id. The first Maybe indicates 183 { -- | Called when a client requests a resource id. The first Maybe indicates
183 -- the name the client referred to this server by. The second Maybe is the 184 -- the name the client referred to this server by. The second Maybe is the
184 -- client's preferred resource name. 185 -- client's preferred resource name.
186 --
187 -- Note: The returned domain will be discarded and replaced with the result of
188 -- 'xmppTellMyNameToClient'.
185 xmppChooseResourceName :: ConnectionKey -> SockAddr -> Maybe Text -> Maybe Text -> IO Text 189 xmppChooseResourceName :: ConnectionKey -> SockAddr -> Maybe Text -> Maybe Text -> IO Text
186 , -- | This should indicate the server's hostname that all client's see. 190 , -- | This should indicate the server's hostname that all client's see.
187 xmppTellMyNameToClient :: IO Text 191 xmppTellMyNameToClient :: ConnectionKey -> IO Text
188 , xmppTellMyNameToPeer :: SockAddr -> IO Text 192 , xmppTellMyNameToPeer :: SockAddr -> IO Text
189 , xmppTellClientHisName :: ConnectionKey -> IO Text 193 , xmppTellClientHisName :: ConnectionKey -> IO Text
190 , xmppTellPeerHisName :: ConnectionKey -> IO Text 194 , xmppTellPeerHisName :: ConnectionKey -> IO Text
@@ -896,7 +900,7 @@ xmppInbound :: Server ConnectionKey SockAddr ReleaseKey XML.Event
896xmppInbound sv xmpp k laddr pingflag stanzas output donevar = doNestingXML $ do 900xmppInbound sv xmpp k laddr pingflag stanzas output donevar = doNestingXML $ do
897 let (namespace,tellmyname,tellyourname) = case k of 901 let (namespace,tellmyname,tellyourname) = case k of
898 ClientKey {} -> ( "jabber:client" 902 ClientKey {} -> ( "jabber:client"
899 , xmppTellMyNameToClient xmpp 903 , xmppTellMyNameToClient xmpp k
900 , xmppTellClientHisName xmpp k 904 , xmppTellClientHisName xmpp k
901 ) 905 )
902 PeerKey {} -> ( "jabber:server" 906 PeerKey {} -> ( "jabber:server"
@@ -1240,7 +1244,7 @@ forkConnection :: Server ConnectionKey SockAddr ReleaseKey XML.Event
1240 -> IO (TChan Stanza) 1244 -> IO (TChan Stanza)
1241forkConnection sv xmpp k laddr pingflag src snk stanzas = do 1245forkConnection sv xmpp k laddr pingflag src snk stanzas = do
1242 let (namespace,tellmyname) = case k of 1246 let (namespace,tellmyname) = case k of
1243 ClientKey {} -> ("jabber:client", xmppTellMyNameToClient xmpp) 1247 ClientKey {} -> ("jabber:client", xmppTellMyNameToClient xmpp k)
1244 PeerKey {} -> ("jabber:server",xmppTellMyNameToPeer xmpp laddr) 1248 PeerKey {} -> ("jabber:server",xmppTellMyNameToPeer xmpp laddr)
1245 me <- tellmyname 1249 me <- tellmyname
1246 rdone <- atomically newEmptyTMVar 1250 rdone <- atomically newEmptyTMVar
@@ -1413,14 +1417,15 @@ xmlifyRosterItems solicited stype set = mapM_ item (Set.toList set)
1413sendRoster :: 1417sendRoster ::
1414 StanzaWrap a 1418 StanzaWrap a
1415 -> XMPPServerParameters 1419 -> XMPPServerParameters
1420 -> ConnectionKey
1416 -> TChan Stanza 1421 -> TChan Stanza
1417 -> IO () 1422 -> IO ()
1418sendRoster query xmpp replyto = do 1423sendRoster query xmpp clientKey replyto = do
1419 let k = case stanzaOrigin query of 1424 let k = case stanzaOrigin query of
1420 NetworkOrigin k _ -> Just k 1425 NetworkOrigin k _ -> Just k
1421 LocalPeer -> Nothing -- local peer requested roster? 1426 LocalPeer -> Nothing -- local peer requested roster?
1422 flip (maybe $ return ()) k $ \k -> do 1427 flip (maybe $ return ()) k $ \k -> do
1423 hostname <- xmppTellMyNameToClient xmpp 1428 hostname <- xmppTellMyNameToClient xmpp clientKey
1424 let getlist f = do 1429 let getlist f = do
1425 bs <- f xmpp k 1430 bs <- f xmpp k
1426 return (Set.fromList bs) -- js) 1431 return (Set.fromList bs) -- js)
@@ -1679,10 +1684,11 @@ monitor sv params xmpp = do
1679 case stanzaType stanza of 1684 case stanzaType stanza of
1680 RequestResource clientsNameForMe wanted -> do 1685 RequestResource clientsNameForMe wanted -> do
1681 sockaddr <- socketFromKey sv k 1686 sockaddr <- socketFromKey sv k
1682 rsc <- xmppChooseResourceName xmpp k sockaddr clientsNameForMe wanted 1687 rsc0 <- xmppChooseResourceName xmpp k sockaddr clientsNameForMe wanted
1688 hostname <- xmppTellMyNameToClient xmpp k
1689 let rsc = unsplitJID (n,hostname,r) where (n,_,r) = splitJID rsc0
1683 let reply = iq_bind_reply (stanzaId stanza) rsc 1690 let reply = iq_bind_reply (stanzaId stanza) rsc
1684 -- sendReply quitVar SetResource reply replyto 1691 -- sendReply quitVar SetResource reply replyto
1685 hostname <- xmppTellMyNameToClient xmpp
1686 let requestVersion :: Producer IO XML.Event 1692 let requestVersion :: Producer IO XML.Event
1687 requestVersion = do 1693 requestVersion = do
1688 yield $ EventBeginElement "{jabber:client}iq" 1694 yield $ EventBeginElement "{jabber:client}iq"
@@ -1711,11 +1717,11 @@ monitor sv params xmpp = do
1711 requestVersion 1717 requestVersion
1712 >>= ioWriteChan replyto 1718 >>= ioWriteChan replyto
1713 SessionRequest -> do 1719 SessionRequest -> do
1714 me <- xmppTellMyNameToClient xmpp 1720 me <- xmppTellMyNameToClient xmpp k
1715 let reply = iq_session_reply (stanzaId stanza) me 1721 let reply = iq_session_reply (stanzaId stanza) me
1716 sendReply quitVar Pong reply replyto 1722 sendReply quitVar Pong reply replyto
1717 RequestRoster -> do 1723 RequestRoster -> do
1718 sendRoster stanza xmpp replyto 1724 sendRoster stanza xmpp k replyto
1719 xmppSubscribeToRoster xmpp k 1725 xmppSubscribeToRoster xmpp k
1720 PresenceStatus {} -> do 1726 PresenceStatus {} -> do
1721 xmppInformClientPresence xmpp k stanza 1727 xmppInformClientPresence xmpp k stanza
@@ -1728,7 +1734,7 @@ monitor sv params xmpp = do
1728 NotifyClientVersion name version -> do 1734 NotifyClientVersion name version -> do
1729 enableClientHacks name version replyto 1735 enableClientHacks name version replyto
1730 UnrecognizedQuery query -> do 1736 UnrecognizedQuery query -> do
1731 me <- xmppTellMyNameToClient xmpp 1737 me <- xmppTellMyNameToClient xmpp k
1732 let reply = iq_service_unavailable (stanzaId stanza) me query 1738 let reply = iq_service_unavailable (stanzaId stanza) me query
1733 sendReply quitVar (Error ServiceUnavailable (head reply)) reply replyto 1739 sendReply quitVar (Error ServiceUnavailable (head reply)) reply replyto
1734 Message {} -> do 1740 Message {} -> do