diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Network/BitTorrent.hs | 3 | ||||
-rw-r--r-- | src/Network/BitTorrent/Peer.hs | 52 | ||||
-rw-r--r-- | src/Network/BitTorrent/Peer/Addr.hs | 78 | ||||
-rw-r--r-- | src/Network/BitTorrent/Peer/ClientInfo.hs (renamed from src/Network/BitTorrent/PeerWire/ClientInfo.hs) | 10 | ||||
-rw-r--r-- | src/Network/BitTorrent/Peer/ID.hs (renamed from src/Network/BitTorrent/PeerID.hs) | 2 | ||||
-rw-r--r-- | src/Network/BitTorrent/PeerWire.hs | 1 | ||||
-rw-r--r-- | src/Network/BitTorrent/PeerWire/Handshake.hs | 4 | ||||
-rw-r--r-- | src/Network/BitTorrent/PeerWire/Message.hs | 1 | ||||
-rw-r--r-- | src/Network/BitTorrent/Tracker.hs | 7 | ||||
-rw-r--r-- | src/Network/BitTorrent/Tracker/Protocol.hs | 25 |
10 files changed, 101 insertions, 82 deletions
diff --git a/src/Network/BitTorrent.hs b/src/Network/BitTorrent.hs index 5ed786d0..bd23b980 100644 --- a/src/Network/BitTorrent.hs +++ b/src/Network/BitTorrent.hs | |||
@@ -8,6 +8,5 @@ | |||
8 | module Network.BitTorrent (module BT) where | 8 | module Network.BitTorrent (module BT) where |
9 | 9 | ||
10 | import Network.BitTorrent.Peer as BT | 10 | import Network.BitTorrent.Peer as BT |
11 | import Network.BitTorrent.PeerID as BT | ||
12 | import Network.BitTorrent.Tracker as BT | ||
13 | import Network.BitTorrent.PeerWire as BT | 11 | import Network.BitTorrent.PeerWire as BT |
12 | import Network.BitTorrent.Tracker as BT | ||
diff --git a/src/Network/BitTorrent/Peer.hs b/src/Network/BitTorrent/Peer.hs index e16329d2..ff32feb5 100644 --- a/src/Network/BitTorrent/Peer.hs +++ b/src/Network/BitTorrent/Peer.hs | |||
@@ -5,52 +5,12 @@ | |||
5 | -- Stability : experimental | 5 | -- Stability : experimental |
6 | -- Portability : non-portable | 6 | -- Portability : non-portable |
7 | -- | 7 | -- |
8 | -- Just convenient reexports for peer related modules. | ||
9 | -- | ||
8 | module Network.BitTorrent.Peer | 10 | module Network.BitTorrent.Peer |
9 | ( Peer(..) | 11 | ( module P |
10 | , peerSockAddr, connectToPeer | ||
11 | , ppPeer | ||
12 | ) where | 12 | ) where |
13 | 13 | ||
14 | import Control.Applicative | 14 | import Network.BitTorrent.Peer.Addr as P |
15 | import Data.Word | 15 | import Network.BitTorrent.Peer.ClientInfo as P |
16 | import Data.Bits | 16 | import Network.BitTorrent.Peer.ID as P \ No newline at end of file |
17 | import Network | ||
18 | import Network.Socket | ||
19 | |||
20 | import Network.BitTorrent.PeerID | ||
21 | import Network.BitTorrent.PeerWire.ClientInfo | ||
22 | |||
23 | |||
24 | data Peer = Peer { | ||
25 | peerID :: Maybe PeerID | ||
26 | , peerIP :: HostAddress | ||
27 | , peerPort :: PortNumber | ||
28 | } deriving Show | ||
29 | |||
30 | -- TODO make platform independent, clarify htonl | ||
31 | -- | Convert peer info from tracker response to socket address. | ||
32 | -- Used for establish connection between peers. | ||
33 | -- | ||
34 | peerSockAddr :: Peer -> SockAddr | ||
35 | peerSockAddr = SockAddrInet <$> (g . peerPort) <*> (htonl . peerIP) | ||
36 | where | ||
37 | htonl :: Word32 -> Word32 | ||
38 | htonl d = | ||
39 | ((d .&. 0xff) `shiftL` 24) .|. | ||
40 | (((d `shiftR` 8 ) .&. 0xff) `shiftL` 16) .|. | ||
41 | (((d `shiftR` 16) .&. 0xff) `shiftL` 8) .|. | ||
42 | ((d `shiftR` 24) .&. 0xff) | ||
43 | |||
44 | g :: PortNumber -> PortNumber | ||
45 | g = id | ||
46 | |||
47 | -- | Tries to connect to peer using reasonable default parameters. | ||
48 | connectToPeer :: Peer -> IO Socket | ||
49 | connectToPeer p = do | ||
50 | sock <- socket AF_INET Stream Network.Socket.defaultProtocol | ||
51 | connect sock (peerSockAddr p) | ||
52 | return sock | ||
53 | |||
54 | ppPeer :: Peer -> String | ||
55 | ppPeer p = maybe "" (++ " at ") ((ppClientInfo . clientInfo) <$> peerID p) | ||
56 | ++ show (peerSockAddr p) | ||
diff --git a/src/Network/BitTorrent/Peer/Addr.hs b/src/Network/BitTorrent/Peer/Addr.hs new file mode 100644 index 00000000..0e6fcfb9 --- /dev/null +++ b/src/Network/BitTorrent/Peer/Addr.hs | |||
@@ -0,0 +1,78 @@ | |||
1 | -- | | ||
2 | -- Copyright : (c) Sam T. 2013 | ||
3 | -- License : MIT | ||
4 | -- Maintainer : pxqr.sta@gmail.com | ||
5 | -- Stability : experimental | ||
6 | -- Portability : non-portable | ||
7 | -- | ||
8 | {-# LANGUAGE OverloadedStrings #-} | ||
9 | {-# OPTIONS -fno-warn-orphans #-} | ||
10 | module Network.BitTorrent.Peer.Addr | ||
11 | ( PeerAddr(..) | ||
12 | , peerSockAddr, connectToPeer | ||
13 | , ppPeer | ||
14 | ) where | ||
15 | |||
16 | import Control.Applicative | ||
17 | import Data.BEncode | ||
18 | import Data.Bits | ||
19 | import Data.Word | ||
20 | import Network | ||
21 | import Network.Socket | ||
22 | |||
23 | import Network.BitTorrent.Peer.ID | ||
24 | import Network.BitTorrent.Peer.ClientInfo | ||
25 | |||
26 | |||
27 | data PeerAddr = PeerAddr { | ||
28 | peerID :: Maybe PeerID | ||
29 | , peerIP :: HostAddress | ||
30 | , peerPort :: PortNumber | ||
31 | } deriving Show | ||
32 | |||
33 | instance BEncodable PortNumber where | ||
34 | toBEncode = toBEncode . fromEnum | ||
35 | fromBEncode b = toEnum <$> fromBEncode b | ||
36 | |||
37 | instance BEncodable PeerAddr where | ||
38 | toBEncode (PeerAddr pid pip pport) = fromAssocs | ||
39 | [ "peer id" -->? pid | ||
40 | , "ip" --> pip | ||
41 | , "port" --> pport | ||
42 | ] | ||
43 | |||
44 | fromBEncode (BDict d) = | ||
45 | PeerAddr <$> d >--? "peer id" | ||
46 | <*> d >-- "ip" | ||
47 | <*> d >-- "port" | ||
48 | |||
49 | fromBEncode _ = decodingError "PeerAddr" | ||
50 | |||
51 | |||
52 | -- TODO make platform independent, clarify htonl | ||
53 | -- | Convert peer info from tracker response to socket address. | ||
54 | -- Used for establish connection between peers. | ||
55 | -- | ||
56 | peerSockAddr :: PeerAddr -> SockAddr | ||
57 | peerSockAddr = SockAddrInet <$> (g . peerPort) <*> (htonl . peerIP) | ||
58 | where | ||
59 | htonl :: Word32 -> Word32 | ||
60 | htonl d = | ||
61 | ((d .&. 0xff) `shiftL` 24) .|. | ||
62 | (((d `shiftR` 8 ) .&. 0xff) `shiftL` 16) .|. | ||
63 | (((d `shiftR` 16) .&. 0xff) `shiftL` 8) .|. | ||
64 | ((d `shiftR` 24) .&. 0xff) | ||
65 | |||
66 | g :: PortNumber -> PortNumber | ||
67 | g = id | ||
68 | |||
69 | -- | Tries to connect to peer using reasonable default parameters. | ||
70 | connectToPeer :: PeerAddr -> IO Socket | ||
71 | connectToPeer p = do | ||
72 | sock <- socket AF_INET Stream Network.Socket.defaultProtocol | ||
73 | connect sock (peerSockAddr p) | ||
74 | return sock | ||
75 | |||
76 | ppPeer :: PeerAddr -> String | ||
77 | ppPeer p = maybe "" (++ " at ") ((ppClientInfo . clientInfo) <$> peerID p) | ||
78 | ++ show (peerSockAddr p) | ||
diff --git a/src/Network/BitTorrent/PeerWire/ClientInfo.hs b/src/Network/BitTorrent/Peer/ClientInfo.hs index 629c883f..ebbecbd7 100644 --- a/src/Network/BitTorrent/PeerWire/ClientInfo.hs +++ b/src/Network/BitTorrent/Peer/ClientInfo.hs | |||
@@ -12,10 +12,14 @@ | |||
12 | -- > See http://bittorrent.org/beps/bep_0020.html for more information. | 12 | -- > See http://bittorrent.org/beps/bep_0020.html for more information. |
13 | -- | 13 | -- |
14 | {-# LANGUAGE OverloadedStrings #-} | 14 | {-# LANGUAGE OverloadedStrings #-} |
15 | module Network.BitTorrent.PeerWire.ClientInfo | 15 | module Network.BitTorrent.Peer.ClientInfo |
16 | ( ClientInfo(..), clientInfo, ppClientInfo, unknownClient | 16 | ( -- * Info |
17 | ClientInfo(..), clientInfo, ppClientInfo, unknownClient | ||
17 | 18 | ||
19 | -- * Version | ||
18 | , ClientVersion, ppClientVersion | 20 | , ClientVersion, ppClientVersion |
21 | |||
22 | -- * Implementation | ||
19 | , ClientImpl(..), ppClientImpl | 23 | , ClientImpl(..), ppClientImpl |
20 | 24 | ||
21 | -- , mkEnumTyDef, mkPars, nameMap | 25 | -- , mkEnumTyDef, mkPars, nameMap |
@@ -27,7 +31,7 @@ import Data.ByteString (ByteString) | |||
27 | import qualified Data.ByteString.Char8 as BC | 31 | import qualified Data.ByteString.Char8 as BC |
28 | import Data.Serialize.Get | 32 | import Data.Serialize.Get |
29 | 33 | ||
30 | import Network.BitTorrent.PeerID | 34 | import Network.BitTorrent.Peer.ID |
31 | 35 | ||
32 | 36 | ||
33 | -- | All known client versions. | 37 | -- | All known client versions. |
diff --git a/src/Network/BitTorrent/PeerID.hs b/src/Network/BitTorrent/Peer/ID.hs index 2c8818fe..f93409ed 100644 --- a/src/Network/BitTorrent/PeerID.hs +++ b/src/Network/BitTorrent/Peer/ID.hs | |||
@@ -13,7 +13,7 @@ | |||
13 | -- though this module exports some other goodies for custom generation. | 13 | -- though this module exports some other goodies for custom generation. |
14 | -- | 14 | -- |
15 | {-# LANGUAGE OverloadedStrings, GeneralizedNewtypeDeriving #-} | 15 | {-# LANGUAGE OverloadedStrings, GeneralizedNewtypeDeriving #-} |
16 | module Network.BitTorrent.PeerID | 16 | module Network.BitTorrent.Peer.ID |
17 | ( -- * Peer identification | 17 | ( -- * Peer identification |
18 | PeerID (getPeerID), ppPeerID | 18 | PeerID (getPeerID), ppPeerID |
19 | 19 | ||
diff --git a/src/Network/BitTorrent/PeerWire.hs b/src/Network/BitTorrent/PeerWire.hs index 9f1e02ca..db9287d8 100644 --- a/src/Network/BitTorrent/PeerWire.hs +++ b/src/Network/BitTorrent/PeerWire.hs | |||
@@ -12,4 +12,3 @@ import Network.BitTorrent.PeerWire.Bitfield as PW | |||
12 | import Network.BitTorrent.PeerWire.Block as PW | 12 | import Network.BitTorrent.PeerWire.Block as PW |
13 | import Network.BitTorrent.PeerWire.Message as PW | 13 | import Network.BitTorrent.PeerWire.Message as PW |
14 | import Network.BitTorrent.PeerWire.Handshake as PW | 14 | import Network.BitTorrent.PeerWire.Handshake as PW |
15 | import Network.BitTorrent.PeerWire.ClientInfo as PW | ||
diff --git a/src/Network/BitTorrent/PeerWire/Handshake.hs b/src/Network/BitTorrent/PeerWire/Handshake.hs index 3fdb48be..e4d27f75 100644 --- a/src/Network/BitTorrent/PeerWire/Handshake.hs +++ b/src/Network/BitTorrent/PeerWire/Handshake.hs | |||
@@ -29,8 +29,8 @@ import Data.Torrent.InfoHash | |||
29 | import Network | 29 | import Network |
30 | import Network.Socket.ByteString | 30 | import Network.Socket.ByteString |
31 | 31 | ||
32 | import Network.BitTorrent.PeerID | 32 | import Network.BitTorrent.Peer.ID |
33 | import Network.BitTorrent.PeerWire.ClientInfo | 33 | import Network.BitTorrent.Peer.ClientInfo |
34 | 34 | ||
35 | 35 | ||
36 | data Handshake = Handshake { | 36 | data Handshake = Handshake { |
diff --git a/src/Network/BitTorrent/PeerWire/Message.hs b/src/Network/BitTorrent/PeerWire/Message.hs index 9cbc2e38..188f0572 100644 --- a/src/Network/BitTorrent/PeerWire/Message.hs +++ b/src/Network/BitTorrent/PeerWire/Message.hs | |||
@@ -5,7 +5,6 @@ module Network.BitTorrent.PeerWire.Message | |||
5 | ) where | 5 | ) where |
6 | 6 | ||
7 | import Control.Applicative | 7 | import Control.Applicative |
8 | import Data.ByteString (ByteString) | ||
9 | import qualified Data.ByteString as B | 8 | import qualified Data.ByteString as B |
10 | 9 | ||
11 | import Data.Serialize | 10 | import Data.Serialize |
diff --git a/src/Network/BitTorrent/Tracker.hs b/src/Network/BitTorrent/Tracker.hs index 6ecf4fc2..e4bcf2cd 100644 --- a/src/Network/BitTorrent/Tracker.hs +++ b/src/Network/BitTorrent/Tracker.hs | |||
@@ -37,7 +37,6 @@ import Network | |||
37 | import Network.URI | 37 | import Network.URI |
38 | 38 | ||
39 | import Network.BitTorrent.Peer | 39 | import Network.BitTorrent.Peer |
40 | import Network.BitTorrent.PeerID | ||
41 | import Network.BitTorrent.Tracker.Protocol | 40 | import Network.BitTorrent.Tracker.Protocol |
42 | import Network.BitTorrent.Tracker.Scrape | 41 | import Network.BitTorrent.Tracker.Scrape |
43 | 42 | ||
@@ -137,13 +136,13 @@ completedReq ses pr = (genericReq ses pr) { | |||
137 | data TSession = TSession { | 136 | data TSession = TSession { |
138 | seProgress :: TVar Progress | 137 | seProgress :: TVar Progress |
139 | , seInterval :: IORef Int | 138 | , seInterval :: IORef Int |
140 | , sePeers :: TVar [Peer] | 139 | , sePeers :: TVar [PeerAddr] |
141 | } | 140 | } |
142 | 141 | ||
143 | newSession :: Progress -> Int -> [Peer] -> IO TSession | 142 | newSession :: Progress -> Int -> [PeerAddr] -> IO TSession |
144 | newSession pr i ps = TSession <$> newTVarIO pr <*> newIORef i <*> newTVarIO ps | 143 | newSession pr i ps = TSession <$> newTVarIO pr <*> newIORef i <*> newTVarIO ps |
145 | 144 | ||
146 | getPeerList :: TSession -> IO [Peer] | 145 | getPeerList :: TSession -> IO [PeerAddr] |
147 | getPeerList = readTVarIO . sePeers | 146 | getPeerList = readTVarIO . sePeers |
148 | 147 | ||
149 | getProgress :: TSession -> IO Progress | 148 | getProgress :: TSession -> IO Progress |
diff --git a/src/Network/BitTorrent/Tracker/Protocol.hs b/src/Network/BitTorrent/Tracker/Protocol.hs index c0e84c24..a6c1c8b6 100644 --- a/src/Network/BitTorrent/Tracker/Protocol.hs +++ b/src/Network/BitTorrent/Tracker/Protocol.hs | |||
@@ -53,7 +53,6 @@ import Network.HTTP | |||
53 | import Network.URI | 53 | import Network.URI |
54 | 54 | ||
55 | import Network.BitTorrent.Peer | 55 | import Network.BitTorrent.Peer |
56 | import Network.BitTorrent.PeerID | ||
57 | import Network.BitTorrent.Tracker.Scrape | 56 | import Network.BitTorrent.Tracker.Scrape |
58 | 57 | ||
59 | 58 | ||
@@ -84,27 +83,9 @@ data TResponse = | |||
84 | , respMinInterval :: Maybe Int -- ^ Minimal amount of time between requests. | 83 | , respMinInterval :: Maybe Int -- ^ Minimal amount of time between requests. |
85 | , respComplete :: Maybe Int -- ^ Number of peers completed the torrent. (seeders) | 84 | , respComplete :: Maybe Int -- ^ Number of peers completed the torrent. (seeders) |
86 | , respIncomplete :: Maybe Int -- ^ Number of peers downloading the torrent. | 85 | , respIncomplete :: Maybe Int -- ^ Number of peers downloading the torrent. |
87 | , respPeers :: [Peer] -- ^ Peers that must be contacted. | 86 | , respPeers :: [PeerAddr] -- ^ Peers that must be contacted. |
88 | } deriving Show | 87 | } deriving Show |
89 | 88 | ||
90 | instance BEncodable PortNumber where | ||
91 | toBEncode = toBEncode . fromEnum | ||
92 | fromBEncode b = toEnum <$> fromBEncode b | ||
93 | |||
94 | instance BEncodable Peer where | ||
95 | toBEncode (Peer pid pip pport) = fromAssocs | ||
96 | [ "peer id" -->? pid | ||
97 | , "ip" --> pip | ||
98 | , "port" --> pport | ||
99 | ] | ||
100 | |||
101 | fromBEncode (BDict d) = | ||
102 | Peer <$> d >--? "peer id" | ||
103 | <*> d >-- "ip" | ||
104 | <*> d >-- "port" | ||
105 | |||
106 | fromBEncode _ = decodingError "Peer" | ||
107 | |||
108 | instance BEncodable TResponse where | 89 | instance BEncodable TResponse where |
109 | toBEncode (Failure t) = fromAssocs ["failure reason" --> t] | 90 | toBEncode (Failure t) = fromAssocs ["failure reason" --> t] |
110 | toBEncode resp@(OK {}) = fromAssocs | 91 | toBEncode resp@(OK {}) = fromAssocs |
@@ -125,7 +106,7 @@ instance BEncodable TResponse where | |||
125 | <*> getPeers (M.lookup "peers" d) | 106 | <*> getPeers (M.lookup "peers" d) |
126 | 107 | ||
127 | where | 108 | where |
128 | getPeers :: Maybe BEncode -> Result [Peer] | 109 | getPeers :: Maybe BEncode -> Result [PeerAddr] |
129 | getPeers (Just (BList l)) = fromBEncode (BList l) | 110 | getPeers (Just (BList l)) = fromBEncode (BList l) |
130 | getPeers (Just (BString s)) | 111 | getPeers (Just (BString s)) |
131 | | B.length s `mod` 6 == 0 = | 112 | | B.length s `mod` 6 == 0 = |
@@ -136,7 +117,7 @@ instance BEncodable TResponse where | |||
136 | peerG = do | 117 | peerG = do |
137 | pip <- getWord32be | 118 | pip <- getWord32be |
138 | pport <- getWord16be | 119 | pport <- getWord16be |
139 | return (Peer Nothing (fromIntegral pip) (fromIntegral pport)) | 120 | return (PeerAddr Nothing (fromIntegral pip) (fromIntegral pport)) |
140 | 121 | ||
141 | getPeers _ = decodingError "Peers" | 122 | getPeers _ = decodingError "Peers" |
142 | 123 | ||