diff options
Diffstat (limited to 'src/fragmentation/defragmentation_new.c')
-rw-r--r-- | src/fragmentation/defragmentation_new.c | 69 |
1 files changed, 44 insertions, 25 deletions
diff --git a/src/fragmentation/defragmentation_new.c b/src/fragmentation/defragmentation_new.c index 2e1136f9f..379ec57d4 100644 --- a/src/fragmentation/defragmentation_new.c +++ b/src/fragmentation/defragmentation_new.c | |||
@@ -391,6 +391,7 @@ discard_oldest_mc (struct GNUNET_DEFRAGMENT_Context *dc) | |||
391 | if (GNUNET_SCHEDULER_NO_TASK != old->ack_task) | 391 | if (GNUNET_SCHEDULER_NO_TASK != old->ack_task) |
392 | GNUNET_SCHEDULER_cancel (old->ack_task); | 392 | GNUNET_SCHEDULER_cancel (old->ack_task); |
393 | GNUNET_free (old); | 393 | GNUNET_free (old); |
394 | fprintf (stderr, "D"); | ||
394 | } | 395 | } |
395 | 396 | ||
396 | 397 | ||
@@ -399,8 +400,9 @@ discard_oldest_mc (struct GNUNET_DEFRAGMENT_Context *dc) | |||
399 | * | 400 | * |
400 | * @param dc the context | 401 | * @param dc the context |
401 | * @param msg the message that was received | 402 | * @param msg the message that was received |
403 | * @return GNUNET_OK on success, GNUNET_NO if this was a duplicate, GNUNET_SYSERR on error | ||
402 | */ | 404 | */ |
403 | void | 405 | int |
404 | GNUNET_DEFRAGMENT_process_fragment (struct GNUNET_DEFRAGMENT_Context *dc, | 406 | GNUNET_DEFRAGMENT_process_fragment (struct GNUNET_DEFRAGMENT_Context *dc, |
405 | const struct GNUNET_MessageHeader *msg) | 407 | const struct GNUNET_MessageHeader *msg) |
406 | { | 408 | { |
@@ -415,25 +417,32 @@ GNUNET_DEFRAGMENT_process_fragment (struct GNUNET_DEFRAGMENT_Context *dc, | |||
415 | struct GNUNET_TIME_Relative delay; | 417 | struct GNUNET_TIME_Relative delay; |
416 | unsigned int bc; | 418 | unsigned int bc; |
417 | unsigned int b; | 419 | unsigned int b; |
420 | unsigned int n; | ||
421 | int duplicate; | ||
418 | 422 | ||
419 | if (ntohs(msg->size) < sizeof (struct FragmentHeader)) | 423 | if (ntohs(msg->size) < sizeof (struct FragmentHeader)) |
420 | { | 424 | { |
421 | GNUNET_break_op (0); | 425 | GNUNET_break_op (0); |
422 | return; | 426 | return GNUNET_SYSERR; |
423 | } | 427 | } |
424 | if (ntohs (msg->size) > dc->mtu) | 428 | if (ntohs (msg->size) > dc->mtu) |
425 | { | 429 | { |
426 | GNUNET_break_op (0); | 430 | GNUNET_break_op (0); |
427 | return; | 431 | return GNUNET_SYSERR; |
428 | } | 432 | } |
429 | fh = (const struct FragmentHeader*) msg; | 433 | fh = (const struct FragmentHeader*) msg; |
430 | msize = ntohs (fh->total_size); | 434 | msize = ntohs (fh->total_size); |
431 | fid = ntohl (fh->fragment_id); | 435 | fid = ntohl (fh->fragment_id); |
432 | foff = ntohl (fh->offset); | 436 | foff = ntohs (fh->offset); |
433 | if (foff >= msize) | 437 | if (foff >= msize) |
434 | { | 438 | { |
435 | GNUNET_break_op (0); | 439 | GNUNET_break_op (0); |
436 | return; | 440 | return GNUNET_SYSERR; |
441 | } | ||
442 | if (0 != (foff % (dc->mtu - sizeof (struct FragmentHeader)))) | ||
443 | { | ||
444 | GNUNET_break_op (0); | ||
445 | return GNUNET_SYSERR; | ||
437 | } | 446 | } |
438 | GNUNET_STATISTICS_update (dc->stats, | 447 | GNUNET_STATISTICS_update (dc->stats, |
439 | _("Fragments received"), | 448 | _("Fragments received"), |
@@ -443,19 +452,19 @@ GNUNET_DEFRAGMENT_process_fragment (struct GNUNET_DEFRAGMENT_Context *dc, | |||
443 | while ( (NULL != mc) && | 452 | while ( (NULL != mc) && |
444 | (fid != mc->fragment_id) ) | 453 | (fid != mc->fragment_id) ) |
445 | mc = mc->next; | 454 | mc = mc->next; |
446 | bit = foff / dc->mtu; | 455 | bit = foff / (dc->mtu - sizeof (struct FragmentHeader)); |
447 | if (bit * dc->mtu + ntohs (msg->size) | 456 | if (bit * (dc->mtu - sizeof (struct FragmentHeader)) + ntohs (msg->size) |
448 | - sizeof (struct FragmentHeader) > msize) | 457 | - sizeof (struct FragmentHeader) > msize) |
449 | { | 458 | { |
450 | /* payload extends past total message size */ | 459 | /* payload extends past total message size */ |
451 | GNUNET_break_op (0); | 460 | GNUNET_break_op (0); |
452 | return; | 461 | return GNUNET_SYSERR; |
453 | } | 462 | } |
454 | if ( (NULL != mc) && (msize != mc->total_size) ) | 463 | if ( (NULL != mc) && (msize != mc->total_size) ) |
455 | { | 464 | { |
456 | /* inconsistent message size */ | 465 | /* inconsistent message size */ |
457 | GNUNET_break_op (0); | 466 | GNUNET_break_op (0); |
458 | return; | 467 | return GNUNET_SYSERR; |
459 | } | 468 | } |
460 | now = GNUNET_TIME_absolute_get (); | 469 | now = GNUNET_TIME_absolute_get (); |
461 | if (NULL == mc) | 470 | if (NULL == mc) |
@@ -466,7 +475,11 @@ GNUNET_DEFRAGMENT_process_fragment (struct GNUNET_DEFRAGMENT_Context *dc, | |||
466 | mc->total_size = msize; | 475 | mc->total_size = msize; |
467 | mc->fragment_id = fid; | 476 | mc->fragment_id = fid; |
468 | mc->last_update = now; | 477 | mc->last_update = now; |
469 | mc->bits = (msize + dc->mtu - 1) / (dc->mtu - sizeof (struct FragmentHeader)); | 478 | n = (msize + dc->mtu - sizeof (struct FragmentHeader) - 1) / (dc->mtu - sizeof (struct FragmentHeader)); |
479 | if (n == 64) | ||
480 | mc->bits = UINT64_MAX; /* set all 64 bit */ | ||
481 | else | ||
482 | mc->bits = (1LL << n) - 1; /* set lowest 'bits' bit */ | ||
470 | GNUNET_CONTAINER_DLL_insert (dc->head, | 483 | GNUNET_CONTAINER_DLL_insert (dc->head, |
471 | dc->tail, | 484 | dc->tail, |
472 | mc); | 485 | mc); |
@@ -476,11 +489,11 @@ GNUNET_DEFRAGMENT_process_fragment (struct GNUNET_DEFRAGMENT_Context *dc, | |||
476 | } | 489 | } |
477 | 490 | ||
478 | /* copy data to 'mc' */ | 491 | /* copy data to 'mc' */ |
479 | if (0 != (mc->bits & (1 << bit))) | 492 | if (0 != (mc->bits & (1LL << bit))) |
480 | { | 493 | { |
481 | mc->bits -= 1 << bit; | 494 | mc->bits -= 1LL << bit; |
482 | mbuf = (char* )&mc[1]; | 495 | mbuf = (char* )&mc[1]; |
483 | memcpy (&mbuf[bit * dc->mtu], | 496 | memcpy (&mbuf[bit * (dc->mtu - sizeof (struct FragmentHeader))], |
484 | &fh[1], | 497 | &fh[1], |
485 | ntohs (msg->size) - sizeof (struct FragmentHeader)); | 498 | ntohs (msg->size) - sizeof (struct FragmentHeader)); |
486 | mc->last_update = now; | 499 | mc->last_update = now; |
@@ -490,19 +503,11 @@ GNUNET_DEFRAGMENT_process_fragment (struct GNUNET_DEFRAGMENT_Context *dc, | |||
490 | mc->frag_times[mc->frag_times_write_offset].time = now; | 503 | mc->frag_times[mc->frag_times_write_offset].time = now; |
491 | mc->frag_times[mc->frag_times_write_offset].bit = bit; | 504 | mc->frag_times[mc->frag_times_write_offset].bit = bit; |
492 | mc->frag_times_write_offset++; | 505 | mc->frag_times_write_offset++; |
493 | if (0 == mc->bits) | 506 | duplicate = GNUNET_NO; |
494 | { | ||
495 | /* message complete, notify! */ | ||
496 | dc->proc (dc->cls, | ||
497 | mc->msg); | ||
498 | GNUNET_STATISTICS_update (dc->stats, | ||
499 | _("Messages defragmented"), | ||
500 | 1, | ||
501 | GNUNET_NO); | ||
502 | } | ||
503 | } | 507 | } |
504 | else | 508 | else |
505 | { | 509 | { |
510 | duplicate = GNUNET_YES; | ||
506 | GNUNET_STATISTICS_update (dc->stats, | 511 | GNUNET_STATISTICS_update (dc->stats, |
507 | _("Duplicate fragments received"), | 512 | _("Duplicate fragments received"), |
508 | 1, | 513 | 1, |
@@ -512,18 +517,32 @@ GNUNET_DEFRAGMENT_process_fragment (struct GNUNET_DEFRAGMENT_Context *dc, | |||
512 | /* count number of missing fragments */ | 517 | /* count number of missing fragments */ |
513 | bc = 0; | 518 | bc = 0; |
514 | for (b=0;b<64;b++) | 519 | for (b=0;b<64;b++) |
515 | if (0 != (mc->bits & (1 << b))) bc++; | 520 | if (0 != (mc->bits & (1LL << b))) bc++; |
516 | if (mc->frag_times_write_offset - mc->frag_times_start_offset > 1) | 521 | if (mc->frag_times_write_offset - mc->frag_times_start_offset > 1) |
517 | dc->latency = estimate_latency (mc); | 522 | dc->latency = estimate_latency (mc); |
518 | delay = GNUNET_TIME_relative_multiply (dc->latency, | 523 | delay = GNUNET_TIME_relative_multiply (dc->latency, |
519 | bc + 1); | 524 | bc + 1); |
520 | if (0 == mc->bits) /* message complete, ACK now! */ | 525 | if ( (0 == mc->bits) || (GNUNET_YES == duplicate) ) /* message complete or duplicate, ACK now! */ |
521 | delay = GNUNET_TIME_UNIT_ZERO; | 526 | delay = GNUNET_TIME_UNIT_ZERO; |
522 | if (GNUNET_SCHEDULER_NO_TASK != mc->ack_task) | 527 | if (GNUNET_SCHEDULER_NO_TASK != mc->ack_task) |
523 | GNUNET_SCHEDULER_cancel (mc->ack_task); | 528 | GNUNET_SCHEDULER_cancel (mc->ack_task); |
524 | mc->ack_task = GNUNET_SCHEDULER_add_delayed (delay, | 529 | mc->ack_task = GNUNET_SCHEDULER_add_delayed (delay, |
525 | &send_ack, | 530 | &send_ack, |
526 | mc); | 531 | mc); |
532 | if ( (duplicate == GNUNET_NO) && | ||
533 | (0 == mc->bits) ) | ||
534 | { | ||
535 | GNUNET_STATISTICS_update (dc->stats, | ||
536 | _("Messages defragmented"), | ||
537 | 1, | ||
538 | GNUNET_NO); | ||
539 | /* message complete, notify! */ | ||
540 | dc->proc (dc->cls, | ||
541 | mc->msg); | ||
542 | } | ||
543 | if (duplicate == GNUNET_YES) | ||
544 | return GNUNET_NO; | ||
545 | return GNUNET_YES; | ||
527 | } | 546 | } |
528 | 547 | ||
529 | /* end of defragmentation_new.c */ | 548 | /* end of defragmentation_new.c */ |