summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ToxToXMPP.hs120
1 files changed, 94 insertions, 26 deletions
diff --git a/ToxToXMPP.hs b/ToxToXMPP.hs
index 8d28507a..8c57da5a 100644
--- a/ToxToXMPP.hs
+++ b/ToxToXMPP.hs
@@ -1,8 +1,8 @@
1{-# LANGUAGE ViewPatterns #-}
2{-# LANGUAGE CPP #-} 1{-# LANGUAGE CPP #-}
3{-# LANGUAGE LambdaCase #-} 2{-# LANGUAGE LambdaCase #-}
4{-# LANGUAGE NamedFieldPuns #-} 3{-# LANGUAGE NamedFieldPuns #-}
5{-# LANGUAGE NondecreasingIndentation #-} 4{-# LANGUAGE NondecreasingIndentation #-}
5{-# LANGUAGE ViewPatterns #-}
6module ToxToXMPP 6module ToxToXMPP
7 ( forkAccountWatcher 7 ( forkAccountWatcher
8 , JabberClients 8 , JabberClients
@@ -20,14 +20,15 @@ import qualified Data.Conduit.List as CL
20import Data.XML.Types as XML 20import Data.XML.Types as XML
21import EventUtil 21import EventUtil
22import Network.Tox.Crypto.Transport as Tox 22import Network.Tox.Crypto.Transport as Tox
23import Network.Tox.Handshake (HandshakeParams (..))
23import Util (unsplitJID) 24import Util (unsplitJID)
24import XMPPServer as XMPP 25import XMPPServer as XMPP
25 26
26import Network.Tox.DHT.Handlers (nodeSearch, nodesOfInterest)
27import Announcer 27import Announcer
28import Announcer.Tox 28import Announcer.Tox
29import Connection 29import Connection
30import Network.QueryResponse 30import Network.QueryResponse
31import Network.Tox.DHT.Handlers (nodeSearch, nodesOfInterest)
31-- import Control.Concurrent 32-- import Control.Concurrent
32import Control.Concurrent.STM 33import Control.Concurrent.STM
33import Control.Monad 34import Control.Monad
@@ -42,6 +43,7 @@ import Network.Kademlia.Search
42import qualified Network.Tox as Tox 43import qualified Network.Tox as Tox
43import Network.Tox.ContactInfo as Tox 44import Network.Tox.ContactInfo as Tox
44import qualified Network.Tox.Crypto.Handlers as Tox 45import qualified Network.Tox.Crypto.Handlers as Tox
46 ;import Network.Tox.Crypto.Handlers (UponCookie (..))
45-- import qualified Network.Tox.DHT.Handlers as Tox 47-- import qualified Network.Tox.DHT.Handlers as Tox
46import ClientState 48import ClientState
47import Data.Bits 49import Data.Bits
@@ -69,6 +71,7 @@ import GHC.Conc (labelThread)
69#endif 71#endif
70import DPut 72import DPut
71import Nesting 73import Nesting
74import qualified Network.Tox.DHT.Handlers
72 75
73xmppToTox :: Conduit XML.Event IO Tox.CryptoMessage 76xmppToTox :: Conduit XML.Event IO Tox.CryptoMessage
74xmppToTox = doNestingXML $ do 77xmppToTox = doNestingXML $ do
@@ -159,22 +162,39 @@ gotDhtPubkey pubkey tx theirKey = do
159 now <- getPOSIXTime 162 now <- getPOSIXTime
160 when (now - tm > nodeinfoStaleTime) doSearch 163 when (now - tm > nodeinfoStaleTime) doSearch
161 where 164 where
165 tox :: Tox JabberClients
166 tox = txTox tx
167
168 myPublicKey = toPublic $ userSecret (txAccount tx)
169 me = key2id myPublicKey
170
162 doSearch = do 171 doSearch = do
163 let pub = toPublic $ userSecret (txAccount tx)
164 me = key2id pub
165 akey <- akeyConnect (txAnnouncer tx) me theirKey 172 akey <- akeyConnect (txAnnouncer tx) me theirKey
166 atomically $ registerNodeCallback (toxRouting tox) (nic akey) 173 atomically $ registerNodeCallback (toxRouting tox) (nic akey)
167 scheduleSearch (txAnnouncer tx) akey meth pubkey 174 scheduleSearch (txAnnouncer tx) akey meth pubkey
168 tox :: Tox JabberClients 175
169 tox = txTox tx
170 byAddr :: TVar (Map.Map SockAddr Tox.NetCryptoSession) 176 byAddr :: TVar (Map.Map SockAddr Tox.NetCryptoSession)
171 byAddr = Tox.netCryptoSessions (toxCryptoSessions tox) 177 byAddr = Tox.netCryptoSessions (toxCryptoSessions tox)
178
179 crypto = Tox.transportCrypto $ toxCryptoSessions tox
180
181 readNcVar :: (Tox.NetCryptoSession -> TVar b) -> SockAddr -> STM (Maybe b)
182 readNcVar v addr = traverse readTVar =<< fmap v . Map.lookup addr <$> readTVar byAddr
183
172 chillSesh :: SockAddr -> STM (Maybe (Status Tox.ToxProgress)) 184 chillSesh :: SockAddr -> STM (Maybe (Status Tox.ToxProgress))
173 chillSesh addr = traverse readTVar =<< fmap Tox.ncState . Map.lookup addr <$> readTVar byAddr 185 chillSesh = readNcVar Tox.ncState
186
174 activeSesh :: SockAddr -> STM Bool 187 activeSesh :: SockAddr -> STM Bool
175 activeSesh a = chillSesh a >>= return . \case 188 activeSesh a = chillSesh a >>= return . \case
176 Just Established -> True 189 Just Established -> True
177 _ -> False 190 _ -> False
191
192 readCookie :: SockAddr -> STM (Maybe (UponCookie (Tox.Cookie Encrypted)))
193 readCookie = readNcVar Tox.ncCookie
194 readCookie' :: SockAddr -> STM (Maybe (Tox.Cookie Encrypted))
195 readCookie' = fmap join . (fmap.fmap) Tox.toMaybe . readCookie
196
197 target :: NodeId
178 target = key2id $ dhtpk pubkey 198 target = key2id $ dhtpk pubkey
179 meth :: SearchMethod Tox.DHTPublicKey 199 meth :: SearchMethod Tox.DHTPublicKey
180 meth = 200 meth =
@@ -193,36 +213,84 @@ gotDhtPubkey pubkey tx theirKey = do
193 , rumoredAddress = assume akey 213 , rumoredAddress = assume akey
194 } 214 }
195 215
216 client :: Network.Tox.DHT.Handlers.Client
217 client = toxDHT tox
218
196 assume :: AnnounceKey -> POSIXTime -> SockAddr -> NodeInfo -> STM () 219 assume :: AnnounceKey -> POSIXTime -> SockAddr -> NodeInfo -> STM ()
197 assume akey time addr ni = 220 assume akey time addr ni =
198 tput XNodeinfoSearch $ show ("rumor", akey, time, addr, ni) 221 tput XNodeinfoSearch $ show ("rumor", akey, time, addr, ni)
199 222
200 observe :: AnnounceKey -> POSIXTime -> NodeInfo -> STM () 223 observe :: AnnounceKey -> POSIXTime -> NodeInfo -> STM ()
201 observe akey time (nodeAddr -> addr) = do 224 observe akey time ni@(nodeAddr -> addr) = do
202 tput XNodeinfoSearch $ show ("observation", akey, time, addr) 225 tput XNodeinfoSearch $ show ("observation", akey, time, addr)
203 scheduleImmediately (txAnnouncer tx) akey $ 226 scheduleImmediately (txAnnouncer tx) akey $
204 ScheduledItem $ shakeHands (activeSesh addr) (getContact theirKey (txAccount tx)) 227 ScheduledItem $ getCookie ni (activeSesh addr) (getContact theirKey (txAccount tx))
205 setContactAddr time theirKey addr (txAccount tx) 228 setContactAddr time theirKey addr (txAccount tx)
206 229
207shakeHands :: STM Bool -> STM (Maybe Contact) -> Announcer -> AnnounceKey -> POSIXTime -> STM (IO ()) 230 getCookie
208shakeHands isActive getC ann akey now = do 231 :: NodeInfo
209 mbContact <- getC 232 -> STM Bool
210 case mbContact of 233 -> STM (Maybe Contact)
211 Nothing -> return $ return () 234 -> Announcer
212 Just contact -> do 235 -> AnnounceKey
213 active <- isActive 236 -> POSIXTime
214 if (not active) then do 237 -> STM (IO ())
215 scheduleRel ann akey (ScheduledItem $ shakeHands isActive getC) 5 238 getCookie ni isActive getC ann akey now = fix $ \goBack -> do
216 return $ shakeHandsIO contact 239 mbContact <- getC
217 else 240 case mbContact of
218 return $ return () 241 Nothing -> return $ return ()
219 242 Just contact -> do
220shakeHandsIO :: Contact -> IO () 243 active <- isActive
221shakeHandsIO _ = return () 244 return $ when (not active) (getCookieIO goBack)
245
246 where
247
248 callRealShakeHands = realShakeHands (userSecret (txAccount tx)) theirKey (dhtpk pubkey) (toxCryptoSessions tox) (nodeAddr ni)
249
250 reschedule n f = scheduleRel ann akey f n
251 reschedule' n f = reschedule n (ScheduledItem $ \_ _ now -> f now)
252
253 cookieMaxAge = 60 * 5
254
255 getCookieIO :: STM (IO ()) -> IO ()
256 getCookieIO getCookieAgain = do
257 cookieRequest crypto client myPublicKey ni >>= \case
258 Nothing -> atomically $ reschedule' 5 (const getCookieAgain)
259 Just cookie -> do
260 void $ callRealShakeHands cookie
261 cookieCreationStamp <- getPOSIXTime
262 let shaker :: POSIXTime -> STM (IO ())
263 shaker now = do
264 if (now > cookieCreationStamp + cookieMaxAge)
265 then return (getCookieIO getCookieAgain)
266 else do
267 reschedule' 5 shaker
268 return . void $ callRealShakeHands cookie
269 atomically $ reschedule' 5 shaker
270
271realShakeHands :: SecretKey -> PublicKey -> PublicKey -> Tox.NetCryptoSessions -> SockAddr -> Tox.Cookie Encrypted -> IO Bool
272realShakeHands myseckey theirpubkey theirDhtKey allsessions saddr cookie = do
273 let hp =
274 HParam
275 { hpOtherCookie = cookie
276 , hpMySecretKey = myseckey
277 , hpCookieRemotePubkey = theirpubkey
278 , hpCookieRemoteDhtkey = theirDhtKey
279 , hpTheirBaseNonce = Nothing
280 , hpTheirSessionKeyPublic = Nothing
281 }
282 newsession <- generateSecretKey
283 timestamp <- getPOSIXTime
284 (myhandshake, ioAction) <-
285 atomically $
286 Tox.freshCryptoSession allsessions saddr newsession timestamp hp
287 ioAction
288 -- send handshake
289 isJust <$> forM myhandshake (Tox.sendHandshake allsessions saddr)
222 290
223dispatch :: ToxToXMPP -> ContactEvent -> IO () 291dispatch :: ToxToXMPP -> ContactEvent -> IO ()
224dispatch tx (SessionEstablished theirKey) = stopConnecting tx theirKey 292dispatch tx (SessionEstablished theirKey) = stopConnecting tx theirKey
225dispatch tx (SessionTerminated theirKey) = startConnecting tx theirKey 293dispatch tx (SessionTerminated theirKey) = startConnecting tx theirKey
226dispatch tx (AddrChange theirkey saddr) = return () -- todo 294dispatch tx (AddrChange theirkey saddr) = return () -- todo
227dispatch tx (PolicyChange theirkey TryingToConnect ) = startConnecting tx theirkey 295dispatch tx (PolicyChange theirkey TryingToConnect ) = startConnecting tx theirkey
228dispatch tx (PolicyChange theirkey policy ) = stopConnecting tx theirkey 296dispatch tx (PolicyChange theirkey policy ) = stopConnecting tx theirkey