summaryrefslogtreecommitdiff
path: root/src/Network/BitTorrent/Peer.hs
diff options
context:
space:
mode:
authorSam T <pxqr.sta@gmail.com>2013-08-28 02:38:21 +0400
committerSam T <pxqr.sta@gmail.com>2013-08-28 02:38:21 +0400
commit54b20f9ac462105cd3857b9c8102954a725ef308 (patch)
treef4c66aef69be9ece2e37a21c206186feb15be5d0 /src/Network/BitTorrent/Peer.hs
parent20db22d1b09079b88e95e5054df2589fa956fc01 (diff)
~ Group AnnounceQuery progress fields to Progress.
Diffstat (limited to 'src/Network/BitTorrent/Peer.hs')
-rw-r--r--src/Network/BitTorrent/Peer.hs88
1 files changed, 85 insertions, 3 deletions
diff --git a/src/Network/BitTorrent/Peer.hs b/src/Network/BitTorrent/Peer.hs
index a4d026dc..d951a1cd 100644
--- a/src/Network/BitTorrent/Peer.hs
+++ b/src/Network/BitTorrent/Peer.hs
@@ -28,6 +28,7 @@
28-- capabilities (such as supported enchancements), this should be 28-- capabilities (such as supported enchancements), this should be
29-- done using 'Network.BitTorrent.Extension'! 29-- done using 'Network.BitTorrent.Extension'!
30-- 30--
31{-# LANGUAGE ViewPatterns #-}
31{-# LANGUAGE GeneralizedNewtypeDeriving #-} 32{-# LANGUAGE GeneralizedNewtypeDeriving #-}
32{-# LANGUAGE StandaloneDeriving #-} 33{-# LANGUAGE StandaloneDeriving #-}
33{-# LANGUAGE TemplateHaskell #-} 34{-# LANGUAGE TemplateHaskell #-}
@@ -56,6 +57,19 @@ module Network.BitTorrent.Peer
56 , connectToPeer 57 , connectToPeer
57 , ppPeer 58 , ppPeer
58 59
60 -- * Peer progress
61 , Progress (..)
62 , left
63 , uploaded
64 , downloaded
65
66 , startProgress
67
68 , downloadedProgress
69 , enqueuedProgress
70 , uploadedProgress
71 , dequeuedProgress
72
59 -- * Client version detection 73 -- * Client version detection
60 -- ** Info 74 -- ** Info
61 , ClientInfo(..), clientInfo, ppClientInfo, unknownClient 75 , ClientInfo(..), clientInfo, ppClientInfo, unknownClient
@@ -70,18 +84,19 @@ module Network.BitTorrent.Peer
70 84
71 85
72import Control.Applicative 86import Control.Applicative
87import Control.Lens
73import Data.Aeson 88import Data.Aeson
74import Data.Aeson.TH 89import Data.Aeson.TH
75import Data.BEncode 90import Data.BEncode
76import Data.Bits 91import Data.Bits
77import Data.Char
78import Data.List as L
79import Data.Word
80import Data.ByteString (ByteString) 92import Data.ByteString (ByteString)
81import qualified Data.ByteString as B 93import qualified Data.ByteString as B
82import qualified Data.ByteString.Char8 as BC 94import qualified Data.ByteString.Char8 as BC
83import qualified Data.ByteString.Lazy as BL 95import qualified Data.ByteString.Lazy as BL
84import qualified Data.ByteString.Lazy.Builder as B 96import qualified Data.ByteString.Lazy.Builder as B
97import Data.Char
98import Data.List as L
99import Data.Word
85import Data.Foldable (foldMap) 100import Data.Foldable (foldMap)
86import Data.Monoid ((<>)) 101import Data.Monoid ((<>))
87import Data.Serialize 102import Data.Serialize
@@ -577,3 +592,70 @@ ppPeer p @ PeerAddr {..} = case peerID of
577 Nothing -> paddr 592 Nothing -> paddr
578 where 593 where
579 paddr = text (show (peerSockAddr p)) 594 paddr = text (show (peerSockAddr p))
595
596{-----------------------------------------------------------------------
597 Progress
598-----------------------------------------------------------------------}
599
600-- TODO: Use Word64?
601-- TODO: Use atomic bits?
602
603-- | 'Progress' contains upload/download/left stats about
604-- current client state and used to notify the tracker.
605--
606-- Progress data is considered as dynamic within one client
607-- session. This data also should be shared across client application
608-- sessions (e.g. files), otherwise use 'startProgress' to get initial
609-- 'Progress'.
610--
611data Progress = Progress
612 { _downloaded :: !Integer -- ^ Total amount of bytes downloaded;
613 , _left :: !Integer -- ^ Total amount of bytes left;
614 , _uploaded :: !Integer -- ^ Total amount of bytes uploaded.
615 } deriving (Show, Read, Eq)
616
617$(makeLenses ''Progress)
618$(deriveJSON (L.tail) ''Progress)
619
620instance Serialize Progress where
621 put Progress {..} = do
622 putWord64be $ fromIntegral _downloaded
623 putWord64be $ fromIntegral _left
624 putWord64be $ fromIntegral _uploaded
625
626 get = Progress
627 <$> (fromIntegral <$> getWord64be)
628 <*> (fromIntegral <$> getWord64be)
629 <*> (fromIntegral <$> getWord64be)
630
631-- | Initial progress is used when there are no session before.
632--
633-- Please note that tracker might penalize client some way if the do
634-- not accumulate progress. If possible and save 'Progress' between
635-- client sessions to avoid that.
636--
637startProgress :: Integer -> Progress
638startProgress = Progress 0 0
639
640-- | Used when the client download some data from /any/ peer.
641downloadedProgress :: Int -> Progress -> Progress
642downloadedProgress (fromIntegral -> amount)
643 = (left -~ amount)
644 . (downloaded +~ amount)
645{-# INLINE downloadedProgress #-}
646
647-- | Used when the client upload some data to /any/ peer.
648uploadedProgress :: Int -> Progress -> Progress
649uploadedProgress (fromIntegral -> amount) = uploaded +~ amount
650{-# INLINE uploadedProgress #-}
651
652-- | Used when leecher join client session.
653enqueuedProgress :: Integer -> Progress -> Progress
654enqueuedProgress amount = left +~ amount
655{-# INLINE enqueuedProgress #-}
656
657-- | Used when leecher leave client session.
658-- (e.g. user deletes not completed torrent)
659dequeuedProgress :: Integer -> Progress -> Progress
660dequeuedProgress amount = left -~ amount
661{-# INLINE dequeuedProgress #-}