=pod

=encoding utf-8

=head1 NAME

Net::BitTorrent - Complete, Modern BitTorrent Client Library

=head1 SYNOPSIS

    use v5.40;
    use Net::BitTorrent;
    use Net::BitTorrent::Types qw[:encryption];

    # Initialize the client
    my $client = Net::BitTorrent->new(
        upnp_enabled => 1,
        encryption   => ENCRYPTION_REQUIRED # or 'required'
    );

    # Unified add() handles magnets, .torrents, or v1/v2 infohashes
    # Supports 20/32-byte binary or 40/64-character hex strings
    my $torrent = $client->add("magnet:?xt=urn:btih:...", "./downloads");

    # Simple event handling
    $client->on(torrent_added => sub ($nb, $t) {
        say "New swarm added: " . $t->name;
        $t->start();
    });

    # Advanced: Manual event loop integration
    # while (1) {
    #     $client->tick(0.1);
    #     select(undef, undef, undef, 0.1);
    # }

    # Wait for all downloads to finish
    $client->wait();

    # Graceful shutdown
    $client->shutdown();

=head1 DESCRIPTION

C<Net::BitTorrent> is a comprehensive, high-performance BitTorrent client library rewritten from the ground up for
B<Modern Perl (v5.40+)> using the native C<class> feature.

The library is designed around three core principles:

=over

=item 1. Loop-agnosticism: The core logic is decoupled from I/O. You can drive it with a simple C<while> loop, integrate it into C<IO::Async>, C<Mojo::IOLoop>, or even run it in a synchronous environment.

=item 2. BitTorrent v2 first: Full support for B<BEP 52 (BitTorrent v2)>, including SHA-256 infohashes, Merkle tree block verification, and hybrid v1/v2 swarms.

=item 3. Security: Features like B<BEP 42 (DHT Security)>, B<Protocol Encryption (MSE/PE)>, and peer reputation tracking are built-in and enabled by default.

=back

=head2 How Everything Fits Together

Net::BitTorrent uses a hierarchical architecture to manage the complexities of the protocol:

=head3 1. The Client (L<Net::BitTorrent>)

The entry point. It manages multiple swarms, global rate limits, decentralized discovery (DHT/LPD), and unified UDP
packet routing. It also provides a centralized "hashing queue" to prevent block verification from starving your CPU.

=head3 2. Torrents (L<Net::BitTorrent::Torrent>)

Orchestrates a single swarm. It manages its own list of discovered peers, the Piece Picker (rarest-first logic), and
communicates with the Trackers. It acts as the bridge between the network (Peers) and the local disk (Storage).

=head3 3. Peers (L<Net::BitTorrent::Peer>)

Tracks the state of a single connection (choking, interested, transfer rates). It uses a B<Protocol Handler> to speak
the wire protocol and a B<Net::BitTorrent::Transport> (TCP or uTP) to move bytes.

=head3 4. Storage (L<Net::BitTorrent::Storage>)

Manages files on disk. It uses Merkle trees for per-block verification (v2) and handles the "virtual contiguous file"
mapping required for v1 compatibility. It includes an asynchronous disk cache to keep the main loop fast.

=head1 METHODS

=head2 C<new( %params )>

Creates a new client instance.

    my $client = Net::BitTorrent->new(
        port         => 6881,
        encryption   => 'required', # 'none', 'preferred', or 'required'
        upnp_enabled => 1
    );

This method initializes the BitTorrent engine with custom configuration.

Expected parameters:

=over

=item C<port> - optional

The port to listen on for incoming connections. Defaults to a random port in the dynamic range.

=item C<user_agent> - optional

The user agent string reported to trackers and peers.

=item C<encryption> - optional

The encryption requirement level. Can be C<none>, C<preferred>, or C<required> (default).

=item C<upnp_enabled> - optional

Whether to attempt UPnP port mapping. Defaults to false.

=item C<bepXX> - optional

Toggles for specific BEPs (e.g., C<bep05 =E<gt> 0> to disable DHT). Defaults to enabled for supported BEPs.

=back

=head2 C<on( $event, $callback )>

Registers a global callback for client-level events.

    $client->on(torrent_added => sub ($nb, $torrent) {
        warn "Added: " . $torrent->name;
    });

This method allows you to react to system-wide changes or automate actions for newly added swarms.

Expected parameters:

=over

=item C<$event>

The name of the event to listen for (e.g., C<torrent_added>).

=item C<$callback>

The code reference to execute when the event is emitted.

=back

=head2 C<add( $thing, $base_path, [%args] )>

The recommended, unified method for adding a swarm.

    # Add a .torrent file
    $client->add("ubuntu.torrent", "./iso");

    # Add a magnet link
    $client->add("magnet:?xt=urn:btih:...", "./data");

This method automatically detects the type of the first parameter and adds the corresponding swarm. It returns a
L<Net::BitTorrent::Torrent> object on success.

Expected parameters:

=over

=item C<$thing>

The resource to add. Can be a file path, a Magnet URI, or an infohash (hex or binary).

=item C<$base_path>

The directory where the torrent's data will be stored.

=item C<%args> - optional

Optional parameters to pass to the L<Net::BitTorrent::Torrent> constructor.

=back

=head2 C<add_torrent( $path, $base_path, [%args] )>

Adds a torrent from a local C<.torrent> file.

    my $t = $client->add_torrent("linux.torrent", "/downloads");

This method is for adding a swarm specifically from a metadata file. It returns a L<Net::BitTorrent::Torrent> object.

Expected parameters:

=over

=item C<$path>

The path to the C<.torrent> file.

=item C<$base_path>

The directory where the torrent's data will be stored.

=item C<%args> - optional

Optional parameters to pass to the L<Net::BitTorrent::Torrent> constructor.

=back

=head2 C<add_infohash( $ih, $base_path, [%args] )>

Adds a torrent by its info hash.

    my $t = $client->add_infohash(pack('H*', '...'), './data');

This method is useful for bootstrapping a swarm when only the hash is known. It returns a L<Net::BitTorrent::Torrent>
object.

Expected parameters:

=over

=item C<$ih>

The infohash. Can be a 20-byte (v1) or 32-byte (v2) binary string, or a 40/64 character hex string.

=item C<$base_path>

The directory where the torrent's data will be stored.

=item C<%args> - optional

Optional parameters to pass to the L<Net::BitTorrent::Torrent> constructor.

=back

=head2 C<add_magnet( $uri, $base_path, [%args] )>

Adds a torrent from a Magnet URI.

    my $t = $client->add_magnet("magnet:?xt=urn:btmh:...", "./data");

This method allows adding resources from web links. It returns a L<Net::BitTorrent::Torrent> object.

Expected parameters:

=over

=item C<$uri>

The Magnet URI.

=item C<$base_path>

The directory where the torrent's data will be stored.

=item C<%args> - optional

Optional parameters to pass to the L<Net::BitTorrent::Torrent> constructor.

=back

=head2 C<torrents( )>

Returns a list of all active torrents.

    my $list = $client->torrents( );

This method returns an array reference containing all currently managed L<Net::BitTorrent::Torrent> objects.

=head2 C<finished( )>

Returns a list of completed torrents.

    my $done = $client->finished();

This method returns an array reference of all managed torrents that have completed their download.

=head2 C<wait( [$condition], [$timeout] )>

Blocks execution until a condition is met.

    $client->wait();

This method runs the internal event loop until the provided condition returns true or a timeout is reached. It returns
a boolean indicating if the condition was met.

Expected parameters:

=over

=item C<$condition> - optional

A code reference that returns true to stop waiting. Defaults to waiting for all torrents to finish.

=item C<$timeout> - optional

The maximum number of seconds to wait.

=back

=head2 C<tick( [$timeout] )>

The "heartbeat" of the library.

    $client->tick(0.1);

This method performs discovery, updates swarm logic, and handles network I/O.

Expected parameters:

=over

=item C<$timeout> - optional

The duration in seconds since the last call. Defaults to 0.1.

=back

=head2 C<save_state( $path )>

Persists session state to a file.

    $client->save_state('session.json');

This method saves the current client state to a JSON file.

Expected parameters:

=over

=item C<$path>

The file path where the state will be saved.

=back

=head2 C<load_state( $path )>

Restores session state from a file.

    $client->load_state('session.json');

This method loads client state from a JSON file.

Expected parameters:

=over

=item C<$path>

The file path to load the state from.

=back

=head2 C<dht_get( $target, $callback )>

Retrieves data from the DHT.

    $client->dht_get($target_hash, sub ($value, $node) { ... });

This method initiates a DHT lookup for the specified target hash.

Expected parameters:

=over

=item C<$target>

The 20-byte SHA-1 hash of the data key.

=item C<$callback>

The code reference called when data is found.

=back

=head2 C<dht_put( $value, [$callback] )>

Stores data in the DHT.

    $client->dht_put('My Shared Note');

This method stores immutable data in the DHT.

Expected parameters:

=over

=item C<$value>

The data to store.

=item C<$callback> - optional

The code reference called when the store operation completes.

=back

=head2 C<dht_scrape( $infohash, $callback )>

Performs a decentralized scrape.

    $client->dht_scrape($infohash, sub ($stats) { ... });

This method queries the DHT for seeder and leecher counts.

Expected parameters:

=over

=item C<$infohash>

The infohash to scrape.

=item C<$callback>

The code reference called with the scrape results.

=back

=head2 C<shutdown( )>

Gracefully stops the client.

    $client->shutdown();

This method stops all swarms, unmaps ports, and releases resources.

=head2 C<features( )>

Returns the enabled features.

    my $f = $client->features();

This method returns a hash reference containing the status of various BEPs.

=head2 C<set_limit_down( $val )>

Sets the global download rate limit.

    $client->set_limit_down( 1024 * 1024 ); # 1MiB/s

This method sets the maximum download rate in bytes per second.

Expected parameters:

=over

=item C<$val>

The limit in bytes per second. Use 0 for unlimited.

=back

=head2 C<hashing_queue_size( )>

Returns the number of pieces waiting for verification.

    my $size = $client->hashing_queue_size();

This method returns the current size of the background hashing queue.

=head2 C<queue_verification( $torrent, $index, $data )>

Queues a piece for background verification.

    $client->queue_verification( $torrent, $index, $data );

This method adds a piece to the throttled background hashing queue.

Expected parameters:

=over

=item C<$torrent>

The L<Net::BitTorrent::Torrent> object the piece belongs to.

=item C<$index>

The piece index.

=item C<$data>

The piece data.

=back

=head1 SUPPORTED BEPS

=over

=item * B<BEP 03>: The BitTorrent Protocol (TCP)

=item * B<BEP 05>: Mainline DHT

=item * B<BEP 06>: Fast Extension

=item * B<BEP 09>: Metadata Exchange

=item * B<BEP 10>: Extension Protocol

=item * B<BEP 11>: Peer Exchange (PEX)

=item * B<BEP 14>: Local Peer Discovery (LPD)

=item * B<BEP 29>: uTP (UDP Transport)

=item * B<BEP 42>: DHT Security Extensions

=item * B<BEP 52>: BitTorrent v2

=item * B<BEP 53>: Magnet URI Extension

=back

=head1 AUTHOR

Sanko Robinson E<lt>sanko@cpan.orgE<gt>

=head1 COPYRIGHT

Copyright (C) 2008-2026 by Sanko Robinson.

This library is free software; you can redistribute it and/or modify it under the terms of the Artistic License 2.0.

=cut
