diff options
-rw-r--r-- | bittorrent.cabal | 1 | ||||
-rw-r--r-- | examples/dhtd.hs | 13 | ||||
-rw-r--r-- | src/Network/BitTorrent/DHT/Session.hs | 20 | ||||
-rw-r--r-- | src/Network/DatagramServer.hs | 9 | ||||
-rw-r--r-- | src/Network/DatagramServer/Mainline.hs | 5 | ||||
-rw-r--r-- | src/Network/DatagramServer/Tox.hs | 7 | ||||
-rw-r--r-- | src/Network/DatagramServer/Types.hs | 26 |
7 files changed, 63 insertions, 18 deletions
diff --git a/bittorrent.cabal b/bittorrent.cabal index 498a29df..835125a5 100644 --- a/bittorrent.cabal +++ b/bittorrent.cabal | |||
@@ -114,6 +114,7 @@ library | |||
114 | Crypto.Internal.Compat | 114 | Crypto.Internal.Compat |
115 | Crypto.Internal.DeepSeq | 115 | Crypto.Internal.DeepSeq |
116 | Crypto.Internal.Imports | 116 | Crypto.Internal.Imports |
117 | Crypto.PubKey.Curve25519 | ||
117 | 118 | ||
118 | C-sources: cbits/cryptonite_xsalsa.c, cbits/cryptonite_salsa.c | 119 | C-sources: cbits/cryptonite_xsalsa.c, cbits/cryptonite_salsa.c |
119 | 120 | ||
diff --git a/examples/dhtd.hs b/examples/dhtd.hs index 993727b5..d9b02c41 100644 --- a/examples/dhtd.hs +++ b/examples/dhtd.hs | |||
@@ -69,6 +69,7 @@ import Data.Typeable | |||
69 | import GHC.Generics | 69 | import GHC.Generics |
70 | import Data.Bool | 70 | import Data.Bool |
71 | import System.Random | 71 | import System.Random |
72 | import Network.DatagramServer.Mainline (PacketDestination(..)) | ||
72 | 73 | ||
73 | mkNodeAddr :: SockAddr -> NodeAddr IPv4 | 74 | mkNodeAddr :: SockAddr -> NodeAddr IPv4 |
74 | mkNodeAddr addr = NodeAddr (fromJust $ fromSockAddr addr) | 75 | mkNodeAddr addr = NodeAddr (fromJust $ fromSockAddr addr) |
@@ -462,13 +463,11 @@ clientSession bt tox signalQuit isBt sock n h = do | |||
462 | let (hs,as) = second (dropWhile isSpace) $ break isSpace s | 463 | let (hs,as) = second (dropWhile isSpace) $ break isSpace s |
463 | parse = do ih <- readEither hs | 464 | parse = do ih <- readEither hs |
464 | a <- readEither as | 465 | a <- readEither as |
465 | -- XXX: using 'InfoHash' only because 'NodeId' currently | 466 | return (ih, a) -- :: NodeAddr IPv4) |
466 | -- has no 'Read' instance. | ||
467 | return (ih, a :: NodeAddr IPv4) | ||
468 | case parse of | 467 | case parse of |
469 | Right (ih,a) -> do | 468 | Right (ih,a) -> do |
470 | nodeIdType ih | 469 | nodeIdType ih |
471 | nodeAddrType a | 470 | -- nodeAddrType a |
472 | proxy <- dhtType | 471 | proxy <- dhtType |
473 | let fn = findNodeMessage proxy ih | 472 | let fn = findNodeMessage proxy ih |
474 | ipType fn | 473 | ipType fn |
@@ -484,10 +483,10 @@ clientSession bt tox signalQuit isBt sock n h = do | |||
484 | let (hs,as) = second (dropWhile isSpace) $ break isSpace s | 483 | let (hs,as) = second (dropWhile isSpace) $ break isSpace s |
485 | parse = do ih <- readEither hs | 484 | parse = do ih <- readEither hs |
486 | a <- readEither as | 485 | a <- readEither as |
487 | return (ih :: InfoHash, a :: NodeAddr IPv4) | 486 | return (ih :: InfoHash, a) |
488 | case parse of | 487 | case parse of |
489 | Right (ih,a) -> do | 488 | Right (ih,a) -> do |
490 | result <- try $ queryNode' (a ::NodeAddr IPv4) $ GetPeers ih | 489 | result <- try $ queryNode' a $ GetPeers ih |
491 | let rs = either (pure . ( (,) "error" ) . showQueryFail) reportPeers result | 490 | let rs = either (pure . ( (,) "error" ) . showQueryFail) reportPeers result |
492 | return $ do | 491 | return $ do |
493 | hPutClient h $ showReport rs | 492 | hPutClient h $ showReport rs |
@@ -591,7 +590,7 @@ main = do | |||
591 | () <- takeMVar signalQuit | 590 | () <- takeMVar signalQuit |
592 | quitListening srv | 591 | quitListening srv |
593 | 592 | ||
594 | bootstrap saved_nodes bs | 593 | bootstrap saved_nodes (map (MainlineNode . toSockAddr) bs) |
595 | 594 | ||
596 | b <- isBootstrapped | 595 | b <- isBootstrapped |
597 | tbl <- getTable | 596 | tbl <- getTable |
diff --git a/src/Network/BitTorrent/DHT/Session.hs b/src/Network/BitTorrent/DHT/Session.hs index d94f028f..b775e7d3 100644 --- a/src/Network/BitTorrent/DHT/Session.hs +++ b/src/Network/BitTorrent/DHT/Session.hs | |||
@@ -116,6 +116,7 @@ import Data.Text as Text | |||
116 | import Text.PrettyPrint.HughesPJClass hiding ((<>),($$)) | 116 | import Text.PrettyPrint.HughesPJClass hiding ((<>),($$)) |
117 | import Data.Serialize as S | 117 | import Data.Serialize as S |
118 | import Network.DHT.Types | 118 | import Network.DHT.Types |
119 | import Network.DatagramServer.Types | ||
119 | 120 | ||
120 | 121 | ||
121 | import Data.Torrent as Torrent | 122 | import Data.Torrent as Torrent |
@@ -343,10 +344,12 @@ locFromCS cs = case getCallStack cs of | |||
343 | -- | Run DHT session. You /must/ properly close session using | 344 | -- | Run DHT session. You /must/ properly close session using |
344 | -- 'closeNode' function, otherwise socket or other scarce resources may | 345 | -- 'closeNode' function, otherwise socket or other scarce resources may |
345 | -- leak. | 346 | -- leak. |
346 | newNode :: ( Address ip | 347 | newNode :: forall raw dht ip u. |
348 | ( Address ip | ||
347 | , FiniteBits (NodeId dht) | 349 | , FiniteBits (NodeId dht) |
348 | , Serialize (NodeId dht) | 350 | , Serialize (NodeId dht) |
349 | , Kademlia dht | 351 | , Kademlia dht |
352 | , WireFormat raw dht | ||
350 | ) | 353 | ) |
351 | => -- [NodeHandler] -- ^ handlers to run on accepted queries; | 354 | => -- [NodeHandler] -- ^ handlers to run on accepted queries; |
352 | Options -- ^ various dht options; | 355 | Options -- ^ various dht options; |
@@ -363,13 +366,18 @@ newNode opts naddr logger mbid = do | |||
363 | nodeAddr = toSockAddr naddr | 366 | nodeAddr = toSockAddr naddr |
364 | initNode = do | 367 | initNode = do |
365 | s <- getInternalState | 368 | s <- getInternalState |
366 | (_, m) <- allocate (newManager rpcOpts (logt logger) nodeAddr []) closeManager | 369 | (myId, infovar, getst) <- liftIO $ do |
370 | (i, ctx) <- initializeServerState (Proxy :: Proxy (dht raw)) mbid | ||
371 | var <- atomically (newTVar Nothing) | ||
372 | let getst dest = do | ||
373 | info <- atomically . readTVar $ var | ||
374 | return ( maybe i myNodeId info, ctx) | ||
375 | return (i, var, getst) | ||
376 | (_, m) <- allocate (newManager rpcOpts (logt logger) nodeAddr getst []) closeManager | ||
367 | liftIO $ do | 377 | liftIO $ do |
368 | dta <- initializeDHTData | 378 | dta <- initializeDHTData |
369 | myId <- maybe genNodeId return mbid | 379 | node <- Node opts myId s m infovar |
370 | node <- Node opts myId s m | 380 | <$> newTVarIO S.empty |
371 | <$> atomically (newTVar Nothing) | ||
372 | <*> newTVarIO S.empty | ||
373 | <*> pure dta | 381 | <*> pure dta |
374 | <*> pure logger | 382 | <*> pure logger |
375 | return node | 383 | return node |
diff --git a/src/Network/DatagramServer.hs b/src/Network/DatagramServer.hs index ca968a8c..8c4ec928 100644 --- a/src/Network/DatagramServer.hs +++ b/src/Network/DatagramServer.hs | |||
@@ -199,6 +199,7 @@ data Manager raw msg = Manager | |||
199 | , pendingCalls :: {-# UNPACK #-} !(PendingCalls msg raw) | 199 | , pendingCalls :: {-# UNPACK #-} !(PendingCalls msg raw) |
200 | -- , handlers :: [Handler h msg raw] -- TODO delete this, it's not used | 200 | -- , handlers :: [Handler h msg raw] -- TODO delete this, it's not used |
201 | , logMsg :: Char -> String -> T.Text -> IO () | 201 | , logMsg :: Char -> String -> T.Text -> IO () |
202 | , serverState :: PacketDestination msg -> IO (NodeId msg, CipherContext raw msg) | ||
202 | } | 203 | } |
203 | 204 | ||
204 | sockAddrFamily :: SockAddr -> Family | 205 | sockAddrFamily :: SockAddr -> Family |
@@ -212,15 +213,16 @@ sockAddrFamily (SockAddrCan _ ) = AF_CAN | |||
212 | newManager :: Options -- ^ various protocol options; | 213 | newManager :: Options -- ^ various protocol options; |
213 | -> (Char -> String -> T.Text -> IO ()) -- ^ loging function | 214 | -> (Char -> String -> T.Text -> IO ()) -- ^ loging function |
214 | -> SockAddr -- ^ address to listen on; | 215 | -> SockAddr -- ^ address to listen on; |
216 | -> ( PacketDestination msg -> IO (NodeId msg, CipherContext raw msg) ) | ||
215 | -> [Handler h msg raw] -- ^ handlers to run on incoming queries. | 217 | -> [Handler h msg raw] -- ^ handlers to run on incoming queries. |
216 | -> IO (Manager raw msg) -- ^ new rpc manager. | 218 | -> IO (Manager raw msg) -- ^ new rpc manager. |
217 | newManager opts @ Options {..} logmsg servAddr handlers = do | 219 | newManager opts @ Options {..} logmsg servAddr getst handlers = do |
218 | validateOptions opts | 220 | validateOptions opts |
219 | sock <- bindServ | 221 | sock <- bindServ |
220 | tref <- newEmptyMVar | 222 | tref <- newEmptyMVar |
221 | tran <- newIORef optSeedTransaction | 223 | tran <- newIORef optSeedTransaction |
222 | calls <- newIORef M.empty | 224 | calls <- newIORef M.empty |
223 | return $ Manager sock opts tref tran calls logmsg | 225 | return $ Manager sock opts tref tran calls logmsg getst |
224 | where | 226 | where |
225 | bindServ = do | 227 | bindServ = do |
226 | let family = sockAddrFamily servAddr | 228 | let family = sockAddrFamily servAddr |
@@ -377,8 +379,7 @@ queryK mgr@Manager{..} dest params kont = do | |||
377 | mres <- liftIO $ do | 379 | mres <- liftIO $ do |
378 | ares <- registerQuery (tid, addr) pendingCalls | 380 | ares <- registerQuery (tid, addr) pendingCalls |
379 | 381 | ||
380 | let cli = error "TODO TOX client node id" | 382 | (cli,ctx) <- serverState dest |
381 | ctx = error "TODO TOX ToxCipherContext or () for Mainline" | ||
382 | q <- buildQuery cli addr meth tid params | 383 | q <- buildQuery cli addr meth tid params |
383 | let qb = encodePayload (q :: msg a) :: msg raw | 384 | let qb = encodePayload (q :: msg a) :: msg raw |
384 | qbs = encodeHeaders ctx qb dest | 385 | qbs = encodeHeaders ctx qb dest |
diff --git a/src/Network/DatagramServer/Mainline.hs b/src/Network/DatagramServer/Mainline.hs index 1f07b13f..fea64ee6 100644 --- a/src/Network/DatagramServer/Mainline.hs +++ b/src/Network/DatagramServer/Mainline.hs | |||
@@ -51,6 +51,7 @@ module Network.DatagramServer.Mainline | |||
51 | , KQueryArgs | 51 | , KQueryArgs |
52 | , QueryExtra(..) | 52 | , QueryExtra(..) |
53 | , ResponseExtra(..) | 53 | , ResponseExtra(..) |
54 | , PacketDestination(..) | ||
54 | 55 | ||
55 | , NodeId(..) | 56 | , NodeId(..) |
56 | , nodeIdSize | 57 | , nodeIdSize |
@@ -347,6 +348,10 @@ instance WireFormat BValue KMessageOf where | |||
347 | encodeHeaders _ kmsg _ = L.toStrict $ BE.encode kmsg | 348 | encodeHeaders _ kmsg _ = L.toStrict $ BE.encode kmsg |
348 | encodePayload msg = fmap BE.toBEncode msg | 349 | encodePayload msg = fmap BE.toBEncode msg |
349 | 350 | ||
351 | initializeServerState _ mbid = do | ||
352 | i <- maybe genNodeId return mbid | ||
353 | return (i, ()) | ||
354 | |||
350 | -- | KRPC 'compact list' compatible encoding: contact information for | 355 | -- | KRPC 'compact list' compatible encoding: contact information for |
351 | -- nodes is encoded as a 26-byte string. Also known as "Compact node | 356 | -- nodes is encoded as a 26-byte string. Also known as "Compact node |
352 | -- info" the 20-byte Node ID in network byte order has the compact | 357 | -- info" the 20-byte Node ID in network byte order has the compact |
diff --git a/src/Network/DatagramServer/Tox.hs b/src/Network/DatagramServer/Tox.hs index 8d2f9289..1763e74c 100644 --- a/src/Network/DatagramServer/Tox.hs +++ b/src/Network/DatagramServer/Tox.hs | |||
@@ -45,6 +45,7 @@ import Crypto.Error.Types | |||
45 | import Data.Hashable | 45 | import Data.Hashable |
46 | import Text.PrettyPrint as PP hiding ((<>)) | 46 | import Text.PrettyPrint as PP hiding ((<>)) |
47 | import Text.PrettyPrint.HughesPJClass hiding (($$), (<>)) | 47 | import Text.PrettyPrint.HughesPJClass hiding (($$), (<>)) |
48 | import Data.ByteArray (convert) | ||
48 | 49 | ||
49 | 50 | ||
50 | type Key32 = Word256 -- 32 byte key | 51 | type Key32 = Word256 -- 32 byte key |
@@ -391,4 +392,10 @@ instance WireFormat ByteString Message where | |||
391 | decodeHeaders ctx bs = runGet getMessage bs >>= decipher ctx | 392 | decodeHeaders ctx bs = runGet getMessage bs >>= decipher ctx |
392 | encodeHeaders ctx msg recipient = runPut $ putMessage $ encipher ctx (toxID recipient) msg | 393 | encodeHeaders ctx msg recipient = runPut $ putMessage $ encipher ctx (toxID recipient) msg |
393 | 394 | ||
395 | initializeServerState _ _ = do | ||
396 | k <- generateSecretKey | ||
397 | let Right nid = S.decode $ convert $ toPublic k | ||
398 | return (nid, ToxCipherContext k) | ||
399 | |||
400 | |||
394 | instance Read (NodeId Message) where readsPrec d s = map (\(w,xs) -> (NodeId w, xs)) $ decodeHex s | 401 | instance Read (NodeId Message) where readsPrec d s = map (\(w,xs) -> (NodeId w, xs)) $ decodeHex s |
diff --git a/src/Network/DatagramServer/Types.hs b/src/Network/DatagramServer/Types.hs index 14968764..6aa7aeaa 100644 --- a/src/Network/DatagramServer/Types.hs +++ b/src/Network/DatagramServer/Types.hs | |||
@@ -35,7 +35,7 @@ import Data.IP | |||
35 | import Network.Socket | 35 | import Network.Socket |
36 | import Text.PrettyPrint as PP hiding ((<>)) | 36 | import Text.PrettyPrint as PP hiding ((<>)) |
37 | import Text.PrettyPrint.HughesPJClass hiding (($$), (<>)) | 37 | import Text.PrettyPrint.HughesPJClass hiding (($$), (<>)) |
38 | import Text.Read (readMaybe) | 38 | import Text.Read (readMaybe, readEither) |
39 | import Data.Serialize as S | 39 | import Data.Serialize as S |
40 | import qualified Data.ByteString.Char8 as Char8 | 40 | import qualified Data.ByteString.Char8 as Char8 |
41 | import qualified Data.ByteString as BS | 41 | import qualified Data.ByteString as BS |
@@ -43,6 +43,7 @@ import Data.ByteString.Base16 as Base16 | |||
43 | import System.Entropy | 43 | import System.Entropy |
44 | import Network.DatagramServer.Error | 44 | import Network.DatagramServer.Error |
45 | import Data.LargeWord | 45 | import Data.LargeWord |
46 | import Data.Char | ||
46 | 47 | ||
47 | 48 | ||
48 | class (Eq a, Serialize a, Typeable a, Hashable a, Pretty a) | 49 | class (Eq a, Serialize a, Typeable a, Hashable a, Pretty a) |
@@ -274,6 +275,26 @@ deriving instance ( Show (NodeId dht) | |||
274 | , Show addr | 275 | , Show addr |
275 | , Show u ) => Show (NodeInfo dht addr u) | 276 | , Show u ) => Show (NodeInfo dht addr u) |
276 | 277 | ||
278 | hexdigit c = ('0' <= c && c <= '9') || ( 'a' <= c && c <= 'f') || ( 'A' <= c && c <= 'F') | ||
279 | |||
280 | instance ( FiniteBits (NodeId dht) | ||
281 | , Read (NodeId dht) | ||
282 | , Read (NodeAddr addr) | ||
283 | , Default u | ||
284 | ) => Read (NodeInfo dht addr u) where | ||
285 | readsPrec i = RP.readP_to_S $ do | ||
286 | RP.skipSpaces | ||
287 | let n = finiteBitSize (undefined :: NodeId dht) `div` 4 | ||
288 | hexhash <- sequence $ replicate n (RP.satisfy hexdigit) | ||
289 | RP.char '@' RP.+++ RP.satisfy isSpace | ||
290 | addrstr <- RP.between (RP.char '(') (RP.char ')') (RP.munch (/=')')) | ||
291 | RP.+++ RP.munch (not . isSpace) | ||
292 | addr <- either fail return $ readEither addrstr | ||
293 | nid <- either fail return $ readEither hexhash | ||
294 | return $ NodeInfo nid addr def | ||
295 | |||
296 | |||
297 | |||
277 | mapAddress :: (addr -> b) -> NodeInfo dht addr u -> NodeInfo dht b u | 298 | mapAddress :: (addr -> b) -> NodeInfo dht addr u -> NodeInfo dht b u |
278 | mapAddress f ni = ni { nodeAddr = fmap f (nodeAddr ni) } | 299 | mapAddress f ni = ni { nodeAddr = fmap f (nodeAddr ni) } |
279 | 300 | ||
@@ -348,6 +369,9 @@ class (Envelope envelope, Address (PacketDestination envelope)) => WireFormat ra | |||
348 | encodeHeaders :: CipherContext raw envelope -> envelope raw -> PacketDestination envelope -> ByteString | 369 | encodeHeaders :: CipherContext raw envelope -> envelope raw -> PacketDestination envelope -> ByteString |
349 | encodePayload :: SerializableTo raw a => envelope a -> envelope raw | 370 | encodePayload :: SerializableTo raw a => envelope a -> envelope raw |
350 | 371 | ||
372 | initializeServerState :: Proxy (envelope raw) -> Maybe (NodeId envelope) -> IO (NodeId envelope, CipherContext raw envelope) | ||
373 | |||
374 | |||
351 | encodeHexDoc :: Serialize x => x -> Doc | 375 | encodeHexDoc :: Serialize x => x -> Doc |
352 | encodeHexDoc nid = PP.text $ Char8.unpack $ Base16.encode $ S.encode nid | 376 | encodeHexDoc nid = PP.text $ Char8.unpack $ Base16.encode $ S.encode nid |
353 | 377 | ||