diff options
-rw-r--r-- | src/Network/Torrent/Handshake.hs | 47 | ||||
-rw-r--r-- | src/Network/Torrent/PeerID.hs | 5 |
2 files changed, 41 insertions, 11 deletions
diff --git a/src/Network/Torrent/Handshake.hs b/src/Network/Torrent/Handshake.hs index d48d04e6..7643b2e9 100644 --- a/src/Network/Torrent/Handshake.hs +++ b/src/Network/Torrent/Handshake.hs | |||
@@ -1,25 +1,54 @@ | |||
1 | {-# LANGUAGE OverloadedStrings #-} | 1 | {-# LANGUAGE OverloadedStrings #-} |
2 | module Network.Torrent.Handshake | 2 | module Network.Torrent.Handshake |
3 | ( Handshake | 3 | ( Handshake |
4 | , defaultProtocol, defaultReserved, defaultHandshake | ||
4 | ) where | 5 | ) where |
5 | 6 | ||
7 | import Control.Applicative | ||
6 | import Data.Word | 8 | import Data.Word |
7 | import Data.ByteString (ByteString) | 9 | import Data.ByteString (ByteString) |
8 | import qualified Data.ByteString as B | 10 | import qualified Data.ByteString as B |
11 | import Data.Serialize | ||
9 | 12 | ||
13 | import Network.Torrent.PeerID | ||
14 | |||
15 | -- | In order to establish the connection between peers we should send 'Handshake' | ||
16 | -- message. The 'Handshake' is a required message and must be the first message | ||
17 | -- transmitted by the peer to the another peer. | ||
10 | data Handshake = Handshake { | 18 | data Handshake = Handshake { |
11 | hsProtocol :: ByteString | 19 | hsProtocol :: ByteString -- ^ Identifier of the protocol. |
12 | , hsReserved :: Word64 | 20 | , hsReserved :: Word64 -- ^ Reserved bytes, rarely used. |
13 | , hsInfoHash :: ByteString | 21 | , hsInfoHash :: ByteString -- ^ Hash from the metainfo file. |
14 | , hsPeerID :: ByteString | 22 | -- This /should be/ same hash that is transmitted in tracker requests. |
23 | , hsPeerID :: PeerID -- ^ Peer id of the initiator. | ||
24 | -- This is /usually the same peer id that is transmitted in tracker requests. | ||
15 | } deriving (Show, Eq) | 25 | } deriving (Show, Eq) |
16 | 26 | ||
27 | instance Serialize Handshake where | ||
28 | put hs = do | ||
29 | putWord8 (49 + fromIntegral (B.length (hsProtocol hs))) | ||
30 | putByteString (hsProtocol hs) | ||
31 | putWord64be (hsReserved hs) | ||
32 | putByteString (hsInfoHash hs) | ||
33 | put (hsPeerID hs) | ||
34 | |||
35 | get = do | ||
36 | len <- getWord8 | ||
37 | Handshake <$> getBytes (fromIntegral len) | ||
38 | <*> getWord64be | ||
39 | <*> getBytes 20 | ||
40 | <*> get | ||
41 | |||
42 | -- | Default protocol string "BitTorrent protocol" as is. | ||
17 | defaultProtocol :: ByteString | 43 | defaultProtocol :: ByteString |
18 | defaultProtocol = "BitTorrent protocol" | 44 | defaultProtocol = "BitTorrent protocol" |
19 | 45 | ||
46 | -- | Default reserved word is 0. | ||
47 | defaultReserved :: Word64 | ||
48 | defaultReserved = 0 | ||
20 | 49 | ||
21 | fromByteString :: ByteString -> Handshake | 50 | -- | Length of info hash and peer id is unchecked, so it /should/ be equal 20. |
22 | fromByteString = undefined | 51 | defaultHandshake :: ByteString -- ^ Info hash string. |
23 | 52 | -> PeerID | |
24 | toByteString :: Handshake -> ByteString | 53 | -> Handshake |
25 | toByteString = undefined \ No newline at end of file | 54 | defaultHandshake hash pid = Handshake defaultProtocol defaultReserved hash pid \ No newline at end of file |
diff --git a/src/Network/Torrent/PeerID.hs b/src/Network/Torrent/PeerID.hs index ec87b470..5ca3ea42 100644 --- a/src/Network/Torrent/PeerID.hs +++ b/src/Network/Torrent/PeerID.hs | |||
@@ -23,19 +23,20 @@ import qualified Data.ByteString.Lazy as BL | |||
23 | import qualified Data.ByteString.Builder as B | 23 | import qualified Data.ByteString.Builder as B |
24 | import Data.Foldable (foldMap) | 24 | import Data.Foldable (foldMap) |
25 | import Data.Monoid ((<>)) | 25 | import Data.Monoid ((<>)) |
26 | import Data.Serialize (Serialize) | ||
26 | import Data.Version (Version(Version), versionBranch) | 27 | import Data.Version (Version(Version), versionBranch) |
27 | import Data.Time.Clock (getCurrentTime) | 28 | import Data.Time.Clock (getCurrentTime) |
28 | import Data.Time.Format (formatTime) | 29 | import Data.Time.Format (formatTime) |
29 | import System.Locale (defaultTimeLocale) | 30 | import System.Locale (defaultTimeLocale) |
30 | 31 | ||
31 | -- TODO we have linker error here, so manual hardcoded version for a while. | 32 | -- TODO we have linker error here, so manual hardcoded version for a while. |
32 | --import Paths_network_bittorrent (version) | 33 | -- import Paths_network_bittorrent (version) |
33 | version :: Version | 34 | version :: Version |
34 | version = Version [0, 10, 0, 0] [] | 35 | version = Version [0, 10, 0, 0] [] |
35 | 36 | ||
36 | -- | Peer identifier is exactly 20 bytes long bytestring. | 37 | -- | Peer identifier is exactly 20 bytes long bytestring. |
37 | newtype PeerID = PeerID { getPeerID :: ByteString } | 38 | newtype PeerID = PeerID { getPeerID :: ByteString } |
38 | deriving (Show, Eq, Ord, BEncodable) | 39 | deriving (Show, Eq, Ord, BEncodable, Serialize) |
39 | 40 | ||
40 | -- | Azureus-style encoding: | 41 | -- | Azureus-style encoding: |
41 | -- * 1 byte : '-' | 42 | -- * 1 byte : '-' |