summaryrefslogtreecommitdiff
path: root/Mainline.hs
diff options
context:
space:
mode:
Diffstat (limited to 'Mainline.hs')
-rw-r--r--Mainline.hs87
1 files changed, 58 insertions, 29 deletions
diff --git a/Mainline.hs b/Mainline.hs
index b24f847d..30e18a09 100644
--- a/Mainline.hs
+++ b/Mainline.hs
@@ -16,65 +16,67 @@ import Control.Arrow
16import Control.Concurrent.STM 16import Control.Concurrent.STM
17import Control.Monad 17import Control.Monad
18import Crypto.Random 18import Crypto.Random
19import Data.BEncode as BE 19import Data.BEncode as BE
20import qualified Data.BEncode.BDict as BE 20import qualified Data.BEncode.BDict as BE
21 ;import Data.BEncode.BDict (BKey) 21 ;import Data.BEncode.BDict (BKey)
22import Data.BEncode.Pretty 22import Data.BEncode.Pretty
23import Data.BEncode.Types (BDict) 23import Data.BEncode.Types (BDict)
24import Data.Bits 24import Data.Bits
25import Data.Bits.ByteString 25import Data.Bits.ByteString
26import Data.Bool 26import Data.Bool
27import qualified Data.ByteArray as BA 27import qualified Data.ByteArray as BA
28 ;import Data.ByteArray (ByteArrayAccess) 28 ;import Data.ByteArray (ByteArrayAccess)
29import qualified Data.ByteString as B 29import qualified Data.ByteString as B
30 ;import Data.ByteString (ByteString) 30 ;import Data.ByteString (ByteString)
31import qualified Data.ByteString.Base16 as Base16 31import qualified Data.ByteString.Base16 as Base16
32import qualified Data.ByteString.Char8 as Char8 32import qualified Data.ByteString.Char8 as Char8
33import Data.ByteString.Lazy (toStrict) 33import Data.ByteString.Lazy (toStrict)
34import qualified Data.ByteString.Lazy.Char8 as L8 34import qualified Data.ByteString.Lazy.Char8 as L8
35import Data.Char
35import Data.Coerce 36import Data.Coerce
36import Data.Data 37import Data.Data
37import Data.Default 38import Data.Default
38import Data.Digest.CRC32C 39import Data.Digest.CRC32C
39import Data.Function (fix) 40import Data.Function (fix)
40import Data.Hashable 41import Data.Hashable
41import Data.IP 42import Data.IP
42import Data.List 43import Data.List
43import Data.Maybe 44import Data.Maybe
44import Data.Monoid 45import Data.Monoid
45import Data.Ord 46import Data.Ord
46import qualified Data.Serialize as S 47import qualified Data.Serialize as S
47import Data.Set (Set) 48import Data.Set (Set)
48import Data.Time.Clock.POSIX (POSIXTime) 49import Data.Time.Clock.POSIX (POSIXTime)
49import Data.Torrent 50import Data.Torrent
50import Data.Typeable 51import Data.Typeable
51import Data.Word 52import Data.Word
52import qualified Data.Wrapper.PSQInt as Int 53import qualified Data.Wrapper.PSQInt as Int
53import Debug.Trace 54import Debug.Trace
54import Kademlia 55import Kademlia
55import Network.Address (Address, fromAddr, fromSockAddr, 56import Network.Address (Address, fromAddr, fromSockAddr,
56 setPort, sockAddrPort, testIdBit, 57 setPort, sockAddrPort, testIdBit,
57 toSockAddr) 58 toSockAddr)
58import Network.BitTorrent.DHT.ContactInfo as Peers 59import Network.BitTorrent.DHT.ContactInfo as Peers
59import Network.BitTorrent.DHT.Search (Search (..)) 60import Network.BitTorrent.DHT.Search (Search (..))
60import Network.BitTorrent.DHT.Token as Token 61import Network.BitTorrent.DHT.Token as Token
61import Network.DatagramServer.Types (genBucketSample') 62import Network.DatagramServer.Types (genBucketSample')
62import qualified Network.DHT.Routing as R 63import qualified Network.DHT.Routing as R
63 ;import Network.DHT.Routing (Info, Timestamp, getTimestamp) 64 ;import Network.DHT.Routing (Info, Timestamp, getTimestamp)
64import Network.QueryResponse 65import Network.QueryResponse
65import Network.Socket 66import Network.Socket
66import System.IO 67import System.IO
67import System.IO.Error 68import System.IO.Error
68import System.IO.Unsafe (unsafeInterleaveIO) 69import System.IO.Unsafe (unsafeInterleaveIO)
70import qualified Text.ParserCombinators.ReadP as RP
69#ifdef THREAD_DEBUG 71#ifdef THREAD_DEBUG
70import Control.Concurrent.Lifted.Instrument 72import Control.Concurrent.Lifted.Instrument
71#else 73#else
72import Control.Concurrent.Lifted 74import Control.Concurrent.Lifted
73import GHC.Conc (labelThread) 75import GHC.Conc (labelThread)
74#endif 76#endif
75import Control.Exception (SomeException(..),handle) 77import Control.Exception (SomeException (..), handle)
76import Data.Aeson (FromJSON,ToJSON,(.=))
77import qualified Data.Aeson as JSON 78import qualified Data.Aeson as JSON
79 ;import Data.Aeson (FromJSON, ToJSON, (.=))
78import Text.Read 80import Text.Read
79 81
80newtype NodeId = NodeId ByteString 82newtype NodeId = NodeId ByteString
@@ -129,6 +131,33 @@ instance FromJSON NodeInfo where
129 guard (B.length bs == 20) 131 guard (B.length bs == 20)
130 return $ NodeInfo (NodeId bs) ip (fromIntegral (portnum :: Word16)) 132 return $ NodeInfo (NodeId bs) ip (fromIntegral (portnum :: Word16))
131 133
134hexdigit :: Char -> Bool
135hexdigit c = ('0' <= c && c <= '9') || ( 'a' <= c && c <= 'f') || ( 'A' <= c && c <= 'F')
136
137instance Read NodeInfo where
138 readsPrec i = RP.readP_to_S $ do
139 RP.skipSpaces
140 let n = 40
141 hexhash <- sequence $ replicate n (RP.satisfy hexdigit)
142 RP.char '@' RP.+++ RP.satisfy isSpace
143 addrstr <- RP.between (RP.char '(') (RP.char ')') (RP.munch (/=')'))
144 RP.+++ RP.munch (not . isSpace)
145 let raddr = do
146 -- TODO: Support IPv6
147 ipv4 <- RP.readS_to_P (readsPrec i)
148 _ <- RP.char ':'
149 port <- toEnum <$> RP.readS_to_P (readsPrec i)
150 return (IPv4 ipv4, port)
151
152 (ip,port) <- case RP.readP_to_S raddr addrstr of
153 [] -> fail "Bad address."
154 ((ip,port),_):_ -> return (ip,port)
155 nid <- case Base16.decode $ Char8.pack hexhash of
156 (bs,_) | B.length bs==20 -> return (NodeId bs)
157 _ -> fail "Bad node id."
158 return $ NodeInfo nid ip port
159
160
132 161
133-- The Hashable instance depends only on the IP address and port number. It is 162-- The Hashable instance depends only on the IP address and port number. It is
134-- used to compute the announce token. 163-- used to compute the announce token.