Skip to content

Commit

Permalink
libtorrent: Optimize UDP trackers for UDNS (#41)
Browse files Browse the repository at this point in the history
This commit optimizes UDP trackers with a fast path to ipv4 sockets. When using UDNS, we know the address is going to resolve to IPV4. We can skip a few checks to increase performance.
  • Loading branch information
stickz authored Jul 20, 2024
1 parent 5517bef commit b51727c
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 2 deletions.
14 changes: 12 additions & 2 deletions libtorrent/src/net/socket_datagram.cc
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,9 @@ SocketDatagram::read_datagram(void* buffer, unsigned int length, rak::socket_add
throw internal_error("Tried to receive buffer length 0");

int r;
socklen_t fromlen;

if (sa != NULL) {
fromlen = sizeof(rak::socket_address);
socklen_t fromlen = sizeof(rak::socket_address);
r = ::recvfrom(m_fileDesc, buffer, length, 0, sa->c_sockaddr(), &fromlen);
} else {
r = ::recv(m_fileDesc, buffer, length, 0);
Expand Down Expand Up @@ -86,4 +85,15 @@ SocketDatagram::write_datagram(const void* buffer, unsigned int length, rak::soc
return r;
}

#ifdef USE_UDNS
int
SocketDatagram::write_datagram_ipv4(const void* buffer, unsigned int length, rak::socket_address* sa) {
if (length == 0)
throw internal_error("Tried to send buffer length 0");

return sa != NULL ? ::sendto(m_fileDesc, buffer, length, 0, sa->c_sockaddr(), sa->length())
: ::send(m_fileDesc, buffer, length, 0);
}
#endif

}
3 changes: 3 additions & 0 deletions libtorrent/src/net/socket_datagram.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ 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);
#ifdef USE_UDNS
int write_datagram_ipv4(const void* buffer, unsigned int length, rak::socket_address* sa = NULL);
#endif
};

}
Expand Down
17 changes: 17 additions & 0 deletions libtorrent/src/net/socket_fd.cc
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,14 @@ SocketFd::open_datagram() {
return true;
}

#ifdef USE_UDNS
bool
SocketFd::open_datagram_ipv4() {
m_ipv6_socket = false;
return (m_fd = socket(rak::socket_address::pf_inet, SOCK_DGRAM, 0)) != -1;
}
#endif

bool
SocketFd::open_local() {
return (m_fd = socket(rak::socket_address::pf_local, SOCK_STREAM, 0)) != -1;
Expand Down Expand Up @@ -198,6 +206,15 @@ SocketFd::bind(const rak::socket_address& sa) {
return !::bind(m_fd, sa.c_sockaddr(), sa.length());
}

#ifdef USE_UDNS
bool
SocketFd::bind_ipv4(const rak::socket_address& sa) {
check_valid();

return !::bind(m_fd, sa.c_sockaddr(), sa.length());
}
#endif

bool
SocketFd::bind(const rak::socket_address& sa, unsigned int length) {
check_valid();
Expand Down
8 changes: 8 additions & 0 deletions libtorrent/src/net/socket_fd.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ class SocketFd {
bool open_stream();
bool open_datagram();
bool open_local();

#ifdef USE_UDNS
bool open_datagram_ipv4();
#endif

static bool open_socket_pair(int& fd1, int& fd2);

Expand All @@ -82,6 +86,10 @@ class SocketFd {
bool bind(const rak::socket_address& sa, unsigned int length);
bool connect(const rak::socket_address& sa);
bool getsockname(rak::socket_address* sa);

#ifdef USE_UDNS
bool bind_ipv4(const rak::socket_address& sa);
#endif

bool listen(int size);
SocketFd accept(rak::socket_address* sa);
Expand Down
12 changes: 12 additions & 0 deletions libtorrent/src/tracker/tracker_udp.cc
Original file line number Diff line number Diff line change
Expand Up @@ -136,12 +136,20 @@ TrackerUdp::start_announce(const sockaddr* sa, int err) {
return receive_failed("invalid tracker address");

// TODO: Make each of these a separate error... at the very least separate open and bind.
#ifdef USE_UDNS
if (!get_fd().open_datagram_ipv4() || !get_fd().set_nonblock())
#else
if (!get_fd().open_datagram() || !get_fd().set_nonblock())
#endif
return receive_failed("could not open UDP socket");

auto bind_address = rak::socket_address::cast_from(manager->connection_manager()->bind_address());

#ifdef USE_UDNS
if (bind_address->is_bindable() && !get_fd().bind_ipv4(*bind_address))
#else
if (bind_address->is_bindable() && !get_fd().bind(*bind_address))
#endif
return receive_failed("failed to bind socket to udp address '" + bind_address->pretty_address_str() + "' with error '" + rak::error_number::current().c_str() + "'");

m_readBuffer = new ReadBuffer;
Expand Down Expand Up @@ -276,7 +284,11 @@ TrackerUdp::event_write() {
if (m_writeBuffer->size_end() == 0)
throw internal_error("TrackerUdp::write() called but the write buffer is empty.");

#ifdef USE_UDNS
int __UNUSED s = write_datagram_ipv4(m_writeBuffer->begin(), m_writeBuffer->size_end(), &m_connectAddress);
#else
int __UNUSED s = write_datagram(m_writeBuffer->begin(), m_writeBuffer->size_end(), &m_connectAddress);
#endif

manager->poll()->remove_write(this);
}
Expand Down

0 comments on commit b51727c

Please sign in to comment.