OpenVPN
reliable.c
Go to the documentation of this file.
1/*
2 * OpenVPN -- An application to securely tunnel IP networks
3 * over a single UDP port, with support for SSL/TLS-based
4 * session authentication and key exchange,
5 * packet encryption, packet authentication, and
6 * packet compression.
7 *
8 * Copyright (C) 2002-2026 OpenVPN Inc <sales@openvpn.net>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, see <https://www.gnu.org/licenses/>.
21 */
22
23/*
24 * These routines implement a reliability layer on top of UDP,
25 * so that SSL/TLS can be run over UDP.
26 */
27
28#ifdef HAVE_CONFIG_H
29#include "config.h"
30#endif
31
32#include "syshead.h"
33
34#include "buffer.h"
35#include "error.h"
36#include "common.h"
37#include "reliable.h"
38
39#include "memdbg.h"
40
41/* calculates test - base while allowing for base or test wraparound. The
42 * result is only meaningful compared against a bound: on its own it does not
43 * say which id came first. */
44static inline packet_id_type
46{
47 return test - base;
48}
49
50/*
51 * verify that test - base < extent while allowing for base or test wraparound
52 */
53static inline bool
55 const unsigned int extent)
56{
57 return subtract_pid(test, base) < extent;
58}
59
60/* check if a particular packet_id is present in ack */
61static inline bool
63{
64 for (int i = 0; i < ack->len; ++i)
65 {
66 if (ack->packet_id[i] == pid)
67 {
68 return true;
69 }
70 }
71 return false;
72}
73
74/* get a packet_id from buf */
75bool
77{
78 packet_id_type net_pid;
79
80 if (buf_read(buf, &net_pid, sizeof(net_pid)))
81 {
82 *pid = ntohpid(net_pid);
83 dmsg(D_REL_DEBUG, "ACK read ID " packet_id_format " (buf->len=%d)",
84 (packet_id_print_type)*pid, buf->len);
85 return true;
86 }
87
88 dmsg(D_REL_LOW, "ACK read ID FAILED (buf->len=%d)", buf->len);
89 return false;
90}
91
92/* acknowledge a packet_id by adding it to a struct reliable_ack */
93bool
95{
97 {
98 ack->packet_id[ack->len++] = pid;
99 dmsg(D_REL_DEBUG, "ACK acknowledge ID " packet_id_format " (ack->len=%d)",
100 (packet_id_print_type)pid, ack->len);
101 return true;
102 }
103
104 dmsg(D_REL_LOW, "ACK acknowledge ID " packet_id_format " FAILED (ack->len=%d)",
105 (packet_id_print_type)pid, ack->len);
106 return false;
107}
108
109
110bool
111reliable_ack_read(struct reliable_ack *ack, struct buffer *buf, const struct session_id *sid)
112{
113 struct session_id session_id_remote;
114
115 if (!reliable_ack_parse(buf, ack, &session_id_remote))
116 {
117 return false;
118 }
119
120 if (ack->len >= 1
121 && (!session_id_defined(&session_id_remote) || !session_id_equal(&session_id_remote, sid)))
122 {
123 struct gc_arena gc = gc_new();
124 dmsg(D_REL_LOW, "ACK read BAD SESSION-ID FROM REMOTE, local=%s, remote=%s",
125 session_id_print(sid, &gc), session_id_print(&session_id_remote, &gc));
126 gc_free(&gc);
127 return false;
128 }
129 return true;
130}
131
132bool
133reliable_ack_parse(struct buffer *buf, struct reliable_ack *ack,
134 struct session_id *session_id_remote)
135{
136 uint8_t count;
137 ack->len = 0;
138
139 if (!buf_read(buf, &count, sizeof(count)))
140 {
141 return false;
142 }
143 for (int i = 0; i < count; ++i)
144 {
145 packet_id_type net_pid;
146 if (!buf_read(buf, &net_pid, sizeof(net_pid)))
147 {
148 return false;
149 }
150 if (ack->len >= RELIABLE_ACK_SIZE)
151 {
152 return false;
153 }
154 packet_id_type pid = ntohpid(net_pid);
155 ack->packet_id[ack->len++] = pid;
156 }
157 if (count)
158 {
159 if (!session_id_read(session_id_remote, buf))
160 {
161 return false;
162 }
163 }
164 return true;
165}
166
170void
171copy_acks_to_mru(struct reliable_ack *ack, struct reliable_ack *ack_mru, int n)
172{
173 ASSERT(ack->len >= n);
174 /* This loop is backward to ensure the same order as in ack */
175 for (int i = n - 1; i >= 0; i--)
176 {
177 packet_id_type id = ack->packet_id[i];
178
179 /* Handle special case of ack_mru empty */
180 if (ack_mru->len == 0)
181 {
182 ack_mru->len = 1;
183 ack_mru->packet_id[0] = id;
184 }
185
186 bool idfound = false;
187
188 /* Move all existing entries one to the right */
189 packet_id_type move = id;
190
191 for (int j = 0; j < ack_mru->len; j++)
192 {
193 packet_id_type tmp = ack_mru->packet_id[j];
194 ack_mru->packet_id[j] = move;
195 move = tmp;
196
197 if (move == id)
198 {
199 idfound = true;
200 break;
201 }
202 }
203
204 if (!idfound && ack_mru->len < RELIABLE_ACK_SIZE)
205 {
206 ack_mru->packet_id[ack_mru->len] = move;
207 ack_mru->len++;
208 }
209 }
210}
211
212/* write a packet ID acknowledgement record to buf, */
213/* removing all acknowledged entries from ack */
214bool
215reliable_ack_write(struct reliable_ack *ack, struct reliable_ack *ack_mru, struct buffer *buf,
216 const struct session_id *sid, int max, bool prepend)
217{
218 int i, j, n;
219 struct buffer sub;
220
221 n = ack->len;
222 if (n > max)
223 {
224 n = max;
225 }
226
227 copy_acks_to_mru(ack, ack_mru, n);
228
229 /* Number of acks we can resend that still fit into the packet */
230 uint8_t total_acks = (uint8_t)min_int(max, ack_mru->len);
231
232 sub = buf_sub(buf, (int)ACK_SIZE(total_acks), prepend);
233 if (!BDEF(&sub))
234 {
235 goto error;
236 }
237 ASSERT(buf_write_u8(&sub, total_acks));
238
239 /* Write the actual acks to the packets. Since we copied the acks that
240 * are going out now already to the front of ack_mru we can fetch all
241 * acks from ack_mru */
242 for (i = 0; i < total_acks; ++i)
243 {
244 packet_id_type pid = ack_mru->packet_id[i];
245 packet_id_type net_pid = htonpid(pid);
246 ASSERT(buf_write(&sub, &net_pid, sizeof(net_pid)));
247 dmsg(D_REL_DEBUG, "ACK write ID " packet_id_format " (ack->len=%d, n=%d)",
248 (packet_id_print_type)pid, ack->len, n);
249 }
250 if (total_acks)
251 {
253 ASSERT(session_id_write(sid, &sub));
254 }
255 if (n)
256 {
257 for (i = 0, j = n; j < ack->len;)
258 {
259 ack->packet_id[i++] = ack->packet_id[j++];
260 }
261 ack->len = i;
262 }
263
264 return true;
265
266error:
267 return false;
268}
269
270/* print a reliable ACK record coming off the wire */
271const char *
272reliable_ack_print(struct buffer *buf, bool verbose, struct gc_arena *gc)
273{
274 uint8_t n_ack;
275 struct buffer out = alloc_buf_gc(256, gc);
276
277 buf_printf(&out, "[");
278 if (!buf_read(buf, &n_ack, sizeof(n_ack)))
279 {
280 goto done;
281 }
282 for (int i = 0; i < n_ack; ++i)
283 {
284 packet_id_type pid;
285 if (!buf_read(buf, &pid, sizeof(pid)))
286 {
287 goto done;
288 }
289 pid = ntohpid(pid);
291 }
292 if (n_ack)
293 {
294 struct session_id sid_ack;
295 if (!session_id_read(&sid_ack, buf))
296 {
297 goto done;
298 }
299 if (verbose)
300 {
301 buf_printf(&out, " sid=%s", session_id_print(&sid_ack, gc));
302 }
303 }
304
305done:
306 buf_printf(&out, " ]");
307 return BSTR(&out);
308}
309
310/*
311 * struct reliable member functions.
312 */
313
314void
315reliable_init(struct reliable *rel, int buf_size, int offset, int array_size, bool hold)
316{
317 CLEAR(*rel);
318 ASSERT(array_size > 0 && array_size <= RELIABLE_CAPACITY);
319 rel->hold = hold;
320 rel->size = array_size;
321 rel->offset = offset;
322 for (int i = 0; i < rel->size; ++i)
323 {
324 struct reliable_entry *e = &rel->array[i];
325 e->buf = alloc_buf(buf_size);
326 ASSERT(buf_init(&e->buf, offset));
327 }
328}
329
330void
332{
333 if (!rel)
334 {
335 return;
336 }
337 for (int i = 0; i < rel->size; ++i)
338 {
339 struct reliable_entry *e = &rel->array[i];
340 free_buf(&e->buf);
341 }
342 free(rel);
343}
344
345/* no active buffers? */
346bool
347reliable_empty(const struct reliable *rel)
348{
349 for (int i = 0; i < rel->size; ++i)
350 {
351 const struct reliable_entry *e = &rel->array[i];
352 if (e->active)
353 {
354 return false;
355 }
356 }
357 return true;
358}
359
360bool
366
367/* del acknowledged items from send buf */
368void
369reliable_send_purge(struct reliable *rel, const struct reliable_ack *ack)
370{
371 unsigned int out_of_window = 0;
372 packet_id_type first_out_of_window = 0;
373
374 for (int i = 0; i < ack->len; ++i)
375 {
376 packet_id_type pid = ack->packet_id[i];
377
378
379 if (!reliable_pid_in_send_window(rel, pid))
380 {
381 if (out_of_window == 0)
382 {
383 first_out_of_window = pid;
384 }
385 out_of_window++;
386 continue;
387 }
388
389 for (int j = 0; j < rel->size; ++j)
390 {
391 struct reliable_entry *e = &rel->array[j];
392 if (e->active && e->packet_id == pid)
393 {
395 "ACK received for pid " packet_id_format ", deleting from send buffer",
397#if 0
398 /* DEBUGGING -- how close were we timing out on ACK failure and resending? */
399 {
400 if (e->next_try)
401 {
402 const interval_t wake = e->next_try - now;
403 msg(M_INFO, "ACK " packet_id_format ", wake=%d", pid, wake);
404 }
405 }
406#endif
407 e->active = false;
408 }
409
410 /* Order the two by their distance below rel->packet_id, as
411 * comparing the ids directly misorders them across the wrap.
412 * Entries further back than rel->size are outside the send window
413 * and left alone. An ACK for a higher pid means this packet
414 * arrived out of order or was lost, and enough of them trigger
415 * the early resend. */
416 const packet_id_type e_dist = subtract_pid(rel->packet_id, e->packet_id);
417
418 if (e->active && e_dist <= (packet_id_type)rel->size
419 && e_dist > subtract_pid(rel->packet_id, pid))
420 {
421 e->n_acks++;
422 }
423 }
424 }
425
426 if (out_of_window > 0)
427 {
428 (void)first_out_of_window; /* dmsg might not generate code */
429 dmsg(D_REL_LOW, "ACK contained %u ids outside the send window, "
430 "first was " packet_id_format,
431 out_of_window, (packet_id_print_type)first_out_of_window);
432 }
433}
434
435#ifndef ENABLE_SMALL
436/* print the current sequence of active packet IDs */
437static const char *
438reliable_print_ids(const struct reliable *rel, struct gc_arena *gc)
439{
440 struct buffer out = alloc_buf_gc(256, gc);
441
443 for (int i = 0; i < rel->size; ++i)
444 {
445 const struct reliable_entry *e = &rel->array[i];
446 if (e->active)
447 {
449 }
450 }
451 return BSTR(&out);
452}
453#endif
454
455/* true if at least one free buffer available */
456bool
457reliable_can_get(const struct reliable *rel)
458{
459 for (int i = 0; i < rel->size; ++i)
460 {
461 const struct reliable_entry *e = &rel->array[i];
462 if (!e->active)
463 {
464 return true;
465 }
466 }
467 struct gc_arena gc = gc_new();
468 dmsg(D_REL_LOW, "ACK no free receive buffer available: %s", reliable_print_ids(rel, &gc));
469 gc_free(&gc);
470 return false;
471}
472
473/* make sure that incoming packet ID isn't a replay */
474bool
476{
477 struct gc_arena gc = gc_new();
478
479 /* outside the receive window: already consumed, or too far ahead to store */
480 if (!reliable_pid_in_range(id, rel->packet_id, rel->size))
481 {
482 goto bad;
483 }
484 for (int i = 0; i < rel->size; ++i)
485 {
486 const struct reliable_entry *e = &rel->array[i];
487 if (e->active && e->packet_id == id)
488 {
489 goto bad;
490 }
491 }
492 gc_free(&gc);
493 return true;
494
495bad:
496 dmsg(D_REL_DEBUG, "ACK " packet_id_format " is a replay: %s", (packet_id_print_type)id,
497 reliable_print_ids(rel, &gc));
498 gc_free(&gc);
499 return false;
500}
501
502/* make sure that incoming packet ID won't deadlock the receive buffer */
503bool
505{
506 /* The first clause is the receive window. The second is an absolute
507 * comparison, kept so that already consumed ids still reach
508 * reliable_ack_acknowledge_packet_id() and a peer whose ACK was lost stops
509 * retransmitting; reliable_not_replay() rejects them. */
510 const bool ret = (subtract_pid(id, rel->packet_id) < (packet_id_type)rel->size
511 || id < rel->packet_id);
512
513 if (!ret)
514 {
515 struct gc_arena gc = gc_new();
516 dmsg(D_REL_LOW, "ACK " packet_id_format " breaks sequentiality: %s",
518 gc_free(&gc);
519 }
520
521 dmsg(D_REL_DEBUG, "ACK RWBS rel->size=%d rel->packet_id=%08x id=%08x ret=%d", rel->size,
522 rel->packet_id, id, ret);
523 return ret;
524}
525
526/* grab a free buffer */
527struct buffer *
529{
530 for (int i = 0; i < rel->size; ++i)
531 {
532 struct reliable_entry *e = &rel->array[i];
533 if (!e->active)
534 {
535 ASSERT(buf_init(&e->buf, rel->offset));
536 return &e->buf;
537 }
538 }
539 return NULL;
540}
541
542/* Distance below rel->packet_id of the oldest unacknowledged entry, 0 if there
543 * is none. Entries more than rel->size away are outside the sequencing window
544 * and ignored, rather than taken for very old ones. */
545static packet_id_type
547{
548 packet_id_type max_dist = 0;
549
550 for (int i = 0; i < rel->size; ++i)
551 {
552 const struct reliable_entry *e = &rel->array[i];
553 if (!e->active)
554 {
555 continue;
556 }
557
558 const packet_id_type dist = subtract_pid(rel->packet_id, e->packet_id);
559 if (dist <= (packet_id_type)rel->size && dist > max_dist)
560 {
561 max_dist = dist;
562 }
563 }
564
565 return max_dist;
566}
567
568int
570{
571 return rel->size - (int)reliable_oldest_active_distance(rel);
572}
573
574/* grab a free buffer, fail if buffer clogged by unacknowledged low packet IDs */
575struct buffer *
577{
578 struct buffer *ret = NULL;
579
580 /* keep the next id within rel->size of the oldest unacknowledged one */
582 {
583 ret = reliable_get_buf(rel);
584 }
585 else
586 {
587 struct gc_arena gc = gc_new();
588 dmsg(D_REL_LOW, "ACK output sequence broken: %s", reliable_print_ids(rel, &gc));
589 gc_free(&gc);
590 }
591 return ret;
592}
593
594/* get active buffer for next sequentially increasing key ID */
595struct reliable_entry *
597{
598 for (int i = 0; i < rel->size; ++i)
599 {
600 struct reliable_entry *e = &rel->array[i];
601 if (e->active && e->packet_id == rel->packet_id)
602 {
603 return e;
604 }
605 }
606 return NULL;
607}
608
609/* return true if reliable_send would return a non-NULL result */
610bool
611reliable_can_send(const struct reliable *rel)
612{
613 struct gc_arena gc = gc_new();
614 int n_active = 0, n_current = 0;
615 for (int i = 0; i < rel->size; ++i)
616 {
617 const struct reliable_entry *e = &rel->array[i];
618 if (e->active)
619 {
620 ++n_active;
621 if (now >= e->next_try || e->n_acks >= N_ACK_RETRANSMIT)
622 {
623 ++n_current;
624 }
625 }
626 }
627 (void)n_active; /* dmsg might not generate code */
628 dmsg(D_REL_DEBUG, "ACK reliable_can_send active=%d current=%d : %s", n_active, n_current,
629 reliable_print_ids(rel, &gc));
630
631 gc_free(&gc);
632 return n_current > 0 && !rel->hold;
633}
634
635/* return next buffer to send to remote */
636struct buffer *
637reliable_send(struct reliable *rel, int *opcode)
638{
639 struct reliable_entry *best = NULL;
640 struct reliable_entry *eligible = NULL;
641 packet_id_type best_dist = 0;
642 const time_t local_now = now;
643
644 for (int i = 0; i < rel->size; ++i)
645 {
646 struct reliable_entry *e = &rel->array[i];
647
648 /* If N_ACK_RETRANSMIT later packets have received ACKs, we assume
649 * that the packet was lost and resend it even if the timeout has
650 * not expired yet. */
651 if (e->active && (e->n_acks >= N_ACK_RETRANSMIT || local_now >= e->next_try))
652 {
653 /* oldest = furthest below rel->packet_id, within the window */
654 const packet_id_type dist = subtract_pid(rel->packet_id, e->packet_id);
655 if (dist <= (packet_id_type)rel->size && dist > best_dist)
656 {
657 best = e;
658 best_dist = dist;
659 }
660
661 if (!eligible)
662 {
663 eligible = e;
664 }
665 }
666 }
667
668 /* reliable_can_send() promises a non-NULL result for these same entries
669 * without applying the window bound, and its caller asserts on that, so
670 * never come back empty while one of them is eligible. */
671 if (!best)
672 {
673 best = eligible;
674 }
675
676 if (best)
677 {
678 /* The initial timeout is bounded by RELIABLE_MAX_INITIAL_TIMEOUT, so
679 * shifting it cannot overflow. */
680 static_assert(RELIABLE_MAX_INITIAL_TIMEOUT <= (INT_MAX >> RELIABLE_MAX_TIMEOUT_SHIFT),
681 "initial reliable timeout overflows when shifted");
682 const interval_t max_timeout = rel->initial_timeout << RELIABLE_MAX_TIMEOUT_SHIFT;
683
684 /* exponential backoff */
685 best->next_try = local_now + best->timeout;
686 if (best->timeout < max_timeout)
687 {
688 best->timeout *= 2;
689 }
690
691 best->n_acks = 0;
692 *opcode = best->opcode;
693 dmsg(D_REL_DEBUG, "ACK reliable_send ID " packet_id_format " (size=%d to=%d)",
695 (int)(best->next_try - local_now));
696 return &best->buf;
697 }
698 return NULL;
699}
700
701/* schedule all pending packets for immediate retransmit */
702void
704{
705 dmsg(D_REL_DEBUG, "ACK reliable_schedule_now");
706 rel->hold = false;
707 for (int i = 0; i < rel->size; ++i)
708 {
709 struct reliable_entry *e = &rel->array[i];
710 if (e->active)
711 {
712 e->next_try = now;
713 e->timeout = rel->initial_timeout;
714 }
715 }
716}
717
718/* in how many seconds should we wake up to check for timeout */
719/* if we return BIG_TIMEOUT, nothing to wait for */
722{
723 struct gc_arena gc = gc_new();
725 const time_t local_now = now;
726
727 for (int i = 0; i < rel->size; ++i)
728 {
729 const struct reliable_entry *e = &rel->array[i];
730 if (e->active)
731 {
732 if (e->next_try <= local_now)
733 {
734 ret = 0;
735 break;
736 }
737 else
738 {
739 ret = min_int(ret, (int)(e->next_try - local_now));
740 }
741 }
742 }
743
744 dmsg(D_REL_DEBUG, "ACK reliable_send_timeout %d %s", (int)ret, reliable_print_ids(rel, &gc));
745
746 gc_free(&gc);
747 return ret;
748}
749
750/*
751 * Enable an incoming buffer previously returned by a get function as active.
752 */
753
754void
756 int opcode)
757{
758 for (int i = 0; i < rel->size; ++i)
759 {
760 struct reliable_entry *e = &rel->array[i];
761 if (buf == &e->buf)
762 {
763 /* storable and not yet consumed, checked before touching the entry */
764 ASSERT(reliable_pid_in_range(pid, rel->packet_id, rel->size));
765
766 e->active = true;
767
768 /* packets may not arrive in sequential order */
769 e->packet_id = pid;
770
771 e->opcode = opcode;
772 e->next_try = 0;
773 e->timeout = 0;
774 e->n_acks = 0;
775 dmsg(D_REL_DEBUG, "ACK mark active incoming ID " packet_id_format,
777 return;
778 }
779 }
780 ASSERT(0); /* buf not found in rel */
781}
782
783/*
784 * Enable an outgoing buffer previously returned by a get function as active.
785 */
786
787void
789{
790 for (int i = 0; i < rel->size; ++i)
791 {
792 struct reliable_entry *e = &rel->array[i];
793 if (buf == &e->buf)
794 {
795 /* Write mode, increment packet_id (i.e. sequence number)
796 * linearly and prepend id to packet */
797 packet_id_type net_pid;
798 e->packet_id = rel->packet_id++;
799 net_pid = htonpid(e->packet_id);
800 ASSERT(buf_write_prepend(buf, &net_pid, sizeof(net_pid)));
801 e->active = true;
802 e->opcode = opcode;
803 e->next_try = 0;
804 e->timeout = rel->initial_timeout;
805 dmsg(D_REL_DEBUG, "ACK mark active outgoing ID " packet_id_format,
807 return;
808 }
809 }
810 ASSERT(0); /* buf not found in rel */
811}
812
813/* delete a buffer previously activated by reliable_mark_active() */
814void
815reliable_mark_deleted(struct reliable *rel, const struct buffer *buf)
816{
817 for (int i = 0; i < rel->size; ++i)
818 {
819 struct reliable_entry *e = &rel->array[i];
820 if (buf == &e->buf)
821 {
822 e->active = false;
823 rel->packet_id = e->packet_id + 1;
824 return;
825 }
826 }
827 ASSERT(0);
828}
829
830#if 0
831
832void
833reliable_ack_debug_print(const struct reliable_ack *ack, char *desc)
834{
835 printf("********* struct reliable_ack %s\n", desc);
836 for (int i = 0; i < ack->len; ++i)
837 {
838 printf(" %d: " packet_id_format "\n", i, (packet_id_print_type) ack->packet_id[i]);
839 }
840}
841
842void
843reliable_debug_print(const struct reliable *rel, char *desc)
844{
845 update_time();
846
847 printf("********* struct reliable %s\n", desc);
848 printf(" initial_timeout=%d\n", (int)rel->initial_timeout);
849 printf(" packet_id=" packet_id_format "\n", rel->packet_id);
850 printf(" now=%" PRIi64 "\n", (int64_t)now);
851 for (int i = 0; i < rel->size; ++i)
852 {
853 const struct reliable_entry *e = &rel->array[i];
854 if (e->active)
855 {
856 printf(" %d: packet_id=" packet_id_format " len=%d", i, e->packet_id, e->buf.len);
857 printf(" next_try=%" PRIi64, (int64_t)e->next_try);
858 printf("\n");
859 }
860 }
861}
862
863#endif /* if 0 */
void free_buf(struct buffer *buf)
Free the memory allocated for a buffer.
Definition buffer.c:169
bool buf_printf(struct buffer *buf, const char *format,...)
printf-style append to a buffer with overflow check.
Definition buffer.c:226
struct buffer buf_sub(struct buffer *buf, int size, bool prepend)
Return a sub-buffer of another buffer.
Definition buffer.c:207
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
Allocate a buffer of the given size under garbage collection.
Definition buffer.c:77
struct buffer alloc_buf(size_t size)
Allocate a buffer of the given size.
Definition buffer.c:60
Buffer management functions and garbage collection.
#define BSTR(buf)
Return the buffer content pointer cast to char *.
Definition buffer.h:157
static bool buf_write_prepend(struct buffer *dest, const void *src, int size)
Prepend data to a buffer.
Definition buffer.h:1263
static bool buf_read(struct buffer *src, void *dest, int size)
Read bytes from the front of a buffer into a caller-supplied destination.
Definition buffer.h:1451
#define BDEF(buf)
Return true iff the buffer is defined (has non-NULL data pointer).
Definition buffer.h:155
static bool buf_write(struct buffer *dest, const void *src, size_t size)
Append data to a buffer.
Definition buffer.h:1239
static bool buf_write_u8(struct buffer *dest, uint8_t data)
Append a uint8_t to a buffer.
Definition buffer.h:1283
static void gc_free(struct gc_arena *a)
Free all allocations in a garbage collection arena.
Definition buffer.h:1965
#define buf_init(buf, offset)
Definition buffer.h:364
static struct gc_arena gc_new(void)
Allocate and return a new, empty garbage collection arena.
Definition buffer.h:1949
int interval_t
Definition common.h:37
#define BIG_TIMEOUT
Definition common.h:42
#define D_REL_DEBUG
Definition errlevel.h:160
#define D_REL_LOW
Definition errlevel.h:122
#define M_INFO
Definition errlevel.h:54
void reliable_mark_deleted(struct reliable *rel, const struct buffer *buf)
Remove an entry from a reliable structure.
Definition reliable.c:815
void reliable_free(struct reliable *rel)
Free allocated memory associated with a reliable structure and the pointer itself.
Definition reliable.c:331
bool reliable_ack_read(struct reliable_ack *ack, struct buffer *buf, const struct session_id *sid)
Read an acknowledgment record from a received packet.
Definition reliable.c:111
struct buffer * reliable_get_buf_output_sequenced(struct reliable *rel)
Get the buffer of free reliable entry and check whether the outgoing acknowledgment sequence is still...
Definition reliable.c:576
void reliable_schedule_now(struct reliable *rel)
Reschedule all entries of a reliable structure to be ready for (re)sending immediately.
Definition reliable.c:703
int reliable_get_num_output_sequenced_available(const struct reliable *rel)
Counts the number of free buffers in output that can be potentially used for sending.
Definition reliable.c:569
void reliable_ack_debug_print(const struct reliable_ack *ack, char *desc)
bool reliable_ack_read_packet_id(struct buffer *buf, packet_id_type *pid)
Read the packet ID of a received packet.
Definition reliable.c:76
void reliable_mark_active_outgoing(struct reliable *rel, struct buffer *buf, int opcode)
Mark the reliable entry associated with the given buffer as active outgoing.
Definition reliable.c:788
const char * reliable_ack_print(struct buffer *buf, bool verbose, struct gc_arena *gc)
Definition reliable.c:272
bool reliable_ack_acknowledge_packet_id(struct reliable_ack *ack, packet_id_type pid)
Record a packet ID for later acknowledgment.
Definition reliable.c:94
#define RELIABLE_MAX_INITIAL_TIMEOUT
Maximum initial timeout (–tls-timeout) we accept.
Definition reliable.h:65
bool reliable_pid_in_send_window(const struct reliable *rel, packet_id_type pid)
Check whether pid is one of the RELIABLE_CAPACITY ids below rel->packet_id, and so could still be out...
Definition reliable.c:361
bool reliable_ack_parse(struct buffer *buf, struct reliable_ack *ack, struct session_id *session_id_remote)
Parse an acknowledgment record from a received packet.
Definition reliable.c:133
#define RELIABLE_MAX_TIMEOUT_SHIFT
Maximum shift or doubling in exponential backoff we allow.
Definition reliable.h:59
bool reliable_ack_write(struct reliable_ack *ack, struct reliable_ack *ack_mru, struct buffer *buf, const struct session_id *sid, int max, bool prepend)
Write a packet ID acknowledgment record to a buffer.
Definition reliable.c:215
#define N_ACK_RETRANSMIT
We retry sending a packet early if this many later packets have been ACKed.
Definition reliable.h:54
void reliable_mark_active_incoming(struct reliable *rel, const struct buffer *buf, packet_id_type pid, int opcode)
Mark the reliable entry associated with the given buffer as active incoming.
Definition reliable.c:755
bool reliable_can_get(const struct reliable *rel)
Check whether a reliable structure has any free buffers available for use.
Definition reliable.c:457
void reliable_send_purge(struct reliable *rel, const struct reliable_ack *ack)
Remove acknowledged packets from a reliable structure.
Definition reliable.c:369
struct buffer * reliable_get_buf(struct reliable *rel)
Get the buffer of a free reliable entry in which to store a packet.
Definition reliable.c:528
struct buffer * reliable_send(struct reliable *rel, int *opcode)
Get the next packet to send to the remote peer.
Definition reliable.c:637
bool reliable_can_send(const struct reliable *rel)
Check whether a reliable structure has any active entries ready to be (re)sent.
Definition reliable.c:611
bool reliable_empty(const struct reliable *rel)
Check whether a reliable structure is empty.
Definition reliable.c:347
void reliable_debug_print(const struct reliable *rel, char *desc)
bool reliable_not_replay(const struct reliable *rel, packet_id_type id)
Check that a received packet's ID is not a replay and is inside the receive window.
Definition reliable.c:475
#define RELIABLE_ACK_SIZE
The maximum number of packet IDs waiting to be acknowledged which can be stored in one reliable_ack s...
Definition reliable.h:43
interval_t reliable_send_timeout(const struct reliable *rel)
Determined how many seconds until the earliest resend should be attempted.
Definition reliable.c:721
#define RELIABLE_CAPACITY
The maximum number of packets that the reliability layer for one VPN tunnel in one direction can stor...
Definition reliable.h:49
struct reliable_entry * reliable_get_entry_sequenced(struct reliable *rel)
Get the buffer of the next sequential and active entry.
Definition reliable.c:596
void reliable_init(struct reliable *rel, int buf_size, int offset, int array_size, bool hold)
Initialize a reliable structure.
Definition reliable.c:315
void copy_acks_to_mru(struct reliable_ack *ack, struct reliable_ack *ack_mru, int n)
Copies the first n acks from ack to ack_mru.
Definition reliable.c:171
bool reliable_wont_break_sequentiality(const struct reliable *rel, packet_id_type id)
Check that a received packet's ID can safely be stored in the reliable structure's processing window.
Definition reliable.c:504
#define ACK_SIZE(n)
Definition reliable.h:81
static int min_int(int x, int y)
Definition integer.h:105
#define CLEAR(x)
Definition basic.h:32
#define dmsg(flags,...)
Definition error.h:164
#define msg(flags,...)
Definition error.h:152
#define ASSERT(x)
Definition error.h:221
time_t now
Definition otime.c:33
static void update_time(void)
Definition otime.h:84
#define packet_id_format
Definition packet_id.h:76
#define htonpid(x)
Definition packet_id.h:61
uint64_t packet_id_print_type
Definition packet_id.h:77
uint32_t packet_id_type
Definition packet_id.h:45
#define ntohpid(x)
Definition packet_id.h:64
static bool reliable_pid_in_range(const packet_id_type test, const packet_id_type base, const unsigned int extent)
Definition reliable.c:54
static packet_id_type subtract_pid(const packet_id_type test, const packet_id_type base)
Definition reliable.c:45
static bool reliable_ack_packet_id_present(const struct reliable_ack *ack, packet_id_type pid)
Definition reliable.c:62
static packet_id_type reliable_oldest_active_distance(const struct reliable *rel)
Definition reliable.c:546
static const char * reliable_print_ids(const struct reliable *rel, struct gc_arena *gc)
Definition reliable.c:438
Reliability Layer module header file.
const char * session_id_print(const struct session_id *sid, struct gc_arena *gc)
Definition session_id.c:54
static bool session_id_write(const struct session_id *sid, struct buffer *buf)
Definition session_id.h:71
static bool session_id_equal(const struct session_id *sid1, const struct session_id *sid2)
Definition session_id.h:47
static bool session_id_defined(const struct session_id *sid1)
Definition session_id.h:53
static bool session_id_read(struct session_id *sid, struct buffer *buf)
Definition session_id.h:59
Wrapper structure for dynamically allocated memory.
Definition buffer.h:71
int len
Length in bytes of the actual content within the allocated memory.
Definition buffer.h:76
Garbage collection arena used to keep track of dynamically allocated memory.
Definition buffer.h:127
The acknowledgment structure in which packet IDs are stored for later acknowledgment.
Definition reliable.h:75
packet_id_type packet_id[RELIABLE_ACK_SIZE]
Definition reliable.h:77
The structure in which the reliability layer stores a single incoming or outgoing packet.
Definition reliable.h:88
struct buffer buf
Definition reliable.h:97
int opcode
Definition reliable.h:96
time_t next_try
Definition reliable.h:91
size_t n_acks
Definition reliable.h:93
packet_id_type packet_id
Definition reliable.h:92
bool active
Definition reliable.h:89
interval_t timeout
Definition reliable.h:90
The reliability layer storage structure for one VPN tunnel's control channel in one direction.
Definition reliable.h:105
struct reliable_entry array[RELIABLE_CAPACITY]
Definition reliable.h:111
bool hold
Definition reliable.h:110
int size
Definition reliable.h:106
packet_id_type packet_id
Packet ID for the next packet to be sent out.
Definition reliable.h:108
interval_t initial_timeout
Definition reliable.h:107
int offset
Offset of the bufs in the reliable_entry array.
Definition reliable.h:109
struct gc_arena gc
Definition test_ssl.c:122