GNUnet 0.26.2-114-g7c6b613e3
 
Loading...
Searching...
No Matches
gnunet-communicator-quic.c File Reference

Transport plugin using QUIC. More...

#include <quiche.h>
#include <stdint.h>
#include <inttypes.h>
#include "platform.h"
#include "gnunet_common.h"
#include "gnunet_util_lib.h"
#include "gnunet_constants.h"
#include "gnunet_pils_service.h"
#include "gnunet_statistics_service.h"
#include "gnunet_transport_application_service.h"
#include "gnunet_transport_communication_service.h"
#include "gnunet_nat_service.h"
Include dependency graph for gnunet-communicator-quic.c:

Go to the source code of this file.

Data Structures

struct  PeerAddress
 Information we track per peer we have recently been in contact with. More...
 
struct  quic_conn
 QUIC connection object. More...
 
struct  QUIC_header
 QUIC_header is used to store information received from an incoming QUIC packet. More...
 

Macros

#define COMMUNICATOR_CONFIG_SECTION   "communicator-quic"
 
#define COMMUNICATOR_ADDRESS_PREFIX   "quic"
 
#define MAX_DATAGRAM_SIZE   1350
 
#define LOCAL_CONN_ID_LEN   20
 
#define MAX_TOKEN_LEN
 
#define CID_LEN   sizeof(uint8_t) * QUICHE_MAX_CONN_ID_LEN
 
#define TOKEN_LEN   sizeof (uint8_t) * MAX_TOKEN_LEN
 
#define STREAMID_BI   4
 
#define ADDRESS_VALIDITY_PERIOD   GNUNET_TIME_UNIT_HOURS
 How long do we believe our addresses to remain up (before the other peer should revalidate).
 

Functions

static void recv_from_streams (struct PeerAddress *peer)
 Given a PeerAddress, receive data from streams after doing connection logic.
 
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.
 
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 struct quic_conncreate_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 void flush_egress (struct quic_conn *conn)
 
static void reschedule_peer_timeout (struct PeerAddress *peer)
 Increment receiver timeout due to activity.
 
static void peer_destroy (struct PeerAddress *peer)
 Destroys a receiving state due to timeout or shutdown.
 
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_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 mq_destroy_d (struct GNUNET_MQ_Handle *mq, void *impl_state)
 Signature of functions implementing the destruction of a message queue.
 
static void mq_cancel (struct GNUNET_MQ_Handle *mq, void *impl_state)
 Implementation function that cancels the currently sent message.
 
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 creation of the message queue.
 
static struct sockaddr * udp_address_to_sockaddr (const char *bindto, socklen_t *sock_len)
 Convert UDP bind specification to a struct sockaddr *
 
static void setup_peer_mq (struct PeerAddress *peer)
 Setup the MQ for the peer.
 
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 in HELLOs.
 
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 (!) via a different return path.
 
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 about another peer.
 
static void try_connection_reversal (void *cls, const struct sockaddr *addr, socklen_t addrlen)
 
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 'valid' addresses changes.
 
static void do_shutdown (void *cls)
 Shutdown the QUIC communicator.
 
static void sock_read (void *cls)
 
static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c)
 Setup communicator and launch network interactions.
 
int main (int argc, char *const *argv)
 

Variables

struct GNUNET_CONTAINER_MultiHashMapconn_map
 Map of DCID (uint8_t) -> quic_conn for quickly retrieving connections to other peers.
 
struct GNUNET_CONTAINER_MultiHashMapaddr_map
 Map of sockaddr -> struct PeerAddress.
 
static const struct GNUNET_CONFIGURATION_Handlecfg
 Handle to the config.
 
static struct GNUNET_NETWORK_Handleudp_sock
 FIXME undocumented.
 
static struct GNUNET_SCHEDULER_Taskread_task
 FIXME undocumented.
 
static struct GNUNET_TRANSPORT_CommunicatorHandlech
 FIXME undocumented.
 
static struct GNUNET_TRANSPORT_ApplicationHandleah
 FIXME undocumented.
 
static int have_v6_socket
 FIXME undocumented.
 
static uint16_t my_port
 FIXME undocumented.
 
static quiche_config * config = NULL
 FIXME undocumented.
 
struct GNUNET_PILS_Handlepils
 Handle to PILS service.
 
static struct GNUNET_NAT_Handlenat
 Connection to NAT service.
 
static struct GNUNET_SCHEDULER_Tasktimeout_task
 ID of timeout task.
 
static struct GNUNET_NT_InterfaceScanneris
 Network scanner to determine network types.
 
static struct GNUNET_STATISTICS_Handlestats
 For logging statistics.
 

Detailed Description

Transport plugin using QUIC.

Author
Marshall Stone
Martin Schanzenbach

TODO:

  • Automatically generate self-signed x509 certificates and load from config
  • Figure out MTU and how we have to handle fragmentation in Quiche.
  • Mandate timeouts
  • Setup stats handler properly
  • Doxygen documentation of methods
  • Refactor code shared with UDP and TCP communicator
  • Performance testing
  • Check for memory leaks with coverity/valgrind

Definition in file gnunet-communicator-quic.c.

Macro Definition Documentation

◆ COMMUNICATOR_CONFIG_SECTION

#define COMMUNICATOR_CONFIG_SECTION   "communicator-quic"

Definition at line 50 of file gnunet-communicator-quic.c.

◆ COMMUNICATOR_ADDRESS_PREFIX

#define COMMUNICATOR_ADDRESS_PREFIX   "quic"

Definition at line 51 of file gnunet-communicator-quic.c.

◆ MAX_DATAGRAM_SIZE

#define MAX_DATAGRAM_SIZE   1350

Definition at line 52 of file gnunet-communicator-quic.c.

◆ LOCAL_CONN_ID_LEN

#define LOCAL_CONN_ID_LEN   20

Definition at line 57 of file gnunet-communicator-quic.c.

◆ MAX_TOKEN_LEN

#define MAX_TOKEN_LEN
Value:
sizeof("quiche") - 1 \
+ sizeof(struct sockaddr_storage) \
+ QUICHE_MAX_CONN_ID_LEN

Definition at line 58 of file gnunet-communicator-quic.c.

145{
149 struct GNUNET_PeerIdentity target;
150
154 int id_rcvd;
155
159 int id_sent;
160
164 int is_receiver;
165
170 char *foreign_addr;
171
175 struct sockaddr *address;
176
180 socklen_t address_len;
181
185 struct quic_conn *conn;
186
190 struct GNUNET_MQ_Handle *d_mq;
191
195 struct GNUNET_TRANSPORT_QueueHandle *d_qh;
196
201
206 size_t d_mtu;
207
212
216 int peer_destroy_called;
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
239static struct GNUNET_NT_InterfaceScanner *is;
240
244static struct GNUNET_STATISTICS_Handle *stats;
245
251struct quic_conn
252{
253 uint8_t cid[LOCAL_CONN_ID_LEN];
254
255 quiche_conn *conn;
256};
257
261struct QUIC_header
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
275 uint8_t token[MAX_TOKEN_LEN];
276 size_t token_len;
277};
278
279
284static void
285recv_from_streams (struct PeerAddress *peer)
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);
454 return NULL;
455 }
456
458 q_conn = quiche_accept (conn->cid, LOCAL_CONN_ID_LEN,
459 odcid, odcid_len,
461 local_addr_len,
462 (struct sockaddr *) peer_addr,
463 peer_addr_len,
464 config);
465 if (NULL == q_conn)
466 {
468 "quiche failed to create connection after call to quiche_accept\n");
469 return NULL;
470 }
471 conn->conn = q_conn;
472 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "new quic connection created\n");
473 return conn;
474}
475
476
477static void
479{
480 static uint8_t out[MAX_DATAGRAM_SIZE];
481 quiche_send_info send_info;
482
483 ssize_t written;
484 ssize_t sent;
485
486 while (1)
487 {
488 written = quiche_conn_send (conn->conn, out, sizeof(out), &send_info);
489 if (QUICHE_ERR_DONE == written)
490 {
491 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "done writing quic packets\n");
492 break;
493 }
494 if (0 > written)
495 {
497 "quiche failed to create packet. quiche error: %zd\n",
498 written);
499 return;
500 }
501 sent = GNUNET_NETWORK_socket_sendto (udp_sock, out, written,
502 (struct sockaddr *) &send_info.to,
503 send_info.to_len);
504 if (sent != written)
505 {
507 "quiche failed to send data to peer\n");
508 return;
509 }
510 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sent %zd bytes\n", sent);
511 }
512}
513
514
520static void
522{
523 peer->timeout =
525 // GNUNET_CONTAINER_heap_update_cost (peer->hn,
526 // peer->timeout.abs_value_us);
527}
528
529
535static void
536peer_destroy (struct PeerAddress *peer)
537{
538 struct GNUNET_HashCode addr_key;
539
542 "Disconnecting peer for peer `%s'\n",
543 GNUNET_i2s (&peer->target));
544 if (NULL != peer->d_qh)
545 {
547 peer->d_qh = NULL;
548 }
549 // GNUNET_assert (peer == GNUNET_CONTAINER_heap_remove_node (peer->hn));
553 GNUNET_CRYPTO_hash (peer->address, peer->address_len, &addr_key);
555 peer))
556 {
558 "tried to remove non-existent peer from addr map\n");
559 return;
560 }
562 "# peers active",
564 GNUNET_NO);
565 quiche_conn_free (peer->conn->conn);
566 GNUNET_free (peer->address);
568 GNUNET_free (peer->conn);
569 GNUNET_free (peer);
570}
571
572
581static int
582get_peer_delete_it (void *cls,
583 const struct GNUNET_HashCode *key,
584 void *value)
585{
586 struct PeerAddress *peer = value;
587 (void) cls;
588 (void) key;
589 peer_destroy (peer);
590 return GNUNET_OK;
591}
592
593
602static void
604 const struct GNUNET_MessageHeader *msg,
605 void *impl_state)
606{
607 struct PeerAddress *peer = impl_state;
608 uint16_t msize = ntohs (msg->size);
609 ssize_t send_len;
610 uint64_t err_code;
611
612 if (NULL == peer->conn->conn)
613 {
615 "peer never established quic connection\n");
616 return;
617 }
618
619 GNUNET_assert (mq == peer->d_mq);
620 if (msize > peer->d_mtu)
621 {
623 "msize: %u, mtu: %lu\n",
624 msize,
625 peer->d_mtu);
626 GNUNET_break (0);
627 if (GNUNET_YES != peer->peer_destroy_called)
628 {
630 "peer destroy called, destroying peer\n");
631 peer_destroy (peer);
632 }
633 return;
634 }
636
637 send_len = quiche_conn_stream_send (peer->conn->conn, 4, (uint8_t *) msg,
638 msize, false, &err_code);
639 if (send_len != msize)
640 {
642 "tried to send message and quiche returned %zd; error_code %"
643 PRIu64,
644 send_len, err_code);
645 return;
646 }
647 flush_egress (peer->conn);
649 "sent a message of %zd bytes\n", send_len);
651}
652
653
662static void
663mq_destroy_d (struct GNUNET_MQ_Handle *mq, void *impl_state)
664{
665 struct PeerAddress *peer = impl_state;
667 "Default MQ destroyed\n");
668 if (mq == peer->d_mq)
669 {
670 peer->d_mq = NULL;
671 if (GNUNET_YES != peer->peer_destroy_called)
672 peer_destroy (peer);
673 }
674}
675
676
683static void
684mq_cancel (struct GNUNET_MQ_Handle *mq, void *impl_state)
685{
686 /* Cancellation is impossible with QUIC; bail */
687 GNUNET_assert (0);
688}
689
690
700static void
701mq_error (void *cls, enum GNUNET_MQ_Error error)
702{
703 struct PeerAddress *peer = cls;
704
706 "MQ error in queue to %s: %d\n",
707 GNUNET_i2s (&peer->target),
708 (int) error);
709 peer_destroy (peer);
710}
711
712
720static struct sockaddr *
721udp_address_to_sockaddr (const char *bindto, socklen_t *sock_len)
722{
723 struct sockaddr *in;
724 unsigned int port;
725 char dummy[2];
726 char *colon;
727 char *cp;
728
729 if (1 == sscanf (bindto, "%u%1s", &port, dummy))
730 {
731 /* interpreting value as just a PORT number */
732 if (port > UINT16_MAX)
733 {
735 "BINDTO specification `%s' invalid: value too large for port\n",
736 bindto);
737 return NULL;
738 }
739 if ((GNUNET_NO == GNUNET_NETWORK_test_pf (PF_INET6)) ||
740 (GNUNET_YES ==
743 "DISABLE_V6")))
744 {
745 struct sockaddr_in *i4;
746
747 i4 = GNUNET_malloc (sizeof(struct sockaddr_in));
748 i4->sin_family = AF_INET;
749 i4->sin_port = htons ((uint16_t) port);
750 *sock_len = sizeof(struct sockaddr_in);
751 in = (struct sockaddr *) i4;
752 }
753 else
754 {
755 struct sockaddr_in6 *i6;
756
757 i6 = GNUNET_malloc (sizeof(struct sockaddr_in6));
758 i6->sin6_family = AF_INET6;
759 i6->sin6_port = htons ((uint16_t) port);
760 *sock_len = sizeof(struct sockaddr_in6);
761 in = (struct sockaddr *) i6;
762 }
763 return in;
764 }
765 cp = GNUNET_strdup (bindto);
766 colon = strrchr (cp, ':');
767 if (NULL != colon)
768 {
769 /* interpret value after colon as port */
770 *colon = '\0';
771 colon++;
772 if (1 == sscanf (colon, "%u%1s", &port, dummy))
773 {
774 /* interpreting value as just a PORT number */
775 if (port > UINT16_MAX)
776 {
778 "BINDTO specification `%s' invalid: value too large for port\n",
779 bindto);
780 GNUNET_free (cp);
781 return NULL;
782 }
783 }
784 else
785 {
786 GNUNET_log (
788 "BINDTO specification `%s' invalid: last ':' not followed by number\n",
789 bindto);
790 GNUNET_free (cp);
791 return NULL;
792 }
793 }
794 else
795 {
796 /* interpret missing port as 0, aka pick any free one */
797 port = 0;
798 }
799 {
800 /* try IPv4 */
801 struct sockaddr_in v4;
802
803 memset (&v4, 0, sizeof(v4));
804 if (1 == inet_pton (AF_INET, cp, &v4.sin_addr))
805 {
806 v4.sin_family = AF_INET;
807 v4.sin_port = htons ((uint16_t) port);
808#if HAVE_SOCKADDR_IN_SIN_LEN
809 v4.sin_len = sizeof(struct sockaddr_in);
810#endif
811 in = GNUNET_memdup (&v4, sizeof(struct sockaddr_in));
812 *sock_len = sizeof(struct sockaddr_in);
813 GNUNET_free (cp);
814 return in;
815 }
816 }
817 {
818 /* try IPv6 */
819 struct sockaddr_in6 v6;
820 const char *start;
821
822 memset (&v6, 0, sizeof(v6));
823 start = cp;
824 if (('[' == *cp) && (']' == cp[strlen (cp) - 1]))
825 {
826 start++; /* skip over '[' */
827 cp[strlen (cp) - 1] = '\0'; /* eat ']' */
828 }
829 if (1 == inet_pton (AF_INET6, start, &v6.sin6_addr))
830 {
831 v6.sin6_family = AF_INET6;
832 v6.sin6_port = htons ((uint16_t) port);
833#if HAVE_SOCKADDR_IN_SIN_LEN
834 v6.sin6_len = sizeof(sizeof(struct sockaddr_in6));
835#endif
836 in = GNUNET_memdup (&v6, sizeof(v6));
837 *sock_len = sizeof(v6);
838 GNUNET_free (cp);
839 return in;
840 }
841 }
842 /* #5528 FIXME (feature!): maybe also try getnameinfo()? */
843 GNUNET_free (cp);
844 return NULL;
845}
846
847
855static void
856setup_peer_mq (struct PeerAddress *peer)
857{
858 size_t base_mtu;
859
860 switch (peer->address->sa_family)
861 {
862 case AF_INET:
863 base_mtu = 1480 /* Ethernet MTU, 1500 - Ethernet header - VLAN tag */
864 - sizeof(struct GNUNET_TUN_IPv4Header) /* 20 */
865 - sizeof(struct GNUNET_TUN_UdpHeader) /* 8 */;
866 break;
867
868 case AF_INET6:
869 base_mtu = 1280 /* Minimum MTU required by IPv6 */
870 - sizeof(struct GNUNET_TUN_IPv6Header) /* 40 */
871 - sizeof(struct GNUNET_TUN_UdpHeader) /* 8 */;
872 break;
873
874 default:
875 GNUNET_assert (0);
876 break;
877 }
878 /* MTU == base_mtu */
879 peer->d_mtu = base_mtu;
880
882 "Setting up MQs and QHs\n");
883 /* => Effective MTU for CORE will range from 1080 (IPv6 + KX) to
884 1404 (IPv4 + Box) bytes, depending on circumstances... */
885
886 if (NULL == peer->d_mq)
889 &mq_cancel,
890 peer,
891 NULL,
892 &mq_error,
893 peer);
894 peer->d_qh =
896 &peer->target,
897 peer->foreign_addr,
898 1000,
900 0, /* Priority */
901 peer->nt,
903 peer->d_mq);
904}
905
906
916static char *
917sockaddr_to_udpaddr_string (const struct sockaddr *address,
918 socklen_t address_len)
919{
920 char *ret;
921
922 switch (address->sa_family)
923 {
924 case AF_INET:
926 "%s-%s",
928 GNUNET_a2s (address, address_len));
929 break;
930
931 case AF_INET6:
933 "%s-%s",
935 GNUNET_a2s (address, address_len));
936 break;
937
938 default:
939 GNUNET_assert (0);
940 }
941 return ret;
942}
943
944
954static void
955notify_cb (void *cls,
956 const struct GNUNET_PeerIdentity *sender,
957 const struct GNUNET_MessageHeader *msg)
958{
959 // const struct UDPAck *ack;
960
961 // (void) cls;
962 // GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
963 // "Storing UDPAck received from backchannel from %s\n",
964 // GNUNET_i2s_full (sender));
965 // if ((ntohs (msg->type) != GNUNET_MESSAGE_TYPE_COMMUNICATOR_UDP_ACK) ||
966 // (ntohs (msg->size) != sizeof(struct UDPAck)))
967 // {
968 // GNUNET_break_op (0);
969 // return;
970 // }
971 // ack = (const struct UDPAck *) msg;
972 // GNUNET_CONTAINER_multipeermap_get_multiple (receivers,
973 // sender,
974 // &handle_ack,
975 // (void *) ack);
976}
977
978
997static int
998mq_init (void *cls, const struct GNUNET_PeerIdentity *peer_id, const
999 char *address)
1000{
1001 struct PeerAddress *peer;
1002 const char *path;
1003 struct sockaddr *in;
1004 socklen_t in_len;
1005 struct GNUNET_HashCode addr_key;
1006 uint8_t scid[LOCAL_CONN_ID_LEN];
1007
1008 struct quic_conn *q_conn;
1009 char *bindto;
1010 socklen_t local_in_len;
1011 struct sockaddr *local_addr;
1012
1013 if (GNUNET_OK !=
1016 "BINDTO",
1017 &bindto))
1018 {
1021 "BINDTO");
1022 return GNUNET_SYSERR;
1023 }
1024 local_addr = udp_address_to_sockaddr (bindto, &local_in_len);
1025
1026 if (0 != strncmp (address,
1028 strlen (COMMUNICATOR_ADDRESS_PREFIX "-")))
1029 {
1030 GNUNET_break_op (0);
1031 return GNUNET_SYSERR;
1032 }
1033 path = &address[strlen (COMMUNICATOR_ADDRESS_PREFIX "-")];
1034 in = udp_address_to_sockaddr (path, &in_len);
1035 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "mq_init in_len length before: %d\n",
1036 in_len);
1040 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "address string in mq_init: %s\n",
1041 address);
1042 GNUNET_CRYPTO_hash (address, strlen (address), &addr_key);
1043 peer = GNUNET_CONTAINER_multihashmap_get (addr_map, &addr_key);
1044 if (NULL != peer)
1045 {
1047 "ignoring transport service mq request, we already have an mq with this peer (address)\n");
1048 return GNUNET_SYSERR;
1049 }
1050 peer = GNUNET_new (struct PeerAddress);
1051 peer->address = in;
1052 peer->address_len = in_len;
1053 peer->target = *peer_id;
1054 peer->id_rcvd = GNUNET_YES;
1055 peer->is_receiver = GNUNET_YES;
1056 peer->nt = GNUNET_NT_scanner_get_type (is, in, in_len);
1057 peer->timeout =
1060 "# peers active",
1062 GNUNET_NO);
1063 peer->foreign_addr =
1069 peer,
1072 "mq_init added new peer to the addr map\n");
1078 q_conn = GNUNET_new (struct quic_conn);
1079 GNUNET_memcpy (q_conn->cid, scid, LOCAL_CONN_ID_LEN);
1080 peer->conn = q_conn;
1082 "attempting to perform QUIC handshake with peer\n");
1083 q_conn->conn = quiche_connect (peer->foreign_addr, scid, LOCAL_CONN_ID_LEN,
1084 local_addr,
1085 local_in_len, peer->address, peer->address_len,
1086 config);
1087 flush_egress (peer->conn);
1089 return GNUNET_OK;
1093 // if (NULL == timeout_task)
1094 // timeout_task = GNUNET_SCHEDULER_add_now (&check_timeouts, NULL);
1095}
1096
1097
1098static void
1099try_connection_reversal (void *cls,
1100 const struct sockaddr *addr,
1101 socklen_t addrlen)
1102{
1103 /* FIXME: support reversal: #5529 */
1105 "No connection reversal implemented!");
1106}
1107
1108
1122static void
1123nat_address_cb (void *cls,
1124 void **app_ctx,
1125 int add_remove,
1127 const struct sockaddr *addr,
1128 socklen_t addrlen)
1129{
1130 char *my_addr;
1132
1133 if (GNUNET_YES == add_remove)
1134 {
1136
1137 GNUNET_asprintf (&my_addr,
1138 "%s-%s",
1140 GNUNET_a2s (addr, addrlen));
1141 nt = GNUNET_NT_scanner_get_type (is, addr, addrlen);
1142 ai =
1144 my_addr,
1145 nt,
1147 GNUNET_free (my_addr);
1148 *app_ctx = ai;
1149 }
1150 else
1151 {
1152 ai = *app_ctx;
1154 *app_ctx = NULL;
1155 }
1156}
1157
1158
1164static void
1165do_shutdown (void *cls)
1166{
1168 "do_shutdown\n");
1171 quiche_config_free (config);
1172
1173 if (NULL != timeout_task)
1174 {
1176 timeout_task = NULL;
1177 }
1178 if (NULL != read_task)
1179 {
1181 read_task = NULL;
1182 }
1183 if (NULL != udp_sock)
1184 {
1187 udp_sock = NULL;
1188 }
1189 if (NULL != ch)
1190 {
1192 ch = NULL;
1193 }
1194 if (NULL != ah)
1195 {
1197 ah = NULL;
1198 }
1199 if (NULL != pils)
1200 {
1202 pils = NULL;
1203 }
1205 "do_shutdown finished\n");
1206}
1207
1208
1209static void
1210sock_read (void *cls)
1211{
1212 struct sockaddr_storage sa;
1213 socklen_t salen = sizeof(sa);
1214 uint8_t buf[UINT16_MAX];
1215 uint8_t out[MAX_DATAGRAM_SIZE];
1216 ssize_t rcvd;
1217
1218 ssize_t process_pkt;
1219 struct QUIC_header quic_header;
1220
1221 struct PeerAddress *peer;
1222 struct GNUNET_HashCode addr_key;
1223
1224 (void) cls;
1225 quic_header.scid_len = sizeof(quic_header.scid);
1226 quic_header.dcid_len = sizeof(quic_header.dcid);
1227 quic_header.odcid_len = sizeof(quic_header.odcid);
1228 quic_header.token_len = sizeof(quic_header.token);
1232 char *bindto;
1233 socklen_t in_len;
1234 if (GNUNET_OK !=
1237 "BINDTO",
1238 &bindto))
1239 {
1242 "BINDTO");
1243 return;
1244 }
1245 struct sockaddr *local_addr = udp_address_to_sockaddr (bindto, &in_len);
1246
1248 udp_sock,
1249 &sock_read,
1250 NULL);
1251 while (1)
1252 {
1254 buf,
1255 sizeof(buf),
1256 (struct sockaddr *) &sa,
1257 &salen);
1258 if (-1 == rcvd)
1259 {
1260 if (EAGAIN == errno)
1261 break; // We are done reading data
1263 return;
1264 }
1265
1267 "Read %lu bytes\n", rcvd);
1268
1269 if (-1 == rcvd)
1270 {
1272 return;
1273 }
1281 char *addr_string = sockaddr_to_udpaddr_string ((const struct
1282 sockaddr *) &sa,
1283 salen);
1284 GNUNET_CRYPTO_hash (addr_string, strlen (addr_string),
1285 &addr_key);
1286 GNUNET_free (addr_string);
1287 peer = GNUNET_CONTAINER_multihashmap_get (addr_map, &addr_key);
1288
1289 if (NULL == peer)
1290 {
1294 peer = GNUNET_new (struct PeerAddress);
1295 peer->address = GNUNET_memdup (&sa, salen);
1296 peer->address_len = salen;
1297 peer->id_rcvd = GNUNET_NO;
1298 peer->id_sent = GNUNET_NO;
1299 peer->is_receiver = GNUNET_NO;
1300 peer->conn = NULL;
1302 peer->address_len);
1306 // setup_peer_mq (peer);
1308 &addr_key,
1309 peer,
1311 {
1313 "tried to add duplicate address into address map\n");
1314 return;
1315 }
1317 "sock_read added new peer to address map\n");
1318 }
1319
1323 int rc = quiche_header_info (buf, rcvd, LOCAL_CONN_ID_LEN,
1324 &quic_header.version,
1325 &quic_header.type, quic_header.scid,
1326 &quic_header.scid_len, quic_header.dcid,
1327 &quic_header.dcid_len,
1328 quic_header.token, &quic_header.token_len);
1329 if (0 > rc)
1330 {
1332 "failed to parse quic header: %d\n",
1333 rc);
1334 return;
1335 }
1336
1340 if (NULL == peer->conn)
1341 {
1343 "attempting to create new connection\n");
1344 if (0 == quiche_version_is_supported (quic_header.version))
1345 {
1347 "quic version negotiation initiated\n");
1355 ssize_t written = quiche_negotiate_version (quic_header.scid,
1356 quic_header.scid_len,
1357 quic_header.dcid,
1358 quic_header.dcid_len,
1359 out, sizeof(out));
1360 if (0 > written)
1361 {
1363 "quiche failed to generate version negotiation packet\n");
1364 return;
1365 }
1366 ssize_t sent = GNUNET_NETWORK_socket_sendto (udp_sock,
1367 out,
1368 written,
1369 (struct sockaddr*) &sa,
1370 salen);
1371 if (sent != written)
1372 {
1374 "failed to send version negotiation packet to peer\n");
1375 return;
1376 }
1378 "sent %zd bytes to peer during version negotiation\n",
1379 sent);
1380 return;
1381 }
1382
1383 if (0 == quic_header.token_len)
1384 {
1385 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "quic stateless retry\n");
1386 mint_token (quic_header.dcid, quic_header.dcid_len, &sa, salen,
1387 quic_header.token, &quic_header.token_len);
1388
1389 uint8_t new_cid[LOCAL_CONN_ID_LEN];
1392
1393 ssize_t written = quiche_retry (quic_header.scid, quic_header.scid_len,
1394 quic_header.dcid, quic_header.dcid_len,
1395 new_cid, LOCAL_CONN_ID_LEN,
1396 quic_header.token,
1397 quic_header.token_len,
1398 quic_header.version, out, sizeof(out));
1399 if (0 > written)
1400 {
1402 "quiche failed to write retry packet\n");
1403 return;
1404 }
1405 ssize_t sent = GNUNET_NETWORK_socket_sendto (udp_sock,
1406 out,
1407 written,
1408 (struct sockaddr*) &sa,
1409 salen);
1410 if (written != sent)
1411 {
1412 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "failed to send retry packet\n");
1413 return;
1414 }
1415
1416 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sent %zd bytes\n", sent);
1417 continue;
1418 }
1419
1420 if (GNUNET_OK != validate_token (quic_header.token, quic_header.token_len,
1421 &sa, salen,
1422 quic_header.odcid,
1423 &quic_header.odcid_len))
1424 {
1426 "invalid address validation token created\n");
1427 return;
1428 }
1429 peer->conn = create_conn (quic_header.dcid, quic_header.dcid_len,
1430 quic_header.odcid, quic_header.odcid_len,
1431 local_addr, in_len,
1432 &sa, salen);
1433 if (NULL == peer->conn)
1434 {
1436 "failed to create quic connection with peer\n");
1437 return;
1438 }
1439 } // null connection
1440
1441 quiche_recv_info recv_info = {
1442 (struct sockaddr *) &sa,
1443 salen,
1444
1445 local_addr,
1446 in_len,
1447 };
1451 if (quiche_conn_is_established (peer->conn->conn) && ! peer->id_sent &&
1452 peer->is_receiver)
1453 {
1454 const struct GNUNET_PeerIdentity *my_identity;
1455 ssize_t send_len;
1456 uint64_t err_code;
1457
1459 "handshake established with peer, sending our peer id\n");
1460
1463
1464 send_len = quiche_conn_stream_send (peer->conn->conn, STREAMID_BI,
1465 (const uint8_t *) my_identity,
1466 sizeof(*my_identity),
1467 false, &err_code);
1468 if (0 > send_len)
1469 {
1471 "failed to write peer identity packet. quiche error: %"
1472 PRIu64 "; len=%zd\n",
1473 err_code,
1474 send_len);
1475 return;
1476 }
1477 flush_egress (peer->conn);
1478 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "peer identity sent to peer\n");
1479 peer->id_sent = GNUNET_YES;
1480 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "setting up peer mq\n");
1481 setup_peer_mq (peer);
1485 }
1486 process_pkt = quiche_conn_recv (peer->conn->conn, buf, rcvd, &recv_info);
1487 if (0 > process_pkt)
1488 {
1490 "quiche failed to process received packet: %zd\n",
1491 process_pkt);
1492 return;
1493 }
1495 "quiche processed %zd bytes\n", process_pkt);
1496 // Check for data on all available streams if the connection is established
1497 if (GNUNET_YES == quiche_conn_is_established (peer->conn->conn))
1498 {
1499 recv_from_streams (peer);
1500 }
1507 quiche_stats stats;
1508 quiche_path_stats path_stats;
1509
1510 flush_egress (peer->conn);
1511
1512 if (quiche_conn_is_closed (peer->conn->conn))
1513 {
1514 quiche_conn_stats (peer->conn->conn, &stats);
1515 quiche_conn_path_stats (peer->conn->conn, 0, &path_stats);
1516
1518 "connection closed. quiche stats: sent=%zu, recv=%zu\n",
1519 stats.sent, stats.recv);
1520 peer_destroy (peer);
1521 }
1522 }
1524}
1525
1526
1535static void
1536run (void *cls,
1537 char *const *args,
1538 const char *cfgfile,
1539 const struct GNUNET_CONFIGURATION_Handle *c)
1540{
1541 char *bindto;
1542 struct sockaddr *in;
1543 socklen_t in_len;
1544 struct sockaddr_storage in_sto;
1545 socklen_t sto_len;
1546
1547 (void) cls;
1548 cfg = c;
1549
1550 if (GNUNET_OK !=
1553 "BINDTO",
1554 &bindto))
1555 {
1558 "BINDTO");
1559 return;
1560 }
1561
1562 in = udp_address_to_sockaddr (bindto, &in_len);
1563
1564 if (NULL == in)
1565 {
1567 "Failed to setup UDP socket address with path `%s'\n",
1568 bindto);
1569 GNUNET_free (bindto);
1570 return;
1571 }
1572 udp_sock =
1573 GNUNET_NETWORK_socket_create (in->sa_family,
1574 SOCK_DGRAM,
1575 IPPROTO_UDP);
1576 if (NULL == udp_sock)
1577 {
1579 GNUNET_free (in);
1580 GNUNET_free (bindto);
1581 return;
1582 }
1583 if (AF_INET6 == in->sa_family)
1585 if (GNUNET_OK !=
1587 in,
1588 in_len))
1589 {
1591 "bind",
1592 bindto);
1594 udp_sock = NULL;
1595 GNUNET_free (in);
1596 GNUNET_free (bindto);
1597 return;
1598 }
1599 sto_len = sizeof(in_sto);
1600 if (0 != getsockname (GNUNET_NETWORK_get_fd (udp_sock),
1601 (struct sockaddr *) &in_sto,
1602 &sto_len))
1603 {
1604 memcpy (&in_sto, in, in_len);
1605 sto_len = in_len;
1606 }
1607 GNUNET_free (in);
1608 GNUNET_free (bindto);
1609 in = (struct sockaddr *) &in_sto;
1610 in_len = sto_len;
1612 "transport",
1613 "Bound to `%s'\n",
1614 GNUNET_a2s ((const struct sockaddr *) &in_sto,
1615 sto_len));
1616 switch (in->sa_family)
1617 {
1618 case AF_INET:
1619 my_port = ntohs (((struct sockaddr_in *) in)->sin_port);
1620 break;
1621
1622 case AF_INET6:
1623 my_port = ntohs (((struct sockaddr_in6 *) in)->sin6_port);
1624 break;
1625
1626 default:
1627 GNUNET_break (0);
1628 my_port = 0;
1629 }
1634 config = quiche_config_new (QUICHE_PROTOCOL_VERSION);
1635 quiche_config_verify_peer (config, false);
1639 quiche_config_load_cert_chain_from_pem_file (config, "./cert.crt");
1640 quiche_config_load_priv_key_from_pem_file (config, "./cert.key");
1641 quiche_config_set_application_protos (config,
1642 (uint8_t *)
1643 "\x0ahq-interop\x05hq-29\x05hq-28\x05hq-27\x08http/0.9",
1644 38);
1645 quiche_config_set_max_idle_timeout (config, 5000);
1646 quiche_config_set_max_recv_udp_payload_size (config, 1200);
1647 quiche_config_set_max_send_udp_payload_size (config, 1200);
1648 quiche_config_set_initial_max_data (config, 10000000);
1649 quiche_config_set_initial_max_stream_data_bidi_local (config, 1000000);
1650 quiche_config_set_initial_max_stream_data_bidi_remote (config, 1000000);
1651 quiche_config_set_initial_max_stream_data_uni (config, 1000000);
1652 quiche_config_set_initial_max_streams_bidi (config, 100);
1653 quiche_config_set_initial_max_streams_uni (config, 100);
1654 quiche_config_set_cc_algorithm (config, QUICHE_CC_RENO);
1655 quiche_config_set_disable_active_migration (config, true);
1660 pils = GNUNET_PILS_connect (cfg, NULL, NULL);
1661 if (NULL == pils)
1662 {
1663 GNUNET_log (
1665 _ (
1666 "Transport service is lacking PILS connection. Exiting.\n"));
1668 return;
1669 }
1670
1671 /* start reading */
1673 udp_sock,
1674 &sock_read,
1675 NULL);
1680 &mq_init,
1681 NULL,
1682 &notify_cb,
1683 NULL,
1684 NULL);
1688 IPPROTO_UDP,
1689 1 /* one address */,
1690 (const struct sockaddr **) &in,
1691 &in_len,
1694 NULL /* closure */);
1695 if (NULL == ch)
1696 {
1697 GNUNET_break (0);
1699 return;
1700 }
1702 if (NULL == ah)
1703 {
1704 GNUNET_break (0);
1706 return;
1707 }
1708
1709 /* start broadcasting */
1710 // if (GNUNET_YES !=
1711 // GNUNET_CONFIGURATION_get_value_yesno (cfg,
1712 // COMMUNICATOR_CONFIG_SECTION,
1713 // "DISABLE_BROADCAST"))
1714 // {
1715 // broadcast_task = GNUNET_SCHEDULER_add_now (&do_broadcast, NULL);
1716 // }
1717}
1718
1719
1720int
1721main (int argc, char *const *argv)
1722{
1723 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
1725 };
1726 int ret;
1727
1729 "transport",
1730 "Starting quic communicator\n");
1732 argc,
1733 argv,
1734 "gnunet-communicator-quic",
1735 _ ("GNUnet QUIC communicator"),
1736 options,
1737 &run,
1738 NULL))
1739 ? 0
1740 : 1;
1741 return ret;
1742}
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 struct GNUNET_TIME_Relative timeout
User defined timestamp for completing operations.
Definition gnunet-arm.c:118
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 *
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.
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
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(enum GNUNET_CRYPTO_Quality mode, void *buffer, size_t length)
Fill block with a random values.
@ GNUNET_CRYPTO_QUALITY_STRONG
High-quality operations are desired.
#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: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.
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:407
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.
Definition of a command line option.
A 512-bit hashcode.
Handle to a message queue.
Definition mq.c:87
Header for all communications.
Handle to the interface scanner.
Definition nt.c:104
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 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.

◆ CID_LEN

#define CID_LEN   sizeof(uint8_t) * QUICHE_MAX_CONN_ID_LEN

Definition at line 62 of file gnunet-communicator-quic.c.

◆ TOKEN_LEN

#define TOKEN_LEN   sizeof (uint8_t) * MAX_TOKEN_LEN

Definition at line 63 of file gnunet-communicator-quic.c.

◆ STREAMID_BI

#define STREAMID_BI   4

Definition at line 68 of file gnunet-communicator-quic.c.

◆ ADDRESS_VALIDITY_PERIOD

#define ADDRESS_VALIDITY_PERIOD   GNUNET_TIME_UNIT_HOURS

How long do we believe our addresses to remain up (before the other peer should revalidate).

Definition at line 74 of file gnunet-communicator-quic.c.

Function Documentation

◆ recv_from_streams()

static void recv_from_streams ( struct PeerAddress peer)
static

Given a PeerAddress, receive data from streams after doing connection logic.

ASSUMES: connection is established to peer

FIXME: Do not use implicit booleans. Use GNUNET_YES, GNUNET_NO, GNUNET_SYSERR and check for that.

Initial packet should contain peerid if they are the initiator

Parse messages to pass to communicator

Check for leftover bytes

FIXME: comment useless fin

Definition at line 285 of file gnunet-communicator-quic.c.

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}

References ADDRESS_VALIDITY_PERIOD, ch, PeerAddress::conn, quic_conn::conn, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_log, GNUNET_NO, GNUNET_TRANSPORT_communicator_receive(), GNUNET_YES, PeerAddress::id_rcvd, PeerAddress::is_receiver, pid, GNUNET_MessageHeader::size, and PeerAddress::target.

Referenced by sock_read().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ mint_token()

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 
)
static

FIXME: review token generation, assure tokens are generated properly.

doxygen

Definition at line 392 of file gnunet-communicator-quic.c.

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}

References GNUNET_memcpy.

Referenced by sock_read().

Here is the caller graph for this function:

◆ validate_token()

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

Definition at line 405 of file gnunet-communicator-quic.c.

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}

References GNUNET_NO, and GNUNET_OK.

Referenced by sock_read().

Here is the caller graph for this function:

◆ create_conn()

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

Definition at line 439 of file gnunet-communicator-quic.c.

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);
454 return NULL;
455 }
456
458 q_conn = quiche_accept (conn->cid, LOCAL_CONN_ID_LEN,
459 odcid, odcid_len,
461 local_addr_len,
462 (struct sockaddr *) peer_addr,
463 peer_addr_len,
464 config);
465 if (NULL == q_conn)
466 {
468 "quiche failed to create connection after call to quiche_accept\n");
469 return NULL;
470 }
471 conn->conn = q_conn;
472 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "new quic connection created\n");
473 return conn;
474}

References config, quic_conn::conn, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_log, GNUNET_memcpy, GNUNET_new, local_addr, and LOCAL_CONN_ID_LEN.

Referenced by sock_read().

Here is the caller graph for this function:

◆ flush_egress()

static void flush_egress ( struct quic_conn conn)
static

Definition at line 478 of file gnunet-communicator-quic.c.

479{
480 static uint8_t out[MAX_DATAGRAM_SIZE];
481 quiche_send_info send_info;
482
483 ssize_t written;
484 ssize_t sent;
485
486 while (1)
487 {
488 written = quiche_conn_send (conn->conn, out, sizeof(out), &send_info);
489 if (QUICHE_ERR_DONE == written)
490 {
491 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "done writing quic packets\n");
492 break;
493 }
494 if (0 > written)
495 {
497 "quiche failed to create packet. quiche error: %zd\n",
498 written);
499 return;
500 }
501 sent = GNUNET_NETWORK_socket_sendto (udp_sock, out, written,
502 (struct sockaddr *) &send_info.to,
503 send_info.to_len);
504 if (sent != written)
505 {
507 "quiche failed to send data to peer\n");
508 return;
509 }
510 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sent %zd bytes\n", sent);
511 }
512}

References quic_conn::conn, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_log, GNUNET_NETWORK_socket_sendto(), MAX_DATAGRAM_SIZE, and udp_sock.

Referenced by mq_init(), mq_send_d(), and sock_read().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ reschedule_peer_timeout()

static void reschedule_peer_timeout ( struct PeerAddress peer)
static

Increment receiver timeout due to activity.

Parameters
receiveraddress for which the timeout should be rescheduled

Definition at line 521 of file gnunet-communicator-quic.c.

522{
523 peer->timeout =
525 // GNUNET_CONTAINER_heap_update_cost (peer->hn,
526 // peer->timeout.abs_value_us);
527}

References GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, GNUNET_TIME_relative_to_absolute(), and PeerAddress::timeout.

Referenced by mq_send_d().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ peer_destroy()

static void peer_destroy ( struct PeerAddress peer)
static

Destroys a receiving state due to timeout or shutdown.

Parameters
receiverentity to close down

Remove peer from hashmap

Definition at line 536 of file gnunet-communicator-quic.c.

537{
538 struct GNUNET_HashCode addr_key;
539
542 "Disconnecting peer for peer `%s'\n",
543 GNUNET_i2s (&peer->target));
544 if (NULL != peer->d_qh)
545 {
547 peer->d_qh = NULL;
548 }
549 // GNUNET_assert (peer == GNUNET_CONTAINER_heap_remove_node (peer->hn));
553 GNUNET_CRYPTO_hash (peer->address, peer->address_len, &addr_key);
555 peer))
556 {
558 "tried to remove non-existent peer from addr map\n");
559 return;
560 }
562 "# peers active",
564 GNUNET_NO);
565 quiche_conn_free (peer->conn->conn);
566 GNUNET_free (peer->address);
568 GNUNET_free (peer->conn);
569 GNUNET_free (peer);
570}

References addr_map, PeerAddress::address, PeerAddress::address_len, PeerAddress::conn, quic_conn::conn, PeerAddress::d_qh, PeerAddress::foreign_addr, GNUNET_CONTAINER_multihashmap_remove(), GNUNET_CONTAINER_multihashmap_size(), GNUNET_CRYPTO_hash(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_i2s(), GNUNET_log, GNUNET_NO, GNUNET_STATISTICS_set(), GNUNET_TRANSPORT_communicator_mq_del(), GNUNET_YES, PeerAddress::peer_destroy_called, stats, and PeerAddress::target.

Referenced by get_peer_delete_it(), mq_destroy_d(), mq_error(), mq_send_d(), and sock_read().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_peer_delete_it()

static int get_peer_delete_it ( void *  cls,
const struct GNUNET_HashCode key,
void *  value 
)
static

Iterator over all peers to clean up.

Parameters
clsNULL
keypeer->address
valuethe peer to destroy
Returns
GNUNET_OK to continue to iterate

Definition at line 582 of file gnunet-communicator-quic.c.

585{
586 struct PeerAddress *peer = value;
587 (void) cls;
588 (void) key;
589 peer_destroy (peer);
590 return GNUNET_OK;
591}

References GNUNET_OK, key, peer_destroy(), and value.

Referenced by do_shutdown().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ mq_send_d()

static void mq_send_d ( struct GNUNET_MQ_Handle mq,
const struct GNUNET_MessageHeader msg,
void *  impl_state 
)
static

Signature of functions implementing the sending functionality of a message queue.

Parameters
mqthe message queue
msgthe message to send
impl_stateour struct PeerAddress

Definition at line 603 of file gnunet-communicator-quic.c.

606{
607 struct PeerAddress *peer = impl_state;
608 uint16_t msize = ntohs (msg->size);
609 ssize_t send_len;
610 uint64_t err_code;
611
612 if (NULL == peer->conn->conn)
613 {
615 "peer never established quic connection\n");
616 return;
617 }
618
619 GNUNET_assert (mq == peer->d_mq);
620 if (msize > peer->d_mtu)
621 {
623 "msize: %u, mtu: %lu\n",
624 msize,
625 peer->d_mtu);
626 GNUNET_break (0);
627 if (GNUNET_YES != peer->peer_destroy_called)
628 {
630 "peer destroy called, destroying peer\n");
631 peer_destroy (peer);
632 }
633 return;
634 }
636
637 send_len = quiche_conn_stream_send (peer->conn->conn, 4, (uint8_t *) msg,
638 msize, false, &err_code);
639 if (send_len != msize)
640 {
642 "tried to send message and quiche returned %zd; error_code %"
643 PRIu64,
644 send_len, err_code);
645 return;
646 }
647 flush_egress (peer->conn);
649 "sent a message of %zd bytes\n", send_len);
651}

References PeerAddress::conn, quic_conn::conn, PeerAddress::d_mq, PeerAddress::d_mtu, flush_egress(), GNUNET_assert, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_log, GNUNET_MQ_impl_send_continue(), GNUNET_YES, mq, msg, peer_destroy(), PeerAddress::peer_destroy_called, reschedule_peer_timeout(), and GNUNET_MessageHeader::size.

Referenced by setup_peer_mq().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ mq_destroy_d()

static void mq_destroy_d ( struct GNUNET_MQ_Handle mq,
void *  impl_state 
)
static

Signature of functions implementing the destruction of a message queue.

Implementations must not free mq, but should take care of impl_state.

Parameters
mqthe message queue to destroy
impl_stateour struct PeerAddress

Definition at line 663 of file gnunet-communicator-quic.c.

664{
665 struct PeerAddress *peer = impl_state;
667 "Default MQ destroyed\n");
668 if (mq == peer->d_mq)
669 {
670 peer->d_mq = NULL;
671 if (GNUNET_YES != peer->peer_destroy_called)
672 peer_destroy (peer);
673 }
674}

References PeerAddress::d_mq, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_YES, mq, peer_destroy(), and PeerAddress::peer_destroy_called.

Referenced by setup_peer_mq().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ mq_cancel()

static void mq_cancel ( struct GNUNET_MQ_Handle mq,
void *  impl_state 
)
static

Implementation function that cancels the currently sent message.

Parameters
mqmessage queue
impl_stateour struct PeerAddress

Definition at line 684 of file gnunet-communicator-quic.c.

685{
686 /* Cancellation is impossible with QUIC; bail */
687 GNUNET_assert (0);
688}

References GNUNET_assert.

Referenced by setup_peer_mq().

Here is the caller graph for this function:

◆ mq_error()

static void mq_error ( void *  cls,
enum GNUNET_MQ_Error  error 
)
static

Generic error handler, called with the appropriate error code and the same closure specified at the creation of the message queue.

Not every message queue implementation supports an error handler.

Parameters
clsour struct ReceiverAddress
errorerror code

Definition at line 701 of file gnunet-communicator-quic.c.

702{
703 struct PeerAddress *peer = cls;
704
706 "MQ error in queue to %s: %d\n",
707 GNUNET_i2s (&peer->target),
708 (int) error);
709 peer_destroy (peer);
710}

References GNUNET_ERROR_TYPE_ERROR, GNUNET_i2s(), GNUNET_log, peer_destroy(), and PeerAddress::target.

Referenced by setup_peer_mq().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ udp_address_to_sockaddr()

static struct sockaddr * udp_address_to_sockaddr ( const char *  bindto,
socklen_t *  sock_len 
)
static

Convert UDP bind specification to a struct sockaddr *

Parameters
bindtobind specification to convert
[out]sock_lenset to the length of the address
Returns
converted bindto specification

Definition at line 721 of file gnunet-communicator-quic.c.

722{
723 struct sockaddr *in;
724 unsigned int port;
725 char dummy[2];
726 char *colon;
727 char *cp;
728
729 if (1 == sscanf (bindto, "%u%1s", &port, dummy))
730 {
731 /* interpreting value as just a PORT number */
732 if (port > UINT16_MAX)
733 {
735 "BINDTO specification `%s' invalid: value too large for port\n",
736 bindto);
737 return NULL;
738 }
739 if ((GNUNET_NO == GNUNET_NETWORK_test_pf (PF_INET6)) ||
740 (GNUNET_YES ==
743 "DISABLE_V6")))
744 {
745 struct sockaddr_in *i4;
746
747 i4 = GNUNET_malloc (sizeof(struct sockaddr_in));
748 i4->sin_family = AF_INET;
749 i4->sin_port = htons ((uint16_t) port);
750 *sock_len = sizeof(struct sockaddr_in);
751 in = (struct sockaddr *) i4;
752 }
753 else
754 {
755 struct sockaddr_in6 *i6;
756
757 i6 = GNUNET_malloc (sizeof(struct sockaddr_in6));
758 i6->sin6_family = AF_INET6;
759 i6->sin6_port = htons ((uint16_t) port);
760 *sock_len = sizeof(struct sockaddr_in6);
761 in = (struct sockaddr *) i6;
762 }
763 return in;
764 }
765 cp = GNUNET_strdup (bindto);
766 colon = strrchr (cp, ':');
767 if (NULL != colon)
768 {
769 /* interpret value after colon as port */
770 *colon = '\0';
771 colon++;
772 if (1 == sscanf (colon, "%u%1s", &port, dummy))
773 {
774 /* interpreting value as just a PORT number */
775 if (port > UINT16_MAX)
776 {
778 "BINDTO specification `%s' invalid: value too large for port\n",
779 bindto);
780 GNUNET_free (cp);
781 return NULL;
782 }
783 }
784 else
785 {
786 GNUNET_log (
788 "BINDTO specification `%s' invalid: last ':' not followed by number\n",
789 bindto);
790 GNUNET_free (cp);
791 return NULL;
792 }
793 }
794 else
795 {
796 /* interpret missing port as 0, aka pick any free one */
797 port = 0;
798 }
799 {
800 /* try IPv4 */
801 struct sockaddr_in v4;
802
803 memset (&v4, 0, sizeof(v4));
804 if (1 == inet_pton (AF_INET, cp, &v4.sin_addr))
805 {
806 v4.sin_family = AF_INET;
807 v4.sin_port = htons ((uint16_t) port);
808#if HAVE_SOCKADDR_IN_SIN_LEN
809 v4.sin_len = sizeof(struct sockaddr_in);
810#endif
811 in = GNUNET_memdup (&v4, sizeof(struct sockaddr_in));
812 *sock_len = sizeof(struct sockaddr_in);
813 GNUNET_free (cp);
814 return in;
815 }
816 }
817 {
818 /* try IPv6 */
819 struct sockaddr_in6 v6;
820 const char *start;
821
822 memset (&v6, 0, sizeof(v6));
823 start = cp;
824 if (('[' == *cp) && (']' == cp[strlen (cp) - 1]))
825 {
826 start++; /* skip over '[' */
827 cp[strlen (cp) - 1] = '\0'; /* eat ']' */
828 }
829 if (1 == inet_pton (AF_INET6, start, &v6.sin6_addr))
830 {
831 v6.sin6_family = AF_INET6;
832 v6.sin6_port = htons ((uint16_t) port);
833#if HAVE_SOCKADDR_IN_SIN_LEN
834 v6.sin6_len = sizeof(sizeof(struct sockaddr_in6));
835#endif
836 in = GNUNET_memdup (&v6, sizeof(v6));
837 *sock_len = sizeof(v6);
838 GNUNET_free (cp);
839 return in;
840 }
841 }
842 /* #5528 FIXME (feature!): maybe also try getnameinfo()? */
843 GNUNET_free (cp);
844 return NULL;
845}

References cfg, COMMUNICATOR_CONFIG_SECTION, dummy, GNUNET_CONFIGURATION_get_value_yesno(), GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_log, GNUNET_malloc, GNUNET_memdup, GNUNET_NETWORK_test_pf(), GNUNET_NO, GNUNET_strdup, GNUNET_YES, port, and start.

Referenced by mq_init(), run(), and sock_read().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ setup_peer_mq()

static void setup_peer_mq ( struct PeerAddress peer)
static

Setup the MQ for the peer.

If a queue exists, the existing one is destroyed. Then the MTU is recalculated and a fresh queue is initialized.

Parameters
peerpeer to setup MQ for

Definition at line 856 of file gnunet-communicator-quic.c.

857{
858 size_t base_mtu;
859
860 switch (peer->address->sa_family)
861 {
862 case AF_INET:
863 base_mtu = 1480 /* Ethernet MTU, 1500 - Ethernet header - VLAN tag */
864 - sizeof(struct GNUNET_TUN_IPv4Header) /* 20 */
865 - sizeof(struct GNUNET_TUN_UdpHeader) /* 8 */;
866 break;
867
868 case AF_INET6:
869 base_mtu = 1280 /* Minimum MTU required by IPv6 */
870 - sizeof(struct GNUNET_TUN_IPv6Header) /* 40 */
871 - sizeof(struct GNUNET_TUN_UdpHeader) /* 8 */;
872 break;
873
874 default:
875 GNUNET_assert (0);
876 break;
877 }
878 /* MTU == base_mtu */
879 peer->d_mtu = base_mtu;
880
882 "Setting up MQs and QHs\n");
883 /* => Effective MTU for CORE will range from 1080 (IPv6 + KX) to
884 1404 (IPv4 + Box) bytes, depending on circumstances... */
885
886 if (NULL == peer->d_mq)
889 &mq_cancel,
890 peer,
891 NULL,
892 &mq_error,
893 peer);
894 peer->d_qh =
896 &peer->target,
897 peer->foreign_addr,
898 1000,
900 0, /* Priority */
901 peer->nt,
903 peer->d_mq);
904}

References PeerAddress::address, ch, PeerAddress::d_mq, PeerAddress::d_mtu, PeerAddress::d_qh, PeerAddress::foreign_addr, GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_MQ_queue_for_callbacks(), GNUNET_TRANSPORT_communicator_mq_add(), GNUNET_TRANSPORT_CS_OUTBOUND, GNUNET_TRANSPORT_QUEUE_LENGTH_UNLIMITED, mq_cancel(), mq_destroy_d(), mq_error(), mq_send_d(), PeerAddress::nt, and PeerAddress::target.

Referenced by sock_read().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ sockaddr_to_udpaddr_string()

static char * sockaddr_to_udpaddr_string ( const struct sockaddr *  address,
socklen_t  address_len 
)
static

Taken from: UDP communicator Converts address to the address string format used by this communicator in HELLOs.

Parameters
addressthe address to convert, must be AF_INET or AF_INET6.
address_lennumber of bytes in address
Returns
string representation of address

Definition at line 917 of file gnunet-communicator-quic.c.

919{
920 char *ret;
921
922 switch (address->sa_family)
923 {
924 case AF_INET:
926 "%s-%s",
928 GNUNET_a2s (address, address_len));
929 break;
930
931 case AF_INET6:
933 "%s-%s",
935 GNUNET_a2s (address, address_len));
936 break;
937
938 default:
939 GNUNET_assert (0);
940 }
941 return ret;
942}

References address, COMMUNICATOR_ADDRESS_PREFIX, GNUNET_a2s(), GNUNET_asprintf(), GNUNET_assert, and ret.

Referenced by mq_init(), and sock_read().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ notify_cb()

static void notify_cb ( void *  cls,
const struct GNUNET_PeerIdentity sender,
const struct GNUNET_MessageHeader msg 
)
static

Function called when the transport service has received a backchannel message for this communicator (!) via a different return path.

Should be an acknowledgement.

Parameters
clsclosure, NULL
senderwhich peer sent the notification
msgpayload

Definition at line 955 of file gnunet-communicator-quic.c.

958{
959 // const struct UDPAck *ack;
960
961 // (void) cls;
962 // GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
963 // "Storing UDPAck received from backchannel from %s\n",
964 // GNUNET_i2s_full (sender));
965 // if ((ntohs (msg->type) != GNUNET_MESSAGE_TYPE_COMMUNICATOR_UDP_ACK) ||
966 // (ntohs (msg->size) != sizeof(struct UDPAck)))
967 // {
968 // GNUNET_break_op (0);
969 // return;
970 // }
971 // ack = (const struct UDPAck *) msg;
972 // GNUNET_CONTAINER_multipeermap_get_multiple (receivers,
973 // sender,
974 // &handle_ack,
975 // (void *) ack);
976}

Referenced by run().

Here is the caller graph for this function:

◆ mq_init()

static int mq_init ( void *  cls,
const struct GNUNET_PeerIdentity peer_id,
const char *  address 
)
static

Function called by the transport service to initialize a message queue given address information about another peer.

If and when the communication channel is established, the communicator must call GNUNET_TRANSPORT_communicator_mq_add() to notify the service that the channel is now up. It is the responsibility of the communicator to manage sane retries and timeouts for any peer/address combination provided by the transport service. Timeouts and retries do not need to be signalled to the transport service.

Parameters
clsclosure
peeridentity of the other peer
addresswhere to send the message, human-readable communicator-specific format, 0-terminated, UTF-8
Returns
GNUNET_OK on success, GNUNET_SYSERR if the provided address is invalid

If we already have a queue with this peer, ignore

Insert peer into hashmap

Before setting up peer mq, initiate a quic connection to the target (perform handshake w/ quiche)

TODO: handle this

Definition at line 998 of file gnunet-communicator-quic.c.

1000{
1001 struct PeerAddress *peer;
1002 const char *path;
1003 struct sockaddr *in;
1004 socklen_t in_len;
1005 struct GNUNET_HashCode addr_key;
1006 uint8_t scid[LOCAL_CONN_ID_LEN];
1007
1008 struct quic_conn *q_conn;
1009 char *bindto;
1010 socklen_t local_in_len;
1011 struct sockaddr *local_addr;
1012
1013 if (GNUNET_OK !=
1016 "BINDTO",
1017 &bindto))
1018 {
1021 "BINDTO");
1022 return GNUNET_SYSERR;
1023 }
1024 local_addr = udp_address_to_sockaddr (bindto, &local_in_len);
1025
1026 if (0 != strncmp (address,
1028 strlen (COMMUNICATOR_ADDRESS_PREFIX "-")))
1029 {
1030 GNUNET_break_op (0);
1031 return GNUNET_SYSERR;
1032 }
1033 path = &address[strlen (COMMUNICATOR_ADDRESS_PREFIX "-")];
1034 in = udp_address_to_sockaddr (path, &in_len);
1035 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "mq_init in_len length before: %d\n",
1036 in_len);
1040 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "address string in mq_init: %s\n",
1041 address);
1042 GNUNET_CRYPTO_hash (address, strlen (address), &addr_key);
1043 peer = GNUNET_CONTAINER_multihashmap_get (addr_map, &addr_key);
1044 if (NULL != peer)
1045 {
1047 "ignoring transport service mq request, we already have an mq with this peer (address)\n");
1048 return GNUNET_SYSERR;
1049 }
1050 peer = GNUNET_new (struct PeerAddress);
1051 peer->address = in;
1052 peer->address_len = in_len;
1053 peer->target = *peer_id;
1054 peer->id_rcvd = GNUNET_YES;
1055 peer->is_receiver = GNUNET_YES;
1056 peer->nt = GNUNET_NT_scanner_get_type (is, in, in_len);
1057 peer->timeout =
1060 "# peers active",
1062 GNUNET_NO);
1063 peer->foreign_addr =
1069 peer,
1072 "mq_init added new peer to the addr map\n");
1078 q_conn = GNUNET_new (struct quic_conn);
1079 GNUNET_memcpy (q_conn->cid, scid, LOCAL_CONN_ID_LEN);
1080 peer->conn = q_conn;
1082 "attempting to perform QUIC handshake with peer\n");
1083 q_conn->conn = quiche_connect (peer->foreign_addr, scid, LOCAL_CONN_ID_LEN,
1084 local_addr,
1085 local_in_len, peer->address, peer->address_len,
1086 config);
1087 flush_egress (peer->conn);
1089 return GNUNET_OK;
1093 // if (NULL == timeout_task)
1094 // timeout_task = GNUNET_SCHEDULER_add_now (&check_timeouts, NULL);
1095}

References addr_map, address, PeerAddress::address, PeerAddress::address_len, cfg, quic_conn::cid, COMMUNICATOR_ADDRESS_PREFIX, COMMUNICATOR_CONFIG_SECTION, config, PeerAddress::conn, quic_conn::conn, flush_egress(), PeerAddress::foreign_addr, GNUNET_break_op, GNUNET_CONFIGURATION_get_value_string(), GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, GNUNET_CONTAINER_multihashmap_get(), GNUNET_CONTAINER_multihashmap_put(), GNUNET_CONTAINER_multihashmap_size(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY, GNUNET_CRYPTO_hash(), GNUNET_CRYPTO_QUALITY_STRONG, GNUNET_CRYPTO_random_block(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_log, GNUNET_log_config_missing(), GNUNET_memcpy, GNUNET_new, GNUNET_NO, GNUNET_NT_scanner_get_type(), GNUNET_OK, GNUNET_STATISTICS_set(), GNUNET_SYSERR, GNUNET_TIME_relative_to_absolute(), GNUNET_YES, PeerAddress::id_rcvd, is, PeerAddress::is_receiver, local_addr, LOCAL_CONN_ID_LEN, PeerAddress::nt, peer_id, sockaddr_to_udpaddr_string(), stats, PeerAddress::target, PeerAddress::timeout, and udp_address_to_sockaddr().

Referenced by run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ try_connection_reversal()

static void try_connection_reversal ( void *  cls,
const struct sockaddr *  addr,
socklen_t  addrlen 
)
static

Definition at line 1099 of file gnunet-communicator-quic.c.

1102{
1103 /* FIXME: support reversal: #5529 */
1105 "No connection reversal implemented!");
1106}

References GNUNET_ERROR_TYPE_INFO, and GNUNET_log.

Referenced by run().

Here is the caller graph for this function:

◆ nat_address_cb()

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 
)
static

Signature of the callback passed to GNUNET_NAT_register() for a function to call whenever our set of 'valid' addresses changes.

Parameters
clsclosure
app_ctx[in,out]location where the app can store stuff on add and retrieve it on remove
add_removeGNUNET_YES to add a new public IP address, GNUNET_NO to remove a previous (now invalid) one
acaddress class the address belongs to
addreither the previous or the new public IP address
addrlenactual length of the addr

Definition at line 1123 of file gnunet-communicator-quic.c.

1129{
1130 char *my_addr;
1132
1133 if (GNUNET_YES == add_remove)
1134 {
1136
1137 GNUNET_asprintf (&my_addr,
1138 "%s-%s",
1140 GNUNET_a2s (addr, addrlen));
1141 nt = GNUNET_NT_scanner_get_type (is, addr, addrlen);
1142 ai =
1144 my_addr,
1145 nt,
1147 GNUNET_free (my_addr);
1148 *app_ctx = ai;
1149 }
1150 else
1151 {
1152 ai = *app_ctx;
1154 *app_ctx = NULL;
1155 }
1156}

References ai, ch, COMMUNICATOR_ADDRESS_PREFIX, GNUNET_a2s(), GNUNET_asprintf(), GNUNET_free, GNUNET_NT_scanner_get_type(), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_TRANSPORT_communicator_address_add(), GNUNET_TRANSPORT_communicator_address_remove(), GNUNET_YES, is, and nt.

Referenced by run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ do_shutdown()

static void do_shutdown ( void *  cls)
static

Shutdown the QUIC communicator.

Parameters
clsNULL (always)

Definition at line 1165 of file gnunet-communicator-quic.c.

1166{
1168 "do_shutdown\n");
1171 quiche_config_free (config);
1172
1173 if (NULL != timeout_task)
1174 {
1176 timeout_task = NULL;
1177 }
1178 if (NULL != read_task)
1179 {
1181 read_task = NULL;
1182 }
1183 if (NULL != udp_sock)
1184 {
1187 udp_sock = NULL;
1188 }
1189 if (NULL != ch)
1190 {
1192 ch = NULL;
1193 }
1194 if (NULL != ah)
1195 {
1197 ah = NULL;
1198 }
1199 if (NULL != pils)
1200 {
1202 pils = NULL;
1203 }
1205 "do_shutdown finished\n");
1206}

References addr_map, ah, ch, config, get_peer_delete_it(), GNUNET_break, GNUNET_CONTAINER_multihashmap_destroy(), GNUNET_CONTAINER_multihashmap_iterate(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_NETWORK_socket_close(), GNUNET_OK, GNUNET_PILS_disconnect(), GNUNET_SCHEDULER_cancel(), GNUNET_TRANSPORT_application_done(), GNUNET_TRANSPORT_communicator_disconnect(), pils, read_task, timeout_task, and udp_sock.

Here is the call graph for this function:

◆ sock_read()

static void sock_read ( void *  cls)
static

Get local_addr, in_len for quiche

FIXME: hashing address string vs ip/port. It is not ideal that we hash the string, instead of the binary representation, but for now it is certainly less code. Note that simply hashing the sockaddr does NOT work because the the struct is not portable.

Create new PeerAddress (receiver) with id_rcvd = false

TODO: after connection established

Parse QUIC info

New QUIC connection with peer

FIXME variables are redeclared often. Refactor either to declare variables once in the beginning or refactor into method.

Write a version negotiation packet to "out"

Send our PeerIdentity if the connection is established now

After this, we should be all good to send/recv data

TODO: Should we use a list instead of hashmap? Overhead for hashing function, O(1) retrieval vs O(n) iteration with n=30?

TODO: Is iteration necessary as in the quiche server example?

Definition at line 1210 of file gnunet-communicator-quic.c.

1211{
1212 struct sockaddr_storage sa;
1213 socklen_t salen = sizeof(sa);
1214 uint8_t buf[UINT16_MAX];
1215 uint8_t out[MAX_DATAGRAM_SIZE];
1216 ssize_t rcvd;
1217
1218 ssize_t process_pkt;
1219 struct QUIC_header quic_header;
1220
1221 struct PeerAddress *peer;
1222 struct GNUNET_HashCode addr_key;
1223
1224 (void) cls;
1225 quic_header.scid_len = sizeof(quic_header.scid);
1226 quic_header.dcid_len = sizeof(quic_header.dcid);
1227 quic_header.odcid_len = sizeof(quic_header.odcid);
1228 quic_header.token_len = sizeof(quic_header.token);
1232 char *bindto;
1233 socklen_t in_len;
1234 if (GNUNET_OK !=
1237 "BINDTO",
1238 &bindto))
1239 {
1242 "BINDTO");
1243 return;
1244 }
1245 struct sockaddr *local_addr = udp_address_to_sockaddr (bindto, &in_len);
1246
1248 udp_sock,
1249 &sock_read,
1250 NULL);
1251 while (1)
1252 {
1254 buf,
1255 sizeof(buf),
1256 (struct sockaddr *) &sa,
1257 &salen);
1258 if (-1 == rcvd)
1259 {
1260 if (EAGAIN == errno)
1261 break; // We are done reading data
1263 return;
1264 }
1265
1267 "Read %lu bytes\n", rcvd);
1268
1269 if (-1 == rcvd)
1270 {
1272 return;
1273 }
1281 char *addr_string = sockaddr_to_udpaddr_string ((const struct
1282 sockaddr *) &sa,
1283 salen);
1284 GNUNET_CRYPTO_hash (addr_string, strlen (addr_string),
1285 &addr_key);
1286 GNUNET_free (addr_string);
1287 peer = GNUNET_CONTAINER_multihashmap_get (addr_map, &addr_key);
1288
1289 if (NULL == peer)
1290 {
1294 peer = GNUNET_new (struct PeerAddress);
1295 peer->address = GNUNET_memdup (&sa, salen);
1296 peer->address_len = salen;
1297 peer->id_rcvd = GNUNET_NO;
1298 peer->id_sent = GNUNET_NO;
1299 peer->is_receiver = GNUNET_NO;
1300 peer->conn = NULL;
1302 peer->address_len);
1306 // setup_peer_mq (peer);
1308 &addr_key,
1309 peer,
1311 {
1313 "tried to add duplicate address into address map\n");
1314 return;
1315 }
1317 "sock_read added new peer to address map\n");
1318 }
1319
1323 int rc = quiche_header_info (buf, rcvd, LOCAL_CONN_ID_LEN,
1324 &quic_header.version,
1325 &quic_header.type, quic_header.scid,
1326 &quic_header.scid_len, quic_header.dcid,
1327 &quic_header.dcid_len,
1328 quic_header.token, &quic_header.token_len);
1329 if (0 > rc)
1330 {
1332 "failed to parse quic header: %d\n",
1333 rc);
1334 return;
1335 }
1336
1340 if (NULL == peer->conn)
1341 {
1343 "attempting to create new connection\n");
1344 if (0 == quiche_version_is_supported (quic_header.version))
1345 {
1347 "quic version negotiation initiated\n");
1355 ssize_t written = quiche_negotiate_version (quic_header.scid,
1356 quic_header.scid_len,
1357 quic_header.dcid,
1358 quic_header.dcid_len,
1359 out, sizeof(out));
1360 if (0 > written)
1361 {
1363 "quiche failed to generate version negotiation packet\n");
1364 return;
1365 }
1366 ssize_t sent = GNUNET_NETWORK_socket_sendto (udp_sock,
1367 out,
1368 written,
1369 (struct sockaddr*) &sa,
1370 salen);
1371 if (sent != written)
1372 {
1374 "failed to send version negotiation packet to peer\n");
1375 return;
1376 }
1378 "sent %zd bytes to peer during version negotiation\n",
1379 sent);
1380 return;
1381 }
1382
1383 if (0 == quic_header.token_len)
1384 {
1385 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "quic stateless retry\n");
1386 mint_token (quic_header.dcid, quic_header.dcid_len, &sa, salen,
1387 quic_header.token, &quic_header.token_len);
1388
1389 uint8_t new_cid[LOCAL_CONN_ID_LEN];
1392
1393 ssize_t written = quiche_retry (quic_header.scid, quic_header.scid_len,
1394 quic_header.dcid, quic_header.dcid_len,
1395 new_cid, LOCAL_CONN_ID_LEN,
1396 quic_header.token,
1397 quic_header.token_len,
1398 quic_header.version, out, sizeof(out));
1399 if (0 > written)
1400 {
1402 "quiche failed to write retry packet\n");
1403 return;
1404 }
1405 ssize_t sent = GNUNET_NETWORK_socket_sendto (udp_sock,
1406 out,
1407 written,
1408 (struct sockaddr*) &sa,
1409 salen);
1410 if (written != sent)
1411 {
1412 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "failed to send retry packet\n");
1413 return;
1414 }
1415
1416 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sent %zd bytes\n", sent);
1417 continue;
1418 }
1419
1420 if (GNUNET_OK != validate_token (quic_header.token, quic_header.token_len,
1421 &sa, salen,
1422 quic_header.odcid,
1423 &quic_header.odcid_len))
1424 {
1426 "invalid address validation token created\n");
1427 return;
1428 }
1429 peer->conn = create_conn (quic_header.dcid, quic_header.dcid_len,
1430 quic_header.odcid, quic_header.odcid_len,
1431 local_addr, in_len,
1432 &sa, salen);
1433 if (NULL == peer->conn)
1434 {
1436 "failed to create quic connection with peer\n");
1437 return;
1438 }
1439 } // null connection
1440
1441 quiche_recv_info recv_info = {
1442 (struct sockaddr *) &sa,
1443 salen,
1444
1445 local_addr,
1446 in_len,
1447 };
1451 if (quiche_conn_is_established (peer->conn->conn) && ! peer->id_sent &&
1452 peer->is_receiver)
1453 {
1454 const struct GNUNET_PeerIdentity *my_identity;
1455 ssize_t send_len;
1456 uint64_t err_code;
1457
1459 "handshake established with peer, sending our peer id\n");
1460
1463
1464 send_len = quiche_conn_stream_send (peer->conn->conn, STREAMID_BI,
1465 (const uint8_t *) my_identity,
1466 sizeof(*my_identity),
1467 false, &err_code);
1468 if (0 > send_len)
1469 {
1471 "failed to write peer identity packet. quiche error: %"
1472 PRIu64 "; len=%zd\n",
1473 err_code,
1474 send_len);
1475 return;
1476 }
1477 flush_egress (peer->conn);
1478 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "peer identity sent to peer\n");
1479 peer->id_sent = GNUNET_YES;
1480 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "setting up peer mq\n");
1481 setup_peer_mq (peer);
1485 }
1486 process_pkt = quiche_conn_recv (peer->conn->conn, buf, rcvd, &recv_info);
1487 if (0 > process_pkt)
1488 {
1490 "quiche failed to process received packet: %zd\n",
1491 process_pkt);
1492 return;
1493 }
1495 "quiche processed %zd bytes\n", process_pkt);
1496 // Check for data on all available streams if the connection is established
1497 if (GNUNET_YES == quiche_conn_is_established (peer->conn->conn))
1498 {
1499 recv_from_streams (peer);
1500 }
1507 quiche_stats stats;
1508 quiche_path_stats path_stats;
1509
1510 flush_egress (peer->conn);
1511
1512 if (quiche_conn_is_closed (peer->conn->conn))
1513 {
1514 quiche_conn_stats (peer->conn->conn, &stats);
1515 quiche_conn_path_stats (peer->conn->conn, 0, &path_stats);
1516
1518 "connection closed. quiche stats: sent=%zu, recv=%zu\n",
1519 stats.sent, stats.recv);
1520 peer_destroy (peer);
1521 }
1522 }
1524}

References addr_map, PeerAddress::address, PeerAddress::address_len, cfg, COMMUNICATOR_CONFIG_SECTION, PeerAddress::conn, quic_conn::conn, create_conn(), QUIC_header::dcid, QUIC_header::dcid_len, flush_egress(), PeerAddress::foreign_addr, GNUNET_assert, GNUNET_CONFIGURATION_get_value_string(), GNUNET_CONTAINER_multihashmap_get(), GNUNET_CONTAINER_multihashmap_put(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY, GNUNET_CRYPTO_hash(), GNUNET_CRYPTO_QUALITY_STRONG, GNUNET_CRYPTO_random_block(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_log, GNUNET_log_config_missing(), GNUNET_log_strerror, GNUNET_memdup, GNUNET_NETWORK_socket_recvfrom(), GNUNET_NETWORK_socket_sendto(), GNUNET_new, GNUNET_NO, GNUNET_OK, GNUNET_PILS_get_identity(), GNUNET_SCHEDULER_add_read_net(), GNUNET_SYSERR, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, PeerAddress::id_rcvd, PeerAddress::id_sent, PeerAddress::is_receiver, local_addr, LOCAL_CONN_ID_LEN, MAX_DATAGRAM_SIZE, mint_token(), my_identity, QUIC_header::odcid, QUIC_header::odcid_len, peer_destroy(), pils, read_task, recv_from_streams(), QUIC_header::scid, QUIC_header::scid_len, setup_peer_mq(), sock_read(), sockaddr_to_udpaddr_string(), stats, STREAMID_BI, QUIC_header::token, QUIC_header::token_len, QUIC_header::type, udp_address_to_sockaddr(), udp_sock, validate_token(), and QUIC_header::version.

Referenced by run(), and sock_read().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ run()

static void run ( void *  cls,
char *const *  args,
const char *  cfgfile,
const struct GNUNET_CONFIGURATION_Handle c 
)
static

Setup communicator and launch network interactions.

Parameters
clsNULL (always)
argsremaining command-line arguments
cfgfilename of the configuration file used (for saving, can be NULL!)
cconfiguration

Setup QUICHE configuration

TODO: configure TLS cert

Get our public key for initial packet

Definition at line 1536 of file gnunet-communicator-quic.c.

1540{
1541 char *bindto;
1542 struct sockaddr *in;
1543 socklen_t in_len;
1544 struct sockaddr_storage in_sto;
1545 socklen_t sto_len;
1546
1547 (void) cls;
1548 cfg = c;
1549
1550 if (GNUNET_OK !=
1553 "BINDTO",
1554 &bindto))
1555 {
1558 "BINDTO");
1559 return;
1560 }
1561
1562 in = udp_address_to_sockaddr (bindto, &in_len);
1563
1564 if (NULL == in)
1565 {
1567 "Failed to setup UDP socket address with path `%s'\n",
1568 bindto);
1569 GNUNET_free (bindto);
1570 return;
1571 }
1572 udp_sock =
1573 GNUNET_NETWORK_socket_create (in->sa_family,
1574 SOCK_DGRAM,
1575 IPPROTO_UDP);
1576 if (NULL == udp_sock)
1577 {
1579 GNUNET_free (in);
1580 GNUNET_free (bindto);
1581 return;
1582 }
1583 if (AF_INET6 == in->sa_family)
1585 if (GNUNET_OK !=
1587 in,
1588 in_len))
1589 {
1591 "bind",
1592 bindto);
1594 udp_sock = NULL;
1595 GNUNET_free (in);
1596 GNUNET_free (bindto);
1597 return;
1598 }
1599 sto_len = sizeof(in_sto);
1600 if (0 != getsockname (GNUNET_NETWORK_get_fd (udp_sock),
1601 (struct sockaddr *) &in_sto,
1602 &sto_len))
1603 {
1604 memcpy (&in_sto, in, in_len);
1605 sto_len = in_len;
1606 }
1607 GNUNET_free (in);
1608 GNUNET_free (bindto);
1609 in = (struct sockaddr *) &in_sto;
1610 in_len = sto_len;
1612 "transport",
1613 "Bound to `%s'\n",
1614 GNUNET_a2s ((const struct sockaddr *) &in_sto,
1615 sto_len));
1616 switch (in->sa_family)
1617 {
1618 case AF_INET:
1619 my_port = ntohs (((struct sockaddr_in *) in)->sin_port);
1620 break;
1621
1622 case AF_INET6:
1623 my_port = ntohs (((struct sockaddr_in6 *) in)->sin6_port);
1624 break;
1625
1626 default:
1627 GNUNET_break (0);
1628 my_port = 0;
1629 }
1634 config = quiche_config_new (QUICHE_PROTOCOL_VERSION);
1635 quiche_config_verify_peer (config, false);
1639 quiche_config_load_cert_chain_from_pem_file (config, "./cert.crt");
1640 quiche_config_load_priv_key_from_pem_file (config, "./cert.key");
1641 quiche_config_set_application_protos (config,
1642 (uint8_t *)
1643 "\x0ahq-interop\x05hq-29\x05hq-28\x05hq-27\x08http/0.9",
1644 38);
1645 quiche_config_set_max_idle_timeout (config, 5000);
1646 quiche_config_set_max_recv_udp_payload_size (config, 1200);
1647 quiche_config_set_max_send_udp_payload_size (config, 1200);
1648 quiche_config_set_initial_max_data (config, 10000000);
1649 quiche_config_set_initial_max_stream_data_bidi_local (config, 1000000);
1650 quiche_config_set_initial_max_stream_data_bidi_remote (config, 1000000);
1651 quiche_config_set_initial_max_stream_data_uni (config, 1000000);
1652 quiche_config_set_initial_max_streams_bidi (config, 100);
1653 quiche_config_set_initial_max_streams_uni (config, 100);
1654 quiche_config_set_cc_algorithm (config, QUICHE_CC_RENO);
1655 quiche_config_set_disable_active_migration (config, true);
1660 pils = GNUNET_PILS_connect (cfg, NULL, NULL);
1661 if (NULL == pils)
1662 {
1663 GNUNET_log (
1665 _ (
1666 "Transport service is lacking PILS connection. Exiting.\n"));
1668 return;
1669 }
1670
1671 /* start reading */
1673 udp_sock,
1674 &sock_read,
1675 NULL);
1680 &mq_init,
1681 NULL,
1682 &notify_cb,
1683 NULL,
1684 NULL);
1688 IPPROTO_UDP,
1689 1 /* one address */,
1690 (const struct sockaddr **) &in,
1691 &in_len,
1694 NULL /* closure */);
1695 if (NULL == ch)
1696 {
1697 GNUNET_break (0);
1699 return;
1700 }
1702 if (NULL == ah)
1703 {
1704 GNUNET_break (0);
1706 return;
1707 }
1708
1709 /* start broadcasting */
1710 // if (GNUNET_YES !=
1711 // GNUNET_CONFIGURATION_get_value_yesno (cfg,
1712 // COMMUNICATOR_CONFIG_SECTION,
1713 // "DISABLE_BROADCAST"))
1714 // {
1715 // broadcast_task = GNUNET_SCHEDULER_add_now (&do_broadcast, NULL);
1716 // }
1717}

References _, addr_map, ah, cfg, ch, COMMUNICATOR_ADDRESS_PREFIX, COMMUNICATOR_CONFIG_SECTION, config, do_shutdown, GNUNET_a2s(), GNUNET_break, GNUNET_CONFIGURATION_get_value_string(), GNUNET_CONTAINER_multihashmap_create(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_log, GNUNET_log_config_missing(), GNUNET_log_from_nocheck(), GNUNET_log_strerror, GNUNET_log_strerror_file, GNUNET_NAT_register(), GNUNET_NETWORK_get_fd(), GNUNET_NETWORK_socket_bind(), GNUNET_NETWORK_socket_close(), GNUNET_NETWORK_socket_create(), GNUNET_NO, GNUNET_NT_scanner_init(), GNUNET_OK, GNUNET_PILS_connect(), GNUNET_SCHEDULER_add_read_net(), GNUNET_SCHEDULER_add_shutdown(), GNUNET_SCHEDULER_shutdown(), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_TRANSPORT_application_init(), GNUNET_TRANSPORT_CC_RELIABLE, GNUNET_TRANSPORT_communicator_connect(), GNUNET_YES, have_v6_socket, is, mq_init(), my_port, nat, nat_address_cb(), notify_cb(), pils, read_task, sock_read(), try_connection_reversal(), udp_address_to_sockaddr(), and udp_sock.

Referenced by main().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ main()

int main ( int  argc,
char *const *  argv 
)

Definition at line 1721 of file gnunet-communicator-quic.c.

1722{
1723 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
1725 };
1726 int ret;
1727
1729 "transport",
1730 "Starting quic communicator\n");
1732 argc,
1733 argv,
1734 "gnunet-communicator-quic",
1735 _ ("GNUnet QUIC communicator"),
1736 options,
1737 &run,
1738 NULL))
1739 ? 0
1740 : 1;
1741 return ret;
1742}

References _, GNUNET_ERROR_TYPE_DEBUG, GNUNET_GETOPT_OPTION_END, GNUNET_log_from_nocheck(), GNUNET_OK, GNUNET_OS_project_data_gnunet(), GNUNET_PROGRAM_run(), options, ret, and run().

Here is the call graph for this function:

Variable Documentation

◆ conn_map

Map of DCID (uint8_t) -> quic_conn for quickly retrieving connections to other peers.

Definition at line 79 of file gnunet-communicator-quic.c.

◆ addr_map

Map of sockaddr -> struct PeerAddress.

Definition at line 84 of file gnunet-communicator-quic.c.

Referenced by do_shutdown(), mq_init(), peer_destroy(), run(), and sock_read().

◆ cfg

const struct GNUNET_CONFIGURATION_Handle* cfg
static

Handle to the config.

Definition at line 89 of file gnunet-communicator-quic.c.

Referenced by mq_init(), run(), sock_read(), and udp_address_to_sockaddr().

◆ udp_sock

struct GNUNET_NETWORK_Handle* udp_sock
static

FIXME undocumented.

Definition at line 94 of file gnunet-communicator-quic.c.

Referenced by do_shutdown(), flush_egress(), run(), and sock_read().

◆ read_task

struct GNUNET_SCHEDULER_Task* read_task
static

FIXME undocumented.

Definition at line 99 of file gnunet-communicator-quic.c.

Referenced by do_shutdown(), run(), and sock_read().

◆ ch

FIXME undocumented.

Definition at line 104 of file gnunet-communicator-quic.c.

Referenced by do_shutdown(), nat_address_cb(), recv_from_streams(), run(), and setup_peer_mq().

◆ ah

FIXME undocumented.

Definition at line 109 of file gnunet-communicator-quic.c.

Referenced by do_shutdown(), and run().

◆ have_v6_socket

int have_v6_socket
static

FIXME undocumented.

Definition at line 114 of file gnunet-communicator-quic.c.

Referenced by run().

◆ my_port

uint16_t my_port
static

FIXME undocumented.

Definition at line 119 of file gnunet-communicator-quic.c.

Referenced by run().

◆ config

quiche_config* config = NULL
static

FIXME undocumented.

Definition at line 124 of file gnunet-communicator-quic.c.

Referenced by create_conn(), do_shutdown(), mq_init(), and run().

◆ pils

struct GNUNET_PILS_Handle* pils

Handle to PILS service.

Handle to Pils service.

Definition at line 129 of file gnunet-communicator-quic.c.

Referenced by do_shutdown(), run(), and sock_read().

◆ nat

struct GNUNET_NAT_Handle* nat
static

Connection to NAT service.

Definition at line 134 of file gnunet-communicator-quic.c.

Referenced by run().

◆ timeout_task

struct GNUNET_SCHEDULER_Task* timeout_task
static

ID of timeout task.

Definition at line 234 of file gnunet-communicator-quic.c.

Referenced by do_shutdown().

◆ is

struct GNUNET_NT_InterfaceScanner* is
static

Network scanner to determine network types.

Definition at line 239 of file gnunet-communicator-quic.c.

Referenced by mq_init(), nat_address_cb(), and run().

◆ stats

struct GNUNET_STATISTICS_Handle* stats
static

For logging statistics.

Definition at line 244 of file gnunet-communicator-quic.c.

Referenced by mq_init(), peer_destroy(), and sock_read().