]> git.rkrishnan.org Git - functorrent.git/blob - src/Peer.hs
74c89a292743639fe34a729b43a60293bbe6a15a
[functorrent.git] / src / Peer.hs
1 module Peer where
2
3 import qualified Utils as U
4 import qualified Bencode as Benc
5 import qualified Data.Map as M
6 import qualified Data.ByteString.Char8 as BC
7 import qualified Data.ByteString.Base16 as B16
8 import qualified Data.List as L
9
10 data Peer = Peer { ip :: String
11                  , port :: Integer
12                  } deriving (Show)
13                             
14 data PeerResp = PeerResponse { interval :: Maybe Integer
15                              , peers :: [Peer]
16                              , complete :: Maybe Integer
17                              , incomplete :: Maybe Integer
18                              } deriving (Show)
19
20 toInt :: String -> Integer
21 toInt = read
22
23 getPeers :: PeerResp -> [Peer]
24 getPeers = peers
25
26 getPeerResponse :: BC.ByteString -> PeerResp
27 getPeerResponse body = case Benc.decode body of
28                         Right (Benc.Bdict peerM) ->
29                           let (Just (Benc.Bint i)) = M.lookup (Benc.Bstr (BC.pack "lookup")) peerM
30                               (Benc.Bstr peersBS) = peerM M.! Benc.Bstr (BC.pack "peers")
31                               pl = map (\peer -> let (ip', port') = BC.splitAt 4 peer
32                                                  in Peer { ip = toIPNum ip'
33                                                          , port =  toPortNum port'
34                                                          })
35                                    (U.splitN 6 peersBS)
36                           in PeerResponse { interval = Just i
37                                           , peers = pl
38                                           , complete = Nothing
39                                           , incomplete = Nothing
40                                           }
41                           where toPortNum = read . ("0x" ++) . BC.unpack . B16.encode
42                                 toIPNum = L.intercalate "." .
43                                           map (show . toInt . ("0x" ++) . BC.unpack) .
44                                           U.splitN 2 . B16.encode
45                         _ -> PeerResponse { interval = Nothing
46                                           , peers = []
47                                           , complete = Nothing
48                                           , incomplete = Nothing
49                                           }