1
0
Fork 0
mirror of https://github.com/transmission/transmission synced 2024-12-22 07:42:37 +00:00
transmission/libtransmission/tr-dht.h
Yat Ho ca11c33d05
fix: various DHT bugs (#6569)
* fix: unconditionally send DHT Port msg if supported

* chore: add "maybe" to dht add_node functions

* feat: change `bind-address-ipv*` defaults to empty string

* chore: housekeeping

* fix: initialise DHT node id with random bytes

* chore: housekeeping
2024-02-04 12:18:01 -06:00

119 lines
3.2 KiB
C++

// This file Copyright © Juliusz Chroboczek.
// It may be used under the MIT (SPDX: MIT) license.
// License text can be found in the licenses/ folder.
#pragma once
#ifndef __TRANSMISSION__
#error only libtransmission should #include this header.
#endif
#include <cstddef> // size_t
#include <ctime>
#include <memory>
#include <string_view>
#include <vector>
#ifdef _WIN32
#include <ws2tcpip.h>
#else
#include <sys/socket.h>
#endif
#include <dht/dht.h>
#include "libtransmission/transmission.h"
#include "libtransmission/net.h" // tr_port
#include "libtransmission/tr-macros.h"
struct tr_pex;
namespace libtransmission
{
class TimerMaker;
} // namespace libtransmission
class tr_dht
{
public:
// Wrapper around DHT library.
// This calls `jech/dht` in production, but makes it possible for tests to inject a mock.
struct API
{
virtual ~API() = default;
virtual int get_nodes(struct sockaddr_in* sin, int* num, struct sockaddr_in6* sin6, int* num6)
{
return ::dht_get_nodes(sin, num, sin6, num6);
}
virtual int nodes(int af, int* good_return, int* dubious_return, int* cached_return, int* incoming_return)
{
return ::dht_nodes(af, good_return, dubious_return, cached_return, incoming_return);
}
virtual int periodic(
void const* buf,
size_t buflen,
struct sockaddr const* from,
int fromlen,
time_t* tosleep,
dht_callback_t callback,
void* closure)
{
return ::dht_periodic(buf, buflen, from, fromlen, tosleep, callback, closure);
}
virtual int ping_node(struct sockaddr const* sa, int salen)
{
return ::dht_ping_node(sa, salen);
}
virtual int search(unsigned char const* id, int port, int af, dht_callback_t callback, void* closure)
{
return ::dht_search(id, port, af, callback, closure);
}
virtual int init(int s, int s6, unsigned char const* id, unsigned char const* v)
{
return ::dht_init(s, s6, id, v);
}
virtual int uninit()
{
return ::dht_uninit();
}
};
class Mediator
{
public:
virtual ~Mediator() = default;
[[nodiscard]] virtual std::vector<tr_torrent_id_t> torrents_allowing_dht() const = 0;
[[nodiscard]] virtual tr_sha1_digest_t torrent_info_hash(tr_torrent_id_t) const = 0;
[[nodiscard]] virtual std::string_view config_dir() const = 0;
[[nodiscard]] virtual libtransmission::TimerMaker& timer_maker() = 0;
[[nodiscard]] virtual API& api()
{
return api_;
}
virtual void add_pex(tr_sha1_digest_t const&, tr_pex const* pex, size_t n_pex) = 0;
private:
API api_;
};
[[nodiscard]] static std::unique_ptr<tr_dht> create(
Mediator& mediator,
tr_port peer_port,
tr_socket_t udp4_socket,
tr_socket_t udp6_socket);
virtual ~tr_dht() = default;
virtual void maybe_add_node(tr_address const& address, tr_port port) = 0;
virtual void handle_message(unsigned char const* msg, size_t msglen, struct sockaddr* from, socklen_t fromlen) = 0;
};