summaryrefslogtreecommitdiff
path: root/src/Network/BitTorrent/Exchange.hs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Network/BitTorrent/Exchange.hs')
-rw-r--r--src/Network/BitTorrent/Exchange.hs124
1 files changed, 89 insertions, 35 deletions
diff --git a/src/Network/BitTorrent/Exchange.hs b/src/Network/BitTorrent/Exchange.hs
index 65ec0eb7..de13d4ce 100644
--- a/src/Network/BitTorrent/Exchange.hs
+++ b/src/Network/BitTorrent/Exchange.hs
@@ -18,7 +18,7 @@ module Network.BitTorrent.Exchange
18 , Event(..) 18 , Event(..)
19 19
20 , P2P, withPeer 20 , P2P, withPeer
21 , awaitEvent, signalEvent 21 , awaitEvent, yieldEvent
22 ) where 22 ) where
23 23
24import Control.Applicative 24import Control.Applicative
@@ -70,29 +70,31 @@ runConduit sock p2p =
70 conduitPut S.put $$ 70 conduitPut S.put $$
71 sinkSocket sock 71 sinkSocket sock
72 72
73waitMessage :: P2P Message 73awaitMessage :: P2P Message
74waitMessage = P2P (ReaderT go) 74awaitMessage = P2P (ReaderT go)
75 where 75 where
76 go se = do 76 go se = do
77 liftIO $ putStrLn "trying recv:"
77 mmsg <- await 78 mmsg <- await
78 case mmsg of 79 case mmsg of
79 Nothing -> go se 80 Nothing -> go se
80 Just msg -> do 81 Just msg -> do
81 liftIO $ updateIncoming se 82-- liftIO $ updateIncoming se
82 liftIO $ print msg 83 liftIO $ print ("recv:" <+> ppMessage msg)
83 return msg 84 return msg
84 85
85signalMessage :: Message -> P2P () 86yieldMessage :: Message -> P2P ()
86signalMessage msg = P2P $ ReaderT $ \se -> do 87yieldMessage msg = P2P $ ReaderT $ \se -> do
87 C.yield msg 88 C.yield msg
89 liftIO $ print $ "sent:" <+> ppMessage msg
88 liftIO $ updateOutcoming se 90 liftIO $ updateOutcoming se
89 91
90 92
91peerWant :: P2P Bitfield 93peerWant :: P2P Bitfield
92peerWant = BF.difference <$> getPeerBF <*> use bitfield 94peerWant = BF.difference <$> getClientBF <*> use bitfield
93 95
94clientWant :: P2P Bitfield 96clientWant :: P2P Bitfield
95clientWant = BF.difference <$> use bitfield <*> getPeerBF 97clientWant = BF.difference <$> use bitfield <*> getClientBF
96 98
97peerOffer :: P2P Bitfield 99peerOffer :: P2P Bitfield
98peerOffer = do 100peerOffer = do
@@ -104,13 +106,17 @@ clientOffer = do
104 sessionStatus <- use status 106 sessionStatus <- use status
105 if canUpload sessionStatus then peerWant else emptyBF 107 if canUpload sessionStatus then peerWant else emptyBF
106 108
107revise :: P2P () 109revise :: P2P Bitfield
108revise = do 110revise = do
109 peerInteresting <- (not . BF.null) <$> clientWant 111 want <- clientWant
112 let peerInteresting = not (BF.null want)
110 clientInterested <- use (status.clientStatus.interested) 113 clientInterested <- use (status.clientStatus.interested)
111 114
112 when (clientInterested /= peerInteresting) $ 115 when (clientInterested /= peerInteresting) $ do
113 signalMessage $ if peerInteresting then Interested else NotInterested 116 yieldMessage $ if peerInteresting then Interested else NotInterested
117 status.clientStatus.interested .= peerInteresting
118
119 return want
114 120
115requireExtension :: Extension -> P2P () 121requireExtension :: Extension -> P2P ()
116requireExtension required = do 122requireExtension required = do
@@ -118,9 +124,6 @@ requireExtension required = do
118 unless (required `elem` enabled) $ 124 unless (required `elem` enabled) $
119 sessionError $ ppExtension required <+> "not enabled" 125 sessionError $ ppExtension required <+> "not enabled"
120 126
121peerHave :: P2P Event
122peerHave = undefined
123
124-- haveMessage bf = do 127-- haveMessage bf = do
125-- cbf <- undefined -- liftIO $ readIORef $ clientBitfield swarmSession 128-- cbf <- undefined -- liftIO $ readIORef $ clientBitfield swarmSession
126-- if undefined -- ix `member` bf 129-- if undefined -- ix `member` bf
@@ -129,12 +132,21 @@ peerHave = undefined
129 132
130 133
131-- | 134-- |
135-- +----------+---------+
136-- | Leacher | Seeder |
137-- |----------+---------+
138-- | Available| |
139-- | Want | Want |
140-- | Fragment | |
141-- +----------+---------+
142--
143--
132-- properties: 144-- properties:
133-- 145--
134-- forall (Fragment block). isPiece block == True 146-- forall (Fragment block). isPiece block == True
135-- 147--
136awaitEvent :: P2P Event 148awaitEvent :: P2P Event
137awaitEvent = waitMessage >>= go 149awaitEvent = awaitMessage >>= go
138 where 150 where
139 go KeepAlive = awaitEvent 151 go KeepAlive = awaitEvent
140 go Choke = do 152 go Choke = do
@@ -142,8 +154,11 @@ awaitEvent = waitMessage >>= go
142 awaitEvent 154 awaitEvent
143 155
144 go Unchoke = do 156 go Unchoke = do
145 status.clientStatus.choking .= False 157 status.peerStatus.choking .= False
146 awaitEvent 158 offer <- peerOffer
159 if BF.null offer
160 then awaitEvent
161 else return (Available offer)
147 162
148 go Interested = do 163 go Interested = do
149 status.peerStatus.interested .= True 164 status.peerStatus.interested .= True
@@ -153,21 +168,45 @@ awaitEvent = waitMessage >>= go
153 status.peerStatus.interested .= False 168 status.peerStatus.interested .= False
154 awaitEvent 169 awaitEvent
155 170
156-- go (Have ix) = peerHave =<< singletonBF ix 171 go (Have ix) = do
157-- go (Bitfield bf) = peerHave =<< adjustBF bf 172 new <- singletonBF ix
173 bitfield %= BF.union new
174 revise
175
176 offer <- peerOffer
177 if not (BF.null offer)
178 then return (Available offer)
179 else awaitEvent
180
181 go (Bitfield bf) = do
182 new <- adjustBF bf
183 bitfield .= new
184 revise
185
186 offer <- peerOffer
187 if not (BF.null offer)
188 then return (Available offer)
189 else awaitEvent
190
158 go (Request bix) = do 191 go (Request bix) = do
159 bf <- use bitfield 192 bf <- clientOffer
160 if ixPiece bix `BF.member` bf 193 if ixPiece bix `BF.member` bf
161 then return (Want bix) 194 then return (Want bix)
162 else do 195 else do
163 signalMessage (RejectRequest bix) 196-- check if extension is enabled
197-- yieldMessage (RejectRequest bix)
164 awaitEvent 198 awaitEvent
165 199
166 go (Piece blk) = undefined 200 go (Piece blk) = do
201 -- this protect us from malicious peers and duplication
202 wanted <- clientWant
203 if blkPiece blk `BF.member` wanted
204 then return (Fragment blk)
205 else awaitEvent
167 206
168{- 207{-
169 go msg @ (Port _) 208 go (Port _) = do
170 = checkExtension msg ExtDHT $ do 209 requireExtension ExtDHT
171 undefined 210 undefined
172 211
173 go HaveAll = do 212 go HaveAll = do
@@ -189,24 +228,39 @@ awaitEvent = waitMessage >>= go
189 then Available <$> singletonBF ix 228 then Available <$> singletonBF ix
190 else awaitEvent 229 else awaitEvent
191 230
192 go msg @ (RejectRequest ix) 231 go (RejectRequest ix) = do
193 = checkExtension msg ExtFast $ do 232 requireExtension ExtFast
194 undefined 233 awaitMessage
195 234
196 go msg @ (AllowedFast pix) 235 go (AllowedFast pix) =
197 = checkExtension msg ExtFast $ do 236 requireExtension ExtFast
198 undefined 237 awaitMessage
199-} 238-}
200 239
201signalEvent :: Event -> P2P () 240
202signalEvent (Available bf) = undefined 241-- |
203signalEvent _ = undefined 242-- @
243-- +----------+---------+
244-- | Leacher | Seeder |
245-- |----------+---------+
246-- | Available| |
247-- | Want |Fragment |
248-- | Fragment | |
249-- +----------+---------+
250-- @
251--
252yieldEvent :: Event -> P2P ()
253yieldEvent (Available bf) = undefined
254yieldEvent _ = undefined
204 255
205--flushBroadcast :: P2P () 256--flushBroadcast :: P2P ()
206--flushBroadcast = nextBroadcast >>= maybe (return ()) go 257--flushBroadcast = nextBroadcast >>= maybe (return ()) go
207-- where 258-- where
208-- go = undefined 259-- go = undefined
209 260
261checkPiece :: PieceLIx -> {-ByteString -> -} P2P Bool
262checkPiece = undefined
263
210{----------------------------------------------------------------------- 264{-----------------------------------------------------------------------
211 P2P monad 265 P2P monad
212-----------------------------------------------------------------------} 266-----------------------------------------------------------------------}