WIP: peer handshake
authorRamakrishnan Muthukrishnan <ram@rkrishnan.org>
Fri, 1 May 2015 10:20:21 +0000 (15:50 +0530)
committerRamakrishnan Muthukrishnan <ram@rkrishnan.org>
Fri, 1 May 2015 15:08:41 +0000 (20:38 +0530)
src/FuncTorrent.hs
src/FuncTorrent/Peer.hs
src/FuncTorrent/Tracker.hs
src/Main.hs

index e17b024052f971e4a885b77f714cb306d063109c..8289da5bae88ce73801cb0edb9d11c407ebf6855 100644 (file)
@@ -7,7 +7,7 @@ module FuncTorrent
      tracker,
      decode,
      encode,
-     handShakeMsg,
+     handShake,
      initLogger,
      logMessage,
      logStop,
index b0c546b9b5abae16d8260290ec0054f06b1db55a..798f60acf0712eef0c0644b320c8fe97750cb212 100644 (file)
@@ -1,26 +1,59 @@
 {-# LANGUAGE OverloadedStrings #-}
 module FuncTorrent.Peer
     (Peer(..),
-     handShakeMsg
+     handShake
     ) where
 
 import Prelude hiding (lookup, concat, replicate, splitAt)
 
-import Data.ByteString.Char8 (ByteString, pack, concat, replicate)
-import Data.ByteString.Lazy (toChunks)
-import Data.Int (Int8)
-import qualified Data.Binary as Bin (encode)
+import System.IO
+import Data.ByteString (ByteString, unpack, concat, hGet, hPut, singleton)
+import Data.ByteString.Char8 (replicate, pack)
+import Network (connectTo, PortID(..))
 
-import FuncTorrent.Metainfo (Metainfo(..))
+type ID = String
+type IP = String
+type Port = Integer
 
--- | Peer is a IP address, port tuple
-data Peer = Peer String Integer
-            deriving (Show, Eq)
+data PeerState = PeerState { am_choking :: Bool
+                           , am_interested :: Bool
+                           , peer_choking :: Bool
+                           , peer_interested :: Bool }
 
-handShakeMsg :: Metainfo -> String -> ByteString
-handShakeMsg m peer_id = concat [pstrlen, pstr, reserved, infoH, peerID]
-    where pstrlen = concat $ toChunks $ Bin.encode (19 :: Int8)
-          pstr = pack "BitTorrent protocol"
-          reserved = replicate 8 '\0'
-          infoH = infoHash m
-          peerID = pack peer_id
+-- | Peer is a PeerID, IP address, port tuple
+data Peer = Peer ID IP Port
+          deriving (Show, Eq)
+
+data Msg = HandShakeMsg ByteString ID
+         | KeepAliveMsg
+         | ChokeMsg
+         | UnChokeMsg
+         | InterestedMsg
+         | NotInterestedMsg
+         | HaveMsg Integer
+         | BitFieldMsg Integer
+         | RequestMsg Integer Integer Integer
+         | PieceMsg Integer Integer Integer
+         | CancelMsg Integer Integer Integer
+         | PortMsg Port
+         deriving (Show)
+
+genHandShakeMsg :: ByteString -> String -> ByteString
+genHandShakeMsg infoHash peer_id = concat [pstrlen, pstr, reserved, infoHash, peerID]
+  where pstrlen = singleton 19
+        pstr = pack "BitTorrent protocol"
+        reserved = replicate 8 '\0'
+        peerID = pack peer_id
+
+handShake :: Peer -> ByteString -> String -> IO ByteString
+handShake (Peer _ ip port) infoHash peerid = do
+  let hs = genHandShakeMsg infoHash peerid
+  handle <- connectTo ip (PortNumber (fromIntegral port))
+  hSetBuffering handle LineBuffering
+  hPut handle hs
+  rlenBS <- hGet handle 1
+  let rlen = fromIntegral $ (unpack rlenBS) !! 0
+  hGet handle rlen
+
+-- sendMsg :: Peer -> Handle -> PeerMsg -> IO ()
+-- recvMsg :: Peer -> Handle -> Msg
index 57c8f9d3b42d2607deec6ddf1672a4dc082259a8..b8166508d20980df85480c8047478388fa265b99 100644 (file)
@@ -62,7 +62,7 @@ mkTrackerResponse resp =
                  splitN 2 . B16.encode
 
       makePeer :: ByteString -> Peer
-      makePeer peer = Peer (toIP ip') (toPort port')
+      makePeer peer = Peer "" (toIP ip') (toPort port')
           where (ip', port') = splitAt 4 peer
 
 -- | Connect to a tracker and get peer info
index 9cb5908c00809d328ccd72bda5e1c4b10ba6a2fa..fa79ac30e8046ab9fe125fb6c45db098a825d2e9 100644 (file)
@@ -2,7 +2,7 @@
 module Main where
 
 import Prelude hiding (log, length, readFile, writeFile)
-import Data.ByteString.Char8 (ByteString, readFile, writeFile, length, unpack)
+import Data.ByteString.Char8 (ByteString, readFile, writeFile, unpack)
 import System.Environment (getArgs)
 import System.Exit (exitSuccess)
 import System.Directory (doesFileExist)
@@ -11,7 +11,7 @@ import Text.ParserCombinators.Parsec (ParseError)
 import FuncTorrent.Bencode (decode)
 import FuncTorrent.Logger (initLogger, logMessage, logStop)
 import FuncTorrent.Metainfo (Info(..), Metainfo(..), mkMetaInfo)
-import FuncTorrent.Peer (handShakeMsg)
+import FuncTorrent.Peer (Peer(..), handShake)
 import FuncTorrent.Tracker (tracker, peers, mkTrackerResponse)
 
 logError :: ParseError -> (String -> IO ()) -> IO ()
@@ -55,17 +55,18 @@ main = do
               log $ "Trackers: " ++ head (announceList m)
               response <- tracker m peerId
 
-              let hsMsgLen = show $ length $ handShakeMsg m peerId
-              log $ "Hand-shake message length : " ++ hsMsgLen
-
               -- TODO: Write to ~/.functorrent/caches
               writeFile (name (info m) ++ ".cache") response
 
               case decode response of
                 Right trackerInfo ->
                     case mkTrackerResponse trackerInfo of
-                      Right peerResp ->
+                      Right peerResp -> do
                           log $ "Peers List : " ++ (show . peers $ peerResp)
+                          let p1 = head (peers peerResp)
+                          msg <- handShake (Peer "" "95.188.88.59" 27000) (infoHash m) peerId
+                          log $ "handshake: " ++ (show msg)
+                          return ()
                       Left e -> log $ "Error" ++ unpack e
                 Left e -> logError e log