diff options
Diffstat (limited to 'Presence')
-rw-r--r-- | Presence/ConfigFiles.hs | 2 | ||||
-rw-r--r-- | Presence/Presence.hs | 34 | ||||
-rw-r--r-- | Presence/XMPPServer.hs | 26 |
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" | |||
30 | otherFile = "others" | 30 | otherFile = "others" |
31 | pendingFile = "pending" | 31 | pendingFile = "pending" |
32 | solicitedFile = "solicited" | 32 | solicitedFile = "solicited" |
33 | secretsFile = "secrets" | 33 | secretsFile = "secret" |
34 | 34 | ||
35 | 35 | ||
36 | configPath :: User -> Profile -> String -> IO String | 36 | configPath :: 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 #-} |
6 | module Presence where | 6 | module Presence where |
7 | 7 | ||
8 | import System.Directory | ||
8 | import System.Environment | 9 | import System.Environment |
10 | import System.IO.Error | ||
9 | import System.Posix.Signals | 11 | import System.Posix.Signals |
10 | import Control.Concurrent (threadDelay,forkIO,forkOS,killThread,throwTo) | 12 | import Control.Concurrent (threadDelay,forkIO,forkOS,killThread,throwTo) |
11 | import Control.Concurrent.STM | 13 | import Control.Concurrent.STM |
@@ -15,6 +17,7 @@ import Control.Monad.Trans | |||
15 | import Control.Monad.IO.Class (MonadIO, liftIO) | 17 | import Control.Monad.IO.Class (MonadIO, liftIO) |
16 | import Network.Socket ( SockAddr(..), PortNumber ) | 18 | import Network.Socket ( SockAddr(..), PortNumber ) |
17 | import System.Endian (fromBE32) | 19 | import System.Endian (fromBE32) |
20 | import Data.Char | ||
18 | import Data.List (nub, (\\), intersect, groupBy, sort, sortBy ) | 21 | import Data.List (nub, (\\), intersect, groupBy, sort, sortBy ) |
19 | import Data.Ord (comparing ) | 22 | import Data.Ord (comparing ) |
20 | import Data.Monoid ( (<>), Sum(..), getSum ) | 23 | import Data.Monoid ( (<>), Sum(..), getSum ) |
@@ -46,6 +49,7 @@ import Crypto.Error | |||
46 | #endif | 49 | #endif |
47 | import Crypto.PubKey.Curve25519 (SecretKey,toPublic) | 50 | import Crypto.PubKey.Curve25519 (SecretKey,toPublic) |
48 | import Text.Read (readMaybe) | 51 | import Text.Read (readMaybe) |
52 | import System.IO | ||
49 | 53 | ||
50 | import LockedChan (LockedChan) | 54 | import LockedChan (LockedChan) |
51 | import TraversableT | 55 | import TraversableT |
@@ -57,7 +61,7 @@ import ConsoleWriter | |||
57 | import ClientState | 61 | import ClientState |
58 | import Util | 62 | import Util |
59 | import qualified Connection | 63 | import qualified Connection |
60 | import Network.Tox.NodeId (id2key) | 64 | import Network.Tox.NodeId (id2key,key2id) |
61 | import Crypto.Tox (decodeSecret) | 65 | import Crypto.Tox (decodeSecret) |
62 | 66 | ||
63 | isPeerKey :: ConnectionKey -> Bool | 67 | isPeerKey :: ConnectionKey -> Bool |
@@ -124,11 +128,22 @@ newPresenceState cw toxman xmpp = atomically $ do | |||
124 | } | 128 | } |
125 | 129 | ||
126 | 130 | ||
131 | nameForClient :: PresenceState -> ConnectionKey -> IO Text | ||
132 | nameForClient 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 | |||
127 | presenceHooks :: PresenceState -> Int -> Maybe PortNumber -> XMPPServerParameters | 142 | presenceHooks :: PresenceState -> Int -> Maybe PortNumber -> XMPPServerParameters |
128 | presenceHooks state verbosity mport = XMPPServerParameters | 143 | presenceHooks 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) | |||
89 | import Control.Applicative | 89 | import Control.Applicative |
90 | import System.IO | 90 | import System.IO |
91 | import qualified Connection | 91 | import qualified Connection |
92 | import Util | ||
92 | 93 | ||
93 | peerport :: PortNumber | 94 | peerport :: PortNumber |
94 | peerport = 5269 | 95 | peerport = 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 | |||
896 | xmppInbound sv xmpp k laddr pingflag stanzas output donevar = doNestingXML $ do | 900 | xmppInbound 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) |
1241 | forkConnection sv xmpp k laddr pingflag src snk stanzas = do | 1245 | forkConnection 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) | |||
1413 | sendRoster :: | 1417 | sendRoster :: |
1414 | StanzaWrap a | 1418 | StanzaWrap a |
1415 | -> XMPPServerParameters | 1419 | -> XMPPServerParameters |
1420 | -> ConnectionKey | ||
1416 | -> TChan Stanza | 1421 | -> TChan Stanza |
1417 | -> IO () | 1422 | -> IO () |
1418 | sendRoster query xmpp replyto = do | 1423 | sendRoster 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 |