diff options
-rw-r--r-- | Roster.hs | 54 |
1 files changed, 40 insertions, 14 deletions
@@ -1,23 +1,41 @@ | |||
1 | {-# LANGUAGE NamedFieldPuns #-} | 1 | {-# LANGUAGE NamedFieldPuns #-} |
2 | module Roster where | 2 | module Roster where |
3 | 3 | ||
4 | import System.IO | ||
5 | import Control.Monad | ||
6 | import Control.Concurrent.STM | 4 | import Control.Concurrent.STM |
5 | import Control.Monad | ||
7 | import Crypto.PubKey.Curve25519 | 6 | import Crypto.PubKey.Curve25519 |
8 | import qualified Data.HashMap.Strict as HashMap | 7 | import qualified Data.HashMap.Strict as HashMap |
9 | ;import Data.HashMap.Strict (HashMap) | 8 | ;import Data.HashMap.Strict (HashMap) |
9 | import Data.Maybe | ||
10 | import Network.Tox.DHT.Transport as DHT | 10 | import Network.Tox.DHT.Transport as DHT |
11 | import Network.Tox.NodeId | 11 | import Network.Tox.NodeId |
12 | import Network.Tox.Onion.Transport as Onion | 12 | import Network.Tox.Onion.Transport as Onion |
13 | import System.IO | ||
13 | 14 | ||
14 | newtype Roster = Roster { accounts :: TVar (HashMap NodeId Account) } | 15 | newtype Roster = Roster { accounts :: TVar (HashMap NodeId Account) } |
15 | 16 | ||
16 | data Account = Account | 17 | data 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 | ||
22 | data Contact = Contact | ||
23 | { contactKeyPacket :: Maybe (DHT.DHTPublicKey) | ||
24 | , contactFriendRequest :: Maybe (DHT.FriendRequest) | ||
25 | } | ||
26 | |||
27 | mergeContact :: Contact -> Maybe Contact -> Maybe Contact | ||
28 | mergeContact (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 | ||
37 | mergeContact new Nothing = Just new | ||
38 | |||
21 | newRoster :: IO Roster | 39 | newRoster :: IO Roster |
22 | newRoster = atomically $ Roster <$> newTVar HashMap.empty | 40 | newRoster = 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 | ||
45 | updateConcts :: DHT.DHTPublicKey -> Maybe DHT.DHTPublicKey -> Maybe DHT.DHTPublicKey | ||
46 | updateConcts new (Just old) | DHT.dhtpkNonce old < DHT.dhtpkNonce new = Just new | ||
47 | updateConcts new Nothing = Just new | ||
48 | updateConcts _ old = old | ||
49 | |||
50 | |||
51 | updateAccount :: PublicKey -> Onion.OnionData -> Account -> STM () | 63 | updateAccount :: PublicKey -> Onion.OnionData -> Account -> STM () |
52 | updateAccount remoteUserKey (Onion.OnionDHTPublicKey dhtpk) acc = do | 64 | updateAccount 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 | ||
56 | updateAccount remoteUserKey (Onion.OnionFriendRequest fr) acc = do | 68 | updateAccount 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 | ||
60 | dnsPresentation :: Roster -> STM String | 72 | dnsPresentation :: Roster -> STM String |
61 | dnsPresentation (Roster accsvar) = do | 73 | dnsPresentation (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 | ||
70 | dnsPresentation1 :: (NodeId,DHTPublicKey) -> String | 84 | dnsPresentation1 :: (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 | ||
89 | type LocalKey = NodeId | ||
90 | type RemoteKey = NodeId | ||
91 | |||
92 | friendRequests :: Roster -> STM (HashMap LocalKey [(RemoteKey,DHT.FriendRequest)]) | ||
93 | friendRequests (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 | |||