Flow 2.0.0
Flow project: Full implementation reference.
peer_socket.hpp
Go to the documentation of this file.
1/* Flow
2 * Copyright 2023 Akamai Technologies, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the
5 * "License"); you may not use this file except in
6 * compliance with the License. You may obtain a copy
7 * of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in
12 * writing, software distributed under the License is
13 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
14 * CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing
16 * permissions and limitations under the License. */
17
18/// @file
19#pragma once
20
25#include "flow/error/error.hpp"
29#include "flow/util/util.hpp"
35#include <boost/utility.hpp>
36#include <boost/shared_ptr.hpp>
37#include <boost/enable_shared_from_this.hpp>
38#include <boost/move/unique_ptr.hpp>
39#include <type_traits>
40
41namespace flow::net_flow
42{
43// Types.
44
45/**
46 * A peer (non-server) socket operating over the Flow network protocol, with optional stream-of-bytes and
47 * reliability support.
48 *
49 * Reliability is enabled or disabled via a socket option, Peer_socket_options::m_st_rexmit_on,
50 * at socket creation. Use unreliable mode with care -- see send() method doc header for details.
51 *
52 * ### Life cycle of a Peer_socket ###
53 * A given Peer_socket can arise either by connecting to
54 * Server_socket on a Node (Node::connect() or Node::sync_connect()), or by listening on a
55 * Node's Server_socket and accepting such a connection (Server_socket::accept() or
56 * Server_socket::sync_accept()). In all cases, Node or Server_socket generates a new Peer_socket
57 * and returns it (factory pattern). Peer_socket is not instantiable otherwise. A Peer_socket
58 * cannot be deleted explicitly by the user and will only be returned via `boost::shared_ptr<>`; when
59 * both the Node and all user code no longer refers to it, the Peer_socket will be destroyed.
60 *
61 * Once a `net_flow` user has a Peer_socket object, that object represents a socket in one of the
62 * following basic states:
63 *
64 * - Open.
65 * - Sub-states:
66 * - Connecting. (Never Writable, never Readable.)
67 * - Connected. (May be Writable, may be Readable.)
68 * - Disconnecting. (May be Readable, never Writable.)
69 * - Closed.
70 * - Socket can neither read nor write.
71 *
72 * Open.Connecting means means Node initiated a connect to the given server, and this is in
73 * progress. Open.Connected means the connection to the other Node is fully functional.
74 * Open.Disconnecting means either our side or the other side has initiated a clean or abrupt
75 * disconnect, but it is not yet entirely finished (background handshaking is happening, you have
76 * not read all available data or sent all queued data, etc.).
77 *
78 * In either case, reading and writing may or may not be possible at a given time, depending on the
79 * state of the internal buffers and the data having arrived on the logical connection. Thus all
80 * Open sub-states can and often should be treated the same way in a typical Flow-protocol-using algorithm:
81 * simply determine when the Peer_socket is Readable, and read; and similarly for Writable and
82 * write. Thus the sub-states are distinguished for informational/diagnostic purposes only, as user
83 * reading/writing logic in these states should usually be identical.
84 *
85 * @todo Closing connection considerations. May implement closing only via timeouts at first (as
86 * opposed to explicit closing). Below text refers to `close_final()` and `close_start()`, but those
87 * are just ideas and may be replaced with timeout, or nothing. At this time, the only closing
88 * supported is abrupt close due to error or abrupt close via close_abruptly().
89 *
90 * Closed means that the Peer_socket has become disconnected, and no data can possibly be
91 * received or sent, AND that Node has no more background internal operations to perform and has
92 * disowned the Peer_socket. In other words, a Closed Peer_socket is entirely dead.
93 *
94 * Exactly the following state transitions are possible for a given Peer_socket returned by Node:
95 *
96 * - start => Closed
97 * - start => Open
98 * - Open => Closed
99 *
100 * Note, in particular, that Closed is final; socket cannot move from Closed to
101 * Open. If after an error or valid disconnection you want to reestablish a
102 * connection, obtain a new Peer_socket from Node's factories. Rationale (subject to change):
103 * this cuts down on state having to be tracked inside a Peer_socket, while the interface becomes
104 * simpler without much impact on usability. Anti-rationale: contradicts BSD socket and boost.asio
105 * established practices; potentially more resource-intensive/slower in the event of errors and
106 * disconnects. Why IMO rationale > anti-rationale: it's simpler, and the potential problems do not
107 * appear immediately serious; added statefulness can be added later if found desirable.
108 *
109 * Receving, sending, and buffers: Peer_socket, like a TCP socket, has a Receive buffer (a/k/a
110 * FIFO queue of bytes) of some maximum size and a Send buffer (a/k/a FIFO queue of bytes) of some
111 * maximum size. They are typically not directly exposed via the interface, but their existence
112 * affects documented behavior. I formally describe them here, but generally they work similarly to
113 * TCP socket Send/Receive buffers.
114 *
115 * The Receive buffer: Contains bytes asynchronously received on the connection that have not yet
116 * been removed with a `*receive()` method. Any bytes that asynchronously arrive on the connection are
117 * asynchronously stored to the buffer on the other side of the buffer in a queued fashion.
118 *
119 * The Send buffer: Contains bytes intended to be asynchronously sent on the connection that have
120 * been placed there by a `*send()` method but not yet sent on the connection. Any bytes that are
121 * asynchronously sent on the connection are asynchronously removed from the buffer on the other
122 * side of the buffer in a queued fashion.
123 *
124 * With that in mind, here are the definitions of Readable and Writable while state is Open:
125 *
126 * - Readable <=> Data available in internal Receive buffer, and user has not explicitly announced
127 * via `close_final()` they're not interested in reading further.
128 * - Writable <=> Space for data available in internal Send buffer, and the state is Open.Connected.
129 *
130 * Note that neither definition really cares about the state of the network connection (e.g., could
131 * bytes actually be sent over the network at the moment?). There is one caveat: A
132 * socket is not Writable until Open.Connecting state is transitioned away from; this prevents user
133 * from buffering up send data before the connection is ready. (Allowing that would not necessarily
134 * be wrong, but I'm taking a cue from BSD socket semantics on this, as they seem to be convenient.)
135 *
136 * In Open, the following archetypal operations are provided. (In Closed all
137 * immediately fail; in Open.Disconnecting some immediately fail if `close*()` has been called.) Let
138 * R be the current size of data in the Receive buffer, and S be the available space for data in the
139 * Send buffer.
140 *
141 * - `receive(N)`. If Readable, return to caller `min(N, R)` oldest data to have been received from
142 * the other side, and remove them from Receive buffer. Otherwise do nothing.
143 * - `send(N)`. If Writable, take from caller `min(N, S)` data to be appended to the Send
144 * buffer and, when possible, sent to the other side. Otherwise do nothing.
145 * - `sync_receive(N)`. If Readable, `receive(N)`. Otherwise sleep until Readable, then `receive(N)`.
146 * - `sync_send(N)`. If Writable, `send(N)`. Otherwise sleep until Writable, then `send(N)`.
147 *
148 * These are similar to TCP Receive and Send APIs in non-blocking mode, and TCP Receive and Send APIs in
149 * blocking mode, respectively. There may be other similarly themed methods, but all use these as
150 * semantic building blocks.
151 *
152 * To understand the order of events, one can think of a disconnect-causing event (like a graceful
153 * close initiation from the remote socket) as a piece of data itself. Thus, for example, if 5
154 * bytes are received and placed into the Receive buffer without being read by the user, and then a
155 * connection close is detected, the socket will be Readable until the 5 bytes have been
156 * receive()ed, and the next receive() (or send()) would yield the error, since that's the order
157 * things happened. Similarly, suppose you've sent 5 bytes, but they haven't been yet
158 * sent over the wire and are sitting in the Send buffer. Then you trigger a graceful connection close.
159 * First the 5 bytes will be sent if possible, and then the closing procedure will actually begin.
160 *
161 * Abrupt closes such as connection resets may force both buffers to be immediately emptied without
162 * giving to the user or writing to the other side, so that the above rule does not have to apply.
163 * Typically a connection reset means the socket is immediately unusable no matter what was in the
164 * buffers at the time, per BSD socket semantics.
165 *
166 * ### Efficiently reading/writing ###
167 * The `sync_*`() methods are efficient, in that they use no processor
168 * cycles until Readable or Writable is achieved (i.e., they sleep until that point). The
169 * non-blocking versions don't sleep/block, however. For a program using them to be efficient it
170 * should sleep until Readable or Writable and only then call receive()/send(), when data are
171 * certainly available for immediate reading or writing. Moreover, a complex program is likely to
172 * want to perform this sleep-and-conditional-wake on a set of several Peer_socket objects simultaneously
173 * (similarly to `select()`, `epoll*()`, etc.). Use class Event_set for this purpose.
174 *
175 * ### Thread safety ###
176 * Same as for Node. (Briefly: all operations safe for simultaneous execution on
177 * separate or the same object.)
178 *
179 * @internal
180 *
181 * Implementation notes
182 * --------------------
183 *
184 * While to a user a Peer_socket appears as a nearly self-sufficient object (i.e., you can do things
185 * like `s->send()`, which means 'socket `s`, send some data!''), the most reasonable way to internally
186 * implement this is to have Node contain the logic behind a Peer_socket (and how it works together
187 * with other Peer_socket objects and other internal infrastructure). Thus Node is the class with all of
188 * the logic behind (for example) `s->send()`. Peer_socket then, privately, is not too much more than a
189 * collection of data (like a `struct` almost) to help Node.
190 *
191 * Therefore Peer_socket provides a clean object-oriented public interface to the user but, on the
192 * implementation side, is basically a data store (with Node as `friend`) and forwards the logic to
193 * the originating Node. One idea to make this dichotomy more cleanly expressed (e.g., without
194 * `friend`) was to make Peer_socket a pure interface and have Node produce `Peer_socket_impl`
195 * objects, where `Peer_socket_impl` implements Peer_socket and is itself private to the user (a
196 * classic factory pattern). Unfortunately defining function templates such as `send<Buffers>()`
197 * (where `Buffers` is an arbitrary `Buffers` concept model) as pure `virtual` functions is not really
198 * possible in C++. Since such a templated interface can be highly convenient (see boost.asio with
199 * its seamless support for buffers and buffer sequences of most types, including scatter-gather),
200 * the usefulness of the interface trumps implementation beauty.
201 *
202 * To prevent node.cpp from being unmanageably large (and also because it makes sense),
203 * implementations for Node methods that deal only with an individual Peer_socket reside in
204 * peer_socket.cpp (even though they are members of Node, since, again, the logic is all forwarded to Node).
205 *
206 * @todo Rename `State` and `Open_sub_state` to `Phase` and `Open_sub_phase` respectively; and
207 * `Int_state` to `State`. Explain difference between phases (application-layer, user-visible and used
208 * close to application layer) and states (transport layer, internal).
209 *
210 * @todo Look into a way to defeat the need for boiler-plate trickery -- with low but non-zero perf cost --
211 * involving `*_socket`-vs-`Node` circular references in method templates, such as the way
212 * Peer_socket::send() and Peer_socket::receive() internally make `Function<>`s before forwarding to the core
213 * in Node. Can this be done with `.inl` files? Look into how Boost internally uses `.inl` files; this could
214 * inspire a solution... or not.
215 */
218 // Endow us with shared_ptr<>s ::Ptr and ::Const_ptr (syntactic sugar).
219 public util::Shared_ptr_alias_holder<boost::shared_ptr<Peer_socket>>,
220 // Allow access to Ptr(this) from inside Peer_socket methods. Just call shared_from_this().
221 public boost::enable_shared_from_this<Peer_socket>,
222 public log::Log_context,
223 private boost::noncopyable
224{
225public:
226 // Types.
227
228 /// State of a Peer_socket.
229 enum class State
230 {
231 /// Future reads or writes may be possible. A socket in this state may be Writable or Readable.
232 S_OPEN,
233 /// Neither future reads nor writes are possible, AND Node has disowned the Peer_socket.
234 S_CLOSED
235 };
236
237 /// The sub-state of a Peer_socket when state is State::S_OPEN.
238 enum class Open_sub_state
239 {
240 /**
241 * This Peer_socket was created through an active connect (Node::connect() and the like), and
242 * the connection to the remote Node is currently being negotiated by this socket's Node.
243 * A socket in this state may be Writable but cannot be Readable. However, except for
244 * diagnostic purposes, this state should generally be treated the same as S_CONNECTED.
245 */
246 S_CONNECTING,
247
248 /**
249 * This Peer_socket was created through a passive connect (Node::accept() and the like) or an
250 * active connect (Node::connect() and the like), and the connection is (as far this socket's
251 * Node knows) set up and functioning. A socket in this state may be Writable or Readable.
252 */
253 S_CONNECTED,
254
255 /**
256 * This Peer_socket was created through a passive connect (Node::accept() and the like) or an
257 * active connect (Node::connect() and the like), but since then either an active close,
258 * passive close, or an error has begun to close the connection, but data may still possibly
259 * arrive and be Readable; also data may have been "sent" but still sitting in the Send buffer
260 * and needs to be sent over the network. A socket in this state may be Readable but cannot
261 * be Writable.
262 *
263 * This implies that a non-S_CLOSED socket may be, at a lower level, disconnected. For
264 * example, say there are 5 bytes in the Receive buffer, and the other side sends a graceful
265 * disconnect packet to this socket. This means the connection is finished, but the user can
266 * still receive() the 5 bytes (without blocking). Then state will remain
267 * S_OPEN.S_DISCONNECTING until the last of the 5 bytes is received (gone from the buffer); at
268 * this point state may change to S_CLOSED (pending any other work Node must do to be able to
269 * disown the socket).
270 */
271 S_DISCONNECTING
272 }; // enum class Open_sub_state
273
274 // Constructors/destructor.
275
276 /// Boring `virtual` destructor. Note that deletion is to be handled exclusively via `shared_ptr`, never explicitly.
277 ~Peer_socket() override;
278
279 // Methods.
280
281 /**
282 * Current State of the socket.
283 *
284 * @param open_sub_state
285 * Ignored if null. Otherwise, if and only if State::S_OPEN is returned, `*open_sub_state` is set to
286 * the current sub-state of `S_OPEN`.
287 * @return Current main state of the socket.
288 */
289 State state(Open_sub_state* open_sub_state = 0) const;
290
291 /**
292 * Node that produced this Peer_socket.
293 *
294 * @return Pointer to (guaranteed valid) Node; null if state is State::S_CLOSED.
295 */
296 Node* node() const;
297
298 /**
299 * Intended other side of the connection (regardless of success, failure, or current State).
300 * For a given Peer_socket, this will always return the same value, even if state is
301 * State::S_CLOSED.
302 *
303 * @return See above.
304 */
305 const Remote_endpoint& remote_endpoint() const;
306
307 /**
308 * The local Flow-protocol port chosen by the Node (if active or passive open) or user (if passive open) for
309 * this side of the connection. For a given Peer_socket, this will always return the same value,
310 * even if state is State::S_CLOSED. However, when state is State::S_CLOSED, the port may be unused or
311 * taken by another socket.
312 *
313 * @return See above.
314 */
315 flow_port_t local_port() const;
316
317 /**
318 * Obtains the serialized connect metadata, as supplied by the user during the connection handshake.
319 * If this side initiated the connection (Node::connect() and friends), then this will equal what
320 * was passed to the connect_with_metadata() (or similar) method. More likely, if this side
321 * accepted the connection (Server_socket::accept() and friends), then this will equal what the
322 * user on the OTHER side passed to connect_with_metadata() or similar.
323 *
324 * @note It is up to the user to deserialize the metadata portably. One recommended convention is to
325 * use `boost::endian::native_to_little()` (and similar) before connecting; and
326 * on the other side use the reverse (`boost::endian::little_to_native()`) before using the value.
327 * Packet dumps will show a flipped (little-endian) representation, while with most platforms the conversion
328 * will be a no-op at compile time. Alternatively use `native_to_big()` and vice-versa.
329 * @note If a connect() variant without `_with_metadata` in the name was used, then the metadata are
330 * composed of a single byte with the zero value.
331 * @param buffer
332 * A buffer to copy the metadata into.
333 * @param err_code
334 * See flow::Error_code docs for error reporting semantics.
335 * @return The size of the copied metadata.
336 */
337 size_t get_connect_metadata(const boost::asio::mutable_buffer& buffer,
338 Error_code* err_code = 0) const;
339
340 /**
341 * Sends (adds to the Send buffer) the given bytes of data up to a maximum internal buffer size;
342 * and asynchronously sends them to the other side. The data given is copied into `*this`, in the order
343 * given. Only as many bytes as possible without the Send buffer size exceeding a certain max are
344 * copied.
345 *
346 * The method does not block. Data are then sent asynchronously (in the background).
347 *
348 * Method does nothing except possibly logging if there are no bytes in data.
349 *
350 * ### Error handling ###
351 * These are the possible outcomes.
352 * 1. There is no space in the Send buffer (usually due to network congestion). Socket not
353 * Writable. 0 is returned; `*err_code` is set to success unless null; no data buffered.
354 * 2. The socket is not yet fully connected (`S_OPEN+S_CONNECTING` state). Socket not
355 * Writable. 0 is returned; `*err_code` is set to success unless null; no data buffered.
356 * 3. There is space in the Send buffer, and socket connection is open (`S_OPEN+S_CONNECTED`).
357 * Socket Writable. >= 1 is returned; `*err_code` is set to success; data buffered.
358 * 4. The operation cannot proceed due to an error. 0 is returned; `*err_code` is set to the
359 * specific error unless null; no data buffered. (If `err_code` null, Runtime_error thrown.)
360 *
361 * The semantics of -3- (the success case) are as follows. N bytes will be copied into Send
362 * buffer from the start of the Const_buffer_sequence data. These N bytes may be spread across 1
363 * or more buffers in that sequence; the subdivision structure of the sequence of bytes into
364 * buffers has no effect on what will be buffered in Send buffer (e.g., "data" could be N+ 1-byte
365 * buffers, or one N+-byte buffer -- the result would be the same). N equals the smaller of: the
366 * available space in the Send buffer; and `buffer_size(data)`. We return N.
367 *
368 * ### Reliability and ordering guarantees: if the socket option rexmit-on is enabled ###
369 * Reliability and ordering are guaranteed, and there is no notion of message boundaries. There is no possibility
370 * of data duplication. In other words full stream-of-bytes functionality is provided, as in TCP.
371 *
372 * ### Reliability and ordering guarantees: if the socket option rexmit-on is NOT enabled ###
373 * NO reliability guarantees are given, UNLESS *ALL* calls to send() (and other `*send`() methods)
374 * satisfy the condition: '`buffer_size(data)` is a multiple of `sock->max_block_size()`'; AND all
375 * calls to receive() (and other `*receive()` methods) on the OTHER side satisfy the condition:
376 * '`buffer_size(target)` is a multiple of `sock->max_block_size()`.' If and only if these guidelines
377 * are followed, and there is no connection closure, the following reliability guarantee is made:
378 *
379 * Let a "block" be a contiguous chunk of bytes in a "data" buffer sequence immediately following
380 * another "block," except the first "block" in a connection, which begins with the first byte of
381 * the "data" buffer sequence passed to the first `*send()` call on that connection. Then: Each
382 * given block will either be available to `*receive()` on the other side exactly once and without
383 * corruption; or not available to `*receive()` at all. Blocks may arrive in a different order than
384 * specified here, including with respect to other `*send()` calls performed before or after this
385 * one. In other words, these are guaranteed: block boundary preservation, protection against
386 * corruption, protection again duplication. These are not guaranteed: order preservation,
387 * delivery. Informally, the latter factors are more likely to be present on higher quality
388 * network paths.
389 *
390 * @tparam Const_buffer_sequence
391 * Type that models the boost.asio `ConstBufferSequence` concept (see Boost docs).
392 * Basically, it's any container with elements convertible to `boost::asio::const_buffer`;
393 * and bidirectional iterator support. Examples: `vector<const_buffer>`, `list<const_buffer>`.
394 * Why allow `const_buffer` instead of, say, `Sequence` of bytes? Same reason as boost.asio's
395 * send functions: it allows a great amount of flexibility without sacrificing performance,
396 * since `boost::asio::buffer()` function can adapt lots of different objects (arrays,
397 * `vector`s, `string`s, and more -- composed of bytes, integers, and more).
398 * @param data
399 * Buffer sequence from which a stream of bytes to add to Send buffer will be obtained.
400 * @param err_code
401 * See flow::Error_code docs for error reporting semantics.
402 * Error implies that neither this send() nor any subsequent `*send()` on this socket
403 * will succeeed. (In particular a clean disconnect is an error.)
404 * @return Number of bytes (possibly zero) added to buffer. Always 0 if `bool(*err_code) == true` when
405 * send() returns.
406 */
407 template<typename Const_buffer_sequence>
408 size_t send(const Const_buffer_sequence& data, Error_code* err_code = 0);
409
410 /**
411 * Blocking (synchronous) version of send(). Acts just like send(), except that if Socket is not
412 * immediately Writable (i.e., send() would return 0 and no error), waits until it is Writable
413 * (send() would return either >0, or 0 and an error) and returns `send(data, err_code)`. If a
414 * timeout is specified, and this timeout expires before socket is Writable, acts like send()
415 * executed on an un-Writable socket.
416 *
417 * ### Error handling ###
418 * These are the possible outcomes (assuming there are data in the argument `data`).
419 * 1. There is space in the Send buffer, and socket connection
420 * is open (`S_OPEN+S_CONNECTED`). Socket Writable. >= 1 is returned; `*err_code` is set to
421 * success unless null; data buffered.
422 * 2. The operation cannot proceed due to an error. 0 is returned; `*err_code` is set to the
423 * specific error unless null; no data buffered. (If `err_code` null, Runtime_error thrown.)
424 * The code error::Code::S_WAIT_INTERRUPTED means the wait was interrupted
425 * (similarly to POSIX's `EINTR`).
426 * 3. Neither condition above is detected before the timeout expires (if provided).
427 * Output semantics are the same as in 2, with the specific code error::Code::S_WAIT_USER_TIMEOUT.
428 *
429 * The semantics of -1- (the success case) equal those of send().
430 *
431 * Note that it is NOT possible to return 0 and no error.
432 *
433 * Tip: Typical types you might use for `max_wait`: `boost::chrono::milliseconds`,
434 * `boost::chrono::seconds`, `boost::chrono::high_resolution_clock::duration`.
435 *
436 * @see The version of sync_send() with no timeout.
437 * @tparam Rep
438 * See boost::chrono::duration documentation (and see above tip).
439 * @tparam Period
440 * See boost::chrono::duration documentation (and see above tip).
441 * @tparam Const_buffer_sequence
442 * See send().
443 * @param data
444 * See send().
445 * @param max_wait
446 * The maximum amount of time from now to wait before giving up on the wait and returning.
447 * `"duration<Rep, Period>::max()"` will eliminate the time limit and cause indefinite wait
448 * (i.e., no timeout).
449 * @param err_code
450 * See flow::Error_code docs for error reporting semantics.
451 * Error, except `WAIT_INTERRUPTED` or `WAIT_USER_TIMEOUT`, implies that
452 * neither this send() nor any subsequent send() on this socket
453 * will succeeed. (In particular a clean disconnect is an error.)
454 * @return Number of bytes (possibly zero) added to Send buffer. Always 0 if `bool(*err_code) == true`
455 * when sync_send() returns.
456 */
457 template<typename Rep, typename Period, typename Const_buffer_sequence>
458 size_t sync_send(const Const_buffer_sequence& data,
459 const boost::chrono::duration<Rep, Period>& max_wait, Error_code* err_code = 0);
460
461 /**
462 * `sync_send()` operating in `nullptr_t` mode, wherein -- if Writable state is reached -- the actual data
463 * are not moved out of any buffer, leaving that to the caller to do if desired. Hence, this is a way of waiting
464 * for Writable state that could be more concise in some situations than Event_set::sync_wait().
465 *
466 * ### Error handling ###
467 * These are the possible outcomes:
468 * 1. There is space in the Send buffer; and socket is fully connected
469 * (`S_OPEN+S_CONNECTED`). Socket
470 * Writable. `true` is returned; `*err_code` is set to success unless null.
471 * 2. The operation cannot proceed due to an error. `false` is returned; `*err_code` is set to the
472 * specific error unless null. `*err_code == S_WAIT_INTERRUPTED` means the wait was
473 * interrupted (similarly to POSIX's `EINTR`). (If `err_code` null, Runtime_error thrown.)
474 * 3. Neither condition above is detected before the timeout expires (if provided).
475 * Output semantics are the same as in 2, with the specific code error::Code::S_WAIT_USER_TIMEOUT.
476 *
477 * Note that it is NOT possible to return `false` and no error.
478 *
479 * Tip: Typical types you might use for `max_wait`: `boost::chrono::milliseconds`,
480 * `boost::chrono::seconds`, `boost::chrono::high_resolution_clock::duration`.
481 *
482 * @tparam Rep
483 * See other sync_send().
484 * @tparam Period
485 * See other sync_send().
486 * @param max_wait
487 * See other sync_receive().
488 * @param err_code
489 * See flow::Error_code docs for error reporting semantics.
490 * Error, except `WAIT_INTERRUPTED` or `WAIT_USER_TIMEOUT`, implies that
491 * neither this nor any subsequent send() on this socket
492 * will succeeed. (In particular a clean disconnect is an error.)
493 * @return `true` if 1+ bytes are possible to add to Send buffer; `false` if either a timeout has occurred (bytes
494 * not writable), or another error has occurred.
495 */
496 template<typename Rep, typename Period>
497 bool sync_send(std::nullptr_t,
498 const boost::chrono::duration<Rep, Period>& max_wait, Error_code* err_code = 0);
499
500 /**
501 * Equivalent to `sync_send(data, duration::max(), err_code)`; i.e., sync_send() with no timeout.
502 *
503 * @tparam Const_buffer_sequence
504 * See other sync_send().
505 * @param data
506 * See other sync_send().
507 * @param err_code
508 * See other sync_send().
509 * @return See other sync_send().
510 */
511 template<typename Const_buffer_sequence>
512 size_t sync_send(const Const_buffer_sequence& data, Error_code* err_code = 0);
513
514 /**
515 * Equivalent to `sync_send(nullptr, duration::max(), err_code)`; i.e., `sync_send(nullptr_t)`
516 * with no timeout.
517 *
518 * @param err_code
519 * See other sync_receive().
520 * @return See other sync_receive().
521 */
522 bool sync_send(std::nullptr_t, Error_code* err_code = 0);
523
524 /**
525 * Receives (consumes from the Receive buffer) bytes of data, up to a given maximum
526 * cumulative number of bytes as inferred from size of provided target buffer sequence. The data
527 * are copied into the user's structure and then removed from the Receive buffer.
528 *
529 * The method does not block. In particular if there are no data already received from the other
530 * side, we return no data.
531 *
532 * If the provided buffer has size zero, the method is a NOOP other than possibly logging.
533 *
534 * ### Error handling ###
535 * These are the possible outcomes.
536 * 1. There are no data in the Receive buffer. Socket not Readable. 0 is returned;
537 * `*err_code` is set to success unless null; no data returned.
538 * 2. The socket is not yet fully connected (`S_OPEN+S_CONNECTING`). Socket not
539 * Readable. 0 is returned; `*err_code` is set to success unless null; no data returned.
540 * 3. There are data in the Receive buffer; and socket is fully connected (`S_OPEN+S_CONNECTED`)
541 * or gracefully shutting down (`S_OPEN+S_DISCONNECTING`). Socket Readable. >= 1 is returned;
542 * *err_code is set to success; data returned.
543 * 4. The operation cannot proceed due to an error. 0 is returned; `*err_code` is set to the
544 * specific error; no data buffered. (If `err_code` null, Runtime_error thrown.)
545 *
546 * The semantics of -3- (the success case) are as follows. N bytes will be copied from Receive
547 * buffer beginning at the start of the `Mutable_buffer_sequence target`. These N bytes may be
548 * spread across 1 or more buffers in that sequence; the subdivision structure of the sequence of
549 * bytes into buffers has no effect on the bytes, or order thereof, that will be moved from the
550 * Receive buffer (e.g., `target` could be N+ 1-byte buffers, or one N+-byte buffer
551 * -- the popped Receive buffer would be the same, as would be the extracted bytes). N equals the
552 * smaller of: the available bytes in the Receive buffer; and `buffer_size(target)`. We return N.
553 *
554 * ### Reliability and ordering guarantees ###
555 * See the send() doc header.
556 *
557 * @tparam Mutable_buffer_sequence
558 * Type that models the boost.asio `MutableBufferSequence` concept (see Boost docs).
559 * Basically, it's any container with elements convertible to `boost::asio::mutable_buffer`;
560 * and bidirectional iterator support. Examples: `vector<mutable_buffer>`,
561 * `list<mutable_buffer>`. Why allow `mutable_buffer` instead of, say, `Sequence` of bytes?
562 * Same reason as boost.asio's receive functions: it allows a great amount of flexibility
563 * without sacrificing performance, since `boost::asio::buffer()` function can adapt lots of
564 * different objects (arrays, `vector`s, `string`s, and more of bytes, integers, and more).
565 * @param target
566 * Buffer sequence to which a stream of bytes to consume from Receive buffer will be
567 * written.
568 * @param err_code
569 * See flow::Error_code docs for error reporting semantics.
570 * Error implies that neither this receive() nor any subsequent receive() on this socket
571 * will succeeed. (In particular a clean disconnect is an error.)
572 * @return The number of bytes consumed (placed into `target`). Always 0 if `bool(*err_code) == true`
573 * when receive() returns.
574 */
575 template<typename Mutable_buffer_sequence>
576 size_t receive(const Mutable_buffer_sequence& target, Error_code* err_code = 0);
577
578 /**
579 * Blocking (synchronous) version of receive(). Acts just like receive(), except that if socket
580 * is not immediately Readable (i.e., receive() would return 0 and no error), waits until it is
581 * Readable (receive() would return either >0, or 0 and an error) and returns
582 * `receive(target, err_code)`. If a timeout is specified, and this timeout expires before socket is
583 * Readable, it acts as if receive() produced error::Code::S_WAIT_USER_TIMEOUT.
584 *
585 * ### Error handling ###
586 * These are the possible outcomes:
587 * 1. There are data in the Receive buffer; and socket is fully connected
588 * (`S_OPEN+S_CONNECTED`) or gracefully shutting down (`S_OPEN+S_DISCONNECTING`). Socket
589 * Readable. >= 1 is returned; `*err_code` is set to success unless null; data returned.
590 * 2. The operation cannot proceed due to an error. 0 is returned; `*err_code` is set to the
591 * specific error unless null; no data buffered. `*err_code == S_WAIT_INTERRUPTED` means the wait was
592 * interrupted (similarly to POSIX's `EINTR`). (If `err_code` null, Runtime_error thrown.)
593 * 3. Neither condition above is detected before the timeout expires (if provided).
594 * Output semantics are the same as in 2, with the specific code error::Code::S_WAIT_USER_TIMEOUT.
595 *
596 * The semantics of -1- (the success case) equal those of receive().
597 *
598 * Note that it is NOT possible to return 0 and no error.
599 *
600 * Tip: Typical types you might use for `max_wait`: `boost::chrono::milliseconds`,
601 * `boost::chrono::seconds`, `boost::chrono::high_resolution_clock::duration`.
602 *
603 * @see The version of sync_receive() with no timeout.
604 * @tparam Rep
605 * See `boost::chrono::duration` documentation (and see above tip).
606 * @tparam Period
607 * See `boost::chrono::duration` documentation (and see above tip).
608 * @tparam Mutable_buffer_sequence
609 * See receive().
610 * @param target
611 * See receive().
612 * @param max_wait
613 * The maximum amount of time from now to wait before giving up on the wait and returning.
614 * `"duration<Rep, Period>::max()"` will eliminate the time limit and cause indefinite wait
615 * (i.e., no timeout).
616 * @param err_code
617 * See flow::Error_code docs for error reporting semantics.
618 * Error, except `WAIT_INTERRUPTED` or `WAIT_USER_TIMEOUT`, implies that
619 * neither this receive() nor any subsequent receive() on this socket
620 * will succeeed. (In particular a clean disconnect is an error.)
621 * @return Number of bytes (possibly zero) added to target. Always 0 if `bool(*err_code) == true` when
622 * sync_receive() returns.
623 */
624 template<typename Rep, typename Period, typename Mutable_buffer_sequence>
625 size_t sync_receive(const Mutable_buffer_sequence& target,
626 const boost::chrono::duration<Rep, Period>& max_wait, Error_code* err_code = 0);
627
628 /**
629 * `sync_receive()` operating in `nullptr_t` mode, wherein -- if Readable state is reached -- the actual data
630 * are not moved into any buffer, leaving that to the caller to do if desired. Hence, this is a way of waiting
631 * for Readable state that could be more concise in some situations than Event_set::sync_wait().
632 *
633 * ### Error handling ###
634 * These are the possible outcomes:
635 * 1. There are data in the Receive buffer; and socket is fully connected
636 * (`S_OPEN+S_CONNECTED`) or gracefully shutting down (`S_OPEN+S_DISCONNECTING`). Socket
637 * Readable. `true` is returned; `*err_code` is set to success unless null.
638 * 2. The operation cannot proceed due to an error. `false` is returned; `*err_code` is set to the
639 * specific error unless null. `*err_code == S_WAIT_INTERRUPTED` means the wait was
640 * interrupted (similarly to POSIX's `EINTR`). (If `err_code` null, Runtime_error thrown.)
641 * 3. Neither condition above is detected before the timeout expires (if provided).
642 * Output semantics are the same as in 2, with the specific code error::Code::S_WAIT_USER_TIMEOUT.
643 *
644 * Note that it is NOT possible to return `false` and no error.
645 *
646 * Tip: Typical types you might use for `max_wait`: `boost::chrono::milliseconds`,
647 * `boost::chrono::seconds`, `boost::chrono::high_resolution_clock::duration`.
648 *
649 * @tparam Rep
650 * See other sync_receive().
651 * @tparam Period
652 * See other sync_receive().
653 * @param max_wait
654 * See other sync_receive().
655 * @param err_code
656 * See flow::Error_code docs for error reporting semantics.
657 * Error, except `WAIT_INTERRUPTED` or `WAIT_USER_TIMEOUT`, implies that
658 * neither this nor any subsequent receive() on this socket
659 * will succeeed. (In particular a clean disconnect is an error.)
660 * @return `true` if there are 1+ bytes ready to read; `false` if either a timeout has occurred (no bytes ready), or
661 * another error has occurred.
662 */
663 template<typename Rep, typename Period>
664 bool sync_receive(std::nullptr_t,
665 const boost::chrono::duration<Rep, Period>& max_wait, Error_code* err_code = 0);
666
667 /**
668 * Equivalent to `sync_receive(target, duration::max(), err_code)`; i.e., sync_receive()
669 * with no timeout.
670 *
671 * @tparam Mutable_buffer_sequence
672 * See other sync_receive().
673 * @param target
674 * See other sync_receive().
675 * @param err_code
676 * See other sync_receive().
677 * @return See other sync_receive().
678 */
679 template<typename Mutable_buffer_sequence>
680 size_t sync_receive(const Mutable_buffer_sequence& target, Error_code* err_code = 0);
681
682 /**
683 * Equivalent to `sync_receive(nullptr, duration::max(), err_code)`; i.e., `sync_receive(nullptr_t)`
684 * with no timeout.
685 *
686 * @param err_code
687 * See other sync_receive().
688 * @return See other sync_receive().
689 */
690 bool sync_receive(std::nullptr_t, Error_code* err_code = 0);
691
692 /**
693 * Acts as if fatal error error::Code::S_USER_CLOSED_ABRUPTLY has been discovered on the
694 * connection. Does not block.
695 *
696 * Post-condition: `state() == State::S_CLOSED`. Additionally, assuming no loss on the
697 * network, the other side will close the connection with error
698 * error::Code::S_CONN_RESET_BY_OTHER_SIDE.
699 *
700 * Note: Discovering a fatal error on the connection would trigger all event waits on this socket
701 * (sync_send(), sync_receive(), Event_set::sync_wait(), Event_set::async_wait()) to execute on-event
702 * behavior (return, return, return, invoke handler, respectively). Therefore this method will cause
703 * just that, if applicable.
704 *
705 * Note: As a corollary, a socket closing this way (or any other way) does NOT cause that socket's
706 * events (if any) to be removed from any Event_set objects. Clearing an Event_set of all or some
707 * sockets is the Event_set user's responsibility (the classic way being Event_set::close()).
708 *
709 * @warning The moment the other side is informed we have abruptly closed the connection, they
710 * will no longer be able to receive() any of it (even if data had been queued up in
711 * their Receive buffer).
712 *
713 * @todo Currently this close_abruptly() is the only way for the user to explicitly close one specified socket.
714 * All other ways are due to error (or other side starting graceful shutdown, once we
715 * implement that). Once we implement graceful close, via `close_start()` and `close_final()`,
716 * use of close_abruptly() should be discouraged, or it may even be deprecated (e.g.,
717 * `Node`s lack a way to initiate an abrupt close for a specific socket).
718 *
719 * @todo close_abruptly() return `bool` (`false` on failure)?
720 *
721 * @param err_code
722 * See flow::Error_code docs for error reporting semantics. Generated codes:
723 * error::Code::S_NODE_NOT_RUNNING, or -- if socket already closed (`state() == State::S_CLOSED`) --
724 * then the error that caused the closure.
725 */
726 void close_abruptly(Error_code* err_code = 0);
727
728 /**
729 * Dynamically replaces the current options set (options()) with the given options set.
730 * Only those members of `opts` designated as dynamic (as opposed to static) may be different
731 * between options() and `opts`. If this is violated, it is an error, and no options are changed.
732 *
733 * Typically one would acquire a copy of the existing options set via options(), modify the
734 * desired dynamic data members of that copy, and then apply that copy back by calling
735 * set_options().
736 *
737 * @param opts
738 * The new options to apply to this socket. It is copied; no reference is saved.
739 * @param err_code
740 * See flow::Error_code docs for error reporting semantics. Generated codes:
741 * error::Code::S_STATIC_OPTION_CHANGED, error::Code::S_OPTION_CHECK_FAILED,
742 * error::Code::S_NODE_NOT_RUNNING.
743 * @return `true` on success, `false` on error.
744 */
745 bool set_options(const Peer_socket_options& opts, Error_code* err_code = 0);
746
747 /**
748 * Copies this socket's option set and returns that copy. If you intend to use set_options() to
749 * modify a socket's options, we recommend you make the modifications on the copy returned by
750 * options().
751 *
752 * @todo Provide a similar options() method that loads an existing structure (for structure
753 * reuse).
754 *
755 * @return See above.
756 */
758
759 /**
760 * Returns a structure containing the most up-to-date stats about this connection.
761 *
762 * @note At the cost of reducing locking overhead in 99.999999% of the Peer_socket's operation,
763 * this method may take a bit of time to run. It's still probably only 10 times or so slower than
764 * a simple lock, work, unlock -- there is a condition variable and stuff involved -- but this may
765 * matter if done very frequently. So you probably should not. (Hmmm... where did I get these estimates,
766 * namely "10 times or so"?)
767 *
768 * @todo Provide a similar info() method that loads an existing structure (for structure
769 * reuse).
770 *
771 * @return See above.
772 */
773 Peer_socket_info info() const;
774
775 /**
776 * The maximum number of bytes of user data per received or sent packet on this connection. See
777 * Peer_socket_options::m_st_max_block_size. Note that this method is ESSENTIAL when using the
778 * socket in unreliable mode (assuming you want to implement reliability outside of `net_flow`).
779 *
780 * @return Ditto.
781 */
782 size_t max_block_size() const;
783
784 /**
785 * The error code that perviously caused state() to become State::S_CLOSED, or success code if state
786 * is not CLOSED. For example, error::code::S_CONN_RESET_BY_OTHER_SIDE (if was connected) or
787 * error::Code::S_CONN_TIMEOUT (if was connecting)
788 *
789 * @return Ditto.
790 */
792
793protected:
794 // Constructors/destructor.
795
796 /**
797 * Constructs object; initializes most values to well-defined (0, empty, etc.) but not necessarily
798 * meaningful values.
799 *
800 * @param logger_ptr
801 * The Logger implementation to use subsequently.
802 * @param task_engine
803 * IO service for the timer(s) stored as data member(s).
804 * @param opts
805 * The options set to copy into this Peer_socket and use subsequently.
806 */
807 explicit Peer_socket(log::Logger* logger_ptr,
808 util::Task_engine* task_engine,
809 const Peer_socket_options& opts);
810
811private:
812 // Friends.
813
814 /**
815 * See rationale for `friend`ing Node in class Peer_socket documentation header.
816 * @see Node.
817 */
818 friend class Node;
819 /**
820 * See rationale for `friend`ing Server_socket in class Peer_socket documentation header.
821 * @see Server_socket.
822 */
823 friend class Server_socket;
824 /**
825 * For access to `Sent_pkt_by_sent_when_map` and Sent_packet types, at least.
826 * (Drop_timer has no actual Peer_socket instance to mess with.)
827 */
828 friend class Drop_timer;
829 /**
830 * Stats modules have const access to all socket internals.
831 * @see Send_bandwidth_estimator.
832 */
834 /**
835 * Congestion control modules have const access to all socket internals.
836 * @see Congestion_control_classic_data.
837 */
839 /**
840 * Congestion control modules have const access to all socket internals.
841 * @see Congestion_control_classic.
842 */
844 /**
845 * Congestion control modules have const access to all socket internals.
846 * @see Congestion_control_classic_with_bandwidth_est.
847 */
849
850 // Types.
851
852 /// Short-hand for `shared_ptr` to immutable Drop_timer (can't use Drop_timer::Ptr due to C++ and circular reference).
853 using Drop_timer_ptr = boost::shared_ptr<Drop_timer>;
854
855 /**
856 * Short-hand for high-performance, non-reentrant, exclusive mutex used to lock #m_opts.
857 *
858 * ### Rationale ###
859 * You might notice this seems tailor-made for shared/exclusive (a/k/a multiple-readers-single-writer) mutex.
860 * Why a 2-level mutex instead of a normal exclusive mutex? Because options can be accessed by
861 * thread W and various user threads, in the vast majority of the time to read option values. On
862 * the other hand, rarely, #m_opts may be modified via set_options(). To avoid thread contention
863 * when no one is writing (which is usual), we could use that 2-level type of mutex and apply the appropriate
864 * (shared or unique) lock depending on the situation. So why not? Answer:
865 * While a shared/exclusive mutex sounds lovely in theory -- and perhaps
866 * if its implementation were closer to the hardware it would be lovely indeed -- in practice it seems its
867 * implementation just causes performance problems rather than solving them. Apparently that's why
868 * it was rejected by C++11 standards people w/r/t inclusion in that standard. The people involved
869 * explained their decision here: http://permalink.gmane.org/gmane.comp.lib.boost.devel/211180.
870 * So until that is improved, just do this. I'm not even adding a to-do for fixing this, as that seems
871 * unlikely anytime soon. Update: C++17 added `std::shared_mutex`, and C++14 added a similar thing named
872 * something else. Seems like a good time to revisit this -- if not to materially improve #Options_mutex
873 * performance then to gain up-to-date knowledge on the topic, specifically whether `shared_mutex` is fast now.
874 * Update: Apparently as of Boost-1.80 the Boost.thread impl of `shared_mutex` is lacking in perf, and there
875 * is a ticket filed for many years for this. Perhaps gcc `std::shared_mutex` is fine. However research
876 * suggests it's less about this nitty-gritty of various impls and more the following bottom line:
877 * A simple mutex is *very* fast to lock/unlock, and perf problems occur only if one must wait for a lock.
878 * Experts say that it is possible but quite rare that there is enough lock contention to make it "worth it":
879 * a shared mutex is *much* slower to lock/unlock sans contention. Only when the read critical sections are
880 * long and very frequently accessed does it become "worth it."
881 */
883
884 /// Short-hand for lock that acquires exclusive access to an #Options_mutex.
886
887 /**
888 * Short-hand for reentrant mutex type. We explicitly rely on reentrant behavior, so this isn't "just in case."
889 *
890 * @todo This doc header for Peer_socket::Mutex should specify what specific behavior requires mutex reentrance, so
891 * that for example one could reevaluate whether there's a sleeker code pattern that would avoid it.
892 */
894
895 /// Short-hand for RAII lock guard of #Mutex.
897
898 /// Type used for #m_security_token.
899 using security_token_t = uint64_t;
900
901 /// Short-hand for order number type. 0 is reserved. Caution: Keep in sync with Drop_timer::packet_id_t.
903
904 /**
905 * The state of the socket (and the connection from this end's point of view) for the internal state
906 * machine governing the operation of the socket.
907 *
908 * @todo Peer_socket::Int_state will also include various states on way to a graceful close, once we implement that.
909 */
910 enum class Int_state
911 {
912 /// Closed (dead or new) socket.
913 S_CLOSED,
914
915 /**
916 * Public state is OPEN+CONNECTING; user requested active connect; we sent SYN and are
917 * awaiting response.
918 */
919 S_SYN_SENT,
920
921 /**
922 * Public state is OPEN+CONNECTING; other side requested passive connect via SYN; we sent
923 * SYN_ACK and are awaiting response.
924 */
925 S_SYN_RCVD,
926
927 /// Public state is OPEN+CONNECTED; in our opinion the connection is established.
928 S_ESTABLISHED
929 }; // enum class Int_state
930
931 // Friend of Peer_socket: For access to private alias Int_state.
932 friend std::ostream& operator<<(std::ostream& os, Int_state state);
933
934 struct Sent_packet;
935
936 /// Short-hand for #m_snd_flying_pkts_by_sent_when type; see that data member.
938
939 /// Short-hand for #m_snd_flying_pkts_by_sent_when `const` iterator type.
941
942 /// Short-hand for #m_snd_flying_pkts_by_sent_when iterator type.
944
945 /// Short-hand for #m_snd_flying_pkts_by_seq_num type; see that data member.
946 using Sent_pkt_by_seq_num_map = std::map<Sequence_number, Sent_pkt_ordered_by_when_iter>;
947
948 /// Short-hand for #m_snd_flying_pkts_by_seq_num `const` iterator type.
949 using Sent_pkt_ordered_by_seq_const_iter = Sent_pkt_by_seq_num_map::const_iterator;
950
951 /// Short-hand for #m_snd_flying_pkts_by_seq_num iterator type.
952 using Sent_pkt_ordered_by_seq_iter = Sent_pkt_by_seq_num_map::iterator;
953
954 struct Received_packet;
955
956 /**
957 * Short-hand for #m_rcv_packets_with_gaps type; see that data member. `struct`s are stored via
958 * shared pointers instead of as direct objects to minimize copying of potentially heavy-weight
959 * data. They are stored as shared pointers instead of as raw pointers to avoid having to
960 * worry about `delete`.
961 */
962 using Recvd_pkt_map = std::map<Sequence_number, boost::shared_ptr<Received_packet>>;
963
964 /// Short-hand for #m_rcv_packets_with_gaps `const` iterator type.
965 using Recvd_pkt_const_iter = Recvd_pkt_map::const_iterator;
966
967 /// Short-hand for #m_rcv_packets_with_gaps iterator type.
968 using Recvd_pkt_iter = Recvd_pkt_map::iterator;
969
970 struct Individual_ack;
971
972 /**
973 * Type used for #m_rcv_syn_rcvd_data_q. Using `vector` because we only need `push_back()` and
974 * iteration at the moment. Using pointer to non-`const` instead of `const` because when we actually handle the
975 * packet as received we will need to be able to modify the packet for performance (see
976 * Node::handle_data_to_established(), when it transfers data to Receive buffer).
977 */
978 using Rcv_syn_rcvd_data_q = std::vector<boost::shared_ptr<Data_packet>>;
979
980 /* Methods: as few as possible. Logic should reside in class Node as discussed (though
981 * implementation may be in peer_socket.cpp). See rationale in class Peer_socket
982 * documentation header. */
983
984 /**
985 * Non-template helper for template send() that forwards the send() logic to Node::send(). Would
986 * be pointless to try to explain more here; see code and how it's used. Anyway, this has to be
987 * in this class.
988 *
989 * @param snd_buf_feed_func
990 * Function that will perform and return `m_snd_buf->feed(...)`. See send().
991 * @param err_code
992 * See send().
993 * @return Value to be returned by calling Node::send().
994 */
995 size_t node_send(const Function<size_t (size_t max_data_size)>& snd_buf_feed_func,
996 Error_code* err_code);
997
998 /**
999 * Same as sync_send() but uses a #Fine_clock-based #Fine_duration non-template type for
1000 * implementation convenience and to avoid code bloat to specify timeout.
1001 *
1002 * @tparam Const_buffer_sequence
1003 * See sync_send().
1004 * @param data
1005 * See sync_send().
1006 * @param wait_until
1007 * See `sync_send(timeout)`. This is the absolute time point corresponding to that.
1008 * `"duration<Rep, Period>::max()"` maps to the value `Fine_time_pt()` (Epoch) for this argument.
1009 * @param err_code
1010 * See sync_send().
1011 * @return See sync_send().
1012 */
1013 template<typename Const_buffer_sequence>
1014 size_t sync_send_impl(const Const_buffer_sequence& data, const Fine_time_pt& wait_until,
1015 Error_code* err_code);
1016
1017 /**
1018 * Helper similar to sync_send_impl() but for the `nullptr_t` versions of `sync_send()`.
1019 *
1020 * @param wait_until
1021 * See sync_send_impl().
1022 * @param err_code
1023 * See sync_send_impl().
1024 * @return See `sync_send(nullptr_t)`. `true` if and only if Writable status successfuly reached in time.
1025 */
1026 bool sync_send_reactor_pattern_impl(const Fine_time_pt& wait_until, Error_code* err_code);
1027
1028 /**
1029 * This is to sync_send() as node_send() is to send().
1030 *
1031 * @param snd_buf_feed_func_or_empty
1032 * See node_send(). Additionally, if this is `.empty()` then `nullptr_t` a/k/a "reactor pattern" mode is
1033 * engaged.
1034 * @param wait_until
1035 * See sync_send_impl().
1036 * @param err_code
1037 * See sync_send().
1038 * @return See sync_send().
1039 */
1040 size_t node_sync_send(const Function<size_t (size_t max_data_size)>& snd_buf_feed_func_or_empty,
1041 const Fine_time_pt& wait_until,
1042 Error_code* err_code);
1043
1044 /**
1045 * Non-template helper for template receive() that forwards the receive() logic to
1046 * Node::receive(). Would be pointless to try to explain more here; see code and how it's used.
1047 * Anyway, this has to be in this class.
1048 *
1049 * @param rcv_buf_consume_func
1050 * Function that will perform and return `m_rcv_buf->consume(...)`. See receive().
1051 * @param err_code
1052 * See receive().
1053 * @return Value to be returned by calling Node::receive().
1054 */
1055 size_t node_receive(const Function<size_t ()>& rcv_buf_consume_func,
1056 Error_code* err_code);
1057
1058 /**
1059 * Same as sync_receive() but uses a #Fine_clock-based #Fine_duration non-template type
1060 * for implementation convenience and to avoid code bloat to specify timeout.
1061 *
1062 * @tparam Block_sequence
1063 * See sync_receive().
1064 * @param target
1065 * See sync_receive().
1066 * @param wait_until
1067 * See `sync_receive(timeout)`. This is the absolute time point corresponding to that.
1068 * `"duration<Rep, Period>::max()"` maps to the value `Fine_time_pt()` (Epoch) for this argument.
1069 * @param err_code
1070 * See sync_receive().
1071 * @return See sync_receive().
1072 */
1073 template<typename Mutable_buffer_sequence>
1074 size_t sync_receive_impl(const Mutable_buffer_sequence& target,
1075 const Fine_time_pt& wait_until, Error_code* err_code);
1076
1077 /**
1078 * Helper similar to sync_receive_impl() but for the `nullptr_t` versions of `sync_receive()`.
1079 *
1080 * @param wait_until
1081 * See sync_receive_impl().
1082 * @param err_code
1083 * See sync_receive_impl().
1084 * @return See `sync_receive(nullptr_t)`. `true` if and only if Readable status successfuly reached in time.
1085 */
1086 bool sync_receive_reactor_pattern_impl(const Fine_time_pt& wait_until, Error_code* err_code);
1087
1088 /**
1089 * This is to sync_receive() as node_receive() is to receive().
1090 *
1091 * @param rcv_buf_consume_func_or_empty
1092 * See node_receive(). Additionally, if this is `.empty()` then `nullptr_t` a/k/a "reactor pattern" mode is
1093 * engaged.
1094 * @param wait_until
1095 * See sync_receive_impl().
1096 * @param err_code
1097 * See sync_receive().
1098 * @return See sync_receive().
1099 */
1100 size_t node_sync_receive(const Function<size_t ()>& rcv_buf_consume_func_or_empty,
1101 const Fine_time_pt& wait_until,
1102 Error_code* err_code);
1103
1104 /**
1105 * Analogous to Node::opt() but for per-socket options. See that method.
1106 *
1107 * Do NOT read option values without opt().
1108 *
1109 * @tparam Opt_type
1110 * The type of the option data member.
1111 * @param opt_val_ref
1112 * A reference (important!) to the value you want; this may be either a data member of
1113 * this->m_opts or the entire this->m_opts itself.
1114 * @return A copy of the value at the given reference.
1115 */
1116 template<typename Opt_type>
1117 Opt_type opt(const Opt_type& opt_val_ref) const;
1118
1119 /**
1120 * Returns the smallest multiple of max_block_size() that is >= the given option value, optionally
1121 * first inflated by a certain %. The intended use case is to obtain a Send of Receive buffer max
1122 * size that is about equal to the user-specified (or otherwise obtained) value, in bytes, but is
1123 * a multiple of max-block-size -- to prevent fragmenting max-block-size-sized chunks of data unnecessarily -- and
1124 * to possibly inflate that value by a certain percentage for subtle flow control reasons.
1125 *
1126 * @param opt_val_ref
1127 * A reference to a `size_t`-sized socket option, as would be passed to opt(). See opt().
1128 * This is the starting value.
1129 * @param inflate_pct_val_ptr
1130 * A pointer to an `unsigned int`-sized socket option, as would be passed to opt(). See
1131 * opt(). This is the % by which to inflate opt_val_ref before rounding up to nearest
1132 * max_block_size() multiple. If null, the % is assumed to be 0.
1133 * @return See above.
1134 */
1135 size_t max_block_size_multiple(const size_t& opt_val_ref,
1136 const unsigned int* inflate_pct_val_ptr = 0) const;
1137
1138 /**
1139 * Whether retransmission is enabled on this connection. Short-hand for appropriate opt() call.
1140 * Note this always returns the same value for a given object.
1141 *
1142 * @return Ditto.
1143 */
1144 bool rexmit_on() const;
1145
1146 /**
1147 * Helper that is equivalent to Node::ensure_sock_open(this, err_code). Used by templated
1148 * methods which must be defined in this header file, which means they cannot access Node members
1149 * directly, as Node is an incomplete type.
1150 *
1151 * @param err_code
1152 * See Node::ensure_sock_open().
1153 * @return See Node::ensure_sock_open().
1154 */
1155 bool ensure_open(Error_code* err_code) const;
1156
1157 /**
1158 * Helper that, given a byte count, returns a string with that byte count and the number of
1159 * max_block_size()-size blocks that can fit within it (rounded down).
1160 *
1161 * @param bytes
1162 * @return See above.
1163 */
1164 std::string bytes_blocks_str(size_t bytes) const;
1165
1166 // Data.
1167
1168 /**
1169 * This socket's per-socket set of options. Initialized at construction; can be subsequently
1170 * modified by set_options(), although only the dynamic members of this may be modified.
1171 *
1172 * Accessed from thread W and user thread U != W. Protected by #m_opts_mutex. When reading, do
1173 * NOT access without locking (which is encapsulated in opt()).
1174 */
1176
1177 /// The mutex protecting #m_opts.
1179
1180 /// `true` if we connect() to server; `false` if we are to be/are `accept()`ed. Should be set once and not modified.
1182
1183 /**
1184 * See state(). Should be set before user gets access to `*this`. Must not be modified by non-W threads after that.
1185 *
1186 * Accessed from thread W and user threads U != W (in state() and others). Must be protected
1187 * by mutex.
1188 */
1190
1191 /**
1192 * See state(). Should be set before user gets access to `*this`. Must not be modified by non-W
1193 * threads after that.
1194 *
1195 * Accessed from thread W and user threads U != W (in state() and others). Must be protected by
1196 * mutex.
1197 */
1199
1200 /**
1201 * See node(). Should be set before user gets access to `*this` and not changed, except to null when
1202 * state is State::S_CLOSED. Must not be modified by non-W threads.
1203 *
1204 * Invariant: `x->node() == y` if and only if `y->m_socks` contains `x`; otherwise `!x->node()`.
1205 * The invariant must hold by the end of the execution of any thread W boost.asio handler (but
1206 * not necessarily at all points within that handler, or generally).
1207 *
1208 * Accessed from thread W and user threads U != W (in node() and others). Must be protected by
1209 * mutex.
1210 *
1211 * @todo `boost::weak_ptr<Node>` would be ideal for this, but of course then Node would have to
1212 * (only?) be available via shared_ptr<>.
1213 */
1215
1216 /**
1217 * For sockets that come a Server_socket, this is the inverse of Server_socket::m_connecting_socks: it is
1218 * the Server_socket from which this Peer_socket will be Server_socket::accept()ed (if that succeeds); or null if
1219 * this is an actively-connecting Peer_socket or has already been `accept()`ed.
1220 *
1221 * More formally, this is null if #m_active_connect; null if not the case but already accept()ed; and otherwise:
1222 * `((y->m_connecting_socks contains x) || (y->m_unaccepted_socks contains x))` if and only if
1223 * `x->m_originating_serv == y`. That is, for a socket in state Int_state::S_SYN_RCVD, or in state
1224 * Int_state::S_ESTABLISHED, but before being accept()ed by the user, this is the server socket that spawned this
1225 * peer socket.
1226 *
1227 * ### Thread safety ###
1228 * This can be write-accessed simultaneously by thread W (e.g., when closing a
1229 * socket before it is accepted) and a user thread U != W (in Server_socket::accept()). It is
1230 * thus protected by a mutex -- but it's Server_socket::m_mutex, not Peer_socket::m_mutex. I
1231 * know it's weird, but it makes sense. Basically Server_socket::m_unaccepted_socks and
1232 * Server_socket::m_originating_serv -- for each element of `m_unaccepted_socks` -- are modified together
1233 * in a synchronized way.
1234 *
1235 * @see Server_socket::m_connecting_socks and Server_socket::m_unaccepted_socks for the closely
1236 * related inverse.
1237 */
1239
1240 /**
1241 * The Receive buffer; Node feeds data at the back; user consumes data at the front. Contains
1242 * application-layer data received from the other side, to be read by user via receive() and
1243 * similar.
1244 *
1245 * A maximum cumulative byte count is maintained. If data are received that would exceed this max
1246 * (i.e., the user is not retrieving the data fast enough to keep up), these data are dropped (and
1247 * if we use ACKs would be eventually treated as dropped by the other side).
1248 *
1249 * Note that this is a high-level structure, near the application layer. This does not store any
1250 * metadata, like sequence numbers, or data not ready to be consumed by the user (such as
1251 * out-of-order packets, if we implement that). Such packets and data should be stored elsewhere.
1252 *
1253 * ### Thread safety ###
1254 * This can be write-accessed simultaneously by thread W (when receiving by Node)
1255 * and a user thread U != W (in receive(), etc.). It is thus protected by a mutex.
1256 */
1258
1259 /**
1260 * The Send buffer; user feeds data at the back; Node consumes data at the front. Contains
1261 * application-layer data to be sent to the other side as supplied by user via send() and friends.
1262 *
1263 * A maximum cumulative byte count is maintained. If data are supplied that would exceed
1264 * this max (i.e., the Node is not sending the data fast enough to keep up), send() will
1265 * inform the caller that fewer bytes than intended have been buffered. Typically this happens if
1266 * the congestion control window is full, so data are getting buffered in #m_snd_buf instead of
1267 * being immediately consumed and sent.
1268 *
1269 * Note that this is a high-level structure, near the application layer. This does not store any
1270 * metadata, like sequence numbers, or data not ready to be consumed by the user (such as
1271 * out-of-order packets, if we implement that). Such packets and data should be stored elsewhere.
1272 *
1273 * Thread safety: Analogous to #m_rcv_buf.
1274 */
1276
1277 /**
1278 * The #Error_code causing disconnection (if one has occurred or is occurring)
1279 * on this socket; otherwise a clear (success) #Error_code. This starts as success
1280 * and may move to one non-success value and then never change after that. Graceful connection
1281 * termination is (unlike in BSD sockets, where this is indicated with receive() returning 0, not an
1282 * error) indeed counted as a non-success value for #m_disconnect_cause.
1283 *
1284 * Exception: if, during graceful close, the connection must be closed abruptly (due to error,
1285 * including error::Code::S_USER_CLOSED_ABRUPTLY), #m_disconnect_cause may change a second time (from "graceful close"
1286 * to "abrupt closure").
1287 *
1288 * As in TCP net-stacks, one cannot recover from a transmission error or termination on the socket
1289 * (fake "error" `EWOULDBLOCK`/`EAGAIN` excepted), which is why this can only go success ->
1290 * non-success and never change after that.
1291 *
1292 * How to report this to the user: attempting to `*receive()` when not Readable while
1293 * #m_disconnect_cause is not success => `*receive()` returns this #Error_code to the user; and
1294 * similarly for `*send()` and Writable.
1295 *
1296 * I emphasize that this should happen only after Receive buffer has been emptied; otherwise user
1297 * will not be able to read queued up received data after the Node internally detects connection
1298 * termination. By the same token, if the Node can still reasonably send data to the other side,
1299 * and Send buffer is not empty, and #m_disconnect_cause is not success, the Node should only halt
1300 * the packet sending once Send buffer has been emptied.
1301 *
1302 * This should be success in all states except State::S_CLOSED and
1303 * State::S_OPEN + Open_sub_state::S_DISCONNECTING.
1304 *
1305 * ### Thread safety ###
1306 * Since user threads will access this at least via receive() and send(), while
1307 * thread W may set it having detected disconnection, this must be protected by a mutex.
1308 */
1310
1311 /**
1312 * If `!m_active_connect`, this contains the serialized metadata that the user supplied on
1313 * the other side when initiating the connect; otherwise this is the serialized metadata that the user
1314 * supplied on this side when initiating the connect. In either case (though obviously more
1315 * useful in the `!m_active_connect` case) it can be obtained via get_connect_metadata().
1316 * In the `m_active_connect` case, this is also needed if we must re-send the original SYN
1317 * (retransmission).
1318 *
1319 * ### Thread safety ###
1320 * Same as #m_snd_buf and #m_rcv_buf (protected by #m_mutex). This would not be
1321 * necessary, since this value is immutable once user gets access to `*this`, and threads other than
1322 * W can access it, but sock_free_memory() does clear it while the user may be accessing it. Due
1323 * to that caveat, we have to lock it.
1324 */
1326
1327 /**
1328 * This object's mutex. The protected items are #m_state, #m_open_sub_state, #m_disconnect_cause,
1329 * #m_node, #m_rcv_buf, #m_snd_buf, #m_serialized_metadata.
1330 *
1331 * Generally speaking, if 2 or more of the protected variables must be changed in the same
1332 * non-blocking "operation" (for some reasonable definition of "operation"), they should probably
1333 * be changed within the same #m_mutex-locking critical section. For example, if closing the
1334 * socket in thread W due to an incoming RST, one should lock #m_mutex, clear both buffers, set
1335 * #m_disconnect_cause, change `m_state = State::S_CLOSED`, and then unlock #m_mutex. Then thread U != W
1336 * will observe all this state changed at the "same time," which is desirable.
1337 */
1339
1340 /// See remote_endpoint(). Should be set before user gets access to `*this` and not changed afterwards.
1342
1343 /// See local_port(). Should be set before user gets access to `*this` and not changed afterwards.
1345
1346 /**
1347 * Current internal state of the socket. Note this is a very central piece of information and is analogous
1348 * to TCP's "state" (ESTABLISHED, etc. etc.).
1349 *
1350 * This gains meaning only in thread W. This should NOT be
1351 * accessed outside of thread W and is not protected by a mutex.
1352 */
1354
1355 /**
1356 * The queue of DATA packets received while in Int_state::S_SYN_RCVD state before the
1357 * Syn_ack_ack_packet arrives to move us to Int_state::S_ESTABLISHED
1358 * state, at which point these packets can be processed normally. Such
1359 * DATA packets would not normally exist, but they can exist if the SYN_ACK_ACK is lost or DATA
1360 * packets are re-ordered to go ahead of it. See Node::handle_data_to_syn_rcvd() for more
1361 * detail.
1362 *
1363 * This gains meaning only in thread W. This should NOT be accessed outside of thread W
1364 * and is not protected by a mutex.
1365 */
1367
1368 /**
1369 * The running total count of bytes in the `m_data` fields of #m_rcv_syn_rcvd_data_q. Undefined
1370 * when the latter is empty. Used to limit its size. This gains meaning only in thread W. This
1371 * should NOT be accessed outside of thread W and is not protected by a mutex.
1372 */
1374
1375 /**
1376 * The Initial Sequence Number (ISN) contained in the original Syn_packet or
1377 * Syn_ack_packet we received.
1378 *
1379 * This gains meaning only in thread W. This should NOT be accessed outside of thread W and is
1380 * not protected by a mutex. Useful at least in verifying the validity of duplicate SYNs and
1381 * SYN_ACKs.
1382 */
1384
1385 /**
1386 * The maximal sequence number R from the remote side such that all data with sequence numbers
1387 * strictly less than R in this connection have been received by us and placed into the Receive
1388 * buffer. This first gains meaning upon receiving SYN and is the sequence number of that SYN,
1389 * plus one (as in TCP); or upon receiving SYN_ACK (similarly). Note that received packets past
1390 * this sequence number may exist, but if so there is at least one missing packet (the one at
1391 * #m_rcv_next_seq_num) preceding all of them.
1392 *
1393 * @see #m_rcv_packets_with_gaps.
1394 *
1395 * This gains meaning only in thread W. This should NOT be accessed outside of thread W and is
1396 * not protected by a mutex.
1397 */
1399
1400 /**
1401 * The sequence-number-ordered collection of all
1402 * received-and-not-dropped-due-to-buffer-overflow packets such that at least
1403 * one unreceived-or-otherwise-unknown datum precedes all sequence numbers in this collection;
1404 * a/k/a the reassembly queue if retransmission is enabled.
1405 * With retransmission off, the only purpose of keeping this structure at all is to detect any
1406 * already-received-and-given-to-Receive-buffer packet coming in again; such a packet should be
1407 * ACKed but NOT given to the Receive buffer again (avoid data duplication). With retransmission
1408 * on, this is additionally used as the reassembly queue (storing the non-contiguous data until
1409 * the gaps are filled in).
1410 *
1411 * The structure is best explained by breaking down the sequence number space. I list the
1412 * sequence number ranges in increasing order starting with the ISN. Let `last_rcv_seq_num` be the
1413 * sequence number of the last datum to have been received (and not dropped due to insufficient
1414 * Receive buffer space), for exposition purposes.
1415 *
1416 * - #m_rcv_init_seq_num =
1417 * - SYN or SYN_ACK
1418 *
1419 * - [`m_rcv_init_seq_num + 1`, `m_rcv_next_seq_num - 1`] =
1420 * - Largest possible range of sequence numbers such that each datum represented by this range
1421 * has been received (and not dropped due to insufficient Receive buffer space) and copied to
1422 * the Receive buffer for user retrieval.
1423 *
1424 * - [#m_rcv_next_seq_num, `m_rcv_next_seq_num + N - 1`] =
1425 * - The first packet after the ISN that has not yet been received (or has been received but has
1426 * been dropped due to insufficient Receive buffer space). `N` is the (unknown to us) length of
1427 * that packet. `N` > 0. This can be seen as the first "gap" in the received sequence number
1428 * space.
1429 *
1430 * - [`m_rcv_next_seq_num + N`, `last_rcv_seq_num`] =
1431 * - The remaining packets up to and including the last byte that has been received (and not
1432 * dropped due to insufficient Receive buffer space). Each packet in this range is one of the
1433 * following:
1434 * - received (and not dropped due to insufficient Receive buffer space);
1435 * - not received (or received and dropped due to insufficient Receive buffer space).
1436 *
1437 * - [`last_rcv_seq_num + 1`, ...] =
1438 * - All remaining not-yet-received (or received but dropped due to insufficient Receive buffer
1439 * space) packets.
1440 *
1441 * #m_rcv_packets_with_gaps contains all Received_packets in the range [`m_rcv_next_seq_num + N`,
1442 * `last_rcv_seq_num`], with each particular Received_packet's first sequence number as its key. If
1443 * there are no gaps -- all received sequence numbers are followed by unreceived sequence numbers
1444 * -- then that range is empty and so is #m_rcv_packets_with_gaps. All the other ranges can be
1445 * null (empty) as well. If there are no received-and-undropped packets, then `m_rcv_init_seq_num
1446 * == m_rcv_next_seq_num`, which is the initial situation.
1447 *
1448 * The above is an invariant, to be true at the end of each boost.asio handler in thread W, at
1449 * least.
1450 *
1451 * Each received-and-undropped packet therefore is placed into #m_rcv_packets_with_gaps, anywhere
1452 * in the middle. If retransmission is off, the data in the packet is added to Receive buffer.
1453 * If retransmission is on, the data in the packet is NOT added to Receive buffer but instead
1454 * saved within the structure for later reassembly (see next paragraph).
1455 *
1456 * If the [#m_rcv_next_seq_num, ...] (first gap) packet is received-and-not-dropped, then
1457 * #m_rcv_next_seq_num is incremented by N (the length of that packet), filling the gap. Moreover,
1458 * any contiguous packets at the front of #m_rcv_packets_with_gaps, assuming the first packet's
1459 * sequence number equals #m_rcv_next_seq_num, must be removed from #m_rcv_packets_with_gaps, and
1460 * #m_rcv_next_seq_num should be incremented accordingly. All of this maintains the invariant. If
1461 * retransmission is on, the data in the byte sequence formed by this operation is to be placed
1462 * (in sequence number order) into the Receive buffer (a/k/a reassembly).
1463 *
1464 * Conceptually, this is the action of receiving a gap packet which links up following
1465 * already-received packets to previous already-received packets, which means all of these can go
1466 * away, as the window slides forward beyond them.
1467 *
1468 * If a packet arrives and is already in #m_rcv_packets_with_gaps, then it is a duplicate and is
1469 * NOT placed on the Receive buffer. The same holds for any packet with sequence numbers
1470 * preceding #m_rcv_next_seq_num.
1471 *
1472 * The type used is a map sorted by starting sequence number of each packet. Why? We need pretty
1473 * fast middle operations, inserting and checking for existence of arriving packet. We need fast
1474 * access to the earliest (smallest sequence number) packet, for when the first gap is filled.
1475 * `std::map` satisfies these needs: `insert()` and `lower_bound()` are <em>O(log n)</em>; `begin()` gives the
1476 * smallest element and is @em O(1). Iteration is @em O(1) as well. (All amortized.)
1477 *
1478 * ### Memory use ###
1479 * The above scheme allows for unbounded memory use given certain behavior from the
1480 * other side, when retransmission is off. Suppose packets 1, 2, 3 are received; then packets 5,
1481 * 6, ..., 1000 are received. Retransmission is off, so eventually the sender
1482 * may give up on packet 4 and consider it Dropped. So the gap will forever exist; hence
1483 * #m_rcv_packets_with_gaps will always hold per-packet data for 5, 6, ..., 1000 (and any
1484 * subsequent packets). With retransmission, packet 4 would eventually arrive, or the connection
1485 * would get RSTed, but without retransmission that doesn't happen. Thus memory use will just
1486 * grow and grow. Solution: come up with some heuristic that would quite conservatively declare
1487 * that packet 4 has been "received," even though it hasn't. This will plug the hole (packet 4)
1488 * and clear #m_rcv_packets_with_gaps in this example. Then if packet 4 does somehow come in, it
1489 * will get ACKed (like any valid received packet) but will NOT be saved into the Receive buffer,
1490 * since it will be considered "duplicate" due to already being "received." Of course, the
1491 * heuristic must be such that few if any packets considered "received" this way will actually get
1492 * delivered eventually, otherwise we may lose a lot of data. Here is one such heuristic, that is
1493 * both simple and conservative: let N be some constant (e.g., N = 100). If
1494 * `m_rcv_packets_with_gaps.size()` exceeds N (i.e., equals (N + 1)), consider all gap packets
1495 * preceding #m_rcv_packets_with_gaps's first sequence number as "received." This will, through
1496 * gap filling logic described above, reduce `m_rcv_packets_with_gaps.size()` to N or less. Thus it
1497 * puts a simple upper bound on #m_rcv_packets_with_gaps's memory; if N = 100 the memory used by
1498 * the structure is not much (since we don't store the actual packet data there [but this can get
1499 * non-trivial with 100,000 sockets all filled up]). Is it conservative? Yes. 100 packets
1500 * arriving after a gap are a near-guarantee those gap packets will never arrive (especially
1501 * without retransmission, which is the predicate for this entire problem). Besides, the Drop
1502 * heuristics on the Sender side almost certainly will consider gap packets with 100 or near 100
1503 * Acknowledged packets after them as Dropped a long time ago; if the receiving side's heuristics
1504 * are far more conservative, then that is good enough.
1505 *
1506 * If retransmission is on, then (as noted) the sender's CWND and retransmission logic will ensure
1507 * that gaps are filled before more future data are sent, so the above situation will not occur.
1508 * However if the sender is a bad boy and for some reason sends new data and ignores gaps
1509 * (possibly malicious behavior), then it would still be a problem. Since in retransmission mode
1510 * it's not OK to just ignore lost packets, we have no choice but to drop received packets when
1511 * the above situation occurs (similarly to when Receive buffer is exceeded). This is basically a
1512 * security measure and should not matter assuming well-behaved operation from the other side.
1513 * Update: With retransmission on, this structure is now subject to overflow protection with a tighter
1514 * limit than with rexmit-off; namely, the limit controlling #m_rcv_buf overflow actually applies to
1515 * the sum of data being stored in #m_rcv_buf and this structure, together. I.e., a packet is dropped
1516 * if the total data stored in #m_rcv_buf and #m_rcv_packets_with_gaps equal or exceed the configured
1517 * limit. Accordingly, rcv-wnd advertised to other side is based on this sum also.
1518 *
1519 * This gains meaning only in thread W. This should NOT be accessed outside of thread W and is
1520 * not protected by a mutex.
1521 *
1522 * @see #m_rcv_reassembly_q_data_size.
1523 *
1524 * @todo The memory use of this structure could be greatly optimized if, instead of storing each
1525 * individual received packet's metadata separately, we always merged contiguous sequence number
1526 * ranges. So for example if packet P1, P2, P3 (contiguous) all arrived in sequence, after
1527 * missing packet P0, then we'd store P1's first sequence number and the total data size of
1528 * P1+P2+P3, in a single `struct` instance. Since a typical pattern might include 1 lost packet
1529 * followed by 100 received packets, we'd be able to cut down memory use by a factor of about 100
1530 * in that case (and thus worry much less about the limit). Of course the code would get more
1531 * complex and potentially slower (but not necessarily significantly).
1532 */
1534
1535 /**
1536 * With retransmission enabled, the sum of Received_packet::m_size over all packets stored in the
1537 * reassembly queue, #m_rcv_packets_with_gaps. Stored for performance.
1538 *
1539 * This gains meaning only in thread W. This should NOT be accessed outside of thread W and is
1540 * not protected by a mutex.
1541 */
1543
1544 /**
1545 * The received packets to be acknowledged in the next low-level ACK packet to be sent to the
1546 * other side, ordered in the chronological order they were received. They are accumulated in a
1547 * data structure because we may not send each desired acknowledgment right away, combining
1548 * several together, thus reducing overhead at the cost of short delays (or even nearly
1549 * non-existent delays, as in the case of several DATA packets handled in one
1550 * NodeLLlow_lvl_recv_and_handle() invocation, i.e., having arrived at nearly at the same time).
1551 *
1552 * Any two packets represented by these Individual_ack objects may be duplicates of each other (same
1553 * Sequence_number, possibly different Individual_ack::m_received_when values). It's up to the sender (receiver
1554 * of ACK) to sort it out. However, again, they MUST be ordered chronologicaly based on the time
1555 * when they were received; from earliest to latest.
1556 *
1557 * Storing shared pointers to avoid copying of structs (however small) during internal
1558 * reshuffling; shared instead of raw pointers to not worry about delete.
1559 *
1560 * This gains meaning only in thread W. This should NOT be accessed outside of thread W and is
1561 * not protected by a mutex.
1562 */
1563 std::vector<boost::shared_ptr<Individual_ack>> m_rcv_pending_acks;
1564
1565 /**
1566 * Helper state, to be used while inside either Node::low_lvl_recv_and_handle() or
1567 * async part of Node::async_wait_latency_then_handle_incoming(), set only at the beginning of either and equal to
1568 * `m_rcv_pending_acks.size()` at that time. Because, for efficiency, individual acknowledgements are
1569 * accumulated over the course of those two methods, and an ACK with those acknowledgments is
1570 * sent at the end of that method (in perform_accumulated_on_recv_tasks()) at the earliest, this
1571 * member is used to determine whether we should start a delayed ACK timer at that point.
1572 *
1573 * This gains meaning only in thread W and only within Node::low_lvl_recv_and_handle()/etc.
1574 * and loses meaning after either method exits. This should NOT
1575 * be accessed outside of thread W and is not protected by a mutex.
1576 */
1578
1579 /**
1580 * While Node::low_lvl_recv_and_handle() or async part of Node::async_wait_latency_then_handle_incoming() is running,
1581 * accumulates the individual acknowledgments contained in all incoming ACK low-level packets
1582 * received in those methods. More precisely, this accumulates the elements of
1583 * `packet.m_rcv_acked_packets` for all packets such that `packet` is an Ack_packet. They are accumulated
1584 * in this data structure for a similar reason that outgoing acknowledgments are accumulated in
1585 * `Peer_socket::m_rcv_pending_acks`. The situation here is simpler, however, since the present
1586 * structure is always scanned and cleared at the end of the current handler and never carried
1587 * over to the next, as we always want to scan all individual acks received within a non-blocking
1588 * amount of time from receipt. See Node::handle_ack_to_established() for details.
1589 *
1590 * This structure is empty, accumulated over the course of those methods, is used to finally scan
1591 * all individual acknowledgments (in the exact order received), and then cleared for the next
1592 * run.
1593 *
1594 * Storing shared pointers to avoid copying of structs (however small) during internal
1595 * reshuffling; shared instead of raw pointers to not worry about delete.
1596 *
1597 * This gains meaning only in thread W and only within Node::low_lvl_recv_and_handle()/etc.
1598 * and loses meaning after either method exits. This should NOT
1599 * be accessed outside of thread W and is not protected by a mutex.
1600 */
1601 std::vector<Ack_packet::Individual_ack::Ptr> m_rcv_acked_packets;
1602
1603 /**
1604 * While Node::low_lvl_recv_and_handle() or async part of Node::async_wait_latency_then_handle_incoming() is running,
1605 * contains the rcv_wnd (eventual #m_snd_remote_rcv_wnd) value in the last observed ACK low-level
1606 * packet received in those methods. The reasoning is similar to #m_rcv_acked_packets. See
1607 * Node::handle_ack_to_established() for details.
1608 *
1609 * This gains meaning only in thread W and only within Node::low_lvl_recv_and_handle()/etc.
1610 * and loses meaning after either method exits. This should NOT
1611 * be accessed outside of thread W and is not protected by a mutex.
1612 */
1614
1615 /**
1616 * The last rcv_wnd value sent to the other side (in an ACK). This is used to gauge how much the
1617 * true rcv_wnd has increased since the value that the sender probably (assuming ACK was not lost)
1618 * knows.
1619 *
1620 * This gains meaning only in thread W. This should NOT be accessed outside of thread W and is
1621 * not protected by a mutex.
1622 */
1624
1625 /**
1626 * `true` indicates we are in a state where we've decided other side needs to be informed that
1627 * our receive window has increased substantially, so that it can resume sending data (probably
1628 * after a zero window being advertised).
1629 *
1630 * This gains meaning only in thread W. This should NOT be accessed outside of thread W and is
1631 * not protected by a mutex.
1632 */
1634
1635 /**
1636 * Time point at which #m_rcv_in_rcv_wnd_recovery was last set to true. It is only used when the
1637 * latter is indeed true.
1638 *
1639 * This gains meaning only in thread W. This should NOT be accessed outside of thread W and is
1640 * not protected by a mutex.
1641 */
1643
1644 /**
1645 * When #m_rcv_in_rcv_wnd_recovery is `true`, this is the scheduled task to possibly
1646 * send another unsolicited rcv_wnd-advertising ACK to the other side.
1647 *
1648 * This gains meaning only in thread W. This should NOT be accessed outside of thread W and is
1649 * not protected by a mutex.
1650 */
1652
1653 /**
1654 * Timer started, assuming delayed ACKs are enabled, when the first Individual_ack is placed onto
1655 * an empty #m_rcv_pending_acks; when it triggers, the pending individual acknowledgments are packed
1656 * into as few as possible ACKs and sent to the other side. After the handler exits
1657 * #m_rcv_pending_acks is again empty and the process can repeat starting with the next received valid
1658 * packet.
1659 *
1660 * This gains meaning only in thread W. This should NOT be accessed outside of thread W and is
1661 * not protected by a mutex.
1662 *
1663 * ### Implementation notes ###
1664 * In other places we have tended to replace a `Timer` with the far simpler util::schedule_task_from_now() (etc.)
1665 * facility (which internally uses a `Timer` but hides its various annoyances and caveats). Why not here?
1666 * Answer: This timer is scheduled and fires often (could be on the order of every 1-500 milliseconds) and throughout
1667 * a given socket's existence; hence the potential performance effects aren't worth the risk (or at least mental
1668 * energy spent on evaluating that risk, originally and over time). The conservative thing to do is reuse a single
1669 * `Timer` repeatedly, as we do here.
1670 */
1672
1673 /// Stats regarding incoming traffic (and resulting outgoing ACKs) for this connection so far.
1675
1676 /**
1677 * The Initial Sequence Number (ISN) used in our original SYN or SYN_ACK. Useful at least in re-sending the
1678 * original SYN or SYN_ACK if unacknowledged for too long.
1679 *
1680 * @see #m_snd_flying_pkts_by_seq_num and #m_snd_flying_pkts_by_sent_when.
1681 *
1682 * This gains meaning only in thread W. This should NOT be accessed outside of thread W and is
1683 * not protected by a mutex.
1684 */
1686
1687 /**
1688 * The sequence number for the start of the data in the next new DATA packet to be sent out. By
1689 * "new" I mean not-retransmitted (assuming retransmission is even enabled).
1690 *
1691 * @todo Possibly #m_snd_next_seq_num will apply to other packet types than DATA, probably anything to do with
1692 * connection termination.
1693 *
1694 * @see #m_snd_flying_pkts_by_seq_num and #m_snd_flying_pkts_by_sent_when.
1695 *
1696 * This gains meaning only in thread W. This should NOT be accessed outside of thread W and is
1697 * not protected by a mutex.
1698 */
1700
1701 /**
1702 * The collection of all In-flight packets, indexed by sequence number and ordered from most to
1703 * least recently sent (including those queued up to wire-send in pacing module). See also
1704 * #m_snd_flying_pkts_by_seq_num which is a similar map but in order of sequence number.
1705 * That map's keys are again sequence numbers, but its values are iterators into the present map
1706 * to save memory and avoid having to sync up data between the two (the only thing we must sync between them
1707 * are their key sets). The two maps together can be considered to be the sender-side "scoreboard."
1708 *
1709 * These are all the packets that have been sent but not Acknowledged that we have not yet considered
1710 * Dropped. (With retransmission on, packets are never considered
1711 * permanently Dropped, but they are considered Dropped until retransmitted.) With retransmission
1712 * off, the ultimate goal of having this structure at all is to handle ACKs, the ultimate goal of
1713 * which is, in turn, for the In-flight vs. Congestion Window comparison for congestion control.
1714 * With retransmission on, the structure additionally stores the data in the In-flight packets, so
1715 * that they can be retransmitted if we determine they were probably dropped.
1716 *
1717 * With retransmission on, this is NOT the retransmission queue itself -- i.e., this does NOT
1718 * store packet data that we know should be retransmitted when possible but rather only the data
1719 * already In-flight (whether from first attempt or from retransmission).
1720 *
1721 * Please see #m_snd_flying_pkts_by_seq_num for a breakdown of the sequence number space.
1722 * Since that structure contains iterators to exactly the values in the present map, that comment will
1723 * explain which packets are in the present map.
1724 *
1725 * #m_snd_flying_pkts_by_sent_when contains In-flight Sent_packet objects as values, with each particular
1726 * Sent_packet's first sequence number as its key. If there are no In-flight Sent_packet objects, then
1727 * `m_snd_flying_pkts_by_sent_when.empty()`.
1728 *
1729 * The above is an invariant, to be true at the end of each boost.asio handler in thread W, at
1730 * least.
1731 *
1732 * Each sent packet therefore is placed into #m_snd_flying_pkts_by_sent_when, at the front (as is standard
1733 * for a Linked_hash_map, and as is expected, since they are ordered by send time). (Note, however,
1734 * that being in this map does not mean it has been sent; it may only be queued up to be sent and
1735 * waiting in the pacing module; however, pacing does not change the order of packets but merely
1736 * the exact send moment, which cannot change the position in this queue.)
1737 * When a packet is Acknowledged, it is removed from #m_snd_flying_pkts_by_sent_when -- could be from anywhere
1738 * in the ordering. Similarly to Acknowledged packets, Dropped ones are also removed.
1739 *
1740 * The type used is a map indexed by starting sequence number of each packet but also in order of
1741 * being sent out. Lookup by sequence number is near constant time; insertion near the end is
1742 * near constant time; and iteration by order of when it was sent out is easy/fast, with iterators
1743 * remaining valid as long as the underlying elements are not erased. Why use this particular
1744 * structure? Well, the lookup by sequence number occurs all the time, such as when matching up
1745 * an arriving acknowledgment against a packet that we'd sent out. We'd prefer it to not invalidate
1746 * iterators when something is erased, so Linked_hash_map is good in that way
1747 * also. So finally, why order by time it was queued up for sending (as opposed to by sequence
1748 * number, as would be the case if this were an std::map)? In truth, both are needed, which is why
1749 * #m_snd_flying_pkts_by_seq_num exists. This ordering is needed particularly for the
1750 * `m_acks_after_me` logic, wherein we count how many times packets that were sent after a given packet
1751 * have been acknowledged so far; by arranging the packets in that same order, that value can be
1752 * easily and quickly accumulated by walking back from the most recently sent packet. On the other
1753 * hand, some operations need sequence number ordering, which is why we have #m_snd_flying_pkts_by_seq_num;
1754 * note (again) that the two maps have the same key set, with one's values being iterators pointing into
1755 * the other.
1756 *
1757 * Whenever a packet with `m_sent_when.back().m_sent_time == T` is acknowledged, we need to (by definition of
1758 * Sent_packet::m_acks_after_me) increment `m_acks_after_me` for each packet with
1759 * `m_sent_when.back().m_sent_time < T`. So, if we
1760 * find the latest-sent element that satisfies that, then all packets appearing to the right
1761 * (i.e., "sent less recently than") and including that one, in this ordering, should have `m_acks_after_me`
1762 * incremented. Using a certain priority queue-using algorithm (see Node::handle_accumulated_acks())
1763 * we can do this quite efficiently.
1764 *
1765 * Note that this means Sent_packet::m_acks_after_me is strictly increasing as one walks this map.
1766 *
1767 * Since any packet with `m_acks_after_me >= C`, where `C` is some constant, is considered Dropped and
1768 * removed from #m_snd_flying_pkts_by_seq_num and therefore this map also, we also get the property that
1769 * if we find a packet in this map for which that is true, then it is also true for all packets
1770 * following it ("sent less recently" than it) in this map. This allows us to more quickly determine which
1771 * packets should be removed from #m_snd_flying_pkts_by_sent_when, without having to walk the entire structure(s).
1772 *
1773 * ### Memory use ###
1774 * This structure's memory use is naturally bounded by the Congestion Window.
1775 * Congestion control will not let it grow beyond that many packets (bytes really, but you get the point).
1776 * At that point blocks will stay on the Send buffer, until that fills up too. Then send() will refuse to enqueue
1777 * any more packets (telling the user as much).
1778 *
1779 * ### Thread safety ###
1780 * This gains meaning only in thread W. This should NOT be accessed outside of thread W and is
1781 * not protected by a mutex.
1782 *
1783 * @see Sent_when and Sent_packet::m_sent_when, where if `X` is the the last element of the latter sequence, then
1784 * `X.m_sent_time` is the value by which elements in the present map are ordered. However, this only
1785 * happens to be the case, because by definition an element
1786 * is always placed at the front of the present map (Linked_hash_map), and this order is inductively maintained;
1787 * AND MEANWHILE A Sent_when::m_sent_time's constructed value can only increase over time (which is a guaranteed
1788 * property of the clock we use (::Fine_clock)).
1789 * @see #m_snd_flying_bytes, which must always be updated to be accurate w/r/t
1790 * #m_snd_flying_pkts_by_sent_when. Use Node::snd_flying_pkts_updated() whenever
1791 * #m_snd_flying_pkts_by_sent_when is changed.
1792 * @see #m_snd_flying_pkts_by_seq_num, which provides an ordering of the elements of
1793 * #m_snd_flying_pkts_by_sent_when by sequence number. Whereas the present structure is used to
1794 * determine `m_acks_after_me` (since logically "after" means "sent after"), `..._by_seq_num`
1795 * is akin to the more classic TCP scoreboard, which is used to subdivide the sequence number
1796 * space (closely related to #m_snd_next_seq_num and such). With
1797 * retransmission off, "after" would simply mean "having higher sequence number," so
1798 * #m_snd_flying_pkts_by_sent_when would already provide this ordering, but with retransmission on
1799 * a retransmitted packet with a lower number could be sent after one with a higher number.
1800 * To make the code simpler, we therefore rely on a separate structure in either situation.
1801 */
1803
1804 /**
1805 * The collection of all In-flight packets (including those queued up to send in pacing module),
1806 * indexed AND ordered by sequence number. See also #m_snd_flying_pkts_by_sent_when which is a similar map
1807 * but in order of time sent. Our map's keys are sequence numbers again, but its values are iterators
1808 * into #m_snd_flying_pkts_by_sent_when to save memory and avoid having to sync up data between the two
1809 * (only keys are in sync). The two maps together can be considered to be the "scoreboard," though in fact
1810 * the present structure alone is closer to a classic TCP scoreboard.
1811 *
1812 * The key sets of the two maps are identical. The values in this map are iterators to exactly all
1813 * elements of #m_snd_flying_pkts_by_sent_when. One can think of the present map as essentially achieving an
1814 * alternate ordering of the values in the other map.
1815 *
1816 * That said, the structure's contents and ordering are closely related to a breakdown of the sequence
1817 * number space. I provide this breakdown here. I list the
1818 * sequence number ranges in increasing order starting with the ISN. Let `first_flying_seq_num
1819 * = m_snd_flying_pkts_by_seq_num.begin()->first` (i.e., the first key Sequence_number in
1820 * #m_snd_flying_pkts_by_seq_num) for exposition purposes.
1821 *
1822 * - #m_snd_init_seq_num =
1823 * - SYN or SYN_ACK
1824 *
1825 * - [`m_snd_init_seq_num + 1`, `first_flying_seq_num - 1`] =
1826 * - Largest possible range of sequence numbers such that each datum represented by this range
1827 * has been sent and either:
1828 * - Acknowledged (ACK received for it); or
1829 * - Dropped (ACK not received; we consider it dropped due to some factor like timeout or
1830 * duplicate ACKs);
1831 *
1832 * - [`first_flying_seq_num`, `first_flying_seq_num + N - 1`] =
1833 * - The first packet that has been sent that is neither Acknowledged nor Dropped. `N` is length
1834 * of that packet. This is always the first packet, if any, to be considered Dropped in the
1835 * future. This packet is categorized In-flight.
1836 *
1837 * - [`first_flying_seq_num + N`, `m_snd_next_seq_num - 1`] =
1838 * - All remaining sent packets. Each packet in this range is one of the following:
1839 * - Acknowledged;
1840 * - not Acknowledged and not Dropped = categorized In-flight.
1841 *
1842 * - [#m_snd_next_seq_num, ...] =
1843 * - Unsent packets, if any.
1844 *
1845 * #m_snd_flying_pkts_by_sent_when and #m_snd_flying_pkts_by_seq_num contain In-flight Sent_packet objects as values
1846 * (though the latter indirectly via iterator into the former) with each particular Sent_packet's first sequence
1847 * number as its key in either structure. If there are no In-flight Sent_packet objects, then
1848 * `m_snd_flying_pkts_by_{sent_when|seq_num}.empty()` and hence `first_flying_seq_num` above does not
1849 * exist. Each of the [ranges] above can be null (empty).
1850 *
1851 * Each sent packet therefore is placed into #m_snd_flying_pkts_by_seq_num, at the back (if it's a new packet) or
1852 * possibly elsewhere (if it's retransmitted) -- while it is also placed into #m_snd_flying_pkts_by_sent_when but
1853 * always at the front (as, regardless of retransmission or anything else, it is the latest packet to be SENT). When
1854 * packet is Acknowledged, it is removed from `m_snd_flying_pkts_by_*` -- could be from anywhere in
1855 * the ordering. Similarly to Acknowledged packets, Dropped ones are also removed.
1856 *
1857 * Why do we need this map type in addition to `Linked_hash_map m_snd_flying_pkts_by_sent_when`? Answer: Essentially,
1858 * when an acknowledgment comes in, we need to be able to determine where in the sequence number space this is.
1859 * If packets are ordered by send time -- not sequence number -- and the sequence number does not match
1860 * exactly one of the elements here (e.g., it erroneously straddles one, or it is a duplicate acknowledgement,
1861 * which means that element isn't in the map any longer), then a tree-sorted-by-key map is invaluable
1862 * (in particular: to get `upper_bound()`, and also to travel to the previous-by-sequence-number packet
1863 * from the latter). So logarithmic-time upper-bound searches and iteration by sequence number are what we want and
1864 * get with this added ordering on top of #m_snd_flying_pkts_by_sent_when.
1865 *
1866 * ### Memory use ###
1867 * This structure's memory use is naturally bounded the same as #m_snd_flying_pkts_by_sent_when.
1868 *
1869 * ### Thread safety ###
1870 * This gains meaning only in thread W. This should NOT be accessed outside of thread W and is
1871 * not protected by a mutex.
1872 *
1873 * @see #m_snd_flying_pkts_by_sent_when. There's a "see also" comment there that contrasts these two
1874 * important structures.
1875 */
1877
1878 /**
1879 * The number of bytes contained in all In-flight packets, used at least for comparison against
1880 * the congestion window (CWND). More formally, this is the sum of all Sent_packet::m_size values
1881 * in #m_snd_flying_pkts_by_sent_when. We keep this, instead of computing it whenever needed, for
1882 * performance. In various TCP and related RFCs this value (or something spiritually similar, if
1883 * only cumulative ACKs are used) is called "pipe" or "FlightSize."
1884 *
1885 * Though in protocols like DCCP, where CWND is stored in packets, instead of bytes, "pipe" is
1886 * actually just `m_snd_flying_pkts_by_sent_when.size()`. Not for us though.
1887 *
1888 * This gains meaning only in thread W. This should NOT be accessed outside of thread W and is
1889 * not protected by a mutex.
1890 *
1891 * @see #m_snd_flying_pkts_by_sent_when, which must always be updated to be accurate w/r/t
1892 * #m_snd_flying_bytes. Use Node::snd_flying_pkts_updated() whenever #m_snd_flying_pkts_by_sent_when
1893 * is changed.
1894 */
1896
1897 /**
1898 * Helper data structure to store the packet IDs of packets that are marked Dropped during a single run
1899 * through accumulated ACKs; it is a data member instead of local variable for performance only. The pattern is
1900 * to simply `clear()` it just before use, then load it up with stuff in that same round of ACK handling;
1901 * and the same thing each time we need to handle accumulated ACKs. Normally one would just create one
1902 * of these locally within the code `{` block `}` each time instead.
1903 * Not doing so avoids unnecessary various internal-to-`vector` buffer
1904 * allocations. Instead the internal buffer will grow as large as it needs to and not go down from there, so
1905 * that it can be reused in subsequent operations. (Even `clear()` does not internally shrink the buffer.)
1906 * Of course some memory is held unnecessarily, but it's a small amount; on the other hand the performance
1907 * gain may be non-trivial due to the frequency of the ACK-handling code being invoked.
1908 *
1909 * This gains meaning only in thread W. This should NOT be accessed outside of thread W and is
1910 * not protected by a mutex.
1911 */
1912 std::vector<order_num_t> m_snd_temp_pkts_marked_to_drop;
1913
1914 /**
1915 * For the Sent_packet representing the next packet to be sent, this is the value to assign to
1916 * `m_sent_when.back().first`. In other words it's an ever-increasing number that is sort of like
1917 * a sequence number but one per packet and represents time at which sent, not order in the byte stream.
1918 * In particular the same packet retransmitted will have the same sequence number the 2nd time but
1919 * an increased order number. Starts at 0.
1920 *
1921 * This is only used for book-keeping locally and never transmitted over network.
1922 *
1923 * This gains meaning only in thread W. This should NOT be accessed outside of thread W and is
1924 * not protected by a mutex.
1925 */
1927
1928 /**
1929 * If retransmission is on, this is the retransmission queue. It's the queue of packets determined to have
1930 * been dropped and thus to be retransmitted, when Congestion Window allows this. Packet in Sent_packet::m_packet
1931 * field of element at top of the queue is to be retransmitted next; and the element itself is to be inserted into
1932 * #m_snd_flying_pkts_by_sent_when while popped from the present structure. The packet's Data_packet::m_rexmit_id
1933 * should be incremented before sending; and the Sent_packet::m_sent_when `vector` should be appended with the
1934 * then-current time (for future RTT calculation).
1935 *
1936 * If retransmission is off, this is empty.
1937 *
1938 * Why use `list<>` and not `queue<>` or `deque<>`? Answer: I'd like to use `list::splice()`.
1939 *
1940 * This gains meaning only in thread W. This should NOT be accessed outside of thread W and is
1941 * not protected by a mutex.
1942 */
1943 std::list<boost::shared_ptr<Sent_packet>> m_snd_rexmit_q;
1944
1945 /// Equals `m_snd_rexmit_q.size().` Kept since `m_snd_rexmit_q.size()` may be @em O(n) depending on implementation.
1947
1948 /**
1949 * The congestion control strategy in use for this connection on this side. Node informs
1950 * this object of events, such as acknowedgments and loss events; conversely this object informs
1951 * (or can inform if asked) the Node whether or not DATA packets can be sent, by means of
1952 * providing the Node with the socket's current Congestion Window (CWND) computed based on the
1953 * particular Congestion_control_strategy implementation's algorithm (e.g., Reno or Westwood+).
1954 * Node then determines whether data can be sent by comparing #m_snd_flying_bytes (# of bytes we think
1955 * are currently In-flight) to CWND (# of bytes the strategy allows to be In-flight currently).
1956 *
1957 * ### Life cycle ###
1958 * #m_snd_cong_ctl must be initialized to an instance before user gains access to this
1959 * socket; the pointer must never change subsequently except back to null (permanently). The
1960 * Peer_socket destructor, at the latest, will delete the underlying object, as #m_snd_cong_ctl
1961 * will be destructed. (Note `unique_ptr` has no copy operator or
1962 * constructor.) There is a 1-to-1 relationship between `*this` and #m_snd_cong_ctl.
1963 *
1964 * ### Visibility between Congestion_control_strategy and Peer_socket ###
1965 * #m_snd_cong_ctl gets read-only (`const`!) but otherwise complete
1966 * private access (via `friend`) to the contents of `*this` Peer_socket. For example, it can
1967 * read `this->m_snd_smoothed_round_trip_time` (the SRTT) and use it
1968 * for computations if needed. Node and Peer_socket get only strict public API access to
1969 * #m_snd_cong_ctl, which is a black box to it.
1970 *
1971 * This gains meaning only in thread W. This should NOT be accessed outside of thread W and is
1972 * not protected by a mutex.
1973 */
1974 boost::movelib::unique_ptr<Congestion_control_strategy> m_snd_cong_ctl;
1975
1976 /**
1977 * The receive window: the maximum number of bytes the other side has advertised it would be
1978 * willing to accept into its Receive buffer if they'd arrived at the moment that advertisement
1979 * was generated by the other side. This starts as 0 (undefined) and is originally set at SYN_ACK
1980 * or SYN_ACK_ACK receipt and then subsequently updated upon each ACK received. Each such update
1981 * is called a "rcv_wnd update" or "window update."
1982 *
1983 * #m_snd_cong_ctl provides congestion control; this value provides flow control. The socket's
1984 * state machine must be extremely careful whenever either this value or
1985 * `m_snd_cong_ctl->congestion_window_bytes()` may increase, as when that occurs it should call
1986 * Node::send_worker() in order to possibly send data over the network.
1987 *
1988 * This gains meaning only in thread W. This should NOT be accessed outside of thread W and is
1989 * not protected by a mutex.
1990 */
1992
1993 /**
1994 * The outgoing available bandwidth estimator for this connection on this side. Node informs
1995 * this object of events, namely as acknowedgments; conversely this object informs
1996 * (or can inform if asked) the Node what it thinks is the current available bandwidth for
1997 * user data in DATA packets. This can be useful at least for some forms of congestion control
1998 * but possibly as information for the user, which is why it's an independent object and not
1999 * part of a specific congestion control strategy (I only mention this because the mechanics of such
2000 * a bandwidth estimator typically originate in service of a congestion control algorithm like Westwood+).
2001 *
2002 * ### Life cycle ###
2003 * It must be initialized to an instance before user gains access to this
2004 * socket; the pointer must never change subsequently except back to null (permanently). The
2005 * Peer_socket destructor, at the latest, will delete the underlying object, as #m_snd_bandwidth_estimator
2006 * is destroyed along with `*this`. The only reason it's a pointer is that it takes a Const_ptr in the constructor,
2007 * and that's not available during Peer_socket construction yet. (Note `unique_ptr` has no copy operator or
2008 * constructor.) There is a 1-to-1 relationship between `*this` and #m_snd_bandwidth_estimator.
2009 *
2010 * ### Visibility between Send_bandwidth_estimator and Peer_socket ###
2011 * The former gets read-only (`const`!) but otherwise complete private access (via `friend`) to the contents of
2012 * `*this` Peer_socket. For example, it can read #m_snd_smoothed_round_trip_time (the SRTT) and use it
2013 * for computations if needed. Node and Peer_socket get only strict public API access to
2014 * #m_snd_bandwidth_estimator, which is a black box to it.
2015 *
2016 * This gains meaning only in thread W. This should NOT be accessed outside of thread W and is
2017 * not protected by a mutex.
2018 */
2019 boost::movelib::unique_ptr<Send_bandwidth_estimator> m_snd_bandwidth_estimator;
2020
2021 /**
2022 * Estimated current round trip time of packets, computed as a smooth value over the
2023 * past individual RTT measurements. This is updated each time we make an RTT measurement (i.e.,
2024 * receive a valid, non-duplicate acknowledgment of a packet we'd sent). The algorithm to compute
2025 * it is taken from RFC 6298. The value is 0 (not a legal value otherwise) until the first RTT
2026 * measurement is made.
2027 *
2028 * We use #Fine_duration (the high fine-grainedness and large bit width corresponding to #Fine_clock) to
2029 * store this, and the algorithm we use to compute it avoids losing digits via unnecessary
2030 * conversions between units (e.g., nanoseconds -> milliseconds).
2031 *
2032 * This gains meaning only in thread W. This should NOT be accessed outside of thread W and is
2033 * not protected by a mutex.
2034 */
2036
2037 /// RTTVAR used for #m_snd_smoothed_round_trip_time calculation. @see #m_snd_smoothed_round_trip_time.
2039
2040 /**
2041 * The Drop Timer engine, which controls how In-flight (#m_snd_flying_pkts_by_sent_when) packets are
2042 * considered Dropped due to being unacknowledged for too long. Used while #m_int_state is
2043 * Int_state::S_ESTABLISHED.
2044 *
2045 * This gains meaning only in thread W. This should NOT be accessed outside of thread W and is
2046 * not protected by a mutex.
2047 */
2049
2050 /**
2051 * The Drop Timeout: Time period between the next time #m_snd_drop_timer schedules a Drop Timer and that timer
2052 * expiring. This is updated each time #m_snd_smoothed_round_trip_time is updated, and the Drop_timer
2053 * itself may change it under certain circumstances.
2054 *
2055 * This gains meaning only in thread W. This should NOT be accessed outside of thread W and is
2056 * not protected by a mutex.
2057 */
2059
2060 /**
2061 * The state of outgoing packet pacing for this socket; segregated into a simple `struct` to keep
2062 * Peer_socket shorter and easier to understand. Packet pacing tries to combat the burstiness of
2063 * outgoing low-level packet stream.
2064 *
2065 * @see `struct Send_pacing_data` doc header for much detail.
2066 */
2068
2069 /**
2070 * The last time that Node has detected a packet loss event and so informed #m_snd_cong_ctl by calling
2071 * the appropriate method of class Congestion_control_strategy. Roughly speaking, this is used to
2072 * determine whether the detection of a given dropped packet is part of the same loss event as the
2073 * previous one; if so then #m_snd_cong_ctl is not informed again (presumably to avoid dropping CWND
2074 * too fast); if not it is informed of the new loss event. Even more roughly speaking, if the new
2075 * event is within a certain time frame of #m_snd_last_loss_event_when, then they're considered in the
2076 * same loss event. You can find detailed discussion in a giant comment in
2077 * Node::handle_accumulated_acks().
2078 *
2079 * Before any loss events, this is set to its default value (zero time since epoch).
2080 *
2081 * This gains meaning only in thread W. This should NOT be accessed outside of thread W and is
2082 * not protected by a mutex.
2083 */
2085
2086 /**
2087 * Time at which the last Data_packet low-level packet for this connection was sent. We
2088 * use this when determining whether the connection is in Idle Timeout (i.e., has sent no traffic
2089 * for a while, which means there has been no data to send). It's used for congestion control.
2090 *
2091 * Before any packets are sent, this is set to its default value (zero time since epoch).
2092 *
2093 * This gains meaning only in thread W. This should NOT be accessed outside of thread W and is
2094 * not protected by a mutex.
2095 *
2096 * ### Pacing ###
2097 * See Send_packet_pacing #m_snd_pacing_data. See pacing-relevant note on Sent_packet::m_sent_when
2098 * which applies equally to this data member.
2099 */
2101
2102 /// Stats regarding outgoing traffic (and resulting incoming ACKs) for this connection so far.
2104
2105 /**
2106 * Random security token used during SYN_ACK-SYN_ACK_ACK. For a given connection handshake, the
2107 * SYN_ACK_ACK receiver ensures that #m_security_token it received is equal to the original one it
2108 * had sent in SYN_ACK. This first gains meaning upong sending SYN_ACK and it does not change afterwards.
2109 * It is not used unless `!m_active_connect`. See #m_active_connect.
2110 *
2111 * This gains meaning only in thread W. This should NOT be accessed outside of thread W and is
2112 * not protected by a mutex.
2113 */
2115
2116 /**
2117 * Connection attempt scheduled task; fires if an individual connection request packet is not answered with a reply
2118 * packet in time. It is readied when *any* SYN or SYN_ACK packet is sent, and fired if that packet has gone
2119 * unacknowledged with a SYN_ACK or SYN_ACK_ACK (respectively), long enough to be retransmitted.
2120 *
2121 * Connection establishment is aborted if it fires too many times, but #m_connection_timeout_scheduled_task is how
2122 * "too many times" is determined.
2123 *
2124 * This gains meaning only in thread W. This should NOT be accessed outside of thread W and is
2125 * not protected by a mutex.
2126 *
2127 * @see #m_connection_timeout_scheduled_task which keeps track of the entire process timing out, as opposed to the
2128 * individual attempts.
2129 */
2131
2132 /**
2133 * If currently using #m_init_rexmit_scheduled_task, this is the number of times the timer has already fired
2134 * in this session. So when the timer is readied the first time it's zero; if it fires and is
2135 * thus readied again it's one; again => two; etc., until timer is canceled or connection is
2136 * aborted due to too many retries.
2137 *
2138 * This gains meaning only in thread W. This should NOT be accessed outside of thread W and is
2139 * not protected by a mutex.
2140 */
2142
2143 /**
2144 * Connection timeout scheduled task; fires if the entire initial connection process does not complete within a
2145 * certain amount of time. It is started when the SYN or SYN_ACK is sent the very first time (NOT counting
2146 * resends), canceled when SYN_ACK or SYN_ACK_ACK (respectively) is received in response to ANY SYN or
2147 * SYN_ACK (respevtively), and fired if the the latter does not occur in time.
2148 *
2149 * This gains meaning only in thread W. This should NOT be accessed outside of thread W and is
2150 * not protected by a mutex.
2151 *
2152 * @see #m_init_rexmit_scheduled_task which keeps track of *individual* attempts timing out, as opposed to the
2153 * entire process.
2154 */
2156
2157 /**
2158 * This is the final set of stats collected at the time the socket was moved to S_CLOSED #m_state.
2159 * If it has not yet moved to that state, this is not applicable (but equals Peer_socket_info()).
2160 * It's used by info() to get at the final set of stats, before the source info is purged by the
2161 * resource cleanup in sock_free_memory().
2162 */
2164}; // class Peer_socket
2165
2166
2167/**
2168 * @private
2169 *
2170 * Metadata (and data, if retransmission is on) for a packet that has been sent one (if
2171 * retransmission is off) or possibly more (if on) times. This is purely a data store, not a
2172 * class. It is not copyable, and moving them around by smart Sent_packet::Ptr is encouraged.
2173 */
2175 // Endow us with shared_ptr<>s ::Ptr and ::Const_ptr (syntactic sugar).
2176 public util::Shared_ptr_alias_holder<boost::shared_ptr<Peer_socket::Sent_packet>>,
2177 private boost::noncopyable
2178{
2179 // Types.
2180
2181 struct Sent_when;
2182
2183 /**
2184 * Type used for #m_acks_after_me. Use a small type to save memory; this is easily large enough,
2185 * given that that we drop a packet after #m_acks_after_me exceeds a very small value (< 10), and
2186 * a given ACK can *conceivably* hold a few thousand individual acknowledgments (most likely many
2187 * fewer). In fact `uint8_t` is probably enough, but it seemed easier to not worry about
2188 * overflows when doing arithmetic with these.
2189 */
2190 using ack_count_t = uint16_t;
2191
2192 // Data.
2193
2194 /// Number of bytes in the Data_packet::m_data field of the sent packet.
2195 const size_t m_size;
2196
2197 /**
2198 * Time stamps, order numbers, and other info at the times when the different attempts (including
2199 * original sending and retransmissions) to send the packet were given to the UDP net-stack. These are
2200 * arranged in the order they were sent (0 = original transmission, 1 = first retransmission, 2 = second
2201 * retransmission, ...). If retransmission is off, this only ever has 1 element (set via
2202 * constructor).
2203 *
2204 * Along with each time stamp, we also store an order number. It is much like a sequence
2205 * number, except (a) we never send it anywhere (internal bookkeeping only), (b) it specifies
2206 * the order in which the packets were sent off. Why use that and not a `m_sent_time` timestamp? Because
2207 * `m_sent_time` can, in theory, have ties (i.e., it's kind of possible for 2 packets to be sent
2208 * within the same high-resolution clock tick). This gives us a solid way to order packets by send time
2209 * in certain key algorithms.
2210 *
2211 * Note: for reasons explained in the pacing module this should be the time stamp when we
2212 * actually send it off to boost.asio UDP net-stack, not when we queue it into the pacing module (which can be
2213 * quite a bit earlier, if pacing is enabled). Subtlety: Note that "time stamp when we actually send it off
2214 * to boost.asio UDP net-stack" IS the same as "time stamp when boost.asio UDP net-stack actually performs the
2215 * `sendto()` call" in practice -- a good thing for accurate RTT measurements.
2216 */
2217 std::vector<Sent_when> m_sent_when;
2218
2219 /**
2220 * The number of times any packet with `m_sent_when.back().m_order_num > this->m_sent_when.back().m_order_num`
2221 * has been acknowledged. Reworded slightly: start at 0; *IF* a packet, other than this one, is In-flight and then
2222 * acknowledged, and that packet was sent out (or, equivalently, scheduled to be sent out -- packets do not
2223 * change order once marked for sending -- a/k/a became In-flight) chronologically AFTER same happened to
2224 * `*this` packet *THEN* add 1. After adding up all such acks, the resulting value = this member.
2225 *
2226 * This is used to determine when `*this` packet should be considered Dropped,
2227 * as in TCP's Fast Retransmit heuristic (but better, since time-when-sent -- not sequence number, which has
2228 * retransmission ambiguities -- is used to order packets).
2229 *
2230 * Note, again, that "after" has little to do with *sequence* number but rather with send time, as ordered via
2231 * the *order* number. E.g., due to retransmission, `*this` may have sequence number greater than another
2232 * packet yet have the lesser order number. (This dichotomy is mentioned a lot, everywhere, and if I'm overdoing
2233 * it, it's only because sometimes TCP cumulative-ack habits die hard, so I have to keep reminding myself.)
2234 * (If retransmission is disabled, however, then sequence number order = order number order.)
2235 */
2237
2238 /**
2239 * If retransmission is on, this is the DATA packet itself that was sent; otherwise null. It is
2240 * stored in case we need to retransmit it. If we don't (it is acknowledged), the entire
2241 * Sent_packet is erased and goes away, so #m_packet's ref-count decreases to zero, and it
2242 * disappears. If we do, all we need to do to retransmit it is increment its Data_packet::m_rexmit_id and
2243 * place it into the retransmission queue for sending, when CWND space is available.
2244 *
2245 * Why store the entire packet and not just its Data_packet::m_data? There's a small bit of memory overhead, but
2246 * we get Data_packet::m_rexmit_id for free and don't have to spend time re-creating the packet to retransmit.
2247 * So it's just convenient.
2248 *
2249 * If retransmission is off, there is no need to store this, as it will not be re-sent.
2250 */
2251 const boost::shared_ptr<Data_packet> m_packet;
2252
2253 // Constructors/destructor.
2254
2255 /**
2256 * Constructs object with the given values and #m_acks_after_me at zero. If rexmit-on option enabled, the
2257 * packet is stored in #m_packet; otherwise #m_packet is initialized to null. Regardless, #m_size
2258 * is set to `packet.m_data.size()`.
2259 *
2260 * @param rexmit_on
2261 * True if and only if `sock->rexmit_on()` for the containing socket.
2262 * @param packet
2263 * The packet that will be sent. Used for #m_size and, if `sock->rexmit_on()`, saved in #m_packet.
2264 * @param sent_when
2265 * #m_sent_when is set to contain one element equalling this argument.
2266 */
2267 explicit Sent_packet(bool rexmit_on, boost::shared_ptr<Data_packet> packet, const Sent_when& sent_when);
2268}; // struct Peer_socket::Sent_packet
2269
2270/**
2271 * @private
2272 *
2273 * Data store to keep timing related info when a packet is sent out. Construct via direct member initialization.
2274 * It is copy-constructible (for initially copying into containers and such) but not assignable to discourage
2275 * unneeded copying (though it is not a heavy structure). Update: A later version of clang does not like
2276 * this technique and warns about it; to avoid any such trouble just forget the non-assignability stuff;
2277 * it's internal code; we should be fine.
2278 */
2280{
2281 // Data.
2282
2283 /**
2284 * Order number of the packet. This can be used to compare two packets sent out; the one with the
2285 * higher order number was sent out later. See Peer_socket::m_snd_last_order_num. The per-socket next-value
2286 * for this is incremented each time another packet is sent out.
2287 *
2288 * @see Peer_socket::Sent_packet::m_sent_when for more discussion.
2289 *
2290 * @internal
2291 * @todo Can we make Sent_when::m_order_num and some of its peers const?
2292 */
2293 // That @internal should not be necessary to hide the @todo in public generated docs -- Doxygen bug?
2295
2296 /**
2297 * The timestamp when the packet is sent out. This may be "corrected" when actually sent *after* pacing delay
2298 * (hence not `const`).
2299 *
2300 * @see Fine_clock. Recall that, due to latter's properties, `Fine_clock::now()` results monotonically increase
2301 * over time -- a property on which we rely on, particularly since this data member is only assigned
2302 * `Fine_clock::now()` at various times.
2303 *
2304 * @see Peer_socket::Sent_packet::m_sent_when for more discussion.
2305 */
2307
2308 /**
2309 * The congestion window size (in bytes) that is used when the packet is sent out.
2310 * We store this to pass to the congestion control module when this packet is acked in the future.
2311 * Some congestion control algorithms compute CWND based on an earlier CWND value.
2312 * Not `const` for similar reason as #m_sent_time.
2313 *
2314 * @internal
2315 * @todo Why is #m_sent_cwnd_bytes in Sent_when `struct` and not directly in `Sent_packet`? Or maybe it should
2316 * stay here, but Sent_when should be renamed `Send_attempt` (or `Send_try` for brevity)? Yeah, I think that's
2317 * it. Then Sent_packet::m_sent_when -- a container of Sent_when objects -- would become `m_send_tries`, a
2318 * container of `Send_try` objects. That makes more sense (sentce?!) than the status quo which involves the
2319 * singular-means-plural strangeness.
2320 *
2321 * @todo Can we make #m_sent_cwnd_bytes and some of its peers `const`?
2322 */
2323 // That @internal should not be necessary to hide the @todo in public generated docs -- Doxygen bug?
2325}; // struct Peer_socket::Sent_packet::Sent_when
2326
2327/**
2328 * @private
2329 *
2330 * Metadata (and data, if retransmission is on) for a packet that has been received (and, if
2331 * retransmission is off, copied to Receive buffer). This is purely a data store, not a class.
2332 * It is not copyable, and moving them around by smart Received_packet::Ptr is encouraged.
2333 */
2335 // Endow us with shared_ptr<>s ::Ptr and ::Const_ptr (syntactic sugar).
2336 public util::Shared_ptr_alias_holder<boost::shared_ptr<Peer_socket::Received_packet>>,
2337 private boost::noncopyable
2338{
2339 // Data.
2340
2341 /// Number of bytes in the Data_packet::m_data field of that packet.
2342 const size_t m_size;
2343
2344 /**
2345 * Byte sequence equal to that of Data_packet::m_data of the packet. Kept `empty()` if retransmission is off,
2346 * since in that mode any received packet's `m_data` is immediately moved to Receive buffer. With
2347 * retransmission on, it is stored until all gaps before the packet are filled (a/k/a
2348 * reassembly).
2349 */
2351
2352 // Constructors/destructor.
2353
2354 /**
2355 * Constructs object by storing size of data and, if so instructed, the data themselves.
2356 *
2357 * @param logger_ptr
2358 * The Logger implementation to use subsequently.
2359 * @param size
2360 * #m_size.
2361 * @param src_data
2362 * Pointer to the packet data to be moved into #m_data; or null if we shouldn't store it.
2363 * This should be null if and only if retransmission is off. If not null, for
2364 * performance, `*src_data` is CLEARED by this constructor (its data moved, in constant
2365 * time, into #m_data). In that case, `src_data.size() == size` must be true at entrance to
2366 * constructor, or behavior is undefined.
2367 */
2368 explicit Received_packet(log::Logger* logger_ptr, size_t size, util::Blob* src_data);
2369};
2370
2371/**
2372 * @private
2373 *
2374 * Metadata describing the data sent in the acknowledgment of an individual received packet. (A
2375 * low-level ACK packet may include several sets of such data.) This is purely a data store, not
2376 * a class. It is not copyable, and moving them around by smart Individual_ack::Ptr is encouraged.
2377 * Construct this by direct member initialization.
2378 */
2380 // Cannot use boost::noncopyable or Shared_ptr_alias_holder, because that turns off direct initialization.
2381{
2382 // Types.
2383
2384 /// Short-hand for ref-counted pointer to mutable objects of this class.
2385 using Ptr = boost::shared_ptr<Individual_ack>;
2386
2387 /// Short-hand for ref-counted pointer to immutable objects of this class.
2388 using Const_ptr = boost::shared_ptr<const Individual_ack>;
2389
2390 // Data.
2391
2392 /// Sequence number of first datum in packet.
2394
2395 /**
2396 * Retransmit counter of the packet (as reported by sender). Identifies which attempt we are
2397 * acknowledging (0 = initial, 1 = first retransmit, 2 = second retransmit, ...). Always 0
2398 * unless retransmission is on.
2399 */
2400 const unsigned int m_rexmit_id;
2401
2402 /// When was it received? Used for supplying delay before acknowledging (for other side's RTT calculations).
2404
2405 /// Number of bytes in the packet's user data.
2406 const size_t m_data_size;
2407
2408 /// Make us noncopyable without breaking aggregateness (direct-init).
2409 [[no_unique_address]] util::Noncopyable m_nc{};
2410}; // struct Peer_socket::Individual_ack
2411// Note: Some static_assert()s about it currently in peer_socket.cpp in a function {} (for boring reasons).
2412
2413// Free functions: in *_fwd.hpp.
2414
2415// However the following refer to inner type(s) and hence must be declared here and not _fwd.hpp.
2416
2417/**
2418 * @internal
2419 *
2420 * @todo There are a few guys like this which are marked `@internal` (Doxygen command) to hide from generated
2421 * public documentation, and that works, but really they should not be visible in the publicly-exported
2422 * (not in detail/) header source code; so this should be reorganized for cleanliness. The prototypes like this one
2423 * can be moved to a detail/ header or maybe directly into .cpp that uses them (for those where it's only one).
2424 *
2425 * Prints string representation of given socket state to given standard `ostream` and returns the
2426 * latter.
2427 *
2428 * @param os
2429 * Stream to print to.
2430 * @param state
2431 * Value to serialize.
2432 * @return `os`.
2433 */
2434std::ostream& operator<<(std::ostream& os, Peer_socket::Int_state state);
2435
2436// Template implementations.
2437
2438template<typename Const_buffer_sequence>
2439size_t Peer_socket::send(const Const_buffer_sequence& data, Error_code* err_code)
2440{
2441 FLOW_ERROR_EXEC_AND_THROW_ON_ERROR(size_t, send<Const_buffer_sequence>, data, _1);
2442 // ^-- Call ourselves and return if err_code is null. If got to present line, err_code is not null.
2443
2444 // We are in user thread U != W.
2445
2446 Lock_guard lock(m_mutex); // Lock m_node; also it's a pre-condition for Node::send().
2447
2448 /* Forward the rest of the logic to Node.
2449 * Now, what I really want to do here is simply:
2450 * m_node->send(this, data, err_code);
2451 * I cannot, however, due to C++'s circular reference BS (Node needs Peer_socket, Peer_socket needs Node,
2452 * and both send()s are templates so cannot be implemented in .cpp). So I perform the following
2453 * voodoo. The only part that must be defined in .hpp is the part that actually uses template
2454 * parameters. The only part that uses template parameters is m_snd_buf->feed_bufs_copy().
2455 * Therefore I prepare a canned call to m_snd_buf->feed_bufs_copy(data, ...) and save it in a
2456 * function pointer (Function) to an untemplated, regular function that makes this canned
2457 * call. Finally, I call an untemplated function in .cpp, which has full understanding of Node,
2458 * and pass the pre-canned thingie into that. That guy finally calls Node::send(), passing along
2459 * the precanned thingie. Node::send() can then call the latter when it needs to feed() to the
2460 * buffer. Therefore Node::send() does not need to be templated.
2461 *
2462 * Yeah, I know. I had to do it though. Logic should be in Node, not in Peer_socket.
2463 *
2464 * Update: As of this writing I've added a formal @todo into Node doc header. .inl tricks a-la-Boost might
2465 * help avoid this issue. */
2466 const auto snd_buf_feed_func = [this, &data](size_t max_data_size)
2467 {
2468 return m_snd_buf.feed_bufs_copy(data, max_data_size);
2469 };
2470 // ^-- Important to capture `&data`, not `data`; else `data` (albeit not actual payload) will be copied!
2471
2472 /* Let this untemplated function, in .cpp, deal with Node (since .cpp knows what *m_node really is).
2473 * Note: whatever contraption lambda generated above will be converted to a Function<...> with ... being
2474 * an appropriate signature that node_send() expects, seen in the above explanatory comment. */
2475 return node_send(snd_buf_feed_func, err_code);
2476} // Peer_socket::send()
2477
2478template<typename Const_buffer_sequence>
2479size_t Peer_socket::sync_send(const Const_buffer_sequence& data, Error_code* err_code)
2480{
2481 return sync_send_impl(data, Fine_time_pt(), err_code); // sync_send() with infinite timeout.
2482}
2483
2484template<typename Rep, typename Period, typename Const_buffer_sequence>
2485size_t Peer_socket::sync_send(const Const_buffer_sequence& data,
2486 const boost::chrono::duration<Rep, Period>& max_wait,
2487 Error_code* err_code)
2488{
2489 assert(max_wait.count() > 0);
2490 return sync_send_impl(data,
2492 err_code);
2493}
2494
2495template<typename Rep, typename Period>
2496bool Peer_socket::sync_send(std::nullptr_t,
2497 const boost::chrono::duration<Rep, Period>& max_wait,
2498 Error_code* err_code)
2499{
2500 assert(max_wait.count() > 0);
2502 err_code);
2503}
2504
2505template<typename Const_buffer_sequence>
2506size_t Peer_socket::sync_send_impl(const Const_buffer_sequence& data, const Fine_time_pt& wait_until,
2507 Error_code* err_code)
2508{
2509 FLOW_ERROR_EXEC_AND_THROW_ON_ERROR(size_t, sync_send_impl<Const_buffer_sequence>, data, wait_until, _1);
2510 // ^-- Call ourselves and return if err_code is null. If got to present line, err_code is not null.
2511
2512 // We are in user thread U != W.
2513
2514 Lock_guard lock(m_mutex); // Lock m_node; also it's a pre-condition for Node::send().
2515
2516 /* Forward the rest of the logic to Node.
2517 * Now, what I really want to do here is simply:
2518 * m_node->sync_send(...args...);
2519 * I cannot, however, due to <see same situation explained in Peer_socket::send()>.
2520 * Therefore I do the following (<see Peer_socket::send() for more comments>). */
2521
2522 const auto snd_buf_feed_func = [this, &data](size_t max_data_size)
2523 {
2524 return m_snd_buf.feed_bufs_copy(data, max_data_size);
2525 };
2526 // ^-- Important to capture `&data`, not `data`; else `data` (albeit not actual payload) will be copied!
2527
2528 lock.release(); // Let go of the mutex (mutex is still LOCKED).
2529 /* Let this untemplated function, in .cpp, deal with Node (since .cpp knows what *m_node really is).
2530 * Note: whatever contraption lambda generated above will be converted to a Function<...> with ... being
2531 * an appropriate signature that node_sync_send() expects, seen in the above explanatory comment. */
2532 return node_sync_send(snd_buf_feed_func, wait_until, err_code);
2533} // Peer_socket::sync_send_impl()
2534
2535template<typename Mutable_buffer_sequence>
2536size_t Peer_socket::receive(const Mutable_buffer_sequence& target, Error_code* err_code)
2537{
2538 FLOW_ERROR_EXEC_AND_THROW_ON_ERROR(size_t, receive<Mutable_buffer_sequence>, target, _1);
2539 // ^-- Call ourselves and return if err_code is null. If got to present line, err_code is not null.
2540
2541 // We are in user thread U != W.
2542
2543 Lock_guard lock(m_mutex); // Lock m_node/m_state; also it's a pre-condition for Node::receive().
2544
2545 /* Forward the rest of the logic to Node.
2546 * Now, what I really want to do here is simply:
2547 * m_node->receive(this, target), err_code);
2548 * I cannot, however, due to <see same situation explained in Peer_socket::send()>.
2549 * Therefore I do the following (<see Peer_socket::send() for more comments>). */
2550
2551 const auto rcv_buf_consume_func = [this, &target]()
2552 {
2553 // Ensure that if there are data in Receive buffer, we will return at least 1 block as
2554 // advertised. @todo: I don't understand this comment now. What does it mean? Explain.
2555 return m_rcv_buf.consume_bufs_copy(target);
2556 };
2557 // ^-- Important to capture `&target`, not `target`; else `target` (albeit no actual buffers) will be copied!
2558
2559 /* Let this untemplated function, in .cpp, deal with Node (since .cpp knows what *m_node really is).
2560 * Note: whatever contraption lambda generated above will be converted to a Function<...> with ... being
2561 * an appropriate signature that node_receive() expects, seen in the above explanatory comment. */
2562 return node_receive(rcv_buf_consume_func, err_code);
2563}
2564
2565template<typename Mutable_buffer_sequence>
2566size_t Peer_socket::sync_receive(const Mutable_buffer_sequence& target, Error_code* err_code)
2567{
2568 return sync_receive_impl(target, Fine_time_pt(), err_code); // sync_receive() with infinite timeout.
2569}
2570
2571template<typename Rep, typename Period, typename Mutable_buffer_sequence>
2572size_t Peer_socket::sync_receive(const Mutable_buffer_sequence& target,
2573 const boost::chrono::duration<Rep, Period>& max_wait, Error_code* err_code)
2574{
2575 assert(max_wait.count() > 0);
2576 return sync_receive_impl(target,
2578 err_code);
2579}
2580
2581template<typename Rep, typename Period>
2582bool Peer_socket::sync_receive(std::nullptr_t,
2583 const boost::chrono::duration<Rep, Period>& max_wait,
2584 Error_code* err_code)
2585{
2586 assert(max_wait.count() > 0);
2588}
2589
2590template<typename Mutable_buffer_sequence>
2591size_t Peer_socket::sync_receive_impl(const Mutable_buffer_sequence& target,
2592 const Fine_time_pt& wait_until, Error_code* err_code)
2593{
2594 FLOW_ERROR_EXEC_AND_THROW_ON_ERROR(size_t, sync_receive_impl<Mutable_buffer_sequence>, target, wait_until, _1);
2595 // ^-- Call ourselves and return if err_code is null. If got to present line, err_code is not null.
2596
2597 // We are in user thread U != W.
2598
2599 Lock_guard lock(m_mutex); // Lock m_node; also it's a pre-condition for Node::send().
2600
2601 /* Forward the rest of the logic to Node.
2602 * Now, what I really want to do here is simply:
2603 * m_node->sync_receive(...args...);
2604 * I cannot, however, due to <see same situation explained in Peer_socket::send()>.
2605 * Therefore I do the following (<see Peer_socket::send() for more comments>). */
2606
2607 const auto rcv_buf_consume_func = [this, &target]()
2608 {
2609 return m_rcv_buf.consume_bufs_copy(target);
2610 };
2611 // ^-- Important to capture `&target`, not `target`; else `target` (albeit no actual buffers) will be copied!
2612
2613 lock.release(); // Let go of the mutex (mutex is still LOCKED).
2614 /* Let this untemplated function, in .cpp, deal with Node (since .cpp knows what *m_node really is).
2615 * Note: whatever contraption lambda generated above will be converted to a Function<...> with ... being
2616 * an appropriate signature that node_sync_receive() expects, seen in the above explanatory comment. */
2617 return node_sync_receive(rcv_buf_consume_func, wait_until, err_code);
2618} // Peer_socket::sync_receive()
2619
2620template<typename Opt_type>
2621Opt_type Peer_socket::opt(const Opt_type& opt_val_ref) const
2622{
2623 // Similar to Node::opt().
2625 return opt_val_ref;
2626}
2627
2628} // namespace flow::net_flow
2629
Convenience class that simply stores a Logger and/or Component passed into a constructor; and returns...
Definition: log.hpp:1612
Interface that the user should implement, passing the implementing Logger into logging classes (Flow'...
Definition: log.hpp:1284
Utility class for use by Congestion_control_strategy implementations that implements congestion windo...
Classic congestion control but with backoff to bandwidth estimate-based pipe size.
Classic congestion control, based on Reno (TCP RFC 5681), with congestion avoidance,...
Internal net_flow class that maintains the Drop Timer for DATA packet(s) to have been sent out over a...
Definition: drop_timer.hpp:152
An object of this class is a single Flow-protocol networking node, in the sense that: (1) it has a di...
Definition: node.hpp:934
A class that keeps a Peer_socket_receive_stats data store, includes methods to conveniently accumulat...
A class that keeps a Peer_socket_send_stats data store, includes methods to conveniently accumulate d...
A peer (non-server) socket operating over the Flow network protocol, with optional stream-of-bytes an...
Drop_timer_ptr m_snd_drop_timer
The Drop Timer engine, which controls how In-flight (m_snd_flying_pkts_by_sent_when) packets are cons...
friend std::ostream & operator<<(std::ostream &os, Int_state state)
size_t m_snd_pending_rcv_wnd
While Node::low_lvl_recv_and_handle() or async part of Node::async_wait_latency_then_handle_incoming(...
size_t get_connect_metadata(const boost::asio::mutable_buffer &buffer, Error_code *err_code=0) const
Obtains the serialized connect metadata, as supplied by the user during the connection handshake.
unsigned int m_init_rexmit_count
If currently using m_init_rexmit_scheduled_task, this is the number of times the timer has already fi...
size_t max_block_size_multiple(const size_t &opt_val_ref, const unsigned int *inflate_pct_val_ptr=0) const
Returns the smallest multiple of max_block_size() that is >= the given option value,...
size_t m_snd_remote_rcv_wnd
The receive window: the maximum number of bytes the other side has advertised it would be willing to ...
Sequence_number m_rcv_next_seq_num
The maximal sequence number R from the remote side such that all data with sequence numbers strictly ...
size_t m_rcv_syn_rcvd_data_cumulative_size
The running total count of bytes in the m_data fields of m_rcv_syn_rcvd_data_q.
bool sync_send_reactor_pattern_impl(const Fine_time_pt &wait_until, Error_code *err_code)
Helper similar to sync_send_impl() but for the nullptr_t versions of sync_send().
std::vector< boost::shared_ptr< Data_packet > > Rcv_syn_rcvd_data_q
Type used for m_rcv_syn_rcvd_data_q.
std::map< Sequence_number, Sent_pkt_ordered_by_when_iter > Sent_pkt_by_seq_num_map
Short-hand for m_snd_flying_pkts_by_seq_num type; see that data member.
bool sync_receive_reactor_pattern_impl(const Fine_time_pt &wait_until, Error_code *err_code)
Helper similar to sync_receive_impl() but for the nullptr_t versions of sync_receive().
util::Mutex_non_recursive Options_mutex
Short-hand for high-performance, non-reentrant, exclusive mutex used to lock m_opts.
order_num_t m_snd_last_order_num
For the Sent_packet representing the next packet to be sent, this is the value to assign to m_sent_wh...
Sequence_number m_snd_next_seq_num
The sequence number for the start of the data in the next new DATA packet to be sent out.
Remote_endpoint m_remote_endpoint
See remote_endpoint(). Should be set before user gets access to *this and not changed afterwards.
size_t sync_receive(const Mutable_buffer_sequence &target, const boost::chrono::duration< Rep, Period > &max_wait, Error_code *err_code=0)
Blocking (synchronous) version of receive().
Fine_duration m_round_trip_time_variance
RTTVAR used for m_snd_smoothed_round_trip_time calculation.
bool m_active_connect
true if we connect() to server; false if we are to be/are accept()ed. Should be set once and not modi...
Int_state m_int_state
Current internal state of the socket.
Fine_duration m_snd_drop_timeout
The Drop Timeout: Time period between the next time m_snd_drop_timer schedules a Drop Timer and that ...
Sent_pkt_by_seq_num_map m_snd_flying_pkts_by_seq_num
The collection of all In-flight packets (including those queued up to send in pacing module),...
boost::movelib::unique_ptr< Send_bandwidth_estimator > m_snd_bandwidth_estimator
The outgoing available bandwidth estimator for this connection on this side.
util::Blob m_serialized_metadata
If !m_active_connect, this contains the serialized metadata that the user supplied on the other side ...
security_token_t m_security_token
Random security token used during SYN_ACK-SYN_ACK_ACK.
size_t node_sync_send(const Function< size_t(size_t max_data_size)> &snd_buf_feed_func_or_empty, const Fine_time_pt &wait_until, Error_code *err_code)
This is to sync_send() as node_send() is to send().
boost::movelib::unique_ptr< Congestion_control_strategy > m_snd_cong_ctl
The congestion control strategy in use for this connection on this side.
size_t sync_send_impl(const Const_buffer_sequence &data, const Fine_time_pt &wait_until, Error_code *err_code)
Same as sync_send() but uses a Fine_clock-based Fine_duration non-template type for implementation co...
Rcv_syn_rcvd_data_q m_rcv_syn_rcvd_data_q
The queue of DATA packets received while in Int_state::S_SYN_RCVD state before the Syn_ack_ack_packet...
Error_code m_disconnect_cause
The Error_code causing disconnection (if one has occurred or is occurring) on this socket; otherwise ...
Peer_socket(log::Logger *logger_ptr, util::Task_engine *task_engine, const Peer_socket_options &opts)
Constructs object; initializes most values to well-defined (0, empty, etc.) but not necessarily meani...
Definition: peer_socket.cpp:37
Fine_time_pt m_rcv_wnd_recovery_start_time
Time point at which m_rcv_in_rcv_wnd_recovery was last set to true.
Send_pacing_data m_snd_pacing_data
The state of outgoing packet pacing for this socket; segregated into a simple struct to keep Peer_soc...
Server_socket::Ptr m_originating_serv
For sockets that come a Server_socket, this is the inverse of Server_socket::m_connecting_socks: it i...
uint64_t security_token_t
Type used for m_security_token.
Sequence_number m_rcv_init_seq_num
The Initial Sequence Number (ISN) contained in the original Syn_packet or Syn_ack_packet we received.
const Remote_endpoint & remote_endpoint() const
Intended other side of the connection (regardless of success, failure, or current State).
Sent_pkt_by_sent_when_map m_snd_flying_pkts_by_sent_when
The collection of all In-flight packets, indexed by sequence number and ordered from most to least re...
State
State of a Peer_socket.
Open_sub_state
The sub-state of a Peer_socket when state is State::S_OPEN.
size_t sync_send(const Const_buffer_sequence &data, const boost::chrono::duration< Rep, Period > &max_wait, Error_code *err_code=0)
Blocking (synchronous) version of send().
~Peer_socket() override
Boring virtual destructor. Note that deletion is to be handled exclusively via shared_ptr,...
Definition: peer_socket.cpp:77
Error_code disconnect_cause() const
The error code that perviously caused state() to become State::S_CLOSED, or success code if state is ...
size_t m_rcv_pending_acks_size_at_recv_handler_start
Helper state, to be used while inside either Node::low_lvl_recv_and_handle() or async part of Node::a...
Sequence_number::seq_num_t order_num_t
Short-hand for order number type. 0 is reserved. Caution: Keep in sync with Drop_timer::packet_id_t.
flow_port_t local_port() const
The local Flow-protocol port chosen by the Node (if active or passive open) or user (if passive open)...
flow_port_t m_local_port
See local_port(). Should be set before user gets access to *this and not changed afterwards.
Peer_socket_receive_stats_accumulator m_rcv_stats
Stats regarding incoming traffic (and resulting outgoing ACKs) for this connection so far.
bool set_options(const Peer_socket_options &opts, Error_code *err_code=0)
Dynamically replaces the current options set (options()) with the given options set.
size_t m_rcv_last_sent_rcv_wnd
The last rcv_wnd value sent to the other side (in an ACK).
std::vector< Ack_packet::Individual_ack::Ptr > m_rcv_acked_packets
While Node::low_lvl_recv_and_handle() or async part of Node::async_wait_latency_then_handle_incoming(...
size_t node_send(const Function< size_t(size_t max_data_size)> &snd_buf_feed_func, Error_code *err_code)
Non-template helper for template send() that forwards the send() logic to Node::send().
std::list< boost::shared_ptr< Sent_packet > > m_snd_rexmit_q
If retransmission is on, this is the retransmission queue.
util::Scheduled_task_handle m_init_rexmit_scheduled_task
Connection attempt scheduled task; fires if an individual connection request packet is not answered w...
util::Timer m_rcv_delayed_ack_timer
Timer started, assuming delayed ACKs are enabled, when the first Individual_ack is placed onto an emp...
bool rexmit_on() const
Whether retransmission is enabled on this connection.
size_t node_sync_receive(const Function< size_t()> &rcv_buf_consume_func_or_empty, const Fine_time_pt &wait_until, Error_code *err_code)
This is to sync_receive() as node_receive() is to receive().
util::Lock_guard< Mutex > Lock_guard
Short-hand for RAII lock guard of Mutex.
Sent_pkt_by_seq_num_map::iterator Sent_pkt_ordered_by_seq_iter
Short-hand for m_snd_flying_pkts_by_seq_num iterator type.
Int_state
The state of the socket (and the connection from this end's point of view) for the internal state mac...
util::Lock_guard< Options_mutex > Options_lock
Short-hand for lock that acquires exclusive access to an Options_mutex.
Socket_buffer m_snd_buf
The Send buffer; user feeds data at the back; Node consumes data at the front.
void close_abruptly(Error_code *err_code=0)
Acts as if fatal error error::Code::S_USER_CLOSED_ABRUPTLY has been discovered on the connection.
size_t m_snd_rexmit_q_size
Equals m_snd_rexmit_q.size(). Kept since m_snd_rexmit_q.size() may be O(n) depending on implementatio...
size_t max_block_size() const
The maximum number of bytes of user data per received or sent packet on this connection.
size_t m_rcv_reassembly_q_data_size
With retransmission enabled, the sum of Received_packet::m_size over all packets stored in the reasse...
Node * node() const
Node that produced this Peer_socket.
Definition: peer_socket.cpp:95
Fine_time_pt m_snd_last_loss_event_when
The last time that Node has detected a packet loss event and so informed m_snd_cong_ctl by calling th...
Peer_socket_info info() const
Returns a structure containing the most up-to-date stats about this connection.
Socket_buffer m_rcv_buf
The Receive buffer; Node feeds data at the back; user consumes data at the front.
Recvd_pkt_map::iterator Recvd_pkt_iter
Short-hand for m_rcv_packets_with_gaps iterator type.
Mutex m_mutex
This object's mutex.
Peer_socket_send_stats_accumulator m_snd_stats
Stats regarding outgoing traffic (and resulting incoming ACKs) for this connection so far.
Sent_pkt_by_sent_when_map::iterator Sent_pkt_ordered_by_when_iter
Short-hand for m_snd_flying_pkts_by_sent_when iterator type.
Sent_pkt_by_seq_num_map::const_iterator Sent_pkt_ordered_by_seq_const_iter
Short-hand for m_snd_flying_pkts_by_seq_num const iterator type.
Peer_socket_info m_info_on_close
This is the final set of stats collected at the time the socket was moved to S_CLOSED m_state.
bool ensure_open(Error_code *err_code) const
Helper that is equivalent to Node::ensure_sock_open(this, err_code).
Sent_pkt_by_sent_when_map::const_iterator Sent_pkt_ordered_by_when_const_iter
Short-hand for m_snd_flying_pkts_by_sent_when const iterator type.
Sequence_number m_snd_init_seq_num
The Initial Sequence Number (ISN) used in our original SYN or SYN_ACK.
Opt_type opt(const Opt_type &opt_val_ref) const
Analogous to Node::opt() but for per-socket options.
std::string bytes_blocks_str(size_t bytes) const
Helper that, given a byte count, returns a string with that byte count and the number of max_block_si...
Fine_duration m_snd_smoothed_round_trip_time
Estimated current round trip time of packets, computed as a smooth value over the past individual RTT...
util::Mutex_recursive Mutex
Short-hand for reentrant mutex type.
size_t sync_receive_impl(const Mutable_buffer_sequence &target, const Fine_time_pt &wait_until, Error_code *err_code)
Same as sync_receive() but uses a Fine_clock-based Fine_duration non-template type for implementation...
std::vector< boost::shared_ptr< Individual_ack > > m_rcv_pending_acks
The received packets to be acknowledged in the next low-level ACK packet to be sent to the other side...
Peer_socket_options m_opts
This socket's per-socket set of options.
bool m_rcv_in_rcv_wnd_recovery
true indicates we are in a state where we've decided other side needs to be informed that our receive...
util::Scheduled_task_handle m_connection_timeout_scheduled_task
Connection timeout scheduled task; fires if the entire initial connection process does not complete w...
Peer_socket_options options() const
Copies this socket's option set and returns that copy.
Options_mutex m_opts_mutex
The mutex protecting m_opts.
std::map< Sequence_number, boost::shared_ptr< Received_packet > > Recvd_pkt_map
Short-hand for m_rcv_packets_with_gaps type; see that data member.
Recvd_pkt_map::const_iterator Recvd_pkt_const_iter
Short-hand for m_rcv_packets_with_gaps const iterator type.
Open_sub_state m_open_sub_state
See state().
boost::shared_ptr< Drop_timer > Drop_timer_ptr
Short-hand for shared_ptr to immutable Drop_timer (can't use Drop_timer::Ptr due to C++ and circular ...
Recvd_pkt_map m_rcv_packets_with_gaps
The sequence-number-ordered collection of all received-and-not-dropped-due-to-buffer-overflow packets...
size_t m_snd_flying_bytes
The number of bytes contained in all In-flight packets, used at least for comparison against the cong...
std::vector< order_num_t > m_snd_temp_pkts_marked_to_drop
Helper data structure to store the packet IDs of packets that are marked Dropped during a single run ...
size_t receive(const Mutable_buffer_sequence &target, Error_code *err_code=0)
Receives (consumes from the Receive buffer) bytes of data, up to a given maximum cumulative number of...
Fine_time_pt m_snd_last_data_sent_when
Time at which the last Data_packet low-level packet for this connection was sent.
size_t node_receive(const Function< size_t()> &rcv_buf_consume_func, Error_code *err_code)
Non-template helper for template receive() that forwards the receive() logic to Node::receive().
size_t send(const Const_buffer_sequence &data, Error_code *err_code=0)
Sends (adds to the Send buffer) the given bytes of data up to a maximum internal buffer size; and asy...
State state(Open_sub_state *open_sub_state=0) const
Current State of the socket.
Definition: peer_socket.cpp:85
util::Scheduled_task_handle m_rcv_wnd_recovery_scheduled_task
When m_rcv_in_rcv_wnd_recovery is true, this is the scheduled task to possibly send another unsolicit...
A per-Peer_socket module that tries to estimate the bandwidth available to the outgoing flow.
Definition: bandwidth.hpp:125
An internal net_flow sequence number identifying a piece of data.
Definition: seq_num.hpp:126
uint64_t seq_num_t
Raw sequence number type.
Definition: seq_num.hpp:138
A server socket able to listen on a single Flow port for incoming connections and return peer sockets...
Internal net_flow class that implements a socket buffer, as used by Peer_socket for Send and Receive ...
size_t feed_bufs_copy(const Const_buffer_sequence &data, size_t max_data_size)
Feeds (adds to the back of the byte buffer) the contents of the byte stream composed of the bytes in ...
size_t consume_bufs_copy(const Mutable_buffer_sequence &target_bufs)
Consumes (removes from the front of the internal byte buffer and returns them to the caller) a byte s...
Iterator iterator
For container compliance (hence the irregular capitalization): Iterator type.
Const_iterator const_iterator
For container compliance (hence the irregular capitalization): Const_iterator type.
An empty interface, consisting of nothing but a default virtual destructor, intended as a boiler-plat...
Definition: util.hpp:45
Convenience class template that endows the given subclass T with nested aliases Ptr and Const_ptr ali...
boost::shared_ptr< Server_socket > Ptr
Short-hand for ref-counted pointer to mutable values of type Target_type::element_type (a-la T*).
#define FLOW_ERROR_EXEC_AND_THROW_ON_ERROR(ARG_ret_type, ARG_function_name,...)
Narrow-use macro that implements the error code/exception semantics expected of most public-facing Fl...
Definition: error.hpp:363
Flow module containing the API and implementation of the Flow network protocol, a TCP-inspired stream...
Definition: node.cpp:25
uint16_t flow_port_t
Logical Flow port type (analogous to a UDP/TCP port in spirit but in no way relevant to UDP/TCP).
std::ostream & operator<<(std::ostream &os, const Congestion_control_selector::Strategy_choice &strategy_choice)
Serializes a Peer_socket_options::Congestion_control_strategy_choice enum to a standard ostream – the...
Definition: cong_ctl.cpp:146
Fine_time_pt chrono_duration_from_now_to_fine_time_pt(const boost::chrono::duration< Rep, Period > &dur)
Helper that takes a non-negative duration of arbitrary precision/period and converts it to Fine_durat...
Definition: util.hpp:42
boost::unique_lock< Mutex > Lock_guard
Short-hand for advanced-capability RAII lock guard for any mutex, ensuring exclusive ownership of tha...
Definition: util_fwd.hpp:265
boost::recursive_mutex Mutex_recursive
Short-hand for reentrant, exclusive mutex.
Definition: util_fwd.hpp:218
boost::shared_ptr< Scheduled_task_handle_state > Scheduled_task_handle
Black-box type that represents a handle to a scheduled task as scheduled by schedule_task_at() or sch...
boost::asio::io_context Task_engine
Short-hand for boost.asio event service, the central class of boost.asio.
Definition: util_fwd.hpp:135
boost::mutex Mutex_non_recursive
Short-hand for non-reentrant, exclusive mutex. ("Reentrant" = one can lock an already-locked-in-that-...
Definition: util_fwd.hpp:215
boost::asio::basic_waitable_timer< Fine_clock > Timer
boost.asio timer.
Definition: util_fwd.hpp:202
Blob_with_log_context<> Blob
A concrete Blob_with_log_context that compile-time-disables Basic_blob::share() and the sharing API d...
Definition: blob_fwd.hpp:60
boost::system::error_code Error_code
Short-hand for a boost.system error code (which basically encapsulates an integer/enum error code and...
Definition: common.hpp:508
Fine_clock::duration Fine_duration
A high-res time duration as computed from two Fine_time_pts.
Definition: common.hpp:416
Fine_clock::time_point Fine_time_pt
A high-res time point as returned by Fine_clock::now() and suitable for precise time math in general.
Definition: common.hpp:413
Metadata describing the data sent in the acknowledgment of an individual received packet.
const size_t m_data_size
Number of bytes in the packet's user data.
boost::shared_ptr< const Individual_ack > Const_ptr
Short-hand for ref-counted pointer to immutable objects of this class.
const unsigned int m_rexmit_id
Retransmit counter of the packet (as reported by sender).
const Sequence_number m_seq_num
Sequence number of first datum in packet.
boost::shared_ptr< Individual_ack > Ptr
Short-hand for ref-counted pointer to mutable objects of this class.
const Fine_time_pt m_received_when
When was it received? Used for supplying delay before acknowledging (for other side's RTT calculation...
util::Noncopyable m_nc
Make us noncopyable without breaking aggregateness (direct-init).
Metadata (and data, if retransmission is on) for a packet that has been received (and,...
const size_t m_size
Number of bytes in the Data_packet::m_data field of that packet.
Received_packet(log::Logger *logger_ptr, size_t size, util::Blob *src_data)
Constructs object by storing size of data and, if so instructed, the data themselves.
util::Blob m_data
Byte sequence equal to that of Data_packet::m_data of the packet.
Data store to keep timing related info when a packet is sent out.
const order_num_t m_order_num
Order number of the packet.
size_t m_sent_cwnd_bytes
The congestion window size (in bytes) that is used when the packet is sent out.
Fine_time_pt m_sent_time
The timestamp when the packet is sent out.
Metadata (and data, if retransmission is on) for a packet that has been sent one (if retransmission i...
Sent_packet(bool rexmit_on, boost::shared_ptr< Data_packet > packet, const Sent_when &sent_when)
Constructs object with the given values and m_acks_after_me at zero.
std::vector< Sent_when > m_sent_when
Time stamps, order numbers, and other info at the times when the different attempts (including origin...
const size_t m_size
Number of bytes in the Data_packet::m_data field of the sent packet.
const boost::shared_ptr< Data_packet > m_packet
If retransmission is on, this is the DATA packet itself that was sent; otherwise null.
uint16_t ack_count_t
Type used for m_acks_after_me.
ack_count_t m_acks_after_me
The number of times any packet with m_sent_when.back().m_order_num > this->m_sent_when....
A data store that keeps stats about the a Peer_socket connection.
Definition: info.hpp:456
A set of low-level options affecting a single Peer_socket.
Definition: options.hpp:36
Represents the remote endpoint of a Flow-protocol connection; identifies the UDP endpoint of the remo...
Definition: endpoint.hpp:93
The current outgoing packet pacing state, including queue of low-level packets to be sent,...
Definition: low_lvl_io.hpp:178
Useful as a no-unique-address private member to make a type noncopyable while keeping that type an ag...
Definition: util.hpp:74