summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bittorrent.cabal1
-rw-r--r--examples/dhtd.hs13
-rw-r--r--src/Network/BitTorrent/DHT/Session.hs20
-rw-r--r--src/Network/DatagramServer.hs9
-rw-r--r--src/Network/DatagramServer/Mainline.hs5
-rw-r--r--src/Network/DatagramServer/Tox.hs7
-rw-r--r--src/Network/DatagramServer/Types.hs26
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
69import GHC.Generics 69import GHC.Generics
70import Data.Bool 70import Data.Bool
71import System.Random 71import System.Random
72import Network.DatagramServer.Mainline (PacketDestination(..))
72 73
73mkNodeAddr :: SockAddr -> NodeAddr IPv4 74mkNodeAddr :: SockAddr -> NodeAddr IPv4
74mkNodeAddr addr = NodeAddr (fromJust $ fromSockAddr addr) 75mkNodeAddr 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
116import Text.PrettyPrint.HughesPJClass hiding ((<>),($$)) 116import Text.PrettyPrint.HughesPJClass hiding ((<>),($$))
117import Data.Serialize as S 117import Data.Serialize as S
118import Network.DHT.Types 118import Network.DHT.Types
119import Network.DatagramServer.Types
119 120
120 121
121import Data.Torrent as Torrent 122import 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.
346newNode :: ( Address ip 347newNode :: 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
204sockAddrFamily :: SockAddr -> Family 205sockAddrFamily :: SockAddr -> Family
@@ -212,15 +213,16 @@ sockAddrFamily (SockAddrCan _ ) = AF_CAN
212newManager :: Options -- ^ various protocol options; 213newManager :: 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.
217newManager opts @ Options {..} logmsg servAddr handlers = do 219newManager 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
45import Data.Hashable 45import Data.Hashable
46import Text.PrettyPrint as PP hiding ((<>)) 46import Text.PrettyPrint as PP hiding ((<>))
47import Text.PrettyPrint.HughesPJClass hiding (($$), (<>)) 47import Text.PrettyPrint.HughesPJClass hiding (($$), (<>))
48import Data.ByteArray (convert)
48 49
49 50
50type Key32 = Word256 -- 32 byte key 51type 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
394instance Read (NodeId Message) where readsPrec d s = map (\(w,xs) -> (NodeId w, xs)) $ decodeHex s 401instance 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
35import Network.Socket 35import Network.Socket
36import Text.PrettyPrint as PP hiding ((<>)) 36import Text.PrettyPrint as PP hiding ((<>))
37import Text.PrettyPrint.HughesPJClass hiding (($$), (<>)) 37import Text.PrettyPrint.HughesPJClass hiding (($$), (<>))
38import Text.Read (readMaybe) 38import Text.Read (readMaybe, readEither)
39import Data.Serialize as S 39import Data.Serialize as S
40import qualified Data.ByteString.Char8 as Char8 40import qualified Data.ByteString.Char8 as Char8
41import qualified Data.ByteString as BS 41import qualified Data.ByteString as BS
@@ -43,6 +43,7 @@ import Data.ByteString.Base16 as Base16
43import System.Entropy 43import System.Entropy
44import Network.DatagramServer.Error 44import Network.DatagramServer.Error
45import Data.LargeWord 45import Data.LargeWord
46import Data.Char
46 47
47 48
48class (Eq a, Serialize a, Typeable a, Hashable a, Pretty a) 49class (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
278hexdigit c = ('0' <= c && c <= '9') || ( 'a' <= c && c <= 'f') || ( 'A' <= c && c <= 'F')
279
280instance ( 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
277mapAddress :: (addr -> b) -> NodeInfo dht addr u -> NodeInfo dht b u 298mapAddress :: (addr -> b) -> NodeInfo dht addr u -> NodeInfo dht b u
278mapAddress f ni = ni { nodeAddr = fmap f (nodeAddr ni) } 299mapAddress 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
351encodeHexDoc :: Serialize x => x -> Doc 375encodeHexDoc :: Serialize x => x -> Doc
352encodeHexDoc nid = PP.text $ Char8.unpack $ Base16.encode $ S.encode nid 376encodeHexDoc nid = PP.text $ Char8.unpack $ Base16.encode $ S.encode nid
353 377