diff options
Diffstat (limited to 'src/Network/BitTorrent/Exchange/Message.hs')
-rw-r--r-- | src/Network/BitTorrent/Exchange/Message.hs | 69 |
1 files changed, 50 insertions, 19 deletions
diff --git a/src/Network/BitTorrent/Exchange/Message.hs b/src/Network/BitTorrent/Exchange/Message.hs index 8fcf582f..8ef9f3da 100644 --- a/src/Network/BitTorrent/Exchange/Message.hs +++ b/src/Network/BitTorrent/Exchange/Message.hs | |||
@@ -210,9 +210,12 @@ instance Serialize Handshake where | |||
210 | <*> S.get | 210 | <*> S.get |
211 | <*> S.get | 211 | <*> S.get |
212 | 212 | ||
213 | -- | Show handshake protocol string, caps and fingerprint. | ||
213 | instance Pretty Handshake where | 214 | instance Pretty Handshake where |
214 | pretty Handshake {..} | 215 | pretty Handshake {..} |
215 | = text (BC.unpack hsProtocol) <+> pretty (fingerprint hsPeerId) | 216 | = text (BC.unpack hsProtocol) $$ |
217 | pretty hsReserved $$ | ||
218 | pretty (fingerprint hsPeerId) | ||
216 | 219 | ||
217 | -- | Get handshake message size in bytes from the length of protocol | 220 | -- | Get handshake message size in bytes from the length of protocol |
218 | -- string. | 221 | -- string. |
@@ -227,31 +230,49 @@ handshakeMaxSize = handshakeSize maxBound | |||
227 | defaultBTProtocol :: BS.ByteString | 230 | defaultBTProtocol :: BS.ByteString |
228 | defaultBTProtocol = "BitTorrent protocol" | 231 | defaultBTProtocol = "BitTorrent protocol" |
229 | 232 | ||
230 | -- | Length of info hash and peer id is unchecked, so it /should/ be | 233 | -- | Handshake with default protocol string and reserved bitmask. |
231 | -- equal 20. | ||
232 | defaultHandshake :: InfoHash -> PeerId -> Handshake | 234 | defaultHandshake :: InfoHash -> PeerId -> Handshake |
233 | defaultHandshake = Handshake defaultBTProtocol def | 235 | defaultHandshake = Handshake defaultBTProtocol def |
234 | 236 | ||
235 | {----------------------------------------------------------------------- | 237 | {----------------------------------------------------------------------- |
236 | Regular messages | 238 | -- Regular messages |
237 | -----------------------------------------------------------------------} | 239 | -----------------------------------------------------------------------} |
238 | 240 | ||
239 | class PeerMessage a where | 241 | class PeerMessage a where |
240 | envelop :: ExtendedCaps -> a -> Message | 242 | -- | Construct a message to be /sent/. |
243 | envelop :: ExtendedCaps -- ^ The /receiver/ extended capabilities; | ||
244 | -> a -- ^ An regular message; | ||
245 | -> Message -- ^ Enveloped message to sent. | ||
241 | 246 | ||
247 | {----------------------------------------------------------------------- | ||
248 | -- Status messages | ||
249 | -----------------------------------------------------------------------} | ||
250 | |||
251 | -- | Notification that the sender have updated its | ||
252 | -- 'Network.BitTorrent.Exchange.Status.PeerStatus'. | ||
242 | data StatusUpdate | 253 | data StatusUpdate |
243 | = Choke | 254 | -- | Notification that the sender will not upload data to the |
244 | | Unchoke | 255 | -- receiver until unchoking happen. |
245 | | Interested | 256 | = Choking !Bool |
246 | | NotInterested | 257 | |
247 | deriving (Show, Eq, Ord, Enum, Bounded) | 258 | -- | Notification that the sender is interested (or not interested) |
259 | -- in any of the receiver's data pieces. | ||
260 | | Interested !Bool | ||
261 | deriving (Show, Eq, Ord, Typeable) | ||
248 | 262 | ||
249 | instance Pretty StatusUpdate where | 263 | instance Pretty StatusUpdate where |
250 | pretty = text . show | 264 | pretty (Choking False) = "not choking" |
265 | pretty (Choking True ) = "choking" | ||
266 | pretty (Interested False) = "not interested" | ||
267 | pretty (Interested True ) = "interested" | ||
251 | 268 | ||
252 | instance PeerMessage StatusUpdate where | 269 | instance PeerMessage StatusUpdate where |
253 | envelop _ = Status | 270 | envelop _ = Status |
254 | 271 | ||
272 | {----------------------------------------------------------------------- | ||
273 | -- Available and transfer messages | ||
274 | -----------------------------------------------------------------------} | ||
275 | |||
255 | data RegularMessage = | 276 | data RegularMessage = |
256 | -- | Zero-based index of a piece that has just been successfully | 277 | -- | Zero-based index of a piece that has just been successfully |
257 | -- downloaded and verified via the hash. | 278 | -- downloaded and verified via the hash. |
@@ -303,6 +324,10 @@ instance PeerMessage BlockIx where | |||
303 | instance PeerMessage (Block BL.ByteString) where | 324 | instance PeerMessage (Block BL.ByteString) where |
304 | envelop c = envelop c . Piece | 325 | envelop c = envelop c . Piece |
305 | 326 | ||
327 | {----------------------------------------------------------------------- | ||
328 | -- Fast messages | ||
329 | -----------------------------------------------------------------------} | ||
330 | |||
306 | -- | BEP6 messages. | 331 | -- | BEP6 messages. |
307 | data FastMessage = | 332 | data FastMessage = |
308 | -- | If a peer have all pieces it might send the 'HaveAll' message | 333 | -- | If a peer have all pieces it might send the 'HaveAll' message |
@@ -526,12 +551,14 @@ type MessageId = Word8 | |||
526 | -- extension then the client MUST close the connection. | 551 | -- extension then the client MUST close the connection. |
527 | -- | 552 | -- |
528 | data Message | 553 | data Message |
529 | -- core | 554 | -- | Peers may close the TCP connection if they have not received |
555 | -- any messages for a given period of time, generally 2 | ||
556 | -- minutes. Thus, the "keep-alive" message is sent tot keep the | ||
557 | -- connection between two peers alive, if no /other/ message has | ||
558 | -- been sentin a given period of time. | ||
530 | = KeepAlive | 559 | = KeepAlive |
531 | | Status !StatusUpdate | 560 | | Status !StatusUpdate |
532 | | Regular !RegularMessage | 561 | | Regular !RegularMessage |
533 | |||
534 | -- extensions | ||
535 | | Port !PortNumber | 562 | | Port !PortNumber |
536 | | Fast !FastMessage | 563 | | Fast !FastMessage |
537 | | Extended !ExtendedMessage | 564 | | Extended !ExtendedMessage |
@@ -581,10 +608,10 @@ instance Serialize Message where | |||
581 | else do | 608 | else do |
582 | mid <- S.getWord8 | 609 | mid <- S.getWord8 |
583 | case mid of | 610 | case mid of |
584 | 0x00 -> return $ Status Choke | 611 | 0x00 -> return $ Status (Choking True) |
585 | 0x01 -> return $ Status Unchoke | 612 | 0x01 -> return $ Status (Choking False) |
586 | 0x02 -> return $ Status Interested | 613 | 0x02 -> return $ Status (Interested True) |
587 | 0x03 -> return $ Status NotInterested | 614 | 0x03 -> return $ Status (Interested False) |
588 | 0x04 -> (Regular . Have) <$> getInt | 615 | 0x04 -> (Regular . Have) <$> getInt |
589 | 0x05 -> (Regular . Bitfield . fromBitmap) | 616 | 0x05 -> (Regular . Bitfield . fromBitmap) |
590 | <$> S.getByteString (pred len) | 617 | <$> S.getByteString (pred len) |
@@ -616,8 +643,12 @@ instance Serialize Message where | |||
616 | put (Fast msg) = putFast msg | 643 | put (Fast msg) = putFast msg |
617 | put (Extended m ) = putExtendedMessage m | 644 | put (Extended m ) = putExtendedMessage m |
618 | 645 | ||
646 | statusUpdateId :: StatusUpdate -> MessageId | ||
647 | statusUpdateId (Choking choking) = fromIntegral (0 + fromEnum choking) | ||
648 | statusUpdateId (Interested choking) = fromIntegral (2 + fromEnum choking) | ||
649 | |||
619 | putStatus :: Putter StatusUpdate | 650 | putStatus :: Putter StatusUpdate |
620 | putStatus su = putInt 1 >> S.putWord8 (fromIntegral (fromEnum su)) | 651 | putStatus su = putInt 1 >> S.putWord8 (statusUpdateId su) |
621 | 652 | ||
622 | putRegular :: Putter RegularMessage | 653 | putRegular :: Putter RegularMessage |
623 | putRegular (Have i) = putInt 5 >> S.putWord8 0x04 >> putInt i | 654 | putRegular (Have i) = putInt 5 >> S.putWord8 0x04 >> putInt i |