diff options
author | joe <joe@jerkface.net> | 2017-10-16 19:22:53 -0400 |
---|---|---|
committer | joe <joe@jerkface.net> | 2017-10-16 19:22:53 -0400 |
commit | 35aed24bdd67cecbd77e0c64c6c054e736aac787 (patch) | |
tree | 6211ae95a2ba74f181e7fb7f93c736bf44c71960 | |
parent | c75c9c8714b1e2f489ac5fe365ecda618c8da872 (diff) |
Untested announce-peer command for bittorrent dht.
-rw-r--r-- | examples/dhtd.hs | 51 | ||||
-rw-r--r-- | src/Network/BitTorrent/DHT/Token.hs | 4 | ||||
-rw-r--r-- | src/Network/BitTorrent/MainlineDHT.hs | 12 |
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 | ||
110 | data 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 | |||
110 | data DHTSearch nid ni = forall addr tok r. DHTSearch | 115 | data 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 | ||
47 | import Control.Arrow | ||
47 | import Control.Monad.State | 48 | import Control.Monad.State |
48 | #ifdef VERSION_bencoding | 49 | #ifdef VERSION_bencoding |
49 | import Data.BEncode (BEncode) | 50 | import Data.BEncode (BEncode) |
@@ -75,6 +76,9 @@ newtype Token = Token BS.ByteString | |||
75 | instance Show Token where | 76 | instance Show Token where |
76 | show (Token bs) = B8.unpack $ Base16.encode bs | 77 | show (Token bs) = B8.unpack $ Base16.encode bs |
77 | 78 | ||
79 | instance 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. |
79 | instance Default Token where | 83 | instance 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 | ||
909 | mkAnnounce :: PortNumber -> InfoHash -> Token -> Announce | ||
910 | mkAnnounce portnum info token = Announce | ||
911 | { topic = info | ||
912 | , port = portnum | ||
913 | , sessionToken = token | ||
914 | , announcedName = Nothing | ||
915 | , impliedPort = False | ||
916 | } | ||
917 | |||
909 | peer_ip_key = "ip" | 918 | peer_ip_key = "ip" |
910 | peer_id_key = "peer id" | 919 | peer_id_key = "peer id" |
911 | peer_port_key = "port" | 920 | peer_port_key = "port" |
@@ -1078,3 +1087,6 @@ resolve want hostAndPort = do | |||
1078 | return $ addrAddress info | 1087 | return $ addrAddress info |
1079 | 1088 | ||
1080 | 1089 | ||
1090 | announce :: MainlineClient -> Announce -> NodeInfo -> IO (Maybe Announced) | ||
1091 | announce client msg addr = do | ||
1092 | mainlineSend (Method "announce_peer") id (\() -> msg) client () addr | ||