src/event/quic/ngx_event_quic_output.c - nginx source code

Functions defined

Macros defined

Source code


  1. /*
  2. * Copyright (C) Nginx, Inc.
  3. */


  4. #include <ngx_config.h>
  5. #include <ngx_core.h>
  6. #include <ngx_event.h>
  7. #include <ngx_event_quic_connection.h>


  8. #define NGX_QUIC_MAX_UDP_SEGMENT_BUF  65487 /* 65K - IPv6 header */
  9. #define NGX_QUIC_MAX_SEGMENTS            64 /* UDP_MAX_SEGMENTS */

  10. #define NGX_QUIC_RETRY_TOKEN_LIFETIME     3 /* seconds */
  11. #define NGX_QUIC_NEW_TOKEN_LIFETIME     600 /* seconds */
  12. #define NGX_QUIC_RETRY_BUFFER_SIZE      256
  13.     /* 1 flags + 4 version + 3 x (1 + 20) s/o/dcid + itag + token(64) */

  14. /*
  15. * RFC 9000, 10.3.  Stateless Reset
  16. *
  17. * Endpoints MUST discard packets that are too small to be valid QUIC
  18. * packets.  With the set of AEAD functions defined in [QUIC-TLS],
  19. * short header packets that are smaller than 21 bytes are never valid.
  20. */
  21. #define NGX_QUIC_MIN_PKT_LEN             21

  22. #define NGX_QUIC_MIN_SR_PACKET           43 /* 5 rand + 16 srt + 22 padding */
  23. #define NGX_QUIC_MAX_SR_PACKET         1200

  24. #define NGX_QUIC_CC_MIN_INTERVAL       1000 /* 1s */

  25. #define NGX_QUIC_SOCKET_RETRY_DELAY      10 /* ms, for NGX_AGAIN on write */


  26. #define ngx_quic_log_packet(log, pkt)                                         \
  27.     ngx_log_debug6(NGX_LOG_DEBUG_EVENT, log, 0,                               \
  28.                    "quic packet tx %s bytes:%ui need_ack:%d"                  \
  29.                    " number:%L encoded nl:%d trunc:0x%xD",                    \
  30.                    ngx_quic_level_name((pkt)->level), (pkt)->payload.len,     \
  31.                    (pkt)->need_ack, (pkt)->number, (pkt)->num_len,            \
  32.                     (pkt)->trunc);


  33. static ngx_int_t ngx_quic_create_datagrams(ngx_connection_t *c);
  34. static void ngx_quic_commit_send(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx);
  35. static void ngx_quic_revert_send(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx,
  36.     uint64_t pnum);
  37. #if ((NGX_HAVE_UDP_SEGMENT) && (NGX_HAVE_MSGHDR_MSG_CONTROL))
  38. static ngx_uint_t ngx_quic_allow_segmentation(ngx_connection_t *c);
  39. static ngx_int_t ngx_quic_create_segments(ngx_connection_t *c);
  40. static ssize_t ngx_quic_send_segments(ngx_connection_t *c, u_char *buf,
  41.     size_t len, struct sockaddr *sockaddr, socklen_t socklen, size_t segment);
  42. #endif
  43. static ssize_t ngx_quic_output_packet(ngx_connection_t *c,
  44.     ngx_quic_send_ctx_t *ctx, u_char *data, size_t max, size_t min);
  45. static void ngx_quic_init_packet(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx,
  46.     ngx_quic_header_t *pkt, ngx_quic_path_t *path);
  47. static ngx_uint_t ngx_quic_get_padding_level(ngx_connection_t *c);
  48. static ssize_t ngx_quic_send(ngx_connection_t *c, u_char *buf, size_t len,
  49.     struct sockaddr *sockaddr, socklen_t socklen);
  50. static void ngx_quic_set_packet_number(ngx_quic_header_t *pkt,
  51.     ngx_quic_send_ctx_t *ctx);


  52. ngx_int_t
  53. ngx_quic_output(ngx_connection_t *c)
  54. {
  55.     size_t                  in_flight;
  56.     ngx_int_t               rc;
  57.     ngx_quic_congestion_t  *cg;
  58.     ngx_quic_connection_t  *qc;

  59.     c->log->action = "sending frames";

  60.     qc = ngx_quic_get_connection(c);
  61.     cg = &qc->congestion;

  62.     in_flight = cg->in_flight;

  63. #if ((NGX_HAVE_UDP_SEGMENT) && (NGX_HAVE_MSGHDR_MSG_CONTROL))
  64.     if (ngx_quic_allow_segmentation(c)) {
  65.         rc = ngx_quic_create_segments(c);
  66.     } else
  67. #endif
  68.     {
  69.         rc = ngx_quic_create_datagrams(c);
  70.     }

  71.     if (rc != NGX_OK) {
  72.         return NGX_ERROR;
  73.     }

  74.     if (in_flight == cg->in_flight || qc->closing) {
  75.         /* no ack-eliciting data was sent or we are done */
  76.         return NGX_OK;
  77.     }

  78.     if (!qc->send_timer_set) {
  79.         qc->send_timer_set = 1;
  80.         ngx_add_timer(c->read, qc->tp.max_idle_timeout);
  81.     }

  82.     ngx_quic_set_lost_timer(c);

  83.     return NGX_OK;
  84. }


  85. static ngx_int_t
  86. ngx_quic_create_datagrams(ngx_connection_t *c)
  87. {
  88.     size_t                  len, min;
  89.     ssize_t                 n;
  90.     u_char                 *p;
  91.     uint64_t                preserved_pnum[NGX_QUIC_SEND_CTX_LAST];
  92.     ngx_uint_t              i, pad;
  93.     ngx_quic_path_t        *path;
  94.     ngx_quic_send_ctx_t    *ctx;
  95.     ngx_quic_congestion_t  *cg;
  96.     ngx_quic_connection_t  *qc;
  97.     static u_char           dst[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE];

  98.     qc = ngx_quic_get_connection(c);
  99.     cg = &qc->congestion;
  100.     path = qc->path;

  101.     while (cg->in_flight < cg->window) {

  102.         p = dst;

  103.         len = ngx_quic_path_limit(c, path, path->mtu);

  104.         pad = ngx_quic_get_padding_level(c);

  105.         for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) {

  106.             ctx = &qc->send_ctx[i];

  107.             preserved_pnum[i] = ctx->pnum;

  108.             if (ngx_quic_generate_ack(c, ctx) != NGX_OK) {
  109.                 return NGX_ERROR;
  110.             }

  111.             min = (i == pad && p - dst < NGX_QUIC_MIN_INITIAL_SIZE)
  112.                   ? NGX_QUIC_MIN_INITIAL_SIZE - (p - dst) : 0;

  113.             if (min > len) {
  114.                 /* padding can't be applied - avoid sending the packet */

  115.                 while (i-- > 0) {
  116.                     ctx = &qc->send_ctx[i];
  117.                     ngx_quic_revert_send(c, ctx, preserved_pnum[i]);
  118.                 }

  119.                 return NGX_OK;
  120.             }

  121.             n = ngx_quic_output_packet(c, ctx, p, len, min);
  122.             if (n == NGX_ERROR) {
  123.                 return NGX_ERROR;
  124.             }

  125.             p += n;
  126.             len -= n;
  127.         }

  128.         len = p - dst;
  129.         if (len == 0) {
  130.             break;
  131.         }

  132.         n = ngx_quic_send(c, dst, len, path->sockaddr, path->socklen);

  133.         if (n == NGX_ERROR) {
  134.             return NGX_ERROR;
  135.         }

  136.         if (n == NGX_AGAIN) {
  137.             for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) {
  138.                 ngx_quic_revert_send(c, &qc->send_ctx[i], preserved_pnum[i]);
  139.             }

  140.             ngx_add_timer(&qc->push, NGX_QUIC_SOCKET_RETRY_DELAY);
  141.             break;
  142.         }

  143.         for (i = 0; i < NGX_QUIC_SEND_CTX_LAST; i++) {
  144.             ngx_quic_commit_send(c, &qc->send_ctx[i]);
  145.         }

  146.         path->sent += len;
  147.     }

  148.     return NGX_OK;
  149. }


  150. static void
  151. ngx_quic_commit_send(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx)
  152. {
  153.     ngx_queue_t            *q;
  154.     ngx_quic_frame_t       *f;
  155.     ngx_quic_congestion_t  *cg;
  156.     ngx_quic_connection_t  *qc;

  157.     qc = ngx_quic_get_connection(c);

  158.     cg = &qc->congestion;

  159.     while (!ngx_queue_empty(&ctx->sending)) {

  160.         q = ngx_queue_head(&ctx->sending);
  161.         f = ngx_queue_data(q, ngx_quic_frame_t, queue);

  162.         ngx_queue_remove(q);

  163.         if (f->pkt_need_ack && !qc->closing) {
  164.             ngx_queue_insert_tail(&ctx->sent, q);

  165.             cg->in_flight += f->plen;

  166.         } else {
  167.             ngx_quic_free_frame(c, f);
  168.         }
  169.     }

  170.     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
  171.                    "quic congestion send if:%uz", cg->in_flight);
  172. }


  173. static void
  174. ngx_quic_revert_send(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx,
  175.     uint64_t pnum)
  176. {
  177.     ngx_queue_t  *q;

  178.     while (!ngx_queue_empty(&ctx->sending)) {

  179.         q = ngx_queue_last(&ctx->sending);
  180.         ngx_queue_remove(q);
  181.         ngx_queue_insert_head(&ctx->frames, q);
  182.     }

  183.     ctx->pnum = pnum;
  184. }


  185. #if ((NGX_HAVE_UDP_SEGMENT) && (NGX_HAVE_MSGHDR_MSG_CONTROL))

  186. static ngx_uint_t
  187. ngx_quic_allow_segmentation(ngx_connection_t *c)
  188. {
  189.     size_t                  bytes, len;
  190.     ngx_queue_t            *q;
  191.     ngx_quic_frame_t       *f;
  192.     ngx_quic_send_ctx_t    *ctx;
  193.     ngx_quic_connection_t  *qc;

  194.     qc = ngx_quic_get_connection(c);

  195.     if (!qc->conf->gso_enabled) {
  196.         return 0;
  197.     }

  198.     if (!qc->path->validated) {
  199.         /* don't even try to be faster on non-validated paths */
  200.         return 0;
  201.     }

  202.     ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_initial);
  203.     if (!ngx_queue_empty(&ctx->frames)) {
  204.         return 0;
  205.     }

  206.     ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_handshake);
  207.     if (!ngx_queue_empty(&ctx->frames)) {
  208.         return 0;
  209.     }

  210.     ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_application);

  211.     bytes = 0;
  212.     len = ngx_min(qc->path->mtu, NGX_QUIC_MAX_UDP_SEGMENT_BUF);

  213.     for (q = ngx_queue_head(&ctx->frames);
  214.          q != ngx_queue_sentinel(&ctx->frames);
  215.          q = ngx_queue_next(q))
  216.     {
  217.         f = ngx_queue_data(q, ngx_quic_frame_t, queue);

  218.         bytes += f->len;

  219.         if (bytes > len * 3) {
  220.             /* require at least ~3 full packets to batch */
  221.             return 1;
  222.         }
  223.     }

  224.     return 0;
  225. }


  226. static ngx_int_t
  227. ngx_quic_create_segments(ngx_connection_t *c)
  228. {
  229.     size_t                  len, segsize;
  230.     ssize_t                 n;
  231.     u_char                 *p, *end;
  232.     uint64_t                preserved_pnum;
  233.     ngx_uint_t              nseg;
  234.     ngx_quic_path_t        *path;
  235.     ngx_quic_send_ctx_t    *ctx;
  236.     ngx_quic_congestion_t  *cg;
  237.     ngx_quic_connection_t  *qc;
  238.     static u_char           dst[NGX_QUIC_MAX_UDP_SEGMENT_BUF];

  239.     qc = ngx_quic_get_connection(c);
  240.     cg = &qc->congestion;
  241.     path = qc->path;

  242.     ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_application);

  243.     if (ngx_quic_generate_ack(c, ctx) != NGX_OK) {
  244.         return NGX_ERROR;
  245.     }

  246.     segsize = ngx_min(path->mtu, NGX_QUIC_MAX_UDP_SEGMENT_BUF);
  247.     p = dst;
  248.     end = dst + sizeof(dst);

  249.     nseg = 0;

  250.     preserved_pnum = ctx->pnum;

  251.     for ( ;; ) {

  252.         len = ngx_min(segsize, (size_t) (end - p));

  253.         if (len && cg->in_flight + (p - dst) < cg->window) {

  254.             n = ngx_quic_output_packet(c, ctx, p, len, len);
  255.             if (n == NGX_ERROR) {
  256.                 return NGX_ERROR;
  257.             }

  258.             if (n) {
  259.                 p += n;
  260.                 nseg++;
  261.             }

  262.         } else {
  263.             n = 0;
  264.         }

  265.         if (p == dst) {
  266.             break;
  267.         }

  268.         if (n == 0 || nseg == NGX_QUIC_MAX_SEGMENTS) {
  269.             n = ngx_quic_send_segments(c, dst, p - dst, path->sockaddr,
  270.                                        path->socklen, segsize);
  271.             if (n == NGX_ERROR) {
  272.                 return NGX_ERROR;
  273.             }

  274.             if (n == NGX_AGAIN) {
  275.                 ngx_quic_revert_send(c, ctx, preserved_pnum);

  276.                 ngx_add_timer(&qc->push, NGX_QUIC_SOCKET_RETRY_DELAY);
  277.                 break;
  278.             }

  279.             ngx_quic_commit_send(c, ctx);

  280.             path->sent += n;

  281.             p = dst;
  282.             nseg = 0;
  283.             preserved_pnum = ctx->pnum;
  284.         }
  285.     }

  286.     return NGX_OK;
  287. }


  288. static ssize_t
  289. ngx_quic_send_segments(ngx_connection_t *c, u_char *buf, size_t len,
  290.     struct sockaddr *sockaddr, socklen_t socklen, size_t segment)
  291. {
  292.     size_t           clen;
  293.     ssize_t          n;
  294.     uint16_t        *valp;
  295.     struct iovec     iov;
  296.     struct msghdr    msg;
  297.     struct cmsghdr  *cmsg;

  298. #if (NGX_HAVE_ADDRINFO_CMSG)
  299.     char             msg_control[CMSG_SPACE(sizeof(uint16_t))
  300.                              + CMSG_SPACE(sizeof(ngx_addrinfo_t))];
  301. #else
  302.     char             msg_control[CMSG_SPACE(sizeof(uint16_t))];
  303. #endif

  304.     ngx_memzero(&msg, sizeof(struct msghdr));
  305.     ngx_memzero(msg_control, sizeof(msg_control));

  306.     iov.iov_len = len;
  307.     iov.iov_base = buf;

  308.     msg.msg_iov = &iov;
  309.     msg.msg_iovlen = 1;

  310.     msg.msg_name = sockaddr;
  311.     msg.msg_namelen = socklen;

  312.     msg.msg_control = msg_control;
  313.     msg.msg_controllen = sizeof(msg_control);

  314.     cmsg = CMSG_FIRSTHDR(&msg);

  315.     cmsg->cmsg_level = SOL_UDP;
  316.     cmsg->cmsg_type = UDP_SEGMENT;
  317.     cmsg->cmsg_len = CMSG_LEN(sizeof(uint16_t));

  318.     clen = CMSG_SPACE(sizeof(uint16_t));

  319.     valp = (void *) CMSG_DATA(cmsg);
  320.     *valp = segment;

  321. #if (NGX_HAVE_ADDRINFO_CMSG)
  322.     if (c->listening && c->listening->wildcard && c->local_sockaddr) {
  323.         cmsg = CMSG_NXTHDR(&msg, cmsg);
  324.         clen += ngx_set_srcaddr_cmsg(cmsg, c->local_sockaddr);
  325.     }
  326. #endif

  327.     msg.msg_controllen = clen;

  328.     n = ngx_sendmsg(c, &msg, 0);
  329.     if (n < 0) {
  330.         return n;
  331.     }

  332.     c->sent += n;

  333.     return n;
  334. }

  335. #endif



  336. static ngx_uint_t
  337. ngx_quic_get_padding_level(ngx_connection_t *c)
  338. {
  339.     ngx_uint_t              i;
  340.     ngx_queue_t            *q;
  341.     ngx_quic_frame_t       *f;
  342.     ngx_quic_send_ctx_t    *ctx;
  343.     ngx_quic_connection_t  *qc;

  344.     /*
  345.      * RFC 9000, 14.1.  Initial Datagram Size
  346.      *
  347.      * Similarly, a server MUST expand the payload of all UDP datagrams
  348.      * carrying ack-eliciting Initial packets to at least the smallest
  349.      * allowed maximum datagram size of 1200 bytes.
  350.      */

  351.     qc = ngx_quic_get_connection(c);
  352.     ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_initial);

  353.     for (q = ngx_queue_head(&ctx->frames);
  354.          q != ngx_queue_sentinel(&ctx->frames);
  355.          q = ngx_queue_next(q))
  356.     {
  357.         f = ngx_queue_data(q, ngx_quic_frame_t, queue);

  358.         if (f->need_ack) {
  359.             for (i = 0; i + 1 < NGX_QUIC_SEND_CTX_LAST; i++) {
  360.                 ctx = &qc->send_ctx[i + 1];

  361.                 if (ngx_queue_empty(&ctx->frames)) {
  362.                     break;
  363.                 }
  364.             }

  365.             return i;
  366.         }
  367.     }

  368.     return NGX_QUIC_SEND_CTX_LAST;
  369. }


  370. static ssize_t
  371. ngx_quic_output_packet(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx,
  372.     u_char *data, size_t max, size_t min)
  373. {
  374.     size_t                  len, pad, min_payload, max_payload;
  375.     u_char                 *p;
  376.     ssize_t                 flen;
  377.     ngx_str_t               res;
  378.     ngx_int_t               rc;
  379.     ngx_uint_t              nframes;
  380.     ngx_msec_t              now;
  381.     ngx_queue_t            *q;
  382.     ngx_quic_frame_t       *f;
  383.     ngx_quic_header_t       pkt;
  384.     ngx_quic_connection_t  *qc;
  385.     static u_char           src[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE];

  386.     if (ngx_queue_empty(&ctx->frames)) {
  387.         return 0;
  388.     }

  389.     ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
  390.                    "quic output %s packet max:%uz min:%uz",
  391.                    ngx_quic_level_name(ctx->level), max, min);

  392.     qc = ngx_quic_get_connection(c);

  393.     if (!ngx_quic_keys_available(qc->keys, ctx->level, 1)) {
  394.         ngx_log_error(NGX_LOG_ALERT, c->log, 0, "quic %s write keys discarded",
  395.                       ngx_quic_level_name(ctx->level));

  396.         while (!ngx_queue_empty(&ctx->frames)) {
  397.             q = ngx_queue_head(&ctx->frames);
  398.             ngx_queue_remove(q);

  399.             f = ngx_queue_data(q, ngx_quic_frame_t, queue);
  400.             ngx_quic_free_frame(c, f);
  401.         }

  402.         return 0;
  403.     }

  404.     ngx_quic_init_packet(c, ctx, &pkt, qc->path);

  405.     min_payload = ngx_quic_payload_size(&pkt, min);
  406.     max_payload = ngx_quic_payload_size(&pkt, max);

  407.     /* RFC 9001, 5.4.2.  Header Protection Sample */
  408.     pad = 4 - pkt.num_len;
  409.     min_payload = ngx_max(min_payload, pad);

  410.     if (min_payload > max_payload) {
  411.         return 0;
  412.     }

  413.     now = ngx_current_msec;
  414.     nframes = 0;
  415.     p = src;
  416.     len = 0;

  417.     for (q = ngx_queue_head(&ctx->frames);
  418.          q != ngx_queue_sentinel(&ctx->frames);
  419.          q = ngx_queue_next(q))
  420.     {
  421.         f = ngx_queue_data(q, ngx_quic_frame_t, queue);

  422.         if (len >= max_payload) {
  423.             break;
  424.         }

  425.         if (len + f->len > max_payload) {
  426.             rc = ngx_quic_split_frame(c, f, max_payload - len);

  427.             if (rc == NGX_ERROR) {
  428.                 return NGX_ERROR;
  429.             }

  430.             if (rc == NGX_DECLINED) {
  431.                 break;
  432.             }
  433.         }

  434.         if (f->need_ack) {
  435.             pkt.need_ack = 1;
  436.         }

  437.         f->pnum = ctx->pnum;
  438.         f->send_time = now;
  439.         f->plen = 0;

  440.         ngx_quic_log_frame(c->log, f, 1);

  441.         flen = ngx_quic_create_frame(p, f);
  442.         if (flen == -1) {
  443.             return NGX_ERROR;
  444.         }

  445.         len += flen;
  446.         p += flen;

  447.         nframes++;
  448.     }

  449.     if (nframes == 0) {
  450.         return 0;
  451.     }

  452.     if (len < min_payload) {
  453.         ngx_memset(p, NGX_QUIC_FT_PADDING, min_payload - len);
  454.         len = min_payload;
  455.     }

  456.     pkt.payload.data = src;
  457.     pkt.payload.len = len;

  458.     res.data = data;

  459.     ngx_quic_log_packet(c->log, &pkt);

  460.     if (ngx_quic_encrypt(&pkt, &res) != NGX_OK) {
  461.         return NGX_ERROR;
  462.     }

  463.     ctx->pnum++;

  464.     if (pkt.need_ack) {
  465.         q = ngx_queue_head(&ctx->frames);
  466.         f = ngx_queue_data(q, ngx_quic_frame_t, queue);

  467.         f->plen = res.len;
  468.     }

  469.     while (nframes--) {
  470.         q = ngx_queue_head(&ctx->frames);
  471.         f = ngx_queue_data(q, ngx_quic_frame_t, queue);

  472.         f->pkt_need_ack = pkt.need_ack;

  473.         ngx_queue_remove(q);
  474.         ngx_queue_insert_tail(&ctx->sending, q);
  475.     }

  476.     return res.len;
  477. }


  478. static void
  479. ngx_quic_init_packet(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx,
  480.     ngx_quic_header_t *pkt, ngx_quic_path_t *path)
  481. {
  482.     ngx_quic_connection_t  *qc;

  483.     qc = ngx_quic_get_connection(c);

  484.     ngx_memzero(pkt, sizeof(ngx_quic_header_t));

  485.     pkt->flags = NGX_QUIC_PKT_FIXED_BIT;

  486.     if (ctx->level == ssl_encryption_initial) {
  487.         pkt->flags |= NGX_QUIC_PKT_LONG | NGX_QUIC_PKT_INITIAL;

  488.     } else if (ctx->level == ssl_encryption_handshake) {
  489.         pkt->flags |= NGX_QUIC_PKT_LONG | NGX_QUIC_PKT_HANDSHAKE;

  490.     } else {
  491.         if (qc->key_phase) {
  492.             pkt->flags |= NGX_QUIC_PKT_KPHASE;
  493.         }
  494.     }

  495.     pkt->dcid.data = path->cid->id;
  496.     pkt->dcid.len = path->cid->len;

  497.     pkt->scid = qc->tp.initial_scid;

  498.     pkt->version = qc->version;
  499.     pkt->log = c->log;
  500.     pkt->level = ctx->level;

  501.     pkt->keys = qc->keys;

  502.     ngx_quic_set_packet_number(pkt, ctx);
  503. }


  504. static ssize_t
  505. ngx_quic_send(ngx_connection_t *c, u_char *buf, size_t len,
  506.     struct sockaddr *sockaddr, socklen_t socklen)
  507. {
  508.     ssize_t          n;
  509.     struct iovec     iov;
  510.     struct msghdr    msg;
  511. #if (NGX_HAVE_ADDRINFO_CMSG)
  512.     struct cmsghdr  *cmsg;
  513.     char             msg_control[CMSG_SPACE(sizeof(ngx_addrinfo_t))];
  514. #endif

  515.     ngx_memzero(&msg, sizeof(struct msghdr));

  516.     iov.iov_len = len;
  517.     iov.iov_base = buf;

  518.     msg.msg_iov = &iov;
  519.     msg.msg_iovlen = 1;

  520.     msg.msg_name = sockaddr;
  521.     msg.msg_namelen = socklen;

  522. #if (NGX_HAVE_ADDRINFO_CMSG)
  523.     if (c->listening && c->listening->wildcard && c->local_sockaddr) {

  524.         msg.msg_control = msg_control;
  525.         msg.msg_controllen = sizeof(msg_control);
  526.         ngx_memzero(msg_control, sizeof(msg_control));

  527.         cmsg = CMSG_FIRSTHDR(&msg);

  528.         msg.msg_controllen = ngx_set_srcaddr_cmsg(cmsg, c->local_sockaddr);
  529.     }
  530. #endif

  531.     n = ngx_sendmsg(c, &msg, 0);
  532.     if (n < 0) {
  533.         return n;
  534.     }

  535.     c->sent += n;

  536.     return n;
  537. }


  538. static void
  539. ngx_quic_set_packet_number(ngx_quic_header_t *pkt, ngx_quic_send_ctx_t *ctx)
  540. {
  541.     uint64_t  delta;

  542.     delta = ctx->pnum - ctx->largest_ack;
  543.     pkt->number = ctx->pnum;

  544.     if (delta <= 0x7F) {
  545.         pkt->num_len = 1;
  546.         pkt->trunc = ctx->pnum & 0xff;

  547.     } else if (delta <= 0x7FFF) {
  548.         pkt->num_len = 2;
  549.         pkt->flags |= 0x1;
  550.         pkt->trunc = ctx->pnum & 0xffff;

  551.     } else if (delta <= 0x7FFFFF) {
  552.         pkt->num_len = 3;
  553.         pkt->flags |= 0x2;
  554.         pkt->trunc = ctx->pnum & 0xffffff;

  555.     } else {
  556.         pkt->num_len = 4;
  557.         pkt->flags |= 0x3;
  558.         pkt->trunc = ctx->pnum & 0xffffffff;
  559.     }
  560. }


  561. ngx_int_t
  562. ngx_quic_negotiate_version(ngx_connection_t *c, ngx_quic_header_t *inpkt)
  563. {
  564.     size_t             len;
  565.     ngx_quic_header_t  pkt;
  566.     static u_char      buf[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE];

  567.     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
  568.                    "sending version negotiation packet");

  569.     pkt.log = c->log;
  570.     pkt.flags = NGX_QUIC_PKT_LONG | NGX_QUIC_PKT_FIXED_BIT;
  571.     pkt.dcid = inpkt->scid;
  572.     pkt.scid = inpkt->dcid;

  573.     len = ngx_quic_create_version_negotiation(&pkt, buf);

  574. #ifdef NGX_QUIC_DEBUG_PACKETS
  575.     ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
  576.                    "quic vnego packet to send len:%uz %*xs", len, len, buf);
  577. #endif

  578.     (void) ngx_quic_send(c, buf, len, c->sockaddr, c->socklen);

  579.     return NGX_DONE;
  580. }


  581. ngx_int_t
  582. ngx_quic_send_stateless_reset(ngx_connection_t *c, ngx_quic_conf_t *conf,
  583.     ngx_quic_header_t *pkt)
  584. {
  585.     u_char    *token;
  586.     size_t     len, max;
  587.     uint16_t   rndbytes;
  588.     u_char     buf[NGX_QUIC_MAX_SR_PACKET];

  589.     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
  590.                    "quic handle stateless reset output");

  591.     if (pkt->len <= NGX_QUIC_MIN_PKT_LEN) {
  592.         return NGX_DECLINED;
  593.     }

  594.     if (pkt->len <= NGX_QUIC_MIN_SR_PACKET) {
  595.         len = pkt->len - 1;

  596.     } else {
  597.         max = ngx_min(NGX_QUIC_MAX_SR_PACKET, pkt->len * 3);

  598.         if (RAND_bytes((u_char *) &rndbytes, sizeof(rndbytes)) != 1) {
  599.             return NGX_ERROR;
  600.         }

  601.         len = (rndbytes % (max - NGX_QUIC_MIN_SR_PACKET + 1))
  602.               + NGX_QUIC_MIN_SR_PACKET;
  603.     }

  604.     if (RAND_bytes(buf, len - NGX_QUIC_SR_TOKEN_LEN) != 1) {
  605.         return NGX_ERROR;
  606.     }

  607.     buf[0] &= ~NGX_QUIC_PKT_LONG;
  608.     buf[0] |= NGX_QUIC_PKT_FIXED_BIT;

  609.     token = &buf[len - NGX_QUIC_SR_TOKEN_LEN];

  610.     if (ngx_quic_new_sr_token(c, &pkt->dcid, conf->sr_token_key, token)
  611.         != NGX_OK)
  612.     {
  613.         return NGX_ERROR;
  614.     }

  615.     (void) ngx_quic_send(c, buf, len, c->sockaddr, c->socklen);

  616.     return NGX_DECLINED;
  617. }


  618. ngx_int_t
  619. ngx_quic_send_cc(ngx_connection_t *c)
  620. {
  621.     ngx_quic_frame_t       *frame;
  622.     ngx_quic_connection_t  *qc;

  623.     qc = ngx_quic_get_connection(c);

  624.     if (qc->draining) {
  625.         return NGX_OK;
  626.     }

  627.     if (qc->closing
  628.         && ngx_current_msec - qc->last_cc < NGX_QUIC_CC_MIN_INTERVAL)
  629.     {
  630.         /* dot not send CC too often */
  631.         return NGX_OK;
  632.     }

  633.     frame = ngx_quic_alloc_frame(c);
  634.     if (frame == NULL) {
  635.         return NGX_ERROR;
  636.     }

  637.     frame->level = qc->error_level;
  638.     frame->type = qc->error_app ? NGX_QUIC_FT_CONNECTION_CLOSE_APP
  639.                                 : NGX_QUIC_FT_CONNECTION_CLOSE;
  640.     frame->u.close.error_code = qc->error;
  641.     frame->u.close.frame_type = qc->error_ftype;

  642.     if (qc->error_reason) {
  643.         frame->u.close.reason.len = ngx_strlen(qc->error_reason);
  644.         frame->u.close.reason.data = (u_char *) qc->error_reason;
  645.     }

  646.     frame->ignore_congestion = 1;

  647.     qc->last_cc = ngx_current_msec;

  648.     return ngx_quic_frame_sendto(c, frame, 0, qc->path);
  649. }


  650. ngx_int_t
  651. ngx_quic_send_early_cc(ngx_connection_t *c, ngx_quic_header_t *inpkt,
  652.     ngx_uint_t err, const char *reason)
  653. {
  654.     ssize_t            len;
  655.     ngx_str_t          res;
  656.     ngx_quic_keys_t    keys;
  657.     ngx_quic_frame_t   frame;
  658.     ngx_quic_header_t  pkt;

  659.     static u_char       src[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE];
  660.     static u_char       dst[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE];

  661.     ngx_memzero(&frame, sizeof(ngx_quic_frame_t));
  662.     ngx_memzero(&pkt, sizeof(ngx_quic_header_t));

  663.     frame.level = inpkt->level;
  664.     frame.type = NGX_QUIC_FT_CONNECTION_CLOSE;
  665.     frame.u.close.error_code = err;

  666.     frame.u.close.reason.data = (u_char *) reason;
  667.     frame.u.close.reason.len = ngx_strlen(reason);

  668.     ngx_quic_log_frame(c->log, &frame, 1);

  669.     len = ngx_quic_create_frame(NULL, &frame);
  670.     if (len > NGX_QUIC_MAX_UDP_PAYLOAD_SIZE) {
  671.         return NGX_ERROR;
  672.     }

  673.     len = ngx_quic_create_frame(src, &frame);
  674.     if (len == -1) {
  675.         return NGX_ERROR;
  676.     }

  677.     ngx_memzero(&keys, sizeof(ngx_quic_keys_t));

  678.     pkt.keys = &keys;

  679.     if (ngx_quic_keys_set_initial_secret(pkt.keys, &inpkt->dcid, c->log)
  680.         != NGX_OK)
  681.     {
  682.         return NGX_ERROR;
  683.     }

  684.     pkt.flags = NGX_QUIC_PKT_FIXED_BIT | NGX_QUIC_PKT_LONG
  685.                 | NGX_QUIC_PKT_INITIAL;

  686.     pkt.num_len = 1;
  687.     /*
  688.      * pkt.num = 0;
  689.      * pkt.trunc = 0;
  690.      */

  691.     pkt.version = inpkt->version;
  692.     pkt.log = c->log;
  693.     pkt.level = inpkt->level;
  694.     pkt.dcid = inpkt->scid;
  695.     pkt.scid = inpkt->dcid;
  696.     pkt.payload.data = src;
  697.     pkt.payload.len = len;

  698.     res.data = dst;

  699.     ngx_quic_log_packet(c->log, &pkt);

  700.     if (ngx_quic_encrypt(&pkt, &res) != NGX_OK) {
  701.         ngx_quic_keys_cleanup(pkt.keys);
  702.         return NGX_ERROR;
  703.     }

  704.     if (ngx_quic_send(c, res.data, res.len, c->sockaddr, c->socklen) < 0) {
  705.         ngx_quic_keys_cleanup(pkt.keys);
  706.         return NGX_ERROR;
  707.     }

  708.     ngx_quic_keys_cleanup(pkt.keys);

  709.     return NGX_DONE;
  710. }


  711. ngx_int_t
  712. ngx_quic_send_retry(ngx_connection_t *c, ngx_quic_conf_t *conf,
  713.     ngx_quic_header_t *inpkt)
  714. {
  715.     time_t             expires;
  716.     ssize_t            len;
  717.     ngx_str_t          res, token;
  718.     ngx_quic_header_t  pkt;

  719.     u_char             buf[NGX_QUIC_RETRY_BUFFER_SIZE];
  720.     u_char             dcid[NGX_QUIC_SERVER_CID_LEN];
  721.     u_char             tbuf[NGX_QUIC_TOKEN_BUF_SIZE];

  722.     expires = ngx_time() + NGX_QUIC_RETRY_TOKEN_LIFETIME;

  723.     token.data = tbuf;
  724.     token.len = NGX_QUIC_TOKEN_BUF_SIZE;

  725.     if (ngx_quic_new_token(c->log, c->sockaddr, c->socklen, conf->av_token_key,
  726.                            &token, &inpkt->dcid, expires, 1)
  727.         != NGX_OK)
  728.     {
  729.         return NGX_ERROR;
  730.     }

  731.     ngx_memzero(&pkt, sizeof(ngx_quic_header_t));
  732.     pkt.flags = NGX_QUIC_PKT_FIXED_BIT | NGX_QUIC_PKT_LONG | NGX_QUIC_PKT_RETRY;
  733.     pkt.version = inpkt->version;
  734.     pkt.log = c->log;

  735.     pkt.odcid = inpkt->dcid;
  736.     pkt.dcid = inpkt->scid;

  737.     /* TODO: generate routable dcid */
  738.     if (RAND_bytes(dcid, NGX_QUIC_SERVER_CID_LEN) != 1) {
  739.         return NGX_ERROR;
  740.     }

  741.     pkt.scid.len = NGX_QUIC_SERVER_CID_LEN;
  742.     pkt.scid.data = dcid;

  743.     pkt.token = token;

  744.     res.data = buf;

  745.     if (ngx_quic_encrypt(&pkt, &res) != NGX_OK) {
  746.         return NGX_ERROR;
  747.     }

  748. #ifdef NGX_QUIC_DEBUG_PACKETS
  749.     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
  750.                    "quic packet to send len:%uz %xV", res.len, &res);
  751. #endif

  752.     len = ngx_quic_send(c, res.data, res.len, c->sockaddr, c->socklen);
  753.     if (len < 0) {
  754.         return NGX_ERROR;
  755.     }

  756.     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
  757.                    "quic retry packet sent to %xV", &pkt.dcid);

  758.     /*
  759.      * RFC 9000, 17.2.5.1.  Sending a Retry Packet
  760.      *
  761.      * A server MUST NOT send more than one Retry
  762.      * packet in response to a single UDP datagram.
  763.      * NGX_DONE will stop quic_input() from processing further
  764.      */
  765.     return NGX_DONE;
  766. }


  767. ngx_int_t
  768. ngx_quic_send_new_token(ngx_connection_t *c, ngx_quic_path_t *path)
  769. {
  770.     time_t                  expires;
  771.     ngx_str_t               token;
  772.     ngx_chain_t            *out;
  773.     ngx_quic_frame_t       *frame;
  774.     ngx_quic_connection_t  *qc;

  775.     u_char                  tbuf[NGX_QUIC_TOKEN_BUF_SIZE];

  776.     qc = ngx_quic_get_connection(c);

  777.     expires = ngx_time() + NGX_QUIC_NEW_TOKEN_LIFETIME;

  778.     token.data = tbuf;
  779.     token.len = NGX_QUIC_TOKEN_BUF_SIZE;

  780.     if (ngx_quic_new_token(c->log, path->sockaddr, path->socklen,
  781.                            qc->conf->av_token_key, &token, NULL, expires, 0)
  782.         != NGX_OK)
  783.     {
  784.         return NGX_ERROR;
  785.     }

  786.     out = ngx_quic_copy_buffer(c, token.data, token.len);
  787.     if (out == NGX_CHAIN_ERROR) {
  788.         return NGX_ERROR;
  789.     }

  790.     frame = ngx_quic_alloc_frame(c);
  791.     if (frame == NULL) {
  792.         return NGX_ERROR;
  793.     }

  794.     frame->level = ssl_encryption_application;
  795.     frame->type = NGX_QUIC_FT_NEW_TOKEN;
  796.     frame->data = out;
  797.     frame->u.token.length = token.len;

  798.     ngx_quic_queue_frame(qc, frame);

  799.     return NGX_OK;
  800. }


  801. ngx_int_t
  802. ngx_quic_send_ack(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx)
  803. {
  804.     size_t                  len, left;
  805.     uint64_t                ack_delay;
  806.     ngx_buf_t              *b;
  807.     ngx_uint_t              i;
  808.     ngx_chain_t            *cl, **ll;
  809.     ngx_quic_frame_t       *frame;
  810.     ngx_quic_connection_t  *qc;

  811.     qc = ngx_quic_get_connection(c);

  812.     ack_delay = ngx_current_msec - ctx->largest_received;
  813.     ack_delay *= 1000;
  814.     ack_delay >>= qc->tp.ack_delay_exponent;

  815.     frame = ngx_quic_alloc_frame(c);
  816.     if (frame == NULL) {
  817.         return NGX_ERROR;
  818.     }

  819.     ll = &frame->data;
  820.     b = NULL;

  821.     for (i = 0; i < ctx->nranges; i++) {
  822.         len = ngx_quic_create_ack_range(NULL, ctx->ranges[i].gap,
  823.                                         ctx->ranges[i].range);

  824.         left = b ? b->end - b->last : 0;

  825.         if (left < len) {
  826.             cl = ngx_quic_alloc_chain(c);
  827.             if (cl == NULL) {
  828.                 return NGX_ERROR;
  829.             }

  830.             *ll = cl;
  831.             ll = &cl->next;

  832.             b = cl->buf;
  833.             left = b->end - b->last;

  834.             if (left < len) {
  835.                 return NGX_ERROR;
  836.             }
  837.         }

  838.         b->last += ngx_quic_create_ack_range(b->last, ctx->ranges[i].gap,
  839.                                              ctx->ranges[i].range);

  840.         frame->u.ack.ranges_length += len;
  841.     }

  842.     *ll = NULL;

  843.     frame->level = ctx->level;
  844.     frame->type = NGX_QUIC_FT_ACK;
  845.     frame->u.ack.largest = ctx->largest_range;
  846.     frame->u.ack.delay = ack_delay;
  847.     frame->u.ack.range_count = ctx->nranges;
  848.     frame->u.ack.first_range = ctx->first_range;
  849.     frame->len = ngx_quic_create_frame(NULL, frame);

  850.     ngx_queue_insert_head(&ctx->frames, &frame->queue);

  851.     return NGX_OK;
  852. }


  853. ngx_int_t
  854. ngx_quic_send_ack_range(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx,
  855.     uint64_t smallest, uint64_t largest)
  856. {
  857.     ngx_quic_frame_t       *frame;
  858.     ngx_quic_connection_t  *qc;

  859.     qc = ngx_quic_get_connection(c);

  860.     frame = ngx_quic_alloc_frame(c);
  861.     if (frame == NULL) {
  862.         return NGX_ERROR;
  863.     }

  864.     frame->level = ctx->level;
  865.     frame->type = NGX_QUIC_FT_ACK;
  866.     frame->u.ack.largest = largest;
  867.     frame->u.ack.delay = 0;
  868.     frame->u.ack.range_count = 0;
  869.     frame->u.ack.first_range = largest - smallest;

  870.     ngx_quic_queue_frame(qc, frame);

  871.     return NGX_OK;
  872. }


  873. ngx_int_t
  874. ngx_quic_frame_sendto(ngx_connection_t *c, ngx_quic_frame_t *frame,
  875.     size_t min, ngx_quic_path_t *path)
  876. {
  877.     size_t                  max, max_payload, min_payload, pad;
  878.     ssize_t                 len, sent;
  879.     ngx_str_t               res;
  880.     ngx_msec_t              now;
  881.     ngx_quic_header_t       pkt;
  882.     ngx_quic_send_ctx_t    *ctx;
  883.     ngx_quic_congestion_t  *cg;
  884.     ngx_quic_connection_t  *qc;

  885.     static u_char           src[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE];
  886.     static u_char           dst[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE];

  887.     qc = ngx_quic_get_connection(c);
  888.     cg = &qc->congestion;
  889.     ctx = ngx_quic_get_send_ctx(qc, frame->level);

  890.     now = ngx_current_msec;

  891.     max = ngx_quic_path_limit(c, path, path->mtu);

  892.     ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
  893.                    "quic sendto %s packet max:%uz min:%uz",
  894.                    ngx_quic_level_name(ctx->level), max, min);

  895.     if (cg->in_flight >= cg->window && !frame->ignore_congestion) {
  896.         ngx_quic_free_frame(c, frame);
  897.         return NGX_AGAIN;
  898.     }

  899.     ngx_quic_init_packet(c, ctx, &pkt, path);

  900.     min_payload = ngx_quic_payload_size(&pkt, min);
  901.     max_payload = ngx_quic_payload_size(&pkt, max);

  902.     /* RFC 9001, 5.4.2.  Header Protection Sample */
  903.     pad = 4 - pkt.num_len;
  904.     min_payload = ngx_max(min_payload, pad);

  905.     if (min_payload > max_payload) {
  906.         ngx_quic_free_frame(c, frame);
  907.         return NGX_AGAIN;
  908.     }

  909. #if (NGX_DEBUG)
  910.     frame->pnum = pkt.number;
  911. #endif

  912.     ngx_quic_log_frame(c->log, frame, 1);

  913.     len = ngx_quic_create_frame(NULL, frame);
  914.     if ((size_t) len > max_payload) {
  915.         ngx_quic_free_frame(c, frame);
  916.         return NGX_AGAIN;
  917.     }

  918.     len = ngx_quic_create_frame(src, frame);
  919.     if (len == -1) {
  920.         ngx_quic_free_frame(c, frame);
  921.         return NGX_ERROR;
  922.     }

  923.     if (len < (ssize_t) min_payload) {
  924.         ngx_memset(src + len, NGX_QUIC_FT_PADDING, min_payload - len);
  925.         len = min_payload;
  926.     }

  927.     pkt.payload.data = src;
  928.     pkt.payload.len = len;

  929.     res.data = dst;

  930.     ngx_quic_log_packet(c->log, &pkt);

  931.     if (ngx_quic_encrypt(&pkt, &res) != NGX_OK) {
  932.         ngx_quic_free_frame(c, frame);
  933.         return NGX_ERROR;
  934.     }

  935.     frame->pnum = ctx->pnum;
  936.     frame->send_time = now;
  937.     frame->plen = res.len;

  938.     ctx->pnum++;

  939.     sent = ngx_quic_send(c, res.data, res.len, path->sockaddr, path->socklen);
  940.     if (sent < 0) {
  941.         ngx_quic_free_frame(c, frame);
  942.         return sent;
  943.     }

  944.     path->sent += sent;

  945.     if (frame->need_ack && !qc->closing) {
  946.         ngx_queue_insert_tail(&ctx->sent, &frame->queue);

  947.         cg->in_flight += frame->plen;

  948.     } else {
  949.         ngx_quic_free_frame(c, frame);
  950.         return NGX_OK;
  951.     }

  952.     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
  953.                    "quic congestion send if:%uz", cg->in_flight);

  954.     if (!qc->send_timer_set) {
  955.         qc->send_timer_set = 1;
  956.         ngx_add_timer(c->read, qc->tp.max_idle_timeout);
  957.     }

  958.     ngx_quic_set_lost_timer(c);

  959.     return NGX_OK;
  960. }


  961. size_t
  962. ngx_quic_path_limit(ngx_connection_t *c, ngx_quic_path_t *path, size_t size)
  963. {
  964.     off_t  max;

  965.     if (!path->validated) {
  966.         max = path->received * 3;
  967.         max = (path->sent >= max) ? 0 : max - path->sent;

  968.         if ((off_t) size > max) {
  969.             return max;
  970.         }
  971.     }

  972.     return size;
  973. }