diff options
Diffstat (limited to 'src/Network/BitTorrent/Exchange/Message.hs')
-rw-r--r-- | src/Network/BitTorrent/Exchange/Message.hs | 124 |
1 files changed, 106 insertions, 18 deletions
diff --git a/src/Network/BitTorrent/Exchange/Message.hs b/src/Network/BitTorrent/Exchange/Message.hs index 38a8ac33..b3100269 100644 --- a/src/Network/BitTorrent/Exchange/Message.hs +++ b/src/Network/BitTorrent/Exchange/Message.hs | |||
@@ -46,10 +46,15 @@ module Network.BitTorrent.Exchange.Message | |||
46 | , handshakeSize | 46 | , handshakeSize |
47 | , handshakeMaxSize | 47 | , handshakeMaxSize |
48 | 48 | ||
49 | -- * Stats | ||
50 | , ByteCount | ||
51 | , ByteStats (..) | ||
52 | , byteLength | ||
53 | |||
49 | -- * Messages | 54 | -- * Messages |
50 | , Message (..) | 55 | , Message (..) |
51 | , PeerMessage (..) | ||
52 | , defaultKeepAliveInterval | 56 | , defaultKeepAliveInterval |
57 | , PeerMessage (..) | ||
53 | 58 | ||
54 | -- ** Core messages | 59 | -- ** Core messages |
55 | , StatusUpdate (..) | 60 | , StatusUpdate (..) |
@@ -292,6 +297,47 @@ defaultHandshake :: InfoHash -> PeerId -> Handshake | |||
292 | defaultHandshake = Handshake def def | 297 | defaultHandshake = Handshake def def |
293 | 298 | ||
294 | {----------------------------------------------------------------------- | 299 | {----------------------------------------------------------------------- |
300 | -- Stats | ||
301 | -----------------------------------------------------------------------} | ||
302 | |||
303 | -- | Number of bytes. | ||
304 | type ByteCount = Int | ||
305 | |||
306 | -- | Summary of encoded message byte layout can be used to collect | ||
307 | -- stats about message flow in both directions. This data can be | ||
308 | -- retrieved using 'stats' function. | ||
309 | data ByteStats = ByteStats | ||
310 | { -- | Number of bytes used to help encode 'control' and 'payload' | ||
311 | -- bytes: message size, message ID's, etc | ||
312 | overhead :: {-# UNPACK #-} !ByteCount | ||
313 | |||
314 | -- | Number of bytes used to exchange peers state\/options: piece | ||
315 | -- and block indexes, infohash, port numbers, peer ID\/IP, etc. | ||
316 | , control :: {-# UNPACK #-} !ByteCount | ||
317 | |||
318 | -- | Number of payload bytes: torrent data blocks and infodict | ||
319 | -- metadata. | ||
320 | , payload :: {-# UNPACK #-} !ByteCount | ||
321 | } deriving Show | ||
322 | |||
323 | -- | Empty byte sequences. | ||
324 | instance Default ByteStats where | ||
325 | def = ByteStats 0 0 0 | ||
326 | |||
327 | -- | Monoid under addition. | ||
328 | instance Monoid ByteStats where | ||
329 | mempty = def | ||
330 | mappend a b = ByteStats | ||
331 | { overhead = overhead a + overhead b | ||
332 | , control = control a + control b | ||
333 | , payload = payload a + payload b | ||
334 | } | ||
335 | |||
336 | -- | Sum of the all byte sequences. | ||
337 | byteLength :: ByteStats -> Int | ||
338 | byteLength ByteStats {..} = overhead + control + payload | ||
339 | |||
340 | {----------------------------------------------------------------------- | ||
295 | -- Regular messages | 341 | -- Regular messages |
296 | -----------------------------------------------------------------------} | 342 | -----------------------------------------------------------------------} |
297 | 343 | ||
@@ -311,6 +357,17 @@ class PeerMessage a where | |||
311 | requires :: a -> Maybe Extension | 357 | requires :: a -> Maybe Extension |
312 | requires _ = Nothing | 358 | requires _ = Nothing |
313 | 359 | ||
360 | -- | Get sizes of overhead\/control\/payload byte sequences of | ||
361 | -- binary message representation without encoding message to binary | ||
362 | -- bytestring. | ||
363 | -- | ||
364 | -- This function should obey one law: | ||
365 | -- | ||
366 | -- * 'byteLength' ('stats' msg) == 'BL.length' ('encode' msg) | ||
367 | -- | ||
368 | stats :: a -> ByteStats | ||
369 | stats _ = ByteStats 4 0 0 | ||
370 | |||
314 | {----------------------------------------------------------------------- | 371 | {----------------------------------------------------------------------- |
315 | -- Status messages | 372 | -- Status messages |
316 | -----------------------------------------------------------------------} | 373 | -----------------------------------------------------------------------} |
@@ -337,6 +394,9 @@ instance PeerMessage StatusUpdate where | |||
337 | envelop _ = Status | 394 | envelop _ = Status |
338 | {-# INLINE envelop #-} | 395 | {-# INLINE envelop #-} |
339 | 396 | ||
397 | stats _ = ByteStats 4 1 0 | ||
398 | {-# INLINE stats #-} | ||
399 | |||
340 | {----------------------------------------------------------------------- | 400 | {----------------------------------------------------------------------- |
341 | -- Available messages | 401 | -- Available messages |
342 | -----------------------------------------------------------------------} | 402 | -----------------------------------------------------------------------} |
@@ -361,12 +421,14 @@ instance Pretty Available where | |||
361 | 421 | ||
362 | instance PeerMessage Available where | 422 | instance PeerMessage Available where |
363 | envelop _ = Available | 423 | envelop _ = Available |
364 | |||
365 | -- | BITFIELD message. | ||
366 | instance PeerMessage Bitfield where | ||
367 | envelop c = envelop c . Bitfield | ||
368 | {-# INLINE envelop #-} | 424 | {-# INLINE envelop #-} |
369 | 425 | ||
426 | stats (Have _) = ByteStats (4 + 1) 4 0 | ||
427 | stats (Bitfield bf) = ByteStats (4 + 1) (q + trailing) 0 | ||
428 | where | ||
429 | trailing = if r == 0 then 0 else 1 | ||
430 | (q, r) = quotRem (totalCount bf) 8 | ||
431 | |||
370 | {----------------------------------------------------------------------- | 432 | {----------------------------------------------------------------------- |
371 | -- Transfer messages | 433 | -- Transfer messages |
372 | -----------------------------------------------------------------------} | 434 | -----------------------------------------------------------------------} |
@@ -395,15 +457,9 @@ instance PeerMessage Transfer where | |||
395 | envelop _ = Transfer | 457 | envelop _ = Transfer |
396 | {-# INLINE envelop #-} | 458 | {-# INLINE envelop #-} |
397 | 459 | ||
398 | -- | REQUEST message. | 460 | stats (Request _ ) = ByteStats (4 + 1) (3 * 4) 0 |
399 | instance PeerMessage BlockIx where | 461 | stats (Piece pi ) = ByteStats (4 + 1) (4 + 4 + blockSize pi) 0 |
400 | envelop c = envelop c . Request | 462 | stats (Cancel _ ) = ByteStats (4 + 1) (3 * 4) 0 |
401 | {-# INLINE envelop #-} | ||
402 | |||
403 | -- | PIECE message. | ||
404 | instance PeerMessage (Block BL.ByteString) where | ||
405 | envelop c = envelop c . Piece | ||
406 | {-# INLINE envelop #-} | ||
407 | 463 | ||
408 | {----------------------------------------------------------------------- | 464 | {----------------------------------------------------------------------- |
409 | -- Fast messages | 465 | -- Fast messages |
@@ -424,11 +480,12 @@ data FastMessage = | |||
424 | -- amount of IO. | 480 | -- amount of IO. |
425 | | SuggestPiece !PieceIx | 481 | | SuggestPiece !PieceIx |
426 | 482 | ||
427 | -- | Notifies a requesting peer that its request will not be satisfied. | 483 | -- | Notifies a requesting peer that its request will not be |
484 | -- satisfied. | ||
428 | | RejectRequest !BlockIx | 485 | | RejectRequest !BlockIx |
429 | 486 | ||
430 | -- | This is an advisory messsage meaning "if you ask for this | 487 | -- | This is an advisory messsage meaning \"if you ask for this |
431 | -- piece, I'll give it to you even if you're choked." Used to | 488 | -- piece, I'll give it to you even if you're choked.\" Used to |
432 | -- shorten starting phase. | 489 | -- shorten starting phase. |
433 | | AllowedFast !PieceIx | 490 | | AllowedFast !PieceIx |
434 | deriving (Show, Eq) | 491 | deriving (Show, Eq) |
@@ -447,6 +504,12 @@ instance PeerMessage FastMessage where | |||
447 | requires _ = Just ExtFast | 504 | requires _ = Just ExtFast |
448 | {-# INLINE requires #-} | 505 | {-# INLINE requires #-} |
449 | 506 | ||
507 | stats HaveAll = ByteStats 4 1 0 | ||
508 | stats HaveNone = ByteStats 4 1 0 | ||
509 | stats (SuggestPiece _) = ByteStats 5 4 0 | ||
510 | stats (RejectRequest _) = ByteStats 5 12 0 | ||
511 | stats (AllowedFast _) = ByteStats 5 4 0 | ||
512 | |||
450 | {----------------------------------------------------------------------- | 513 | {----------------------------------------------------------------------- |
451 | -- Extension protocol | 514 | -- Extension protocol |
452 | -----------------------------------------------------------------------} | 515 | -----------------------------------------------------------------------} |
@@ -588,7 +651,7 @@ extHandshakeId = 0 | |||
588 | 651 | ||
589 | -- | Default 'Request' queue size. | 652 | -- | Default 'Request' queue size. |
590 | defaultQueueLength :: Int | 653 | defaultQueueLength :: Int |
591 | defaultQueueLength = 0 | 654 | defaultQueueLength = 1 |
592 | 655 | ||
593 | -- | All fields are empty. | 656 | -- | All fields are empty. |
594 | instance Default ExtendedHandshake where | 657 | instance Default ExtendedHandshake where |
@@ -619,6 +682,7 @@ instance BEncode ExtendedHandshake where | |||
619 | instance Pretty ExtendedHandshake where | 682 | instance Pretty ExtendedHandshake where |
620 | pretty = PP.text . show | 683 | pretty = PP.text . show |
621 | 684 | ||
685 | -- | NOTE: Approximated 'stats'. | ||
622 | instance PeerMessage ExtendedHandshake where | 686 | instance PeerMessage ExtendedHandshake where |
623 | envelop c = envelop c . EHandshake | 687 | envelop c = envelop c . EHandshake |
624 | {-# INLINE envelop #-} | 688 | {-# INLINE envelop #-} |
@@ -626,6 +690,9 @@ instance PeerMessage ExtendedHandshake where | |||
626 | requires _ = Just ExtExtended | 690 | requires _ = Just ExtExtended |
627 | {-# INLINE requires #-} | 691 | {-# INLINE requires #-} |
628 | 692 | ||
693 | stats _ = ByteStats (4 + 1 + 1) 100 {- is it ok? -} 0 -- FIXME | ||
694 | {-# INLINE stats #-} | ||
695 | |||
629 | -- | Set default values and the specified 'ExtendedCaps'. | 696 | -- | Set default values and the specified 'ExtendedCaps'. |
630 | nullExtendedHandshake :: ExtendedCaps -> ExtendedHandshake | 697 | nullExtendedHandshake :: ExtendedCaps -> ExtendedHandshake |
631 | nullExtendedHandshake caps = ExtendedHandshake | 698 | nullExtendedHandshake caps = ExtendedHandshake |
@@ -721,6 +788,7 @@ instance Pretty ExtendedMetadata where | |||
721 | pretty (MetadataReject pix ) = "Reject" <+> PP.int pix | 788 | pretty (MetadataReject pix ) = "Reject" <+> PP.int pix |
722 | pretty (MetadataUnknown bval ) = "Unknown" <+> ppBEncode bval | 789 | pretty (MetadataUnknown bval ) = "Unknown" <+> ppBEncode bval |
723 | 790 | ||
791 | -- | NOTE: Approximated 'stats'. | ||
724 | instance PeerMessage ExtendedMetadata where | 792 | instance PeerMessage ExtendedMetadata where |
725 | envelop c = envelop c . EMetadata (remoteMessageId ExtMetadata c) | 793 | envelop c = envelop c . EMetadata (remoteMessageId ExtMetadata c) |
726 | {-# INLINE envelop #-} | 794 | {-# INLINE envelop #-} |
@@ -728,6 +796,14 @@ instance PeerMessage ExtendedMetadata where | |||
728 | requires _ = Just ExtExtended | 796 | requires _ = Just ExtExtended |
729 | {-# INLINE requires #-} | 797 | {-# INLINE requires #-} |
730 | 798 | ||
799 | stats (MetadataRequest _) = ByteStats (4 + 1 + 1) {- ~ -} 25 0 | ||
800 | stats (MetadataData pi t) = ByteStats (4 + 1 + 1) {- ~ -} 41 $ | ||
801 | BS.length (Data.pieceData pi) | ||
802 | stats (MetadataReject _) = ByteStats (4 + 1 + 1) {- ~ -} 25 0 | ||
803 | stats (MetadataUnknown _) = ByteStats (4 + 1 + 1) {- ? -} 0 0 | ||
804 | |||
805 | -- | All 'Piece's in 'MetadataData' messages MUST have size equal to | ||
806 | -- this value. The last trailing piece can be shorter. | ||
731 | metadataPieceSize :: Int | 807 | metadataPieceSize :: Int |
732 | metadataPieceSize = 16 * 1024 | 808 | metadataPieceSize = 16 * 1024 |
733 | 809 | ||
@@ -791,6 +867,10 @@ instance PeerMessage ExtendedMessage where | |||
791 | requires _ = Just ExtExtended | 867 | requires _ = Just ExtExtended |
792 | {-# INLINE requires #-} | 868 | {-# INLINE requires #-} |
793 | 869 | ||
870 | stats (EHandshake hs) = stats hs | ||
871 | stats (EMetadata _ msg) = stats msg | ||
872 | stats (EUnknown _ msg) = ByteStats (4 + 1 + 1) (BS.length msg) 0 | ||
873 | |||
794 | {----------------------------------------------------------------------- | 874 | {----------------------------------------------------------------------- |
795 | -- The message datatype | 875 | -- The message datatype |
796 | -----------------------------------------------------------------------} | 876 | -----------------------------------------------------------------------} |
@@ -849,6 +929,14 @@ instance PeerMessage Message where | |||
849 | requires (Fast _) = Just ExtFast | 929 | requires (Fast _) = Just ExtFast |
850 | requires (Extended _) = Just ExtExtended | 930 | requires (Extended _) = Just ExtExtended |
851 | 931 | ||
932 | stats KeepAlive = ByteStats 4 0 0 | ||
933 | stats (Status m) = stats m | ||
934 | stats (Available m) = stats m | ||
935 | stats (Transfer m) = stats m | ||
936 | stats (Port _) = ByteStats 5 2 0 | ||
937 | stats (Fast m) = stats m | ||
938 | stats (Extended m) = stats m | ||
939 | |||
852 | -- | PORT message. | 940 | -- | PORT message. |
853 | instance PeerMessage PortNumber where | 941 | instance PeerMessage PortNumber where |
854 | envelop _ = Port | 942 | envelop _ = Port |