Mercurial > hg > nginx
comparison src/event/quic/ngx_event_quic.c @ 8687:1c6343bd7933 quic
QUIC: refactored packet processing.
- split ngx_quic_process_packet() in two functions with the second one called
ngx_quic_process_payload() in charge of decrypring and handling the payload
- renamed ngx_quic_payload_handler() to ngx_quic_handle_frames()
- moved error cleanup from ngx_quic_input() to ngx_quic_process_payload()
- moved handling closed connection from ngx_quic_handle_frames() to
ngx_quic_process_payload()
- minor fixes
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Thu, 28 Jan 2021 12:35:18 +0300 |
parents | dffb66fb783b |
children | a346905c359f |
comparison
equal
deleted
inserted
replaced
8686:dffb66fb783b | 8687:1c6343bd7933 |
---|---|
253 | 253 |
254 static ngx_int_t ngx_quic_input(ngx_connection_t *c, ngx_buf_t *b, | 254 static ngx_int_t ngx_quic_input(ngx_connection_t *c, ngx_buf_t *b, |
255 ngx_quic_conf_t *conf); | 255 ngx_quic_conf_t *conf); |
256 static ngx_int_t ngx_quic_process_packet(ngx_connection_t *c, | 256 static ngx_int_t ngx_quic_process_packet(ngx_connection_t *c, |
257 ngx_quic_conf_t *conf, ngx_quic_header_t *pkt); | 257 ngx_quic_conf_t *conf, ngx_quic_header_t *pkt); |
258 static ngx_int_t ngx_quic_process_payload(ngx_connection_t *c, | |
259 ngx_quic_header_t *pkt); | |
258 static ngx_int_t ngx_quic_send_early_cc(ngx_connection_t *c, | 260 static ngx_int_t ngx_quic_send_early_cc(ngx_connection_t *c, |
259 ngx_quic_header_t *inpkt, ngx_uint_t err, const char *reason); | 261 ngx_quic_header_t *inpkt, ngx_uint_t err, const char *reason); |
260 static void ngx_quic_discard_ctx(ngx_connection_t *c, | 262 static void ngx_quic_discard_ctx(ngx_connection_t *c, |
261 enum ssl_encryption_level_t level); | 263 enum ssl_encryption_level_t level); |
262 static ngx_int_t ngx_quic_check_peer(ngx_quic_connection_t *qc, | 264 static ngx_int_t ngx_quic_check_peer(ngx_quic_connection_t *qc, |
263 ngx_quic_header_t *pkt); | 265 ngx_quic_header_t *pkt); |
264 static ngx_int_t ngx_quic_payload_handler(ngx_connection_t *c, | 266 static ngx_int_t ngx_quic_handle_frames(ngx_connection_t *c, |
265 ngx_quic_header_t *pkt); | 267 ngx_quic_header_t *pkt); |
266 static ngx_int_t ngx_quic_ack_packet(ngx_connection_t *c, | 268 static ngx_int_t ngx_quic_ack_packet(ngx_connection_t *c, |
267 ngx_quic_header_t *pkt); | 269 ngx_quic_header_t *pkt); |
268 static ngx_int_t ngx_quic_send_ack_range(ngx_connection_t *c, | 270 static ngx_int_t ngx_quic_send_ack_range(ngx_connection_t *c, |
269 ngx_quic_send_ctx_t *ctx, uint64_t smallest, uint64_t largest); | 271 ngx_quic_send_ctx_t *ctx, uint64_t smallest, uint64_t largest); |
2118 | 2120 |
2119 | 2121 |
2120 static ngx_int_t | 2122 static ngx_int_t |
2121 ngx_quic_input(ngx_connection_t *c, ngx_buf_t *b, ngx_quic_conf_t *conf) | 2123 ngx_quic_input(ngx_connection_t *c, ngx_buf_t *b, ngx_quic_conf_t *conf) |
2122 { | 2124 { |
2123 u_char *p; | 2125 u_char *p; |
2124 ngx_int_t rc; | 2126 ngx_int_t rc; |
2125 ngx_uint_t good; | 2127 ngx_uint_t good; |
2126 ngx_quic_header_t pkt; | 2128 ngx_quic_header_t pkt; |
2127 ngx_quic_connection_t *qc; | |
2128 | 2129 |
2129 good = 0; | 2130 good = 0; |
2130 | 2131 |
2131 p = b->pos; | 2132 p = b->pos; |
2132 | 2133 |
2137 pkt.data = p; | 2138 pkt.data = p; |
2138 pkt.len = b->last - p; | 2139 pkt.len = b->last - p; |
2139 pkt.log = c->log; | 2140 pkt.log = c->log; |
2140 pkt.flags = p[0]; | 2141 pkt.flags = p[0]; |
2141 pkt.raw->pos++; | 2142 pkt.raw->pos++; |
2142 | |
2143 qc = ngx_quic_get_connection(c); | |
2144 if (qc) { | |
2145 qc->error = 0; | |
2146 qc->error_reason = 0; | |
2147 } | |
2148 | 2143 |
2149 rc = ngx_quic_process_packet(c, conf, &pkt); | 2144 rc = ngx_quic_process_packet(c, conf, &pkt); |
2150 | 2145 |
2151 #if (NGX_DEBUG) | 2146 #if (NGX_DEBUG) |
2152 if (pkt.parsed) { | 2147 if (pkt.parsed) { |
2210 static ngx_int_t | 2205 static ngx_int_t |
2211 ngx_quic_process_packet(ngx_connection_t *c, ngx_quic_conf_t *conf, | 2206 ngx_quic_process_packet(ngx_connection_t *c, ngx_quic_conf_t *conf, |
2212 ngx_quic_header_t *pkt) | 2207 ngx_quic_header_t *pkt) |
2213 { | 2208 { |
2214 ngx_int_t rc; | 2209 ngx_int_t rc; |
2215 ngx_quic_send_ctx_t *ctx; | |
2216 ngx_quic_connection_t *qc; | 2210 ngx_quic_connection_t *qc; |
2217 | |
2218 static u_char buf[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE]; | |
2219 | 2211 |
2220 c->log->action = "parsing quic packet"; | 2212 c->log->action = "parsing quic packet"; |
2221 | 2213 |
2222 rc = ngx_quic_parse_packet(pkt); | 2214 rc = ngx_quic_parse_packet(pkt); |
2223 | 2215 |
2226 } | 2218 } |
2227 | 2219 |
2228 pkt->parsed = 1; | 2220 pkt->parsed = 1; |
2229 | 2221 |
2230 c->log->action = "processing quic packet"; | 2222 c->log->action = "processing quic packet"; |
2231 | |
2232 qc = ngx_quic_get_connection(c); | |
2233 | 2223 |
2234 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, | 2224 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, |
2235 "quic packet rx dcid len:%uz %xV", | 2225 "quic packet rx dcid len:%uz %xV", |
2236 pkt->dcid.len, &pkt->dcid); | 2226 pkt->dcid.len, &pkt->dcid); |
2237 | 2227 |
2246 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, | 2236 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, |
2247 "quic token len:%uz %xV", | 2237 "quic token len:%uz %xV", |
2248 pkt->token.len, &pkt->token); | 2238 pkt->token.len, &pkt->token); |
2249 } | 2239 } |
2250 #endif | 2240 #endif |
2241 | |
2242 qc = ngx_quic_get_connection(c); | |
2251 | 2243 |
2252 if (qc) { | 2244 if (qc) { |
2253 | 2245 |
2254 if (rc == NGX_ABORT) { | 2246 if (rc == NGX_ABORT) { |
2255 ngx_log_error(NGX_LOG_INFO, c->log, 0, | 2247 ngx_log_error(NGX_LOG_INFO, c->log, 0, |
2282 } | 2274 } |
2283 | 2275 |
2284 return NGX_DECLINED; | 2276 return NGX_DECLINED; |
2285 } | 2277 } |
2286 | 2278 |
2279 return ngx_quic_process_payload(c, pkt); | |
2280 } | |
2281 | |
2282 /* packet does not belong to a connection */ | |
2283 | |
2284 if (rc == NGX_ABORT) { | |
2285 return ngx_quic_negotiate_version(c, pkt); | |
2286 } | |
2287 | |
2288 if (pkt->level == ssl_encryption_application) { | |
2289 return ngx_quic_send_stateless_reset(c, conf, pkt); | |
2290 } | |
2291 | |
2292 if (pkt->level != ssl_encryption_initial) { | |
2293 return NGX_ERROR; | |
2294 } | |
2295 | |
2296 c->log->action = "processing initial packet"; | |
2297 | |
2298 if (pkt->dcid.len < NGX_QUIC_CID_LEN_MIN) { | |
2299 /* 7.2. Negotiating Connection IDs */ | |
2300 ngx_log_error(NGX_LOG_INFO, c->log, 0, | |
2301 "quic too short dcid in initial" | |
2302 " packet: len:%i", pkt->dcid.len); | |
2303 return NGX_ERROR; | |
2304 } | |
2305 | |
2306 /* process retry and initialize connection IDs */ | |
2307 | |
2308 if (pkt->token.len) { | |
2309 | |
2310 rc = ngx_quic_validate_token(c, conf->token_key, pkt); | |
2311 | |
2312 if (rc == NGX_ERROR) { | |
2313 /* internal error */ | |
2314 return NGX_ERROR; | |
2315 | |
2316 } else if (rc == NGX_ABORT) { | |
2317 /* token cannot be decrypted */ | |
2318 return ngx_quic_send_early_cc(c, pkt, | |
2319 NGX_QUIC_ERR_INVALID_TOKEN, | |
2320 "cannot decrypt token"); | |
2321 } else if (rc == NGX_DECLINED) { | |
2322 /* token is invalid */ | |
2323 | |
2324 if (pkt->retried) { | |
2325 /* invalid Retry token */ | |
2326 return ngx_quic_send_early_cc(c, pkt, | |
2327 NGX_QUIC_ERR_INVALID_TOKEN, | |
2328 "invalid token"); | |
2329 } else if (conf->retry) { | |
2330 /* invalid NEW_TOKEN */ | |
2331 return ngx_quic_send_retry(c, conf, pkt); | |
2332 } | |
2333 } | |
2334 | |
2335 /* NGX_OK */ | |
2336 | |
2337 } else if (conf->retry) { | |
2338 return ngx_quic_send_retry(c, conf, pkt); | |
2339 | |
2287 } else { | 2340 } else { |
2288 | 2341 pkt->odcid = pkt->dcid; |
2289 if (rc == NGX_ABORT) { | 2342 } |
2290 return ngx_quic_negotiate_version(c, pkt); | 2343 |
2291 } | 2344 if (ngx_terminate || ngx_exiting) { |
2292 | 2345 if (conf->retry) { |
2293 if (pkt->level == ssl_encryption_initial) { | 2346 return ngx_quic_send_retry(c, conf, pkt); |
2294 c->log->action = "processing initial packet"; | 2347 } |
2295 | 2348 |
2296 if (pkt->dcid.len < NGX_QUIC_CID_LEN_MIN) { | 2349 return NGX_ERROR; |
2297 /* 7.2. Negotiating Connection IDs */ | 2350 } |
2298 ngx_log_error(NGX_LOG_INFO, c->log, 0, | 2351 |
2299 "quic too short dcid in initial" | 2352 c->log->action = "creating quic connection"; |
2300 " packet: len:%i", pkt->dcid.len); | 2353 |
2301 return NGX_ERROR; | 2354 qc = ngx_quic_new_connection(c, conf, pkt); |
2302 } | 2355 if (qc == NULL) { |
2303 | 2356 return NGX_ERROR; |
2304 /* process retry and initialize connection IDs */ | 2357 } |
2305 | 2358 |
2306 if (pkt->token.len) { | 2359 return ngx_quic_process_payload(c, pkt); |
2307 | 2360 } |
2308 rc = ngx_quic_validate_token(c, conf->token_key, pkt); | 2361 |
2309 | 2362 |
2310 if (rc == NGX_ERROR) { | 2363 static ngx_int_t |
2311 /* internal error */ | 2364 ngx_quic_process_payload(ngx_connection_t *c, ngx_quic_header_t *pkt) |
2312 return NGX_ERROR; | 2365 { |
2313 | 2366 ngx_int_t rc; |
2314 } else if (rc == NGX_ABORT) { | 2367 ngx_quic_send_ctx_t *ctx; |
2315 /* token cannot be decrypted */ | 2368 ngx_quic_connection_t *qc; |
2316 return ngx_quic_send_early_cc(c, pkt, | 2369 static u_char buf[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE]; |
2317 NGX_QUIC_ERR_INVALID_TOKEN, | 2370 |
2318 "cannot decrypt token"); | 2371 qc = ngx_quic_get_connection(c); |
2319 } else if (rc == NGX_DECLINED) { | 2372 |
2320 /* token is invalid */ | 2373 qc->error = 0; |
2321 | 2374 qc->error_reason = 0; |
2322 if (pkt->retried) { | |
2323 /* invalid Retry token */ | |
2324 return ngx_quic_send_early_cc(c, pkt, | |
2325 NGX_QUIC_ERR_INVALID_TOKEN, | |
2326 "invalid token"); | |
2327 } else if (conf->retry) { | |
2328 /* invalid NEW_TOKEN */ | |
2329 return ngx_quic_send_retry(c, conf, pkt); | |
2330 } | |
2331 } | |
2332 | |
2333 /* NGX_OK */ | |
2334 | |
2335 } else if (conf->retry) { | |
2336 return ngx_quic_send_retry(c, conf, pkt); | |
2337 | |
2338 } else { | |
2339 pkt->odcid = pkt->dcid; | |
2340 } | |
2341 | |
2342 if (ngx_terminate || ngx_exiting) { | |
2343 if (conf->retry) { | |
2344 return ngx_quic_send_retry(c, conf, pkt); | |
2345 } | |
2346 | |
2347 return NGX_ERROR; | |
2348 } | |
2349 | |
2350 c->log->action = "creating quic connection"; | |
2351 | |
2352 qc = ngx_quic_new_connection(c, conf, pkt); | |
2353 if (qc == NULL) { | |
2354 return NGX_ERROR; | |
2355 } | |
2356 | |
2357 } else if (pkt->level == ssl_encryption_application) { | |
2358 return ngx_quic_send_stateless_reset(c, conf, pkt); | |
2359 | |
2360 } else { | |
2361 return NGX_ERROR; | |
2362 } | |
2363 } | |
2364 | 2375 |
2365 c->log->action = "decrypting packet"; | 2376 c->log->action = "decrypting packet"; |
2366 | 2377 |
2367 if (!ngx_quic_keys_available(qc->keys, pkt->level)) { | 2378 if (!ngx_quic_keys_available(qc->keys, pkt->level)) { |
2368 ngx_log_error(NGX_LOG_INFO, c->log, 0, | 2379 ngx_log_error(NGX_LOG_INFO, c->log, 0, |
2401 if (qc->validated == 0) { | 2412 if (qc->validated == 0) { |
2402 qc->validated = 1; | 2413 qc->validated = 1; |
2403 ngx_post_event(&qc->push, &ngx_posted_events); | 2414 ngx_post_event(&qc->push, &ngx_posted_events); |
2404 } | 2415 } |
2405 } | 2416 } |
2406 | |
2407 pkt->received = ngx_current_msec; | |
2408 | |
2409 c->log->action = "handling payload"; | |
2410 | |
2411 if (pkt->level != ssl_encryption_application) { | |
2412 return ngx_quic_payload_handler(c, pkt); | |
2413 } | |
2414 | |
2415 if (!pkt->key_update) { | |
2416 return ngx_quic_payload_handler(c, pkt); | |
2417 } | |
2418 | |
2419 /* switch keys and generate next on Key Phase change */ | |
2420 | |
2421 qc->key_phase ^= 1; | |
2422 ngx_quic_keys_switch(c, qc->keys); | |
2423 | |
2424 rc = ngx_quic_payload_handler(c, pkt); | |
2425 if (rc != NGX_OK) { | |
2426 return rc; | |
2427 } | |
2428 | |
2429 return ngx_quic_keys_update(c, qc->keys); | |
2430 } | |
2431 | |
2432 | |
2433 static ngx_int_t | |
2434 ngx_quic_send_early_cc(ngx_connection_t *c, ngx_quic_header_t *inpkt, | |
2435 ngx_uint_t err, const char *reason) | |
2436 { | |
2437 ssize_t len; | |
2438 ngx_str_t res; | |
2439 ngx_quic_frame_t frame; | |
2440 ngx_quic_header_t pkt; | |
2441 | |
2442 static u_char src[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE]; | |
2443 static u_char dst[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE]; | |
2444 | |
2445 ngx_memzero(&frame, sizeof(ngx_quic_frame_t)); | |
2446 ngx_memzero(&pkt, sizeof(ngx_quic_header_t)); | |
2447 | |
2448 frame.level = inpkt->level; | |
2449 frame.type = NGX_QUIC_FT_CONNECTION_CLOSE; | |
2450 frame.u.close.error_code = err; | |
2451 | |
2452 frame.u.close.reason.data = (u_char *) reason; | |
2453 frame.u.close.reason.len = ngx_strlen(reason); | |
2454 | |
2455 len = ngx_quic_create_frame(NULL, &frame); | |
2456 if (len > NGX_QUIC_MAX_UDP_PAYLOAD_SIZE) { | |
2457 return NGX_ERROR; | |
2458 } | |
2459 | |
2460 ngx_quic_log_frame(c->log, &frame, 1); | |
2461 | |
2462 len = ngx_quic_create_frame(src, &frame); | |
2463 if (len == -1) { | |
2464 return NGX_ERROR; | |
2465 } | |
2466 | |
2467 pkt.keys = ngx_quic_keys_new(c->pool); | |
2468 if (pkt.keys == NULL) { | |
2469 return NGX_ERROR; | |
2470 } | |
2471 | |
2472 if (ngx_quic_keys_set_initial_secret(c->pool, pkt.keys, &inpkt->dcid) | |
2473 != NGX_OK) | |
2474 { | |
2475 return NGX_ERROR; | |
2476 } | |
2477 | |
2478 pkt.flags = NGX_QUIC_PKT_FIXED_BIT | NGX_QUIC_PKT_LONG | |
2479 | NGX_QUIC_PKT_INITIAL; | |
2480 | |
2481 pkt.num_len = 1; | |
2482 /* | |
2483 * pkt.num = 0; | |
2484 * pkt.trunc = 0; | |
2485 */ | |
2486 | |
2487 pkt.version = inpkt->version; | |
2488 pkt.log = c->log; | |
2489 pkt.level = inpkt->level; | |
2490 pkt.dcid = inpkt->scid; | |
2491 pkt.scid = inpkt->dcid; | |
2492 pkt.payload.data = src; | |
2493 pkt.payload.len = len; | |
2494 | |
2495 res.data = dst; | |
2496 | |
2497 if (ngx_quic_encrypt(&pkt, &res) != NGX_OK) { | |
2498 return NGX_ERROR; | |
2499 } | |
2500 | |
2501 if (ngx_quic_send(c, res.data, res.len) == NGX_ERROR) { | |
2502 return NGX_ERROR; | |
2503 } | |
2504 | |
2505 return NGX_OK; | |
2506 } | |
2507 | |
2508 | |
2509 static void | |
2510 ngx_quic_discard_ctx(ngx_connection_t *c, enum ssl_encryption_level_t level) | |
2511 { | |
2512 ngx_queue_t *q; | |
2513 ngx_quic_frame_t *f; | |
2514 ngx_quic_send_ctx_t *ctx; | |
2515 ngx_quic_connection_t *qc; | |
2516 | |
2517 qc = ngx_quic_get_connection(c); | |
2518 | |
2519 if (!ngx_quic_keys_available(qc->keys, level)) { | |
2520 return; | |
2521 } | |
2522 | |
2523 ngx_quic_keys_discard(qc->keys, level); | |
2524 | |
2525 qc->pto_count = 0; | |
2526 | |
2527 ctx = ngx_quic_get_send_ctx(qc, level); | |
2528 | |
2529 while (!ngx_queue_empty(&ctx->sent)) { | |
2530 q = ngx_queue_head(&ctx->sent); | |
2531 ngx_queue_remove(q); | |
2532 | |
2533 f = ngx_queue_data(q, ngx_quic_frame_t, queue); | |
2534 ngx_quic_congestion_ack(c, f); | |
2535 ngx_quic_free_frame(c, f); | |
2536 } | |
2537 | |
2538 while (!ngx_queue_empty(&ctx->frames)) { | |
2539 q = ngx_queue_head(&ctx->frames); | |
2540 ngx_queue_remove(q); | |
2541 | |
2542 f = ngx_queue_data(q, ngx_quic_frame_t, queue); | |
2543 ngx_quic_congestion_ack(c, f); | |
2544 ngx_quic_free_frame(c, f); | |
2545 } | |
2546 | |
2547 if (level == ssl_encryption_initial) { | |
2548 ngx_quic_clear_temp_server_ids(c); | |
2549 } | |
2550 | |
2551 ctx->send_ack = 0; | |
2552 } | |
2553 | |
2554 | |
2555 static ngx_int_t | |
2556 ngx_quic_check_peer(ngx_quic_connection_t *qc, ngx_quic_header_t *pkt) | |
2557 { | |
2558 ngx_queue_t *q; | |
2559 ngx_quic_client_id_t *cid; | |
2560 | |
2561 if (pkt->level == ssl_encryption_application) { | |
2562 return NGX_OK; | |
2563 } | |
2564 | |
2565 for (q = ngx_queue_head(&qc->client_ids); | |
2566 q != ngx_queue_sentinel(&qc->client_ids); | |
2567 q = ngx_queue_next(q)) | |
2568 { | |
2569 cid = ngx_queue_data(q, ngx_quic_client_id_t, queue); | |
2570 | |
2571 if (pkt->scid.len == cid->len | |
2572 && ngx_memcmp(pkt->scid.data, cid->id, cid->len) == 0) | |
2573 { | |
2574 return NGX_OK; | |
2575 } | |
2576 } | |
2577 | |
2578 ngx_log_error(NGX_LOG_INFO, pkt->log, 0, "quic unexpected quic scid"); | |
2579 return NGX_ERROR; | |
2580 } | |
2581 | |
2582 | |
2583 static ngx_int_t | |
2584 ngx_quic_payload_handler(ngx_connection_t *c, ngx_quic_header_t *pkt) | |
2585 { | |
2586 u_char *end, *p; | |
2587 ssize_t len; | |
2588 ngx_buf_t buf; | |
2589 ngx_uint_t do_close; | |
2590 ngx_chain_t chain; | |
2591 ngx_quic_frame_t frame; | |
2592 ngx_quic_connection_t *qc; | |
2593 | |
2594 qc = ngx_quic_get_connection(c); | |
2595 | 2417 |
2596 if (qc->closing) { | 2418 if (qc->closing) { |
2597 /* | 2419 /* |
2598 * 10.1 Closing and Draining Connection States | 2420 * 10.1 Closing and Draining Connection States |
2599 * ... delayed or reordered packets are properly discarded. | 2421 * ... delayed or reordered packets are properly discarded. |
2609 qc->error_ftype = 0; | 2431 qc->error_ftype = 0; |
2610 qc->error_app = 0; | 2432 qc->error_app = 0; |
2611 | 2433 |
2612 return ngx_quic_send_cc(c); | 2434 return ngx_quic_send_cc(c); |
2613 } | 2435 } |
2436 | |
2437 pkt->received = ngx_current_msec; | |
2438 | |
2439 c->log->action = "handling payload"; | |
2440 | |
2441 if (pkt->level != ssl_encryption_application) { | |
2442 return ngx_quic_handle_frames(c, pkt); | |
2443 } | |
2444 | |
2445 if (!pkt->key_update) { | |
2446 return ngx_quic_handle_frames(c, pkt); | |
2447 } | |
2448 | |
2449 /* switch keys and generate next on Key Phase change */ | |
2450 | |
2451 qc->key_phase ^= 1; | |
2452 ngx_quic_keys_switch(c, qc->keys); | |
2453 | |
2454 rc = ngx_quic_handle_frames(c, pkt); | |
2455 if (rc != NGX_OK) { | |
2456 return rc; | |
2457 } | |
2458 | |
2459 return ngx_quic_keys_update(c, qc->keys); | |
2460 } | |
2461 | |
2462 | |
2463 static ngx_int_t | |
2464 ngx_quic_send_early_cc(ngx_connection_t *c, ngx_quic_header_t *inpkt, | |
2465 ngx_uint_t err, const char *reason) | |
2466 { | |
2467 ssize_t len; | |
2468 ngx_str_t res; | |
2469 ngx_quic_frame_t frame; | |
2470 ngx_quic_header_t pkt; | |
2471 | |
2472 static u_char src[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE]; | |
2473 static u_char dst[NGX_QUIC_MAX_UDP_PAYLOAD_SIZE]; | |
2474 | |
2475 ngx_memzero(&frame, sizeof(ngx_quic_frame_t)); | |
2476 ngx_memzero(&pkt, sizeof(ngx_quic_header_t)); | |
2477 | |
2478 frame.level = inpkt->level; | |
2479 frame.type = NGX_QUIC_FT_CONNECTION_CLOSE; | |
2480 frame.u.close.error_code = err; | |
2481 | |
2482 frame.u.close.reason.data = (u_char *) reason; | |
2483 frame.u.close.reason.len = ngx_strlen(reason); | |
2484 | |
2485 len = ngx_quic_create_frame(NULL, &frame); | |
2486 if (len > NGX_QUIC_MAX_UDP_PAYLOAD_SIZE) { | |
2487 return NGX_ERROR; | |
2488 } | |
2489 | |
2490 ngx_quic_log_frame(c->log, &frame, 1); | |
2491 | |
2492 len = ngx_quic_create_frame(src, &frame); | |
2493 if (len == -1) { | |
2494 return NGX_ERROR; | |
2495 } | |
2496 | |
2497 pkt.keys = ngx_quic_keys_new(c->pool); | |
2498 if (pkt.keys == NULL) { | |
2499 return NGX_ERROR; | |
2500 } | |
2501 | |
2502 if (ngx_quic_keys_set_initial_secret(c->pool, pkt.keys, &inpkt->dcid) | |
2503 != NGX_OK) | |
2504 { | |
2505 return NGX_ERROR; | |
2506 } | |
2507 | |
2508 pkt.flags = NGX_QUIC_PKT_FIXED_BIT | NGX_QUIC_PKT_LONG | |
2509 | NGX_QUIC_PKT_INITIAL; | |
2510 | |
2511 pkt.num_len = 1; | |
2512 /* | |
2513 * pkt.num = 0; | |
2514 * pkt.trunc = 0; | |
2515 */ | |
2516 | |
2517 pkt.version = inpkt->version; | |
2518 pkt.log = c->log; | |
2519 pkt.level = inpkt->level; | |
2520 pkt.dcid = inpkt->scid; | |
2521 pkt.scid = inpkt->dcid; | |
2522 pkt.payload.data = src; | |
2523 pkt.payload.len = len; | |
2524 | |
2525 res.data = dst; | |
2526 | |
2527 if (ngx_quic_encrypt(&pkt, &res) != NGX_OK) { | |
2528 return NGX_ERROR; | |
2529 } | |
2530 | |
2531 if (ngx_quic_send(c, res.data, res.len) == NGX_ERROR) { | |
2532 return NGX_ERROR; | |
2533 } | |
2534 | |
2535 return NGX_OK; | |
2536 } | |
2537 | |
2538 | |
2539 static void | |
2540 ngx_quic_discard_ctx(ngx_connection_t *c, enum ssl_encryption_level_t level) | |
2541 { | |
2542 ngx_queue_t *q; | |
2543 ngx_quic_frame_t *f; | |
2544 ngx_quic_send_ctx_t *ctx; | |
2545 ngx_quic_connection_t *qc; | |
2546 | |
2547 qc = ngx_quic_get_connection(c); | |
2548 | |
2549 if (!ngx_quic_keys_available(qc->keys, level)) { | |
2550 return; | |
2551 } | |
2552 | |
2553 ngx_quic_keys_discard(qc->keys, level); | |
2554 | |
2555 qc->pto_count = 0; | |
2556 | |
2557 ctx = ngx_quic_get_send_ctx(qc, level); | |
2558 | |
2559 while (!ngx_queue_empty(&ctx->sent)) { | |
2560 q = ngx_queue_head(&ctx->sent); | |
2561 ngx_queue_remove(q); | |
2562 | |
2563 f = ngx_queue_data(q, ngx_quic_frame_t, queue); | |
2564 ngx_quic_congestion_ack(c, f); | |
2565 ngx_quic_free_frame(c, f); | |
2566 } | |
2567 | |
2568 while (!ngx_queue_empty(&ctx->frames)) { | |
2569 q = ngx_queue_head(&ctx->frames); | |
2570 ngx_queue_remove(q); | |
2571 | |
2572 f = ngx_queue_data(q, ngx_quic_frame_t, queue); | |
2573 ngx_quic_congestion_ack(c, f); | |
2574 ngx_quic_free_frame(c, f); | |
2575 } | |
2576 | |
2577 if (level == ssl_encryption_initial) { | |
2578 ngx_quic_clear_temp_server_ids(c); | |
2579 } | |
2580 | |
2581 ctx->send_ack = 0; | |
2582 } | |
2583 | |
2584 | |
2585 static ngx_int_t | |
2586 ngx_quic_check_peer(ngx_quic_connection_t *qc, ngx_quic_header_t *pkt) | |
2587 { | |
2588 ngx_queue_t *q; | |
2589 ngx_quic_client_id_t *cid; | |
2590 | |
2591 if (pkt->level == ssl_encryption_application) { | |
2592 return NGX_OK; | |
2593 } | |
2594 | |
2595 for (q = ngx_queue_head(&qc->client_ids); | |
2596 q != ngx_queue_sentinel(&qc->client_ids); | |
2597 q = ngx_queue_next(q)) | |
2598 { | |
2599 cid = ngx_queue_data(q, ngx_quic_client_id_t, queue); | |
2600 | |
2601 if (pkt->scid.len == cid->len | |
2602 && ngx_memcmp(pkt->scid.data, cid->id, cid->len) == 0) | |
2603 { | |
2604 return NGX_OK; | |
2605 } | |
2606 } | |
2607 | |
2608 ngx_log_error(NGX_LOG_INFO, pkt->log, 0, "quic unexpected quic scid"); | |
2609 return NGX_ERROR; | |
2610 } | |
2611 | |
2612 | |
2613 static ngx_int_t | |
2614 ngx_quic_handle_frames(ngx_connection_t *c, ngx_quic_header_t *pkt) | |
2615 { | |
2616 u_char *end, *p; | |
2617 ssize_t len; | |
2618 ngx_buf_t buf; | |
2619 ngx_uint_t do_close; | |
2620 ngx_chain_t chain; | |
2621 ngx_quic_frame_t frame; | |
2622 ngx_quic_connection_t *qc; | |
2623 | |
2624 qc = ngx_quic_get_connection(c); | |
2614 | 2625 |
2615 p = pkt->payload.data; | 2626 p = pkt->payload.data; |
2616 end = p + pkt->payload.len; | 2627 end = p + pkt->payload.len; |
2617 | 2628 |
2618 do_close = 0; | 2629 do_close = 0; |