GNUnet 0.22.2
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
58{
65};
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
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, const char *value, uint8_t flag)
962{
963 nghttp3_nv nv;
964 nv.name = (const uint8_t *) name;
965 nv.namelen = strlen (name);
966 nv.value = (const uint8_t *) value;
967 nv.valuelen = strlen (value);
968 nv.flags = flag;
969
970 return nv;
971}
972
973
977static nghttp3_ssize
978read_data (nghttp3_conn *conn, int64_t stream_id, nghttp3_vec *vec,
979 size_t veccnt, uint32_t *pflags, void *user_data,
980 void *stream_user_data)
981{
982 struct Stream *stream = stream_user_data;
983
984 vec[0].base = stream->data;
985 vec[0].len = stream->datalen;
986 *pflags |= NGHTTP3_DATA_FLAG_EOF;
987
988 return 1;
989}
990
991
1002static int
1004 struct Stream *stream,
1005 const uint8_t *data,
1006 size_t datalen)
1007{
1008 nghttp3_nv nva[7];
1009 char contentlen[20];
1010 nghttp3_data_reader dr = {};
1011 int rv;
1012
1013 GNUNET_snprintf (contentlen, sizeof(contentlen), "%zu", datalen);
1014 stream->data = (uint8_t *) data;
1015 stream->datalen = datalen;
1016
1017 nva[0] = make_nv (":method", "POST",
1018 NGHTTP3_NV_FLAG_NO_COPY_NAME
1019 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1020 nva[1] = make_nv (":scheme", "https",
1021 NGHTTP3_NV_FLAG_NO_COPY_NAME
1022 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1023 nva[2] = make_nv (":authority",
1025 NGHTTP3_NV_FLAG_NO_COPY_NAME);
1026 nva[3] = make_nv (":path", "/",
1027 NGHTTP3_NV_FLAG_NO_COPY_NAME
1028 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1029 nva[4] = make_nv ("user-agent", "nghttp3/ngtcp2 client",
1030 NGHTTP3_NV_FLAG_NO_COPY_NAME
1031 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1032 nva[5] = make_nv ("content-type", "application/octet-stream",
1033 NGHTTP3_NV_FLAG_NO_COPY_NAME
1034 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1035 nva[6] = make_nv ("content-length", contentlen,
1036 NGHTTP3_NV_FLAG_NO_COPY_NAME);
1037
1038 dr.read_data = read_data;
1039 rv = nghttp3_conn_submit_request (connection->h3_conn,
1040 stream->stream_id,
1041 nva, 7, &dr, stream);
1042 if (0 != rv)
1043 {
1045 "nghttp3_conn_submit_request: %s\n",
1046 nghttp3_strerror (rv));
1047 return GNUNET_SYSERR;
1048 }
1049
1050 return GNUNET_NO;
1051}
1052
1053
1063static int
1065 struct Stream *stream)
1066{
1068 "send get request\n");
1069 nghttp3_nv nva[6];
1070 int rv;
1071
1072 nva[0] = make_nv (":method", "GET",
1073 NGHTTP3_NV_FLAG_NO_COPY_NAME
1074 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1075 nva[1] = make_nv (":scheme", "https",
1076 NGHTTP3_NV_FLAG_NO_COPY_NAME
1077 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1078 nva[2] = make_nv (":authority",
1080 NGHTTP3_NV_FLAG_NO_COPY_NAME);
1081 nva[3] = make_nv (":path", "/",
1082 NGHTTP3_NV_FLAG_NO_COPY_NAME
1083 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1084 nva[4] = make_nv ("user-agent", "nghttp3/ngtcp2 client",
1085 NGHTTP3_NV_FLAG_NO_COPY_NAME
1086 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1087
1088 rv = nghttp3_conn_submit_request (connection->h3_conn,
1089 stream->stream_id,
1090 nva, 5, NULL, stream);
1091 if (0 != rv)
1092 {
1094 "nghttp3_conn_submit_request: %s\n",
1095 nghttp3_strerror (rv));
1096 return GNUNET_SYSERR;
1097 }
1098
1099 return GNUNET_NO;
1100}
1101
1102
1108static void
1110{
1112 "long_poll_timeoutcb called!\n");
1113 struct Long_Poll_Request *long_poll = cls;
1114 nghttp3_nv nva[2];
1115 struct Stream *stream;
1116 struct Connection *connection;
1117 int rv;
1118
1119 long_poll->timer = NULL;
1120
1121 stream = long_poll->stream;
1122 connection = stream->connection;
1123 if (NULL != long_poll->prev)
1124 {
1125 long_poll->prev->next = long_poll->next;
1126 }
1127 if (NULL != long_poll->next)
1128 {
1129 long_poll->next->prev = long_poll->prev;
1130 }
1131 if (connection->long_poll_head == long_poll)
1132 {
1133 connection->long_poll_head = long_poll->next;
1134 }
1135 if (connection->long_poll_rear == long_poll)
1136 {
1137 connection->long_poll_rear = long_poll->prev;
1138 }
1139 GNUNET_free (long_poll);
1140
1141 nva[0] = make_nv (":status", "204",
1142 NGHTTP3_NV_FLAG_NO_COPY_NAME
1143 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1144 nva[1] = make_nv ("server", "nghttp3/ngtcp2 server",
1145 NGHTTP3_NV_FLAG_NO_COPY_NAME
1146 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1147 rv = nghttp3_conn_submit_response (connection->h3_conn,
1148 stream->stream_id, nva, 2, NULL);
1149 if (0 != rv)
1150 {
1152 "nghttp3_conn_submit_response: %s\n",
1153 nghttp3_strerror (rv));
1154 return;
1155 }
1156 ngtcp2_conn_shutdown_stream_read (connection->conn, 0,
1157 stream->stream_id,
1158 NGHTTP3_H3_NO_ERROR);
1159}
1160
1161
1172static int
1173stream_send_data (struct Stream *stream,
1174 uint8_t *data, size_t datalen)
1175{
1176 nghttp3_nv nva[4];
1177 nghttp3_data_reader dr = {};
1178 char content_length_str[20];
1179 int rv;
1180
1181 GNUNET_snprintf (content_length_str, sizeof(content_length_str),
1182 "%zu", datalen);
1183 nva[0] = make_nv (":status", "200",
1184 NGHTTP3_NV_FLAG_NO_COPY_NAME
1185 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1186 nva[1] = make_nv ("server", "nghttp3/ngtcp2 server",
1187 NGHTTP3_NV_FLAG_NO_COPY_NAME
1188 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1189 nva[2] = make_nv ("content-type", "application/octet-stream",
1190 NGHTTP3_NV_FLAG_NO_COPY_NAME
1191 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1192 nva[3] = make_nv ("content-length", content_length_str,
1193 NGHTTP3_NV_FLAG_NO_COPY_NAME);
1194
1195 stream->data = data;
1196 stream->datalen = datalen;
1197 dr.read_data = read_data;
1198 rv = nghttp3_conn_submit_response (stream->connection->h3_conn,
1199 stream->stream_id,
1200 nva, 4, &dr);
1201 if (0 != rv)
1202 {
1204 "nghttp3_conn_submit_response: %s\n",
1205 nghttp3_strerror (rv));
1206 return GNUNET_SYSERR;
1207 }
1208 return GNUNET_NO;
1209}
1210
1211
1220static int
1221stream_start_response (struct Connection *connection, struct Stream *stream)
1222{
1223 nghttp3_nv nva[4];
1224 struct HTTP_Message *msg;
1225 struct Long_Poll_Request *long_poll;
1226 struct GNUNET_TIME_Relative delay;
1227 int rv;
1228
1229 nva[0] = make_nv (":status", "200",
1230 NGHTTP3_NV_FLAG_NO_COPY_NAME
1231 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1232 nva[1] = make_nv ("server", "nghttp3/ngtcp2 server",
1233 NGHTTP3_NV_FLAG_NO_COPY_NAME
1234 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1235
1236 // method is POST
1237 if (4 == stream->methodlen)
1238 {
1239 if (NULL == connection->msg_queue_head)
1240 {
1241 rv = nghttp3_conn_submit_response (connection->h3_conn, stream->stream_id,
1242 nva, 2, NULL);
1243 if (0 != rv)
1244 {
1246 "nghttp3_conn_submit_response: %s\n",
1247 nghttp3_strerror (rv));
1248 return GNUNET_SYSERR;
1249 }
1250 }
1251 else
1252 {
1253 connection->msg_queue_len -= 1;
1255 "rm msg, len = %lu\n",
1256 connection->msg_queue_len);
1257 msg = connection->msg_queue_head;
1258 stream_send_data (stream, (uint8_t *) msg->buf, msg->size);
1259 connection->msg_queue_head = msg->next;
1260 msg->next = connection->submitted_msg_queue_head;
1261 connection->submitted_msg_queue_head = msg;
1262 }
1263 }
1264 // method is GET
1265 else
1266 {
1268 "server recv GET request\n");
1269 if (NULL != connection->msg_queue_head &&
1270 NULL == connection->long_poll_head)
1271 {
1272 msg = connection->msg_queue_head;
1273 stream_send_data (stream,
1274 (uint8_t *) msg->buf,
1275 msg->size);
1276 connection->msg_queue_head = msg->next;
1277 msg->next = connection->submitted_msg_queue_head;
1278 connection->submitted_msg_queue_head = msg;
1279 }
1280 else if (NULL == connection->msg_queue_head ||
1281 NULL != connection->long_poll_head)
1282 {
1283 connection->long_poll_len += 1;
1285 "add long_poll, len = %lu\n",
1286 connection->long_poll_len);
1287 long_poll = GNUNET_new (struct Long_Poll_Request);
1288 long_poll->stream = stream;
1289 long_poll->next = NULL;
1290 long_poll->prev = connection->long_poll_rear;
1291 long_poll->delay_time = 1ULL;
1292 if (NULL != connection->long_poll_rear)
1293 {
1294 connection->long_poll_rear->next = long_poll;
1295 long_poll->delay_time =
1296 (connection->long_poll_head->delay_time & (NUM_LONG_POLL - 1)) + 1ULL;
1297 }
1298 connection->long_poll_rear = long_poll;
1299 if (NULL == connection->long_poll_head)
1300 {
1301 connection->long_poll_head = long_poll;
1302 }
1304 long_poll->delay_time);
1305 long_poll->timer = GNUNET_SCHEDULER_add_delayed (delay,
1307 long_poll);
1308 }
1309 long_poll = connection->long_poll_head;
1310
1311 while (NULL != long_poll &&
1312 NULL != connection->msg_queue_head)
1313 {
1314 GNUNET_SCHEDULER_cancel (long_poll->timer);
1315 if (NULL != long_poll->next)
1316 {
1317 long_poll->next->prev = NULL;
1318 }
1319
1320 msg = connection->msg_queue_head;
1321 connection->msg_queue_head = msg->next;
1322 msg->next = connection->submitted_msg_queue_head;
1323 connection->submitted_msg_queue_head = msg;
1324 stream_send_data (long_poll->stream,
1325 (uint8_t *) msg->buf,
1326 msg->size);
1327 connection->long_poll_head = long_poll->next;
1328 if (NULL != long_poll->next)
1329 {
1330 long_poll->next->prev = NULL;
1331 }
1332 connection->long_poll_len -= 1;
1334 "rm long_poll, len = %lu\n",
1335 connection->long_poll_len);
1336 GNUNET_free (long_poll);
1337 long_poll = connection->long_poll_head;
1338 }
1339 }
1340 return GNUNET_NO;
1341}
1342
1343
1352static void
1354 const struct GNUNET_MessageHeader *msg,
1355 void *impl_state)
1356{
1357 struct Connection *connection = impl_state;
1358 uint16_t msize = ntohs (msg->size);
1359 struct Stream *post_stream;
1360 struct HTTP_Message *send_buf;
1361 struct Long_Poll_Request *long_poll;
1362
1364 "mq_send_d: init = %d, msg->size = %u, time: %llu\n",
1365 connection->is_initiator, msize,
1366 (unsigned long long) timestamp () / NGTCP2_SECONDS);
1367 if (NULL == connection->conn)
1368 {
1370 "No quic connection has been established yet\n");
1371 return;
1372 }
1373
1374 GNUNET_assert (mq == connection->d_mq);
1375
1376 if (msize > connection->d_mtu)
1377 {
1379 "msize: %u, mtu: %lu\n",
1380 msize,
1381 connection->d_mtu);
1382 GNUNET_break (0);
1383 if (GNUNET_YES != connection->connection_destroy_called)
1384 {
1386 "connection destroy called, destroying connection\n");
1387 connection_destroy (connection);
1388 }
1389 return;
1390 }
1391 reschedule_peer_timeout (connection);
1392
1393 // If we are client side.
1394 if (GNUNET_YES == connection->is_initiator)
1395 {
1396 post_stream = create_stream (connection, -1);
1397 ngtcp2_conn_open_bidi_stream (connection->conn,
1398 &post_stream->stream_id,
1399 NULL);
1400 submit_post_request (connection, post_stream, (uint8_t *) msg, msize);
1401 connection_write (connection);
1402 }
1403 // If we are server side.
1404 else
1405 {
1406 if (NULL == connection->msg_queue_head &&
1407 NULL != connection->long_poll_head)
1408 {
1409 long_poll = connection->long_poll_head;
1410 GNUNET_SCHEDULER_cancel (long_poll->timer);
1411 stream_send_data (long_poll->stream, (uint8_t *) msg, msize);
1412 connection_write (connection);
1413 connection->long_poll_head = long_poll->next;
1414 if (NULL != long_poll->next)
1415 {
1416 long_poll->next->prev = NULL;
1417 }
1418 connection->long_poll_len -= 1;
1420 "rm long_poll, len = %lu\n",
1421 connection->long_poll_len);
1422 GNUNET_free (long_poll);
1423 }
1424 else if (NULL == connection->long_poll_head ||
1425 NULL != connection->msg_queue_head)
1426 {
1427 connection->msg_queue_len += 1;
1429 "add msg, len = %lu\n",
1430 connection->msg_queue_len);
1431 send_buf = GNUNET_new (struct HTTP_Message);
1432 send_buf->size = msize;
1433 send_buf->buf = GNUNET_memdup (msg, msize);
1434 send_buf->next = NULL;
1435 connection->msg_queue_rear = send_buf;
1436 if (NULL == connection->msg_queue_head)
1437 {
1438 connection->msg_queue_head = send_buf;
1439 }
1440 }
1441
1442 long_poll = connection->long_poll_head;
1443 while (NULL != long_poll &&
1444 NULL != connection->msg_queue_head)
1445 {
1446 GNUNET_SCHEDULER_cancel (long_poll->timer);
1447 if (NULL != long_poll->next)
1448 {
1449 long_poll->next->prev = NULL;
1450 }
1451
1452 send_buf = connection->msg_queue_head;
1453 connection->msg_queue_head = send_buf->next;
1454 send_buf->next = connection->submitted_msg_queue_head;
1455 connection->submitted_msg_queue_head = send_buf;
1456 stream_send_data (long_poll->stream,
1457 (uint8_t *) send_buf->buf,
1458 send_buf->size);
1459 connection->long_poll_head = long_poll->next;
1460 if (NULL != long_poll->next)
1461 {
1462 long_poll->next->prev = NULL;
1463 }
1464 connection->long_poll_len -= 1;
1466 "rm long_poll, len = %lu\n",
1467 connection->long_poll_len);
1468 GNUNET_free (long_poll);
1469 long_poll = connection->long_poll_head;
1470 }
1471 }
1473}
1474
1475
1484static void
1485mq_destroy_d (struct GNUNET_MQ_Handle *mq, void *impl_state)
1486{
1487 struct Connection *connection = impl_state;
1489 "Default MQ destroyed\n");
1490 if (mq == connection->d_mq)
1491 {
1492 connection->d_mq = NULL;
1493 if (GNUNET_YES != connection->connection_destroy_called)
1494 connection_destroy (connection);
1495 }
1496}
1497
1498
1505static void
1506mq_cancel (struct GNUNET_MQ_Handle *mq, void *impl_state)
1507{
1508 /* Cancellation is impossible with QUIC; bail */
1509 GNUNET_assert (0);
1510}
1511
1512
1522static void
1523mq_error (void *cls, enum GNUNET_MQ_Error error)
1524{
1525 struct Connection *connection = cls;
1527 "MQ error in queue to %s: %d\n",
1528 GNUNET_i2s (&connection->target),
1529 (int) error);
1530 connection_destroy (connection);
1531}
1532
1533
1541static void
1543{
1545 "setup_connection_mq: init = %u\n",
1546 connection->is_initiator);
1547 size_t base_mtu;
1548
1549 switch (connection->address->sa_family)
1550 {
1551 case AF_INET:
1552 base_mtu = 1480 /* Ethernet MTU, 1500 - Ethernet header - VLAN tag */
1553 - sizeof(struct GNUNET_TUN_IPv4Header) /* 20 */
1554 - sizeof(struct GNUNET_TUN_UdpHeader) /* 8 */;
1555 break;
1556
1557 case AF_INET6:
1558 base_mtu = 1280 /* Minimum MTU required by IPv6 */
1559 - sizeof(struct GNUNET_TUN_IPv6Header) /* 40 */
1560 - sizeof(struct GNUNET_TUN_UdpHeader) /* 8 */;
1561 break;
1562
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, stream_id, consumed);
1598 ngtcp2_conn_extend_max_offset (connection->conn, consumed);
1599}
1600
1601
1605static int
1606http_stream_close_cb (nghttp3_conn *conn, int64_t stream_id,
1607 uint64_t app_error_code, void *conn_user_data,
1608 void *stream_user_data)
1609{
1610 struct Connection *connection = conn_user_data;
1611
1612 remove_stream (connection, stream_id);
1614 "HTTP stream %lu closed\n",
1615 (unsigned long) stream_id);
1616 if (GNUNET_NO == connection->is_initiator &&
1617 ngtcp2_is_bidi_stream (stream_id))
1618 {
1619 ngtcp2_conn_extend_max_streams_bidi (connection->conn, 1);
1620 }
1621 else if (GNUNET_YES == connection->is_initiator &&
1622 ! ngtcp2_is_bidi_stream (stream_id))
1623 {
1624 ngtcp2_conn_extend_max_streams_uni (connection->conn, 1);
1625 }
1626
1627 return 0;
1628}
1629
1630
1634static int
1635http_recv_data_cb (nghttp3_conn *conn, int64_t stream_id, const uint8_t *data,
1636 size_t datalen, void *user_data, void *stream_user_data)
1637{
1639 "http_recv_data_cb\n");
1640 struct Connection *connection = user_data;
1641 struct GNUNET_PeerIdentity *pid;
1642 struct GNUNET_MessageHeader *hdr;
1643 int rv;
1644
1645 http_consume (connection, stream_id, datalen);
1646
1647 if (GNUNET_NO == connection->is_initiator &&
1648 GNUNET_NO == connection->id_rcvd)
1649 {
1650 if (datalen < sizeof (struct GNUNET_PeerIdentity))
1651 {
1653 "message recv len of %zd less than length of peer identity\n",
1654 datalen);
1655 return NGHTTP3_ERR_CALLBACK_FAILURE;
1656 }
1657 pid = (struct GNUNET_PeerIdentity *) data;
1658 connection->target = *pid;
1659 connection->id_rcvd = GNUNET_YES;
1660 setup_connection_mq (connection);
1661
1662 return GNUNET_NO;
1663 }
1664
1665 hdr = (struct GNUNET_MessageHeader *) data;
1667 &connection->target,
1668 hdr,
1670 NULL,
1671 NULL);
1672 if (GNUNET_SYSERR == rv)
1673 {
1675 "GNUNET_TRANSPORT_communicator_receive:%d, hdr->len = %u, datalen = %lu, init = %d\n",
1676 rv, ntohs (hdr->size), datalen, connection->is_initiator);
1677 return NGHTTP3_ERR_CALLBACK_FAILURE;
1678 }
1680 "GNUNET_TRANSPORT_communicator_receive:%d, hdr->len = %u, datalen = %lu, init = %d\n",
1681 rv, ntohs (hdr->size), datalen, connection->is_initiator);
1682 return 0;
1683}
1684
1685
1689static int
1690http_deferred_consume_cb (nghttp3_conn *conn, int64_t stream_id,
1691 size_t nconsumed, void *user_data,
1692 void *stream_user_data)
1693{
1694 struct Connection *connection = user_data;
1695 http_consume (connection, stream_id, nconsumed);
1696 return 0;
1697}
1698
1699
1703static int
1704http_begin_headers_cb (nghttp3_conn *conn, int64_t stream_id,
1705 void *user_data, void *stream_user_data)
1706{
1707 struct Connection *connection = user_data;
1708 struct Stream *stream;
1709
1710 stream = find_stream (connection, stream_id);
1711 if (NULL == stream)
1712 {
1713 return NGHTTP3_ERR_CALLBACK_FAILURE;
1714 }
1715 nghttp3_conn_set_stream_user_data (connection->h3_conn, stream_id, stream);
1716
1717 return 0;
1718}
1719
1720
1724static int
1725http_recv_header_cb (nghttp3_conn *conn, int64_t stream_id, int32_t token,
1726 nghttp3_rcbuf *name, nghttp3_rcbuf *value, uint8_t flags,
1727 void *user_data, void *stream_user_data)
1728{
1729 nghttp3_vec namebuf = nghttp3_rcbuf_get_buf (name);
1730 nghttp3_vec valbuf = nghttp3_rcbuf_get_buf (value);
1731 struct Connection *connection = user_data;
1732
1733 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "http header: [%.*s: %.*s]\n",
1734 (int) namebuf.len, namebuf.base,
1735 (int) valbuf.len, valbuf.base);
1736
1737 if (GNUNET_NO == connection->is_initiator)
1738 {
1739 struct Stream *stream = stream_user_data;
1740 switch (token)
1741 {
1742 case NGHTTP3_QPACK_TOKEN__PATH:
1743 stream->urilen = valbuf.len;
1744 stream->uri = (uint8_t *) malloc (valbuf.len);
1745 memcpy (stream->uri, valbuf.base, valbuf.len);
1746 break;
1747 case NGHTTP3_QPACK_TOKEN__METHOD:
1748 stream->methodlen = valbuf.len;
1749 stream->method = (uint8_t *) malloc (valbuf.len);
1750 memcpy (stream->method, valbuf.base, valbuf.len);
1751 break;
1752 case NGHTTP3_QPACK_TOKEN__AUTHORITY:
1753 stream->authoritylen = valbuf.len;
1754 stream->authority = (uint8_t *) malloc (valbuf.len);
1755 memcpy (stream->authority, valbuf.base, valbuf.len);
1756 break;
1757 }
1758 }
1759 return 0;
1760}
1761
1762
1766static int
1767http_stop_sending_cb (nghttp3_conn *conn, int64_t stream_id,
1768 uint64_t app_error_code, void *user_data,
1769 void *stream_user_data)
1770{
1771 struct Connection *connection = user_data;
1772 int rv;
1773
1774 rv = ngtcp2_conn_shutdown_stream_read (connection->conn,
1775 0,
1776 stream_id,
1777 app_error_code);
1778 if (0 != rv)
1779 {
1781 "ngtcp2_conn_shutdown_stream_read: %s\n",
1782 ngtcp2_strerror (rv));
1783 return NGHTTP3_ERR_CALLBACK_FAILURE;
1784 }
1785 return 0;
1786}
1787
1788
1792static int
1793http_end_stream_cb (nghttp3_conn *conn, int64_t stream_id, void *user_data,
1794 void *stream_user_data)
1795{
1796 struct Connection *connection = user_data;
1797 struct Stream *stream = stream_user_data;
1798 struct Long_Poll_Request *long_poll;
1799 int rv;
1800
1801 if (GNUNET_NO == connection->is_initiator)
1802 {
1803 // Send response
1804 rv = stream_start_response (connection, stream);
1805 if (0 != rv)
1806 {
1807 return NGHTTP3_ERR_CALLBACK_FAILURE;
1808 }
1809 }
1810 else
1811 {
1816 long_poll = connection->long_poll_head;
1817 while (NULL != long_poll)
1818 {
1819 if (stream_id == long_poll->stream->stream_id)
1820 {
1822 "client side recv GET response\n");
1823 stream = create_stream (connection, -1);
1824 rv = ngtcp2_conn_open_bidi_stream (connection->conn,
1826 if (0 != rv)
1827 {
1829 "ngtcp2_conn_open_bidi_stream: %s\n",
1830 ngtcp2_strerror (rv));
1831 }
1832 submit_get_request (connection, stream);
1833 long_poll->stream = stream;
1834 break;
1835 }
1836 long_poll = long_poll->next;
1837 }
1838 }
1839 return 0;
1840}
1841
1842
1846static int
1847http_reset_stream_cb (nghttp3_conn *conn, int64_t stream_id,
1848 uint64_t app_error_code, void *user_data,
1849 void *stream_user_data)
1850{
1851 struct Connection *connection = user_data;
1852 int rv;
1853
1854 rv = ngtcp2_conn_shutdown_stream_write (connection->conn,
1855 0,
1856 stream_id,
1857 app_error_code);
1858 if (0 != rv)
1859 {
1861 "ngtcp2_conn_shutdown_stream_write: %s\n",
1862 ngtcp2_strerror (rv));
1863 return NGHTTP3_ERR_CALLBACK_FAILURE;
1864 }
1865 return 0;
1866}
1867
1868
1876static int
1877setup_httpconn (struct Connection *connection)
1878{
1879 nghttp3_settings settings;
1880 const nghttp3_mem *mem = nghttp3_mem_default ();
1881 int64_t ctrl_stream_id;
1882 int64_t enc_stream_id;
1883 int64_t dec_stream_id;
1884 nghttp3_callbacks callbacks = {
1885 .stream_close = http_stream_close_cb,
1886 .recv_data = http_recv_data_cb,
1887 .deferred_consume = http_deferred_consume_cb,
1888 .begin_headers = http_begin_headers_cb,
1889 .recv_header = http_recv_header_cb,
1890 .stop_sending = http_stop_sending_cb,
1891 .end_stream = http_end_stream_cb,
1892 .reset_stream = http_reset_stream_cb,
1893 };
1894 int rv;
1895
1896 if (NULL != connection->h3_conn)
1897 {
1898 return GNUNET_NO;
1899 }
1900
1901 if (ngtcp2_conn_get_streams_uni_left (connection->conn) < 3)
1902 {
1904 "uni stream left less than 3\n");
1905 return GNUNET_SYSERR;
1906 }
1907
1908 if (GNUNET_YES == connection->is_initiator)
1909 {
1910 callbacks.begin_headers = NULL;
1911 // callbacks.end_stream = NULL;
1912 }
1913
1914 nghttp3_settings_default (&settings);
1915 settings.qpack_blocked_streams = 100;
1916 settings.qpack_encoder_max_dtable_capacity = 4096;
1917
1918 if (GNUNET_NO == connection->is_initiator)
1919 {
1920 const ngtcp2_transport_params *params =
1921 ngtcp2_conn_get_local_transport_params (connection->conn);
1922
1923 rv = nghttp3_conn_server_new (&connection->h3_conn,
1924 &callbacks,
1925 &settings,
1926 mem,
1927 connection);
1928 nghttp3_conn_set_max_client_streams_bidi (connection->h3_conn,
1929 params->initial_max_streams_bidi);
1930 if (0 != rv)
1931 {
1933 "nghttp3_conn_server_new: %s\n",
1934 nghttp3_strerror (rv));
1935 return GNUNET_SYSERR;
1936 }
1937 }
1938 else
1939 {
1940 rv = nghttp3_conn_client_new (&connection->h3_conn,
1941 &callbacks,
1942 &settings,
1943 mem,
1944 connection);
1945 if (0 != rv)
1946 {
1948 "nghttp3_conn_client_new: %s\n",
1949 nghttp3_strerror (rv));
1950 return GNUNET_SYSERR;
1951 }
1952 }
1953
1954 rv = ngtcp2_conn_open_uni_stream (connection->conn, &ctrl_stream_id, NULL);
1955 if (0 != rv)
1956 {
1958 "ngtcp2_conn_open_uni_stream: %s\n",
1959 ngtcp2_strerror (rv));
1960 return GNUNET_SYSERR;
1961 }
1962
1963 rv = nghttp3_conn_bind_control_stream (connection->h3_conn, ctrl_stream_id);
1964 if (0 != rv)
1965 {
1967 "nghttp3_conn_bind_control_stream: %s\n",
1968 nghttp3_strerror (rv));
1969 return GNUNET_SYSERR;
1970 }
1971
1972 rv = ngtcp2_conn_open_uni_stream (connection->conn, &enc_stream_id, NULL);
1973 if (0 != rv)
1974 {
1976 "ngtcp2_conn_open_uni_stream: %s\n",
1977 ngtcp2_strerror (rv));
1978 return GNUNET_SYSERR;
1979 }
1980
1981 rv = ngtcp2_conn_open_uni_stream (connection->conn, &dec_stream_id, NULL);
1982 if (0 != rv)
1983 {
1985 "ngtcp2_conn_open_uni_stream: %s\n",
1986 ngtcp2_strerror (rv));
1987 return GNUNET_SYSERR;
1988 }
1989
1990 rv = nghttp3_conn_bind_qpack_streams (connection->h3_conn,
1991 enc_stream_id, dec_stream_id);
1992 if (0 != rv)
1993 {
1995 "nghttp3_conn_bind_qpack_streams: %s\n",
1996 nghttp3_strerror (rv));
1997 return GNUNET_SYSERR;
1998 }
1999
2001 "Bind control stream: %" PRIi64 ", enc stream: %" PRIi64
2002 ", dec stream: %" PRIi64 "\n",
2003 ctrl_stream_id, enc_stream_id, dec_stream_id);
2004 return GNUNET_NO;
2005}
2006
2007
2011static void
2012rand_cb (uint8_t *dest,
2013 size_t destlen,
2014 const ngtcp2_rand_ctx *rand_ctx)
2015{
2016 (void) rand_ctx;
2018 dest,
2019 destlen);
2020}
2021
2022
2026static int
2027get_new_connection_id_cb (ngtcp2_conn *conn, ngtcp2_cid *cid,
2028 uint8_t *token, size_t cidlen,
2029 void *user_data)
2030{
2031 (void) conn;
2032 (void) user_data;
2033
2035 cid->data,
2036 cidlen);
2037 cid->datalen = cidlen;
2039 token,
2040 NGTCP2_STATELESS_RESET_TOKENLEN);
2041 return GNUNET_NO;
2042}
2043
2044
2048static int
2049recv_stream_data_cb (ngtcp2_conn *conn, uint32_t flags, int64_t stream_id,
2050 uint64_t offset, const uint8_t *data, size_t datalen,
2051 void *user_data,
2052 void *stream_user_data)
2053{
2054 struct Connection *connection = user_data;
2055 nghttp3_ssize nconsumed;
2056
2057 if (NULL == connection->h3_conn)
2058 {
2059 return 0;
2060 }
2061 nconsumed = nghttp3_conn_read_stream (connection->h3_conn, stream_id,
2062 data, datalen,
2063 flags & NGTCP2_STREAM_DATA_FLAG_FIN);
2064 if (nconsumed < 0)
2065 {
2067 "nghttp3_conn_read_stream: %s, init = %d\n",
2068 nghttp3_strerror (nconsumed), connection->is_initiator);
2069 ngtcp2_ccerr_set_application_error (
2070 &connection->last_error,
2071 nghttp3_err_infer_quic_app_error_code (nconsumed),
2072 NULL, 0);
2073 return NGTCP2_ERR_CALLBACK_FAILURE;
2074 }
2075 http_consume (connection, stream_id, nconsumed);
2076 return 0;
2077}
2078
2079
2083static int
2084stream_open_cb (ngtcp2_conn *conn, int64_t stream_id, void *user_data)
2085{
2086 struct Connection *connection = user_data;
2087 if (! ngtcp2_is_bidi_stream (stream_id))
2088 {
2089 return 0;
2090 }
2091 create_stream (connection, stream_id);
2092 return 0;
2093}
2094
2095
2101static int
2102stream_close_cb (ngtcp2_conn *conn, uint32_t flags, int64_t stream_id,
2103 uint64_t app_error_code, void *user_data,
2104 void *stream_user_data)
2105{
2107 "stream_close id = %" PRIi64 "\n",
2108 stream_id);
2109 struct Connection *connection = user_data;
2110 int rv;
2111
2112 if (! (flags & NGTCP2_STREAM_CLOSE_FLAG_APP_ERROR_CODE_SET))
2113 {
2114 app_error_code = NGHTTP3_H3_NO_ERROR;
2115 }
2116
2117 if (connection->h3_conn)
2118 {
2119 if (0 == app_error_code)
2120 {
2121 app_error_code = NGHTTP3_H3_NO_ERROR;
2122 }
2123
2124 rv = nghttp3_conn_close_stream (connection->h3_conn,
2125 stream_id,
2126 app_error_code);
2127 switch (rv)
2128 {
2129 case 0:
2130 break;
2131 case NGHTTP3_ERR_STREAM_NOT_FOUND:
2132 if (GNUNET_NO == connection->is_initiator &&
2133 ngtcp2_is_bidi_stream (stream_id))
2134 {
2135 ngtcp2_conn_extend_max_streams_bidi (connection->conn, 1);
2136 }
2137 else if (GNUNET_YES == connection->is_initiator &&
2138 ! ngtcp2_is_bidi_stream (stream_id))
2139 {
2140 ngtcp2_conn_extend_max_streams_uni (connection->conn, 1);
2141 }
2142 break;
2143 default:
2145 "nghttp3_conn_close_stream: %s\n",
2146 nghttp3_strerror (rv));
2147 ngtcp2_ccerr_set_application_error (
2148 &connection->last_error,
2149 nghttp3_err_infer_quic_app_error_code (rv),
2150 NULL, 0);
2151 return NGTCP2_ERR_CALLBACK_FAILURE;
2152 }
2153 }
2154 return 0;
2155}
2156
2157
2161static int
2162acked_stream_data_offset_cb (ngtcp2_conn *conn, int64_t stream_id,
2163 uint64_t offset, uint64_t datalen, void *user_data,
2164 void *stream_user_data)
2165{
2166 struct Connection *connection = user_data;
2167 int rv;
2168
2169 if (NULL == connection->h3_conn)
2170 {
2171 return 0;
2172 }
2173
2174 rv = nghttp3_conn_add_ack_offset (connection->h3_conn, stream_id, datalen);
2175 if (0 != rv)
2176 {
2178 "nghttp3_conn_add_ack_offset: %s\n",
2179 nghttp3_strerror (rv));
2180 return NGTCP2_ERR_CALLBACK_FAILURE;
2181 }
2182 return 0;
2183}
2184
2185
2189static int
2190extend_max_stream_data_cb (ngtcp2_conn *conn, int64_t stream_id,
2191 uint64_t max_data, void *user_data,
2192 void *stream_user_data)
2193{
2194 struct Connection *connection = user_data;
2195 int rv;
2196
2197 rv = nghttp3_conn_unblock_stream (connection->h3_conn, stream_id);
2198 if (0 != rv)
2199 {
2201 "nghttp3_conn_unblock_stream: %s\n",
2202 nghttp3_strerror (rv));
2203 return NGTCP2_ERR_CALLBACK_FAILURE;
2204 }
2205 return 0;
2206}
2207
2208
2212static int
2213stream_reset_cb (ngtcp2_conn *conn, int64_t stream_id, uint64_t final_size,
2214 uint64_t app_error_code, void *user_data,
2215 void *stream_user_data)
2216{
2217 struct Connection *connection = user_data;
2218 int rv;
2219
2220 if (connection->h3_conn)
2221 {
2222 rv = nghttp3_conn_shutdown_stream_read (connection->h3_conn, stream_id);
2223 if (0 != rv)
2224 {
2226 "nghttp3_conn_shutdown_stream_read: %s\n",
2227 nghttp3_strerror (rv));
2228 return NGTCP2_ERR_CALLBACK_FAILURE;
2229 }
2230 }
2231 return 0;
2232}
2233
2234
2238static int
2239extend_max_remote_streams_bidi_cb (ngtcp2_conn *conn, uint64_t max_streams,
2240 void *user_data)
2241{
2242 struct Connection *connection = user_data;
2243 if (NULL == connection->h3_conn)
2244 {
2245 return 0;
2246 }
2247 nghttp3_conn_set_max_client_streams_bidi (connection->h3_conn, max_streams);
2248 return 0;
2249}
2250
2251
2255static int
2256stream_stop_sending_cb (ngtcp2_conn *conn, int64_t stream_id,
2257 uint64_t app_error_code, void *user_data,
2258 void *stream_user_data)
2259{
2260 struct Connection *connection = user_data;
2261 int rv;
2262
2263 if (connection->h3_conn)
2264 {
2265 rv = nghttp3_conn_shutdown_stream_read (connection->h3_conn, stream_id);
2266 if (0 != rv)
2267 {
2269 "nghttp3_conn_shutdown_stream_read: %s\n",
2270 nghttp3_strerror (rv));
2271 return NGTCP2_ERR_CALLBACK_FAILURE;
2272 }
2273 }
2274 return 0;
2275}
2276
2277
2281static int
2282recv_tx_key_cb (ngtcp2_conn *conn, ngtcp2_encryption_level level,
2283 void *user_data)
2284{
2285 if (NGTCP2_ENCRYPTION_LEVEL_1RTT != level)
2286 {
2287 return 0;
2288 }
2289
2290 struct Connection *connection = user_data;
2291 int rv;
2292
2293 rv = setup_httpconn (connection);
2294 if (0 != rv)
2295 {
2296 return NGTCP2_ERR_CALLBACK_FAILURE;
2297 }
2298 return 0;
2299}
2300
2301
2305static int
2306recv_rx_key_cb (ngtcp2_conn *conn, ngtcp2_encryption_level level,
2307 void *user_data)
2308{
2309 if (NGTCP2_ENCRYPTION_LEVEL_1RTT != level)
2310 {
2311 return 0;
2312 }
2313
2314 struct Connection *connection = user_data;
2315 struct Stream *stream;
2316 struct Long_Poll_Request *long_poll;
2317 int i;
2318 int rv;
2319
2320 rv = setup_httpconn (connection);
2321 if (0 != rv)
2322 {
2323 return NGTCP2_ERR_CALLBACK_FAILURE;
2324 }
2325
2326 if (GNUNET_YES == connection->is_initiator &&
2327 GNUNET_NO == connection->id_sent)
2328 {
2329 stream = create_stream (connection, -1);
2330 rv = ngtcp2_conn_open_bidi_stream (conn, &stream->stream_id, NULL);
2331
2332 submit_post_request (connection, stream,
2333 (uint8_t *) &my_identity,
2334 sizeof (my_identity));
2335
2336 connection->id_sent = GNUNET_YES;
2337 setup_connection_mq (connection);
2338
2339 for (i = 0; i < NUM_LONG_POLL; i++)
2340 {
2341 stream = create_stream (connection, -1);
2342 rv = ngtcp2_conn_open_bidi_stream (conn, &stream->stream_id, NULL);
2343 submit_get_request (connection, stream);
2344 long_poll = GNUNET_new (struct Long_Poll_Request);
2345 long_poll->stream = stream;
2346 long_poll->next = NULL;
2347 long_poll->prev = connection->long_poll_rear;
2348 long_poll->timer = NULL;
2349 if (NULL != connection->long_poll_rear)
2350 {
2351 connection->long_poll_rear->next = long_poll;
2352 }
2353 connection->long_poll_rear = long_poll;
2354 if (NULL == connection->long_poll_head)
2355 {
2356 connection->long_poll_head = long_poll;
2357 }
2358 }
2359 }
2360 return 0;
2361}
2362
2363
2376static int
2377client_quic_init (struct Connection *connection,
2378 struct sockaddr *local_addr,
2379 socklen_t local_addrlen,
2380 struct sockaddr *remote_addr,
2381 socklen_t remote_addrlen)
2382{
2383 int rv;
2384 ngtcp2_cid dcid;
2385 ngtcp2_cid scid;
2386 ngtcp2_settings settings;
2387 ngtcp2_transport_params params;
2388 ngtcp2_path path = {
2389 {local_addr, local_addrlen},
2390 {remote_addr, remote_addrlen},
2391 NULL,
2392 };
2393 ngtcp2_callbacks callbacks = {
2394 .client_initial = ngtcp2_crypto_client_initial_cb,
2395 .recv_crypto_data = ngtcp2_crypto_recv_crypto_data_cb,
2396 .encrypt = ngtcp2_crypto_encrypt_cb,
2397 .decrypt = ngtcp2_crypto_decrypt_cb,
2398 .hp_mask = ngtcp2_crypto_hp_mask_cb,
2399 .recv_retry = ngtcp2_crypto_recv_retry_cb,
2400 .update_key = ngtcp2_crypto_update_key_cb,
2401 .delete_crypto_aead_ctx = ngtcp2_crypto_delete_crypto_aead_ctx_cb,
2402 .delete_crypto_cipher_ctx = ngtcp2_crypto_delete_crypto_cipher_ctx_cb,
2403 .get_path_challenge_data = ngtcp2_crypto_get_path_challenge_data_cb,
2404 .version_negotiation = ngtcp2_crypto_version_negotiation_cb,
2405 .rand = rand_cb,
2406 .get_new_connection_id = get_new_connection_id_cb,
2407 .recv_stream_data = recv_stream_data_cb,
2408 .stream_close = stream_close_cb,
2409 .acked_stream_data_offset = acked_stream_data_offset_cb,
2410 .extend_max_stream_data = extend_max_stream_data_cb,
2411 .stream_reset = stream_reset_cb,
2412 .stream_stop_sending = stream_stop_sending_cb,
2413 .recv_rx_key = recv_rx_key_cb,
2414 };
2415
2416
2417 scid.datalen = NGTCP2_MAX_CIDLEN;
2419 scid.data,
2420 scid.datalen);
2421 dcid.datalen = NGTCP2_MAX_CIDLEN;
2423 dcid.data,
2424 dcid.datalen);
2425 ngtcp2_settings_default (&settings);
2426 settings.initial_ts = timestamp ();
2427
2428 ngtcp2_transport_params_default (&params);
2429 params.initial_max_streams_uni = 100;
2430 params.initial_max_stream_data_bidi_local = 6291456;
2431 params.initial_max_data = 15728640;
2432 params.initial_max_stream_data_bidi_remote = 0;
2433 params.initial_max_stream_data_uni = 6291456;
2434 params.initial_max_streams_bidi = 0;
2435 params.max_idle_timeout = 30 * NGTCP2_SECONDS;
2436 params.active_connection_id_limit = 7;
2437 params.grease_quic_bit = 1;
2438 rv = ngtcp2_conn_client_new (&connection->conn,
2439 &dcid,
2440 &scid,
2441 &path,
2442 NGTCP2_PROTO_VER_V1,
2443 &callbacks,
2444 &settings,
2445 &params,
2446 NULL,
2447 connection);
2448 if (GNUNET_NO != rv)
2449 {
2451 "ngtcp2_conn_client_new: %s\n",
2452 ngtcp2_strerror (rv));
2453 return GNUNET_SYSERR;
2454 }
2455 ngtcp2_conn_set_tls_native_handle (connection->conn, connection->session);
2456 connection->conn_ref.user_data = connection;
2457 connection->conn_ref.get_conn = get_conn;
2458 return GNUNET_NO;
2459}
2460
2461
2467static void
2468close_waitcb (void *cls)
2469{
2470 struct Connection *connection = cls;
2471 connection->timer = NULL;
2472
2473 if (ngtcp2_conn_in_closing_period (connection->conn))
2474 {
2476 "Closing period over\n");
2477 connection_destroy (connection);
2478 return;
2479 }
2480 if (ngtcp2_conn_in_draining_period (connection->conn))
2481 {
2483 "Draining period over\n");
2484 connection_destroy (connection);
2485 return;
2486 }
2487}
2488
2489
2495static void
2497{
2498 ngtcp2_duration pto;
2499 struct GNUNET_TIME_Relative delay;
2500
2501 if (NULL != connection->timer)
2502 {
2503 GNUNET_SCHEDULER_cancel (connection->timer);
2504 connection->timer = NULL;
2505 }
2506 pto = ngtcp2_conn_get_pto (connection->conn);
2508 pto / 1000ULL * 3);
2509 connection->timer = GNUNET_SCHEDULER_add_delayed (delay,
2511 connection);
2513 "Start draining period\n");
2514}
2515
2516
2527static int
2529{
2530 ngtcp2_path_storage ps;
2531 ngtcp2_pkt_info pi;
2532 ngtcp2_ssize nwrite;
2533 ngtcp2_duration pto;
2534 struct GNUNET_TIME_Relative delay;
2535
2536 if (NULL == connection->conn ||
2537 ngtcp2_conn_in_closing_period (connection->conn) ||
2538 ngtcp2_conn_in_draining_period (connection->conn))
2539 {
2540 return GNUNET_NO;
2541 }
2542
2544 "Start closing period\n");
2545
2546 if (GNUNET_NO == connection->is_initiator)
2547 {
2548 if (NULL != connection->timer)
2549 {
2550 GNUNET_SCHEDULER_cancel (connection->timer);
2551 connection->timer = NULL;
2552 }
2553 pto = ngtcp2_conn_get_pto (connection->conn);
2555 pto / 1000ULL * 3);
2556 connection->timer = GNUNET_SCHEDULER_add_delayed (delay,
2558 connection);
2559 }
2560
2561 connection->conn_closebuf =
2562 GNUNET_new_array (NGTCP2_MAX_UDP_PAYLOAD_SIZE, uint8_t);
2563
2564 ngtcp2_path_storage_zero (&ps);
2565 nwrite = ngtcp2_conn_write_connection_close (connection->conn,
2566 &ps.path,
2567 &pi,
2568 connection->conn_closebuf,
2569 NGTCP2_MAX_UDP_PAYLOAD_SIZE,
2570 &connection->last_error,
2571 timestamp ());
2572 if (nwrite < 0)
2573 {
2575 "ngtcp2_conn_write_connection_close: %s\n",
2576 ngtcp2_strerror (nwrite));
2577 return GNUNET_SYSERR;
2578 }
2579 if (0 == nwrite)
2580 {
2581 return GNUNET_NO;
2582 }
2583 connection->conn_closebuflen = nwrite;
2584 if (GNUNET_YES == connection->is_initiator)
2585 {
2586 return send_packet (connection,
2587 connection->conn_closebuf,
2588 connection->conn_closebuflen);
2589 }
2590 return GNUNET_NO;
2591}
2592
2593
2600static int
2601send_conn_close (struct Connection *connection)
2602{
2603 int rv;
2604
2606 "Closing period, send CONNECTION_CLOSE\n");
2607 rv = send_packet (connection,
2608 connection->conn_closebuf,
2609 connection->conn_closebuflen);
2610 return rv;
2611}
2612
2613
2621static int
2622handle_error (struct Connection *connection)
2623{
2624 int rv;
2625
2626 /* if we are the client side */
2627 if (GNUNET_YES == connection->is_initiator)
2628 {
2629 /* this will send CONNECTION_CLOSE immedietly and don't wait */
2630 start_closing_period (connection);
2631 connection_destroy (connection);
2632 return GNUNET_SYSERR;
2633 }
2634
2635 if (NGTCP2_CCERR_TYPE_IDLE_CLOSE == connection->last_error.type)
2636 {
2637 return GNUNET_SYSERR;
2638 }
2639
2640 if (GNUNET_NO != start_closing_period (connection))
2641 {
2642 return GNUNET_SYSERR;
2643 }
2644
2645 if (ngtcp2_conn_in_draining_period (connection->conn))
2646 {
2648 }
2649
2650 rv = send_conn_close (connection);
2651 if (NETWORK_ERR_OK != rv)
2652 {
2653 return rv;
2654 }
2655
2657}
2658
2659
2666static int
2667handle_expiry (struct Connection *connection)
2668{
2669 int rv;
2670
2671 rv = ngtcp2_conn_handle_expiry (connection->conn, timestamp ());
2672 if (0 != rv)
2673 {
2675 "ngtcp2_conn_handle_expiry: %s\n",
2676 ngtcp2_strerror (rv));
2677 ngtcp2_ccerr_set_liberr (&connection->last_error, rv, NULL, 0);
2678 return handle_error (connection);
2679 }
2680 return GNUNET_NO;
2681}
2682
2683
2689static void
2690timeoutcb (void *cls)
2691{
2693 "timeoutcb func called!\n");
2694 struct Connection *connection = cls;
2695 connection->timer = NULL;
2696 int rv;
2697
2698 rv = handle_expiry (connection);
2699 if (GNUNET_NO != rv)
2700 {
2701 if (GNUNET_YES == connection->is_initiator)
2702 {
2703 return;
2704 }
2705 switch (rv)
2706 {
2708 return;
2709 default:
2710 connection_destroy (connection);
2711 return;
2712 }
2713 }
2714
2715 rv = connection_write (connection);
2716 if (GNUNET_YES == connection->is_initiator)
2717 {
2718 return;
2719 }
2720 if (GNUNET_NO != rv)
2721 {
2722 switch (rv)
2723 {
2725 return;
2726 default:
2727 connection_destroy (connection);
2728 return;
2729 }
2730
2731 }
2732}
2733
2734
2740static void
2742{
2744 "update_timer!\n");
2745 ngtcp2_tstamp expiry;
2746 ngtcp2_tstamp now;
2747 struct GNUNET_TIME_Relative delay;
2748
2749 expiry = ngtcp2_conn_get_expiry (connection->conn);
2750 now = timestamp ();
2751
2752 if (NULL != connection->timer)
2753 {
2754 GNUNET_SCHEDULER_cancel (connection->timer);
2755 connection->timer = NULL;
2756 }
2757 if (now >= expiry)
2758 {
2760 "Timer has expired\n");
2761 connection->timer = GNUNET_SCHEDULER_add_now (timeoutcb, connection);
2762 return;
2763 }
2764
2766 "Timer set: %lf\n",
2767 (double) (expiry - now) / NGTCP2_SECONDS);
2768 /* ngtcp2_tstamp is nanosecond */
2770 (expiry - now) / 1000ULL + 1);
2771 connection->timer = GNUNET_SCHEDULER_add_delayed (delay, timeoutcb,
2772 connection);
2773}
2774
2775
2783static int
2785{
2786 uint8_t buf[1280];
2787 ngtcp2_tstamp ts = timestamp ();
2788 ngtcp2_path_storage ps;
2789 int64_t stream_id;
2790 uint32_t flags;
2791 ngtcp2_ssize nwrite;
2792 ngtcp2_ssize wdatalen;
2793 nghttp3_vec vec[16];
2794 nghttp3_ssize sveccnt;
2795 ngtcp2_pkt_info pi;
2796 int fin;
2797 int rv;
2798
2799 ngtcp2_path_storage_zero (&ps);
2800
2801 for (;;)
2802 {
2803 stream_id = -1;
2804 fin = 0;
2805 sveccnt = 0;
2806
2807 if (connection->h3_conn &&
2808 ngtcp2_conn_get_max_data_left (connection->conn))
2809 {
2810 sveccnt = nghttp3_conn_writev_stream (connection->h3_conn,
2811 &stream_id,
2812 &fin,
2813 vec,
2814 16);
2815 if (sveccnt < 0)
2816 {
2818 "nghttp3_conn_writev_stream: %s\n",
2819 nghttp3_strerror (sveccnt));
2820
2821 ngtcp2_ccerr_set_application_error (
2822 &connection->last_error,
2823 nghttp3_err_infer_quic_app_error_code (sveccnt),
2824 NULL,
2825 0);
2826 return handle_error (connection);
2827 }
2828 }
2829
2830 flags = NGTCP2_WRITE_STREAM_FLAG_MORE;
2831 if (fin)
2832 flags |= NGTCP2_WRITE_STREAM_FLAG_FIN;
2833
2834 nwrite = ngtcp2_conn_writev_stream (connection->conn,
2835 &ps.path,
2836 &pi,
2837 buf,
2838 sizeof(buf),
2839 &wdatalen,
2840 flags,
2841 stream_id,
2842 (ngtcp2_vec *) vec,
2843 (size_t) sveccnt,
2844 ts);
2845 if (nwrite < 0)
2846 {
2847 switch (nwrite)
2848 {
2849 case NGTCP2_ERR_STREAM_DATA_BLOCKED:
2850 nghttp3_conn_block_stream (connection->h3_conn, stream_id);
2851 continue;
2852 case NGTCP2_ERR_STREAM_SHUT_WR:
2853 nghttp3_conn_shutdown_stream_write (connection->h3_conn, stream_id);
2854 continue;
2855 case NGTCP2_ERR_WRITE_MORE:
2856 rv = nghttp3_conn_add_write_offset (connection->h3_conn, stream_id,
2857 wdatalen);
2858 if (0 != rv)
2859 {
2861 "nghttp3_conn_add_write_offset: %s\n",
2862 nghttp3_strerror (rv));
2863 ngtcp2_ccerr_set_application_error (
2864 &connection->last_error,
2865 nghttp3_err_infer_quic_app_error_code (rv),
2866 NULL, 0);
2867 return handle_error (connection);
2868 }
2869 continue;
2870 }
2872 "ngtcp2_conn_writev_stream: %s\n",
2873 ngtcp2_strerror (nwrite));
2874 ngtcp2_ccerr_set_liberr (&connection->last_error,
2875 nwrite,
2876 NULL,
2877 0);
2878 return handle_error (connection);
2879 }
2880 if (0 == nwrite)
2881 {
2882 ngtcp2_conn_update_pkt_tx_time (connection->conn, ts);
2883 return 0;
2884 }
2885 if (wdatalen > 0)
2886 {
2887 rv = nghttp3_conn_add_write_offset (connection->h3_conn, stream_id,
2888 wdatalen);
2889 if (0 != rv)
2890 {
2892 "nghttp3_conn_add_write_offset: %s\n",
2893 nghttp3_strerror (rv));
2894 ngtcp2_ccerr_set_application_error (
2895 &connection->last_error,
2896 nghttp3_err_infer_quic_app_error_code (rv),
2897 NULL, 0);
2898 return handle_error (connection);
2899 }
2900 }
2901 if (GNUNET_NO != send_packet (connection, buf, nwrite))
2902 break;
2903 }
2904
2905 return GNUNET_NO;
2906}
2907
2908
2916static int
2917connection_write (struct Connection *connection)
2918{
2919 int rv;
2920
2921 if (GNUNET_NO == connection->is_initiator &&
2922 (ngtcp2_conn_in_closing_period (connection->conn) ||
2923 ngtcp2_conn_in_draining_period (connection->conn)))
2924 {
2925 return GNUNET_NO;
2926 }
2927
2928 rv = connection_write_streams (connection);
2929 if (GNUNET_NO != rv)
2930 {
2931 return rv;
2932 }
2933 connection_update_timer (connection);
2934
2935 return GNUNET_NO;
2936}
2937
2938
2957static int
2958mq_init (void *cls,
2959 const struct GNUNET_PeerIdentity *peer_id,
2960 const char *address)
2961{
2962 struct Connection *connection;
2963 struct sockaddr *local_addr;
2964 socklen_t local_addrlen;
2965 struct sockaddr *remote_addr;
2966 socklen_t remote_addrlen;
2967 const char *path;
2968 char *bindto;
2969 struct GNUNET_HashCode remote_addr_key;
2970 int rv;
2971
2972 if (GNUNET_OK !=
2975 "BINDTO",
2976 &bindto))
2977 {
2980 "BINDTO");
2981 return GNUNET_SYSERR;
2982 }
2983 local_addr = udp_address_to_sockaddr (bindto, &local_addrlen);
2984 if (0 != strncmp (address,
2986 strlen (COMMUNICATOR_ADDRESS_PREFIX "-")))
2987 {
2988 GNUNET_break_op (0);
2989 return GNUNET_SYSERR;
2990 }
2991 path = &address[strlen (COMMUNICATOR_ADDRESS_PREFIX "-")];
2992 remote_addr = udp_address_to_sockaddr (path, &remote_addrlen);
2993
2994 GNUNET_CRYPTO_hash (address, strlen (address), &remote_addr_key);
2995 connection = GNUNET_CONTAINER_multihashmap_get (addr_map, &remote_addr_key);
2996 if (NULL != connection)
2997 {
2999 "receiver %s already exist or is being connected to\n",
3000 address);
3001 return GNUNET_SYSERR;
3002 }
3003
3004 /* Create a new connection */
3005 connection = GNUNET_new (struct Connection);
3006 connection->address = remote_addr;
3007 connection->address_len = remote_addrlen;
3008 connection->target = *peer_id;
3009 connection->is_initiator = GNUNET_YES;
3010 connection->id_rcvd = GNUNET_YES;
3011 connection->id_sent = GNUNET_NO;
3012 connection->foreign_addr =
3013 sockaddr_to_udpaddr_string (connection->address, connection->address_len);
3014 connection->nt = GNUNET_NT_scanner_get_type (is,
3016 remote_addrlen);
3017 connection->timeout =
3021 &remote_addr_key,
3022 connection,
3025 "# connections active",
3027 GNUNET_NO);
3028
3029 /* client_gnutls_init */
3030 rv = client_gnutls_init (connection);
3031 if (GNUNET_NO != rv)
3032 {
3033 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "client_gnutls_init failed\n");
3034 return GNUNET_SYSERR;
3035 }
3036
3037 /* client_quic_init */
3038 rv = client_quic_init (connection,
3039 local_addr, local_addrlen,
3040 remote_addr, remote_addrlen);
3041 if (GNUNET_NO != rv)
3042 {
3043 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "client_quic_init failed\n");
3044 return GNUNET_SYSERR;
3045 }
3046
3047 ngtcp2_conn_set_tls_native_handle (connection->conn, connection->session);
3048
3049 rv = connection_write (connection);
3050 if (GNUNET_NO != rv)
3051 {
3053 "connection_write failed\n");
3054 return GNUNET_SYSERR;
3055 }
3057 return GNUNET_OK;
3058}
3059
3060
3074static void
3076 void **app_ctx,
3077 int add_remove,
3079 const struct sockaddr *addr,
3080 socklen_t addrlen)
3081{
3082 char *my_addr;
3084
3085 if (GNUNET_YES == add_remove)
3086 {
3088
3089 GNUNET_asprintf (&my_addr,
3090 "%s-%s",
3092 GNUNET_a2s (addr, addrlen));
3093 nt = GNUNET_NT_scanner_get_type (is, addr, addrlen);
3094 ai =
3096 my_addr,
3097 nt,
3099 GNUNET_free (my_addr);
3100 *app_ctx = ai;
3101 }
3102 else
3103 {
3104 ai = *app_ctx;
3106 *app_ctx = NULL;
3107 }
3108}
3109
3110
3119static int
3121 const struct GNUNET_HashCode *key,
3122 void *value)
3123{
3124 struct Connection *connection = value;
3125 (void) cls;
3126 (void) key;
3127 handle_error (connection);
3128 connection_destroy (connection);
3129 return GNUNET_OK;
3130}
3131
3132
3138static void
3139do_shutdown (void *cls)
3140{
3142 "do_shutdown start\n");
3145 NULL);
3147 gnutls_certificate_free_credentials (cred);
3148
3149 if (NULL != nat)
3150 {
3152 nat = NULL;
3153 }
3154 if (NULL != read_task)
3155 {
3157 read_task = NULL;
3158 }
3159 if (NULL != udp_sock)
3160 {
3163 udp_sock = NULL;
3164 }
3165 if (NULL != ch)
3166 {
3168 ch = NULL;
3169 }
3170 if (NULL != stats)
3171 {
3173 stats = NULL;
3174 }
3175 if (NULL != my_private_key)
3176 {
3178 my_private_key = NULL;
3179 }
3180 if (NULL != is)
3181 {
3183 is = NULL;
3184 }
3186 "do_shutdown finished\n");
3187}
3188
3189
3204static int
3206 struct sockaddr *local_addr, socklen_t local_addrlen,
3207 struct sockaddr *remote_addr, socklen_t remote_addrlen,
3208 const ngtcp2_pkt_info *pi,
3209 const uint8_t *data, size_t datalen)
3210{
3211 ngtcp2_path path;
3212 int rv;
3213
3214 path.local.addr = local_addr;
3215 path.local.addrlen = local_addrlen;
3216 path.remote.addr = remote_addr;
3217 path.remote.addrlen = remote_addrlen;
3218
3219 rv = ngtcp2_conn_read_pkt (connection->conn, &path, pi, data, datalen,
3220 timestamp ());
3221 if (0 != rv)
3222 {
3224 "ngtcp2_conn_read_pkt: %s\n",
3225 ngtcp2_strerror (rv));
3226 switch (rv)
3227 {
3228 case NGTCP2_ERR_DRAINING:
3229 if (GNUNET_NO == connection->is_initiator)
3230 {
3231 start_draining_period (connection);
3233 }
3234 else
3235 {
3236 ngtcp2_ccerr_set_liberr (&connection->last_error, rv, NULL, 0);
3237 }
3238 case NGTCP2_ERR_RETRY:
3239 /* client side doesn't get this */
3240 return NETWORK_ERR_RETRY;
3241 case NGTCP2_ERR_DROP_CONN:
3242 /* client side doesn't get this */
3243 return NETWORK_ERR_DROP_CONN;
3244 case NGTCP2_ERR_CRYPTO:
3245 if (! connection->last_error.error_code)
3246 {
3247 ngtcp2_ccerr_set_tls_alert (
3248 &connection->last_error,
3249 ngtcp2_conn_get_tls_alert (connection->conn),
3250 NULL, 0);
3251 }
3252 break;
3253 default:
3254 if (! connection->last_error.error_code)
3255 {
3256 ngtcp2_ccerr_set_liberr (&connection->last_error, rv, NULL, 0);
3257 }
3258 }
3259 return handle_error (connection);
3260 }
3261 return GNUNET_NO;
3262}
3263
3264
3280static int
3281connection_on_read (struct Connection *connection,
3282 struct sockaddr *local_addr, socklen_t local_addrlen,
3283 struct sockaddr *remote_addr, socklen_t remote_addrlen,
3284 const ngtcp2_pkt_info *pi,
3285 const uint8_t *data, size_t datalen)
3286{
3287 int rv;
3288 rv = connection_feed_data (connection, local_addr, local_addrlen, remote_addr,
3289 remote_addrlen, pi, data, datalen);
3290 if (GNUNET_NO != rv)
3291 {
3292 return rv;
3293 }
3294
3295 connection_update_timer (connection);
3296 return GNUNET_NO;
3297}
3298
3299
3313static struct Connection *
3314connection_init (struct sockaddr *local_addr,
3315 socklen_t local_addrlen,
3316 struct sockaddr *remote_addr,
3317 socklen_t remote_addrlen,
3318 const ngtcp2_cid *dcid, const ngtcp2_cid *scid,
3319 uint32_t version)
3320{
3321 struct Connection *new_connection;
3322 ngtcp2_path path;
3323 ngtcp2_transport_params params;
3324 ngtcp2_cid scid_;
3325 ngtcp2_conn *conn = NULL;
3326 ngtcp2_settings settings;
3327 ngtcp2_callbacks callbacks = {
3328 .recv_client_initial = ngtcp2_crypto_recv_client_initial_cb,
3329 .recv_crypto_data = ngtcp2_crypto_recv_crypto_data_cb,
3330 .encrypt = ngtcp2_crypto_encrypt_cb,
3331 .decrypt = ngtcp2_crypto_decrypt_cb,
3332 .hp_mask = ngtcp2_crypto_hp_mask_cb,
3333 .update_key = ngtcp2_crypto_update_key_cb,
3334 .delete_crypto_aead_ctx = ngtcp2_crypto_delete_crypto_aead_ctx_cb,
3335 .delete_crypto_cipher_ctx = ngtcp2_crypto_delete_crypto_cipher_ctx_cb,
3336 .get_path_challenge_data = ngtcp2_crypto_get_path_challenge_data_cb,
3337 .version_negotiation = ngtcp2_crypto_version_negotiation_cb,
3338
3339 .acked_stream_data_offset = acked_stream_data_offset_cb,
3340 .recv_stream_data = recv_stream_data_cb,
3341 .stream_open = stream_open_cb,
3342 .rand = rand_cb,
3343 .get_new_connection_id = get_new_connection_id_cb,
3344 .stream_close = stream_close_cb,
3345 .extend_max_remote_streams_bidi = extend_max_remote_streams_bidi_cb,
3346 .stream_stop_sending = stream_stop_sending_cb,
3347 .extend_max_stream_data = extend_max_stream_data_cb,
3348 .recv_tx_key = recv_tx_key_cb,
3349 };
3350
3351
3352 int rv;
3353
3354 path.local.addr = local_addr;
3355 path.local.addrlen = local_addrlen;
3356 path.remote.addr = remote_addr;
3357 path.remote.addrlen = remote_addrlen;
3358
3359 new_connection = GNUNET_new (struct Connection);
3360 memset (new_connection, 0, sizeof (struct Connection));
3361
3362 gnutls_init (&new_connection->session,
3363 GNUTLS_SERVER
3364 | GNUTLS_ENABLE_EARLY_DATA
3365 | GNUTLS_NO_END_OF_EARLY_DATA);
3366 gnutls_priority_set_direct (new_connection->session, PRIORITY, NULL);
3367 gnutls_credentials_set (new_connection->session,
3368 GNUTLS_CRD_CERTIFICATE, cred);
3369
3370 ngtcp2_transport_params_default (&params);
3371 params.initial_max_streams_uni = 3;
3372 params.initial_max_streams_bidi = 128;
3373 params.initial_max_stream_data_bidi_local = 128 * 1024;
3374 params.initial_max_stream_data_bidi_remote = 256 * 1024;
3375 params.initial_max_stream_data_uni = 256 * 1024;
3376 params.initial_max_data = 1024 * 1024;
3377 params.original_dcid_present = 1;
3378 params.max_idle_timeout = 30 * NGTCP2_SECONDS;
3379 params.original_dcid = *scid;
3380
3381 ngtcp2_settings_default (&settings);
3382
3383 scid_.datalen = NGTCP2_MAX_CIDLEN;
3385 &scid_.data, scid_.datalen);
3386
3387 rv = ngtcp2_conn_server_new (&conn,
3388 dcid,
3389 &scid_,
3390 &path,
3391 version,
3392 &callbacks,
3393 &settings,
3394 &params,
3395 NULL,
3396 new_connection);
3397 if (rv < 0)
3398 {
3400 "ngtcp2_conn_server_new: %s\n",
3401 ngtcp2_strerror (rv));
3402 return NULL;
3403 }
3404 new_connection->conn = conn;
3405 new_connection->address = GNUNET_memdup (remote_addr, remote_addrlen);
3406 new_connection->address_len = remote_addrlen;
3407 new_connection->foreign_addr =
3408 sockaddr_to_udpaddr_string (new_connection->address,
3409 new_connection->address_len);
3410 new_connection->is_initiator = GNUNET_NO;
3411 new_connection->id_rcvd = GNUNET_NO;
3412 new_connection->id_sent = GNUNET_NO;
3413 ngtcp2_crypto_gnutls_configure_server_session (new_connection->session);
3414 ngtcp2_conn_set_tls_native_handle (new_connection->conn,
3415 new_connection->session);
3416 gnutls_session_set_ptr (new_connection->session,
3417 &new_connection->conn_ref);
3418
3419 new_connection->conn_ref.get_conn = get_conn;
3420 new_connection->conn_ref.user_data = new_connection;
3421 new_connection->streams = GNUNET_CONTAINER_multihashmap_create (10,
3422 GNUNET_NO);
3423
3424 return new_connection;
3425}
3426
3427
3442static void
3443server_read_pkt (struct Connection *connection,
3444 const struct GNUNET_HashCode *addr_key,
3445 struct sockaddr *local_addr, socklen_t local_addrlen,
3446 struct sockaddr *remote_addr, socklen_t remote_addrlen,
3447 const ngtcp2_pkt_info *pi,
3448 const uint8_t *data, size_t datalen)
3449{
3450 ngtcp2_version_cid version_cid;
3451 int rv;
3452
3453 rv = ngtcp2_pkt_decode_version_cid (&version_cid, data, datalen,
3454 NGTCP2_MAX_CIDLEN);
3455 switch (rv)
3456 {
3457 case 0:
3458 break;
3459 case NGTCP2_ERR_VERSION_NEGOTIATION:
3460 // TODO: send version negotiation
3461 return;
3462 default:
3464 "Can't decode version and CID: %s\n",
3465 ngtcp2_strerror (rv));
3466 return;
3467 }
3468
3469 if (NULL == connection)
3470 {
3471 ngtcp2_pkt_hd header;
3472 rv = ngtcp2_accept (&header, data, datalen);
3473 if (0 != rv)
3474 {
3476 "ngtcp2_accept: %s\n",
3477 ngtcp2_strerror (rv));
3478 return;
3479 }
3480
3485 connection = connection_init (local_addr, local_addrlen, remote_addr,
3486 remote_addrlen, &header.scid, &header.dcid,
3487 header.version);
3488 if (NULL == connection)
3489 {
3491 "accept connection error!\n");
3492 return;
3493 }
3494
3496 addr_key,
3497 connection,
3499 rv = connection_on_read (connection, local_addr, local_addrlen, remote_addr,
3500 remote_addrlen, pi, data, datalen);
3501 switch (rv)
3502 {
3503 case 0:
3504 break;
3505 case NETWORK_ERR_RETRY:
3506 // TODO: send retry
3507 return;
3508 default:
3509 return;
3510 }
3511
3512 rv = connection_write (connection);
3513 if (GNUNET_NO != rv)
3514 {
3515 return;
3516 }
3517
3518 // add to cid_map here
3519 return;
3520 }
3521
3522 if (ngtcp2_conn_in_closing_period (connection->conn))
3523 {
3524 rv = send_conn_close (connection);
3525 if (GNUNET_NO != rv)
3526 {
3527 connection_destroy (connection);
3528 }
3529 return;
3530 }
3531
3532 if (ngtcp2_conn_in_draining_period (connection->conn))
3533 {
3534 return;
3535 }
3536
3537 rv = connection_on_read (connection, local_addr, local_addrlen, remote_addr,
3538 remote_addrlen, pi, data, datalen);
3539 if (GNUNET_NO != rv)
3540 {
3541 if (NETWORK_ERR_CLOSE_WAIT != rv)
3542 {
3543 connection_destroy (connection);
3544 }
3545 return;
3546 }
3547
3548 connection_write (connection);
3549}
3550
3551
3557static void
3558sock_read (void *cls)
3559{
3560 (void) cls;
3561 struct sockaddr_storage sa;
3562 socklen_t salen = sizeof (sa);
3563 ssize_t rcvd;
3564 uint8_t buf[UINT16_MAX];
3565 struct GNUNET_HashCode addr_key;
3566 struct Connection *connection;
3567 int rv;
3568 char *bindto;
3569 struct sockaddr *local_addr;
3570 socklen_t local_addrlen;
3571
3572 if (GNUNET_OK !=
3575 "BINDTO",
3576 &bindto))
3577 {
3580 "BINDTO");
3581 return;
3582 }
3583 local_addr = udp_address_to_sockaddr (bindto, &local_addrlen);
3585 udp_sock,
3586 &sock_read,
3587 NULL);
3588
3589 while (1)
3590 {
3592 buf,
3593 sizeof(buf),
3594 (struct sockaddr *) &sa,
3595 &salen);
3596 if (-1 == rcvd)
3597 {
3598 struct sockaddr *addr = (struct sockaddr*) &sa;
3599
3600 if (EAGAIN == errno)
3601 break; // We are done reading data
3603 "Failed to recv from %s family %d failed sock %p\n",
3604 GNUNET_a2s ((struct sockaddr*) &sa,
3605 sizeof (*addr)),
3606 addr->sa_family,
3607 udp_sock);
3609 return;
3610 }
3612 "Read %llu bytes\n",
3613 (unsigned long long) rcvd);
3614 if (0 == rcvd)
3615 {
3616 GNUNET_break_op (0);
3618 "Read 0 bytes from UDP socket\n");
3619 return;
3620 }
3621
3622 char *addr_string =
3623 sockaddr_to_udpaddr_string ((const struct sockaddr *) &sa,
3624 salen);
3625 GNUNET_CRYPTO_hash (addr_string, strlen (addr_string),
3626 &addr_key);
3627 GNUNET_free (addr_string);
3628 connection = GNUNET_CONTAINER_multihashmap_get (addr_map, &addr_key);
3629
3630 ngtcp2_pkt_info pi = {0};
3631 if (NULL != connection && GNUNET_YES == connection->is_initiator)
3632 {
3633 rv = connection_feed_data (connection, local_addr, local_addrlen,
3634 (struct sockaddr *) &sa,
3635 salen, &pi, buf, rcvd);
3636 if (GNUNET_NO != rv)
3637 {
3638 return;
3639 }
3640 rv = connection_write (connection);
3641 if (rv < 0)
3642 {
3644 "connection write error!\n");
3645 return;
3646 }
3647 }
3648 else
3649 {
3650 server_read_pkt (connection, &addr_key,
3651 local_addr, local_addrlen,
3652 (struct sockaddr *) &sa, salen,
3653 &pi, buf, rcvd);
3654 }
3655
3656 }
3657
3659
3660}
3661
3662
3671static void
3672run (void *cls,
3673 char *const *args,
3674 const char *cfgfile,
3675 const struct GNUNET_CONFIGURATION_Handle *c)
3676{
3677 char *bindto;
3678 struct sockaddr *in;
3679 socklen_t in_len;
3680 struct sockaddr_storage in_sto;
3681 socklen_t sto_len;
3682 char *cert_file;
3683 char *key_file;
3684
3685 (void) cls;
3686 cfg = c;
3687 if (GNUNET_OK !=
3690 "BINDTO",
3691 &bindto))
3692 {
3695 "BINDTO");
3696 return;
3697 }
3698
3699 key_file = NULL;
3700 cert_file = NULL;
3701 if ((GNUNET_OK !=
3704 "KEY_FILE",
3705 &key_file)))
3706 key_file = GNUNET_strdup ("https.key");
3707 if (GNUNET_OK !=
3710 "CERT_FILE",
3711 &cert_file))
3712 cert_file = GNUNET_strdup ("https.crt");
3713 if ((GNUNET_OK != GNUNET_DISK_file_test (key_file)) ||
3714 (GNUNET_OK != GNUNET_DISK_file_test (cert_file)))
3715 {
3717 "Creating new certificate\n");
3718
3719 struct GNUNET_OS_Process *cert_creation;
3720
3722 NULL, NULL, NULL,
3723 "gnunet-transport-certificate-creation",
3724 "gnunet-transport-certificate-creation",
3725 key_file,
3726 cert_file,
3727 NULL);
3728 if (NULL == cert_creation)
3729 {
3731 "Can't create new key pair %s/%s\n",
3732 key_file, cert_file);
3733 GNUNET_free (key_file);
3734 GNUNET_free (cert_file);
3735
3736 return;
3737 }
3738 GNUNET_OS_process_wait (cert_creation);
3739 GNUNET_OS_process_destroy (cert_creation);
3740 }
3741
3743 if ((GNUNET_NO == GNUNET_NETWORK_test_pf (PF_INET6)) ||
3744 (GNUNET_YES ==
3747 "DISABLE_V6")))
3748 {
3750 }
3751
3752 in = udp_address_to_sockaddr (bindto, &in_len);
3753
3754 if (NULL == in)
3755 {
3757 "Failed to setup UDP socket address with path `%s'\n",
3758 bindto);
3759 GNUNET_free (bindto);
3760 return;
3761 }
3762 udp_sock =
3763 GNUNET_NETWORK_socket_create (in->sa_family,
3764 SOCK_DGRAM,
3765 IPPROTO_UDP);
3766 if (NULL == udp_sock)
3767 {
3770 "Failed to create socket for %s family %d\n",
3771 GNUNET_a2s (in,
3772 in_len),
3773 in->sa_family);
3774 GNUNET_free (in);
3775 GNUNET_free (bindto);
3776 return;
3777 }
3778 if (AF_INET6 == in->sa_family)
3780 if (GNUNET_OK !=
3782 in,
3783 in_len))
3784 {
3786 "bind",
3787 bindto);
3789 "Failed to bind socket for %s family %d sock %p\n",
3790 GNUNET_a2s (in,
3791 in_len),
3792 in->sa_family,
3793 udp_sock);
3795 udp_sock = NULL;
3796 GNUNET_free (in);
3797 GNUNET_free (bindto);
3798 return;
3799 }
3800 sto_len = sizeof(in_sto);
3801 if (0 != getsockname (GNUNET_NETWORK_get_fd (udp_sock),
3802 (struct sockaddr *) &in_sto,
3803 &sto_len))
3804 {
3805 memcpy (&in_sto, in, in_len);
3806 sto_len = in_len;
3807 }
3808 GNUNET_free (in);
3809 GNUNET_free (bindto);
3810 in = (struct sockaddr *) &in_sto;
3811 in_len = sto_len;
3813 "transport",
3814 "Bound to `%s' sock %p\n",
3815 GNUNET_a2s ((const struct sockaddr *) &in_sto,
3816 sto_len),
3817 udp_sock);
3818 switch (in->sa_family)
3819 {
3820 case AF_INET:
3821 my_port = ntohs (((struct sockaddr_in *) in)->sin_port);
3822 break;
3823
3824 case AF_INET6:
3825 my_port = ntohs (((struct sockaddr_in6 *) in)->sin6_port);
3826 break;
3827
3828 default:
3829 GNUNET_break (0);
3830 my_port = 0;
3831 }
3833
3836
3837 int rv;
3838 rv = gnutls_certificate_allocate_credentials (&cred);
3839 if (GNUNET_NO == rv)
3840 rv = gnutls_certificate_set_x509_system_trust (cred);
3841 if (GNUNET_NO > rv)
3842 {
3844 "cred init failed: %s\n",
3845 gnutls_strerror (rv));
3846 return;
3847 }
3848 rv = gnutls_certificate_set_x509_key_file (cred,
3849 cert_file,
3850 key_file,
3851 GNUTLS_X509_FMT_PEM);
3853 "key_file: %s\ncert_file: %s\n",
3854 key_file, cert_file);
3855 GNUNET_free (cert_file);
3856 GNUNET_free (key_file);
3857 if (rv < 0)
3858 {
3860 "gnutls_certificate_set_x509_key_file: %s\n",
3861 gnutls_strerror (rv));
3862 return;
3863 }
3868 if (NULL == my_private_key)
3869 {
3870 GNUNET_log (
3872 _ (
3873 "Transport service is lacking key configuration settings. Exiting.\n"));
3875 return;
3876 }
3878
3880 udp_sock,
3881 &sock_read,
3882 NULL);
3887 &mq_init,
3888 NULL,
3889 &notify_cb,
3890 NULL,
3891 NULL);
3892 if (NULL == ch)
3893 {
3894 GNUNET_break (0);
3896 return;
3897 }
3898
3901 IPPROTO_UDP,
3902 1 /* one address */,
3903 (const struct sockaddr **) &in,
3904 &in_len,
3907 NULL /* closure */);
3908}
3909
3910
3918int
3919main (int argc, char *const *argv)
3920{
3921 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
3923 };
3924 int ret;
3925
3927 "transport",
3928 "Starting http3 communicator\n");
3929 ret = (GNUNET_OK ==
3931 argc,
3932 argv,
3933 "gnunet-communicator-http3",
3934 _ ("GNUnet HTTP3 communicator"),
3935 options,
3936 &run,
3937 NULL))
3938 ? 0
3939 : 1;
3940 return ret;
3941}
3942
3943
3944/* end of gnunet-communicator-http3.c */
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_OPTION_END
Definition: 002.c:13
struct GNUNET_GETOPT_CommandLineOption options[]
Definition: 002.c:5
struct GNUNET_MQ_Handle * mq
Definition: 003.c:5
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
static int start
Set if we are to start default services (including ARM).
Definition: gnunet-arm.c:38
static int ret
Final status code.
Definition: gnunet-arm.c:93
static uint16_t port
Port number.
Definition: gnunet-bcd.c:146
static char * peer_id
Option –peer.
Definition: gnunet-cadet.c:42
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.
static void do_shutdown(void *cls)
Shutdown the HTTP3 communicator.
#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.
int main(int argc, char *const *argv)
The main function for the UNIX communicator.
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:506
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:1001
ssize_t GNUNET_NETWORK_socket_recvfrom(const struct GNUNET_NETWORK_Handle *desc, void *buffer, size_t length, struct sockaddr *src_addr, socklen_t *addrlen)
Read data from a socket (always non-blocking).
Definition: network.c:688
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_create(int domain, int type, int protocol)
Create a new socket.
Definition: network.c:833
enum GNUNET_GenericReturnValue GNUNET_NETWORK_test_pf(int pf)
Test if the given protocol family is supported by this system.
Definition: network.c: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:772
GNUNET_NetworkType
Types of networks (with separate quotas) we support.
Definition: gnunet_nt_lib.h:44
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
struct GNUNET_OS_Process * GNUNET_OS_start_process(enum GNUNET_OS_InheritStdioFlags std_inheritance, struct GNUNET_DISK_PipeHandle *pipe_stdin, struct GNUNET_DISK_PipeHandle *pipe_stdout, struct GNUNET_DISK_PipeHandle *pipe_stderr, const char *filename,...)
Start a process.
Definition: os_priority.c:620
const struct GNUNET_OS_ProjectData * GNUNET_OS_project_data_gnunet(void)
Return default project data used by 'libgnunetutil' for GNUnet.
void GNUNET_OS_process_destroy(struct GNUNET_OS_Process *proc)
Cleans up process structure contents (OS-dependent) and deallocates it.
Definition: os_priority.c:260
enum GNUNET_GenericReturnValue GNUNET_OS_process_wait(struct GNUNET_OS_Process *proc)
Wait for a process to terminate.
Definition: os_priority.c:871
@ 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:567
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_net(struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition: scheduler.c:1511
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:1339
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:980
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:1304
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:1277
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:178
Information of the connection with 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:136
Handle for the service.
Time for absolute times used by GNUnet, in microseconds.
Time for relative time used by GNUnet, in microseconds.
Internal representation of an address a communicator is currently providing for the transport service...
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.