]> git.rkrishnan.org Git - functorrent.git/blobdiff - src/Peer.hs
Merge pull request #10 from jaseemabid/master
[functorrent.git] / src / Peer.hs
index d30f9b0699e71d1fd3de2ae902ee2918bee2a8bb..b07b79d6561d551b55c8a2bfeb15403d1982c50a 100644 (file)
@@ -1,19 +1,29 @@
 module Peer where
 
-import qualified Utils as U
-import qualified Bencode as Benc
-import qualified Data.Map as M
-import qualified Data.ByteString.Char8 as BC
-import qualified Data.ByteString.Base16 as B16
-import qualified Data.List as L
-import Control.Applicative ((<$>))
-
-data Peer = Peer { ip :: String
-                 , port :: Integer
-                 } deriving (Show)
-                            
+import Prelude hiding (lookup, concat, replicate, splitAt)
+
+import Bencode (BVal(..), InfoDict, decode)
+import Data.ByteString.Char8 (ByteString, pack, unpack, concat, replicate, splitAt)
+import Data.ByteString.Lazy (toChunks)
+import Data.Int (Int8)
+import Data.List (intercalate)
+import Data.Map as M ((!), lookup)
+import Tracker (infoHash)
+import Utils (splitN)
+import qualified Data.Binary as Bin (encode)
+import qualified Data.ByteString.Base16 as B16 (encode)
+
+
+type Address = String
+type Port = Integer
+
+data Peer = Peer Address Port
+            deriving (Show)
+
 data PeerResp = PeerResponse { interval :: Maybe Integer
                              , peers :: [Peer]
+                             , complete :: Maybe Integer
+                             , incomplete :: Maybe Integer
                              } deriving (Show)
 
 toInt :: String -> Integer
@@ -22,19 +32,35 @@ toInt = read
 getPeers :: PeerResp -> [Peer]
 getPeers = peers
 
-getPeerResponse :: BC.ByteString -> PeerResp
-getPeerResponse body = case (Benc.decode body) of
-                        Right (Benc.Bdict peerM) ->
-                          let (Just (Benc.Bint i)) = M.lookup (Benc.Bstr (BC.pack "lookup")) peerM
-                              (Benc.Bstr peersBS) = peerM M.! (Benc.Bstr (BC.pack "peers"))
-                              pl = map (\peer -> let (ip', port') = BC.splitAt 4 peer
-                                                 in Peer { ip = toIPNum ip',
-                                                           port =  toPortNum port'
-                                                         })
-                                   (U.splitN 6 peersBS)
-                          in PeerResponse { interval = Just i, peers = pl }
-                          where toPortNum = read . ("0x" ++) . BC.unpack . B16.encode
-                                toIPNum = (L.intercalate ".") .
-                                          map (show . toInt . ("0x" ++) . BC.unpack) .
-                                          (U.splitN 2) . B16.encode
-                        Left _ -> PeerResponse { interval = Nothing, peers = [] }
+getPeerResponse :: ByteString -> PeerResp
+getPeerResponse body = case decode body of
+                        Right (Bdict peerM) ->
+                          let (Just (Bint i)) = lookup (Bstr (pack "lookup")) peerM
+                              (Bstr peersBS) = peerM ! Bstr (pack "peers")
+                              pl = map (\peer -> let (ip', port') = splitAt 4 peer
+                                                 in Peer (toIPNum ip') (toPortNum port'))
+                                   (splitN 6 peersBS)
+                          in PeerResponse { interval = Just i
+                                          , peers = pl
+                                          , complete = Nothing
+                                          , incomplete = Nothing
+                                          }
+                          where toPortNum = read . ("0x" ++) . unpack . B16.encode
+                                toIPNum = intercalate "." .
+                                          map (show . toInt . ("0x" ++) . unpack) .
+                                          splitN 2 . B16.encode
+
+                        _ -> PeerResponse { interval = Nothing
+                                          , peers = []
+                                          , complete = Nothing
+                                          , incomplete = Nothing
+                                          }
+
+
+handShakeMsg :: InfoDict -> String -> ByteString
+handShakeMsg m peer_id = let pstrlen = concat $ toChunks $ Bin.encode (19 :: Int8)
+                             pstr = pack "BitTorrent protocol"
+                             reserved = replicate 8 '\0'
+                             infoH = infoHash m
+                             peerID = pack peer_id
+                         in concat [pstrlen, pstr, reserved, infoH, peerID]