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