comparison src/event/ngx_event_quic.c @ 8458:e0f92f68e018 quic

QUIC: Introduced ngx_quic_finalize_connection(). The function finalizes QUIC connection with an application protocol error code and sends a CONNECTION_CLOSE frame with type=0x1d. Also, renamed NGX_QUIC_FT_CONNECTION_CLOSE2 to NGX_QUIC_FT_CONNECTION_CLOSE_APP.
author Roman Arutyunyan <arut@nginx.com>
date Thu, 02 Jul 2020 16:33:59 +0300
parents a62849b6463c
children 3b107aadc9f6
comparison
equal deleted inserted replaced
8457:a7f64438aa3c 8458:e0f92f68e018
108 108
109 uint64_t cur_streams; 109 uint64_t cur_streams;
110 uint64_t max_streams; 110 uint64_t max_streams;
111 111
112 ngx_uint_t error; 112 ngx_uint_t error;
113 enum ssl_encryption_level_t error_level;
113 ngx_uint_t error_ftype; 114 ngx_uint_t error_ftype;
114 const char *error_reason; 115 const char *error_reason;
115 116
117 unsigned error_app:1;
116 unsigned send_timer_set:1; 118 unsigned send_timer_set:1;
117 unsigned closing:1; 119 unsigned closing:1;
118 unsigned draining:1; 120 unsigned draining:1;
119 unsigned key_phase:1; 121 unsigned key_phase:1;
120 unsigned in_retry:1; 122 unsigned in_retry:1;
179 static ngx_int_t ngx_quic_app_input(ngx_connection_t *c, 181 static ngx_int_t ngx_quic_app_input(ngx_connection_t *c,
180 ngx_quic_header_t *pkt); 182 ngx_quic_header_t *pkt);
181 static ngx_int_t ngx_quic_payload_handler(ngx_connection_t *c, 183 static ngx_int_t ngx_quic_payload_handler(ngx_connection_t *c,
182 ngx_quic_header_t *pkt); 184 ngx_quic_header_t *pkt);
183 static ngx_int_t ngx_quic_send_ack(ngx_connection_t *c, ngx_quic_header_t *pkt); 185 static ngx_int_t ngx_quic_send_ack(ngx_connection_t *c, ngx_quic_header_t *pkt);
184 static ngx_int_t ngx_quic_send_cc(ngx_connection_t *c, 186 static ngx_int_t ngx_quic_send_cc(ngx_connection_t *c);
185 enum ssl_encryption_level_t level, ngx_uint_t err, ngx_uint_t frame_type,
186 const char *reason);
187 static ngx_int_t ngx_quic_send_new_token(ngx_connection_t *c); 187 static ngx_int_t ngx_quic_send_new_token(ngx_connection_t *c);
188 188
189 static ngx_int_t ngx_quic_handle_ack_frame(ngx_connection_t *c, 189 static ngx_int_t ngx_quic_handle_ack_frame(ngx_connection_t *c,
190 ngx_quic_header_t *pkt, ngx_quic_ack_frame_t *f); 190 ngx_quic_header_t *pkt, ngx_quic_ack_frame_t *f);
191 static ngx_int_t ngx_quic_handle_ack_frame_range(ngx_connection_t *c, 191 static ngx_int_t ngx_quic_handle_ack_frame_range(ngx_connection_t *c,
538 538
539 static int 539 static int
540 ngx_quic_send_alert(ngx_ssl_conn_t *ssl_conn, enum ssl_encryption_level_t level, 540 ngx_quic_send_alert(ngx_ssl_conn_t *ssl_conn, enum ssl_encryption_level_t level,
541 uint8_t alert) 541 uint8_t alert)
542 { 542 {
543 ngx_connection_t *c; 543 ngx_connection_t *c;
544 ngx_quic_connection_t *qc;
544 545
545 c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn); 546 c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
546 547
547 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, 548 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
548 "quic ngx_quic_send_alert(), lvl=%d, alert=%d", 549 "quic ngx_quic_send_alert(), lvl=%d, alert=%d",
549 (int) level, (int) alert); 550 (int) level, (int) alert);
550 551
551 if (c->quic == NULL) { 552 qc = c->quic;
553 if (qc == NULL) {
552 return 1; 554 return 1;
553 } 555 }
554 556
555 if (ngx_quic_send_cc(c, level, NGX_QUIC_ERR_CRYPTO(alert), 0, "TLS alert") 557 qc->error_level = level;
556 != NGX_OK) 558 qc->error = NGX_QUIC_ERR_CRYPTO(alert);
557 { 559 qc->error_reason = "TLS alert";
560 qc->error_app = 0;
561 qc->error_ftype = 0;
562
563 if (ngx_quic_send_cc(c) != NGX_OK) {
558 return 0; 564 return 0;
559 } 565 }
560 566
561 return 1; 567 return 1;
562 } 568 }
1260 1266
1261 1267
1262 static ngx_int_t 1268 static ngx_int_t
1263 ngx_quic_close_quic(ngx_connection_t *c, ngx_int_t rc) 1269 ngx_quic_close_quic(ngx_connection_t *c, ngx_int_t rc)
1264 { 1270 {
1265 ngx_uint_t i, err; 1271 ngx_uint_t i;
1266 ngx_quic_send_ctx_t *ctx; 1272 ngx_quic_send_ctx_t *ctx;
1267 ngx_quic_connection_t *qc; 1273 ngx_quic_connection_t *qc;
1268 enum ssl_encryption_level_t level;
1269 1274
1270 qc = c->quic; 1275 qc = c->quic;
1271 1276
1272 if (!qc->closing) { 1277 if (!qc->closing) {
1273 1278
1309 qc->close.handler = ngx_quic_close_timer_handler; 1314 qc->close.handler = ngx_quic_close_timer_handler;
1310 qc->close.cancelable = 1; 1315 qc->close.cancelable = 1;
1311 1316
1312 ngx_add_timer(&qc->close, 3 * NGX_QUIC_HARDCODED_PTO); 1317 ngx_add_timer(&qc->close, 3 * NGX_QUIC_HARDCODED_PTO);
1313 1318
1314 err = NGX_QUIC_ERR_NO_ERROR; 1319 qc->error = NGX_QUIC_ERR_NO_ERROR;
1315 1320
1316 } else { 1321 } else {
1317 err = qc->error ? qc->error : NGX_QUIC_ERR_INTERNAL_ERROR; 1322 if (qc->error == 0 && !qc->error_app) {
1318 1323 qc->error = NGX_QUIC_ERR_INTERNAL_ERROR;
1319 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, 1324 }
1320 "quic immediate close due to error: %ui %s", 1325
1321 qc->error, 1326 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
1327 "quic immediate close due to %serror: %ui %s",
1328 qc->error_app ? "app " : "", qc->error,
1322 qc->error_reason ? qc->error_reason : ""); 1329 qc->error_reason ? qc->error_reason : "");
1323 } 1330 }
1324 1331
1325 level = c->ssl ? SSL_quic_read_level(c->ssl->connection) 1332 qc->error_level = c->ssl ? SSL_quic_read_level(c->ssl->connection)
1326 : ssl_encryption_initial; 1333 : ssl_encryption_initial;
1327 1334
1328 (void) ngx_quic_send_cc(c, level, err, qc->error_ftype, 1335 (void) ngx_quic_send_cc(c);
1329 qc->error_reason); 1336
1330 1337 if (qc->error_level == ssl_encryption_handshake) {
1331 if (level == ssl_encryption_handshake) {
1332 /* for clients that might not have handshake keys */ 1338 /* for clients that might not have handshake keys */
1333 (void) ngx_quic_send_cc(c, ssl_encryption_initial, err, 1339 qc->error_level = ssl_encryption_initial;
1334 qc->error_ftype, qc->error_reason); 1340 (void) ngx_quic_send_cc(c);
1335 } 1341 }
1336 } 1342 }
1337 1343
1338 qc->closing = 1; 1344 qc->closing = 1;
1339 } 1345 }
1377 1383
1378 /* may be tested from SSL callback during SSL shutdown */ 1384 /* may be tested from SSL callback during SSL shutdown */
1379 c->quic = NULL; 1385 c->quic = NULL;
1380 1386
1381 return NGX_OK; 1387 return NGX_OK;
1388 }
1389
1390
1391 void
1392 ngx_quic_finalize_connection(ngx_connection_t *c, ngx_uint_t err,
1393 const char *reason)
1394 {
1395 ngx_quic_connection_t *qc;
1396
1397 qc = c->quic;
1398 qc->error = err;
1399 qc->error_reason = reason;
1400 qc->error_app = 1;
1401 qc->error_ftype = 0;
1402
1403 ngx_quic_close_connection(c, NGX_ERROR);
1382 } 1404 }
1383 1405
1384 1406
1385 static void 1407 static void
1386 ngx_quic_close_timer_handler(ngx_event_t *ev) 1408 ngx_quic_close_timer_handler(ngx_event_t *ev)
1885 * 1907 *
1886 * An endpoint retains only enough information to generate 1908 * An endpoint retains only enough information to generate
1887 * a packet containing a CONNECTION_CLOSE frame and to identify 1909 * a packet containing a CONNECTION_CLOSE frame and to identify
1888 * packets as belonging to the connection. 1910 * packets as belonging to the connection.
1889 */ 1911 */
1890 return ngx_quic_send_cc(c, pkt->level, NGX_QUIC_ERR_NO_ERROR, 0, 1912
1891 "connection is closing, packet discarded"); 1913 qc->error_level = pkt->level;
1914 qc->error = NGX_QUIC_ERR_NO_ERROR;
1915 qc->error_reason = "connection is closing, packet discarded";
1916 qc->error_ftype = 0;
1917 qc->error_app = 0;
1918
1919 return ngx_quic_send_cc(c);
1892 } 1920 }
1893 1921
1894 p = pkt->payload.data; 1922 p = pkt->payload.data;
1895 end = p + pkt->payload.len; 1923 end = p + pkt->payload.len;
1896 1924
1924 case NGX_QUIC_FT_PADDING: 1952 case NGX_QUIC_FT_PADDING:
1925 /* no action required */ 1953 /* no action required */
1926 continue; 1954 continue;
1927 1955
1928 case NGX_QUIC_FT_CONNECTION_CLOSE: 1956 case NGX_QUIC_FT_CONNECTION_CLOSE:
1929 case NGX_QUIC_FT_CONNECTION_CLOSE2: 1957 case NGX_QUIC_FT_CONNECTION_CLOSE_APP:
1930 do_close = 1; 1958 do_close = 1;
1931 continue; 1959 continue;
1932 } 1960 }
1933 1961
1934 /* got there with ack-eliciting packet */ 1962 /* got there with ack-eliciting packet */
2096 return NGX_OK; 2124 return NGX_OK;
2097 } 2125 }
2098 2126
2099 2127
2100 static ngx_int_t 2128 static ngx_int_t
2101 ngx_quic_send_cc(ngx_connection_t *c, enum ssl_encryption_level_t level, 2129 ngx_quic_send_cc(ngx_connection_t *c)
2102 ngx_uint_t err, ngx_uint_t frame_type, const char *reason)
2103 { 2130 {
2104 ngx_quic_frame_t *frame; 2131 ngx_quic_frame_t *frame;
2105 ngx_quic_connection_t *qc; 2132 ngx_quic_connection_t *qc;
2106 2133
2107 qc = c->quic; 2134 qc = c->quic;
2120 frame = ngx_quic_alloc_frame(c, 0); 2147 frame = ngx_quic_alloc_frame(c, 0);
2121 if (frame == NULL) { 2148 if (frame == NULL) {
2122 return NGX_ERROR; 2149 return NGX_ERROR;
2123 } 2150 }
2124 2151
2125 frame->level = level; 2152 frame->level = qc->error_level;
2126 frame->type = NGX_QUIC_FT_CONNECTION_CLOSE; 2153 frame->type = NGX_QUIC_FT_CONNECTION_CLOSE;
2127 frame->u.close.error_code = err; 2154 frame->u.close.error_code = qc->error;
2128 frame->u.close.frame_type = frame_type; 2155 frame->u.close.frame_type = qc->error_ftype;
2129 2156 frame->u.close.app = qc->error_app;
2130 if (reason) { 2157
2131 frame->u.close.reason.len = ngx_strlen(reason); 2158 if (qc->error_reason) {
2132 frame->u.close.reason.data = (u_char *) reason; 2159 frame->u.close.reason.len = ngx_strlen(qc->error_reason);
2160 frame->u.close.reason.data = (u_char *) qc->error_reason;
2133 } 2161 }
2134 2162
2135 ngx_snprintf(frame->info, sizeof(frame->info) - 1, 2163 ngx_snprintf(frame->info, sizeof(frame->info) - 1,
2136 "cc from send_cc err=%ui level=%d ft=%ui reason \"%s\"", 2164 "CONNECTION_CLOSE%s err:%ui level:%d ft:%ui reason:\"%s\"",
2137 err, level, frame_type, reason ? reason : "-"); 2165 qc->error_app ? "_APP" : "", qc->error, qc->error_level,
2166 qc->error_ftype, qc->error_reason ? qc->error_reason : "-");
2138 2167
2139 ngx_quic_queue_frame(c->quic, frame); 2168 ngx_quic_queue_frame(c->quic, frame);
2140 2169
2141 qc->last_cc = ngx_current_msec; 2170 qc->last_cc = ngx_current_msec;
2142 2171