summaryrefslogtreecommitdiff
path: root/Presence
diff options
context:
space:
mode:
authorjoe <joe@jerkface.net>2017-11-21 00:05:07 -0500
committerjoe <joe@jerkface.net>2017-11-21 00:05:07 -0500
commit48ff993d35b45225cde3e0fbc6ebb775f3be4443 (patch)
tree8d1b3a1720b8fb134e3dd495511d32052dc5910b /Presence
parent99df8d61a79dd93fb8f2df28cfda1667ad6a47ab (diff)
Interface to enable Tox users in an XMPP client's roster.
Diffstat (limited to 'Presence')
-rw-r--r--Presence/ConfigFiles.hs3
-rw-r--r--Presence/Presence.hs61
2 files changed, 55 insertions, 9 deletions
diff --git a/Presence/ConfigFiles.hs b/Presence/ConfigFiles.hs
index b745094f..d405bd8f 100644
--- a/Presence/ConfigFiles.hs
+++ b/Presence/ConfigFiles.hs
@@ -151,3 +151,6 @@ getPending user profile = configPath user profile pendingFile >>= getConfigList
151 151
152getSolicited :: User -> Profile -> IO [ByteString] 152getSolicited :: User -> Profile -> IO [ByteString]
153getSolicited user profile = configPath user profile solicitedFile >>= getConfigList 153getSolicited user profile = configPath user profile solicitedFile >>= getConfigList
154
155getSecrets :: User -> Profile -> IO [ByteString]
156getSecrets user profile = configPath user profile secretsFile >>= getConfigList
diff --git a/Presence/Presence.hs b/Presence/Presence.hs
index 4cb6266a..77689d1e 100644
--- a/Presence/Presence.hs
+++ b/Presence/Presence.hs
@@ -38,6 +38,8 @@ import Data.Int (Int8)
38import Data.XML.Types (Event) 38import Data.XML.Types (Event)
39import System.Posix.Types (UserID,CPid) 39import System.Posix.Types (UserID,CPid)
40import Control.Applicative 40import Control.Applicative
41import Crypto.Error.Types (CryptoFailable (..))
42import Crypto.PubKey.Curve25519 (publicKey, secretKey, toPublic)
41 43
42import LockedChan (LockedChan) 44import LockedChan (LockedChan)
43import TraversableT 45import TraversableT
@@ -63,6 +65,12 @@ localJID user "." resource = do
63localJID user profile resource = 65localJID user profile resource =
64 return $ user <> "@" <> profile <> "/" <> resource 66 return $ user <> "@" <> profile <> "/" <> resource
65 67
68data ToxManager k = ToxManager
69 { activateAccount :: k -> Text -> IO ()
70 , deactivateAccount :: k -> Text -> IO ()
71 , setToxConnectionPolicy :: Text -> Text -> Connection.Policy -> IO ()
72 }
73
66data PresenceState = forall status. PresenceState 74data PresenceState = forall status. PresenceState
67 { clients :: TVar (Map ConnectionKey ClientState) 75 { clients :: TVar (Map ConnectionKey ClientState)
68 , clientsByUser :: TVar (Map Text LocalPresence) 76 , clientsByUser :: TVar (Map Text LocalPresence)
@@ -71,24 +79,27 @@ data PresenceState = forall status. PresenceState
71 , server :: TMVar (XMPPServer, Connection.Manager status Text) 79 , server :: TMVar (XMPPServer, Connection.Manager status Text)
72 , keyToChan :: TVar (Map ConnectionKey Conn) 80 , keyToChan :: TVar (Map ConnectionKey Conn)
73 , consoleWriter :: Maybe ConsoleWriter 81 , consoleWriter :: Maybe ConsoleWriter
82 , toxManager :: Maybe (ToxManager ConnectionKey)
74 } 83 }
75 84
76 85
77newPresenceState :: Maybe ConsoleWriter 86newPresenceState :: Maybe ConsoleWriter
87 -> Maybe (ToxManager ConnectionKey)
78 -> TMVar (XMPPServer, Connection.Manager status Text) 88 -> TMVar (XMPPServer, Connection.Manager status Text)
79 -> IO PresenceState 89 -> IO PresenceState
80newPresenceState cw xmpp = atomically $ do 90newPresenceState cw toxman xmpp = atomically $ do
81 clients <- newTVar Map.empty 91 clients <- newTVar Map.empty
82 clientsByUser <- newTVar Map.empty 92 clientsByUser <- newTVar Map.empty
83 remotesByPeer <- newTVar Map.empty 93 remotesByPeer <- newTVar Map.empty
84 keyToChan <- newTVar Map.empty 94 keyToChan <- newTVar Map.empty
85 return PresenceState 95 return PresenceState
86 { clients = clients 96 { clients = clients
87 , clientsByUser = clientsByUser 97 , clientsByUser = clientsByUser
88 , remotesByPeer = remotesByPeer 98 , remotesByPeer = remotesByPeer
89 , keyToChan = keyToChan 99 , keyToChan = keyToChan
90 , server = xmpp 100 , server = xmpp
91 , consoleWriter = cw 101 , consoleWriter = cw
102 , toxManager = toxman
92 } 103 }
93 104
94 105
@@ -178,9 +189,26 @@ chooseResourceName state k addr clientsNameForMe desired = do
178 user <- getJabberUserForId muid 189 user <- getJabberUserForId muid
179 status <- atomically $ newTVar Nothing 190 status <- atomically $ newTVar Nothing
180 flgs <- atomically $ newTVar 0 191 flgs <- atomically $ newTVar 0
181 profile <- fmap (fromMaybe ".") $ forM clientsNameForMe $ \wanted_profile -> do 192 profile <- fmap (fromMaybe ".")
182 -- TODO: allow user to select profile 193 $ forM ((,) <$> clientsNameForMe <*> toxManager state) $ \(wanted_profile,toxman) ->
183 return "." 194 case Text.splitAt 43 wanted_profile of
195 (pub,".tox") -> do
196 -- TODO: Tox key profile.
197 secs <- configText ConfigFiles.getSecrets user wanted_profile
198 case secs of
199 sec:_ | CryptoPassed s <- secretKey (Text.encodeUtf8 sec)
200 , CryptoPassed (toPublic s) == publicKey (Text.encodeUtf8 pub)
201 -> do activateAccount toxman k wanted_profile
202 return wanted_profile
203 _ -> do
204 -- XXX: We should probably fail to connect when an
205 -- invalid Tox profile is used. For now, we'll
206 -- fall back to the Unix account login.
207 return "."
208 ("*.tox","") -> do
209 -- TODO: Match single tox key profile or generate first.
210 _todo
211 _ -> return "."
184 let client = ClientState { clientResource = maybe "fallback" id mtty 212 let client = ClientState { clientResource = maybe "fallback" id mtty
185 , clientUser = user 213 , clientUser = user
186 , clientProfile = profile 214 , clientProfile = profile
@@ -257,7 +285,13 @@ rosterGetStuff what state k = forClient state k (return [])
257 PresenceState { server = svVar } -> do 285 PresenceState { server = svVar } -> do
258 (sv,conns) <- atomically $ takeTMVar svVar 286 (sv,conns) <- atomically $ takeTMVar svVar
259 -- Grok peers to associate with from the roster: 287 -- Grok peers to associate with from the roster:
260 forM_ hosts $ \host -> Connection.setPolicy conns host Connection.TryingToConnect 288 forM_ hosts $ \host -> do
289 let policySetter = fromMaybe (Connection.setPolicy conns host) $ do
290 toxman <- toxManager state
291 (me , ".tox") <- Just $ Text.splitAt 43 (clientProfile client)
292 (them, ".tox") <- Just $ Text.splitAt 43 host
293 Just $ setToxConnectionPolicy toxman (clientProfile client) host
294 policySetter Connection.TryingToConnect
261 atomically $ putTMVar svVar (sv,conns) 295 atomically $ putTMVar svVar (sv,conns)
262 return jids 296 return jids
263 297
@@ -348,6 +382,10 @@ eofConn state k = do
348 case k of 382 case k of
349 ClientKey {} -> do 383 ClientKey {} -> do
350 forClient state k (return ()) $ \client -> do 384 forClient state k (return ()) $ \client -> do
385 forM_ (toxManager state) $ \toxman -> do
386 case Text.splitAt 43 (clientProfile client) of
387 (pub,".tox") -> deactivateAccount toxman k (clientProfile client)
388 _ -> return ()
351 stanza <- makePresenceStanza "jabber:server" Nothing Offline 389 stanza <- makePresenceStanza "jabber:server" Nothing Offline
352 informClientPresence state k stanza 390 informClientPresence state k stanza
353 atomically $ do 391 atomically $ do
@@ -870,8 +908,13 @@ clientSubscriptionRequest state fail k stanza chan = do
870 , stanzaFrom = Just from }) 908 , stanzaFrom = Just from })
871 (connChan con) 909 (connChan con)
872 let addrm = Map.fromList (map (,()) addrs) 910 let addrm = Map.fromList (map (,()) addrs)
911 policySetter = fromMaybe (Connection.setPolicy conns h) $ do
912 toxman <- toxManager state
913 (me , ".tox") <- Just $ Text.splitAt 43 (clientProfile client)
914 (them, ".tox") <- Just $ Text.splitAt 43 h
915 Just $ setToxConnectionPolicy toxman (clientProfile client) h
873 -- Add peer if we are not already associated ... 916 -- Add peer if we are not already associated ...
874 Connection.setPolicy conns h Connection.TryingToConnect 917 policySetter Connection.TryingToConnect
875 atomically $ putTMVar svVar (sv,conns) 918 atomically $ putTMVar svVar (sv,conns)
876 919
877 920