summaryrefslogtreecommitdiff
path: root/src/Network/BitTorrent/Core
diff options
context:
space:
mode:
Diffstat (limited to 'src/Network/BitTorrent/Core')
-rw-r--r--src/Network/BitTorrent/Core/PeerAddr.hs51
1 files changed, 23 insertions, 28 deletions
diff --git a/src/Network/BitTorrent/Core/PeerAddr.hs b/src/Network/BitTorrent/Core/PeerAddr.hs
index 77f042d5..71c92a15 100644
--- a/src/Network/BitTorrent/Core/PeerAddr.hs
+++ b/src/Network/BitTorrent/Core/PeerAddr.hs
@@ -24,6 +24,7 @@ import Control.Applicative
24import Data.Aeson (ToJSON, FromJSON) 24import Data.Aeson (ToJSON, FromJSON)
25import Data.Aeson.TH 25import Data.Aeson.TH
26import Data.BEncode as BS 26import Data.BEncode as BS
27import Data.BEncode.BDict (BKey)
27import Data.Bits 28import Data.Bits
28import Data.Char 29import Data.Char
29import Data.List as L 30import Data.List as L
@@ -55,26 +56,32 @@ instance Serialize PortNumber where
55 56
56-- | Peer address info normally extracted from peer list or peer 57-- | Peer address info normally extracted from peer list or peer
57-- compact list encoding. 58-- compact list encoding.
58data PeerAddr = PeerAddr { 59data PeerAddr = PeerAddr
59 peerId :: !(Maybe PeerId) 60 { peerId :: !(Maybe PeerId)
60 , peerIP :: {-# UNPACK #-} !HostAddress 61 , peerIP :: {-# UNPACK #-} !HostAddress
61 , peerPort :: {-# UNPACK #-} !PortNumber 62 , peerPort :: {-# UNPACK #-} !PortNumber
62 } deriving (Show, Eq, Ord, Typeable) 63 } deriving (Show, Eq, Ord, Typeable)
63 64
64$(deriveJSON defaultOptions { fieldLabelModifier = (L.map toLower . L.dropWhile isLower) } ''PeerAddr) 65$(deriveJSON defaultOptions { fieldLabelModifier = (L.map toLower . L.dropWhile isLower) } ''PeerAddr)
65 66
66-- | The tracker "announce query" compatible encoding. 67peer_id_key, peer_ip_key, peer_port_key :: BKey
68peer_id_key = "peer id"
69peer_ip_key = "ip"
70peer_port_key = "port"
71
72-- FIXME do we need to byteswap peerIP in bencode instance?
73-- | The tracker announce response compatible encoding.
67instance BEncode PeerAddr where 74instance BEncode PeerAddr where
68 toBEncode (PeerAddr pid pip pport) = toDict $ 75 toBEncode PeerAddr {..} = toDict $
69 "peer id" .=? pid 76 peer_id_key .=? peerId
70 .: "ip" .=! pip 77 .: peer_ip_key .=! peerIP
71 .: "port" .=! pport 78 .: peer_port_key .=! peerPort
72 .: endDict 79 .: endDict
73 80
74 fromBEncode = fromDict $ do 81 fromBEncode = fromDict $ do
75 PeerAddr <$>? "peer id" 82 PeerAddr <$>? peer_id_key
76 <*>! "ip" 83 <*>! peer_ip_key
77 <*>! "port" 84 <*>! peer_port_key
78 85
79-- | The tracker "compact peer list" compatible encoding. The 86-- | The tracker "compact peer list" compatible encoding. The
80-- 'peerId' is always 'Nothing'. 87-- 'peerId' is always 'Nothing'.
@@ -82,9 +89,9 @@ instance BEncode PeerAddr where
82-- For more info see: <http://www.bittorrent.org/beps/bep_0023.html> 89-- For more info see: <http://www.bittorrent.org/beps/bep_0023.html>
83-- 90--
84instance Serialize PeerAddr where 91instance Serialize PeerAddr where
85 put PeerAddr {..} = put peerId >> put peerPort 92 put PeerAddr {..} = putWord32host peerId >> putWord peerPort
86 {-# INLINE put #-} 93 {-# INLINE put #-}
87 get = PeerAddr Nothing <$> get <*> get 94 get = PeerAddr Nothing <$> getWord32host <*> get
88 {-# INLINE get #-} 95 {-# INLINE get #-}
89 96
90instance Pretty PeerAddr where 97instance Pretty PeerAddr where
@@ -98,20 +105,8 @@ instance Pretty PeerAddr where
98defaultPorts :: [PortNumber] 105defaultPorts :: [PortNumber]
99defaultPorts = [6881..6889] 106defaultPorts = [6881..6889]
100 107
101-- TODO make platform independent, clarify htonl
102
103-- | Convert peer info from tracker response to socket address. Used 108-- | Convert peer info from tracker response to socket address. Used
104-- for establish connection between peers. 109-- for establish connection between peers.
105-- 110--
106peerSockAddr :: PeerAddr -> SockAddr 111peerSockAddr :: PeerAddr -> SockAddr
107peerSockAddr = SockAddrInet <$> (g . peerPort) <*> (htonl . peerIP) 112peerSockAddr = SockAddrInet <$> peerPort <*> peerIP
108 where
109 htonl :: Word32 -> Word32
110 htonl d =
111 ((d .&. 0xff) `shiftL` 24) .|.
112 (((d `shiftR` 8 ) .&. 0xff) `shiftL` 16) .|.
113 (((d `shiftR` 16) .&. 0xff) `shiftL` 8) .|.
114 ((d `shiftR` 24) .&. 0xff)
115
116 g :: PortNumber -> PortNumber
117 g = id