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