diff options
Diffstat (limited to 'src/Network/BitTorrent/Exchange/Extension.hs')
-rw-r--r-- | src/Network/BitTorrent/Exchange/Extension.hs | 67 |
1 files changed, 36 insertions, 31 deletions
diff --git a/src/Network/BitTorrent/Exchange/Extension.hs b/src/Network/BitTorrent/Exchange/Extension.hs index a4d72f96..e81cdb87 100644 --- a/src/Network/BitTorrent/Exchange/Extension.hs +++ b/src/Network/BitTorrent/Exchange/Extension.hs | |||
@@ -12,54 +12,59 @@ | |||
12 | -- | 12 | -- |
13 | module Network.BitTorrent.Exchange.Extension | 13 | module Network.BitTorrent.Exchange.Extension |
14 | ( -- * Capabilities | 14 | ( -- * Capabilities |
15 | Capabilities | 15 | Caps |
16 | , ppCaps, defaultCaps | ||
17 | , enabledCaps | ||
18 | 16 | ||
19 | -- * Extensions | 17 | -- * Extensions |
20 | , Extension(..) | 18 | , Extension(..) |
21 | , defaultExtensions, ppExtension | ||
22 | , encodeExts, decodeExts | ||
23 | ) where | 19 | ) where |
24 | 20 | ||
25 | import Data.Bits | 21 | import Data.Bits |
22 | import Data.Default | ||
23 | import Data.Monoid | ||
26 | import Data.Word | 24 | import Data.Word |
27 | import Text.PrettyPrint | 25 | import Text.PrettyPrint |
26 | import Text.PrettyPrint.Class | ||
28 | 27 | ||
28 | class (Enum a, Bounded a) => Capability a where | ||
29 | capMask :: a -> Word64 | ||
30 | capRequires :: a -> Word64 | ||
29 | 31 | ||
30 | type Capabilities = Word64 | 32 | newtype Caps a = Caps Word64 |
31 | 33 | ||
32 | ppCaps :: Capabilities -> Doc | 34 | instance (Pretty a, Capability a) => Pretty (Caps a) where |
33 | ppCaps = hcat . punctuate ", " . map ppExtension . decodeExts | 35 | pretty = hcat . punctuate ", " . map pretty . toList |
34 | 36 | ||
35 | defaultCaps :: Capabilities | 37 | instance Default (Caps a) where |
36 | defaultCaps = 0 | 38 | def = Caps 0 |
39 | {-# INLINE def #-} | ||
37 | 40 | ||
38 | enabledCaps :: Capabilities -- ^ of the client. | 41 | instance Monoid (Caps a) where |
39 | -> Capabilities -- ^ of the peer. | 42 | mempty = Caps (-1) |
40 | -> Capabilities -- ^ should be considered as enabled. | 43 | {-# INLINE mempty #-} |
41 | enabledCaps = (.&.) | ||
42 | 44 | ||
45 | mappend (Caps a) (Caps b) = Caps (a .&. b) | ||
46 | {-# INLINE mappend #-} | ||
43 | 47 | ||
44 | data Extension = ExtDHT -- ^ BEP 5 | 48 | allowed :: Capability a => a -> Caps a -> Bool |
45 | | ExtFast -- ^ BEP 6 | 49 | allowed = member |
46 | deriving (Show, Eq, Ord, Enum, Bounded) | 50 | fromList :: Capability a => [a] -> Caps a |
51 | fromList = Caps . foldr (.&.) 0 . map capMask | ||
47 | 52 | ||
48 | ppExtension :: Extension -> Doc | 53 | toList :: Capability a => Caps a -> [a] |
49 | ppExtension ExtDHT = "DHT" | 54 | toList (Caps rb) = filter (testMask rb . capMask) [minBound..maxBound] |
50 | ppExtension ExtFast = "Fast Extension" | 55 | where |
56 | testMask bits x = bits .&. x > 0 | ||
51 | 57 | ||
52 | extensionMask :: Extension -> Word64 | ||
53 | extensionMask ExtDHT = 0x01 | ||
54 | extensionMask ExtFast = 0x04 | ||
55 | 58 | ||
56 | defaultExtensions :: [Extension] | 59 | data Extension |
57 | defaultExtensions = [] | 60 | = ExtDHT -- ^ BEP 5 |
61 | | ExtFast -- ^ BEP 6 | ||
62 | deriving (Show, Eq, Ord, Enum, Bounded) | ||
58 | 63 | ||
59 | encodeExts :: [Extension] -> Capabilities | 64 | instance Pretty Extension where |
60 | encodeExts = foldr (.&.) 0 . map extensionMask | 65 | pretty ExtDHT = "DHT" |
66 | pretty ExtFast = "Fast Extension" | ||
61 | 67 | ||
62 | decodeExts :: Capabilities -> [Extension] | 68 | instance Capability Extension where |
63 | decodeExts rb = filter (testMask rb . extensionMask) [minBound..maxBound] | 69 | capMask ExtDHT = 0x01 |
64 | where | 70 | capMask ExtFast = 0x04 |
65 | testMask bits x = bits .&. x > 0 | ||