Mercurial > hg > nginx-quic
comparison src/event/ngx_event_quic.c @ 7792:1cdd53532309 quic
ACK ranges processing.
+ since number of ranges in unknown, provide a function to parse them once
again in handler to avoid memory allocation
+ ack handler now processes all ranges, not only the first
+ ECN counters are parsed and saved into frame if present
author | Vladimir Homutov <vl@nginx.com> |
---|---|
date | Mon, 06 Apr 2020 16:19:26 +0300 |
parents | 9b9d592c0da3 |
children | 0ae50d90658a |
comparison
equal
deleted
inserted
replaced
7791:9b9d592c0da3 | 7792:1cdd53532309 |
---|---|
132 static ngx_int_t ngx_quic_payload_handler(ngx_connection_t *c, | 132 static ngx_int_t ngx_quic_payload_handler(ngx_connection_t *c, |
133 ngx_quic_header_t *pkt); | 133 ngx_quic_header_t *pkt); |
134 | 134 |
135 static ngx_int_t ngx_quic_handle_ack_frame(ngx_connection_t *c, | 135 static ngx_int_t ngx_quic_handle_ack_frame(ngx_connection_t *c, |
136 ngx_quic_header_t *pkt, ngx_quic_ack_frame_t *f); | 136 ngx_quic_header_t *pkt, ngx_quic_ack_frame_t *f); |
137 static ngx_int_t ngx_quic_handle_ack_frame_range(ngx_connection_t *c, | |
138 ngx_quic_namespace_t *ns, uint64_t min, uint64_t max); | |
137 static ngx_int_t ngx_quic_handle_crypto_frame(ngx_connection_t *c, | 139 static ngx_int_t ngx_quic_handle_crypto_frame(ngx_connection_t *c, |
138 ngx_quic_header_t *pkt, ngx_quic_crypto_frame_t *frame); | 140 ngx_quic_header_t *pkt, ngx_quic_crypto_frame_t *frame); |
139 static ngx_int_t ngx_quic_handle_stream_frame(ngx_connection_t *c, | 141 static ngx_int_t ngx_quic_handle_stream_frame(ngx_connection_t *c, |
140 ngx_quic_header_t *pkt, ngx_quic_stream_frame_t *frame); | 142 ngx_quic_header_t *pkt, ngx_quic_stream_frame_t *frame); |
141 static ngx_int_t ngx_quic_handle_max_streams(ngx_connection_t *c); | 143 static ngx_int_t ngx_quic_handle_max_streams(ngx_connection_t *c); |
1240 | 1242 |
1241 static ngx_int_t | 1243 static ngx_int_t |
1242 ngx_quic_handle_ack_frame(ngx_connection_t *c, ngx_quic_header_t *pkt, | 1244 ngx_quic_handle_ack_frame(ngx_connection_t *c, ngx_quic_header_t *pkt, |
1243 ngx_quic_ack_frame_t *ack) | 1245 ngx_quic_ack_frame_t *ack) |
1244 { | 1246 { |
1245 ngx_uint_t found, min; | 1247 ssize_t n; |
1246 ngx_queue_t *q, range; | 1248 u_char *pos, *end; |
1247 ngx_quic_frame_t *f; | 1249 uint64_t gap, range; |
1250 ngx_uint_t i, min, max; | |
1248 ngx_quic_namespace_t *ns; | 1251 ngx_quic_namespace_t *ns; |
1249 | 1252 |
1250 ns = &c->quic->ns[ngx_quic_ns(pkt->level)]; | 1253 ns = &c->quic->ns[ngx_quic_ns(pkt->level)]; |
1251 | 1254 |
1252 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, | 1255 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, |
1253 "ngx_quic_handle_ack_frame in namespace %d", | 1256 "ngx_quic_handle_ack_frame in namespace %d", |
1254 ngx_quic_ns(pkt->level)); | 1257 ngx_quic_ns(pkt->level)); |
1255 | 1258 |
1259 /* | |
1260 * TODO: If any computed packet number is negative, an endpoint MUST | |
1261 * generate a connection error of type FRAME_ENCODING_ERROR. | |
1262 * (19.3.1) | |
1263 */ | |
1264 | |
1256 if (ack->first_range > ack->largest) { | 1265 if (ack->first_range > ack->largest) { |
1257 ngx_log_error(NGX_LOG_INFO, c->log, 0, | 1266 ngx_log_error(NGX_LOG_INFO, c->log, 0, |
1258 "invalid first range in ack frame"); | 1267 "invalid first range in ack frame"); |
1259 return NGX_ERROR; | 1268 return NGX_ERROR; |
1260 } | 1269 } |
1261 | 1270 |
1262 min = ack->largest - ack->first_range; | 1271 min = ack->largest - ack->first_range; |
1272 max = ack->largest; | |
1273 | |
1274 if (ngx_quic_handle_ack_frame_range(c, ns, min, max) != NGX_OK) { | |
1275 return NGX_ERROR; | |
1276 } | |
1277 | |
1278 /* 13.2.3. Receiver Tracking of ACK Frames */ | |
1279 if (ns->largest < max) { | |
1280 ns->largest = max; | |
1281 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
1282 "updated largest received: %ui", max); | |
1283 } | |
1284 | |
1285 pos = ack->ranges_start; | |
1286 end = ack->ranges_end; | |
1287 | |
1288 for (i = 0; i < ack->range_count; i++) { | |
1289 | |
1290 n = ngx_quic_parse_ack_range(pkt, pos, end, &gap, &range); | |
1291 if (n == NGX_ERROR) { | |
1292 return NGX_ERROR; | |
1293 } | |
1294 pos += n; | |
1295 | |
1296 if (gap >= min) { | |
1297 ngx_log_error(NGX_LOG_INFO, c->log, 0, | |
1298 "invalid range %ui in ack frame", i); | |
1299 return NGX_ERROR; | |
1300 } | |
1301 | |
1302 max = min - 1 - gap; | |
1303 | |
1304 if (range > max + 1) { | |
1305 ngx_log_error(NGX_LOG_INFO, c->log, 0, | |
1306 "invalid range %ui in ack frame", i); | |
1307 return NGX_ERROR; | |
1308 } | |
1309 | |
1310 min = max - range + 1; | |
1311 | |
1312 if (ngx_quic_handle_ack_frame_range(c, ns, min, max) != NGX_OK) { | |
1313 return NGX_ERROR; | |
1314 } | |
1315 } | |
1316 | |
1317 return NGX_OK; | |
1318 } | |
1319 | |
1320 | |
1321 static ngx_int_t | |
1322 ngx_quic_handle_ack_frame_range(ngx_connection_t *c, ngx_quic_namespace_t *ns, | |
1323 uint64_t min, uint64_t max) | |
1324 { | |
1325 ngx_uint_t found; | |
1326 ngx_queue_t *q, range; | |
1327 ngx_quic_frame_t *f; | |
1263 | 1328 |
1264 found = 0; | 1329 found = 0; |
1265 | 1330 |
1266 ngx_queue_init(&range); | 1331 ngx_queue_init(&range); |
1267 | 1332 |
1269 | 1334 |
1270 while (q != ngx_queue_sentinel(&ns->sent)) { | 1335 while (q != ngx_queue_sentinel(&ns->sent)) { |
1271 | 1336 |
1272 f = ngx_queue_data(q, ngx_quic_frame_t, queue); | 1337 f = ngx_queue_data(q, ngx_quic_frame_t, queue); |
1273 | 1338 |
1274 if (f->pnum >= min && f->pnum <= ack->largest) { | 1339 if (f->pnum >= min && f->pnum <= max) { |
1275 q = ngx_queue_next(q); | 1340 q = ngx_queue_next(q); |
1276 ngx_queue_remove(&f->queue); | 1341 ngx_queue_remove(&f->queue); |
1277 ngx_quic_free_frame(c, f); | 1342 ngx_quic_free_frame(c, f); |
1278 found = 1; | 1343 found = 1; |
1279 | 1344 |
1282 } | 1347 } |
1283 } | 1348 } |
1284 | 1349 |
1285 if (!found) { | 1350 if (!found) { |
1286 | 1351 |
1287 if (ack->largest <= ns->pnum) { | 1352 if (max <= ns->pnum) { |
1288 /* duplicate ACK or ACK for non-ack-eliciting frame */ | 1353 /* duplicate ACK or ACK for non-ack-eliciting frame */ |
1289 goto done; | 1354 return NGX_OK; |
1290 } | 1355 } |
1291 | 1356 |
1292 ngx_log_error(NGX_LOG_INFO, c->log, 0, | 1357 ngx_log_error(NGX_LOG_INFO, c->log, 0, |
1293 "ACK for the packet not in sent queue "); | 1358 "ACK for the packet not in sent queue "); |
1294 // TODO: handle error properly: PROTOCOL VIOLATION? | 1359 // TODO: handle error properly: PROTOCOL VIOLATION? |
1295 return NGX_ERROR; | 1360 return NGX_ERROR; |
1296 } | |
1297 | |
1298 done: | |
1299 | |
1300 /* 13.2.3. Receiver Tracking of ACK Frames */ | |
1301 if (ns->largest < ack->largest) { | |
1302 ns->largest = ack->largest; | |
1303 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
1304 "updated largest received: %ui", ns->largest); | |
1305 } | 1361 } |
1306 | 1362 |
1307 return NGX_OK; | 1363 return NGX_OK; |
1308 } | 1364 } |
1309 | 1365 |