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 }