|
19 | 19 |
|
20 | 20 | #define _STOP (_STOP_SUCCESS + _STOP_FAILURE) |
21 | 21 |
|
22 | | -static unsigned long long _acknowledgment_range_gap_sizes[] = { |
23 | | - UINT32_MAX, |
24 | | - UINT16_MAX, |
25 | | - UINT16_MAX, |
26 | | - UINT16_MAX, |
27 | | - UINT16_MAX |
28 | | -}; |
29 | | - |
30 | 22 | /* This is the wire format for a message. It's only used internally here. */ |
31 | 23 | struct _message { |
32 | 24 | unsigned char id[4]; |
@@ -113,9 +105,14 @@ int curvecpr_messager_recv (struct curvecpr_messager *messager, const unsigned c |
113 | 105 | /* Range 1. */ |
114 | 106 | start = 0; |
115 | 107 | end = curvecpr_bytes_unpack_uint64(message->acknowledging_range_1_size); |
116 | | - if (start - end > 0) |
| 108 | + if (start - end > 0) { |
117 | 109 | cf->ops.sendmarkq_remove_range(messager, start, end); |
118 | 110 |
|
| 111 | + /* If we're at EOF, see if we can move to a final state. */ |
| 112 | + if (messager->my_eof && end >= messager->my_sent_bytes) |
| 113 | + messager->my_final = 1; |
| 114 | + } |
| 115 | + |
119 | 116 | /* Range 2. */ |
120 | 117 | start = end + (unsigned long long)curvecpr_bytes_unpack_uint32(message->acknowledging_range_12_gap); |
121 | 118 | end = start + (unsigned long long)curvecpr_bytes_unpack_uint16(message->acknowledging_range_2_size); |
@@ -232,7 +229,7 @@ static int _send_block (struct curvecpr_messager *messager, struct curvecpr_bloc |
232 | 229 |
|
233 | 230 | crypto_uint32 id = 0; |
234 | 231 |
|
235 | | - struct { unsigned char exists; unsigned long long start; unsigned long long end; } acknowledgment_ranges[6] = { { .exists = 0, .start = 0, .end = 0 } }; |
| 232 | + struct { unsigned char exists; crypto_uint64 start; crypto_uint64 end; } acknowledgment_ranges[6] = { { .exists = 0, .start = 0, .end = 0 } }; |
236 | 233 |
|
237 | 234 | /* NB: It is perfectly acceptable for block to be null in this function. */ |
238 | 235 |
|
@@ -262,44 +259,40 @@ static int _send_block (struct curvecpr_messager *messager, struct curvecpr_bloc |
262 | 259 | /* Write range acknowledgments. */ |
263 | 260 | { |
264 | 261 | struct curvecpr_block *received_block = NULL; |
265 | | - unsigned int received_block_num = 0; |
266 | | - int i = 0; |
| 262 | + int block_num = 0, i = 0; |
| 263 | + |
| 264 | + crypto_uint64 check = messager->their_contiguous_sent_bytes; |
| 265 | + unsigned long long maximum_gap = UINT32_MAX; |
267 | 266 |
|
268 | | - /* XXX: Should really figure out a better way to do this. */ |
269 | 267 | for (;;) { |
270 | | - if (cf->ops.recvmarkq_get(messager, received_block_num++, &received_block)) |
271 | | - /* Less than 6 ranges to acknowledge! */ |
| 268 | + if (cf->ops.recvmarkq_get(messager, block_num++, &received_block)) |
272 | 269 | break; |
273 | 270 |
|
274 | | - if (!acknowledgment_ranges[i].exists) { |
275 | | - /* This basically only happens for the first block in the first range. */ |
| 271 | + acknowledgment_ranges[i].exists = 1; |
| 272 | + |
| 273 | + if (received_block->offset > check) { |
| 274 | + acknowledgment_ranges[i].end = check; |
| 275 | + |
| 276 | + if (!(i < 5)) |
| 277 | + /* Can't fit any more acknowledgments in this message. */ |
| 278 | + break; |
| 279 | + else if (received_block->offset - check > maximum_gap) |
| 280 | + /* Gap is too large... need more packets! */ |
| 281 | + break; |
| 282 | + |
| 283 | + i++; |
276 | 284 | acknowledgment_ranges[i].exists = 1; |
277 | 285 | acknowledgment_ranges[i].start = received_block->offset; |
278 | 286 | acknowledgment_ranges[i].end = received_block->offset + received_block->data_len; |
279 | | - } else if (received_block->offset == acknowledgment_ranges[i].end) { |
280 | | - /* Continuation of the previous block. Just add. */ |
281 | | - acknowledgment_ranges[i].end += received_block->data_len; |
282 | | - } else if (i < 5) { |
283 | | - /* Doesn't fit at all. */ |
284 | | - unsigned long long maximum_gap = _acknowledgment_range_gap_sizes[i]; |
285 | | - if (received_block->offset - acknowledgment_ranges[i].end > maximum_gap) { |
286 | | - /* The gap is too large! We'll have to send another acknowledgment |
287 | | - later. */ |
288 | | - break; |
289 | | - } else if (received_block->data_len > UINT16_MAX) { |
290 | | - /* Range size is too large! */ |
291 | | - break; |
292 | | - } else { |
293 | | - /* Add a new range. */ |
294 | | - ++i; |
295 | | - acknowledgment_ranges[i].exists = 1; |
296 | | - acknowledgment_ranges[i].start = received_block->offset; |
297 | | - acknowledgment_ranges[i].end = received_block->offset + received_block->data_len; |
298 | | - } |
| 287 | + |
| 288 | + maximum_gap = UINT16_MAX; |
299 | 289 | } else { |
300 | | - /* End of the line. We can't fit any more acknowledgments in. */ |
301 | | - break; |
| 290 | + crypto_uint64 received_block_end = received_block->offset + received_block->data_len; |
| 291 | + |
| 292 | + acknowledgment_ranges[i].end = check > received_block_end ? check : received_block_end; |
302 | 293 | } |
| 294 | + |
| 295 | + check = acknowledgment_ranges[i].end; |
303 | 296 | } |
304 | 297 |
|
305 | 298 | if (acknowledgment_ranges[0].exists) { |
@@ -409,8 +402,16 @@ static int _send_block (struct curvecpr_messager *messager, struct curvecpr_bloc |
409 | 402 |
|
410 | 403 | for (i = 0; i < 6 && acknowledgment_ranges[i].exists; ++i) |
411 | 404 | cf->ops.recvmarkq_move_range_to_recvq(messager, acknowledgment_ranges[i].start, acknowledgment_ranges[i].end); |
| 405 | + |
412 | 406 | } |
413 | 407 |
|
| 408 | + if (acknowledgment_ranges[0].exists) |
| 409 | + messager->their_contiguous_sent_bytes = acknowledgment_ranges[0].end; |
| 410 | + |
| 411 | + /* The remote side is in a final state if we've acknowledged their EOF. */ |
| 412 | + if (messager->their_eof && messager->their_contiguous_sent_bytes >= messager->their_total_bytes) |
| 413 | + messager->their_final = 1; |
| 414 | + |
414 | 415 | /* Update the last sent time for timeout calcuations. */ |
415 | 416 | messager->my_sent_clock = messager->chicago.clock; |
416 | 417 |
|
|
0 commit comments