summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--network-bittorrent.cabal7
-rw-r--r--src/Network/BitTorrent.hs3
-rw-r--r--src/Network/BitTorrent/Peer.hs52
-rw-r--r--src/Network/BitTorrent/Peer/Addr.hs78
-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.hs1
-rw-r--r--src/Network/BitTorrent/PeerWire/Handshake.hs4
-rw-r--r--src/Network/BitTorrent/PeerWire/Message.hs1
-rw-r--r--src/Network/BitTorrent/Tracker.hs7
-rw-r--r--src/Network/BitTorrent/Tracker/Protocol.hs25
11 files changed, 106 insertions, 84 deletions
diff --git a/network-bittorrent.cabal b/network-bittorrent.cabal
index 00ed2162..6a14b3e9 100644
--- a/network-bittorrent.cabal
+++ b/network-bittorrent.cabal
@@ -23,9 +23,13 @@ source-repository head
23library 23library
24 exposed-modules: Data.Torrent 24 exposed-modules: Data.Torrent
25 , Data.Torrent.InfoHash 25 , Data.Torrent.InfoHash
26
26 , Network.BitTorrent 27 , Network.BitTorrent
28
27 , Network.BitTorrent.Peer 29 , Network.BitTorrent.Peer
28 , Network.BitTorrent.PeerID 30 , Network.BitTorrent.Peer.Addr
31 , Network.BitTorrent.Peer.ID
32 , Network.BitTorrent.Peer.ClientInfo
29 33
30 , Network.BitTorrent.Tracker 34 , Network.BitTorrent.Tracker
31 , Network.BitTorrent.Tracker.Protocol 35 , Network.BitTorrent.Tracker.Protocol
@@ -34,7 +38,6 @@ library
34 , Network.BitTorrent.PeerWire 38 , Network.BitTorrent.PeerWire
35 , Network.BitTorrent.PeerWire.Bitfield 39 , Network.BitTorrent.PeerWire.Bitfield
36 , Network.BitTorrent.PeerWire.Block 40 , Network.BitTorrent.PeerWire.Block
37 , Network.BitTorrent.PeerWire.ClientInfo
38 , Network.BitTorrent.PeerWire.Message 41 , Network.BitTorrent.PeerWire.Message
39 , Network.BitTorrent.PeerWire.Handshake 42 , Network.BitTorrent.PeerWire.Handshake
40 43
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 @@
8module Network.BitTorrent (module BT) where 8module Network.BitTorrent (module BT) where
9 9
10import Network.BitTorrent.Peer as BT 10import Network.BitTorrent.Peer as BT
11import Network.BitTorrent.PeerID as BT
12import Network.BitTorrent.Tracker as BT
13import Network.BitTorrent.PeerWire as BT 11import Network.BitTorrent.PeerWire as BT
12import 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--
8module Network.BitTorrent.Peer 10module Network.BitTorrent.Peer
9 ( Peer(..) 11 ( module P
10 , peerSockAddr, connectToPeer
11 , ppPeer
12 ) where 12 ) where
13 13
14import Control.Applicative 14import Network.BitTorrent.Peer.Addr as P
15import Data.Word 15import Network.BitTorrent.Peer.ClientInfo as P
16import Data.Bits 16import Network.BitTorrent.Peer.ID as P \ No newline at end of file
17import Network
18import Network.Socket
19
20import Network.BitTorrent.PeerID
21import Network.BitTorrent.PeerWire.ClientInfo
22
23
24data 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--
34peerSockAddr :: Peer -> SockAddr
35peerSockAddr = 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.
48connectToPeer :: Peer -> IO Socket
49connectToPeer p = do
50 sock <- socket AF_INET Stream Network.Socket.defaultProtocol
51 connect sock (peerSockAddr p)
52 return sock
53
54ppPeer :: Peer -> String
55ppPeer 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 #-}
10module Network.BitTorrent.Peer.Addr
11 ( PeerAddr(..)
12 , peerSockAddr, connectToPeer
13 , ppPeer
14 ) where
15
16import Control.Applicative
17import Data.BEncode
18import Data.Bits
19import Data.Word
20import Network
21import Network.Socket
22
23import Network.BitTorrent.Peer.ID
24import Network.BitTorrent.Peer.ClientInfo
25
26
27data PeerAddr = PeerAddr {
28 peerID :: Maybe PeerID
29 , peerIP :: HostAddress
30 , peerPort :: PortNumber
31 } deriving Show
32
33instance BEncodable PortNumber where
34 toBEncode = toBEncode . fromEnum
35 fromBEncode b = toEnum <$> fromBEncode b
36
37instance 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--
56peerSockAddr :: PeerAddr -> SockAddr
57peerSockAddr = 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.
70connectToPeer :: PeerAddr -> IO Socket
71connectToPeer p = do
72 sock <- socket AF_INET Stream Network.Socket.defaultProtocol
73 connect sock (peerSockAddr p)
74 return sock
75
76ppPeer :: PeerAddr -> String
77ppPeer 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 #-}
15module Network.BitTorrent.PeerWire.ClientInfo 15module 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)
27import qualified Data.ByteString.Char8 as BC 31import qualified Data.ByteString.Char8 as BC
28import Data.Serialize.Get 32import Data.Serialize.Get
29 33
30import Network.BitTorrent.PeerID 34import 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 #-}
16module Network.BitTorrent.PeerID 16module 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
12import Network.BitTorrent.PeerWire.Block as PW 12import Network.BitTorrent.PeerWire.Block as PW
13import Network.BitTorrent.PeerWire.Message as PW 13import Network.BitTorrent.PeerWire.Message as PW
14import Network.BitTorrent.PeerWire.Handshake as PW 14import Network.BitTorrent.PeerWire.Handshake as PW
15import 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
29import Network 29import Network
30import Network.Socket.ByteString 30import Network.Socket.ByteString
31 31
32import Network.BitTorrent.PeerID 32import Network.BitTorrent.Peer.ID
33import Network.BitTorrent.PeerWire.ClientInfo 33import Network.BitTorrent.Peer.ClientInfo
34 34
35 35
36data Handshake = Handshake { 36data 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
7import Control.Applicative 7import Control.Applicative
8import Data.ByteString (ByteString)
9import qualified Data.ByteString as B 8import qualified Data.ByteString as B
10 9
11import Data.Serialize 10import 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
37import Network.URI 37import Network.URI
38 38
39import Network.BitTorrent.Peer 39import Network.BitTorrent.Peer
40import Network.BitTorrent.PeerID
41import Network.BitTorrent.Tracker.Protocol 40import Network.BitTorrent.Tracker.Protocol
42import Network.BitTorrent.Tracker.Scrape 41import Network.BitTorrent.Tracker.Scrape
43 42
@@ -137,13 +136,13 @@ completedReq ses pr = (genericReq ses pr) {
137data TSession = TSession { 136data 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
143newSession :: Progress -> Int -> [Peer] -> IO TSession 142newSession :: Progress -> Int -> [PeerAddr] -> IO TSession
144newSession pr i ps = TSession <$> newTVarIO pr <*> newIORef i <*> newTVarIO ps 143newSession pr i ps = TSession <$> newTVarIO pr <*> newIORef i <*> newTVarIO ps
145 144
146getPeerList :: TSession -> IO [Peer] 145getPeerList :: TSession -> IO [PeerAddr]
147getPeerList = readTVarIO . sePeers 146getPeerList = readTVarIO . sePeers
148 147
149getProgress :: TSession -> IO Progress 148getProgress :: 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
53import Network.URI 53import Network.URI
54 54
55import Network.BitTorrent.Peer 55import Network.BitTorrent.Peer
56import Network.BitTorrent.PeerID
57import Network.BitTorrent.Tracker.Scrape 56import 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
90instance BEncodable PortNumber where
91 toBEncode = toBEncode . fromEnum
92 fromBEncode b = toEnum <$> fromBEncode b
93
94instance 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
108instance BEncodable TResponse where 89instance 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