aboutsummaryrefslogtreecommitdiff
path: root/src/fragmentation/defragmentation_new.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fragmentation/defragmentation_new.c')
-rw-r--r--src/fragmentation/defragmentation_new.c69
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 */
403void 405int
404GNUNET_DEFRAGMENT_process_fragment (struct GNUNET_DEFRAGMENT_Context *dc, 406GNUNET_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 */