summaryrefslogtreecommitdiff
path: root/src/Network/BitTorrent/DHT/ContactInfo.hs
diff options
context:
space:
mode:
authorjoe <joe@jerkface.net>2017-01-23 07:04:42 -0500
committerjoe <joe@jerkface.net>2017-01-23 07:04:42 -0500
commite6c068447a1ba88eb1805f9397657ef45a9eda2f (patch)
treefa52cb81ee58fae82cccaff4c8299fe770ae7377 /src/Network/BitTorrent/DHT/ContactInfo.hs
parentd2adf592c46afa0f8c0640dec4715ee74f4776ca (diff)
PeerStore is now persistent.
Diffstat (limited to 'src/Network/BitTorrent/DHT/ContactInfo.hs')
-rw-r--r--src/Network/BitTorrent/DHT/ContactInfo.hs59
1 files changed, 48 insertions, 11 deletions
diff --git a/src/Network/BitTorrent/DHT/ContactInfo.hs b/src/Network/BitTorrent/DHT/ContactInfo.hs
index 4302288c..117325fc 100644
--- a/src/Network/BitTorrent/DHT/ContactInfo.hs
+++ b/src/Network/BitTorrent/DHT/ContactInfo.hs
@@ -15,6 +15,8 @@ import Data.Serialize
15import Data.PSQueue as PSQ 15import Data.PSQueue as PSQ
16import Data.Time.Clock.POSIX 16import Data.Time.Clock.POSIX
17import Data.ByteString (ByteString) 17import Data.ByteString (ByteString)
18import Data.Word
19import Network.Socket (SockAddr(..))
18 20
19import Data.Torrent 21import Data.Torrent
20import Network.BitTorrent.Address 22import Network.BitTorrent.Address
@@ -122,6 +124,40 @@ data SwarmData ip = SwarmData
122 , name :: Maybe ByteString 124 , name :: Maybe ByteString
123 } 125 }
124 126
127
128newtype SerializeAddress a = SerializeAddress { unserializeAddress :: a }
129
130instance Address a => Serialize (SerializeAddress a) where
131 get = SerializeAddress <$> do
132 c <- get
133 case (c::Word8) of
134 0x34 -> do ip4 <- get
135 return $ fromJust $ fromAddr (ip4::IPv4)
136 0x36 -> do ip6 <- get
137 return $ fromJust $ fromAddr (ip6::IPv6)
138 _ -> return $ error "cannot deserialize non-IP SerializeAddress"
139 put (SerializeAddress a)
140 | Just ip4 <- fromAddr a
141 = put (0x34::Word8) >> put (ip4::IPv4)
142 | Just ip6 <- fromAddr a
143 = put (0x36::Word8) >> put (ip6::IPv6)
144 | otherwise = return $ error "cannot serialize non-IP SerializeAddress"
145
146
147instance (Ord ip, Address ip) => Serialize (SwarmData ip) where
148 get = flip SwarmData <$> get
149 <*> ( PSQ.fromList . L.map parseAddr <$> get )
150 where
151 parseAddr addr = (unserializeAddress <$> addr)
152 :-> 0
153
154 put SwarmData{..} = do
155 put name
156 put $ L.map (\(addr :-> _) -> (SerializeAddress <$> addr))
157 -- XXX: should we serialize the timestamp?
158 $ PSQ.toList peers
159
160
125knownSwarms :: PeerStore ip -> [ (InfoHash, Int, Maybe ByteString) ] 161knownSwarms :: PeerStore ip -> [ (InfoHash, Int, Maybe ByteString) ]
126knownSwarms (PeerStore m) = L.map (\(ih,SwarmData q n) -> (ih,PSQ.size q,n)) $ HM.toList m 162knownSwarms (PeerStore m) = L.map (\(ih,SwarmData q n) -> (ih,PSQ.size q,n)) $ HM.toList m
127 163
@@ -136,26 +172,27 @@ swarmInsert old new = SwarmData
136 , name = name new <|> name old -- TODO: decodeUtf8' check 172 , name = name new <|> name old -- TODO: decodeUtf8' check
137 } 173 }
138 174
175isSwarmOccupied SwarmData{..} = not $ PSQ.null peers
139 176
140-- | Empty store. 177-- | Empty store.
141instance Default (PeerStore a) where 178instance Default (PeerStore a) where
142 def = PeerStore HM.empty 179 def = PeerStore HM.empty
143 {-# INLINE def #-} 180 {-# INLINE def #-}
144 181
145-- -- | Monoid under union operation. 182-- | Monoid under union operation.
146-- instance Eq a => Monoid (PeerStore a) where 183instance Ord a => Monoid (PeerStore a) where
147-- mempty = def 184 mempty = def
148-- {-# INLINE mempty #-} 185 {-# INLINE mempty #-}
149-- 186
150-- mappend (PeerStore a) (PeerStore b) = 187 mappend (PeerStore a) (PeerStore b) =
151-- PeerStore (HM.unionWith L.union a b) 188 PeerStore (HM.unionWith swarmInsert a b)
152-- {-# INLINE mappend #-} 189 {-# INLINE mappend #-}
153 190
154-- | Can be used to store peers between invocations of the client 191-- | Can be used to store peers between invocations of the client
155-- software. 192-- software.
156instance Serialize (PeerStore a) where 193instance (Ord a, Address a) => Serialize (PeerStore a) where
157 get = undefined 194 get = PeerStore . HM.fromList <$> get
158 put = undefined 195 put (PeerStore m) = put (L.filter (isSwarmOccupied . snd) $ HM.toList m)
159 196
160-- | Returns all peers associated with a given info hash. 197-- | Returns all peers associated with a given info hash.
161lookup :: Ord a => InfoHash -> PeerStore a -> [PeerAddr a] 198lookup :: Ord a => InfoHash -> PeerStore a -> [PeerAddr a]