GNUnet 0.28.0-4-ge21227b96
 
Loading...
Searching...
No Matches
gnunet-communicator-quic.c
Go to the documentation of this file.
1/*
2 This file is part of GNUnet
3 Copyright (C) 2010-2014, 2018, 2019, 2026 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
37#include <quiche.h>
38#include <stdint.h>
39#include <inttypes.h>
40#include "platform.h"
41#include "gnunet_common.h"
42#include "gnunet_util_lib.h"
43#include "gnunet_constants.h"
44#include "gnunet_pils_service.h"
48#include "gnunet_nat_service.h"
49
50#define COMMUNICATOR_CONFIG_SECTION "communicator-quic"
51#define COMMUNICATOR_ADDRESS_PREFIX "quic"
52#define MAX_DATAGRAM_SIZE 1350
53
54
55/* FIXME: Review all static lengths/contents below. Maybe this can be done smarter */
56/* Currently equivalent to QUICHE_MAX_CONN_ID_LEN */
57#define LOCAL_CONN_ID_LEN 20
58#define MAX_TOKEN_LEN \
59 sizeof("quiche") - 1 \
60 + sizeof(struct sockaddr_storage) \
61 + QUICHE_MAX_CONN_ID_LEN
62#define CID_LEN sizeof(uint8_t) * QUICHE_MAX_CONN_ID_LEN
63#define TOKEN_LEN sizeof (uint8_t) * MAX_TOKEN_LEN
64
65
66/* FIXME: Why 4?
67 Generic, bidirectional, client-initiated quic stream id */
68#define STREAMID_BI 4
69
74#define ADDRESS_VALIDITY_PERIOD GNUNET_TIME_UNIT_HOURS
75
80
85
89static const struct GNUNET_CONFIGURATION_Handle *cfg;
90
95
100
105
110
114static int have_v6_socket;
115
119static uint16_t my_port;
120
124static quiche_config *config = NULL;
125
130
134static struct GNUNET_NAT_Handle *nat;
135
145{
150
155
160
165
171
175 struct sockaddr *address;
176
180 socklen_t address_len;
181
186
191
196
201
206 size_t d_mtu;
207
212
217
222 // struct GNUNET_CONTAINER_HeapNode *hn;
223};
224
225// /**
226// * FIXME: Implementation missing
227// * Expiration heap for peers (contains `struct PeerAddress`)
228// */
229// static struct GNUNET_CONTAINER_Heap *peers_heap;
230
235
240
245
252{
254
255 quiche_conn *conn;
256};
257
262{
263 uint8_t type;
264 uint32_t version;
265
266 uint8_t scid[QUICHE_MAX_CONN_ID_LEN];
267 size_t scid_len;
268
269 uint8_t dcid[QUICHE_MAX_CONN_ID_LEN];
270 size_t dcid_len;
271
272 uint8_t odcid[QUICHE_MAX_CONN_ID_LEN];
273 size_t odcid_len;
274
276 size_t token_len;
277};
278
279
284static void
286{
287 char stream_buf[UINT16_MAX];
288 size_t buf_size = UINT16_MAX;
289 char *buf_ptr = stream_buf;
290 struct GNUNET_MessageHeader *hdr;
291
292 uint64_t s = 0;
293 quiche_stream_iter *readable;
294 bool fin;
295 uint64_t err_code;
296 ssize_t recv_len;
297
298 readable = quiche_conn_readable (peer->conn->conn);
299 while (quiche_stream_iter_next (readable, &s))
300 {
301 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "stream %" PRIu64 " is readable\n",
302 s);
303 fin = false;
304 recv_len = quiche_conn_stream_recv (peer->conn->conn, s,
305 (uint8_t *) stream_buf, buf_size,
306 &fin, &err_code);
307 if (recv_len < 0)
308 {
310 "error while receiving data from stream %" PRIu64
311 "; error_code %" PRIu64 "\n",
312 s, err_code);
313 break;
314 }
321 if (! peer->is_receiver && GNUNET_NO == peer->id_rcvd)
322 {
323 if (recv_len < sizeof(struct GNUNET_PeerIdentity))
324 {
326 "message recv len of %zd less than length of peer identity\n",
327 recv_len);
328 return;
329 }
331 "received peer identity\n");
332 struct GNUNET_PeerIdentity *pid = (struct
333 GNUNET_PeerIdentity *) stream_buf;
334 peer->target = *pid;
335 peer->id_rcvd = GNUNET_YES;
336 buf_ptr += sizeof(struct GNUNET_PeerIdentity);
337 recv_len -= sizeof(struct GNUNET_PeerIdentity);
338 }
342 while (recv_len >= sizeof(struct GNUNET_MessageHeader))
343 {
344 hdr = (struct GNUNET_MessageHeader *) buf_ptr;
345 if (ntohs (hdr->size) > recv_len)
346 {
348 "message size stated (%d) is greater than length of rcvd data (%zd)!\n",
349 ntohs (hdr->size), recv_len);
350 return;
351 }
352 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "passing %zd bytes to core\n",
353 recv_len);
356 NULL);
357 recv_len -= ntohs (hdr->size);
358 buf_ptr += ntohs (hdr->size);
359 }
363 if (0 != recv_len)
364 {
366 "message recv len of %zd less than length of message header\n",
367 recv_len);
368 }
373 if (fin)
374 {
376 "fin received, closing connection\n");
377 if (0 > quiche_conn_close (peer->conn->conn, true, 0, NULL, 0))
378 {
380 "quiche failed to close connection to peer\n");
381 }
382 }
383 }
384 quiche_stream_iter_free (readable);
385}
386
387
391static void
392mint_token (const uint8_t *dcid, size_t dcid_len,
393 struct sockaddr_storage *addr, socklen_t addr_len,
394 uint8_t *token, size_t *token_len)
395{
396 GNUNET_memcpy (token, "quiche", sizeof("quiche") - 1);
397 GNUNET_memcpy (token + sizeof("quiche") - 1, addr, addr_len);
398 GNUNET_memcpy (token + sizeof("quiche") - 1 + addr_len, dcid, dcid_len);
399
400 *token_len = sizeof("quiche") - 1 + addr_len + dcid_len;
401}
402
403
405validate_token (const uint8_t *token, size_t token_len,
406 struct sockaddr_storage *addr, socklen_t addr_len,
407 uint8_t *odcid, size_t *odcid_len)
408{
409 if ((token_len < sizeof("quiche") - 1) ||
410 memcmp (token, "quiche", sizeof("quiche") - 1))
411 {
412 return GNUNET_NO;
413 }
414
415 token += sizeof("quiche") - 1;
416 token_len -= sizeof("quiche") - 1;
417
418 if ((token_len < addr_len) || memcmp (token, addr, addr_len))
419 {
420 return GNUNET_NO;
421 }
422
423 token += addr_len;
424 token_len -= addr_len;
425
426 if (*odcid_len < token_len)
427 {
428 return GNUNET_NO;
429 }
430
431 memcpy (odcid, token, token_len);
432 *odcid_len = token_len;
433
434 return GNUNET_OK;
435}
436
437
438static struct quic_conn*
439create_conn (uint8_t *scid, size_t scid_len,
440 uint8_t *odcid, size_t odcid_len,
441 struct sockaddr *local_addr,
442 socklen_t local_addr_len,
443 struct sockaddr_storage *peer_addr,
444 socklen_t peer_addr_len)
445{
446 struct quic_conn *conn;
447 quiche_conn *q_conn;
448 conn = GNUNET_new (struct quic_conn);
449 if (scid_len != LOCAL_CONN_ID_LEN)
450 {
452 "error while creating connection, scid length too short: %zu\n",
453 scid_len);
455 return NULL;
456 }
457
459 q_conn = quiche_accept (conn->cid, LOCAL_CONN_ID_LEN,
460 odcid, odcid_len,
462 local_addr_len,
463 (struct sockaddr *) peer_addr,
464 peer_addr_len,
465 config);
466 if (NULL == q_conn)
467 {
469 "quiche failed to create connection after call to quiche_accept\n");
471 return NULL;
472 }
473 conn->conn = q_conn;
474 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "new quic connection created\n");
475 return conn;
476}
477
478
479static void
481{
482 static uint8_t out[MAX_DATAGRAM_SIZE];
483 quiche_send_info send_info;
484
485 ssize_t written;
486 ssize_t sent;
487
488 while (1)
489 {
490 written = quiche_conn_send (conn->conn, out, sizeof(out), &send_info);
491 if (QUICHE_ERR_DONE == written)
492 {
493 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "done writing quic packets\n");
494 break;
495 }
496 if (0 > written)
497 {
499 "quiche failed to create packet. quiche error: %zd\n",
500 written);
501 return;
502 }
503 sent = GNUNET_NETWORK_socket_sendto (udp_sock, out, written,
504 (struct sockaddr *) &send_info.to,
505 send_info.to_len);
506 if (sent != written)
507 {
509 "quiche failed to send data to peer\n");
510 return;
511 }
512 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sent %zd bytes\n", sent);
513 }
514}
515
516
522static void
524{
525 peer->timeout =
527 // GNUNET_CONTAINER_heap_update_cost (peer->hn,
528 // peer->timeout.abs_value_us);
529}
530
531
537static void
539{
540 struct GNUNET_HashCode addr_key;
541
544 "Disconnecting peer for peer `%s'\n",
545 GNUNET_i2s (&peer->target));
546 if (NULL != peer->d_qh)
547 {
549 peer->d_qh = NULL;
550 }
551 // GNUNET_assert (peer == GNUNET_CONTAINER_heap_remove_node (peer->hn));
555 GNUNET_CRYPTO_hash (peer->address, peer->address_len, &addr_key);
557 peer))
558 {
560 "tried to remove non-existent peer from addr map\n");
561 return;
562 }
564 "# peers active",
566 GNUNET_NO);
567 quiche_conn_free (peer->conn->conn);
568 GNUNET_free (peer->address);
570 GNUNET_free (peer->conn);
571 GNUNET_free (peer);
572}
573
574
583static int
585 const struct GNUNET_HashCode *key,
586 void *value)
587{
588 struct PeerAddress *peer = value;
589 (void) cls;
590 (void) key;
591 peer_destroy (peer);
592 return GNUNET_OK;
593}
594
595
604static void
606 const struct GNUNET_MessageHeader *msg,
607 void *impl_state)
608{
609 struct PeerAddress *peer = impl_state;
610 uint16_t msize = ntohs (msg->size);
611 ssize_t send_len;
612 uint64_t err_code;
613
614 if (NULL == peer->conn->conn)
615 {
617 "peer never established quic connection\n");
618 return;
619 }
620
621 GNUNET_assert (mq == peer->d_mq);
622 if (msize > peer->d_mtu)
623 {
625 "msize: %u, mtu: %lu\n",
626 msize,
627 peer->d_mtu);
628 GNUNET_break (0);
629 if (GNUNET_YES != peer->peer_destroy_called)
630 {
632 "peer destroy called, destroying peer\n");
633 peer_destroy (peer);
634 }
635 return;
636 }
638
639 send_len = quiche_conn_stream_send (peer->conn->conn, 4, (uint8_t *) msg,
640 msize, false, &err_code);
641 if (send_len != msize)
642 {
644 "tried to send message and quiche returned %zd; error_code %"
645 PRIu64,
646 send_len, err_code);
647 return;
648 }
649 flush_egress (peer->conn);
651 "sent a message of %zd bytes\n", send_len);
653}
654
655
664static void
665mq_destroy_d (struct GNUNET_MQ_Handle *mq, void *impl_state)
666{
667 struct PeerAddress *peer = impl_state;
669 "Default MQ destroyed\n");
670 if (mq == peer->d_mq)
671 {
672 peer->d_mq = NULL;
673 if (GNUNET_YES != peer->peer_destroy_called)
674 peer_destroy (peer);
675 }
676}
677
678
685static void
686mq_cancel (struct GNUNET_MQ_Handle *mq, void *impl_state)
687{
688 /* Cancellation is impossible with QUIC; bail */
689 GNUNET_assert (0);
690}
691
692
702static void
703mq_error (void *cls, enum GNUNET_MQ_Error error)
704{
705 struct PeerAddress *peer = cls;
706
708 "MQ error in queue to %s: %d\n",
709 GNUNET_i2s (&peer->target),
710 (int) error);
711 peer_destroy (peer);
712}
713
714
722static struct sockaddr *
723udp_address_to_sockaddr (const char *bindto, socklen_t *sock_len)
724{
725 struct sockaddr *in;
726 unsigned int port;
727 char dummy[2];
728 char *colon;
729 char *cp;
730
731 if (1 == sscanf (bindto, "%u%1s", &port, dummy))
732 {
733 /* interpreting value as just a PORT number */
734 if (port > UINT16_MAX)
735 {
737 "BINDTO specification `%s' invalid: value too large for port\n",
738 bindto);
739 return NULL;
740 }
741 if ((GNUNET_NO == GNUNET_NETWORK_test_pf (PF_INET6)) ||
742 (GNUNET_YES ==
745 "DISABLE_V6")))
746 {
747 struct sockaddr_in *i4;
748
749 i4 = GNUNET_malloc (sizeof(struct sockaddr_in));
750 i4->sin_family = AF_INET;
751 i4->sin_port = htons ((uint16_t) port);
752 *sock_len = sizeof(struct sockaddr_in);
753 in = (struct sockaddr *) i4;
754 }
755 else
756 {
757 struct sockaddr_in6 *i6;
758
759 i6 = GNUNET_malloc (sizeof(struct sockaddr_in6));
760 i6->sin6_family = AF_INET6;
761 i6->sin6_port = htons ((uint16_t) port);
762 *sock_len = sizeof(struct sockaddr_in6);
763 in = (struct sockaddr *) i6;
764 }
765 return in;
766 }
767 cp = GNUNET_strdup (bindto);
768 colon = strrchr (cp, ':');
769 if (NULL != colon)
770 {
771 /* interpret value after colon as port */
772 *colon = '\0';
773 colon++;
774 if (1 == sscanf (colon, "%u%1s", &port, dummy))
775 {
776 /* interpreting value as just a PORT number */
777 if (port > UINT16_MAX)
778 {
780 "BINDTO specification `%s' invalid: value too large for port\n",
781 bindto);
782 GNUNET_free (cp);
783 return NULL;
784 }
785 }
786 else
787 {
788 GNUNET_log (
790 "BINDTO specification `%s' invalid: last ':' not followed by number\n",
791 bindto);
792 GNUNET_free (cp);
793 return NULL;
794 }
795 }
796 else
797 {
798 /* interpret missing port as 0, aka pick any free one */
799 port = 0;
800 }
801 {
802 /* try IPv4 */
803 struct sockaddr_in v4;
804
805 memset (&v4, 0, sizeof(v4));
806 if (1 == inet_pton (AF_INET, cp, &v4.sin_addr))
807 {
808 v4.sin_family = AF_INET;
809 v4.sin_port = htons ((uint16_t) port);
810#if HAVE_SOCKADDR_IN_SIN_LEN
811 v4.sin_len = sizeof(struct sockaddr_in);
812#endif
813 in = GNUNET_memdup (&v4, sizeof(struct sockaddr_in));
814 *sock_len = sizeof(struct sockaddr_in);
815 GNUNET_free (cp);
816 return in;
817 }
818 }
819 {
820 /* try IPv6 */
821 struct sockaddr_in6 v6;
822 const char *start;
823
824 memset (&v6, 0, sizeof(v6));
825 start = cp;
826 if (('[' == *cp) && (']' == cp[strlen (cp) - 1]))
827 {
828 start++; /* skip over '[' */
829 cp[strlen (cp) - 1] = '\0'; /* eat ']' */
830 }
831 if (1 == inet_pton (AF_INET6, start, &v6.sin6_addr))
832 {
833 v6.sin6_family = AF_INET6;
834 v6.sin6_port = htons ((uint16_t) port);
835#if HAVE_SOCKADDR_IN_SIN_LEN
836 v6.sin6_len = sizeof(sizeof(struct sockaddr_in6));
837#endif
838 in = GNUNET_memdup (&v6, sizeof(v6));
839 *sock_len = sizeof(v6);
840 GNUNET_free (cp);
841 return in;
842 }
843 }
844 /* #5528 FIXME (feature!): maybe also try getnameinfo()? */
845 GNUNET_free (cp);
846 return NULL;
847}
848
849
857static void
859{
860 size_t base_mtu;
861
862 switch (peer->address->sa_family)
863 {
864 case AF_INET:
865 base_mtu = 1480 /* Ethernet MTU, 1500 - Ethernet header - VLAN tag */
866 - sizeof(struct GNUNET_TUN_IPv4Header) /* 20 */
867 - sizeof(struct GNUNET_TUN_UdpHeader) /* 8 */;
868 break;
869
870 case AF_INET6:
871 base_mtu = 1280 /* Minimum MTU required by IPv6 */
872 - sizeof(struct GNUNET_TUN_IPv6Header) /* 40 */
873 - sizeof(struct GNUNET_TUN_UdpHeader) /* 8 */;
874 break;
875
876 default:
877 GNUNET_assert (0);
878 break;
879 }
880 /* MTU == base_mtu */
881 peer->d_mtu = base_mtu;
882
884 "Setting up MQs and QHs\n");
885 /* => Effective MTU for CORE will range from 1080 (IPv6 + KX) to
886 1404 (IPv4 + Box) bytes, depending on circumstances... */
887
888 if (NULL == peer->d_mq)
891 &mq_cancel,
892 peer,
893 NULL,
894 &mq_error,
895 peer);
896 peer->d_qh =
898 &peer->target,
899 peer->foreign_addr,
900 1000,
902 0, /* Priority */
903 peer->nt,
905 peer->d_mq);
906}
907
908
918static char *
919sockaddr_to_udpaddr_string (const struct sockaddr *address,
920 socklen_t address_len)
921{
922 char *ret;
923
924 switch (address->sa_family)
925 {
926 case AF_INET:
928 "%s-%s",
930 GNUNET_a2s (address, address_len));
931 break;
932
933 case AF_INET6:
935 "%s-%s",
937 GNUNET_a2s (address, address_len));
938 break;
939
940 default:
941 GNUNET_assert (0);
942 }
943 return ret;
944}
945
946
956static void
957notify_cb (void *cls,
958 const struct GNUNET_PeerIdentity *sender,
959 const struct GNUNET_MessageHeader *msg)
960{
961 // const struct UDPAck *ack;
962
963 // (void) cls;
964 // GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
965 // "Storing UDPAck received from backchannel from %s\n",
966 // GNUNET_i2s_full (sender));
967 // if ((ntohs (msg->type) != GNUNET_MESSAGE_TYPE_COMMUNICATOR_UDP_ACK) ||
968 // (ntohs (msg->size) != sizeof(struct UDPAck)))
969 // {
970 // GNUNET_break_op (0);
971 // return;
972 // }
973 // ack = (const struct UDPAck *) msg;
974 // GNUNET_CONTAINER_multipeermap_get_multiple (receivers,
975 // sender,
976 // &handle_ack,
977 // (void *) ack);
978}
979
980
999static int
1000mq_init (void *cls, const struct GNUNET_PeerIdentity *peer_id, const
1001 char *address)
1002{
1003 struct PeerAddress *peer;
1004 const char *path;
1005 struct sockaddr *in;
1006 socklen_t in_len;
1007 struct GNUNET_HashCode addr_key;
1008 uint8_t scid[LOCAL_CONN_ID_LEN];
1009
1010 struct quic_conn *q_conn;
1011 char *bindto;
1012 socklen_t local_in_len;
1013 struct sockaddr *local_addr;
1014
1015 if (GNUNET_OK !=
1018 "BINDTO",
1019 &bindto))
1020 {
1023 "BINDTO");
1024 return GNUNET_SYSERR;
1025 }
1026 local_addr = udp_address_to_sockaddr (bindto, &local_in_len);
1027
1028 if (0 != strncmp (address,
1030 strlen (COMMUNICATOR_ADDRESS_PREFIX "-")))
1031 {
1032 GNUNET_break_op (0);
1033 return GNUNET_SYSERR;
1034 }
1035 path = &address[strlen (COMMUNICATOR_ADDRESS_PREFIX "-")];
1036 in = udp_address_to_sockaddr (path, &in_len);
1037 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "mq_init in_len length before: %d\n",
1038 in_len);
1042 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "address string in mq_init: %s\n",
1043 address);
1044 GNUNET_CRYPTO_hash (address, strlen (address), &addr_key);
1045 peer = GNUNET_CONTAINER_multihashmap_get (addr_map, &addr_key);
1046 if (NULL != peer)
1047 {
1049 "ignoring transport service mq request, we already have an mq with this peer (address)\n");
1050 return GNUNET_SYSERR;
1051 }
1052 peer = GNUNET_new (struct PeerAddress);
1053 peer->address = in;
1054 peer->address_len = in_len;
1055 peer->target = *peer_id;
1056 peer->id_rcvd = GNUNET_YES;
1057 peer->is_receiver = GNUNET_YES;
1058 peer->nt = GNUNET_NT_scanner_get_type (is, in, in_len);
1059 peer->timeout =
1062 "# peers active",
1064 GNUNET_NO);
1065 peer->foreign_addr =
1071 peer,
1074 "mq_init added new peer to the addr map\n");
1080 q_conn = GNUNET_new (struct quic_conn);
1081 GNUNET_memcpy (q_conn->cid, scid, LOCAL_CONN_ID_LEN);
1082 peer->conn = q_conn;
1084 "attempting to perform QUIC handshake with peer\n");
1085 q_conn->conn = quiche_connect (peer->foreign_addr, scid, LOCAL_CONN_ID_LEN,
1086 local_addr,
1087 local_in_len, peer->address, peer->address_len,
1088 config);
1089 flush_egress (peer->conn);
1091 return GNUNET_OK;
1095 // if (NULL == timeout_task)
1096 // timeout_task = GNUNET_SCHEDULER_add_now (&check_timeouts, NULL);
1097}
1098
1099
1100static void
1102 const struct sockaddr *addr,
1103 socklen_t addrlen)
1104{
1105 /* FIXME: support reversal: #5529 */
1107 "No connection reversal implemented!");
1108}
1109
1110
1124static void
1126 void **app_ctx,
1127 int add_remove,
1129 const struct sockaddr *addr,
1130 socklen_t addrlen)
1131{
1132 char *my_addr;
1134
1135 if (GNUNET_YES == add_remove)
1136 {
1138
1139 GNUNET_asprintf (&my_addr,
1140 "%s-%s",
1142 GNUNET_a2s (addr, addrlen));
1143 nt = GNUNET_NT_scanner_get_type (is, addr, addrlen);
1144 ai =
1146 my_addr,
1147 nt,
1149 GNUNET_free (my_addr);
1150 *app_ctx = ai;
1151 }
1152 else
1153 {
1154 ai = *app_ctx;
1156 *app_ctx = NULL;
1157 }
1158}
1159
1160
1166static void
1167do_shutdown (void *cls)
1168{
1170 "do_shutdown\n");
1173 quiche_config_free (config);
1174
1175 if (NULL != timeout_task)
1176 {
1178 timeout_task = NULL;
1179 }
1180 if (NULL != read_task)
1181 {
1183 read_task = NULL;
1184 }
1185 if (NULL != udp_sock)
1186 {
1189 udp_sock = NULL;
1190 }
1191 if (NULL != ch)
1192 {
1194 ch = NULL;
1195 }
1196 if (NULL != ah)
1197 {
1199 ah = NULL;
1200 }
1201 if (NULL != pils)
1202 {
1204 pils = NULL;
1205 }
1207 "do_shutdown finished\n");
1208}
1209
1210
1211static void
1212sock_read (void *cls)
1213{
1214 struct sockaddr_storage sa;
1215 socklen_t salen = sizeof(sa);
1216 uint8_t buf[UINT16_MAX];
1217 uint8_t out[MAX_DATAGRAM_SIZE];
1218 ssize_t rcvd;
1219
1220 ssize_t process_pkt;
1221 struct QUIC_header quic_header;
1222
1223 struct PeerAddress *peer;
1224 struct GNUNET_HashCode addr_key;
1225
1226 (void) cls;
1230 char *bindto;
1231 socklen_t in_len;
1232 if (GNUNET_OK !=
1235 "BINDTO",
1236 &bindto))
1237 {
1240 "BINDTO");
1241 return;
1242 }
1243 struct sockaddr *local_addr = udp_address_to_sockaddr (bindto, &in_len);
1244
1246 udp_sock,
1247 &sock_read,
1248 NULL);
1249 while (1)
1250 {
1251 quic_header.scid_len = sizeof(quic_header.scid);
1252 quic_header.dcid_len = sizeof(quic_header.dcid);
1253 quic_header.odcid_len = sizeof(quic_header.odcid);
1254 quic_header.token_len = sizeof(quic_header.token);
1256 buf,
1257 sizeof(buf),
1258 (struct sockaddr *) &sa,
1259 &salen);
1260 if (-1 == rcvd)
1261 {
1262 if (EAGAIN == errno)
1263 break; // We are done reading data
1265 return;
1266 }
1267
1269 "Read %lu bytes\n", rcvd);
1270
1271 if (-1 == rcvd)
1272 {
1274 return;
1275 }
1283 char *addr_string = sockaddr_to_udpaddr_string ((const struct
1284 sockaddr *) &sa,
1285 salen);
1286 GNUNET_CRYPTO_hash (addr_string, strlen (addr_string),
1287 &addr_key);
1288 GNUNET_free (addr_string);
1289 peer = GNUNET_CONTAINER_multihashmap_get (addr_map, &addr_key);
1290
1291 if (NULL == peer)
1292 {
1296 peer = GNUNET_new (struct PeerAddress);
1297 peer->address = GNUNET_memdup (&sa, salen);
1298 peer->address_len = salen;
1299 peer->id_rcvd = GNUNET_NO;
1300 peer->id_sent = GNUNET_NO;
1301 peer->is_receiver = GNUNET_NO;
1302 peer->conn = NULL;
1304 peer->address_len);
1308 // setup_peer_mq (peer);
1310 &addr_key,
1311 peer,
1313 {
1315 "tried to add duplicate address into address map\n");
1316 return;
1317 }
1319 "sock_read added new peer to address map\n");
1320 }
1321
1325 int rc = quiche_header_info (buf, rcvd, LOCAL_CONN_ID_LEN,
1326 &quic_header.version,
1327 &quic_header.type, quic_header.scid,
1328 &quic_header.scid_len, quic_header.dcid,
1329 &quic_header.dcid_len,
1330 quic_header.token, &quic_header.token_len);
1331 if (0 > rc)
1332 {
1334 "failed to parse quic header: %d\n",
1335 rc);
1336 return;
1337 }
1338
1342 if (NULL == peer->conn)
1343 {
1345 "attempting to create new connection\n");
1346 if (0 == quiche_version_is_supported (quic_header.version))
1347 {
1349 "quic version negotiation initiated\n");
1357 ssize_t written = quiche_negotiate_version (quic_header.scid,
1358 quic_header.scid_len,
1359 quic_header.dcid,
1360 quic_header.dcid_len,
1361 out, sizeof(out));
1362 if (0 > written)
1363 {
1365 "quiche failed to generate version negotiation packet\n");
1366 return;
1367 }
1368 ssize_t sent = GNUNET_NETWORK_socket_sendto (udp_sock,
1369 out,
1370 written,
1371 (struct sockaddr*) &sa,
1372 salen);
1373 if (sent != written)
1374 {
1376 "failed to send version negotiation packet to peer\n");
1377 return;
1378 }
1380 "sent %zd bytes to peer during version negotiation\n",
1381 sent);
1382 return;
1383 }
1384
1385 if (0 == quic_header.token_len)
1386 {
1387 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "quic stateless retry\n");
1388 mint_token (quic_header.dcid, quic_header.dcid_len, &sa, salen,
1389 quic_header.token, &quic_header.token_len);
1390
1391 uint8_t new_cid[LOCAL_CONN_ID_LEN];
1394
1395 ssize_t written = quiche_retry (quic_header.scid, quic_header.scid_len,
1396 quic_header.dcid, quic_header.dcid_len,
1397 new_cid, LOCAL_CONN_ID_LEN,
1398 quic_header.token,
1399 quic_header.token_len,
1400 quic_header.version, out, sizeof(out));
1401 if (0 > written)
1402 {
1404 "quiche failed to write retry packet\n");
1405 return;
1406 }
1407 ssize_t sent = GNUNET_NETWORK_socket_sendto (udp_sock,
1408 out,
1409 written,
1410 (struct sockaddr*) &sa,
1411 salen);
1412 if (written != sent)
1413 {
1414 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "failed to send retry packet\n");
1415 return;
1416 }
1417
1418 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sent %zd bytes\n", sent);
1419 continue;
1420 }
1421
1422 if (GNUNET_OK != validate_token (quic_header.token, quic_header.token_len,
1423 &sa, salen,
1424 quic_header.odcid,
1425 &quic_header.odcid_len))
1426 {
1428 "invalid address validation token created\n");
1429 return;
1430 }
1431 peer->conn = create_conn (quic_header.dcid, quic_header.dcid_len,
1432 quic_header.odcid, quic_header.odcid_len,
1433 local_addr, in_len,
1434 &sa, salen);
1435 if (NULL == peer->conn)
1436 {
1438 "failed to create quic connection with peer\n");
1439 return;
1440 }
1441 } // null connection
1442
1443 quiche_recv_info recv_info = {
1444 (struct sockaddr *) &sa,
1445 salen,
1446
1447 local_addr,
1448 in_len,
1449 };
1453 if (quiche_conn_is_established (peer->conn->conn) && ! peer->id_sent &&
1454 peer->is_receiver)
1455 {
1456 const struct GNUNET_PeerIdentity *my_identity;
1457 ssize_t send_len;
1458 uint64_t err_code;
1459
1461 "handshake established with peer, sending our peer id\n");
1462
1465
1466 send_len = quiche_conn_stream_send (peer->conn->conn, STREAMID_BI,
1467 (const uint8_t *) my_identity,
1468 sizeof(*my_identity),
1469 false, &err_code);
1470 if (0 > send_len)
1471 {
1473 "failed to write peer identity packet. quiche error: %"
1474 PRIu64 "; len=%zd\n",
1475 err_code,
1476 send_len);
1477 return;
1478 }
1479 flush_egress (peer->conn);
1480 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "peer identity sent to peer\n");
1481 peer->id_sent = GNUNET_YES;
1482 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "setting up peer mq\n");
1483 setup_peer_mq (peer);
1487 }
1488 process_pkt = quiche_conn_recv (peer->conn->conn, buf, rcvd, &recv_info);
1489 if (0 > process_pkt)
1490 {
1492 "quiche failed to process received packet: %zd\n",
1493 process_pkt);
1494 return;
1495 }
1497 "quiche processed %zd bytes\n", process_pkt);
1498 // Check for data on all available streams if the connection is established
1499 if (GNUNET_YES == quiche_conn_is_established (peer->conn->conn))
1500 {
1501 recv_from_streams (peer);
1502 }
1509 quiche_stats stats;
1510 quiche_path_stats path_stats;
1511
1512 flush_egress (peer->conn);
1513
1514 if (quiche_conn_is_closed (peer->conn->conn))
1515 {
1516 quiche_conn_stats (peer->conn->conn, &stats);
1517 quiche_conn_path_stats (peer->conn->conn, 0, &path_stats);
1518
1520 "connection closed. quiche stats: sent=%zu, recv=%zu\n",
1521 stats.sent, stats.recv);
1522 peer_destroy (peer);
1523 }
1524 }
1526}
1527
1528
1537static void
1538run (void *cls,
1539 char *const *args,
1540 const char *cfgfile,
1541 const struct GNUNET_CONFIGURATION_Handle *c)
1542{
1543 char *bindto;
1544 struct sockaddr *in;
1545 socklen_t in_len;
1546 struct sockaddr_storage in_sto;
1547 socklen_t sto_len;
1548
1549 (void) cls;
1550 cfg = c;
1551
1552 if (GNUNET_OK !=
1555 "BINDTO",
1556 &bindto))
1557 {
1560 "BINDTO");
1561 return;
1562 }
1563
1564 in = udp_address_to_sockaddr (bindto, &in_len);
1565
1566 if (NULL == in)
1567 {
1569 "Failed to setup UDP socket address with path `%s'\n",
1570 bindto);
1571 GNUNET_free (bindto);
1572 return;
1573 }
1574 udp_sock =
1575 GNUNET_NETWORK_socket_create (in->sa_family,
1576 SOCK_DGRAM,
1577 IPPROTO_UDP);
1578 if (NULL == udp_sock)
1579 {
1581 GNUNET_free (in);
1582 GNUNET_free (bindto);
1583 return;
1584 }
1585 if (AF_INET6 == in->sa_family)
1587 if (GNUNET_OK !=
1589 in,
1590 in_len))
1591 {
1593 "bind",
1594 bindto);
1596 udp_sock = NULL;
1597 GNUNET_free (in);
1598 GNUNET_free (bindto);
1599 return;
1600 }
1601 sto_len = sizeof(in_sto);
1602 if (0 != getsockname (GNUNET_NETWORK_get_fd (udp_sock),
1603 (struct sockaddr *) &in_sto,
1604 &sto_len))
1605 {
1606 memcpy (&in_sto, in, in_len);
1607 sto_len = in_len;
1608 }
1609 GNUNET_free (in);
1610 GNUNET_free (bindto);
1611 in = (struct sockaddr *) &in_sto;
1612 in_len = sto_len;
1614 "transport",
1615 "Bound to `%s'\n",
1616 GNUNET_a2s ((const struct sockaddr *) &in_sto,
1617 sto_len));
1618 switch (in->sa_family)
1619 {
1620 case AF_INET:
1621 my_port = ntohs (((struct sockaddr_in *) in)->sin_port);
1622 break;
1623
1624 case AF_INET6:
1625 my_port = ntohs (((struct sockaddr_in6 *) in)->sin6_port);
1626 break;
1627
1628 default:
1629 GNUNET_break (0);
1630 my_port = 0;
1631 }
1636 config = quiche_config_new (QUICHE_PROTOCOL_VERSION);
1637 quiche_config_verify_peer (config, false);
1641 quiche_config_load_cert_chain_from_pem_file (config, "./cert.crt");
1642 quiche_config_load_priv_key_from_pem_file (config, "./cert.key");
1643 quiche_config_set_application_protos (config,
1644 (uint8_t *)
1645 "\x0ahq-interop\x05hq-29\x05hq-28\x05hq-27\x08http/0.9",
1646 38);
1647 quiche_config_set_max_idle_timeout (config, 5000);
1648 quiche_config_set_max_recv_udp_payload_size (config, 1200);
1649 quiche_config_set_max_send_udp_payload_size (config, 1200);
1650 quiche_config_set_initial_max_data (config, 10000000);
1651 quiche_config_set_initial_max_stream_data_bidi_local (config, 1000000);
1652 quiche_config_set_initial_max_stream_data_bidi_remote (config, 1000000);
1653 quiche_config_set_initial_max_stream_data_uni (config, 1000000);
1654 quiche_config_set_initial_max_streams_bidi (config, 100);
1655 quiche_config_set_initial_max_streams_uni (config, 100);
1656 quiche_config_set_cc_algorithm (config, QUICHE_CC_RENO);
1657 quiche_config_set_disable_active_migration (config, true);
1662 pils = GNUNET_PILS_connect (cfg, NULL, NULL);
1663 if (NULL == pils)
1664 {
1665 GNUNET_log (
1667 _ (
1668 "Transport service is lacking PILS connection. Exiting.\n"));
1670 return;
1671 }
1672
1673 /* start reading */
1675 udp_sock,
1676 &sock_read,
1677 NULL);
1682 &mq_init,
1683 NULL,
1684 &notify_cb,
1685 NULL,
1686 NULL);
1690 IPPROTO_UDP,
1691 1 /* one address */,
1692 (const struct sockaddr **) &in,
1693 &in_len,
1696 NULL /* closure */);
1697 if (NULL == ch)
1698 {
1699 GNUNET_break (0);
1701 return;
1702 }
1704 if (NULL == ah)
1705 {
1706 GNUNET_break (0);
1708 return;
1709 }
1710
1711 /* start broadcasting */
1712 // if (GNUNET_YES !=
1713 // GNUNET_CONFIGURATION_get_value_yesno (cfg,
1714 // COMMUNICATOR_CONFIG_SECTION,
1715 // "DISABLE_BROADCAST"))
1716 // {
1717 // broadcast_task = GNUNET_SCHEDULER_add_now (&do_broadcast, NULL);
1718 // }
1719}
1720
1721
1722int
1723main (int argc, char *const *argv)
1724{
1725 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
1727 };
1728 int ret;
1729
1731 "transport",
1732 "Starting quic communicator\n");
1734 argc,
1735 argv,
1736 "gnunet-communicator-quic",
1737 _ ("GNUnet QUIC communicator"),
1738 options,
1739 &run,
1740 NULL))
1741 ? 0
1742 : 1;
1743 return ret;
1744}
struct GNUNET_GETOPT_CommandLineOption options[]
Definition 002.c:5
struct GNUNET_MessageHeader * msg
Definition 005.c:2
int main()
Program to simulate results from GCP_get_desirability_of_path() for various plausible inputs.
static int start
Set if we are to start default services (including ARM).
Definition gnunet-arm.c:38
static int ret
Final status code.
Definition gnunet-arm.c:93
static int do_shutdown
Set to GNUNET_YES if we are shutting down.
static uint16_t port
Port number.
Definition gnunet-bcd.c:146
static char * peer_id
Option –peer.
static void mq_destroy_d(struct GNUNET_MQ_Handle *mq, void *impl_state)
Signature of functions implementing the destruction of a message queue.
#define COMMUNICATOR_ADDRESS_PREFIX
static void notify_cb(void *cls, const struct GNUNET_PeerIdentity *sender, const struct GNUNET_MessageHeader *msg)
Function called when the transport service has received a backchannel message for this communicator (...
#define ADDRESS_VALIDITY_PERIOD
How long do we believe our addresses to remain up (before the other peer should revalidate).
#define MAX_TOKEN_LEN
static enum GNUNET_GenericReturnValue validate_token(const uint8_t *token, size_t token_len, struct sockaddr_storage *addr, socklen_t addr_len, uint8_t *odcid, size_t *odcid_len)
static void try_connection_reversal(void *cls, const struct sockaddr *addr, socklen_t addrlen)
static struct GNUNET_NT_InterfaceScanner * is
Network scanner to determine network types.
static struct GNUNET_STATISTICS_Handle * stats
For logging statistics.
static const struct GNUNET_CONFIGURATION_Handle * cfg
Handle to the config.
static int mq_init(void *cls, const struct GNUNET_PeerIdentity *peer_id, const char *address)
Function called by the transport service to initialize a message queue given address information abou...
static void mint_token(const uint8_t *dcid, size_t dcid_len, struct sockaddr_storage *addr, socklen_t addr_len, uint8_t *token, size_t *token_len)
FIXME: review token generation, assure tokens are generated properly.
#define LOCAL_CONN_ID_LEN
static void flush_egress(struct quic_conn *conn)
static struct GNUNET_NETWORK_Handle * udp_sock
FIXME undocumented.
static void peer_destroy(struct PeerAddress *peer)
Destroys a receiving state due to timeout or shutdown.
static void mq_send_d(struct GNUNET_MQ_Handle *mq, const struct GNUNET_MessageHeader *msg, void *impl_state)
Signature of functions implementing the sending functionality of a message queue.
static void sock_read(void *cls)
#define COMMUNICATOR_CONFIG_SECTION
static void nat_address_cb(void *cls, void **app_ctx, int add_remove, enum GNUNET_NAT_AddressClass ac, const struct sockaddr *addr, socklen_t addrlen)
Signature of the callback passed to GNUNET_NAT_register() for a function to call whenever our set of ...
static struct GNUNET_TRANSPORT_CommunicatorHandle * ch
FIXME undocumented.
static void reschedule_peer_timeout(struct PeerAddress *peer)
Increment receiver timeout due to activity.
static quiche_config * config
FIXME undocumented.
static struct sockaddr * udp_address_to_sockaddr(const char *bindto, socklen_t *sock_len)
Convert UDP bind specification to a struct sockaddr *
struct GNUNET_CONTAINER_MultiHashMap * conn_map
Map of DCID (uint8_t) -> quic_conn for quickly retrieving connections to other peers.
static void run(void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c)
Setup communicator and launch network interactions.
static struct GNUNET_NAT_Handle * nat
Connection to NAT service.
struct GNUNET_CONTAINER_MultiHashMap * addr_map
Map of sockaddr -> struct PeerAddress.
static struct GNUNET_SCHEDULER_Task * read_task
FIXME undocumented.
static int get_peer_delete_it(void *cls, const struct GNUNET_HashCode *key, void *value)
Iterator over all peers to clean up.
static void mq_cancel(struct GNUNET_MQ_Handle *mq, void *impl_state)
Implementation function that cancels the currently sent message.
static struct GNUNET_TRANSPORT_ApplicationHandle * ah
FIXME undocumented.
static int have_v6_socket
FIXME undocumented.
#define STREAMID_BI
static uint16_t my_port
FIXME undocumented.
static char * sockaddr_to_udpaddr_string(const struct sockaddr *address, socklen_t address_len)
Taken from: UDP communicator Converts address to the address string format used by this communicator ...
#define MAX_DATAGRAM_SIZE
static void recv_from_streams(struct PeerAddress *peer)
Given a PeerAddress, receive data from streams after doing connection logic.
static struct GNUNET_SCHEDULER_Task * timeout_task
ID of timeout task.
static void setup_peer_mq(struct PeerAddress *peer)
Setup the MQ for the peer.
static void mq_error(void *cls, enum GNUNET_MQ_Error error)
Generic error handler, called with the appropriate error code and the same closure specified at the c...
static struct quic_conn * create_conn(uint8_t *scid, size_t scid_len, uint8_t *odcid, size_t odcid_len, struct sockaddr *local_addr, socklen_t local_addr_len, struct sockaddr_storage *peer_addr, socklen_t peer_addr_len)
struct GNUNET_PILS_Handle * pils
Handle to PILS service.
static struct GNUNET_TRANSPORT_AddressIdentifier * ai
Handle to the operation that publishes our address.
static char * address
GNS address for this phone.
struct GNUNET_HashCode key
The key used in the DHT.
static struct in_addr dummy
Target "dummy" address of the packet we pretend to respond to.
static char * value
Value of the record to add/remove.
static struct GNUNET_NAT_AUTO_Test * nt
Handle to a NAT test operation.
static char * local_addr
Local address to use for connection reversal request.
Definition gnunet-nat.c:65
static struct GNUNET_PeerIdentity my_identity
Identity of this peer.
static struct GNUNET_PeerIdentity pid
Identity of the peer we transmit to / connect to.
commonly used definitions; globals in this file are exempt from the rule that the module name ("commo...
struct GNUNET_PILS_Handle * GNUNET_PILS_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_PILS_PidChangeCallback pid_change_cb, void *cls)
Connect to the PILS service.
Definition pils_api.c:465
void GNUNET_PILS_disconnect(struct GNUNET_PILS_Handle *handle)
Disconnect from the PILS service.
Definition pils_api.c:488
const struct GNUNET_PeerIdentity * GNUNET_PILS_get_identity(const struct GNUNET_PILS_Handle *handle)
Return the current peer identity of a given handle.
Definition pils_api.c:727
API to create, modify and access statistics.
Bandwidth allocation API for applications to interact with.
API of the transport service towards the communicator processes.
void GNUNET_TRANSPORT_communicator_address_remove(struct GNUNET_TRANSPORT_AddressIdentifier *ai)
Notify transport service about an address that this communicator no longer provides for this peer.
int GNUNET_TRANSPORT_communicator_receive(struct GNUNET_TRANSPORT_CommunicatorHandle *handle, const struct GNUNET_PeerIdentity *sender, const struct GNUNET_MessageHeader *msg, struct GNUNET_TIME_Relative expected_addr_validity, GNUNET_TRANSPORT_MessageCompletedCallback cb, void *cb_cls)
Notify transport service that the communicator has received a message.
void GNUNET_TRANSPORT_communicator_mq_del(struct GNUNET_TRANSPORT_QueueHandle *qh)
Notify transport service that an MQ became unavailable due to a disconnect or timeout.
void GNUNET_TRANSPORT_application_done(struct GNUNET_TRANSPORT_ApplicationHandle *ch)
Shutdown TRANSPORT application client.
#define GNUNET_TRANSPORT_QUEUE_LENGTH_UNLIMITED
Queue length.
struct GNUNET_TRANSPORT_QueueHandle * GNUNET_TRANSPORT_communicator_mq_add(struct GNUNET_TRANSPORT_CommunicatorHandle *ch, const struct GNUNET_PeerIdentity *peer, const char *address, uint32_t mtu, uint64_t q_len, uint32_t priority, enum GNUNET_NetworkType nt, enum GNUNET_TRANSPORT_ConnectionStatus cs, struct GNUNET_MQ_Handle *mq)
Notify transport service that a MQ became available due to an "inbound" connection or because the com...
void GNUNET_TRANSPORT_communicator_disconnect(struct GNUNET_TRANSPORT_CommunicatorHandle *ch)
Disconnect from the transport service.
struct GNUNET_TRANSPORT_ApplicationHandle * GNUNET_TRANSPORT_application_init(const struct GNUNET_CONFIGURATION_Handle *cfg)
Initialize the TRANSPORT application client handle.
struct GNUNET_TRANSPORT_CommunicatorHandle * GNUNET_TRANSPORT_communicator_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *config_section_name, const char *addr_prefix, enum GNUNET_TRANSPORT_CommunicatorCharacteristics cc, GNUNET_TRANSPORT_CommunicatorMqInit mq_init, void *mq_init_cls, GNUNET_TRANSPORT_CommunicatorNotify notify_cb, void *notify_cb_cls, GNUNET_TRANSPORT_StartBurstNotify sb)
Connect to the transport service.
struct GNUNET_TRANSPORT_AddressIdentifier * GNUNET_TRANSPORT_communicator_address_add(struct GNUNET_TRANSPORT_CommunicatorHandle *ch, const char *address, enum GNUNET_NetworkType nt, struct GNUNET_TIME_Relative expiration)
Notify transport service about an address that this communicator provides for this peer.
@ GNUNET_TRANSPORT_CC_RELIABLE
Transmission is reliabile (with ACKs), e.g.
@ GNUNET_TRANSPORT_CS_OUTBOUND
this is an outbound connection (transport initiated)
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
#define GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT
After how long do we consider a connection to a peer dead if we don't receive messages from the peer?
void GNUNET_CRYPTO_random_block(void *buffer, size_t length)
Fill block with a random values.
#define GNUNET_GETOPT_OPTION_END
Marker for the end of the list of options.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition crypto_hash.c:40
int GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_MultiHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
void * GNUNET_CONTAINER_multihashmap_get(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Given a key find a value in the map matching the key.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_remove(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, const void *value)
Remove the given key-value pair from the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
unsigned int GNUNET_CONTAINER_multihashmap_size(const struct GNUNET_CONTAINER_MultiHashMap *map)
Get the number of key-value pairs in the map.
void GNUNET_CONTAINER_multihashmap_destroy(struct GNUNET_CONTAINER_MultiHashMap *map)
Destroy a hash map.
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY
There must only be one value per key; storing a value should fail if a value under the same key alrea...
#define GNUNET_log(kind,...)
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
GNUNET_GenericReturnValue
Named constants for return values.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
const char * GNUNET_a2s(const struct sockaddr *addr, socklen_t addrlen)
Convert a "struct sockaddr*" (IPv4 or IPv6 address) to a string (for printing debug messages).
void GNUNET_log_config_missing(enum GNUNET_ErrorType kind, const char *section, const char *option)
Log error message about missing configuration option.
#define GNUNET_log_strerror(level, cmd)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
void GNUNET_log_from_nocheck(enum GNUNET_ErrorType kind, const char *comp, const char *message,...) __attribute__((format(printf
Log function that specifies an alternative component.
#define GNUNET_log_strerror_file(level, cmd, filename)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
#define GNUNET_memdup(buf, size)
Allocate and initialize a block of memory.
GNUNET_MQ_Error
Error codes for the queue.
struct GNUNET_MQ_Handle * GNUNET_MQ_queue_for_callbacks(GNUNET_MQ_SendImpl send, GNUNET_MQ_DestroyImpl destroy, GNUNET_MQ_CancelImpl cancel, void *impl_state, const struct GNUNET_MQ_MessageHandler *handlers, GNUNET_MQ_ErrorHandler error_handler, void *cls)
Create a message queue for the specified handlers.
Definition mq.c:482
void GNUNET_MQ_impl_send_continue(struct GNUNET_MQ_Handle *mq)
Call the send implementation for the next queued message, if any.
Definition mq.c:437
struct GNUNET_NAT_Handle * GNUNET_NAT_register(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *config_section, uint8_t proto, unsigned int num_addrs, const struct sockaddr **addrs, const socklen_t *addrlens, GNUNET_NAT_AddressCallback address_callback, GNUNET_NAT_ReversalCallback reversal_callback, void *callback_cls)
Attempt to enable port redirection and detect public IP address contacting UPnP or NAT-PMP routers on...
Definition nat_api.c:366
GNUNET_NAT_AddressClass
Some addresses contain sensitive information or are not suitable for global distribution.
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition network.c:508
int GNUNET_NETWORK_get_fd(const struct GNUNET_NETWORK_Handle *desc)
Return file descriptor for this network handle.
Definition network.c:1000
ssize_t GNUNET_NETWORK_socket_recvfrom(const struct GNUNET_NETWORK_Handle *desc, void *buffer, size_t length, struct sockaddr *src_addr, socklen_t *addrlen)
Read data from a socket (always non-blocking).
Definition network.c:687
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_create(int domain, int type, int protocol)
Create a new socket.
Definition network.c:832
enum GNUNET_GenericReturnValue GNUNET_NETWORK_test_pf(int pf)
Test if the given protocol family is supported by this system.
Definition network.c:79
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_bind(struct GNUNET_NETWORK_Handle *desc, const struct sockaddr *address, socklen_t address_len)
Bind a socket to a particular address.
Definition network.c:439
ssize_t GNUNET_NETWORK_socket_sendto(const struct GNUNET_NETWORK_Handle *desc, const void *message, size_t length, const struct sockaddr *dest_addr, socklen_t dest_len)
Send data to a particular destination (always non-blocking).
Definition network.c:771
GNUNET_NetworkType
Types of networks (with separate quotas) we support.
struct GNUNET_NT_InterfaceScanner * GNUNET_NT_scanner_init(void)
Initialize the address characterization client handle.
Definition nt.c:407
enum GNUNET_NetworkType GNUNET_NT_scanner_get_type(struct GNUNET_NT_InterfaceScanner *is, const struct sockaddr *addr, socklen_t addrlen)
Returns where the address is located: loopback, LAN or WAN.
Definition nt.c:309
const struct GNUNET_OS_ProjectData * GNUNET_OS_project_data_gnunet(void)
Return default project data used by 'libgnunetutil' for GNUnet.
enum GNUNET_GenericReturnValue GNUNET_PROGRAM_run(const struct GNUNET_OS_ProjectData *pd, int argc, char *const *argv, const char *binaryName, const char *binaryHelp, const struct GNUNET_GETOPT_CommandLineOption *options, GNUNET_PROGRAM_Main task, void *task_cls)
Run a standard GNUnet command startup sequence (initialize loggers and configuration,...
Definition program.c:406
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition scheduler.c:572
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_net(struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition scheduler.c:1517
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received,...
Definition scheduler.c:1345
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition scheduler.c:986
void GNUNET_STATISTICS_set(struct GNUNET_STATISTICS_Handle *handle, const char *name, uint64_t value, int make_persistent)
Set statistic value for the peer.
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition time.c:316
#define _(String)
GNU gettext support macro.
Definition platform.h:179
static struct GNUNET_MQ_Handle * mq
Our connection to the resolver service, created on-demand, but then persists until error or shutdown.
Internal representation of the hash map.
Definition of a command line option.
A 512-bit hashcode.
Handle to a message queue.
Definition mq.c:87
Header for all communications.
Handle for active NAT registrations.
Definition nat_api.c:72
handle to a socket
Definition network.c:53
Handle to the interface scanner.
Definition nt.c:104
A handle for the PILS service.
Definition pils_api.c:82
The identity of the host (wraps the signing key of the peer).
Entry in list of pending tasks.
Definition scheduler.c:141
Handle for the service.
Time for absolute times used by GNUnet, in microseconds.
Internal representation of an address a communicator is currently providing for the transport service...
Handle to the TRANSPORT subsystem for application management.
Opaque handle to the transport service for communicators.
Handle returned to identify the internal data structure the transport API has created to manage a mes...
Standard IPv4 header.
Standard IPv6 header.
UDP packet header.
Information we track per peer we have recently been in contact with.
int id_rcvd
Flag to indicate whether we know the PeerIdentity (target) yet.
struct GNUNET_PeerIdentity target
To whom are we talking to.
struct GNUNET_TRANSPORT_QueueHandle * d_qh
handle for default queue with the ch.
struct sockaddr * address
Address of the other peer.
size_t d_mtu
MTU we allowed transport for this peer's default queue.
enum GNUNET_NetworkType nt
Which network type does this queue use?
struct GNUNET_TIME_Absolute timeout
Timeout for this peer address.
struct quic_conn * conn
The QUIC connection associated with this peer.
struct GNUNET_MQ_Handle * d_mq
Default message queue we are providing for the ch.
int id_sent
Flag to indicate whether we have sent OUR PeerIdentity to this peer.
char * foreign_addr
Address of the receiver in the human-readable format with the COMMUNICATOR_ADDRESS_PREFIX.
int peer_destroy_called
receiver_destroy already called on receiver.
socklen_t address_len
Length of the address.
int is_receiver
Flag to indicate if we are the initiator of the connection.
QUIC_header is used to store information received from an incoming QUIC packet.
uint8_t scid[QUICHE_MAX_CONN_ID_LEN]
uint8_t dcid[QUICHE_MAX_CONN_ID_LEN]
uint8_t token[sizeof("quiche") - 1+sizeof(struct sockaddr_storage)+QUICHE_MAX_CONN_ID_LEN]
uint8_t odcid[QUICHE_MAX_CONN_ID_LEN]
QUIC connection object.