summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjoe <joe@jerkface.net>2017-10-16 19:22:53 -0400
committerjoe <joe@jerkface.net>2017-10-16 19:22:53 -0400
commit35aed24bdd67cecbd77e0c64c6c054e736aac787 (patch)
tree6211ae95a2ba74f181e7fb7f93c736bf44c71960
parentc75c9c8714b1e2f489ac5fe365ecda618c8da872 (diff)
Untested announce-peer command for bittorrent dht.
-rw-r--r--examples/dhtd.hs51
-rw-r--r--src/Network/BitTorrent/DHT/Token.hs4
-rw-r--r--src/Network/BitTorrent/MainlineDHT.hs12
3 files changed, 67 insertions, 0 deletions
diff --git a/examples/dhtd.hs b/examples/dhtd.hs
index d23aca78..6529e746 100644
--- a/examples/dhtd.hs
+++ b/examples/dhtd.hs
@@ -107,6 +107,11 @@ data DHTQuery nid ni = forall addr r tok.
107 , qshowTok :: tok -> Maybe String 107 , qshowTok :: tok -> Maybe String
108 } 108 }
109 109
110data DHTAnnouncable nid ni = forall dta r. Show r => DHTAnnouncable
111 { announceParseData :: String -> String -> IO (Either String dta)
112 , announceSendData :: dta -> Maybe ni -> IO (Maybe r)
113 }
114
110data DHTSearch nid ni = forall addr tok r. DHTSearch 115data DHTSearch nid ni = forall addr tok r. DHTSearch
111 { searchThread :: ThreadId 116 { searchThread :: ThreadId
112 , searchState :: SearchState nid addr tok ni r 117 , searchState :: SearchState nid addr tok ni r
@@ -130,6 +135,7 @@ data DHT = forall nid ni. ( Show ni
130 { dhtBuckets :: TVar (BucketList ni) 135 { dhtBuckets :: TVar (BucketList ni)
131 , dhtPing :: ni -> IO Bool 136 , dhtPing :: ni -> IO Bool
132 , dhtQuery :: Map.Map String (DHTQuery nid ni) 137 , dhtQuery :: Map.Map String (DHTQuery nid ni)
138 , dhtAnnouncables :: Map.Map String (DHTAnnouncable nid ni)
133 , dhtParseId :: String -> Either String nid 139 , dhtParseId :: String -> Either String nid
134 , dhtSearches :: TVar (Map.Map (String,nid) (DHTSearch nid ni)) 140 , dhtSearches :: TVar (Map.Map (String,nid) (DHTSearch nid ni))
135 , dhtFallbackNodes :: IO [ni] 141 , dhtFallbackNodes :: IO [ni]
@@ -440,6 +446,32 @@ clientSession s@Session{..} sock cnum h = do
440 goQuery 446 goQuery
441 $ Map.lookup method dhtQuery 447 $ Map.lookup method dhtQuery
442 448
449 ("p", s) | Just DHT{..} <- Map.lookup netname dhts
450 -> cmd0 $ do
451 -- arguments: method
452 -- data
453 -- token
454 -- (optional dest-ni)
455 self <- atomically $ thisNode <$> readTVar dhtBuckets
456 let (method,xs) = break isSpace $ dropWhile isSpace s
457 (dtastr,ys) = break isSpace $ dropWhile isSpace xs
458 (tokenstr,zs) = break isSpace $ dropWhile isSpace ys
459 destination = dropWhile isSpace zs
460 goTarget DHTAnnouncable{..} = do
461 parseResult <- announceParseData dtastr tokenstr
462 case parseResult of
463 Left e -> hPutClient h e
464 Right nid -> go nid >>= either (hPutClient h) (hPutClient h . show)
465 where
466 go | null destination = fmap (maybe (Left "Timeout.") Right)
467 . flip announceSendData Nothing
468 | otherwise = case readEither destination of
469 Right ni -> fmap (maybe (Left "Timeout.") Right)
470 . flip announceSendData (Just ni)
471 Left e -> const $ return $ Left ("Bad destination: "++e)
472 maybe (hPutClient h ("Unsupported method: "++method))
473 goTarget
474 $ Map.lookup method dhtAnnouncables
443 ("s", s) | Just dht@DHT{..} <- Map.lookup netname dhts 475 ("s", s) | Just dht@DHT{..} <- Map.lookup netname dhts
444 -> cmd0 $ do 476 -> cmd0 $ do
445 let (method,xs) = break isSpace s 477 let (method,xs) = break isSpace s
@@ -583,6 +615,7 @@ main = do
583 (bt,btR) <- Mainline.newClient swarms addr 615 (bt,btR) <- Mainline.newClient swarms addr
584 quitBt <- forkListener "bt" (clientNet bt) 616 quitBt <- forkListener "bt" (clientNet bt)
585 mainlineSearches <- atomically $ newTVar Map.empty 617 mainlineSearches <- atomically $ newTVar Map.empty
618 peerPort <- atomically $ newTVar 6881 -- BitTorrent client TCP port.
586 let mainlineDHT bkts wantip = DHT 619 let mainlineDHT bkts wantip = DHT
587 { dhtBuckets = bkts btR 620 { dhtBuckets = bkts btR
588 , dhtPing = Mainline.ping bt 621 , dhtPing = Mainline.ping bt
@@ -604,6 +637,23 @@ main = do
604 , dhtParseId = readEither :: String -> Either String Mainline.NodeId 637 , dhtParseId = readEither :: String -> Either String Mainline.NodeId
605 , dhtSearches = mainlineSearches 638 , dhtSearches = mainlineSearches
606 , dhtFallbackNodes = Mainline.bootstrapNodes wantip 639 , dhtFallbackNodes = Mainline.bootstrapNodes wantip
640 , dhtAnnouncables = Map.fromList
641 [ ("peer", DHTAnnouncable { announceSendData = \dta -> \case
642 Just ni -> Mainline.announce bt dta ni
643 Nothing -> return Nothing
644 , announceParseData = \str tokstr -> do
645 port <- atomically $ readTVar peerPort
646 let ih = read str
647 tok = read tokstr
648 return $ Right $ Mainline.mkAnnounce port ih tok
649 })
650 , ("port", DHTAnnouncable { announceParseData = \portstr _ -> return $ readEither portstr
651 , announceSendData = \dta -> \case
652 Nothing -> do atomically $ writeTVar peerPort (dta :: PortNumber)
653 return $ Just dta
654 Just _ -> return Nothing
655 })]
656
607 } 657 }
608 dhts = Map.fromList $ 658 dhts = Map.fromList $
609 ("bt4", mainlineDHT Mainline.routing4 Want_IP4) 659 ("bt4", mainlineDHT Mainline.routing4 Want_IP4)
@@ -656,6 +706,7 @@ main = do
656 , dhtParseId = readEither :: String -> Either String Tox.NodeId 706 , dhtParseId = readEither :: String -> Either String Tox.NodeId
657 , dhtSearches = toxSearches 707 , dhtSearches = toxSearches
658 , dhtFallbackNodes = return [] 708 , dhtFallbackNodes = return []
709 , dhtAnnouncables = Map.empty -- TODO
659 } 710 }
660 dhts = Map.fromList $ 711 dhts = Map.fromList $
661 ("tox4", toxDHT Tox.routing4) 712 ("tox4", toxDHT Tox.routing4)
diff --git a/src/Network/BitTorrent/DHT/Token.hs b/src/Network/BitTorrent/DHT/Token.hs
index 756b5a98..3da59c53 100644
--- a/src/Network/BitTorrent/DHT/Token.hs
+++ b/src/Network/BitTorrent/DHT/Token.hs
@@ -44,6 +44,7 @@ module Network.BitTorrent.DHT.Token
44 , Network.BitTorrent.DHT.Token.update 44 , Network.BitTorrent.DHT.Token.update
45 ) where 45 ) where
46 46
47import Control.Arrow
47import Control.Monad.State 48import Control.Monad.State
48#ifdef VERSION_bencoding 49#ifdef VERSION_bencoding
49import Data.BEncode (BEncode) 50import Data.BEncode (BEncode)
@@ -75,6 +76,9 @@ newtype Token = Token BS.ByteString
75instance Show Token where 76instance Show Token where
76 show (Token bs) = B8.unpack $ Base16.encode bs 77 show (Token bs) = B8.unpack $ Base16.encode bs
77 78
79instance Read Token where
80 readsPrec i s = pure $ (Token *** B8.unpack) $ Base16.decode (B8.pack s)
81
78-- | Meaningless token, for testing purposes only. 82-- | Meaningless token, for testing purposes only.
79instance Default Token where 83instance Default Token where
80 def = makeToken (0::Int) 0 84 def = makeToken (0::Int) 0
diff --git a/src/Network/BitTorrent/MainlineDHT.hs b/src/Network/BitTorrent/MainlineDHT.hs
index f4ce4019..a7359bda 100644
--- a/src/Network/BitTorrent/MainlineDHT.hs
+++ b/src/Network/BitTorrent/MainlineDHT.hs
@@ -906,6 +906,15 @@ data Announce = Announce
906 906
907 } deriving (Show, Eq, Typeable) 907 } deriving (Show, Eq, Typeable)
908 908
909mkAnnounce :: PortNumber -> InfoHash -> Token -> Announce
910mkAnnounce portnum info token = Announce
911 { topic = info
912 , port = portnum
913 , sessionToken = token
914 , announcedName = Nothing
915 , impliedPort = False
916 }
917
909peer_ip_key = "ip" 918peer_ip_key = "ip"
910peer_id_key = "peer id" 919peer_id_key = "peer id"
911peer_port_key = "port" 920peer_port_key = "port"
@@ -1078,3 +1087,6 @@ resolve want hostAndPort = do
1078 return $ addrAddress info 1087 return $ addrAddress info
1079 1088
1080 1089
1090announce :: MainlineClient -> Announce -> NodeInfo -> IO (Maybe Announced)
1091announce client msg addr = do
1092 mainlineSend (Method "announce_peer") id (\() -> msg) client () addr