Earlier implementation used a wrong handhake sequence for the server.
This commit fixes it. It is untested at the moment.
-import Prelude hiding (lookup, concat, replicate, splitAt, take, filter)
+import Prelude hiding (lookup, concat, replicate, splitAt, take, drop, filter)
-import System.IO (Handle, BufferMode(..), hSetBuffering)
-import Data.ByteString (ByteString, unpack, concat, hGet, hPut, take, empty)
+import System.IO (Handle, BufferMode(..), hSetBuffering, hClose)
+import Data.ByteString (ByteString, unpack, concat, hGet, hPut, take, drop, empty)
import qualified Data.ByteString.Char8 as BC (length)
import Network (connectTo, PortID(..))
import Control.Monad.State
import qualified Data.ByteString.Char8 as BC (length)
import Network (connectTo, PortID(..))
import Control.Monad.State
hSetBuffering h LineBuffering
return h
hSetBuffering h LineBuffering
return h
-doHandshake :: Handle -> Peer -> ByteString -> String -> IO ()
-doHandshake h peer infoHash peerid = do
+doHandshake :: Bool -> Handle -> Peer -> ByteString -> String -> IO ()
+doHandshake isClient h peer infoHash peerid =
let hs = genHandshakeMsg infoHash peerid
let hs = genHandshakeMsg infoHash peerid
- hPut h hs
- putStrLn $ "--> handhake to peer: " ++ show peer
- _ <- hGet h (length (unpack hs))
- putStrLn $ "<-- handshake from peer: " ++ show peer
- return ()
+ in
+ if isClient
+ then do
+ hPut h hs
+ putStrLn $ "--> handhake to peer: " ++ show peer
+ _ <- hGet h (length (unpack hs))
+ putStrLn $ "<-- handshake from peer: " ++ show peer
+ return ()
+ else do
+ putStrLn $ "waiting for a handshake"
+ hsMsg <- hGet h (length (unpack hs))
+ putStrLn $ "<-- handshake from peer: " ++ show peer
+ let rxInfoHash = take 20 $ drop 28 hsMsg
+ if rxInfoHash /= infoHash
+ then do
+ putStrLn $ "infoHashes does not match"
+ hClose h
+ return ()
+ else do
+ _ <- hPut h hs
+ putStrLn $ "--> handhake to peer: " ++ show peer
+ return ()
bitfieldToList :: [Word8] -> [Integer]
bitfieldToList bs = go bs 0
bitfieldToList :: [Word8] -> [Integer]
bitfieldToList bs = go bs 0
then (pd { peers = p : peers pd })
else pd) pieceStatus
then (pd { peers = p : peers pd })
else pd) pieceStatus
-handlePeerMsgs :: Peer -> String -> Metainfo -> PieceMap -> IO ()
-handlePeerMsgs p peerId m pieceMap = do
+handlePeerMsgs :: Peer -> String -> Metainfo -> PieceMap -> Bool -> IO ()
+handlePeerMsgs p peerId m pieceMap isClient = do
- doHandshake h p (infoHash m) peerId
+ doHandshake isClient h p (infoHash m) peerId
let pstate = toPeerState h p False False True True
filePath = name (info m)
_ <- runStateT (msgLoop pieceMap filePath) pstate
let pstate = toPeerState h p False False True True
filePath = name (info m)
_ <- runStateT (msgLoop pieceMap filePath) pstate
(handle, ip, port) <- accept listenSock
let peer = Peer "" ip (fromIntegral port)
hSetBuffering handle NoBuffering
(handle, ip, port) <- accept listenSock
let peer = Peer "" ip (fromIntegral port)
hSetBuffering handle NoBuffering
- forkIO $ handlePeerMsgs peer peerid m pieceMap
+ forkIO $ handlePeerMsgs peer peerid m pieceMap False
Right peerList -> do
log $ "Peers List : " ++ (show . peers $ peerList)
let p1 = head (peers peerList)
Right peerList -> do
log $ "Peers List : " ++ (show . peers $ peerList)
let p1 = head (peers peerList)
- handlePeerMsgs p1 peerId m pieceMap
+ handlePeerMsgs p1 peerId m pieceMap True