librats 2.3.3 → 2.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,400 @@
1
+ #pragma once
2
+
3
+ /**
4
+ * @file utp_stream.h
5
+ * @brief One uTP connection (BEP 29): an ordered, reliable, delay-controlled byte
6
+ * stream over datagrams.
7
+ *
8
+ * uTP is what most of the swarm now speaks. It exists for one reason: a BitTorrent
9
+ * client saturating an uplink with TCP starves everything else on the same line —
10
+ * VoIP, SSH, the web page the user is reading — because TCP only backs off once a
11
+ * router has already filled its queue and started dropping. uTP measures the
12
+ * *one-way delay* instead and backs off as soon as the queue starts growing, so it
13
+ * yields to any TCP flow sharing the path. That is the whole design, and it is why
14
+ * `wnd_size` is in bytes, why every packet carries two timestamps, and why the
15
+ * congestion controller (LEDBAT, RFC 6817) targets 100 ms of queuing delay rather
16
+ * than a loss event.
17
+ *
18
+ * ## What this is not
19
+ *
20
+ * The library already has a reliable-UDP transport (`transport/udp_stream.h`) for
21
+ * the node's own mesh. This is a *second* one, deliberately: that one is ours to
22
+ * design, this one has to be bit-compatible with uTorrent and libtorrent or it is
23
+ * worthless. They share no code, and per the project's layering BitTorrent never
24
+ * reaches into `transport/`.
25
+ *
26
+ * ## Structure
27
+ *
28
+ * A Stream has no socket, no thread and no locks: it is driven entirely by
29
+ * `on_packet()` and `tick()` and emits datagrams through its `Host`, exactly like
30
+ * `dht::Node` is driven by `on_datagram()`. The Host (utp_manager.h) owns the one
31
+ * shared UDP socket and demultiplexes to us. Everything lives on the BitTorrent
32
+ * reactor thread.
33
+ *
34
+ * Reads and writes mirror non-blocking socket semantics, because that is what the
35
+ * layer above (`PeerLink` → `PeerConnection`) is written against: `write()` takes
36
+ * what it can and reports WouldBlock; `read()` drains what has arrived in order and
37
+ * reports Eof once the peer's FIN has been reached.
38
+ *
39
+ * ## Connection ids
40
+ *
41
+ * Each direction has its own 16-bit id, and the pair is always adjacent. The
42
+ * initiator picks `recv_id` at random and uses `send_id = recv_id + 1`; the SYN
43
+ * itself is sent carrying `recv_id` — that is, the id the initiator expects the
44
+ * *answer* on, which is the one genuinely surprising thing about the uTP handshake.
45
+ * The responder reads that id, and takes `send_id = id`, `recv_id = id + 1`.
46
+ *
47
+ * ## What is not implemented (on purpose)
48
+ *
49
+ * - **Path-MTU discovery.** libtorrent probes upwards from a floor. We instead fix
50
+ * the payload at a size that fits inside IPv6's 1280-byte minimum MTU, so no path
51
+ * can fragment us. That costs some throughput on a 1500-byte path and buys
52
+ * immunity to the whole class of black-holed-fragment failures.
53
+ * - **The close-reason extension** (type 3). Parsed past, never acted on: it is a
54
+ * diagnostic uTorrent emits, and nothing downstream of us would use it.
55
+ * - **Delayed-ACK timers.** Acks are deferred only to the end of the current socket
56
+ * drain (see Host::utp_defer_ack), never on a timer, so we never sit on an ack the
57
+ * sender's congestion control is waiting for.
58
+ */
59
+
60
+ #include "librats/bittorrent/utp_packet.h"
61
+ #include "librats/core/address.h"
62
+ #include "librats/core/bytes.h"
63
+
64
+ #include <chrono>
65
+ #include <cstdint>
66
+ #include <deque>
67
+ #include <string>
68
+ #include <unordered_map>
69
+
70
+ namespace librats::bittorrent::utp {
71
+
72
+ // ---- Tunables, all matching libtorrent's shipping defaults --------------------
73
+
74
+ /// LEDBAT's target queuing delay. Above it we shrink the window, below it we grow:
75
+ /// this single number is what makes uTP yield to TCP rather than compete with it.
76
+ constexpr int kTargetDelayUs = 100 * 1000;
77
+ /// How aggressively the window follows the delay signal (`utp_gain_factor`).
78
+ constexpr int kGainFactor = 3000;
79
+ /// Floor on the retransmit timeout, so a very short RTT can't produce a hair
80
+ /// trigger that mistakes reordering for loss.
81
+ constexpr int kMinTimeoutMs = 500;
82
+ /// Timeout for the SYN, where there is no RTT estimate to base one on.
83
+ constexpr int kConnectTimeoutMs = 3000;
84
+ /// Retransmission budgets before the connection is declared dead.
85
+ constexpr int kSynResends = 2;
86
+ constexpr int kFinResends = 2;
87
+ constexpr int kNumResends = 3;
88
+ /// What fraction (percent) of the window survives a loss event.
89
+ constexpr int kLossMultiplier = 50;
90
+ /// The window is cut at most once per this interval, so a burst of losses inside
91
+ /// one round trip is charged once rather than collapsing the window to nothing.
92
+ constexpr int kCwndReduceTimerMs = 100;
93
+ /// Duplicate acks that trigger a fast retransmit.
94
+ constexpr int kDupAckLimit = 3;
95
+
96
+ /// In-order bytes we will hold for a reader that has not drained us, and therefore
97
+ /// the largest window we ever advertise. Also the ceiling on throughput: this many
98
+ /// bytes per RTT, i.e. ~20 Mbit/s per peer at 100 ms — far more than a single peer
99
+ /// in a swarm ever supplies, and small enough that a few hundred connections cannot
100
+ /// add up to anything alarming (the buffer is grown on demand, not preallocated).
101
+ constexpr std::size_t kRecvBufferCapacity = 256 * 1024;
102
+
103
+ /// Bytes the writer may queue ahead of what the window will pass. Backpressure
104
+ /// above this is reported as WouldBlock and handled by the layer above, which
105
+ /// already has a send queue and a high-water mark of its own.
106
+ constexpr std::size_t kSendHighWater = 256 * 1024;
107
+
108
+ /// How long a closed stream is kept around to retransmit its FIN and absorb the
109
+ /// peer's last packets before the manager reaps it.
110
+ constexpr std::chrono::milliseconds kLinger{3000};
111
+
112
+ // ---- Delay history -----------------------------------------------------------
113
+
114
+ /**
115
+ * The lowest delay sample seen recently, used as the zero point for the delay
116
+ * measurements LEDBAT runs on.
117
+ *
118
+ * The two endpoints' clocks are unrelated, so a raw one-way delay sample is a
119
+ * meaningless number — but the *difference* between it and the smallest such
120
+ * sample is real queuing delay. The base has to be able to rise as well as fall or
121
+ * clock drift would slowly convince us the path is permanently congested, hence the ring of
122
+ * per-minute minima rather than a single running minimum. Ported from libtorrent's
123
+ * timestamp_history.
124
+ */
125
+ class DelayHistory {
126
+ public:
127
+ static constexpr int kHistorySize = 20; ///< minutes of history
128
+
129
+ bool initialized() const noexcept { return num_samples_ != kNotInitialized; }
130
+ /// Record a sample and return it relative to the base. @p step advances the
131
+ /// ring (called once a minute).
132
+ std::uint32_t add_sample(std::uint32_t sample, bool step);
133
+ std::uint32_t base() const noexcept { return base_; }
134
+ /// Shift the whole history, to compensate for observed clock drift.
135
+ void adjust_base(int change);
136
+
137
+ private:
138
+ static constexpr std::uint16_t kNotInitialized = 0xffff;
139
+
140
+ std::uint32_t history_[kHistorySize] = {};
141
+ std::uint32_t base_ = 0;
142
+ std::uint16_t index_ = 0;
143
+ std::uint16_t num_samples_ = kNotInitialized;
144
+ };
145
+
146
+ /// Exponential moving average with a companion average deviation, in the fixed-point
147
+ /// form libtorrent uses for its RTT estimator (RFC 6298's SRTT/RTTVAR by another name).
148
+ class SlidingAverage {
149
+ public:
150
+ void add_sample(int s);
151
+ int mean() const noexcept { return num_samples_ > 0 ? (mean_ + 32) / 64 : 0; }
152
+ int avg_deviation() const noexcept { return num_samples_ > 1 ? (deviation_ + 32) / 64 : 0; }
153
+ int num_samples() const noexcept { return num_samples_; }
154
+
155
+ private:
156
+ static constexpr int kInvertedGain = 16;
157
+ int mean_ = 0; ///< fixed point, x64
158
+ int deviation_ = 0; ///< fixed point, x64
159
+ int num_samples_ = 0;
160
+ };
161
+
162
+ // ---- The stream --------------------------------------------------------------
163
+
164
+ class Stream;
165
+
166
+ /// What a Stream needs from whoever owns the socket. Implemented by utp::Manager.
167
+ class Host {
168
+ public:
169
+ virtual ~Host() = default;
170
+ /// Put one datagram on the wire. Failures are the Host's to swallow — a stream
171
+ /// treats a datagram as sent, and its own retransmit timer as the recovery path.
172
+ virtual void utp_send(const Address& to, const std::uint8_t* data, std::size_t len) = 0;
173
+ /// Ask to be called back at Stream::send_deferred_ack() once the socket's
174
+ /// current receive burst has been fully drained, so a burst of N data packets
175
+ /// costs one ack instead of N.
176
+ virtual void utp_defer_ack(Stream& s) = 0;
177
+ };
178
+
179
+ class Stream {
180
+ public:
181
+ using Clock = std::chrono::steady_clock;
182
+
183
+ enum class State : std::uint8_t {
184
+ Idle, ///< created, nothing sent (a responder before its SYN arrives)
185
+ SynSent, ///< initiator waiting for the SYN-ack
186
+ Connected, ///< data may flow
187
+ FinSent, ///< our side is done sending; still acking theirs
188
+ Closed, ///< dead: reaped by the manager
189
+ };
190
+
191
+ enum class Status : std::uint8_t { Ok, WouldBlock, Eof, Error };
192
+ struct IoResult {
193
+ std::size_t bytes = 0;
194
+ Status status = Status::WouldBlock;
195
+ };
196
+
197
+ /// All callbacks fire on the reactor thread, from inside on_packet()/tick().
198
+ /// An observer may close the stream from within one; it must not delete it
199
+ /// (the manager owns streams and reaps them between callbacks).
200
+ struct Observer {
201
+ virtual ~Observer() = default;
202
+ virtual void on_utp_connected() {}
203
+ virtual void on_utp_readable() {}
204
+ virtual void on_utp_writable() {}
205
+ /// The connection died on its own: reset, timeout, protocol error. An
206
+ /// orderly close by the peer is *not* reported here — it surfaces as Eof
207
+ /// from read(), exactly as a TCP recv() of 0 would.
208
+ virtual void on_utp_error(const std::string& why) {}
209
+ };
210
+
211
+ Stream(Host& host, std::uint16_t recv_id, std::uint16_t send_id);
212
+ ~Stream() = default;
213
+
214
+ Stream(const Stream&) = delete;
215
+ Stream& operator=(const Stream&) = delete;
216
+
217
+ void set_observer(Observer* o) noexcept { obs_ = o; }
218
+ /// Does a live user object still own this stream? The manager reaps only
219
+ /// streams nobody is holding.
220
+ bool has_observer() const noexcept { return obs_ != nullptr; }
221
+ /// The user object is going away. Stop delivering callbacks; keep enough state
222
+ /// alive to finish the close handshake.
223
+ void detach() noexcept { obs_ = nullptr; }
224
+
225
+ /// Start an outgoing connection: sends the SYN.
226
+ void connect(const Address& to, Clock::time_point now);
227
+
228
+ /// Drain in-order received bytes. Eof once the peer's FIN has been reached and
229
+ /// everything before it delivered.
230
+ IoResult read(ByteSpan into);
231
+ /// Queue bytes for transmission, taking as many as the send buffer will hold.
232
+ IoResult write(const ByteView* slices, std::size_t count, Clock::time_point now);
233
+ /// Orderly shutdown: flush what is queued, then FIN. Idempotent.
234
+ void close(Clock::time_point now);
235
+ /// Abort: tell the peer the connection is gone and stop immediately.
236
+ void reset(Clock::time_point now);
237
+
238
+ /// Feed one datagram addressed to this stream. Returns false if it was
239
+ /// malformed or did not belong here (the caller may then look elsewhere).
240
+ bool on_packet(const std::uint8_t* data, std::size_t len,
241
+ const Address& from, Clock::time_point now);
242
+ /// Periodic timer: retransmissions, timeouts, linger expiry.
243
+ void tick(Clock::time_point now);
244
+ /// Emit the acknowledgement that on_packet() deferred (see Host::utp_defer_ack).
245
+ void send_deferred_ack(Clock::time_point now);
246
+
247
+ // ---- state ----
248
+ std::uint16_t recv_id() const noexcept { return recv_id_; }
249
+ std::uint16_t send_id() const noexcept { return send_id_; }
250
+ const Address& remote() const noexcept { return remote_; }
251
+ State state() const noexcept { return state_; }
252
+ bool connected() const noexcept { return state_ == State::Connected || state_ == State::FinSent; }
253
+ /// True once nothing more will happen here and the manager may destroy it.
254
+ bool reapable(Clock::time_point now) const noexcept;
255
+ /// Does this datagram belong to this stream? Both the id and the sender must
256
+ /// match, so a third party cannot inject into a connection by guessing an id.
257
+ bool matches(const Address& from, std::uint16_t id) const noexcept {
258
+ return id == recv_id_ && from == remote_;
259
+ }
260
+
261
+ // ---- introspection, for tests and logging ----
262
+ std::size_t bytes_in_flight() const noexcept { return bytes_in_flight_; }
263
+ std::size_t send_queue_bytes() const noexcept { return pending_bytes_ + bytes_in_flight_; }
264
+ std::uint32_t cwnd() const noexcept { return std::uint32_t(cwnd_ >> 16); }
265
+ std::uint16_t seq_nr() const noexcept { return seq_nr_; }
266
+ std::uint16_t ack_nr() const noexcept { return ack_nr_; }
267
+
268
+ private:
269
+ /// One packet we have sent and not yet had acknowledged. The payload is kept
270
+ /// (not the datagram): every transmission rebuilds the header, so a retransmit
271
+ /// carries an up-to-date ack_nr, window and SACK rather than a stale snapshot.
272
+ struct OutPacket {
273
+ std::uint16_t seq = 0;
274
+ PacketType type = PacketType::Data;
275
+ Bytes payload;
276
+ Clock::time_point send_time{};
277
+ std::uint16_t transmissions = 0;
278
+ bool acked = false;
279
+ bool in_flight = false; ///< counted in bytes_in_flight_
280
+ };
281
+
282
+ // ---- sending ----
283
+ void send_syn(Clock::time_point now);
284
+ void send_state(Clock::time_point now); ///< a pure ack
285
+ void send_reset_packet(Clock::time_point now);
286
+ /// Build and transmit one packet from outbuf_, (re)writing its header.
287
+ void transmit(OutPacket& p, Clock::time_point now);
288
+ /// Move as much of pending_ into flight as the windows allow.
289
+ void pump(Clock::time_point now);
290
+ /// Assemble a datagram into scratch_ and hand it to the host.
291
+ void emit(PacketType type, std::uint16_t seq, const std::uint8_t* payload,
292
+ std::size_t payload_len, Clock::time_point now, bool with_sack);
293
+ std::size_t write_sack(std::uint8_t* out) const;
294
+ bool has_sack() const noexcept { return !inbuf_.empty(); }
295
+ /// Register with the host for one acknowledgement at the end of the current
296
+ /// receive burst. Idempotent, so N data packets still cost exactly one ack.
297
+ void defer_ack();
298
+
299
+ // ---- receiving ----
300
+ /// Apply a cumulative ack, popping everything it covers off outbuf_.
301
+ void process_ack(std::uint16_t ack_nr, Clock::time_point now,
302
+ int& acked_bytes, std::uint32_t& min_rtt);
303
+ /// Apply a selective ack bitmap; may trigger fast retransmits.
304
+ void process_sack(std::uint16_t packet_ack, const std::uint8_t* bitmap, std::size_t len,
305
+ Clock::time_point now, int& acked_bytes, std::uint32_t& min_rtt);
306
+ void ack_packet(OutPacket& p, Clock::time_point now, std::uint32_t& min_rtt);
307
+ void pop_acked_front();
308
+ OutPacket* packet_at(std::uint16_t seq);
309
+ /// Deliver payload in order, draining the reorder buffer behind it.
310
+ void consume_data(const Header& h, const std::uint8_t* payload, std::size_t len);
311
+ void deliver(const std::uint8_t* data, std::size_t len);
312
+
313
+ // ---- congestion control ----
314
+ void do_ledbat(int acked_bytes, int delay, int in_flight);
315
+ void experienced_loss(std::uint16_t seq, Clock::time_point now);
316
+ int packet_timeout() const;
317
+ void resend(OutPacket& p, Clock::time_point now, bool fast);
318
+
319
+ void fail(const std::string& why);
320
+ /// Bytes the peer says it can still take, intersected with what we may send.
321
+ std::size_t window_available() const noexcept;
322
+ std::uint32_t advertised_window() const noexcept;
323
+
324
+ Host& host_;
325
+ Observer* obs_ = nullptr;
326
+
327
+ std::uint16_t recv_id_;
328
+ std::uint16_t send_id_;
329
+ Address remote_{};
330
+ State state_ = State::Idle;
331
+
332
+ // ---- sequence state ----
333
+ std::uint16_t seq_nr_ = 0; ///< sequence number of the next packet we send
334
+ std::uint16_t acked_seq_nr_ = 0; ///< highest of ours acknowledged in order
335
+ std::uint16_t ack_nr_ = 0; ///< highest of theirs received in order
336
+ std::uint16_t fast_resend_seq_nr_ = 0; ///< nothing below this is fast-resent again
337
+ std::uint16_t loss_seq_nr_ = 0; ///< a loss past this cuts the window again
338
+ int duplicate_acks_ = 0;
339
+
340
+ bool in_eof_ = false; ///< their FIN arrived
341
+ std::uint16_t in_eof_seq_nr_ = 0; ///< the sequence number it carried
342
+ bool out_eof_ = false; ///< our FIN has been queued
343
+ bool error_ = false;
344
+ /// The writer was told WouldBlock and is waiting to be woken. Without this the
345
+ /// layer above would sit on a full queue after the window reopened.
346
+ bool write_blocked_ = false;
347
+ /// Zero-window persist is in progress: pump() may put one packet on the wire
348
+ /// even though the peer says it has no room. See window_available().
349
+ bool probe_ = false;
350
+ /// Datagrams emitted, ever. Only the *change* across one incoming packet is
351
+ /// used — to tell whether an ack already rode out on a data packet.
352
+ std::uint32_t out_packets_ = 0;
353
+
354
+ // ---- send side ----
355
+ /// Payload chunks not yet given a sequence number. All but the last are full
356
+ /// (kMaxPayload); the last stays open so successive small writes coalesce into
357
+ /// one packet instead of one packet each — Nagle, without a timer.
358
+ std::deque<Bytes> pending_;
359
+ std::size_t pending_bytes_ = 0;
360
+ std::deque<OutPacket> outbuf_; ///< outbuf_[i].seq == acked_seq_nr_ + 1 + i
361
+ std::size_t bytes_in_flight_ = 0;
362
+
363
+ // ---- receive side ----
364
+ std::deque<Bytes> recv_q_; ///< in-order bytes waiting for the reader
365
+ std::size_t recv_head_ = 0; ///< bytes already consumed from recv_q_.front()
366
+ std::size_t recv_bytes_ = 0;
367
+ std::unordered_map<std::uint16_t, Bytes> inbuf_; ///< out-of-order, keyed by seq
368
+ std::size_t inbuf_bytes_ = 0;
369
+
370
+ // ---- congestion control / timing ----
371
+ std::int64_t cwnd_ = 0; ///< bytes, fixed point with 16 fractional bits
372
+ std::int32_t ssthresh_ = 0;
373
+ bool slow_start_ = true;
374
+ std::uint32_t adv_wnd_ = kMaxPayload; ///< the peer's advertised window, bytes
375
+ SlidingAverage rtt_;
376
+ DelayHistory their_delay_hist_; ///< our measurement of their one-way delay
377
+ DelayHistory delay_hist_; ///< the delay they measured, reflected to us
378
+ /// The last few delay readings. LEDBAT uses the smallest of them, because a
379
+ /// single sample is as likely to record a scheduling hiccup at either end as
380
+ /// anything about the path.
381
+ static constexpr int kDelaySampleCount = 3;
382
+ std::uint32_t delay_samples_[kDelaySampleCount] = {0xffffffffu, 0xffffffffu, 0xffffffffu};
383
+ int delay_sample_idx_ = 0;
384
+ std::uint32_t reply_micro_ = 0; ///< what we put in timestamp_difference
385
+ Clock::time_point last_history_step_{};
386
+ Clock::time_point timeout_{}; ///< retransmission deadline
387
+ Clock::time_point next_loss_{}; ///< earliest the window may be cut again
388
+ Clock::time_point closed_at_{}; ///< when linger started
389
+ int num_timeouts_ = 0;
390
+ /// Have we ever heard from this endpoint? A stream that has not is dropped on
391
+ /// its first timeout: the address may simply have been made up by whoever
392
+ /// handed it to us, and there is no reason to spend retransmissions on it.
393
+ bool confirmed_ = false;
394
+ bool deferred_ack_ = false;
395
+
396
+ /// Reused datagram assembly buffer, so a packet costs no allocation.
397
+ std::uint8_t scratch_[kMaxDatagram] = {};
398
+ };
399
+
400
+ } // namespace librats::bittorrent::utp
@@ -860,7 +860,8 @@ int send_tcp_string(socket_t socket, const std::string& data) {
860
860
 
861
861
  // ── UDP Socket Functions ────────────────────────────────────────────────────
862
862
 
863
- socket_t create_udp_socket(int port, const std::string& bind_address, AddressFamily af) {
863
+ socket_t create_udp_socket(int port, const std::string& bind_address, AddressFamily af,
864
+ UdpPortMode mode) {
864
865
  if (!validate_port(port)) return RATS_INVALID_SOCKET;
865
866
 
866
867
  const char* af_label = (af == AddressFamily::IPv4) ? "IPv4" :
@@ -891,8 +892,8 @@ socket_t create_udp_socket(int port, const std::string& bind_address, AddressFam
891
892
  }
892
893
  #endif
893
894
 
894
- // Reuse the address — but only for a port we asked for by number, where the
895
- // point is to rebind a port a previous run may still be lingering on.
895
+ // Reuse the address — but only for a port we asked for by number, and only when
896
+ // the caller has not said the port must be its own.
896
897
  //
897
898
  // Never when the kernel is choosing the port. On a datagram socket the option
898
899
  // does not merely relax rebinding, it takes the port out of the set an auto-bind
@@ -901,7 +902,13 @@ socket_t create_udp_socket(int port, const std::string& bind_address, AddressFam
901
902
  // here did. The two then share the port and the kernel picks one of them per
902
903
  // datagram, so a dial-only socket can land on the port a listener beside it is
903
904
  // serving and start eating its traffic. Rare, and invisible from either end.
904
- if (port != 0) {
905
+ //
906
+ // Exclusive asks for the same guarantee on a port given by number, where the
907
+ // clash is not rare at all: two subsystems can want one number by protocol. Not
908
+ // setting the option is what makes *our* bind fail over somebody else's socket;
909
+ // SO_EXCLUSIVEADDRUSE closes the other direction on Windows, where a later bind
910
+ // that does set SO_REUSEADDR would otherwise take the port out from under us.
911
+ if (port != 0 && mode == UdpPortMode::Shared) {
905
912
  int opt = 1;
906
913
  if (setsockopt(udp_socket, SOL_SOCKET, SO_REUSEADDR,
907
914
  (char*)&opt, sizeof(opt)) == RATS_SOCKET_ERROR) {
@@ -911,6 +918,19 @@ socket_t create_udp_socket(int port, const std::string& bind_address, AddressFam
911
918
  return RATS_INVALID_SOCKET;
912
919
  }
913
920
  }
921
+ #ifdef _WIN32
922
+ if (port != 0 && mode == UdpPortMode::Exclusive) {
923
+ // Best-effort: not having it still leaves the bind itself exclusive, which
924
+ // is the half that matters for a socket opened after the one it clashes with.
925
+ int opt = 1;
926
+ if (setsockopt(udp_socket, SOL_SOCKET, SO_EXCLUSIVEADDRUSE,
927
+ (char*)&opt, sizeof(opt)) == RATS_SOCKET_ERROR) {
928
+ LOG_SOCKET_DEBUG("SO_EXCLUSIVEADDRUSE unavailable on " << af_label
929
+ << " UDP socket (error: "
930
+ << socket_error_string(get_last_socket_error()) << ")");
931
+ }
932
+ }
933
+ #endif
914
934
 
915
935
  // For IPv6/DualStack sockets, configure IPV6_V6ONLY
916
936
  if (family == AF_INET6) {
@@ -943,8 +963,16 @@ socket_t create_udp_socket(int port, const std::string& bind_address, AddressFam
943
963
 
944
964
  if (bind(udp_socket, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) == RATS_SOCKET_ERROR) {
945
965
  const int error = get_last_socket_error();
946
- LOG_SOCKET_ERROR("Failed to bind " << af_label << " UDP socket to port " << port
947
- << " (error: " << socket_error_string(error) << ")");
966
+ // An Exclusive bind losing a contested port is the question being
967
+ // answered, not a fault: the caller asked precisely so it could move.
968
+ if (mode == UdpPortMode::Exclusive) {
969
+ LOG_SOCKET_DEBUG("Port " << port << " already held, " << af_label
970
+ << " UDP bind declined (error: "
971
+ << socket_error_string(error) << ")");
972
+ } else {
973
+ LOG_SOCKET_ERROR("Failed to bind " << af_label << " UDP socket to port " << port
974
+ << " (error: " << socket_error_string(error) << ")");
975
+ }
948
976
  return fail_socket(udp_socket, error);
949
977
  }
950
978
  } else {
@@ -965,8 +993,16 @@ socket_t create_udp_socket(int port, const std::string& bind_address, AddressFam
965
993
 
966
994
  if (bind(udp_socket, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) == RATS_SOCKET_ERROR) {
967
995
  const int error = get_last_socket_error();
968
- LOG_SOCKET_ERROR("Failed to bind " << af_label << " UDP socket to port " << port
969
- << " (error: " << socket_error_string(error) << ")");
996
+ // An Exclusive bind losing a contested port is the question being
997
+ // answered, not a fault: the caller asked precisely so it could move.
998
+ if (mode == UdpPortMode::Exclusive) {
999
+ LOG_SOCKET_DEBUG("Port " << port << " already held, " << af_label
1000
+ << " UDP bind declined (error: "
1001
+ << socket_error_string(error) << ")");
1002
+ } else {
1003
+ LOG_SOCKET_ERROR("Failed to bind " << af_label << " UDP socket to port " << port
1004
+ << " (error: " << socket_error_string(error) << ")");
1005
+ }
970
1006
  return fail_socket(udp_socket, error);
971
1007
  }
972
1008
  }
@@ -52,6 +52,26 @@ enum class AddressFamily {
52
52
  DualStack // IPv6 socket with IPv4 support (default)
53
53
  };
54
54
 
55
+ /**
56
+ * Whether a UDP bind is allowed to land on a port another socket already holds.
57
+ *
58
+ * On a datagram socket SO_REUSEADDR does not mean what it means for TCP. There is
59
+ * no TIME_WAIT to wait out, so what the option actually buys is the right to bind
60
+ * a port somebody else is already serving — and then the kernel hands each arriving
61
+ * datagram to one of the two, by a rule neither of them can see. Both sockets read
62
+ * a fraction of a stream neither of them is meant to share, and nothing reports an
63
+ * error at any point.
64
+ *
65
+ * `Shared` is the historical default and is right for a port only one subsystem
66
+ * ever wants. `Exclusive` is for a port that is *also* plausibly somebody else's —
67
+ * the BitTorrent uTP mux, which by protocol wants the same number the DHT is
68
+ * already serving. There the bind must fail loudly so the caller can move.
69
+ */
70
+ enum class UdpPortMode {
71
+ Shared, ///< May bind over an existing holder (SO_REUSEADDR).
72
+ Exclusive ///< Bind fails if the port is taken, and refuses later sharers.
73
+ };
74
+
55
75
  /**
56
76
  * Whether a socket bound with `af` can send to an address of the given family
57
77
  * at all.
@@ -240,10 +260,12 @@ int send_tcp_string(socket_t socket, const std::string& data);
240
260
  * @param port The port to bind to (0 for any available port)
241
261
  * @param bind_address The interface IP address to bind to (empty for all interfaces)
242
262
  * @param af Address family (DualStack by default)
263
+ * @param mode Whether the port may be shared with a socket that already holds it
243
264
  * @return UDP socket handle, or RATS_INVALID_SOCKET on error
244
265
  */
245
266
  socket_t create_udp_socket(int port = 0, const std::string& bind_address = "",
246
- AddressFamily af = AddressFamily::DualStack);
267
+ AddressFamily af = AddressFamily::DualStack,
268
+ UdpPortMode mode = UdpPortMode::Shared);
247
269
 
248
270
  /**
249
271
  * Send UDP data to a destination host and port
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "librats",
3
- "version": "2.3.3",
3
+ "version": "2.3.4",
4
4
  "description": "Node.js bindings for librats - A high-performance peer-to-peer networking library",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",