summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bittorrent.cabal1
-rw-r--r--src/Network/BitTorrent/Exchange/Connection.hs111
-rw-r--r--src/Network/BitTorrent/Exchange/Connection/Status.hs131
-rw-r--r--src/Network/BitTorrent/Exchange/Session.hs1
4 files changed, 105 insertions, 139 deletions
diff --git a/bittorrent.cabal b/bittorrent.cabal
index 91d227b2..af6caefa 100644
--- a/bittorrent.cabal
+++ b/bittorrent.cabal
@@ -72,7 +72,6 @@ library
72 Network.BitTorrent.Exchange.Assembler 72 Network.BitTorrent.Exchange.Assembler
73 Network.BitTorrent.Exchange.Block 73 Network.BitTorrent.Exchange.Block
74 Network.BitTorrent.Exchange.Connection 74 Network.BitTorrent.Exchange.Connection
75 Network.BitTorrent.Exchange.Connection.Status
76 Network.BitTorrent.Exchange.Manager 75 Network.BitTorrent.Exchange.Manager
77 Network.BitTorrent.Exchange.Message 76 Network.BitTorrent.Exchange.Message
78 Network.BitTorrent.Exchange.Selection 77 Network.BitTorrent.Exchange.Selection
diff --git a/src/Network/BitTorrent/Exchange/Connection.hs b/src/Network/BitTorrent/Exchange/Connection.hs
index dde9a468..fd9022da 100644
--- a/src/Network/BitTorrent/Exchange/Connection.hs
+++ b/src/Network/BitTorrent/Exchange/Connection.hs
@@ -49,6 +49,19 @@ module Network.BitTorrent.Exchange.Connection
49 , connSession 49 , connSession
50 , connStats 50 , connStats
51 51
52 -- ** Status
53 , PeerStatus (..)
54 , ConnectionStatus (..)
55 , updateStatus
56 , statusUpdates
57 , clientStatus
58 , remoteStatus
59 , canUpload
60 , canDownload
61 , defaultUnchokeSlots
62 , defaultRechokeInterval
63
64
52 -- * Setup 65 -- * Setup
53 , ConnectionPrefs (..) 66 , ConnectionPrefs (..)
54 , SessionLink (..) 67 , SessionLink (..)
@@ -102,21 +115,21 @@ import Control.Monad.State
102import Control.Lens 115import Control.Lens
103import Data.ByteString as BS 116import Data.ByteString as BS
104import Data.ByteString.Lazy as BSL 117import Data.ByteString.Lazy as BSL
105import Data.Conduit 118import Data.Conduit as C
106import Data.Conduit.Cereal 119import Data.Conduit.Cereal
107import Data.Conduit.List 120import Data.Conduit.List
108import Data.Conduit.Network 121import Data.Conduit.Network
109import Data.Default 122import Data.Default
110import Data.IORef 123import Data.IORef
111import Data.List as L 124import Data.List as L
112import Data.Maybe 125import Data.Maybe as M
113import Data.Monoid 126import Data.Monoid
114import Data.Serialize as S 127import Data.Serialize as S
115import Data.Typeable 128import Data.Typeable
116import Network 129import Network
117import Network.Socket hiding (Connected) 130import Network.Socket hiding (Connected)
118import Network.Socket.ByteString as BS 131import Network.Socket.ByteString as BS
119import Text.PrettyPrint as PP hiding (($$), (<>)) 132import Text.PrettyPrint as PP hiding ((<>))
120import Text.PrettyPrint.Class 133import Text.PrettyPrint.Class
121import Text.Show.Functions () 134import Text.Show.Functions ()
122import System.Log.FastLogger (ToLogStr(..)) 135import System.Log.FastLogger (ToLogStr(..))
@@ -125,7 +138,6 @@ import System.Timeout
125import Data.Torrent.Bitfield as BF 138import Data.Torrent.Bitfield as BF
126import Data.Torrent.InfoHash 139import Data.Torrent.InfoHash
127import Network.BitTorrent.Core 140import Network.BitTorrent.Core
128import Network.BitTorrent.Exchange.Connection.Status
129import Network.BitTorrent.Exchange.Message as Msg 141import Network.BitTorrent.Exchange.Message as Msg
130 142
131-- TODO handle port message? 143-- TODO handle port message?
@@ -463,6 +475,93 @@ instance Default Options where
463 } 475 }
464 476
465{----------------------------------------------------------------------- 477{-----------------------------------------------------------------------
478-- Peer status
479-----------------------------------------------------------------------}
480
481-- | Connections contain two bits of state on either end: choked or
482-- not, and interested or not.
483data PeerStatus = PeerStatus
484 { -- | Choking is a notification that no data will be sent until
485 -- unchoking happens.
486 _choking :: !Bool
487
488 -- |
489 , _interested :: !Bool
490 } deriving (Show, Eq, Ord)
491
492$(makeLenses ''PeerStatus)
493
494instance Pretty PeerStatus where
495 pretty PeerStatus {..} =
496 pretty (Choking _choking) <+> "and" <+> pretty (Interested _interested)
497
498-- | Connections start out choked and not interested.
499instance Default PeerStatus where
500 def = PeerStatus True False
501
502instance Monoid PeerStatus where
503 mempty = def
504 mappend a b = PeerStatus
505 { _choking = _choking a && _choking b
506 , _interested = _interested a || _interested b
507 }
508
509-- | Can be used to update remote peer status using incoming 'Status'
510-- message.
511updateStatus :: StatusUpdate -> PeerStatus -> PeerStatus
512updateStatus (Choking b) = choking .~ b
513updateStatus (Interested b) = interested .~ b
514
515-- | Can be used to generate outcoming messages.
516statusUpdates :: PeerStatus -> PeerStatus -> [StatusUpdate]
517statusUpdates a b = M.catMaybes $
518 [ if _choking a == _choking b then Nothing
519 else Just $ Choking $ _choking b
520 , if _interested a == _interested b then Nothing
521 else Just $ Interested $ _interested b
522 ]
523
524{-----------------------------------------------------------------------
525-- Connection status
526-----------------------------------------------------------------------}
527
528-- | Status of the both endpoints.
529data ConnectionStatus = ConnectionStatus
530 { _clientStatus :: !PeerStatus
531 , _remoteStatus :: !PeerStatus
532 } deriving (Show, Eq)
533
534$(makeLenses ''ConnectionStatus)
535
536instance Pretty ConnectionStatus where
537 pretty ConnectionStatus {..} =
538 "this " PP.<+> pretty _clientStatus PP.$$
539 "remote" PP.<+> pretty _remoteStatus
540
541-- | Connections start out choked and not interested.
542instance Default ConnectionStatus where
543 def = ConnectionStatus def def
544
545-- | Can the client transfer to the remote peer?
546canUpload :: ConnectionStatus -> Bool
547canUpload ConnectionStatus {..}
548 = _interested _remoteStatus && not (_choking _clientStatus)
549
550-- | Can the client transfer from the remote peer?
551canDownload :: ConnectionStatus -> Bool
552canDownload ConnectionStatus {..}
553 = _interested _clientStatus && not (_choking _remoteStatus)
554
555-- | Indicates how many peers are allowed to download from the client
556-- by default.
557defaultUnchokeSlots :: Int
558defaultUnchokeSlots = 4
559
560-- |
561defaultRechokeInterval :: Int
562defaultRechokeInterval = 10 * 1000 * 1000
563
564{-----------------------------------------------------------------------
466-- Connection 565-- Connection
467-----------------------------------------------------------------------} 566-----------------------------------------------------------------------}
468 567
@@ -681,7 +780,7 @@ runWire action sock chan conn = flip runReaderT conn $ runConnected $
681 conduitGet S.get $= 780 conduitGet S.get $=
682 trackFlow RemotePeer $= 781 trackFlow RemotePeer $=
683 action $= 782 action $=
684 trackFlow ThisPeer $$ 783 trackFlow ThisPeer C.$$
685 sinkChan chan 784 sinkChan chan
686 785
687-- | This function will block until a peer send new message. You can 786-- | This function will block until a peer send new message. You can
@@ -835,7 +934,7 @@ closePending PendingConnection {..} = do
835 934
836chanToSock :: Int -> Chan Message -> Socket -> IO () 935chanToSock :: Int -> Chan Message -> Socket -> IO ()
837chanToSock ka chan sock = 936chanToSock ka chan sock =
838 sourceChan ka chan $= conduitPut S.put $$ sinkSocket sock 937 sourceChan ka chan $= conduitPut S.put C.$$ sinkSocket sock
839 938
840afterHandshaking :: ChannelSide -> PeerAddr IP -> Socket -> HandshakePair 939afterHandshaking :: ChannelSide -> PeerAddr IP -> Socket -> HandshakePair
841 -> ConnectionConfig s -> IO () 940 -> ConnectionConfig s -> IO ()
diff --git a/src/Network/BitTorrent/Exchange/Connection/Status.hs b/src/Network/BitTorrent/Exchange/Connection/Status.hs
deleted file mode 100644
index f6abc580..00000000
--- a/src/Network/BitTorrent/Exchange/Connection/Status.hs
+++ /dev/null
@@ -1,131 +0,0 @@
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--
11{-# LANGUAGE TemplateHaskell #-}
12module Network.BitTorrent.Exchange.Connection.Status
13 ( -- * Peer status
14 PeerStatus(..)
15 , choking
16 , interested
17
18 -- ** Query
19 , updateStatus
20 , statusUpdates
21
22 -- * Connection status
23 , ConnectionStatus(..)
24 , clientStatus
25 , remoteStatus
26
27 -- ** Query
28 , canUpload
29 , canDownload
30
31 -- * Extra
32 , defaultUnchokeSlots
33 , defaultRechokeInterval
34 ) where
35
36import Control.Lens
37import Data.Default
38import Data.Maybe
39import Data.Monoid
40import Text.PrettyPrint as PP hiding ((<>))
41import Text.PrettyPrint.Class
42
43import Network.BitTorrent.Exchange.Message
44
45
46{-----------------------------------------------------------------------
47-- Peer status
48-----------------------------------------------------------------------}
49
50-- | Connections contain two bits of state on either end: choked or
51-- not, and interested or not.
52data PeerStatus = PeerStatus
53 { -- | Choking is a notification that no data will be sent until
54 -- unchoking happens.
55 _choking :: !Bool
56
57 -- |
58 , _interested :: !Bool
59 } deriving (Show, Eq, Ord)
60
61$(makeLenses ''PeerStatus)
62
63instance Pretty PeerStatus where
64 pretty PeerStatus {..} =
65 pretty (Choking _choking) <+> "and" <+> pretty (Interested _interested)
66
67-- | Connections start out choked and not interested.
68instance Default PeerStatus where
69 def = PeerStatus True False
70
71instance Monoid PeerStatus where
72 mempty = def
73 mappend a b = PeerStatus
74 { _choking = _choking a && _choking b
75 , _interested = _interested a || _interested b
76 }
77
78-- | Can be used to update remote peer status using incoming 'Status'
79-- message.
80updateStatus :: StatusUpdate -> PeerStatus -> PeerStatus
81updateStatus (Choking b) = choking .~ b
82updateStatus (Interested b) = interested .~ b
83
84-- | Can be used to generate outcoming messages.
85statusUpdates :: PeerStatus -> PeerStatus -> [StatusUpdate]
86statusUpdates a b = catMaybes $
87 [ if _choking a == _choking b then Nothing
88 else Just $ Choking $ _choking b
89 , if _interested a == _interested b then Nothing
90 else Just $ Interested $ _interested b
91 ]
92
93{-----------------------------------------------------------------------
94-- Connection status
95-----------------------------------------------------------------------}
96
97-- | Status of the both endpoints.
98data ConnectionStatus = ConnectionStatus
99 { _clientStatus :: !PeerStatus
100 , _remoteStatus :: !PeerStatus
101 } deriving (Show, Eq)
102
103$(makeLenses ''ConnectionStatus)
104
105instance Pretty ConnectionStatus where
106 pretty ConnectionStatus {..} =
107 "this " <+> pretty _clientStatus $$
108 "remote" <+> pretty _remoteStatus
109
110-- | Connections start out choked and not interested.
111instance Default ConnectionStatus where
112 def = ConnectionStatus def def
113
114-- | Can the client transfer to the remote peer?
115canUpload :: ConnectionStatus -> Bool
116canUpload ConnectionStatus {..}
117 = _interested _remoteStatus && not (_choking _clientStatus)
118
119-- | Can the client transfer from the remote peer?
120canDownload :: ConnectionStatus -> Bool
121canDownload ConnectionStatus {..}
122 = _interested _clientStatus && not (_choking _remoteStatus)
123
124-- | Indicates how many peers are allowed to download from the client
125-- by default.
126defaultUnchokeSlots :: Int
127defaultUnchokeSlots = 4
128
129-- |
130defaultRechokeInterval :: Int
131defaultRechokeInterval = 10 * 1000 * 1000 \ No newline at end of file
diff --git a/src/Network/BitTorrent/Exchange/Session.hs b/src/Network/BitTorrent/Exchange/Session.hs
index 91ea8da9..6f480ce4 100644
--- a/src/Network/BitTorrent/Exchange/Session.hs
+++ b/src/Network/BitTorrent/Exchange/Session.hs
@@ -54,7 +54,6 @@ import Network.BitTorrent.Internal.Types
54import Network.BitTorrent.Core 54import Network.BitTorrent.Core
55import Network.BitTorrent.Exchange.Block as Block 55import Network.BitTorrent.Exchange.Block as Block
56import Network.BitTorrent.Exchange.Connection 56import Network.BitTorrent.Exchange.Connection
57import Network.BitTorrent.Exchange.Connection.Status
58import Network.BitTorrent.Exchange.Message as Message 57import Network.BitTorrent.Exchange.Message as Message
59import Network.BitTorrent.Exchange.Session.Metadata as Metadata 58import Network.BitTorrent.Exchange.Session.Metadata as Metadata
60import Network.BitTorrent.Exchange.Session.Status as SS 59import Network.BitTorrent.Exchange.Session.Status as SS