Mercurial > hg > nginx
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 |