summaryrefslogtreecommitdiff
path: root/src/Network/BitTorrent/Exchange/Status.hs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Network/BitTorrent/Exchange/Status.hs')
-rw-r--r--src/Network/BitTorrent/Exchange/Status.hs102
1 files changed, 78 insertions, 24 deletions
diff --git a/src/Network/BitTorrent/Exchange/Status.hs b/src/Network/BitTorrent/Exchange/Status.hs
index ae323e09..42766428 100644
--- a/src/Network/BitTorrent/Exchange/Status.hs
+++ b/src/Network/BitTorrent/Exchange/Status.hs
@@ -1,80 +1,134 @@
1-- |
2-- Copyright : (c) Sam Truzjan 2013
3-- License : BSD3
4-- Maintainer : pxqr.sta@gmail.com
5-- Stability : experimental
6-- Portability : portable
7--
8-- Each P2P connection endpoint should keep track status of both
9-- sides.
10--
1{-# LANGUAGE TemplateHaskell #-} 11{-# LANGUAGE TemplateHaskell #-}
2module Network.BitTorrent.Exchange.Status 12module Network.BitTorrent.Exchange.Status
3 ( -- * Peer status 13 ( -- * Peer status
4 PeerStatus(..) 14 PeerStatus(..)
5 , choking 15 , choking
6 , interested 16 , interested
17
18 -- ** Query
7 , updateStatus 19 , updateStatus
20 , statusUpdates
8 21
9 -- * Session status 22 -- * Session status
10 , SessionStatus(..) 23 , SessionStatus(..)
11 , clientStatus 24 , clientStatus
12 , peerStatus 25 , remoteStatus
13 26
14 -- ** Query 27 -- ** Query
15 , canUpload 28 , canUpload
16 , canDownload 29 , canDownload
17 30
18 -- * Extra 31 -- * Extra
19 , inverseStatus
20 , defaultUnchokeSlots 32 , defaultUnchokeSlots
33 , defaultRechokeInterval
21 ) where 34 ) where
22 35
23import Control.Lens 36import Control.Lens
24import Data.Aeson.TH 37import Data.Aeson.TH
25import Data.List as L
26import Data.Default 38import Data.Default
39import Data.List as L
40import Data.Maybe
41import Data.Monoid
42import Text.PrettyPrint as PP hiding ((<>))
43import Text.PrettyPrint.Class
27 44
28import Network.BitTorrent.Exchange.Message 45import Network.BitTorrent.Exchange.Message
29 46
47{-----------------------------------------------------------------------
48-- Peer status
49-----------------------------------------------------------------------}
30 50
31-- | 51-- | Connections contain two bits of state on either end: choked or
32data PeerStatus = PeerStatus { 52-- not, and interested or not.
53data PeerStatus = PeerStatus
54 { -- | Choking is a notification that no data will be sent until
55 -- unchoking happens.
33 _choking :: !Bool 56 _choking :: !Bool
57
58 -- |
34 , _interested :: !Bool 59 , _interested :: !Bool
35 } deriving (Show, Eq) 60 } deriving (Show, Eq, Ord)
36 61
37$(makeLenses ''PeerStatus) 62$(makeLenses ''PeerStatus)
38$(deriveJSON defaultOptions { fieldLabelModifier = L.tail } ''PeerStatus) 63$(deriveJSON defaultOptions { fieldLabelModifier = L.tail } ''PeerStatus)
39 64
65instance Pretty PeerStatus where
66 pretty PeerStatus {..} =
67 pretty (Choking _choking) <+> "and" <+> pretty (Interested _interested)
68
69-- | Connections start out choked and not interested.
40instance Default PeerStatus where 70instance Default PeerStatus where
41 def = PeerStatus True False 71 def = PeerStatus True False
42 72
73instance Monoid PeerStatus where
74 mempty = def
75 mappend a b = PeerStatus
76 { _choking = _choking a && _choking b
77 , _interested = _interested a || _interested b
78 }
79
80-- | Can be used to update remote peer status using incoming 'Status'
81-- message.
43updateStatus :: StatusUpdate -> PeerStatus -> PeerStatus 82updateStatus :: StatusUpdate -> PeerStatus -> PeerStatus
44updateStatus Choke = choking .~ True 83updateStatus (Choking b) = choking .~ b
45updateStatus Unchoke = choking .~ False 84updateStatus (Interested b) = interested .~ b
46updateStatus Interested = interested .~ True
47updateStatus NotInterested = interested .~ False
48 85
86-- | Can be used to generate outcoming messages.
49statusUpdates :: PeerStatus -> PeerStatus -> [StatusUpdate] 87statusUpdates :: PeerStatus -> PeerStatus -> [StatusUpdate]
50statusUpdates a b = undefined 88statusUpdates a b = catMaybes $
51 89 [ if _choking a == _choking b then Nothing
52-- | 90 else Just $ Choking $ _choking b
53data SessionStatus = SessionStatus { 91 , if _interested a == _interested b then Nothing
54 _clientStatus :: !PeerStatus 92 else Just $ Interested $ _interested b
55 , _peerStatus :: !PeerStatus 93 ]
94
95{-----------------------------------------------------------------------
96-- Session status
97-----------------------------------------------------------------------}
98
99-- | Status of the both endpoints.
100data SessionStatus = SessionStatus
101 { _clientStatus :: !PeerStatus
102 , _remoteStatus :: !PeerStatus
56 } deriving (Show, Eq) 103 } deriving (Show, Eq)
57 104
58$(makeLenses ''SessionStatus) 105$(makeLenses ''SessionStatus)
59$(deriveJSON defaultOptions { fieldLabelModifier = L.tail } ''SessionStatus) 106$(deriveJSON defaultOptions { fieldLabelModifier = L.tail } ''SessionStatus)
60 107
108instance Pretty SessionStatus where
109 pretty SessionStatus {..} =
110 "this " <+> pretty _clientStatus $$
111 "remote" <+> pretty _remoteStatus
112
113-- | Connections start out choked and not interested.
61instance Default SessionStatus where 114instance Default SessionStatus where
62 def = SessionStatus def def 115 def = SessionStatus def def
63 116
64-- | Can the /client/ transfer to the /peer/? 117-- | Can the client transfer to the remote peer?
65canUpload :: SessionStatus -> Bool 118canUpload :: SessionStatus -> Bool
66canUpload SessionStatus {..} 119canUpload SessionStatus {..}
67 = _interested _peerStatus && not (_choking _clientStatus) 120 = _interested _remoteStatus && not (_choking _clientStatus)
68 121
69-- | Can the /client/ transfer from the /peer/? 122-- | Can the client transfer from the remote peer?
70canDownload :: SessionStatus -> Bool 123canDownload :: SessionStatus -> Bool
71canDownload SessionStatus {..} 124canDownload SessionStatus {..}
72 = _interested _clientStatus && not (_choking _peerStatus) 125 = _interested _clientStatus && not (_choking _remoteStatus)
73
74inverseStatus :: SessionStatus -> SessionStatus
75inverseStatus SessionStatus {..} = SessionStatus _peerStatus _clientStatus
76 126
77-- | Indicates how many peers are allowed to download from the client 127-- | Indicates how many peers are allowed to download from the client
78-- by default. 128-- by default.
79defaultUnchokeSlots :: Int 129defaultUnchokeSlots :: Int
80defaultUnchokeSlots = 4 \ No newline at end of file 130defaultUnchokeSlots = 4
131
132-- |
133defaultRechokeInterval :: Int
134defaultRechokeInterval = 10 * 1000 * 1000 \ No newline at end of file