summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Roster.hs54
1 files changed, 40 insertions, 14 deletions
diff --git a/Roster.hs b/Roster.hs
index ab2f9911..7c40e371 100644
--- a/Roster.hs
+++ b/Roster.hs
@@ -1,23 +1,41 @@
1{-# LANGUAGE NamedFieldPuns #-} 1{-# LANGUAGE NamedFieldPuns #-}
2module Roster where 2module Roster where
3 3
4import System.IO
5import Control.Monad
6import Control.Concurrent.STM 4import Control.Concurrent.STM
5import Control.Monad
7import Crypto.PubKey.Curve25519 6import Crypto.PubKey.Curve25519
8import qualified Data.HashMap.Strict as HashMap 7import qualified Data.HashMap.Strict as HashMap
9 ;import Data.HashMap.Strict (HashMap) 8 ;import Data.HashMap.Strict (HashMap)
9import Data.Maybe
10import Network.Tox.DHT.Transport as DHT 10import Network.Tox.DHT.Transport as DHT
11import Network.Tox.NodeId 11import Network.Tox.NodeId
12import Network.Tox.Onion.Transport as Onion 12import Network.Tox.Onion.Transport as Onion
13import System.IO
13 14
14newtype Roster = Roster { accounts :: TVar (HashMap NodeId Account) } 15newtype Roster = Roster { accounts :: TVar (HashMap NodeId Account) }
15 16
16data Account = Account 17data Account = Account
17 { userSecret :: SecretKey -- local secret key 18 { userSecret :: SecretKey -- local secret key
18 , contacts :: TVar (HashMap NodeId DHT.DHTPublicKey) -- received contact info 19 , contacts :: TVar (HashMap NodeId Contact) -- received contact info
19 } 20 }
20 21
22data Contact = Contact
23 { contactKeyPacket :: Maybe (DHT.DHTPublicKey)
24 , contactFriendRequest :: Maybe (DHT.FriendRequest)
25 }
26
27mergeContact :: Contact -> Maybe Contact -> Maybe Contact
28mergeContact (Contact newk newf) (Just (Contact oldk oldf)) =
29 Just (Contact mergek mergef)
30 where
31 mergek = mplus oldk $ do
32 n <- newk
33 stamp <- fmap DHT.dhtpkNonce oldk `mplus` return minBound
34 guard (stamp <= DHT.dhtpkNonce n)
35 return n
36 mergef = mplus oldf newf
37mergeContact new Nothing = Just new
38
21newRoster :: IO Roster 39newRoster :: IO Roster
22newRoster = atomically $ Roster <$> newTVar HashMap.empty 40newRoster = atomically $ Roster <$> newTVar HashMap.empty
23 41
@@ -42,20 +60,14 @@ updateRoster roster Onion.AnnouncedRendezvous{remoteUserKey} (localUserKey,omsg)
42 $ HashMap.lookup (key2id localUserKey) as 60 $ HashMap.lookup (key2id localUserKey) as
43 61
44 62
45updateConcts :: DHT.DHTPublicKey -> Maybe DHT.DHTPublicKey -> Maybe DHT.DHTPublicKey
46updateConcts new (Just old) | DHT.dhtpkNonce old < DHT.dhtpkNonce new = Just new
47updateConcts new Nothing = Just new
48updateConcts _ old = old
49
50
51updateAccount :: PublicKey -> Onion.OnionData -> Account -> STM () 63updateAccount :: PublicKey -> Onion.OnionData -> Account -> STM ()
52updateAccount remoteUserKey (Onion.OnionDHTPublicKey dhtpk) acc = do 64updateAccount remoteUserKey (Onion.OnionDHTPublicKey dhtpk) acc = do
53 modifyTVar' (contacts acc) $ HashMap.alter (updateConcts dhtpk) 65 modifyTVar' (contacts acc) $ HashMap.alter (mergeContact $ Contact (Just dhtpk) Nothing)
54 (key2id remoteUserKey) 66 (key2id remoteUserKey)
55 67
56updateAccount remoteUserKey (Onion.OnionFriendRequest fr) acc = do 68updateAccount remoteUserKey (Onion.OnionFriendRequest fr) acc = do
57 -- TODO 69 modifyTVar' (contacts acc) $ HashMap.alter (mergeContact $ Contact Nothing (Just fr))
58 return () 70 (key2id remoteUserKey)
59 71
60dnsPresentation :: Roster -> STM String 72dnsPresentation :: Roster -> STM String
61dnsPresentation (Roster accsvar) = do 73dnsPresentation (Roster accsvar) = do
@@ -64,7 +76,9 @@ dnsPresentation (Roster accsvar) = do
64 cs <- readTVar cvar 76 cs <- readTVar cvar
65 return $ 77 return $
66 "; local key = " ++ show (key2id $ toPublic sec) ++ "\n" 78 "; local key = " ++ show (key2id $ toPublic sec) ++ "\n"
67 ++ concatMap dnsPresentation1 (HashMap.toList cs) 79 ++ concatMap dnsPresentation1
80 (mapMaybe (\(nid,m) -> ((,) nid) <$> contactKeyPacket m)
81 $ HashMap.toList cs)
68 return $ concat ms 82 return $ concat ms
69 83
70dnsPresentation1 :: (NodeId,DHTPublicKey) -> String 84dnsPresentation1 :: (NodeId,DHTPublicKey) -> String
@@ -72,3 +86,15 @@ dnsPresentation1 (nid,dk) = unlines
72 [ concat [ show nid, ".tox. IN CNAME ", show (key2id $ dhtpk dk), ".dht." ] 86 [ concat [ show nid, ".tox. IN CNAME ", show (key2id $ dhtpk dk), ".dht." ]
73 ] 87 ]
74 88
89type LocalKey = NodeId
90type RemoteKey = NodeId
91
92friendRequests :: Roster -> STM (HashMap LocalKey [(RemoteKey,DHT.FriendRequest)])
93friendRequests (Roster roster) = do
94 accs <- readTVar roster
95 forM accs $ \Account { userSecret = sec, contacts = cvar } -> do
96 cs <- readTVar cvar
97 let remotes = mapMaybe (\(nid,m) -> ((,) nid) <$> contactFriendRequest m)
98 $ HashMap.toList cs
99 return remotes
100