summaryrefslogtreecommitdiff
path: root/src/Network/BitTorrent/DHT/ContactInfo.hs
diff options
context:
space:
mode:
authorjoe <joe@jerkface.net>2017-07-14 23:50:39 -0400
committerjoe <joe@jerkface.net>2017-07-14 23:50:39 -0400
commitf5186fa528bf9c79533d4c4ee1a3846eab4fc6be (patch)
tree247d8eb8411c671c17546777740e010e2b0155b7 /src/Network/BitTorrent/DHT/ContactInfo.hs
parent31d72c02c1bd3574042ac3b67eb4d28d87d187df (diff)
Removed ip polymorphism from PeerAddr type.
Diffstat (limited to 'src/Network/BitTorrent/DHT/ContactInfo.hs')
-rw-r--r--src/Network/BitTorrent/DHT/ContactInfo.hs43
1 files changed, 25 insertions, 18 deletions
diff --git a/src/Network/BitTorrent/DHT/ContactInfo.hs b/src/Network/BitTorrent/DHT/ContactInfo.hs
index 3db3d5a8..172306a1 100644
--- a/src/Network/BitTorrent/DHT/ContactInfo.hs
+++ b/src/Network/BitTorrent/DHT/ContactInfo.hs
@@ -1,6 +1,7 @@
1{-# LANGUAGE BangPatterns #-} 1{-# LANGUAGE BangPatterns #-}
2module Network.BitTorrent.DHT.ContactInfo 2module Network.BitTorrent.DHT.ContactInfo
3 ( PeerStore 3 ( PeerStore
4 , PeerAddr(..)
4 , Network.BitTorrent.DHT.ContactInfo.lookup 5 , Network.BitTorrent.DHT.ContactInfo.lookup
5 , Network.BitTorrent.DHT.ContactInfo.freshPeers 6 , Network.BitTorrent.DHT.ContactInfo.freshPeers
6 , Network.BitTorrent.DHT.ContactInfo.insertPeer 7 , Network.BitTorrent.DHT.ContactInfo.insertPeer
@@ -36,17 +37,17 @@ import Network.Address
36-- -- PeerSet 37-- -- PeerSet
37-- -----------------------------------------------------------------------} 38-- -----------------------------------------------------------------------}
38-- 39--
39-- type PeerSet a = [(PeerAddr a, NodeInfo a, Timestamp)] 40-- type PeerSet a = [(PeerAddr, NodeInfo a, Timestamp)]
40-- 41--
41-- -- compare PSQueue vs Ordered list 42-- -- compare PSQueue vs Ordered list
42-- 43--
43-- takeNewest :: PeerSet a -> [PeerAddr a] 44-- takeNewest :: PeerSet a -> [PeerAddr]
44-- takeNewest = undefined 45-- takeNewest = undefined
45-- 46--
46-- dropOld :: Timestamp -> PeerSet a -> PeerSet a 47-- dropOld :: Timestamp -> PeerSet a -> PeerSet a
47-- dropOld = undefined 48-- dropOld = undefined
48-- 49--
49-- insert :: PeerAddr a -> Timestamp -> PeerSet a -> PeerSet a 50-- insert :: PeerAddr -> Timestamp -> PeerSet a -> PeerSet a
50-- insert = undefined 51-- insert = undefined
51-- 52--
52-- type Mask = Int 53-- type Mask = Int
@@ -116,16 +117,19 @@ import Network.Address
116 117
117-- | Storage used to keep track a set of known peers in client, 118-- | Storage used to keep track a set of known peers in client,
118-- tracker or DHT sessions. 119-- tracker or DHT sessions.
119newtype PeerStore ip = PeerStore (HashMap InfoHash (SwarmData ip)) 120newtype PeerStore = PeerStore (HashMap InfoHash SwarmData)
120 121
121type Timestamp = POSIXTime 122type Timestamp = POSIXTime
122 123
123data SwarmData ip = SwarmData 124data SwarmData = SwarmData
124 { peers :: !(PSQ (PeerAddr ip) Timestamp) 125 { peers :: !(PSQ PeerAddr Timestamp)
125 , name :: !(Maybe ByteString) 126 , name :: !(Maybe ByteString)
126 } 127 }
127 128
128 129-- | This wrapper will serialize an ip address with a '4' or '6' prefix byte
130-- to indicate whether it is IPv4 or IPv6.
131--
132-- Note: it does not serialize port numbers.
129newtype SerializeAddress a = SerializeAddress { unserializeAddress :: a } 133newtype SerializeAddress a = SerializeAddress { unserializeAddress :: a }
130 134
131instance Address a => Serialize (SerializeAddress a) where 135instance Address a => Serialize (SerializeAddress a) where
@@ -145,7 +149,8 @@ instance Address a => Serialize (SerializeAddress a) where
145 | otherwise = return $ error "cannot serialize non-IP SerializeAddress" 149 | otherwise = return $ error "cannot serialize non-IP SerializeAddress"
146 150
147 151
148instance (Ord ip, Address ip) => Serialize (SwarmData ip) where 152{- XXX: What happened to the ports?
153instance Serialize SwarmData where
149 get = flip SwarmData <$> get 154 get = flip SwarmData <$> get
150 <*> ( PSQ.fromList . L.map parseAddr <$> get ) 155 <*> ( PSQ.fromList . L.map parseAddr <$> get )
151 where 156 where
@@ -157,17 +162,17 @@ instance (Ord ip, Address ip) => Serialize (SwarmData ip) where
157 put $ L.map (\(addr :-> _) -> (SerializeAddress <$> addr)) 162 put $ L.map (\(addr :-> _) -> (SerializeAddress <$> addr))
158 -- XXX: should we serialize the timestamp? 163 -- XXX: should we serialize the timestamp?
159 $ PSQ.toList peers 164 $ PSQ.toList peers
165-}
160 166
161 167knownSwarms :: PeerStore -> [ (InfoHash, Int, Maybe ByteString) ]
162knownSwarms :: PeerStore ip -> [ (InfoHash, Int, Maybe ByteString) ]
163knownSwarms (PeerStore m) = L.map (\(ih,SwarmData q n) -> (ih,PSQ.size q,n)) $ HM.toList m 168knownSwarms (PeerStore m) = L.map (\(ih,SwarmData q n) -> (ih,PSQ.size q,n)) $ HM.toList m
164 169
165swarmSingleton :: Ord ip => PeerAddr ip -> SwarmData ip 170swarmSingleton :: PeerAddr -> SwarmData
166swarmSingleton a = SwarmData 171swarmSingleton a = SwarmData
167 { peers = PSQ.singleton a 0 172 { peers = PSQ.singleton a 0
168 , name = Nothing } 173 , name = Nothing }
169 174
170swarmInsert :: Ord ip => SwarmData ip -> SwarmData ip -> SwarmData ip 175swarmInsert :: SwarmData -> SwarmData -> SwarmData
171swarmInsert old new = SwarmData 176swarmInsert old new = SwarmData
172 { peers = L.foldl' (\q (a :-> t) -> PSQ.insertWith (\p _ -> p) a t q) (peers old) (PSQ.toList $ peers new) 177 { peers = L.foldl' (\q (a :-> t) -> PSQ.insertWith (\p _ -> p) a t q) (peers old) (PSQ.toList $ peers new)
173 , name = name new <|> name old -- TODO: decodeUtf8' check 178 , name = name new <|> name old -- TODO: decodeUtf8' check
@@ -176,12 +181,12 @@ swarmInsert old new = SwarmData
176isSwarmOccupied SwarmData{..} = not $ PSQ.null peers 181isSwarmOccupied SwarmData{..} = not $ PSQ.null peers
177 182
178-- | Empty store. 183-- | Empty store.
179instance Default (PeerStore a) where 184instance Default (PeerStore) where
180 def = PeerStore HM.empty 185 def = PeerStore HM.empty
181 {-# INLINE def #-} 186 {-# INLINE def #-}
182 187
183-- | Monoid under union operation. 188-- | Monoid under union operation.
184instance Ord a => Monoid (PeerStore a) where 189instance Monoid PeerStore where
185 mempty = def 190 mempty = def
186 {-# INLINE mempty #-} 191 {-# INLINE mempty #-}
187 192
@@ -189,20 +194,22 @@ instance Ord a => Monoid (PeerStore a) where
189 PeerStore (HM.unionWith swarmInsert a b) 194 PeerStore (HM.unionWith swarmInsert a b)
190 {-# INLINE mappend #-} 195 {-# INLINE mappend #-}
191 196
197{-
192-- | Can be used to store peers between invocations of the client 198-- | Can be used to store peers between invocations of the client
193-- software. 199-- software.
194instance (Ord a, Address a) => Serialize (PeerStore a) where 200instance Serialize PeerStore where
195 get = PeerStore . HM.fromList <$> get 201 get = PeerStore . HM.fromList <$> get
196 put (PeerStore m) = put (L.filter (isSwarmOccupied . snd) $ HM.toList m) 202 put (PeerStore m) = put (L.filter (isSwarmOccupied . snd) $ HM.toList m)
203-}
197 204
198-- | Returns all peers associated with a given info hash. 205-- | Returns all peers associated with a given info hash.
199lookup :: Ord a => InfoHash -> PeerStore a -> [PeerAddr a] 206lookup :: InfoHash -> PeerStore -> [PeerAddr]
200lookup ih (PeerStore m) = maybe [] (PSQ.keys . peers) $ HM.lookup ih m 207lookup ih (PeerStore m) = maybe [] (PSQ.keys . peers) $ HM.lookup ih m
201 208
202batchSize = 64 209batchSize = 64
203 210
204-- | Used in 'get_peers' DHT queries. 211-- | Used in 'get_peers' DHT queries.
205freshPeers :: Ord a => InfoHash -> Timestamp -> PeerStore a -> ([PeerAddr a], PeerStore a) 212freshPeers :: InfoHash -> Timestamp -> PeerStore -> ([PeerAddr], PeerStore)
206freshPeers ih tm (PeerStore m) = fromMaybe ([],PeerStore m) $ do 213freshPeers ih tm (PeerStore m) = fromMaybe ([],PeerStore m) $ do
207 swarm <- HM.lookup ih m 214 swarm <- HM.lookup ih m
208 let ps0 = take batchSize $ unfoldr (incomp minView) (peers swarm) 215 let ps0 = take batchSize $ unfoldr (incomp minView) (peers swarm)
@@ -219,7 +226,7 @@ incomp !f !x = do
219 pure $! ( (result,x'), x' ) 226 pure $! ( (result,x'), x' )
220 227
221-- | Used in 'announce_peer' DHT queries. 228-- | Used in 'announce_peer' DHT queries.
222insertPeer :: Ord a => InfoHash -> Maybe ByteString -> PeerAddr a -> PeerStore a -> PeerStore a 229insertPeer :: InfoHash -> Maybe ByteString -> PeerAddr -> PeerStore -> PeerStore
223insertPeer !ih !name !a !(PeerStore m) = seq a' $ PeerStore (HM.insertWith swarmInsert ih a' m) 230insertPeer !ih !name !a !(PeerStore m) = seq a' $ PeerStore (HM.insertWith swarmInsert ih a' m)
224 where 231 where
225 a' = SwarmData { peers = PSQ.singleton a 0 232 a' = SwarmData { peers = PSQ.singleton a 0