GNUnet 0.28.0-dev.3-7-g31e20e2e6
 
Loading...
Searching...
No Matches
gnunet-communicator-http3.c
Go to the documentation of this file.
1#include "platform.h"
2#include "gnunet_common.h"
3#include "gnunet_util_lib.h"
9#include "gnunet_protocols.h"
10#include "gnunet_signatures.h"
11#include "gnunet_constants.h"
13#include "stdint.h"
14#include "inttypes.h"
15#include "stdlib.h"
16
17#include <ngtcp2/ngtcp2.h>
18#include <ngtcp2/ngtcp2_crypto.h>
19#include <ngtcp2/ngtcp2_crypto_gnutls.h>
20#include <nghttp3/nghttp3.h>
21#include <gnutls/crypto.h>
22#include <gnutls/gnutls.h>
23#include <stdint.h>
24
25
29#define COMMUNICATOR_CONFIG_SECTION "communicator-http3"
30
34#define COMMUNICATOR_ADDRESS_PREFIX "http3"
35
39#define PRIORITY "NORMAL:-VERS-ALL:+VERS-TLS1.3:" \
40 "-CIPHER-ALL:+AES-128-GCM:+AES-256-GCM:+CHACHA20-POLY1305:+AES-128-CCM:" \
41 "-GROUP-ALL:+GROUP-SECP256R1:+GROUP-X25519:+GROUP-SECP384R1:+GROUP-SECP521R1:" \
42 "%DISABLE_TLS13_COMPAT_MODE"
43
48#define ADDRESS_VALIDITY_PERIOD GNUNET_TIME_UNIT_HOURS
49
53#define NUM_LONG_POLL 16
54
67
76
80static const struct GNUNET_CONFIGURATION_Handle *cfg;
81
85static struct GNUNET_PILS_Handle *pils;
86
90static int disable_v6;
91
96
101
106
110static struct GNUNET_NAT_Handle *nat;
111
115static int have_v6_socket;
116
120static uint16_t my_port;
121
126
131
135static gnutls_certificate_credentials_t cred;
136
140struct Stream
141{
145 int64_t stream_id;
146
150 uint8_t *data;
151
155 uint64_t datalen;
156
161
166
170 uint8_t *uri;
171
175 size_t urilen;
176
180 uint8_t *method;
181
185 size_t methodlen;
186
190 uint8_t *authority;
191
196};
197
202{
207
211 char *buf;
212
216 size_t size;
217};
218
223{
227 struct Stream *stream;
228
233
237 uint64_t delay_time;
238
243
248};
249
253struct Connection
254{
258 ngtcp2_conn *conn;
259
263 nghttp3_conn *h3_conn;
264
268 ngtcp2_ccerr last_error;
269
273 ngtcp2_crypto_conn_ref conn_ref;
274
278 gnutls_session_t session;
283
287 struct sockaddr *address;
288
292 socklen_t address_len;
293
298
303
308
313
318
323
327 size_t d_mtu;
328
333
338
344
349
354
359
363 ngtcp2_ssize conn_closebuflen;
364
369
374
379
384
389
394
399};
400
401
402static int
403connection_write (struct Connection *connection);
404
410static uint64_t
412{
413 struct timespec tp;
414 clock_gettime (CLOCK_MONOTONIC, &tp);
415 return (uint64_t) tp.tv_sec * NGTCP2_SECONDS + (uint64_t) tp.tv_nsec;
416}
417
418
428static char *
429sockaddr_to_udpaddr_string (const struct sockaddr *address,
430 socklen_t address_len)
431{
432 char *ret;
433
434 switch (address->sa_family)
435 {
436 case AF_INET:
438 "%s-%s",
440 GNUNET_a2s (address, address_len));
441 break;
442
443 case AF_INET6:
445 "%s-%s",
447 GNUNET_a2s (address, address_len));
448 break;
449
450 default:
451 GNUNET_assert (0);
452 }
453 return ret;
454}
455
456
464static struct sockaddr *
465udp_address_to_sockaddr (const char *bindto, socklen_t *sock_len)
466{
467 struct sockaddr *in;
468 unsigned int port;
469 char dummy[2];
470 char *colon;
471 char *cp;
472
473 if (1 == sscanf (bindto, "%u%1s", &port, dummy))
474 {
475 /* interpreting value as just a PORT number */
476 if (port > UINT16_MAX)
477 {
479 "BINDTO specification `%s' invalid: value too large for port\n",
480 bindto);
481 return NULL;
482 }
483 if (GNUNET_YES == disable_v6)
484 {
485 struct sockaddr_in *i4;
486
487 i4 = GNUNET_malloc (sizeof(struct sockaddr_in));
488 i4->sin_family = AF_INET;
489 i4->sin_port = htons ((uint16_t) port);
490 *sock_len = sizeof(struct sockaddr_in);
491 in = (struct sockaddr *) i4;
492 }
493 else
494 {
495 struct sockaddr_in6 *i6;
496
497 i6 = GNUNET_malloc (sizeof(struct sockaddr_in6));
498 i6->sin6_family = AF_INET6;
499 i6->sin6_port = htons ((uint16_t) port);
500 *sock_len = sizeof(struct sockaddr_in6);
501 in = (struct sockaddr *) i6;
502 }
503 return in;
504 }
505 cp = GNUNET_strdup (bindto);
506 colon = strrchr (cp, ':');
507 if (NULL != colon)
508 {
509 /* interpret value after colon as port */
510 *colon = '\0';
511 colon++;
512 if (1 == sscanf (colon, "%u%1s", &port, dummy))
513 {
514 /* interpreting value as just a PORT number */
515 if (port > UINT16_MAX)
516 {
518 "BINDTO specification `%s' invalid: value too large for port\n",
519 bindto);
520 GNUNET_free (cp);
521 return NULL;
522 }
523 }
524 else
525 {
526 GNUNET_log (
528 "BINDTO specification `%s' invalid: last ':' not followed by number\n",
529 bindto);
530 GNUNET_free (cp);
531 return NULL;
532 }
533 }
534 else
535 {
536 /* interpret missing port as 0, aka pick any free one */
537 port = 0;
538 }
539 {
540 /* try IPv4 */
541 struct sockaddr_in v4;
542
543 memset (&v4, 0, sizeof(v4));
544 if (1 == inet_pton (AF_INET, cp, &v4.sin_addr))
545 {
546 v4.sin_family = AF_INET;
547 v4.sin_port = htons ((uint16_t) port);
548#if HAVE_SOCKADDR_IN_SIN_LEN
549 v4.sin_len = sizeof(struct sockaddr_in);
550#endif
551 in = GNUNET_memdup (&v4, sizeof(struct sockaddr_in));
552 *sock_len = sizeof(struct sockaddr_in);
553 GNUNET_free (cp);
554 return in;
555 }
556 }
557 {
558 /* try IPv6 */
559 struct sockaddr_in6 v6;
560 const char *start;
561
562 memset (&v6, 0, sizeof(v6));
563 start = cp;
564 if (('[' == *cp) && (']' == cp[strlen (cp) - 1]))
565 {
566 start++; /* skip over '[' */
567 cp[strlen (cp) - 1] = '\0'; /* eat ']' */
568 }
569 if (1 == inet_pton (AF_INET6, start, &v6.sin6_addr))
570 {
571 v6.sin6_family = AF_INET6;
572 v6.sin6_port = htons ((uint16_t) port);
573#if HAVE_SOCKADDR_IN_SIN_LEN
574 v6.sin6_len = sizeof(struct sockaddr_in6);
575#endif
576 in = GNUNET_memdup (&v6, sizeof(v6));
577 *sock_len = sizeof(v6);
578 GNUNET_free (cp);
579 return in;
580 }
581 }
582 /* #5528 FIXME (feature!): maybe also try getnameinfo()? */
583 GNUNET_free (cp);
584 return NULL;
585}
586
587
591static ngtcp2_conn*
592get_conn (ngtcp2_crypto_conn_ref *ref)
593{
594 return ((struct Connection*) (ref->user_data))->conn;
595}
596
597
598static void
600 const struct sockaddr *addr,
601 socklen_t addrlen)
602{
603 /* FIXME: support reversal: #5529 */
605 "No connection reversal implemented!\n");
606}
607
608
618static void
619notify_cb (void *cls,
620 const struct GNUNET_PeerIdentity *sender,
621 const struct GNUNET_MessageHeader *msg)
622{
623
624}
625
626
636static int
637send_packet (struct Connection *connection, const uint8_t *data, size_t datalen)
638{
639 int rv;
640
642 connection->address,
643 connection->address_len);
644 if (GNUNET_SYSERR == rv)
645 {
647 "send packet failed!\n");
648 return GNUNET_SYSERR;
649 }
650 return GNUNET_NO;
651}
652
653
663static struct Stream*
665{
666 struct Stream *new_stream;
667 struct GNUNET_HashCode stream_key;
668
669 new_stream = GNUNET_new (struct Stream);
670 memset (new_stream, 0, sizeof (struct Stream));
671 new_stream->stream_id = stream_id;
672 new_stream->connection = connection;
673 GNUNET_CRYPTO_hash (&stream_id, sizeof (stream_id), &stream_key);
675 &stream_key,
676 new_stream,
678 return new_stream;
679}
680
681
688static void
689remove_stream (struct Connection *connection, int64_t stream_id)
690{
691 struct GNUNET_HashCode stream_key;
692 struct Stream *stream;
693 int rv;
694
695 GNUNET_CRYPTO_hash (&stream_id, sizeof (stream_id), &stream_key);
698 &stream_key,
699 stream);
700 if (GNUNET_NO == rv)
701 {
703 "can't remove non-exist pair in connection->streams, stream_id = %"
704 PRIi64 "\n",
705 stream_id);
706 return;
707 }
708
709 if (stream->uri)
710 {
711 GNUNET_free (stream->uri);
712 }
713 if (stream->method)
714 {
715 GNUNET_free (stream->method);
716 }
717 if (stream->authority)
718 {
719 GNUNET_free (stream->authority);
720 }
721 GNUNET_free (stream);
722}
723
724
735static struct Stream *
737{
738 struct GNUNET_HashCode stream_key;
739 struct Stream *stream;
740
741 GNUNET_CRYPTO_hash (&stream_id, sizeof (stream_id), &stream_key);
743 return stream;
744}
745
746
754static int
756{
757 int rv;
758 gnutls_datum_t alpn = { (unsigned char *) "h3", sizeof("h3") - 1};
759 // rv = gnutls_certificate_allocate_credentials (&connection->cred);
760 // if (GNUNET_NO == rv)
761 // rv = gnutls_certificate_set_x509_system_trust (connection->cred);
762 // if (GNUNET_NO > rv)
763 // {
764 // GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
765 // "cred init failed: %s\n",
766 // gnutls_strerror (rv));
767 // return GNUNET_SYSERR;
768 // }
769 rv = gnutls_init (&connection->session,
770 GNUTLS_CLIENT
771 | GNUTLS_ENABLE_EARLY_DATA
772 | GNUTLS_NO_END_OF_EARLY_DATA);
773 if (GNUNET_NO != rv)
774 {
776 "gnutls_init error: %s\n",
777 gnutls_strerror (rv));
778 return GNUNET_SYSERR;
779 }
780 rv = ngtcp2_crypto_gnutls_configure_client_session (connection->session);
781 if (GNUNET_NO != rv)
782 {
784 "ngtcp2_crypto_gnutls_configure_client_session failed\n");
785 return GNUNET_SYSERR;
786 }
787 rv = gnutls_priority_set_direct (connection->session, PRIORITY, NULL);
788 if (GNUNET_NO != rv)
789 {
791 "gnutls_priority_set_direct: %s\n",
792 gnutls_strerror (rv));
793 return GNUNET_SYSERR;
794 }
795 gnutls_session_set_ptr (connection->session, &connection->conn_ref);
796 rv = gnutls_credentials_set (connection->session, GNUTLS_CRD_CERTIFICATE,
797 cred);
798 if (GNUNET_NO != rv)
799 {
801 "gnutls_credentials_set: %s\n",
802 gnutls_strerror (rv));
803 return GNUNET_SYSERR;
804 }
805 gnutls_alpn_set_protocols (connection->session, &alpn, 1,
806 GNUTLS_ALPN_MANDATORY);
807
812 // gnutls_server_name_set (connection->session, GNUTLS_NAME_DNS, "localhost",
813 // strlen ("localhost"));
814
815 return GNUNET_NO;
816}
817
818
824static void
826{
829 // GNUNET_CONTAINER_heap_update_cost (peer->hn,
830 // peer->timeout.abs_value_us);
831}
832
833
842static int
844 const struct GNUNET_HashCode *key,
845 void *value)
846{
847 struct Stream *stream = value;
848 (void) cls;
849 (void) key;
850
851 if (stream->uri)
852 {
853 GNUNET_free (stream->uri);
854 }
855 if (stream->method)
856 {
857 GNUNET_free (stream->method);
858 }
859 if (stream->authority)
860 {
861 GNUNET_free (stream->authority);
862 }
863 GNUNET_free (stream);
864 return GNUNET_OK;
865}
866
867
873static void
875{
876 struct GNUNET_HashCode addr_key;
877 struct HTTP_Message *msg_curr;
878 struct Long_Poll_Request *long_poll_curr;
879 struct Long_Poll_Request *long_poll_temp;
880 int rv;
882
883 msg_curr = connection->msg_queue_head;
884 connection->msg_queue_rear = NULL;
885 while (NULL != msg_curr)
886 {
887 msg_curr = msg_curr->next;
888 GNUNET_free (msg_curr->buf);
889 GNUNET_free (msg_curr);
890 }
891
892 msg_curr = connection->submitted_msg_queue_head;
893 while (NULL != msg_curr)
894 {
895 msg_curr = msg_curr->next;
896 GNUNET_free (msg_curr->buf);
897 GNUNET_free (msg_curr);
898 }
899
900 long_poll_curr = connection->long_poll_head;
901 connection->long_poll_rear = NULL;
902 while (NULL != long_poll_curr)
903 {
904 long_poll_temp = long_poll_curr;
905 long_poll_curr = long_poll_curr->next;
906 if (long_poll_temp->timer)
907 GNUNET_SCHEDULER_cancel (long_poll_temp->timer);
908 GNUNET_free (long_poll_temp);
909 }
910
911 if (NULL != connection->d_qh)
912 {
914 connection->d_qh = NULL;
915 }
916
917 GNUNET_CRYPTO_hash (connection->address,
918 connection->address_len,
919 &addr_key);
920 rv = GNUNET_CONTAINER_multihashmap_remove (addr_map, &addr_key, connection);
921 if (GNUNET_NO == rv)
922 {
924 "tried to remove non-existent connection from addr_map\n");
925 return;
926 }
928 "# connections active",
930 GNUNET_NO);
931
932 ngtcp2_conn_del (connection->conn);
933 if (connection->h3_conn)
934 {
935 nghttp3_conn_del (connection->h3_conn);
936 }
937 gnutls_deinit (connection->session);
938 GNUNET_free (connection->address);
939 GNUNET_free (connection->foreign_addr);
940 GNUNET_free (connection->conn_closebuf);
943 NULL);
945 GNUNET_free (connection);
946}
947
948
958static nghttp3_nv
959make_nv (const char *name,
960 const char *value,
961 uint8_t flag)
962{
963 nghttp3_nv nv;
964
965 nv.name = (const uint8_t *) name;
966 nv.namelen = strlen (name);
967 nv.value = (const uint8_t *) value;
968 nv.valuelen = strlen (value);
969 nv.flags = flag;
970
971 return nv;
972}
973
974
978static nghttp3_ssize
979read_data (nghttp3_conn *conn, int64_t stream_id, nghttp3_vec *vec,
980 size_t veccnt, uint32_t *pflags, void *user_data,
981 void *stream_user_data)
982{
983 struct Stream *stream = stream_user_data;
984
985 vec[0].base = stream->data;
986 vec[0].len = stream->datalen;
987 *pflags |= NGHTTP3_DATA_FLAG_EOF;
988
989 return 1;
990}
991
992
1003static int
1005 struct Stream *stream,
1006 const uint8_t *data,
1007 size_t datalen)
1008{
1009 nghttp3_nv nva[7];
1010 char contentlen[20];
1011 nghttp3_data_reader dr = {};
1012 int rv;
1013
1014 GNUNET_snprintf (contentlen, sizeof(contentlen), "%zu", datalen);
1015 stream->data = (uint8_t *) data;
1016 stream->datalen = datalen;
1017
1018 nva[0] = make_nv (":method", "POST",
1019 NGHTTP3_NV_FLAG_NO_COPY_NAME
1020 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1021 nva[1] = make_nv (":scheme", "https",
1022 NGHTTP3_NV_FLAG_NO_COPY_NAME
1023 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1024 nva[2] = make_nv (":authority",
1026 NGHTTP3_NV_FLAG_NO_COPY_NAME);
1027 nva[3] = make_nv (":path", "/",
1028 NGHTTP3_NV_FLAG_NO_COPY_NAME
1029 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1030 nva[4] = make_nv ("user-agent", "nghttp3/ngtcp2 client",
1031 NGHTTP3_NV_FLAG_NO_COPY_NAME
1032 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1033 nva[5] = make_nv ("content-type", "application/octet-stream",
1034 NGHTTP3_NV_FLAG_NO_COPY_NAME
1035 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1036 nva[6] = make_nv ("content-length", contentlen,
1037 NGHTTP3_NV_FLAG_NO_COPY_NAME);
1038
1039 dr.read_data = read_data;
1040 rv = nghttp3_conn_submit_request (connection->h3_conn,
1041 stream->stream_id,
1042 nva, 7, &dr, stream);
1043 if (0 != rv)
1044 {
1046 "nghttp3_conn_submit_request: %s\n",
1047 nghttp3_strerror (rv));
1048 return GNUNET_SYSERR;
1049 }
1050
1051 return GNUNET_NO;
1052}
1053
1054
1064static int
1066 struct Stream *stream)
1067{
1068 nghttp3_nv nva[6];
1069 int rv;
1070
1072 "send get request\n");
1073 nva[0] = make_nv (":method", "GET",
1074 NGHTTP3_NV_FLAG_NO_COPY_NAME
1075 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1076 nva[1] = make_nv (":scheme", "https",
1077 NGHTTP3_NV_FLAG_NO_COPY_NAME
1078 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1079 nva[2] = make_nv (":authority",
1081 NGHTTP3_NV_FLAG_NO_COPY_NAME);
1082 nva[3] = make_nv (":path", "/",
1083 NGHTTP3_NV_FLAG_NO_COPY_NAME
1084 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1085 nva[4] = make_nv ("user-agent", "nghttp3/ngtcp2 client",
1086 NGHTTP3_NV_FLAG_NO_COPY_NAME
1087 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1088
1089 rv = nghttp3_conn_submit_request (connection->h3_conn,
1090 stream->stream_id,
1091 nva, 5, NULL, stream);
1092 if (0 != rv)
1093 {
1095 "nghttp3_conn_submit_request: %s\n",
1096 nghttp3_strerror (rv));
1097 return GNUNET_SYSERR;
1098 }
1099
1100 return GNUNET_NO;
1101}
1102
1103
1109static void
1111{
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;
1120 "long_poll_timeoutcb called!\n");
1121 stream = long_poll->stream;
1122 connection = stream->connection;
1123 if (NULL != long_poll->prev)
1124 {
1125 long_poll->prev->next = long_poll->next;
1126 }
1127 if (NULL != long_poll->next)
1128 {
1129 long_poll->next->prev = long_poll->prev;
1130 }
1131 if (connection->long_poll_head == long_poll)
1132 {
1133 connection->long_poll_head = long_poll->next;
1134 }
1135 if (connection->long_poll_rear == long_poll)
1136 {
1137 connection->long_poll_rear = long_poll->prev;
1138 }
1139 GNUNET_free (long_poll);
1140
1141 nva[0] = make_nv (":status", "204",
1142 NGHTTP3_NV_FLAG_NO_COPY_NAME
1143 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1144 nva[1] = make_nv ("server", "nghttp3/ngtcp2 server",
1145 NGHTTP3_NV_FLAG_NO_COPY_NAME
1146 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1147 rv = nghttp3_conn_submit_response (connection->h3_conn,
1148 stream->stream_id, nva, 2, NULL);
1149 if (0 != rv)
1150 {
1152 "nghttp3_conn_submit_response: %s\n",
1153 nghttp3_strerror (rv));
1154 return;
1155 }
1156 ngtcp2_conn_shutdown_stream_read (connection->conn, 0,
1157 stream->stream_id,
1158 NGHTTP3_H3_NO_ERROR);
1159}
1160
1161
1172static int
1173stream_send_data (struct Stream *stream,
1174 uint8_t *data, size_t datalen)
1175{
1176 nghttp3_nv nva[4];
1177 nghttp3_data_reader dr = {};
1178 char content_length_str[20];
1179 int rv;
1180
1181 GNUNET_snprintf (content_length_str, sizeof(content_length_str),
1182 "%zu", datalen);
1183 nva[0] = make_nv (":status", "200",
1184 NGHTTP3_NV_FLAG_NO_COPY_NAME
1185 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1186 nva[1] = make_nv ("server", "nghttp3/ngtcp2 server",
1187 NGHTTP3_NV_FLAG_NO_COPY_NAME
1188 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1189 nva[2] = make_nv ("content-type", "application/octet-stream",
1190 NGHTTP3_NV_FLAG_NO_COPY_NAME
1191 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1192 nva[3] = make_nv ("content-length", content_length_str,
1193 NGHTTP3_NV_FLAG_NO_COPY_NAME);
1194
1195 stream->data = data;
1196 stream->datalen = datalen;
1197 dr.read_data = read_data;
1198 rv = nghttp3_conn_submit_response (stream->connection->h3_conn,
1199 stream->stream_id,
1200 nva, 4, &dr);
1201 if (0 != rv)
1202 {
1204 "nghttp3_conn_submit_response: %s\n",
1205 nghttp3_strerror (rv));
1206 return GNUNET_SYSERR;
1207 }
1208 return GNUNET_NO;
1209}
1210
1211
1220static int
1221stream_start_response (struct Connection *connection, struct Stream *stream)
1222{
1223 nghttp3_nv nva[4];
1224 struct HTTP_Message *msg;
1225 struct Long_Poll_Request *long_poll;
1226 struct GNUNET_TIME_Relative delay;
1227 int rv;
1228
1229 nva[0] = make_nv (":status", "200",
1230 NGHTTP3_NV_FLAG_NO_COPY_NAME
1231 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1232 nva[1] = make_nv ("server", "nghttp3/ngtcp2 server",
1233 NGHTTP3_NV_FLAG_NO_COPY_NAME
1234 | NGHTTP3_NV_FLAG_NO_COPY_VALUE);
1235
1236 // method is POST
1237 if (4 == stream->methodlen)
1238 {
1239 if (NULL == connection->msg_queue_head)
1240 {
1241 rv = nghttp3_conn_submit_response (connection->h3_conn, stream->stream_id,
1242 nva, 2, NULL);
1243 if (0 != rv)
1244 {
1246 "nghttp3_conn_submit_response: %s\n",
1247 nghttp3_strerror (rv));
1248 return GNUNET_SYSERR;
1249 }
1250 }
1251 else
1252 {
1253 connection->msg_queue_len -= 1;
1255 "rm msg, len = %lu\n",
1256 connection->msg_queue_len);
1257 msg = connection->msg_queue_head;
1258 stream_send_data (stream, (uint8_t *) msg->buf, msg->size);
1259 connection->msg_queue_head = msg->next;
1260 msg->next = connection->submitted_msg_queue_head;
1261 connection->submitted_msg_queue_head = msg;
1262 }
1263 }
1264 // method is GET
1265 else
1266 {
1268 "server recv GET request\n");
1269 if (NULL != connection->msg_queue_head &&
1270 NULL == connection->long_poll_head)
1271 {
1272 msg = connection->msg_queue_head;
1273 stream_send_data (stream,
1274 (uint8_t *) msg->buf,
1275 msg->size);
1276 connection->msg_queue_head = msg->next;
1277 msg->next = connection->submitted_msg_queue_head;
1278 connection->submitted_msg_queue_head = msg;
1279 }
1280 else if (NULL == connection->msg_queue_head ||
1281 NULL != connection->long_poll_head)
1282 {
1283 connection->long_poll_len += 1;
1285 "add long_poll, len = %lu\n",
1286 connection->long_poll_len);
1287 long_poll = GNUNET_new (struct Long_Poll_Request);
1288 long_poll->stream = stream;
1289 long_poll->next = NULL;
1290 long_poll->prev = connection->long_poll_rear;
1291 long_poll->delay_time = 1ULL;
1292 if (NULL != connection->long_poll_rear)
1293 {
1294 connection->long_poll_rear->next = long_poll;
1295 long_poll->delay_time =
1296 (connection->long_poll_head->delay_time & (NUM_LONG_POLL - 1)) + 1ULL;
1297 }
1298 connection->long_poll_rear = long_poll;
1299 if (NULL == connection->long_poll_head)
1300 {
1301 connection->long_poll_head = long_poll;
1302 }
1304 long_poll->delay_time);
1305 long_poll->timer = GNUNET_SCHEDULER_add_delayed (delay,
1307 long_poll);
1308 }
1309 long_poll = connection->long_poll_head;
1310
1311 while (NULL != long_poll &&
1312 NULL != connection->msg_queue_head)
1313 {
1314 GNUNET_SCHEDULER_cancel (long_poll->timer);
1315 if (NULL != long_poll->next)
1316 {
1317 long_poll->next->prev = NULL;
1318 }
1319
1320 msg = connection->msg_queue_head;
1321 connection->msg_queue_head = msg->next;
1322 msg->next = connection->submitted_msg_queue_head;
1323 connection->submitted_msg_queue_head = msg;
1324 stream_send_data (long_poll->stream,
1325 (uint8_t *) msg->buf,
1326 msg->size);
1327 connection->long_poll_head = long_poll->next;
1328 if (NULL != long_poll->next)
1329 {
1330 long_poll->next->prev = NULL;
1331 }
1332 connection->long_poll_len -= 1;
1334 "rm long_poll, len = %lu\n",
1335 connection->long_poll_len);
1336 GNUNET_free (long_poll);
1337 long_poll = connection->long_poll_head;
1338 }
1339 }
1340 return GNUNET_NO;
1341}
1342
1343
1352static void
1354 const struct GNUNET_MessageHeader *msg,
1355 void *impl_state)
1356{
1357 struct Connection *connection = impl_state;
1358 uint16_t msize = ntohs (msg->size);
1359 struct Stream *post_stream;
1360 struct HTTP_Message *send_buf;
1361 struct Long_Poll_Request *long_poll;
1362
1364 "mq_send_d: init = %d, msg->size = %u, time: %llu\n",
1365 connection->is_initiator, msize,
1366 (unsigned long long) timestamp () / NGTCP2_SECONDS);
1367 if (NULL == connection->conn)
1368 {
1370 "No quic connection has been established yet\n");
1371 return;
1372 }
1373
1374 GNUNET_assert (mq == connection->d_mq);
1375
1376 if (msize > connection->d_mtu)
1377 {
1379 "msize: %u, mtu: %lu\n",
1380 msize,
1381 connection->d_mtu);
1382 GNUNET_break (0);
1383 if (GNUNET_YES != connection->connection_destroy_called)
1384 {
1386 "connection destroy called, destroying connection\n");
1387 connection_destroy (connection);
1388 }
1389 return;
1390 }
1391 reschedule_peer_timeout (connection);
1392
1393 // If we are client side.
1394 if (GNUNET_YES == connection->is_initiator)
1395 {
1396 post_stream = create_stream (connection, -1);
1397 ngtcp2_conn_open_bidi_stream (connection->conn,
1398 &post_stream->stream_id,
1399 NULL);
1400 submit_post_request (connection, post_stream, (uint8_t *) msg, msize);
1401 connection_write (connection);
1402 }
1403 // If we are server side.
1404 else
1405 {
1406 if (NULL == connection->msg_queue_head &&
1407 NULL != connection->long_poll_head)
1408 {
1409 long_poll = connection->long_poll_head;
1410 GNUNET_SCHEDULER_cancel (long_poll->timer);
1411 stream_send_data (long_poll->stream, (uint8_t *) msg, msize);
1412 connection_write (connection);
1413 connection->long_poll_head = long_poll->next;
1414 if (NULL != long_poll->next)
1415 {
1416 long_poll->next->prev = NULL;
1417 }
1418 connection->long_poll_len -= 1;
1420 "rm long_poll, len = %lu\n",
1421 connection->long_poll_len);
1422 GNUNET_free (long_poll);
1423 }
1424 else if (NULL == connection->long_poll_head ||
1425 NULL != connection->msg_queue_head)
1426 {
1427 connection->msg_queue_len += 1;
1429 "add msg, len = %lu\n",
1430 connection->msg_queue_len);
1431 send_buf = GNUNET_new (struct HTTP_Message);
1432 send_buf->size = msize;
1433 send_buf->buf = GNUNET_memdup (msg, msize);
1434 send_buf->next = NULL;
1435 connection->msg_queue_rear = send_buf;
1436 if (NULL == connection->msg_queue_head)
1437 {
1438 connection->msg_queue_head = send_buf;
1439 }
1440 }
1441
1442 long_poll = connection->long_poll_head;
1443 while (NULL != long_poll &&
1444 NULL != connection->msg_queue_head)
1445 {
1446 GNUNET_SCHEDULER_cancel (long_poll->timer);
1447 if (NULL != long_poll->next)
1448 {
1449 long_poll->next->prev = NULL;
1450 }
1451
1452 send_buf = connection->msg_queue_head;
1453 connection->msg_queue_head = send_buf->next;
1454 send_buf->next = connection->submitted_msg_queue_head;
1455 connection->submitted_msg_queue_head = send_buf;
1456 stream_send_data (long_poll->stream,
1457 (uint8_t *) send_buf->buf,
1458 send_buf->size);
1459 connection->long_poll_head = long_poll->next;
1460 if (NULL != long_poll->next)
1461 {
1462 long_poll->next->prev = NULL;
1463 }
1464 connection->long_poll_len -= 1;
1466 "rm long_poll, len = %lu\n",
1467 connection->long_poll_len);
1468 GNUNET_free (long_poll);
1469 long_poll = connection->long_poll_head;
1470 }
1471 }
1473}
1474
1475
1484static void
1485mq_destroy_d (struct GNUNET_MQ_Handle *mq, void *impl_state)
1486{
1487 struct Connection *connection = impl_state;
1489 "Default MQ destroyed\n");
1490 if (mq == connection->d_mq)
1491 {
1492 connection->d_mq = NULL;
1493 if (GNUNET_YES != connection->connection_destroy_called)
1494 connection_destroy (connection);
1495 }
1496}
1497
1498
1505static void
1506mq_cancel (struct GNUNET_MQ_Handle *mq, void *impl_state)
1507{
1508 /* Cancellation is impossible with QUIC; bail */
1509 GNUNET_assert (0);
1510}
1511
1512
1522static void
1523mq_error (void *cls, enum GNUNET_MQ_Error error)
1524{
1525 struct Connection *connection = cls;
1527 "MQ error in queue to %s: %d\n",
1528 GNUNET_i2s (&connection->target),
1529 (int) error);
1530 connection_destroy (connection);
1531}
1532
1533
1541static void
1543{
1544 size_t base_mtu;
1545
1547 "setup_connection_mq: init = %u\n",
1548 connection->is_initiator);
1549 switch (connection->address->sa_family)
1550 {
1551 case AF_INET:
1552 base_mtu = 1480 /* Ethernet MTU, 1500 - Ethernet header - VLAN tag */
1553 - sizeof(struct GNUNET_TUN_IPv4Header) /* 20 */
1554 - sizeof(struct GNUNET_TUN_UdpHeader) /* 8 */;
1555 break;
1556 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 default:
1562 GNUNET_assert (0);
1563 break;
1564 }
1565 /* MTU == base_mtu */
1566 connection->d_mtu = base_mtu;
1567
1568 if (NULL == connection->d_mq)
1570 &mq_destroy_d,
1571 &mq_cancel,
1572 connection,
1573 NULL,
1574 &mq_error,
1575 connection);
1576 connection->d_qh =
1578 &connection->target,
1579 connection->foreign_addr,
1580 1080,
1582 0, /* Priority */
1583 connection->nt,
1585 connection->d_mq);
1586}
1587
1588
1592static void
1593http_consume (struct Connection *connection, int64_t stream_id, size_t consumed)
1594{
1595 ngtcp2_conn_extend_max_stream_offset (connection->conn,
1596 stream_id,
1597 consumed);
1598 ngtcp2_conn_extend_max_offset (connection->conn,
1599 consumed);
1600}
1601
1602
1606static int
1607http_stream_close_cb (nghttp3_conn *conn, int64_t stream_id,
1608 uint64_t app_error_code, void *conn_user_data,
1609 void *stream_user_data)
1610{
1611 struct Connection *connection = conn_user_data;
1612
1613 remove_stream (connection, stream_id);
1615 "HTTP stream %lu closed\n",
1616 (unsigned long) stream_id);
1617 if (GNUNET_NO == connection->is_initiator &&
1618 ngtcp2_is_bidi_stream (stream_id))
1619 {
1620 ngtcp2_conn_extend_max_streams_bidi (connection->conn, 1);
1621 }
1622 else if (GNUNET_YES == connection->is_initiator &&
1623 ! ngtcp2_is_bidi_stream (stream_id))
1624 {
1625 ngtcp2_conn_extend_max_streams_uni (connection->conn, 1);
1626 }
1627
1628 return 0;
1629}
1630
1631
1635static int
1637 int64_t stream_id,
1638 const uint8_t *data,
1639 size_t datalen,
1640 void *user_data,
1641 void *stream_user_data)
1642{
1643 struct Connection *connection = user_data;
1644 struct GNUNET_PeerIdentity *pid;
1645 struct GNUNET_MessageHeader *hdr;
1646 int rv;
1647
1649 "http_recv_data_cb\n");
1650 http_consume (connection, stream_id, datalen);
1651
1652 if (GNUNET_NO == connection->is_initiator &&
1653 GNUNET_NO == connection->id_rcvd)
1654 {
1655 if (datalen < sizeof (struct GNUNET_PeerIdentity))
1656 {
1658 "message recv len of %zd less than length of peer identity\n",
1659 datalen);
1660 return NGHTTP3_ERR_CALLBACK_FAILURE;
1661 }
1662 pid = (struct GNUNET_PeerIdentity *) data;
1663 connection->target = *pid;
1664 connection->id_rcvd = GNUNET_YES;
1665 setup_connection_mq (connection);
1666
1667 return GNUNET_NO;
1668 }
1669
1670 hdr = (struct GNUNET_MessageHeader *) data;
1672 &connection->target,
1673 hdr,
1675 NULL,
1676 NULL);
1677 if (GNUNET_SYSERR == rv)
1678 {
1680 "GNUNET_TRANSPORT_communicator_receive:%d, hdr->len = %u, datalen = %lu, init = %d\n",
1681 rv, ntohs (hdr->size), datalen, connection->is_initiator);
1682 return NGHTTP3_ERR_CALLBACK_FAILURE;
1683 }
1685 "GNUNET_TRANSPORT_communicator_receive:%d, hdr->len = %u, datalen = %lu, init = %d\n",
1686 rv, ntohs (hdr->size), datalen, connection->is_initiator);
1687 return 0;
1688}
1689
1690
1694static int
1695http_deferred_consume_cb (nghttp3_conn *conn,
1696 int64_t stream_id,
1697 size_t nconsumed,
1698 void *user_data,
1699 void *stream_user_data)
1700{
1701 struct Connection *connection = user_data;
1702
1703 http_consume (connection,
1704 stream_id,
1705 nconsumed);
1706 return 0;
1707}
1708
1709
1713static int
1714http_begin_headers_cb (nghttp3_conn *conn, int64_t stream_id,
1715 void *user_data, void *stream_user_data)
1716{
1717 struct Connection *connection = user_data;
1718 struct Stream *stream;
1719
1720 stream = find_stream (connection, stream_id);
1721 if (NULL == stream)
1722 {
1723 return NGHTTP3_ERR_CALLBACK_FAILURE;
1724 }
1725 nghttp3_conn_set_stream_user_data (connection->h3_conn, stream_id, stream);
1726
1727 return 0;
1728}
1729
1730
1734static int
1735http_recv_header_cb (nghttp3_conn *conn, int64_t stream_id, int32_t token,
1736 nghttp3_rcbuf *name, nghttp3_rcbuf *value, uint8_t flags,
1737 void *user_data, void *stream_user_data)
1738{
1739 nghttp3_vec namebuf = nghttp3_rcbuf_get_buf (name);
1740 nghttp3_vec valbuf = nghttp3_rcbuf_get_buf (value);
1741 struct Connection *connection = user_data;
1742
1743 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "http header: [%.*s: %.*s]\n",
1744 (int) namebuf.len, namebuf.base,
1745 (int) valbuf.len, valbuf.base);
1746
1747 if (GNUNET_NO == connection->is_initiator)
1748 {
1749 struct Stream *stream = stream_user_data;
1750 switch (token)
1751 {
1752 case NGHTTP3_QPACK_TOKEN__PATH:
1753 stream->urilen = valbuf.len;
1754 stream->uri = (uint8_t *) malloc (valbuf.len);
1755 memcpy (stream->uri, valbuf.base, valbuf.len);
1756 break;
1757 case NGHTTP3_QPACK_TOKEN__METHOD:
1758 stream->methodlen = valbuf.len;
1759 stream->method = (uint8_t *) malloc (valbuf.len);
1760 memcpy (stream->method, valbuf.base, valbuf.len);
1761 break;
1762 case NGHTTP3_QPACK_TOKEN__AUTHORITY:
1763 stream->authoritylen = valbuf.len;
1764 stream->authority = (uint8_t *) malloc (valbuf.len);
1765 memcpy (stream->authority, valbuf.base, valbuf.len);
1766 break;
1767 }
1768 }
1769 return 0;
1770}
1771
1772
1776static int
1777http_stop_sending_cb (nghttp3_conn *conn, int64_t stream_id,
1778 uint64_t app_error_code, void *user_data,
1779 void *stream_user_data)
1780{
1781 struct Connection *connection = user_data;
1782 int rv;
1783
1784 rv = ngtcp2_conn_shutdown_stream_read (connection->conn,
1785 0,
1786 stream_id,
1787 app_error_code);
1788 if (0 != rv)
1789 {
1791 "ngtcp2_conn_shutdown_stream_read: %s\n",
1792 ngtcp2_strerror (rv));
1793 return NGHTTP3_ERR_CALLBACK_FAILURE;
1794 }
1795 return 0;
1796}
1797
1798
1802static int
1803http_end_stream_cb (nghttp3_conn *conn, int64_t stream_id, void *user_data,
1804 void *stream_user_data)
1805{
1806 struct Connection *connection = user_data;
1807 struct Stream *stream = stream_user_data;
1808 struct Long_Poll_Request *long_poll;
1809 int rv;
1810
1811 if (GNUNET_NO == connection->is_initiator)
1812 {
1813 // Send response
1814 rv = stream_start_response (connection, stream);
1815 if (0 != rv)
1816 {
1817 return NGHTTP3_ERR_CALLBACK_FAILURE;
1818 }
1819 }
1820 else
1821 {
1826 long_poll = connection->long_poll_head;
1827 while (NULL != long_poll)
1828 {
1829 if (stream_id == long_poll->stream->stream_id)
1830 {
1832 "client side recv GET response\n");
1833 stream = create_stream (connection, -1);
1834 rv = ngtcp2_conn_open_bidi_stream (connection->conn,
1836 if (0 != rv)
1837 {
1839 "ngtcp2_conn_open_bidi_stream: %s\n",
1840 ngtcp2_strerror (rv));
1841 }
1842 submit_get_request (connection, stream);
1843 long_poll->stream = stream;
1844 break;
1845 }
1846 long_poll = long_poll->next;
1847 }
1848 }
1849 return 0;
1850}
1851
1852
1856static int
1857http_reset_stream_cb (nghttp3_conn *conn, int64_t stream_id,
1858 uint64_t app_error_code, void *user_data,
1859 void *stream_user_data)
1860{
1861 struct Connection *connection = user_data;
1862 int rv;
1863
1864 rv = ngtcp2_conn_shutdown_stream_write (connection->conn,
1865 0,
1866 stream_id,
1867 app_error_code);
1868 if (0 != rv)
1869 {
1871 "ngtcp2_conn_shutdown_stream_write: %s\n",
1872 ngtcp2_strerror (rv));
1873 return NGHTTP3_ERR_CALLBACK_FAILURE;
1874 }
1875 return 0;
1876}
1877
1878
1886static int
1887setup_httpconn (struct Connection *connection)
1888{
1889 nghttp3_settings settings;
1890 const nghttp3_mem *mem = nghttp3_mem_default ();
1891 int64_t ctrl_stream_id;
1892 int64_t enc_stream_id;
1893 int64_t dec_stream_id;
1894 nghttp3_callbacks callbacks = {
1895 .stream_close = http_stream_close_cb,
1896 .recv_data = http_recv_data_cb,
1897 .deferred_consume = http_deferred_consume_cb,
1898 .begin_headers = http_begin_headers_cb,
1899 .recv_header = http_recv_header_cb,
1900 .stop_sending = http_stop_sending_cb,
1901 .end_stream = http_end_stream_cb,
1902 .reset_stream = http_reset_stream_cb,
1903 };
1904 int rv;
1905
1906 if (NULL != connection->h3_conn)
1907 {
1908 return GNUNET_NO;
1909 }
1910
1911 if (ngtcp2_conn_get_streams_uni_left (connection->conn) < 3)
1912 {
1914 "uni stream left less than 3\n");
1915 return GNUNET_SYSERR;
1916 }
1917
1918 if (GNUNET_YES == connection->is_initiator)
1919 {
1920 callbacks.begin_headers = NULL;
1921 // callbacks.end_stream = NULL;
1922 }
1923
1924 nghttp3_settings_default (&settings);
1925 settings.qpack_blocked_streams = 100;
1926 settings.qpack_encoder_max_dtable_capacity = 4096;
1927
1928 if (GNUNET_NO == connection->is_initiator)
1929 {
1930 const ngtcp2_transport_params *params =
1931 ngtcp2_conn_get_local_transport_params (connection->conn);
1932
1933 rv = nghttp3_conn_server_new (&connection->h3_conn,
1934 &callbacks,
1935 &settings,
1936 mem,
1937 connection);
1938 nghttp3_conn_set_max_client_streams_bidi (connection->h3_conn,
1939 params->initial_max_streams_bidi);
1940 if (0 != rv)
1941 {
1943 "nghttp3_conn_server_new: %s\n",
1944 nghttp3_strerror (rv));
1945 return GNUNET_SYSERR;
1946 }
1947 }
1948 else
1949 {
1950 rv = nghttp3_conn_client_new (&connection->h3_conn,
1951 &callbacks,
1952 &settings,
1953 mem,
1954 connection);
1955 if (0 != rv)
1956 {
1958 "nghttp3_conn_client_new: %s\n",
1959 nghttp3_strerror (rv));
1960 return GNUNET_SYSERR;
1961 }
1962 }
1963
1964 rv = ngtcp2_conn_open_uni_stream (connection->conn, &ctrl_stream_id, NULL);
1965 if (0 != rv)
1966 {
1968 "ngtcp2_conn_open_uni_stream: %s\n",
1969 ngtcp2_strerror (rv));
1970 return GNUNET_SYSERR;
1971 }
1972
1973 rv = nghttp3_conn_bind_control_stream (connection->h3_conn, ctrl_stream_id);
1974 if (0 != rv)
1975 {
1977 "nghttp3_conn_bind_control_stream: %s\n",
1978 nghttp3_strerror (rv));
1979 return GNUNET_SYSERR;
1980 }
1981
1982 rv = ngtcp2_conn_open_uni_stream (connection->conn, &enc_stream_id, NULL);
1983 if (0 != rv)
1984 {
1986 "ngtcp2_conn_open_uni_stream: %s\n",
1987 ngtcp2_strerror (rv));
1988 return GNUNET_SYSERR;
1989 }
1990
1991 rv = ngtcp2_conn_open_uni_stream (connection->conn, &dec_stream_id, NULL);
1992 if (0 != rv)
1993 {
1995 "ngtcp2_conn_open_uni_stream: %s\n",
1996 ngtcp2_strerror (rv));
1997 return GNUNET_SYSERR;
1998 }
1999
2000 rv = nghttp3_conn_bind_qpack_streams (connection->h3_conn,
2001 enc_stream_id, dec_stream_id);
2002 if (0 != rv)
2003 {
2005 "nghttp3_conn_bind_qpack_streams: %s\n",
2006 nghttp3_strerror (rv));
2007 return GNUNET_SYSERR;
2008 }
2009
2011 "Bind control stream: %" PRIi64 ", enc stream: %" PRIi64
2012 ", dec stream: %" PRIi64 "\n",
2013 ctrl_stream_id, enc_stream_id, dec_stream_id);
2014 return GNUNET_NO;
2015}
2016
2017
2021static void
2022rand_cb (uint8_t *dest,
2023 size_t destlen,
2024 const ngtcp2_rand_ctx *rand_ctx)
2025{
2026 (void) rand_ctx;
2028 destlen);
2029}
2030
2031
2035static int
2036get_new_connection_id_cb (ngtcp2_conn *conn, ngtcp2_cid *cid,
2037 uint8_t *token, size_t cidlen,
2038 void *user_data)
2039{
2040 (void) conn;
2041 (void) user_data;
2042
2043 GNUNET_CRYPTO_random_block (cid->data,
2044 cidlen);
2045 cid->datalen = cidlen;
2047 NGTCP2_STATELESS_RESET_TOKENLEN);
2048 return GNUNET_NO;
2049}
2050
2051
2055static int
2056recv_stream_data_cb (ngtcp2_conn *conn, uint32_t flags, int64_t stream_id,
2057 uint64_t offset, const uint8_t *data, size_t datalen,
2058 void *user_data,
2059 void *stream_user_data)
2060{
2061 struct Connection *connection = user_data;
2062 nghttp3_ssize nconsumed;
2063
2064 if (NULL == connection->h3_conn)
2065 {
2066 return 0;
2067 }
2068 nconsumed = nghttp3_conn_read_stream (connection->h3_conn, stream_id,
2069 data, datalen,
2070 flags & NGTCP2_STREAM_DATA_FLAG_FIN);
2071 if (nconsumed < 0)
2072 {
2074 "nghttp3_conn_read_stream: %s, init = %d\n",
2075 nghttp3_strerror (nconsumed), connection->is_initiator);
2076 ngtcp2_ccerr_set_application_error (
2077 &connection->last_error,
2078 nghttp3_err_infer_quic_app_error_code (nconsumed),
2079 NULL, 0);
2080 return NGTCP2_ERR_CALLBACK_FAILURE;
2081 }
2082 http_consume (connection, stream_id, nconsumed);
2083 return 0;
2084}
2085
2086
2090static int
2091stream_open_cb (ngtcp2_conn *conn,
2092 int64_t stream_id,
2093 void *user_data)
2094{
2095 struct Connection *connection = user_data;
2096 if (! ngtcp2_is_bidi_stream (stream_id))
2097 {
2098 return 0;
2099 }
2100 create_stream (connection, stream_id);
2101 return 0;
2102}
2103
2104
2110static int
2111stream_close_cb (ngtcp2_conn *conn, uint32_t flags, int64_t stream_id,
2112 uint64_t app_error_code, void *user_data,
2113 void *stream_user_data)
2114{
2115 struct Connection *connection = user_data;
2116 int rv;
2117
2119 "stream_close id = %" PRIi64 "\n",
2120 stream_id);
2121 if (! (flags & NGTCP2_STREAM_CLOSE_FLAG_APP_ERROR_CODE_SET))
2122 {
2123 app_error_code = NGHTTP3_H3_NO_ERROR;
2124 }
2125
2126 if (connection->h3_conn)
2127 {
2128 if (0 == app_error_code)
2129 {
2130 app_error_code = NGHTTP3_H3_NO_ERROR;
2131 }
2132
2133 rv = nghttp3_conn_close_stream (connection->h3_conn,
2134 stream_id,
2135 app_error_code);
2136 switch (rv)
2137 {
2138 case 0:
2139 break;
2140 case NGHTTP3_ERR_STREAM_NOT_FOUND:
2141 if (GNUNET_NO == connection->is_initiator &&
2142 ngtcp2_is_bidi_stream (stream_id))
2143 {
2144 ngtcp2_conn_extend_max_streams_bidi (connection->conn, 1);
2145 }
2146 else if (GNUNET_YES == connection->is_initiator &&
2147 ! ngtcp2_is_bidi_stream (stream_id))
2148 {
2149 ngtcp2_conn_extend_max_streams_uni (connection->conn, 1);
2150 }
2151 break;
2152 default:
2154 "nghttp3_conn_close_stream: %s\n",
2155 nghttp3_strerror (rv));
2156 ngtcp2_ccerr_set_application_error (
2157 &connection->last_error,
2158 nghttp3_err_infer_quic_app_error_code (rv),
2159 NULL, 0);
2160 return NGTCP2_ERR_CALLBACK_FAILURE;
2161 }
2162 }
2163 return 0;
2164}
2165
2166
2170static int
2171acked_stream_data_offset_cb (ngtcp2_conn *conn, int64_t stream_id,
2172 uint64_t offset, uint64_t datalen, void *user_data,
2173 void *stream_user_data)
2174{
2175 struct Connection *connection = user_data;
2176 int rv;
2177
2178 if (NULL == connection->h3_conn)
2179 {
2180 return 0;
2181 }
2182
2183 rv = nghttp3_conn_add_ack_offset (connection->h3_conn, stream_id, datalen);
2184 if (0 != rv)
2185 {
2187 "nghttp3_conn_add_ack_offset: %s\n",
2188 nghttp3_strerror (rv));
2189 return NGTCP2_ERR_CALLBACK_FAILURE;
2190 }
2191 return 0;
2192}
2193
2194
2198static int
2199extend_max_stream_data_cb (ngtcp2_conn *conn, int64_t stream_id,
2200 uint64_t max_data, void *user_data,
2201 void *stream_user_data)
2202{
2203 struct Connection *connection = user_data;
2204 int rv;
2205
2206 rv = nghttp3_conn_unblock_stream (connection->h3_conn, stream_id);
2207 if (0 != rv)
2208 {
2210 "nghttp3_conn_unblock_stream: %s\n",
2211 nghttp3_strerror (rv));
2212 return NGTCP2_ERR_CALLBACK_FAILURE;
2213 }
2214 return 0;
2215}
2216
2217
2221static int
2222stream_reset_cb (ngtcp2_conn *conn, int64_t stream_id, uint64_t final_size,
2223 uint64_t app_error_code, void *user_data,
2224 void *stream_user_data)
2225{
2226 struct Connection *connection = user_data;
2227 int rv;
2228
2229 if (connection->h3_conn)
2230 {
2231 rv = nghttp3_conn_shutdown_stream_read (connection->h3_conn, stream_id);
2232 if (0 != rv)
2233 {
2235 "nghttp3_conn_shutdown_stream_read: %s\n",
2236 nghttp3_strerror (rv));
2237 return NGTCP2_ERR_CALLBACK_FAILURE;
2238 }
2239 }
2240 return 0;
2241}
2242
2243
2247static int
2248extend_max_remote_streams_bidi_cb (ngtcp2_conn *conn, uint64_t max_streams,
2249 void *user_data)
2250{
2251 struct Connection *connection = user_data;
2252 if (NULL == connection->h3_conn)
2253 {
2254 return 0;
2255 }
2256 nghttp3_conn_set_max_client_streams_bidi (connection->h3_conn, max_streams);
2257 return 0;
2258}
2259
2260
2264static int
2265stream_stop_sending_cb (ngtcp2_conn *conn, int64_t stream_id,
2266 uint64_t app_error_code, void *user_data,
2267 void *stream_user_data)
2268{
2269 struct Connection *connection = user_data;
2270 int rv;
2271
2272 if (connection->h3_conn)
2273 {
2274 rv = nghttp3_conn_shutdown_stream_read (connection->h3_conn, stream_id);
2275 if (0 != rv)
2276 {
2278 "nghttp3_conn_shutdown_stream_read: %s\n",
2279 nghttp3_strerror (rv));
2280 return NGTCP2_ERR_CALLBACK_FAILURE;
2281 }
2282 }
2283 return 0;
2284}
2285
2286
2290static int
2291recv_tx_key_cb (ngtcp2_conn *conn, ngtcp2_encryption_level level,
2292 void *user_data)
2293{
2294 struct Connection *connection = user_data;
2295 int rv;
2296
2297 if (NGTCP2_ENCRYPTION_LEVEL_1RTT != level)
2298 {
2299 return 0;
2300 }
2301
2302 rv = setup_httpconn (connection);
2303 if (0 != rv)
2304 {
2305 return NGTCP2_ERR_CALLBACK_FAILURE;
2306 }
2307 return 0;
2308}
2309
2310
2314static int
2315recv_rx_key_cb (ngtcp2_conn *conn, ngtcp2_encryption_level level,
2316 void *user_data)
2317{
2318 struct Connection *connection = user_data;
2319 struct Stream *stream;
2320 struct Long_Poll_Request *long_poll;
2321 int i;
2322 int rv;
2323
2324 if (NGTCP2_ENCRYPTION_LEVEL_1RTT != level)
2325 {
2326 return 0;
2327 }
2328
2329 rv = setup_httpconn (connection);
2330 if (0 != rv)
2331 {
2332 return NGTCP2_ERR_CALLBACK_FAILURE;
2333 }
2334
2335 if (GNUNET_YES == connection->is_initiator &&
2336 GNUNET_NO == connection->id_sent)
2337 {
2338 const struct GNUNET_PeerIdentity *my_identity;
2339
2342
2343 stream = create_stream (connection, -1);
2344 rv = ngtcp2_conn_open_bidi_stream (conn, &stream->stream_id, NULL);
2345
2346 submit_post_request (connection, stream,
2347 (uint8_t *) my_identity,
2348 sizeof (*my_identity));
2349
2350 connection->id_sent = GNUNET_YES;
2351 setup_connection_mq (connection);
2352
2353 for (i = 0; i < NUM_LONG_POLL; i++)
2354 {
2355 stream = create_stream (connection, -1);
2356 rv = ngtcp2_conn_open_bidi_stream (conn, &stream->stream_id, NULL);
2357 submit_get_request (connection, stream);
2358 long_poll = GNUNET_new (struct Long_Poll_Request);
2359 long_poll->stream = stream;
2360 long_poll->next = NULL;
2361 long_poll->prev = connection->long_poll_rear;
2362 long_poll->timer = NULL;
2363 if (NULL != connection->long_poll_rear)
2364 {
2365 connection->long_poll_rear->next = long_poll;
2366 }
2367 connection->long_poll_rear = long_poll;
2368 if (NULL == connection->long_poll_head)
2369 {
2370 connection->long_poll_head = long_poll;
2371 }
2372 }
2373 }
2374 return 0;
2375}
2376
2377
2390static int
2391client_quic_init (struct Connection *connection,
2392 struct sockaddr *local_addr,
2393 socklen_t local_addrlen,
2394 struct sockaddr *remote_addr,
2395 socklen_t remote_addrlen)
2396{
2397 int rv;
2398 ngtcp2_cid dcid;
2399 ngtcp2_cid scid;
2400 ngtcp2_settings settings;
2401 ngtcp2_transport_params params;
2402 ngtcp2_path path = {
2403 {local_addr, local_addrlen},
2404 {remote_addr, remote_addrlen},
2405 NULL,
2406 };
2407 ngtcp2_callbacks callbacks = {
2408 .client_initial = ngtcp2_crypto_client_initial_cb,
2409 .recv_crypto_data = ngtcp2_crypto_recv_crypto_data_cb,
2410 .encrypt = ngtcp2_crypto_encrypt_cb,
2411 .decrypt = ngtcp2_crypto_decrypt_cb,
2412 .hp_mask = ngtcp2_crypto_hp_mask_cb,
2413 .recv_retry = ngtcp2_crypto_recv_retry_cb,
2414 .update_key = ngtcp2_crypto_update_key_cb,
2415 .delete_crypto_aead_ctx = ngtcp2_crypto_delete_crypto_aead_ctx_cb,
2416 .delete_crypto_cipher_ctx = ngtcp2_crypto_delete_crypto_cipher_ctx_cb,
2417 .get_path_challenge_data = ngtcp2_crypto_get_path_challenge_data_cb,
2418 .version_negotiation = ngtcp2_crypto_version_negotiation_cb,
2419 .rand = rand_cb,
2420 .get_new_connection_id = get_new_connection_id_cb,
2421 .recv_stream_data = recv_stream_data_cb,
2422 .stream_close = stream_close_cb,
2423 .acked_stream_data_offset = acked_stream_data_offset_cb,
2424 .extend_max_stream_data = extend_max_stream_data_cb,
2425 .stream_reset = stream_reset_cb,
2426 .stream_stop_sending = stream_stop_sending_cb,
2427 .recv_rx_key = recv_rx_key_cb,
2428 };
2429
2430
2431 scid.datalen = NGTCP2_MAX_CIDLEN;
2432 GNUNET_CRYPTO_random_block (scid.data,
2433 scid.datalen);
2434 dcid.datalen = NGTCP2_MAX_CIDLEN;
2435 GNUNET_CRYPTO_random_block (dcid.data,
2436 dcid.datalen);
2437 ngtcp2_settings_default (&settings);
2438 settings.initial_ts = timestamp ();
2439
2440 ngtcp2_transport_params_default (&params);
2441 params.initial_max_streams_uni = 100;
2442 params.initial_max_stream_data_bidi_local = 6291456;
2443 params.initial_max_data = 15728640;
2444 params.initial_max_stream_data_bidi_remote = 0;
2445 params.initial_max_stream_data_uni = 6291456;
2446 params.initial_max_streams_bidi = 0;
2447 params.max_idle_timeout = 30 * NGTCP2_SECONDS;
2448 params.active_connection_id_limit = 7;
2449 params.grease_quic_bit = 1;
2450 rv = ngtcp2_conn_client_new (&connection->conn,
2451 &dcid,
2452 &scid,
2453 &path,
2454 NGTCP2_PROTO_VER_V1,
2455 &callbacks,
2456 &settings,
2457 &params,
2458 NULL,
2459 connection);
2460 if (GNUNET_NO != rv)
2461 {
2463 "ngtcp2_conn_client_new: %s\n",
2464 ngtcp2_strerror (rv));
2465 return GNUNET_SYSERR;
2466 }
2467 ngtcp2_conn_set_tls_native_handle (connection->conn, connection->session);
2468 connection->conn_ref.user_data = connection;
2469 connection->conn_ref.get_conn = get_conn;
2470 return GNUNET_NO;
2471}
2472
2473
2479static void
2480close_waitcb (void *cls)
2481{
2482 struct Connection *connection = cls;
2483 connection->timer = NULL;
2484
2485 if (ngtcp2_conn_in_closing_period (connection->conn))
2486 {
2488 "Closing period over\n");
2489 connection_destroy (connection);
2490 return;
2491 }
2492 if (ngtcp2_conn_in_draining_period (connection->conn))
2493 {
2495 "Draining period over\n");
2496 connection_destroy (connection);
2497 return;
2498 }
2499}
2500
2501
2507static void
2509{
2510 ngtcp2_duration pto;
2511 struct GNUNET_TIME_Relative delay;
2512
2513 if (NULL != connection->timer)
2514 {
2515 GNUNET_SCHEDULER_cancel (connection->timer);
2516 connection->timer = NULL;
2517 }
2518 pto = ngtcp2_conn_get_pto (connection->conn);
2520 pto / 1000ULL * 3);
2521 connection->timer = GNUNET_SCHEDULER_add_delayed (delay,
2523 connection);
2525 "Start draining period\n");
2526}
2527
2528
2539static int
2541{
2542 ngtcp2_path_storage ps;
2543 ngtcp2_pkt_info pi;
2544 ngtcp2_ssize nwrite;
2545 ngtcp2_duration pto;
2546 struct GNUNET_TIME_Relative delay;
2547
2548 if (NULL == connection->conn ||
2549 ngtcp2_conn_in_closing_period (connection->conn) ||
2550 ngtcp2_conn_in_draining_period (connection->conn))
2551 {
2552 return GNUNET_NO;
2553 }
2554
2556 "Start closing period\n");
2557
2558 if (GNUNET_NO == connection->is_initiator)
2559 {
2560 if (NULL != connection->timer)
2561 {
2562 GNUNET_SCHEDULER_cancel (connection->timer);
2563 connection->timer = NULL;
2564 }
2565 pto = ngtcp2_conn_get_pto (connection->conn);
2567 pto / 1000ULL * 3);
2568 connection->timer = GNUNET_SCHEDULER_add_delayed (delay,
2570 connection);
2571 }
2572
2573 connection->conn_closebuf =
2574 GNUNET_new_array (NGTCP2_MAX_UDP_PAYLOAD_SIZE, uint8_t);
2575
2576 ngtcp2_path_storage_zero (&ps);
2577 nwrite = ngtcp2_conn_write_connection_close (connection->conn,
2578 &ps.path,
2579 &pi,
2580 connection->conn_closebuf,
2581 NGTCP2_MAX_UDP_PAYLOAD_SIZE,
2582 &connection->last_error,
2583 timestamp ());
2584 if (nwrite < 0)
2585 {
2587 "ngtcp2_conn_write_connection_close: %s\n",
2588 ngtcp2_strerror (nwrite));
2589 return GNUNET_SYSERR;
2590 }
2591 if (0 == nwrite)
2592 {
2593 return GNUNET_NO;
2594 }
2595 connection->conn_closebuflen = nwrite;
2596 if (GNUNET_YES == connection->is_initiator)
2597 {
2598 return send_packet (connection,
2599 connection->conn_closebuf,
2600 connection->conn_closebuflen);
2601 }
2602 return GNUNET_NO;
2603}
2604
2605
2612static int
2613send_conn_close (struct Connection *connection)
2614{
2615 int rv;
2616
2618 "Closing period, send CONNECTION_CLOSE\n");
2619 rv = send_packet (connection,
2620 connection->conn_closebuf,
2621 connection->conn_closebuflen);
2622 return rv;
2623}
2624
2625
2633static int
2634handle_error (struct Connection *connection)
2635{
2636 int rv;
2637
2638 /* if we are the client side */
2639 if (GNUNET_YES == connection->is_initiator)
2640 {
2641 /* this will send CONNECTION_CLOSE immediately and don't wait */
2642 start_closing_period (connection);
2643 connection_destroy (connection);
2644 return GNUNET_SYSERR;
2645 }
2646
2647 if (NGTCP2_CCERR_TYPE_IDLE_CLOSE == connection->last_error.type)
2648 {
2649 return GNUNET_SYSERR;
2650 }
2651
2652 if (GNUNET_NO != start_closing_period (connection))
2653 {
2654 return GNUNET_SYSERR;
2655 }
2656
2657 if (ngtcp2_conn_in_draining_period (connection->conn))
2658 {
2660 }
2661
2662 rv = send_conn_close (connection);
2663 if (NETWORK_ERR_OK != rv)
2664 {
2665 return rv;
2666 }
2667
2669}
2670
2671
2678static int
2679handle_expiry (struct Connection *connection)
2680{
2681 int rv;
2682
2683 rv = ngtcp2_conn_handle_expiry (connection->conn, timestamp ());
2684 if (0 != rv)
2685 {
2687 "ngtcp2_conn_handle_expiry: %s\n",
2688 ngtcp2_strerror (rv));
2689 ngtcp2_ccerr_set_liberr (&connection->last_error, rv, NULL, 0);
2690 return handle_error (connection);
2691 }
2692 return GNUNET_NO;
2693}
2694
2695
2701static void
2702timeoutcb (void *cls)
2703{
2704 struct Connection *connection = cls;
2705 int rv;
2706
2708 "timeoutcb func called!\n");
2709 connection->timer = NULL;
2710
2711 rv = handle_expiry (connection);
2712 if (GNUNET_NO != rv)
2713 {
2714 if (GNUNET_YES == connection->is_initiator)
2715 {
2716 return;
2717 }
2718 switch (rv)
2719 {
2721 return;
2722 default:
2723 connection_destroy (connection);
2724 return;
2725 }
2726 }
2727
2728 rv = connection_write (connection);
2729 if (GNUNET_YES == connection->is_initiator)
2730 {
2731 return;
2732 }
2733 if (GNUNET_NO != rv)
2734 {
2735 switch (rv)
2736 {
2738 return;
2739 default:
2740 connection_destroy (connection);
2741 return;
2742 }
2743
2744 }
2745}
2746
2747
2753static void
2755{
2756 ngtcp2_tstamp expiry;
2757 ngtcp2_tstamp now;
2758 struct GNUNET_TIME_Relative delay;
2759
2761 "update_timer!\n");
2762 expiry = ngtcp2_conn_get_expiry (connection->conn);
2763 now = timestamp ();
2764
2765 if (NULL != connection->timer)
2766 {
2767 GNUNET_SCHEDULER_cancel (connection->timer);
2768 connection->timer = NULL;
2769 }
2770 if (now >= expiry)
2771 {
2773 "Timer has expired\n");
2774 connection->timer = GNUNET_SCHEDULER_add_now (timeoutcb, connection);
2775 return;
2776 }
2777
2779 "Timer set: %lf\n",
2780 (double) (expiry - now) / NGTCP2_SECONDS);
2781 /* ngtcp2_tstamp is nanosecond */
2783 (expiry - now) / 1000ULL + 1);
2784 connection->timer = GNUNET_SCHEDULER_add_delayed (delay, timeoutcb,
2785 connection);
2786}
2787
2788
2796static int
2798{
2799 uint8_t buf[1280];
2800 ngtcp2_tstamp ts = timestamp ();
2801 ngtcp2_path_storage ps;
2802 int64_t stream_id;
2803 uint32_t flags;
2804 ngtcp2_ssize nwrite;
2805 ngtcp2_ssize wdatalen;
2806 nghttp3_vec vec[16];
2807 nghttp3_ssize sveccnt;
2808 ngtcp2_pkt_info pi;
2809 int fin;
2810 int rv;
2811
2812 ngtcp2_path_storage_zero (&ps);
2813
2814 for (;;)
2815 {
2816 stream_id = -1;
2817 fin = 0;
2818 sveccnt = 0;
2819
2820 if (connection->h3_conn &&
2821 ngtcp2_conn_get_max_data_left (connection->conn))
2822 {
2823 sveccnt = nghttp3_conn_writev_stream (connection->h3_conn,
2824 &stream_id,
2825 &fin,
2826 vec,
2827 16);
2828 if (sveccnt < 0)
2829 {
2831 "nghttp3_conn_writev_stream: %s\n",
2832 nghttp3_strerror (sveccnt));
2833
2834 ngtcp2_ccerr_set_application_error (
2835 &connection->last_error,
2836 nghttp3_err_infer_quic_app_error_code (sveccnt),
2837 NULL,
2838 0);
2839 return handle_error (connection);
2840 }
2841 }
2842
2843 flags = NGTCP2_WRITE_STREAM_FLAG_MORE;
2844 if (fin)
2845 flags |= NGTCP2_WRITE_STREAM_FLAG_FIN;
2846
2847 nwrite = ngtcp2_conn_writev_stream (connection->conn,
2848 &ps.path,
2849 &pi,
2850 buf,
2851 sizeof(buf),
2852 &wdatalen,
2853 flags,
2854 stream_id,
2855 (ngtcp2_vec *) vec,
2856 (size_t) sveccnt,
2857 ts);
2858 if (nwrite < 0)
2859 {
2860 switch (nwrite)
2861 {
2862 case NGTCP2_ERR_STREAM_DATA_BLOCKED:
2863 nghttp3_conn_block_stream (connection->h3_conn, stream_id);
2864 continue;
2865 case NGTCP2_ERR_STREAM_SHUT_WR:
2866 nghttp3_conn_shutdown_stream_write (connection->h3_conn, stream_id);
2867 continue;
2868 case NGTCP2_ERR_WRITE_MORE:
2869 rv = nghttp3_conn_add_write_offset (connection->h3_conn, stream_id,
2870 wdatalen);
2871 if (0 != rv)
2872 {
2874 "nghttp3_conn_add_write_offset: %s\n",
2875 nghttp3_strerror (rv));
2876 ngtcp2_ccerr_set_application_error (
2877 &connection->last_error,
2878 nghttp3_err_infer_quic_app_error_code (rv),
2879 NULL, 0);
2880 return handle_error (connection);
2881 }
2882 continue;
2883 }
2885 "ngtcp2_conn_writev_stream: %s\n",
2886 ngtcp2_strerror (nwrite));
2887 ngtcp2_ccerr_set_liberr (&connection->last_error,
2888 nwrite,
2889 NULL,
2890 0);
2891 return handle_error (connection);
2892 }
2893 if (0 == nwrite)
2894 {
2895 ngtcp2_conn_update_pkt_tx_time (connection->conn, ts);
2896 return 0;
2897 }
2898 if (wdatalen > 0)
2899 {
2900 rv = nghttp3_conn_add_write_offset (connection->h3_conn, stream_id,
2901 wdatalen);
2902 if (0 != rv)
2903 {
2905 "nghttp3_conn_add_write_offset: %s\n",
2906 nghttp3_strerror (rv));
2907 ngtcp2_ccerr_set_application_error (
2908 &connection->last_error,
2909 nghttp3_err_infer_quic_app_error_code (rv),
2910 NULL, 0);
2911 return handle_error (connection);
2912 }
2913 }
2914 if (GNUNET_NO != send_packet (connection, buf, nwrite))
2915 break;
2916 }
2917
2918 return GNUNET_NO;
2919}
2920
2921
2929static int
2930connection_write (struct Connection *connection)
2931{
2932 int rv;
2933
2934 if (GNUNET_NO == connection->is_initiator &&
2935 (ngtcp2_conn_in_closing_period (connection->conn) ||
2936 ngtcp2_conn_in_draining_period (connection->conn)))
2937 {
2938 return GNUNET_NO;
2939 }
2940
2941 rv = connection_write_streams (connection);
2942 if (GNUNET_NO != rv)
2943 {
2944 return rv;
2945 }
2946 connection_update_timer (connection);
2947
2948 return GNUNET_NO;
2949}
2950
2951
2970static int
2971mq_init (void *cls,
2972 const struct GNUNET_PeerIdentity *peer_id,
2973 const char *address)
2974{
2975 struct Connection *connection;
2976 struct sockaddr *local_addr;
2977 socklen_t local_addrlen;
2978 struct sockaddr *remote_addr;
2979 socklen_t remote_addrlen;
2980 const char *path;
2981 char *bindto;
2982 struct GNUNET_HashCode remote_addr_key;
2983 int rv;
2984
2985 if (GNUNET_OK !=
2988 "BINDTO",
2989 &bindto))
2990 {
2993 "BINDTO");
2994 return GNUNET_SYSERR;
2995 }
2996 local_addr = udp_address_to_sockaddr (bindto, &local_addrlen);
2997 if (0 != strncmp (address,
2999 strlen (COMMUNICATOR_ADDRESS_PREFIX "-")))
3000 {
3001 GNUNET_break_op (0);
3002 return GNUNET_SYSERR;
3003 }
3004 path = &address[strlen (COMMUNICATOR_ADDRESS_PREFIX "-")];
3005 remote_addr = udp_address_to_sockaddr (path, &remote_addrlen);
3006
3007 GNUNET_CRYPTO_hash (address, strlen (address), &remote_addr_key);
3008 connection = GNUNET_CONTAINER_multihashmap_get (addr_map, &remote_addr_key);
3009 if (NULL != connection)
3010 {
3012 "receiver %s already exist or is being connected to\n",
3013 address);
3014 return GNUNET_SYSERR;
3015 }
3016
3017 /* Create a new connection */
3018 connection = GNUNET_new (struct Connection);
3019 connection->address = remote_addr;
3020 connection->address_len = remote_addrlen;
3021 connection->target = *peer_id;
3022 connection->is_initiator = GNUNET_YES;
3023 connection->id_rcvd = GNUNET_YES;
3024 connection->id_sent = GNUNET_NO;
3025 connection->foreign_addr =
3026 sockaddr_to_udpaddr_string (connection->address, connection->address_len);
3027 connection->nt = GNUNET_NT_scanner_get_type (is,
3029 remote_addrlen);
3030 connection->timeout =
3034 &remote_addr_key,
3035 connection,
3038 "# connections active",
3040 GNUNET_NO);
3041
3042 /* client_gnutls_init */
3043 rv = client_gnutls_init (connection);
3044 if (GNUNET_NO != rv)
3045 {
3046 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "client_gnutls_init failed\n");
3047 return GNUNET_SYSERR;
3048 }
3049
3050 /* client_quic_init */
3051 rv = client_quic_init (connection,
3052 local_addr, local_addrlen,
3053 remote_addr, remote_addrlen);
3054 if (GNUNET_NO != rv)
3055 {
3056 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "client_quic_init failed\n");
3057 return GNUNET_SYSERR;
3058 }
3059
3060 ngtcp2_conn_set_tls_native_handle (connection->conn, connection->session);
3061
3062 rv = connection_write (connection);
3063 if (GNUNET_NO != rv)
3064 {
3066 "connection_write failed\n");
3067 return GNUNET_SYSERR;
3068 }
3070 return GNUNET_OK;
3071}
3072
3073
3087static void
3089 void **app_ctx,
3090 int add_remove,
3092 const struct sockaddr *addr,
3093 socklen_t addrlen)
3094{
3095 char *my_addr;
3097
3098 if (GNUNET_YES == add_remove)
3099 {
3101
3102 GNUNET_asprintf (&my_addr,
3103 "%s-%s",
3105 GNUNET_a2s (addr, addrlen));
3106 nt = GNUNET_NT_scanner_get_type (is, addr, addrlen);
3107 ai =
3109 my_addr,
3110 nt,
3112 GNUNET_free (my_addr);
3113 *app_ctx = ai;
3114 }
3115 else
3116 {
3117 ai = *app_ctx;
3119 *app_ctx = NULL;
3120 }
3121}
3122
3123
3132static int
3134 const struct GNUNET_HashCode *key,
3135 void *value)
3136{
3137 struct Connection *connection = value;
3138 (void) cls;
3139 (void) key;
3140 handle_error (connection);
3141 connection_destroy (connection);
3142 return GNUNET_OK;
3143}
3144
3145
3151static void
3152do_shutdown (void *cls)
3153{
3155 "do_shutdown start\n");
3158 NULL);
3160 gnutls_certificate_free_credentials (cred);
3161
3162 if (NULL != nat)
3163 {
3165 nat = NULL;
3166 }
3167 if (NULL != read_task)
3168 {
3170 read_task = NULL;
3171 }
3172 if (NULL != udp_sock)
3173 {
3176 udp_sock = NULL;
3177 }
3178 if (NULL != ch)
3179 {
3181 ch = NULL;
3182 }
3183 if (NULL != stats)
3184 {
3186 stats = NULL;
3187 }
3188 if (NULL != pils)
3189 {
3191 pils = NULL;
3192 }
3193 if (NULL != is)
3194 {
3196 is = NULL;
3197 }
3199 "do_shutdown finished\n");
3200}
3201
3202
3217static int
3219 struct sockaddr *local_addr, socklen_t local_addrlen,
3220 struct sockaddr *remote_addr, socklen_t remote_addrlen,
3221 const ngtcp2_pkt_info *pi,
3222 const uint8_t *data, size_t datalen)
3223{
3224 ngtcp2_path path;
3225 int rv;
3226
3227 path.local.addr = local_addr;
3228 path.local.addrlen = local_addrlen;
3229 path.remote.addr = remote_addr;
3230 path.remote.addrlen = remote_addrlen;
3231
3232 rv = ngtcp2_conn_read_pkt (connection->conn, &path, pi, data, datalen,
3233 timestamp ());
3234 if (0 != rv)
3235 {
3237 "ngtcp2_conn_read_pkt: %s\n",
3238 ngtcp2_strerror (rv));
3239 switch (rv)
3240 {
3241 case NGTCP2_ERR_DRAINING:
3242 if (GNUNET_NO == connection->is_initiator)
3243 {
3244 start_draining_period (connection);
3246 }
3247 else
3248 {
3249 ngtcp2_ccerr_set_liberr (&connection->last_error, rv, NULL, 0);
3250 }
3251 case NGTCP2_ERR_RETRY:
3252 /* client side doesn't get this */
3253 return NETWORK_ERR_RETRY;
3254 case NGTCP2_ERR_DROP_CONN:
3255 /* client side doesn't get this */
3256 return NETWORK_ERR_DROP_CONN;
3257 case NGTCP2_ERR_CRYPTO:
3258 if (! connection->last_error.error_code)
3259 {
3260 ngtcp2_ccerr_set_tls_alert (
3261 &connection->last_error,
3262 ngtcp2_conn_get_tls_alert (connection->conn),
3263 NULL, 0);
3264 }
3265 break;
3266 default:
3267 if (! connection->last_error.error_code)
3268 {
3269 ngtcp2_ccerr_set_liberr (&connection->last_error, rv, NULL, 0);
3270 }
3271 }
3272 return handle_error (connection);
3273 }
3274 return GNUNET_NO;
3275}
3276
3277
3293static int
3294connection_on_read (struct Connection *connection,
3295 struct sockaddr *local_addr, socklen_t local_addrlen,
3296 struct sockaddr *remote_addr, socklen_t remote_addrlen,
3297 const ngtcp2_pkt_info *pi,
3298 const uint8_t *data, size_t datalen)
3299{
3300 int rv;
3301 rv = connection_feed_data (connection, local_addr, local_addrlen, remote_addr,
3302 remote_addrlen, pi, data, datalen);
3303 if (GNUNET_NO != rv)
3304 {
3305 return rv;
3306 }
3307
3308 connection_update_timer (connection);
3309 return GNUNET_NO;
3310}
3311
3312
3326static struct Connection *
3327connection_init (struct sockaddr *local_addr,
3328 socklen_t local_addrlen,
3329 struct sockaddr *remote_addr,
3330 socklen_t remote_addrlen,
3331 const ngtcp2_cid *dcid, const ngtcp2_cid *scid,
3332 uint32_t version)
3333{
3334 struct Connection *new_connection;
3335 ngtcp2_path path;
3336 ngtcp2_transport_params params;
3337 ngtcp2_cid scid_;
3338 ngtcp2_conn *conn = NULL;
3339 ngtcp2_settings settings;
3340 ngtcp2_callbacks callbacks = {
3341 .recv_client_initial = ngtcp2_crypto_recv_client_initial_cb,
3342 .recv_crypto_data = ngtcp2_crypto_recv_crypto_data_cb,
3343 .encrypt = ngtcp2_crypto_encrypt_cb,
3344 .decrypt = ngtcp2_crypto_decrypt_cb,
3345 .hp_mask = ngtcp2_crypto_hp_mask_cb,
3346 .update_key = ngtcp2_crypto_update_key_cb,
3347 .delete_crypto_aead_ctx = ngtcp2_crypto_delete_crypto_aead_ctx_cb,
3348 .delete_crypto_cipher_ctx = ngtcp2_crypto_delete_crypto_cipher_ctx_cb,
3349 .get_path_challenge_data = ngtcp2_crypto_get_path_challenge_data_cb,
3350 .version_negotiation = ngtcp2_crypto_version_negotiation_cb,
3351
3352 .acked_stream_data_offset = acked_stream_data_offset_cb,
3353 .recv_stream_data = recv_stream_data_cb,
3354 .stream_open = stream_open_cb,
3355 .rand = rand_cb,
3356 .get_new_connection_id = get_new_connection_id_cb,
3357 .stream_close = stream_close_cb,
3358 .extend_max_remote_streams_bidi = extend_max_remote_streams_bidi_cb,
3359 .stream_stop_sending = stream_stop_sending_cb,
3360 .extend_max_stream_data = extend_max_stream_data_cb,
3361 .recv_tx_key = recv_tx_key_cb,
3362 };
3363
3364
3365 int rv;
3366
3367 path.local.addr = local_addr;
3368 path.local.addrlen = local_addrlen;
3369 path.remote.addr = remote_addr;
3370 path.remote.addrlen = remote_addrlen;
3371
3372 new_connection = GNUNET_new (struct Connection);
3373 memset (new_connection, 0, sizeof (struct Connection));
3374
3375 gnutls_init (&new_connection->session,
3376 GNUTLS_SERVER
3377 | GNUTLS_ENABLE_EARLY_DATA
3378 | GNUTLS_NO_END_OF_EARLY_DATA);
3379 gnutls_priority_set_direct (new_connection->session, PRIORITY, NULL);
3380 gnutls_credentials_set (new_connection->session,
3381 GNUTLS_CRD_CERTIFICATE, cred);
3382
3383 ngtcp2_transport_params_default (&params);
3384 params.initial_max_streams_uni = 3;
3385 params.initial_max_streams_bidi = 128;
3386 params.initial_max_stream_data_bidi_local = 128 * 1024;
3387 params.initial_max_stream_data_bidi_remote = 256 * 1024;
3388 params.initial_max_stream_data_uni = 256 * 1024;
3389 params.initial_max_data = 1024 * 1024;
3390 params.original_dcid_present = 1;
3391 params.max_idle_timeout = 30 * NGTCP2_SECONDS;
3392 params.original_dcid = *scid;
3393
3394 ngtcp2_settings_default (&settings);
3395
3396 scid_.datalen = NGTCP2_MAX_CIDLEN;
3397 GNUNET_CRYPTO_random_block (&scid_.data,
3398 scid_.datalen);
3399
3400 rv = ngtcp2_conn_server_new (&conn,
3401 dcid,
3402 &scid_,
3403 &path,
3404 version,
3405 &callbacks,
3406 &settings,
3407 &params,
3408 NULL,
3409 new_connection);
3410 if (rv < 0)
3411 {
3413 "ngtcp2_conn_server_new: %s\n",
3414 ngtcp2_strerror (rv));
3415 return NULL;
3416 }
3417 new_connection->conn = conn;
3418 new_connection->address = GNUNET_memdup (remote_addr, remote_addrlen);
3419 new_connection->address_len = remote_addrlen;
3420 new_connection->foreign_addr =
3421 sockaddr_to_udpaddr_string (new_connection->address,
3422 new_connection->address_len);
3423 new_connection->is_initiator = GNUNET_NO;
3424 new_connection->id_rcvd = GNUNET_NO;
3425 new_connection->id_sent = GNUNET_NO;
3426 ngtcp2_crypto_gnutls_configure_server_session (new_connection->session);
3427 ngtcp2_conn_set_tls_native_handle (new_connection->conn,
3428 new_connection->session);
3429 gnutls_session_set_ptr (new_connection->session,
3430 &new_connection->conn_ref);
3431
3432 new_connection->conn_ref.get_conn = get_conn;
3433 new_connection->conn_ref.user_data = new_connection;
3434 new_connection->streams = GNUNET_CONTAINER_multihashmap_create (10,
3435 GNUNET_NO);
3436
3437 return new_connection;
3438}
3439
3440
3455static void
3456server_read_pkt (struct Connection *connection,
3457 const struct GNUNET_HashCode *addr_key,
3458 struct sockaddr *local_addr, socklen_t local_addrlen,
3459 struct sockaddr *remote_addr, socklen_t remote_addrlen,
3460 const ngtcp2_pkt_info *pi,
3461 const uint8_t *data, size_t datalen)
3462{
3463 ngtcp2_version_cid version_cid;
3464 int rv;
3465
3466 rv = ngtcp2_pkt_decode_version_cid (&version_cid, data, datalen,
3467 NGTCP2_MAX_CIDLEN);
3468 switch (rv)
3469 {
3470 case 0:
3471 break;
3472 case NGTCP2_ERR_VERSION_NEGOTIATION:
3473 // TODO: send version negotiation
3474 return;
3475 default:
3477 "Can't decode version and CID: %s\n",
3478 ngtcp2_strerror (rv));
3479 return;
3480 }
3481
3482 if (NULL == connection)
3483 {
3484 ngtcp2_pkt_hd header;
3485 rv = ngtcp2_accept (&header, data, datalen);
3486 if (0 != rv)
3487 {
3489 "ngtcp2_accept: %s\n",
3490 ngtcp2_strerror (rv));
3491 return;
3492 }
3493
3498 connection = connection_init (local_addr, local_addrlen, remote_addr,
3499 remote_addrlen, &header.scid, &header.dcid,
3500 header.version);
3501 if (NULL == connection)
3502 {
3504 "accept connection error!\n");
3505 return;
3506 }
3507
3509 addr_key,
3510 connection,
3512 rv = connection_on_read (connection, local_addr, local_addrlen, remote_addr,
3513 remote_addrlen, pi, data, datalen);
3514 switch (rv)
3515 {
3516 case 0:
3517 break;
3518 case NETWORK_ERR_RETRY:
3519 // TODO: send retry
3520 return;
3521 default:
3522 return;
3523 }
3524
3525 rv = connection_write (connection);
3526 if (GNUNET_NO != rv)
3527 {
3528 return;
3529 }
3530
3531 // add to cid_map here
3532 return;
3533 }
3534
3535 if (ngtcp2_conn_in_closing_period (connection->conn))
3536 {
3537 rv = send_conn_close (connection);
3538 if (GNUNET_NO != rv)
3539 {
3540 connection_destroy (connection);
3541 }
3542 return;
3543 }
3544
3545 if (ngtcp2_conn_in_draining_period (connection->conn))
3546 {
3547 return;
3548 }
3549
3550 rv = connection_on_read (connection, local_addr, local_addrlen, remote_addr,
3551 remote_addrlen, pi, data, datalen);
3552 if (GNUNET_NO != rv)
3553 {
3554 if (NETWORK_ERR_CLOSE_WAIT != rv)
3555 {
3556 connection_destroy (connection);
3557 }
3558 return;
3559 }
3560
3561 connection_write (connection);
3562}
3563
3564
3570static void
3571sock_read (void *cls)
3572{
3573 struct sockaddr_storage sa;
3574 socklen_t salen = sizeof (sa);
3575 ssize_t rcvd;
3576 uint8_t buf[UINT16_MAX];
3577 struct GNUNET_HashCode addr_key;
3578 struct Connection *connection;
3579 int rv;
3580 char *bindto;
3581 struct sockaddr *local_addr;
3582 socklen_t local_addrlen;
3583
3584 (void) cls;
3585 if (GNUNET_OK !=
3588 "BINDTO",
3589 &bindto))
3590 {
3593 "BINDTO");
3594 return;
3595 }
3596 local_addr = udp_address_to_sockaddr (bindto, &local_addrlen);
3598 udp_sock,
3599 &sock_read,
3600 NULL);
3601
3602 while (1)
3603 {
3604 char *addr_string;
3605
3607 buf,
3608 sizeof(buf),
3609 (struct sockaddr *) &sa,
3610 &salen);
3611 if (-1 == rcvd)
3612 {
3613 struct sockaddr *addr = (struct sockaddr*) &sa;
3614
3615 if (EAGAIN == errno)
3616 break; // We are done reading data
3618 "Failed to recv from %s family %d failed sock %p\n",
3619 GNUNET_a2s ((struct sockaddr*) &sa,
3620 sizeof (*addr)),
3621 addr->sa_family,
3622 udp_sock);
3624 return;
3625 }
3627 "Read %llu bytes\n",
3628 (unsigned long long) rcvd);
3629 if (0 == rcvd)
3630 {
3631 GNUNET_break_op (0);
3633 "Read 0 bytes from UDP socket\n");
3634 return;
3635 }
3636
3637 addr_string =
3638 sockaddr_to_udpaddr_string ((const struct sockaddr *) &sa,
3639 salen);
3640 GNUNET_CRYPTO_hash (addr_string, strlen (addr_string),
3641 &addr_key);
3642 GNUNET_free (addr_string);
3643 connection = GNUNET_CONTAINER_multihashmap_get (addr_map, &addr_key);
3644
3645 if (NULL != connection && GNUNET_YES == connection->is_initiator)
3646 {
3647 ngtcp2_pkt_info pi = {0};
3648
3649 rv = connection_feed_data (connection, local_addr, local_addrlen,
3650 (struct sockaddr *) &sa,
3651 salen, &pi, buf, rcvd);
3652 if (GNUNET_NO != rv)
3653 {
3654 return;
3655 }
3656 rv = connection_write (connection);
3657 if (rv < 0)
3658 {
3660 "connection write error!\n");
3661 return;
3662 }
3663 }
3664 else
3665 {
3666 ngtcp2_pkt_info pi = {0};
3667
3668 server_read_pkt (connection, &addr_key,
3669 local_addr, local_addrlen,
3670 (struct sockaddr *) &sa, salen,
3671 &pi, buf, rcvd);
3672 }
3673
3674 }
3675
3677
3678}
3679
3680
3689static void
3690run (void *cls,
3691 char *const *args,
3692 const char *cfgfile,
3693 const struct GNUNET_CONFIGURATION_Handle *c)
3694{
3695 char *bindto;
3696 struct sockaddr *in;
3697 socklen_t in_len;
3698 struct sockaddr_storage in_sto;
3699 socklen_t sto_len;
3700 char *cert_file;
3701 char *key_file;
3702 int rv;
3703
3704 (void) cls;
3705 cfg = c;
3706 if (GNUNET_OK !=
3709 "BINDTO",
3710 &bindto))
3711 {
3714 "BINDTO");
3715 return;
3716 }
3717
3718 key_file = NULL;
3719 cert_file = NULL;
3720 if ((GNUNET_OK !=
3723 "KEY_FILE",
3724 &key_file)))
3725 key_file = GNUNET_strdup ("https.key");
3726 if (GNUNET_OK !=
3729 "CERT_FILE",
3730 &cert_file))
3731 cert_file = GNUNET_strdup ("https.crt");
3732 if ((GNUNET_OK != GNUNET_DISK_file_test (key_file)) ||
3733 (GNUNET_OK != GNUNET_DISK_file_test (cert_file)))
3734 {
3735 struct GNUNET_Process *cert_creation;
3736
3738 "Creating new certificate\n");
3740 if (GNUNET_OK !=
3742 cert_creation,
3743 "gnunet-transport-certificate-creation",
3744 "gnunet-transport-certificate-creation",
3745 key_file,
3746 cert_file,
3747 NULL))
3748 {
3749 GNUNET_process_destroy (cert_creation);
3751 "Can't create new key pair %s/%s\n",
3752 key_file,
3753 cert_file);
3754 GNUNET_free (key_file);
3755 GNUNET_free (cert_file);
3756 return;
3757 }
3759 GNUNET_process_wait (cert_creation,
3760 true,
3761 NULL,
3762 NULL));
3763 GNUNET_process_destroy (cert_creation);
3764 }
3765
3767 if ((GNUNET_NO == GNUNET_NETWORK_test_pf (PF_INET6)) ||
3768 (GNUNET_YES ==
3771 "DISABLE_V6")))
3772 {
3774 }
3775
3776 in = udp_address_to_sockaddr (bindto, &in_len);
3777
3778 if (NULL == in)
3779 {
3781 "Failed to setup UDP socket address with path `%s'\n",
3782 bindto);
3783 GNUNET_free (bindto);
3784 return;
3785 }
3786 udp_sock =
3787 GNUNET_NETWORK_socket_create (in->sa_family,
3788 SOCK_DGRAM,
3789 IPPROTO_UDP);
3790 if (NULL == udp_sock)
3791 {
3794 "Failed to create socket for %s family %d\n",
3795 GNUNET_a2s (in,
3796 in_len),
3797 in->sa_family);
3798 GNUNET_free (in);
3799 GNUNET_free (bindto);
3800 return;
3801 }
3802 if (AF_INET6 == in->sa_family)
3804 if (GNUNET_OK !=
3806 in,
3807 in_len))
3808 {
3810 "bind",
3811 bindto);
3813 "Failed to bind socket for %s family %d sock %p\n",
3814 GNUNET_a2s (in,
3815 in_len),
3816 in->sa_family,
3817 udp_sock);
3819 udp_sock = NULL;
3820 GNUNET_free (in);
3821 GNUNET_free (bindto);
3822 return;
3823 }
3824 sto_len = sizeof(in_sto);
3825 if (0 != getsockname (GNUNET_NETWORK_get_fd (udp_sock),
3826 (struct sockaddr *) &in_sto,
3827 &sto_len))
3828 {
3829 memcpy (&in_sto, in, in_len);
3830 sto_len = in_len;
3831 }
3832 GNUNET_free (in);
3833 GNUNET_free (bindto);
3834 in = (struct sockaddr *) &in_sto;
3835 in_len = sto_len;
3837 "transport",
3838 "Bound to `%s' sock %p\n",
3839 GNUNET_a2s ((const struct sockaddr *) &in_sto,
3840 sto_len),
3841 udp_sock);
3842 switch (in->sa_family)
3843 {
3844 case AF_INET:
3845 my_port = ntohs (((struct sockaddr_in *) in)->sin_port);
3846 break;
3847
3848 case AF_INET6:
3849 my_port = ntohs (((struct sockaddr_in6 *) in)->sin6_port);
3850 break;
3851
3852 default:
3853 GNUNET_break (0);
3854 my_port = 0;
3855 }
3857
3860
3861 rv = gnutls_certificate_allocate_credentials (&cred);
3862 if (GNUNET_NO == rv)
3863 rv = gnutls_certificate_set_x509_system_trust (cred);
3864 if (GNUNET_NO > rv)
3865 {
3867 "cred init failed: %s\n",
3868 gnutls_strerror (rv));
3869 return;
3870 }
3871 rv = gnutls_certificate_set_x509_key_file (cred,
3872 cert_file,
3873 key_file,
3874 GNUTLS_X509_FMT_PEM);
3876 "key_file: %s\ncert_file: %s\n",
3877 key_file, cert_file);
3878 GNUNET_free (cert_file);
3879 GNUNET_free (key_file);
3880 if (rv < 0)
3881 {
3883 "gnutls_certificate_set_x509_key_file: %s\n",
3884 gnutls_strerror (rv));
3885 return;
3886 }
3890 pils = GNUNET_PILS_connect (cfg, NULL, NULL);
3891 if (NULL == pils)
3892 {
3893 GNUNET_log (
3895 _ (
3896 "Transport service is lacking PILS connection. Exiting.\n"));
3898 return;
3899 }
3900
3902 udp_sock,
3903 &sock_read,
3904 NULL);
3909 &mq_init,
3910 NULL,
3911 &notify_cb,
3912 NULL,
3913 NULL);
3914 if (NULL == ch)
3915 {
3916 GNUNET_break (0);
3918 return;
3919 }
3920
3923 IPPROTO_UDP,
3924 1 /* one address */,
3925 (const struct sockaddr **) &in,
3926 &in_len,
3929 NULL /* closure */);
3930}
3931
3932
3940int
3941main (int argc, char *const *argv)
3942{
3943 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
3945 };
3946 int ret;
3947
3949 "transport",
3950 "Starting http3 communicator\n");
3951 ret = (GNUNET_OK ==
3953 argc,
3954 argv,
3955 "gnunet-communicator-http3",
3956 _ ("GNUnet HTTP3 communicator"),
3957 options,
3958 &run,
3959 NULL))
3960 ? 0
3961 : 1;
3962 return ret;
3963}
3964
3965
3966/* end of gnunet-communicator-http3.c */
struct GNUNET_GETOPT_CommandLineOption options[]
Definition 002.c:5
struct GNUNET_MessageHeader * msg
Definition 005.c:2
int main()
Program to simulate results from GCP_get_desirability_of_path() for various plausible inputs.
static int start
Set if we are to start default services (including ARM).
Definition gnunet-arm.c:38
static int ret
Final status code.
Definition gnunet-arm.c:93
static int do_shutdown
Set to GNUNET_YES if we are shutting down.
static uint16_t port
Port number.
Definition gnunet-bcd.c:146
static char * peer_id
Option –peer.
static int send_conn_close(struct Connection *connection)
Send the packet in the conn_closebuf.
static void start_draining_period(struct Connection *connection)
Start the draining period, called after receiving CONNECTION_CLOSE.
static int recv_stream_data_cb(ngtcp2_conn *conn, uint32_t flags, int64_t stream_id, uint64_t offset, const uint8_t *data, size_t datalen, void *user_data, void *stream_user_data)
The callback function for ngtcp2_callbacks.recv_stream_data.
static int client_quic_init(struct Connection *connection, struct sockaddr *local_addr, socklen_t local_addrlen, struct sockaddr *remote_addr, socklen_t remote_addrlen)
Create new ngtcp2_conn as client side.
static int connection_write(struct Connection *connection)
Write the data in the stream into the packet and handle timer.
static int get_connection_delete_it(void *cls, const struct GNUNET_HashCode *key, void *value)
Iterator over all connection to clean up.
static void mq_destroy_d(struct GNUNET_MQ_Handle *mq, void *impl_state)
Signature of functions implementing the destruction of a message queue.
static int get_stream_delete_it(void *cls, const struct GNUNET_HashCode *key, void *value)
Iterator over all streams to clean up.
static int stream_open_cb(ngtcp2_conn *conn, int64_t stream_id, void *user_data)
The callback function for ngtcp2_callbacks.stream_open.
static int http_reset_stream_cb(nghttp3_conn *conn, int64_t stream_id, uint64_t app_error_code, void *user_data, void *stream_user_data)
The callback of nghttp3_callback.reset_stream.
static int http_stop_sending_cb(nghttp3_conn *conn, int64_t stream_id, uint64_t app_error_code, void *user_data, void *stream_user_data)
The callback of nghttp3_callback.stop_sending.
#define PRIORITY
the priorities to use on the ciphers, key exchange methods, and macs.
static int stream_start_response(struct Connection *connection, struct Stream *stream)
Make response to the request.
#define COMMUNICATOR_ADDRESS_PREFIX
Address prefix used by the communicator.
static void long_poll_timeoutcb(void *cls)
Timeout callback function in the long polling struct.
static void notify_cb(void *cls, const struct GNUNET_PeerIdentity *sender, const struct GNUNET_MessageHeader *msg)
Function called when the transport service has received a backchannel message for this communicator (...
static int extend_max_stream_data_cb(ngtcp2_conn *conn, int64_t stream_id, uint64_t max_data, void *user_data, void *stream_user_data)
The callback function for ngtcp2_callbacks.extend_max_stream_data.
static int connection_write_streams(struct Connection *connection)
Write HTTP stream data and send the packets.
static int send_packet(struct Connection *connection, const uint8_t *data, size_t datalen)
Send the udp packet to remote.
static uint64_t timestamp(void)
Get current timestamp.
#define ADDRESS_VALIDITY_PERIOD
How long do we believe our addresses to remain up (before the other peer should revalidate).
static void rand_cb(uint8_t *dest, size_t destlen, const ngtcp2_rand_ctx *rand_ctx)
The callback function for ngtcp2_callbacks.rand.
static int stream_stop_sending_cb(ngtcp2_conn *conn, int64_t stream_id, uint64_t app_error_code, void *user_data, void *stream_user_data)
The callback function for ngtcp2_callbacks.stream_stop_sending.
static gnutls_certificate_credentials_t cred
The credential.
static int setup_httpconn(struct Connection *connection)
Setup the http3 connection.
network_error
Defines some error types related to network errors.
@ NETWORK_ERR_CLOSE_WAIT
@ NETWORK_ERR_SEND_BLOCKED
@ NETWORK_ERR_DROP_CONN
static int client_gnutls_init(struct Connection *connection)
As the client, initialize the corresponding connection.
static int http_end_stream_cb(nghttp3_conn *conn, int64_t stream_id, void *user_data, void *stream_user_data)
The callback of nghttp3_callback.end_stream.
static void connection_destroy(struct Connection *connection)
Destroys a receiving state due to timeout or shutdown.
static void try_connection_reversal(void *cls, const struct sockaddr *addr, socklen_t addrlen)
static int connection_feed_data(struct Connection *connection, struct sockaddr *local_addr, socklen_t local_addrlen, struct sockaddr *remote_addr, socklen_t remote_addrlen, const ngtcp2_pkt_info *pi, const uint8_t *data, size_t datalen)
Decrypt QUIC packet.
static struct GNUNET_NT_InterfaceScanner * is
Network scanner to determine network types.
static void connection_update_timer(struct Connection *connection)
Update the timer.
static int disable_v6
IPv6 disabled or not.
static struct Connection * connection_init(struct sockaddr *local_addr, socklen_t local_addrlen, struct sockaddr *remote_addr, socklen_t remote_addrlen, const ngtcp2_cid *dcid, const ngtcp2_cid *scid, uint32_t version)
Create a new connection.
static struct GNUNET_STATISTICS_Handle * stats
For logging statistics.
static const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
static int mq_init(void *cls, const struct GNUNET_PeerIdentity *peer_id, const char *address)
Function called by the transport service to initialize a message queue given address information abou...
static int recv_tx_key_cb(ngtcp2_conn *conn, ngtcp2_encryption_level level, void *user_data)
The callback function for ngtcp2_callbacks.recv_tx_key.
#define NUM_LONG_POLL
Long polling requests' number.
static void http_consume(struct Connection *connection, int64_t stream_id, size_t consumed)
Extend connection and stream offset.
static struct GNUNET_NETWORK_Handle * udp_sock
Our socket.
static nghttp3_ssize read_data(nghttp3_conn *conn, int64_t stream_id, nghttp3_vec *vec, size_t veccnt, uint32_t *pflags, void *user_data, void *stream_user_data)
The callback function to generate body.
static void mq_send_d(struct GNUNET_MQ_Handle *mq, const struct GNUNET_MessageHeader *msg, void *impl_state)
Signature of functions implementing the sending functionality of a message queue.
static void sock_read(void *cls)
Socket read task.
#define COMMUNICATOR_CONFIG_SECTION
Configuration section used by the communicator.
static nghttp3_nv make_nv(const char *name, const char *value, uint8_t flag)
Make name/value pair for request headers.
static void nat_address_cb(void *cls, void **app_ctx, int add_remove, enum GNUNET_NAT_AddressClass ac, const struct sockaddr *addr, socklen_t addrlen)
Signature of the callback passed to GNUNET_NAT_register() for a function to call whenever our set of ...
static struct GNUNET_TRANSPORT_CommunicatorHandle * ch
Our environment.
static int get_new_connection_id_cb(ngtcp2_conn *conn, ngtcp2_cid *cid, uint8_t *token, size_t cidlen, void *user_data)
The callback function for ngtcp2_callbacks.get_new_connection_id.
static struct sockaddr * udp_address_to_sockaddr(const char *bindto, socklen_t *sock_len)
Convert UDP bind specification to a struct sockaddr *
static int extend_max_remote_streams_bidi_cb(ngtcp2_conn *conn, uint64_t max_streams, void *user_data)
The callback function for ngtcp2_callbacks.extend_max_remote_streams_bidi.
static int http_recv_data_cb(nghttp3_conn *conn, int64_t stream_id, const uint8_t *data, size_t datalen, void *user_data, void *stream_user_data)
The callback of nghttp3_callback.recv_data.
static void run(void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c)
Setup communicator and launch network interactions.
static void reschedule_peer_timeout(struct Connection *connection)
Increment connection timeout due to activity.
static struct GNUNET_NAT_Handle * nat
Connection to NAT service.
static int acked_stream_data_offset_cb(ngtcp2_conn *conn, int64_t stream_id, uint64_t offset, uint64_t datalen, void *user_data, void *stream_user_data)
The callback function for ngtcp2_callbacks.acked_stream_data_offset.
static struct GNUNET_CONTAINER_MultiHashMap * addr_map
Map of sockaddr -> struct Connection.
static struct GNUNET_SCHEDULER_Task * read_task
ID of listen task.
static int http_begin_headers_cb(nghttp3_conn *conn, int64_t stream_id, void *user_data, void *stream_user_data)
The callback of nghttp3_callback.begin_headers.
static int handle_error(struct Connection *connection)
Handle errors.
static void setup_connection_mq(struct Connection *connection)
Setup the MQ for the connection.
static void mq_cancel(struct GNUNET_MQ_Handle *mq, void *impl_state)
Implementation function that cancels the currently sent message.
static int have_v6_socket
GNUNET_YES if udp_sock supports IPv6.
static uint16_t my_port
Port number to which we are actually bound.
static int submit_post_request(struct Connection *connection, struct Stream *stream, const uint8_t *data, size_t datalen)
Submit the post request, send our data.
static void close_waitcb(void *cls)
The timeout callback function of closing/draining period.
static char * sockaddr_to_udpaddr_string(const struct sockaddr *address, socklen_t address_len)
Taken from: UDP communicator Converts address to the address string format used by this communicator ...
static int connection_on_read(struct Connection *connection, struct sockaddr *local_addr, socklen_t local_addrlen, struct sockaddr *remote_addr, socklen_t remote_addrlen, const ngtcp2_pkt_info *pi, const uint8_t *data, size_t datalen)
Connection read the packet data.
static struct Stream * create_stream(struct Connection *connection, int64_t stream_id)
Create a new stream of connection with stream_id.
static int stream_reset_cb(ngtcp2_conn *conn, int64_t stream_id, uint64_t final_size, uint64_t app_error_code, void *user_data, void *stream_user_data)
The callback function for ngtcp2_callbacks.stream_reset.
static ngtcp2_conn * get_conn(ngtcp2_crypto_conn_ref *ref)
The callback function for ngtcp2_crypto_conn_ref.
static int start_closing_period(struct Connection *connection)
Start the closing period and build the packet contains CONNECTION_CLOSE.
static 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 struct GNUNET_PILS_Handle * pils
Handle to the pils service.
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 my_identity
Identity of this peer.
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.
struct GNUNET_PILS_Handle * GNUNET_PILS_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_PILS_PidChangeCallback pid_change_cb, void *cls)
Connect to the PILS service.
Definition pils_api.c:465
void GNUNET_PILS_disconnect(struct GNUNET_PILS_Handle *handle)
Disconnect from the PILS service.
Definition pils_api.c:488
const struct GNUNET_PeerIdentity * GNUNET_PILS_get_identity(const struct GNUNET_PILS_Handle *handle)
Return the current peer identity of a given handle.
Definition pils_api.c:727
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(void *buffer, size_t length)
Fill block with a random values.
enum GNUNET_GenericReturnValue GNUNET_DISK_file_test(const char *fil)
Check that fil corresponds to a filename (of a file that exists and that is not a directory).
Definition disk.c:557
#define GNUNET_GETOPT_OPTION_END
Marker for the end of the list of options.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition crypto_hash.c:40
int GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_MultiHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
void * GNUNET_CONTAINER_multihashmap_get(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Given a key find a value in the map matching the key.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_remove(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, const void *value)
Remove the given key-value pair from the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
unsigned int GNUNET_CONTAINER_multihashmap_size(const struct GNUNET_CONTAINER_MultiHashMap *map)
Get the number of key-value pairs in the map.
void GNUNET_CONTAINER_multihashmap_destroy(struct GNUNET_CONTAINER_MultiHashMap *map)
Destroy a hash map.
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY
There must only be one value per key; storing a value should fail if a value under the same key alrea...
#define GNUNET_log(kind,...)
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
const char * GNUNET_a2s(const struct sockaddr *addr, socklen_t addrlen)
Convert a "struct sockaddr*" (IPv4 or IPv6 address) to a string (for printing debug messages).
void GNUNET_log_config_missing(enum GNUNET_ErrorType kind, const char *section, const char *option)
Log error message about missing configuration option.
#define GNUNET_log_strerror(level, cmd)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
void GNUNET_log_from_nocheck(enum GNUNET_ErrorType kind, const char *comp, const char *message,...) __attribute__((format(printf
Log function that specifies an alternative component.
#define GNUNET_log_strerror_file(level, cmd, filename)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
int GNUNET_snprintf(char *buf, size_t size, const char *format,...) __attribute__((format(printf
Like snprintf, just aborts if the buffer is of insufficient size.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.
#define GNUNET_free(ptr)
Wrapper around free.
#define GNUNET_memdup(buf, size)
Allocate and initialize a block of memory.
GNUNET_MQ_Error
Error codes for the queue.
struct GNUNET_MQ_Handle * GNUNET_MQ_queue_for_callbacks(GNUNET_MQ_SendImpl send, GNUNET_MQ_DestroyImpl destroy, GNUNET_MQ_CancelImpl cancel, void *impl_state, const struct GNUNET_MQ_MessageHandler *handlers, GNUNET_MQ_ErrorHandler error_handler, void *cls)
Create a message queue for the specified handlers.
Definition mq.c:482
void GNUNET_MQ_impl_send_continue(struct GNUNET_MQ_Handle *mq)
Call the send implementation for the next queued message, if any.
Definition mq.c:437
struct GNUNET_NAT_Handle * GNUNET_NAT_register(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *config_section, uint8_t proto, unsigned int num_addrs, const struct sockaddr **addrs, const socklen_t *addrlens, GNUNET_NAT_AddressCallback address_callback, GNUNET_NAT_ReversalCallback reversal_callback, void *callback_cls)
Attempt to enable port redirection and detect public IP address contacting UPnP or NAT-PMP routers on...
Definition nat_api.c:366
void GNUNET_NAT_unregister(struct GNUNET_NAT_Handle *nh)
Stop port redirection and public IP address detection for the given handle.
Definition nat_api.c:703
GNUNET_NAT_AddressClass
Some addresses contain sensitive information or are not suitable for global distribution.
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition network.c:508
int GNUNET_NETWORK_get_fd(const struct GNUNET_NETWORK_Handle *desc)
Return file descriptor for this network handle.
Definition network.c:1000
ssize_t GNUNET_NETWORK_socket_recvfrom(const struct GNUNET_NETWORK_Handle *desc, void *buffer, size_t length, struct sockaddr *src_addr, socklen_t *addrlen)
Read data from a socket (always non-blocking).
Definition network.c:687
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_create(int domain, int type, int protocol)
Create a new socket.
Definition network.c:832
enum GNUNET_GenericReturnValue GNUNET_NETWORK_test_pf(int pf)
Test if the given protocol family is supported by this system.
Definition network.c:79
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_bind(struct GNUNET_NETWORK_Handle *desc, const struct sockaddr *address, socklen_t address_len)
Bind a socket to a particular address.
Definition network.c:439
ssize_t GNUNET_NETWORK_socket_sendto(const struct GNUNET_NETWORK_Handle *desc, const void *message, size_t length, const struct sockaddr *dest_addr, socklen_t dest_len)
Send data to a particular destination (always non-blocking).
Definition network.c:771
GNUNET_NetworkType
Types of networks (with separate quotas) we support.
void GNUNET_NT_scanner_done(struct GNUNET_NT_InterfaceScanner *is)
Terminate interface scanner.
Definition nt.c:428
struct GNUNET_NT_InterfaceScanner * GNUNET_NT_scanner_init(void)
Initialize the address characterization client handle.
Definition nt.c:407
enum GNUNET_NetworkType GNUNET_NT_scanner_get_type(struct GNUNET_NT_InterfaceScanner *is, const struct sockaddr *addr, socklen_t addrlen)
Returns where the address is located: loopback, LAN or WAN.
Definition nt.c:309
const struct GNUNET_OS_ProjectData * GNUNET_OS_project_data_gnunet(void)
Return default project data used by 'libgnunetutil' for GNUnet.
enum GNUNET_GenericReturnValue GNUNET_process_run_command_va(struct GNUNET_Process *p, const char *filename,...)
Set the command and start a process.
Definition os_process.c:903
enum GNUNET_GenericReturnValue GNUNET_process_wait(struct GNUNET_Process *proc, bool blocking, enum GNUNET_OS_ProcessStatusType *type, unsigned long *code)
Wait for a process to terminate.
void GNUNET_process_destroy(struct GNUNET_Process *proc)
Cleans up process structure contents (OS-dependent) and deallocates it.
Definition os_process.c:363
struct GNUNET_Process * GNUNET_process_create(enum GNUNET_OS_InheritStdioFlags std_inheritance)
Create a process handle.
Definition os_process.c:462
@ GNUNET_OS_INHERIT_STD_OUT_AND_ERR
When these flags are set, the child process will inherit stdout and stderr of the parent.
enum GNUNET_GenericReturnValue GNUNET_PROGRAM_run(const struct GNUNET_OS_ProjectData *pd, int argc, char *const *argv, const char *binaryName, const char *binaryHelp, const struct GNUNET_GETOPT_CommandLineOption *options, GNUNET_PROGRAM_Main task, void *task_cls)
Run a standard GNUnet command startup sequence (initialize loggers and configuration,...
Definition program.c:406
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition scheduler.c:572
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_net(struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition scheduler.c:1517
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received,...
Definition scheduler.c:1345
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition scheduler.c:986
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition scheduler.c:1310
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition scheduler.c:1283
void GNUNET_STATISTICS_set(struct GNUNET_STATISTICS_Handle *handle, const char *name, uint64_t value, int make_persistent)
Set statistic value for the peer.
void GNUNET_STATISTICS_destroy(struct GNUNET_STATISTICS_Handle *h, int sync_first)
Destroy a handle (free all state associated with it).
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
#define GNUNET_TIME_UNIT_SECONDS
One second.
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition time.c:316
struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Multiply relative time by a given factor.
Definition time.c:486
#define GNUNET_TIME_UNIT_MICROSECONDS
One microsecond, our basic time unit.
#define _(String)
GNU gettext support macro.
Definition platform.h:179
static struct GNUNET_MQ_Handle * mq
Our connection to the resolver service, created on-demand, but then persists until error or shutdown.
Used to keep track of context of peer.
ngtcp2_conn * conn
The QUIC connection.
ngtcp2_ssize conn_closebuflen
The length of conn_closebuf;.
enum GNUNET_NetworkType nt
Which network type does this queue use?
gnutls_session_t session
The gnutls session.
struct Long_Poll_Request * long_poll_head
head pointer of long polling struct queue.
ngtcp2_crypto_conn_ref conn_ref
The structure to get a pointer to ngtcp2_conn.
struct sockaddr * address
Address of the other peer.
int is_initiator
Flag to indicate if we are the initiator of the connection.
nghttp3_conn * h3_conn
The HTTP/3 connection.
struct Long_Poll_Request * long_poll_rear
rear pointer of long polling struct queue.
struct GNUNET_TRANSPORT_QueueHandle * d_qh
handle for default queue with the ch.
size_t d_mtu
MTU we allowed transport for this receiver's default queue.
struct GNUNET_PeerIdentity target
To whom are we talking to.
struct HTTP_Message * msg_queue_rear
rear pointer of message queue.
char * foreign_addr
Address of the receiver in the human-readable format with the COMMUNICATOR_ADDRESS_PREFIX.
struct GNUNET_CONTAINER_MultiHashMap * streams
Information of the stream.
int id_rcvd
Flag to indicate whether we know the PeerIdentity (target) yet.
struct GNUNET_TIME_Absolute timeout
Timeout for this connection.
struct GNUNET_MQ_Handle * d_mq
Default message queue we are providing for the ch.
ngtcp2_ccerr last_error
The connection error.
uint8_t * conn_closebuf
conn_closebuf contains a packet which contains CONNECTION_CLOSE.
size_t long_poll_len
length of long polling struct queue.
struct HTTP_Message * msg_queue_head
head pointer of message queue.
struct HTTP_Message * submitted_msg_queue_head
Messages that have been submitted will be put into this queue.
socklen_t address_len
Length of the address.
int connection_destroy_called
connection_destroy already called on connection.
struct GNUNET_SCHEDULER_Task * timer
The timer of this connection.
int id_sent
Flag to indicate whether we have sent OUR PeerIdentity to this peer.
size_t msg_queue_len
length of message queue.
Internal representation of the hash map.
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
A handle for the PILS service.
Definition pils_api.c:82
The identity of the host (wraps the signing key of the peer).
Entry in list of pending tasks.
Definition scheduler.c:141
Handle for the service.
Time for absolute times used by GNUnet, in microseconds.
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.