diff options
author | Christian Grothoff <christian@grothoff.org> | 2011-08-15 21:46:35 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2011-08-15 21:46:35 +0000 |
commit | 502af2167f7c218366666ca4944bd7cc54b5b19a (patch) | |
tree | a91fec5cc9769d260640bd91c6633cb9cf395524 /src/fragmentation | |
parent | 03af5a603b7cc53432249d5854cd412aa90dde0d (diff) | |
download | gnunet-502af2167f7c218366666ca4944bd7cc54b5b19a.tar.gz gnunet-502af2167f7c218366666ca4944bd7cc54b5b19a.zip |
indentation
Diffstat (limited to 'src/fragmentation')
-rw-r--r-- | src/fragmentation/defragmentation.c | 313 | ||||
-rw-r--r-- | src/fragmentation/fragmentation.c | 209 | ||||
-rw-r--r-- | src/fragmentation/test_fragmentation.c | 170 |
3 files changed, 325 insertions, 367 deletions
diff --git a/src/fragmentation/defragmentation.c b/src/fragmentation/defragmentation.c index 8aad86003..35d59854f 100644 --- a/src/fragmentation/defragmentation.c +++ b/src/fragmentation/defragmentation.c | |||
@@ -69,7 +69,7 @@ struct MessageContext | |||
69 | /** | 69 | /** |
70 | * Pointer to the assembled message, allocated at the | 70 | * Pointer to the assembled message, allocated at the |
71 | * end of this struct. | 71 | * end of this struct. |
72 | */ | 72 | */ |
73 | const struct GNUNET_MessageHeader *msg; | 73 | const struct GNUNET_MessageHeader *msg; |
74 | 74 | ||
75 | /** | 75 | /** |
@@ -183,7 +183,7 @@ struct GNUNET_DEFRAGMENT_Context | |||
183 | 183 | ||
184 | /** | 184 | /** |
185 | * Maximum message size for each fragment. | 185 | * Maximum message size for each fragment. |
186 | */ | 186 | */ |
187 | uint16_t mtu; | 187 | uint16_t mtu; |
188 | }; | 188 | }; |
189 | 189 | ||
@@ -203,11 +203,11 @@ struct GNUNET_DEFRAGMENT_Context | |||
203 | */ | 203 | */ |
204 | struct GNUNET_DEFRAGMENT_Context * | 204 | struct GNUNET_DEFRAGMENT_Context * |
205 | GNUNET_DEFRAGMENT_context_create (struct GNUNET_STATISTICS_Handle *stats, | 205 | GNUNET_DEFRAGMENT_context_create (struct GNUNET_STATISTICS_Handle *stats, |
206 | uint16_t mtu, | 206 | uint16_t mtu, |
207 | unsigned int num_msgs, | 207 | unsigned int num_msgs, |
208 | void *cls, | 208 | void *cls, |
209 | GNUNET_FRAGMENT_MessageProcessor proc, | 209 | GNUNET_FRAGMENT_MessageProcessor proc, |
210 | GNUNET_DEFRAGMENT_AckProcessor ackp) | 210 | GNUNET_DEFRAGMENT_AckProcessor ackp) |
211 | { | 211 | { |
212 | struct GNUNET_DEFRAGMENT_Context *dc; | 212 | struct GNUNET_DEFRAGMENT_Context *dc; |
213 | 213 | ||
@@ -218,7 +218,7 @@ GNUNET_DEFRAGMENT_context_create (struct GNUNET_STATISTICS_Handle *stats, | |||
218 | dc->ackp = ackp; | 218 | dc->ackp = ackp; |
219 | dc->num_msgs = num_msgs; | 219 | dc->num_msgs = num_msgs; |
220 | dc->mtu = mtu; | 220 | dc->mtu = mtu; |
221 | dc->latency = GNUNET_TIME_UNIT_SECONDS; /* start with likely overestimate */ | 221 | dc->latency = GNUNET_TIME_UNIT_SECONDS; /* start with likely overestimate */ |
222 | return dc; | 222 | return dc; |
223 | } | 223 | } |
224 | 224 | ||
@@ -228,24 +228,22 @@ GNUNET_DEFRAGMENT_context_create (struct GNUNET_STATISTICS_Handle *stats, | |||
228 | * | 228 | * |
229 | * @param dc defragmentation context | 229 | * @param dc defragmentation context |
230 | */ | 230 | */ |
231 | void | 231 | void |
232 | GNUNET_DEFRAGMENT_context_destroy (struct GNUNET_DEFRAGMENT_Context *dc) | 232 | GNUNET_DEFRAGMENT_context_destroy (struct GNUNET_DEFRAGMENT_Context *dc) |
233 | { | 233 | { |
234 | struct MessageContext *mc; | 234 | struct MessageContext *mc; |
235 | 235 | ||
236 | while (NULL != (mc = dc->head)) | 236 | while (NULL != (mc = dc->head)) |
237 | { | ||
238 | GNUNET_CONTAINER_DLL_remove (dc->head, dc->tail, mc); | ||
239 | dc->list_size--; | ||
240 | if (GNUNET_SCHEDULER_NO_TASK != mc->ack_task) | ||
237 | { | 241 | { |
238 | GNUNET_CONTAINER_DLL_remove (dc->head, | 242 | GNUNET_SCHEDULER_cancel (mc->ack_task); |
239 | dc->tail, | 243 | mc->ack_task = GNUNET_SCHEDULER_NO_TASK; |
240 | mc); | ||
241 | dc->list_size--; | ||
242 | if (GNUNET_SCHEDULER_NO_TASK != mc->ack_task) | ||
243 | { | ||
244 | GNUNET_SCHEDULER_cancel (mc->ack_task); | ||
245 | mc->ack_task = GNUNET_SCHEDULER_NO_TASK; | ||
246 | } | ||
247 | GNUNET_free (mc); | ||
248 | } | 244 | } |
245 | GNUNET_free (mc); | ||
246 | } | ||
249 | GNUNET_assert (0 == dc->list_size); | 247 | GNUNET_assert (0 == dc->list_size); |
250 | GNUNET_free (dc); | 248 | GNUNET_free (dc); |
251 | } | 249 | } |
@@ -258,8 +256,7 @@ GNUNET_DEFRAGMENT_context_destroy (struct GNUNET_DEFRAGMENT_Context *dc) | |||
258 | * @param tc the scheduler context | 256 | * @param tc the scheduler context |
259 | */ | 257 | */ |
260 | static void | 258 | static void |
261 | send_ack (void *cls, | 259 | send_ack (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) |
262 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
263 | { | 260 | { |
264 | struct MessageContext *mc = cls; | 261 | struct MessageContext *mc = cls; |
265 | struct GNUNET_DEFRAGMENT_Context *dc = mc->dc; | 262 | struct GNUNET_DEFRAGMENT_Context *dc = mc->dc; |
@@ -271,9 +268,8 @@ send_ack (void *cls, | |||
271 | fa.fragment_id = htonl (mc->fragment_id); | 268 | fa.fragment_id = htonl (mc->fragment_id); |
272 | fa.bits = GNUNET_htonll (mc->bits); | 269 | fa.bits = GNUNET_htonll (mc->bits); |
273 | GNUNET_STATISTICS_update (mc->dc->stats, | 270 | GNUNET_STATISTICS_update (mc->dc->stats, |
274 | _("# acknowledgements sent for fragment"), | 271 | _("# acknowledgements sent for fragment"), |
275 | 1, | 272 | 1, GNUNET_NO); |
276 | GNUNET_NO); | ||
277 | dc->ackp (dc->cls, mc->fragment_id, &fa.header); | 273 | dc->ackp (dc->cls, mc->fragment_id, &fa.header); |
278 | } | 274 | } |
279 | 275 | ||
@@ -285,27 +281,26 @@ send_ack (void *cls, | |||
285 | static void | 281 | static void |
286 | gsl_fit_mul (const double *x, const size_t xstride, | 282 | gsl_fit_mul (const double *x, const size_t xstride, |
287 | const double *y, const size_t ystride, | 283 | const double *y, const size_t ystride, |
288 | const size_t n, | 284 | const size_t n, double *c1, double *cov_11, double *sumsq) |
289 | double *c1, double *cov_11, double *sumsq) | ||
290 | { | 285 | { |
291 | double m_x = 0, m_y = 0, m_dx2 = 0, m_dxdy = 0; | 286 | double m_x = 0, m_y = 0, m_dx2 = 0, m_dxdy = 0; |
292 | 287 | ||
293 | size_t i; | 288 | size_t i; |
294 | 289 | ||
295 | for (i = 0; i < n; i++) | 290 | for (i = 0; i < n; i++) |
296 | { | 291 | { |
297 | m_x += (x[i * xstride] - m_x) / (i + 1.0); | 292 | m_x += (x[i * xstride] - m_x) / (i + 1.0); |
298 | m_y += (y[i * ystride] - m_y) / (i + 1.0); | 293 | m_y += (y[i * ystride] - m_y) / (i + 1.0); |
299 | } | 294 | } |
300 | 295 | ||
301 | for (i = 0; i < n; i++) | 296 | for (i = 0; i < n; i++) |
302 | { | 297 | { |
303 | const double dx = x[i * xstride] - m_x; | 298 | const double dx = x[i * xstride] - m_x; |
304 | const double dy = y[i * ystride] - m_y; | 299 | const double dy = y[i * ystride] - m_y; |
305 | 300 | ||
306 | m_dx2 += (dx * dx - m_dx2) / (i + 1.0); | 301 | m_dx2 += (dx * dx - m_dx2) / (i + 1.0); |
307 | m_dxdy += (dx * dy - m_dxdy) / (i + 1.0); | 302 | m_dxdy += (dx * dy - m_dxdy) / (i + 1.0); |
308 | } | 303 | } |
309 | 304 | ||
310 | /* In terms of y = b x */ | 305 | /* In terms of y = b x */ |
311 | 306 | ||
@@ -318,12 +313,13 @@ gsl_fit_mul (const double *x, const size_t xstride, | |||
318 | /* Compute chi^2 = \sum (y_i - b * x_i)^2 */ | 313 | /* Compute chi^2 = \sum (y_i - b * x_i)^2 */ |
319 | 314 | ||
320 | for (i = 0; i < n; i++) | 315 | for (i = 0; i < n; i++) |
321 | { | 316 | { |
322 | const double dx = x[i * xstride] - m_x; | 317 | const double dx = x[i * xstride] - m_x; |
323 | const double dy = y[i * ystride] - m_y; | 318 | const double dy = y[i * ystride] - m_y; |
324 | const double d = (m_y - b * m_x) + dy - b * dx; | 319 | const double d = (m_y - b * m_x) + dy - b * dx; |
325 | d2 += d * d; | 320 | |
326 | } | 321 | d2 += d * d; |
322 | } | ||
327 | 323 | ||
328 | s2 = d2 / (n - 1.0); /* chisq per degree of freedom */ | 324 | s2 = d2 / (n - 1.0); /* chisq per degree of freedom */ |
329 | 325 | ||
@@ -356,16 +352,16 @@ estimate_latency (struct MessageContext *mc) | |||
356 | 352 | ||
357 | first = &mc->frag_times[mc->frag_times_start_offset]; | 353 | first = &mc->frag_times[mc->frag_times_start_offset]; |
358 | GNUNET_assert (total > 1); | 354 | GNUNET_assert (total > 1); |
359 | for (i=0;i<total;i++) | 355 | for (i = 0; i < total; i++) |
360 | { | 356 | { |
361 | x[i] = (double) i; | 357 | x[i] = (double) i; |
362 | y[i] = (double) (first[i].time.abs_value - first[0].time.abs_value); | 358 | y[i] = (double) (first[i].time.abs_value - first[0].time.abs_value); |
363 | } | 359 | } |
364 | gsl_fit_mul (x, 1, y, 1, total, &c1, &cov11, &sumsq); | 360 | gsl_fit_mul (x, 1, y, 1, total, &c1, &cov11, &sumsq); |
365 | c1 += sqrt (sumsq); /* add 1 std dev */ | 361 | c1 += sqrt (sumsq); /* add 1 std dev */ |
366 | ret.rel_value = (uint64_t) c1; | 362 | ret.rel_value = (uint64_t) c1; |
367 | if (ret.rel_value == 0) | 363 | if (ret.rel_value == 0) |
368 | ret = GNUNET_TIME_UNIT_MILLISECONDS; /* always at least 1 */ | 364 | ret = GNUNET_TIME_UNIT_MILLISECONDS; /* always at least 1 */ |
369 | return ret; | 365 | return ret; |
370 | }; | 366 | }; |
371 | 367 | ||
@@ -384,22 +380,20 @@ discard_oldest_mc (struct GNUNET_DEFRAGMENT_Context *dc) | |||
384 | old = NULL; | 380 | old = NULL; |
385 | pos = dc->head; | 381 | pos = dc->head; |
386 | while (NULL != pos) | 382 | while (NULL != pos) |
387 | { | 383 | { |
388 | if ( (old == NULL) || | 384 | if ((old == NULL) || |
389 | (old->last_update.abs_value > pos->last_update.abs_value) ) | 385 | (old->last_update.abs_value > pos->last_update.abs_value)) |
390 | old = pos; | 386 | old = pos; |
391 | pos = pos->next; | 387 | pos = pos->next; |
392 | } | 388 | } |
393 | GNUNET_assert (NULL != old); | 389 | GNUNET_assert (NULL != old); |
394 | GNUNET_CONTAINER_DLL_remove (dc->head, | 390 | GNUNET_CONTAINER_DLL_remove (dc->head, dc->tail, old); |
395 | dc->tail, | ||
396 | old); | ||
397 | dc->list_size--; | 391 | dc->list_size--; |
398 | if (GNUNET_SCHEDULER_NO_TASK != old->ack_task) | 392 | if (GNUNET_SCHEDULER_NO_TASK != old->ack_task) |
399 | { | 393 | { |
400 | GNUNET_SCHEDULER_cancel (old->ack_task); | 394 | GNUNET_SCHEDULER_cancel (old->ack_task); |
401 | old->ack_task = GNUNET_SCHEDULER_NO_TASK; | 395 | old->ack_task = GNUNET_SCHEDULER_NO_TASK; |
402 | } | 396 | } |
403 | GNUNET_free (old); | 397 | GNUNET_free (old); |
404 | } | 398 | } |
405 | 399 | ||
@@ -411,9 +405,9 @@ discard_oldest_mc (struct GNUNET_DEFRAGMENT_Context *dc) | |||
411 | * @param msg the message that was received | 405 | * @param msg the message that was received |
412 | * @return GNUNET_OK on success, GNUNET_NO if this was a duplicate, GNUNET_SYSERR on error | 406 | * @return GNUNET_OK on success, GNUNET_NO if this was a duplicate, GNUNET_SYSERR on error |
413 | */ | 407 | */ |
414 | int | 408 | int |
415 | GNUNET_DEFRAGMENT_process_fragment (struct GNUNET_DEFRAGMENT_Context *dc, | 409 | GNUNET_DEFRAGMENT_process_fragment (struct GNUNET_DEFRAGMENT_Context *dc, |
416 | const struct GNUNET_MessageHeader *msg) | 410 | const struct GNUNET_MessageHeader *msg) |
417 | { | 411 | { |
418 | struct MessageContext *mc; | 412 | struct MessageContext *mc; |
419 | const struct FragmentHeader *fh; | 413 | const struct FragmentHeader *fh; |
@@ -429,135 +423,122 @@ GNUNET_DEFRAGMENT_process_fragment (struct GNUNET_DEFRAGMENT_Context *dc, | |||
429 | unsigned int n; | 423 | unsigned int n; |
430 | int duplicate; | 424 | int duplicate; |
431 | 425 | ||
432 | if (ntohs(msg->size) < sizeof (struct FragmentHeader)) | 426 | if (ntohs (msg->size) < sizeof (struct FragmentHeader)) |
433 | { | 427 | { |
434 | GNUNET_break_op (0); | 428 | GNUNET_break_op (0); |
435 | return GNUNET_SYSERR; | 429 | return GNUNET_SYSERR; |
436 | } | 430 | } |
437 | if (ntohs (msg->size) > dc->mtu) | 431 | if (ntohs (msg->size) > dc->mtu) |
438 | { | 432 | { |
439 | GNUNET_break_op (0); | 433 | GNUNET_break_op (0); |
440 | return GNUNET_SYSERR; | 434 | return GNUNET_SYSERR; |
441 | } | 435 | } |
442 | fh = (const struct FragmentHeader*) msg; | 436 | fh = (const struct FragmentHeader *) msg; |
443 | msize = ntohs (fh->total_size); | 437 | msize = ntohs (fh->total_size); |
444 | if (msize < sizeof (struct GNUNET_MessageHeader)) | 438 | if (msize < sizeof (struct GNUNET_MessageHeader)) |
445 | { | 439 | { |
446 | GNUNET_break_op (0); | 440 | GNUNET_break_op (0); |
447 | return GNUNET_SYSERR; | 441 | return GNUNET_SYSERR; |
448 | } | 442 | } |
449 | fid = ntohl (fh->fragment_id); | 443 | fid = ntohl (fh->fragment_id); |
450 | foff = ntohs (fh->offset); | 444 | foff = ntohs (fh->offset); |
451 | if (foff >= msize) | 445 | if (foff >= msize) |
452 | { | 446 | { |
453 | GNUNET_break_op (0); | 447 | GNUNET_break_op (0); |
454 | return GNUNET_SYSERR; | 448 | return GNUNET_SYSERR; |
455 | } | 449 | } |
456 | if (0 != (foff % (dc->mtu - sizeof (struct FragmentHeader)))) | 450 | if (0 != (foff % (dc->mtu - sizeof (struct FragmentHeader)))) |
457 | { | 451 | { |
458 | GNUNET_break_op (0); | 452 | GNUNET_break_op (0); |
459 | return GNUNET_SYSERR; | 453 | return GNUNET_SYSERR; |
460 | } | 454 | } |
461 | GNUNET_STATISTICS_update (dc->stats, | 455 | GNUNET_STATISTICS_update (dc->stats, _("# fragments received"), 1, GNUNET_NO); |
462 | _("# fragments received"), | ||
463 | 1, | ||
464 | GNUNET_NO); | ||
465 | mc = dc->head; | 456 | mc = dc->head; |
466 | while ( (NULL != mc) && | 457 | while ((NULL != mc) && (fid != mc->fragment_id)) |
467 | (fid != mc->fragment_id) ) | ||
468 | mc = mc->next; | 458 | mc = mc->next; |
469 | bit = foff / (dc->mtu - sizeof (struct FragmentHeader)); | 459 | bit = foff / (dc->mtu - sizeof (struct FragmentHeader)); |
470 | if (bit * (dc->mtu - sizeof (struct FragmentHeader)) + ntohs (msg->size) | 460 | if (bit * (dc->mtu - sizeof (struct FragmentHeader)) + ntohs (msg->size) |
471 | - sizeof (struct FragmentHeader) > msize) | 461 | - sizeof (struct FragmentHeader) > msize) |
472 | { | 462 | { |
473 | /* payload extends past total message size */ | 463 | /* payload extends past total message size */ |
474 | GNUNET_break_op (0); | 464 | GNUNET_break_op (0); |
475 | return GNUNET_SYSERR; | 465 | return GNUNET_SYSERR; |
476 | } | 466 | } |
477 | if ( (NULL != mc) && (msize != mc->total_size) ) | 467 | if ((NULL != mc) && (msize != mc->total_size)) |
478 | { | 468 | { |
479 | /* inconsistent message size */ | 469 | /* inconsistent message size */ |
480 | GNUNET_break_op (0); | 470 | GNUNET_break_op (0); |
481 | return GNUNET_SYSERR; | 471 | return GNUNET_SYSERR; |
482 | } | 472 | } |
483 | now = GNUNET_TIME_absolute_get (); | 473 | now = GNUNET_TIME_absolute_get (); |
484 | if (NULL == mc) | 474 | if (NULL == mc) |
485 | { | 475 | { |
486 | mc = GNUNET_malloc (sizeof (struct MessageContext) + msize); | 476 | mc = GNUNET_malloc (sizeof (struct MessageContext) + msize); |
487 | mc->msg = (const struct GNUNET_MessageHeader*) &mc[1]; | 477 | mc->msg = (const struct GNUNET_MessageHeader *) &mc[1]; |
488 | mc->dc = dc; | 478 | mc->dc = dc; |
489 | mc->total_size = msize; | 479 | mc->total_size = msize; |
490 | mc->fragment_id = fid; | 480 | mc->fragment_id = fid; |
491 | mc->last_update = now; | 481 | mc->last_update = now; |
492 | n = (msize + dc->mtu - sizeof (struct FragmentHeader) - 1) / (dc->mtu - sizeof (struct FragmentHeader)); | 482 | n = (msize + dc->mtu - sizeof (struct FragmentHeader) - 1) / (dc->mtu - |
493 | if (n == 64) | 483 | sizeof (struct |
494 | mc->bits = UINT64_MAX; /* set all 64 bit */ | 484 | FragmentHeader)); |
495 | else | 485 | if (n == 64) |
496 | mc->bits = (1LL << n) - 1; /* set lowest 'bits' bit */ | 486 | mc->bits = UINT64_MAX; /* set all 64 bit */ |
497 | if (dc->list_size >= dc->num_msgs) | 487 | else |
498 | discard_oldest_mc (dc); | 488 | mc->bits = (1LL << n) - 1; /* set lowest 'bits' bit */ |
499 | GNUNET_CONTAINER_DLL_insert (dc->head, | 489 | if (dc->list_size >= dc->num_msgs) |
500 | dc->tail, | 490 | discard_oldest_mc (dc); |
501 | mc); | 491 | GNUNET_CONTAINER_DLL_insert (dc->head, dc->tail, mc); |
502 | dc->list_size++; | 492 | dc->list_size++; |
503 | } | 493 | } |
504 | 494 | ||
505 | /* copy data to 'mc' */ | 495 | /* copy data to 'mc' */ |
506 | if (0 != (mc->bits & (1LL << bit))) | 496 | if (0 != (mc->bits & (1LL << bit))) |
507 | { | 497 | { |
508 | mc->bits -= 1LL << bit; | 498 | mc->bits -= 1LL << bit; |
509 | mbuf = (char* )&mc[1]; | 499 | mbuf = (char *) &mc[1]; |
510 | memcpy (&mbuf[bit * (dc->mtu - sizeof (struct FragmentHeader))], | 500 | memcpy (&mbuf[bit * (dc->mtu - sizeof (struct FragmentHeader))], |
511 | &fh[1], | 501 | &fh[1], ntohs (msg->size) - sizeof (struct FragmentHeader)); |
512 | ntohs (msg->size) - sizeof (struct FragmentHeader)); | 502 | mc->last_update = now; |
513 | mc->last_update = now; | 503 | if (bit < mc->last_bit) |
514 | if (bit < mc->last_bit) | 504 | mc->frag_times_start_offset = mc->frag_times_write_offset; |
515 | mc->frag_times_start_offset = mc->frag_times_write_offset; | 505 | mc->last_bit = bit; |
516 | mc->last_bit = bit; | 506 | mc->frag_times[mc->frag_times_write_offset].time = now; |
517 | mc->frag_times[mc->frag_times_write_offset].time = now; | 507 | mc->frag_times[mc->frag_times_write_offset].bit = bit; |
518 | mc->frag_times[mc->frag_times_write_offset].bit = bit; | 508 | mc->frag_times_write_offset++; |
519 | mc->frag_times_write_offset++; | 509 | duplicate = GNUNET_NO; |
520 | duplicate = GNUNET_NO; | 510 | } |
521 | } | ||
522 | else | 511 | else |
523 | { | 512 | { |
524 | duplicate = GNUNET_YES; | 513 | duplicate = GNUNET_YES; |
525 | GNUNET_STATISTICS_update (dc->stats, | 514 | GNUNET_STATISTICS_update (dc->stats, |
526 | _("# duplicate fragments received"), | 515 | _("# duplicate fragments received"), |
527 | 1, | 516 | 1, GNUNET_NO); |
528 | GNUNET_NO); | 517 | } |
529 | } | ||
530 | 518 | ||
531 | /* count number of missing fragments */ | 519 | /* count number of missing fragments */ |
532 | bc = 0; | 520 | bc = 0; |
533 | for (b=0;b<64;b++) | 521 | for (b = 0; b < 64; b++) |
534 | if (0 != (mc->bits & (1LL << b))) bc++; | 522 | if (0 != (mc->bits & (1LL << b))) |
523 | bc++; | ||
535 | if (mc->frag_times_write_offset - mc->frag_times_start_offset > 1) | 524 | if (mc->frag_times_write_offset - mc->frag_times_start_offset > 1) |
536 | dc->latency = estimate_latency (mc); | 525 | dc->latency = estimate_latency (mc); |
537 | delay = GNUNET_TIME_relative_multiply (dc->latency, | 526 | delay = GNUNET_TIME_relative_multiply (dc->latency, bc + 1); |
538 | bc + 1); | 527 | if ((0 == mc->bits) || (GNUNET_YES == duplicate)) /* message complete or duplicate, ACK now! */ |
539 | if ( (0 == mc->bits) || (GNUNET_YES == duplicate) ) /* message complete or duplicate, ACK now! */ | ||
540 | delay = GNUNET_TIME_UNIT_ZERO; | 528 | delay = GNUNET_TIME_UNIT_ZERO; |
541 | if (GNUNET_SCHEDULER_NO_TASK != mc->ack_task) | 529 | if (GNUNET_SCHEDULER_NO_TASK != mc->ack_task) |
542 | GNUNET_SCHEDULER_cancel (mc->ack_task); | 530 | GNUNET_SCHEDULER_cancel (mc->ack_task); |
543 | mc->ack_task = GNUNET_SCHEDULER_add_delayed (delay, | 531 | mc->ack_task = GNUNET_SCHEDULER_add_delayed (delay, &send_ack, mc); |
544 | &send_ack, | 532 | if ((duplicate == GNUNET_NO) && (0 == mc->bits)) |
545 | mc); | 533 | { |
546 | if ( (duplicate == GNUNET_NO) && | 534 | GNUNET_STATISTICS_update (dc->stats, |
547 | (0 == mc->bits) ) | 535 | _("# messages defragmented"), 1, GNUNET_NO); |
548 | { | 536 | /* message complete, notify! */ |
549 | GNUNET_STATISTICS_update (dc->stats, | 537 | dc->proc (dc->cls, mc->msg); |
550 | _("# messages defragmented"), | 538 | } |
551 | 1, | ||
552 | GNUNET_NO); | ||
553 | /* message complete, notify! */ | ||
554 | dc->proc (dc->cls, | ||
555 | mc->msg); | ||
556 | } | ||
557 | if (duplicate == GNUNET_YES) | 539 | if (duplicate == GNUNET_YES) |
558 | return GNUNET_NO; | 540 | return GNUNET_NO; |
559 | return GNUNET_YES; | 541 | return GNUNET_YES; |
560 | } | 542 | } |
561 | 543 | ||
562 | /* end of defragmentation.c */ | 544 | /* end of defragmentation.c */ |
563 | |||
diff --git a/src/fragmentation/fragmentation.c b/src/fragmentation/fragmentation.c index 81db1b831..d3483fc8d 100644 --- a/src/fragmentation/fragmentation.c +++ b/src/fragmentation/fragmentation.c | |||
@@ -113,7 +113,7 @@ struct GNUNET_FRAGMENT_Context | |||
113 | * Target fragment size. | 113 | * Target fragment size. |
114 | */ | 114 | */ |
115 | uint16_t mtu; | 115 | uint16_t mtu; |
116 | 116 | ||
117 | }; | 117 | }; |
118 | 118 | ||
119 | 119 | ||
@@ -124,8 +124,7 @@ struct GNUNET_FRAGMENT_Context | |||
124 | * @param tc scheduler context | 124 | * @param tc scheduler context |
125 | */ | 125 | */ |
126 | static void | 126 | static void |
127 | transmit_next (void *cls, | 127 | transmit_next (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) |
128 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
129 | { | 128 | { |
130 | struct GNUNET_FRAGMENT_Context *fc = cls; | 129 | struct GNUNET_FRAGMENT_Context *fc = cls; |
131 | char msg[fc->mtu]; | 130 | char msg[fc->mtu]; |
@@ -140,56 +139,53 @@ transmit_next (void *cls, | |||
140 | fc->task = GNUNET_SCHEDULER_NO_TASK; | 139 | fc->task = GNUNET_SCHEDULER_NO_TASK; |
141 | GNUNET_assert (GNUNET_NO == fc->proc_busy); | 140 | GNUNET_assert (GNUNET_NO == fc->proc_busy); |
142 | if (0 == fc->acks) | 141 | if (0 == fc->acks) |
143 | return; /* all done */ | 142 | return; /* all done */ |
144 | 143 | ||
145 | /* calculate delay */ | 144 | /* calculate delay */ |
146 | wrap = 0; | 145 | wrap = 0; |
147 | while (0 == (fc->acks & (1LL << fc->next_transmission))) | 146 | while (0 == (fc->acks & (1LL << fc->next_transmission))) |
148 | { | 147 | { |
149 | fc->next_transmission = (fc->next_transmission + 1) % 64; | 148 | fc->next_transmission = (fc->next_transmission + 1) % 64; |
150 | wrap |= (fc->next_transmission == 0); | 149 | wrap |= (fc->next_transmission == 0); |
151 | } | 150 | } |
152 | bit = fc->next_transmission; | 151 | bit = fc->next_transmission; |
153 | size = ntohs (fc->msg->size); | 152 | size = ntohs (fc->msg->size); |
154 | if (bit == size / (fc->mtu - sizeof (struct FragmentHeader))) | 153 | if (bit == size / (fc->mtu - sizeof (struct FragmentHeader))) |
155 | fsize = size % (fc->mtu - sizeof (struct FragmentHeader)) + sizeof (struct FragmentHeader); | 154 | fsize = |
155 | size % (fc->mtu - sizeof (struct FragmentHeader)) + | ||
156 | sizeof (struct FragmentHeader); | ||
156 | else | 157 | else |
157 | fsize = fc->mtu; | 158 | fsize = fc->mtu; |
158 | if (fc->tracker != NULL) | 159 | if (fc->tracker != NULL) |
159 | delay = GNUNET_BANDWIDTH_tracker_get_delay (fc->tracker, | 160 | delay = GNUNET_BANDWIDTH_tracker_get_delay (fc->tracker, fsize); |
160 | fsize); | ||
161 | else | 161 | else |
162 | delay = GNUNET_TIME_UNIT_ZERO; | 162 | delay = GNUNET_TIME_UNIT_ZERO; |
163 | if (delay.rel_value > 0) | 163 | if (delay.rel_value > 0) |
164 | { | 164 | { |
165 | fc->task = GNUNET_SCHEDULER_add_delayed (delay, | 165 | fc->task = GNUNET_SCHEDULER_add_delayed (delay, &transmit_next, fc); |
166 | &transmit_next, | 166 | return; |
167 | fc); | 167 | } |
168 | return; | ||
169 | } | ||
170 | fc->next_transmission = (fc->next_transmission + 1) % 64; | 168 | fc->next_transmission = (fc->next_transmission + 1) % 64; |
171 | wrap |= (fc->next_transmission == 0); | 169 | wrap |= (fc->next_transmission == 0); |
172 | 170 | ||
173 | /* assemble fragmentation message */ | 171 | /* assemble fragmentation message */ |
174 | mbuf = (const char*) &fc[1]; | 172 | mbuf = (const char *) &fc[1]; |
175 | fh = (struct FragmentHeader*) msg; | 173 | fh = (struct FragmentHeader *) msg; |
176 | fh->header.size = htons (fsize); | 174 | fh->header.size = htons (fsize); |
177 | fh->header.type = htons (GNUNET_MESSAGE_TYPE_FRAGMENT); | 175 | fh->header.type = htons (GNUNET_MESSAGE_TYPE_FRAGMENT); |
178 | fh->fragment_id = htonl (fc->fragment_id); | 176 | fh->fragment_id = htonl (fc->fragment_id); |
179 | fh->total_size = fc->msg->size; /* already in big-endian */ | 177 | fh->total_size = fc->msg->size; /* already in big-endian */ |
180 | fh->offset = htons ((fc->mtu - sizeof (struct FragmentHeader)) * bit); | 178 | fh->offset = htons ((fc->mtu - sizeof (struct FragmentHeader)) * bit); |
181 | memcpy (&fh[1], | 179 | memcpy (&fh[1], |
182 | &mbuf[bit * (fc->mtu - sizeof (struct FragmentHeader))], | 180 | &mbuf[bit * (fc->mtu - sizeof (struct FragmentHeader))], |
183 | fsize - sizeof (struct FragmentHeader)); | 181 | fsize - sizeof (struct FragmentHeader)); |
184 | if (NULL != fc->tracker) | 182 | if (NULL != fc->tracker) |
185 | GNUNET_BANDWIDTH_tracker_consume (fc->tracker, fsize); | 183 | GNUNET_BANDWIDTH_tracker_consume (fc->tracker, fsize); |
186 | GNUNET_STATISTICS_update (fc->stats, | 184 | GNUNET_STATISTICS_update (fc->stats, |
187 | _("# fragments transmitted"), | 185 | _("# fragments transmitted"), 1, GNUNET_NO); |
188 | 1, GNUNET_NO); | ||
189 | if (0 != fc->last_round.abs_value) | 186 | if (0 != fc->last_round.abs_value) |
190 | GNUNET_STATISTICS_update (fc->stats, | 187 | GNUNET_STATISTICS_update (fc->stats, |
191 | _("# fragments retransmitted"), | 188 | _("# fragments retransmitted"), 1, GNUNET_NO); |
192 | 1, GNUNET_NO); | ||
193 | 189 | ||
194 | /* select next message to calculate delay */ | 190 | /* select next message to calculate delay */ |
195 | bit = fc->next_transmission; | 191 | bit = fc->next_transmission; |
@@ -199,21 +195,19 @@ transmit_next (void *cls, | |||
199 | else | 195 | else |
200 | fsize = fc->mtu; | 196 | fsize = fc->mtu; |
201 | if (NULL != fc->tracker) | 197 | if (NULL != fc->tracker) |
202 | delay = GNUNET_BANDWIDTH_tracker_get_delay (fc->tracker, | 198 | delay = GNUNET_BANDWIDTH_tracker_get_delay (fc->tracker, fsize); |
203 | fsize); | ||
204 | else | 199 | else |
205 | delay = GNUNET_TIME_UNIT_ZERO; | 200 | delay = GNUNET_TIME_UNIT_ZERO; |
206 | if (wrap) | 201 | if (wrap) |
207 | { | 202 | { |
208 | /* full round transmitted wait 2x delay for ACK before going again */ | 203 | /* full round transmitted wait 2x delay for ACK before going again */ |
209 | delay = GNUNET_TIME_relative_max (GNUNET_TIME_relative_multiply (delay, 2), | 204 | delay = GNUNET_TIME_relative_max (GNUNET_TIME_relative_multiply (delay, 2), |
210 | fc->delay); | 205 | fc->delay); |
211 | /* never use zero, need some time for ACK always */ | 206 | /* never use zero, need some time for ACK always */ |
212 | delay = GNUNET_TIME_relative_max (GNUNET_TIME_UNIT_MILLISECONDS, | 207 | delay = GNUNET_TIME_relative_max (GNUNET_TIME_UNIT_MILLISECONDS, delay); |
213 | delay); | 208 | fc->last_round = GNUNET_TIME_absolute_get (); |
214 | fc->last_round = GNUNET_TIME_absolute_get (); | 209 | fc->wack = GNUNET_YES; |
215 | fc->wack = GNUNET_YES; | 210 | } |
216 | } | ||
217 | fc->proc_busy = GNUNET_YES; | 211 | fc->proc_busy = GNUNET_YES; |
218 | fc->delay_until = GNUNET_TIME_relative_to_absolute (delay); | 212 | fc->delay_until = GNUNET_TIME_relative_to_absolute (delay); |
219 | fc->proc (fc->proc_cls, &fh->header); | 213 | fc->proc (fc->proc_cls, &fh->header); |
@@ -240,46 +234,46 @@ transmit_next (void *cls, | |||
240 | */ | 234 | */ |
241 | struct GNUNET_FRAGMENT_Context * | 235 | struct GNUNET_FRAGMENT_Context * |
242 | GNUNET_FRAGMENT_context_create (struct GNUNET_STATISTICS_Handle *stats, | 236 | GNUNET_FRAGMENT_context_create (struct GNUNET_STATISTICS_Handle *stats, |
243 | uint16_t mtu, | 237 | uint16_t mtu, |
244 | struct GNUNET_BANDWIDTH_Tracker *tracker, | 238 | struct GNUNET_BANDWIDTH_Tracker *tracker, |
245 | struct GNUNET_TIME_Relative delay, | 239 | struct GNUNET_TIME_Relative delay, |
246 | const struct GNUNET_MessageHeader *msg, | 240 | const struct GNUNET_MessageHeader *msg, |
247 | GNUNET_FRAGMENT_MessageProcessor proc, | 241 | GNUNET_FRAGMENT_MessageProcessor proc, |
248 | void *proc_cls) | 242 | void *proc_cls) |
249 | { | 243 | { |
250 | struct GNUNET_FRAGMENT_Context *fc; | 244 | struct GNUNET_FRAGMENT_Context *fc; |
251 | size_t size; | 245 | size_t size; |
252 | uint64_t bits; | 246 | uint64_t bits; |
253 | 247 | ||
254 | GNUNET_STATISTICS_update (stats, | 248 | GNUNET_STATISTICS_update (stats, _("# messages fragmented"), 1, GNUNET_NO); |
255 | _("# messages fragmented"), | ||
256 | 1, GNUNET_NO); | ||
257 | GNUNET_assert (mtu >= 1024 + sizeof (struct FragmentHeader)); | 249 | GNUNET_assert (mtu >= 1024 + sizeof (struct FragmentHeader)); |
258 | size = ntohs (msg->size); | 250 | size = ntohs (msg->size); |
259 | GNUNET_STATISTICS_update (stats, | 251 | GNUNET_STATISTICS_update (stats, |
260 | _("# total size of fragmented messages"), | 252 | _("# total size of fragmented messages"), |
261 | size, GNUNET_NO); | 253 | size, GNUNET_NO); |
262 | GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader)); | 254 | GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader)); |
263 | fc = GNUNET_malloc (sizeof (struct GNUNET_FRAGMENT_Context) + size); | 255 | fc = GNUNET_malloc (sizeof (struct GNUNET_FRAGMENT_Context) + size); |
264 | fc->stats = stats; | 256 | fc->stats = stats; |
265 | fc->mtu = mtu; | 257 | fc->mtu = mtu; |
266 | fc->tracker = tracker; | 258 | fc->tracker = tracker; |
267 | fc->delay = delay; | 259 | fc->delay = delay; |
268 | fc->msg = (const struct GNUNET_MessageHeader*)&fc[1]; | 260 | fc->msg = (const struct GNUNET_MessageHeader *) &fc[1]; |
269 | fc->proc = proc; | 261 | fc->proc = proc; |
270 | fc->proc_cls = proc_cls; | 262 | fc->proc_cls = proc_cls; |
271 | fc->fragment_id = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, | 263 | fc->fragment_id = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, |
272 | UINT32_MAX); | 264 | UINT32_MAX); |
273 | memcpy (&fc[1], msg, size); | 265 | memcpy (&fc[1], msg, size); |
274 | bits = (size + mtu - sizeof (struct FragmentHeader) - 1) / (mtu - sizeof (struct FragmentHeader)); | 266 | bits = |
267 | (size + mtu - sizeof (struct FragmentHeader) - 1) / (mtu - | ||
268 | sizeof (struct | ||
269 | FragmentHeader)); | ||
275 | GNUNET_assert (bits <= 64); | 270 | GNUNET_assert (bits <= 64); |
276 | if (bits == 64) | 271 | if (bits == 64) |
277 | fc->acks_mask = UINT64_MAX; /* set all 64 bit */ | 272 | fc->acks_mask = UINT64_MAX; /* set all 64 bit */ |
278 | else | 273 | else |
279 | fc->acks_mask = (1LL << bits) - 1; /* set lowest 'bits' bit */ | 274 | fc->acks_mask = (1LL << bits) - 1; /* set lowest 'bits' bit */ |
280 | fc->acks = fc->acks_mask; | 275 | fc->acks = fc->acks_mask; |
281 | fc->task = GNUNET_SCHEDULER_add_now (&transmit_next, | 276 | fc->task = GNUNET_SCHEDULER_add_now (&transmit_next, fc); |
282 | fc); | ||
283 | return fc; | 277 | return fc; |
284 | } | 278 | } |
285 | 279 | ||
@@ -297,9 +291,9 @@ GNUNET_FRAGMENT_context_transmission_done (struct GNUNET_FRAGMENT_Context *fc) | |||
297 | GNUNET_assert (fc->proc_busy == GNUNET_YES); | 291 | GNUNET_assert (fc->proc_busy == GNUNET_YES); |
298 | fc->proc_busy = GNUNET_NO; | 292 | fc->proc_busy = GNUNET_NO; |
299 | GNUNET_assert (fc->task == GNUNET_SCHEDULER_NO_TASK); | 293 | GNUNET_assert (fc->task == GNUNET_SCHEDULER_NO_TASK); |
300 | fc->task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining (fc->delay_until), | 294 | fc->task = |
301 | &transmit_next, | 295 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining |
302 | fc); | 296 | (fc->delay_until), &transmit_next, fc); |
303 | } | 297 | } |
304 | 298 | ||
305 | 299 | ||
@@ -314,72 +308,68 @@ GNUNET_FRAGMENT_context_transmission_done (struct GNUNET_FRAGMENT_Context *fc) | |||
314 | * GNUNET_NO if more messages are pending | 308 | * GNUNET_NO if more messages are pending |
315 | * GNUNET_SYSERR if this ack is not valid for this fc | 309 | * GNUNET_SYSERR if this ack is not valid for this fc |
316 | */ | 310 | */ |
317 | int | 311 | int |
318 | GNUNET_FRAGMENT_process_ack (struct GNUNET_FRAGMENT_Context *fc, | 312 | GNUNET_FRAGMENT_process_ack (struct GNUNET_FRAGMENT_Context *fc, |
319 | const struct GNUNET_MessageHeader *msg) | 313 | const struct GNUNET_MessageHeader *msg) |
320 | { | 314 | { |
321 | const struct FragmentAcknowledgement *fa; | 315 | const struct FragmentAcknowledgement *fa; |
322 | uint64_t abits; | 316 | uint64_t abits; |
323 | struct GNUNET_TIME_Relative ndelay; | 317 | struct GNUNET_TIME_Relative ndelay; |
324 | 318 | ||
325 | if (sizeof (struct FragmentAcknowledgement) != | 319 | if (sizeof (struct FragmentAcknowledgement) != ntohs (msg->size)) |
326 | ntohs (msg->size)) | 320 | { |
327 | { | 321 | GNUNET_break_op (0); |
328 | GNUNET_break_op (0); | 322 | return GNUNET_SYSERR; |
329 | return GNUNET_SYSERR; | 323 | } |
330 | } | ||
331 | fa = (const struct FragmentAcknowledgement *) msg; | 324 | fa = (const struct FragmentAcknowledgement *) msg; |
332 | if (ntohl (fa->fragment_id) != fc->fragment_id) | 325 | if (ntohl (fa->fragment_id) != fc->fragment_id) |
333 | return GNUNET_SYSERR; /* not our ACK */ | 326 | return GNUNET_SYSERR; /* not our ACK */ |
334 | abits = GNUNET_ntohll (fa->bits); | 327 | abits = GNUNET_ntohll (fa->bits); |
335 | if (GNUNET_YES == fc->wack) | 328 | if (GNUNET_YES == fc->wack) |
336 | { | 329 | { |
337 | /* normal ACK, can update running average of delay... */ | 330 | /* normal ACK, can update running average of delay... */ |
338 | fc->wack = GNUNET_NO; | 331 | fc->wack = GNUNET_NO; |
339 | ndelay = GNUNET_TIME_absolute_get_duration (fc->last_round); | 332 | ndelay = GNUNET_TIME_absolute_get_duration (fc->last_round); |
340 | fc->delay.rel_value = (ndelay.rel_value + 3 * fc->delay.rel_value) / 4; | 333 | fc->delay.rel_value = (ndelay.rel_value + 3 * fc->delay.rel_value) / 4; |
341 | } | 334 | } |
342 | GNUNET_STATISTICS_update (fc->stats, | 335 | GNUNET_STATISTICS_update (fc->stats, |
343 | _("# fragment acknowledgements received"), | 336 | _("# fragment acknowledgements received"), |
344 | 1, | 337 | 1, GNUNET_NO); |
345 | GNUNET_NO); | ||
346 | if (abits != (fc->acks & abits)) | 338 | if (abits != (fc->acks & abits)) |
347 | { | 339 | { |
348 | /* ID collission or message reordering, count! This should be rare! */ | 340 | /* ID collission or message reordering, count! This should be rare! */ |
349 | GNUNET_STATISTICS_update (fc->stats, | 341 | GNUNET_STATISTICS_update (fc->stats, |
350 | _("# bits removed from fragmentation ACKs"), | 342 | _("# bits removed from fragmentation ACKs"), |
351 | 1, GNUNET_NO); | 343 | 1, GNUNET_NO); |
352 | } | 344 | } |
353 | fc->acks = abits & fc->acks_mask; | 345 | fc->acks = abits & fc->acks_mask; |
354 | if (0 != fc->acks) | 346 | if (0 != fc->acks) |
347 | { | ||
348 | /* more to transmit, do so right now (if tracker permits...) */ | ||
349 | if (fc->task != GNUNET_SCHEDULER_NO_TASK) | ||
350 | { | ||
351 | /* schedule next transmission now, no point in waiting... */ | ||
352 | GNUNET_SCHEDULER_cancel (fc->task); | ||
353 | fc->task = GNUNET_SCHEDULER_add_now (&transmit_next, fc); | ||
354 | } | ||
355 | else | ||
355 | { | 356 | { |
356 | /* more to transmit, do so right now (if tracker permits...) */ | 357 | /* only case where there is no task should be if we're waiting |
357 | if (fc->task != GNUNET_SCHEDULER_NO_TASK) | 358 | * for the right to transmit again (proc_busy set to YES) */ |
358 | { | 359 | GNUNET_assert (GNUNET_YES == fc->proc_busy); |
359 | /* schedule next transmission now, no point in waiting... */ | ||
360 | GNUNET_SCHEDULER_cancel (fc->task); | ||
361 | fc->task = GNUNET_SCHEDULER_add_now (&transmit_next, | ||
362 | fc); | ||
363 | } | ||
364 | else | ||
365 | { | ||
366 | /* only case where there is no task should be if we're waiting | ||
367 | for the right to transmit again (proc_busy set to YES) */ | ||
368 | GNUNET_assert (GNUNET_YES == fc->proc_busy); | ||
369 | } | ||
370 | return GNUNET_NO; | ||
371 | } | 360 | } |
361 | return GNUNET_NO; | ||
362 | } | ||
372 | 363 | ||
373 | /* all done */ | 364 | /* all done */ |
374 | GNUNET_STATISTICS_update (fc->stats, | 365 | GNUNET_STATISTICS_update (fc->stats, |
375 | _("# fragmentation transmissions completed"), | 366 | _("# fragmentation transmissions completed"), |
376 | 1, | 367 | 1, GNUNET_NO); |
377 | GNUNET_NO); | ||
378 | if (fc->task != GNUNET_SCHEDULER_NO_TASK) | 368 | if (fc->task != GNUNET_SCHEDULER_NO_TASK) |
379 | { | 369 | { |
380 | GNUNET_SCHEDULER_cancel (fc->task); | 370 | GNUNET_SCHEDULER_cancel (fc->task); |
381 | fc->task = GNUNET_SCHEDULER_NO_TASK; | 371 | fc->task = GNUNET_SCHEDULER_NO_TASK; |
382 | } | 372 | } |
383 | return GNUNET_OK; | 373 | return GNUNET_OK; |
384 | } | 374 | } |
385 | 375 | ||
@@ -406,4 +396,3 @@ GNUNET_FRAGMENT_context_destroy (struct GNUNET_FRAGMENT_Context *fc) | |||
406 | 396 | ||
407 | 397 | ||
408 | /* end of fragmentation.c */ | 398 | /* end of fragmentation.c */ |
409 | |||
diff --git a/src/fragmentation/test_fragmentation.c b/src/fragmentation/test_fragmentation.c index 25f1c2053..b534a134e 100644 --- a/src/fragmentation/test_fragmentation.c +++ b/src/fragmentation/test_fragmentation.c | |||
@@ -44,7 +44,7 @@ | |||
44 | */ | 44 | */ |
45 | #define DROPRATE 10 | 45 | #define DROPRATE 10 |
46 | 46 | ||
47 | static int ret = 1; | 47 | static int ret = 1; |
48 | 48 | ||
49 | static unsigned int dups; | 49 | static unsigned int dups; |
50 | 50 | ||
@@ -63,18 +63,17 @@ static struct GNUNET_BANDWIDTH_Tracker trackers[NUM_MSGS]; | |||
63 | static struct GNUNET_FRAGMENT_Context *frags[NUM_MSGS]; | 63 | static struct GNUNET_FRAGMENT_Context *frags[NUM_MSGS]; |
64 | 64 | ||
65 | static void | 65 | static void |
66 | proc_msgs (void *cls, | 66 | proc_msgs (void *cls, const struct GNUNET_MessageHeader *hdr) |
67 | const struct GNUNET_MessageHeader *hdr) | ||
68 | { | 67 | { |
69 | static unsigned int total; | 68 | static unsigned int total; |
70 | unsigned int i; | 69 | unsigned int i; |
71 | const char *buf; | 70 | const char *buf; |
72 | 71 | ||
73 | #if DETAILS | 72 | #if DETAILS |
74 | fprintf (stderr, "!"); /* message complete, good! */ | 73 | fprintf (stderr, "!"); /* message complete, good! */ |
75 | #endif | 74 | #endif |
76 | buf = (const char*) hdr; | 75 | buf = (const char *) hdr; |
77 | for (i=sizeof (struct GNUNET_MessageHeader);i<ntohs(hdr->size);i++) | 76 | for (i = sizeof (struct GNUNET_MessageHeader); i < ntohs (hdr->size); i++) |
78 | GNUNET_assert (buf[i] == (char) i); | 77 | GNUNET_assert (buf[i] == (char) i); |
79 | total++; | 78 | total++; |
80 | #if ! DETAILS | 79 | #if ! DETAILS |
@@ -83,18 +82,18 @@ proc_msgs (void *cls, | |||
83 | #endif | 82 | #endif |
84 | /* tolerate 10% loss, i.e. due to duplicate fragment IDs */ | 83 | /* tolerate 10% loss, i.e. due to duplicate fragment IDs */ |
85 | if (total >= NUM_MSGS - (NUM_MSGS / 10)) | 84 | if (total >= NUM_MSGS - (NUM_MSGS / 10)) |
85 | { | ||
86 | ret = 0; | ||
87 | GNUNET_DEFRAGMENT_context_destroy (defrag); | ||
88 | defrag = NULL; | ||
89 | for (i = 0; i < NUM_MSGS; i++) | ||
86 | { | 90 | { |
87 | ret = 0; | 91 | if (frags[i] == NULL) |
88 | GNUNET_DEFRAGMENT_context_destroy (defrag); | 92 | continue; |
89 | defrag = NULL; | 93 | GNUNET_FRAGMENT_context_destroy (frags[i]); |
90 | for (i=0;i<NUM_MSGS;i++) | 94 | frags[i] = NULL; |
91 | { | ||
92 | if (frags[i] == NULL) | ||
93 | continue; | ||
94 | GNUNET_FRAGMENT_context_destroy (frags[i]); | ||
95 | frags[i] = NULL; | ||
96 | } | ||
97 | } | 95 | } |
96 | } | ||
98 | } | 97 | } |
99 | 98 | ||
100 | 99 | ||
@@ -102,45 +101,42 @@ proc_msgs (void *cls, | |||
102 | * Process ACK (by passing to fragmenter) | 101 | * Process ACK (by passing to fragmenter) |
103 | */ | 102 | */ |
104 | static void | 103 | static void |
105 | proc_acks (void *cls, | 104 | proc_acks (void *cls, uint32_t msg_id, const struct GNUNET_MessageHeader *hdr) |
106 | uint32_t msg_id, | ||
107 | const struct GNUNET_MessageHeader *hdr) | ||
108 | { | 105 | { |
109 | unsigned int i; | 106 | unsigned int i; |
110 | int ret; | 107 | int ret; |
111 | 108 | ||
112 | if (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, DROPRATE)) | 109 | if (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, DROPRATE)) |
113 | { | 110 | { |
114 | ack_drops++; | 111 | ack_drops++; |
115 | return; /* random drop */ | 112 | return; /* random drop */ |
116 | } | 113 | } |
117 | for (i=0;i<NUM_MSGS;i++) | 114 | for (i = 0; i < NUM_MSGS; i++) |
115 | { | ||
116 | if (frags[i] == NULL) | ||
117 | continue; | ||
118 | ret = GNUNET_FRAGMENT_process_ack (frags[i], hdr); | ||
119 | if (ret == GNUNET_OK) | ||
118 | { | 120 | { |
119 | if (frags[i] == NULL) | ||
120 | continue; | ||
121 | ret = GNUNET_FRAGMENT_process_ack (frags[i], | ||
122 | hdr); | ||
123 | if (ret == GNUNET_OK) | ||
124 | { | ||
125 | #if DETAILS | 121 | #if DETAILS |
126 | fprintf (stderr, "@"); /* good ACK */ | 122 | fprintf (stderr, "@"); /* good ACK */ |
127 | #endif | 123 | #endif |
128 | GNUNET_FRAGMENT_context_destroy (frags[i]); | 124 | GNUNET_FRAGMENT_context_destroy (frags[i]); |
129 | frags[i] = NULL; | 125 | frags[i] = NULL; |
130 | acks++; | 126 | acks++; |
131 | return; | 127 | return; |
132 | } | 128 | } |
133 | if (ret == GNUNET_NO) | 129 | if (ret == GNUNET_NO) |
134 | { | 130 | { |
135 | #if DETAILS | 131 | #if DETAILS |
136 | fprintf (stderr, "@"); /* good ACK */ | 132 | fprintf (stderr, "@"); /* good ACK */ |
137 | #endif | 133 | #endif |
138 | acks++; | 134 | acks++; |
139 | return; | 135 | return; |
140 | } | ||
141 | } | 136 | } |
137 | } | ||
142 | #if DETAILS | 138 | #if DETAILS |
143 | fprintf (stderr, "_"); /* BAD: ack that nobody feels responsible for... */ | 139 | fprintf (stderr, "_"); /* BAD: ack that nobody feels responsible for... */ |
144 | #endif | 140 | #endif |
145 | } | 141 | } |
146 | 142 | ||
@@ -149,38 +145,37 @@ proc_acks (void *cls, | |||
149 | * Process fragment (by passing to defrag). | 145 | * Process fragment (by passing to defrag). |
150 | */ | 146 | */ |
151 | static void | 147 | static void |
152 | proc_frac (void *cls, | 148 | proc_frac (void *cls, const struct GNUNET_MessageHeader *hdr) |
153 | const struct GNUNET_MessageHeader *hdr) | ||
154 | { | 149 | { |
155 | struct GNUNET_FRAGMENT_Context **fc = cls; | 150 | struct GNUNET_FRAGMENT_Context **fc = cls; |
156 | int ret; | 151 | int ret; |
157 | 152 | ||
158 | GNUNET_FRAGMENT_context_transmission_done (*fc); | 153 | GNUNET_FRAGMENT_context_transmission_done (*fc); |
159 | if (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, DROPRATE)) | 154 | if (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, DROPRATE)) |
160 | { | 155 | { |
161 | frag_drops++; | 156 | frag_drops++; |
162 | return; /* random drop */ | 157 | return; /* random drop */ |
163 | } | 158 | } |
164 | if (NULL == defrag) | 159 | if (NULL == defrag) |
165 | { | 160 | { |
166 | fprintf (stderr, "E"); /* Error: frag after shutdown!? */ | 161 | fprintf (stderr, "E"); /* Error: frag after shutdown!? */ |
167 | return; | 162 | return; |
168 | } | 163 | } |
169 | ret = GNUNET_DEFRAGMENT_process_fragment (defrag, hdr); | 164 | ret = GNUNET_DEFRAGMENT_process_fragment (defrag, hdr); |
170 | if (ret == GNUNET_NO) | 165 | if (ret == GNUNET_NO) |
171 | { | 166 | { |
172 | #if DETAILS | 167 | #if DETAILS |
173 | fprintf (stderr, "?"); /* duplicate fragment */ | 168 | fprintf (stderr, "?"); /* duplicate fragment */ |
174 | #endif | 169 | #endif |
175 | dups++; | 170 | dups++; |
176 | } | 171 | } |
177 | else if (ret == GNUNET_OK) | 172 | else if (ret == GNUNET_OK) |
178 | { | 173 | { |
179 | #if DETAILS | 174 | #if DETAILS |
180 | fprintf (stderr, "."); /* good fragment */ | 175 | fprintf (stderr, "."); /* good fragment */ |
181 | #endif | 176 | #endif |
182 | fragc++; | 177 | fragc++; |
183 | } | 178 | } |
184 | } | 179 | } |
185 | 180 | ||
186 | 181 | ||
@@ -196,27 +191,22 @@ run (void *cls, | |||
196 | struct GNUNET_MessageHeader *msg; | 191 | struct GNUNET_MessageHeader *msg; |
197 | char buf[MTU + 32 * 1024]; | 192 | char buf[MTU + 32 * 1024]; |
198 | 193 | ||
199 | defrag = GNUNET_DEFRAGMENT_context_create (NULL, | 194 | defrag = GNUNET_DEFRAGMENT_context_create (NULL, MTU, NUM_MSGS /* enough space for all */ |
200 | MTU, | 195 | , NULL, &proc_msgs, &proc_acks); |
201 | NUM_MSGS /* enough space for all */, | 196 | for (i = 0; i < sizeof (buf); i++) |
202 | NULL, | ||
203 | &proc_msgs, | ||
204 | &proc_acks); | ||
205 | for (i=0;i<sizeof(buf);i++) | ||
206 | buf[i] = (char) i; | 197 | buf[i] = (char) i; |
207 | msg = (struct GNUNET_MessageHeader* ) buf; | 198 | msg = (struct GNUNET_MessageHeader *) buf; |
208 | for (i=0;i<NUM_MSGS;i++) | 199 | for (i = 0; i < NUM_MSGS; i++) |
209 | { | 200 | { |
210 | msg->type = htons ((uint16_t) i); | 201 | msg->type = htons ((uint16_t) i); |
211 | msg->size = htons (sizeof (struct GNUNET_MessageHeader) + (17 * i) % (32 * 1024)); | 202 | msg->size = |
212 | frags[i] = GNUNET_FRAGMENT_context_create (NULL /* no stats */, | 203 | htons (sizeof (struct GNUNET_MessageHeader) + (17 * i) % (32 * 1024)); |
213 | MTU, | 204 | frags[i] = GNUNET_FRAGMENT_context_create (NULL /* no stats */ , |
214 | &trackers[i], | 205 | MTU, |
215 | GNUNET_TIME_UNIT_SECONDS, | 206 | &trackers[i], |
216 | msg, | 207 | GNUNET_TIME_UNIT_SECONDS, |
217 | &proc_frac, | 208 | msg, &proc_frac, &frags[i]); |
218 | &frags[i]); | 209 | } |
219 | } | ||
220 | } | 210 | } |
221 | 211 | ||
222 | 212 | ||
@@ -247,16 +237,14 @@ main (int argc, char *argv[]) | |||
247 | "WARNING", | 237 | "WARNING", |
248 | #endif | 238 | #endif |
249 | NULL); | 239 | NULL); |
250 | for (i=0;i<NUM_MSGS;i++) | 240 | for (i = 0; i < NUM_MSGS; i++) |
251 | GNUNET_BANDWIDTH_tracker_init (&trackers[i], | 241 | GNUNET_BANDWIDTH_tracker_init (&trackers[i], |
252 | GNUNET_BANDWIDTH_value_init ((i+1) * 1024), | 242 | GNUNET_BANDWIDTH_value_init ((i + 1) * 1024), |
253 | 100); | 243 | 100); |
254 | GNUNET_PROGRAM_run (5, argv_prog, "test-fragmentation", "nohelp", options, &run, NULL); | 244 | GNUNET_PROGRAM_run (5, argv_prog, "test-fragmentation", "nohelp", options, |
255 | fprintf (stderr, | 245 | &run, NULL); |
256 | "\nHad %u good fragments, %u duplicate fragments, %u acks and %u simulated drops of acks\n", | 246 | fprintf (stderr, |
257 | fragc, | 247 | "\nHad %u good fragments, %u duplicate fragments, %u acks and %u simulated drops of acks\n", |
258 | dups, | 248 | fragc, dups, acks, ack_drops); |
259 | acks, | ||
260 | ack_drops); | ||
261 | return ret; | 249 | return ret; |
262 | } | 250 | } |