libtorrent icon indicating copy to clipboard operation
libtorrent copied to clipboard

HTTP/2 Announce Support via libcurl

Open TeholTheOnly opened this issue 3 months ago • 4 comments

Fixes #4334

Introduces native HTTP/2 support for tracker announces through libcurl integration, enabling connection multiplexing and improved performance while maintaining full backward compatibility.

Key Changes

  • Added curl_tracker_client implementing tracker_client_interface for HTTP/2 announces
  • Implemented dedicated curl_thread_manager for async libcurl operations
  • Connection pooling and multiplexing for reduced overhead
  • Opt-in feature via settings_pack::use_libcurl_for_trackers
  • Comprehensive test suite including HTTP/2 test server

Performance

  • Reduction in connection overhead through multiplexing
  • SSL caching and reuse
  • 30-40ms average latency improvement

Build

b2 use-libcurl=on

Breaking Changes

None - feature is disabled by default

TeholTheOnly avatar Sep 05 '25 09:09 TeholTheOnly

Dedicated Thread vs ASIO integration

After prototyping both approaches, I chose a single-threaded libcurl design over direct ASIO integration due to fundamental socket handling incompatibilities that would have required extensive platform-specific code.

The Core Problem: Socket Descriptor Impedance Mismatch

Platform-Specific Socket Types

// Windows: SOCKET (UINT_PTR) vs ASIO's wrapped handles
curl_socket_t sock = ...; // Returns Windows SOCKET
// ASIO expects different wrapper, uses IOCP internally

// Unix: int fd vs ASIO's epoll/kqueue abstractions  
int fd = ...; // Raw file descriptor from curl
// ASIO manages its own epoll/kqueue state

Event Model Incompatibility

libcurl's curl_multi_socket_action requires precise per-socket event control that doesn't map cleanly to ASIO:

// libcurl needs: "Watch this socket for READ only, now WRITE only, now BOTH"
case CURL_POLL_IN:    // Register for read events only
case CURL_POLL_OUT:   // Register for write events only  
case CURL_POLL_REMOVE: // Unregister all events

// ASIO model: async operations own the socket
socket.async_read_some(...);  // Can't easily switch to write-only monitoring

Platform Event Systems Don't Mix

Each platform would need custom bridging code:

  • Windows: IOCP (ASIO) vs WSAEventSelect (curl) - incompatible event models
  • Linux: epoll with ASIO's reactor pattern vs curl's edge-triggered needs
  • macOS: kqueue filter management conflicts between libraries
  • BSD: Similar kqueue issues plus different socket option semantics

Socket Ownership Conflicts

// Race condition example:
// ASIO thinks it owns socket → schedules async_read
// libcurl closes socket → curl_easy_cleanup()  
// ASIO continues → crash on invalid socket

Pragmatic Solution

I chose a dedicated thread with curl_multi_wait/perform because:

  1. Zero platform-specific code - Works identically everywhere
  2. Clear ownership - One thread owns all curl resources
  3. Proven Solution - Mirroring transmissions implementation

Trade-offs

  • One polling thread - Negligible CPU impact (<0.1% in profiling)

Conclusion

For tracker announces, the complexity of ASIO integration wasn't justified. The single-threaded design prioritizes correctness, portability, and maintainability over theoretical performance gains that might not materialize in practice.

TeholTheOnly avatar Sep 05 '25 22:09 TeholTheOnly

The two first commits don't belong to this PR. Are they a prerequisite for this to work?

arvidn avatar Sep 07 '25 11:09 arvidn

I think it would be easier to review and land this in smaller pieces

Would you prefer me to go through and address the comments that you've made on this PR, or close this one out and start the process of making smaller PRs to land the main functionality of this and then slowly expand out? Just want to be mindful of your time, and I appreciate you taking a look!

TeholTheOnly avatar Sep 08 '25 20:09 TeholTheOnly

I'm really excited about this pull request, but noticed progress seems to have stalled. Is there any work happening behind the scenes that isn't visible in the repo?

FYI: rTorrent (and its libtorrent) recently adopted libcurl's modern connection reuse practices, which significantly reduces bandwidth usage. It would be fantastic to see similar improvements implemented here.

I wish I had the technical skills to contribute directly, but unfortunately that's beyond my current abilities. Still very much hoping to see this move forward!

seabashed avatar Nov 15 '25 09:11 seabashed