summaryrefslogtreecommitdiff
path: root/src/Network/BitTorrent
diff options
context:
space:
mode:
Diffstat (limited to 'src/Network/BitTorrent')
-rw-r--r--src/Network/BitTorrent/Core/PeerAddr.hs41
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
29import Control.Applicative 31import Control.Applicative
30import Control.Exception
31import Data.Aeson (ToJSON, FromJSON) 32import Data.Aeson (ToJSON, FromJSON)
32import Data.Aeson.TH
33import Data.BEncode as BS 33import Data.BEncode as BS
34import Data.BEncode.BDict (BKey) 34import Data.BEncode.BDict (BKey)
35import Data.ByteString
36import Data.ByteString.Char8 as BS8 35import Data.ByteString.Char8 as BS8
37import Data.Bits
38import Data.Char 36import Data.Char
39import Data.Default 37import Data.Default
40import Data.List as L 38import Data.List as L
@@ -42,9 +40,7 @@ import Data.List.Split
42import Data.Serialize as S 40import Data.Serialize as S
43import Data.String 41import Data.String
44import Data.Typeable 42import Data.Typeable
45import Data.Word
46import Data.IP 43import Data.IP
47import Data.Maybe
48import Data.Foldable 44import Data.Foldable
49import Data.Either 45import Data.Either
50import Network.Socket 46import Network.Socket
@@ -52,9 +48,7 @@ import Text.PrettyPrint
52import Text.PrettyPrint.Class 48import Text.PrettyPrint.Class
53import Text.Read (readMaybe) 49import Text.Read (readMaybe)
54import qualified Text.ParserCombinators.ReadP as RP 50import qualified Text.ParserCombinators.ReadP as RP
55import System.IO.Unsafe
56 51
57import Data.Torrent.JSON
58import Network.BitTorrent.Core.PeerId 52import Network.BitTorrent.Core.PeerId
59 53
60 54
@@ -95,8 +89,12 @@ deriving instance Typeable IP
95deriving instance Typeable IPv4 89deriving instance Typeable IPv4
96deriving instance Typeable IPv6 90deriving instance Typeable IPv6
97 91
92ipToBEncode :: IPAddress i => i -> BValue
98ipToBEncode ip = BString $ BS8.pack $ showIp ip 93ipToBEncode ip = BString $ BS8.pack $ showIp ip
94
95ipFromBEncode :: Monad m => IPAddress a => BValue -> m a
99ipFromBEncode (BString ip) = return $ readIp $ BS8.unpack ip 96ipFromBEncode (BString ip) = return $ readIp $ BS8.unpack ip
97ipFromBEncode _ = fail "ipFromBEncode"
100 98
101instance BEncode IP where 99instance 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
175instance Default (PeerAddr IPv4) where 171instance 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
179unsafeCatchIO :: IO a -> Maybe a
180unsafeCatchIO 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
198readsIPv6_port :: String -> [((IPv6, PortNumber), String)] 186readsIPv6_port :: String -> [((IPv6, PortNumber), String)]
199readsIPv6_port = RP.readP_to_S $ do 187readsIPv6_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
213instance Pretty (PeerAddr IP) where 201instance 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
221defaultPorts :: [PortNumber] 209defaultPorts :: [PortNumber]
222defaultPorts = [6881..6889] 210defaultPorts = [6881..6889]
223 211
224resolvePeerAddr :: (IPAddress i) => PeerAddr HostName -> PeerAddr i 212_resolvePeerAddr :: (IPAddress i) => PeerAddr HostName -> PeerAddr i
225resolvePeerAddr = 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--
230peerSockAddr :: (IPAddress i) => PeerAddr i -> SockAddr 218peerSockAddr :: (IPAddress i) => PeerAddr i -> SockAddr
231peerSockAddr PeerAddr {..} 219peerSockAddr 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