summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSam T <sta.cs.vsu@gmail.com>2013-04-24 19:44:32 +0400
committerSam T <sta.cs.vsu@gmail.com>2013-04-24 19:44:32 +0400
commita7c82906934d7e640cda5c26448ce4fa232d2b46 (patch)
tree7a16fee4c81eeacc0c2347d263fcf11a66e46714 /src
parentea7947d3db0217f31dc507f930f3d9e6c6f437c0 (diff)
+ Add BEP 6 messages.
Diffstat (limited to 'src')
-rw-r--r--src/Network/BitTorrent/PeerWire/Block.hs4
-rw-r--r--src/Network/BitTorrent/PeerWire/Message.hs106
2 files changed, 84 insertions, 26 deletions
diff --git a/src/Network/BitTorrent/PeerWire/Block.hs b/src/Network/BitTorrent/PeerWire/Block.hs
index 8e4a1f24..ddbc1020 100644
--- a/src/Network/BitTorrent/PeerWire/Block.hs
+++ b/src/Network/BitTorrent/PeerWire/Block.hs
@@ -1,5 +1,5 @@
1module Network.BitTorrent.PeerWire.Block 1module Network.BitTorrent.PeerWire.Block
2 ( BlockIx(..), Block(..) 2 ( BlockIx(..), Block(..), PieceIx
3 , BlockLIx, PieceLIx 3 , BlockLIx, PieceLIx
4 , defaultBlockSize 4 , defaultBlockSize
5 , pieceIx, blockIx 5 , pieceIx, blockIx
@@ -17,7 +17,7 @@ import Data.Serialize
17 17
18type BlockLIx = Int 18type BlockLIx = Int
19type PieceLIx = Int 19type PieceLIx = Int
20 20type PieceIx = Int
21 21
22data BlockIx = BlockIx { 22data BlockIx = BlockIx {
23 -- ^ Zero-based piece index. 23 -- ^ Zero-based piece index.
diff --git a/src/Network/BitTorrent/PeerWire/Message.hs b/src/Network/BitTorrent/PeerWire/Message.hs
index 66021487..650e0082 100644
--- a/src/Network/BitTorrent/PeerWire/Message.hs
+++ b/src/Network/BitTorrent/PeerWire/Message.hs
@@ -11,18 +11,65 @@ import Data.Serialize
11import Network.BitTorrent.PeerWire.Block 11import Network.BitTorrent.PeerWire.Block
12 12
13 13
14-- TODO comment message constructors 14-- | Messages used in communication between peers.
15--
16-- Note: If some extensions are disabled (not present in extension
17-- mask) and client receive message used by the disabled
18-- extension then the client MUST close the connection.
19--
15data Message = KeepAlive 20data Message = KeepAlive
16 | Choke 21 | Choke
17 | Unchoke 22 | Unchoke
18 | Interested 23 | Interested
19 | NotInterested 24 | NotInterested
20 | Have Int 25
26 -- | Zero-based index of a piece that has just been
27 -- successfully downloaded and verified via the hash.
28 | Have PieceIx
29
30 -- | The bitfield message may only be sent immediately
31 -- after the handshaking sequence is complete, and
32 -- before any other message are sent. If client have no
33 -- pieces then bitfield need not to be sent.
21 | Bitfield ByteString 34 | Bitfield ByteString
35
36 -- | Request for a particular block. If a client is
37 -- requested a block that another peer do not have the
38 -- peer might not answer at all.
22 | Request BlockIx 39 | Request BlockIx
40
41 -- | Response for a request for a block.
23 | Piece Block 42 | Piece Block
43
44 -- | Used to cancel block requests. It is typically
45 -- used during "End Game".
24 | Cancel BlockIx 46 | Cancel BlockIx
47
25 | Port Int 48 | Port Int
49
50 -- | BEP 6: Then peer have all pieces it might send the
51 -- 'HaveAll' message instead of 'Bitfield'
52 -- message. Used to save bandwidth.
53 | HaveAll
54
55 -- | BEP 6: Then peer have no pieces it might send
56 -- 'HaveNone' message intead of 'Bitfield'
57 -- message. Used to save bandwidth.
58 | HaveNone
59
60 -- | BEP 6: This is an advisory message meaning "you
61 -- might like to download this piece." Used to avoid
62 -- excessive disk seeks and amount of IO.
63 | SuggestPiece PieceIx
64
65 -- | BEP 6: Notifies a requesting peer that its request
66 -- will not be satisfied.
67 | RejectRequest BlockIx
68
69 -- | BEP 6: This is an advisory messsage meaning "if
70 -- you ask for this piece, I'll give it to you even if
71 -- you're choked." Used to shorten starting phase.
72 | AllowedFast PieceIx
26 deriving (Show, Eq) 73 deriving (Show, Eq)
27 74
28 75
@@ -30,38 +77,44 @@ instance Serialize Message where
30 get = do 77 get = do
31 len <- getInt 78 len <- getInt
32 lookAhead $ ensure len 79 lookAhead $ ensure len
33 if len == 0 then return KeepAlive -- FIX check if BS is empty instead of reading len 80 if len == 0 then return KeepAlive
34 else do 81 else do
35 mid <- getWord8 82 mid <- getWord8
36 case mid of 83 case mid of
37 0 -> return Choke 84 0x00 -> return Choke
38 1 -> return Unchoke 85 0x01 -> return Unchoke
39 2 -> return Interested 86 0x02 -> return Interested
40 3 -> return NotInterested 87 0x03 -> return NotInterested
41 4 -> Have <$> getInt 88 0x04 -> Have <$> getInt
42 5 -> Bitfield <$> getBytes (pred len) 89 0x05 -> Bitfield <$> getBytes (pred len)
43 6 -> Request <$> get 90 0x06 -> Request <$> get
44 7 -> Piece <$> getBlock (len - 9) 91 0x07 -> Piece <$> getBlock (len - 9)
45 8 -> Cancel <$> get 92 0x08 -> Cancel <$> get
46 9 -> (Port . fromIntegral) <$> getWord16be 93 0x09 -> (Port . fromIntegral) <$> getWord16be
47 _ -> fail $ "unknown message ID: " ++ show mid 94 0x0E -> return HaveAll
95 0x0F -> return HaveNone
96 0x0D -> SuggestPiece <$> getInt
97 0x10 -> RejectRequest <$> get
98 0x11 -> AllowedFast <$> getInt
99 _ -> fail $ "unknown message ID: " ++ show mid
48 100
49 where 101 where
50 getBlock :: Int -> Get Block 102 getBlock :: Int -> Get Block
51 getBlock len = Block <$> getInt <*> getInt <*> getBytes len 103 getBlock len = Block <$> getInt <*> getInt <*> getBytes len
52 {-# INLINE getBlock #-} 104 {-# INLINE getBlock #-}
53 105
106
54 put KeepAlive = putInt 0 107 put KeepAlive = putInt 0
55 put Choke = putInt 1 >> putWord8 0 108 put Choke = putInt 1 >> putWord8 0x00
56 put Unchoke = putInt 1 >> putWord8 1 109 put Unchoke = putInt 1 >> putWord8 0x01
57 put Interested = putInt 1 >> putWord8 2 110 put Interested = putInt 1 >> putWord8 0x02
58 put NotInterested = putInt 1 >> putWord8 3 111 put NotInterested = putInt 1 >> putWord8 0x03
59 put (Have i) = putInt 5 >> putWord8 4 >> putInt i 112 put (Have i) = putInt 5 >> putWord8 0x04 >> putInt i
60 put (Bitfield b) = putInt l >> putWord8 5 >> putByteString b 113 put (Bitfield b) = putInt l >> putWord8 0x05 >> putByteString b
61 where l = succ (B.length b) 114 where l = succ (B.length b)
62 {-# INLINE l #-} 115 {-# INLINE l #-}
63 put (Request blk) = putInt 13 >> putWord8 6 >> put blk 116 put (Request blk) = putInt 13 >> putWord8 0x06 >> put blk
64 put (Piece blk) = putInt l >> putWord8 7 >> putBlock 117 put (Piece blk) = putInt l >> putWord8 0x07 >> putBlock
65 where l = 9 + B.length (blkData blk) 118 where l = 9 + B.length (blkData blk)
66 {-# INLINE l #-} 119 {-# INLINE l #-}
67 putBlock = do putInt (blkPiece blk) 120 putBlock = do putInt (blkPiece blk)
@@ -69,5 +122,10 @@ instance Serialize Message where
69 putByteString (blkData blk) 122 putByteString (blkData blk)
70 {-# INLINE putBlock #-} 123 {-# INLINE putBlock #-}
71 124
72 put (Cancel blk) = putInt 13 >> putWord8 8 >> put blk 125 put (Cancel blk) = putInt 13 >> putWord8 0x08 >> put blk
73 put (Port p ) = putInt 3 >> putWord8 9 >> putWord16be (fromIntegral p) 126 put (Port p ) = putInt 3 >> putWord8 0x09 >> putWord16be (fromIntegral p)
127 put HaveAll = putInt 1 >> putWord8 0x0E
128 put HaveNone = putInt 1 >> putWord8 0x0F
129 put (SuggestPiece pix) = putInt 5 >> putWord8 0x0D >> putInt pix
130 put (RejectRequest ix) = putInt 13 >> putWord8 0x10 >> put ix
131 put (AllowedFast ix) = putInt 5 >> putWord8 0x11 >> putInt ix