diff options
Diffstat (limited to 'src/Network/BitTorrent/Core/PeerAddr.hs')
-rw-r--r-- | src/Network/BitTorrent/Core/PeerAddr.hs | 51 |
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 | |||
24 | import Data.Aeson (ToJSON, FromJSON) | 24 | import Data.Aeson (ToJSON, FromJSON) |
25 | import Data.Aeson.TH | 25 | import Data.Aeson.TH |
26 | import Data.BEncode as BS | 26 | import Data.BEncode as BS |
27 | import Data.BEncode.BDict (BKey) | ||
27 | import Data.Bits | 28 | import Data.Bits |
28 | import Data.Char | 29 | import Data.Char |
29 | import Data.List as L | 30 | import 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. |
58 | data PeerAddr = PeerAddr { | 59 | data 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. | 67 | peer_id_key, peer_ip_key, peer_port_key :: BKey |
68 | peer_id_key = "peer id" | ||
69 | peer_ip_key = "ip" | ||
70 | peer_port_key = "port" | ||
71 | |||
72 | -- FIXME do we need to byteswap peerIP in bencode instance? | ||
73 | -- | The tracker announce response compatible encoding. | ||
67 | instance BEncode PeerAddr where | 74 | instance 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 | -- |
84 | instance Serialize PeerAddr where | 91 | instance 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 | ||
90 | instance Pretty PeerAddr where | 97 | instance Pretty PeerAddr where |
@@ -98,20 +105,8 @@ instance Pretty PeerAddr where | |||
98 | defaultPorts :: [PortNumber] | 105 | defaultPorts :: [PortNumber] |
99 | defaultPorts = [6881..6889] | 106 | defaultPorts = [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 | -- |
106 | peerSockAddr :: PeerAddr -> SockAddr | 111 | peerSockAddr :: PeerAddr -> SockAddr |
107 | peerSockAddr = SockAddrInet <$> (g . peerPort) <*> (htonl . peerIP) | 112 | peerSockAddr = 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 | ||