# NAME Net::BitTorrent::DHT - Kademlia-like DHT Node # Synopsis use Net::BitTorrent::DHT; use AnyEvent; # Standalone node with user-defined port and boot_nodes my $dht = Net::BitTorrent::DHT->new( port => [1337 .. 1340, 0], boot_nodes => [['router.bittorrent.com', 6881], ['router.utorrent.com', 6881]] ); my $peer_quest = $dht->get_peers('ab97a7bca78f2628380e6609a8241a7fb02aa981', \&dht_cb); # tick, tick, tick, ... AnyEvent->condvar->recv; sub dht_cb { my ($infohash, $node, $peers) = @_; printf "We found %d peers for %s from %s:%d via DHT\n\t%s\n", scalar(@$peers), $infohash->to_Hex, $node->host, $node->port, join ', ', map { sprintf '%s:%d', @$_ } @$peers; } # Description BitTorrent uses a "distributed sloppy hash table" (DHT) for storing peer contact information for "trackerless" torrents. In effect, each peer becomes a tracker. The protocol is based on [Kademila](#kademlia) and is implemented over UDP. # Methods [Net::BitTorrent::DHT](https://metacpan.org/pod/Net::BitTorrent::DHT)'s API is simple but powerful. ...well, I think so anyway. # Net::BitTorrent::DHT->new( ) The constructor accepts a number different arguments which all greatly affect the function of your DHT node. Any combination of the following arguments may be used during construction. Note that [standalone](https://metacpan.org/pod/Net::BitTorrent::DHT::Standalone) DHT nodes do not support or require the `client` argument but internally a [Net::BitTorrent](https://metacpan.org/pod/Net::BitTorrent) client is passed and serves as the parent of this node. For brevity, the following examples assume you are building a [standalone node](https://metacpan.org/pod/Net::BitTorrent::DHT::Standalone) (for reasearch, etc.). ## Net::BitTorrent::DHT->new( nodeid => 'F' x 40 ) During construction, our local DHT nodeID can be set during construction. This is mostly useful when creating a [standalone DHT node](https://metacpan.org/pod/Net::BitTorrent::DHT::Standalone). use Net::BitTorrent::DHT; # Bit::Vector object use Bit::Vector; my $node_c = Net::BitTorrent::DHT->new( nodeid => Bit::Vector->new_Hex( 160, 'ABCD' x 10 ) ); # A SHA1 digest use Digest::SHA; my $node_d = Net::BitTorrent::DHT->new( nodeid => Bit::Vector->new_Hex( 160, Digest::SHA::sha1( $possibly_random_value ) ) ); Note that storing and reusing DHT nodeIDs over a number of sessions may seem advantagious (as if you had a "reserved parking place" in the DHT network) but will likely not improve performance as unseen nodeIDs are removed from remote routing tables after a half hour. NodeIDs, are 160-bit integers. ## Net::BitTorrent::DHT->new( port => ... ) Opens a specific UDP port number to the outside world on both IPv4 and IPv6. use Net::BitTorrent::DHT; # A single possible port my $node_a = Net::BitTorrent::DHT->new( port => 1123 ); # A list of ports my $node_b = Net::BitTorrent::DHT->new( port => [1235 .. 9875] ); Note that when handed a list of ports, they are each tried until we are able to bind to the specific port. # Net::BitTorrent::DHT->find\_node( $target, $callback ) This method asks for remote nodes with nodeIDs closer to our target. As the remote nodes respond, the callback is called with the following arguments: - target This is the target nodeid. This is useful when you've set the same callback for multiple, concurrent `find_node( )` [quest](#quests-and-callbacks) . - node This is a blessed object. TODO. - nodes This is a list of ip:port combinations the remote node claims are close to our target. A single `find_node` [quest](https://metacpan.org/pod/Net::BitTorrent::Notes#Quests-and-Callbacks) is an array ref which contains the following data: - target This is the target nodeID. - coderef This is the callback triggered as we locate new peers. - nodes This is a list of nodes we have announced to so far. - timer This is an [AnyEvent](https://metacpan.org/pod/AnyEvent) timer which is triggered every few minutes. Don't modify this. # Net::BitTorrent::DHT->get\_peers( $infohash, $callback ) This method initiates a search for peers serving a torrent with this infohash. As they are found, the callback is called with the following arguments: - infohash This is the infohash related to these peers. This is useful when you've set the same callback for multiple, concurrent `get_peers( )` quests. - node This is a blessed object. TODO. - peers This is an array ref of peers sent to us by aforementioned remote node. A single `get_peers` [quest](https://metacpan.org/pod/Net::BitTorrent::Notes#Quests-and-Callbacks) is an array ref which contains the following data: - infohash This is the infohash related to these peers. - coderef This is the callback triggered as we locate new peers. - peers This is a compacted list of all peers found so far. This is probably more useful than the list passed to the callback. - timer This is an [AnyEvent](https://metacpan.org/pod/AnyEvent) timer which is triggered every five minutes. When triggered, the node requests new peers from nodes in the bucket nearest to the infohash. Don't modify this. # Net::BitTorrent::DHT->**announce\_peer**( $infohash, $port, $callback ) This method announces that the peer controlling the querying node is downloading a torrent on a port. These outgoing queries are sent to nodes 'close' to the target infohash. As the remote nodes respond, the callback is called with the following arguments: - infohash This is the infohash related to this announcment. This is useful when you've set the same callback for multiple, concurrent `announce_peer( )` [quest](#quests-and-callbacks) . - port This is port you defined above. - node This is a blessed object. TODO. A single `announce_peer` [quest](#quests-and-callbacks) is an array ref which contains the following data: - infohash This is the infohash related to these peers. - coderef This is the callback triggered as we locate new peers. - port This is port you defined above. - nodes This is a list of nodes we have announced to so far. - timer This is an [AnyEvent](https://metacpan.org/pod/AnyEvent) timer which is triggered every few minutes. Don't modify this. `announce_peer` queries require a token sent in reply to a `get_peers` query so they should be used together. use Net::BitTorrent::DHT; my $node = Net::BitTorrent::DHT->new( ); my $quest_a = $dht->announce_peer(pack('H*', 'A' x 40), 6881, \&dht_cb); my $quest_b = $dht->announce_peer('1' x 40, 9585, \&dht_cb); sub dht_cb { my ($infohash, $port, $node) = @_; say sprintf '%s:%d now knows we are serving %s on port %d', $node->host, $node->port, $infohash->to_Hex, $port; } # Net::BitTorrent::DHT->dump\_ipv4\_buckets( ) This is a quick utility method which returns or prints (depending on context) a list of the IPv4-based routing table's bucket structure. use Net::BitTorrent::DHT; my $node = Net::BitTorrent::DHT->new( ); # After some time has passed... $node->dump_ipv4_buckets; # prints to STDOUT with say my @dump = $node->dump_ipv4_buckets; # returns list of lines # Net::BitTorrent::DHT->dump\_ipv6\_buckets( ) This is a quick utility method which returns or prints (depending on context) a list of the IPv6-based routing table's bucket structure. use Net::BitTorrent::DHT; my $node = Net::BitTorrent::DHT->new( ); # After some time has passed... $node->dump_ipv6_buckets; # prints to STDOUT with say my @dump = $node->dump_ipv6_buckets; # returns list of lines # Author Sanko Robinson - http://sankorobinson.com/ CPAN ID: SANKO # License and Legal Copyright (C) 2008-2014 by Sanko Robinson This program is free software; you can redistribute it and/or modify it under the terms of [The Artistic License 2.0](http://www.perlfoundation.org/artistic_license_2_0). See the `LICENSE` file included with this distribution or [notes on the Artistic License 2.0](http://www.perlfoundation.org/artistic_2_0_notes) for clarification. When separated from the distribution, all original POD documentation is covered by the [Creative Commons Attribution-Share Alike 3.0 License](http://creativecommons.org/licenses/by-sa/3.0/us/legalcode). See the [clarification of the CCA-SA3.0](http://creativecommons.org/licenses/by-sa/3.0/us/). Neither this module nor the [Author](#author) is affiliated with BitTorrent, Inc.