summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Cady <d@jerkface.net>2018-06-18 15:13:55 -0400
committerAndrew Cady <d@jerkface.net>2018-06-18 15:13:55 -0400
commit58ba472d59c2c20a9c525c36cf36ad02c1826331 (patch)
tree6a6f20f9af71bfd6c0a632d7e321d709df8d81a6
parent0e4cf7e622d2e5b2af6a3707e08f0fac45cd6bb4 (diff)
parenta45b000e07a806e171f1e4701abd3e025382ecf3 (diff)
Merge branch 'toxManager' of blackbird:bittorrent into avoid-exposing-psq
-rw-r--r--Announcer/Tox.hs102
-rw-r--r--ToxManager.hs4
-rw-r--r--ToxToXMPP.hs6
-rw-r--r--examples/dhtd.hs20
4 files changed, 88 insertions, 44 deletions
diff --git a/Announcer/Tox.hs b/Announcer/Tox.hs
index 03cd0871..60a5a8b1 100644
--- a/Announcer/Tox.hs
+++ b/Announcer/Tox.hs
@@ -50,23 +50,16 @@ data AnnounceMethod r = forall nid ni sr addr tok a.
50 -- already in progress at announce time. Repeated searches are 50 -- already in progress at announce time. Repeated searches are
51 -- likely to finish faster than the first since nearby nodes 51 -- likely to finish faster than the first since nearby nodes
52 -- are not discarded. 52 -- are not discarded.
53 , aPublish :: Either (r -> sr -> IO ()) 53 , aPublish :: r -> tok -> Maybe ni -> IO (Maybe a)
54 (r -> tok -> Maybe ni -> IO (Maybe a))
55 -- ^ The action to perform when we find nearby nodes. The 54 -- ^ The action to perform when we find nearby nodes. The
56 -- destination node is given as a Maybe so that methods that 55 -- destination node is given as a Maybe so that methods that
57 -- treat 'Nothing' as loop-back address can be passed here, 56 -- treat 'Nothing' as loop-back address can be passed here,
58 -- however 'Nothing' will not be passed by the announcer 57 -- however 'Nothing' will not be passed by the announcer
59 -- thread. 58 -- thread.
60 -- 59 --
61 -- There are two cases: 60 -- The action requires a "token" from the destination
62 -- 61 -- node. This is the more typical "announce" semantics for
63 -- [Left] The action to perform requires a search result. 62 -- Kademlia.
64 -- This was implemented to support Tox's DHTKey and
65 -- Friend-Request messages.
66 --
67 -- [Right] The action requires a "token" from the destination
68 -- node. This is the more typical "announce" semantics for
69 -- Kademlia.
70 , aNearestNodes :: nid -> STM [ni] 63 , aNearestNodes :: nid -> STM [ni]
71 -- ^ Method to obtain starting nodes from an iterative Kademlia search. 64 -- ^ Method to obtain starting nodes from an iterative Kademlia search.
72 , aTarget :: nid 65 , aTarget :: nid
@@ -80,6 +73,38 @@ data AnnounceMethod r = forall nid ni sr addr tok a.
80 -- use the closest nodes found so far. 73 -- use the closest nodes found so far.
81 } 74 }
82 75
76-- | This type specifies a Kademlia search and an action to perform upon the result.
77data SearchMethod r = forall nid ni sr addr tok a.
78 ( Show nid
79 , Hashable nid
80 , Hashable ni
81 , Ord addr
82 , Ord nid
83 , Ord ni
84 ) => SearchMethod
85 { sSearch :: Search nid addr tok ni sr
86 -- ^ This is the Kademlia search to run repeatedly to find the
87 -- nearby nodes. A new search is started whenever one is not
88 -- already in progress at announce time. Repeated searches are
89 -- likely to finish faster than the first since nearby nodes
90 -- are not discarded.
91 --
92 -- XXX: Currently, "repeatedly" is wrong.
93 , sWithResult :: r -> sr -> IO ()
94 -- ^
95 -- The action to perform upon a search result. This was
96 -- implemented to support Tox's DHTKey and Friend-Request
97 -- messages.
98 , sNearestNodes :: nid -> STM [ni]
99 -- ^ Method to obtain starting nodes from an iterative Kademlia search.
100 , sTarget :: nid
101 -- ^ This is the Kademlia node-id of the item being announced.
102 , sInterval :: POSIXTime
103 -- ^ The time between searches.
104 --
105 -- XXX: Currently, search results will stop any repetition.
106 }
107
83 108
84-- announcement started: 109-- announcement started:
85newAnnouncement :: STM (IO a) 110newAnnouncement :: STM (IO a)
@@ -113,17 +138,15 @@ reAnnounce checkFin announce interval = \announcer k now -> do
113 announce 138 announce
114 139
115-- | Schedule a recurring Search + Announce sequence. 140-- | Schedule a recurring Search + Announce sequence.
116schedule :: Announcer -> AnnounceKey -> AnnounceMethod r -> r -> IO () 141scheduleAnnounce :: Announcer -> AnnounceKey -> AnnounceMethod r -> r -> IO ()
117schedule announcer k AnnounceMethod{aSearch,aPublish,aNearestNodes,aTarget,aInterval} r = do 142scheduleAnnounce announcer k AnnounceMethod{aSearch,aPublish,aNearestNodes,aTarget,aInterval} r = do
118 st <- atomically $ newSearch aSearch aTarget [] 143 st <- atomically $ newSearch aSearch aTarget []
119 ns <- atomically $ newTVar MM.empty 144 ns <- atomically $ newTVar MM.empty
120 let astate = AnnounceState st ns 145 let astate = AnnounceState st ns
121 publishToNodes is 146 publishToNodes is = do
122 | Left _ <- aPublish = return ()
123 | Right publish <- aPublish = do
124 forM_ is $ \(Binding ni mtok _) -> do 147 forM_ is $ \(Binding ni mtok _) -> do
125 forM_ mtok $ \tok -> do 148 forM_ mtok $ \tok -> do
126 got <- publish r tok (Just ni) 149 got <- aPublish r tok (Just ni)
127 now <- getPOSIXTime 150 now <- getPOSIXTime
128 forM_ got $ \_ -> do 151 forM_ got $ \_ -> do
129 atomically $ modifyTVar ns $ MM.insertTake announceK ni (Down now) 152 atomically $ modifyTVar ns $ MM.insertTake announceK ni (Down now)
@@ -132,20 +155,7 @@ schedule announcer k AnnounceMethod{aSearch,aPublish,aNearestNodes,aTarget,aInte
132 bs <- readTVar (searchInformant st {- :: TVar (MinMaxPSQ' ni nid tok -}) 155 bs <- readTVar (searchInformant st {- :: TVar (MinMaxPSQ' ni nid tok -})
133 return $ MM.toList bs 156 return $ MM.toList bs
134 publishToNodes is 157 publishToNodes is
135 onResult sr 158 onResult sr = return True
136 | Right _ <- aPublish = return True
137 | Left sendit <- aPublish = do
138 scheduleImmediately announcer k $ ScheduledItem $ \_ _ _ -> return $ do
139 got <- sendit r sr
140 -- If we had a way to get the source of a search result, we might want to
141 -- treat it similarly to an announcing node and remember it in the 'aStoringNodes'
142 -- MinMaxPSQ. For now, I'm just letting the nodes for which we've already sent
143 -- a message be forgotten.
144 --
145 -- forM_ got $ \_ -> do
146 -- atomically $ modifyTVar ns $ MM.insertTake announceK ni (Down now)
147 return ()
148 return True -- True to keep searching.
149 searchAgain = do 159 searchAgain = do
150 -- Canceling a pending search here seems to make announcements more reliable. 160 -- Canceling a pending search here seems to make announcements more reliable.
151 searchCancel st 161 searchCancel st
@@ -170,3 +180,33 @@ schedule announcer k AnnounceMethod{aSearch,aPublish,aNearestNodes,aTarget,aInte
170 atomically $ scheduleImmediately announcer k $ ScheduledItem (newAnnouncement searchAgain search announce aInterval) 180 atomically $ scheduleImmediately announcer k $ ScheduledItem (newAnnouncement searchAgain search announce aInterval)
171 interruptDelay (interrutible announcer) 181 interruptDelay (interrutible announcer)
172 182
183-- | Schedule a recurring Search + Publish sequence.
184scheduleSearch :: Announcer -> AnnounceKey -> SearchMethod r -> r -> IO ()
185scheduleSearch announcer k SearchMethod{sSearch,sWithResult,sNearestNodes,sTarget,sInterval} r = do
186 st <- atomically $ newSearch sSearch sTarget []
187 ns <- atomically $ newTVar MM.empty
188 let astate = AnnounceState st ns
189 onResult sr = do
190 -- XXX: Using /k/ here as the announce key is causing the search not to repeat.
191 scheduleImmediately announcer k $ ScheduledItem $ \_ _ _ -> return $ do
192 got <- sWithResult r sr
193 -- If we had a way to get the source of a search result, we might want to
194 -- treat it similarly to an announcing node and remember it in the 'aStoringNodes'
195 -- MinMaxPSQ. For now, I'm just letting the nodes for which we've already sent
196 -- a message be forgotten.
197 --
198 -- forM_ got $ \_ -> do
199 -- atomically $ modifyTVar ns $ MM.insertTake announceK ni (Down now)
200 return ()
201 return True -- True to keep searching.
202 searchAgain = do
203 -- Canceling a pending search here seems to make announcements more reliable.
204 searchCancel st
205 isfin <- searchIsFinished st -- Always True, since we canceled.
206 return $ when isfin $ void $ fork search
207 search = do -- thread to fork
208 atomically $ reset sNearestNodes sSearch sTarget st
209 searchLoop sSearch sTarget onResult st
210 atomically $ scheduleImmediately announcer k $ ScheduledItem (newAnnouncement searchAgain search (return ()) sInterval)
211 interruptDelay (interrutible announcer)
212
diff --git a/ToxManager.hs b/ToxManager.hs
index af1911d4..1e9c618d 100644
--- a/ToxManager.hs
+++ b/ToxManager.hs
@@ -81,10 +81,10 @@ toxman announcer toxbkts tox presence = ToxManager
81 -- Schedule recurring announce. 81 -- Schedule recurring announce.
82 -- 82 --
83 akey <- atomically $ packAnnounceKey announcer $ "toxid:" ++ show pubid 83 akey <- atomically $ packAnnounceKey announcer $ "toxid:" ++ show pubid
84 schedule announcer 84 scheduleAnnounce announcer
85 akey 85 akey
86 (AnnounceMethod (toxQSearch tox) 86 (AnnounceMethod (toxQSearch tox)
87 (Right $ toxAnnounceSendData tox) 87 (toxAnnounceSendData tox)
88 nearNodes 88 nearNodes
89 pubid 89 pubid
90 toxAnnounceInterval) 90 toxAnnounceInterval)
diff --git a/ToxToXMPP.hs b/ToxToXMPP.hs
index ac24ce6d..ad5cb0dd 100644
--- a/ToxToXMPP.hs
+++ b/ToxToXMPP.hs
@@ -165,10 +165,10 @@ forkAccountWatcher acc tox st announcer = forkIO $ do
165 -- likelihood of failure as the chances of packet loss 165 -- likelihood of failure as the chances of packet loss
166 -- happening to all (up to to 8) packets sent is low. 166 -- happening to all (up to to 8) packets sent is low.
167 -- 167 --
168 schedule announcer 168 scheduleSearch announcer
169 akey 169 akey
170 (AnnounceMethod (toxQSearch tox) 170 (SearchMethod (toxQSearch tox)
171 (Left $ \theirkey rendezvous -> do 171 (\theirkey rendezvous -> do
172 dkey <- Tox.getContactInfo tox 172 dkey <- Tox.getContactInfo tox
173 sendMessage 173 sendMessage
174 (Tox.toxToRoute tox) 174 (Tox.toxToRoute tox)
diff --git a/examples/dhtd.hs b/examples/dhtd.hs
index 3f9685cf..35035372 100644
--- a/examples/dhtd.hs
+++ b/examples/dhtd.hs
@@ -1009,10 +1009,14 @@ clientSession s@Session{..} sock cnum h = do
1009 (const method) 1009 (const method)
1010 announceSendData) 1010 announceSendData)
1011 dhtQuery 1011 dhtQuery
1012 doit :: Char -> Announcer -> AnnounceKey -> AnnounceMethod r -> r -> IO () 1012 doitR :: Char -> Announcer -> AnnounceKey -> AnnounceMethod r -> r -> IO ()
1013 doit '+' = schedule 1013 doitR '+' = scheduleAnnounce
1014 doit '-' = \a k _ _ -> cancel a k 1014 doitR '-' = \a k _ _ -> cancel a k
1015 doit _ = \_ _ _ _ -> hPutClientChunk h "Starting(+) or canceling(-)?" 1015 doitR _ = \_ _ _ _ -> hPutClientChunk h "Starting(+) or canceling(-)?"
1016 doitL :: Char -> Announcer -> AnnounceKey -> SearchMethod r -> r -> IO ()
1017 doitL '+' = scheduleSearch
1018 doitL '-' = \a k _ _ -> cancel a k
1019 doitL _ = \_ _ _ _ -> hPutClientChunk h "Starting(+) or canceling(-)?"
1016 matchingResult :: 1020 matchingResult ::
1017 ( Typeable stok 1021 ( Typeable stok
1018 , Typeable ptok 1022 , Typeable ptok
@@ -1046,9 +1050,9 @@ clientSession s@Session{..} sock cnum h = do
1046 dta <- either (const Nothing) Just $ announceParseData dtastr 1050 dta <- either (const Nothing) Just $ announceParseData dtastr
1047 return $ do 1051 return $ do
1048 akey <- atomically $ packAnnounceKey announcer (method ++ ":" ++ dtastr) 1052 akey <- atomically $ packAnnounceKey announcer (method ++ ":" ++ dtastr)
1049 doit op announcer 1053 doitR op announcer
1050 akey 1054 akey
1051 (AnnounceMethod qsearch (Right asend) 1055 (AnnounceMethod qsearch asend
1052 (\nid -> R.kclosest (searchSpace qsearch) 1056 (\nid -> R.kclosest (searchSpace qsearch)
1053 searchK 1057 searchK
1054 nid 1058 nid
@@ -1072,9 +1076,9 @@ clientSession s@Session{..} sock cnum h = do
1072 pub <- selectedKey 1076 pub <- selectedKey
1073 return $ do 1077 return $ do
1074 akey <- atomically $ packAnnounceKey announcer (method ++ ":" ++ dtastr) 1078 akey <- atomically $ packAnnounceKey announcer (method ++ ":" ++ dtastr)
1075 doit op announcer 1079 doitL op announcer
1076 akey 1080 akey
1077 (AnnounceMethod qsearch (Left $ asend pub) 1081 (SearchMethod qsearch (asend pub)
1078 (\nid -> R.kclosest (searchSpace qsearch) 1082 (\nid -> R.kclosest (searchSpace qsearch)
1079 searchK 1083 searchK
1080 nid 1084 nid