GNUnet 0.26.2-45-gb0324da85
 
Loading...
Searching...
No Matches
gnunet-communicator-http3.c
Go to the documentation of this file.
1#include "platform.h"
2#include "gnunet_common.h"
3#include "gnunet_util_lib.h"
8#include "gnunet_protocols.h"
9#include "gnunet_signatures.h"
10#include "gnunet_constants.h"
12#include "stdint.h"
13#include "inttypes.h"
14#include "stdlib.h"
15
16#include <ngtcp2/ngtcp2.h>
17#include <ngtcp2/ngtcp2_crypto.h>
18#include <ngtcp2/ngtcp2_crypto_gnutls.h>
19#include <nghttp3/nghttp3.h>
20#include <gnutls/crypto.h>
21#include <gnutls/gnutls.h>
22#include <stdint.h>
23
24
28#define COMMUNICATOR_CONFIG_SECTION "communicator-http3"
29
33#define COMMUNICATOR_ADDRESS_PREFIX "http3"
34
38#define PRIORITY "NORMAL:-VERS-ALL:+VERS-TLS1.3:" \
39 "-CIPHER-ALL:+AES-128-GCM:+AES-256-GCM:+CHACHA20-POLY1305:+AES-128-CCM:" \
40 "-GROUP-ALL:+GROUP-SECP256R1:+GROUP-X25519:+GROUP-SECP384R1:+GROUP-SECP521R1:" \
41 "%DISABLE_TLS13_COMPAT_MODE"
42
47#define ADDRESS_VALIDITY_PERIOD GNUNET_TIME_UNIT_HOURS
48
52#define NUM_LONG_POLL 16
53
66
75
79static const struct GNUNET_CONFIGURATION_Handle *cfg;
80
85
90
94static int disable_v6;
95
100
105
110
114static struct GNUNET_NAT_Handle *nat;
115
119static int have_v6_socket;
120
124static uint16_t my_port;
125
130
135
139static gnutls_certificate_credentials_t cred;
140
144struct Stream
145{
149 int64_t stream_id;
150
154 uint8_t *data;
155
159 uint64_t datalen;
160
165
170
174 uint8_t *uri;
175
179 size_t urilen;
180
184 uint8_t *method;
185
189 size_t methodlen;
190
194 uint8_t *authority;
195
200};
201
206{
211
215 char *buf;
216
220 size_t size;
221};
222
227{
231 struct Stream *stream;
232
237
241 uint64_t delay_time;
242
247
252};
253
257struct Connection
258{
262 ngtcp2_conn *conn;
263
267 nghttp3_conn *h3_conn;
268
272 ngtcp2_ccerr last_error;
273
277 ngtcp2_crypto_conn_ref conn_ref;
278
282 gnutls_session_t session;
287
291 struct sockaddr *address;
292
296 socklen_t address_len;
297
302
307
312
317
322
327
331 size_t d_mtu;
332
337
342
348
353
358
363
367 ngtcp2_ssize conn_closebuflen;
368
373
378
383
388
393
398
403};
404
405
406static int
407connection_write (struct Connection *connection);
408
414static uint64_t
416{
417 struct timespec tp;
418 clock_gettime (CLOCK_MONOTONIC, &tp);
419 return (uint64_t) tp.tv_sec * NGTCP2_SECONDS + (uint64_t) tp.tv_nsec;
420}
421
422
432static char *
433sockaddr_to_udpaddr_string (const struct sockaddr *address,
434 socklen_t address_len)
435{
436 char *ret;
437
438 switch (address->sa_family)
439 {
440 case AF_INET:
442 "%s-%s",
444 GNUNET_a2s (address, address_len));
445 break;
446
447 case AF_INET6:
449 "%s-%s",
451 GNUNET_a2s (address, address_len));
452 break;
453
454 default:
455 GNUNET_assert (0);
456 }
457 return ret;
458}
459
460
468static struct sockaddr *
469udp_address_to_sockaddr (const char *bindto, socklen_t *sock_len)
470{
471 struct sockaddr *in;
472 unsigned int port;
473 char dummy[2];
474 char *colon;
475 char *cp;
476
477 if (1 == sscanf (bindto, "%u%1s", &port, dummy))
478 {
479 /* interpreting value as just a PORT number */
480 if (port > UINT16_MAX)
481 {
483 "BINDTO specification `%s' invalid: value too large for port\n",
484 bindto);
485 return NULL;
486 }
487 if (GNUNET_YES == disable_v6)
488 {
489 struct sockaddr_in *i4;
490
491 i4 = GNUNET_malloc (sizeof(struct sockaddr_in));
492 i4->sin_family = AF_INET;
493 i4->sin_port = htons ((uint16_t) port);
494 *sock_len = sizeof(struct sockaddr_in);
495 in = (struct sockaddr *) i4;
496 }
497 else
498 {
499 struct sockaddr_in6 *i6;
500
501 i6 = GNUNET_malloc (sizeof(struct sockaddr_in6));
502 i6->sin6_family = AF_INET6;
503 i6->sin6_port = htons ((uint16_t) port);
504 *sock_len = sizeof(struct sockaddr_in6);
505 in = (struct sockaddr *) i6;
506 }
507 return in;
508 }
509 cp = GNUNET_strdup (bindto);
510 colon = strrchr (cp, ':');
511 if (NULL != colon)
512 {
513 /* interpret value after colon as port */
514 *colon = '\0';
515 colon++;
516 if (1 == sscanf (colon, "%u%1s", &port, dummy))
517 {
518 /* interpreting value as just a PORT number */
519 if (port > UINT16_MAX)
520 {
522 "BINDTO specification `%s' invalid: value too large for port\n",
523 bindto);
524 GNUNET_free (cp);
525 return NULL;
526 }
527 }
528 else
529 {
530 GNUNET_log (
532 "BINDTO specification `%s' invalid: last ':' not followed by number\n",
533 bindto);
534 GNUNET_free (cp);
535 return NULL;
536 }
537 }
538 else
539 {
540 /* interpret missing port as 0, aka pick any free one */
541 port = 0;
542 }
543 {
544 /* try IPv4 */
545 struct sockaddr_in v4;
546
547 memset (&v4, 0, sizeof(v4));
548 if (1 == inet_pton (AF_INET, cp, &v4.sin_addr))
549 {
550 v4.sin_family = AF_INET;
551 v4.sin_port = htons ((uint16_t) port);
552#if HAVE_SOCKADDR_IN_SIN_LEN
553 v4.sin_len = sizeof(struct sockaddr_in);
554#endif
555 in = GNUNET_memdup (&v4, sizeof(struct sockaddr_in));
556 *sock_len = sizeof(struct sockaddr_in);
557 GNUNET_free (cp);
558 return in;
559 }
560 }
561 {
562 /* try IPv6 */
563 struct sockaddr_in6 v6;
564 const char *start;
565
566 memset (&v6, 0, sizeof(v6));
567 start = cp;
568 if (('[' == *cp) && (']' == cp[strlen (cp) - 1]))
569 {
570 start++; /* skip over '[' */
571 cp[strlen (cp) - 1] = '\0'; /* eat ']' */
572 }
573 if (1 == inet_pton (AF_INET6, start, &v6.sin6_addr))
574 {
575 v6.sin6_family = AF_INET6;
576 v6.sin6_port = htons ((uint16_t) port);
577#if HAVE_SOCKADDR_IN_SIN_LEN
578 v6.sin6_len = sizeof(struct sockaddr_in6);
579#endif
580 in = GNUNET_memdup (&v6, sizeof(v6));
581 *sock_len = sizeof(v6);
582 GNUNET_free (cp);
583 return in;
584 }
585 }
586 /* #5528 FIXME (feature!): maybe also try getnameinfo()? */
587 GNUNET_free (cp);
588 return NULL;
589}
590
591
595static ngtcp2_conn*
596get_conn (ngtcp2_crypto_conn_ref *ref)
597{
598 return ((struct Connection*) (ref->user_data))->conn;
599}
600
601
602static void
604 const struct sockaddr *addr,
605 socklen_t addrlen)
606{
607 /* FIXME: support reversal: #5529 */
609 "No connection reversal implemented!\n");
610}
611
612
622static void
623notify_cb (void *cls,
624 const struct GNUNET_PeerIdentity *sender,
625 const struct GNUNET_MessageHeader *msg)
626{
627
628}
629
630
640static int
641send_packet (struct Connection *connection, const uint8_t *data, size_t datalen)
642{
643 int rv;
644
646 connection->address,
647 connection->address_len);
648 if (GNUNET_SYSERR == rv)
649 {
651 "send packet failed!\n");
652 return GNUNET_SYSERR;
653 }
654 return GNUNET_NO;
655}
656
657
667static struct Stream*
669{
670 struct Stream *new_stream;
671 struct GNUNET_HashCode stream_key;
672
673 new_stream = GNUNET_new (struct Stream);
674 memset (new_stream, 0, sizeof (struct Stream));
675 new_stream->stream_id = stream_id;
676 new_stream->connection = connection;
677 GNUNET_CRYPTO_hash (&stream_id, sizeof (stream_id), &stream_key);
679 &stream_key,
680 new_stream,
682 return new_stream;
683}
684
685
692static void
693remove_stream (struct Connection *connection, int64_t stream_id)
694{
695 struct GNUNET_HashCode stream_key;
696 struct Stream *stream;
697 int rv;
698
699 GNUNET_CRYPTO_hash (&stream_id, sizeof (stream_id), &stream_key);
702 &stream_key,
703 stream);
704 if (GNUNET_NO == rv)
705 {
707 "can't remove non-exist pair in connection->streams, stream_id = %"
708 PRIi64 "\n",
709 stream_id);
710 return;
711 }
712
713 if (stream->uri)
714 {
715 GNUNET_free (stream->uri);
716 }
717 if (stream->method)
718 {
719 GNUNET_free (stream->method);
720 }
721 if (stream->authority)
722 {
723 GNUNET_free (stream->authority);
724 }
725 GNUNET_free (stream);
726}
727
728
739static struct Stream *
741{
742 struct GNUNET_HashCode stream_key;
743 struct Stream *stream;
744
745 GNUNET_CRYPTO_hash (&stream_id, sizeof (stream_id), &stream_key);
747 return stream;
748}
749
750
758static int
760{
761 int rv;
762 gnutls_datum_t alpn = { (unsigned char *) "h3", sizeof("h3") - 1};
763 // rv = gnutls_certificate_allocate_credentials (&connection->cred);
764 // if (GNUNET_NO == rv)
765 // rv = gnutls_certificate_set_x509_system_trust (connection->cred);
766 // if (GNUNET_NO > rv)
767 // {
768 // GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
769 // "cred init failed: %s\n",
770 // gnutls_strerror (rv));
771 // return GNUNET_SYSERR;
772 // }
773 rv = gnutls_init (&connection->session,
774 GNUTLS_CLIENT
775 | GNUTLS_ENABLE_EARLY_DATA
776 | GNUTLS_NO_END_OF_EARLY_DATA);
777 if (GNUNET_NO != rv)
778 {
780 "gnutls_init error: %s\n",
781 gnutls_strerror (rv));
782 return GNUNET_SYSERR;
783 }
784 rv = ngtcp2_crypto_gnutls_configure_client_session (connection->session);
785 if (GNUNET_NO != rv)
786 {
788 "ngtcp2_crypto_gnutls_configure_client_session failed\n");
789 return GNUNET_SYSERR;
790 }
791 rv = gnutls_priority_set_direct (connection->session, PRIORITY, NULL);
792 if (GNUNET_NO != rv)
793 {
795 "gnutls_priority_set_direct: %s\n",
796 gnutls_strerror (rv));
797 return GNUNET_SYSERR;
798 }
799 gnutls_session_set_ptr (connection->session, &connection->conn_ref);
800 rv = gnutls_credentials_set (connection->session, GNUTLS_CRD_CERTIFICATE,
801 cred);
802 if (GNUNET_NO != rv)
803 {
805 "gnutls_credentials_set: %s\n",
806 gnutls_strerror (rv));
807 return GNUNET_SYSERR;
808 }
809 gnutls_alpn_set_protocols (connection->session, &alpn, 1,
810 GNUTLS_ALPN_MANDATORY);
811
816 // gnutls_server_name_set (connection->session, GNUTLS_NAME_DNS, "localhost",
817 // strlen ("localhost"));
818
819 return GNUNET_NO;
820}
821
822
828static void
830{
833 // GNUNET_CONTAINER_heap_update_cost (peer->hn,
834 // peer->timeout.abs_value_us);
835}
836
837
846static int
848 const struct GNUNET_HashCode *key,
849 void *value)
850{
851 struct Stream *stream = value;
852 (void) cls;
853 (void) key;
854
855 if (stream->uri)
856 {
857 GNUNET_free (stream->uri);
858 }
859 if (stream->method)
860 {
861 GNUNET_free (stream->method);
862 }
863 if (stream->authority)
864 {
865 GNUNET_free (stream->authority);
866 }
867 GNUNET_free (stream);
868 return GNUNET_OK;
869}
870
871
877static void
879{
880 struct GNUNET_HashCode addr_key;
881 struct HTTP_Message *msg_curr;
882 struct Long_Poll_Request *long_poll_curr;
883 struct Long_Poll_Request *long_poll_temp;
884 int rv;
886
887 msg_curr = connection->msg_queue_head;
888 connection->msg_queue_rear = NULL;
889 while (NULL != msg_curr)
890 {
891 msg_curr = msg_curr->next;
892 GNUNET_free (msg_curr->buf);
893 GNUNET_free (msg_curr);
894 }
895
896 msg_curr = connection->submitted_msg_queue_head;
897 while (NULL != msg_curr)
898 {
899 msg_curr = msg_curr->next;
900 GNUNET_free (msg_curr->buf);
901 GNUNET_free (msg_curr);
902 }
903
904 long_poll_curr = connection->long_poll_head;
905 connection->long_poll_rear = NULL;
906 while (NULL != long_poll_curr)
907 {
908 long_poll_temp = long_poll_curr;
909 long_poll_curr = long_poll_curr->next;
910 GNUNET_free (long_poll_temp);
911 }
912
913 if (NULL != connection->d_qh)
914 {
916 connection->d_qh = NULL;
917 }
918
919 GNUNET_CRYPTO_hash (connection->address,
920 connection->address_len,
921 &addr_key);
922 rv = GNUNET_CONTAINER_multihashmap_remove (addr_map, &addr_key, connection);
923 if (GNUNET_NO == rv)
924 {
926 "tried to remove non-existent connection from addr_map\n");
927 return;
928 }
930 "# connections active",
932 GNUNET_NO);
933
934 ngtcp2_conn_del (connection->conn);
935 if (connection->h3_conn)
936 {
937 nghttp3_conn_del (connection->h3_conn);
938 }
939 gnutls_deinit (connection->session);
940 GNUNET_free (connection->address);
941 GNUNET_free (connection->foreign_addr);
942 GNUNET_free (connection->conn_closebuf);
945 NULL);
947 GNUNET_free (connection);
948}
949
950
960static nghttp3_nv
961make_nv (const char *name,
962 const char *value,
963 uint8_t flag)
964{
965 nghttp3_nv nv;
966
967 nv.name = (const uint8_t *) name;
968 nv.namelen = strlen (name);
969 nv.value = (const uint8_t *) value;
970 nv.valuelen = strlen (value);
971 nv.flags = flag;
972
973 return nv;
974}
975
976
980static nghttp3_ssize
981read_data (nghttp3_conn *conn, int64_t stream_id, nghttp3_vec *vec,
982 size_t veccnt, uint32_t *pflags, void *user_data,
983 void *stream_user_data)
984{
985 struct Stream *stream = stream_user_data;
986
987 vec[0].base = stream->data;
988 vec[0].len = stream->datalen;
989 *pflags |= NGHTTP3_DATA_FLAG_EOF;
990
991 return 1;
992}
993
994
1005static int
1007 struct Stream *stream,
1008 const uint8_t *data,
1009 size_t datalen)
1010{
1011 nghttp3_nv nva[7];
1012 char contentlen[20];
1013 nghttp3_data_reader dr = {};
1014 int rv;
1015
1016 GNUNET_snprintf (contentlen, sizeof(contentlen), "%zu", datalen);
1017 stream->data = (uint8_t *) data;
1018 stream->datalen = datalen;
1019
1020 nva[0] = make_nv (":method", "POST",
1021 NGHTTP3_NV_FLAG_NO_COPY_NAME
1022 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1023 nva[1] = make_nv (":scheme", "https",
1024 NGHTTP3_NV_FLAG_NO_COPY_NAME
1025 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1026 nva[2] = make_nv (":authority",
1028 NGHTTP3_NV_FLAG_NO_COPY_NAME);
1029 nva[3] = make_nv (":path", "/",
1030 NGHTTP3_NV_FLAG_NO_COPY_NAME
1031 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1032 nva[4] = make_nv ("user-agent", "nghttp3/ngtcp2 client",
1033 NGHTTP3_NV_FLAG_NO_COPY_NAME
1034 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1035 nva[5] = make_nv ("content-type", "application/octet-stream",
1036 NGHTTP3_NV_FLAG_NO_COPY_NAME
1037 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1038 nva[6] = make_nv ("content-length", contentlen,
1039 NGHTTP3_NV_FLAG_NO_COPY_NAME);
1040
1041 dr.read_data = read_data;
1042 rv = nghttp3_conn_submit_request (connection->h3_conn,
1043 stream->stream_id,
1044 nva, 7, &dr, stream);
1045 if (0 != rv)
1046 {
1048 "nghttp3_conn_submit_request: %s\n",
1049 nghttp3_strerror (rv));
1050 return GNUNET_SYSERR;
1051 }
1052
1053 return GNUNET_NO;
1054}
1055
1056
1066static int
1068 struct Stream *stream)
1069{
1070 nghttp3_nv nva[6];
1071 int rv;
1072
1074 "send get request\n");
1075 nva[0] = make_nv (":method", "GET",
1076 NGHTTP3_NV_FLAG_NO_COPY_NAME
1077 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1078 nva[1] = make_nv (":scheme", "https",
1079 NGHTTP3_NV_FLAG_NO_COPY_NAME
1080 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1081 nva[2] = make_nv (":authority",
1083 NGHTTP3_NV_FLAG_NO_COPY_NAME);
1084 nva[3] = make_nv (":path", "/",
1085 NGHTTP3_NV_FLAG_NO_COPY_NAME
1086 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1087 nva[4] = make_nv ("user-agent", "nghttp3/ngtcp2 client",
1088 NGHTTP3_NV_FLAG_NO_COPY_NAME
1089 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1090
1091 rv = nghttp3_conn_submit_request (connection->h3_conn,
1092 stream->stream_id,
1093 nva, 5, NULL, stream);
1094 if (0 != rv)
1095 {
1097 "nghttp3_conn_submit_request: %s\n",
1098 nghttp3_strerror (rv));
1099 return GNUNET_SYSERR;
1100 }
1101
1102 return GNUNET_NO;
1103}
1104
1105
1111static void
1113{
1114 struct Long_Poll_Request *long_poll = cls;
1115 nghttp3_nv nva[2];
1116 struct Stream *stream;
1117 struct Connection *connection;
1118 int rv;
1119
1120 long_poll->timer = NULL;
1122 "long_poll_timeoutcb called!\n");
1123 stream = long_poll->stream;
1124 connection = stream->connection;
1125 if (NULL != long_poll->prev)
1126 {
1127 long_poll->prev->next = long_poll->next;
1128 }
1129 if (NULL != long_poll->next)
1130 {
1131 long_poll->next->prev = long_poll->prev;
1132 }
1133 if (connection->long_poll_head == long_poll)
1134 {
1135 connection->long_poll_head = long_poll->next;
1136 }
1137 if (connection->long_poll_rear == long_poll)
1138 {
1139 connection->long_poll_rear = long_poll->prev;
1140 }
1141 GNUNET_free (long_poll);
1142
1143 nva[0] = make_nv (":status", "204",
1144 NGHTTP3_NV_FLAG_NO_COPY_NAME
1145 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1146 nva[1] = make_nv ("server", "nghttp3/ngtcp2 server",
1147 NGHTTP3_NV_FLAG_NO_COPY_NAME
1148 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1149 rv = nghttp3_conn_submit_response (connection->h3_conn,
1150 stream->stream_id, nva, 2, NULL);
1151 if (0 != rv)
1152 {
1154 "nghttp3_conn_submit_response: %s\n",
1155 nghttp3_strerror (rv));
1156 return;
1157 }
1158 ngtcp2_conn_shutdown_stream_read (connection->conn, 0,
1159 stream->stream_id,
1160 NGHTTP3_H3_NO_ERROR);
1161}
1162
1163
1174static int
1175stream_send_data (struct Stream *stream,
1176 uint8_t *data, size_t datalen)
1177{
1178 nghttp3_nv nva[4];
1179 nghttp3_data_reader dr = {};
1180 char content_length_str[20];
1181 int rv;
1182
1183 GNUNET_snprintf (content_length_str, sizeof(content_length_str),
1184 "%zu", datalen);
1185 nva[0] = make_nv (":status", "200",
1186 NGHTTP3_NV_FLAG_NO_COPY_NAME
1187 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1188 nva[1] = make_nv ("server", "nghttp3/ngtcp2 server",
1189 NGHTTP3_NV_FLAG_NO_COPY_NAME
1190 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1191 nva[2] = make_nv ("content-type", "application/octet-stream",
1192 NGHTTP3_NV_FLAG_NO_COPY_NAME
1193 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1194 nva[3] = make_nv ("content-length", content_length_str,
1195 NGHTTP3_NV_FLAG_NO_COPY_NAME);
1196
1197 stream->data = data;
1198 stream->datalen = datalen;
1199 dr.read_data = read_data;
1200 rv = nghttp3_conn_submit_response (stream->connection->h3_conn,
1201 stream->stream_id,
1202 nva, 4, &dr);
1203 if (0 != rv)
1204 {
1206 "nghttp3_conn_submit_response: %s\n",
1207 nghttp3_strerror (rv));
1208 return GNUNET_SYSERR;
1209 }
1210 return GNUNET_NO;
1211}
1212
1213
1222static int
1223stream_start_response (struct Connection *connection, struct Stream *stream)
1224{
1225 nghttp3_nv nva[4];
1226 struct HTTP_Message *msg;
1227 struct Long_Poll_Request *long_poll;
1228 struct GNUNET_TIME_Relative delay;
1229 int rv;
1230
1231 nva[0] = make_nv (":status", "200",
1232 NGHTTP3_NV_FLAG_NO_COPY_NAME
1233 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1234 nva[1] = make_nv ("server", "nghttp3/ngtcp2 server",
1235 NGHTTP3_NV_FLAG_NO_COPY_NAME
1236 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1237
1238 // method is POST
1239 if (4 == stream->methodlen)
1240 {
1241 if (NULL == connection->msg_queue_head)
1242 {
1243 rv = nghttp3_conn_submit_response (connection->h3_conn, stream->stream_id,
1244 nva, 2, NULL);
1245 if (0 != rv)
1246 {
1248 "nghttp3_conn_submit_response: %s\n",
1249 nghttp3_strerror (rv));
1250 return GNUNET_SYSERR;
1251 }
1252 }
1253 else
1254 {
1255 connection->msg_queue_len -= 1;
1257 "rm msg, len = %lu\n",
1258 connection->msg_queue_len);
1259 msg = connection->msg_queue_head;
1260 stream_send_data (stream, (uint8_t *) msg->buf, msg->size);
1261 connection->msg_queue_head = msg->next;
1262 msg->next = connection->submitted_msg_queue_head;
1263 connection->submitted_msg_queue_head = msg;
1264 }
1265 }
1266 // method is GET
1267 else
1268 {
1270 "server recv GET request\n");
1271 if (NULL != connection->msg_queue_head &&
1272 NULL == connection->long_poll_head)
1273 {
1274 msg = connection->msg_queue_head;
1275 stream_send_data (stream,
1276 (uint8_t *) msg->buf,
1277 msg->size);
1278 connection->msg_queue_head = msg->next;
1279 msg->next = connection->submitted_msg_queue_head;
1280 connection->submitted_msg_queue_head = msg;
1281 }
1282 else if (NULL == connection->msg_queue_head ||
1283 NULL != connection->long_poll_head)
1284 {
1285 connection->long_poll_len += 1;
1287 "add long_poll, len = %lu\n",
1288 connection->long_poll_len);
1289 long_poll = GNUNET_new (struct Long_Poll_Request);
1290 long_poll->stream = stream;
1291 long_poll->next = NULL;
1292 long_poll->prev = connection->long_poll_rear;
1293 long_poll->delay_time = 1ULL;
1294 if (NULL != connection->long_poll_rear)
1295 {
1296 connection->long_poll_rear->next = long_poll;
1297 long_poll->delay_time =
1298 (connection->long_poll_head->delay_time & (NUM_LONG_POLL - 1)) + 1ULL;
1299 }
1300 connection->long_poll_rear = long_poll;
1301 if (NULL == connection->long_poll_head)
1302 {
1303 connection->long_poll_head = long_poll;
1304 }
1306 long_poll->delay_time);
1307 long_poll->timer = GNUNET_SCHEDULER_add_delayed (delay,
1309 long_poll);
1310 }
1311 long_poll = connection->long_poll_head;
1312
1313 while (NULL != long_poll &&
1314 NULL != connection->msg_queue_head)
1315 {
1316 GNUNET_SCHEDULER_cancel (long_poll->timer);
1317 if (NULL != long_poll->next)
1318 {
1319 long_poll->next->prev = NULL;
1320 }
1321
1322 msg = connection->msg_queue_head;
1323 connection->msg_queue_head = msg->next;
1324 msg->next = connection->submitted_msg_queue_head;
1325 connection->submitted_msg_queue_head = msg;
1326 stream_send_data (long_poll->stream,
1327 (uint8_t *) msg->buf,
1328 msg->size);
1329 connection->long_poll_head = long_poll->next;
1330 if (NULL != long_poll->next)
1331 {
1332 long_poll->next->prev = NULL;
1333 }
1334 connection->long_poll_len -= 1;
1336 "rm long_poll, len = %lu\n",
1337 connection->long_poll_len);
1338 GNUNET_free (long_poll);
1339 long_poll = connection->long_poll_head;
1340 }
1341 }
1342 return GNUNET_NO;
1343}
1344
1345
1354static void
1356 const struct GNUNET_MessageHeader *msg,
1357 void *impl_state)
1358{
1359 struct Connection *connection = impl_state;
1360 uint16_t msize = ntohs (msg->size);
1361 struct Stream *post_stream;
1362 struct HTTP_Message *send_buf;
1363 struct Long_Poll_Request *long_poll;
1364
1366 "mq_send_d: init = %d, msg->size = %u, time: %llu\n",
1367 connection->is_initiator, msize,
1368 (unsigned long long) timestamp () / NGTCP2_SECONDS);
1369 if (NULL == connection->conn)
1370 {
1372 "No quic connection has been established yet\n");
1373 return;
1374 }
1375
1376 GNUNET_assert (mq == connection->d_mq);
1377
1378 if (msize > connection->d_mtu)
1379 {
1381 "msize: %u, mtu: %lu\n",
1382 msize,
1383 connection->d_mtu);
1384 GNUNET_break (0);
1385 if (GNUNET_YES != connection->connection_destroy_called)
1386 {
1388 "connection destroy called, destroying connection\n");
1389 connection_destroy (connection);
1390 }
1391 return;
1392 }
1393 reschedule_peer_timeout (connection);
1394
1395 // If we are client side.
1396 if (GNUNET_YES == connection->is_initiator)
1397 {
1398 post_stream = create_stream (connection, -1);
1399 ngtcp2_conn_open_bidi_stream (connection->conn,
1400 &post_stream->stream_id,
1401 NULL);
1402 submit_post_request (connection, post_stream, (uint8_t *) msg, msize);
1403 connection_write (connection);
1404 }
1405 // If we are server side.
1406 else
1407 {
1408 if (NULL == connection->msg_queue_head &&
1409 NULL != connection->long_poll_head)
1410 {
1411 long_poll = connection->long_poll_head;
1412 GNUNET_SCHEDULER_cancel (long_poll->timer);
1413 stream_send_data (long_poll->stream, (uint8_t *) msg, msize);
1414 connection_write (connection);
1415 connection->long_poll_head = long_poll->next;
1416 if (NULL != long_poll->next)
1417 {
1418 long_poll->next->prev = NULL;
1419 }
1420 connection->long_poll_len -= 1;
1422 "rm long_poll, len = %lu\n",
1423 connection->long_poll_len);
1424 GNUNET_free (long_poll);
1425 }
1426 else if (NULL == connection->long_poll_head ||
1427 NULL != connection->msg_queue_head)
1428 {
1429 connection->msg_queue_len += 1;
1431 "add msg, len = %lu\n",
1432 connection->msg_queue_len);
1433 send_buf = GNUNET_new (struct HTTP_Message);
1434 send_buf->size = msize;
1435 send_buf->buf = GNUNET_memdup (msg, msize);
1436 send_buf->next = NULL;
1437 connection->msg_queue_rear = send_buf;
1438 if (NULL == connection->msg_queue_head)
1439 {
1440 connection->msg_queue_head = send_buf;
1441 }
1442 }
1443
1444 long_poll = connection->long_poll_head;
1445 while (NULL != long_poll &&
1446 NULL != connection->msg_queue_head)
1447 {
1448 GNUNET_SCHEDULER_cancel (long_poll->timer);
1449 if (NULL != long_poll->next)
1450 {
1451 long_poll->next->prev = NULL;
1452 }
1453
1454 send_buf = connection->msg_queue_head;
1455 connection->msg_queue_head = send_buf->next;
1456 send_buf->next = connection->submitted_msg_queue_head;
1457 connection->submitted_msg_queue_head = send_buf;
1458 stream_send_data (long_poll->stream,
1459 (uint8_t *) send_buf->buf,
1460 send_buf->size);
1461 connection->long_poll_head = long_poll->next;
1462 if (NULL != long_poll->next)
1463 {
1464 long_poll->next->prev = NULL;
1465 }
1466 connection->long_poll_len -= 1;
1468 "rm long_poll, len = %lu\n",
1469 connection->long_poll_len);
1470 GNUNET_free (long_poll);
1471 long_poll = connection->long_poll_head;
1472 }
1473 }
1475}
1476
1477
1486static void
1487mq_destroy_d (struct GNUNET_MQ_Handle *mq, void *impl_state)
1488{
1489 struct Connection *connection = impl_state;
1491 "Default MQ destroyed\n");
1492 if (mq == connection->d_mq)
1493 {
1494 connection->d_mq = NULL;
1495 if (GNUNET_YES != connection->connection_destroy_called)
1496 connection_destroy (connection);
1497 }
1498}
1499
1500
1507static void
1508mq_cancel (struct GNUNET_MQ_Handle *mq, void *impl_state)
1509{
1510 /* Cancellation is impossible with QUIC; bail */
1511 GNUNET_assert (0);
1512}
1513
1514
1524static void
1525mq_error (void *cls, enum GNUNET_MQ_Error error)
1526{
1527 struct Connection *connection = cls;
1529 "MQ error in queue to %s: %d\n",
1530 GNUNET_i2s (&connection->target),
1531 (int) error);
1532 connection_destroy (connection);
1533}
1534
1535
1543static void
1545{
1546 size_t base_mtu;
1547
1549 "setup_connection_mq: init = %u\n",
1550 connection->is_initiator);
1551 switch (connection->address->sa_family)
1552 {
1553 case AF_INET:
1554 base_mtu = 1480 /* Ethernet MTU, 1500 - Ethernet header - VLAN tag */
1555 - sizeof(struct GNUNET_TUN_IPv4Header) /* 20 */
1556 - sizeof(struct GNUNET_TUN_UdpHeader) /* 8 */;
1557 break;
1558 case AF_INET6:
1559 base_mtu = 1280 /* Minimum MTU required by IPv6 */
1560 - sizeof(struct GNUNET_TUN_IPv6Header) /* 40 */
1561 - sizeof(struct GNUNET_TUN_UdpHeader) /* 8 */;
1562 break;
1563 default:
1564 GNUNET_assert (0);
1565 break;
1566 }
1567 /* MTU == base_mtu */
1568 connection->d_mtu = base_mtu;
1569
1570 if (NULL == connection->d_mq)
1572 &mq_destroy_d,
1573 &mq_cancel,
1574 connection,
1575 NULL,
1576 &mq_error,
1577 connection);
1578 connection->d_qh =
1580 &connection->target,
1581 connection->foreign_addr,
1582 1080,
1584 0, /* Priority */
1585 connection->nt,
1587 connection->d_mq);
1588}
1589
1590
1594static void
1595http_consume (struct Connection *connection, int64_t stream_id, size_t consumed)
1596{
1597 ngtcp2_conn_extend_max_stream_offset (connection->conn,
1598 stream_id,
1599 consumed);
1600 ngtcp2_conn_extend_max_offset (connection->conn,
1601 consumed);
1602}
1603
1604
1608static int
1609http_stream_close_cb (nghttp3_conn *conn, int64_t stream_id,
1610 uint64_t app_error_code, void *conn_user_data,
1611 void *stream_user_data)
1612{
1613 struct Connection *connection = conn_user_data;
1614
1615 remove_stream (connection, stream_id);
1617 "HTTP stream %lu closed\n",
1618 (unsigned long) stream_id);
1619 if (GNUNET_NO == connection->is_initiator &&
1620 ngtcp2_is_bidi_stream (stream_id))
1621 {
1622 ngtcp2_conn_extend_max_streams_bidi (connection->conn, 1);
1623 }
1624 else if (GNUNET_YES == connection->is_initiator &&
1625 ! ngtcp2_is_bidi_stream (stream_id))
1626 {
1627 ngtcp2_conn_extend_max_streams_uni (connection->conn, 1);
1628 }
1629
1630 return 0;
1631}
1632
1633
1637static int
1639 int64_t stream_id,
1640 const uint8_t *data,
1641 size_t datalen,
1642 void *user_data,
1643 void *stream_user_data)
1644{
1645 struct Connection *connection = user_data;
1646 struct GNUNET_PeerIdentity *pid;
1647 struct GNUNET_MessageHeader *hdr;
1648 int rv;
1649
1651 "http_recv_data_cb\n");
1652 http_consume (connection, stream_id, datalen);
1653
1654 if (GNUNET_NO == connection->is_initiator &&
1655 GNUNET_NO == connection->id_rcvd)
1656 {
1657 if (datalen < sizeof (struct GNUNET_PeerIdentity))
1658 {
1660 "message recv len of %zd less than length of peer identity\n",
1661 datalen);
1662 return NGHTTP3_ERR_CALLBACK_FAILURE;
1663 }
1664 pid = (struct GNUNET_PeerIdentity *) data;
1665 connection->target = *pid;
1666 connection->id_rcvd = GNUNET_YES;
1667 setup_connection_mq (connection);
1668
1669 return GNUNET_NO;
1670 }
1671
1672 hdr = (struct GNUNET_MessageHeader *) data;
1674 &connection->target,
1675 hdr,
1677 NULL,
1678 NULL);
1679 if (GNUNET_SYSERR == rv)
1680 {
1682 "GNUNET_TRANSPORT_communicator_receive:%d, hdr->len = %u, datalen = %lu, init = %d\n",
1683 rv, ntohs (hdr->size), datalen, connection->is_initiator);
1684 return NGHTTP3_ERR_CALLBACK_FAILURE;
1685 }
1687 "GNUNET_TRANSPORT_communicator_receive:%d, hdr->len = %u, datalen = %lu, init = %d\n",
1688 rv, ntohs (hdr->size), datalen, connection->is_initiator);
1689 return 0;
1690}
1691
1692
1696static int
1697http_deferred_consume_cb (nghttp3_conn *conn,
1698 int64_t stream_id,
1699 size_t nconsumed,
1700 void *user_data,
1701 void *stream_user_data)
1702{
1703 struct Connection *connection = user_data;
1704
1705 http_consume (connection,
1706 stream_id,
1707 nconsumed);
1708 return 0;
1709}
1710
1711
1715static int
1716http_begin_headers_cb (nghttp3_conn *conn, int64_t stream_id,
1717 void *user_data, void *stream_user_data)
1718{
1719 struct Connection *connection = user_data;
1720 struct Stream *stream;
1721
1722 stream = find_stream (connection, stream_id);
1723 if (NULL == stream)
1724 {
1725 return NGHTTP3_ERR_CALLBACK_FAILURE;
1726 }
1727 nghttp3_conn_set_stream_user_data (connection->h3_conn, stream_id, stream);
1728
1729 return 0;
1730}
1731
1732
1736static int
1737http_recv_header_cb (nghttp3_conn *conn, int64_t stream_id, int32_t token,
1738 nghttp3_rcbuf *name, nghttp3_rcbuf *value, uint8_t flags,
1739 void *user_data, void *stream_user_data)
1740{
1741 nghttp3_vec namebuf = nghttp3_rcbuf_get_buf (name);
1742 nghttp3_vec valbuf = nghttp3_rcbuf_get_buf (value);
1743 struct Connection *connection = user_data;
1744
1745 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "http header: [%.*s: %.*s]\n",
1746 (int) namebuf.len, namebuf.base,
1747 (int) valbuf.len, valbuf.base);
1748
1749 if (GNUNET_NO == connection->is_initiator)
1750 {
1751 struct Stream *stream = stream_user_data;
1752 switch (token)
1753 {
1754 case NGHTTP3_QPACK_TOKEN__PATH:
1755 stream->urilen = valbuf.len;
1756 stream->uri = (uint8_t *) malloc (valbuf.len);
1757 memcpy (stream->uri, valbuf.base, valbuf.len);
1758 break;
1759 case NGHTTP3_QPACK_TOKEN__METHOD:
1760 stream->methodlen = valbuf.len;
1761 stream->method = (uint8_t *) malloc (valbuf.len);
1762 memcpy (stream->method, valbuf.base, valbuf.len);
1763 break;
1764 case NGHTTP3_QPACK_TOKEN__AUTHORITY:
1765 stream->authoritylen = valbuf.len;
1766 stream->authority = (uint8_t *) malloc (valbuf.len);
1767 memcpy (stream->authority, valbuf.base, valbuf.len);
1768 break;
1769 }
1770 }
1771 return 0;
1772}
1773
1774
1778static int
1779http_stop_sending_cb (nghttp3_conn *conn, int64_t stream_id,
1780 uint64_t app_error_code, void *user_data,
1781 void *stream_user_data)
1782{
1783 struct Connection *connection = user_data;
1784 int rv;
1785
1786 rv = ngtcp2_conn_shutdown_stream_read (connection->conn,
1787 0,
1788 stream_id,
1789 app_error_code);
1790 if (0 != rv)
1791 {
1793 "ngtcp2_conn_shutdown_stream_read: %s\n",
1794 ngtcp2_strerror (rv));
1795 return NGHTTP3_ERR_CALLBACK_FAILURE;
1796 }
1797 return 0;
1798}
1799
1800
1804static int
1805http_end_stream_cb (nghttp3_conn *conn, int64_t stream_id, void *user_data,
1806 void *stream_user_data)
1807{
1808 struct Connection *connection = user_data;
1809 struct Stream *stream = stream_user_data;
1810 struct Long_Poll_Request *long_poll;
1811 int rv;
1812
1813 if (GNUNET_NO == connection->is_initiator)
1814 {
1815 // Send response
1816 rv = stream_start_response (connection, stream);
1817 if (0 != rv)
1818 {
1819 return NGHTTP3_ERR_CALLBACK_FAILURE;
1820 }
1821 }
1822 else
1823 {
1828 long_poll = connection->long_poll_head;
1829 while (NULL != long_poll)
1830 {
1831 if (stream_id == long_poll->stream->stream_id)
1832 {
1834 "client side recv GET response\n");
1835 stream = create_stream (connection, -1);
1836 rv = ngtcp2_conn_open_bidi_stream (connection->conn,
1838 if (0 != rv)
1839 {
1841 "ngtcp2_conn_open_bidi_stream: %s\n",
1842 ngtcp2_strerror (rv));
1843 }
1844 submit_get_request (connection, stream);
1845 long_poll->stream = stream;
1846 break;
1847 }
1848 long_poll = long_poll->next;
1849 }
1850 }
1851 return 0;
1852}
1853
1854
1858static int
1859http_reset_stream_cb (nghttp3_conn *conn, int64_t stream_id,
1860 uint64_t app_error_code, void *user_data,
1861 void *stream_user_data)
1862{
1863 struct Connection *connection = user_data;
1864 int rv;
1865
1866 rv = ngtcp2_conn_shutdown_stream_write (connection->conn,
1867 0,
1868 stream_id,
1869 app_error_code);
1870 if (0 != rv)
1871 {
1873 "ngtcp2_conn_shutdown_stream_write: %s\n",
1874 ngtcp2_strerror (rv));
1875 return NGHTTP3_ERR_CALLBACK_FAILURE;
1876 }
1877 return 0;
1878}
1879
1880
1888static int
1889setup_httpconn (struct Connection *connection)
1890{
1891 nghttp3_settings settings;
1892 const nghttp3_mem *mem = nghttp3_mem_default ();
1893 int64_t ctrl_stream_id;
1894 int64_t enc_stream_id;
1895 int64_t dec_stream_id;
1896 nghttp3_callbacks callbacks = {
1897 .stream_close = http_stream_close_cb,
1898 .recv_data = http_recv_data_cb,
1899 .deferred_consume = http_deferred_consume_cb,
1900 .begin_headers = http_begin_headers_cb,
1901 .recv_header = http_recv_header_cb,
1902 .stop_sending = http_stop_sending_cb,
1903 .end_stream = http_end_stream_cb,
1904 .reset_stream = http_reset_stream_cb,
1905 };
1906 int rv;
1907
1908 if (NULL != connection->h3_conn)
1909 {
1910 return GNUNET_NO;
1911 }
1912
1913 if (ngtcp2_conn_get_streams_uni_left (connection->conn) < 3)
1914 {
1916 "uni stream left less than 3\n");
1917 return GNUNET_SYSERR;
1918 }
1919
1920 if (GNUNET_YES == connection->is_initiator)
1921 {
1922 callbacks.begin_headers = NULL;
1923 // callbacks.end_stream = NULL;
1924 }
1925
1926 nghttp3_settings_default (&settings);
1927 settings.qpack_blocked_streams = 100;
1928 settings.qpack_encoder_max_dtable_capacity = 4096;
1929
1930 if (GNUNET_NO == connection->is_initiator)
1931 {
1932 const ngtcp2_transport_params *params =
1933 ngtcp2_conn_get_local_transport_params (connection->conn);
1934
1935 rv = nghttp3_conn_server_new (&connection->h3_conn,
1936 &callbacks,
1937 &settings,
1938 mem,
1939 connection);
1940 nghttp3_conn_set_max_client_streams_bidi (connection->h3_conn,
1941 params->initial_max_streams_bidi);
1942 if (0 != rv)
1943 {
1945 "nghttp3_conn_server_new: %s\n",
1946 nghttp3_strerror (rv));
1947 return GNUNET_SYSERR;
1948 }
1949 }
1950 else
1951 {
1952 rv = nghttp3_conn_client_new (&connection->h3_conn,
1953 &callbacks,
1954 &settings,
1955 mem,
1956 connection);
1957 if (0 != rv)
1958 {
1960 "nghttp3_conn_client_new: %s\n",
1961 nghttp3_strerror (rv));
1962 return GNUNET_SYSERR;
1963 }
1964 }
1965
1966 rv = ngtcp2_conn_open_uni_stream (connection->conn, &ctrl_stream_id, NULL);
1967 if (0 != rv)
1968 {
1970 "ngtcp2_conn_open_uni_stream: %s\n",
1971 ngtcp2_strerror (rv));
1972 return GNUNET_SYSERR;
1973 }
1974
1975 rv = nghttp3_conn_bind_control_stream (connection->h3_conn, ctrl_stream_id);
1976 if (0 != rv)
1977 {
1979 "nghttp3_conn_bind_control_stream: %s\n",
1980 nghttp3_strerror (rv));
1981 return GNUNET_SYSERR;
1982 }
1983
1984 rv = ngtcp2_conn_open_uni_stream (connection->conn, &enc_stream_id, NULL);
1985 if (0 != rv)
1986 {
1988 "ngtcp2_conn_open_uni_stream: %s\n",
1989 ngtcp2_strerror (rv));
1990 return GNUNET_SYSERR;
1991 }
1992
1993 rv = ngtcp2_conn_open_uni_stream (connection->conn, &dec_stream_id, NULL);
1994 if (0 != rv)
1995 {
1997 "ngtcp2_conn_open_uni_stream: %s\n",
1998 ngtcp2_strerror (rv));
1999 return GNUNET_SYSERR;
2000 }
2001
2002 rv = nghttp3_conn_bind_qpack_streams (connection->h3_conn,
2003 enc_stream_id, dec_stream_id);
2004 if (0 != rv)
2005 {
2007 "nghttp3_conn_bind_qpack_streams: %s\n",
2008 nghttp3_strerror (rv));
2009 return GNUNET_SYSERR;
2010 }
2011
2013 "Bind control stream: %" PRIi64 ", enc stream: %" PRIi64
2014 ", dec stream: %" PRIi64 "\n",
2015 ctrl_stream_id, enc_stream_id, dec_stream_id);
2016 return GNUNET_NO;
2017}
2018
2019
2023static void
2024rand_cb (uint8_t *dest,
2025 size_t destlen,
2026 const ngtcp2_rand_ctx *rand_ctx)
2027{
2028 (void) rand_ctx;
2030 dest,
2031 destlen);
2032}
2033
2034
2038static int
2039get_new_connection_id_cb (ngtcp2_conn *conn, ngtcp2_cid *cid,
2040 uint8_t *token, size_t cidlen,
2041 void *user_data)
2042{
2043 (void) conn;
2044 (void) user_data;
2045
2047 cid->data,
2048 cidlen);
2049 cid->datalen = cidlen;
2051 token,
2052 NGTCP2_STATELESS_RESET_TOKENLEN);
2053 return GNUNET_NO;
2054}
2055
2056
2060static int
2061recv_stream_data_cb (ngtcp2_conn *conn, uint32_t flags, int64_t stream_id,
2062 uint64_t offset, const uint8_t *data, size_t datalen,
2063 void *user_data,
2064 void *stream_user_data)
2065{
2066 struct Connection *connection = user_data;
2067 nghttp3_ssize nconsumed;
2068
2069 if (NULL == connection->h3_conn)
2070 {
2071 return 0;
2072 }
2073 nconsumed = nghttp3_conn_read_stream (connection->h3_conn, stream_id,
2074 data, datalen,
2075 flags & NGTCP2_STREAM_DATA_FLAG_FIN);
2076 if (nconsumed < 0)
2077 {
2079 "nghttp3_conn_read_stream: %s, init = %d\n",
2080 nghttp3_strerror (nconsumed), connection->is_initiator);
2081 ngtcp2_ccerr_set_application_error (
2082 &connection->last_error,
2083 nghttp3_err_infer_quic_app_error_code (nconsumed),
2084 NULL, 0);
2085 return NGTCP2_ERR_CALLBACK_FAILURE;
2086 }
2087 http_consume (connection, stream_id, nconsumed);
2088 return 0;
2089}
2090
2091
2095static int
2096stream_open_cb (ngtcp2_conn *conn,
2097 int64_t stream_id,
2098 void *user_data)
2099{
2100 struct Connection *connection = user_data;
2101 if (! ngtcp2_is_bidi_stream (stream_id))
2102 {
2103 return 0;
2104 }
2105 create_stream (connection, stream_id);
2106 return 0;
2107}
2108
2109
2115static int
2116stream_close_cb (ngtcp2_conn *conn, uint32_t flags, int64_t stream_id,
2117 uint64_t app_error_code, void *user_data,
2118 void *stream_user_data)
2119{
2120 struct Connection *connection = user_data;
2121 int rv;
2122
2124 "stream_close id = %" PRIi64 "\n",
2125 stream_id);
2126 if (! (flags & NGTCP2_STREAM_CLOSE_FLAG_APP_ERROR_CODE_SET))
2127 {
2128 app_error_code = NGHTTP3_H3_NO_ERROR;
2129 }
2130
2131 if (connection->h3_conn)
2132 {
2133 if (0 == app_error_code)
2134 {
2135 app_error_code = NGHTTP3_H3_NO_ERROR;
2136 }
2137
2138 rv = nghttp3_conn_close_stream (connection->h3_conn,
2139 stream_id,
2140 app_error_code);
2141 switch (rv)
2142 {
2143 case 0:
2144 break;
2145 case NGHTTP3_ERR_STREAM_NOT_FOUND:
2146 if (GNUNET_NO == connection->is_initiator &&
2147 ngtcp2_is_bidi_stream (stream_id))
2148 {
2149 ngtcp2_conn_extend_max_streams_bidi (connection->conn, 1);
2150 }
2151 else if (GNUNET_YES == connection->is_initiator &&
2152 ! ngtcp2_is_bidi_stream (stream_id))
2153 {
2154 ngtcp2_conn_extend_max_streams_uni (connection->conn, 1);
2155 }
2156 break;
2157 default:
2159 "nghttp3_conn_close_stream: %s\n",
2160 nghttp3_strerror (rv));
2161 ngtcp2_ccerr_set_application_error (
2162 &connection->last_error,
2163 nghttp3_err_infer_quic_app_error_code (rv),
2164 NULL, 0);
2165 return NGTCP2_ERR_CALLBACK_FAILURE;
2166 }
2167 }
2168 return 0;
2169}
2170
2171
2175static int
2176acked_stream_data_offset_cb (ngtcp2_conn *conn, int64_t stream_id,
2177 uint64_t offset, uint64_t datalen, void *user_data,
2178 void *stream_user_data)
2179{
2180 struct Connection *connection = user_data;
2181 int rv;
2182
2183 if (NULL == connection->h3_conn)
2184 {
2185 return 0;
2186 }
2187
2188 rv = nghttp3_conn_add_ack_offset (connection->h3_conn, stream_id, datalen);
2189 if (0 != rv)
2190 {
2192 "nghttp3_conn_add_ack_offset: %s\n",
2193 nghttp3_strerror (rv));
2194 return NGTCP2_ERR_CALLBACK_FAILURE;
2195 }
2196 return 0;
2197}
2198
2199
2203static int
2204extend_max_stream_data_cb (ngtcp2_conn *conn, int64_t stream_id,
2205 uint64_t max_data, void *user_data,
2206 void *stream_user_data)
2207{
2208 struct Connection *connection = user_data;
2209 int rv;
2210
2211 rv = nghttp3_conn_unblock_stream (connection->h3_conn, stream_id);
2212 if (0 != rv)
2213 {
2215 "nghttp3_conn_unblock_stream: %s\n",
2216 nghttp3_strerror (rv));
2217 return NGTCP2_ERR_CALLBACK_FAILURE;
2218 }
2219 return 0;
2220}
2221
2222
2226static int
2227stream_reset_cb (ngtcp2_conn *conn, int64_t stream_id, uint64_t final_size,
2228 uint64_t app_error_code, void *user_data,
2229 void *stream_user_data)
2230{
2231 struct Connection *connection = user_data;
2232 int rv;
2233
2234 if (connection->h3_conn)
2235 {
2236 rv = nghttp3_conn_shutdown_stream_read (connection->h3_conn, stream_id);
2237 if (0 != rv)
2238 {
2240 "nghttp3_conn_shutdown_stream_read: %s\n",
2241 nghttp3_strerror (rv));
2242 return NGTCP2_ERR_CALLBACK_FAILURE;
2243 }
2244 }
2245 return 0;
2246}
2247
2248
2252static int
2253extend_max_remote_streams_bidi_cb (ngtcp2_conn *conn, uint64_t max_streams,
2254 void *user_data)
2255{
2256 struct Connection *connection = user_data;
2257 if (NULL == connection->h3_conn)
2258 {
2259 return 0;
2260 }
2261 nghttp3_conn_set_max_client_streams_bidi (connection->h3_conn, max_streams);
2262 return 0;
2263}
2264
2265
2269static int
2270stream_stop_sending_cb (ngtcp2_conn *conn, int64_t stream_id,
2271 uint64_t app_error_code, void *user_data,
2272 void *stream_user_data)
2273{
2274 struct Connection *connection = user_data;
2275 int rv;
2276
2277 if (connection->h3_conn)
2278 {
2279 rv = nghttp3_conn_shutdown_stream_read (connection->h3_conn, stream_id);
2280 if (0 != rv)
2281 {
2283 "nghttp3_conn_shutdown_stream_read: %s\n",
2284 nghttp3_strerror (rv));
2285 return NGTCP2_ERR_CALLBACK_FAILURE;
2286 }
2287 }
2288 return 0;
2289}
2290
2291
2295static int
2296recv_tx_key_cb (ngtcp2_conn *conn, ngtcp2_encryption_level level,
2297 void *user_data)
2298{
2299 struct Connection *connection = user_data;
2300 int rv;
2301
2302 if (NGTCP2_ENCRYPTION_LEVEL_1RTT != level)
2303 {
2304 return 0;
2305 }
2306
2307 rv = setup_httpconn (connection);
2308 if (0 != rv)
2309 {
2310 return NGTCP2_ERR_CALLBACK_FAILURE;
2311 }
2312 return 0;
2313}
2314
2315
2319static int
2320recv_rx_key_cb (ngtcp2_conn *conn, ngtcp2_encryption_level level,
2321 void *user_data)
2322{
2323 struct Connection *connection = user_data;
2324 struct Stream *stream;
2325 struct Long_Poll_Request *long_poll;
2326 int i;
2327 int rv;
2328
2329 if (NGTCP2_ENCRYPTION_LEVEL_1RTT != level)
2330 {
2331 return 0;
2332 }
2333
2334 rv = setup_httpconn (connection);
2335 if (0 != rv)
2336 {
2337 return NGTCP2_ERR_CALLBACK_FAILURE;
2338 }
2339
2340 if (GNUNET_YES == connection->is_initiator &&
2341 GNUNET_NO == connection->id_sent)
2342 {
2343 stream = create_stream (connection, -1);
2344 rv = ngtcp2_conn_open_bidi_stream (conn, &stream->stream_id, NULL);
2345
2346 submit_post_request (connection, stream,
2347 (uint8_t *) &my_identity,
2348 sizeof (my_identity));
2349
2350 connection->id_sent = GNUNET_YES;
2351 setup_connection_mq (connection);
2352
2353 for (i = 0; i < NUM_LONG_POLL; i++)
2354 {
2355 stream = create_stream (connection, -1);
2356 rv = ngtcp2_conn_open_bidi_stream (conn, &stream->stream_id, NULL);
2357 submit_get_request (connection, stream);
2358 long_poll = GNUNET_new (struct Long_Poll_Request);
2359 long_poll->stream = stream;
2360 long_poll->next = NULL;
2361 long_poll->prev = connection->long_poll_rear;
2362 long_poll->timer = NULL;
2363 if (NULL != connection->long_poll_rear)
2364 {
2365 connection->long_poll_rear->next = long_poll;
2366 }
2367 connection->long_poll_rear = long_poll;
2368 if (NULL == connection->long_poll_head)
2369 {
2370 connection->long_poll_head = long_poll;
2371 }
2372 }
2373 }
2374 return 0;
2375}
2376
2377
2390static int
2391client_quic_init (struct Connection *connection,
2392 struct sockaddr *local_addr,
2393 socklen_t local_addrlen,
2394 struct sockaddr *remote_addr,
2395 socklen_t remote_addrlen)
2396{
2397 int rv;
2398 ngtcp2_cid dcid;
2399 ngtcp2_cid scid;
2400 ngtcp2_settings settings;
2401 ngtcp2_transport_params params;
2402 ngtcp2_path path = {
2403 {local_addr, local_addrlen},
2404 {remote_addr, remote_addrlen},
2405 NULL,
2406 };
2407 ngtcp2_callbacks callbacks = {
2408 .client_initial = ngtcp2_crypto_client_initial_cb,
2409 .recv_crypto_data = ngtcp2_crypto_recv_crypto_data_cb,
2410 .encrypt = ngtcp2_crypto_encrypt_cb,
2411 .decrypt = ngtcp2_crypto_decrypt_cb,
2412 .hp_mask = ngtcp2_crypto_hp_mask_cb,
2413 .recv_retry = ngtcp2_crypto_recv_retry_cb,
2414 .update_key = ngtcp2_crypto_update_key_cb,
2415 .delete_crypto_aead_ctx = ngtcp2_crypto_delete_crypto_aead_ctx_cb,
2416 .delete_crypto_cipher_ctx = ngtcp2_crypto_delete_crypto_cipher_ctx_cb,
2417 .get_path_challenge_data = ngtcp2_crypto_get_path_challenge_data_cb,
2418 .version_negotiation = ngtcp2_crypto_version_negotiation_cb,
2419 .rand = rand_cb,
2420 .get_new_connection_id = get_new_connection_id_cb,
2421 .recv_stream_data = recv_stream_data_cb,
2422 .stream_close = stream_close_cb,
2423 .acked_stream_data_offset = acked_stream_data_offset_cb,
2424 .extend_max_stream_data = extend_max_stream_data_cb,
2425 .stream_reset = stream_reset_cb,
2426 .stream_stop_sending = stream_stop_sending_cb,
2427 .recv_rx_key = recv_rx_key_cb,
2428 };
2429
2430
2431 scid.datalen = NGTCP2_MAX_CIDLEN;
2433 scid.data,
2434 scid.datalen);
2435 dcid.datalen = NGTCP2_MAX_CIDLEN;
2437 dcid.data,
2438 dcid.datalen);
2439 ngtcp2_settings_default (&settings);
2440 settings.initial_ts = timestamp ();
2441
2442 ngtcp2_transport_params_default (&params);
2443 params.initial_max_streams_uni = 100;
2444 params.initial_max_stream_data_bidi_local = 6291456;
2445 params.initial_max_data = 15728640;
2446 params.initial_max_stream_data_bidi_remote = 0;
2447 params.initial_max_stream_data_uni = 6291456;
2448 params.initial_max_streams_bidi = 0;
2449 params.max_idle_timeout = 30 * NGTCP2_SECONDS;
2450 params.active_connection_id_limit = 7;
2451 params.grease_quic_bit = 1;
2452 rv = ngtcp2_conn_client_new (&connection->conn,
2453 &dcid,
2454 &scid,
2455 &path,
2456 NGTCP2_PROTO_VER_V1,
2457 &callbacks,
2458 &settings,
2459 &params,
2460 NULL,
2461 connection);
2462 if (GNUNET_NO != rv)
2463 {
2465 "ngtcp2_conn_client_new: %s\n",
2466 ngtcp2_strerror (rv));
2467 return GNUNET_SYSERR;
2468 }
2469 ngtcp2_conn_set_tls_native_handle (connection->conn, connection->session);
2470 connection->conn_ref.user_data = connection;
2471 connection->conn_ref.get_conn = get_conn;
2472 return GNUNET_NO;
2473}
2474
2475
2481static void
2482close_waitcb (void *cls)
2483{
2484 struct Connection *connection = cls;
2485 connection->timer = NULL;
2486
2487 if (ngtcp2_conn_in_closing_period (connection->conn))
2488 {
2490 "Closing period over\n");
2491 connection_destroy (connection);
2492 return;
2493 }
2494 if (ngtcp2_conn_in_draining_period (connection->conn))
2495 {
2497 "Draining period over\n");
2498 connection_destroy (connection);
2499 return;
2500 }
2501}
2502
2503
2509static void
2511{
2512 ngtcp2_duration pto;
2513 struct GNUNET_TIME_Relative delay;
2514
2515 if (NULL != connection->timer)
2516 {
2517 GNUNET_SCHEDULER_cancel (connection->timer);
2518 connection->timer = NULL;
2519 }
2520 pto = ngtcp2_conn_get_pto (connection->conn);
2522 pto / 1000ULL * 3);
2523 connection->timer = GNUNET_SCHEDULER_add_delayed (delay,
2525 connection);
2527 "Start draining period\n");
2528}
2529
2530
2541static int
2543{
2544 ngtcp2_path_storage ps;
2545 ngtcp2_pkt_info pi;
2546 ngtcp2_ssize nwrite;
2547 ngtcp2_duration pto;
2548 struct GNUNET_TIME_Relative delay;
2549
2550 if (NULL == connection->conn ||
2551 ngtcp2_conn_in_closing_period (connection->conn) ||
2552 ngtcp2_conn_in_draining_period (connection->conn))
2553 {
2554 return GNUNET_NO;
2555 }
2556
2558 "Start closing period\n");
2559
2560 if (GNUNET_NO == connection->is_initiator)
2561 {
2562 if (NULL != connection->timer)
2563 {
2564 GNUNET_SCHEDULER_cancel (connection->timer);
2565 connection->timer = NULL;
2566 }
2567 pto = ngtcp2_conn_get_pto (connection->conn);
2569 pto / 1000ULL * 3);
2570 connection->timer = GNUNET_SCHEDULER_add_delayed (delay,
2572 connection);
2573 }
2574
2575 connection->conn_closebuf =
2576 GNUNET_new_array (NGTCP2_MAX_UDP_PAYLOAD_SIZE, uint8_t);
2577
2578 ngtcp2_path_storage_zero (&ps);
2579 nwrite = ngtcp2_conn_write_connection_close (connection->conn,
2580 &ps.path,
2581 &pi,
2582 connection->conn_closebuf,
2583 NGTCP2_MAX_UDP_PAYLOAD_SIZE,
2584 &connection->last_error,
2585 timestamp ());
2586 if (nwrite < 0)
2587 {
2589 "ngtcp2_conn_write_connection_close: %s\n",
2590 ngtcp2_strerror (nwrite));
2591 return GNUNET_SYSERR;
2592 }
2593 if (0 == nwrite)
2594 {
2595 return GNUNET_NO;
2596 }
2597 connection->conn_closebuflen = nwrite;
2598 if (GNUNET_YES == connection->is_initiator)
2599 {
2600 return send_packet (connection,
2601 connection->conn_closebuf,
2602 connection->conn_closebuflen);
2603 }
2604 return GNUNET_NO;
2605}
2606
2607
2614static int
2615send_conn_close (struct Connection *connection)
2616{
2617 int rv;
2618
2620 "Closing period, send CONNECTION_CLOSE\n");
2621 rv = send_packet (connection,
2622 connection->conn_closebuf,
2623 connection->conn_closebuflen);
2624 return rv;
2625}
2626
2627
2635static int
2636handle_error (struct Connection *connection)
2637{
2638 int rv;
2639
2640 /* if we are the client side */
2641 if (GNUNET_YES == connection->is_initiator)
2642 {
2643 /* this will send CONNECTION_CLOSE immediately and don't wait */
2644 start_closing_period (connection);
2645 connection_destroy (connection);
2646 return GNUNET_SYSERR;
2647 }
2648
2649 if (NGTCP2_CCERR_TYPE_IDLE_CLOSE == connection->last_error.type)
2650 {
2651 return GNUNET_SYSERR;
2652 }
2653
2654 if (GNUNET_NO != start_closing_period (connection))
2655 {
2656 return GNUNET_SYSERR;
2657 }
2658
2659 if (ngtcp2_conn_in_draining_period (connection->conn))
2660 {
2662 }
2663
2664 rv = send_conn_close (connection);
2665 if (NETWORK_ERR_OK != rv)
2666 {
2667 return rv;
2668 }
2669
2671}
2672
2673
2680static int
2681handle_expiry (struct Connection *connection)
2682{
2683 int rv;
2684
2685 rv = ngtcp2_conn_handle_expiry (connection->conn, timestamp ());
2686 if (0 != rv)
2687 {
2689 "ngtcp2_conn_handle_expiry: %s\n",
2690 ngtcp2_strerror (rv));
2691 ngtcp2_ccerr_set_liberr (&connection->last_error, rv, NULL, 0);
2692 return handle_error (connection);
2693 }
2694 return GNUNET_NO;
2695}
2696
2697
2703static void
2704timeoutcb (void *cls)
2705{
2706 struct Connection *connection = cls;
2707 int rv;
2708
2710 "timeoutcb func called!\n");
2711 connection->timer = NULL;
2712
2713 rv = handle_expiry (connection);
2714 if (GNUNET_NO != rv)
2715 {
2716 if (GNUNET_YES == connection->is_initiator)
2717 {
2718 return;
2719 }
2720 switch (rv)
2721 {
2723 return;
2724 default:
2725 connection_destroy (connection);
2726 return;
2727 }
2728 }
2729
2730 rv = connection_write (connection);
2731 if (GNUNET_YES == connection->is_initiator)
2732 {
2733 return;
2734 }
2735 if (GNUNET_NO != rv)
2736 {
2737 switch (rv)
2738 {
2740 return;
2741 default:
2742 connection_destroy (connection);
2743 return;
2744 }
2745
2746 }
2747}
2748
2749
2755static void
2757{
2758 ngtcp2_tstamp expiry;
2759 ngtcp2_tstamp now;
2760 struct GNUNET_TIME_Relative delay;
2761
2763 "update_timer!\n");
2764 expiry = ngtcp2_conn_get_expiry (connection->conn);
2765 now = timestamp ();
2766
2767 if (NULL != connection->timer)
2768 {
2769 GNUNET_SCHEDULER_cancel (connection->timer);
2770 connection->timer = NULL;
2771 }
2772 if (now >= expiry)
2773 {
2775 "Timer has expired\n");
2776 connection->timer = GNUNET_SCHEDULER_add_now (timeoutcb, connection);
2777 return;
2778 }
2779
2781 "Timer set: %lf\n",
2782 (double) (expiry - now) / NGTCP2_SECONDS);
2783 /* ngtcp2_tstamp is nanosecond */
2785 (expiry - now) / 1000ULL + 1);
2786 connection->timer = GNUNET_SCHEDULER_add_delayed (delay, timeoutcb,
2787 connection);
2788}
2789
2790
2798static int
2800{
2801 uint8_t buf[1280];
2802 ngtcp2_tstamp ts = timestamp ();
2803 ngtcp2_path_storage ps;
2804 int64_t stream_id;
2805 uint32_t flags;
2806 ngtcp2_ssize nwrite;
2807 ngtcp2_ssize wdatalen;
2808 nghttp3_vec vec[16];
2809 nghttp3_ssize sveccnt;
2810 ngtcp2_pkt_info pi;
2811 int fin;
2812 int rv;
2813
2814 ngtcp2_path_storage_zero (&ps);
2815
2816 for (;;)
2817 {
2818 stream_id = -1;
2819 fin = 0;
2820 sveccnt = 0;
2821
2822 if (connection->h3_conn &&
2823 ngtcp2_conn_get_max_data_left (connection->conn))
2824 {
2825 sveccnt = nghttp3_conn_writev_stream (connection->h3_conn,
2826 &stream_id,
2827 &fin,
2828 vec,
2829 16);
2830 if (sveccnt < 0)
2831 {
2833 "nghttp3_conn_writev_stream: %s\n",
2834 nghttp3_strerror (sveccnt));
2835
2836 ngtcp2_ccerr_set_application_error (
2837 &connection->last_error,
2838 nghttp3_err_infer_quic_app_error_code (sveccnt),
2839 NULL,
2840 0);
2841 return handle_error (connection);
2842 }
2843 }
2844
2845 flags = NGTCP2_WRITE_STREAM_FLAG_MORE;
2846 if (fin)
2847 flags |= NGTCP2_WRITE_STREAM_FLAG_FIN;
2848
2849 nwrite = ngtcp2_conn_writev_stream (connection->conn,
2850 &ps.path,
2851 &pi,
2852 buf,
2853 sizeof(buf),
2854 &wdatalen,
2855 flags,
2856 stream_id,
2857 (ngtcp2_vec *) vec,
2858 (size_t) sveccnt,
2859 ts);
2860 if (nwrite < 0)
2861 {
2862 switch (nwrite)
2863 {
2864 case NGTCP2_ERR_STREAM_DATA_BLOCKED:
2865 nghttp3_conn_block_stream (connection->h3_conn, stream_id);
2866 continue;
2867 case NGTCP2_ERR_STREAM_SHUT_WR:
2868 nghttp3_conn_shutdown_stream_write (connection->h3_conn, stream_id);
2869 continue;
2870 case NGTCP2_ERR_WRITE_MORE:
2871 rv = nghttp3_conn_add_write_offset (connection->h3_conn, stream_id,
2872 wdatalen);
2873 if (0 != rv)
2874 {
2876 "nghttp3_conn_add_write_offset: %s\n",
2877 nghttp3_strerror (rv));
2878 ngtcp2_ccerr_set_application_error (
2879 &connection->last_error,
2880 nghttp3_err_infer_quic_app_error_code (rv),
2881 NULL, 0);
2882 return handle_error (connection);
2883 }
2884 continue;
2885 }
2887 "ngtcp2_conn_writev_stream: %s\n",
2888 ngtcp2_strerror (nwrite));
2889 ngtcp2_ccerr_set_liberr (&connection->last_error,
2890 nwrite,
2891 NULL,
2892 0);
2893 return handle_error (connection);
2894 }
2895 if (0 == nwrite)
2896 {
2897 ngtcp2_conn_update_pkt_tx_time (connection->conn, ts);
2898 return 0;
2899 }
2900 if (wdatalen > 0)
2901 {
2902 rv = nghttp3_conn_add_write_offset (connection->h3_conn, stream_id,
2903 wdatalen);
2904 if (0 != rv)
2905 {
2907 "nghttp3_conn_add_write_offset: %s\n",
2908 nghttp3_strerror (rv));
2909 ngtcp2_ccerr_set_application_error (
2910 &connection->last_error,
2911 nghttp3_err_infer_quic_app_error_code (rv),
2912 NULL, 0);
2913 return handle_error (connection);
2914 }
2915 }
2916 if (GNUNET_NO != send_packet (connection, buf, nwrite))
2917 break;
2918 }
2919
2920 return GNUNET_NO;
2921}
2922
2923
2931static int
2932connection_write (struct Connection *connection)
2933{
2934 int rv;
2935
2936 if (GNUNET_NO == connection->is_initiator &&
2937 (ngtcp2_conn_in_closing_period (connection->conn) ||
2938 ngtcp2_conn_in_draining_period (connection->conn)))
2939 {
2940 return GNUNET_NO;
2941 }
2942
2943 rv = connection_write_streams (connection);
2944 if (GNUNET_NO != rv)
2945 {
2946 return rv;
2947 }
2948 connection_update_timer (connection);
2949
2950 return GNUNET_NO;
2951}
2952
2953
2972static int
2973mq_init (void *cls,
2974 const struct GNUNET_PeerIdentity *peer_id,
2975 const char *address)
2976{
2977 struct Connection *connection;
2978 struct sockaddr *local_addr;
2979 socklen_t local_addrlen;
2980 struct sockaddr *remote_addr;
2981 socklen_t remote_addrlen;
2982 const char *path;
2983 char *bindto;
2984 struct GNUNET_HashCode remote_addr_key;
2985 int rv;
2986
2987 if (GNUNET_OK !=
2990 "BINDTO",
2991 &bindto))
2992 {
2995 "BINDTO");
2996 return GNUNET_SYSERR;
2997 }
2998 local_addr = udp_address_to_sockaddr (bindto, &local_addrlen);
2999 if (0 != strncmp (address,
3001 strlen (COMMUNICATOR_ADDRESS_PREFIX "-")))
3002 {
3003 GNUNET_break_op (0);
3004 return GNUNET_SYSERR;
3005 }
3006 path = &address[strlen (COMMUNICATOR_ADDRESS_PREFIX "-")];
3007 remote_addr = udp_address_to_sockaddr (path, &remote_addrlen);
3008
3009 GNUNET_CRYPTO_hash (address, strlen (address), &remote_addr_key);
3010 connection = GNUNET_CONTAINER_multihashmap_get (addr_map, &remote_addr_key);
3011 if (NULL != connection)
3012 {
3014 "receiver %s already exist or is being connected to\n",
3015 address);
3016 return GNUNET_SYSERR;
3017 }
3018
3019 /* Create a new connection */
3020 connection = GNUNET_new (struct Connection);
3021 connection->address = remote_addr;
3022 connection->address_len = remote_addrlen;
3023 connection->target = *peer_id;
3024 connection->is_initiator = GNUNET_YES;
3025 connection->id_rcvd = GNUNET_YES;
3026 connection->id_sent = GNUNET_NO;
3027 connection->foreign_addr =
3028 sockaddr_to_udpaddr_string (connection->address, connection->address_len);
3029 connection->nt = GNUNET_NT_scanner_get_type (is,
3031 remote_addrlen);
3032 connection->timeout =
3036 &remote_addr_key,
3037 connection,
3040 "# connections active",
3042 GNUNET_NO);
3043
3044 /* client_gnutls_init */
3045 rv = client_gnutls_init (connection);
3046 if (GNUNET_NO != rv)
3047 {
3048 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "client_gnutls_init failed\n");
3049 return GNUNET_SYSERR;
3050 }
3051
3052 /* client_quic_init */
3053 rv = client_quic_init (connection,
3054 local_addr, local_addrlen,
3055 remote_addr, remote_addrlen);
3056 if (GNUNET_NO != rv)
3057 {
3058 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "client_quic_init failed\n");
3059 return GNUNET_SYSERR;
3060 }
3061
3062 ngtcp2_conn_set_tls_native_handle (connection->conn, connection->session);
3063
3064 rv = connection_write (connection);
3065 if (GNUNET_NO != rv)
3066 {
3068 "connection_write failed\n");
3069 return GNUNET_SYSERR;
3070 }
3072 return GNUNET_OK;
3073}
3074
3075
3089static void
3091 void **app_ctx,
3092 int add_remove,
3094 const struct sockaddr *addr,
3095 socklen_t addrlen)
3096{
3097 char *my_addr;
3099
3100 if (GNUNET_YES == add_remove)
3101 {
3103
3104 GNUNET_asprintf (&my_addr,
3105 "%s-%s",
3107 GNUNET_a2s (addr, addrlen));
3108 nt = GNUNET_NT_scanner_get_type (is, addr, addrlen);
3109 ai =
3111 my_addr,
3112 nt,
3114 GNUNET_free (my_addr);
3115 *app_ctx = ai;
3116 }
3117 else
3118 {
3119 ai = *app_ctx;
3121 *app_ctx = NULL;
3122 }
3123}
3124
3125
3134static int
3136 const struct GNUNET_HashCode *key,
3137 void *value)
3138{
3139 struct Connection *connection = value;
3140 (void) cls;
3141 (void) key;
3142 handle_error (connection);
3143 connection_destroy (connection);
3144 return GNUNET_OK;
3145}
3146
3147
3153static void
3154do_shutdown (void *cls)
3155{
3157 "do_shutdown start\n");
3160 NULL);
3162 gnutls_certificate_free_credentials (cred);
3163
3164 if (NULL != nat)
3165 {
3167 nat = NULL;
3168 }
3169 if (NULL != read_task)
3170 {
3172 read_task = NULL;
3173 }
3174 if (NULL != udp_sock)
3175 {
3178 udp_sock = NULL;
3179 }
3180 if (NULL != ch)
3181 {
3183 ch = NULL;
3184 }
3185 if (NULL != stats)
3186 {
3188 stats = NULL;
3189 }
3190 if (NULL != my_private_key)
3191 {
3193 my_private_key = NULL;
3194 }
3195 if (NULL != is)
3196 {
3198 is = NULL;
3199 }
3201 "do_shutdown finished\n");
3202}
3203
3204
3219static int
3221 struct sockaddr *local_addr, socklen_t local_addrlen,
3222 struct sockaddr *remote_addr, socklen_t remote_addrlen,
3223 const ngtcp2_pkt_info *pi,
3224 const uint8_t *data, size_t datalen)
3225{
3226 ngtcp2_path path;
3227 int rv;
3228
3229 path.local.addr = local_addr;
3230 path.local.addrlen = local_addrlen;
3231 path.remote.addr = remote_addr;
3232 path.remote.addrlen = remote_addrlen;
3233
3234 rv = ngtcp2_conn_read_pkt (connection->conn, &path, pi, data, datalen,
3235 timestamp ());
3236 if (0 != rv)
3237 {
3239 "ngtcp2_conn_read_pkt: %s\n",
3240 ngtcp2_strerror (rv));
3241 switch (rv)
3242 {
3243 case NGTCP2_ERR_DRAINING:
3244 if (GNUNET_NO == connection->is_initiator)
3245 {
3246 start_draining_period (connection);
3248 }
3249 else
3250 {
3251 ngtcp2_ccerr_set_liberr (&connection->last_error, rv, NULL, 0);
3252 }
3253 case NGTCP2_ERR_RETRY:
3254 /* client side doesn't get this */
3255 return NETWORK_ERR_RETRY;
3256 case NGTCP2_ERR_DROP_CONN:
3257 /* client side doesn't get this */
3258 return NETWORK_ERR_DROP_CONN;
3259 case NGTCP2_ERR_CRYPTO:
3260 if (! connection->last_error.error_code)
3261 {
3262 ngtcp2_ccerr_set_tls_alert (
3263 &connection->last_error,
3264 ngtcp2_conn_get_tls_alert (connection->conn),
3265 NULL, 0);
3266 }
3267 break;
3268 default:
3269 if (! connection->last_error.error_code)
3270 {
3271 ngtcp2_ccerr_set_liberr (&connection->last_error, rv, NULL, 0);
3272 }
3273 }
3274 return handle_error (connection);
3275 }
3276 return GNUNET_NO;
3277}
3278
3279
3295static int
3296connection_on_read (struct Connection *connection,
3297 struct sockaddr *local_addr, socklen_t local_addrlen,
3298 struct sockaddr *remote_addr, socklen_t remote_addrlen,
3299 const ngtcp2_pkt_info *pi,
3300 const uint8_t *data, size_t datalen)
3301{
3302 int rv;
3303 rv = connection_feed_data (connection, local_addr, local_addrlen, remote_addr,
3304 remote_addrlen, pi, data, datalen);
3305 if (GNUNET_NO != rv)
3306 {
3307 return rv;
3308 }
3309
3310 connection_update_timer (connection);
3311 return GNUNET_NO;
3312}
3313
3314
3328static struct Connection *
3329connection_init (struct sockaddr *local_addr,
3330 socklen_t local_addrlen,
3331 struct sockaddr *remote_addr,
3332 socklen_t remote_addrlen,
3333 const ngtcp2_cid *dcid, const ngtcp2_cid *scid,
3334 uint32_t version)
3335{
3336 struct Connection *new_connection;
3337 ngtcp2_path path;
3338 ngtcp2_transport_params params;
3339 ngtcp2_cid scid_;
3340 ngtcp2_conn *conn = NULL;
3341 ngtcp2_settings settings;
3342 ngtcp2_callbacks callbacks = {
3343 .recv_client_initial = ngtcp2_crypto_recv_client_initial_cb,
3344 .recv_crypto_data = ngtcp2_crypto_recv_crypto_data_cb,
3345 .encrypt = ngtcp2_crypto_encrypt_cb,
3346 .decrypt = ngtcp2_crypto_decrypt_cb,
3347 .hp_mask = ngtcp2_crypto_hp_mask_cb,
3348 .update_key = ngtcp2_crypto_update_key_cb,
3349 .delete_crypto_aead_ctx = ngtcp2_crypto_delete_crypto_aead_ctx_cb,
3350 .delete_crypto_cipher_ctx = ngtcp2_crypto_delete_crypto_cipher_ctx_cb,
3351 .get_path_challenge_data = ngtcp2_crypto_get_path_challenge_data_cb,
3352 .version_negotiation = ngtcp2_crypto_version_negotiation_cb,
3353
3354 .acked_stream_data_offset = acked_stream_data_offset_cb,
3355 .recv_stream_data = recv_stream_data_cb,
3356 .stream_open = stream_open_cb,
3357 .rand = rand_cb,
3358 .get_new_connection_id = get_new_connection_id_cb,
3359 .stream_close = stream_close_cb,
3360 .extend_max_remote_streams_bidi = extend_max_remote_streams_bidi_cb,
3361 .stream_stop_sending = stream_stop_sending_cb,
3362 .extend_max_stream_data = extend_max_stream_data_cb,
3363 .recv_tx_key = recv_tx_key_cb,
3364 };
3365
3366
3367 int rv;
3368
3369 path.local.addr = local_addr;
3370 path.local.addrlen = local_addrlen;
3371 path.remote.addr = remote_addr;
3372 path.remote.addrlen = remote_addrlen;
3373
3374 new_connection = GNUNET_new (struct Connection);
3375 memset (new_connection, 0, sizeof (struct Connection));
3376
3377 gnutls_init (&new_connection->session,
3378 GNUTLS_SERVER
3379 | GNUTLS_ENABLE_EARLY_DATA
3380 | GNUTLS_NO_END_OF_EARLY_DATA);
3381 gnutls_priority_set_direct (new_connection->session, PRIORITY, NULL);
3382 gnutls_credentials_set (new_connection->session,
3383 GNUTLS_CRD_CERTIFICATE, cred);
3384
3385 ngtcp2_transport_params_default (&params);
3386 params.initial_max_streams_uni = 3;
3387 params.initial_max_streams_bidi = 128;
3388 params.initial_max_stream_data_bidi_local = 128 * 1024;
3389 params.initial_max_stream_data_bidi_remote = 256 * 1024;
3390 params.initial_max_stream_data_uni = 256 * 1024;
3391 params.initial_max_data = 1024 * 1024;
3392 params.original_dcid_present = 1;
3393 params.max_idle_timeout = 30 * NGTCP2_SECONDS;
3394 params.original_dcid = *scid;
3395
3396 ngtcp2_settings_default (&settings);
3397
3398 scid_.datalen = NGTCP2_MAX_CIDLEN;
3400 &scid_.data, scid_.datalen);
3401
3402 rv = ngtcp2_conn_server_new (&conn,
3403 dcid,
3404 &scid_,
3405 &path,
3406 version,
3407 &callbacks,
3408 &settings,
3409 &params,
3410 NULL,
3411 new_connection);
3412 if (rv < 0)
3413 {
3415 "ngtcp2_conn_server_new: %s\n",
3416 ngtcp2_strerror (rv));
3417 return NULL;
3418 }
3419 new_connection->conn = conn;
3420 new_connection->address = GNUNET_memdup (remote_addr, remote_addrlen);
3421 new_connection->address_len = remote_addrlen;
3422 new_connection->foreign_addr =
3423 sockaddr_to_udpaddr_string (new_connection->address,
3424 new_connection->address_len);
3425 new_connection->is_initiator = GNUNET_NO;
3426 new_connection->id_rcvd = GNUNET_NO;
3427 new_connection->id_sent = GNUNET_NO;
3428 ngtcp2_crypto_gnutls_configure_server_session (new_connection->session);
3429 ngtcp2_conn_set_tls_native_handle (new_connection->conn,
3430 new_connection->session);
3431 gnutls_session_set_ptr (new_connection->session,
3432 &new_connection->conn_ref);
3433
3434 new_connection->conn_ref.get_conn = get_conn;
3435 new_connection->conn_ref.user_data = new_connection;
3436 new_connection->streams = GNUNET_CONTAINER_multihashmap_create (10,
3437 GNUNET_NO);
3438
3439 return new_connection;
3440}
3441
3442
3457static void
3458server_read_pkt (struct Connection *connection,
3459 const struct GNUNET_HashCode *addr_key,
3460 struct sockaddr *local_addr, socklen_t local_addrlen,
3461 struct sockaddr *remote_addr, socklen_t remote_addrlen,
3462 const ngtcp2_pkt_info *pi,
3463 const uint8_t *data, size_t datalen)
3464{
3465 ngtcp2_version_cid version_cid;
3466 int rv;
3467
3468 rv = ngtcp2_pkt_decode_version_cid (&version_cid, data, datalen,
3469 NGTCP2_MAX_CIDLEN);
3470 switch (rv)
3471 {
3472 case 0:
3473 break;
3474 case NGTCP2_ERR_VERSION_NEGOTIATION:
3475 // TODO: send version negotiation
3476 return;
3477 default:
3479 "Can't decode version and CID: %s\n",
3480 ngtcp2_strerror (rv));
3481 return;
3482 }
3483
3484 if (NULL == connection)
3485 {
3486 ngtcp2_pkt_hd header;
3487 rv = ngtcp2_accept (&header, data, datalen);
3488 if (0 != rv)
3489 {
3491 "ngtcp2_accept: %s\n",
3492 ngtcp2_strerror (rv));
3493 return;
3494 }
3495
3500 connection = connection_init (local_addr, local_addrlen, remote_addr,
3501 remote_addrlen, &header.scid, &header.dcid,
3502 header.version);
3503 if (NULL == connection)
3504 {
3506 "accept connection error!\n");
3507 return;
3508 }
3509
3511 addr_key,
3512 connection,
3514 rv = connection_on_read (connection, local_addr, local_addrlen, remote_addr,
3515 remote_addrlen, pi, data, datalen);
3516 switch (rv)
3517 {
3518 case 0:
3519 break;
3520 case NETWORK_ERR_RETRY:
3521 // TODO: send retry
3522 return;
3523 default:
3524 return;
3525 }
3526
3527 rv = connection_write (connection);
3528 if (GNUNET_NO != rv)
3529 {
3530 return;
3531 }
3532
3533 // add to cid_map here
3534 return;
3535 }
3536
3537 if (ngtcp2_conn_in_closing_period (connection->conn))
3538 {
3539 rv = send_conn_close (connection);
3540 if (GNUNET_NO != rv)
3541 {
3542 connection_destroy (connection);
3543 }
3544 return;
3545 }
3546
3547 if (ngtcp2_conn_in_draining_period (connection->conn))
3548 {
3549 return;
3550 }
3551
3552 rv = connection_on_read (connection, local_addr, local_addrlen, remote_addr,
3553 remote_addrlen, pi, data, datalen);
3554 if (GNUNET_NO != rv)
3555 {
3556 if (NETWORK_ERR_CLOSE_WAIT != rv)
3557 {
3558 connection_destroy (connection);
3559 }
3560 return;
3561 }
3562
3563 connection_write (connection);
3564}
3565
3566
3572static void
3573sock_read (void *cls)
3574{
3575 struct sockaddr_storage sa;
3576 socklen_t salen = sizeof (sa);
3577 ssize_t rcvd;
3578 uint8_t buf[UINT16_MAX];
3579 struct GNUNET_HashCode addr_key;
3580 struct Connection *connection;
3581 int rv;
3582 char *bindto;
3583 struct sockaddr *local_addr;
3584 socklen_t local_addrlen;
3585
3586 (void) cls;
3587 if (GNUNET_OK !=
3590 "BINDTO",
3591 &bindto))
3592 {
3595 "BINDTO");
3596 return;
3597 }
3598 local_addr = udp_address_to_sockaddr (bindto, &local_addrlen);
3600 udp_sock,
3601 &sock_read,
3602 NULL);
3603
3604 while (1)
3605 {
3606 char *addr_string;
3607
3609 buf,
3610 sizeof(buf),
3611 (struct sockaddr *) &sa,
3612 &salen);
3613 if (-1 == rcvd)
3614 {
3615 struct sockaddr *addr = (struct sockaddr*) &sa;
3616
3617 if (EAGAIN == errno)
3618 break; // We are done reading data
3620 "Failed to recv from %s family %d failed sock %p\n",
3621 GNUNET_a2s ((struct sockaddr*) &sa,
3622 sizeof (*addr)),
3623 addr->sa_family,
3624 udp_sock);
3626 return;
3627 }
3629 "Read %llu bytes\n",
3630 (unsigned long long) rcvd);
3631 if (0 == rcvd)
3632 {
3633 GNUNET_break_op (0);
3635 "Read 0 bytes from UDP socket\n");
3636 return;
3637 }
3638
3639 addr_string =
3640 sockaddr_to_udpaddr_string ((const struct sockaddr *) &sa,
3641 salen);
3642 GNUNET_CRYPTO_hash (addr_string, strlen (addr_string),
3643 &addr_key);
3644 GNUNET_free (addr_string);
3645 connection = GNUNET_CONTAINER_multihashmap_get (addr_map, &addr_key);
3646
3647 if (NULL != connection && GNUNET_YES == connection->is_initiator)
3648 {
3649 ngtcp2_pkt_info pi = {0};
3650
3651 rv = connection_feed_data (connection, local_addr, local_addrlen,
3652 (struct sockaddr *) &sa,
3653 salen, &pi, buf, rcvd);
3654 if (GNUNET_NO != rv)
3655 {
3656 return;
3657 }
3658 rv = connection_write (connection);
3659 if (rv < 0)
3660 {
3662 "connection write error!\n");
3663 return;
3664 }
3665 }
3666 else
3667 {
3668 ngtcp2_pkt_info pi = {0};
3669
3670 server_read_pkt (connection, &addr_key,
3671 local_addr, local_addrlen,
3672 (struct sockaddr *) &sa, salen,
3673 &pi, buf, rcvd);
3674 }
3675
3676 }
3677
3679
3680}
3681
3682
3691static void
3692run (void *cls,
3693 char *const *args,
3694 const char *cfgfile,
3695 const struct GNUNET_CONFIGURATION_Handle *c)
3696{
3697 char *bindto;
3698 struct sockaddr *in;
3699 socklen_t in_len;
3700 struct sockaddr_storage in_sto;
3701 socklen_t sto_len;
3702 char *cert_file;
3703 char *key_file;
3704 int rv;
3705
3706 (void) cls;
3707 cfg = c;
3708 if (GNUNET_OK !=
3711 "BINDTO",
3712 &bindto))
3713 {
3716 "BINDTO");
3717 return;
3718 }
3719
3720 key_file = NULL;
3721 cert_file = NULL;
3722 if ((GNUNET_OK !=
3725 "KEY_FILE",
3726 &key_file)))
3727 key_file = GNUNET_strdup ("https.key");
3728 if (GNUNET_OK !=
3731 "CERT_FILE",
3732 &cert_file))
3733 cert_file = GNUNET_strdup ("https.crt");
3734 if ((GNUNET_OK != GNUNET_DISK_file_test (key_file)) ||
3735 (GNUNET_OK != GNUNET_DISK_file_test (cert_file)))
3736 {
3737 struct GNUNET_Process *cert_creation;
3738
3740 "Creating new certificate\n");
3742 if (GNUNET_OK !=
3744 cert_creation,
3745 "gnunet-transport-certificate-creation",
3746 "gnunet-transport-certificate-creation",
3747 key_file,
3748 cert_file,
3749 NULL))
3750 {
3751 GNUNET_process_destroy (cert_creation);
3753 "Can't create new key pair %s/%s\n",
3754 key_file,
3755 cert_file);
3756 GNUNET_free (key_file);
3757 GNUNET_free (cert_file);
3758 return;
3759 }
3761 GNUNET_process_wait (cert_creation,
3762 true,
3763 NULL,
3764 NULL));
3765 GNUNET_process_destroy (cert_creation);
3766 }
3767
3769 if ((GNUNET_NO == GNUNET_NETWORK_test_pf (PF_INET6)) ||
3770 (GNUNET_YES ==
3773 "DISABLE_V6")))
3774 {
3776 }
3777
3778 in = udp_address_to_sockaddr (bindto, &in_len);
3779
3780 if (NULL == in)
3781 {
3783 "Failed to setup UDP socket address with path `%s'\n",
3784 bindto);
3785 GNUNET_free (bindto);
3786 return;
3787 }
3788 udp_sock =
3789 GNUNET_NETWORK_socket_create (in->sa_family,
3790 SOCK_DGRAM,
3791 IPPROTO_UDP);
3792 if (NULL == udp_sock)
3793 {
3796 "Failed to create socket for %s family %d\n",
3797 GNUNET_a2s (in,
3798 in_len),
3799 in->sa_family);
3800 GNUNET_free (in);
3801 GNUNET_free (bindto);
3802 return;
3803 }
3804 if (AF_INET6 == in->sa_family)
3806 if (GNUNET_OK !=
3808 in,
3809 in_len))
3810 {
3812 "bind",
3813 bindto);
3815 "Failed to bind socket for %s family %d sock %p\n",
3816 GNUNET_a2s (in,
3817 in_len),
3818 in->sa_family,
3819 udp_sock);
3821 udp_sock = NULL;
3822 GNUNET_free (in);
3823 GNUNET_free (bindto);
3824 return;
3825 }
3826 sto_len = sizeof(in_sto);
3827 if (0 != getsockname (GNUNET_NETWORK_get_fd (udp_sock),
3828 (struct sockaddr *) &in_sto,
3829 &sto_len))
3830 {
3831 memcpy (&in_sto, in, in_len);
3832 sto_len = in_len;
3833 }
3834 GNUNET_free (in);
3835 GNUNET_free (bindto);
3836 in = (struct sockaddr *) &in_sto;
3837 in_len = sto_len;
3839 "transport",
3840 "Bound to `%s' sock %p\n",
3841 GNUNET_a2s ((const struct sockaddr *) &in_sto,
3842 sto_len),
3843 udp_sock);
3844 switch (in->sa_family)
3845 {
3846 case AF_INET:
3847 my_port = ntohs (((struct sockaddr_in *) in)->sin_port);
3848 break;
3849
3850 case AF_INET6:
3851 my_port = ntohs (((struct sockaddr_in6 *) in)->sin6_port);
3852 break;
3853
3854 default:
3855 GNUNET_break (0);
3856 my_port = 0;
3857 }
3859
3862
3863 rv = gnutls_certificate_allocate_credentials (&cred);
3864 if (GNUNET_NO == rv)
3865 rv = gnutls_certificate_set_x509_system_trust (cred);
3866 if (GNUNET_NO > rv)
3867 {
3869 "cred init failed: %s\n",
3870 gnutls_strerror (rv));
3871 return;
3872 }
3873 rv = gnutls_certificate_set_x509_key_file (cred,
3874 cert_file,
3875 key_file,
3876 GNUTLS_X509_FMT_PEM);
3878 "key_file: %s\ncert_file: %s\n",
3879 key_file, cert_file);
3880 GNUNET_free (cert_file);
3881 GNUNET_free (key_file);
3882 if (rv < 0)
3883 {
3885 "gnutls_certificate_set_x509_key_file: %s\n",
3886 gnutls_strerror (rv));
3887 return;
3888 }
3893 if (NULL == my_private_key)
3894 {
3895 GNUNET_log (
3897 _ (
3898 "Transport service is lacking key configuration settings. Exiting.\n"));
3900 return;
3901 }
3903
3905 udp_sock,
3906 &sock_read,
3907 NULL);
3912 &mq_init,
3913 NULL,
3914 &notify_cb,
3915 NULL,
3916 NULL);
3917 if (NULL == ch)
3918 {
3919 GNUNET_break (0);
3921 return;
3922 }
3923
3926 IPPROTO_UDP,
3927 1 /* one address */,
3928 (const struct sockaddr **) &in,
3929 &in_len,
3932 NULL /* closure */);
3933}
3934
3935
3943int
3944main (int argc, char *const *argv)
3945{
3946 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
3948 };
3949 int ret;
3950
3952 "transport",
3953 "Starting http3 communicator\n");
3954 ret = (GNUNET_OK ==
3956 argc,
3957 argv,
3958 "gnunet-communicator-http3",
3959 _ ("GNUnet HTTP3 communicator"),
3960 options,
3961 &run,
3962 NULL))
3963 ? 0
3964 : 1;
3965 return ret;
3966}
3967
3968
3969/* end of gnunet-communicator-http3.c */
struct GNUNET_GETOPT_CommandLineOption options[]
Definition 002.c:5
struct GNUNET_MessageHeader * msg
Definition 005.c:2
int main()
Program to simulate results from GCP_get_desirability_of_path() for various plausible inputs.
static int start
Set if we are to start default services (including ARM).
Definition gnunet-arm.c:38
static int ret
Final status code.
Definition gnunet-arm.c:93
static int do_shutdown
Set to GNUNET_YES if we are shutting down.
static uint16_t port
Port number.
Definition gnunet-bcd.c:146
static char * peer_id
Option –peer.
static int send_conn_close(struct Connection *connection)
Send the packet in the conn_closebuf.
static void start_draining_period(struct Connection *connection)
Start the draining period, called after receiving CONNECTION_CLOSE.
static int recv_stream_data_cb(ngtcp2_conn *conn, uint32_t flags, int64_t stream_id, uint64_t offset, const uint8_t *data, size_t datalen, void *user_data, void *stream_user_data)
The callback function for ngtcp2_callbacks.recv_stream_data.
static int client_quic_init(struct Connection *connection, struct sockaddr *local_addr, socklen_t local_addrlen, struct sockaddr *remote_addr, socklen_t remote_addrlen)
Create new ngtcp2_conn as client side.
static int connection_write(struct Connection *connection)
Write the data in the stream into the packet and handle timer.
static int get_connection_delete_it(void *cls, const struct GNUNET_HashCode *key, void *value)
Iterator over all connection to clean up.
static void mq_destroy_d(struct GNUNET_MQ_Handle *mq, void *impl_state)
Signature of functions implementing the destruction of a message queue.
static int get_stream_delete_it(void *cls, const struct GNUNET_HashCode *key, void *value)
Iterator over all streams to clean up.
static int stream_open_cb(ngtcp2_conn *conn, int64_t stream_id, void *user_data)
The callback function for ngtcp2_callbacks.stream_open.
static struct GNUNET_PeerIdentity my_identity
Our peer identity.
static int http_reset_stream_cb(nghttp3_conn *conn, int64_t stream_id, uint64_t app_error_code, void *user_data, void *stream_user_data)
The callback of nghttp3_callback.reset_stream.
static int http_stop_sending_cb(nghttp3_conn *conn, int64_t stream_id, uint64_t app_error_code, void *user_data, void *stream_user_data)
The callback of nghttp3_callback.stop_sending.
#define PRIORITY
the priorities to use on the ciphers, key exchange methods, and macs.
static int stream_start_response(struct Connection *connection, struct Stream *stream)
Make response to the request.
#define COMMUNICATOR_ADDRESS_PREFIX
Address prefix used by the communicator.
static void long_poll_timeoutcb(void *cls)
Timeout callback function in the long polling struct.
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 int extend_max_stream_data_cb(ngtcp2_conn *conn, int64_t stream_id, uint64_t max_data, void *user_data, void *stream_user_data)
The callback function for ngtcp2_callbacks.extend_max_stream_data.
static int connection_write_streams(struct Connection *connection)
Write HTTP stream data and send the packets.
static int send_packet(struct Connection *connection, const uint8_t *data, size_t datalen)
Send the udp packet to remote.
static uint64_t timestamp(void)
Get current timestamp.
#define ADDRESS_VALIDITY_PERIOD
How long do we believe our addresses to remain up (before the other peer should revalidate).
static void rand_cb(uint8_t *dest, size_t destlen, const ngtcp2_rand_ctx *rand_ctx)
The callback function for ngtcp2_callbacks.rand.
static int stream_stop_sending_cb(ngtcp2_conn *conn, int64_t stream_id, uint64_t app_error_code, void *user_data, void *stream_user_data)
The callback function for ngtcp2_callbacks.stream_stop_sending.
static gnutls_certificate_credentials_t cred
The credential.
static int setup_httpconn(struct Connection *connection)
Setup the http3 connection.
network_error
Defines some error types related to network errors.
@ NETWORK_ERR_CLOSE_WAIT
@ NETWORK_ERR_SEND_BLOCKED
@ NETWORK_ERR_DROP_CONN
static int client_gnutls_init(struct Connection *connection)
As the client, initialize the corresponding connection.
static int http_end_stream_cb(nghttp3_conn *conn, int64_t stream_id, void *user_data, void *stream_user_data)
The callback of nghttp3_callback.end_stream.
static void connection_destroy(struct Connection *connection)
Destroys a receiving state due to timeout or shutdown.
static void try_connection_reversal(void *cls, const struct sockaddr *addr, socklen_t addrlen)
static int connection_feed_data(struct Connection *connection, struct sockaddr *local_addr, socklen_t local_addrlen, struct sockaddr *remote_addr, socklen_t remote_addrlen, const ngtcp2_pkt_info *pi, const uint8_t *data, size_t datalen)
Decrypt QUIC packet.
static struct GNUNET_NT_InterfaceScanner * is
Network scanner to determine network types.
static void connection_update_timer(struct Connection *connection)
Update the timer.
static int disable_v6
IPv6 disabled or not.
static struct Connection * connection_init(struct sockaddr *local_addr, socklen_t local_addrlen, struct sockaddr *remote_addr, socklen_t remote_addrlen, const ngtcp2_cid *dcid, const ngtcp2_cid *scid, uint32_t version)
Create a new connection.
static struct GNUNET_STATISTICS_Handle * stats
For logging statistics.
static const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
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 int recv_tx_key_cb(ngtcp2_conn *conn, ngtcp2_encryption_level level, void *user_data)
The callback function for ngtcp2_callbacks.recv_tx_key.
#define NUM_LONG_POLL
Long polling requests' number.
static void http_consume(struct Connection *connection, int64_t stream_id, size_t consumed)
Extend connection and stream offset.
static struct GNUNET_NETWORK_Handle * udp_sock
Our socket.
static nghttp3_ssize read_data(nghttp3_conn *conn, int64_t stream_id, nghttp3_vec *vec, size_t veccnt, uint32_t *pflags, void *user_data, void *stream_user_data)
The callback function to generate body.
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)
Socket read task.
#define COMMUNICATOR_CONFIG_SECTION
Configuration section used by the communicator.
static nghttp3_nv make_nv(const char *name, const char *value, uint8_t flag)
Make name/value pair for request headers.
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
Our environment.
static int get_new_connection_id_cb(ngtcp2_conn *conn, ngtcp2_cid *cid, uint8_t *token, size_t cidlen, void *user_data)
The callback function for ngtcp2_callbacks.get_new_connection_id.
static struct sockaddr * udp_address_to_sockaddr(const char *bindto, socklen_t *sock_len)
Convert UDP bind specification to a struct sockaddr *
static int extend_max_remote_streams_bidi_cb(ngtcp2_conn *conn, uint64_t max_streams, void *user_data)
The callback function for ngtcp2_callbacks.extend_max_remote_streams_bidi.
static int http_recv_data_cb(nghttp3_conn *conn, int64_t stream_id, const uint8_t *data, size_t datalen, void *user_data, void *stream_user_data)
The callback of nghttp3_callback.recv_data.
static void run(void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c)
Setup communicator and launch network interactions.
static void reschedule_peer_timeout(struct Connection *connection)
Increment connection timeout due to activity.
static struct GNUNET_NAT_Handle * nat
Connection to NAT service.
static int acked_stream_data_offset_cb(ngtcp2_conn *conn, int64_t stream_id, uint64_t offset, uint64_t datalen, void *user_data, void *stream_user_data)
The callback function for ngtcp2_callbacks.acked_stream_data_offset.
static struct GNUNET_CONTAINER_MultiHashMap * addr_map
Map of sockaddr -> struct Connection.
static struct GNUNET_SCHEDULER_Task * read_task
ID of listen task.
static int http_begin_headers_cb(nghttp3_conn *conn, int64_t stream_id, void *user_data, void *stream_user_data)
The callback of nghttp3_callback.begin_headers.
static int handle_error(struct Connection *connection)
Handle errors.
static void setup_connection_mq(struct Connection *connection)
Setup the MQ for the connection.
static void mq_cancel(struct GNUNET_MQ_Handle *mq, void *impl_state)
Implementation function that cancels the currently sent message.
static int have_v6_socket
GNUNET_YES if udp_sock supports IPv6.
static uint16_t my_port
Port number to which we are actually bound.
static int submit_post_request(struct Connection *connection, struct Stream *stream, const uint8_t *data, size_t datalen)
Submit the post request, send our data.
static void close_waitcb(void *cls)
The timeout callback function of closing/draining period.
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 int connection_on_read(struct Connection *connection, struct sockaddr *local_addr, socklen_t local_addrlen, struct sockaddr *remote_addr, socklen_t remote_addrlen, const ngtcp2_pkt_info *pi, const uint8_t *data, size_t datalen)
Connection read the packet data.
static struct Stream * create_stream(struct Connection *connection, int64_t stream_id)
Create a new stream of connection with stream_id.
static int stream_reset_cb(ngtcp2_conn *conn, int64_t stream_id, uint64_t final_size, uint64_t app_error_code, void *user_data, void *stream_user_data)
The callback function for ngtcp2_callbacks.stream_reset.
static ngtcp2_conn * get_conn(ngtcp2_crypto_conn_ref *ref)
The callback function for ngtcp2_crypto_conn_ref.
static int start_closing_period(struct Connection *connection)
Start the closing period and build the packet contains CONNECTION_CLOSE.
static struct GNUNET_CRYPTO_EddsaPrivateKey * my_private_key
Our private key.
static void server_read_pkt(struct Connection *connection, const struct GNUNET_HashCode *addr_key, struct sockaddr *local_addr, socklen_t local_addrlen, struct sockaddr *remote_addr, socklen_t remote_addrlen, const ngtcp2_pkt_info *pi, const uint8_t *data, size_t datalen)
The server processes the newly received data packet.
static void timeoutcb(void *cls)
The timer callback function.
static int handle_expiry(struct Connection *connection)
Handles expired timer.
static int http_deferred_consume_cb(nghttp3_conn *conn, int64_t stream_id, size_t nconsumed, void *user_data, void *stream_user_data)
The callback of nghttp3_callback.deferred_consume.
static struct Stream * find_stream(struct Connection *connection, int64_t stream_id)
Find the stream specified with stream_id in connection and return the pointer of the stream,...
static int stream_close_cb(ngtcp2_conn *conn, uint32_t flags, int64_t stream_id, uint64_t app_error_code, void *user_data, void *stream_user_data)
The callback function for ngtcp2_callbacks.stream_close.
static int submit_get_request(struct Connection *connection, struct Stream *stream)
Client side submits the GET request, allow the server to send messages.
static int recv_rx_key_cb(ngtcp2_conn *conn, ngtcp2_encryption_level level, void *user_data)
The callback function for ngtcp2_callbacks.recv_rx_key.
static void remove_stream(struct Connection *connection, int64_t stream_id)
Remove the stream with the specified stream_id in connection.
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 int http_stream_close_cb(nghttp3_conn *conn, int64_t stream_id, uint64_t app_error_code, void *conn_user_data, void *stream_user_data)
The callback of nghttp3_callback.stream_close.
static int http_recv_header_cb(nghttp3_conn *conn, int64_t stream_id, int32_t token, nghttp3_rcbuf *name, nghttp3_rcbuf *value, uint8_t flags, void *user_data, void *stream_user_data)
The callback of nghttp3_callback.recv_header.
static int stream_send_data(struct Stream *stream, uint8_t *data, size_t datalen)
Send message through the specified stream.
static struct GNUNET_TRANSPORT_AddressIdentifier * ai
Handle to the operation that publishes our address.
static char * address
GNS address for this phone.
static struct GNUNET_PEERSTORE_Handle * ps
Handle to the PEERSTORE service.
static char * data
The data to insert into the dht.
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 * name
Name (label) of the records to list.
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 * remote_addr
Remote address to use for connection reversal request.
Definition gnunet-nat.c:70
static char * local_addr
Local address to use for connection reversal request.
Definition gnunet-nat.c:65
static struct GNUNET_PeerIdentity pid
Identity of the peer we transmit to / connect to.
commonly used definitions; globals in this file are exempt from the rule that the module name ("commo...
Core service; the main API for encrypted P2P communications.
Constants for network protocols.
API to create, modify and access statistics.
Bandwidth allocation API for applications to interact with.
API of the transport service towards the communicator processes.
void GNUNET_TRANSPORT_communicator_address_remove(struct GNUNET_TRANSPORT_AddressIdentifier *ai)
Notify transport service about an address that this communicator no longer provides for this peer.
int GNUNET_TRANSPORT_communicator_receive(struct GNUNET_TRANSPORT_CommunicatorHandle *handle, const struct GNUNET_PeerIdentity *sender, const struct GNUNET_MessageHeader *msg, struct GNUNET_TIME_Relative expected_addr_validity, GNUNET_TRANSPORT_MessageCompletedCallback cb, void *cb_cls)
Notify transport service that the communicator has received a message.
void GNUNET_TRANSPORT_communicator_mq_del(struct GNUNET_TRANSPORT_QueueHandle *qh)
Notify transport service that an MQ became unavailable due to a disconnect or timeout.
#define GNUNET_TRANSPORT_QUEUE_LENGTH_UNLIMITED
Queue length.
struct GNUNET_TRANSPORT_QueueHandle * GNUNET_TRANSPORT_communicator_mq_add(struct GNUNET_TRANSPORT_CommunicatorHandle *ch, const struct GNUNET_PeerIdentity *peer, const char *address, uint32_t mtu, uint64_t q_len, uint32_t priority, enum GNUNET_NetworkType nt, enum GNUNET_TRANSPORT_ConnectionStatus cs, struct GNUNET_MQ_Handle *mq)
Notify transport service that a MQ became available due to an "inbound" connection or because the com...
void GNUNET_TRANSPORT_communicator_disconnect(struct GNUNET_TRANSPORT_CommunicatorHandle *ch)
Disconnect from the transport service.
struct GNUNET_TRANSPORT_CommunicatorHandle * GNUNET_TRANSPORT_communicator_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *config_section_name, const char *addr_prefix, enum GNUNET_TRANSPORT_CommunicatorCharacteristics cc, GNUNET_TRANSPORT_CommunicatorMqInit mq_init, void *mq_init_cls, GNUNET_TRANSPORT_CommunicatorNotify notify_cb, void *notify_cb_cls, 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_filename(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be the name of a file or directory.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
#define GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT
After how long do we consider a connection to a peer dead if we don't receive messages from the peer?
void GNUNET_CRYPTO_random_block(enum GNUNET_CRYPTO_Quality mode, void *buffer, size_t length)
Fill block with a random values.
void GNUNET_CRYPTO_eddsa_key_get_public(const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, struct GNUNET_CRYPTO_EddsaPublicKey *pub)
Extract the public key for the given private key.
Definition crypto_ecc.c:201
struct GNUNET_CRYPTO_EddsaPrivateKey * GNUNET_CRYPTO_eddsa_key_create_from_configuration(const struct GNUNET_CONFIGURATION_Handle *cfg)
Create a new private key by reading our peer's key from the file specified in the configuration.
@ GNUNET_CRYPTO_QUALITY_STRONG
High-quality operations are desired.
enum GNUNET_GenericReturnValue GNUNET_DISK_file_test(const char *fil)
Check that fil corresponds to a filename (of a file that exists and that is not a directory).
Definition disk.c:557
#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,...)
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_WARNING
@ 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_.
int GNUNET_snprintf(char *buf, size_t size, const char *format,...) __attribute__((format(printf
Like snprintf, just aborts if the buffer is of insufficient size.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.
#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
void GNUNET_NAT_unregister(struct GNUNET_NAT_Handle *nh)
Stop port redirection and public IP address detection for the given handle.
Definition nat_api.c:703
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.
void GNUNET_NT_scanner_done(struct GNUNET_NT_InterfaceScanner *is)
Terminate interface scanner.
Definition nt.c:428
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_process_run_command_va(struct GNUNET_Process *p, const char *filename,...)
Set the command and start a process.
Definition os_process.c:903
enum GNUNET_GenericReturnValue GNUNET_process_wait(struct GNUNET_Process *proc, bool blocking, enum GNUNET_OS_ProcessStatusType *type, unsigned long *code)
Wait for a process to terminate.
void GNUNET_process_destroy(struct GNUNET_Process *proc)
Cleans up process structure contents (OS-dependent) and deallocates it.
Definition os_process.c:363
struct GNUNET_Process * GNUNET_process_create(enum GNUNET_OS_InheritStdioFlags std_inheritance)
Create a process handle.
Definition os_process.c:462
@ GNUNET_OS_INHERIT_STD_OUT_AND_ERR
When these flags are set, the child process will inherit stdout and stderr of the parent.
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
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition scheduler.c:1310
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition scheduler.c:1283
void GNUNET_STATISTICS_set(struct GNUNET_STATISTICS_Handle *handle, const char *name, uint64_t value, int make_persistent)
Set statistic value for the peer.
void GNUNET_STATISTICS_destroy(struct GNUNET_STATISTICS_Handle *h, int sync_first)
Destroy a handle (free all state associated with it).
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
#define GNUNET_TIME_UNIT_SECONDS
One second.
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
struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Multiply relative time by a given factor.
Definition time.c:486
#define GNUNET_TIME_UNIT_MICROSECONDS
One microsecond, our basic time unit.
#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.
Used to keep track of context of peer.
ngtcp2_conn * conn
The QUIC connection.
ngtcp2_ssize conn_closebuflen
The length of conn_closebuf;.
enum GNUNET_NetworkType nt
Which network type does this queue use?
gnutls_session_t session
The gnutls session.
struct Long_Poll_Request * long_poll_head
head pointer of long polling struct queue.
ngtcp2_crypto_conn_ref conn_ref
The structure to get a pointer to ngtcp2_conn.
struct sockaddr * address
Address of the other peer.
int is_initiator
Flag to indicate if we are the initiator of the connection.
nghttp3_conn * h3_conn
The HTTP/3 connection.
struct Long_Poll_Request * long_poll_rear
rear pointer of long polling struct queue.
struct GNUNET_TRANSPORT_QueueHandle * d_qh
handle for default queue with the ch.
size_t d_mtu
MTU we allowed transport for this receiver's default queue.
struct GNUNET_PeerIdentity target
To whom are we talking to.
struct HTTP_Message * msg_queue_rear
rear pointer of message queue.
char * foreign_addr
Address of the receiver in the human-readable format with the COMMUNICATOR_ADDRESS_PREFIX.
struct GNUNET_CONTAINER_MultiHashMap * streams
Information of the stream.
int id_rcvd
Flag to indicate whether we know the PeerIdentity (target) yet.
struct GNUNET_TIME_Absolute timeout
Timeout for this connection.
struct GNUNET_MQ_Handle * d_mq
Default message queue we are providing for the ch.
ngtcp2_ccerr last_error
The connection error.
uint8_t * conn_closebuf
conn_closebuf contains a packet which contains CONNECTION_CLOSE.
size_t long_poll_len
length of long polling struct queue.
struct HTTP_Message * msg_queue_head
head pointer of message queue.
struct HTTP_Message * submitted_msg_queue_head
Messages that have been submitted will be put into this queue.
socklen_t address_len
Length of the address.
int connection_destroy_called
connection_destroy already called on connection.
struct GNUNET_SCHEDULER_Task * timer
The timer of this connection.
int id_sent
Flag to indicate whether we have sent OUR PeerIdentity to this peer.
size_t msg_queue_len
length of message queue.
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.
Handle for active NAT registrations.
Definition nat_api.c:72
handle to a socket
Definition network.c:53
Handle to the interface scanner.
Definition nt.c:104
The identity of the host (wraps the signing key of the peer).
struct GNUNET_CRYPTO_EddsaPublicKey public_key
Entry in list of pending tasks.
Definition scheduler.c:141
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...
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.
Message to send using http.
size_t size
buffer length
char * buf
buffer containing data to send
struct HTTP_Message * next
next pointer for double linked list
Long polling structure.
uint64_t delay_time
Timeout value.
struct Long_Poll_Request * prev
Previous structure.
struct Long_Poll_Request * next
Next structure.
struct Stream * stream
The long polling stream.
struct GNUNET_SCHEDULER_Task * timer
Timeout timer for long polling stream.
Information of a stream.
size_t urilen
The length of request uri.
struct Connection * connection
The connection that stream belongs to.
size_t authoritylen
The length of request authority.
uint8_t * uri
The request uri.
uint8_t * method
The request method.
uint8_t * data
The stream data.
uint64_t datalen
The length of stream data.
int64_t stream_id
ID of this stream.
size_t methodlen
The length of request method.
uint8_t * authority
The request authority.
struct Long_Poll_Request * long_poll_struct
The long polling request structure.