GNUnet 0.21.1
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 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 "gnunet_common.h"
38#include "gnunet_util_lib.h"
39#include "gnunet_core_service.h"
40#include "quiche.h"
41#include "platform.h"
42#include "gnunet_protocols.h"
43#include "gnunet_signatures.h"
44#include "gnunet_constants.h"
48#include "gnunet_nat_service.h"
49#include "stdint.h"
50#include "inttypes.h"
51
52#define COMMUNICATOR_CONFIG_SECTION "communicator-quic"
53#define COMMUNICATOR_ADDRESS_PREFIX "quic"
54#define MAX_DATAGRAM_SIZE 1350
55
56
57/* FIXME: Review all static lengths/contents below. Maybe this can be done smarter */
58/* Currently equivalent to QUICHE_MAX_CONN_ID_LEN */
59#define LOCAL_CONN_ID_LEN 20
60#define MAX_TOKEN_LEN \
61 sizeof("quiche") - 1 \
62 + sizeof(struct sockaddr_storage) \
63 + QUICHE_MAX_CONN_ID_LEN
64#define CID_LEN sizeof(uint8_t) * QUICHE_MAX_CONN_ID_LEN
65#define TOKEN_LEN sizeof (uint8_t) * MAX_TOKEN_LEN
66
67
68/* FIXME: Why 4?
69 Generic, bidirectional, client-initiated quic stream id */
70#define STREAMID_BI 4
71
76#define ADDRESS_VALIDITY_PERIOD GNUNET_TIME_UNIT_HOURS
77
82
87
91static const struct GNUNET_CONFIGURATION_Handle *cfg;
92
97
102
107
112
117
121static int have_v6_socket;
122
126static uint16_t my_port;
127
131static unsigned long long rekey_max_bytes;
132
136static quiche_config *config = NULL;
137
142
147
151static struct GNUNET_NAT_Handle *nat;
152
162{
167
172
177
182
188
192 struct sockaddr *address;
193
197 socklen_t address_len;
198
203
208
213
218
223 size_t d_mtu;
224
229
234
239 // struct GNUNET_CONTAINER_HeapNode *hn;
240};
241
242// /**
243// * FIXME: Implementation missing
244// * Expiration heap for peers (contains `struct PeerAddress`)
245// */
246// static struct GNUNET_CONTAINER_Heap *peers_heap;
247
252
257
262
269{
271
272 quiche_conn *conn;
273};
274
279{
280 uint8_t type;
281 uint32_t version;
282
283 uint8_t scid[QUICHE_MAX_CONN_ID_LEN];
284 size_t scid_len;
285
286 uint8_t dcid[QUICHE_MAX_CONN_ID_LEN];
287 size_t dcid_len;
288
289 uint8_t odcid[QUICHE_MAX_CONN_ID_LEN];
290 size_t odcid_len;
291
293 size_t token_len;
294};
295
296
301static void
303{
304 char stream_buf[UINT16_MAX];
305 size_t buf_size = UINT16_MAX;
306 char *buf_ptr = stream_buf;
307 struct GNUNET_MessageHeader *hdr;
308
309 uint64_t s = 0;
310 quiche_stream_iter *readable;
311 bool fin;
312 ssize_t recv_len;
313
314 readable = quiche_conn_readable (peer->conn->conn);
315 while (quiche_stream_iter_next (readable, &s))
316 {
317 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "stream %" PRIu64 " is readable\n",
318 s);
319 fin = false;
320 recv_len = quiche_conn_stream_recv (peer->conn->conn, s,
321 (uint8_t *) stream_buf, buf_size,
322 &fin);
323 if (recv_len < 0)
324 {
326 "error while receiving data from stream %" PRIu64 "\n", s);
327 break;
328 }
335 if (! peer->is_receiver && GNUNET_NO == peer->id_rcvd)
336 {
337 if (recv_len < sizeof(struct GNUNET_PeerIdentity))
338 {
340 "message recv len of %zd less than length of peer identity\n",
341 recv_len);
342 return;
343 }
345 "received peer identity\n");
346 struct GNUNET_PeerIdentity *pid = (struct
347 GNUNET_PeerIdentity *) stream_buf;
348 peer->target = *pid;
349 peer->id_rcvd = GNUNET_YES;
350 buf_ptr += sizeof(struct GNUNET_PeerIdentity);
351 recv_len -= sizeof(struct GNUNET_PeerIdentity);
352 }
356 while (recv_len >= sizeof(struct GNUNET_MessageHeader))
357 {
358 hdr = (struct GNUNET_MessageHeader *) buf_ptr;
359 if (ntohs (hdr->size) > recv_len)
360 {
362 "message size stated (%d) is greater than length of rcvd data (%zd)!\n",
363 ntohs (hdr->size), recv_len);
364 return;
365 }
366 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "passing %zd bytes to core\n",
367 recv_len);
370 NULL);
371 recv_len -= ntohs (hdr->size);
372 buf_ptr += ntohs (hdr->size);
373 }
377 if (0 != recv_len)
378 {
380 "message recv len of %zd less than length of message header\n",
381 recv_len);
382 }
387 if (fin)
388 {
390 "fin received, closing connection\n");
391 if (0 > quiche_conn_close (peer->conn->conn, true, 0, NULL, 0))
392 {
394 "quiche failed to close connection to peer\n");
395 }
396 }
397 }
398 quiche_stream_iter_free (readable);
399}
400
401
405static void
406mint_token (const uint8_t *dcid, size_t dcid_len,
407 struct sockaddr_storage *addr, socklen_t addr_len,
408 uint8_t *token, size_t *token_len)
409{
410 GNUNET_memcpy (token, "quiche", sizeof("quiche") - 1);
411 GNUNET_memcpy (token + sizeof("quiche") - 1, addr, addr_len);
412 GNUNET_memcpy (token + sizeof("quiche") - 1 + addr_len, dcid, dcid_len);
413
414 *token_len = sizeof("quiche") - 1 + addr_len + dcid_len;
415}
416
417
419validate_token (const uint8_t *token, size_t token_len,
420 struct sockaddr_storage *addr, socklen_t addr_len,
421 uint8_t *odcid, size_t *odcid_len)
422{
423 if ((token_len < sizeof("quiche") - 1) ||
424 memcmp (token, "quiche", sizeof("quiche") - 1))
425 {
426 return GNUNET_NO;
427 }
428
429 token += sizeof("quiche") - 1;
430 token_len -= sizeof("quiche") - 1;
431
432 if ((token_len < addr_len) || memcmp (token, addr, addr_len))
433 {
434 return GNUNET_NO;
435 }
436
437 token += addr_len;
438 token_len -= addr_len;
439
440 if (*odcid_len < token_len)
441 {
442 return GNUNET_NO;
443 }
444
445 memcpy (odcid, token, token_len);
446 *odcid_len = token_len;
447
448 return GNUNET_OK;
449}
450
451
452static struct quic_conn*
453create_conn (uint8_t *scid, size_t scid_len,
454 uint8_t *odcid, size_t odcid_len,
455 struct sockaddr *local_addr,
456 socklen_t local_addr_len,
457 struct sockaddr_storage *peer_addr,
458 socklen_t peer_addr_len)
459{
460 struct quic_conn *conn;
461 quiche_conn *q_conn;
462 conn = GNUNET_new (struct quic_conn);
463 if (scid_len != LOCAL_CONN_ID_LEN)
464 {
466 "error while creating connection, scid length too short: %zu\n",
467 scid_len);
468 return NULL;
469 }
470
472 q_conn = quiche_accept (conn->cid, LOCAL_CONN_ID_LEN,
473 odcid, odcid_len,
475 local_addr_len,
476 (struct sockaddr *) peer_addr,
477 peer_addr_len,
478 config);
479 if (NULL == q_conn)
480 {
482 "quiche failed to create connection after call to quiche_accept\n");
483 return NULL;
484 }
485 conn->conn = q_conn;
486 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "new quic connection created\n");
487 return conn;
488}
489
490
491static void
493{
494 static uint8_t out[MAX_DATAGRAM_SIZE];
495 quiche_send_info send_info;
496
497 ssize_t written;
498 ssize_t sent;
499
500 while (1)
501 {
502 written = quiche_conn_send (conn->conn, out, sizeof(out), &send_info);
503 if (QUICHE_ERR_DONE == written)
504 {
505 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "done writing quic packets\n");
506 break;
507 }
508 if (0 > written)
509 {
511 "quiche failed to create packet. quiche error: %zd\n",
512 written);
513 return;
514 }
515 sent = GNUNET_NETWORK_socket_sendto (udp_sock, out, written,
516 (struct sockaddr *) &send_info.to,
517 send_info.to_len);
518 if (sent != written)
519 {
521 "quiche failed to send data to peer\n");
522 return;
523 }
524 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sent %zd bytes\n", sent);
525 }
526}
527
528
534static void
536{
537 peer->timeout =
539 // GNUNET_CONTAINER_heap_update_cost (peer->hn,
540 // peer->timeout.abs_value_us);
541}
542
543
549static void
551{
552 struct GNUNET_HashCode addr_key;
553
556 "Disconnecting peer for peer `%s'\n",
557 GNUNET_i2s (&peer->target));
558 if (NULL != peer->d_qh)
559 {
561 peer->d_qh = NULL;
562 }
563 // GNUNET_assert (peer == GNUNET_CONTAINER_heap_remove_node (peer->hn));
567 GNUNET_CRYPTO_hash (peer->address, peer->address_len, &addr_key);
569 peer))
570 {
572 "tried to remove non-existent peer from addr map\n");
573 return;
574 }
576 "# peers active",
578 GNUNET_NO);
579 quiche_conn_free (peer->conn->conn);
580 GNUNET_free (peer->address);
582 GNUNET_free (peer->conn);
583 GNUNET_free (peer);
584}
585
586
595static int
597 const struct GNUNET_HashCode *key,
598 void *value)
599{
600 struct PeerAddress *peer = value;
601 (void) cls;
602 (void) key;
603 peer_destroy (peer);
604 return GNUNET_OK;
605}
606
607
616static void
618 const struct GNUNET_MessageHeader *msg,
619 void *impl_state)
620{
621 struct PeerAddress *peer = impl_state;
622 uint16_t msize = ntohs (msg->size);
623 ssize_t send_len;
624
625 if (NULL == peer->conn->conn)
626 {
628 "peer never established quic connection\n");
629 return;
630 }
631
632 GNUNET_assert (mq == peer->d_mq);
633 if (msize > peer->d_mtu)
634 {
636 "msize: %u, mtu: %lu\n",
637 msize,
638 peer->d_mtu);
639 GNUNET_break (0);
640 if (GNUNET_YES != peer->peer_destroy_called)
641 {
643 "peer destroy called, destroying peer\n");
644 peer_destroy (peer);
645 }
646 return;
647 }
649
650 send_len = quiche_conn_stream_send (peer->conn->conn, 4, (uint8_t *) msg,
651 msize, false);
652 if (send_len != msize)
653 {
655 "tried to send message and quiche returned %zd", send_len);
656 return;
657 }
658 flush_egress (peer->conn);
660 "sent a message of %zd bytes\n", send_len);
662}
663
664
673static void
674mq_destroy_d (struct GNUNET_MQ_Handle *mq, void *impl_state)
675{
676 struct PeerAddress *peer = impl_state;
678 "Default MQ destroyed\n");
679 if (mq == peer->d_mq)
680 {
681 peer->d_mq = NULL;
682 if (GNUNET_YES != peer->peer_destroy_called)
683 peer_destroy (peer);
684 }
685}
686
687
694static void
695mq_cancel (struct GNUNET_MQ_Handle *mq, void *impl_state)
696{
697 /* Cancellation is impossible with QUIC; bail */
698 GNUNET_assert (0);
699}
700
701
711static void
712mq_error (void *cls, enum GNUNET_MQ_Error error)
713{
714 struct PeerAddress *peer = cls;
715
717 "MQ error in queue to %s: %d\n",
718 GNUNET_i2s (&peer->target),
719 (int) error);
720 peer_destroy (peer);
721}
722
723
731static struct sockaddr *
732udp_address_to_sockaddr (const char *bindto, socklen_t *sock_len)
733{
734 struct sockaddr *in;
735 unsigned int port;
736 char dummy[2];
737 char *colon;
738 char *cp;
739
740 if (1 == sscanf (bindto, "%u%1s", &port, dummy))
741 {
742 /* interpreting value as just a PORT number */
743 if (port > UINT16_MAX)
744 {
746 "BINDTO specification `%s' invalid: value too large for port\n",
747 bindto);
748 return NULL;
749 }
750 if ((GNUNET_NO == GNUNET_NETWORK_test_pf (PF_INET6)) ||
751 (GNUNET_YES ==
754 "DISABLE_V6")))
755 {
756 struct sockaddr_in *i4;
757
758 i4 = GNUNET_malloc (sizeof(struct sockaddr_in));
759 i4->sin_family = AF_INET;
760 i4->sin_port = htons ((uint16_t) port);
761 *sock_len = sizeof(struct sockaddr_in);
762 in = (struct sockaddr *) i4;
763 }
764 else
765 {
766 struct sockaddr_in6 *i6;
767
768 i6 = GNUNET_malloc (sizeof(struct sockaddr_in6));
769 i6->sin6_family = AF_INET6;
770 i6->sin6_port = htons ((uint16_t) port);
771 *sock_len = sizeof(struct sockaddr_in6);
772 in = (struct sockaddr *) i6;
773 }
774 return in;
775 }
776 cp = GNUNET_strdup (bindto);
777 colon = strrchr (cp, ':');
778 if (NULL != colon)
779 {
780 /* interpret value after colon as port */
781 *colon = '\0';
782 colon++;
783 if (1 == sscanf (colon, "%u%1s", &port, dummy))
784 {
785 /* interpreting value as just a PORT number */
786 if (port > UINT16_MAX)
787 {
789 "BINDTO specification `%s' invalid: value too large for port\n",
790 bindto);
791 GNUNET_free (cp);
792 return NULL;
793 }
794 }
795 else
796 {
797 GNUNET_log (
799 "BINDTO specification `%s' invalid: last ':' not followed by number\n",
800 bindto);
801 GNUNET_free (cp);
802 return NULL;
803 }
804 }
805 else
806 {
807 /* interpret missing port as 0, aka pick any free one */
808 port = 0;
809 }
810 {
811 /* try IPv4 */
812 struct sockaddr_in v4;
813
814 memset (&v4, 0, sizeof(v4));
815 if (1 == inet_pton (AF_INET, cp, &v4.sin_addr))
816 {
817 v4.sin_family = AF_INET;
818 v4.sin_port = htons ((uint16_t) port);
819#if HAVE_SOCKADDR_IN_SIN_LEN
820 v4.sin_len = sizeof(struct sockaddr_in);
821#endif
822 in = GNUNET_memdup (&v4, sizeof(struct sockaddr_in));
823 *sock_len = sizeof(struct sockaddr_in);
824 GNUNET_free (cp);
825 return in;
826 }
827 }
828 {
829 /* try IPv6 */
830 struct sockaddr_in6 v6;
831 const char *start;
832
833 memset (&v6, 0, sizeof(v6));
834 start = cp;
835 if (('[' == *cp) && (']' == cp[strlen (cp) - 1]))
836 {
837 start++; /* skip over '[' */
838 cp[strlen (cp) - 1] = '\0'; /* eat ']' */
839 }
840 if (1 == inet_pton (AF_INET6, start, &v6.sin6_addr))
841 {
842 v6.sin6_family = AF_INET6;
843 v6.sin6_port = htons ((uint16_t) port);
844#if HAVE_SOCKADDR_IN_SIN_LEN
845 v6.sin6_len = sizeof(sizeof(struct sockaddr_in6));
846#endif
847 in = GNUNET_memdup (&v6, sizeof(v6));
848 *sock_len = sizeof(v6);
849 GNUNET_free (cp);
850 return in;
851 }
852 }
853 /* #5528 FIXME (feature!): maybe also try getnameinfo()? */
854 GNUNET_free (cp);
855 return NULL;
856}
857
858
866static void
868{
869 size_t base_mtu;
870
871 switch (peer->address->sa_family)
872 {
873 case AF_INET:
874 base_mtu = 1480 /* Ethernet MTU, 1500 - Ethernet header - VLAN tag */
875 - sizeof(struct GNUNET_TUN_IPv4Header) /* 20 */
876 - sizeof(struct GNUNET_TUN_UdpHeader) /* 8 */;
877 break;
878
879 case AF_INET6:
880 base_mtu = 1280 /* Minimum MTU required by IPv6 */
881 - sizeof(struct GNUNET_TUN_IPv6Header) /* 40 */
882 - sizeof(struct GNUNET_TUN_UdpHeader) /* 8 */;
883 break;
884
885 default:
886 GNUNET_assert (0);
887 break;
888 }
889 /* MTU == base_mtu */
890 peer->d_mtu = base_mtu;
891
893 "Setting up MQs and QHs\n");
894 /* => Effective MTU for CORE will range from 1080 (IPv6 + KX) to
895 1404 (IPv4 + Box) bytes, depending on circumstances... */
896
897 if (NULL == peer->d_mq)
900 &mq_cancel,
901 peer,
902 NULL,
903 &mq_error,
904 peer);
905 peer->d_qh =
907 &peer->target,
908 peer->foreign_addr,
909 1000,
911 0, /* Priority */
912 peer->nt,
914 peer->d_mq);
915}
916
917
927static char *
928sockaddr_to_udpaddr_string (const struct sockaddr *address,
929 socklen_t address_len)
930{
931 char *ret;
932
933 switch (address->sa_family)
934 {
935 case AF_INET:
937 "%s-%s",
939 GNUNET_a2s (address, address_len));
940 break;
941
942 case AF_INET6:
944 "%s-%s",
946 GNUNET_a2s (address, address_len));
947 break;
948
949 default:
950 GNUNET_assert (0);
951 }
952 return ret;
953}
954
955
965static void
966notify_cb (void *cls,
967 const struct GNUNET_PeerIdentity *sender,
968 const struct GNUNET_MessageHeader *msg)
969{
970 // const struct UDPAck *ack;
971
972 // (void) cls;
973 // GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
974 // "Storing UDPAck received from backchannel from %s\n",
975 // GNUNET_i2s_full (sender));
976 // if ((ntohs (msg->type) != GNUNET_MESSAGE_TYPE_COMMUNICATOR_UDP_ACK) ||
977 // (ntohs (msg->size) != sizeof(struct UDPAck)))
978 // {
979 // GNUNET_break_op (0);
980 // return;
981 // }
982 // ack = (const struct UDPAck *) msg;
983 // GNUNET_CONTAINER_multipeermap_get_multiple (receivers,
984 // sender,
985 // &handle_ack,
986 // (void *) ack);
987}
988
989
995static void
996check_timeouts (void *cls)
997{
998 // struct GNUNET_TIME_Relative st;
999 // struct GNUNET_TIME_Relative rt;
1000 // struct GNUNET_TIME_Relative delay;
1001 // struct ReceiverAddress *receiver;
1002 // struct SenderAddress *sender;
1003
1004 // (void) cls;
1005 // timeout_task = NULL;
1006 // rt = GNUNET_TIME_UNIT_FOREVER_REL;
1007 // while (NULL != (receiver = GNUNET_CONTAINER_heap_peek (receivers_heap)))
1008 // {
1009 // /* if (GNUNET_YES != receiver->receiver_destroy_called) */
1010 // /* { */
1011 // rt = GNUNET_TIME_absolute_get_remaining (receiver->timeout);
1012 // if (0 != rt.rel_value_us)
1013 // break;
1014 // GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1015 // "Receiver timed out\n");
1016 // receiver_destroy (receiver);
1017 // // }
1018 // }
1019 // st = GNUNET_TIME_UNIT_FOREVER_REL;
1020 // while (NULL != (sender = GNUNET_CONTAINER_heap_peek (senders_heap)))
1021 // {
1022 // if (GNUNET_YES != sender->sender_destroy_called)
1023 // {
1024 // st = GNUNET_TIME_absolute_get_remaining (sender->timeout);
1025 // if (0 != st.rel_value_us)
1026 // break;
1027 // sender_destroy (sender);
1028 // }
1029 // }
1030 // delay = GNUNET_TIME_relative_min (rt, st);
1031 // if (delay.rel_value_us < GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1032 // timeout_task = GNUNET_SCHEDULER_add_delayed (delay, &check_timeouts, NULL);
1033}
1034
1035
1054static int
1055mq_init (void *cls, const struct GNUNET_PeerIdentity *peer_id, const
1056 char *address)
1057{
1058 struct PeerAddress *peer;
1059 const char *path;
1060 struct sockaddr *in;
1061 socklen_t in_len;
1062 struct GNUNET_HashCode addr_key;
1063 uint8_t scid[LOCAL_CONN_ID_LEN];
1064
1065 struct quic_conn *q_conn;
1066 char *bindto;
1067 socklen_t local_in_len;
1068 struct sockaddr *local_addr;
1069
1070 if (GNUNET_OK !=
1073 "BINDTO",
1074 &bindto))
1075 {
1078 "BINDTO");
1079 return GNUNET_SYSERR;
1080 }
1081 local_addr = udp_address_to_sockaddr (bindto, &local_in_len);
1082
1083 if (0 != strncmp (address,
1085 strlen (COMMUNICATOR_ADDRESS_PREFIX "-")))
1086 {
1087 GNUNET_break_op (0);
1088 return GNUNET_SYSERR;
1089 }
1090 path = &address[strlen (COMMUNICATOR_ADDRESS_PREFIX "-")];
1091 in = udp_address_to_sockaddr (path, &in_len);
1092 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "mq_init in_len length before: %d\n",
1093 in_len);
1097 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "address string in mq_init: %s\n",
1098 address);
1099 GNUNET_CRYPTO_hash (address, strlen (address), &addr_key);
1100 peer = GNUNET_CONTAINER_multihashmap_get (addr_map, &addr_key);
1101 if (NULL != peer)
1102 {
1104 "ignoring transport service mq request, we already have an mq with this peer (address)\n");
1105 return GNUNET_SYSERR;
1106 }
1107 peer = GNUNET_new (struct PeerAddress);
1108 peer->address = in;
1109 peer->address_len = in_len;
1110 peer->target = *peer_id;
1111 peer->id_rcvd = GNUNET_YES;
1112 peer->is_receiver = GNUNET_YES;
1113 peer->nt = GNUNET_NT_scanner_get_type (is, in, in_len);
1114 peer->timeout =
1117 "# peers active",
1119 GNUNET_NO);
1120 peer->foreign_addr =
1126 peer,
1129 "mq_init added new peer to the addr map\n");
1135 q_conn = GNUNET_new (struct quic_conn);
1136 GNUNET_memcpy (q_conn->cid, scid, LOCAL_CONN_ID_LEN);
1137 peer->conn = q_conn;
1139 "attempting to perform QUIC handshake with peer\n");
1140 q_conn->conn = quiche_connect (peer->foreign_addr, scid, LOCAL_CONN_ID_LEN,
1141 local_addr,
1142 local_in_len, peer->address, peer->address_len,
1143 config);
1144 flush_egress (peer->conn);
1146 return GNUNET_OK;
1150 // if (NULL == timeout_task)
1151 // timeout_task = GNUNET_SCHEDULER_add_now (&check_timeouts, NULL);
1152}
1153
1154
1155static void
1157 const struct sockaddr *addr,
1158 socklen_t addrlen)
1159{
1160 /* FIXME: support reversal: #5529 */
1162 "No connection reversal implemented!");
1163}
1164
1165
1179static void
1181 void **app_ctx,
1182 int add_remove,
1184 const struct sockaddr *addr,
1185 socklen_t addrlen)
1186{
1187 char *my_addr;
1189
1190 if (GNUNET_YES == add_remove)
1191 {
1193
1194 GNUNET_asprintf (&my_addr,
1195 "%s-%s",
1197 GNUNET_a2s (addr, addrlen));
1198 nt = GNUNET_NT_scanner_get_type (is, addr, addrlen);
1199 ai =
1201 my_addr,
1202 nt,
1204 GNUNET_free (my_addr);
1205 *app_ctx = ai;
1206 }
1207 else
1208 {
1209 ai = *app_ctx;
1211 *app_ctx = NULL;
1212 }
1213}
1214
1215
1221static void
1222do_shutdown (void *cls)
1223{
1225 "do_shutdown\n");
1228 quiche_config_free (config);
1229
1230 if (NULL != timeout_task)
1231 {
1233 timeout_task = NULL;
1234 }
1235 if (NULL != read_task)
1236 {
1238 read_task = NULL;
1239 }
1240 if (NULL != udp_sock)
1241 {
1244 udp_sock = NULL;
1245 }
1246 if (NULL != ch)
1247 {
1249 ch = NULL;
1250 }
1251 if (NULL != ah)
1252 {
1254 ah = NULL;
1255 }
1256 if (NULL != my_private_key)
1257 {
1259 my_private_key = NULL;
1260 }
1262 "do_shutdown finished\n");
1263}
1264
1265
1266static void
1267sock_read (void *cls)
1268{
1269 struct sockaddr_storage sa;
1270 struct sockaddr_in *addr_verify;
1271 socklen_t salen = sizeof(sa);
1272 uint8_t buf[UINT16_MAX];
1273 uint8_t out[MAX_DATAGRAM_SIZE];
1274 ssize_t rcvd;
1275
1276 ssize_t process_pkt;
1277 struct QUIC_header quic_header;
1278 uint8_t new_cid[LOCAL_CONN_ID_LEN];
1279
1280 struct PeerAddress *peer;
1281 struct GNUNET_HashCode addr_key;
1282
1283 (void) cls;
1284 quic_header.scid_len = sizeof(quic_header.scid);
1285 quic_header.dcid_len = sizeof(quic_header.dcid);
1286 quic_header.odcid_len = sizeof(quic_header.odcid);
1287 quic_header.token_len = sizeof(quic_header.token);
1291 char *bindto;
1292 socklen_t in_len;
1293 if (GNUNET_OK !=
1296 "BINDTO",
1297 &bindto))
1298 {
1301 "BINDTO");
1302 return;
1303 }
1304 struct sockaddr *local_addr = udp_address_to_sockaddr (bindto, &in_len);
1305
1307 udp_sock,
1308 &sock_read,
1309 NULL);
1310 while (1)
1311 {
1313 buf,
1314 sizeof(buf),
1315 (struct sockaddr *) &sa,
1316 &salen);
1317 if (-1 == rcvd)
1318 {
1319 if (EAGAIN == errno)
1320 break; // We are done reading data
1322 return;
1323 }
1324
1326 "Read %lu bytes\n", rcvd);
1327
1328 if (-1 == rcvd)
1329 {
1331 return;
1332 }
1340 const char *addr_string = sockaddr_to_udpaddr_string ((const struct
1341 sockaddr *) &sa,
1342 salen);
1343 GNUNET_CRYPTO_hash (addr_string, strlen (addr_string),
1344 &addr_key);
1345 GNUNET_free (addr_string);
1346 peer = GNUNET_CONTAINER_multihashmap_get (addr_map, &addr_key);
1347
1348 if (NULL == peer)
1349 {
1353 peer = GNUNET_new (struct PeerAddress);
1354 peer->address = GNUNET_memdup (&sa, salen);
1355 peer->address_len = salen;
1356 peer->id_rcvd = GNUNET_NO;
1357 peer->id_sent = GNUNET_NO;
1358 peer->is_receiver = GNUNET_NO;
1359 peer->conn = NULL;
1361 peer->address_len);
1365 // setup_peer_mq (peer);
1367 &addr_key,
1368 peer,
1370 {
1372 "tried to add duplicate address into address map\n");
1373 return;
1374 }
1376 "sock_read added new peer to address map\n");
1377 }
1378
1382 int rc = quiche_header_info (buf, rcvd, LOCAL_CONN_ID_LEN,
1383 &quic_header.version,
1384 &quic_header.type, quic_header.scid,
1385 &quic_header.scid_len, quic_header.dcid,
1386 &quic_header.dcid_len,
1387 quic_header.token, &quic_header.token_len);
1388 if (0 > rc)
1389 {
1391 "failed to parse quic header: %d\n",
1392 rc);
1393 return;
1394 }
1395
1399 if (NULL == peer->conn)
1400 {
1402 "attempting to create new connection\n");
1403 if (0 == quiche_version_is_supported (quic_header.version))
1404 {
1406 "quic version negotiation initiated\n");
1414 ssize_t written = quiche_negotiate_version (quic_header.scid,
1415 quic_header.scid_len,
1416 quic_header.dcid,
1417 quic_header.dcid_len,
1418 out, sizeof(out));
1419 if (0 > written)
1420 {
1422 "quiche failed to generate version negotiation packet\n");
1423 return;
1424 }
1425 ssize_t sent = GNUNET_NETWORK_socket_sendto (udp_sock,
1426 out,
1427 written,
1428 (struct sockaddr*) &sa,
1429 salen);
1430 if (sent != written)
1431 {
1433 "failed to send version negotiation packet to peer\n");
1434 return;
1435 }
1437 "sent %zd bytes to peer during version negotiation\n",
1438 sent);
1439 return;
1440 }
1441
1442 if (0 == quic_header.token_len)
1443 {
1444 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "quic stateless retry\n");
1445 mint_token (quic_header.dcid, quic_header.dcid_len, &sa, salen,
1446 quic_header.token, &quic_header.token_len);
1447
1448 uint8_t new_cid[LOCAL_CONN_ID_LEN];
1451
1452 ssize_t written = quiche_retry (quic_header.scid, quic_header.scid_len,
1453 quic_header.dcid, quic_header.dcid_len,
1454 new_cid, LOCAL_CONN_ID_LEN,
1455 quic_header.token,
1456 quic_header.token_len,
1457 quic_header.version, out, sizeof(out));
1458 if (0 > written)
1459 {
1461 "quiche failed to write retry packet\n");
1462 return;
1463 }
1464 ssize_t sent = GNUNET_NETWORK_socket_sendto (udp_sock,
1465 out,
1466 written,
1467 (struct sockaddr*) &sa,
1468 salen);
1469 if (written != sent)
1470 {
1471 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "failed to send retry packet\n");
1472 return;
1473 }
1474
1475 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sent %zd bytes\n", sent);
1476 continue;
1477 }
1478
1479 if (GNUNET_OK != validate_token (quic_header.token, quic_header.token_len,
1480 &sa, salen,
1481 quic_header.odcid,
1482 &quic_header.odcid_len))
1483 {
1485 "invalid address validation token created\n");
1486 return;
1487 }
1488 peer->conn = create_conn (quic_header.dcid, quic_header.dcid_len,
1489 quic_header.odcid, quic_header.odcid_len,
1490 local_addr, in_len,
1491 &sa, salen);
1492 if (NULL == peer->conn)
1493 {
1495 "failed to create quic connection with peer\n");
1496 return;
1497 }
1498 } // null connection
1499
1500 quiche_recv_info recv_info = {
1501 (struct sockaddr *) &sa,
1502 salen,
1503
1504 local_addr,
1505 in_len,
1506 };
1510 if (quiche_conn_is_established (peer->conn->conn) && ! peer->id_sent &&
1511 peer->is_receiver)
1512 {
1513 ssize_t send_len;
1514
1516 "handshake established with peer, sending our peer id\n");
1517 send_len = quiche_conn_stream_send (peer->conn->conn, STREAMID_BI,
1518 (const uint8_t *) &my_identity,
1519 sizeof(my_identity),
1520 false);
1521 if (0 > send_len)
1522 {
1524 "failed to write peer identity packet. quiche error: %zd\n",
1525 send_len);
1526 return;
1527 }
1528 flush_egress (peer->conn);
1529 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "peer identity sent to peer\n");
1530 peer->id_sent = GNUNET_YES;
1531 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "setting up peer mq\n");
1532 setup_peer_mq (peer);
1536 }
1537 process_pkt = quiche_conn_recv (peer->conn->conn, buf, rcvd, &recv_info);
1538 if (0 > process_pkt)
1539 {
1541 "quiche failed to process received packet: %zd\n",
1542 process_pkt);
1543 return;
1544 }
1546 "quiche processed %zd bytes\n", process_pkt);
1547 // Check for data on all available streams if the connection is established
1548 if (GNUNET_YES == quiche_conn_is_established (peer->conn->conn))
1549 {
1550 recv_from_streams (peer);
1551 }
1558 quiche_stats stats;
1559 quiche_path_stats path_stats;
1560
1561 flush_egress (peer->conn);
1562
1563 if (quiche_conn_is_closed (peer->conn->conn))
1564 {
1565 quiche_conn_stats (peer->conn->conn, &stats);
1566 quiche_conn_path_stats (peer->conn->conn, 0, &path_stats);
1567
1569 "connection closed. quiche stats: sent=%zu, recv=%zu\n",
1570 stats.sent, stats.recv);
1571 peer_destroy (peer);
1572 }
1573 }
1575}
1576
1577
1586static void
1587run (void *cls,
1588 char *const *args,
1589 const char *cfgfile,
1590 const struct GNUNET_CONFIGURATION_Handle *c)
1591{
1592 char *bindto;
1593 struct sockaddr *in;
1594 socklen_t in_len;
1595 struct sockaddr_storage in_sto;
1596 socklen_t sto_len;
1597
1598 (void) cls;
1599 cfg = c;
1600
1601 if (GNUNET_OK !=
1604 "BINDTO",
1605 &bindto))
1606 {
1609 "BINDTO");
1610 return;
1611 }
1612
1613 in = udp_address_to_sockaddr (bindto, &in_len);
1614
1615 if (NULL == in)
1616 {
1618 "Failed to setup UDP socket address with path `%s'\n",
1619 bindto);
1620 GNUNET_free (bindto);
1621 return;
1622 }
1623 udp_sock =
1624 GNUNET_NETWORK_socket_create (in->sa_family,
1625 SOCK_DGRAM,
1626 IPPROTO_UDP);
1627 if (NULL == udp_sock)
1628 {
1630 GNUNET_free (in);
1631 GNUNET_free (bindto);
1632 return;
1633 }
1634 if (AF_INET6 == in->sa_family)
1636 if (GNUNET_OK !=
1638 in,
1639 in_len))
1640 {
1642 "bind",
1643 bindto);
1645 udp_sock = NULL;
1646 GNUNET_free (in);
1647 GNUNET_free (bindto);
1648 return;
1649 }
1650 sto_len = sizeof(in_sto);
1651 if (0 != getsockname (GNUNET_NETWORK_get_fd (udp_sock),
1652 (struct sockaddr *) &in_sto,
1653 &sto_len))
1654 {
1655 memcpy (&in_sto, in, in_len);
1656 sto_len = in_len;
1657 }
1658 GNUNET_free (in);
1659 GNUNET_free (bindto);
1660 in = (struct sockaddr *) &in_sto;
1661 in_len = sto_len;
1663 "transport",
1664 "Bound to `%s'\n",
1665 GNUNET_a2s ((const struct sockaddr *) &in_sto,
1666 sto_len));
1667 switch (in->sa_family)
1668 {
1669 case AF_INET:
1670 my_port = ntohs (((struct sockaddr_in *) in)->sin_port);
1671 break;
1672
1673 case AF_INET6:
1674 my_port = ntohs (((struct sockaddr_in6 *) in)->sin6_port);
1675 break;
1676
1677 default:
1678 GNUNET_break (0);
1679 my_port = 0;
1680 }
1685 config = quiche_config_new (QUICHE_PROTOCOL_VERSION);
1686 quiche_config_verify_peer (config, false);
1690 quiche_config_load_cert_chain_from_pem_file (config, "./cert.crt");
1691 quiche_config_load_priv_key_from_pem_file (config, "./cert.key");
1692 quiche_config_set_application_protos (config,
1693 (uint8_t *)
1694 "\x0ahq-interop\x05hq-29\x05hq-28\x05hq-27\x08http/0.9",
1695 38);
1696 quiche_config_set_max_idle_timeout (config, 5000);
1697 quiche_config_set_max_recv_udp_payload_size (config, 1200);
1698 quiche_config_set_max_send_udp_payload_size (config, 1200);
1699 quiche_config_set_initial_max_data (config, 10000000);
1700 quiche_config_set_initial_max_stream_data_bidi_local (config, 1000000);
1701 quiche_config_set_initial_max_stream_data_bidi_remote (config, 1000000);
1702 quiche_config_set_initial_max_stream_data_uni (config, 1000000);
1703 quiche_config_set_initial_max_streams_bidi (config, 100);
1704 quiche_config_set_initial_max_streams_uni (config, 100);
1705 quiche_config_set_cc_algorithm (config, QUICHE_CC_RENO);
1706 quiche_config_set_disable_active_migration (config, true);
1712 if (NULL == my_private_key)
1713 {
1714 GNUNET_log (
1716 _ (
1717 "Transport service is lacking key configuration settings. Exiting.\n"));
1719 return;
1720 }
1722 /* start reading */
1724 udp_sock,
1725 &sock_read,
1726 NULL);
1731 &mq_init,
1732 NULL,
1733 &notify_cb,
1734 NULL);
1738 IPPROTO_UDP,
1739 1 /* one address */,
1740 (const struct sockaddr **) &in,
1741 &in_len,
1744 NULL /* closure */);
1745 if (NULL == ch)
1746 {
1747 GNUNET_break (0);
1749 return;
1750 }
1752 if (NULL == ah)
1753 {
1754 GNUNET_break (0);
1756 return;
1757 }
1758
1759 /* start broadcasting */
1760 // if (GNUNET_YES !=
1761 // GNUNET_CONFIGURATION_get_value_yesno (cfg,
1762 // COMMUNICATOR_CONFIG_SECTION,
1763 // "DISABLE_BROADCAST"))
1764 // {
1765 // broadcast_task = GNUNET_SCHEDULER_add_now (&do_broadcast, NULL);
1766 // }
1767}
1768
1769
1770int
1771main (int argc, char *const *argv)
1772{
1773 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
1775 };
1776 int ret;
1777
1779 "transport",
1780 "Starting quic communicator\n");
1781 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
1782 return 2;
1783
1784 ret = (GNUNET_OK == GNUNET_PROGRAM_run (argc,
1785 argv,
1786 "gnunet-communicator-quic",
1787 _ ("GNUnet QUIC communicator"),
1788 options,
1789 &run,
1790 NULL))
1791 ? 0
1792 : 1;
1793 GNUNET_free_nz ((void *) argv);
1794 return ret;
1795}
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_OPTION_END
Definition: 002.c:13
struct GNUNET_GETOPT_CommandLineOption options[]
Definition: 002.c:5
struct GNUNET_MQ_Handle * mq
Definition: 003.c:5
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
static int start
Set if we are to start default services (including ARM).
Definition: gnunet-arm.c:39
static int ret
Final status code.
Definition: gnunet-arm.c:94
static uint16_t port
Port number.
Definition: gnunet-bcd.c:147
static char * peer_id
Option –peer.
Definition: gnunet-cadet.c:42
static void mq_destroy_d(struct GNUNET_MQ_Handle *mq, void *impl_state)
Signature of functions implementing the destruction of a message queue.
struct GNUNET_PeerIdentity my_identity
Our peer identity.
#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_TIME_Relative rekey_interval
FIXME undocumented.
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)
static void do_shutdown(void *cls)
Shutdown the QUIC communicator.
#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 ...
static void check_timeouts(void *cls)
Task run to check #receiver_heap and #sender_heap for timeouts.
#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.
int main(int argc, char *const *argv)
static struct GNUNET_CRYPTO_EddsaPrivateKey * my_private_key
Our private key.
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)
static unsigned long long rekey_max_bytes
FIXME undocumented.
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 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...
Core service; the main API for encrypted P2P communications.
Constants for network protocols.
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_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)
Connect to 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_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(enum GNUNET_CRYPTO_Quality mode, void *buffer, size_t length)
Fill block with a random values.
void GNUNET_CRYPTO_eddsa_key_get_public(const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, struct GNUNET_CRYPTO_EddsaPublicKey *pub)
Extract the public key for the given private key.
Definition: crypto_ecc.c:198
struct GNUNET_CRYPTO_EddsaPrivateKey * GNUNET_CRYPTO_eddsa_key_create_from_configuration(const struct GNUNET_CONFIGURATION_Handle *cfg)
Create a new private key by reading our peer's key from the file specified in the configuration.
@ GNUNET_CRYPTO_QUALITY_STRONG
High-quality operations are desired.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:41
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.
@ 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_free_nz(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:465
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:421
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.
Definition: gnunet_nt_lib.h:44
struct GNUNET_NT_InterfaceScanner * GNUNET_NT_scanner_init(void)
Initialize the address characterization client handle.
Definition: nt.c:405
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:307
enum GNUNET_GenericReturnValue GNUNET_PROGRAM_run(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:400
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:567
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:1512
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:1340
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:981
void GNUNET_STATISTICS_set(struct GNUNET_STATISTICS_Handle *handle, const char *name, uint64_t value, int make_persistent)
Set statistic value for the peer.
enum GNUNET_GenericReturnValue GNUNET_STRINGS_get_utf8_args(int argc, char *const *argv, int *u8argc, char *const **u8argv)
Returns utf-8 encoded arguments.
Definition: strings.c:1230
#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:178
Internal representation of the hash map.
Private ECC key encoded for transmission.
Definition of a command line option.
A 512-bit hashcode.
Handle to a message queue.
Definition: mq.c:87
Header for all communications.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
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
The identity of the host (wraps the signing key of the peer).
struct GNUNET_CRYPTO_EddsaPublicKey public_key
Entry in list of pending tasks.
Definition: scheduler.c:136
Handle for the service.
Time for absolute times used by GNUnet, in microseconds.
Time for relative time 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.
quiche_conn * conn