diff options
-rw-r--r-- | Presence/ConfigFiles.hs | 3 | ||||
-rw-r--r-- | Presence/Presence.hs | 61 | ||||
-rw-r--r-- | examples/dhtd.hs | 8 |
3 files changed, 62 insertions, 10 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 | ||
152 | getSolicited :: User -> Profile -> IO [ByteString] | 152 | getSolicited :: User -> Profile -> IO [ByteString] |
153 | getSolicited user profile = configPath user profile solicitedFile >>= getConfigList | 153 | getSolicited user profile = configPath user profile solicitedFile >>= getConfigList |
154 | |||
155 | getSecrets :: User -> Profile -> IO [ByteString] | ||
156 | getSecrets 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) | |||
38 | import Data.XML.Types (Event) | 38 | import Data.XML.Types (Event) |
39 | import System.Posix.Types (UserID,CPid) | 39 | import System.Posix.Types (UserID,CPid) |
40 | import Control.Applicative | 40 | import Control.Applicative |
41 | import Crypto.Error.Types (CryptoFailable (..)) | ||
42 | import Crypto.PubKey.Curve25519 (publicKey, secretKey, toPublic) | ||
41 | 43 | ||
42 | import LockedChan (LockedChan) | 44 | import LockedChan (LockedChan) |
43 | import TraversableT | 45 | import TraversableT |
@@ -63,6 +65,12 @@ localJID user "." resource = do | |||
63 | localJID user profile resource = | 65 | localJID user profile resource = |
64 | return $ user <> "@" <> profile <> "/" <> resource | 66 | return $ user <> "@" <> profile <> "/" <> resource |
65 | 67 | ||
68 | data ToxManager k = ToxManager | ||
69 | { activateAccount :: k -> Text -> IO () | ||
70 | , deactivateAccount :: k -> Text -> IO () | ||
71 | , setToxConnectionPolicy :: Text -> Text -> Connection.Policy -> IO () | ||
72 | } | ||
73 | |||
66 | data PresenceState = forall status. PresenceState | 74 | data 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 | ||
77 | newPresenceState :: Maybe ConsoleWriter | 86 | newPresenceState :: 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 |
80 | newPresenceState cw xmpp = atomically $ do | 90 | newPresenceState 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 | ||
diff --git a/examples/dhtd.hs b/examples/dhtd.hs index d5310f57..ed7d5e63 100644 --- a/examples/dhtd.hs +++ b/examples/dhtd.hs | |||
@@ -1027,10 +1027,16 @@ main = runResourceT $ liftBaseWith $ \resT -> do | |||
1027 | 1027 | ||
1028 | announcer <- forkAnnouncer | 1028 | announcer <- forkAnnouncer |
1029 | 1029 | ||
1030 | let toxman = ToxManager | ||
1031 | { activateAccount = \k pubkey -> return () | ||
1032 | , deactivateAccount = \k pubkey -> return () | ||
1033 | , setToxConnectionPolicy = \me them policy -> return () | ||
1034 | } | ||
1035 | |||
1030 | -- XMPP initialization | 1036 | -- XMPP initialization |
1031 | cw <- newConsoleWriter | 1037 | cw <- newConsoleWriter |
1032 | serverVar <- atomically $ newEmptyTMVar | 1038 | serverVar <- atomically $ newEmptyTMVar |
1033 | state <- newPresenceState cw serverVar | 1039 | state <- newPresenceState cw (Just toxman) serverVar |
1034 | 1040 | ||
1035 | -- XMPP stanza handling | 1041 | -- XMPP stanza handling |
1036 | sv <- resT $ xmppServer (presenceHooks state (verbosity opts)) | 1042 | sv <- resT $ xmppServer (presenceHooks state (verbosity opts)) |