Skip to content

Commit

Permalink
Revert: UDNS static cast
Browse files Browse the repository at this point in the history
It did not resolve the crash problem.
  • Loading branch information
stickz committed Jul 17, 2024
1 parent 1303959 commit 7f12473
Show file tree
Hide file tree
Showing 9 changed files with 61 additions and 62 deletions.
7 changes: 1 addition & 6 deletions libtorrent/rak/socket_address.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,6 @@ class socket_address {

static socket_address* cast_from(sockaddr* sa) { return reinterpret_cast<socket_address*>(sa); }
static const socket_address* cast_from(const sockaddr* sa) { return reinterpret_cast<const socket_address*>(sa); }

static socket_address_inet* cast_from_in(sockaddr_in* sa) { return reinterpret_cast<socket_address_inet*>(sa); }
static const socket_address_inet* cast_from_in(const sockaddr_in* sa) { return reinterpret_cast<const socket_address_inet*>(sa); }

// The different families will be sorted according to the
// sa_family_t's numeric value.
Expand Down Expand Up @@ -164,9 +161,7 @@ class socket_address_inet {
uint16_t port_n() const { return m_sockaddr.sin_port; }
void set_port(uint16_t p) { m_sockaddr.sin_port = htons(p); }
void set_port_n(uint16_t p) { m_sockaddr.sin_port = p; }

uint32_t length() const { return sizeof(sockaddr_in); }


// Should address() return the uint32_t?
in_addr address() const { return m_sockaddr.sin_addr; }
uint32_t address_h() const { return ntohl(m_sockaddr.sin_addr.s_addr); }
Expand Down
34 changes: 0 additions & 34 deletions libtorrent/src/net/socket_datagram.cc
Original file line number Diff line number Diff line change
Expand Up @@ -86,38 +86,4 @@ SocketDatagram::write_datagram(const void* buffer, unsigned int length, rak::soc
return r;
}

int
SocketDatagram::read_datagram_inet(void* buffer, unsigned int length, rak::socket_address_inet* sa) {
if (length == 0)
throw internal_error("Tried to receive buffer length 0");

int r;
socklen_t fromlen;

if (sa != NULL) {
fromlen = sizeof(rak::socket_address);
r = ::recvfrom(m_fileDesc, buffer, length, 0, sa->c_sockaddr(), &fromlen);
} else {
r = ::recv(m_fileDesc, buffer, length, 0);
}

return r;
}

int
SocketDatagram::write_datagram_inet(const void* buffer, unsigned int length, rak::socket_address_inet* sa) {
if (length == 0)
throw internal_error("Tried to send buffer length 0");

int r;

if (sa != NULL) {
r = ::sendto(m_fileDesc, buffer, length, 0, sa->c_sockaddr(), sa->length());
} else {
r = ::send(m_fileDesc, buffer, length, 0);
}

return r;
}

}
3 changes: 0 additions & 3 deletions libtorrent/src/net/socket_datagram.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,6 @@ class SocketDatagram : public SocketBase {
// used.
int read_datagram(void* buffer, unsigned int length, rak::socket_address* sa = NULL);
int write_datagram(const void* buffer, unsigned int length, rak::socket_address* sa = NULL);

int read_datagram_inet(void* buffer, unsigned int length, rak::socket_address_inet* sa = NULL);
int write_datagram_inet(const void* buffer, unsigned int length, rak::socket_address_inet* sa = NULL);
};

}
Expand Down
6 changes: 3 additions & 3 deletions libtorrent/src/torrent/connection_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ class UdnsAsyncResolver : public AsyncResolver {
public:
UdnsAsyncResolver(ConnectionManager *cm) : AsyncResolver(cm) {}

void *enqueue(const char *name, int family, async_resolver_callback *cbck) {
void *enqueue(const char *name, int family, resolver_callback *cbck) {
return m_udnsevent.enqueue_resolve(name, family, cbck);
}

Expand All @@ -83,12 +83,12 @@ class StubAsyncResolver : public AsyncResolver {
struct mock_resolve {
std::string hostname;
int family;
async_resolver_callback *callback;
resolver_callback *callback;
};

StubAsyncResolver(ConnectionManager *cm): AsyncResolver(cm), m_connection_manager(cm) {}

void *enqueue(const char *name, int family, async_resolver_callback *cbck) {
void *enqueue(const char *name, int family, resolver_callback *cbck) {
mock_resolve *mr = new mock_resolve {name, family, cbck};
m_mock_resolve_queue.emplace_back(mr);
return mr;
Expand Down
7 changes: 3 additions & 4 deletions libtorrent/src/torrent/connection_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,7 @@ typedef std::pair<Throttle*, Throttle*> ThrottlePair;

// The sockaddr argument in the result call is NULL if the resolve failed,
// and the int holds the error code.
typedef std::function<void (const sockaddr*, int)> resolver_callback;
typedef std::function<void (const sockaddr_in*, int)> async_resolver_callback;
typedef std::function<void (const sockaddr*, int)> resolver_callback;

// Encapsulates whether we do genuine async resolution or fall back to sync.
// In a build with USE_UDNS, these do genuine asynchronous DNS resolution.
Expand All @@ -71,7 +70,7 @@ class LIBTORRENT_EXPORT AsyncResolver {
// this queues a DNS resolve but doesn't send it. it doesn't execute any callbacks
// and returns control immediately. the return value is an opaque identifier that
// can be used to cancel the query (as long as the callback hasn't been executed yet):
virtual void* enqueue(const char *name, int family, async_resolver_callback *cbck) = 0;
virtual void* enqueue(const char *name, int family, resolver_callback *cbck) = 0;
// this sends any queued resolves. it can execute arbitrary callbacks
// before returning control:
virtual void flush() = 0;
Expand Down Expand Up @@ -179,7 +178,7 @@ class LIBTORRENT_EXPORT ConnectionManager {
void set_listen_port(port_type p) { m_listen_port = p; }
void set_listen_backlog(int v);

void* enqueue_async_resolve(const char *name, int family, async_resolver_callback *cbck);
void* enqueue_async_resolve(const char *name, int family, resolver_callback *cbck);
void flush_async_resolves();
void cancel_async_resolve(void *query);

Expand Down
11 changes: 6 additions & 5 deletions libtorrent/src/tracker/tracker_udp.cc
Original file line number Diff line number Diff line change
Expand Up @@ -107,13 +107,13 @@ TrackerUdp::send_state(int state) {
}

void
TrackerUdp::start_announce(const sockaddr_in* sa, int err) {
TrackerUdp::start_announce(const sockaddr* sa, int err) {
m_resolver_query = NULL;

if (sa == NULL)
return receive_failed("could not resolve hostname");

m_connectAddress = *rak::socket_address::cast_from_in(sa);
m_connectAddress = *rak::socket_address::cast_from(sa);
m_connectAddress.set_port(m_port);

LT_LOG_TRACKER(DEBUG, "address found (address:%s)", m_connectAddress.address_str().c_str());
Expand Down Expand Up @@ -209,8 +209,9 @@ TrackerUdp::receive_timeout() {

void
TrackerUdp::event_read() {
rak::socket_address_inet sa;
int s = read_datagram_inet(m_readBuffer->begin(), m_readBuffer->reserved(), &sa);
rak::socket_address sa;

int s = read_datagram(m_readBuffer->begin(), m_readBuffer->reserved(), &sa);

if (s < 0)
return;
Expand Down Expand Up @@ -261,7 +262,7 @@ TrackerUdp::event_write() {
if (m_writeBuffer->size_end() == 0)
throw internal_error("TrackerUdp::write() called but the write buffer is empty.");

int __UNUSED s = write_datagram_inet(m_writeBuffer->begin(), m_writeBuffer->size_end(), &m_connectAddress);
int __UNUSED s = write_datagram(m_writeBuffer->begin(), m_writeBuffer->size_end(), &m_connectAddress);

manager->poll()->remove_write(this);
}
Expand Down
6 changes: 3 additions & 3 deletions libtorrent/src/tracker/tracker_udp.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ class TrackerUdp : public SocketDatagram, public Tracker {
void receive_failed(const std::string& msg);
void receive_timeout();

void start_announce(const sockaddr_in* sa, int err);
void start_announce(const sockaddr* sa, int err);

void prepare_connect_input();
void prepare_announce_input();
Expand All @@ -93,13 +93,13 @@ class TrackerUdp : public SocketDatagram, public Tracker {

bool parse_udp_url(const std::string& url, hostname_type& hostname, int& port) const;

rak::socket_address_inet m_connectAddress;
rak::socket_address m_connectAddress;
int m_port;
std::string m_hostname;

int m_sendState;

async_resolver_callback m_resolver_callback;
resolver_callback m_resolver_callback;
void* m_resolver_query;

uint32_t m_action;
Expand Down
45 changes: 43 additions & 2 deletions libtorrent/src/utils/udnsevent.cc
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,37 @@ void a4_callback_wrapper(struct ::dns_ctx *ctx, ::dns_rr_a4 *result, void *data)
if (query->a6_query != NULL) {
::dns_cancel(ctx, query->a6_query);
}
if (*query->callback) { (*query->callback)(static_cast<sockaddr_in*>(&sa), 0); }
if (*query->callback) { (*query->callback)(reinterpret_cast<sockaddr_in*>(&sa), 0); }
delete query;
}
}

void a6_callback_wrapper(struct ::dns_ctx *ctx, ::dns_rr_a6 *result, void *data) {
struct sockaddr_in6 sa;
udns_query *query = static_cast<udns_query*>(data);
// udns will free the a6_query after this callback exits
query->a6_query = NULL;

if (result == NULL || result->dnsa6_nrr == 0) {
if (query->a4_query == NULL) {
// nothing more to do: call the callback with a failure status
(*(query->callback))(NULL, udnserror_to_gaierror(::dns_status(ctx)));
delete query;
}
// else: return and wait to see if we get an a6 response
} else {
sa.sin6_family = AF_INET6;
sa.sin6_port = 0;
sa.sin6_addr = result->dnsa6_addr[0];
if (query->a4_query != NULL) {
::dns_cancel(ctx, query->a4_query);
}
(*query->callback)(reinterpret_cast<sockaddr*>(&sa), 0);
delete query;
}
}


UdnsEvent::UdnsEvent() {
// reinitialize the default context, no-op
// TODO don't do this here --- do it once in the manager, or in rtorrent
Expand Down Expand Up @@ -95,7 +121,7 @@ void UdnsEvent::event_write() {
void UdnsEvent::event_error() {
}

struct udns_query *UdnsEvent::enqueue_resolve(const char *name, int family, async_resolver_callback *callback) {
struct udns_query *UdnsEvent::enqueue_resolve(const char *name, int family, resolver_callback *callback) {
struct udns_query *query = new udns_query { NULL, NULL, callback, 0 };

if (family == AF_INET || family == AF_UNSPEC) {
Expand All @@ -117,6 +143,21 @@ struct udns_query *UdnsEvent::enqueue_resolve(const char *name, int family, asyn
}
}

if (family == AF_INET6) {
query->a6_query = ::dns_submit_a6(m_ctx, name, 0, a6_callback_wrapper, query);
if (query->a6_query == NULL) {
// it should be impossible for dns_submit_a6 to fail if dns_submit_a4
// succeeded, but just in case, make it a hard failure:
if (::dns_status(m_ctx) == DNS_E_BADQUERY && query->a4_query == NULL) {
query->error = EAI_NONAME;
m_malformed_queries.push_back(query);
return query;
} else {
throw new internal_error("dns_submit_a6 failed");
}
}
}

return query;
}

Expand Down
4 changes: 2 additions & 2 deletions libtorrent/src/utils/udnsevent.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ namespace torrent {
struct udns_query {
::dns_query *a4_query;
::dns_query *a6_query;
async_resolver_callback *callback;
resolver_callback *callback;
int error;
};

Expand All @@ -37,7 +37,7 @@ class UdnsEvent : public Event {

// wraps udns's dns_submit_a[46] functions. they and it return control immediately,
// without either sending outgoing UDP packets or executing callbacks:
udns_query* enqueue_resolve(const char *name, int family, async_resolver_callback *callback);
udns_query* enqueue_resolve(const char *name, int family, resolver_callback *callback);
// wraps the dns_timeouts function. it sends packets and can execute arbitrary
// callbacks:
void flush_resolves();
Expand Down

0 comments on commit 7f12473

Please sign in to comment.