diff options
Diffstat (limited to 'src/fragmentation/fragmentation.c')
-rw-r--r-- | src/fragmentation/fragmentation.c | 402 |
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 | */ |
40 | struct GNUNET_FRAGMENT_Context | 40 | struct 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 | */ |
147 | const char * | 145 | const char * |
148 | GNUNET_FRAGMENT_print_ack (const struct GNUNET_MessageHeader *ack) | 146 | GNUNET_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 | */ |
171 | static void | 169 | static void |
172 | transmit_next (void *cls) | 170 | transmit_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 | */ |
310 | struct GNUNET_FRAGMENT_Context * | 308 | struct GNUNET_FRAGMENT_Context * |
311 | GNUNET_FRAGMENT_context_create (struct GNUNET_STATISTICS_Handle *stats, | 309 | GNUNET_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 | */ |
369 | void | 367 | void |
370 | GNUNET_FRAGMENT_context_transmission_done (struct GNUNET_FRAGMENT_Context *fc) | 368 | GNUNET_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 | */ |
393 | int | 391 | int |
394 | GNUNET_FRAGMENT_process_ack (struct GNUNET_FRAGMENT_Context *fc, | 392 | GNUNET_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 | */ |
509 | void | 507 | void |
510 | GNUNET_FRAGMENT_context_destroy (struct GNUNET_FRAGMENT_Context *fc, | 508 | GNUNET_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 | ||