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