GNUnet 0.22.0
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 = %"PRIi64"\n",
708 stream_id);
709 return;
710 }
711
712 if (stream->uri)
713 {
714 GNUNET_free (stream->uri);
715 }
716 if (stream->method)
717 {
718 GNUNET_free (stream->method);
719 }
720 if (stream->authority)
721 {
722 GNUNET_free (stream->authority);
723 }
724 GNUNET_free (stream);
725}
726
727
738static struct Stream *
740{
741 struct GNUNET_HashCode stream_key;
742 struct Stream *stream;
743
744 GNUNET_CRYPTO_hash (&stream_id, sizeof (stream_id), &stream_key);
746 return stream;
747}
748
749
757static int
759{
760 int rv;
761 gnutls_datum_t alpn = { (unsigned char *) "h3", sizeof("h3") - 1};
762 // rv = gnutls_certificate_allocate_credentials (&connection->cred);
763 // if (GNUNET_NO == rv)
764 // rv = gnutls_certificate_set_x509_system_trust (connection->cred);
765 // if (GNUNET_NO > rv)
766 // {
767 // GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
768 // "cred init failed: %s\n",
769 // gnutls_strerror (rv));
770 // return GNUNET_SYSERR;
771 // }
772 rv = gnutls_init (&connection->session,
773 GNUTLS_CLIENT
774 | GNUTLS_ENABLE_EARLY_DATA
775 | GNUTLS_NO_END_OF_EARLY_DATA);
776 if (GNUNET_NO != rv)
777 {
779 "gnutls_init error: %s\n",
780 gnutls_strerror (rv));
781 return GNUNET_SYSERR;
782 }
783 rv = ngtcp2_crypto_gnutls_configure_client_session (connection->session);
784 if (GNUNET_NO != rv)
785 {
787 "ngtcp2_crypto_gnutls_configure_client_session failed\n");
788 return GNUNET_SYSERR;
789 }
790 rv = gnutls_priority_set_direct (connection->session, PRIORITY, NULL);
791 if (GNUNET_NO != rv)
792 {
794 "gnutls_priority_set_direct: %s\n",
795 gnutls_strerror (rv));
796 return GNUNET_SYSERR;
797 }
798 gnutls_session_set_ptr (connection->session, &connection->conn_ref);
799 rv = gnutls_credentials_set (connection->session, GNUTLS_CRD_CERTIFICATE,
800 cred);
801 if (GNUNET_NO != rv)
802 {
804 "gnutls_credentials_set: %s\n",
805 gnutls_strerror (rv));
806 return GNUNET_SYSERR;
807 }
808 gnutls_alpn_set_protocols (connection->session, &alpn, 1,
809 GNUTLS_ALPN_MANDATORY);
810
815 // gnutls_server_name_set (connection->session, GNUTLS_NAME_DNS, "localhost",
816 // strlen ("localhost"));
817
818 return GNUNET_NO;
819}
820
821
827static void
829{
832 // GNUNET_CONTAINER_heap_update_cost (peer->hn,
833 // peer->timeout.abs_value_us);
834}
835
836
845static int
847 const struct GNUNET_HashCode *key,
848 void *value)
849{
850 struct Stream *stream = value;
851 (void) cls;
852 (void) key;
853
854 if (stream->uri)
855 {
856 GNUNET_free (stream->uri);
857 }
858 if (stream->method)
859 {
860 GNUNET_free (stream->method);
861 }
862 if (stream->authority)
863 {
864 GNUNET_free (stream->authority);
865 }
866 GNUNET_free (stream);
867 return GNUNET_OK;
868}
869
870
876static void
878{
879 struct GNUNET_HashCode addr_key;
880 struct HTTP_Message *msg_curr;
881 struct Long_Poll_Request *long_poll_curr;
882 struct Long_Poll_Request *long_poll_temp;
883 int rv;
885
886 msg_curr = connection->msg_queue_head;
887 connection->msg_queue_rear = NULL;
888 while (NULL != msg_curr)
889 {
890 msg_curr = msg_curr->next;
891 GNUNET_free (msg_curr->buf);
892 GNUNET_free (msg_curr);
893 }
894
895 msg_curr = connection->submitted_msg_queue_head;
896 while (NULL != msg_curr)
897 {
898 msg_curr = msg_curr->next;
899 GNUNET_free (msg_curr->buf);
900 GNUNET_free (msg_curr);
901 }
902
903 long_poll_curr = connection->long_poll_head;
904 connection->long_poll_rear = NULL;
905 while (NULL != long_poll_curr)
906 {
907 long_poll_temp = long_poll_curr;
908 long_poll_curr = long_poll_curr->next;
909 GNUNET_free (long_poll_temp);
910 }
911
912 if (NULL != connection->d_qh)
913 {
915 connection->d_qh = NULL;
916 }
917
918 GNUNET_CRYPTO_hash (connection->address,
919 connection->address_len,
920 &addr_key);
921 rv = GNUNET_CONTAINER_multihashmap_remove (addr_map, &addr_key, connection);
922 if (GNUNET_NO == rv)
923 {
925 "tried to remove non-existent connection from addr_map\n");
926 return;
927 }
929 "# connections active",
931 GNUNET_NO);
932
933 ngtcp2_conn_del (connection->conn);
934 if (connection->h3_conn)
935 {
936 nghttp3_conn_del (connection->h3_conn);
937 }
938 gnutls_deinit (connection->session);
939 GNUNET_free (connection->address);
940 GNUNET_free (connection->foreign_addr);
941 GNUNET_free (connection->conn_closebuf);
944 NULL);
946 GNUNET_free (connection);
947}
948
949
959static nghttp3_nv
960make_nv (const char *name, const char *value, uint8_t flag)
961{
962 nghttp3_nv nv;
963 nv.name = (const uint8_t *) name;
964 nv.namelen = strlen (name);
965 nv.value = (const uint8_t *) value;
966 nv.valuelen = strlen (value);
967 nv.flags = flag;
968
969 return nv;
970}
971
972
976static nghttp3_ssize
977read_data (nghttp3_conn *conn, int64_t stream_id, nghttp3_vec *vec,
978 size_t veccnt, uint32_t *pflags, void *user_data,
979 void *stream_user_data)
980{
981 struct Stream *stream = stream_user_data;
982
983 vec[0].base = stream->data;
984 vec[0].len = stream->datalen;
985 *pflags |= NGHTTP3_DATA_FLAG_EOF;
986
987 return 1;
988}
989
990
1001static int
1003 struct Stream *stream,
1004 const uint8_t *data,
1005 size_t datalen)
1006{
1007 nghttp3_nv nva[7];
1008 char contentlen[20];
1009 nghttp3_data_reader dr = {};
1010 int rv;
1011
1012 GNUNET_snprintf (contentlen, sizeof(contentlen), "%zu", datalen);
1013 stream->data = (uint8_t *) data;
1014 stream->datalen = datalen;
1015
1016 nva[0] = make_nv (":method", "POST",
1017 NGHTTP3_NV_FLAG_NO_COPY_NAME
1018 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1019 nva[1] = make_nv (":scheme", "https",
1020 NGHTTP3_NV_FLAG_NO_COPY_NAME
1021 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1022 nva[2] = make_nv (":authority",
1024 NGHTTP3_NV_FLAG_NO_COPY_NAME);
1025 nva[3] = make_nv (":path", "/",
1026 NGHTTP3_NV_FLAG_NO_COPY_NAME
1027 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1028 nva[4] = make_nv ("user-agent", "nghttp3/ngtcp2 client",
1029 NGHTTP3_NV_FLAG_NO_COPY_NAME
1030 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1031 nva[5] = make_nv ("content-type", "application/octet-stream",
1032 NGHTTP3_NV_FLAG_NO_COPY_NAME
1033 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1034 nva[6] = make_nv ("content-length", contentlen,
1035 NGHTTP3_NV_FLAG_NO_COPY_NAME);
1036
1037 dr.read_data = read_data;
1038 rv = nghttp3_conn_submit_request (connection->h3_conn,
1039 stream->stream_id,
1040 nva, 7, &dr, stream);
1041 if (0 != rv)
1042 {
1044 "nghttp3_conn_submit_request: %s\n",
1045 nghttp3_strerror (rv));
1046 return GNUNET_SYSERR;
1047 }
1048
1049 return GNUNET_NO;
1050}
1051
1052
1062static int
1064 struct Stream *stream)
1065{
1067 "send get request\n");
1068 nghttp3_nv nva[6];
1069 int rv;
1070
1071 nva[0] = make_nv (":method", "GET",
1072 NGHTTP3_NV_FLAG_NO_COPY_NAME
1073 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1074 nva[1] = make_nv (":scheme", "https",
1075 NGHTTP3_NV_FLAG_NO_COPY_NAME
1076 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1077 nva[2] = make_nv (":authority",
1079 NGHTTP3_NV_FLAG_NO_COPY_NAME);
1080 nva[3] = make_nv (":path", "/",
1081 NGHTTP3_NV_FLAG_NO_COPY_NAME
1082 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1083 nva[4] = make_nv ("user-agent", "nghttp3/ngtcp2 client",
1084 NGHTTP3_NV_FLAG_NO_COPY_NAME
1085 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1086
1087 rv = nghttp3_conn_submit_request (connection->h3_conn,
1088 stream->stream_id,
1089 nva, 5, NULL, stream);
1090 if (0 != rv)
1091 {
1093 "nghttp3_conn_submit_request: %s\n",
1094 nghttp3_strerror (rv));
1095 return GNUNET_SYSERR;
1096 }
1097
1098 return GNUNET_NO;
1099}
1100
1101
1107static void
1109{
1111 "long_poll_timeoutcb called!\n");
1112 struct Long_Poll_Request *long_poll = cls;
1113 nghttp3_nv nva[2];
1114 struct Stream *stream;
1115 struct Connection *connection;
1116 int rv;
1117
1118 long_poll->timer = NULL;
1119
1120 stream = long_poll->stream;
1121 connection = stream->connection;
1122 if (NULL != long_poll->prev)
1123 {
1124 long_poll->prev->next = long_poll->next;
1125 }
1126 if (NULL != long_poll->next)
1127 {
1128 long_poll->next->prev = long_poll->prev;
1129 }
1130 if (connection->long_poll_head == long_poll)
1131 {
1132 connection->long_poll_head = long_poll->next;
1133 }
1134 if (connection->long_poll_rear == long_poll)
1135 {
1136 connection->long_poll_rear = long_poll->prev;
1137 }
1138 GNUNET_free (long_poll);
1139
1140 nva[0] = make_nv (":status", "204",
1141 NGHTTP3_NV_FLAG_NO_COPY_NAME
1142 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1143 nva[1] = make_nv ("server", "nghttp3/ngtcp2 server",
1144 NGHTTP3_NV_FLAG_NO_COPY_NAME
1145 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1146 rv = nghttp3_conn_submit_response (connection->h3_conn,
1147 stream->stream_id, nva, 2, NULL);
1148 if (0 != rv)
1149 {
1151 "nghttp3_conn_submit_response: %s\n",
1152 nghttp3_strerror (rv));
1153 return;
1154 }
1155 ngtcp2_conn_shutdown_stream_read (connection->conn, 0,
1156 stream->stream_id,
1157 NGHTTP3_H3_NO_ERROR);
1158}
1159
1160
1171static int
1172stream_send_data (struct Stream *stream,
1173 uint8_t *data, size_t datalen)
1174{
1175 nghttp3_nv nva[4];
1176 nghttp3_data_reader dr = {};
1177 char content_length_str[20];
1178 int rv;
1179
1180 GNUNET_snprintf (content_length_str, sizeof(content_length_str),
1181 "%zu", datalen);
1182 nva[0] = make_nv (":status", "200",
1183 NGHTTP3_NV_FLAG_NO_COPY_NAME
1184 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1185 nva[1] = make_nv ("server", "nghttp3/ngtcp2 server",
1186 NGHTTP3_NV_FLAG_NO_COPY_NAME
1187 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1188 nva[2] = make_nv ("content-type", "application/octet-stream",
1189 NGHTTP3_NV_FLAG_NO_COPY_NAME
1190 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1191 nva[3] = make_nv ("content-length", content_length_str,
1192 NGHTTP3_NV_FLAG_NO_COPY_NAME);
1193
1194 stream->data = data;
1195 stream->datalen = datalen;
1196 dr.read_data = read_data;
1197 rv = nghttp3_conn_submit_response (stream->connection->h3_conn,
1198 stream->stream_id,
1199 nva, 4, &dr);
1200 if (0 != rv)
1201 {
1203 "nghttp3_conn_submit_response: %s\n",
1204 nghttp3_strerror (rv));
1205 return GNUNET_SYSERR;
1206 }
1207 return GNUNET_NO;
1208}
1209
1210
1219static int
1220stream_start_response (struct Connection *connection, struct Stream *stream)
1221{
1222 nghttp3_nv nva[4];
1223 struct HTTP_Message *msg;
1224 struct Long_Poll_Request *long_poll;
1225 struct GNUNET_TIME_Relative delay;
1226 int rv;
1227
1228 nva[0] = make_nv (":status", "200",
1229 NGHTTP3_NV_FLAG_NO_COPY_NAME
1230 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1231 nva[1] = make_nv ("server", "nghttp3/ngtcp2 server",
1232 NGHTTP3_NV_FLAG_NO_COPY_NAME
1233 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1234
1235 // method is POST
1236 if (4 == stream->methodlen)
1237 {
1238 if (NULL == connection->msg_queue_head)
1239 {
1240 rv = nghttp3_conn_submit_response (connection->h3_conn, stream->stream_id,
1241 nva, 2, NULL);
1242 if (0 != rv)
1243 {
1245 "nghttp3_conn_submit_response: %s\n",
1246 nghttp3_strerror (rv));
1247 return GNUNET_SYSERR;
1248 }
1249 }
1250 else
1251 {
1252 connection->msg_queue_len -= 1;
1254 "rm msg, len = %lu\n",
1255 connection->msg_queue_len);
1256 msg = connection->msg_queue_head;
1257 stream_send_data (stream, (uint8_t *) msg->buf, msg->size);
1258 connection->msg_queue_head = msg->next;
1259 msg->next = connection->submitted_msg_queue_head;
1260 connection->submitted_msg_queue_head = msg;
1261 }
1262 }
1263 // method is GET
1264 else
1265 {
1267 "server recv GET request\n");
1268 if (NULL != connection->msg_queue_head &&
1269 NULL == connection->long_poll_head)
1270 {
1271 msg = connection->msg_queue_head;
1272 stream_send_data (stream,
1273 (uint8_t *) msg->buf,
1274 msg->size);
1275 connection->msg_queue_head = msg->next;
1276 msg->next = connection->submitted_msg_queue_head;
1277 connection->submitted_msg_queue_head = msg;
1278 }
1279 else if (NULL == connection->msg_queue_head ||
1280 NULL != connection->long_poll_head)
1281 {
1282 connection->long_poll_len += 1;
1284 "add long_poll, len = %lu\n",
1285 connection->long_poll_len);
1286 long_poll = GNUNET_new (struct Long_Poll_Request);
1287 long_poll->stream = stream;
1288 long_poll->next = NULL;
1289 long_poll->prev = connection->long_poll_rear;
1290 long_poll->delay_time = 1ULL;
1291 if (NULL != connection->long_poll_rear)
1292 {
1293 connection->long_poll_rear->next = long_poll;
1294 long_poll->delay_time =
1295 (connection->long_poll_head->delay_time & (NUM_LONG_POLL - 1)) + 1ULL;
1296 }
1297 connection->long_poll_rear = long_poll;
1298 if (NULL == connection->long_poll_head)
1299 {
1300 connection->long_poll_head = long_poll;
1301 }
1303 long_poll->delay_time);
1304 long_poll->timer = GNUNET_SCHEDULER_add_delayed (delay,
1306 long_poll);
1307 }
1308 long_poll = connection->long_poll_head;
1309
1310 while (NULL != long_poll &&
1311 NULL != connection->msg_queue_head)
1312 {
1313 GNUNET_SCHEDULER_cancel (long_poll->timer);
1314 if (NULL != long_poll->next)
1315 {
1316 long_poll->next->prev = NULL;
1317 }
1318
1319 msg = connection->msg_queue_head;
1320 connection->msg_queue_head = msg->next;
1321 msg->next = connection->submitted_msg_queue_head;
1322 connection->submitted_msg_queue_head = msg;
1323 stream_send_data (long_poll->stream,
1324 (uint8_t *) msg->buf,
1325 msg->size);
1326 connection->long_poll_head = long_poll->next;
1327 if (NULL != long_poll->next)
1328 {
1329 long_poll->next->prev = NULL;
1330 }
1331 connection->long_poll_len -= 1;
1333 "rm long_poll, len = %lu\n",
1334 connection->long_poll_len);
1335 GNUNET_free (long_poll);
1336 long_poll = connection->long_poll_head;
1337 }
1338 }
1339 return GNUNET_NO;
1340}
1341
1342
1351static void
1353 const struct GNUNET_MessageHeader *msg,
1354 void *impl_state)
1355{
1356 struct Connection *connection = impl_state;
1357 uint16_t msize = ntohs (msg->size);
1358 struct Stream *post_stream;
1359 struct HTTP_Message *send_buf;
1360 struct Long_Poll_Request *long_poll;
1361
1363 "mq_send_d: init = %d, msg->size = %u, time: %llu\n",
1364 connection->is_initiator, msize,
1365 (unsigned long long) timestamp () / NGTCP2_SECONDS);
1366 if (NULL == connection->conn)
1367 {
1369 "No quic connection has been established yet\n");
1370 return;
1371 }
1372
1373 GNUNET_assert (mq == connection->d_mq);
1374
1375 if (msize > connection->d_mtu)
1376 {
1378 "msize: %u, mtu: %lu\n",
1379 msize,
1380 connection->d_mtu);
1381 GNUNET_break (0);
1382 if (GNUNET_YES != connection->connection_destroy_called)
1383 {
1385 "connection destroy called, destroying connection\n");
1386 connection_destroy (connection);
1387 }
1388 return;
1389 }
1390 reschedule_peer_timeout (connection);
1391
1392 // If we are client side.
1393 if (GNUNET_YES == connection->is_initiator)
1394 {
1395 post_stream = create_stream (connection, -1);
1396 ngtcp2_conn_open_bidi_stream (connection->conn,
1397 &post_stream->stream_id,
1398 NULL);
1399 submit_post_request (connection, post_stream, (uint8_t *) msg, msize);
1400 connection_write (connection);
1401 }
1402 // If we are server side.
1403 else
1404 {
1405 if (NULL == connection->msg_queue_head &&
1406 NULL != connection->long_poll_head)
1407 {
1408 long_poll = connection->long_poll_head;
1409 GNUNET_SCHEDULER_cancel (long_poll->timer);
1410 stream_send_data (long_poll->stream, (uint8_t *) msg, msize);
1411 connection_write (connection);
1412 connection->long_poll_head = long_poll->next;
1413 if (NULL != long_poll->next)
1414 {
1415 long_poll->next->prev = NULL;
1416 }
1417 connection->long_poll_len -= 1;
1419 "rm long_poll, len = %lu\n",
1420 connection->long_poll_len);
1421 GNUNET_free (long_poll);
1422 }
1423 else if (NULL == connection->long_poll_head ||
1424 NULL != connection->msg_queue_head)
1425 {
1426 connection->msg_queue_len += 1;
1428 "add msg, len = %lu\n",
1429 connection->msg_queue_len);
1430 send_buf = GNUNET_new (struct HTTP_Message);
1431 send_buf->size = msize;
1432 send_buf->buf = GNUNET_memdup (msg, msize);
1433 send_buf->next = NULL;
1434 connection->msg_queue_rear = send_buf;
1435 if (NULL == connection->msg_queue_head)
1436 {
1437 connection->msg_queue_head = send_buf;
1438 }
1439 }
1440
1441 long_poll = connection->long_poll_head;
1442 while (NULL != long_poll &&
1443 NULL != connection->msg_queue_head)
1444 {
1445 GNUNET_SCHEDULER_cancel (long_poll->timer);
1446 if (NULL != long_poll->next)
1447 {
1448 long_poll->next->prev = NULL;
1449 }
1450
1451 send_buf = connection->msg_queue_head;
1452 connection->msg_queue_head = send_buf->next;
1453 send_buf->next = connection->submitted_msg_queue_head;
1454 connection->submitted_msg_queue_head = send_buf;
1455 stream_send_data (long_poll->stream,
1456 (uint8_t *) send_buf->buf,
1457 send_buf->size);
1458 connection->long_poll_head = long_poll->next;
1459 if (NULL != long_poll->next)
1460 {
1461 long_poll->next->prev = NULL;
1462 }
1463 connection->long_poll_len -= 1;
1465 "rm long_poll, len = %lu\n",
1466 connection->long_poll_len);
1467 GNUNET_free (long_poll);
1468 long_poll = connection->long_poll_head;
1469 }
1470 }
1472}
1473
1474
1483static void
1484mq_destroy_d (struct GNUNET_MQ_Handle *mq, void *impl_state)
1485{
1486 struct Connection *connection = impl_state;
1488 "Default MQ destroyed\n");
1489 if (mq == connection->d_mq)
1490 {
1491 connection->d_mq = NULL;
1492 if (GNUNET_YES != connection->connection_destroy_called)
1493 connection_destroy (connection);
1494 }
1495}
1496
1497
1504static void
1505mq_cancel (struct GNUNET_MQ_Handle *mq, void *impl_state)
1506{
1507 /* Cancellation is impossible with QUIC; bail */
1508 GNUNET_assert (0);
1509}
1510
1511
1521static void
1522mq_error (void *cls, enum GNUNET_MQ_Error error)
1523{
1524 struct Connection *connection = cls;
1526 "MQ error in queue to %s: %d\n",
1527 GNUNET_i2s (&connection->target),
1528 (int) error);
1529 connection_destroy (connection);
1530}
1531
1532
1540static void
1542{
1544 "setup_connection_mq: init = %u\n",
1545 connection->is_initiator);
1546 size_t base_mtu;
1547
1548 switch (connection->address->sa_family)
1549 {
1550 case AF_INET:
1551 base_mtu = 1480 /* Ethernet MTU, 1500 - Ethernet header - VLAN tag */
1552 - sizeof(struct GNUNET_TUN_IPv4Header) /* 20 */
1553 - sizeof(struct GNUNET_TUN_UdpHeader) /* 8 */;
1554 break;
1555
1556 case AF_INET6:
1557 base_mtu = 1280 /* Minimum MTU required by IPv6 */
1558 - sizeof(struct GNUNET_TUN_IPv6Header) /* 40 */
1559 - sizeof(struct GNUNET_TUN_UdpHeader) /* 8 */;
1560 break;
1561
1562 default:
1563 GNUNET_assert (0);
1564 break;
1565 }
1566 /* MTU == base_mtu */
1567 connection->d_mtu = base_mtu;
1568
1569 if (NULL == connection->d_mq)
1571 &mq_destroy_d,
1572 &mq_cancel,
1573 connection,
1574 NULL,
1575 &mq_error,
1576 connection);
1577 connection->d_qh =
1579 &connection->target,
1580 connection->foreign_addr,
1581 1080,
1583 0, /* Priority */
1584 connection->nt,
1586 connection->d_mq);
1587}
1588
1589
1593static void
1594http_consume (struct Connection *connection, int64_t stream_id, size_t consumed)
1595{
1596 ngtcp2_conn_extend_max_stream_offset (connection->conn, stream_id, consumed);
1597 ngtcp2_conn_extend_max_offset (connection->conn, consumed);
1598}
1599
1600
1604static int
1605http_stream_close_cb (nghttp3_conn *conn, int64_t stream_id,
1606 uint64_t app_error_code, void *conn_user_data,
1607 void *stream_user_data)
1608{
1609 struct Connection *connection = conn_user_data;
1610
1611 remove_stream (connection, stream_id);
1613 "HTTP stream %lu closed\n",
1614 (unsigned long) stream_id);
1615 if (GNUNET_NO == connection->is_initiator &&
1616 ngtcp2_is_bidi_stream (stream_id))
1617 {
1618 ngtcp2_conn_extend_max_streams_bidi (connection->conn, 1);
1619 }
1620 else if (GNUNET_YES == connection->is_initiator &&
1621 ! ngtcp2_is_bidi_stream (stream_id))
1622 {
1623 ngtcp2_conn_extend_max_streams_uni (connection->conn, 1);
1624 }
1625
1626 return 0;
1627}
1628
1629
1633static int
1634http_recv_data_cb (nghttp3_conn *conn, int64_t stream_id, const uint8_t *data,
1635 size_t datalen, void *user_data, void *stream_user_data)
1636{
1638 "http_recv_data_cb\n");
1639 struct Connection *connection = user_data;
1640 struct GNUNET_PeerIdentity *pid;
1641 struct GNUNET_MessageHeader *hdr;
1642 int rv;
1643
1644 http_consume (connection, stream_id, datalen);
1645
1646 if (GNUNET_NO == connection->is_initiator &&
1647 GNUNET_NO == connection->id_rcvd)
1648 {
1649 if (datalen < sizeof (struct GNUNET_PeerIdentity))
1650 {
1652 "message recv len of %zd less than length of peer identity\n",
1653 datalen);
1654 return NGHTTP3_ERR_CALLBACK_FAILURE;
1655 }
1656 pid = (struct GNUNET_PeerIdentity *) data;
1657 connection->target = *pid;
1658 connection->id_rcvd = GNUNET_YES;
1659 setup_connection_mq (connection);
1660
1661 return GNUNET_NO;
1662 }
1663
1664 hdr = (struct GNUNET_MessageHeader *) data;
1666 &connection->target,
1667 hdr,
1669 NULL,
1670 NULL);
1671 if (GNUNET_SYSERR == rv)
1672 {
1674 "GNUNET_TRANSPORT_communicator_receive:%d, hdr->len = %u, datalen = %lu, init = %d\n",
1675 rv, ntohs (hdr->size), datalen, connection->is_initiator);
1676 return NGHTTP3_ERR_CALLBACK_FAILURE;
1677 }
1679 "GNUNET_TRANSPORT_communicator_receive:%d, hdr->len = %u, datalen = %lu, init = %d\n",
1680 rv, ntohs (hdr->size), datalen, connection->is_initiator);
1681 return 0;
1682}
1683
1684
1688static int
1689http_deferred_consume_cb (nghttp3_conn *conn, int64_t stream_id,
1690 size_t nconsumed, void *user_data,
1691 void *stream_user_data)
1692{
1693 struct Connection *connection = user_data;
1694 http_consume (connection, stream_id, nconsumed);
1695 return 0;
1696}
1697
1698
1702static int
1703http_begin_headers_cb (nghttp3_conn *conn, int64_t stream_id,
1704 void *user_data, void *stream_user_data)
1705{
1706 struct Connection *connection = user_data;
1707 struct Stream *stream;
1708
1709 stream = find_stream (connection, stream_id);
1710 if (NULL == stream)
1711 {
1712 return NGHTTP3_ERR_CALLBACK_FAILURE;
1713 }
1714 nghttp3_conn_set_stream_user_data (connection->h3_conn, stream_id, stream);
1715
1716 return 0;
1717}
1718
1719
1723static int
1724http_recv_header_cb (nghttp3_conn *conn, int64_t stream_id, int32_t token,
1725 nghttp3_rcbuf *name, nghttp3_rcbuf *value, uint8_t flags,
1726 void *user_data, void *stream_user_data)
1727{
1728 nghttp3_vec namebuf = nghttp3_rcbuf_get_buf (name);
1729 nghttp3_vec valbuf = nghttp3_rcbuf_get_buf (value);
1730 struct Connection *connection = user_data;
1731
1732 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "http header: [%.*s: %.*s]\n",
1733 (int) namebuf.len, namebuf.base,
1734 (int) valbuf.len, valbuf.base);
1735
1736 if (GNUNET_NO == connection->is_initiator)
1737 {
1738 struct Stream *stream = stream_user_data;
1739 switch (token)
1740 {
1741 case NGHTTP3_QPACK_TOKEN__PATH:
1742 stream->urilen = valbuf.len;
1743 stream->uri = (uint8_t *) malloc (valbuf.len);
1744 memcpy (stream->uri, valbuf.base, valbuf.len);
1745 break;
1746 case NGHTTP3_QPACK_TOKEN__METHOD:
1747 stream->methodlen = valbuf.len;
1748 stream->method = (uint8_t *) malloc (valbuf.len);
1749 memcpy (stream->method, valbuf.base, valbuf.len);
1750 break;
1751 case NGHTTP3_QPACK_TOKEN__AUTHORITY:
1752 stream->authoritylen = valbuf.len;
1753 stream->authority = (uint8_t *) malloc (valbuf.len);
1754 memcpy (stream->authority, valbuf.base, valbuf.len);
1755 break;
1756 }
1757 }
1758 return 0;
1759}
1760
1761
1765static int
1766http_stop_sending_cb (nghttp3_conn *conn, int64_t stream_id,
1767 uint64_t app_error_code, void *user_data,
1768 void *stream_user_data)
1769{
1770 struct Connection *connection = user_data;
1771 int rv;
1772
1773 rv = ngtcp2_conn_shutdown_stream_read (connection->conn,
1774 0,
1775 stream_id,
1776 app_error_code);
1777 if (0 != rv)
1778 {
1780 "ngtcp2_conn_shutdown_stream_read: %s\n",
1781 ngtcp2_strerror (rv));
1782 return NGHTTP3_ERR_CALLBACK_FAILURE;
1783 }
1784 return 0;
1785}
1786
1787
1791static int
1792http_end_stream_cb (nghttp3_conn *conn, int64_t stream_id, void *user_data,
1793 void *stream_user_data)
1794{
1795 struct Connection *connection = user_data;
1796 struct Stream *stream = stream_user_data;
1797 struct Long_Poll_Request *long_poll;
1798 int rv;
1799
1800 if (GNUNET_NO == connection->is_initiator)
1801 {
1802 // Send response
1803 rv = stream_start_response (connection, stream);
1804 if (0 != rv)
1805 {
1806 return NGHTTP3_ERR_CALLBACK_FAILURE;
1807 }
1808 }
1809 else
1810 {
1815 long_poll = connection->long_poll_head;
1816 while (NULL != long_poll)
1817 {
1818 if (stream_id == long_poll->stream->stream_id)
1819 {
1821 "client side recv GET response\n");
1822 stream = create_stream (connection, -1);
1823 rv = ngtcp2_conn_open_bidi_stream (connection->conn,
1825 if (0 != rv)
1826 {
1828 "ngtcp2_conn_open_bidi_stream: %s\n",
1829 ngtcp2_strerror (rv));
1830 }
1831 submit_get_request (connection, stream);
1832 long_poll->stream = stream;
1833 break;
1834 }
1835 long_poll = long_poll->next;
1836 }
1837 }
1838 return 0;
1839}
1840
1841
1845static int
1846http_reset_stream_cb (nghttp3_conn *conn, int64_t stream_id,
1847 uint64_t app_error_code, void *user_data,
1848 void *stream_user_data)
1849{
1850 struct Connection *connection = user_data;
1851 int rv;
1852
1853 rv = ngtcp2_conn_shutdown_stream_write (connection->conn,
1854 0,
1855 stream_id,
1856 app_error_code);
1857 if (0 != rv)
1858 {
1860 "ngtcp2_conn_shutdown_stream_write: %s\n",
1861 ngtcp2_strerror (rv));
1862 return NGHTTP3_ERR_CALLBACK_FAILURE;
1863 }
1864 return 0;
1865}
1866
1867
1875static int
1876setup_httpconn (struct Connection *connection)
1877{
1878 nghttp3_settings settings;
1879 const nghttp3_mem *mem = nghttp3_mem_default ();
1880 int64_t ctrl_stream_id;
1881 int64_t enc_stream_id;
1882 int64_t dec_stream_id;
1883 nghttp3_callbacks callbacks = {
1884 .stream_close = http_stream_close_cb,
1885 .recv_data = http_recv_data_cb,
1886 .deferred_consume = http_deferred_consume_cb,
1887 .begin_headers = http_begin_headers_cb,
1888 .recv_header = http_recv_header_cb,
1889 .stop_sending = http_stop_sending_cb,
1890 .end_stream = http_end_stream_cb,
1891 .reset_stream = http_reset_stream_cb,
1892 };
1893 int rv;
1894
1895 if (NULL != connection->h3_conn)
1896 {
1897 return GNUNET_NO;
1898 }
1899
1900 if (ngtcp2_conn_get_streams_uni_left (connection->conn) < 3)
1901 {
1903 "uni stream left less than 3\n");
1904 return GNUNET_SYSERR;
1905 }
1906
1907 if (GNUNET_YES == connection->is_initiator)
1908 {
1909 callbacks.begin_headers = NULL;
1910 // callbacks.end_stream = NULL;
1911 }
1912
1913 nghttp3_settings_default (&settings);
1914 settings.qpack_blocked_streams = 100;
1915 settings.qpack_encoder_max_dtable_capacity = 4096;
1916
1917 if (GNUNET_NO == connection->is_initiator)
1918 {
1919 const ngtcp2_transport_params *params =
1920 ngtcp2_conn_get_local_transport_params (connection->conn);
1921
1922 rv = nghttp3_conn_server_new (&connection->h3_conn,
1923 &callbacks,
1924 &settings,
1925 mem,
1926 connection);
1927 nghttp3_conn_set_max_client_streams_bidi (connection->h3_conn,
1928 params->initial_max_streams_bidi);
1929 if (0 != rv)
1930 {
1932 "nghttp3_conn_server_new: %s\n",
1933 nghttp3_strerror (rv));
1934 return GNUNET_SYSERR;
1935 }
1936 }
1937 else
1938 {
1939 rv = nghttp3_conn_client_new (&connection->h3_conn,
1940 &callbacks,
1941 &settings,
1942 mem,
1943 connection);
1944 if (0 != rv)
1945 {
1947 "nghttp3_conn_client_new: %s\n",
1948 nghttp3_strerror (rv));
1949 return GNUNET_SYSERR;
1950 }
1951 }
1952
1953 rv = ngtcp2_conn_open_uni_stream (connection->conn, &ctrl_stream_id, NULL);
1954 if (0 != rv)
1955 {
1957 "ngtcp2_conn_open_uni_stream: %s\n",
1958 ngtcp2_strerror (rv));
1959 return GNUNET_SYSERR;
1960 }
1961
1962 rv = nghttp3_conn_bind_control_stream (connection->h3_conn, ctrl_stream_id);
1963 if (0 != rv)
1964 {
1966 "nghttp3_conn_bind_control_stream: %s\n",
1967 nghttp3_strerror (rv));
1968 return GNUNET_SYSERR;
1969 }
1970
1971 rv = ngtcp2_conn_open_uni_stream (connection->conn, &enc_stream_id, NULL);
1972 if (0 != rv)
1973 {
1975 "ngtcp2_conn_open_uni_stream: %s\n",
1976 ngtcp2_strerror (rv));
1977 return GNUNET_SYSERR;
1978 }
1979
1980 rv = ngtcp2_conn_open_uni_stream (connection->conn, &dec_stream_id, NULL);
1981 if (0 != rv)
1982 {
1984 "ngtcp2_conn_open_uni_stream: %s\n",
1985 ngtcp2_strerror (rv));
1986 return GNUNET_SYSERR;
1987 }
1988
1989 rv = nghttp3_conn_bind_qpack_streams (connection->h3_conn,
1990 enc_stream_id, dec_stream_id);
1991 if (0 != rv)
1992 {
1994 "nghttp3_conn_bind_qpack_streams: %s\n",
1995 nghttp3_strerror (rv));
1996 return GNUNET_SYSERR;
1997 }
1998
2000 "Bind control stream: %"PRIi64", enc stream: %"PRIi64", dec stream: %"PRIi64"\n",
2001 ctrl_stream_id, enc_stream_id, dec_stream_id);
2002 return GNUNET_NO;
2003}
2004
2005
2009static void
2010rand_cb (uint8_t *dest,
2011 size_t destlen,
2012 const ngtcp2_rand_ctx *rand_ctx)
2013{
2014 (void) rand_ctx;
2016 dest,
2017 destlen);
2018}
2019
2020
2024static int
2025get_new_connection_id_cb (ngtcp2_conn *conn, ngtcp2_cid *cid,
2026 uint8_t *token, size_t cidlen,
2027 void *user_data)
2028{
2029 (void) conn;
2030 (void) user_data;
2031
2033 cid->data,
2034 cidlen);
2035 cid->datalen = cidlen;
2037 token,
2038 NGTCP2_STATELESS_RESET_TOKENLEN);
2039 return GNUNET_NO;
2040}
2041
2042
2046static int
2047recv_stream_data_cb (ngtcp2_conn *conn, uint32_t flags, int64_t stream_id,
2048 uint64_t offset, const uint8_t *data, size_t datalen,
2049 void *user_data,
2050 void *stream_user_data)
2051{
2052 struct Connection *connection = user_data;
2053 nghttp3_ssize nconsumed;
2054
2055 if (NULL == connection->h3_conn)
2056 {
2057 return 0;
2058 }
2059 nconsumed = nghttp3_conn_read_stream (connection->h3_conn, stream_id,
2060 data, datalen,
2061 flags & NGTCP2_STREAM_DATA_FLAG_FIN);
2062 if (nconsumed < 0)
2063 {
2065 "nghttp3_conn_read_stream: %s, init = %d\n",
2066 nghttp3_strerror (nconsumed), connection->is_initiator);
2067 ngtcp2_ccerr_set_application_error (
2068 &connection->last_error,
2069 nghttp3_err_infer_quic_app_error_code (nconsumed),
2070 NULL, 0);
2071 return NGTCP2_ERR_CALLBACK_FAILURE;
2072 }
2073 http_consume (connection, stream_id, nconsumed);
2074 return 0;
2075}
2076
2077
2081static int
2082stream_open_cb (ngtcp2_conn *conn, int64_t stream_id, void *user_data)
2083{
2084 struct Connection *connection = user_data;
2085 if (! ngtcp2_is_bidi_stream (stream_id))
2086 {
2087 return 0;
2088 }
2089 create_stream (connection, stream_id);
2090 return 0;
2091}
2092
2093
2099static int
2100stream_close_cb (ngtcp2_conn *conn, uint32_t flags, int64_t stream_id,
2101 uint64_t app_error_code, void *user_data,
2102 void *stream_user_data)
2103{
2105 "stream_close id = %"PRIi64"\n",
2106 stream_id);
2107 struct Connection *connection = user_data;
2108 int rv;
2109
2110 if (! (flags & NGTCP2_STREAM_CLOSE_FLAG_APP_ERROR_CODE_SET))
2111 {
2112 app_error_code = NGHTTP3_H3_NO_ERROR;
2113 }
2114
2115 if (connection->h3_conn)
2116 {
2117 if (0 == app_error_code)
2118 {
2119 app_error_code = NGHTTP3_H3_NO_ERROR;
2120 }
2121
2122 rv = nghttp3_conn_close_stream (connection->h3_conn,
2123 stream_id,
2124 app_error_code);
2125 switch (rv)
2126 {
2127 case 0:
2128 break;
2129 case NGHTTP3_ERR_STREAM_NOT_FOUND:
2130 if (GNUNET_NO == connection->is_initiator &&
2131 ngtcp2_is_bidi_stream (stream_id))
2132 {
2133 ngtcp2_conn_extend_max_streams_bidi (connection->conn, 1);
2134 }
2135 else if (GNUNET_YES == connection->is_initiator &&
2136 ! ngtcp2_is_bidi_stream (stream_id))
2137 {
2138 ngtcp2_conn_extend_max_streams_uni (connection->conn, 1);
2139 }
2140 break;
2141 default:
2143 "nghttp3_conn_close_stream: %s\n",
2144 nghttp3_strerror (rv));
2145 ngtcp2_ccerr_set_application_error (
2146 &connection->last_error,
2147 nghttp3_err_infer_quic_app_error_code (rv),
2148 NULL, 0);
2149 return NGTCP2_ERR_CALLBACK_FAILURE;
2150 }
2151 }
2152 return 0;
2153}
2154
2155
2159static int
2160acked_stream_data_offset_cb (ngtcp2_conn *conn, int64_t stream_id,
2161 uint64_t offset, uint64_t datalen, void *user_data,
2162 void *stream_user_data)
2163{
2164 struct Connection *connection = user_data;
2165 int rv;
2166
2167 if (NULL == connection->h3_conn)
2168 {
2169 return 0;
2170 }
2171
2172 rv = nghttp3_conn_add_ack_offset (connection->h3_conn, stream_id, datalen);
2173 if (0 != rv)
2174 {
2176 "nghttp3_conn_add_ack_offset: %s\n",
2177 nghttp3_strerror (rv));
2178 return NGTCP2_ERR_CALLBACK_FAILURE;
2179 }
2180 return 0;
2181}
2182
2183
2187static int
2188extend_max_stream_data_cb (ngtcp2_conn *conn, int64_t stream_id,
2189 uint64_t max_data, void *user_data,
2190 void *stream_user_data)
2191{
2192 struct Connection *connection = user_data;
2193 int rv;
2194
2195 rv = nghttp3_conn_unblock_stream (connection->h3_conn, stream_id);
2196 if (0 != rv)
2197 {
2199 "nghttp3_conn_unblock_stream: %s\n",
2200 nghttp3_strerror (rv));
2201 return NGTCP2_ERR_CALLBACK_FAILURE;
2202 }
2203 return 0;
2204}
2205
2206
2210static int
2211stream_reset_cb (ngtcp2_conn *conn, int64_t stream_id, uint64_t final_size,
2212 uint64_t app_error_code, void *user_data,
2213 void *stream_user_data)
2214{
2215 struct Connection *connection = user_data;
2216 int rv;
2217
2218 if (connection->h3_conn)
2219 {
2220 rv = nghttp3_conn_shutdown_stream_read (connection->h3_conn, stream_id);
2221 if (0 != rv)
2222 {
2224 "nghttp3_conn_shutdown_stream_read: %s\n",
2225 nghttp3_strerror (rv));
2226 return NGTCP2_ERR_CALLBACK_FAILURE;
2227 }
2228 }
2229 return 0;
2230}
2231
2232
2236static int
2237extend_max_remote_streams_bidi_cb (ngtcp2_conn *conn, uint64_t max_streams,
2238 void *user_data)
2239{
2240 struct Connection *connection = user_data;
2241 if (NULL == connection->h3_conn)
2242 {
2243 return 0;
2244 }
2245 nghttp3_conn_set_max_client_streams_bidi (connection->h3_conn, max_streams);
2246 return 0;
2247}
2248
2249
2253static int
2254stream_stop_sending_cb (ngtcp2_conn *conn, int64_t stream_id,
2255 uint64_t app_error_code, void *user_data,
2256 void *stream_user_data)
2257{
2258 struct Connection *connection = user_data;
2259 int rv;
2260
2261 if (connection->h3_conn)
2262 {
2263 rv = nghttp3_conn_shutdown_stream_read (connection->h3_conn, stream_id);
2264 if (0 != rv)
2265 {
2267 "nghttp3_conn_shutdown_stream_read: %s\n",
2268 nghttp3_strerror (rv));
2269 return NGTCP2_ERR_CALLBACK_FAILURE;
2270 }
2271 }
2272 return 0;
2273}
2274
2275
2279static int
2280recv_tx_key_cb (ngtcp2_conn *conn, ngtcp2_encryption_level level,
2281 void *user_data)
2282{
2283 if (NGTCP2_ENCRYPTION_LEVEL_1RTT != level)
2284 {
2285 return 0;
2286 }
2287
2288 struct Connection *connection = user_data;
2289 int rv;
2290
2291 rv = setup_httpconn (connection);
2292 if (0 != rv)
2293 {
2294 return NGTCP2_ERR_CALLBACK_FAILURE;
2295 }
2296 return 0;
2297}
2298
2299
2303static int
2304recv_rx_key_cb (ngtcp2_conn *conn, ngtcp2_encryption_level level,
2305 void *user_data)
2306{
2307 if (NGTCP2_ENCRYPTION_LEVEL_1RTT != level)
2308 {
2309 return 0;
2310 }
2311
2312 struct Connection *connection = user_data;
2313 struct Stream *stream;
2314 struct Long_Poll_Request *long_poll;
2315 int i;
2316 int rv;
2317
2318 rv = setup_httpconn (connection);
2319 if (0 != rv)
2320 {
2321 return NGTCP2_ERR_CALLBACK_FAILURE;
2322 }
2323
2324 if (GNUNET_YES == connection->is_initiator &&
2325 GNUNET_NO == connection->id_sent)
2326 {
2327 stream = create_stream (connection, -1);
2328 rv = ngtcp2_conn_open_bidi_stream (conn, &stream->stream_id, NULL);
2329
2330 submit_post_request (connection, stream,
2331 (uint8_t *) &my_identity,
2332 sizeof (my_identity));
2333
2334 connection->id_sent = GNUNET_YES;
2335 setup_connection_mq (connection);
2336
2337 for (i = 0; i < NUM_LONG_POLL; i++)
2338 {
2339 stream = create_stream (connection, -1);
2340 rv = ngtcp2_conn_open_bidi_stream (conn, &stream->stream_id, NULL);
2341 submit_get_request (connection, stream);
2342 long_poll = GNUNET_new (struct Long_Poll_Request);
2343 long_poll->stream = stream;
2344 long_poll->next = NULL;
2345 long_poll->prev = connection->long_poll_rear;
2346 long_poll->timer = NULL;
2347 if (NULL != connection->long_poll_rear)
2348 {
2349 connection->long_poll_rear->next = long_poll;
2350 }
2351 connection->long_poll_rear = long_poll;
2352 if (NULL == connection->long_poll_head)
2353 {
2354 connection->long_poll_head = long_poll;
2355 }
2356 }
2357 }
2358 return 0;
2359}
2360
2361
2374static int
2375client_quic_init (struct Connection *connection,
2376 struct sockaddr *local_addr,
2377 socklen_t local_addrlen,
2378 struct sockaddr *remote_addr,
2379 socklen_t remote_addrlen)
2380{
2381 int rv;
2382 ngtcp2_cid dcid;
2383 ngtcp2_cid scid;
2384 ngtcp2_settings settings;
2385 ngtcp2_transport_params params;
2386 ngtcp2_path path = {
2387 {local_addr, local_addrlen},
2388 {remote_addr, remote_addrlen},
2389 NULL,
2390 };
2391 ngtcp2_callbacks callbacks = {
2392 .client_initial = ngtcp2_crypto_client_initial_cb,
2393 .recv_crypto_data = ngtcp2_crypto_recv_crypto_data_cb,
2394 .encrypt = ngtcp2_crypto_encrypt_cb,
2395 .decrypt = ngtcp2_crypto_decrypt_cb,
2396 .hp_mask = ngtcp2_crypto_hp_mask_cb,
2397 .recv_retry = ngtcp2_crypto_recv_retry_cb,
2398 .update_key = ngtcp2_crypto_update_key_cb,
2399 .delete_crypto_aead_ctx = ngtcp2_crypto_delete_crypto_aead_ctx_cb,
2400 .delete_crypto_cipher_ctx = ngtcp2_crypto_delete_crypto_cipher_ctx_cb,
2401 .get_path_challenge_data = ngtcp2_crypto_get_path_challenge_data_cb,
2402 .version_negotiation = ngtcp2_crypto_version_negotiation_cb,
2403 .rand = rand_cb,
2404 .get_new_connection_id = get_new_connection_id_cb,
2405 .recv_stream_data = recv_stream_data_cb,
2406 .stream_close = stream_close_cb,
2407 .acked_stream_data_offset = acked_stream_data_offset_cb,
2408 .extend_max_stream_data = extend_max_stream_data_cb,
2409 .stream_reset = stream_reset_cb,
2410 .stream_stop_sending = stream_stop_sending_cb,
2411 .recv_rx_key = recv_rx_key_cb,
2412 };
2413
2414
2415 scid.datalen = NGTCP2_MAX_CIDLEN;
2417 scid.data,
2418 scid.datalen);
2419 dcid.datalen = NGTCP2_MAX_CIDLEN;
2421 dcid.data,
2422 dcid.datalen);
2423 ngtcp2_settings_default (&settings);
2424 settings.initial_ts = timestamp ();
2425
2426 ngtcp2_transport_params_default (&params);
2427 params.initial_max_streams_uni = 100;
2428 params.initial_max_stream_data_bidi_local = 6291456;
2429 params.initial_max_data = 15728640;
2430 params.initial_max_stream_data_bidi_remote = 0;
2431 params.initial_max_stream_data_uni = 6291456;
2432 params.initial_max_streams_bidi = 0;
2433 params.max_idle_timeout = 30 * NGTCP2_SECONDS;
2434 params.active_connection_id_limit = 7;
2435 params.grease_quic_bit = 1;
2436 rv = ngtcp2_conn_client_new (&connection->conn,
2437 &dcid,
2438 &scid,
2439 &path,
2440 NGTCP2_PROTO_VER_V1,
2441 &callbacks,
2442 &settings,
2443 &params,
2444 NULL,
2445 connection);
2446 if (GNUNET_NO != rv)
2447 {
2449 "ngtcp2_conn_client_new: %s\n",
2450 ngtcp2_strerror (rv));
2451 return GNUNET_SYSERR;
2452 }
2453 ngtcp2_conn_set_tls_native_handle (connection->conn, connection->session);
2454 connection->conn_ref.user_data = connection;
2455 connection->conn_ref.get_conn = get_conn;
2456 return GNUNET_NO;
2457}
2458
2459
2465static void
2466close_waitcb (void *cls)
2467{
2468 struct Connection *connection = cls;
2469 connection->timer = NULL;
2470
2471 if (ngtcp2_conn_in_closing_period (connection->conn))
2472 {
2474 "Closing period over\n");
2475 connection_destroy (connection);
2476 return;
2477 }
2478 if (ngtcp2_conn_in_draining_period (connection->conn))
2479 {
2481 "Draining period over\n");
2482 connection_destroy (connection);
2483 return;
2484 }
2485}
2486
2487
2493static void
2495{
2496 ngtcp2_duration pto;
2497 struct GNUNET_TIME_Relative delay;
2498
2499 if (NULL != connection->timer)
2500 {
2501 GNUNET_SCHEDULER_cancel (connection->timer);
2502 connection->timer = NULL;
2503 }
2504 pto = ngtcp2_conn_get_pto (connection->conn);
2506 pto / 1000ULL * 3);
2507 connection->timer = GNUNET_SCHEDULER_add_delayed (delay,
2509 connection);
2511 "Start draining period\n");
2512}
2513
2514
2525static int
2527{
2528 ngtcp2_path_storage ps;
2529 ngtcp2_pkt_info pi;
2530 ngtcp2_ssize nwrite;
2531 ngtcp2_duration pto;
2532 struct GNUNET_TIME_Relative delay;
2533
2534 if (NULL == connection->conn ||
2535 ngtcp2_conn_in_closing_period (connection->conn) ||
2536 ngtcp2_conn_in_draining_period (connection->conn))
2537 {
2538 return GNUNET_NO;
2539 }
2540
2542 "Start closing period\n");
2543
2544 if (GNUNET_NO == connection->is_initiator)
2545 {
2546 if (NULL != connection->timer)
2547 {
2548 GNUNET_SCHEDULER_cancel (connection->timer);
2549 connection->timer = NULL;
2550 }
2551 pto = ngtcp2_conn_get_pto (connection->conn);
2553 pto / 1000ULL * 3);
2554 connection->timer = GNUNET_SCHEDULER_add_delayed (delay,
2556 connection);
2557 }
2558
2559 connection->conn_closebuf =
2560 GNUNET_new_array (NGTCP2_MAX_UDP_PAYLOAD_SIZE, uint8_t);
2561
2562 ngtcp2_path_storage_zero (&ps);
2563 nwrite = ngtcp2_conn_write_connection_close (connection->conn,
2564 &ps.path,
2565 &pi,
2566 connection->conn_closebuf,
2567 NGTCP2_MAX_UDP_PAYLOAD_SIZE,
2568 &connection->last_error,
2569 timestamp ());
2570 if (nwrite < 0)
2571 {
2573 "ngtcp2_conn_write_connection_close: %s\n",
2574 ngtcp2_strerror (nwrite));
2575 return GNUNET_SYSERR;
2576 }
2577 if (0 == nwrite)
2578 {
2579 return GNUNET_NO;
2580 }
2581 connection->conn_closebuflen = nwrite;
2582 if (GNUNET_YES == connection->is_initiator)
2583 {
2584 return send_packet (connection,
2585 connection->conn_closebuf,
2586 connection->conn_closebuflen);
2587 }
2588 return GNUNET_NO;
2589}
2590
2591
2598static int
2599send_conn_close (struct Connection *connection)
2600{
2601 int rv;
2602
2604 "Closing period, send CONNECTION_CLOSE\n");
2605 rv = send_packet (connection,
2606 connection->conn_closebuf,
2607 connection->conn_closebuflen);
2608 return rv;
2609}
2610
2611
2619static int
2620handle_error (struct Connection *connection)
2621{
2622 int rv;
2623
2624 /* if we are the client side */
2625 if (GNUNET_YES == connection->is_initiator)
2626 {
2627 /* this will send CONNECTION_CLOSE immedietly and don't wait */
2628 start_closing_period (connection);
2629 connection_destroy (connection);
2630 return GNUNET_SYSERR;
2631 }
2632
2633 if (NGTCP2_CCERR_TYPE_IDLE_CLOSE == connection->last_error.type)
2634 {
2635 return GNUNET_SYSERR;
2636 }
2637
2638 if (GNUNET_NO != start_closing_period (connection))
2639 {
2640 return GNUNET_SYSERR;
2641 }
2642
2643 if (ngtcp2_conn_in_draining_period (connection->conn))
2644 {
2646 }
2647
2648 rv = send_conn_close (connection);
2649 if (NETWORK_ERR_OK != rv)
2650 {
2651 return rv;
2652 }
2653
2655}
2656
2657
2664static int
2665handle_expiry (struct Connection *connection)
2666{
2667 int rv;
2668
2669 rv = ngtcp2_conn_handle_expiry (connection->conn, timestamp ());
2670 if (0 != rv)
2671 {
2673 "ngtcp2_conn_handle_expiry: %s\n",
2674 ngtcp2_strerror (rv));
2675 ngtcp2_ccerr_set_liberr (&connection->last_error, rv, NULL, 0);
2676 return handle_error (connection);
2677 }
2678 return GNUNET_NO;
2679}
2680
2681
2687static void
2688timeoutcb (void *cls)
2689{
2691 "timeoutcb func called!\n");
2692 struct Connection *connection = cls;
2693 connection->timer = NULL;
2694 int rv;
2695
2696 rv = handle_expiry (connection);
2697 if (GNUNET_NO != rv)
2698 {
2699 if (GNUNET_YES == connection->is_initiator)
2700 {
2701 return;
2702 }
2703 switch (rv)
2704 {
2706 return;
2707 default:
2708 connection_destroy (connection);
2709 return;
2710 }
2711 }
2712
2713 rv = connection_write (connection);
2714 if (GNUNET_YES == connection->is_initiator)
2715 {
2716 return;
2717 }
2718 if (GNUNET_NO != rv)
2719 {
2720 switch (rv)
2721 {
2723 return;
2724 default:
2725 connection_destroy (connection);
2726 return;
2727 }
2728
2729 }
2730}
2731
2732
2738static void
2740{
2742 "update_timer!\n");
2743 ngtcp2_tstamp expiry;
2744 ngtcp2_tstamp now;
2745 struct GNUNET_TIME_Relative delay;
2746
2747 expiry = ngtcp2_conn_get_expiry (connection->conn);
2748 now = timestamp ();
2749
2750 if (NULL != connection->timer)
2751 {
2752 GNUNET_SCHEDULER_cancel (connection->timer);
2753 connection->timer = NULL;
2754 }
2755 if (now >= expiry)
2756 {
2758 "Timer has expired\n");
2759 connection->timer = GNUNET_SCHEDULER_add_now (timeoutcb, connection);
2760 return;
2761 }
2762
2764 "Timer set: %lf\n",
2765 (double) (expiry - now) / NGTCP2_SECONDS);
2766 /* ngtcp2_tstamp is nanosecond */
2768 (expiry - now) / 1000ULL + 1);
2769 connection->timer = GNUNET_SCHEDULER_add_delayed (delay, timeoutcb,
2770 connection);
2771}
2772
2773
2781static int
2783{
2784 uint8_t buf[1280];
2785 ngtcp2_tstamp ts = timestamp ();
2786 ngtcp2_path_storage ps;
2787 int64_t stream_id;
2788 uint32_t flags;
2789 ngtcp2_ssize nwrite;
2790 ngtcp2_ssize wdatalen;
2791 nghttp3_vec vec[16];
2792 nghttp3_ssize sveccnt;
2793 ngtcp2_pkt_info pi;
2794 int fin;
2795 int rv;
2796
2797 ngtcp2_path_storage_zero (&ps);
2798
2799 for (;;)
2800 {
2801 stream_id = -1;
2802 fin = 0;
2803 sveccnt = 0;
2804
2805 if (connection->h3_conn &&
2806 ngtcp2_conn_get_max_data_left (connection->conn))
2807 {
2808 sveccnt = nghttp3_conn_writev_stream (connection->h3_conn,
2809 &stream_id,
2810 &fin,
2811 vec,
2812 16);
2813 if (sveccnt < 0)
2814 {
2816 "nghttp3_conn_writev_stream: %s\n",
2817 nghttp3_strerror (sveccnt));
2818
2819 ngtcp2_ccerr_set_application_error (
2820 &connection->last_error,
2821 nghttp3_err_infer_quic_app_error_code (sveccnt),
2822 NULL,
2823 0);
2824 return handle_error (connection);
2825 }
2826 }
2827
2828 flags = NGTCP2_WRITE_STREAM_FLAG_MORE;
2829 if (fin)
2830 flags |= NGTCP2_WRITE_STREAM_FLAG_FIN;
2831
2832 nwrite = ngtcp2_conn_writev_stream (connection->conn,
2833 &ps.path,
2834 &pi,
2835 buf,
2836 sizeof(buf),
2837 &wdatalen,
2838 flags,
2839 stream_id,
2840 (ngtcp2_vec *) vec,
2841 (size_t) sveccnt,
2842 ts);
2843 if (nwrite < 0)
2844 {
2845 switch (nwrite)
2846 {
2847 case NGTCP2_ERR_STREAM_DATA_BLOCKED:
2848 nghttp3_conn_block_stream (connection->h3_conn, stream_id);
2849 continue;
2850 case NGTCP2_ERR_STREAM_SHUT_WR:
2851 nghttp3_conn_shutdown_stream_write (connection->h3_conn, stream_id);
2852 continue;
2853 case NGTCP2_ERR_WRITE_MORE:
2854 rv = nghttp3_conn_add_write_offset (connection->h3_conn, stream_id,
2855 wdatalen);
2856 if (0 != rv)
2857 {
2859 "nghttp3_conn_add_write_offset: %s\n",
2860 nghttp3_strerror (rv));
2861 ngtcp2_ccerr_set_application_error (
2862 &connection->last_error,
2863 nghttp3_err_infer_quic_app_error_code (rv),
2864 NULL, 0);
2865 return handle_error (connection);
2866 }
2867 continue;
2868 }
2870 "ngtcp2_conn_writev_stream: %s\n",
2871 ngtcp2_strerror (nwrite));
2872 ngtcp2_ccerr_set_liberr (&connection->last_error,
2873 nwrite,
2874 NULL,
2875 0);
2876 return handle_error (connection);
2877 }
2878 if (0 == nwrite)
2879 {
2880 ngtcp2_conn_update_pkt_tx_time (connection->conn, ts);
2881 return 0;
2882 }
2883 if (wdatalen > 0)
2884 {
2885 rv = nghttp3_conn_add_write_offset (connection->h3_conn, stream_id,
2886 wdatalen);
2887 if (0 != rv)
2888 {
2890 "nghttp3_conn_add_write_offset: %s\n",
2891 nghttp3_strerror (rv));
2892 ngtcp2_ccerr_set_application_error (
2893 &connection->last_error,
2894 nghttp3_err_infer_quic_app_error_code (rv),
2895 NULL, 0);
2896 return handle_error (connection);
2897 }
2898 }
2899 if (GNUNET_NO != send_packet (connection, buf, nwrite))
2900 break;
2901 }
2902
2903 return GNUNET_NO;
2904}
2905
2906
2914static int
2915connection_write (struct Connection *connection)
2916{
2917 int rv;
2918
2919 if (GNUNET_NO == connection->is_initiator &&
2920 (ngtcp2_conn_in_closing_period (connection->conn) ||
2921 ngtcp2_conn_in_draining_period (connection->conn)))
2922 {
2923 return GNUNET_NO;
2924 }
2925
2926 rv = connection_write_streams (connection);
2927 if (GNUNET_NO != rv)
2928 {
2929 return rv;
2930 }
2931 connection_update_timer (connection);
2932
2933 return GNUNET_NO;
2934}
2935
2936
2955static int
2956mq_init (void *cls,
2957 const struct GNUNET_PeerIdentity *peer_id,
2958 const char *address)
2959{
2960 struct Connection *connection;
2961 struct sockaddr *local_addr;
2962 socklen_t local_addrlen;
2963 struct sockaddr *remote_addr;
2964 socklen_t remote_addrlen;
2965 const char *path;
2966 char *bindto;
2967 struct GNUNET_HashCode remote_addr_key;
2968 int rv;
2969
2970 if (GNUNET_OK !=
2973 "BINDTO",
2974 &bindto))
2975 {
2978 "BINDTO");
2979 return GNUNET_SYSERR;
2980 }
2981 local_addr = udp_address_to_sockaddr (bindto, &local_addrlen);
2982 if (0 != strncmp (address,
2984 strlen (COMMUNICATOR_ADDRESS_PREFIX "-")))
2985 {
2986 GNUNET_break_op (0);
2987 return GNUNET_SYSERR;
2988 }
2989 path = &address[strlen (COMMUNICATOR_ADDRESS_PREFIX "-")];
2990 remote_addr = udp_address_to_sockaddr (path, &remote_addrlen);
2991
2992 GNUNET_CRYPTO_hash (address, strlen (address), &remote_addr_key);
2993 connection = GNUNET_CONTAINER_multihashmap_get (addr_map, &remote_addr_key);
2994 if (NULL != connection)
2995 {
2997 "receiver %s already exist or is being connected to\n",
2998 address);
2999 return GNUNET_SYSERR;
3000 }
3001
3002 /* Create a new connection */
3003 connection = GNUNET_new (struct Connection);
3004 connection->address = remote_addr;
3005 connection->address_len = remote_addrlen;
3006 connection->target = *peer_id;
3007 connection->is_initiator = GNUNET_YES;
3008 connection->id_rcvd = GNUNET_YES;
3009 connection->id_sent = GNUNET_NO;
3010 connection->foreign_addr =
3011 sockaddr_to_udpaddr_string (connection->address, connection->address_len);
3012 connection->nt = GNUNET_NT_scanner_get_type (is,
3014 remote_addrlen);
3015 connection->timeout =
3019 &remote_addr_key,
3020 connection,
3023 "# connections active",
3025 GNUNET_NO);
3026
3027 /* client_gnutls_init */
3028 rv = client_gnutls_init (connection);
3029 if (GNUNET_NO != rv)
3030 {
3031 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "client_gnutls_init failed\n");
3032 return GNUNET_SYSERR;
3033 }
3034
3035 /* client_quic_init */
3036 rv = client_quic_init (connection,
3037 local_addr, local_addrlen,
3038 remote_addr, remote_addrlen);
3039 if (GNUNET_NO != rv)
3040 {
3041 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "client_quic_init failed\n");
3042 return GNUNET_SYSERR;
3043 }
3044
3045 ngtcp2_conn_set_tls_native_handle (connection->conn, connection->session);
3046
3047 rv = connection_write (connection);
3048 if (GNUNET_NO != rv)
3049 {
3051 "connection_write failed\n");
3052 return GNUNET_SYSERR;
3053 }
3055 return GNUNET_OK;
3056}
3057
3058
3072static void
3074 void **app_ctx,
3075 int add_remove,
3077 const struct sockaddr *addr,
3078 socklen_t addrlen)
3079{
3080 char *my_addr;
3082
3083 if (GNUNET_YES == add_remove)
3084 {
3086
3087 GNUNET_asprintf (&my_addr,
3088 "%s-%s",
3090 GNUNET_a2s (addr, addrlen));
3091 nt = GNUNET_NT_scanner_get_type (is, addr, addrlen);
3092 ai =
3094 my_addr,
3095 nt,
3097 GNUNET_free (my_addr);
3098 *app_ctx = ai;
3099 }
3100 else
3101 {
3102 ai = *app_ctx;
3104 *app_ctx = NULL;
3105 }
3106}
3107
3108
3117static int
3119 const struct GNUNET_HashCode *key,
3120 void *value)
3121{
3122 struct Connection *connection = value;
3123 (void) cls;
3124 (void) key;
3125 handle_error (connection);
3126 connection_destroy (connection);
3127 return GNUNET_OK;
3128}
3129
3130
3136static void
3137do_shutdown (void *cls)
3138{
3140 "do_shutdown start\n");
3143 NULL);
3145 gnutls_certificate_free_credentials (cred);
3146
3147 if (NULL != nat)
3148 {
3150 nat = NULL;
3151 }
3152 if (NULL != read_task)
3153 {
3155 read_task = NULL;
3156 }
3157 if (NULL != udp_sock)
3158 {
3161 udp_sock = NULL;
3162 }
3163 if (NULL != ch)
3164 {
3166 ch = NULL;
3167 }
3168 if (NULL != stats)
3169 {
3171 stats = NULL;
3172 }
3173 if (NULL != my_private_key)
3174 {
3176 my_private_key = NULL;
3177 }
3178 if (NULL != is)
3179 {
3181 is = NULL;
3182 }
3184 "do_shutdown finished\n");
3185}
3186
3187
3202static int
3204 struct sockaddr *local_addr, socklen_t local_addrlen,
3205 struct sockaddr *remote_addr, socklen_t remote_addrlen,
3206 const ngtcp2_pkt_info *pi,
3207 const uint8_t *data, size_t datalen)
3208{
3209 ngtcp2_path path;
3210 int rv;
3211
3212 path.local.addr = local_addr;
3213 path.local.addrlen = local_addrlen;
3214 path.remote.addr = remote_addr;
3215 path.remote.addrlen = remote_addrlen;
3216
3217 rv = ngtcp2_conn_read_pkt (connection->conn, &path, pi, data, datalen,
3218 timestamp ());
3219 if (0 != rv)
3220 {
3222 "ngtcp2_conn_read_pkt: %s\n",
3223 ngtcp2_strerror (rv));
3224 switch (rv)
3225 {
3226 case NGTCP2_ERR_DRAINING:
3227 if (GNUNET_NO == connection->is_initiator)
3228 {
3229 start_draining_period (connection);
3231 }
3232 else
3233 {
3234 ngtcp2_ccerr_set_liberr (&connection->last_error, rv, NULL, 0);
3235 }
3236 case NGTCP2_ERR_RETRY:
3237 /* client side doesn't get this */
3238 return NETWORK_ERR_RETRY;
3239 case NGTCP2_ERR_DROP_CONN:
3240 /* client side doesn't get this */
3241 return NETWORK_ERR_DROP_CONN;
3242 case NGTCP2_ERR_CRYPTO:
3243 if (! connection->last_error.error_code)
3244 {
3245 ngtcp2_ccerr_set_tls_alert (
3246 &connection->last_error,
3247 ngtcp2_conn_get_tls_alert (connection->conn),
3248 NULL, 0);
3249 }
3250 break;
3251 default:
3252 if (! connection->last_error.error_code)
3253 {
3254 ngtcp2_ccerr_set_liberr (&connection->last_error, rv, NULL, 0);
3255 }
3256 }
3257 return handle_error (connection);
3258 }
3259 return GNUNET_NO;
3260}
3261
3262
3278static int
3279connection_on_read (struct Connection *connection,
3280 struct sockaddr *local_addr, socklen_t local_addrlen,
3281 struct sockaddr *remote_addr, socklen_t remote_addrlen,
3282 const ngtcp2_pkt_info *pi,
3283 const uint8_t *data, size_t datalen)
3284{
3285 int rv;
3286 rv = connection_feed_data (connection, local_addr, local_addrlen, remote_addr,
3287 remote_addrlen, pi, data, datalen);
3288 if (GNUNET_NO != rv)
3289 {
3290 return rv;
3291 }
3292
3293 connection_update_timer (connection);
3294 return GNUNET_NO;
3295}
3296
3297
3311static struct Connection *
3312connection_init (struct sockaddr *local_addr,
3313 socklen_t local_addrlen,
3314 struct sockaddr *remote_addr,
3315 socklen_t remote_addrlen,
3316 const ngtcp2_cid *dcid, const ngtcp2_cid *scid,
3317 uint32_t version)
3318{
3319 struct Connection *new_connection;
3320 ngtcp2_path path;
3321 ngtcp2_transport_params params;
3322 ngtcp2_cid scid_;
3323 ngtcp2_conn *conn = NULL;
3324 ngtcp2_settings settings;
3325 ngtcp2_callbacks callbacks = {
3326 .recv_client_initial = ngtcp2_crypto_recv_client_initial_cb,
3327 .recv_crypto_data = ngtcp2_crypto_recv_crypto_data_cb,
3328 .encrypt = ngtcp2_crypto_encrypt_cb,
3329 .decrypt = ngtcp2_crypto_decrypt_cb,
3330 .hp_mask = ngtcp2_crypto_hp_mask_cb,
3331 .update_key = ngtcp2_crypto_update_key_cb,
3332 .delete_crypto_aead_ctx = ngtcp2_crypto_delete_crypto_aead_ctx_cb,
3333 .delete_crypto_cipher_ctx = ngtcp2_crypto_delete_crypto_cipher_ctx_cb,
3334 .get_path_challenge_data = ngtcp2_crypto_get_path_challenge_data_cb,
3335 .version_negotiation = ngtcp2_crypto_version_negotiation_cb,
3336
3337 .acked_stream_data_offset = acked_stream_data_offset_cb,
3338 .recv_stream_data = recv_stream_data_cb,
3339 .stream_open = stream_open_cb,
3340 .rand = rand_cb,
3341 .get_new_connection_id = get_new_connection_id_cb,
3342 .stream_close = stream_close_cb,
3343 .extend_max_remote_streams_bidi = extend_max_remote_streams_bidi_cb,
3344 .stream_stop_sending = stream_stop_sending_cb,
3345 .extend_max_stream_data = extend_max_stream_data_cb,
3346 .recv_tx_key = recv_tx_key_cb,
3347 };
3348
3349
3350 int rv;
3351
3352 path.local.addr = local_addr;
3353 path.local.addrlen = local_addrlen;
3354 path.remote.addr = remote_addr;
3355 path.remote.addrlen = remote_addrlen;
3356
3357 new_connection = GNUNET_new (struct Connection);
3358 memset (new_connection, 0, sizeof (struct Connection));
3359
3360 gnutls_init (&new_connection->session,
3361 GNUTLS_SERVER
3362 | GNUTLS_ENABLE_EARLY_DATA
3363 | GNUTLS_NO_END_OF_EARLY_DATA);
3364 gnutls_priority_set_direct (new_connection->session, PRIORITY, NULL);
3365 gnutls_credentials_set (new_connection->session,
3366 GNUTLS_CRD_CERTIFICATE, cred);
3367
3368 ngtcp2_transport_params_default (&params);
3369 params.initial_max_streams_uni = 3;
3370 params.initial_max_streams_bidi = 128;
3371 params.initial_max_stream_data_bidi_local = 128 * 1024;
3372 params.initial_max_stream_data_bidi_remote = 256 * 1024;
3373 params.initial_max_stream_data_uni = 256 * 1024;
3374 params.initial_max_data = 1024 * 1024;
3375 params.original_dcid_present = 1;
3376 params.max_idle_timeout = 30 * NGTCP2_SECONDS;
3377 params.original_dcid = *scid;
3378
3379 ngtcp2_settings_default (&settings);
3380
3381 scid_.datalen = NGTCP2_MAX_CIDLEN;
3383 &scid_.data, scid_.datalen);
3384
3385 rv = ngtcp2_conn_server_new (&conn,
3386 dcid,
3387 &scid_,
3388 &path,
3389 version,
3390 &callbacks,
3391 &settings,
3392 &params,
3393 NULL,
3394 new_connection);
3395 if (rv < 0)
3396 {
3398 "ngtcp2_conn_server_new: %s\n",
3399 ngtcp2_strerror (rv));
3400 return NULL;
3401 }
3402 new_connection->conn = conn;
3403 new_connection->address = GNUNET_memdup (remote_addr, remote_addrlen);
3404 new_connection->address_len = remote_addrlen;
3405 new_connection->foreign_addr =
3406 sockaddr_to_udpaddr_string (new_connection->address,
3407 new_connection->address_len);
3408 new_connection->is_initiator = GNUNET_NO;
3409 new_connection->id_rcvd = GNUNET_NO;
3410 new_connection->id_sent = GNUNET_NO;
3411 ngtcp2_crypto_gnutls_configure_server_session (new_connection->session);
3412 ngtcp2_conn_set_tls_native_handle (new_connection->conn,
3413 new_connection->session);
3414 gnutls_session_set_ptr (new_connection->session,
3415 &new_connection->conn_ref);
3416
3417 new_connection->conn_ref.get_conn = get_conn;
3418 new_connection->conn_ref.user_data = new_connection;
3419 new_connection->streams = GNUNET_CONTAINER_multihashmap_create (10,
3420 GNUNET_NO);
3421
3422 return new_connection;
3423}
3424
3425
3440static void
3441server_read_pkt (struct Connection *connection,
3442 const struct GNUNET_HashCode *addr_key,
3443 struct sockaddr *local_addr, socklen_t local_addrlen,
3444 struct sockaddr *remote_addr, socklen_t remote_addrlen,
3445 const ngtcp2_pkt_info *pi,
3446 const uint8_t *data, size_t datalen)
3447{
3448 ngtcp2_version_cid version_cid;
3449 int rv;
3450
3451 rv = ngtcp2_pkt_decode_version_cid (&version_cid, data, datalen,
3452 NGTCP2_MAX_CIDLEN);
3453 switch (rv)
3454 {
3455 case 0:
3456 break;
3457 case NGTCP2_ERR_VERSION_NEGOTIATION:
3458 // TODO: send version negotiation
3459 return;
3460 default:
3462 "Can't decode version and CID: %s\n",
3463 ngtcp2_strerror (rv));
3464 return;
3465 }
3466
3467 if (NULL == connection)
3468 {
3469 ngtcp2_pkt_hd header;
3470 rv = ngtcp2_accept (&header, data, datalen);
3471 if (0 != rv)
3472 {
3474 "ngtcp2_accept: %s\n",
3475 ngtcp2_strerror (rv));
3476 return;
3477 }
3478
3483 connection = connection_init (local_addr, local_addrlen, remote_addr,
3484 remote_addrlen, &header.scid, &header.dcid,
3485 header.version);
3486 if (NULL == connection)
3487 {
3489 "accept connection error!\n");
3490 return;
3491 }
3492
3494 addr_key,
3495 connection,
3497 rv = connection_on_read (connection, local_addr, local_addrlen, remote_addr,
3498 remote_addrlen, pi, data, datalen);
3499 switch (rv)
3500 {
3501 case 0:
3502 break;
3503 case NETWORK_ERR_RETRY:
3504 // TODO: send retry
3505 return;
3506 default:
3507 return;
3508 }
3509
3510 rv = connection_write (connection);
3511 if (GNUNET_NO != rv)
3512 {
3513 return;
3514 }
3515
3516 // add to cid_map here
3517 return;
3518 }
3519
3520 if (ngtcp2_conn_in_closing_period (connection->conn))
3521 {
3522 rv = send_conn_close (connection);
3523 if (GNUNET_NO != rv)
3524 {
3525 connection_destroy (connection);
3526 }
3527 return;
3528 }
3529
3530 if (ngtcp2_conn_in_draining_period (connection->conn))
3531 {
3532 return;
3533 }
3534
3535 rv = connection_on_read (connection, local_addr, local_addrlen, remote_addr,
3536 remote_addrlen, pi, data, datalen);
3537 if (GNUNET_NO != rv)
3538 {
3539 if (NETWORK_ERR_CLOSE_WAIT != rv)
3540 {
3541 connection_destroy (connection);
3542 }
3543 return;
3544 }
3545
3546 connection_write (connection);
3547}
3548
3549
3555static void
3556sock_read (void *cls)
3557{
3558 (void) cls;
3559 struct sockaddr_storage sa;
3560 socklen_t salen = sizeof (sa);
3561 ssize_t rcvd;
3562 uint8_t buf[UINT16_MAX];
3563 struct GNUNET_HashCode addr_key;
3564 struct Connection *connection;
3565 int rv;
3566 char *bindto;
3567 struct sockaddr *local_addr;
3568 socklen_t local_addrlen;
3569
3570 if (GNUNET_OK !=
3573 "BINDTO",
3574 &bindto))
3575 {
3578 "BINDTO");
3579 return;
3580 }
3581 local_addr = udp_address_to_sockaddr (bindto, &local_addrlen);
3583 udp_sock,
3584 &sock_read,
3585 NULL);
3586
3587 while (1)
3588 {
3590 buf,
3591 sizeof(buf),
3592 (struct sockaddr *) &sa,
3593 &salen);
3594 if (-1 == rcvd)
3595 {
3596 struct sockaddr *addr = (struct sockaddr*) &sa;
3597
3598 if (EAGAIN == errno)
3599 break; // We are done reading data
3601 "Failed to recv from %s family %d failed sock %p\n",
3602 GNUNET_a2s ((struct sockaddr*) &sa,
3603 sizeof (*addr)),
3604 addr->sa_family,
3605 udp_sock);
3607 return;
3608 }
3610 "Read %llu bytes\n",
3611 (unsigned long long) rcvd);
3612 if (0 == rcvd)
3613 {
3614 GNUNET_break_op (0);
3616 "Read 0 bytes from UDP socket\n");
3617 return;
3618 }
3619
3620 char *addr_string =
3621 sockaddr_to_udpaddr_string ((const struct sockaddr *) &sa,
3622 salen);
3623 GNUNET_CRYPTO_hash (addr_string, strlen (addr_string),
3624 &addr_key);
3625 GNUNET_free (addr_string);
3626 connection = GNUNET_CONTAINER_multihashmap_get (addr_map, &addr_key);
3627
3628 ngtcp2_pkt_info pi = {0};
3629 if (NULL != connection && GNUNET_YES == connection->is_initiator)
3630 {
3631 rv = connection_feed_data (connection, local_addr, local_addrlen,
3632 (struct sockaddr *) &sa,
3633 salen, &pi, buf, rcvd);
3634 if (GNUNET_NO != rv)
3635 {
3636 return;
3637 }
3638 rv = connection_write (connection);
3639 if (rv < 0)
3640 {
3642 "connection write error!\n");
3643 return;
3644 }
3645 }
3646 else
3647 {
3648 server_read_pkt (connection, &addr_key,
3649 local_addr, local_addrlen,
3650 (struct sockaddr *) &sa, salen,
3651 &pi, buf, rcvd);
3652 }
3653
3654 }
3655
3657
3658}
3659
3660
3669static void
3670run (void *cls,
3671 char *const *args,
3672 const char *cfgfile,
3673 const struct GNUNET_CONFIGURATION_Handle *c)
3674{
3675 char *bindto;
3676 struct sockaddr *in;
3677 socklen_t in_len;
3678 struct sockaddr_storage in_sto;
3679 socklen_t sto_len;
3680 char *cert_file;
3681 char *key_file;
3682
3683 (void) cls;
3684 cfg = c;
3685 if (GNUNET_OK !=
3688 "BINDTO",
3689 &bindto))
3690 {
3693 "BINDTO");
3694 return;
3695 }
3696
3697 key_file = NULL;
3698 cert_file = NULL;
3699 if ((GNUNET_OK !=
3702 "KEY_FILE",
3703 &key_file)))
3704 key_file = GNUNET_strdup ("https.key");
3705 if (GNUNET_OK !=
3708 "CERT_FILE",
3709 &cert_file))
3710 cert_file = GNUNET_strdup ("https.crt");
3711 if ((GNUNET_OK != GNUNET_DISK_file_test (key_file)) ||
3712 (GNUNET_OK != GNUNET_DISK_file_test (cert_file)))
3713 {
3715 "Creating new certificate\n");
3716
3717 struct GNUNET_OS_Process *cert_creation;
3718
3720 NULL, NULL, NULL,
3721 "gnunet-transport-certificate-creation",
3722 "gnunet-transport-certificate-creation",
3723 key_file,
3724 cert_file,
3725 NULL);
3726 if (NULL == cert_creation)
3727 {
3729 "Can't create new key pair %s/%s\n",
3730 key_file, cert_file);
3731 GNUNET_free (key_file);
3732 GNUNET_free (cert_file);
3733
3734 return;
3735 }
3736 GNUNET_OS_process_wait (cert_creation);
3737 GNUNET_OS_process_destroy (cert_creation);
3738 }
3739
3741 if ((GNUNET_NO == GNUNET_NETWORK_test_pf (PF_INET6)) ||
3742 (GNUNET_YES ==
3745 "DISABLE_V6")))
3746 {
3748 }
3749
3750 in = udp_address_to_sockaddr (bindto, &in_len);
3751
3752 if (NULL == in)
3753 {
3755 "Failed to setup UDP socket address with path `%s'\n",
3756 bindto);
3757 GNUNET_free (bindto);
3758 return;
3759 }
3760 udp_sock =
3761 GNUNET_NETWORK_socket_create (in->sa_family,
3762 SOCK_DGRAM,
3763 IPPROTO_UDP);
3764 if (NULL == udp_sock)
3765 {
3768 "Failed to create socket for %s family %d\n",
3769 GNUNET_a2s (in,
3770 in_len),
3771 in->sa_family);
3772 GNUNET_free (in);
3773 GNUNET_free (bindto);
3774 return;
3775 }
3776 if (AF_INET6 == in->sa_family)
3778 if (GNUNET_OK !=
3780 in,
3781 in_len))
3782 {
3784 "bind",
3785 bindto);
3787 "Failed to bind socket for %s family %d sock %p\n",
3788 GNUNET_a2s (in,
3789 in_len),
3790 in->sa_family,
3791 udp_sock);
3793 udp_sock = NULL;
3794 GNUNET_free (in);
3795 GNUNET_free (bindto);
3796 return;
3797 }
3798 sto_len = sizeof(in_sto);
3799 if (0 != getsockname (GNUNET_NETWORK_get_fd (udp_sock),
3800 (struct sockaddr *) &in_sto,
3801 &sto_len))
3802 {
3803 memcpy (&in_sto, in, in_len);
3804 sto_len = in_len;
3805 }
3806 GNUNET_free (in);
3807 GNUNET_free (bindto);
3808 in = (struct sockaddr *) &in_sto;
3809 in_len = sto_len;
3811 "transport",
3812 "Bound to `%s' sock %p\n",
3813 GNUNET_a2s ((const struct sockaddr *) &in_sto,
3814 sto_len),
3815 udp_sock);
3816 switch (in->sa_family)
3817 {
3818 case AF_INET:
3819 my_port = ntohs (((struct sockaddr_in *) in)->sin_port);
3820 break;
3821
3822 case AF_INET6:
3823 my_port = ntohs (((struct sockaddr_in6 *) in)->sin6_port);
3824 break;
3825
3826 default:
3827 GNUNET_break (0);
3828 my_port = 0;
3829 }
3831
3834
3835 int rv;
3836 rv = gnutls_certificate_allocate_credentials (&cred);
3837 if (GNUNET_NO == rv)
3838 rv = gnutls_certificate_set_x509_system_trust (cred);
3839 if (GNUNET_NO > rv)
3840 {
3842 "cred init failed: %s\n",
3843 gnutls_strerror (rv));
3844 return;
3845 }
3846 rv = gnutls_certificate_set_x509_key_file (cred,
3847 cert_file,
3848 key_file,
3849 GNUTLS_X509_FMT_PEM);
3851 "key_file: %s\ncert_file: %s\n",
3852 key_file, cert_file);
3853 GNUNET_free (cert_file);
3854 GNUNET_free (key_file);
3855 if (rv < 0)
3856 {
3858 "gnutls_certificate_set_x509_key_file: %s\n",
3859 gnutls_strerror (rv));
3860 return;
3861 }
3866 if (NULL == my_private_key)
3867 {
3868 GNUNET_log (
3870 _ (
3871 "Transport service is lacking key configuration settings. Exiting.\n"));
3873 return;
3874 }
3876
3878 udp_sock,
3879 &sock_read,
3880 NULL);
3885 &mq_init,
3886 NULL,
3887 &notify_cb,
3888 NULL,
3889 NULL);
3890 if (NULL == ch)
3891 {
3892 GNUNET_break (0);
3894 return;
3895 }
3896
3899 IPPROTO_UDP,
3900 1 /* one address */,
3901 (const struct sockaddr **) &in,
3902 &in_len,
3905 NULL /* closure */);
3906}
3907
3908
3916int
3917main (int argc, char *const *argv)
3918{
3919 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
3921 };
3922 int ret;
3923
3925 "transport",
3926 "Starting http3 communicator\n");
3927 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
3928 return 2;
3929
3930 ret = (GNUNET_OK ==
3931 GNUNET_PROGRAM_run (argc,
3932 argv,
3933 "gnunet-communicator-http3",
3934 _ ("GNUnet HTTP3 communicator"),
3935 options,
3936 &run,
3937 NULL))
3938 ? 0
3939 : 1;
3940 GNUNET_free_nz ((void *) argv);
3941 return ret;
3942}
3943
3944
3945/* 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:147
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:483
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_free_nz(ptr)
Wrapper around free.
#define GNUNET_memdup(buf, size)
Allocate and initialize a block of memory.
GNUNET_MQ_Error
Error codes for the queue.
struct GNUNET_MQ_Handle * GNUNET_MQ_queue_for_callbacks(GNUNET_MQ_SendImpl send, GNUNET_MQ_DestroyImpl destroy, GNUNET_MQ_CancelImpl cancel, void *impl_state, const struct GNUNET_MQ_MessageHandler *handlers, GNUNET_MQ_ErrorHandler error_handler, void *cls)
Create a message queue for the specified handlers.
Definition: mq.c: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:627
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:878
@ 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(int argc, char *const *argv, const char *binaryName, const char *binaryHelp, const struct GNUNET_GETOPT_CommandLineOption *options, GNUNET_PROGRAM_Main task, void *task_cls)
Run a standard GNUnet command startup sequence (initialize loggers and configuration,...
Definition: program.c:400
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:566
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:1510
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:1338
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:979
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:1303
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:1276
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).
enum GNUNET_GenericReturnValue GNUNET_STRINGS_get_utf8_args(int argc, char *const *argv, int *u8argc, char *const **u8argv)
Returns utf-8 encoded arguments.
Definition: strings.c:1230
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
#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:135
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.