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-2024 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, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 */
23
24/*
25 * These routines implement a reliability layer on top of UDP,
26 * so that SSL/TLS can be run over UDP.
27 */
28
29#ifdef HAVE_CONFIG_H
30#include "config.h"
31#endif
32
33#include "syshead.h"
34
35#include "buffer.h"
36#include "error.h"
37#include "common.h"
38#include "reliable.h"
39
40#include "memdbg.h"
41
42/* calculates test - base while allowing for base or test wraparound. test is
43 * assumed to be higher than base */
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 packet_id_type base,
56 const unsigned int extent)
57{
58 return subtract_pid(test, base) < extent;
59}
60
61/*
62 * verify that test < base + extent while allowing for base or test wraparound
63 */
64static inline bool
66 const packet_id_type base,
67 const unsigned int extent)
68{
69 if (base + extent >= base)
70 {
71 if (test < base + extent)
72 {
73 return true;
74 }
75 }
76 else
77 {
78 if ((test+0x80000000u) < (base+0x80000000u) + extent)
79 {
80 return true;
81 }
82 }
83
84 return false;
85}
86
87/*
88 * verify that p1 < p2 while allowing for p1 or p2 wraparound
89 */
90static inline bool
92 const packet_id_type p2)
93{
94 return !reliable_pid_in_range1(p1, p2, 0x80000000u);
95}
96
97/* check if a particular packet_id is present in ack */
98static inline bool
100{
101 int i;
102 for (i = 0; i < ack->len; ++i)
103 {
104 if (ack->packet_id[i] == pid)
105 {
106 return true;
107 }
108 }
109 return false;
110}
111
112/* get a packet_id from buf */
113bool
115{
116 packet_id_type net_pid;
117
118 if (buf_read(buf, &net_pid, sizeof(net_pid)))
119 {
120 *pid = ntohpid(net_pid);
121 dmsg(D_REL_DEBUG, "ACK read ID " packet_id_format " (buf->len=%d)",
122 (packet_id_print_type)*pid, buf->len);
123 return true;
124 }
125
126 dmsg(D_REL_LOW, "ACK read ID FAILED (buf->len=%d)", buf->len);
127 return false;
128}
129
130/* acknowledge a packet_id by adding it to a struct reliable_ack */
131bool
133{
135 {
136 ack->packet_id[ack->len++] = pid;
137 dmsg(D_REL_DEBUG, "ACK acknowledge ID " packet_id_format " (ack->len=%d)",
138 (packet_id_print_type)pid, ack->len);
139 return true;
140 }
141
142 dmsg(D_REL_LOW, "ACK acknowledge ID " packet_id_format " FAILED (ack->len=%d)",
143 (packet_id_print_type)pid, ack->len);
144 return false;
145}
146
147
148bool
150 struct buffer *buf, const struct session_id *sid)
151{
152 struct session_id session_id_remote;
153
154 if (!reliable_ack_parse(buf, ack, &session_id_remote))
155 {
156 return false;
157 }
158
159 if (ack->len >= 1 && (!session_id_defined(&session_id_remote)
160 || !session_id_equal(&session_id_remote, sid)))
161 {
162 struct gc_arena gc = gc_new();
164 "ACK read BAD SESSION-ID FROM REMOTE, local=%s, remote=%s",
165 session_id_print(sid, &gc), session_id_print(&session_id_remote, &gc));
166 gc_free(&gc);
167 return false;
168 }
169 return true;
170}
171
172bool
173reliable_ack_parse(struct buffer *buf, struct reliable_ack *ack,
174 struct session_id *session_id_remote)
175{
176 uint8_t count;
177 ack->len = 0;
178
179 if (!buf_read(buf, &count, sizeof(count)))
180 {
181 return false;
182 }
183 for (int i = 0; i < count; ++i)
184 {
185 packet_id_type net_pid;
186 if (!buf_read(buf, &net_pid, sizeof(net_pid)))
187 {
188 return false;
189 }
190 if (ack->len >= RELIABLE_ACK_SIZE)
191 {
192 return false;
193 }
194 packet_id_type pid = ntohpid(net_pid);
195 ack->packet_id[ack->len++] = pid;
196 }
197 if (count)
198 {
199 if (!session_id_read(session_id_remote, buf))
200 {
201 return false;
202 }
203 }
204 return true;
205}
206
210void
211copy_acks_to_mru(struct reliable_ack *ack, struct reliable_ack *ack_mru, int n)
212{
213 ASSERT(ack->len >= n);
214 /* This loop is backward to ensure the same order as in ack */
215 for (int i = n-1; i >= 0; i--)
216 {
217 packet_id_type id = ack->packet_id[i];
218
219 /* Handle special case of ack_mru empty */
220 if (ack_mru->len == 0)
221 {
222 ack_mru->len = 1;
223 ack_mru->packet_id[0] = id;
224 }
225
226 bool idfound = false;
227
228 /* Move all existing entries one to the right */
229 packet_id_type move = id;
230
231 for (int j = 0; j < ack_mru->len; j++)
232 {
233 packet_id_type tmp = ack_mru->packet_id[j];
234 ack_mru->packet_id[j] = move;
235 move = tmp;
236
237 if (move == id)
238 {
239 idfound = true;
240 break;
241 }
242 }
243
244 if (!idfound && ack_mru->len < RELIABLE_ACK_SIZE)
245 {
246 ack_mru->packet_id[ack_mru->len] = move;
247 ack_mru->len++;
248 }
249 }
250}
251
252/* write a packet ID acknowledgement record to buf, */
253/* removing all acknowledged entries from ack */
254bool
256 struct reliable_ack *ack_mru,
257 struct buffer *buf,
258 const struct session_id *sid, int max, bool prepend)
259{
260 int i, j, n;
261 struct buffer sub;
262
263 n = ack->len;
264 if (n > max)
265 {
266 n = max;
267 }
268
270
271 /* Number of acks we can resend that still fit into the packet */
273
274 sub = buf_sub(buf, (int)ACK_SIZE(total_acks), prepend);
275 if (!BDEF(&sub))
276 {
277 goto error;
278 }
280
281 /* Write the actual acks to the packets. Since we copied the acks that
282 * are going out now already to the front of ack_mru we can fetch all
283 * acks from ack_mru */
284 for (i = 0; i < total_acks; ++i)
285 {
286 packet_id_type pid = ack_mru->packet_id[i];
288 ASSERT(buf_write(&sub, &net_pid, sizeof(net_pid)));
289 dmsg(D_REL_DEBUG, "ACK write ID " packet_id_format " (ack->len=%d, n=%d)", (packet_id_print_type)pid, ack->len, n);
290 }
291 if (total_acks)
292 {
295 }
296 if (n)
297 {
298 for (i = 0, j = n; j < ack->len; )
299 {
300 ack->packet_id[i++] = ack->packet_id[j++];
301 }
302 ack->len = i;
303 }
304
305 return true;
306
307error:
308 return false;
309}
310
311/* print a reliable ACK record coming off the wire */
312const char *
313reliable_ack_print(struct buffer *buf, bool verbose, struct gc_arena *gc)
314{
315 int i;
317 struct session_id sid_ack;
318 packet_id_type pid;
319 struct buffer out = alloc_buf_gc(256, gc);
320
321 buf_printf(&out, "[");
322 if (!buf_read(buf, &n_ack, sizeof(n_ack)))
323 {
324 goto done;
325 }
326 for (i = 0; i < n_ack; ++i)
327 {
328 if (!buf_read(buf, &pid, sizeof(pid)))
329 {
330 goto done;
331 }
332 pid = ntohpid(pid);
334 }
335 if (n_ack)
336 {
337 if (!session_id_read(&sid_ack, buf))
338 {
339 goto done;
340 }
341 if (verbose)
342 {
343 buf_printf(&out, " sid=%s", session_id_print(&sid_ack, gc));
344 }
345 }
346
347done:
348 buf_printf(&out, " ]");
349 return BSTR(&out);
350}
351
352/*
353 * struct reliable member functions.
354 */
355
356void
357reliable_init(struct reliable *rel, int buf_size, int offset, int array_size, bool hold)
358{
359 int i;
360
361 CLEAR(*rel);
363 rel->hold = hold;
364 rel->size = array_size;
365 rel->offset = offset;
366 for (i = 0; i < rel->size; ++i)
367 {
368 struct reliable_entry *e = &rel->array[i];
369 e->buf = alloc_buf(buf_size);
370 ASSERT(buf_init(&e->buf, offset));
371 }
372}
373
374void
376{
377 if (!rel)
378 {
379 return;
380 }
381 int i;
382 for (i = 0; i < rel->size; ++i)
383 {
384 struct reliable_entry *e = &rel->array[i];
385 free_buf(&e->buf);
386 }
387 free(rel);
388}
389
390/* no active buffers? */
391bool
392reliable_empty(const struct reliable *rel)
393{
394 int i;
395 for (i = 0; i < rel->size; ++i)
396 {
397 const struct reliable_entry *e = &rel->array[i];
398 if (e->active)
399 {
400 return false;
401 }
402 }
403 return true;
404}
405
406/* del acknowledged items from send buf */
407void
408reliable_send_purge(struct reliable *rel, const struct reliable_ack *ack)
409{
410 int i, j;
411 for (i = 0; i < ack->len; ++i)
412 {
413 packet_id_type pid = ack->packet_id[i];
414 for (j = 0; j < rel->size; ++j)
415 {
416 struct reliable_entry *e = &rel->array[j];
417 if (e->active && e->packet_id == pid)
418 {
420 "ACK received for pid " packet_id_format ", deleting from send buffer",
422#if 0
423 /* DEBUGGING -- how close were we timing out on ACK failure and resending? */
424 {
425 if (e->next_try)
426 {
427 const interval_t wake = e->next_try - now;
428 msg(M_INFO, "ACK " packet_id_format ", wake=%d", pid, wake);
429 }
430 }
431#endif
432 e->active = false;
433 }
434 else if (e->active && e->packet_id < pid)
435 {
436 /* We have received an ACK for a packet with a higher PID. Either
437 * we have received ACKs out of or order or the packet has been
438 * lost. We count the number of ACKs to determine if we should
439 * resend it early. */
440 e->n_acks++;
441 }
442 }
443 }
444}
445
446#ifdef ENABLE_DEBUG
447/* print the current sequence of active packet IDs */
448static const char *
449reliable_print_ids(const struct reliable *rel, struct gc_arena *gc)
450{
451 struct buffer out = alloc_buf_gc(256, gc);
452 int i;
453
454 buf_printf(&out, "[" packet_id_format "]", (packet_id_print_type)rel->packet_id);
455 for (i = 0; i < rel->size; ++i)
456 {
457 const struct reliable_entry *e = &rel->array[i];
458 if (e->active)
459 {
461 }
462 }
463 return BSTR(&out);
464}
465#endif /* ENABLE_DEBUG */
466
467/* true if at least one free buffer available */
468bool
469reliable_can_get(const struct reliable *rel)
470{
471 struct gc_arena gc = gc_new();
472 int i;
473 for (i = 0; i < rel->size; ++i)
474 {
475 const struct reliable_entry *e = &rel->array[i];
476 if (!e->active)
477 {
478 return true;
479 }
480 }
481 dmsg(D_REL_LOW, "ACK no free receive buffer available: %s", reliable_print_ids(rel, &gc));
482 gc_free(&gc);
483 return false;
484}
485
486/* make sure that incoming packet ID isn't a replay */
487bool
489{
490 struct gc_arena gc = gc_new();
491 int i;
492 if (reliable_pid_min(id, rel->packet_id))
493 {
494 goto bad;
495 }
496 for (i = 0; i < rel->size; ++i)
497 {
498 const struct reliable_entry *e = &rel->array[i];
499 if (e->active && e->packet_id == id)
500 {
501 goto bad;
502 }
503 }
504 gc_free(&gc);
505 return true;
506
507bad:
508 dmsg(D_REL_DEBUG, "ACK " packet_id_format " is a replay: %s", (packet_id_print_type)id, reliable_print_ids(rel, &gc));
509 gc_free(&gc);
510 return false;
511}
512
513/* make sure that incoming packet ID won't deadlock the receive buffer */
514bool
516{
517 struct gc_arena gc = gc_new();
518
519 const int ret = reliable_pid_in_range2(id, rel->packet_id, rel->size);
520
521 if (!ret)
522 {
523 dmsg(D_REL_LOW, "ACK " packet_id_format " breaks sequentiality: %s",
524 (packet_id_print_type)id, reliable_print_ids(rel, &gc));
525 }
526
527 dmsg(D_REL_DEBUG, "ACK RWBS rel->size=%d rel->packet_id=%08x id=%08x ret=%d", rel->size, rel->packet_id, id, ret);
528
529 gc_free(&gc);
530 return ret;
531}
532
533/* grab a free buffer */
534struct buffer *
536{
537 int i;
538 for (i = 0; i < rel->size; ++i)
539 {
540 struct reliable_entry *e = &rel->array[i];
541 if (!e->active)
542 {
543 ASSERT(buf_init(&e->buf, rel->offset));
544 return &e->buf;
545 }
546 }
547 return NULL;
548}
549
550int
552{
553 struct gc_arena gc = gc_new();
554 packet_id_type min_id = 0;
555 bool min_id_defined = false;
556
557 /* find minimum active packet_id */
558 for (int i = 0; i < rel->size; ++i)
559 {
560 const struct reliable_entry *e = &rel->array[i];
561 if (e->active)
562 {
563 if (!min_id_defined || reliable_pid_min(e->packet_id, min_id))
564 {
565 min_id_defined = true;
566 min_id = e->packet_id;
567 }
568 }
569 }
570
571 int ret = rel->size;
572 if (min_id_defined)
573 {
574 ret -= subtract_pid(rel->packet_id, min_id);
575 }
576 gc_free(&gc);
577 return ret;
578}
579
580/* grab a free buffer, fail if buffer clogged by unacknowledged low packet IDs */
581struct buffer *
583{
584 struct gc_arena gc = gc_new();
585 int i;
586 packet_id_type min_id = 0;
587 bool min_id_defined = false;
588 struct buffer *ret = NULL;
589
590 /* find minimum active packet_id */
591 for (i = 0; i < rel->size; ++i)
592 {
593 const struct reliable_entry *e = &rel->array[i];
594 if (e->active)
595 {
596 if (!min_id_defined || reliable_pid_min(e->packet_id, min_id))
597 {
598 min_id_defined = true;
599 min_id = e->packet_id;
600 }
601 }
602 }
603
604 if (!min_id_defined || reliable_pid_in_range1(rel->packet_id, min_id, rel->size))
605 {
606 ret = reliable_get_buf(rel);
607 }
608 else
609 {
610 dmsg(D_REL_LOW, "ACK output sequence broken: %s", reliable_print_ids(rel, &gc));
611 }
612 gc_free(&gc);
613 return ret;
614}
615
616/* get active buffer for next sequentially increasing key ID */
617struct reliable_entry *
619{
620 int i;
621 for (i = 0; i < rel->size; ++i)
622 {
623 struct reliable_entry *e = &rel->array[i];
624 if (e->active && e->packet_id == rel->packet_id)
625 {
626 return e;
627 }
628 }
629 return NULL;
630}
631
632/* return true if reliable_send would return a non-NULL result */
633bool
634reliable_can_send(const struct reliable *rel)
635{
636 struct gc_arena gc = gc_new();
637 int i;
638 int n_active = 0, n_current = 0;
639 for (i = 0; i < rel->size; ++i)
640 {
641 const struct reliable_entry *e = &rel->array[i];
642 if (e->active)
643 {
644 ++n_active;
645 if (now >= e->next_try || e->n_acks >= N_ACK_RETRANSMIT)
646 {
647 ++n_current;
648 }
649 }
650 }
651 dmsg(D_REL_DEBUG, "ACK reliable_can_send active=%d current=%d : %s",
652 n_active,
653 n_current,
654 reliable_print_ids(rel, &gc));
655
656 gc_free(&gc);
657 return n_current > 0 && !rel->hold;
658}
659
660/* return next buffer to send to remote */
661struct buffer *
662reliable_send(struct reliable *rel, int *opcode)
663{
664 int i;
665 struct reliable_entry *best = NULL;
666 const time_t local_now = now;
667
668 for (i = 0; i < rel->size; ++i)
669 {
670 struct reliable_entry *e = &rel->array[i];
671
672 /* If N_ACK_RETRANSMIT later packets have received ACKs, we assume
673 * that the packet was lost and resend it even if the timeout has
674 * not expired yet. */
675 if (e->active
676 && (e->n_acks >= N_ACK_RETRANSMIT || local_now >= e->next_try))
677 {
678 if (!best || reliable_pid_min(e->packet_id, best->packet_id))
679 {
680 best = e;
681 }
682 }
683 }
684 if (best)
685 {
686 /* exponential backoff */
687 best->next_try = local_now + best->timeout;
688 best->timeout *= 2;
689 best->n_acks = 0;
690 *opcode = best->opcode;
691 dmsg(D_REL_DEBUG, "ACK reliable_send ID " packet_id_format " (size=%d to=%d)",
693 (int)(best->next_try - local_now));
694 return &best->buf;
695 }
696 return NULL;
697}
698
699/* schedule all pending packets for immediate retransmit */
700void
702{
703 int i;
704 dmsg(D_REL_DEBUG, "ACK reliable_schedule_now");
705 rel->hold = false;
706 for (i = 0; i < rel->size; ++i)
707 {
708 struct reliable_entry *e = &rel->array[i];
709 if (e->active)
710 {
711 e->next_try = now;
712 e->timeout = rel->initial_timeout;
713 }
714 }
715}
716
717/* in how many seconds should we wake up to check for timeout */
718/* if we return BIG_TIMEOUT, nothing to wait for */
721{
722 struct gc_arena gc = gc_new();
724 int i;
725 const time_t local_now = now;
726
727 for (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, e->next_try - local_now);
740 }
741 }
742 }
743
744 dmsg(D_REL_DEBUG, "ACK reliable_send_timeout %d %s",
745 (int) ret,
746 reliable_print_ids(rel, &gc));
747
748 gc_free(&gc);
749 return ret;
750}
751
752/*
753 * Enable an incoming buffer previously returned by a get function as active.
754 */
755
756void
758 packet_id_type pid, int opcode)
759{
760 int i;
761 for (i = 0; i < rel->size; ++i)
762 {
763 struct reliable_entry *e = &rel->array[i];
764 if (buf == &e->buf)
765 {
766 e->active = true;
767
768 /* packets may not arrive in sequential order */
769 e->packet_id = pid;
770
771 /* check for replay */
772 ASSERT(!reliable_pid_min(pid, rel->packet_id));
773
774 e->opcode = opcode;
775 e->next_try = 0;
776 e->timeout = 0;
777 e->n_acks = 0;
778 dmsg(D_REL_DEBUG, "ACK mark active incoming ID " packet_id_format, (packet_id_print_type)e->packet_id);
779 return;
780 }
781 }
782 ASSERT(0); /* buf not found in rel */
783}
784
785/*
786 * Enable an outgoing buffer previously returned by a get function as active.
787 */
788
789void
791{
792 int i;
793 for (i = 0; i < rel->size; ++i)
794 {
795 struct reliable_entry *e = &rel->array[i];
796 if (buf == &e->buf)
797 {
798 /* Write mode, increment packet_id (i.e. sequence number)
799 * linearly and prepend id to packet */
800 packet_id_type net_pid;
801 e->packet_id = rel->packet_id++;
802 net_pid = htonpid(e->packet_id);
803 ASSERT(buf_write_prepend(buf, &net_pid, sizeof(net_pid)));
804 e->active = true;
805 e->opcode = opcode;
806 e->next_try = 0;
807 e->timeout = rel->initial_timeout;
808 dmsg(D_REL_DEBUG, "ACK mark active outgoing ID " packet_id_format, (packet_id_print_type)e->packet_id);
809 return;
810 }
811 }
812 ASSERT(0); /* buf not found in rel */
813}
814
815/* delete a buffer previously activated by reliable_mark_active() */
816void
818{
819 int i;
820 for (i = 0; i < rel->size; ++i)
821 {
822 struct reliable_entry *e = &rel->array[i];
823 if (buf == &e->buf)
824 {
825 e->active = false;
826 rel->packet_id = e->packet_id + 1;
827 return;
828 }
829 }
830 ASSERT(0);
831}
832
833#if 0
834
835void
836reliable_ack_debug_print(const struct reliable_ack *ack, char *desc)
837{
838 int i;
839
840 printf("********* struct reliable_ack %s\n", desc);
841 for (i = 0; i < ack->len; ++i)
842 {
843 printf(" %d: " packet_id_format "\n", i, (packet_id_print_type) ack->packet_id[i]);
844 }
845}
846
847void
848reliable_debug_print(const struct reliable *rel, char *desc)
849{
850 int i;
851 update_time();
852
853 printf("********* struct reliable %s\n", desc);
854 printf(" initial_timeout=%d\n", (int)rel->initial_timeout);
855 printf(" packet_id=" packet_id_format "\n", rel->packet_id);
856 printf(" now=%" PRIi64 "\n", (int64_t)now);
857 for (i = 0; i < rel->size; ++i)
858 {
859 const struct reliable_entry *e = &rel->array[i];
860 if (e->active)
861 {
862 printf(" %d: packet_id=" packet_id_format " len=%d", i, e->packet_id, e->buf.len);
863 printf(" next_try=%" PRIi64, (int64_t)e->next_try);
864 printf("\n");
865 }
866 }
867}
868
869#endif /* if 0 */
void free_buf(struct buffer *buf)
Definition buffer.c:183
bool buf_printf(struct buffer *buf, const char *format,...)
Definition buffer.c:240
struct buffer buf_sub(struct buffer *buf, int size, bool prepend)
Definition buffer.c:221
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
Definition buffer.c:88
struct buffer alloc_buf(size_t size)
Definition buffer.c:62
#define BSTR(buf)
Definition buffer.h:129
static bool buf_write_prepend(struct buffer *dest, const void *src, int size)
Definition buffer.h:680
static bool buf_read(struct buffer *src, void *dest, int size)
Definition buffer.h:778
#define BDEF(buf)
Definition buffer.h:128
static bool buf_write(struct buffer *dest, const void *src, size_t size)
Definition buffer.h:668
static bool buf_write_u8(struct buffer *dest, uint8_t data)
Definition buffer.h:692
static void gc_free(struct gc_arena *a)
Definition buffer.h:1033
#define buf_init(buf, offset)
Definition buffer.h:209
static struct gc_arena gc_new(void)
Definition buffer.h:1025
int interval_t
Definition common.h:36
#define BIG_TIMEOUT
Definition common.h:41
#define D_REL_DEBUG
Definition errlevel.h:161
#define D_REL_LOW
Definition errlevel.h:123
#define M_INFO
Definition errlevel.h:55
void reliable_free(struct reliable *rel)
Free allocated memory associated with a reliable structure and the pointer itself.
Definition reliable.c:375
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:149
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:582
void reliable_schedule_now(struct reliable *rel)
Reschedule all entries of a reliable structure to be ready for (re)sending immediately.
Definition reliable.c:701
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:114
void reliable_mark_active_incoming(struct reliable *rel, struct buffer *buf, packet_id_type pid, int opcode)
Mark the reliable entry associated with the given buffer as active incoming.
Definition reliable.c:757
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:790
const char * reliable_ack_print(struct buffer *buf, bool verbose, struct gc_arena *gc)
Definition reliable.c:313
bool reliable_ack_acknowledge_packet_id(struct reliable_ack *ack, packet_id_type pid)
Record a packet ID for later acknowledgment.
Definition reliable.c:132
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:173
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:255
#define N_ACK_RETRANSMIT
We retry sending a packet early if this many later packets have been ACKed.
Definition reliable.h:53
bool reliable_can_get(const struct reliable *rel)
Check whether a reliable structure has any free buffers available for use.
Definition reliable.c:469
void reliable_send_purge(struct reliable *rel, const struct reliable_ack *ack)
Remove acknowledged packets from a reliable structure.
Definition reliable.c:408
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:535
struct buffer * reliable_send(struct reliable *rel, int *opcode)
Get the next packet to send to the remote peer.
Definition reliable.c:662
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:634
bool reliable_empty(const struct reliable *rel)
Check whether a reliable structure is empty.
Definition reliable.c:392
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.
Definition reliable.c:488
#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:44
interval_t reliable_send_timeout(const struct reliable *rel)
Determined how many seconds until the earliest resend should be attempted.
Definition reliable.c:720
#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:618
void reliable_init(struct reliable *rel, int buf_size, int offset, int array_size, bool hold)
Initialize a reliable structure.
Definition reliable.c:357
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:211
void reliable_mark_deleted(struct reliable *rel, struct buffer *buf)
Remove an entry from a reliable structure.
Definition reliable.c:817
int reliable_get_num_output_sequenced_available(struct reliable *rel)
Counts the number of free buffers in output that can be potentially used for sending.
Definition reliable.c:551
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:515
#define ACK_SIZE(n)
Definition reliable.h:68
static int min_int(int x, int y)
Definition integer.h:102
#define CLEAR(x)
Definition basic.h:33
#define dmsg(flags,...)
Definition error.h:148
#define msg(flags,...)
Definition error.h:144
#define ASSERT(x)
Definition error.h:195
time_t now
Definition otime.c:34
static void update_time(void)
Definition otime.h:77
#define packet_id_format
Definition packet_id.h:77
#define htonpid(x)
Definition packet_id.h:62
uint64_t packet_id_print_type
Definition packet_id.h:78
uint32_t packet_id_type
Definition packet_id.h:46
#define ntohpid(x)
Definition packet_id.h:65
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(struct reliable_ack *ack, packet_id_type pid)
Definition reliable.c:99
static bool reliable_pid_in_range1(const packet_id_type test, const packet_id_type base, const unsigned int extent)
Definition reliable.c:54
static bool reliable_pid_min(const packet_id_type p1, const packet_id_type p2)
Definition reliable.c:91
static bool reliable_pid_in_range2(const packet_id_type test, const packet_id_type base, const unsigned int extent)
Definition reliable.c:65
Reliability Layer module header file.
const char * session_id_print(const struct session_id *sid, struct gc_arena *gc)
Definition session_id.c:55
static bool session_id_write(const struct session_id *sid, struct buffer *buf)
Definition session_id.h:73
static bool session_id_equal(const struct session_id *sid1, const struct session_id *sid2)
Definition session_id.h:48
static bool session_id_defined(const struct session_id *sid1)
Definition session_id.h:55
static bool session_id_read(struct session_id *sid, struct buffer *buf)
Definition session_id.h:61
Wrapper structure for dynamically allocated memory.
Definition buffer.h:61
int len
Length in bytes of the actual content within the allocated memory.
Definition buffer.h:66
int offset
Offset in bytes of the actual content within the allocated memory.
Definition buffer.h:64
Garbage collection arena used to keep track of dynamically allocated memory.
Definition buffer.h:117
The acknowledgment structure in which packet IDs are stored for later acknowledgment.
Definition reliable.h:62
packet_id_type packet_id[RELIABLE_ACK_SIZE]
Definition reliable.h:64
The structure in which the reliability layer stores a single incoming or outgoing packet.
Definition reliable.h:75
struct buffer buf
Definition reliable.h:84
int opcode
Definition reliable.h:83
time_t next_try
Definition reliable.h:78
size_t n_acks
Definition reliable.h:80
packet_id_type packet_id
Definition reliable.h:79
bool active
Definition reliable.h:76
interval_t timeout
Definition reliable.h:77
The reliability layer storage structure for one VPN tunnel's control channel in one direction.
Definition reliable.h:92
struct reliable_entry array[RELIABLE_CAPACITY]
Definition reliable.h:98
bool hold
Definition reliable.h:97
int size
Definition reliable.h:93
packet_id_type packet_id
Definition reliable.h:95
interval_t initial_timeout
Definition reliable.h:94
int offset
Offset of the bufs in the reliable_entry array.
Definition reliable.h:96
struct gc_arena gc
Definition test_ssl.c:155