Flow 1.0.0
Flow project: Full implementation reference.
drop_timer.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
24#include <boost/enable_shared_from_this.hpp>
25#include <set>
26
27namespace flow::net_flow
28{
29// Types.
30
31/**
32 * Internal `net_flow` class that maintains the Drop Timer for DATA packet(s) to have been sent out
33 * over a connection but not yet acknowledged by the receiver. This is similar to the
34 * Retransmission Timer of TCP (although the way that timer works is not solidly standardized,
35 * though there are recommended setups in RFCs like RFC 6298). However, this applies even with
36 * retransmission disabled (which is allowed in NetFlow but not in TCP), so it would be incorrect to
37 * call it `Rexmit_timer`; on the other hand when retransmission is enabled, Drop_timer will still be
38 * an accurate name (as a packet has to be considered Dropped before we retransmit it). `net_flow`
39 * users should not use this class directly.
40 *
41 * The basic idea is: if you send a packet, and it's not acknowledged within some amount of time,
42 * then consider that packet Dropped. (At that point you can take it out of the In-flight window,
43 * or retransmit it, or whatever else is appropriate.) Beyond this concept the details are
44 * ambiguous, and there is no one right/standard/accepted answer for how it should work. For
45 * example, when to restart the timer? What to do with the timer after it fires? Etc. Therefore
46 * the class is reasonably configurable, so that we can experiment with different approaches.
47 *
48 * This class works together with Node, Peer_socket, and Server_socket and accordingly assumes
49 * very specific algorithms are used in sending and handling acknowledgments. However it
50 * could pretty easily be swapped out with another implementationr
51 *
52 * A Drop_timer works as follows. It keeps an internal timer that fires every DTO seconds, where
53 * DTO is computed externally (from SRTT, etc.). Certain events start or restart the timer (e.g.,
54 * receiving an acknowledgment). Other events stop the timer (namely having no more In-flight
55 * packets). Then when the timer fires, certain actions have to be taken, such as considering
56 * packets Dropped and/or restarting the timer. Additionally the DTO value itself can be written to
57 * by Drop_timer (e.g., timer backoff).
58 *
59 * Therefore, the interface of Drop_timer is simple: you call `on_...()`, when a Drop
60 * Timer-influencing event has occurred; and when some action needs to be taken due to a Drop Timer
61 * firing, it calls a user-supplied callback which will perform that action. The action callbacks
62 * are supplied at construction. Drop_timer internally takes care of everything in-between:
63 * running/stopping the timer, catching the timer firing, etc. All of the "policy" about how the
64 * timer operates is also inside. Calling done() means the socket is done, and no action callbacks
65 * will subsequently fire.
66 *
67 * To schedule the timer, Drop_timer shares Node's main event queue (Node::m_task_engine).
68 *
69 * ### Thread safety ###
70 * To be used in the containing Node's thread W only.
71 *
72 * Implementation notes
73 * --------------------
74 *
75 * Having written this class, it looks over-engineered. The code would be shorter (no `shared_ptr`,
76 * callbacks, factory, `enable_shared_from_this`) if it were directly in Node and Peer_socket. On the
77 * other hand the Strategy Pattern setup used here is nice for segregating the Drop Timer logic and
78 * for future modification, and it does make Node (which is huge) much easier to understand. So could
79 * go either way... rewrite in Node and Peer_socket or leave it alone.
80 *
81 * We use a `Ptr`-emitting factory, because wrapping the object in a `Ptr` helps with some internal
82 * book-keeping and is useful to the user as well.
83 *
84 * ### Regarding events ###
85 * You'll note the interface is extremely simple: essentially, outside code just registers whenever
86 * packet becomes In-flight (a/k/a is sent over wire); and the opposite. This simplicity comes at
87 * an implementation cost, because it requires us to keep -- *internally* -- an ordered (by send time) set
88 * of packets currently In-flight. Why do this? Because the true events we are interested in are slightly
89 * more complex than what the Drop_timer API exposes: we want to detect when no packets are In-flight and
90 * suddenly a packet is sent off; the reverse; the acknowledgment of a packet that is NOT the oldest
91 * one currently In-flight; and the changing of the oldest currently In-flight packet from packet A to
92 * packet B =/= A. (That's as of this writing; perhaps this set of events could change.)
93 *
94 * One might wonder whether it would be -- overall -- simpler to just have the event API of Drop_timer (the set of
95 * on_...() methods) just be those exact events I just listed. Then outside code could just call them when detecting
96 * those events. After all, Peer_socket has complex structures keeping track all sorts of details including how
97 * many and which packets are In-flight, so Peer_socket and Node code could easily detect all those situations.
98 *
99 * In fact, that IS how Drop_timer was implemented in the past. Here is why I changed it: There is a small
100 * caveat about what "In-flight" means. Peer_socket's `m_snd_flying_pkts_...` data structures define "In-flight
101 * packet" as "packet that has been determined to be fit to send over the wire, having passed the availability
102 * and CWND constraints." For Drop_timer's ideal operation, "In-flight packet" is defined as "packet that has
103 * been sent over the wire." The practical difference between the two definitions is that the former may be
104 * awaiting certain send pacing conditions to actually be sent off; whereas the latter means it has been sent
105 * off -- period. (See `struct Send_pacing_data` and related code for info on pacing. Essentially, though,
106 * any packet that's definitely going to be sent out barring existential disaster may be delayed a bit in a pacing
107 * queue to avoid bunching up packets in the pipe.) However, we lack a data structure that specifically
108 * stores packets to have been sent off over the wire, except indirectly in Peer_socket::m_snd_flying_pkts_by_sent_when
109 * minus Send_pacing_data::m_packet_q. The former is unwieldy for our purposes, let along when combined with the
110 * other. So it made more sense to just let outside code report truly In-flight packets appearing and disappearing
111 * to us, then we store the (rather minimal) information internally. Thus we separate concerns and divide
112 * labor among modules in an accurate fashion instead of Drop_timer becoming ultra-dependent on other modules'
113 * implementation details. That said, there is probably some memory cost and (maybe) a little processor cycle
114 * cost to this approach. (One could also say that the pacing delay is so minor as to make it ignorable
115 * here. However, I decided I don't need the headache of wondering/worrying about that ad infinitum; and
116 * solved the problem instead.)
117 *
118 * ### Update regarding events ###
119 * In order to increase performance by smooshing together lots of little checks and
120 * actions that might occur when handling lots of little events, namely received acknowledgments, the class
121 * user must now bracket groups of `on_...()` method calls with start_contemporaneous_events() and
122 * end_contemporaneous_events(). Thus each `on_...()` call performs only very basic/quick book-keeping; while
123 * end_contemporaneous_events() is what compares the situation against what it was at start_contemporaneous_events()
124 * and possibly detects the true events of interest that may actually trigger something (start timer, stop timer,
125 * restart running timer).
126 *
127 * ### `Timer` vs util::schedule_task_from_now() ###
128 * In other places we have tended to replace a `Timer` with the far simpler util::schedule_task_from_now() (etc.)
129 * facility (which internally uses a `Timer` but hides its various annoyances and caveats). Why not here?
130 * Answer: We don't happen to use any of `Timer`'s advanced features that the simpler facility lacks; we just
131 * schedule and cancel, and the other facility supports those. So that just leaves the potential performance
132 * effects as the reason not to use the simpler facility (as listed in util::schedule_task_from_now() doc header).
133 * The logic concerning the delay before each scheduled task, and how often it might be canceled and/or
134 * rescheduled is not simple. It's hard to make iron-clad guarantees, therefore, that using a single repeatedly-reused
135 * `Timer` is no better perf-wise than using multiple schedulings using the simpler facility. So we do the
136 * perf-conservative thing and use `Timer` despite having to worry about a couple of the associated corner cases.
137 *
138 * Or to put it concisely: The timer logic here is complicated, so the perf and flexibility aspects of directly using
139 * the advanced `Timer` feature are suitable.
140 *
141 * @todo Drop_timer has data members that are references to non-`const`. These should be pointers for max consistency
142 * of style with other code in the project (and that style is encouraged for certain good reasons). Scour rest of
143 * code for other such data members as well.
144 */
146 // Endow us with shared_ptr<>s ::Ptr and ::Const_ptr (syntactic sugar).
147 public util::Shared_ptr_alias_holder<boost::shared_ptr<Drop_timer>>,
148 // Allow access to Ptr(this) from inside Drop_timer methods. Just call shared_from_this().
149 public boost::enable_shared_from_this<Drop_timer>,
150 public log::Log_context,
151 private boost::noncopyable
152{
153public:
154 // Types.
155
156 /**
157 * Type to uniquely identify a packet sent over the wire in the socket to which this Drop_timer applies.
158 * Caution: keep in sync with Peer_socket::order_num_t. That way Peer_socket
159 * code can easily form a #packet_id_t from an `order_num_t` which, too, uniquely identifies a packet.
160 * 0 is reserved, not to be used for any actual packets.
161 */
163
164 // Constructors/destructor.
165
166 /// Destructor.
167 ~Drop_timer();
168
169 // Methods.
170
171 /**
172 * Constructs Drop_timer and returns a ref-counted pointer wrapping it. Saves the "action
173 * callbacks" to call when various events fire in this Drop_timer. The callbacks may be placed
174 * onto `*node_task_engine` in the manner of `Task_engine::post()`, at any future time until done()
175 * is called. At construction, the timer is guaranteed not to fire until the first `on_...()` call.
176 *
177 * After construction, call `on_...()` as events occur. If an event described by the doc comment of
178 * an `on_...()` method occurs, you MUST call it or results are undefined (the state machine breaks
179 * down).
180 *
181 * @param logger_ptr
182 * The Logger implementation to use subsequently.
183 * @param node_task_engine
184 * The containing Node's `&m_task_engine`. Asyncronous callbacks will be placed on it
185 * (see below).
186 * @param sock_drop_timeout
187 * Pointer to the containing Peer_socket's `m_snd_drop_timeout.` Drop_timer may write to this
188 * member if it feels the need to modify Drop Timeout value (as in RFC 6298 section 5.5)!
189 * @param sock
190 * Pointer to the containing Peer_socket. Access is read-only.
191 * @param timer_failure
192 * Function `F` with signature `void F(const Error_code& err_code)`.
193 * `F(<failure code>)` will be called if and only if there was an internal system timer
194 * failure. Required action of `timer_failure()`: RST/close with the given error.
195 * @param timer_fired
196 * Function `F` with signature `void F(bool drop_all_packets)`. `F(drop_all_packets)` will be
197 * called if and only if the Drop Timer has fired. Required action of `timer_fired()`: mark
198 * either all (if `drop_all_packets`) or just the earliest (otherwise) In-flight packet(s) as
199 * Dropped.
200 * @return A ref-counted pointer wrapping a newly created Drop_timer as described above.
201 */
202 static Ptr create_drop_timer(log::Logger* logger_ptr,
203 util::Task_engine* node_task_engine,
204 Fine_duration* sock_drop_timeout,
206 const Function<void (const Error_code& err_code)>& timer_failure,
207 const Function<void (bool drop_all_packets)>& timer_fired);
208
209 /**
210 * Indicates the start of a series of zero or more contemporary `on_*()` event calls, to be marked as finished
211 * via end_contemporaneous_events(). Contemporary means to be treated as occurring in that order but essentially
212 * simultaneously. (It is recommended but not enforced that they be registered in the same boost.asio task.)
213 * This call should be followed by the 0+ `on_*()` calls; and finally end_contemporaneous_events(). Grouping events
214 * in this way allows for better performance than, for example, a series of one-event groups.
215 */
217
218 /**
219 * Indicates that a packet identified by the given unique ID has just been
220 * sent over the wire (the low-level transport, currently UDP). Subtlety: Peer_socket may consider a packet
221 * In-flight before it has actually been sent out over the wire, namely if it is queued in the pacing
222 * module. This should be called only once it is actually sent. Note, however, that IF `on_packet_in_flight(P)`
223 * is called, then indeed the packet identified by `P` _must_ be considered In-flight in the Peer_socket
224 * sense. See Peer_socket::m_snd_flying_pkts_by_sent_when for definition of In-flight.
225 *
226 * A contemporary event group must be in progress via start_contemporaneous_events(); or behavior is undefined.
227 *
228 * @param packet_id
229 * ID of the packet that was sent out. This can be any number as long as it increases with each
230 * subsequent call to this method for `*this Drop_timer` (in particular, it'll therefore also be unique
231 * per Drop_timer). Behavior is undefined if this rule is not followed.
232 */
233 void on_packet_in_flight(packet_id_t packet_id);
234
235 /**
236 * Indicates that a packet for which on_packet_in_flight() was called is now no longer considered In-flight
237 * in the Peer_socket sense; see Peer_socket::m_snd_flying_pkts_by_sent_when for definition of In-flight.
238 * Since `on_packet_in_flight(P)` must be called only if `P` was then In-flight, `on_packet_no_longer_in_flight(P)`
239 * can be called at most once and only after the former call.
240 *
241 * A contemporary event group must be in progress via start_contemporaneous_events(); or behavior is undefined.
242 *
243 * @param packet_id
244 * ID of a packet for which on_packet_in_flight() has been called exactly once for `*this`.
245 * Otherwise behavior is undefined.
246 */
248
249 /**
250 * Equivalent to `on_packet_no_longer_in_flight(P)`, for all `P` currently In-flight as registered by
251 * `on_packet_in_flight(P)`. When you know it would be correct, call it instead of the former method many times
252 * for better efficiency. (Do not do "both." Trying to register more than once that `P` is no longer In-flight leads
253 * to undefined behavior.)
254 *
255 * Calling this when no packets are In-flight already leads to undefined behavior.
256 *
257 * A contemporary event group must be in progress via start_contemporaneous_events(); or behavior is undefined.
258 */
260
261 /**
262 * Indicates that a packet for which on_packet_in_flight() was called has just been validly acked.
263 * To be validly acked means that an acknowledgment was received while the packet was considered In-flight in
264 * the Peer_socket sense. See Peer_socket::m_snd_flying_pkts_by_sent_when for definition of In-flight.
265 *
266 * Such a packet also requires an on_packet_no_longer_in_flight() call. You must call on_ack() first; and the latter
267 * subsequently. Otherwise behavior is undefined.
268 *
269 * A contemporary event group must be in progress via start_contemporaneous_events(); or behavior is undefined.
270 *
271 * @param packet_id
272 * ID of a packet for which on_packet_in_flight() has been called exactly once for *this.
273 * Otherwise behavior is undefined.
274 */
275 void on_ack(packet_id_t packet_id);
276
277 /**
278 * Finishes the group started by start start_contemporaneous_events(). This may trigger various on-event behavior
279 * such as starting, stopping, or restarting the Drop_timer.
280 */
282
283 /**
284 * Causes the Drop_timer to guarantee none of the action callbacks provided at construction will
285 * be called from this point on. Call this once you have no need of the Drop_timer (probably upon
286 * exiting Peer_socket::Int_state::S_ESTABLISHED). Subsequent calls to done() are harmless.
287 *
288 * Behavior is undefined if calling any other methods after done().
289 */
290 void done();
291
292private:
293
294 // Types.
295
296 /// The counter type used to distinguish a given start_timer() call from any other such call (for this object).
297 using timer_wait_id_t = uint64_t;
298
299 // Constructors.
300
301 /**
302 * Constructs Drop_timer as described in the factory constructor create_drop_timer().
303 * Why have the factory method? We guarantee that this won't get deleted before the timer
304 * callback executes (causing a crash therein), by passing a `Ptr(this)` to
305 * `basic_waitable_timer::async_wait()`. However that can only work if all users of the object also
306 * access it by a sharing `Ptr`. Thus we only provide access to the outside via a `Ptr` (the
307 * factory).
308 *
309 * @param logger
310 * See create_drop_timer().
311 * @param node_task_engine
312 * See create_drop_timer().
313 * @param sock_drop_timeout
314 * See create_drop_timer().
315 * @param sock
316 * See create_drop_timer().
317 * @param timer_failure
318 * See create_drop_timer().
319 * @param timer_fired
320 * See create_drop_timer().
321 */
322 explicit Drop_timer(log::Logger* logger,
323 util::Task_engine* node_task_engine,
324 Fine_duration* sock_drop_timeout,
326 const Function<void (const Error_code& err_code)>& timer_failure,
327 const Function<void (bool drop_all_packets)>& timer_fired);
328
329 // Methods.
330
331 /**
332 * Starts a new wait on the timer, so that is it asynchronously triggered according to the current
333 * DTO value. Pre-condition: `!m_timer_running`.
334 */
335 void start_timer();
336
337 /// Invalidates the running asynchronous wait on #m_timer. Pre-condition: #m_timer_running.
338 void disable_timer();
339
340 /**
341 * Called by boost.asio when the Drop Timer fires; disables timer and calls an outside action
342 * callback (given in constructor). If #m_done or `m_current_wait_id != wait_id` or `err_code` is
343 * `operation_aborted` (meaning this invokation by boost.asio is obsolete and replaced by a
344 * subsequent async_wait(), or canceled), does nothing.
345 *
346 * @param wait_id
347 * The value of #m_current_wait_id at the time that `m_timer.async_wait()` was called with
348 * this method invokation as an argument.
349 * @param prevent_destruction
350 * `shared_from_this()` at the time of `m_timer.async_wait()`. It assures `this` cannot be
351 * deleted until this handle_timer_firing() is called and returns.
352 * @param sys_err_code
353 * boost.asio error code indicating the circumstances of the callback executing. If this
354 * is `boost::error::operation_aborted`, method does nothing.
355 */
356 void handle_timer_firing(Ptr prevent_destruction,
357 timer_wait_id_t wait_id,
358 const Error_code& sys_err_code);
359
360 /**
361 * Called by boost.asio after we post it, in the event of some timer error. If #m_done, does
362 * nothing (meaning the object was turned off before this had a chance to be executed). Otherwise
363 * executes the `m_timer_failure()` callback.
364 *
365 * @param prevent_destruction
366 * `shared_from_this()` at the time of `m_timer.async_wait()`. It assures `this` cannot be
367 * deleted until `this->handle_timer_firing()` is called and returns.
368 * @param err_code
369 * The portable error to pass to the `m_timer_failure()`.
370 */
371 void timer_failure(Ptr prevent_destruction, const Error_code& err_code);
372
373 // Data.
374
375 /// Node::m_task_engine of the containing Node. Used to schedule timer events.
377
378 /**
379 * Reference to the containing Peer_socket's Peer_socket::m_snd_drop_timeout data member (= DTO, Drop Timeout,
380 * RTO). Why is this not `const`? Because under certain policies this object is allowed to
381 * CHANGE the value of the DTO. E.g., RFC 6298 says that RTO MUST be doubled each time the
382 * Retransmit Timer fires. (However a subsequent RTT measurement and SRTT recalculation will
383 * change it back to the normally computed value.)
384 */
386
387 /**
388 * The containing Peer_socket (note that this is read-only access). This may be used
389 * to, at least, get the time point at which a packet was originally sent, to schedule the timer,
390 * as well to get socket options related to Drop Timer.
391 */
393
394 /**
395 * The Drop Timer itself. This class maintains it (including based on input events reported by
396 * the user) and informs the user when it expires and what to do about it if so.
397 */
399
400 /**
401 * Is there an active (non-obsolete, not-canceled) asynchronous wait in progress on #m_timer? More
402 * precisely, this is `true` if the latest start_timer() call was later than the latest
403 * disable_timer() or handle_timer_firing(), or if start_timer() has been called but
404 * disable_timer() or handle_timer_firing() has not.
405 *
406 * #m_timer_running should not be checked unless `!m_done`.
407 */
409
410 /**
411 * Unique (within this object) identifier of the last start_timer() call. Each time start_timer()
412 * calls `boost::asio::basic_waitable_timer::async_wait()`, it passes `++m_current_wait_id` to the timer
413 * firing callback. Then when that callback runs, it can check whether this passed `wait_id` is
414 * equal to #m_current_wait_id; if not then it knows the callback is called for an obsolete wait
415 * and should do nothing. This is to help deal with the fact that a `basic_waitable_timer` callback can
416 * fire after it is `cancel()`ed if the callback was already queued by the time `cancel()` is called
417 * (see `boost::asio::basic_waitable_timer` documentation).
418 *
419 * For example, if I schedule wait 1, and it is queued to fire 5 seconds later, but at that point
420 * something causes me to cancel and schedule wait 2 for another 5 seconds later, then wait 1's
421 * callback, though soon called, will detect that `wait_id < m_current_wait_id` and do nothing, as
422 * desired. Another 5 seconds later, wait 2's callback will see that `wait_id == m_current_wait_id`
423 * and do stuff, as desired.
424 *
425 * This must only change via increment and start at zero. Wrap-around is impossible due to the
426 * range of #timer_wait_id_t and the time periods practically involved.
427 *
428 * #m_current_wait_id should not be checked unless #m_timer_running.
429 */
431
432 /// `true` if and only if done() has been called. Starts at `false`, can only change to `true`.
433 bool m_done;
434
435 /// Called on error. See Drop_timer constructor.
436 Function<void (const Error_code& err_code)> m_timer_failure;
437
438 /// Called on Drop Timeout. See Drop_timer constructor.
439 Function<void (bool drop_all_packets)> m_timer_fired;
440
441 /**
442 * Packet IDs of packets to have been sent over wire and still considered In-flight, ordered from
443 * earliest to latest to have been sent out. These are packet IDs for which on_packet_in_flight() but not
444 * yet on_packet_no_longer_in_flight() has been called.
445 *
446 * Since the iterator ordering is increasing numerical order (ordered set of `packet_id`s), and `packet_id`s passed to
447 * on_packet_in_flight() must be increasing from call to call, the aforementioned ordering (by time sent) is
448 * expressed via the iterator ordering. Thus the earliest-sent packet is easily accessible via `begin()`; this is
449 * needed for certain drop-timer situations.
450 *
451 * Logarithmic-time erasure for on_packet_no_longer_in_flight() is also available.
452 */
453 std::set<packet_id_t> m_flying_packets;
454
455 /**
456 * The packet ID of the least recently sent In-flight packet at last
457 * start_contemporaneous_events() call; or 0 if `m_flying_packets.empty()` at the time.
458 */
460
461 /**
462 * During the time period starting with the last start_contemporaneous_events() call and ending with the subsequent
463 * end_contemporaneous_events() call, if any -- in other words, during the last
464 * contemporary events group, finished or otherwise -- this is the ID of the most-recently-sent packet (highest
465 * packet ID) such that that packet was acknowledged during that time period. 0 if none were acknowledged.
466 */
468
469 /**
470 * `true` if and only if the last start_contemporaneous_events() call exists, and either end_contemporaneous_events()
471 * hasn't been called at all or was called before the former call.
472 */
474}; // class Drop_timer
475
476} // namespace flow::net_flow
Convenience class that simply stores a Logger and/or Component passed into a constructor; and returns...
Definition: log.hpp:1619
Interface that the user should implement, passing the implementing Logger into logging classes (Flow'...
Definition: log.hpp:1291
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
Sequence_number::seq_num_t packet_id_t
Type to uniquely identify a packet sent over the wire in the socket to which this Drop_timer applies.
Definition: drop_timer.hpp:162
packet_id_t m_during_events_newest_acked_packet
During the time period starting with the last start_contemporaneous_events() call and ending with the...
Definition: drop_timer.hpp:467
Function< void(const Error_code &err_code)> m_timer_failure
Called on error. See Drop_timer constructor.
Definition: drop_timer.hpp:436
packet_id_t m_at_events_start_oldest_flying_packet
The packet ID of the least recently sent In-flight packet at last start_contemporaneous_events() call...
Definition: drop_timer.hpp:459
void timer_failure(Ptr prevent_destruction, const Error_code &err_code)
Called by boost.asio after we post it, in the event of some timer error.
Definition: drop_timer.cpp:571
void end_contemporaneous_events()
Finishes the group started by start start_contemporaneous_events().
Definition: drop_timer.cpp:118
void on_ack(packet_id_t packet_id)
Indicates that a packet for which on_packet_in_flight() was called has just been validly acked.
Definition: drop_timer.cpp:72
void start_timer()
Starts a new wait on the timer, so that is it asynchronously triggered according to the current DTO v...
Definition: drop_timer.cpp:347
void on_packet_no_longer_in_flight(packet_id_t packet_id)
Indicates that a packet for which on_packet_in_flight() was called is now no longer considered In-fli...
Definition: drop_timer.cpp:92
static Ptr create_drop_timer(log::Logger *logger_ptr, util::Task_engine *node_task_engine, Fine_duration *sock_drop_timeout, Peer_socket::Const_ptr &&sock, const Function< void(const Error_code &err_code)> &timer_failure, const Function< void(bool drop_all_packets)> &timer_fired)
Constructs Drop_timer and returns a ref-counted pointer wrapping it.
Definition: drop_timer.cpp:28
const Peer_socket::Const_ptr m_sock
The containing Peer_socket (note that this is read-only access).
Definition: drop_timer.hpp:392
std::set< packet_id_t > m_flying_packets
Packet IDs of packets to have been sent over wire and still considered In-flight, ordered from earlie...
Definition: drop_timer.hpp:453
Function< void(bool drop_all_packets)> m_timer_fired
Called on Drop Timeout. See Drop_timer constructor.
Definition: drop_timer.hpp:439
bool m_timer_running
Is there an active (non-obsolete, not-canceled) asynchronous wait in progress on m_timer?...
Definition: drop_timer.hpp:408
Drop_timer(log::Logger *logger, util::Task_engine *node_task_engine, Fine_duration *sock_drop_timeout, Peer_socket::Const_ptr &&sock, const Function< void(const Error_code &err_code)> &timer_failure, const Function< void(bool drop_all_packets)> &timer_fired)
Constructs Drop_timer as described in the factory constructor create_drop_timer().
Definition: drop_timer.cpp:293
bool m_done
true if and only if done() has been called. Starts at false, can only change to true.
Definition: drop_timer.hpp:433
timer_wait_id_t m_current_wait_id
Unique (within this object) identifier of the last start_timer() call.
Definition: drop_timer.hpp:430
void handle_timer_firing(Ptr prevent_destruction, timer_wait_id_t wait_id, const Error_code &sys_err_code)
Called by boost.asio when the Drop Timer fires; disables timer and calls an outside action callback (...
Definition: drop_timer.cpp:477
void done()
Causes the Drop_timer to guarantee none of the action callbacks provided at construction will be call...
Definition: drop_timer.cpp:321
void start_contemporaneous_events()
Indicates the start of a series of zero or more contemporary on_*() event calls, to be marked as fini...
Definition: drop_timer.cpp:41
util::Task_engine & m_node_task_engine
Node::m_task_engine of the containing Node. Used to schedule timer events.
Definition: drop_timer.hpp:376
void on_no_packets_in_flight_any_longer()
Equivalent to on_packet_no_longer_in_flight(P), for all P currently In-flight as registered by on_pac...
Definition: drop_timer.cpp:105
util::Timer m_timer
The Drop Timer itself.
Definition: drop_timer.hpp:398
void disable_timer()
Invalidates the running asynchronous wait on m_timer. Pre-condition: m_timer_running.
Definition: drop_timer.cpp:452
uint64_t timer_wait_id_t
The counter type used to distinguish a given start_timer() call from any other such call (for this ob...
Definition: drop_timer.hpp:297
Fine_duration & m_sock_drop_timeout
Reference to the containing Peer_socket's Peer_socket::m_snd_drop_timeout data member (= DTO,...
Definition: drop_timer.hpp:385
bool m_in_events_group
true if and only if the last start_contemporaneous_events() call exists, and either end_contemporaneo...
Definition: drop_timer.hpp:473
void on_packet_in_flight(packet_id_t packet_id)
Indicates that a packet identified by the given unique ID has just been sent over the wire (the low-l...
Definition: drop_timer.cpp:52
uint64_t seq_num_t
Raw sequence number type.
Definition: seq_num.hpp:138
Convenience class template that endows the given subclass T with nested aliases Ptr and Const_ptr ali...
boost::shared_ptr< Drop_timer > Ptr
Short-hand for ref-counted pointer to mutable values of type Target_type::element_type (a-la T*).
Const_target_ptr Const_ptr
Short-hand for ref-counted pointer to immutable values of type Target_type::element_type (a-la T cons...
Flow module containing the API and implementation of the Flow network protocol, a TCP-inspired stream...
Definition: node.cpp:25
boost::asio::io_service Task_engine
Short-hand for boost.asio event service, the central class of boost.asio.
Definition: util_fwd.hpp:135
boost::asio::basic_waitable_timer< Fine_clock > Timer
boost.asio timer.
Definition: util_fwd.hpp:202
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:502
Fine_clock::duration Fine_duration
A high-res time duration as computed from two Fine_time_pts.
Definition: common.hpp:410