Mercurial > hg > nginx
comparison src/event/ngx_event_quic.c @ 8308:e10b4c61420f quic
Implemented retransmission and retransmit queue.
All frames collected to packet are moved into a per-namespace send queue.
QUIC connection has a timer which fires on the closest max_ack_delay time.
The frame is deleted from the queue when a corresponding packet is acknowledged.
The NGX_QUIC_MAX_RETRANSMISSION is a timeout that defines maximum length
of retransmission of a frame.
author | Vladimir Homutov <vl@nginx.com> |
---|---|
date | Wed, 01 Apr 2020 17:06:26 +0300 |
parents | dc7ac778aafe |
children | 7ea2c68735f9 |
comparison
equal
deleted
inserted
replaced
8307:dc7ac778aafe | 8308:e10b4c61420f |
---|---|
42 | 42 |
43 typedef struct { | 43 typedef struct { |
44 ngx_quic_secret_t client_secret; | 44 ngx_quic_secret_t client_secret; |
45 ngx_quic_secret_t server_secret; | 45 ngx_quic_secret_t server_secret; |
46 | 46 |
47 ngx_uint_t pnum; | 47 uint64_t pnum; |
48 uint64_t largest; | |
49 | |
50 ngx_queue_t frames; | |
51 ngx_queue_t sent; | |
48 } ngx_quic_namespace_t; | 52 } ngx_quic_namespace_t; |
49 | 53 |
50 | 54 |
51 struct ngx_quic_connection_s { | 55 struct ngx_quic_connection_s { |
52 ngx_str_t scid; | 56 ngx_str_t scid; |
62 ngx_quic_namespace_t ns[NGX_QUIC_NAMESPACE_LAST]; | 66 ngx_quic_namespace_t ns[NGX_QUIC_NAMESPACE_LAST]; |
63 ngx_quic_secrets_t keys[NGX_QUIC_ENCRYPTION_LAST]; | 67 ngx_quic_secrets_t keys[NGX_QUIC_ENCRYPTION_LAST]; |
64 uint64_t crypto_offset[NGX_QUIC_ENCRYPTION_LAST]; | 68 uint64_t crypto_offset[NGX_QUIC_ENCRYPTION_LAST]; |
65 | 69 |
66 ngx_ssl_t *ssl; | 70 ngx_ssl_t *ssl; |
67 ngx_quic_frame_t *frames; | 71 |
68 ngx_quic_frame_t *free_frames; | 72 ngx_event_t retry; |
73 ngx_queue_t free_frames; | |
69 | 74 |
70 #if (NGX_DEBUG) | 75 #if (NGX_DEBUG) |
71 ngx_uint_t nframes; | 76 ngx_uint_t nframes; |
72 #endif | 77 #endif |
73 | 78 |
131 | 136 |
132 static void ngx_quic_queue_frame(ngx_quic_connection_t *qc, | 137 static void ngx_quic_queue_frame(ngx_quic_connection_t *qc, |
133 ngx_quic_frame_t *frame); | 138 ngx_quic_frame_t *frame); |
134 | 139 |
135 static ngx_int_t ngx_quic_output(ngx_connection_t *c); | 140 static ngx_int_t ngx_quic_output(ngx_connection_t *c); |
136 ngx_int_t ngx_quic_frames_send(ngx_connection_t *c, ngx_quic_frame_t *start, | 141 static ngx_int_t ngx_quic_output_ns(ngx_connection_t *c, |
137 ngx_quic_frame_t *end, size_t total); | 142 ngx_quic_namespace_t *ns, ngx_uint_t nsi); |
143 static void ngx_quic_free_frames(ngx_connection_t *c, ngx_queue_t *frames); | |
144 static ngx_int_t ngx_quic_send_frames(ngx_connection_t *c, ngx_queue_t *frames); | |
145 static void ngx_quic_retransmit_handler(ngx_event_t *ev); | |
146 static ngx_int_t ngx_quic_retransmit_ns(ngx_connection_t *c, | |
147 ngx_quic_namespace_t *ns, ngx_msec_t *waitp); | |
138 | 148 |
139 static void ngx_quic_rbtree_insert_stream(ngx_rbtree_node_t *temp, | 149 static void ngx_quic_rbtree_insert_stream(ngx_rbtree_node_t *temp, |
140 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel); | 150 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel); |
141 static ngx_quic_stream_t *ngx_quic_find_stream(ngx_rbtree_t *rbtree, | 151 static ngx_quic_stream_t *ngx_quic_find_stream(ngx_rbtree_t *rbtree, |
142 uint64_t id); | 152 uint64_t id); |
403 | 413 |
404 static ngx_int_t | 414 static ngx_int_t |
405 ngx_quic_new_connection(ngx_connection_t *c, ngx_ssl_t *ssl, ngx_quic_tp_t *tp, | 415 ngx_quic_new_connection(ngx_connection_t *c, ngx_ssl_t *ssl, ngx_quic_tp_t *tp, |
406 ngx_quic_header_t *pkt, ngx_connection_handler_pt handler) | 416 ngx_quic_header_t *pkt, ngx_connection_handler_pt handler) |
407 { | 417 { |
418 ngx_uint_t i; | |
408 ngx_quic_tp_t *ctp; | 419 ngx_quic_tp_t *ctp; |
409 ngx_quic_secrets_t *keys; | 420 ngx_quic_secrets_t *keys; |
410 ngx_quic_connection_t *qc; | 421 ngx_quic_connection_t *qc; |
411 static u_char buf[NGX_QUIC_DEFAULT_MAX_PACKET_SIZE]; | 422 static u_char buf[NGX_QUIC_DEFAULT_MAX_PACKET_SIZE]; |
412 | 423 |
438 | 449 |
439 qc->state = NGX_QUIC_ST_INITIAL; | 450 qc->state = NGX_QUIC_ST_INITIAL; |
440 | 451 |
441 ngx_rbtree_init(&qc->streams.tree, &qc->streams.sentinel, | 452 ngx_rbtree_init(&qc->streams.tree, &qc->streams.sentinel, |
442 ngx_quic_rbtree_insert_stream); | 453 ngx_quic_rbtree_insert_stream); |
454 | |
455 for (i = 0; i < 3; i++) { | |
456 ngx_queue_init(&qc->ns[i].frames); | |
457 ngx_queue_init(&qc->ns[i].sent); | |
458 } | |
459 | |
460 ngx_queue_init(&qc->free_frames); | |
461 | |
462 qc->retry.log = c->log; | |
463 qc->retry.data = c; | |
464 qc->retry.handler = ngx_quic_retransmit_handler; | |
465 qc->retry.cancelable = 1; | |
443 | 466 |
444 c->quic = qc; | 467 c->quic = qc; |
445 qc->ssl = ssl; | 468 qc->ssl = ssl; |
446 qc->tp = *tp; | 469 qc->tp = *tp; |
447 qc->streams.handler = handler; | 470 qc->streams.handler = handler; |
687 "quic connection has %ui active streams", ns); | 710 "quic connection has %ui active streams", ns); |
688 | 711 |
689 qc->closing = 1; | 712 qc->closing = 1; |
690 return; | 713 return; |
691 } | 714 } |
715 | |
716 if (qc->retry.timer_set) { | |
717 ngx_del_timer(&qc->retry); | |
718 } | |
692 } | 719 } |
693 | 720 |
694 if (c->ssl) { | 721 if (c->ssl) { |
695 (void) ngx_ssl_shutdown(c); | 722 (void) ngx_ssl_shutdown(c); |
696 } | 723 } |
1127 ack_frame->level = (pkt->level == ssl_encryption_early_data) | 1154 ack_frame->level = (pkt->level == ssl_encryption_early_data) |
1128 ? ssl_encryption_application | 1155 ? ssl_encryption_application |
1129 : pkt->level; | 1156 : pkt->level; |
1130 | 1157 |
1131 ack_frame->type = NGX_QUIC_FT_ACK; | 1158 ack_frame->type = NGX_QUIC_FT_ACK; |
1132 ack_frame->u.ack.pn = pkt->pn; | 1159 ack_frame->u.ack.largest = pkt->pn; |
1160 /* only ack immediate packet ]*/ | |
1161 ack_frame->u.ack.first_range = 0; | |
1133 | 1162 |
1134 ngx_sprintf(ack_frame->info, "ACK for PN=%d from frame handler level=%d", pkt->pn, ack_frame->level); | 1163 ngx_sprintf(ack_frame->info, "ACK for PN=%d from frame handler level=%d", pkt->pn, ack_frame->level); |
1135 ngx_quic_queue_frame(qc, ack_frame); | 1164 ngx_quic_queue_frame(qc, ack_frame); |
1136 | 1165 |
1137 return ngx_quic_output(c); | 1166 return ngx_quic_output(c); |
1138 } | 1167 } |
1139 | 1168 |
1140 | 1169 |
1141 static ngx_int_t | 1170 static ngx_int_t |
1142 ngx_quic_handle_ack_frame(ngx_connection_t *c, ngx_quic_header_t *pkt, | 1171 ngx_quic_handle_ack_frame(ngx_connection_t *c, ngx_quic_header_t *pkt, |
1143 ngx_quic_ack_frame_t *f) | 1172 ngx_quic_ack_frame_t *ack) |
1144 { | 1173 { |
1145 /* TODO: handle ACK here */ | 1174 ngx_uint_t found, min; |
1175 ngx_queue_t *q, range; | |
1176 ngx_quic_frame_t *f; | |
1177 ngx_quic_namespace_t *ns; | |
1178 | |
1179 ns = &c->quic->ns[ngx_quic_ns(pkt->level)]; | |
1180 | |
1181 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
1182 "ngx_quic_handle_ack_frame in namespace %d", | |
1183 ngx_quic_ns(pkt->level)); | |
1184 | |
1185 if (ack->first_range > ack->largest) { | |
1186 ngx_log_error(NGX_LOG_INFO, c->log, 0, | |
1187 "invalid first range in ack frame"); | |
1188 return NGX_ERROR; | |
1189 } | |
1190 | |
1191 min = ack->largest - ack->first_range; | |
1192 | |
1193 found = 0; | |
1194 | |
1195 ngx_queue_init(&range); | |
1196 | |
1197 q = ngx_queue_head(&ns->sent); | |
1198 | |
1199 while (q != ngx_queue_sentinel(&ns->sent)) { | |
1200 | |
1201 f = ngx_queue_data(q, ngx_quic_frame_t, queue); | |
1202 | |
1203 if (f->pnum >= min && f->pnum <= ack->largest) { | |
1204 q = ngx_queue_next(q); | |
1205 ngx_queue_remove(&f->queue); | |
1206 ngx_quic_free_frame(c, f); | |
1207 found = 1; | |
1208 | |
1209 } else { | |
1210 q = ngx_queue_next(q); | |
1211 } | |
1212 } | |
1213 | |
1214 if (!found) { | |
1215 | |
1216 if (ack->largest <= ns->pnum) { | |
1217 /* duplicate ACK or ACK for non-ack-eliciting frame */ | |
1218 return NGX_OK; | |
1219 } | |
1220 | |
1221 ngx_log_error(NGX_LOG_INFO, c->log, 0, | |
1222 "ACK for the packet not in sent queue "); | |
1223 // TODO: handle error properly: PROTOCOL VIOLATION? | |
1224 return NGX_ERROR; | |
1225 } | |
1226 | |
1227 /* 13.2.3. Receiver Tracking of ACK Frames */ | |
1228 if (ns->largest < ack->largest) { | |
1229 ack->largest = ns->largest; | |
1230 } | |
1231 | |
1146 return NGX_OK; | 1232 return NGX_OK; |
1147 } | 1233 } |
1148 | 1234 |
1149 | 1235 |
1150 static ngx_int_t | 1236 static ngx_int_t |
1378 | 1464 |
1379 | 1465 |
1380 static void | 1466 static void |
1381 ngx_quic_queue_frame(ngx_quic_connection_t *qc, ngx_quic_frame_t *frame) | 1467 ngx_quic_queue_frame(ngx_quic_connection_t *qc, ngx_quic_frame_t *frame) |
1382 { | 1468 { |
1383 ngx_quic_frame_t **f; | 1469 ngx_quic_namespace_t *ns; |
1384 | 1470 |
1385 for (f = &qc->frames; *f; f = &(*f)->next) { | 1471 ns = &qc->ns[ngx_quic_ns(frame->level)]; |
1386 if ((*f)->level > frame->level) { | 1472 |
1387 break; | 1473 ngx_queue_insert_tail(&ns->frames, &frame->queue); |
1388 } | |
1389 } | |
1390 | |
1391 frame->next = *f; | |
1392 *f = frame; | |
1393 } | 1474 } |
1394 | 1475 |
1395 | 1476 |
1396 static ngx_int_t | 1477 static ngx_int_t |
1397 ngx_quic_output(ngx_connection_t *c) | 1478 ngx_quic_output(ngx_connection_t *c) |
1398 { | 1479 { |
1480 ngx_uint_t i; | |
1481 ngx_quic_namespace_t *ns; | |
1482 ngx_quic_connection_t *qc; | |
1483 | |
1484 c->log->action = "sending frames"; | |
1485 | |
1486 qc = c->quic; | |
1487 | |
1488 for (i = 0; i < 3; i++) { | |
1489 ns = &qc->ns[i]; | |
1490 if (ngx_quic_output_ns(c, ns, i) != NGX_OK) { | |
1491 return NGX_ERROR; | |
1492 } | |
1493 } | |
1494 | |
1495 if (!qc->send_timer_set) { | |
1496 qc->send_timer_set = 1; | |
1497 ngx_add_timer(c->read, qc->tp.max_idle_timeout); | |
1498 } | |
1499 | |
1500 if (!qc->retry.timer_set && !qc->closing) { | |
1501 ngx_add_timer(&qc->retry, qc->tp.max_ack_delay * 1000); | |
1502 } | |
1503 | |
1504 return NGX_OK; | |
1505 } | |
1506 | |
1507 | |
1508 static ngx_int_t | |
1509 ngx_quic_output_ns(ngx_connection_t *c, ngx_quic_namespace_t *ns, | |
1510 ngx_uint_t nsi) | |
1511 { | |
1399 size_t len, hlen, n; | 1512 size_t len, hlen, n; |
1400 ngx_uint_t lvl; | 1513 ngx_int_t rc; |
1401 ngx_quic_frame_t *f, *start, *next; | 1514 ngx_queue_t *q, range; |
1515 ngx_quic_frame_t *f; | |
1402 ngx_quic_connection_t *qc; | 1516 ngx_quic_connection_t *qc; |
1403 | 1517 |
1404 qc = c->quic; | 1518 qc = c->quic; |
1405 | 1519 |
1406 if (qc->frames == NULL) { | 1520 if (ngx_queue_empty(&ns->frames)) { |
1407 return NGX_OK; | 1521 return NGX_OK; |
1408 } | 1522 } |
1409 | 1523 |
1410 c->log->action = "sending frames"; | 1524 hlen = (nsi == 2) ? NGX_QUIC_MAX_SHORT_HEADER |
1411 | 1525 : NGX_QUIC_MAX_LONG_HEADER; |
1412 lvl = qc->frames->level; | 1526 |
1413 start = qc->frames; | 1527 hlen += EVP_GCM_TLS_TAG_LEN; |
1414 f = start; | 1528 |
1529 q = ngx_queue_head(&ns->frames); | |
1415 | 1530 |
1416 do { | 1531 do { |
1417 len = 0; | 1532 len = 0; |
1418 | 1533 ngx_queue_init(&range); |
1419 hlen = (lvl == ssl_encryption_application) ? NGX_QUIC_MAX_SHORT_HEADER | |
1420 : NGX_QUIC_MAX_LONG_HEADER; | |
1421 hlen += EVP_GCM_TLS_TAG_LEN; | |
1422 | 1534 |
1423 do { | 1535 do { |
1424 /* process same-level group of frames */ | 1536 /* process group of frames that fits into packet */ |
1425 | 1537 f = ngx_queue_data(q, ngx_quic_frame_t, queue); |
1426 n = ngx_quic_create_frame(NULL, NULL, f); | 1538 |
1539 n = ngx_quic_create_frame(NULL, f); | |
1427 | 1540 |
1428 if (len && hlen + len + n > qc->ctp.max_packet_size) { | 1541 if (len && hlen + len + n > qc->ctp.max_packet_size) { |
1429 break; | 1542 break; |
1430 } | 1543 } |
1431 | 1544 |
1545 q = ngx_queue_next(q); | |
1546 | |
1547 f->first = ngx_current_msec; | |
1548 | |
1549 ngx_queue_remove(&f->queue); | |
1550 ngx_queue_insert_tail(&range, &f->queue); | |
1551 | |
1432 len += n; | 1552 len += n; |
1433 | 1553 |
1434 f = f->next; | 1554 } while (q != ngx_queue_sentinel(&ns->frames)); |
1435 } while (f && f->level == lvl); | 1555 |
1436 | 1556 rc = ngx_quic_send_frames(c, &range); |
1437 | 1557 |
1438 if (ngx_quic_frames_send(c, start, f, len) != NGX_OK) { | 1558 if (rc == NGX_OK) { |
1559 /* | |
1560 * frames are moved into the sent queue | |
1561 * to wait for ack/be retransmitted | |
1562 */ | |
1563 ngx_queue_add(&ns->sent, &range); | |
1564 | |
1565 } else if (rc == NGX_DONE) { | |
1566 | |
1567 /* no ack is expected for this frames, can free them */ | |
1568 ngx_quic_free_frames(c, &range); | |
1569 | |
1570 } else { | |
1439 return NGX_ERROR; | 1571 return NGX_ERROR; |
1440 } | 1572 } |
1441 | 1573 |
1442 while (start != f) { | 1574 |
1443 next = start->next; | 1575 } while (q != ngx_queue_sentinel(&ns->frames)); |
1444 ngx_quic_free_frame(c, start); | |
1445 start = next; | |
1446 } | |
1447 | |
1448 if (f == NULL) { | |
1449 break; | |
1450 } | |
1451 | |
1452 lvl = f->level; // TODO: must not decrease (ever, also between calls) | |
1453 | |
1454 } while (1); | |
1455 | |
1456 qc->frames = NULL; | |
1457 | |
1458 if (!qc->send_timer_set) { | |
1459 qc->send_timer_set = 1; | |
1460 ngx_add_timer(c->read, qc->tp.max_idle_timeout); | |
1461 } | |
1462 | 1576 |
1463 return NGX_OK; | 1577 return NGX_OK; |
1464 } | 1578 } |
1465 | 1579 |
1466 | 1580 |
1581 static void | |
1582 ngx_quic_free_frames(ngx_connection_t *c, ngx_queue_t *frames) | |
1583 { | |
1584 ngx_queue_t *q; | |
1585 ngx_quic_frame_t *f; | |
1586 | |
1587 q = ngx_queue_head(frames); | |
1588 | |
1589 do { | |
1590 f = ngx_queue_data(q, ngx_quic_frame_t, queue); | |
1591 q = ngx_queue_next(q); | |
1592 | |
1593 ngx_quic_free_frame(c, f); | |
1594 | |
1595 } while (q != ngx_queue_sentinel(frames)); | |
1596 } | |
1597 | |
1598 | |
1467 /* pack a group of frames [start; end) into memory p and send as single packet */ | 1599 /* pack a group of frames [start; end) into memory p and send as single packet */ |
1468 ngx_int_t | 1600 static ngx_int_t |
1469 ngx_quic_frames_send(ngx_connection_t *c, ngx_quic_frame_t *start, | 1601 ngx_quic_send_frames(ngx_connection_t *c, ngx_queue_t *frames) |
1470 ngx_quic_frame_t *end, size_t total) | |
1471 { | 1602 { |
1472 ssize_t len; | 1603 ssize_t len; |
1473 u_char *p; | 1604 u_char *p; |
1605 ngx_msec_t now; | |
1474 ngx_str_t out, res; | 1606 ngx_str_t out, res; |
1475 ngx_quic_frame_t *f; | 1607 ngx_queue_t *q; |
1608 ngx_quic_frame_t *f, *start; | |
1476 ngx_quic_header_t pkt; | 1609 ngx_quic_header_t pkt; |
1477 ngx_quic_secrets_t *keys; | 1610 ngx_quic_secrets_t *keys; |
1478 ngx_quic_namespace_t *ns; | 1611 ngx_quic_namespace_t *ns; |
1479 ngx_quic_connection_t *qc; | 1612 ngx_quic_connection_t *qc; |
1480 static ngx_str_t initial_token = ngx_null_string; | 1613 static ngx_str_t initial_token = ngx_null_string; |
1481 static u_char src[NGX_QUIC_DEFAULT_MAX_PACKET_SIZE]; | 1614 static u_char src[NGX_QUIC_DEFAULT_MAX_PACKET_SIZE]; |
1482 static u_char dst[NGX_QUIC_DEFAULT_MAX_PACKET_SIZE]; | 1615 static u_char dst[NGX_QUIC_DEFAULT_MAX_PACKET_SIZE]; |
1483 | 1616 |
1484 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, | 1617 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "ngx_quic_send_frames"); |
1485 "sending frames %p...%p", start, end); | 1618 |
1619 q = ngx_queue_head(frames); | |
1620 start = ngx_queue_data(q, ngx_quic_frame_t, queue); | |
1621 | |
1622 ns = &c->quic->ns[ngx_quic_ns(start->level)]; | |
1486 | 1623 |
1487 ngx_memzero(&pkt, sizeof(ngx_quic_header_t)); | 1624 ngx_memzero(&pkt, sizeof(ngx_quic_header_t)); |
1488 | 1625 |
1489 p = src; | 1626 p = src; |
1490 out.data = src; | 1627 out.data = src; |
1491 | 1628 |
1492 for (f = start; f != end; f = f->next) { | 1629 for (q = ngx_queue_head(frames); |
1630 q != ngx_queue_sentinel(frames); | |
1631 q = ngx_queue_next(q)) | |
1632 { | |
1633 f = ngx_queue_data(q, ngx_quic_frame_t, queue); | |
1493 | 1634 |
1494 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "frame: %s", f->info); | 1635 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "frame: %s", f->info); |
1495 | 1636 |
1496 len = ngx_quic_create_frame(p, p + total, f); | 1637 len = ngx_quic_create_frame(p, f); |
1497 if (len == -1) { | 1638 if (len == -1) { |
1498 return NGX_ERROR; | 1639 return NGX_ERROR; |
1499 } | 1640 } |
1500 | 1641 |
1501 p += len; | 1642 p += len; |
1643 f->pnum = ns->pnum; | |
1644 } | |
1645 | |
1646 if (start->level == ssl_encryption_initial) { | |
1647 /* ack will not be sent in initial packets due to initial keys being | |
1648 * discarded when handshake start. | |
1649 * Thus consider initial packets as non-ack-eliciting | |
1650 */ | |
1651 pkt.need_ack = 0; | |
1502 } | 1652 } |
1503 | 1653 |
1504 out.len = p - out.data; | 1654 out.len = p - out.data; |
1505 | 1655 |
1506 while (out.len < 4) { | 1656 while (out.len < 4) { |
1507 *p++ = NGX_QUIC_FT_PADDING; | 1657 *p++ = NGX_QUIC_FT_PADDING; |
1508 out.len++; | 1658 out.len++; |
1509 } | 1659 } |
1510 | 1660 |
1511 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, | 1661 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, |
1512 "packet ready: %ui bytes at level %d", | 1662 "packet ready: %ui bytes at level %d need_ack: %ui", |
1513 out.len, start->level); | 1663 out.len, start->level, pkt.need_ack); |
1514 | 1664 |
1515 qc = c->quic; | 1665 qc = c->quic; |
1516 | 1666 |
1517 keys = &c->quic->keys[start->level]; | 1667 keys = &c->quic->keys[start->level]; |
1518 ns = &c->quic->ns[ngx_quic_ns(start->level)]; | |
1519 | 1668 |
1520 pkt.secret = &keys->server; | 1669 pkt.secret = &keys->server; |
1521 pkt.number = ns->pnum; | 1670 pkt.number = ns->pnum; |
1522 | 1671 |
1523 if (start->level == ssl_encryption_initial) { | 1672 if (start->level == ssl_encryption_initial) { |
1540 return NGX_ERROR; | 1689 return NGX_ERROR; |
1541 } | 1690 } |
1542 | 1691 |
1543 ngx_quic_hexdump0(c->log, "packet to send", res.data, res.len); | 1692 ngx_quic_hexdump0(c->log, "packet to send", res.data, res.len); |
1544 | 1693 |
1545 c->send(c, res.data, res.len); // TODO: err handling | 1694 len = c->send(c, res.data, res.len); |
1546 | 1695 if (len == NGX_ERROR || (size_t) len != res.len) { |
1696 return NGX_ERROR; | |
1697 } | |
1698 | |
1699 /* len == NGX_OK || NGX_AGAIN */ | |
1547 ns->pnum++; | 1700 ns->pnum++; |
1701 | |
1702 now = ngx_current_msec; | |
1703 start->last = now; | |
1704 | |
1705 return pkt.need_ack ? NGX_OK : NGX_DONE; | |
1706 } | |
1707 | |
1708 | |
1709 static void | |
1710 ngx_quic_retransmit_handler(ngx_event_t *ev) | |
1711 { | |
1712 ngx_uint_t i; | |
1713 ngx_msec_t wait, nswait; | |
1714 ngx_connection_t *c; | |
1715 ngx_quic_connection_t *qc; | |
1716 | |
1717 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0, | |
1718 "retransmit timer"); | |
1719 | |
1720 c = ev->data; | |
1721 qc = c->quic; | |
1722 | |
1723 wait = 0; | |
1724 | |
1725 for (i = 0; i < NGX_QUIC_NAMESPACE_LAST; i++) { | |
1726 if (ngx_quic_retransmit_ns(c, &qc->ns[i], &nswait) != NGX_OK) { | |
1727 ngx_quic_close_connection(c); | |
1728 return; | |
1729 } | |
1730 | |
1731 if (i == 0) { | |
1732 wait = nswait; | |
1733 | |
1734 } else if (nswait > 0 && nswait < wait) { | |
1735 wait = nswait; | |
1736 } | |
1737 } | |
1738 | |
1739 if (wait > 0) { | |
1740 ngx_add_timer(&qc->retry, wait); | |
1741 } | |
1742 } | |
1743 | |
1744 | |
1745 static ngx_int_t | |
1746 ngx_quic_retransmit_ns(ngx_connection_t *c, ngx_quic_namespace_t *ns, | |
1747 ngx_msec_t *waitp) | |
1748 { | |
1749 uint64_t pn; | |
1750 ngx_msec_t now, wait; | |
1751 ngx_queue_t *q, range; | |
1752 ngx_quic_frame_t *f, *start; | |
1753 ngx_quic_connection_t *qc; | |
1754 | |
1755 qc = c->quic; | |
1756 | |
1757 now = ngx_current_msec; | |
1758 wait = 0; | |
1759 | |
1760 if (ngx_queue_empty(&ns->sent)) { | |
1761 *waitp = 0; | |
1762 return NGX_OK; | |
1763 } | |
1764 | |
1765 q = ngx_queue_head(&ns->sent); | |
1766 start = ngx_queue_data(q, ngx_quic_frame_t, queue); | |
1767 pn = start->pnum; | |
1768 f = start; | |
1769 | |
1770 do { | |
1771 ngx_queue_init(&range); | |
1772 | |
1773 /* send frames with same packet number to the wire */ | |
1774 do { | |
1775 f = ngx_queue_data(q, ngx_quic_frame_t, queue); | |
1776 | |
1777 if (start->first + qc->tp.max_idle_timeout < now) { | |
1778 ngx_log_error(NGX_LOG_ERR, c->log, 0, | |
1779 "retransmission timeout"); | |
1780 return NGX_DECLINED; | |
1781 } | |
1782 | |
1783 if (f->pnum != pn) { | |
1784 break; | |
1785 } | |
1786 | |
1787 q = ngx_queue_next(q); | |
1788 | |
1789 ngx_queue_remove(&f->queue); | |
1790 ngx_queue_insert_tail(&range, &f->queue); | |
1791 | |
1792 } while (q != ngx_queue_sentinel(&ns->sent)); | |
1793 | |
1794 wait = start->last + qc->tp.max_ack_delay - now; | |
1795 | |
1796 if ((ngx_msec_int_t) wait > 0) { | |
1797 break; | |
1798 } | |
1799 | |
1800 /* NGX_DONE is impossible here, such frames don't get into this queue */ | |
1801 if (ngx_quic_send_frames(c, &range) != NGX_OK) { | |
1802 return NGX_ERROR; | |
1803 } | |
1804 | |
1805 /* move frames group to the end of queue */ | |
1806 ngx_queue_add(&ns->sent, &range); | |
1807 | |
1808 } while (q != ngx_queue_sentinel(&ns->sent)); | |
1809 | |
1810 *waitp = wait; | |
1548 | 1811 |
1549 return NGX_OK; | 1812 return NGX_OK; |
1550 } | 1813 } |
1551 | 1814 |
1552 | 1815 |
1901 | 2164 |
1902 static ngx_quic_frame_t * | 2165 static ngx_quic_frame_t * |
1903 ngx_quic_alloc_frame(ngx_connection_t *c, size_t size) | 2166 ngx_quic_alloc_frame(ngx_connection_t *c, size_t size) |
1904 { | 2167 { |
1905 u_char *p; | 2168 u_char *p; |
2169 ngx_queue_t *q; | |
1906 ngx_quic_frame_t *frame; | 2170 ngx_quic_frame_t *frame; |
1907 ngx_quic_connection_t *qc; | 2171 ngx_quic_connection_t *qc; |
1908 | 2172 |
1909 if (size) { | 2173 if (size) { |
1910 p = ngx_alloc(size, c->log); | 2174 p = ngx_alloc(size, c->log); |
1915 } else { | 2179 } else { |
1916 p = NULL; | 2180 p = NULL; |
1917 } | 2181 } |
1918 | 2182 |
1919 qc = c->quic; | 2183 qc = c->quic; |
1920 frame = qc->free_frames; | 2184 |
1921 | 2185 if (!ngx_queue_empty(&qc->free_frames)) { |
1922 if (frame) { | 2186 |
1923 qc->free_frames = frame->next; | 2187 q = ngx_queue_head(&qc->free_frames); |
2188 frame = ngx_queue_data(q, ngx_quic_frame_t, queue); | |
2189 | |
2190 ngx_queue_remove(&frame->queue); | |
1924 | 2191 |
1925 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, | 2192 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, |
1926 "reuse quic frame n:%ui", qc->nframes); | 2193 "reuse quic frame n:%ui", qc->nframes); |
1927 | 2194 |
1928 } else { | 2195 } else { |
1957 | 2224 |
1958 if (frame->data) { | 2225 if (frame->data) { |
1959 ngx_free(frame->data); | 2226 ngx_free(frame->data); |
1960 } | 2227 } |
1961 | 2228 |
1962 frame->next = qc->free_frames; | 2229 ngx_queue_insert_head(&qc->free_frames, &frame->queue); |
1963 qc->free_frames = frame; | |
1964 | 2230 |
1965 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, | 2231 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, |
1966 "free quic frame n:%ui", qc->nframes); | 2232 "free quic frame n:%ui", qc->nframes); |
1967 } | 2233 } |