diff options
author | Sam T <pxqr.sta@gmail.com> | 2013-05-08 10:02:48 +0400 |
---|---|---|
committer | Sam T <pxqr.sta@gmail.com> | 2013-05-08 10:02:48 +0400 |
commit | d0282172da33bbc58cc40f14d7368726dfde8b37 (patch) | |
tree | 6c7bb5511f8cd67b8af3a196a5566d4f4fda947f /src/Network | |
parent | fe546e6c3926019efd614787f6c2e8cf12469aed (diff) |
+ Add capabilities.
Diffstat (limited to 'src/Network')
-rw-r--r-- | src/Network/BitTorrent/Extension.hs | 56 | ||||
-rw-r--r-- | src/Network/BitTorrent/PeerWire/Block.hs | 7 | ||||
-rw-r--r-- | src/Network/BitTorrent/PeerWire/Handshake.hs | 24 |
3 files changed, 78 insertions, 9 deletions
diff --git a/src/Network/BitTorrent/Extension.hs b/src/Network/BitTorrent/Extension.hs new file mode 100644 index 00000000..e37f3afb --- /dev/null +++ b/src/Network/BitTorrent/Extension.hs | |||
@@ -0,0 +1,56 @@ | |||
1 | -- | | ||
2 | -- Copyright : (c) Sam T. 2013 | ||
3 | -- License : MIT | ||
4 | -- Maintainer : pxqr.sta@gmail.com | ||
5 | -- Stability : experimental | ||
6 | -- Portability : portable | ||
7 | -- | ||
8 | -- This module provides peer capabilities detection. | ||
9 | -- | ||
10 | -- > See http://www.bittorrent.org/beps/bep_0004.html | ||
11 | -- | ||
12 | module Network.BitTorrent.Extension | ||
13 | ( Capabilities, ppCaps, defaultCaps, enabledCaps | ||
14 | , Extension, ppExtension, encodeExts, decodeExts | ||
15 | ) where | ||
16 | |||
17 | import Data.Bits | ||
18 | import Data.List | ||
19 | import Data.Word | ||
20 | |||
21 | |||
22 | type Capabilities = Word64 | ||
23 | |||
24 | ppCaps :: Capabilities -> String | ||
25 | ppCaps = intercalate ", " . map ppExtension . decodeExts | ||
26 | |||
27 | defaultCaps :: Capabilities | ||
28 | defaultCaps = 0 | ||
29 | |||
30 | enabledCaps :: Capabilities -- ^ of the client. | ||
31 | -> Capabilities -- ^ of the peer. | ||
32 | -> Capabilities -- ^ should be considered as enabled. | ||
33 | enabledCaps = (.&.) | ||
34 | |||
35 | |||
36 | |||
37 | data Extension = ExtDHT -- ^ BEP 5 | ||
38 | | ExtFast -- ^ BEP 6 | ||
39 | deriving (Show, Eq, Ord, Enum, Bounded) | ||
40 | |||
41 | ppExtension :: Extension -> String | ||
42 | ppExtension ExtDHT = "DHT" | ||
43 | ppExtension ExtFast = "Fast Extension" | ||
44 | |||
45 | extensionMask :: Extension -> Word64 | ||
46 | extensionMask ExtDHT = 0x01 | ||
47 | extensionMask ExtFast = 0x04 | ||
48 | |||
49 | |||
50 | encodeExts :: [Extension] -> Capabilities | ||
51 | encodeExts = foldr (.&.) 0 . map extensionMask | ||
52 | |||
53 | decodeExts :: Capabilities -> [Extension] | ||
54 | decodeExts rb = filter (testMask rb . extensionMask) [minBound..maxBound] | ||
55 | where | ||
56 | testMask bits x = bits .&. x > 0 | ||
diff --git a/src/Network/BitTorrent/PeerWire/Block.hs b/src/Network/BitTorrent/PeerWire/Block.hs index 582accdb..fbc65338 100644 --- a/src/Network/BitTorrent/PeerWire/Block.hs +++ b/src/Network/BitTorrent/PeerWire/Block.hs | |||
@@ -1,5 +1,7 @@ | |||
1 | module Network.BitTorrent.PeerWire.Block | 1 | module Network.BitTorrent.PeerWire.Block |
2 | ( BlockIx(..), Block(..), PieceIx | 2 | ( BlockIx(..) |
3 | , Block(..), blockSize | ||
4 | , PieceIx | ||
3 | , BlockLIx, PieceLIx | 5 | , BlockLIx, PieceLIx |
4 | , defaultBlockSize | 6 | , defaultBlockSize |
5 | , pieceIx, blockIx | 7 | , pieceIx, blockIx |
@@ -68,6 +70,9 @@ data Block = Block { | |||
68 | ppBlock :: Block -> String | 70 | ppBlock :: Block -> String |
69 | ppBlock = ppBlockIx . blockIx | 71 | ppBlock = ppBlockIx . blockIx |
70 | 72 | ||
73 | blockSize :: Block -> Int | ||
74 | blockSize blk = B.length (blkData blk) | ||
75 | |||
71 | -- | Widely used semi-official block size. | 76 | -- | Widely used semi-official block size. |
72 | defaultBlockSize :: Int | 77 | defaultBlockSize :: Int |
73 | defaultBlockSize = 16 * 1024 | 78 | defaultBlockSize = 16 * 1024 |
diff --git a/src/Network/BitTorrent/PeerWire/Handshake.hs b/src/Network/BitTorrent/PeerWire/Handshake.hs index e0d1672b..62d7d7f4 100644 --- a/src/Network/BitTorrent/PeerWire/Handshake.hs +++ b/src/Network/BitTorrent/PeerWire/Handshake.hs | |||
@@ -12,7 +12,7 @@ | |||
12 | -- | 12 | -- |
13 | {-# LANGUAGE OverloadedStrings #-} | 13 | {-# LANGUAGE OverloadedStrings #-} |
14 | module Network.BitTorrent.PeerWire.Handshake | 14 | module Network.BitTorrent.PeerWire.Handshake |
15 | ( Handshake | 15 | ( Handshake, handshakeCaps |
16 | , handshake | 16 | , handshake |
17 | , ppHandshake | 17 | , ppHandshake |
18 | , defaultHandshake, defaultBTProtocol, defaultReserved | 18 | , defaultHandshake, defaultBTProtocol, defaultReserved |
@@ -29,6 +29,7 @@ import Data.Torrent.InfoHash | |||
29 | import Network | 29 | import Network |
30 | import Network.Socket.ByteString | 30 | import Network.Socket.ByteString |
31 | 31 | ||
32 | import Network.BitTorrent.Extension | ||
32 | import Network.BitTorrent.Peer.ID | 33 | import Network.BitTorrent.Peer.ID |
33 | import Network.BitTorrent.Peer.ClientInfo | 34 | import Network.BitTorrent.Peer.ClientInfo |
34 | 35 | ||
@@ -69,6 +70,10 @@ instance Serialize Handshake where | |||
69 | <*> get | 70 | <*> get |
70 | <*> get | 71 | <*> get |
71 | 72 | ||
73 | |||
74 | handshakeCaps :: Handshake -> Capabilities | ||
75 | handshakeCaps = hsReserved | ||
76 | |||
72 | -- TODO add reserved bits info | 77 | -- TODO add reserved bits info |
73 | -- | Format handshake in human readable form. | 78 | -- | Format handshake in human readable form. |
74 | ppHandshake :: Handshake -> String | 79 | ppHandshake :: Handshake -> String |
@@ -95,7 +100,7 @@ defaultReserved = 0 | |||
95 | defaultHandshake :: InfoHash -> PeerID -> Handshake | 100 | defaultHandshake :: InfoHash -> PeerID -> Handshake |
96 | defaultHandshake = Handshake defaultBTProtocol defaultReserved | 101 | defaultHandshake = Handshake defaultBTProtocol defaultReserved |
97 | 102 | ||
98 | 103 | -- TODO exceptions instead of Either | |
99 | -- | Handshaking with a peer specified by the second argument. | 104 | -- | Handshaking with a peer specified by the second argument. |
100 | -- | 105 | -- |
101 | handshake :: Socket -> Handshake -> IO (Either String Handshake) | 106 | handshake :: Socket -> Handshake -> IO (Either String Handshake) |
@@ -103,12 +108,15 @@ handshake sock hs = do | |||
103 | sendAll sock (S.encode hs) | 108 | sendAll sock (S.encode hs) |
104 | 109 | ||
105 | header <- recv sock 1 | 110 | header <- recv sock 1 |
106 | let protocolLen = B.head header | 111 | if B.length header == 0 then |
107 | let restLen = handshakeSize protocolLen - 1 | 112 | return $ Left "" |
108 | body <- recv sock restLen | 113 | else do |
109 | let resp = B.cons protocolLen body | 114 | let protocolLen = B.head header |
110 | 115 | let restLen = handshakeSize protocolLen - 1 | |
111 | return (checkIH (S.decode resp)) | 116 | body <- recv sock restLen |
117 | let resp = B.cons protocolLen body | ||
118 | |||
119 | return (checkIH (S.decode resp)) | ||
112 | where | 120 | where |
113 | checkIH (Right hs') | 121 | checkIH (Right hs') |
114 | | hsInfoHash hs /= hsInfoHash hs' = Left "Handshake info hash do not match." | 122 | | hsInfoHash hs /= hsInfoHash hs' = Left "Handshake info hash do not match." |