GNUnet  0.20.0
gnunet-communicator-quic.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet
3  Copyright (C) 2010-2014, 2018, 2019 GNUnet e.V.
4 
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  GNUnet is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Affero General Public License for more details.
14 
15  You should have received a copy of the GNU Affero General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19  */
20 
37 #include "gnunet_common.h"
38 #include "gnunet_util_lib.h"
39 #include "gnunet_core_service.h"
40 #include "quiche.h"
41 #include "platform.h"
42 #include "gnunet_protocols.h"
43 #include "gnunet_signatures.h"
44 #include "gnunet_constants.h"
48 #include "gnunet_nt_lib.h"
49 #include "gnunet_nat_service.h"
50 #include "stdint.h"
51 #include "inttypes.h"
52 
53 #define COMMUNICATOR_CONFIG_SECTION "communicator-quic"
54 #define COMMUNICATOR_ADDRESS_PREFIX "quic"
55 #define MAX_DATAGRAM_SIZE 1350
56 
57 
58 /* FIXME: Review all static lengths/contents below. Maybe this can be done smarter */
59 /* Currently equivalent to QUICHE_MAX_CONN_ID_LEN */
60 #define LOCAL_CONN_ID_LEN 20
61 #define MAX_TOKEN_LEN \
62  sizeof("quiche") - 1 \
63  + sizeof(struct sockaddr_storage) \
64  + QUICHE_MAX_CONN_ID_LEN
65 #define CID_LEN sizeof(uint8_t) * QUICHE_MAX_CONN_ID_LEN
66 #define TOKEN_LEN sizeof (uint8_t) * MAX_TOKEN_LEN
67 
68 
69 /* FIXME: Why 4?
70  Generic, bidirectional, client-initiated quic stream id */
71 #define STREAMID_BI 4
72 
77 #define ADDRESS_VALIDITY_PERIOD GNUNET_TIME_UNIT_HOURS
78 
83 
88 
92 static const struct GNUNET_CONFIGURATION_Handle *cfg;
93 
98 
103 
108 
113 
118 
122 static int have_v6_socket;
123 
127 static uint16_t my_port;
128 
132 static unsigned long long rekey_max_bytes;
133 
137 static quiche_config *config = NULL;
138 
143 
148 
152 static struct GNUNET_NAT_Handle *nat;
153 
163 {
168 
172  int id_rcvd;
173 
177  int id_sent;
178 
183 
189 
193  struct sockaddr *address;
194 
198  socklen_t address_len;
199 
203  struct quic_conn *conn;
204 
209 
214 
219 
224  size_t d_mtu;
225 
229  enum GNUNET_NetworkType nt;
230 
235 
240  // struct GNUNET_CONTAINER_HeapNode *hn;
241 };
242 
243 // /**
244 // * FIXME: Implementation missing
245 // * Expiration heap for peers (contains `struct PeerAddress`)
246 // */
247 // static struct GNUNET_CONTAINER_Heap *peers_heap;
248 
253 
258 
263 
269 struct quic_conn
270 {
272 
273  quiche_conn *conn;
274 };
275 
280 {
281  uint8_t type;
282  uint32_t version;
283 
284  uint8_t scid[QUICHE_MAX_CONN_ID_LEN];
285  size_t scid_len;
286 
287  uint8_t dcid[QUICHE_MAX_CONN_ID_LEN];
288  size_t dcid_len;
289 
290  uint8_t odcid[QUICHE_MAX_CONN_ID_LEN];
291  size_t odcid_len;
292 
294  size_t token_len;
295 };
296 
297 
302 static void
304 {
305  char stream_buf[UINT16_MAX];
306  size_t buf_size = UINT16_MAX;
307  char *buf_ptr = stream_buf;
308  struct GNUNET_MessageHeader *hdr;
309 
310  uint64_t s = 0;
311  quiche_stream_iter *readable;
312  bool fin;
313  ssize_t recv_len;
314 
315  readable = quiche_conn_readable (peer->conn->conn);
316  while (quiche_stream_iter_next (readable, &s))
317  {
318  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "stream %" PRIu64 " is readable\n",
319  s);
320  fin = false;
321  recv_len = quiche_conn_stream_recv (peer->conn->conn, s,
322  (uint8_t *) stream_buf, buf_size,
323  &fin);
324  if (recv_len < 0)
325  {
327  "error while receiving data from stream %" PRIu64 "\n", s);
328  break;
329  }
336  if (! peer->is_receiver && GNUNET_NO == peer->id_rcvd)
337  {
338  if (recv_len < sizeof(struct GNUNET_PeerIdentity))
339  {
341  "message recv len of %zd less than length of peer identity\n",
342  recv_len);
343  return;
344  }
346  "received peer identity\n");
347  struct GNUNET_PeerIdentity *pid = (struct
348  GNUNET_PeerIdentity *) stream_buf;
349  peer->target = *pid;
350  peer->id_rcvd = GNUNET_YES;
351  buf_ptr += sizeof(struct GNUNET_PeerIdentity);
352  recv_len -= sizeof(struct GNUNET_PeerIdentity);
353  }
357  while (recv_len >= sizeof(struct GNUNET_MessageHeader))
358  {
359  hdr = (struct GNUNET_MessageHeader *) buf_ptr;
360  if (ntohs (hdr->size) > recv_len)
361  {
363  "message size stated (%d) is greater than length of rcvd data (%zd)!\n",
364  ntohs (hdr->size), recv_len);
365  return;
366  }
367  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "passing %zd bytes to core\n",
368  recv_len);
371  NULL);
372  recv_len -= ntohs (hdr->size);
373  buf_ptr += ntohs (hdr->size);
374  }
378  if (0 != recv_len)
379  {
381  "message recv len of %zd less than length of message header\n",
382  recv_len);
383  }
388  if (fin)
389  {
391  "fin received, closing connection\n");
392  if (0 > quiche_conn_close (peer->conn->conn, true, 0, NULL, 0))
393  {
395  "quiche failed to close connection to peer\n");
396  }
397  }
398  }
399  quiche_stream_iter_free (readable);
400 }
401 
402 
406 static void
407 mint_token (const uint8_t *dcid, size_t dcid_len,
408  struct sockaddr_storage *addr, socklen_t addr_len,
409  uint8_t *token, size_t *token_len)
410 {
411  GNUNET_memcpy (token, "quiche", sizeof("quiche") - 1);
412  GNUNET_memcpy (token + sizeof("quiche") - 1, addr, addr_len);
413  GNUNET_memcpy (token + sizeof("quiche") - 1 + addr_len, dcid, dcid_len);
414 
415  *token_len = sizeof("quiche") - 1 + addr_len + dcid_len;
416 }
417 
418 
419 static enum GNUNET_GenericReturnValue
420 validate_token (const uint8_t *token, size_t token_len,
421  struct sockaddr_storage *addr, socklen_t addr_len,
422  uint8_t *odcid, size_t *odcid_len)
423 {
424  if ((token_len < sizeof("quiche") - 1) ||
425  memcmp (token, "quiche", sizeof("quiche") - 1))
426  {
427  return GNUNET_NO;
428  }
429 
430  token += sizeof("quiche") - 1;
431  token_len -= sizeof("quiche") - 1;
432 
433  if ((token_len < addr_len) || memcmp (token, addr, addr_len))
434  {
435  return GNUNET_NO;
436  }
437 
438  token += addr_len;
439  token_len -= addr_len;
440 
441  if (*odcid_len < token_len)
442  {
443  return GNUNET_NO;
444  }
445 
446  memcpy (odcid, token, token_len);
447  *odcid_len = token_len;
448 
449  return GNUNET_OK;
450 }
451 
452 
453 static struct quic_conn*
454 create_conn (uint8_t *scid, size_t scid_len,
455  uint8_t *odcid, size_t odcid_len,
456  struct sockaddr *local_addr,
457  socklen_t local_addr_len,
458  struct sockaddr_storage *peer_addr,
459  socklen_t peer_addr_len)
460 {
461  struct quic_conn *conn;
462  quiche_conn *q_conn;
463  conn = GNUNET_new (struct quic_conn);
464  if (scid_len != LOCAL_CONN_ID_LEN)
465  {
467  "error while creating connection, scid length too short: %zu\n",
468  scid_len);
469  return NULL;
470  }
471 
472  GNUNET_memcpy (conn->cid, scid, LOCAL_CONN_ID_LEN);
473  q_conn = quiche_accept (conn->cid, LOCAL_CONN_ID_LEN,
474  odcid, odcid_len,
475  local_addr,
476  local_addr_len,
477  (struct sockaddr *) peer_addr,
478  peer_addr_len,
479  config);
480  if (NULL == q_conn)
481  {
483  "quiche failed to create connection after call to quiche_accept\n");
484  return NULL;
485  }
486  conn->conn = q_conn;
487  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "new quic connection created\n");
488  return conn;
489 }
490 
491 
492 static void
494 {
495  static uint8_t out[MAX_DATAGRAM_SIZE];
496  quiche_send_info send_info;
497 
498  ssize_t written;
499  ssize_t sent;
500 
501  while (1)
502  {
503  written = quiche_conn_send (conn->conn, out, sizeof(out), &send_info);
504  if (QUICHE_ERR_DONE == written)
505  {
506  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "done writing quic packets\n");
507  break;
508  }
509  if (0 > written)
510  {
512  "quiche failed to create packet. quiche error: %zd\n",
513  written);
514  return;
515  }
516  sent = GNUNET_NETWORK_socket_sendto (udp_sock, out, written,
517  (struct sockaddr *) &send_info.to,
518  send_info.to_len);
519  if (sent != written)
520  {
522  "quiche failed to send data to peer\n");
523  return;
524  }
525  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sent %zd bytes\n", sent);
526  }
527 }
528 
529 
535 static void
537 {
538  peer->timeout =
540  // GNUNET_CONTAINER_heap_update_cost (peer->hn,
541  // peer->timeout.abs_value_us);
542 }
543 
544 
550 static void
552 {
553  struct GNUNET_HashCode addr_key;
554 
555  peer->peer_destroy_called = GNUNET_YES;
557  "Disconnecting peer for peer `%s'\n",
558  GNUNET_i2s (&peer->target));
559  if (NULL != peer->d_qh)
560  {
562  peer->d_qh = NULL;
563  }
564  // GNUNET_assert (peer == GNUNET_CONTAINER_heap_remove_node (peer->hn));
568  GNUNET_CRYPTO_hash (peer->address, peer->address_len, &addr_key);
570  peer))
571  {
573  "tried to remove non-existent peer from addr map\n");
574  return;
575  }
577  "# peers active",
579  GNUNET_NO);
580  quiche_conn_free (peer->conn->conn);
581  GNUNET_free (peer->address);
582  GNUNET_free (peer->foreign_addr);
583  GNUNET_free (peer->conn);
584  GNUNET_free (peer);
585 }
586 
587 
596 static int
598  const struct GNUNET_HashCode *key,
599  void *value)
600 {
601  struct PeerAddress *peer = value;
602  (void) cls;
603  (void) key;
604  peer_destroy (peer);
605  return GNUNET_OK;
606 }
607 
608 
617 static void
619  const struct GNUNET_MessageHeader *msg,
620  void *impl_state)
621 {
622  struct PeerAddress *peer = impl_state;
623  uint16_t msize = ntohs (msg->size);
624  ssize_t send_len;
625 
626  if (NULL == peer->conn->conn)
627  {
629  "peer never established quic connection\n");
630  return;
631  }
632 
633  GNUNET_assert (mq == peer->d_mq);
634  if (msize > peer->d_mtu)
635  {
637  "msize: %u, mtu: %lu\n",
638  msize,
639  peer->d_mtu);
640  GNUNET_break (0);
641  if (GNUNET_YES != peer->peer_destroy_called)
642  {
644  "peer destroy called, destroying peer\n");
645  peer_destroy (peer);
646  }
647  return;
648  }
650 
651  send_len = quiche_conn_stream_send (peer->conn->conn, 4, (uint8_t *) msg,
652  msize, false);
653  if (send_len != msize)
654  {
656  "tried to send message and quiche returned %zd", send_len);
657  return;
658  }
659  flush_egress (peer->conn);
661  "sent a message of %zd bytes\n", send_len);
663 }
664 
665 
674 static void
675 mq_destroy_d (struct GNUNET_MQ_Handle *mq, void *impl_state)
676 {
677  struct PeerAddress *peer = impl_state;
679  "Default MQ destroyed\n");
680  if (mq == peer->d_mq)
681  {
682  peer->d_mq = NULL;
683  if (GNUNET_YES != peer->peer_destroy_called)
684  peer_destroy (peer);
685  }
686 }
687 
688 
695 static void
696 mq_cancel (struct GNUNET_MQ_Handle *mq, void *impl_state)
697 {
698  /* Cancellation is impossible with QUIC; bail */
699  GNUNET_assert (0);
700 }
701 
702 
712 static void
713 mq_error (void *cls, enum GNUNET_MQ_Error error)
714 {
715  struct PeerAddress *peer = cls;
716 
718  "MQ error in queue to %s: %d\n",
719  GNUNET_i2s (&peer->target),
720  (int) error);
721  peer_destroy (peer);
722 }
723 
724 
732 static struct sockaddr *
733 udp_address_to_sockaddr (const char *bindto, socklen_t *sock_len)
734 {
735  struct sockaddr *in;
736  unsigned int port;
737  char dummy[2];
738  char *colon;
739  char *cp;
740 
741  if (1 == sscanf (bindto, "%u%1s", &port, dummy))
742  {
743  /* interpreting value as just a PORT number */
744  if (port > UINT16_MAX)
745  {
747  "BINDTO specification `%s' invalid: value too large for port\n",
748  bindto);
749  return NULL;
750  }
751  if ((GNUNET_NO == GNUNET_NETWORK_test_pf (PF_INET6)) ||
752  (GNUNET_YES ==
755  "DISABLE_V6")))
756  {
757  struct sockaddr_in *i4;
758 
759  i4 = GNUNET_malloc (sizeof(struct sockaddr_in));
760  i4->sin_family = AF_INET;
761  i4->sin_port = htons ((uint16_t) port);
762  *sock_len = sizeof(struct sockaddr_in);
763  in = (struct sockaddr *) i4;
764  }
765  else
766  {
767  struct sockaddr_in6 *i6;
768 
769  i6 = GNUNET_malloc (sizeof(struct sockaddr_in6));
770  i6->sin6_family = AF_INET6;
771  i6->sin6_port = htons ((uint16_t) port);
772  *sock_len = sizeof(struct sockaddr_in6);
773  in = (struct sockaddr *) i6;
774  }
775  return in;
776  }
777  cp = GNUNET_strdup (bindto);
778  colon = strrchr (cp, ':');
779  if (NULL != colon)
780  {
781  /* interpret value after colon as port */
782  *colon = '\0';
783  colon++;
784  if (1 == sscanf (colon, "%u%1s", &port, dummy))
785  {
786  /* interpreting value as just a PORT number */
787  if (port > UINT16_MAX)
788  {
790  "BINDTO specification `%s' invalid: value too large for port\n",
791  bindto);
792  GNUNET_free (cp);
793  return NULL;
794  }
795  }
796  else
797  {
798  GNUNET_log (
800  "BINDTO specification `%s' invalid: last ':' not followed by number\n",
801  bindto);
802  GNUNET_free (cp);
803  return NULL;
804  }
805  }
806  else
807  {
808  /* interpret missing port as 0, aka pick any free one */
809  port = 0;
810  }
811  {
812  /* try IPv4 */
813  struct sockaddr_in v4;
814 
815  memset (&v4, 0, sizeof(v4));
816  if (1 == inet_pton (AF_INET, cp, &v4.sin_addr))
817  {
818  v4.sin_family = AF_INET;
819  v4.sin_port = htons ((uint16_t) port);
820 #if HAVE_SOCKADDR_IN_SIN_LEN
821  v4.sin_len = sizeof(struct sockaddr_in);
822 #endif
823  in = GNUNET_memdup (&v4, sizeof(struct sockaddr_in));
824  *sock_len = sizeof(struct sockaddr_in);
825  GNUNET_free (cp);
826  return in;
827  }
828  }
829  {
830  /* try IPv6 */
831  struct sockaddr_in6 v6;
832  const char *start;
833 
834  memset (&v6, 0, sizeof(v6));
835  start = cp;
836  if (('[' == *cp) && (']' == cp[strlen (cp) - 1]))
837  {
838  start++; /* skip over '[' */
839  cp[strlen (cp) - 1] = '\0'; /* eat ']' */
840  }
841  if (1 == inet_pton (AF_INET6, start, &v6.sin6_addr))
842  {
843  v6.sin6_family = AF_INET6;
844  v6.sin6_port = htons ((uint16_t) port);
845 #if HAVE_SOCKADDR_IN_SIN_LEN
846  v6.sin6_len = sizeof(sizeof(struct sockaddr_in6));
847 #endif
848  in = GNUNET_memdup (&v6, sizeof(v6));
849  *sock_len = sizeof(v6);
850  GNUNET_free (cp);
851  return in;
852  }
853  }
854  /* #5528 FIXME (feature!): maybe also try getnameinfo()? */
855  GNUNET_free (cp);
856  return NULL;
857 }
858 
859 
867 static void
869 {
870  size_t base_mtu;
871 
872  switch (peer->address->sa_family)
873  {
874  case AF_INET:
875  base_mtu = 1480 /* Ethernet MTU, 1500 - Ethernet header - VLAN tag */
876  - sizeof(struct GNUNET_TUN_IPv4Header) /* 20 */
877  - sizeof(struct GNUNET_TUN_UdpHeader) /* 8 */;
878  break;
879 
880  case AF_INET6:
881  base_mtu = 1280 /* Minimum MTU required by IPv6 */
882  - sizeof(struct GNUNET_TUN_IPv6Header) /* 40 */
883  - sizeof(struct GNUNET_TUN_UdpHeader) /* 8 */;
884  break;
885 
886  default:
887  GNUNET_assert (0);
888  break;
889  }
890  /* MTU == base_mtu */
891  peer->d_mtu = base_mtu;
892 
894  "Setting up MQs and QHs\n");
895  /* => Effective MTU for CORE will range from 1080 (IPv6 + KX) to
896  1404 (IPv4 + Box) bytes, depending on circumstances... */
897 
898  if (NULL == peer->d_mq)
900  &mq_destroy_d,
901  &mq_cancel,
902  peer,
903  NULL,
904  &mq_error,
905  peer);
906  peer->d_qh =
908  &peer->target,
909  peer->foreign_addr,
910  1000,
912  0, /* Priority */
913  peer->nt,
915  peer->d_mq);
916 }
917 
918 
928 static char *
929 sockaddr_to_udpaddr_string (const struct sockaddr *address,
930  socklen_t address_len)
931 {
932  char *ret;
933 
934  switch (address->sa_family)
935  {
936  case AF_INET:
938  "%s-%s",
940  GNUNET_a2s (address, address_len));
941  break;
942 
943  case AF_INET6:
945  "%s-%s",
947  GNUNET_a2s (address, address_len));
948  break;
949 
950  default:
951  GNUNET_assert (0);
952  }
953  return ret;
954 }
955 
956 
966 static void
967 notify_cb (void *cls,
968  const struct GNUNET_PeerIdentity *sender,
969  const struct GNUNET_MessageHeader *msg)
970 {
971  // const struct UDPAck *ack;
972 
973  // (void) cls;
974  // GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
975  // "Storing UDPAck received from backchannel from %s\n",
976  // GNUNET_i2s_full (sender));
977  // if ((ntohs (msg->type) != GNUNET_MESSAGE_TYPE_COMMUNICATOR_UDP_ACK) ||
978  // (ntohs (msg->size) != sizeof(struct UDPAck)))
979  // {
980  // GNUNET_break_op (0);
981  // return;
982  // }
983  // ack = (const struct UDPAck *) msg;
984  // GNUNET_CONTAINER_multipeermap_get_multiple (receivers,
985  // sender,
986  // &handle_ack,
987  // (void *) ack);
988 }
989 
990 
996 static void
997 check_timeouts (void *cls)
998 {
999  // struct GNUNET_TIME_Relative st;
1000  // struct GNUNET_TIME_Relative rt;
1001  // struct GNUNET_TIME_Relative delay;
1002  // struct ReceiverAddress *receiver;
1003  // struct SenderAddress *sender;
1004 
1005  // (void) cls;
1006  // timeout_task = NULL;
1007  // rt = GNUNET_TIME_UNIT_FOREVER_REL;
1008  // while (NULL != (receiver = GNUNET_CONTAINER_heap_peek (receivers_heap)))
1009  // {
1010  // /* if (GNUNET_YES != receiver->receiver_destroy_called) */
1011  // /* { */
1012  // rt = GNUNET_TIME_absolute_get_remaining (receiver->timeout);
1013  // if (0 != rt.rel_value_us)
1014  // break;
1015  // GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1016  // "Receiver timed out\n");
1017  // receiver_destroy (receiver);
1018  // // }
1019  // }
1020  // st = GNUNET_TIME_UNIT_FOREVER_REL;
1021  // while (NULL != (sender = GNUNET_CONTAINER_heap_peek (senders_heap)))
1022  // {
1023  // if (GNUNET_YES != sender->sender_destroy_called)
1024  // {
1025  // st = GNUNET_TIME_absolute_get_remaining (sender->timeout);
1026  // if (0 != st.rel_value_us)
1027  // break;
1028  // sender_destroy (sender);
1029  // }
1030  // }
1031  // delay = GNUNET_TIME_relative_min (rt, st);
1032  // if (delay.rel_value_us < GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1033  // timeout_task = GNUNET_SCHEDULER_add_delayed (delay, &check_timeouts, NULL);
1034 }
1035 
1036 
1055 static int
1056 mq_init (void *cls, const struct GNUNET_PeerIdentity *peer_id, const
1057  char *address)
1058 {
1059  struct PeerAddress *peer;
1060  const char *path;
1061  struct sockaddr *in;
1062  socklen_t in_len;
1063  struct GNUNET_HashCode addr_key;
1064  uint8_t scid[LOCAL_CONN_ID_LEN];
1065 
1066  struct quic_conn *q_conn;
1067  char *bindto;
1068  socklen_t local_in_len;
1069  struct sockaddr *local_addr;
1070 
1071  if (GNUNET_OK !=
1074  "BINDTO",
1075  &bindto))
1076  {
1079  "BINDTO");
1080  return GNUNET_SYSERR;
1081  }
1082  local_addr = udp_address_to_sockaddr (bindto, &local_in_len);
1083 
1084  if (0 != strncmp (address,
1086  strlen (COMMUNICATOR_ADDRESS_PREFIX "-")))
1087  {
1088  GNUNET_break_op (0);
1089  return GNUNET_SYSERR;
1090  }
1091  path = &address[strlen (COMMUNICATOR_ADDRESS_PREFIX "-")];
1092  in = udp_address_to_sockaddr (path, &in_len);
1093  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "mq_init in_len length before: %d\n",
1094  in_len);
1098  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "address string in mq_init: %s\n",
1099  address);
1100  GNUNET_CRYPTO_hash (address, strlen (address), &addr_key);
1102  if (NULL != peer)
1103  {
1105  "ignoring transport service mq request, we already have an mq with this peer (address)\n");
1106  return GNUNET_SYSERR;
1107  }
1108  peer = GNUNET_new (struct PeerAddress);
1109  peer->address = in;
1110  peer->address_len = in_len;
1111  peer->target = *peer_id;
1112  peer->id_rcvd = GNUNET_YES;
1113  peer->is_receiver = GNUNET_YES;
1114  peer->nt = GNUNET_NT_scanner_get_type (is, in, in_len);
1115  peer->timeout =
1118  "# peers active",
1120  GNUNET_NO);
1121  peer->foreign_addr =
1122  sockaddr_to_udpaddr_string (peer->address, peer->address_len);
1127  peer,
1130  "mq_init added new peer to the addr map\n");
1136  q_conn = GNUNET_new (struct quic_conn);
1137  GNUNET_memcpy (q_conn->cid, scid, LOCAL_CONN_ID_LEN);
1138  peer->conn = q_conn;
1140  "attempting to perform QUIC handshake with peer\n");
1141  q_conn->conn = quiche_connect (peer->foreign_addr, scid, LOCAL_CONN_ID_LEN,
1142  local_addr,
1143  local_in_len, peer->address, peer->address_len,
1144  config);
1145  flush_egress (peer->conn);
1147  return GNUNET_OK;
1151  // if (NULL == timeout_task)
1152  // timeout_task = GNUNET_SCHEDULER_add_now (&check_timeouts, NULL);
1153 }
1154 
1155 
1156 static void
1158  const struct sockaddr *addr,
1159  socklen_t addrlen)
1160 {
1161  /* FIXME: support reversal: #5529 */
1163  "No connection reversal implemented!");
1164 }
1165 
1166 
1180 static void
1181 nat_address_cb (void *cls,
1182  void **app_ctx,
1183  int add_remove,
1185  const struct sockaddr *addr,
1186  socklen_t addrlen)
1187 {
1188  char *my_addr;
1190 
1191  if (GNUNET_YES == add_remove)
1192  {
1193  enum GNUNET_NetworkType nt;
1194 
1195  GNUNET_asprintf (&my_addr,
1196  "%s-%s",
1198  GNUNET_a2s (addr, addrlen));
1199  nt = GNUNET_NT_scanner_get_type (is, addr, addrlen);
1200  ai =
1202  my_addr,
1203  nt,
1205  GNUNET_free (my_addr);
1206  *app_ctx = ai;
1207  }
1208  else
1209  {
1210  ai = *app_ctx;
1212  *app_ctx = NULL;
1213  }
1214 }
1215 
1216 
1222 static void
1223 do_shutdown (void *cls)
1224 {
1226  "do_shutdown\n");
1229  quiche_config_free (config);
1230 
1231  if (NULL != timeout_task)
1232  {
1234  timeout_task = NULL;
1235  }
1236  if (NULL != read_task)
1237  {
1239  read_task = NULL;
1240  }
1241  if (NULL != udp_sock)
1242  {
1245  udp_sock = NULL;
1246  }
1247  if (NULL != ch)
1248  {
1250  ch = NULL;
1251  }
1252  if (NULL != ah)
1253  {
1255  ah = NULL;
1256  }
1257  if (NULL != my_private_key)
1258  {
1260  my_private_key = NULL;
1261  }
1263  "do_shutdown finished\n");
1264 }
1265 
1266 
1267 static void
1268 sock_read (void *cls)
1269 {
1270  struct sockaddr_storage sa;
1271  struct sockaddr_in *addr_verify;
1272  socklen_t salen = sizeof(sa);
1273  uint8_t buf[UINT16_MAX];
1274  uint8_t out[MAX_DATAGRAM_SIZE];
1275  ssize_t rcvd;
1276 
1277  ssize_t process_pkt;
1278  struct QUIC_header quic_header;
1279  uint8_t new_cid[LOCAL_CONN_ID_LEN];
1280 
1281  struct PeerAddress *peer;
1282  struct GNUNET_HashCode addr_key;
1283 
1284  (void) cls;
1285  quic_header.scid_len = sizeof(quic_header.scid);
1286  quic_header.dcid_len = sizeof(quic_header.dcid);
1287  quic_header.odcid_len = sizeof(quic_header.odcid);
1288  quic_header.token_len = sizeof(quic_header.token);
1292  char *bindto;
1293  socklen_t in_len;
1294  if (GNUNET_OK !=
1297  "BINDTO",
1298  &bindto))
1299  {
1302  "BINDTO");
1303  return;
1304  }
1305  struct sockaddr *local_addr = udp_address_to_sockaddr (bindto, &in_len);
1306 
1308  udp_sock,
1309  &sock_read,
1310  NULL);
1311  while (1)
1312  {
1314  buf,
1315  sizeof(buf),
1316  (struct sockaddr *) &sa,
1317  &salen);
1318  if (-1 == rcvd)
1319  {
1320  if (EAGAIN == errno)
1321  break; // We are done reading data
1323  return;
1324  }
1325 
1327  "Read %lu bytes\n", rcvd);
1328 
1329  if (-1 == rcvd)
1330  {
1332  return;
1333  }
1341  const char *addr_string = sockaddr_to_udpaddr_string ((const struct
1342  sockaddr *) &sa,
1343  salen);
1344  GNUNET_CRYPTO_hash (addr_string, strlen (addr_string),
1345  &addr_key);
1346  GNUNET_free (addr_string);
1348 
1349  if (NULL == peer)
1350  {
1354  peer = GNUNET_new (struct PeerAddress);
1355  peer->address = GNUNET_memdup (&sa, salen);
1356  peer->address_len = salen;
1357  peer->id_rcvd = GNUNET_NO;
1358  peer->id_sent = GNUNET_NO;
1359  peer->is_receiver = GNUNET_NO;
1360  peer->conn = NULL;
1361  peer->foreign_addr = sockaddr_to_udpaddr_string (peer->address,
1362  peer->address_len);
1366  // setup_peer_mq (peer);
1368  &addr_key,
1369  peer,
1371  {
1373  "tried to add duplicate address into address map\n");
1374  return;
1375  }
1377  "sock_read added new peer to address map\n");
1378  }
1379 
1383  int rc = quiche_header_info (buf, rcvd, LOCAL_CONN_ID_LEN,
1384  &quic_header.version,
1385  &quic_header.type, quic_header.scid,
1386  &quic_header.scid_len, quic_header.dcid,
1387  &quic_header.dcid_len,
1388  quic_header.token, &quic_header.token_len);
1389  if (0 > rc)
1390  {
1392  "failed to parse quic header: %d\n",
1393  rc);
1394  return;
1395  }
1396 
1400  if (NULL == peer->conn)
1401  {
1403  "attempting to create new connection\n");
1404  if (0 == quiche_version_is_supported (quic_header.version))
1405  {
1407  "quic version negotiation initiated\n");
1415  ssize_t written = quiche_negotiate_version (quic_header.scid,
1416  quic_header.scid_len,
1417  quic_header.dcid,
1418  quic_header.dcid_len,
1419  out, sizeof(out));
1420  if (0 > written)
1421  {
1423  "quiche failed to generate version negotiation packet\n");
1424  return;
1425  }
1426  ssize_t sent = GNUNET_NETWORK_socket_sendto (udp_sock,
1427  out,
1428  written,
1429  (struct sockaddr*) &sa,
1430  salen);
1431  if (sent != written)
1432  {
1434  "failed to send version negotiation packet to peer\n");
1435  return;
1436  }
1438  "sent %zd bytes to peer during version negotiation\n",
1439  sent);
1440  return;
1441  }
1442 
1443  if (0 == quic_header.token_len)
1444  {
1445  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "quic stateless retry\n");
1446  mint_token (quic_header.dcid, quic_header.dcid_len, &sa, salen,
1447  quic_header.token, &quic_header.token_len);
1448 
1449  uint8_t new_cid[LOCAL_CONN_ID_LEN];
1452 
1453  ssize_t written = quiche_retry (quic_header.scid, quic_header.scid_len,
1454  quic_header.dcid, quic_header.dcid_len,
1455  new_cid, LOCAL_CONN_ID_LEN,
1456  quic_header.token,
1457  quic_header.token_len,
1458  quic_header.version, out, sizeof(out));
1459  if (0 > written)
1460  {
1462  "quiche failed to write retry packet\n");
1463  return;
1464  }
1465  ssize_t sent = GNUNET_NETWORK_socket_sendto (udp_sock,
1466  out,
1467  written,
1468  (struct sockaddr*) &sa,
1469  salen);
1470  if (written != sent)
1471  {
1472  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "failed to send retry packet\n");
1473  return;
1474  }
1475 
1476  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sent %zd bytes\n", sent);
1477  continue;
1478  }
1479 
1480  if (GNUNET_OK != validate_token (quic_header.token, quic_header.token_len,
1481  &sa, salen,
1482  quic_header.odcid,
1483  &quic_header.odcid_len))
1484  {
1486  "invalid address validation token created\n");
1487  return;
1488  }
1489  peer->conn = create_conn (quic_header.dcid, quic_header.dcid_len,
1490  quic_header.odcid, quic_header.odcid_len,
1491  local_addr, in_len,
1492  &sa, salen);
1493  if (NULL == peer->conn)
1494  {
1496  "failed to create quic connection with peer\n");
1497  return;
1498  }
1499  } // null connection
1500 
1501  quiche_recv_info recv_info = {
1502  (struct sockaddr *) &sa,
1503  salen,
1504 
1505  local_addr,
1506  in_len,
1507  };
1511  if (quiche_conn_is_established (peer->conn->conn) && ! peer->id_sent &&
1512  peer->is_receiver)
1513  {
1514  ssize_t send_len;
1515 
1517  "handshake established with peer, sending our peer id\n");
1518  send_len = quiche_conn_stream_send (peer->conn->conn, STREAMID_BI,
1519  (const uint8_t *) &my_identity,
1520  sizeof(my_identity),
1521  false);
1522  if (0 > send_len)
1523  {
1525  "failed to write peer identity packet. quiche error: %zd\n",
1526  send_len);
1527  return;
1528  }
1529  flush_egress (peer->conn);
1530  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "peer identity sent to peer\n");
1531  peer->id_sent = GNUNET_YES;
1532  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "setting up peer mq\n");
1533  setup_peer_mq (peer);
1537  }
1538  process_pkt = quiche_conn_recv (peer->conn->conn, buf, rcvd, &recv_info);
1539  if (0 > process_pkt)
1540  {
1542  "quiche failed to process received packet: %zd\n",
1543  process_pkt);
1544  return;
1545  }
1547  "quiche processed %zd bytes\n", process_pkt);
1548  // Check for data on all available streams if the connection is established
1549  if (GNUNET_YES == quiche_conn_is_established (peer->conn->conn))
1550  {
1552  }
1559  quiche_stats stats;
1560  quiche_path_stats path_stats;
1561 
1562  flush_egress (peer->conn);
1563 
1564  if (quiche_conn_is_closed (peer->conn->conn))
1565  {
1566  quiche_conn_stats (peer->conn->conn, &stats);
1567  quiche_conn_path_stats (peer->conn->conn, 0, &path_stats);
1568 
1570  "connection closed. quiche stats: sent=%zu, recv=%zu\n",
1571  stats.sent, stats.recv);
1572  peer_destroy (peer);
1573  }
1574  }
1576 }
1577 
1578 
1587 static void
1588 run (void *cls,
1589  char *const *args,
1590  const char *cfgfile,
1591  const struct GNUNET_CONFIGURATION_Handle *c)
1592 {
1593  char *bindto;
1594  struct sockaddr *in;
1595  socklen_t in_len;
1596  struct sockaddr_storage in_sto;
1597  socklen_t sto_len;
1598 
1599  (void) cls;
1600  cfg = c;
1601 
1602  if (GNUNET_OK !=
1605  "BINDTO",
1606  &bindto))
1607  {
1610  "BINDTO");
1611  return;
1612  }
1613 
1614  in = udp_address_to_sockaddr (bindto, &in_len);
1615 
1616  if (NULL == in)
1617  {
1619  "Failed to setup UDP socket address with path `%s'\n",
1620  bindto);
1621  GNUNET_free (bindto);
1622  return;
1623  }
1624  udp_sock =
1625  GNUNET_NETWORK_socket_create (in->sa_family,
1626  SOCK_DGRAM,
1627  IPPROTO_UDP);
1628  if (NULL == udp_sock)
1629  {
1631  GNUNET_free (in);
1632  GNUNET_free (bindto);
1633  return;
1634  }
1635  if (AF_INET6 == in->sa_family)
1637  if (GNUNET_OK !=
1639  in,
1640  in_len))
1641  {
1643  "bind",
1644  bindto);
1646  udp_sock = NULL;
1647  GNUNET_free (in);
1648  GNUNET_free (bindto);
1649  return;
1650  }
1651  sto_len = sizeof(in_sto);
1652  if (0 != getsockname (GNUNET_NETWORK_get_fd (udp_sock),
1653  (struct sockaddr *) &in_sto,
1654  &sto_len))
1655  {
1656  memcpy (&in_sto, in, in_len);
1657  sto_len = in_len;
1658  }
1659  GNUNET_free (in);
1660  GNUNET_free (bindto);
1661  in = (struct sockaddr *) &in_sto;
1662  in_len = sto_len;
1664  "transport",
1665  "Bound to `%s'\n",
1666  GNUNET_a2s ((const struct sockaddr *) &in_sto,
1667  sto_len));
1668  switch (in->sa_family)
1669  {
1670  case AF_INET:
1671  my_port = ntohs (((struct sockaddr_in *) in)->sin_port);
1672  break;
1673 
1674  case AF_INET6:
1675  my_port = ntohs (((struct sockaddr_in6 *) in)->sin6_port);
1676  break;
1677 
1678  default:
1679  GNUNET_break (0);
1680  my_port = 0;
1681  }
1686  config = quiche_config_new (QUICHE_PROTOCOL_VERSION);
1687  quiche_config_verify_peer (config, false);
1691  quiche_config_load_cert_chain_from_pem_file (config, "./cert.crt");
1692  quiche_config_load_priv_key_from_pem_file (config, "./cert.key");
1693  quiche_config_set_application_protos (config,
1694  (uint8_t *)
1695  "\x0ahq-interop\x05hq-29\x05hq-28\x05hq-27\x08http/0.9",
1696  38);
1697  quiche_config_set_max_idle_timeout (config, 5000);
1698  quiche_config_set_max_recv_udp_payload_size (config, 1200);
1699  quiche_config_set_max_send_udp_payload_size (config, 1200);
1700  quiche_config_set_initial_max_data (config, 10000000);
1701  quiche_config_set_initial_max_stream_data_bidi_local (config, 1000000);
1702  quiche_config_set_initial_max_stream_data_bidi_remote (config, 1000000);
1703  quiche_config_set_initial_max_stream_data_uni (config, 1000000);
1704  quiche_config_set_initial_max_streams_bidi (config, 100);
1705  quiche_config_set_initial_max_streams_uni (config, 100);
1706  quiche_config_set_cc_algorithm (config, QUICHE_CC_RENO);
1707  quiche_config_set_disable_active_migration (config, true);
1713  if (NULL == my_private_key)
1714  {
1715  GNUNET_log (
1717  _ (
1718  "Transport service is lacking key configuration settings. Exiting.\n"));
1720  return;
1721  }
1723  /* start reading */
1725  udp_sock,
1726  &sock_read,
1727  NULL);
1732  &mq_init,
1733  NULL,
1734  &notify_cb,
1735  NULL);
1739  IPPROTO_UDP,
1740  1 /* one address */,
1741  (const struct sockaddr **) &in,
1742  &in_len,
1743  &nat_address_cb,
1745  NULL /* closure */);
1746  if (NULL == ch)
1747  {
1748  GNUNET_break (0);
1750  return;
1751  }
1753  if (NULL == ah)
1754  {
1755  GNUNET_break (0);
1757  return;
1758  }
1759 
1760  /* start broadcasting */
1761  // if (GNUNET_YES !=
1762  // GNUNET_CONFIGURATION_get_value_yesno (cfg,
1763  // COMMUNICATOR_CONFIG_SECTION,
1764  // "DISABLE_BROADCAST"))
1765  // {
1766  // broadcast_task = GNUNET_SCHEDULER_add_now (&do_broadcast, NULL);
1767  // }
1768 }
1769 
1770 
1771 int
1772 main (int argc, char *const *argv)
1773 {
1774  static const struct GNUNET_GETOPT_CommandLineOption options[] = {
1776  };
1777  int ret;
1778 
1780  "transport",
1781  "Starting quic communicator\n");
1782  if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
1783  return 2;
1784 
1785  ret = (GNUNET_OK == GNUNET_PROGRAM_run (argc,
1786  argv,
1787  "gnunet-communicator-quic",
1788  _ ("GNUnet QUIC communicator"),
1789  options,
1790  &run,
1791  NULL))
1792  ? 0
1793  : 1;
1794  GNUNET_free_nz ((void *) argv);
1795  return ret;
1796 }
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_OPTION_END
Definition: 002.c:13
struct GNUNET_GETOPT_CommandLineOption options[]
Definition: 002.c:5
struct GNUNET_MQ_Handle * mq
Definition: 003.c:5
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static int start
Set if we are to start default services (including ARM).
Definition: gnunet-arm.c:39
static uint16_t port
Port number.
Definition: gnunet-bcd.c:147
static char * peer_id
Option –peer.
Definition: gnunet-cadet.c:42
static void mq_destroy_d(struct GNUNET_MQ_Handle *mq, void *impl_state)
Signature of functions implementing the destruction of a message queue.
struct GNUNET_PeerIdentity my_identity
Our peer identity.
#define COMMUNICATOR_ADDRESS_PREFIX
static void notify_cb(void *cls, const struct GNUNET_PeerIdentity *sender, const struct GNUNET_MessageHeader *msg)
Function called when the transport service has received a backchannel message for this communicator (...
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)
#define ADDRESS_VALIDITY_PERIOD
How long do we believe our addresses to remain up (before the other peer should revalidate).
#define MAX_TOKEN_LEN
static enum GNUNET_GenericReturnValue validate_token(const uint8_t *token, size_t token_len, struct sockaddr_storage *addr, socklen_t addr_len, uint8_t *odcid, size_t *odcid_len)
static void try_connection_reversal(void *cls, const struct sockaddr *addr, socklen_t addrlen)
static struct GNUNET_NT_InterfaceScanner * is
Network scanner to determine network types.
static struct GNUNET_STATISTICS_Handle * stats
For logging statistics.
static const struct GNUNET_CONFIGURATION_Handle * cfg
Handle to the config.
static int mq_init(void *cls, const struct GNUNET_PeerIdentity *peer_id, const char *address)
Function called by the transport service to initialize a message queue given address information abou...
static void mint_token(const uint8_t *dcid, size_t dcid_len, struct sockaddr_storage *addr, socklen_t addr_len, uint8_t *token, size_t *token_len)
FIXME: review token generation, assure tokens are generated properly.
#define LOCAL_CONN_ID_LEN
static void flush_egress(struct quic_conn *conn)
static struct GNUNET_TIME_Relative rekey_interval
FIXME undocumented.
static struct GNUNET_NETWORK_Handle * udp_sock
FIXME undocumented.
static void peer_destroy(struct PeerAddress *peer)
Destroys a receiving state due to timeout or shutdown.
static void mq_send_d(struct GNUNET_MQ_Handle *mq, const struct GNUNET_MessageHeader *msg, void *impl_state)
Signature of functions implementing the sending functionality of a message queue.
static void sock_read(void *cls)
static void do_shutdown(void *cls)
Shutdown the QUIC communicator.
#define COMMUNICATOR_CONFIG_SECTION
static void nat_address_cb(void *cls, void **app_ctx, int add_remove, enum GNUNET_NAT_AddressClass ac, const struct sockaddr *addr, socklen_t addrlen)
Signature of the callback passed to GNUNET_NAT_register() for a function to call whenever our set of ...
static struct GNUNET_TRANSPORT_CommunicatorHandle * ch
FIXME undocumented.
static void reschedule_peer_timeout(struct PeerAddress *peer)
Increment receiver timeout due to activity.
static quiche_config * config
FIXME undocumented.
struct GNUNET_CONTAINER_MultiHashMap * conn_map
Map of DCID (uint8_t) -> quic_conn for quickly retrieving connections to other peers.
static void run(void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c)
Setup communicator and launch network interactions.
static struct GNUNET_NAT_Handle * nat
Connection to NAT service.
struct GNUNET_CONTAINER_MultiHashMap * addr_map
Map of sockaddr -> struct PeerAddress.
static struct GNUNET_SCHEDULER_Task * read_task
FIXME undocumented.
static int get_peer_delete_it(void *cls, const struct GNUNET_HashCode *key, void *value)
Iterator over all peers to clean up.
static struct sockaddr * udp_address_to_sockaddr(const char *bindto, socklen_t *sock_len)
Convert UDP bind specification to a struct sockaddr *
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 void check_timeouts(void *cls)
Task run to check #receiver_heap and #sender_heap for timeouts.
#define MAX_DATAGRAM_SIZE
static void recv_from_streams(struct PeerAddress *peer)
Given a PeerAddress, receive data from streams after doing connection logic.
static struct GNUNET_SCHEDULER_Task * timeout_task
ID of timeout task.
int main(int argc, char *const *argv)
static struct GNUNET_CRYPTO_EddsaPrivateKey * my_private_key
Our private key.
static void setup_peer_mq(struct PeerAddress *peer)
Setup the MQ for the peer.
static char * sockaddr_to_udpaddr_string(const struct sockaddr *address, socklen_t address_len)
Taken from: UDP communicator Converts address to the address string format used by this communicator ...
static void 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 unsigned long long rekey_max_bytes
FIXME undocumented.
static struct GNUNET_TRANSPORT_AddressIdentifier * ai
Handle to the operation that publishes our address.
static char * address
GNS address for this phone.
struct GNUNET_HashCode key
The key used in the DHT.
static struct in_addr dummy
Target "dummy" address of the packet we pretend to respond to.
static char * value
Value of the record to add/remove.
static struct GNUNET_NAT_AUTO_Test * nt
Handle to a NAT test operation.
static char * local_addr
Local address to use for connection reversal request.
Definition: gnunet-nat.c:65
static struct GNUNET_MQ_Envelope * ac
Handle to current GNUNET_PEERINFO_add_peer() operation.
static char buf[2048]
static struct GNUNET_PeerIdentity pid
Identity of the peer we transmit to / connect to.
commonly used definitions; globals in this file are exempt from the rule that the module name ("commo...
Core service; the main API for encrypted P2P communications.
Constants for network protocols.
API to create, modify and access statistics.
Bandwidth allocation API for applications to interact with.
API of the transport service towards the communicator processes.
void GNUNET_TRANSPORT_communicator_address_remove(struct GNUNET_TRANSPORT_AddressIdentifier *ai)
Notify transport service about an address that this communicator no longer provides for this peer.
int GNUNET_TRANSPORT_communicator_receive(struct GNUNET_TRANSPORT_CommunicatorHandle *handle, const struct GNUNET_PeerIdentity *sender, const struct GNUNET_MessageHeader *msg, struct GNUNET_TIME_Relative expected_addr_validity, GNUNET_TRANSPORT_MessageCompletedCallback cb, void *cb_cls)
Notify transport service that the communicator has received a message.
void GNUNET_TRANSPORT_communicator_mq_del(struct GNUNET_TRANSPORT_QueueHandle *qh)
Notify transport service that an MQ became unavailable due to a disconnect or timeout.
void GNUNET_TRANSPORT_application_done(struct GNUNET_TRANSPORT_ApplicationHandle *ch)
Shutdown TRANSPORT application client.
#define GNUNET_TRANSPORT_QUEUE_LENGTH_UNLIMITED
Queue length.
struct GNUNET_TRANSPORT_ApplicationHandle * GNUNET_TRANSPORT_application_init(const struct GNUNET_CONFIGURATION_Handle *cfg)
Initialize the TRANSPORT application client handle.
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...
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.
void GNUNET_TRANSPORT_communicator_disconnect(struct GNUNET_TRANSPORT_CommunicatorHandle *ch)
Disconnect from the transport service.
struct GNUNET_TRANSPORT_CommunicatorHandle * GNUNET_TRANSPORT_communicator_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *config_section_name, const char *addr_prefix, enum GNUNET_TRANSPORT_CommunicatorCharacteristics cc, GNUNET_TRANSPORT_CommunicatorMqInit mq_init, void *mq_init_cls, GNUNET_TRANSPORT_CommunicatorNotify notify_cb, void *notify_cb_cls)
Connect to the transport service.
@ 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?
struct GNUNET_CRYPTO_EddsaPrivateKey * GNUNET_CRYPTO_eddsa_key_create_from_configuration(const struct GNUNET_CONFIGURATION_Handle *cfg)
Create a new private key by reading our peer's key from the file specified in the configuration.
void GNUNET_CRYPTO_random_block(enum GNUNET_CRYPTO_Quality mode, void *buffer, size_t length)
Fill block with a random values.
void GNUNET_CRYPTO_eddsa_key_get_public(const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, struct GNUNET_CRYPTO_EddsaPublicKey *pub)
Extract the public key for the given private key.
Definition: crypto_ecc.c:198
@ GNUNET_CRYPTO_QUALITY_STRONG
High-quality operations are desired.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:41
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.
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash 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.
enum GNUNET_GenericReturnValue 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.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY
There must only be one value per key; storing a value should fail if a value under the same key alrea...
#define GNUNET_log(kind,...)
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
GNUNET_GenericReturnValue
Named constants for return values.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
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.
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).
#define GNUNET_log_strerror_file(level, cmd, filename)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
#define GNUNET_free_nz(ptr)
Wrapper around free.
#define GNUNET_memdup(buf, size)
Allocate and initialize a block of memory.
GNUNET_MQ_Error
Error codes for the queue.
struct GNUNET_MQ_Handle * GNUNET_MQ_queue_for_callbacks(GNUNET_MQ_SendImpl send, GNUNET_MQ_DestroyImpl destroy, GNUNET_MQ_CancelImpl cancel, void *impl_state, const struct GNUNET_MQ_MessageHandler *handlers, GNUNET_MQ_ErrorHandler error_handler, void *cls)
Create a message queue for the specified handlers.
Definition: mq.c:465
void GNUNET_MQ_impl_send_continue(struct GNUNET_MQ_Handle *mq)
Call the send implementation for the next queued message, if any.
Definition: mq.c:421
GNUNET_NAT_AddressClass
Some addresses contain sensitive information or are not suitable for global distribution.
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
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition: network.c:509
int GNUNET_NETWORK_get_fd(const struct GNUNET_NETWORK_Handle *desc)
Return file descriptor for this network handle.
Definition: network.c:1001
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:688
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_create(int domain, int type, int protocol)
Create a new socket.
Definition: network.c:833
enum GNUNET_GenericReturnValue GNUNET_NETWORK_test_pf(int pf)
Test if the given protocol family is supported by this system.
Definition: network.c:80
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:440
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:772
GNUNET_NetworkType
Types of networks (with separate quotas) we support.
Definition: gnunet_nt_lib.h:39
struct GNUNET_NT_InterfaceScanner * GNUNET_NT_scanner_init(void)
Initialize the address characterization client handle.
Definition: nt.c:406
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:308
enum GNUNET_GenericReturnValue GNUNET_PROGRAM_run(int argc, char *const *argv, const char *binaryName, const char *binaryHelp, const struct GNUNET_GETOPT_CommandLineOption *options, GNUNET_PROGRAM_Main task, void *task_cls)
Run a standard GNUnet command startup sequence (initialize loggers and configuration,...
Definition: program.c:400
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:562
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:1506
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:1334
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:975
void GNUNET_STATISTICS_set(struct GNUNET_STATISTICS_Handle *handle, const char *name, uint64_t value, int make_persistent)
Set statistic value for the peer.
enum GNUNET_GenericReturnValue GNUNET_STRINGS_get_utf8_args(int argc, char *const *argv, int *u8argc, char *const **u8argv)
Returns utf-8 encoded arguments.
Definition: strings.c:1222
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition: time.c:316
#define _(String)
GNU gettext support macro.
Definition: platform.h:178
Internal representation of the hash map.
Private ECC key encoded for transmission.
Definition of a command line option.
A 512-bit hashcode.
Handle to a message queue.
Definition: mq.c:87
Header for all communications.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
Handle for active NAT registrations.
Definition: nat_api.c:72
handle to a socket
Definition: network.c:54
Handle to the interface scanner.
Definition: nt.c:105
The identity of the host (wraps the signing key of the peer).
struct GNUNET_CRYPTO_EddsaPublicKey public_key
Entry in list of pending tasks.
Definition: scheduler.c:136
Handle for the service.
Time for absolute times used by GNUnet, in microseconds.
Time for relative time used by GNUnet, in microseconds.
Internal representation of an address a communicator is currently providing for the transport service...
Handle to the TRANSPORT subsystem for application management.
Opaque handle to the transport service for communicators.
Handle returned to identify the internal data structure the transport API has created to manage a mes...
Standard IPv4 header.
Standard IPv6 header.
UDP packet header.
Information we track per peer we have recently been in contact with.
int id_rcvd
Flag to indicate whether we know the PeerIdentity (target) yet.
struct GNUNET_PeerIdentity target
To whom are we talking to.
struct GNUNET_TRANSPORT_QueueHandle * d_qh
handle for default queue with the ch.
struct sockaddr * address
Address of the other peer.
size_t d_mtu
MTU we allowed transport for this peer's default queue.
enum GNUNET_NetworkType nt
Which network type does this queue use?
struct GNUNET_TIME_Absolute timeout
Timeout for this peer address.
struct quic_conn * conn
The QUIC connection associated with this peer.
struct GNUNET_MQ_Handle * d_mq
Default message queue we are providing for the ch.
int id_sent
Flag to indicate whether we have sent OUR PeerIdentity to this peer.
char * foreign_addr
Address of the receiver in the human-readable format with the COMMUNICATOR_ADDRESS_PREFIX.
int peer_destroy_called
receiver_destroy already called on receiver.
socklen_t address_len
Length of the address.
int is_receiver
Flag to indicate if we are the initiator of the connection.
QUIC_header is used to store information received from an incoming QUIC packet.
uint8_t scid[QUICHE_MAX_CONN_ID_LEN]
uint8_t dcid[QUICHE_MAX_CONN_ID_LEN]
uint8_t token[sizeof("quiche") - 1+sizeof(struct sockaddr_storage)+QUICHE_MAX_CONN_ID_LEN]
uint8_t odcid[QUICHE_MAX_CONN_ID_LEN]
QUIC connection object.
quiche_conn * conn
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.