2022-01-20 18:27:56 +00:00
|
|
|
// This file Copyright © 2007-2022 Mnemosyne LLC.
|
2022-08-08 18:05:39 +00:00
|
|
|
// It may be used under GPLv2 (SPDX: GPL-2.0-only), GPLv3 (SPDX: GPL-3.0-only),
|
2022-01-20 18:27:56 +00:00
|
|
|
// or any future license endorsed by Mnemosyne LLC.
|
|
|
|
// License text can be found in the licenses/ folder.
|
2007-09-20 16:32:01 +00:00
|
|
|
|
2017-11-14 20:21:28 +00:00
|
|
|
#pragma once
|
|
|
|
|
2008-11-24 20:17:36 +00:00
|
|
|
#ifndef __TRANSMISSION__
|
2017-04-19 12:04:45 +00:00
|
|
|
#error only libtransmission should #include this header.
|
2008-11-24 20:17:36 +00:00
|
|
|
#endif
|
|
|
|
|
2021-12-16 09:43:51 +00:00
|
|
|
#include <cstddef> // size_t
|
|
|
|
#include <cstdint> // uintX_t
|
2022-07-10 18:51:35 +00:00
|
|
|
#include <deque>
|
2022-04-02 14:06:02 +00:00
|
|
|
#include <memory>
|
2022-12-16 23:21:01 +00:00
|
|
|
#include <utility> // std::pair
|
2021-12-15 21:25:42 +00:00
|
|
|
|
2009-01-02 17:46:22 +00:00
|
|
|
#include "transmission.h"
|
2021-12-15 21:25:42 +00:00
|
|
|
|
2009-01-02 19:56:06 +00:00
|
|
|
#include "bandwidth.h"
|
2022-05-26 17:17:03 +00:00
|
|
|
#include "net.h" // tr_address
|
2022-07-15 00:54:10 +00:00
|
|
|
#include "peer-mse.h"
|
2017-06-28 15:46:06 +00:00
|
|
|
#include "peer-socket.h"
|
2022-10-19 16:42:08 +00:00
|
|
|
#include "tr-buffer.h"
|
2022-11-06 21:11:30 +00:00
|
|
|
#include "utils-ev.h"
|
2009-01-02 17:46:22 +00:00
|
|
|
|
2022-07-08 15:13:22 +00:00
|
|
|
struct struct_utp_context;
|
2009-01-02 17:46:22 +00:00
|
|
|
|
2022-12-16 07:23:12 +00:00
|
|
|
namespace libtransmission::test
|
|
|
|
{
|
|
|
|
class HandshakeTest;
|
|
|
|
} // namespace libtransmission::test
|
|
|
|
|
2021-10-06 14:26:07 +00:00
|
|
|
enum ReadState
|
2009-01-02 17:46:22 +00:00
|
|
|
{
|
|
|
|
READ_NOW,
|
|
|
|
READ_LATER,
|
|
|
|
READ_ERR
|
2021-10-06 14:26:07 +00:00
|
|
|
};
|
2009-01-02 17:46:22 +00:00
|
|
|
|
2022-08-30 17:38:30 +00:00
|
|
|
class tr_peerIo final : public std::enable_shared_from_this<tr_peerIo>
|
2021-10-11 21:54:16 +00:00
|
|
|
{
|
2022-07-15 00:54:10 +00:00
|
|
|
using DH = tr_message_stream_encryption::DH;
|
|
|
|
using Filter = tr_message_stream_encryption::Filter;
|
2022-12-16 07:23:12 +00:00
|
|
|
using CanRead = ReadState (*)(tr_peerIo* io, void* user_data, size_t* setme_piece_byte_count);
|
|
|
|
using DidWrite = void (*)(tr_peerIo* io, size_t bytesWritten, bool wasPieceData, void* userData);
|
|
|
|
using GotError = void (*)(tr_peerIo* io, tr_error const& error, void* userData);
|
|
|
|
|
2022-12-16 23:21:01 +00:00
|
|
|
public:
|
2022-12-16 07:23:12 +00:00
|
|
|
tr_peerIo(
|
|
|
|
tr_session* session_in,
|
|
|
|
tr_sha1_digest_t const* info_hash,
|
|
|
|
bool is_incoming,
|
|
|
|
bool is_seed,
|
|
|
|
tr_bandwidth* parent_bandwidth);
|
|
|
|
|
2022-08-30 17:38:30 +00:00
|
|
|
~tr_peerIo();
|
|
|
|
|
2022-12-16 07:23:12 +00:00
|
|
|
static std::shared_ptr<tr_peerIo> new_outgoing(
|
2022-08-29 20:58:18 +00:00
|
|
|
tr_session* session,
|
|
|
|
tr_bandwidth* parent,
|
2022-12-06 16:28:28 +00:00
|
|
|
tr_address const& addr,
|
2022-05-26 17:17:03 +00:00
|
|
|
tr_port port,
|
2022-12-16 07:23:12 +00:00
|
|
|
tr_sha1_digest_t const& info_hash,
|
2022-05-26 17:17:03 +00:00
|
|
|
bool is_seed,
|
2022-08-29 20:58:18 +00:00
|
|
|
bool utp);
|
|
|
|
|
2022-12-16 07:23:12 +00:00
|
|
|
static std::shared_ptr<tr_peerIo> new_incoming(tr_session* session, tr_bandwidth* parent, tr_peer_socket socket);
|
|
|
|
|
2022-12-16 23:21:01 +00:00
|
|
|
constexpr void set_callbacks(CanRead can_read, DidWrite did_write, GotError got_error, void* user_data)
|
2022-12-16 07:23:12 +00:00
|
|
|
{
|
2022-12-16 23:21:01 +00:00
|
|
|
can_read_ = can_read;
|
|
|
|
did_write_ = did_write;
|
|
|
|
got_error_ = got_error;
|
|
|
|
user_data_ = user_data;
|
2022-12-16 07:23:12 +00:00
|
|
|
}
|
2022-08-29 20:58:18 +00:00
|
|
|
|
2022-12-16 23:21:01 +00:00
|
|
|
void clear_callbacks()
|
|
|
|
{
|
|
|
|
set_callbacks(nullptr, nullptr, nullptr, nullptr);
|
|
|
|
}
|
2022-08-29 18:33:08 +00:00
|
|
|
|
2022-12-16 23:21:01 +00:00
|
|
|
void set_socket(tr_peer_socket);
|
2022-08-29 18:33:08 +00:00
|
|
|
|
2022-12-16 23:21:01 +00:00
|
|
|
[[nodiscard]] constexpr auto is_utp() const noexcept
|
2022-08-29 18:33:08 +00:00
|
|
|
{
|
2022-12-16 23:21:01 +00:00
|
|
|
return socket_.is_utp();
|
2022-08-29 18:33:08 +00:00
|
|
|
}
|
|
|
|
|
2022-12-16 23:21:01 +00:00
|
|
|
void clear();
|
2022-08-29 18:33:08 +00:00
|
|
|
|
2022-12-16 07:23:12 +00:00
|
|
|
[[nodiscard]] bool reconnect();
|
2022-08-29 18:33:08 +00:00
|
|
|
|
2022-12-16 07:23:12 +00:00
|
|
|
void set_enabled(tr_direction dir, bool is_enabled);
|
2022-08-29 20:58:18 +00:00
|
|
|
|
2022-12-16 23:21:01 +00:00
|
|
|
///
|
2022-05-26 17:17:03 +00:00
|
|
|
|
2022-12-23 21:21:40 +00:00
|
|
|
[[nodiscard]] TR_CONSTEXPR20 auto read_buffer_size() const noexcept
|
2022-05-26 17:17:03 +00:00
|
|
|
{
|
2022-12-16 23:21:01 +00:00
|
|
|
return std::size(inbuf_);
|
2022-05-26 17:17:03 +00:00
|
|
|
}
|
|
|
|
|
2022-12-16 23:21:01 +00:00
|
|
|
template<typename T>
|
|
|
|
[[nodiscard]] auto read_buffer_starts_with(T const& t) const noexcept
|
2022-12-06 00:53:31 +00:00
|
|
|
{
|
2023-01-28 02:12:09 +00:00
|
|
|
return inbuf_.starts_with(t);
|
2022-12-06 00:53:31 +00:00
|
|
|
}
|
2022-04-02 14:06:02 +00:00
|
|
|
|
2022-12-16 07:23:12 +00:00
|
|
|
void read_buffer_drain(size_t byte_count);
|
2022-08-29 18:33:08 +00:00
|
|
|
|
2022-12-16 23:21:01 +00:00
|
|
|
void read_bytes(void* bytes, size_t byte_count);
|
2022-08-29 18:33:08 +00:00
|
|
|
|
2022-12-16 23:21:01 +00:00
|
|
|
void read_uint8(uint8_t* setme)
|
2022-09-09 18:12:47 +00:00
|
|
|
{
|
2022-12-16 23:21:01 +00:00
|
|
|
read_bytes(setme, sizeof(uint8_t));
|
2022-09-09 18:12:47 +00:00
|
|
|
}
|
|
|
|
|
2022-12-16 23:21:01 +00:00
|
|
|
void read_uint16(uint16_t* setme);
|
|
|
|
|
|
|
|
void read_uint32(uint32_t* setme);
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
[[nodiscard]] size_t get_write_buffer_space(uint64_t now) const noexcept;
|
2022-07-16 20:25:44 +00:00
|
|
|
|
2022-12-16 07:23:12 +00:00
|
|
|
void write_bytes(void const* bytes, size_t n_bytes, bool is_piece_data);
|
2022-10-19 16:42:08 +00:00
|
|
|
|
|
|
|
// Write all the data from `buf`.
|
|
|
|
// This is a destructive add: `buf` is empty after this call.
|
|
|
|
void write(libtransmission::Buffer& buf, bool is_piece_data);
|
|
|
|
|
2022-12-16 23:21:01 +00:00
|
|
|
size_t flush_outgoing_protocol_msgs();
|
|
|
|
|
|
|
|
size_t flush(tr_direction dir, size_t byte_limit);
|
2022-08-29 20:58:18 +00:00
|
|
|
|
2022-12-16 23:21:01 +00:00
|
|
|
///
|
|
|
|
|
|
|
|
[[nodiscard]] auto has_bandwidth_left(tr_direction dir) const noexcept
|
2022-05-26 17:17:03 +00:00
|
|
|
{
|
2022-06-29 20:08:58 +00:00
|
|
|
return bandwidth_.clamp(dir, 1024) > 0;
|
2022-05-26 17:17:03 +00:00
|
|
|
}
|
|
|
|
|
2022-12-16 23:21:01 +00:00
|
|
|
[[nodiscard]] auto get_piece_speed_bytes_per_second(uint64_t now, tr_direction dir) const noexcept
|
2022-05-26 17:17:03 +00:00
|
|
|
{
|
2022-06-29 20:08:58 +00:00
|
|
|
return bandwidth_.getPieceSpeedBytesPerSecond(now, dir);
|
2022-05-26 17:17:03 +00:00
|
|
|
}
|
|
|
|
|
2022-12-16 23:21:01 +00:00
|
|
|
///
|
2022-05-26 17:17:03 +00:00
|
|
|
|
2022-12-16 07:23:12 +00:00
|
|
|
[[nodiscard]] constexpr auto supports_fext() const noexcept
|
2022-05-26 17:17:03 +00:00
|
|
|
{
|
|
|
|
return fast_extension_supported_;
|
|
|
|
}
|
|
|
|
|
2022-12-16 23:21:01 +00:00
|
|
|
constexpr void set_supports_fext(bool flag) noexcept
|
2022-05-26 17:17:03 +00:00
|
|
|
{
|
2022-12-16 23:21:01 +00:00
|
|
|
fast_extension_supported_ = flag;
|
2022-05-26 17:17:03 +00:00
|
|
|
}
|
|
|
|
|
2022-12-16 23:21:01 +00:00
|
|
|
///
|
|
|
|
|
2022-12-16 07:23:12 +00:00
|
|
|
[[nodiscard]] constexpr auto supports_ltep() const noexcept
|
2022-05-26 17:17:03 +00:00
|
|
|
{
|
|
|
|
return extended_protocol_supported_;
|
|
|
|
}
|
|
|
|
|
2022-12-16 23:21:01 +00:00
|
|
|
constexpr void set_supports_ltep(bool flag) noexcept
|
2022-05-26 17:17:03 +00:00
|
|
|
{
|
2022-12-16 23:21:01 +00:00
|
|
|
extended_protocol_supported_ = flag;
|
2022-05-26 17:17:03 +00:00
|
|
|
}
|
2009-01-05 04:27:54 +00:00
|
|
|
|
2022-12-16 23:21:01 +00:00
|
|
|
///
|
|
|
|
|
2022-12-16 07:23:12 +00:00
|
|
|
[[nodiscard]] constexpr auto supports_dht() const noexcept
|
2022-05-26 17:17:03 +00:00
|
|
|
{
|
|
|
|
return dht_supported_;
|
|
|
|
}
|
|
|
|
|
2022-12-16 23:21:01 +00:00
|
|
|
constexpr void set_supports_dht(bool flag) noexcept
|
2022-05-26 17:17:03 +00:00
|
|
|
{
|
2022-12-16 23:21:01 +00:00
|
|
|
dht_supported_ = flag;
|
2022-05-26 17:17:03 +00:00
|
|
|
}
|
|
|
|
|
2022-12-16 23:21:01 +00:00
|
|
|
///
|
2022-05-26 17:17:03 +00:00
|
|
|
|
2022-06-29 20:08:58 +00:00
|
|
|
[[nodiscard]] constexpr auto const& bandwidth() const noexcept
|
|
|
|
{
|
|
|
|
return bandwidth_;
|
|
|
|
}
|
|
|
|
|
|
|
|
[[nodiscard]] constexpr auto& bandwidth() noexcept
|
|
|
|
{
|
|
|
|
return bandwidth_;
|
|
|
|
}
|
|
|
|
|
2022-12-16 23:21:01 +00:00
|
|
|
void set_bandwidth(tr_bandwidth* parent)
|
2022-06-29 20:08:58 +00:00
|
|
|
{
|
|
|
|
bandwidth_.setParent(parent);
|
|
|
|
}
|
|
|
|
|
2022-12-16 23:21:01 +00:00
|
|
|
///
|
|
|
|
|
|
|
|
[[nodiscard]] constexpr auto const& torrent_hash() const noexcept
|
2022-07-11 02:57:05 +00:00
|
|
|
{
|
2022-12-16 23:21:01 +00:00
|
|
|
return info_hash_;
|
2022-07-11 02:57:05 +00:00
|
|
|
}
|
|
|
|
|
2022-12-16 23:21:01 +00:00
|
|
|
void set_torrent_hash(tr_sha1_digest_t const& hash) noexcept
|
2022-07-11 02:57:05 +00:00
|
|
|
{
|
2022-12-16 07:23:12 +00:00
|
|
|
info_hash_ = hash;
|
2022-07-11 02:57:05 +00:00
|
|
|
}
|
|
|
|
|
2022-12-16 23:21:01 +00:00
|
|
|
///
|
|
|
|
|
|
|
|
[[nodiscard]] constexpr auto priority() const noexcept
|
2022-07-11 02:57:05 +00:00
|
|
|
{
|
2022-12-16 23:21:01 +00:00
|
|
|
return priority_;
|
2022-07-11 02:57:05 +00:00
|
|
|
}
|
|
|
|
|
2022-12-16 23:21:01 +00:00
|
|
|
constexpr void set_priority(tr_priority_t priority)
|
|
|
|
{
|
|
|
|
priority_ = priority;
|
|
|
|
}
|
2022-08-29 18:33:08 +00:00
|
|
|
|
2022-12-16 23:21:01 +00:00
|
|
|
///
|
|
|
|
|
|
|
|
[[nodiscard]] constexpr auto supports_utp() const noexcept
|
2022-10-29 21:59:24 +00:00
|
|
|
{
|
2022-12-16 23:21:01 +00:00
|
|
|
return utp_supported_;
|
2022-10-29 21:59:24 +00:00
|
|
|
}
|
|
|
|
|
2022-12-16 23:21:01 +00:00
|
|
|
[[nodiscard]] constexpr auto is_incoming() const noexcept
|
2022-11-17 20:53:08 +00:00
|
|
|
{
|
2022-12-16 23:21:01 +00:00
|
|
|
return is_incoming_;
|
2022-11-17 20:53:08 +00:00
|
|
|
}
|
|
|
|
|
2022-12-16 23:21:01 +00:00
|
|
|
[[nodiscard]] constexpr auto const& address() const noexcept
|
2022-12-16 07:23:12 +00:00
|
|
|
{
|
2022-12-16 23:21:01 +00:00
|
|
|
return socket_.address();
|
2022-12-16 07:23:12 +00:00
|
|
|
}
|
2021-10-11 21:54:16 +00:00
|
|
|
|
2022-12-16 23:21:01 +00:00
|
|
|
[[nodiscard]] constexpr auto socket_address() const noexcept
|
2022-12-16 07:23:12 +00:00
|
|
|
{
|
2022-12-16 23:21:01 +00:00
|
|
|
return socket_.socketAddress();
|
2022-12-16 07:23:12 +00:00
|
|
|
}
|
2022-05-26 17:17:03 +00:00
|
|
|
|
2022-12-16 23:21:01 +00:00
|
|
|
[[nodiscard]] auto display_name() const
|
2022-07-15 00:54:10 +00:00
|
|
|
{
|
2022-12-16 23:21:01 +00:00
|
|
|
return socket_.display_name();
|
2022-07-15 00:54:10 +00:00
|
|
|
}
|
|
|
|
|
2022-12-16 23:21:01 +00:00
|
|
|
///
|
|
|
|
|
|
|
|
[[nodiscard]] constexpr auto is_encrypted() const noexcept
|
2022-07-15 00:54:10 +00:00
|
|
|
{
|
2022-12-16 23:21:01 +00:00
|
|
|
return filter_.is_active();
|
|
|
|
}
|
|
|
|
|
|
|
|
void decrypt_init(bool is_incoming, DH const& dh, tr_sha1_digest_t const& info_hash)
|
|
|
|
{
|
|
|
|
filter_.decryptInit(is_incoming, dh, info_hash);
|
2022-07-15 00:54:10 +00:00
|
|
|
}
|
|
|
|
|
2022-12-16 07:23:12 +00:00
|
|
|
void encrypt_init(bool is_incoming, DH const& dh, tr_sha1_digest_t const& info_hash)
|
2022-07-15 00:54:10 +00:00
|
|
|
{
|
2022-11-22 00:08:06 +00:00
|
|
|
filter_.encryptInit(is_incoming, dh, info_hash);
|
2022-07-15 00:54:10 +00:00
|
|
|
}
|
|
|
|
|
2022-12-16 23:21:01 +00:00
|
|
|
///
|
|
|
|
|
2022-12-16 07:23:12 +00:00
|
|
|
static void utp_init(struct_utp_context* ctx);
|
|
|
|
|
|
|
|
private:
|
|
|
|
static constexpr auto RcvBuf = size_t{ 256 * 1024 };
|
|
|
|
|
|
|
|
friend class libtransmission::test::HandshakeTest;
|
|
|
|
|
2022-12-16 23:21:01 +00:00
|
|
|
[[nodiscard]] constexpr auto is_seed() const noexcept
|
|
|
|
{
|
|
|
|
return is_seed_;
|
|
|
|
}
|
|
|
|
|
2022-12-16 07:23:12 +00:00
|
|
|
void call_error_callback(tr_error const& error)
|
2022-07-15 00:54:10 +00:00
|
|
|
{
|
2022-12-16 07:23:12 +00:00
|
|
|
if (got_error_ != nullptr)
|
|
|
|
{
|
|
|
|
got_error_(this, error, user_data_);
|
|
|
|
}
|
2022-07-15 00:54:10 +00:00
|
|
|
}
|
|
|
|
|
2022-12-16 23:21:01 +00:00
|
|
|
void decrypt(size_t buflen, void* buf)
|
|
|
|
{
|
|
|
|
filter_.decrypt(buflen, buf);
|
|
|
|
}
|
|
|
|
|
2022-12-16 07:23:12 +00:00
|
|
|
void encrypt(size_t buflen, void* buf)
|
2022-07-15 00:54:10 +00:00
|
|
|
{
|
2022-12-16 07:23:12 +00:00
|
|
|
filter_.encrypt(buflen, buf);
|
2022-07-15 00:54:10 +00:00
|
|
|
}
|
|
|
|
|
2022-12-16 07:23:12 +00:00
|
|
|
void on_utp_state_change(int new_state);
|
|
|
|
void on_utp_error(int errcode);
|
2022-06-29 20:08:58 +00:00
|
|
|
|
2022-12-16 07:23:12 +00:00
|
|
|
void close();
|
2022-07-15 00:54:10 +00:00
|
|
|
|
2022-12-16 07:23:12 +00:00
|
|
|
static void event_read_cb(evutil_socket_t fd, short /*event*/, void* vio);
|
|
|
|
static void event_write_cb(evutil_socket_t fd, short /*event*/, void* vio);
|
|
|
|
|
|
|
|
void event_enable(short event);
|
|
|
|
void event_disable(short event);
|
|
|
|
|
|
|
|
void can_read_wrapper();
|
|
|
|
void did_write_wrapper(size_t bytes_transferred);
|
|
|
|
|
|
|
|
size_t try_read(size_t max);
|
|
|
|
size_t try_write(size_t max);
|
2022-12-06 00:53:31 +00:00
|
|
|
|
|
|
|
// this is only public for testing purposes.
|
2022-12-16 07:23:12 +00:00
|
|
|
// production code should use new_outgoing() or new_incoming()
|
2022-12-06 00:53:31 +00:00
|
|
|
static std::shared_ptr<tr_peerIo> create(
|
|
|
|
tr_session* session,
|
|
|
|
tr_bandwidth* parent,
|
2022-12-16 07:23:12 +00:00
|
|
|
tr_sha1_digest_t const* info_hash,
|
2022-12-06 00:53:31 +00:00
|
|
|
bool is_incoming,
|
2022-12-16 07:23:12 +00:00
|
|
|
bool is_seed);
|
|
|
|
|
|
|
|
Filter filter_;
|
|
|
|
|
|
|
|
std::deque<std::pair<size_t /*n_bytes*/, bool /*is_piece_data*/>> outbuf_info_;
|
|
|
|
|
|
|
|
tr_peer_socket socket_ = {};
|
2022-12-06 00:53:31 +00:00
|
|
|
|
2022-08-29 20:58:18 +00:00
|
|
|
tr_bandwidth bandwidth_;
|
|
|
|
|
2022-12-16 07:23:12 +00:00
|
|
|
tr_sha1_digest_t info_hash_;
|
|
|
|
|
|
|
|
libtransmission::Buffer inbuf_;
|
|
|
|
libtransmission::Buffer outbuf_;
|
|
|
|
|
|
|
|
tr_session* const session_;
|
2022-08-29 20:58:18 +00:00
|
|
|
|
2022-12-16 07:23:12 +00:00
|
|
|
CanRead can_read_ = nullptr;
|
|
|
|
DidWrite did_write_ = nullptr;
|
|
|
|
GotError got_error_ = nullptr;
|
|
|
|
void* user_data_ = nullptr;
|
|
|
|
|
|
|
|
libtransmission::evhelpers::event_unique_ptr event_read_;
|
|
|
|
libtransmission::evhelpers::event_unique_ptr event_write_;
|
|
|
|
|
|
|
|
short int pending_events_ = 0;
|
|
|
|
|
|
|
|
tr_priority_t priority_ = TR_PRI_NORMAL;
|
2022-07-15 00:54:10 +00:00
|
|
|
|
2022-05-26 17:17:03 +00:00
|
|
|
bool const is_seed_;
|
2022-07-15 00:54:10 +00:00
|
|
|
bool const is_incoming_;
|
2022-05-26 17:17:03 +00:00
|
|
|
|
2022-12-16 07:23:12 +00:00
|
|
|
bool utp_supported_ = false;
|
2022-05-26 17:17:03 +00:00
|
|
|
bool dht_supported_ = false;
|
|
|
|
bool extended_protocol_supported_ = false;
|
|
|
|
bool fast_extension_supported_ = false;
|
2021-10-06 14:26:07 +00:00
|
|
|
};
|