comparison src/event/ngx_event_quic.c @ 8206:8d6ac639feac quic

Added support of multiple QUIC packets in single datagram. - now NEW_CONNECTION_ID frames can be received and parsed The packet structure is created in ngx_quic_input() and passed to all handlers (initial, handshake and application data). The UDP datagram buffer is saved as pkt->raw; The QUIC packet is stored as pkt->data and pkt->len (instead of pkt->buf) (pkt->len is adjusted after parsing headers to actual length) The pkt->pos is removed, pkt->raw->pos is used instead.
author Vladimir Homutov <vl@nginx.com>
date Thu, 12 Mar 2020 14:43:24 +0300
parents a5423632d67b
children cc8d211cb45c
comparison
equal deleted inserted replaced
8205:a5423632d67b 8206:8d6ac639feac
164 size_t len; 164 size_t len;
165 u_char *data; 165 u_char *data;
166 } ngx_quic_crypto_frame_t; 166 } ngx_quic_crypto_frame_t;
167 167
168 168
169 typedef struct {
170 uint64_t seqnum;
171 uint64_t retire;
172 uint64_t len;
173 u_char cid[20];
174 u_char srt[16];
175 } ngx_quic_ncid_t;
176
177
169 struct ngx_quic_frame_s { 178 struct ngx_quic_frame_s {
170 ngx_uint_t type; 179 ngx_uint_t type;
171 ngx_quic_level_t level; 180 ngx_quic_level_t level;
172 ngx_quic_frame_t *next; 181 ngx_quic_frame_t *next;
173 union { 182 union {
174 ngx_quic_crypto_frame_t crypto; 183 ngx_quic_crypto_frame_t crypto;
175 ngx_quic_ack_frame_t ack; 184 ngx_quic_ack_frame_t ack;
185 ngx_quic_ncid_t ncid;
176 // more frames 186 // more frames
177 } u; 187 } u;
178 188
179 u_char info[128]; // for debug purposes 189 u_char info[128]; // for debug purposes
180 }; 190 };
213 uint32_t version; 223 uint32_t version;
214 ngx_str_t token; 224 ngx_str_t token;
215 ngx_quic_level_t level; 225 ngx_quic_level_t level;
216 226
217 /* filled in by parser */ 227 /* filled in by parser */
218 ngx_str_t buf; /* quic packet from wire */ 228 ngx_buf_t *raw; /* udp datagram from wire */
219 u_char *pos; /* current parser position */ 229
230 u_char *data; /* quic packet */
231 size_t len;
220 232
221 /* cleartext fields */ 233 /* cleartext fields */
222 ngx_str_t dcid; 234 ngx_str_t dcid;
223 ngx_str_t scid; 235 ngx_str_t scid;
224 236
228 240
229 } ngx_quic_header_t; 241 } ngx_quic_header_t;
230 242
231 243
232 static ngx_int_t ngx_quic_new_connection(ngx_connection_t *c, ngx_ssl_t *ssl, 244 static ngx_int_t ngx_quic_new_connection(ngx_connection_t *c, ngx_ssl_t *ssl,
233 ngx_buf_t *b); 245 ngx_quic_header_t *pkt);
234 static ngx_int_t ngx_quic_handshake_input(ngx_connection_t *c, ngx_buf_t *b); 246
235 static ngx_int_t ngx_quic_app_input(ngx_connection_t *c, ngx_buf_t *b); 247 static ngx_int_t ngx_quic_handshake_input(ngx_connection_t *c,
248 ngx_quic_header_t *pkt);
249 static ngx_int_t ngx_quic_app_input(ngx_connection_t *c,
250 ngx_quic_header_t *pkt);
251
236 252
237 #if BORINGSSL_API_VERSION >= 10 253 #if BORINGSSL_API_VERSION >= 10
238 static int ngx_quic_set_read_secret(ngx_ssl_conn_t *ssl_conn, 254 static int ngx_quic_set_read_secret(ngx_ssl_conn_t *ssl_conn,
239 enum ssl_encryption_level_t level, const SSL_CIPHER *cipher, 255 enum ssl_encryption_level_t level, const SSL_CIPHER *cipher,
240 const uint8_t *secret, size_t secret_len); 256 const uint8_t *secret, size_t secret_len);
317 333
318 334
319 ngx_int_t 335 ngx_int_t
320 ngx_quic_input(ngx_connection_t *c, ngx_ssl_t *ssl, ngx_buf_t *b) 336 ngx_quic_input(ngx_connection_t *c, ngx_ssl_t *ssl, ngx_buf_t *b)
321 { 337 {
338 u_char *p;
339 ngx_quic_header_t pkt;
340
341 ngx_memzero(&pkt, sizeof(ngx_quic_header_t));
342
343 pkt.raw = b;
344 pkt.data = b->start;
345 pkt.len = b->last - b->start;
346
322 if (c->quic == NULL) { 347 if (c->quic == NULL) {
323 return ngx_quic_new_connection(c, ssl, b); 348 return ngx_quic_new_connection(c, ssl, &pkt);
324 } 349 }
325 350
326 if (b->start[0] & NGX_QUIC_PKT_LONG) { 351 p = b->start;
327 // TODO: check current state 352
328 return ngx_quic_handshake_input(c, b); 353 do {
329 } 354 ngx_memzero(&pkt, sizeof(ngx_quic_header_t));
330 355 pkt.raw = b;
331 return ngx_quic_app_input(c, b); 356 pkt.data = p;
357 pkt.len = b->last - p;
358
359 if (p[0] & NGX_QUIC_PKT_LONG) {
360 // TODO: check current state
361 if (ngx_quic_handshake_input(c, &pkt) != NGX_OK) {
362 return NGX_ERROR;
363 }
364 } else {
365
366 if (ngx_quic_app_input(c, &pkt) != NGX_OK) {
367 return NGX_ERROR;
368 }
369 }
370
371 /* b->pos is at header end, adjust by actual packet length */
372 p = b->pos + pkt.len;
373 b->pos = p; /* reset b->pos to the next packet start */
374
375 } while (p < b->last);
376
377 return NGX_OK;
332 } 378 }
333 379
334 static ngx_int_t 380 static ngx_int_t
335 ngx_quic_send_packet(ngx_connection_t *c, ngx_quic_connection_t *qc, 381 ngx_quic_send_packet(ngx_connection_t *c, ngx_quic_connection_t *qc,
336 ngx_quic_level_t level, ngx_str_t *payload) 382 ngx_quic_level_t level, ngx_str_t *payload)
1016 1062
1017 return 1; 1063 return 1;
1018 } 1064 }
1019 1065
1020 1066
1021 /* TODO: stub for short packet header processing */
1022 static ngx_int_t 1067 static ngx_int_t
1023 ngx_quic_process_short_header(ngx_connection_t *c, ngx_quic_header_t *pkt) 1068 ngx_quic_process_short_header(ngx_connection_t *c, ngx_quic_header_t *pkt)
1024 { 1069 {
1025 u_char *p; 1070 u_char *p;
1026 1071
1027 p = pkt->buf.data; 1072 p = pkt->data;
1028 1073
1029 ngx_quic_hexdump0(c->log, "input", pkt->buf.data, pkt->buf.len); 1074 ngx_quic_hexdump0(c->log, "short input", pkt->data, pkt->len);
1030 1075
1031 if ((p[0] & NGX_QUIC_PKT_LONG)) { 1076 if ((p[0] & NGX_QUIC_PKT_LONG)) {
1032 ngx_log_error(NGX_LOG_INFO, c->log, 0, "not a short packet"); 1077 ngx_log_error(NGX_LOG_INFO, c->log, 0, "not a short packet");
1033 return NGX_ERROR; 1078 return NGX_ERROR;
1034 } 1079 }
1041 if (ngx_memcmp(p, c->quic->dcid.data, c->quic->dcid.len) != 0) { 1086 if (ngx_memcmp(p, c->quic->dcid.data, c->quic->dcid.len) != 0) {
1042 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unexpected quic dcid"); 1087 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unexpected quic dcid");
1043 return NGX_ERROR; 1088 return NGX_ERROR;
1044 } 1089 }
1045 1090
1091 pkt->dcid.len = c->quic->dcid.len;
1046 pkt->dcid.data = p; 1092 pkt->dcid.data = p;
1047 p += c->quic->dcid.len; 1093 p += pkt->dcid.len;
1048 1094
1049 pkt->pos = p; 1095 pkt->raw->pos = p;
1050 1096
1051 return NGX_OK; 1097 return NGX_OK;
1052 } 1098 }
1053 1099
1054 1100
1055 static ngx_int_t 1101 static ngx_int_t
1056 ngx_quic_process_long_header(ngx_connection_t *c, ngx_quic_header_t *pkt) 1102 ngx_quic_process_long_header(ngx_connection_t *c, ngx_quic_header_t *pkt)
1057 { 1103 {
1058 u_char *p; 1104 u_char *p;
1059 1105
1060 p = pkt->buf.data; 1106 p = pkt->data;
1061 1107
1062 ngx_quic_hexdump0(c->log, "input", pkt->buf.data, pkt->buf.len); 1108 ngx_quic_hexdump0(c->log, "long input", pkt->data, pkt->len);
1063 1109
1064 if (!(p[0] & NGX_QUIC_PKT_LONG)) { 1110 if (!(p[0] & NGX_QUIC_PKT_LONG)) {
1065 ngx_log_error(NGX_LOG_INFO, c->log, 0, "not a long packet"); 1111 ngx_log_error(NGX_LOG_INFO, c->log, 0, "not a long packet");
1066 return NGX_ERROR; 1112 return NGX_ERROR;
1067 } 1113 }
1085 1131
1086 pkt->scid.len = *p++; 1132 pkt->scid.len = *p++;
1087 pkt->scid.data = p; 1133 pkt->scid.data = p;
1088 p += pkt->scid.len; 1134 p += pkt->scid.len;
1089 1135
1090 pkt->pos = p; 1136 pkt->raw->pos = p;
1091 1137
1092 return NGX_OK; 1138 return NGX_OK;
1093 } 1139 }
1094 1140
1095 1141
1097 ngx_quic_process_initial_header(ngx_connection_t *c, ngx_quic_header_t *pkt) 1143 ngx_quic_process_initial_header(ngx_connection_t *c, ngx_quic_header_t *pkt)
1098 { 1144 {
1099 u_char *p; 1145 u_char *p;
1100 ngx_int_t plen; 1146 ngx_int_t plen;
1101 1147
1102 p = pkt->pos; 1148 p = pkt->raw->pos;
1103 1149
1104 pkt->token.len = ngx_quic_parse_int(&p); 1150 pkt->token.len = ngx_quic_parse_int(&p);
1105 pkt->token.data = p; 1151 pkt->token.data = p;
1106 1152
1107 p += pkt->token.len; 1153 p += pkt->token.len;
1109 plen = ngx_quic_parse_int(&p); 1155 plen = ngx_quic_parse_int(&p);
1110 1156
1111 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, 1157 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
1112 "quic packet length: %d", plen); 1158 "quic packet length: %d", plen);
1113 1159
1114 if (plen > pkt->buf.data + pkt->buf.len - p) { 1160 if (plen > pkt->data + pkt->len - p) {
1115 ngx_log_error(NGX_LOG_INFO, c->log, 0, "truncated initial packet"); 1161 ngx_log_error(NGX_LOG_INFO, c->log, 0, "truncated initial packet");
1116 return NGX_ERROR; 1162 return NGX_ERROR;
1117 } 1163 }
1118 1164
1119 pkt->pos = p; 1165 pkt->raw->pos = p;
1120 pkt->buf.len = plen; 1166 pkt->len = plen;
1121 1167
1122 ngx_quic_hexdump0(c->log, "DCID", pkt->dcid.data, pkt->dcid.len); 1168 ngx_quic_hexdump0(c->log, "DCID", pkt->dcid.data, pkt->dcid.len);
1123 ngx_quic_hexdump0(c->log, "SCID", pkt->scid.data, pkt->scid.len); 1169 ngx_quic_hexdump0(c->log, "SCID", pkt->scid.data, pkt->scid.len);
1124 ngx_quic_hexdump0(c->log, "token", pkt->token.data, pkt->token.len); 1170 ngx_quic_hexdump0(c->log, "token", pkt->token.data, pkt->token.len);
1125 1171
1133 ngx_quic_process_handshake_header(ngx_connection_t *c, ngx_quic_header_t *pkt) 1179 ngx_quic_process_handshake_header(ngx_connection_t *c, ngx_quic_header_t *pkt)
1134 { 1180 {
1135 u_char *p; 1181 u_char *p;
1136 ngx_int_t plen; 1182 ngx_int_t plen;
1137 1183
1138 p = pkt->pos; 1184 p = pkt->raw->pos;
1139 1185
1140 plen = ngx_quic_parse_int(&p); 1186 plen = ngx_quic_parse_int(&p);
1141 1187
1142 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, 1188 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
1143 "quic packet length: %d", plen); 1189 "quic packet length: %d", plen);
1144 1190
1145 if (plen > pkt->buf.data + pkt->buf.len - p) { 1191 if (plen > pkt->data + pkt->len - p) {
1146 ngx_log_error(NGX_LOG_INFO, c->log, 0, "truncated handshake packet"); 1192 ngx_log_error(NGX_LOG_INFO, c->log, 0, "truncated handshake packet");
1147 return NGX_ERROR; 1193 return NGX_ERROR;
1148 } 1194 }
1149 1195
1150 pkt->pos = p; 1196 pkt->raw->pos = p;
1151 pkt->buf.len = plen; 1197 pkt->len = plen;
1152 1198
1153 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, 1199 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
1154 "quic packet length: %d", plen); 1200 "quic packet length: %d", plen);
1155 1201
1156 return NGX_OK; 1202 return NGX_OK;
1278 1324
1279 if (ngx_quic_ciphers(c, &ciphers, pkt->level) == NGX_ERROR) { 1325 if (ngx_quic_ciphers(c, &ciphers, pkt->level) == NGX_ERROR) {
1280 return NGX_ERROR; 1326 return NGX_ERROR;
1281 } 1327 }
1282 1328
1283 p = pkt->pos; 1329 p = pkt->raw->pos;
1284 1330
1285 /* draft-ietf-quic-tls-23#section-5.4.2: 1331 /* draft-ietf-quic-tls-23#section-5.4.2:
1286 * the Packet Number field is assumed to be 4 bytes long 1332 * the Packet Number field is assumed to be 4 bytes long
1287 * draft-ietf-quic-tls-23#section-5.4.[34]: 1333 * draft-ietf-quic-tls-23#section-5.4.[34]:
1288 * AES-Based and ChaCha20-Based header protections sample 16 bytes 1334 * AES-Based and ChaCha20-Based header protections sample 16 bytes
1319 /* packet protection */ 1365 /* packet protection */
1320 1366
1321 in.data = p; 1367 in.data = p;
1322 1368
1323 if (pkt->flags & NGX_QUIC_PKT_LONG) { 1369 if (pkt->flags & NGX_QUIC_PKT_LONG) {
1324 in.len = pkt->buf.len - pnl; 1370 in.len = pkt->len - pnl;
1325 1371
1326 } else { 1372 } else {
1327 in.len = pkt->buf.data + pkt->buf.len - p; 1373 in.len = pkt->data + pkt->len - p;
1328 } 1374 }
1329 1375
1330 ad.len = p - pkt->buf.data; 1376 ad.len = p - pkt->data;
1331 ad.data = ngx_pnalloc(c->pool, ad.len); 1377 ad.data = ngx_pnalloc(c->pool, ad.len);
1332 if (ad.data == NULL) { 1378 if (ad.data == NULL) {
1333 return NGX_ERROR; 1379 return NGX_ERROR;
1334 } 1380 }
1335 1381
1336 ngx_memcpy(ad.data, pkt->buf.data, ad.len); 1382 ngx_memcpy(ad.data, pkt->data, ad.len);
1337 ad.data[0] = clearflags; 1383 ad.data[0] = clearflags;
1338 ad.data[ad.len - pnl] = (u_char) pn; 1384 ad.data[ad.len - pnl] = (u_char) pn;
1339 1385
1340 nonce = ngx_pstrdup(c->pool, &pkt->secret->iv); 1386 nonce = ngx_pstrdup(c->pool, &pkt->secret->iv);
1341 nonce[11] ^= pn; 1387 nonce[11] ^= pn;
1347 nonce, &in, &ad); 1393 nonce, &in, &ad);
1348 1394
1349 ngx_quic_hexdump0(c->log, "packet payload", 1395 ngx_quic_hexdump0(c->log, "packet payload",
1350 pkt->payload.data, pkt->payload.len); 1396 pkt->payload.data, pkt->payload.len);
1351 1397
1352 pkt->pos = pkt->payload.data;
1353
1354 return rc; 1398 return rc;
1355 } 1399 }
1356 1400
1357 1401
1358 ngx_int_t 1402 ssize_t
1359 ngx_quic_read_frame(ngx_connection_t *c, ngx_quic_header_t *pkt, 1403 ngx_quic_read_frame(ngx_connection_t *c, u_char *start, u_char *end,
1360 ngx_quic_frame_t *frame) 1404 ngx_quic_frame_t *frame)
1361 { 1405 {
1362 u_char *p, *end; 1406 u_char *p;
1363 1407
1364 size_t npad; 1408 size_t npad;
1365 1409
1366 p = pkt->pos; 1410 p = start;
1367 end = pkt->payload.data + pkt->payload.len; 1411
1368 1412 frame->type = *p++; // TODO: check overflow (p < end)
1369 frame->type = *p++;
1370 1413
1371 switch (frame->type) { 1414 switch (frame->type) {
1372 1415
1373 case NGX_QUIC_FT_CRYPTO: 1416 case NGX_QUIC_FT_CRYPTO:
1374 frame->u.crypto.offset = *p++; 1417 frame->u.crypto.offset = *p++;
1418 1461
1419 case NGX_QUIC_FT_PING: 1462 case NGX_QUIC_FT_PING:
1420 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "PING frame"); 1463 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "PING frame");
1421 p++; 1464 p++;
1422 break; 1465 break;
1466
1467 case NGX_QUIC_FT_NEW_CONNECTION_ID:
1468 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "NCID frame");
1469
1470 frame->u.ncid.seqnum = ngx_quic_parse_int(&p);
1471 frame->u.ncid.retire = ngx_quic_parse_int(&p);
1472 frame->u.ncid.len = *p++;
1473 ngx_memcpy(frame->u.ncid.cid, p, frame->u.ncid.len);
1474 p += frame->u.ncid.len;
1475
1476 ngx_memcpy(frame->u.ncid.srt, p, 16);
1477 p += 16;
1478
1479 break;
1480
1481 case NGX_QUIC_FT_CONNECTION_CLOSE:
1482 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "connection close frame => NGX_ERROR");
1483
1484 // TODO: parse connection close here
1485 return NGX_ERROR;
1486 break;
1487
1423 default: 1488 default:
1424 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, 1489 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
1425 "unknown frame type %xi", frame->type); 1490 "unknown frame type %xi", frame->type);
1426 return NGX_ERROR; 1491 return NGX_ERROR;
1427 } 1492 }
1428 1493
1429 pkt->pos = p; 1494 return p - start;
1430
1431 return NGX_OK;
1432 } 1495 }
1433 1496
1434 1497
1435 static ngx_int_t 1498 static ngx_int_t
1436 ngx_quic_handle_crypto_frame(ngx_connection_t *c, ngx_quic_header_t *pkt, 1499 ngx_quic_handle_crypto_frame(ngx_connection_t *c, ngx_quic_header_t *pkt,
1537 1600
1538 /* process all payload from the current packet and generate ack if required */ 1601 /* process all payload from the current packet and generate ack if required */
1539 static ngx_int_t 1602 static ngx_int_t
1540 ngx_quic_payload_handler(ngx_connection_t *c, ngx_quic_header_t *pkt) 1603 ngx_quic_payload_handler(ngx_connection_t *c, ngx_quic_header_t *pkt)
1541 { 1604 {
1542 u_char *end; 1605 u_char *end, *p;
1606 ssize_t len;
1543 ngx_uint_t ack_this; 1607 ngx_uint_t ack_this;
1544 ngx_quic_frame_t frame, *ack_frame; 1608 ngx_quic_frame_t frame, *ack_frame;
1545 ngx_quic_connection_t *qc; 1609 ngx_quic_connection_t *qc;
1546 1610
1547 qc = c->quic; 1611 qc = c->quic;
1548 end = pkt->payload.data + pkt->payload.len; 1612
1613 p = pkt->payload.data;
1614 end = p + pkt->payload.len;
1549 1615
1550 ack_this = 0; 1616 ack_this = 0;
1551 1617
1552 while (pkt->pos < end) { 1618 while (p < end) {
1553 1619
1554 if (ngx_quic_read_frame(c, pkt, &frame) != NGX_OK) { 1620 len = ngx_quic_read_frame(c, p, end, &frame);
1621 if (len < 0) {
1555 return NGX_ERROR; 1622 return NGX_ERROR;
1556 } 1623 }
1624
1625 p += len;
1557 1626
1558 switch (frame.type) { 1627 switch (frame.type) {
1559 1628
1560 case NGX_QUIC_FT_ACK: 1629 case NGX_QUIC_FT_ACK:
1561 1630
1592 1661
1593 case NGX_QUIC_FT_PING: 1662 case NGX_QUIC_FT_PING:
1594 ack_this = 1; 1663 ack_this = 1;
1595 continue; 1664 continue;
1596 1665
1666 case NGX_QUIC_FT_NEW_CONNECTION_ID:
1667 ack_this = 1;
1668 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
1669 "NCID: { seq=%ui retire=%ui len=%ui}",
1670 frame.u.ncid.seqnum,
1671 frame.u.ncid.retire,
1672 frame.u.ncid.len);
1673 continue;
1674
1597 default: 1675 default:
1598 ngx_log_error(NGX_LOG_INFO, c->log, 0, 1676 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1599 "unexpected frame type 0x%xd in packet", frame.type); 1677 "unexpected frame type 0x%xd in packet", frame.type);
1600 return NGX_ERROR; 1678 return NGX_ERROR;
1601 } 1679 }
1602 } 1680 }
1603 1681
1682 if (p != end) {
1683 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1684 "trailing garbage in payload: %ui bytes", end - p);
1685 return NGX_ERROR;
1686 }
1687
1688
1604 if (ack_this == 0) { 1689 if (ack_this == 0) {
1605 /* do not ack packets with ACKs and PADDING */ 1690 /* do not ack packets with ACKs and PADDING */
1606 return NGX_OK; 1691 return NGX_OK;
1607 } 1692 }
1608 1693
1624 return ngx_quic_output(c); 1709 return ngx_quic_output(c);
1625 } 1710 }
1626 1711
1627 1712
1628 static ngx_int_t 1713 static ngx_int_t
1629 ngx_quic_new_connection(ngx_connection_t *c, ngx_ssl_t *ssl, ngx_buf_t *b) 1714 ngx_quic_new_connection(ngx_connection_t *c, ngx_ssl_t *ssl,
1715 ngx_quic_header_t *pkt)
1630 { 1716 {
1631 ngx_quic_connection_t *qc; 1717 ngx_quic_connection_t *qc;
1632 1718
1633 ngx_quic_header_t pkt = { 0 }; 1719 if (ngx_buf_size(pkt->raw) < 1200) {
1634
1635 pkt.buf.data = b->start;
1636 pkt.buf.len = b->last - b->pos;
1637
1638 if (ngx_buf_size(b) < 1200) {
1639 ngx_log_error(NGX_LOG_INFO, c->log, 0, "too small UDP datagram"); 1720 ngx_log_error(NGX_LOG_INFO, c->log, 0, "too small UDP datagram");
1640 return NGX_ERROR; 1721 return NGX_ERROR;
1641 } 1722 }
1642 1723
1643 if (ngx_quic_process_long_header(c, &pkt) != NGX_OK) { 1724 if (ngx_quic_process_long_header(c, pkt) != NGX_OK) {
1644 return NGX_ERROR; 1725 return NGX_ERROR;
1645 } 1726 }
1646 1727
1647 if ((pkt.flags & 0xf0) != NGX_QUIC_PKT_INITIAL) { 1728 if ((pkt->flags & 0xf0) != NGX_QUIC_PKT_INITIAL) {
1648 ngx_log_error(NGX_LOG_INFO, c->log, 0, 1729 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1649 "invalid initial packet: 0x%xi", pkt.flags); 1730 "invalid initial packet: 0x%xi", pkt->flags);
1650 return NGX_ERROR; 1731 return NGX_ERROR;
1651 } 1732 }
1652 1733
1653 if (ngx_quic_process_initial_header(c, &pkt) != NGX_OK) { 1734 if (ngx_quic_process_initial_header(c, pkt) != NGX_OK) {
1654 return NGX_ERROR; 1735 return NGX_ERROR;
1655 } 1736 }
1656 1737
1657 qc = ngx_pcalloc(c->pool, sizeof(ngx_quic_connection_t)); 1738 qc = ngx_pcalloc(c->pool, sizeof(ngx_quic_connection_t));
1658 if (qc == NULL) { 1739 if (qc == NULL) {
1660 } 1741 }
1661 1742
1662 c->quic = qc; 1743 c->quic = qc;
1663 qc->ssl = ssl; 1744 qc->ssl = ssl;
1664 1745
1665 qc->dcid.len = pkt.dcid.len; 1746 qc->dcid.len = pkt->dcid.len;
1666 qc->dcid.data = ngx_pnalloc(c->pool, pkt.dcid.len); 1747 qc->dcid.data = ngx_pnalloc(c->pool, pkt->dcid.len);
1667 if (qc->dcid.data == NULL) { 1748 if (qc->dcid.data == NULL) {
1668 return NGX_ERROR; 1749 return NGX_ERROR;
1669 } 1750 }
1670 ngx_memcpy(qc->dcid.data, pkt.dcid.data, qc->dcid.len); 1751 ngx_memcpy(qc->dcid.data, pkt->dcid.data, qc->dcid.len);
1671 1752
1672 qc->scid.len = pkt.scid.len; 1753 qc->scid.len = pkt->scid.len;
1673 qc->scid.data = ngx_pnalloc(c->pool, qc->scid.len); 1754 qc->scid.data = ngx_pnalloc(c->pool, qc->scid.len);
1674 if (qc->scid.data == NULL) { 1755 if (qc->scid.data == NULL) {
1675 return NGX_ERROR; 1756 return NGX_ERROR;
1676 } 1757 }
1677 ngx_memcpy(qc->scid.data, pkt.scid.data, qc->scid.len); 1758 ngx_memcpy(qc->scid.data, pkt->scid.data, qc->scid.len);
1678 1759
1679 qc->token.len = pkt.token.len; 1760 qc->token.len = pkt->token.len;
1680 qc->token.data = ngx_pnalloc(c->pool, qc->token.len); 1761 qc->token.data = ngx_pnalloc(c->pool, qc->token.len);
1681 if (qc->token.data == NULL) { 1762 if (qc->token.data == NULL) {
1682 return NGX_ERROR; 1763 return NGX_ERROR;
1683 } 1764 }
1684 ngx_memcpy(qc->token.data, pkt.token.data, qc->token.len); 1765 ngx_memcpy(qc->token.data, pkt->token.data, qc->token.len);
1685 1766
1686 1767
1687 if (ngx_quic_initial_secret(c) != NGX_OK) { 1768 if (ngx_quic_initial_secret(c) != NGX_OK) {
1688 return NGX_ERROR; 1769 return NGX_ERROR;
1689 } 1770 }
1690 1771
1691 pkt.secret = &qc->client_in; 1772 pkt->secret = &qc->client_in;
1692 pkt.level = ssl_encryption_initial; 1773 pkt->level = ssl_encryption_initial;
1693 1774
1694 if (ngx_quic_decrypt(c, &pkt) != NGX_OK) { 1775 if (ngx_quic_decrypt(c, pkt) != NGX_OK) {
1695 return NGX_ERROR; 1776 return NGX_ERROR;
1696 } 1777 }
1697 1778
1698 if (ngx_quic_init_connection(c, &pkt) != NGX_OK) { 1779 if (ngx_quic_init_connection(c, pkt) != NGX_OK) {
1699 return NGX_ERROR; 1780 return NGX_ERROR;
1700 } 1781 }
1701 1782
1702 return ngx_quic_payload_handler(c, &pkt); 1783 return ngx_quic_payload_handler(c, pkt);
1703 } 1784 }
1704 1785
1705 1786
1706 static ngx_int_t 1787 static ngx_int_t
1707 ngx_quic_handshake_input(ngx_connection_t *c, ngx_buf_t *b) 1788 ngx_quic_handshake_input(ngx_connection_t *c, ngx_quic_header_t *pkt)
1708 { 1789 {
1709 ngx_ssl_conn_t *ssl_conn; 1790 ngx_ssl_conn_t *ssl_conn;
1710 ngx_quic_connection_t *qc; 1791 ngx_quic_connection_t *qc;
1711 1792
1712 ngx_quic_header_t pkt = { 0 };
1713
1714 qc = c->quic; 1793 qc = c->quic;
1715 ssl_conn = c->ssl->connection; 1794 ssl_conn = c->ssl->connection;
1716 1795
1717 pkt.buf.data = b->start;
1718 pkt.buf.len = b->last - b->pos;
1719
1720 /* extract cleartext data into pkt */ 1796 /* extract cleartext data into pkt */
1721 if (ngx_quic_process_long_header(c, &pkt) != NGX_OK) { 1797 if (ngx_quic_process_long_header(c, pkt) != NGX_OK) {
1722 return NGX_ERROR; 1798 return NGX_ERROR;
1723 } 1799 }
1724 1800
1725 if (pkt.dcid.len != qc->dcid.len) { 1801 if (pkt->dcid.len != qc->dcid.len) {
1726 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unexpected quic dcidl"); 1802 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unexpected quic dcidl");
1727 return NGX_ERROR; 1803 return NGX_ERROR;
1728 } 1804 }
1729 1805
1730 if (ngx_memcmp(pkt.dcid.data, qc->dcid.data, qc->dcid.len) != 0) { 1806 if (ngx_memcmp(pkt->dcid.data, qc->dcid.data, qc->dcid.len) != 0) {
1731 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unexpected quic dcid"); 1807 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unexpected quic dcid");
1732 return NGX_ERROR; 1808 return NGX_ERROR;
1733 } 1809 }
1734 1810
1735 if (pkt.scid.len != qc->scid.len) { 1811 if (pkt->scid.len != qc->scid.len) {
1736 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unexpected quic scidl"); 1812 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unexpected quic scidl");
1737 return NGX_ERROR; 1813 return NGX_ERROR;
1738 } 1814 }
1739 1815
1740 if (ngx_memcmp(pkt.scid.data, qc->scid.data, qc->scid.len) != 0) { 1816 if (ngx_memcmp(pkt->scid.data, qc->scid.data, qc->scid.len) != 0) {
1741 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unexpected quic scid"); 1817 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unexpected quic scid");
1742 return NGX_ERROR; 1818 return NGX_ERROR;
1743 } 1819 }
1744 1820
1745 if ((pkt.flags & 0xf0) != NGX_QUIC_PKT_HANDSHAKE) { 1821 if ((pkt->flags & 0xf0) != NGX_QUIC_PKT_HANDSHAKE) {
1746 ngx_log_error(NGX_LOG_INFO, c->log, 0, 1822 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1747 "invalid packet type: 0x%xi", pkt.flags); 1823 "invalid packet type: 0x%xi", pkt->flags);
1748 return NGX_ERROR; 1824 return NGX_ERROR;
1749 } 1825 }
1750 1826
1751 if (ngx_quic_process_handshake_header(c, &pkt) != NGX_OK) { 1827 if (ngx_quic_process_handshake_header(c, pkt) != NGX_OK) {
1752 return NGX_ERROR; 1828 return NGX_ERROR;
1753 } 1829 }
1754 1830
1755 pkt.secret = &qc->client_hs; 1831 pkt->secret = &qc->client_hs;
1756 pkt.level = ssl_encryption_handshake; 1832 pkt->level = ssl_encryption_handshake;
1757 1833
1758 if (ngx_quic_decrypt(c, &pkt) != NGX_OK) { 1834 if (ngx_quic_decrypt(c, pkt) != NGX_OK) {
1759 return NGX_ERROR; 1835 return NGX_ERROR;
1760 } 1836 }
1761 1837
1762 return ngx_quic_payload_handler(c, &pkt); 1838 return ngx_quic_payload_handler(c, pkt);
1763 } 1839 }
1764 1840
1765 1841
1766 static ngx_int_t 1842 static ngx_int_t
1767 ngx_quic_app_input(ngx_connection_t *c, ngx_buf_t *b) 1843 ngx_quic_app_input(ngx_connection_t *c, ngx_quic_header_t *pkt)
1768 { 1844 {
1769 ngx_quic_connection_t *qc; 1845 ngx_quic_connection_t *qc;
1770 1846
1771 qc = c->quic; 1847 qc = c->quic;
1772 1848
1773 /* TODO: this is a stub, untested */ 1849 /* TODO: this is a stub, untested */
1774 1850
1775 ngx_quic_header_t pkt = { 0 }; 1851 if (ngx_quic_process_short_header(c, pkt) != NGX_OK) {
1776 1852 return NGX_ERROR;
1777 pkt.buf.data = b->start; 1853 }
1778 pkt.buf.len = b->last - b->pos; 1854
1779 1855 pkt->secret = &qc->client_ad;
1780 if (ngx_quic_process_short_header(c, &pkt) != NGX_OK) { 1856 pkt->level = ssl_encryption_application;
1781 return NGX_ERROR; 1857
1782 } 1858 if (ngx_quic_decrypt(c, pkt) != NGX_OK) {
1783 1859 return NGX_ERROR;
1784 pkt.secret = &qc->client_ad; 1860 }
1785 pkt.level = ssl_encryption_application; 1861
1786 1862 return ngx_quic_payload_handler(c, pkt);
1787 if (ngx_quic_decrypt(c, &pkt) != NGX_OK) {
1788 return NGX_ERROR;
1789 }
1790
1791 return ngx_quic_payload_handler(c, &pkt);
1792 } 1863 }
1793 1864
1794 1865
1795 uint64_t 1866 uint64_t
1796 ngx_quic_parse_int(u_char **pos) 1867 ngx_quic_parse_int(u_char **pos)