summaryrefslogtreecommitdiff
path: root/src/Network/BitTorrent
diff options
context:
space:
mode:
authorSam T <pxqr.sta@gmail.com>2013-07-20 16:29:11 +0400
committerSam T <pxqr.sta@gmail.com>2013-07-20 16:29:11 +0400
commita6b52c1bbb536a569ab988802cfd128c6a8cf89f (patch)
tree93f5563d8e8bab1e71f78c3d797daf265a59c63c /src/Network/BitTorrent
parent2eade3a3dc198e602ffd834fdd95ac53ee172e7a (diff)
~ Add binary serialization for Tracker messages.
Diffstat (limited to 'src/Network/BitTorrent')
-rw-r--r--src/Network/BitTorrent/Tracker/Protocol.hs113
1 files changed, 108 insertions, 5 deletions
diff --git a/src/Network/BitTorrent/Tracker/Protocol.hs b/src/Network/BitTorrent/Tracker/Protocol.hs
index 51d713dd..5741c1d7 100644
--- a/src/Network/BitTorrent/Tracker/Protocol.hs
+++ b/src/Network/BitTorrent/Tracker/Protocol.hs
@@ -35,14 +35,14 @@ module Network.BitTorrent.Tracker.Protocol
35import Control.Applicative 35import Control.Applicative
36import Control.Monad 36import Control.Monad
37import Data.Char as Char 37import Data.Char as Char
38import Data.Word (Word32)
39import Data.Map as M 38import Data.Map as M
40import Data.Maybe 39import Data.Maybe
41import Data.Word 40import Data.Word
42import Data.Monoid 41import Data.Monoid
43import Data.BEncode 42import Data.BEncode
44import Data.ByteString as B 43import Data.ByteString as B
45import Data.Text as T 44import Data.Text as T
45import Data.Text.Encoding as T
46import Data.Serialize hiding (Result) 46import Data.Serialize hiding (Result)
47import Data.URLEncoded as URL 47import Data.URLEncoded as URL
48import Data.Torrent 48import Data.Torrent
@@ -53,8 +53,10 @@ import Network.HTTP
53import Network.URI 53import Network.URI
54 54
55import Network.BitTorrent.Peer 55import Network.BitTorrent.Peer
56import Network.BitTorrent.Exchange.Protocol hiding (Request)
57 56
57{-----------------------------------------------------------------------
58 Tracker messages
59-----------------------------------------------------------------------}
58 60
59-- | Events used to specify which kind of tracker request is performed. 61-- | Events used to specify which kind of tracker request is performed.
60data Event = Started 62data Event = Started
@@ -138,6 +140,9 @@ data TResponse =
138 -- ^ Peers that must be contacted. 140 -- ^ Peers that must be contacted.
139 } deriving Show 141 } deriving Show
140 142
143{-----------------------------------------------------------------------
144 HTTP Tracker encoding
145-----------------------------------------------------------------------}
141 146
142instance BEncodable TResponse where 147instance BEncodable TResponse where
143 toBEncode (Failure t) = fromAssocs ["failure reason" --> t] 148 toBEncode (Failure t) = fromAssocs ["failure reason" --> t]
@@ -196,8 +201,106 @@ encodeRequest req = URL.urlEncode req
196 `addToURI` reqAnnounce req 201 `addToURI` reqAnnounce req
197 `addHashToURI` reqInfoHash req 202 `addHashToURI` reqInfoHash req
198 203
199 204{-----------------------------------------------------------------------
200-- | Ports typically reserved for bittorrent P2P communication. 205 UDP tracker encoding
206-----------------------------------------------------------------------}
207
208type EventId = Word32
209
210eventId :: Event -> EventId
211eventId Completed = 1
212eventId Started = 2
213eventId Stopped = 3
214
215-- TODO add Regular event
216putEvent :: Putter (Maybe Event)
217putEvent Nothing = putWord32be 0
218putEvent (Just e) = putWord32be (eventId e)
219
220getEvent :: Get (Maybe Event)
221getEvent = do
222 eid <- getWord32be
223 case eid of
224 0 -> return Nothing
225 1 -> return $ Just Completed
226 2 -> return $ Just Started
227 3 -> return $ Just Stopped
228 _ -> fail "unknown event id"
229
230instance Serialize TRequest where
231 put TRequest {..} = do
232 put reqInfoHash
233 put reqPeerId
234
235 putWord64be $ fromIntegral reqDownloaded
236 putWord64be $ fromIntegral reqLeft
237 putWord64be $ fromIntegral reqUploaded
238
239 putEvent reqEvent
240 putWord32be $ fromMaybe 0 reqIP
241 putWord32be $ 0 -- TODO what the fuck is "key"?
242 putWord32be $ fromIntegral $ fromMaybe (-1) reqNumWant
243
244 put reqPort
245
246 get = do
247 ih <- get
248 pid <- get
249
250 down <- getWord64be
251 left <- getWord64be
252 up <- getWord64be
253
254 ev <- getEvent
255 ip <- getWord32be
256 key <- getWord32be
257 want <- getWord32be
258
259 port <- get
260
261 return $ TRequest {
262 -- TODO remove reqAnnounce field from TRequest
263 reqAnnounce = error "tracker request decode"
264 , reqInfoHash = ih
265 , reqPeerId = pid
266 , reqPort = port
267 , reqUploaded = fromIntegral up
268 , reqDownloaded = fromIntegral down
269 , reqLeft = fromIntegral left
270 , reqIP = if ip == 0 then Nothing else Just ip
271 , reqNumWant = if want == -1 then Nothing else Just (fromIntegral want)
272 , reqEvent = ev
273 }
274
275instance Serialize TResponse where
276 put (Failure msg) = put $ encodeUtf8 msg
277 put OK {..} = do
278 putWord32be $ fromIntegral respInterval
279 putWord32be $ fromIntegral $ fromMaybe 0 respIncomplete
280 putWord32be $ fromIntegral $ fromMaybe 0 respComplete
281 forM_ respPeers put
282
283 get = do
284 interval <- getWord32be
285 leechers <- getWord32be
286 seeders <- getWord32be
287 peers <- many get
288
289 return $ OK {
290 respWarning = Nothing
291 , respInterval = fromIntegral interval
292 , respMinInterval = Nothing
293 , respIncomplete = Just $ fromIntegral leechers
294 , respComplete = Just $ fromIntegral seeders
295 , respPeers = peers
296 }
297
298
299{-----------------------------------------------------------------------
300 Tracker
301-----------------------------------------------------------------------}
302
303-- | Ports typically reserved for bittorrent P2P listener.
201defaultPorts :: [PortNumber] 304defaultPorts :: [PortNumber]
202defaultPorts = [6881..6889] 305defaultPorts = [6881..6889]
203 306