diff options
-rw-r--r-- | ToxToXMPP.hs | 91 |
1 files changed, 61 insertions, 30 deletions
diff --git a/ToxToXMPP.hs b/ToxToXMPP.hs index d6a31f1e..cc3b929d 100644 --- a/ToxToXMPP.hs +++ b/ToxToXMPP.hs | |||
@@ -100,13 +100,23 @@ key2jid nospam key = T.pack $ show $ NoSpamId nsp key | |||
100 | nlo = fromIntegral (0x0FFFF .&. nospam) :: Word16 | 100 | nlo = fromIntegral (0x0FFFF .&. nospam) :: Word16 |
101 | nhi = fromIntegral (0x0FFFF .&. (nospam `shiftR` 16)) :: Word16 | 101 | nhi = fromIntegral (0x0FFFF .&. (nospam `shiftR` 16)) :: Word16 |
102 | 102 | ||
103 | dispatch :: Announcer -> Account -> PresenceState -> ContactEvent -> IO () | 103 | data ToxToXMPP = ToxToXMPP |
104 | dispatch acr acnt st (SessionEstablished theirKey) = return () | 104 | { txAnnouncer :: Announcer |
105 | dispatch acr acnt st (SessionTerminated theirKey) = return () | 105 | , txAccount :: Account |
106 | dispatch acr acnt st (AddrChange theirkey saddr) = return () -- todo | 106 | , txPresence :: PresenceState |
107 | dispatch acr acnt st (PolicyChange theirkey policy ) = return () -- todo | 107 | , txTox :: Tox |
108 | dispatch acr acnt st (OnionRouted theirkey (OnionDHTPublicKey pkey)) = return () -- todo | 108 | } |
109 | dispatch acr acnt st (OnionRouted theirkey (OnionFriendRequest fr) ) = do | 109 | |
110 | dispatch :: ToxToXMPP -> ContactEvent -> IO () | ||
111 | dispatch tx (SessionEstablished theirKey) = stopConnecting tx theirKey | ||
112 | dispatch tx (SessionTerminated theirKey) = startConnecting tx theirKey | ||
113 | dispatch tx (AddrChange theirkey saddr) = return () -- todo | ||
114 | dispatch tx (PolicyChange theirkey policy ) = return () -- todo | ||
115 | dispatch tx (OnionRouted theirkey (OnionDHTPublicKey pkey)) = return () -- todo | ||
116 | dispatch tx (OnionRouted theirkey (OnionFriendRequest fr) ) = do | ||
117 | let ToxToXMPP { txAnnouncer = acr | ||
118 | , txAccount = acnt | ||
119 | , txPresence = st } = tx | ||
110 | k2c <- atomically $ do | 120 | k2c <- atomically $ do |
111 | refs <- readTVar (clientRefs acnt) | 121 | refs <- readTVar (clientRefs acnt) |
112 | k2c <- Map.filterWithKey (\k _ -> k `Set.member` refs) <$> readTVar (keyToChan st) | 122 | k2c <- Map.filterWithKey (\k _ -> k `Set.member` refs) <$> readTVar (keyToChan st) |
@@ -134,28 +144,20 @@ akeyDHTKeyShare announcer me them = atomically $ do | |||
134 | akeyConnect announcer me them = atomically $ do | 144 | akeyConnect announcer me them = atomically $ do |
135 | packAnnounceKey announcer $ "connect:" ++ (take 8 $ show me) ++ ":" ++ show them | 145 | packAnnounceKey announcer $ "connect:" ++ (take 8 $ show me) ++ ":" ++ show them |
136 | 146 | ||
137 | forkAccountWatcher :: Account -> Tox -> PresenceState -> Announcer -> IO ThreadId | 147 | startConnecting0 :: ToxToXMPP -> PublicKey -> Contact -> IO () |
138 | forkAccountWatcher acc tox st announcer = forkIO $ do | 148 | startConnecting0 tx them contact = do |
139 | myThreadId >>= flip labelThread ("tox-xmpp:" | 149 | let ToxToXMPP { txTox = tox |
140 | ++ show (key2id $ toPublic $ userSecret acc)) | 150 | , txAnnouncer = announcer |
141 | (chan,contacts) <- atomically $ do | 151 | , txAccount = acnt } = tx |
142 | chan <- dupTChan $ eventChan acc -- duplicate broadcast channel for reading. | 152 | let nearNodes nid = do |
143 | contacts <- readTVar (contacts acc) | 153 | bkts4 <- readTVar $ routing4 $ toxRouting tox |
144 | return (chan,contacts) | 154 | bkts6 <- readTVar $ routing6 $ toxRouting tox |
145 | -- TODO: process information in contacts HashMap. | 155 | let nss = map (R.kclosest (searchSpace (toxQSearch tox)) searchK nid) |
146 | 156 | [bkts4,bkts6] | |
147 | let nearNodes nid = do | 157 | return $ foldr interweave [] nss |
148 | bkts4 <- readTVar $ routing4 $ toxRouting tox | 158 | wanted <- atomically $ (==Just TryingToConnect) <$> readTVar (contactPolicy contact) |
149 | bkts6 <- readTVar $ routing6 $ toxRouting tox | ||
150 | let nss = map (R.kclosest (searchSpace (toxQSearch tox)) searchK nid) | ||
151 | [bkts4,bkts6] | ||
152 | return $ foldr interweave [] nss | ||
153 | |||
154 | |||
155 | forM_ (HashMap.toList contacts) $ \(them,Contact{contactPolicy}) -> do | ||
156 | wanted <- atomically $ (==Just TryingToConnect) <$> readTVar contactPolicy | ||
157 | when wanted $ do | 159 | when wanted $ do |
158 | let pub = toPublic $ userSecret acc | 160 | let pub = toPublic $ userSecret acnt |
159 | me = key2id pub | 161 | me = key2id pub |
160 | akey <- akeyDHTKeyShare announcer me them | 162 | akey <- akeyDHTKeyShare announcer me them |
161 | -- We send this packet every 30 seconds if there is more | 163 | -- We send this packet every 30 seconds if there is more |
@@ -183,12 +185,40 @@ forkAccountWatcher acc tox st announcer = forkIO $ do | |||
183 | (Tox.AnnouncedRendezvous theirkey rendezvous) | 185 | (Tox.AnnouncedRendezvous theirkey rendezvous) |
184 | (pub,Tox.OnionDHTPublicKey dkey)) | 186 | (pub,Tox.OnionDHTPublicKey dkey)) |
185 | nearNodes | 187 | nearNodes |
186 | them | 188 | (key2id them) |
187 | 30) -- every 30 seconds | 189 | 30) -- every 30 seconds |
188 | pub | 190 | pub |
189 | 191 | ||
192 | startConnecting :: ToxToXMPP -> PublicKey -> IO () | ||
193 | startConnecting tx them = do | ||
194 | mc <- atomically $ HashMap.lookup (key2id them) | ||
195 | <$> readTVar (contacts $ txAccount tx) | ||
196 | forM_ mc $ startConnecting0 tx them | ||
190 | 197 | ||
191 | 198 | ||
199 | stopConnecting :: ToxToXMPP -> PublicKey -> IO () | ||
200 | stopConnecting ToxToXMPP{txAnnouncer=announcer,txAccount=acnt} them = do | ||
201 | let pub = toPublic $ userSecret acnt | ||
202 | me = key2id pub | ||
203 | akey <- akeyDHTKeyShare announcer me them | ||
204 | cancel announcer akey | ||
205 | |||
206 | forkAccountWatcher :: Account -> Tox -> PresenceState -> Announcer -> IO ThreadId | ||
207 | forkAccountWatcher acc tox st announcer = forkIO $ do | ||
208 | myThreadId >>= flip labelThread ("tox-xmpp:" | ||
209 | ++ show (key2id $ toPublic $ userSecret acc)) | ||
210 | (chan,contacts) <- atomically $ do | ||
211 | chan <- dupTChan $ eventChan acc -- duplicate broadcast channel for reading. | ||
212 | contacts <- readTVar (contacts acc) | ||
213 | return (chan,contacts) | ||
214 | let tx = ToxToXMPP { txAnnouncer = announcer | ||
215 | , txAccount = acc | ||
216 | , txPresence = st | ||
217 | , txTox = tox | ||
218 | } | ||
219 | forM_ (HashMap.toList contacts) $ \(them,c) -> do | ||
220 | startConnecting0 tx (id2key them) c | ||
221 | |||
192 | -- Loop endlessly until clientRefs is null. | 222 | -- Loop endlessly until clientRefs is null. |
193 | fix $ \loop -> do | 223 | fix $ \loop -> do |
194 | mev <- atomically $ | 224 | mev <- atomically $ |
@@ -197,7 +227,8 @@ forkAccountWatcher acc tox st announcer = forkIO $ do | |||
197 | refs <- readTVar $ clientRefs acc | 227 | refs <- readTVar $ clientRefs acc |
198 | check $ Set.null refs | 228 | check $ Set.null refs |
199 | return Nothing | 229 | return Nothing |
200 | forM_ mev $ \ev -> dispatch announcer acc st ev >> loop | 230 | |
231 | forM_ mev $ \ev -> dispatch tx ev >> loop | ||
201 | 232 | ||
202 | toxQSearch :: Tox.Tox -> Search Tox.NodeId (IP, PortNumber) Nonce32 Tox.NodeInfo Tox.Rendezvous | 233 | toxQSearch :: Tox.Tox -> Search Tox.NodeId (IP, PortNumber) Nonce32 Tox.NodeInfo Tox.Rendezvous |
203 | toxQSearch tox = Tox.toxidSearch (Tox.onionTimeout tox) (Tox.toxCryptoKeys tox) (Tox.toxOnion tox) | 234 | toxQSearch tox = Tox.toxidSearch (Tox.onionTimeout tox) (Tox.toxCryptoKeys tox) (Tox.toxOnion tox) |