aboutsummaryrefslogtreecommitdiff
path: root/src/fragmentation/fragmentation.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fragmentation/fragmentation.c')
-rw-r--r--src/fragmentation/fragmentation.c393
1 files changed, 199 insertions, 194 deletions
diff --git a/src/fragmentation/fragmentation.c b/src/fragmentation/fragmentation.c
index 5f31f9094..3a7da37e8 100644
--- a/src/fragmentation/fragmentation.c
+++ b/src/fragmentation/fragmentation.c
@@ -31,13 +31,15 @@
31/** 31/**
32 * Absolute minimum delay we impose between sending and expecting ACK to arrive. 32 * Absolute minimum delay we impose between sending and expecting ACK to arrive.
33 */ 33 */
34#define MIN_ACK_DELAY GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 1) 34#define MIN_ACK_DELAY GNUNET_TIME_relative_multiply ( \
35 GNUNET_TIME_UNIT_MILLISECONDS, 1)
35 36
36 37
37/** 38/**
38 * Fragmentation context. 39 * Fragmentation context.
39 */ 40 */
40struct GNUNET_FRAGMENT_Context { 41struct GNUNET_FRAGMENT_Context
42{
41 /** 43 /**
42 * Statistics to use. 44 * Statistics to use.
43 */ 45 */
@@ -143,20 +145,20 @@ struct GNUNET_FRAGMENT_Context {
143 * @return ack in human-readable format 145 * @return ack in human-readable format
144 */ 146 */
145const char * 147const char *
146GNUNET_FRAGMENT_print_ack(const struct GNUNET_MessageHeader *ack) 148GNUNET_FRAGMENT_print_ack (const struct GNUNET_MessageHeader *ack)
147{ 149{
148 static char buf[128]; 150 static char buf[128];
149 const struct FragmentAcknowledgement *fa; 151 const struct FragmentAcknowledgement *fa;
150 152
151 if (sizeof(struct FragmentAcknowledgement) != 153 if (sizeof(struct FragmentAcknowledgement) !=
152 htons(ack->size)) 154 htons (ack->size))
153 return "<malformed ack>"; 155 return "<malformed ack>";
154 fa = (const struct FragmentAcknowledgement *)ack; 156 fa = (const struct FragmentAcknowledgement *) ack;
155 GNUNET_snprintf(buf, 157 GNUNET_snprintf (buf,
156 sizeof(buf), 158 sizeof(buf),
157 "%u-%llX", 159 "%u-%llX",
158 ntohl(fa->fragment_id), 160 ntohl (fa->fragment_id),
159 GNUNET_ntohll(fa->bits)); 161 GNUNET_ntohll (fa->bits));
160 return buf; 162 return buf;
161} 163}
162 164
@@ -167,7 +169,7 @@ GNUNET_FRAGMENT_print_ack(const struct GNUNET_MessageHeader *ack)
167 * @param cls the `struct GNUNET_FRAGMENT_Context` 169 * @param cls the `struct GNUNET_FRAGMENT_Context`
168 */ 170 */
169static void 171static void
170transmit_next(void *cls) 172transmit_next (void *cls)
171{ 173{
172 struct GNUNET_FRAGMENT_Context *fc = cls; 174 struct GNUNET_FRAGMENT_Context *fc = cls;
173 char msg[fc->mtu]; 175 char msg[fc->mtu];
@@ -180,108 +182,108 @@ transmit_next(void *cls)
180 int wrap; 182 int wrap;
181 183
182 fc->task = NULL; 184 fc->task = NULL;
183 GNUNET_assert(GNUNET_NO == fc->proc_busy); 185 GNUNET_assert (GNUNET_NO == fc->proc_busy);
184 if (0 == fc->acks) 186 if (0 == fc->acks)
185 return; /* all done */ 187 return; /* all done */
186 /* calculate delay */ 188 /* calculate delay */
187 wrap = 0; 189 wrap = 0;
188 while (0 == (fc->acks & (1LLU << fc->next_transmission))) 190 while (0 == (fc->acks & (1LLU << fc->next_transmission)))
189 { 191 {
190 fc->next_transmission = (fc->next_transmission + 1) % 64; 192 fc->next_transmission = (fc->next_transmission + 1) % 64;
191 wrap |= (0 == fc->next_transmission); 193 wrap |= (0 == fc->next_transmission);
192 } 194 }
193 bit = fc->next_transmission; 195 bit = fc->next_transmission;
194 size = ntohs(fc->msg->size); 196 size = ntohs (fc->msg->size);
195 if (bit == size / (fc->mtu - sizeof(struct FragmentHeader))) 197 if (bit == size / (fc->mtu - sizeof(struct FragmentHeader)))
196 fsize = 198 fsize =
197 (size % (fc->mtu - sizeof(struct FragmentHeader))) + 199 (size % (fc->mtu - sizeof(struct FragmentHeader)))
198 sizeof(struct FragmentHeader); 200 + sizeof(struct FragmentHeader);
199 else 201 else
200 fsize = fc->mtu; 202 fsize = fc->mtu;
201 if (NULL != fc->tracker) 203 if (NULL != fc->tracker)
202 delay = GNUNET_BANDWIDTH_tracker_get_delay(fc->tracker, 204 delay = GNUNET_BANDWIDTH_tracker_get_delay (fc->tracker,
203 fsize); 205 fsize);
204 else 206 else
205 delay = GNUNET_TIME_UNIT_ZERO; 207 delay = GNUNET_TIME_UNIT_ZERO;
206 if (delay.rel_value_us > 0) 208 if (delay.rel_value_us > 0)
207 { 209 {
208 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, 210 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
209 "Fragmentation logic delays transmission of next fragment by %s\n", 211 "Fragmentation logic delays transmission of next fragment by %s\n",
210 GNUNET_STRINGS_relative_time_to_string(delay, 212 GNUNET_STRINGS_relative_time_to_string (delay,
211 GNUNET_YES)); 213 GNUNET_YES));
212 fc->task = GNUNET_SCHEDULER_add_delayed(delay, 214 fc->task = GNUNET_SCHEDULER_add_delayed (delay,
213 &transmit_next, 215 &transmit_next,
214 fc); 216 fc);
215 return; 217 return;
216 } 218 }
217 fc->next_transmission = (fc->next_transmission + 1) % 64; 219 fc->next_transmission = (fc->next_transmission + 1) % 64;
218 wrap |= (0 == fc->next_transmission); 220 wrap |= (0 == fc->next_transmission);
219 while (0 == (fc->acks & (1LLU << fc->next_transmission))) 221 while (0 == (fc->acks & (1LLU << fc->next_transmission)))
220 { 222 {
221 fc->next_transmission = (fc->next_transmission + 1) % 64; 223 fc->next_transmission = (fc->next_transmission + 1) % 64;
222 wrap |= (0 == fc->next_transmission); 224 wrap |= (0 == fc->next_transmission);
223 } 225 }
224 226
225 /* assemble fragmentation message */ 227 /* assemble fragmentation message */
226 mbuf = (const char *)&fc[1]; 228 mbuf = (const char *) &fc[1];
227 fh = (struct FragmentHeader *)msg; 229 fh = (struct FragmentHeader *) msg;
228 fh->header.size = htons(fsize); 230 fh->header.size = htons (fsize);
229 fh->header.type = htons(GNUNET_MESSAGE_TYPE_FRAGMENT); 231 fh->header.type = htons (GNUNET_MESSAGE_TYPE_FRAGMENT);
230 fh->fragment_id = htonl(fc->fragment_id); 232 fh->fragment_id = htonl (fc->fragment_id);
231 fh->total_size = fc->msg->size; /* already in big-endian */ 233 fh->total_size = fc->msg->size; /* already in big-endian */
232 fh->offset = htons((fc->mtu - sizeof(struct FragmentHeader)) * bit); 234 fh->offset = htons ((fc->mtu - sizeof(struct FragmentHeader)) * bit);
233 GNUNET_memcpy(&fh[1], &mbuf[bit * (fc->mtu - sizeof(struct FragmentHeader))], 235 GNUNET_memcpy (&fh[1], &mbuf[bit * (fc->mtu - sizeof(struct FragmentHeader))],
234 fsize - sizeof(struct FragmentHeader)); 236 fsize - sizeof(struct FragmentHeader));
235 if (NULL != fc->tracker) 237 if (NULL != fc->tracker)
236 GNUNET_BANDWIDTH_tracker_consume(fc->tracker, fsize); 238 GNUNET_BANDWIDTH_tracker_consume (fc->tracker, fsize);
237 GNUNET_STATISTICS_update(fc->stats, 239 GNUNET_STATISTICS_update (fc->stats,
238 _("# fragments transmitted"), 240 _ ("# fragments transmitted"),
239 1, 241 1,
240 GNUNET_NO); 242 GNUNET_NO);
241 if (0 != fc->last_round.abs_value_us) 243 if (0 != fc->last_round.abs_value_us)
242 GNUNET_STATISTICS_update(fc->stats, 244 GNUNET_STATISTICS_update (fc->stats,
243 _("# fragments retransmitted"), 245 _ ("# fragments retransmitted"),
244 1, 246 1,
245 GNUNET_NO); 247 GNUNET_NO);
246 248
247 /* select next message to calculate delay */ 249 /* select next message to calculate delay */
248 bit = fc->next_transmission; 250 bit = fc->next_transmission;
249 size = ntohs(fc->msg->size); 251 size = ntohs (fc->msg->size);
250 if (bit == size / (fc->mtu - sizeof(struct FragmentHeader))) 252 if (bit == size / (fc->mtu - sizeof(struct FragmentHeader)))
251 fsize = size % (fc->mtu - sizeof(struct FragmentHeader)); 253 fsize = size % (fc->mtu - sizeof(struct FragmentHeader));
252 else 254 else
253 fsize = fc->mtu; 255 fsize = fc->mtu;
254 if (NULL != fc->tracker) 256 if (NULL != fc->tracker)
255 delay = GNUNET_BANDWIDTH_tracker_get_delay(fc->tracker, 257 delay = GNUNET_BANDWIDTH_tracker_get_delay (fc->tracker,
256 fsize); 258 fsize);
257 else 259 else
258 delay = GNUNET_TIME_UNIT_ZERO; 260 delay = GNUNET_TIME_UNIT_ZERO;
259 if (fc->num_rounds < 64) 261 if (fc->num_rounds < 64)
260 delay = GNUNET_TIME_relative_max(delay, 262 delay = GNUNET_TIME_relative_max (delay,
261 GNUNET_TIME_relative_saturating_multiply 263 GNUNET_TIME_relative_saturating_multiply
262 (fc->msg_delay, 264 (fc->msg_delay,
263 (1ULL << fc->num_rounds))); 265 (1ULL << fc->num_rounds)));
264 else 266 else
265 delay = GNUNET_TIME_UNIT_FOREVER_REL; 267 delay = GNUNET_TIME_UNIT_FOREVER_REL;
266 if (wrap) 268 if (wrap)
267 { 269 {
268 /* full round transmitted wait 2x delay for ACK before going again */ 270 /* full round transmitted wait 2x delay for ACK before going again */
269 fc->num_rounds++; 271 fc->num_rounds++;
270 delay = GNUNET_TIME_relative_saturating_multiply(fc->ack_delay, 2); 272 delay = GNUNET_TIME_relative_saturating_multiply (fc->ack_delay, 2);
271 /* never use zero, need some time for ACK always */ 273 /* never use zero, need some time for ACK always */
272 delay = GNUNET_TIME_relative_max(MIN_ACK_DELAY, delay); 274 delay = GNUNET_TIME_relative_max (MIN_ACK_DELAY, delay);
273 fc->wack = GNUNET_YES; 275 fc->wack = GNUNET_YES;
274 fc->last_round = GNUNET_TIME_absolute_get(); 276 fc->last_round = GNUNET_TIME_absolute_get ();
275 GNUNET_STATISTICS_update(fc->stats, 277 GNUNET_STATISTICS_update (fc->stats,
276 _("# fragments wrap arounds"), 278 _ ("# fragments wrap arounds"),
277 1, 279 1,
278 GNUNET_NO); 280 GNUNET_NO);
279 } 281 }
280 fc->proc_busy = GNUNET_YES; 282 fc->proc_busy = GNUNET_YES;
281 fc->delay_until = GNUNET_TIME_relative_to_absolute(delay); 283 fc->delay_until = GNUNET_TIME_relative_to_absolute (delay);
282 fc->num_transmissions++; 284 fc->num_transmissions++;
283 fc->proc(fc->proc_cls, 285 fc->proc (fc->proc_cls,
284 &fh->header); 286 &fh->header);
285} 287}
286 288
287 289
@@ -306,53 +308,53 @@ transmit_next(void *cls)
306 * @return the fragmentation context 308 * @return the fragmentation context
307 */ 309 */
308struct GNUNET_FRAGMENT_Context * 310struct GNUNET_FRAGMENT_Context *
309GNUNET_FRAGMENT_context_create(struct GNUNET_STATISTICS_Handle *stats, 311GNUNET_FRAGMENT_context_create (struct GNUNET_STATISTICS_Handle *stats,
310 uint16_t mtu, 312 uint16_t mtu,
311 struct GNUNET_BANDWIDTH_Tracker *tracker, 313 struct GNUNET_BANDWIDTH_Tracker *tracker,
312 struct GNUNET_TIME_Relative msg_delay, 314 struct GNUNET_TIME_Relative msg_delay,
313 struct GNUNET_TIME_Relative ack_delay, 315 struct GNUNET_TIME_Relative ack_delay,
314 const struct GNUNET_MessageHeader *msg, 316 const struct GNUNET_MessageHeader *msg,
315 GNUNET_FRAGMENT_MessageProcessor proc, 317 GNUNET_FRAGMENT_MessageProcessor proc,
316 void *proc_cls) 318 void *proc_cls)
317{ 319{
318 struct GNUNET_FRAGMENT_Context *fc; 320 struct GNUNET_FRAGMENT_Context *fc;
319 size_t size; 321 size_t size;
320 uint64_t bits; 322 uint64_t bits;
321 323
322 GNUNET_STATISTICS_update(stats, 324 GNUNET_STATISTICS_update (stats,
323 _("# messages fragmented"), 325 _ ("# messages fragmented"),
324 1, 326 1,
325 GNUNET_NO); 327 GNUNET_NO);
326 GNUNET_assert(mtu >= 1024 + sizeof(struct FragmentHeader)); 328 GNUNET_assert (mtu >= 1024 + sizeof(struct FragmentHeader));
327 size = ntohs(msg->size); 329 size = ntohs (msg->size);
328 GNUNET_STATISTICS_update(stats, 330 GNUNET_STATISTICS_update (stats,
329 _("# total size of fragmented messages"), 331 _ ("# total size of fragmented messages"),
330 size, GNUNET_NO); 332 size, GNUNET_NO);
331 GNUNET_assert(size >= sizeof(struct GNUNET_MessageHeader)); 333 GNUNET_assert (size >= sizeof(struct GNUNET_MessageHeader));
332 fc = GNUNET_malloc(sizeof(struct GNUNET_FRAGMENT_Context) + size); 334 fc = GNUNET_malloc (sizeof(struct GNUNET_FRAGMENT_Context) + size);
333 fc->stats = stats; 335 fc->stats = stats;
334 fc->mtu = mtu; 336 fc->mtu = mtu;
335 fc->tracker = tracker; 337 fc->tracker = tracker;
336 fc->ack_delay = ack_delay; 338 fc->ack_delay = ack_delay;
337 fc->msg_delay = msg_delay; 339 fc->msg_delay = msg_delay;
338 fc->msg = (const struct GNUNET_MessageHeader *)&fc[1]; 340 fc->msg = (const struct GNUNET_MessageHeader *) &fc[1];
339 fc->proc = proc; 341 fc->proc = proc;
340 fc->proc_cls = proc_cls; 342 fc->proc_cls = proc_cls;
341 fc->fragment_id = 343 fc->fragment_id =
342 GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, 344 GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
343 UINT32_MAX); 345 UINT32_MAX);
344 GNUNET_memcpy(&fc[1], msg, size); 346 GNUNET_memcpy (&fc[1], msg, size);
345 bits = 347 bits =
346 (size + mtu - sizeof(struct FragmentHeader) - 1) / (mtu - 348 (size + mtu - sizeof(struct FragmentHeader) - 1) / (mtu
347 sizeof(struct 349 - sizeof(struct
348 FragmentHeader)); 350 FragmentHeader));
349 GNUNET_assert(bits <= 64); 351 GNUNET_assert (bits <= 64);
350 if (bits == 64) 352 if (bits == 64)
351 fc->acks_mask = UINT64_MAX; /* set all 64 bit */ 353 fc->acks_mask = UINT64_MAX; /* set all 64 bit */
352 else 354 else
353 fc->acks_mask = (1LLU << bits) - 1; /* set lowest 'bits' bit */ 355 fc->acks_mask = (1LLU << bits) - 1; /* set lowest 'bits' bit */
354 fc->acks = fc->acks_mask; 356 fc->acks = fc->acks_mask;
355 fc->task = GNUNET_SCHEDULER_add_now(&transmit_next, fc); 357 fc->task = GNUNET_SCHEDULER_add_now (&transmit_next, fc);
356 return fc; 358 return fc;
357} 359}
358 360
@@ -365,15 +367,15 @@ GNUNET_FRAGMENT_context_create(struct GNUNET_STATISTICS_Handle *stats,
365 * @param fc fragmentation context 367 * @param fc fragmentation context
366 */ 368 */
367void 369void
368GNUNET_FRAGMENT_context_transmission_done(struct GNUNET_FRAGMENT_Context *fc) 370GNUNET_FRAGMENT_context_transmission_done (struct GNUNET_FRAGMENT_Context *fc)
369{ 371{
370 GNUNET_assert(fc->proc_busy == GNUNET_YES); 372 GNUNET_assert (fc->proc_busy == GNUNET_YES);
371 fc->proc_busy = GNUNET_NO; 373 fc->proc_busy = GNUNET_NO;
372 GNUNET_assert(fc->task == NULL); 374 GNUNET_assert (fc->task == NULL);
373 fc->task = 375 fc->task =
374 GNUNET_SCHEDULER_add_at(fc->delay_until, 376 GNUNET_SCHEDULER_add_at (fc->delay_until,
375 &transmit_next, 377 &transmit_next,
376 fc); 378 fc);
377} 379}
378 380
379 381
@@ -389,8 +391,8 @@ GNUNET_FRAGMENT_context_transmission_done(struct GNUNET_FRAGMENT_Context *fc)
389 * #GNUNET_SYSERR if this ack is not valid for this fc 391 * #GNUNET_SYSERR if this ack is not valid for this fc
390 */ 392 */
391int 393int
392GNUNET_FRAGMENT_process_ack(struct GNUNET_FRAGMENT_Context *fc, 394GNUNET_FRAGMENT_process_ack (struct GNUNET_FRAGMENT_Context *fc,
393 const struct GNUNET_MessageHeader *msg) 395 const struct GNUNET_MessageHeader *msg)
394{ 396{
395 const struct FragmentAcknowledgement *fa; 397 const struct FragmentAcknowledgement *fa;
396 uint64_t abits; 398 uint64_t abits;
@@ -399,97 +401,100 @@ GNUNET_FRAGMENT_process_ack(struct GNUNET_FRAGMENT_Context *fc,
399 unsigned int snd_cnt; 401 unsigned int snd_cnt;
400 unsigned int i; 402 unsigned int i;
401 403
402 if (sizeof(struct FragmentAcknowledgement) != ntohs(msg->size)) 404 if (sizeof(struct FragmentAcknowledgement) != ntohs (msg->size))
403 { 405 {
404 GNUNET_break_op(0); 406 GNUNET_break_op (0);
405 return GNUNET_SYSERR; 407 return GNUNET_SYSERR;
406 } 408 }
407 fa = (const struct FragmentAcknowledgement *)msg; 409 fa = (const struct FragmentAcknowledgement *) msg;
408 if (ntohl(fa->fragment_id) != fc->fragment_id) 410 if (ntohl (fa->fragment_id) != fc->fragment_id)
409 return GNUNET_SYSERR; /* not our ACK */ 411 return GNUNET_SYSERR; /* not our ACK */
410 abits = GNUNET_ntohll(fa->bits); 412 abits = GNUNET_ntohll (fa->bits);
411 if ((GNUNET_YES == fc->wack) && 413 if ((GNUNET_YES == fc->wack) &&
412 (0 != fc->num_transmissions)) 414 (0 != fc->num_transmissions))
415 {
416 /* normal ACK, can update running average of delay... */
417 fc->wack = GNUNET_NO;
418 ndelay = GNUNET_TIME_absolute_get_duration (fc->last_round);
419 fc->ack_delay.rel_value_us =
420 (ndelay.rel_value_us / fc->num_transmissions + 3
421 * fc->ack_delay.rel_value_us) / 4;
422 /* calculate ratio msg sent vs. msg acked */
423 ack_cnt = 0;
424 snd_cnt = 0;
425 for (i = 0; i < 64; i++)
413 { 426 {
414 /* normal ACK, can update running average of delay... */ 427 if (1 == (fc->acks_mask & (1ULL << i)))
415 fc->wack = GNUNET_NO; 428 {
416 ndelay = GNUNET_TIME_absolute_get_duration(fc->last_round); 429 snd_cnt++;
417 fc->ack_delay.rel_value_us = 430 if (0 == (abits & (1ULL << i)))
418 (ndelay.rel_value_us / fc->num_transmissions + 3 * fc->ack_delay.rel_value_us) / 4; 431 ack_cnt++;
419 /* calculate ratio msg sent vs. msg acked */ 432 }
420 ack_cnt = 0;
421 snd_cnt = 0;
422 for (i = 0; i < 64; i++)
423 {
424 if (1 == (fc->acks_mask & (1ULL << i)))
425 {
426 snd_cnt++;
427 if (0 == (abits & (1ULL << i)))
428 ack_cnt++;
429 }
430 }
431 if (0 == ack_cnt)
432 {
433 /* complete loss */
434 fc->msg_delay = GNUNET_TIME_relative_saturating_multiply(fc->msg_delay,
435 snd_cnt);
436 }
437 else if (snd_cnt > ack_cnt)
438 {
439 /* some loss, slow down proportionally */
440 fc->msg_delay.rel_value_us = ((fc->msg_delay.rel_value_us * ack_cnt) / snd_cnt);
441 }
442 else if (snd_cnt == ack_cnt)
443 {
444 fc->msg_delay.rel_value_us =
445 (ndelay.rel_value_us / fc->num_transmissions + 3 * fc->msg_delay.rel_value_us) / 5;
446 }
447 fc->num_transmissions = 0;
448 fc->msg_delay = GNUNET_TIME_relative_min(fc->msg_delay,
449 GNUNET_TIME_UNIT_SECONDS);
450 fc->ack_delay = GNUNET_TIME_relative_min(fc->ack_delay,
451 GNUNET_TIME_UNIT_SECONDS);
452 } 433 }
453 GNUNET_STATISTICS_update(fc->stats, 434 if (0 == ack_cnt)
454 _("# fragment acknowledgements received"), 435 {
455 1, 436 /* complete loss */
456 GNUNET_NO); 437 fc->msg_delay = GNUNET_TIME_relative_saturating_multiply (fc->msg_delay,
457 if (abits != (fc->acks & abits)) 438 snd_cnt);
439 }
440 else if (snd_cnt > ack_cnt)
441 {
442 /* some loss, slow down proportionally */
443 fc->msg_delay.rel_value_us = ((fc->msg_delay.rel_value_us * ack_cnt)
444 / snd_cnt);
445 }
446 else if (snd_cnt == ack_cnt)
458 { 447 {
459 /* ID collission or message reordering, count! This should be rare! */ 448 fc->msg_delay.rel_value_us =
460 GNUNET_STATISTICS_update(fc->stats, 449 (ndelay.rel_value_us / fc->num_transmissions + 3
461 _("# bits removed from fragmentation ACKs"), 1, 450 * fc->msg_delay.rel_value_us) / 5;
462 GNUNET_NO);
463 } 451 }
452 fc->num_transmissions = 0;
453 fc->msg_delay = GNUNET_TIME_relative_min (fc->msg_delay,
454 GNUNET_TIME_UNIT_SECONDS);
455 fc->ack_delay = GNUNET_TIME_relative_min (fc->ack_delay,
456 GNUNET_TIME_UNIT_SECONDS);
457 }
458 GNUNET_STATISTICS_update (fc->stats,
459 _ ("# fragment acknowledgements received"),
460 1,
461 GNUNET_NO);
462 if (abits != (fc->acks & abits))
463 {
464 /* ID collission or message reordering, count! This should be rare! */
465 GNUNET_STATISTICS_update (fc->stats,
466 _ ("# bits removed from fragmentation ACKs"), 1,
467 GNUNET_NO);
468 }
464 fc->acks = abits & fc->acks_mask; 469 fc->acks = abits & fc->acks_mask;
465 if (0 != fc->acks) 470 if (0 != fc->acks)
471 {
472 /* more to transmit, do so right now (if tracker permits...) */
473 if (fc->task != NULL)
474 {
475 /* schedule next transmission now, no point in waiting... */
476 GNUNET_SCHEDULER_cancel (fc->task);
477 fc->task = GNUNET_SCHEDULER_add_now (&transmit_next, fc);
478 }
479 else
466 { 480 {
467 /* more to transmit, do so right now (if tracker permits...) */ 481 /* only case where there is no task should be if we're waiting
468 if (fc->task != NULL) 482 * for the right to transmit again (proc_busy set to YES) */
469 { 483 GNUNET_assert (GNUNET_YES == fc->proc_busy);
470 /* schedule next transmission now, no point in waiting... */
471 GNUNET_SCHEDULER_cancel(fc->task);
472 fc->task = GNUNET_SCHEDULER_add_now(&transmit_next, fc);
473 }
474 else
475 {
476 /* only case where there is no task should be if we're waiting
477 * for the right to transmit again (proc_busy set to YES) */
478 GNUNET_assert(GNUNET_YES == fc->proc_busy);
479 }
480 return GNUNET_NO;
481 } 484 }
485 return GNUNET_NO;
486 }
482 487
483 /* all done */ 488 /* all done */
484 GNUNET_STATISTICS_update(fc->stats, 489 GNUNET_STATISTICS_update (fc->stats,
485 _("# fragmentation transmissions completed"), 490 _ ("# fragmentation transmissions completed"),
486 1, 491 1,
487 GNUNET_NO); 492 GNUNET_NO);
488 if (NULL != fc->task) 493 if (NULL != fc->task)
489 { 494 {
490 GNUNET_SCHEDULER_cancel(fc->task); 495 GNUNET_SCHEDULER_cancel (fc->task);
491 fc->task = NULL; 496 fc->task = NULL;
492 } 497 }
493 return GNUNET_OK; 498 return GNUNET_OK;
494} 499}
495 500
@@ -505,18 +510,18 @@ GNUNET_FRAGMENT_process_ack(struct GNUNET_FRAGMENT_Context *fc,
505 * last message, set to FOREVER if the message was not fully transmitted (OUT only) 510 * last message, set to FOREVER if the message was not fully transmitted (OUT only)
506 */ 511 */
507void 512void
508GNUNET_FRAGMENT_context_destroy(struct GNUNET_FRAGMENT_Context *fc, 513GNUNET_FRAGMENT_context_destroy (struct GNUNET_FRAGMENT_Context *fc,
509 struct GNUNET_TIME_Relative *msg_delay, 514 struct GNUNET_TIME_Relative *msg_delay,
510 struct GNUNET_TIME_Relative *ack_delay) 515 struct GNUNET_TIME_Relative *ack_delay)
511{ 516{
512 if (fc->task != NULL) 517 if (fc->task != NULL)
513 GNUNET_SCHEDULER_cancel(fc->task); 518 GNUNET_SCHEDULER_cancel (fc->task);
514 if (NULL != ack_delay) 519 if (NULL != ack_delay)
515 *ack_delay = fc->ack_delay; 520 *ack_delay = fc->ack_delay;
516 if (NULL != msg_delay) 521 if (NULL != msg_delay)
517 *msg_delay = GNUNET_TIME_relative_saturating_multiply(fc->msg_delay, 522 *msg_delay = GNUNET_TIME_relative_saturating_multiply (fc->msg_delay,
518 fc->num_rounds); 523 fc->num_rounds);
519 GNUNET_free(fc); 524 GNUNET_free (fc);
520} 525}
521 526
522 527