aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShichao <mrrr61@outlook.com>2024-05-19 13:07:15 +0800
committerShichao <mrrr61@outlook.com>2024-05-19 13:07:15 +0800
commitbe3e225a493d79c4c721290b7ef7bf081e30a652 (patch)
tree4ac33f40cce876d021bf5a406c33b266178debab
parentb384ef7534238a99ae9f04083d9ced602af7e55d (diff)
downloadgnunet-dev/shichao/http3.tar.gz
gnunet-dev/shichao/http3.zip
http3: handle read from sock.dev/shichao/http3
-rw-r--r--src/service/transport/gnunet-communicator-http3.c297
1 files changed, 297 insertions, 0 deletions
diff --git a/src/service/transport/gnunet-communicator-http3.c b/src/service/transport/gnunet-communicator-http3.c
index 806e5209d..428788fb8 100644
--- a/src/service/transport/gnunet-communicator-http3.c
+++ b/src/service/transport/gnunet-communicator-http3.c
@@ -17,6 +17,8 @@
17#include <ngtcp2/ngtcp2_crypto.h> 17#include <ngtcp2/ngtcp2_crypto.h>
18#include <ngtcp2/ngtcp2_crypto_gnutls.h> 18#include <ngtcp2/ngtcp2_crypto_gnutls.h>
19#include <nghttp3/nghttp3.h> 19#include <nghttp3/nghttp3.h>
20#include <gnutls/crypto.h>
21#include <gnutls/gnutls.h>
20 22
21 23
22/** 24/**
@@ -39,6 +41,8 @@
39 41
40/** 42/**
41 * Map of sockaddr -> struct Connection 43 * Map of sockaddr -> struct Connection
44 *
45 * TODO: Maybe it would be better to use cid as key?
42 */ 46 */
43struct GNUNET_CONTAINER_MultiHashMap *addr_map; 47struct GNUNET_CONTAINER_MultiHashMap *addr_map;
44 48
@@ -161,6 +165,16 @@ struct Connection
161 * Flag to indicate if we are the initiator of the connection 165 * Flag to indicate if we are the initiator of the connection
162 */ 166 */
163 int is_initiator; 167 int is_initiator;
168
169 /**
170 * Flag to indicate whether we know the PeerIdentity (target) yet
171 */
172 int id_rcvd;
173
174 /**
175 * Flag to indicate whether we have sent OUR PeerIdentity to this peer
176 */
177 int id_sent;
164}; 178};
165 179
166 180
@@ -179,6 +193,44 @@ timestamp (void)
179 193
180 194
181/** 195/**
196 * Taken from: UDP communicator
197 * Converts @a address to the address string format used by this
198 * communicator in HELLOs.
199 *
200 * @param address the address to convert, must be AF_INET or AF_INET6.
201 * @param address_len number of bytes in @a address
202 * @return string representation of @a address
203 */
204static char *
205sockaddr_to_udpaddr_string (const struct sockaddr *address,
206 socklen_t address_len)
207{
208 char *ret;
209
210 switch (address->sa_family)
211 {
212 case AF_INET:
213 GNUNET_asprintf (&ret,
214 "%s-%s",
215 COMMUNICATOR_ADDRESS_PREFIX,
216 GNUNET_a2s (address, address_len));
217 break;
218
219 case AF_INET6:
220 GNUNET_asprintf (&ret,
221 "%s-%s",
222 COMMUNICATOR_ADDRESS_PREFIX,
223 GNUNET_a2s (address, address_len));
224 break;
225
226 default:
227 GNUNET_assert (0);
228 }
229 return ret;
230}
231
232
233/**
182 * Convert UDP bind specification to a `struct sockaddr *` 234 * Convert UDP bind specification to a `struct sockaddr *`
183 * 235 *
184 * @param bindto bind specification to convert 236 * @param bindto bind specification to convert
@@ -758,6 +810,8 @@ mq_init (void *cls,
758 connection->address_len = remote_addrlen; 810 connection->address_len = remote_addrlen;
759 connection->target = *peer_id; 811 connection->target = *peer_id;
760 connection->is_initiator = GNUNET_YES; 812 connection->is_initiator = GNUNET_YES;
813 connection->id_rcvd = GNUNET_YES;
814 connection->id_sent = GNUNET_NO;
761 connection->nt = GNUNET_NT_scanner_get_type (is, 815 connection->nt = GNUNET_NT_scanner_get_type (is,
762 remote_addr, 816 remote_addr,
763 remote_addrlen); 817 remote_addrlen);
@@ -866,6 +920,135 @@ do_shutdown (void *cls)
866 920
867 921
868/** 922/**
923 * Accept new connections.
924 *
925 * @param local_addr local socket address
926 * @param local_addrlen local socket address length
927 * @param remote_addr remote(peer's) socket address
928 * @param remote_addrlen remote socket address length
929 *
930 * @return the pointer of new connection on success, NULL if failed
931 */
932static struct Connection*
933accept_connection (struct sockaddr *local_addr,
934 socklen_t local_addrlen,
935 struct sockaddr *remote_addr,
936 socklen_t remote_addrlen,
937 uint8_t *data,
938 size_t datalen)
939{
940 ngtcp2_pkt_hd header;
941 struct Connection *new_connection = NULL;
942 ngtcp2_transport_params params;
943 ngtcp2_cid scid;
944 ngtcp2_conn *conn = NULL;
945 ngtcp2_settings settings;
946 uint8_t cid_buf[NGTCP2_MAX_CIDLEN];
947 ngtcp2_path path = {
948 {local_addr, local_addrlen},
949 {remote_addr, remote_addrlen},
950 NULL,
951 };
952 ngtcp2_callbacks callbacks = {
953 // .client_initial
954 .recv_client_initial = ngtcp2_crypto_recv_client_initial_cb,
955 .recv_crypto_data = ngtcp2_crypto_recv_crypto_data_cb,
956 .encrypt = ngtcp2_crypto_encrypt_cb,
957 .decrypt = ngtcp2_crypto_decrypt_cb,
958 .hp_mask = ngtcp2_crypto_hp_mask_cb,
959 // .recv_retry = ngtcp2_crypto_recv_retry_cb,
960 .update_key = ngtcp2_crypto_update_key_cb,
961 .delete_crypto_aead_ctx = ngtcp2_crypto_delete_crypto_aead_ctx_cb,
962 .delete_crypto_cipher_ctx = ngtcp2_crypto_delete_crypto_cipher_ctx_cb,
963 .get_path_challenge_data = ngtcp2_crypto_get_path_challenge_data_cb,
964 .version_negotiation = ngtcp2_crypto_version_negotiation_cb,
965
966 // .acked_stream_data_offset = acked_stream_data_offset_cb,
967 // .recv_stream_data = recv_stream_data_cb,
968 // .stream_open = stream_open_cb,
969 .rand = rand_cb,
970 .get_new_connection_id = get_new_connection_id_cb,
971 };
972 int rv;
973
974 rv = ngtcp2_accept (&header, data, datalen);
975 if (rv < 0)
976 {
977 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
978 "ngtcp2_accept: %s\n", ngtcp2_strerror (rv));
979 return NULL;
980 }
981 new_connection = GNUNET_new (struct Connection);
982 memset (new_connection, 0, sizeof (new_connection));
983
984 gnutls_init (&new_connection->session,
985 GNUTLS_SERVER
986 | GNUTLS_ENABLE_EARLY_DATA
987 | GNUTLS_NO_END_OF_EARLY_DATA);
988 gnutls_priority_set_direct (new_connection->session, PRIORITY, NULL);
989 /*
990 * TODO: The cred here has not been initialized and
991 * there is no need to maintain a cred for each connection
992 */
993 gnutls_credentials_set (new_connection->session,
994 GNUTLS_CRD_CERTIFICATE, new_connection->cred);
995
996 ngtcp2_transport_params_default (&params);
997 params.initial_max_streams_uni = 3;
998 params.initial_max_streams_bidi = 3;
999 params.initial_max_stream_data_bidi_local = 128 * 1024;
1000 params.initial_max_stream_data_bidi_remote = 128 * 1024;
1001 params.initial_max_data = 1024 * 1024;
1002 params.original_dcid_present = 1;
1003 params.max_idle_timeout = 30 * NGTCP2_SECONDS;
1004 memcpy (&params.original_dcid, &header.dcid,
1005 sizeof (params.original_dcid));
1006
1007 ngtcp2_settings_default (&settings);
1008 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG,
1009 cid_buf,
1010 sizeof (cid_buf));
1011 ngtcp2_cid_init (&scid, cid_buf, sizeof (cid_buf));
1012
1013 rv = ngtcp2_conn_server_new (&conn,
1014 &header.scid,
1015 &scid,
1016 &path,
1017 header.version,
1018 &callbacks,
1019 &settings,
1020 &params,
1021 NULL,
1022 new_connection);
1023 if (rv < 0)
1024 {
1025 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1026 "ngtcp2_conn_server_new: %s\n",
1027 ngtcp2_strerror (rv));
1028 return NULL;
1029 }
1030
1031 new_connection->conn = conn;
1032 new_connection->address = GNUNET_memdup (remote_addr, remote_addrlen);
1033 new_connection->address_len = remote_addrlen;
1034 new_connection->is_initiator = GNUNET_NO;
1035 new_connection->id_rcvd = GNUNET_NO;
1036 new_connection->id_sent = GNUNET_NO;
1037 ngtcp2_crypto_gnutls_configure_server_session (new_connection->session);
1038 ngtcp2_conn_set_tls_native_handle (new_connection->conn,
1039 new_connection->session);
1040 gnutls_session_set_ptr (new_connection->session,
1041 &new_connection->conn_ref);
1042
1043 new_connection->conn_ref.get_conn = get_conn;
1044 new_connection->conn_ref.user_data = new_connection;
1045 new_connection->stream.id = -1;
1046
1047 return new_connection;
1048}
1049
1050
1051/**
869 * Socket read task. 1052 * Socket read task.
870 * 1053 *
871 * @param cls NULL 1054 * @param cls NULL
@@ -873,6 +1056,120 @@ do_shutdown (void *cls)
873static void 1056static void
874sock_read (void *cls) 1057sock_read (void *cls)
875{ 1058{
1059 (void) cls;
1060 struct sockaddr_storage sa;
1061 socklen_t salen = sizeof (sa);
1062 ssize_t rcvd;
1063 uint8_t buf[UINT16_MAX];
1064 ngtcp2_path path;
1065 // ngtcp2_version_cid version_cid;
1066 struct GNUNET_HashCode addr_key;
1067 struct Connection *connection;
1068 int rv;
1069 char *bindto;
1070 struct sockaddr *local_addr;
1071 socklen_t local_addrlen;
1072
1073 if (GNUNET_OK !=
1074 GNUNET_CONFIGURATION_get_value_string (cfg,
1075 COMMUNICATOR_CONFIG_SECTION,
1076 "BINDTO",
1077 &bindto))
1078 {
1079 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
1080 COMMUNICATOR_CONFIG_SECTION,
1081 "BINDTO");
1082 return;
1083 }
1084 local_addr = udp_address_to_sockaddr (bindto, &local_addrlen);
1085 read_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
1086 udp_sock,
1087 &sock_read,
1088 NULL);
1089
1090 while (1)
1091 {
1092 rcvd = GNUNET_NETWORK_socket_recvfrom (udp_sock,
1093 buf,
1094 sizeof(buf),
1095 (struct sockaddr *) &sa,
1096 &salen);
1097 if (-1 == rcvd)
1098 {
1099 struct sockaddr *addr = (struct sockaddr*) &sa;
1100
1101 if (EAGAIN == errno)
1102 break; // We are done reading data
1103 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1104 "Failed to recv from %s family %d failed sock %p\n",
1105 GNUNET_a2s ((struct sockaddr*) &sa,
1106 sizeof (*addr)),
1107 addr->sa_family,
1108 udp_sock);
1109 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "recv");
1110 return;
1111 }
1112 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1113 "Read %llu bytes\n",
1114 (unsigned long long) rcvd);
1115 if (0 == rcvd)
1116 {
1117 GNUNET_break_op (0);
1118 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1119 "Read 0 bytes from UDP socket\n");
1120 return;
1121 }
1122
1123 // rv = ngtcp2_pkt_decode_version_cid (&version_cid, buf, rcvd,
1124 // NGTCP2_MAX_CIDLEN);
1125 // if (rv < 0)
1126 // {
1127 // GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1128 // "ngtcp2_pkt_decode_version_cid: %s\n", ngtcp2_strerror (rv));
1129 // return;
1130 // }
1131
1132 char *addr_string =
1133 sockaddr_to_udpaddr_string ((const struct sockaddr *) &sa,
1134 salen);
1135 GNUNET_CRYPTO_hash (addr_string, strlen (addr_string),
1136 &addr_key);
1137 GNUNET_free (addr_string);
1138 connection = GNUNET_CONTAINER_multihashmap_get (addr_map, &addr_key);
1139
1140 if (NULL == connection)
1141 {
1142 connection = accept_connection (local_addr, local_addrlen,
1143 (struct sockaddr *) &sa,
1144 salen, buf, rcvd);
1145 if (NULL == connection)
1146 {
1147 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1148 "accept connection error!\n");
1149 return;
1150 }
1151 GNUNET_CONTAINER_multihashmap_put (addr_map,
1152 &addr_key,
1153 connection,
1154 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1155 }
1156
1157 memcpy (&path, ngtcp2_conn_get_path (connection->conn), sizeof (path));
1158 path.remote.addr = (struct sockaddr *) &sa;
1159 path.remote.addrlen = salen;
1160
1161 rv = ngtcp2_conn_read_pkt (connection->conn, &path, NULL, buf, rcvd,
1162 timestamp ());
1163 if (rv < 0)
1164 {
1165 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1166 "ngtcp2_conn_read_pkt: %s",
1167 ngtcp2_strerror (rv));
1168 return;
1169 }
1170 }
1171
1172 GNUNET_free (local_addr);
876 1173
877} 1174}
878 1175