30 Commits

Author SHA1 Message Date
Darren Horrocks 58052ec8ee 4.0 D6: rename Metadata.Load(BDict) + portable path separator
- Rename the misleadingly-overloaded Load(BDict) to LoadInfoDictionary (it loads the
  info dictionary, e.g. from ut_metadata), distinct from Load(Stream)/Load(MagnetLink).
  Demo updated.
- MetadataFileInfo.PathSeparator: '\' -> '/' (portable, BitTorrent/URL convention;
  the old Windows-only backslash could also collide with a real path component).

The disk-based-build responsibility (the genuinely separable concern flagged for the
'split') was already extracted to TorrentBuilder in Phase 10; the remaining parse
populates the Metadata value object itself, so a separate parser type reaching into
its internals would be ceremony rather than real separation -- not done.

Breaking: Metadata.Load(BDict) -> LoadInfoDictionary; Filename uses '/'. Suite green (187).
2026-07-04 00:11:36 +01:00
Darren Horrocks 6828f676c3 4.0 D4: replace 11-parameter Announce with AnnounceRequest options object
The 11-positional-parameter Announce was hard to call correctly and the HTTP
client silently ignored several of its parameters. Replaced with an AnnounceRequest
options object (sensible defaults for Event/NumWant/ListenPort) honored consistently.
Demo + tracker tests updated.

Breaking: ITrackerClient.Announce(url,hash,peerId,...11 args) -> Announce(AnnounceRequest).
Suite green (187).
2026-07-04 00:06:33 +01:00
Darren Horrocks 9a4bcdf3f6 4.0 D3: promote AnnounceInfo/ScrapeInfo to top-level types
They were nested in BaseScraper, forcing ITrackerClient to depend on the concrete
base class. Now top-level types owned by ITrackerClient. ScrapeInfo's
ScraperType-switched ctor (positional a,b,c leaving half the fields zero) becomes
named ScrapeInfo.FromHttp/FromUdp factories. Demo updated. Suite green (187).
2026-07-04 00:01:23 +01:00
Darren Horrocks 7c64ae8c50 Phase 3.2 / deferred Phase 2: split UTPSocket into UTPConnection + UTPListener
Eliminates the 758-line UTPSocket god class that fused two fundamentally
different roles (listener vs data socket) behind isListening/isServerChild flags.

- UTPConnection (IO/UTPConnection.cs): the data-transfer connection — client
  (owns socket + own receive loop) or accepted child (shares the listener's
  socket, fed via HandleIncomingPacket). Connect/Send/Receive/BeginReceive,
  reliability (retransmit/reorder/ack), MSE-friendly synchronous Receive pump.
- UTPListener (IO/UTPListener.cs): passive open — Listen/Accept, the demux loop,
  activeChildren registry, accept-waiter registration; creates UTPConnection
  children and routes datagrams to them.
- PacketType promoted to top-level UTPPacketType (IO/UTPPacketType.cs); refs in
  UTPPacketCodec, UTPRetransmissionTracker and tests updated.
- UTPSocket.cs deleted. Demo uses UTPConnection (client); passive-open tests use
  UTPListener + UTPConnection.

Logic moved verbatim (not rewritten) to preserve the validated wire behaviour.
The inherent client-vs-accepted-child duality remains inside UTPConnection (uTP
shares one UDP socket across a listener's accepted connections). Validated
against the real two-instance loopback e2e tests. Full suite green (176; 39 UTP).

Note: the ISocket interface-segregation + socket-factory portion of Phase 3 was
NOT done — MSE (6 ISocket signatures), PeerWireConnection and LocalPeerDiscovery
are deeply coupled to the fat ISocket, making that a wide, high-risk rewrite for
mostly-structural gain. The concrete LSP defect it targeted was already fixed in
Phase 3.0. See plan.md.
2026-07-03 20:51:39 +01:00
Darren Horrocks 819e7cfa18 Add BEP-55 holepunch extension
UTHolepunchExtension implements ut_holepunch (Rendezvous/Connect/Error
messages) as an IBTExtension, same scope as the other extensions
(UTPeerExchange etc): wire format, send methods, and events only — the
consumer decides when to rendezvous, tracks which peers are connected to
whom, and retries the connection. Registered in the Demo app alongside
PEX/tracker-exchange/metadata.

The payload byte layout is implemented to the best available
understanding of BEP-55 (msg_type, addr_type, address, port, and an
error_code for the Error variant) — flagged in both the code and README
for verification against the published BEP text before relying on it for
interop, the same caveat already applied to this library's other
experimental pieces (uTP).

Tested via a real PeerWireClient + ExtendedProtocolExtensions +
FakePeerConnection (the pattern the existing PeerWireClient integration
tests use — no mocking framework, matches project convention): send-path
wire format, decode of Rendezvous/Connect/Error messages, and an
encode/decode round-trip through the extension's own logic. Live-verified
via Demo against real DHT/tracker peers for the ubuntu torrent fixture for
45s with the extension registered — handshakes completed normally and no
exceptions; no peer happened to trigger an actual holepunch exchange in
this window (expected — it needs a specific NAT-traversal scenario), but
that's consistent with this task's scope being the protocol plumbing, not
guaranteed real-peer interop.
2026-07-02 22:35:04 +01:00
Darren Horrocks 2f3c46b8a5 Add RTO-based retransmission and out-of-order delivery to UTPSocket
Extracts the retransmission/reordering logic into two pure, socket-free
classes (UTPRetransmissionTracker, UTPReorderBuffer) following the same
pattern already used for UTPCongestionControl, so the algorithms are
deterministically unit-testable without real sockets or timers:

- UTPRetransmissionTracker: tracks in-flight packets, RTO via
  Jacobson/Karels RTT estimation, exponential backoff, Karn's algorithm
  (no RTT sample from retransmitted packets), gives up after
  MaxRetransmits.
- UTPReorderBuffer: buffers ST_DATA packets that arrive ahead of a gap and
  releases them in order once the gap fills, replacing the previous
  "blindly advance ack to whatever arrives" logic.

UTPSocket wires these in: a Timer drives periodic retransmission
independent of inbound traffic, and BeginReceive/EndReceive were reworked
so out-of-order packets are buffered rather than delivered immediately,
with a delivery queue draining reassembled-in-order payloads on
subsequent calls.

Verified: dotnet test (120 passing, including 16 new deterministic tests),
plus a live run via a new Demo -utp flag against real DHT/tracker peers
for Demo/TestTorrents/ubuntu-26.04-desktop-amd64.iso.torrent — ran cleanly
for 45s with no exceptions across 6 real peer connection attempts. No real
peer completed the uTP handshake; this traces to a separate, pre-existing
gap (UTPSocket has no passive-open/listener support — Listen/Accept are
TCP-shaped stubs that don't work for a UDP transport), not a regression
from this change. Documented in the README's existing uTP experimental
note.
2026-07-02 22:16:48 +01:00
Darren Horrocks d128574e29 final mse/pe changes 2026-07-01 15:16:54 +01:00
Darren Horrocks 49429c47a9 fix mse/pe 2026-07-01 14:28:41 +01:00
Darren Horrocks 839aaab485 MSE/PE work in progress 2026-07-01 12:50:16 +01:00
Darren Horrocks b94ae5e95f various correctness fixes and updates to the demo project 2026-07-01 12:17:43 +01:00
Darren Horrocks 800f207bc0 multiple fixes, added dht. updated demo and updated demo to work with a torrent that ubuntu still supports. Demo works as a bittorrent client 2026-06-28 23:26:00 +01:00
Darren Horrocks eb3d94941b large refactor 2025-11-13 00:15:11 +00:00
Darren Horrocks 4786ef67aa Local peer discovery converted to use ISocket 2023-11-06 21:53:21 +00:00
Darren Horrocks 74e174a245 waning message 2023-11-04 21:13:35 +00:00
Darren Horrocks dbe6ff1a87 WIP: peer wire connections are now a single connection. sockets denote the protocol 2023-11-02 23:20:36 +00:00
Darren Horrocks acdeab461c utpsocket implementation 2023-10-29 23:41:41 +00:00
Darren Horrocks eeb45e2769 updates to test/demo app 2023-10-23 21:41:24 +01:00
Darren Horrocks 061682209f slightly expanded demo app that connects to a peer 2023-10-15 23:42:18 +01:00
Darren Horrocks c232625bcf switched to 2.0 for use in more frameworks, and some tidying up 2023-10-04 13:11:33 +01:00
Darren Horrocks 99aff9f4f0 re-change the demo 2021-10-21 18:49:20 +01:00
Darren Horrocks 0263e01736 basic (working) implementation of uTP 2021-09-28 21:52:42 +01:00
Darren Horrocks bc9222e984 send keep-alive to remote peer once per minute 2021-09-21 23:33:23 +01:00
Darren Horrocks 4b6cc0f1c6 rename solution, project and namespace, and add default namespaces back in 2021-09-20 19:20:25 +01:00
Darren Horrocks e70e3dfb76 completed ability to send peer wire packets 2021-09-19 23:08:57 +01:00
Darren Horrocks 551f0dc2af ability to handshake and parse incoming buffer into individual peer wire packets and consume peer wire packets 2021-09-19 18:19:20 +01:00
Darren Horrocks 41a35d01fd added handshake dto and ability to handshake via the new connection logic 2021-09-19 00:22:17 +01:00
Darren Horrocks 00465dd4ff basic example on how to connect via tcp 2021-09-06 23:40:34 +01:00
Darren Horrocks e682256b53 udp demos 2021-09-04 19:48:53 +01:00
Russell Webster f1ad47c1c7 Tidy up demo
Add unit test project
Add unit tests for PackHelper
2021-07-24 15:27:49 +01:00
Darren Horrocks 96362c8c16 basic demos 2018-07-13 23:32:02 +01:00