diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Network/BitTorrent/Core/PeerAddr.hs | 41 |
1 files changed, 14 insertions, 27 deletions
diff --git a/src/Network/BitTorrent/Core/PeerAddr.hs b/src/Network/BitTorrent/Core/PeerAddr.hs index 1da4c81a..60ada54d 100644 --- a/src/Network/BitTorrent/Core/PeerAddr.hs +++ b/src/Network/BitTorrent/Core/PeerAddr.hs | |||
@@ -20,6 +20,8 @@ module Network.BitTorrent.Core.PeerAddr | |||
20 | PeerAddr(..) | 20 | PeerAddr(..) |
21 | , defaultPorts | 21 | , defaultPorts |
22 | , peerSockAddr | 22 | , peerSockAddr |
23 | |||
24 | -- * IP | ||
23 | , mergeIPLists | 25 | , mergeIPLists |
24 | , splitIPList | 26 | , splitIPList |
25 | , IP, IPv4, IPv6 --re-export Data.IP constructors | 27 | , IP, IPv4, IPv6 --re-export Data.IP constructors |
@@ -27,14 +29,10 @@ module Network.BitTorrent.Core.PeerAddr | |||
27 | ) where | 29 | ) where |
28 | 30 | ||
29 | import Control.Applicative | 31 | import Control.Applicative |
30 | import Control.Exception | ||
31 | import Data.Aeson (ToJSON, FromJSON) | 32 | import Data.Aeson (ToJSON, FromJSON) |
32 | import Data.Aeson.TH | ||
33 | import Data.BEncode as BS | 33 | import Data.BEncode as BS |
34 | import Data.BEncode.BDict (BKey) | 34 | import Data.BEncode.BDict (BKey) |
35 | import Data.ByteString | ||
36 | import Data.ByteString.Char8 as BS8 | 35 | import Data.ByteString.Char8 as BS8 |
37 | import Data.Bits | ||
38 | import Data.Char | 36 | import Data.Char |
39 | import Data.Default | 37 | import Data.Default |
40 | import Data.List as L | 38 | import Data.List as L |
@@ -42,9 +40,7 @@ import Data.List.Split | |||
42 | import Data.Serialize as S | 40 | import Data.Serialize as S |
43 | import Data.String | 41 | import Data.String |
44 | import Data.Typeable | 42 | import Data.Typeable |
45 | import Data.Word | ||
46 | import Data.IP | 43 | import Data.IP |
47 | import Data.Maybe | ||
48 | import Data.Foldable | 44 | import Data.Foldable |
49 | import Data.Either | 45 | import Data.Either |
50 | import Network.Socket | 46 | import Network.Socket |
@@ -52,9 +48,7 @@ import Text.PrettyPrint | |||
52 | import Text.PrettyPrint.Class | 48 | import Text.PrettyPrint.Class |
53 | import Text.Read (readMaybe) | 49 | import Text.Read (readMaybe) |
54 | import qualified Text.ParserCombinators.ReadP as RP | 50 | import qualified Text.ParserCombinators.ReadP as RP |
55 | import System.IO.Unsafe | ||
56 | 51 | ||
57 | import Data.Torrent.JSON | ||
58 | import Network.BitTorrent.Core.PeerId | 52 | import Network.BitTorrent.Core.PeerId |
59 | 53 | ||
60 | 54 | ||
@@ -95,8 +89,12 @@ deriving instance Typeable IP | |||
95 | deriving instance Typeable IPv4 | 89 | deriving instance Typeable IPv4 |
96 | deriving instance Typeable IPv6 | 90 | deriving instance Typeable IPv6 |
97 | 91 | ||
92 | ipToBEncode :: IPAddress i => i -> BValue | ||
98 | ipToBEncode ip = BString $ BS8.pack $ showIp ip | 93 | ipToBEncode ip = BString $ BS8.pack $ showIp ip |
94 | |||
95 | ipFromBEncode :: Monad m => IPAddress a => BValue -> m a | ||
99 | ipFromBEncode (BString ip) = return $ readIp $ BS8.unpack ip | 96 | ipFromBEncode (BString ip) = return $ readIp $ BS8.unpack ip |
97 | ipFromBEncode _ = fail "ipFromBEncode" | ||
100 | 98 | ||
101 | instance BEncode IP where | 99 | instance BEncode IP where |
102 | toBEncode = ipToBEncode | 100 | toBEncode = ipToBEncode |
@@ -119,7 +117,6 @@ instance Serialize IPv6 where | |||
119 | get = fromHostAddress6 <$> get | 117 | get = fromHostAddress6 <$> get |
120 | 118 | ||
121 | -- TODO check semantic of ord and eq instances | 119 | -- TODO check semantic of ord and eq instances |
122 | -- TODO use SockAddr instead of peerIP and peerPort | ||
123 | 120 | ||
124 | -- | Peer address info normally extracted from peer list or peer | 121 | -- | Peer address info normally extracted from peer list or peer |
125 | -- compact list encoding. | 122 | -- compact list encoding. |
@@ -158,7 +155,6 @@ splitIPList xs = partitionEithers $ toEither <$> xs | |||
158 | toEither pa@(PeerAddr _ (IPv4 _) _) = Left (ipv4 <$> pa) | 155 | toEither pa@(PeerAddr _ (IPv4 _) _) = Left (ipv4 <$> pa) |
159 | toEither pa@(PeerAddr _ (IPv6 _) _) = Right (ipv6 <$> pa) | 156 | toEither pa@(PeerAddr _ (IPv6 _) _) = Right (ipv6 <$> pa) |
160 | 157 | ||
161 | |||
162 | -- | The tracker's 'compact peer list' compatible encoding. The | 158 | -- | The tracker's 'compact peer list' compatible encoding. The |
163 | -- 'peerId' is always 'Nothing'. | 159 | -- 'peerId' is always 'Nothing'. |
164 | -- | 160 | -- |
@@ -175,14 +171,6 @@ instance (Serialize a) => Serialize (PeerAddr a) where | |||
175 | instance Default (PeerAddr IPv4) where | 171 | instance Default (PeerAddr IPv4) where |
176 | def = "127.0.0.1:6881" | 172 | def = "127.0.0.1:6881" |
177 | 173 | ||
178 | -- inet_addr is pure; so it is safe to throw IO | ||
179 | unsafeCatchIO :: IO a -> Maybe a | ||
180 | unsafeCatchIO m = unsafePerformIO $ | ||
181 | catch (m >>= evaluate >>= return . Just) handler | ||
182 | where | ||
183 | handler :: IOError -> IO (Maybe a) | ||
184 | handler _ = pure Nothing | ||
185 | |||
186 | -- | Example: | 174 | -- | Example: |
187 | -- | 175 | -- |
188 | -- @peerPort \"127.0.0.1:6881\" == 6881@ | 176 | -- @peerPort \"127.0.0.1:6881\" == 6881@ |
@@ -198,7 +186,7 @@ instance IsString (PeerAddr IPv4) where | |||
198 | readsIPv6_port :: String -> [((IPv6, PortNumber), String)] | 186 | readsIPv6_port :: String -> [((IPv6, PortNumber), String)] |
199 | readsIPv6_port = RP.readP_to_S $ do | 187 | readsIPv6_port = RP.readP_to_S $ do |
200 | ip <- RP.char '[' *> (RP.readS_to_P reads) <* RP.char ']' | 188 | ip <- RP.char '[' *> (RP.readS_to_P reads) <* RP.char ']' |
201 | RP.char ':' | 189 | _ <- RP.char ':' |
202 | port <- toEnum <$> read <$> (RP.many1 $ RP.satisfy isDigit) <* RP.eof | 190 | port <- toEnum <$> read <$> (RP.many1 $ RP.satisfy isDigit) <* RP.eof |
203 | return (ip,port) | 191 | return (ip,port) |
204 | 192 | ||
@@ -211,7 +199,7 @@ instance IsString (PeerAddr IPv6) where | |||
211 | -- | fingerprint + "at" + dotted.host.inet.addr:port | 199 | -- | fingerprint + "at" + dotted.host.inet.addr:port |
212 | -- TODO: instances for IPv6, HostName | 200 | -- TODO: instances for IPv6, HostName |
213 | instance Pretty (PeerAddr IP) where | 201 | instance Pretty (PeerAddr IP) where |
214 | pretty p @ PeerAddr {..} | 202 | pretty PeerAddr {..} |
215 | | Just pid <- peerId = pretty (fingerprint pid) <+> "at" <+> paddr | 203 | | Just pid <- peerId = pretty (fingerprint pid) <+> "at" <+> paddr |
216 | | otherwise = paddr | 204 | | otherwise = paddr |
217 | where | 205 | where |
@@ -221,15 +209,14 @@ instance Pretty (PeerAddr IP) where | |||
221 | defaultPorts :: [PortNumber] | 209 | defaultPorts :: [PortNumber] |
222 | defaultPorts = [6881..6889] | 210 | defaultPorts = [6881..6889] |
223 | 211 | ||
224 | resolvePeerAddr :: (IPAddress i) => PeerAddr HostName -> PeerAddr i | 212 | _resolvePeerAddr :: (IPAddress i) => PeerAddr HostName -> PeerAddr i |
225 | resolvePeerAddr = undefined | 213 | _resolvePeerAddr = undefined |
226 | 214 | ||
227 | -- | Convert peer info from tracker response to socket address. Used | 215 | -- | Convert peer info from tracker response to socket address. Used |
228 | -- for establish connection between peers. | 216 | -- for establish connection between peers. |
229 | -- | 217 | -- |
230 | peerSockAddr :: (IPAddress i) => PeerAddr i -> SockAddr | 218 | peerSockAddr :: (IPAddress i) => PeerAddr i -> SockAddr |
231 | peerSockAddr PeerAddr {..} | 219 | peerSockAddr PeerAddr {..} = |
232 | | Left hAddr <- toHostAddr peerAddr = | 220 | case toHostAddr peerAddr of |
233 | SockAddrInet peerPort hAddr | 221 | Left host4 -> SockAddrInet peerPort host4 |
234 | | Right hAddr <- toHostAddr peerAddr = | 222 | Right host6 -> SockAddrInet6 peerPort 0 host6 0 |
235 | SockAddrInet6 peerPort 0 hAddr 0 | ||