GNUnet  0.10.x
Typedefs | Functions
Fragmentation library

Library to help fragment messages. More...

Typedefs

typedef void(* GNUNET_FRAGMENT_MessageProcessor) (void *cls, const struct GNUNET_MessageHeader *msg)
 Function that is called with messages created by the fragmentation module. More...
 
typedef void(* GNUNET_DEFRAGMENT_AckProcessor) (void *cls, uint32_t id, const struct GNUNET_MessageHeader *msg)
 Function that is called with acknowledgement messages created by the fragmentation module. More...
 

Functions

struct GNUNET_FRAGMENT_ContextGNUNET_FRAGMENT_context_create (struct GNUNET_STATISTICS_Handle *stats, uint16_t mtu, struct GNUNET_BANDWIDTH_Tracker *tracker, struct GNUNET_TIME_Relative msg_delay, struct GNUNET_TIME_Relative ack_delay, const struct GNUNET_MessageHeader *msg, GNUNET_FRAGMENT_MessageProcessor proc, void *proc_cls)
 Create a fragmentation context for the given message. More...
 
void GNUNET_FRAGMENT_context_transmission_done (struct GNUNET_FRAGMENT_Context *fc)
 Continuation to call from the 'proc' function after the fragment has been transmitted (and hence the next fragment can now be given to proc). More...
 
int GNUNET_FRAGMENT_process_ack (struct GNUNET_FRAGMENT_Context *fc, const struct GNUNET_MessageHeader *msg)
 Process an acknowledgement message we got from the other side (to control re-transmits). More...
 
void GNUNET_FRAGMENT_context_destroy (struct GNUNET_FRAGMENT_Context *fc, struct GNUNET_TIME_Relative *msg_delay, struct GNUNET_TIME_Relative *ack_delay)
 Destroy the given fragmentation context (stop calling 'proc', free resources). More...
 
const char * GNUNET_FRAGMENT_print_ack (const struct GNUNET_MessageHeader *ack)
 Convert an ACK message to a printable format suitable for logging. More...
 
struct GNUNET_DEFRAGMENT_ContextGNUNET_DEFRAGMENT_context_create (struct GNUNET_STATISTICS_Handle *stats, uint16_t mtu, unsigned int num_msgs, void *cls, GNUNET_FRAGMENT_MessageProcessor proc, GNUNET_DEFRAGMENT_AckProcessor ackp)
 Create a defragmentation context. More...
 
void GNUNET_DEFRAGMENT_context_destroy (struct GNUNET_DEFRAGMENT_Context *dc)
 Destroy the given defragmentation context. More...
 
int GNUNET_DEFRAGMENT_process_fragment (struct GNUNET_DEFRAGMENT_Context *dc, const struct GNUNET_MessageHeader *msg)
 We have received a fragment. More...
 

Detailed Description

Library to help fragment messages.

Todo:
Consider additional flow-control for sending from fragmentation based on continuations.

Typedef Documentation

◆ GNUNET_FRAGMENT_MessageProcessor

typedef void(* GNUNET_FRAGMENT_MessageProcessor) (void *cls, const struct GNUNET_MessageHeader *msg)

Function that is called with messages created by the fragmentation module.

In the case of the 'proc' callback of the GNUNET_FRAGMENT_context_create() function, this function must eventually call GNUNET_FRAGMENT_context_transmission_done().

Parameters
clsclosure
msgthe message that was created

Definition at line 66 of file gnunet_fragmentation_lib.h.

◆ GNUNET_DEFRAGMENT_AckProcessor

typedef void(* GNUNET_DEFRAGMENT_AckProcessor) (void *cls, uint32_t id, const struct GNUNET_MessageHeader *msg)

Function that is called with acknowledgement messages created by the fragmentation module.

Acknowledgements are cummulative, so it is OK to only transmit the 'latest' ack message for the same message ID.

Parameters
clsclosure
idunique message ID (modulo collisions)
msgthe message that was created

Definition at line 171 of file gnunet_fragmentation_lib.h.

Function Documentation

◆ GNUNET_FRAGMENT_context_create()

struct GNUNET_FRAGMENT_Context* GNUNET_FRAGMENT_context_create ( struct GNUNET_STATISTICS_Handle stats,
uint16_t  mtu,
struct GNUNET_BANDWIDTH_Tracker tracker,
struct GNUNET_TIME_Relative  msg_delay,
struct GNUNET_TIME_Relative  ack_delay,
const struct GNUNET_MessageHeader msg,
GNUNET_FRAGMENT_MessageProcessor  proc,
void *  proc_cls 
)

Create a fragmentation context for the given message.

Fragments the message into fragments of size mtu or less. Calls proc on each un-acknowledged fragment, using both the expected msg_delay between messages and acknowledgements and the given tracker to guide the frequency of calls to proc.

Parameters
statsstatistics context
mtuthe maximum message size for each fragment
trackerbandwidth tracker to use for flow control (can be NULL)
msg_delayinitial delay to insert between fragment transmissions based on previous messages
ack_delayexpected delay between fragment transmission and ACK based on previous messages
msgthe message to fragment
procfunction to call for each fragment to transmit
proc_clsclosure for proc
Returns
the fragmentation context

Fragments the message into fragments of size mtu or less. Calls proc on each un-acknowledged fragment, using both the expected msg_delay between messages and acknowledgements and the given tracker to guide the frequency of calls to proc.

Parameters
statsstatistics context
mtuthe maximum message size for each fragment
trackerbandwidth tracker to use for flow control (can be NULL)
msg_delayinitial delay to insert between fragment transmissions based on previous messages
ack_delayexpected delay between fragment transmission and ACK based on previous messages
msgthe message to fragment
procfunction to call for each fragment to transmit
proc_clsclosure for proc
Returns
the fragmentation context

Definition at line 309 of file fragmentation.c.

References _, GNUNET_FRAGMENT_Context::ack_delay, GNUNET_FRAGMENT_Context::acks, GNUNET_FRAGMENT_Context::acks_mask, GNUNET_FRAGMENT_Context::fragment_id, GNUNET_assert, GNUNET_CRYPTO_QUALITY_WEAK, GNUNET_CRYPTO_random_u32(), GNUNET_malloc, GNUNET_memcpy, GNUNET_NO, GNUNET_SCHEDULER_add_now(), GNUNET_STATISTICS_update(), GNUNET_FRAGMENT_Context::msg, GNUNET_FRAGMENT_Context::msg_delay, GNUNET_FRAGMENT_Context::mtu, GNUNET_FRAGMENT_Context::proc, GNUNET_FRAGMENT_Context::proc_cls, size, GNUNET_MessageHeader::size, GNUNET_FRAGMENT_Context::stats, GNUNET_FRAGMENT_Context::task, GNUNET_FRAGMENT_Context::tracker, and transmit_next().

Referenced by handle_helper_message(), send_with_fragmentation(), and udp_plugin_send().

317 {
318  struct GNUNET_FRAGMENT_Context *fc;
319  size_t size;
320  uint64_t bits;
321 
323  _("# messages fragmented"),
324  1,
325  GNUNET_NO);
326  GNUNET_assert(mtu >= 1024 + sizeof(struct FragmentHeader));
327  size = ntohs(msg->size);
329  _("# total size of fragmented messages"),
330  size, GNUNET_NO);
331  GNUNET_assert(size >= sizeof(struct GNUNET_MessageHeader));
332  fc = GNUNET_malloc(sizeof(struct GNUNET_FRAGMENT_Context) + size);
333  fc->stats = stats;
334  fc->mtu = mtu;
335  fc->tracker = tracker;
336  fc->ack_delay = ack_delay;
337  fc->msg_delay = msg_delay;
338  fc->msg = (const struct GNUNET_MessageHeader *)&fc[1];
339  fc->proc = proc;
340  fc->proc_cls = proc_cls;
341  fc->fragment_id =
343  UINT32_MAX);
344  GNUNET_memcpy(&fc[1], msg, size);
345  bits =
346  (size + mtu - sizeof(struct FragmentHeader) - 1) / (mtu -
347  sizeof(struct
348  FragmentHeader));
349  GNUNET_assert(bits <= 64);
350  if (bits == 64)
351  fc->acks_mask = UINT64_MAX; /* set all 64 bit */
352  else
353  fc->acks_mask = (1LLU << bits) - 1; /* set lowest 'bits' bit */
354  fc->acks = fc->acks_mask;
356  return fc;
357 }
static struct GNUNET_STATISTICS_Handle * stats
Handle for statistics.
uint64_t acks
Bitfield, set to 1 for each unacknowledged fragment.
Definition: fragmentation.c:89
struct GNUNET_SCHEDULER_Task * task
Task performing work for the fragmenter.
struct GNUNET_STATISTICS_Handle * stats
Statistics to use.
Definition: fragmentation.c:44
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct GNUNET_TIME_Relative msg_delay
Current expected delay between messages.
Definition: fragmentation.c:59
GNUNET_FRAGMENT_MessageProcessor proc
Function to call for transmissions.
Definition: fragmentation.c:79
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
uint64_t acks_mask
Bitfield with all possible bits for acks (used to mask the ack we get back).
Definition: fragmentation.c:95
#define GNUNET_NO
Definition: gnunet_common.h:78
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
struct GNUNET_BANDWIDTH_Tracker * tracker
Tracker for flow control.
Definition: fragmentation.c:49
void * proc_cls
Closure for proc.
Definition: fragmentation.c:84
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
uint16_t mtu
Target fragment size.
uint32_t fragment_id
Our fragmentation ID.
Fragmentation context.
Definition: fragmentation.c:40
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1264
static void transmit_next(void *cls)
Transmit the next fragment to the other peer.
const struct GNUNET_MessageHeader * msg
Message to fragment (allocated at the end of this struct).
Definition: fragmentation.c:74
static unsigned int size
Size of the "table".
Definition: peer.c:66
Header for all communications.
struct GNUNET_TIME_Relative ack_delay
Current expected delay for ACKs.
Definition: fragmentation.c:54
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).
#define GNUNET_malloc(size)
Wrapper around malloc.
Header for a message fragment.
Definition: fragmentation.h:36
Here is the call graph for this function:
Here is the caller graph for this function:

◆ GNUNET_FRAGMENT_context_transmission_done()

void GNUNET_FRAGMENT_context_transmission_done ( struct GNUNET_FRAGMENT_Context fc)

Continuation to call from the 'proc' function after the fragment has been transmitted (and hence the next fragment can now be given to proc).

Parameters
fcfragmentation context

Definition at line 368 of file fragmentation.c.

References GNUNET_FRAGMENT_Context::delay_until, GNUNET_assert, GNUNET_NO, GNUNET_SCHEDULER_add_at(), GNUNET_YES, GNUNET_FRAGMENT_Context::proc_busy, GNUNET_FRAGMENT_Context::task, and transmit_next().

Referenced by fragment_transmission_done(), qc_fragment_sent(), and transmit_fragment().

369 {
371  fc->proc_busy = GNUNET_NO;
372  GNUNET_assert(fc->task == NULL);
373  fc->task =
375  &transmit_next,
376  fc);
377 }
struct GNUNET_SCHEDULER_Task * task
Task performing work for the fragmenter.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_NO
Definition: gnunet_common.h:78
int8_t proc_busy
GNUNET_YES if we called proc and are now waiting for GNUNET_FRAGMENT_context_transmission_done() ...
static void transmit_next(void *cls)
Transmit the next fragment to the other peer.
#define GNUNET_YES
Definition: gnunet_common.h:77
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_at(struct GNUNET_TIME_Absolute at, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run at the specified time.
Definition: scheduler.c:1214
struct GNUNET_TIME_Absolute delay_until
Next allowed transmission time.
Definition: fragmentation.c:64
Here is the call graph for this function:
Here is the caller graph for this function:

◆ GNUNET_FRAGMENT_process_ack()

int GNUNET_FRAGMENT_process_ack ( struct GNUNET_FRAGMENT_Context fc,
const struct GNUNET_MessageHeader msg 
)

Process an acknowledgement message we got from the other side (to control re-transmits).

Parameters
fcfragmentation context
msgacknowledgement message we received
Returns
GNUNET_OK if this ack completes the work of the 'fc' (all fragments have been received); GNUNET_NO if more messages are pending GNUNET_SYSERR if this ack is not valid for this fc

Definition at line 392 of file fragmentation.c.

References _, GNUNET_FRAGMENT_Context::ack_delay, GNUNET_FRAGMENT_Context::acks, GNUNET_FRAGMENT_Context::acks_mask, FragmentAcknowledgement::bits, FragmentAcknowledgement::fragment_id, GNUNET_FRAGMENT_Context::fragment_id, GNUNET_assert, GNUNET_break_op, GNUNET_NO, GNUNET_ntohll(), GNUNET_OK, GNUNET_SCHEDULER_add_now(), GNUNET_SCHEDULER_cancel(), GNUNET_STATISTICS_update(), GNUNET_SYSERR, GNUNET_TIME_absolute_get_duration(), GNUNET_TIME_relative_min(), GNUNET_TIME_relative_saturating_multiply(), GNUNET_TIME_UNIT_SECONDS, GNUNET_YES, GNUNET_FRAGMENT_Context::last_round, GNUNET_FRAGMENT_Context::msg_delay, GNUNET_FRAGMENT_Context::num_transmissions, GNUNET_FRAGMENT_Context::proc_busy, GNUNET_TIME_Relative::rel_value_us, GNUNET_MessageHeader::size, GNUNET_FRAGMENT_Context::stats, GNUNET_FRAGMENT_Context::task, transmit_next(), and GNUNET_FRAGMENT_Context::wack.

Referenced by process_data(), and read_process_ack().

394 {
395  const struct FragmentAcknowledgement *fa;
396  uint64_t abits;
397  struct GNUNET_TIME_Relative ndelay;
398  unsigned int ack_cnt;
399  unsigned int snd_cnt;
400  unsigned int i;
401 
402  if (sizeof(struct FragmentAcknowledgement) != ntohs(msg->size))
403  {
404  GNUNET_break_op(0);
405  return GNUNET_SYSERR;
406  }
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))
413  {
414  /* normal ACK, can update running average of delay... */
415  fc->wack = GNUNET_NO;
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 */
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;
452  }
454  _("# fragment acknowledgements received"),
455  1,
456  GNUNET_NO);
457  if (abits != (fc->acks & abits))
458  {
459  /* ID collission or message reordering, count! This should be rare! */
461  _("# bits removed from fragmentation ACKs"), 1,
462  GNUNET_NO);
463  }
464  fc->acks = abits & fc->acks_mask;
465  if (0 != fc->acks)
466  {
467  /* more to transmit, do so right now (if tracker permits...) */
468  if (fc->task != NULL)
469  {
470  /* schedule next transmission now, no point in waiting... */
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) */
479  }
480  return GNUNET_NO;
481  }
482 
483  /* all done */
485  _("# fragmentation transmissions completed"),
486  1,
487  GNUNET_NO);
488  if (NULL != fc->task)
489  {
491  fc->task = NULL;
492  }
493  return GNUNET_OK;
494 }
uint32_t fragment_id
Unique fragment ID.
Definition: fragmentation.h:72
uint64_t acks
Bitfield, set to 1 for each unacknowledged fragment.
Definition: fragmentation.c:89
struct GNUNET_SCHEDULER_Task * task
Task performing work for the fragmenter.
uint64_t rel_value_us
The actual value.
struct GNUNET_TIME_Absolute last_round
Time we transmitted the last message of the last round.
Definition: fragmentation.c:69
uint64_t bits
Bits that are being acknowledged, in big-endian.
Definition: fragmentation.h:79
struct GNUNET_STATISTICS_Handle * stats
Statistics to use.
Definition: fragmentation.c:44
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_TIME_UNIT_SECONDS
One second.
struct GNUNET_TIME_Relative msg_delay
Current expected delay between messages.
Definition: fragmentation.c:59
uint64_t acks_mask
Bitfield with all possible bits for acks (used to mask the ack we get back).
Definition: fragmentation.c:95
#define GNUNET_NO
Definition: gnunet_common.h:78
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
int8_t proc_busy
GNUNET_YES if we called proc and are now waiting for GNUNET_FRAGMENT_context_transmission_done() ...
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
uint32_t fragment_id
Our fragmentation ID.
unsigned int num_transmissions
How many transmission have we completed in this round?
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1264
static void transmit_next(void *cls)
Transmit the next fragment to the other peer.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_min(struct GNUNET_TIME_Relative t1, struct GNUNET_TIME_Relative t2)
Return the minimum of two relative time values.
Definition: time.c:272
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
int8_t wack
GNUNET_YES if we are waiting for an ACK.
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_duration(struct GNUNET_TIME_Absolute whence)
Get the duration of an operation as the difference of the current time and the given start time "henc...
Definition: time.c:373
Message fragment acknowledgement.
Definition: fragmentation.h:63
struct GNUNET_TIME_Relative ack_delay
Current expected delay for ACKs.
Definition: fragmentation.c:54
#define GNUNET_YES
Definition: gnunet_common.h:77
struct GNUNET_TIME_Relative GNUNET_TIME_relative_saturating_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Saturating multiply relative time by a given factor.
Definition: time.c:499
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
Definition: common_endian.c:48
Time for relative time used by GNUnet, in microseconds.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:956
Here is the call graph for this function:
Here is the caller graph for this function:

◆ GNUNET_FRAGMENT_context_destroy()

void GNUNET_FRAGMENT_context_destroy ( struct GNUNET_FRAGMENT_Context fc,
struct GNUNET_TIME_Relative msg_delay,
struct GNUNET_TIME_Relative ack_delay 
)

Destroy the given fragmentation context (stop calling 'proc', free resources).

Parameters
fcfragmentation context
msg_delaywhere to store average delay between individual message transmissions the last message (OUT only)
ack_delaywhere to store average delay between transmission and ACK for the last message, set to FOREVER if the message was not fully transmitted (OUT only)

Definition at line 508 of file fragmentation.c.

References GNUNET_FRAGMENT_Context::ack_delay, GNUNET_free, GNUNET_SCHEDULER_cancel(), GNUNET_TIME_relative_saturating_multiply(), GNUNET_FRAGMENT_Context::msg_delay, GNUNET_FRAGMENT_Context::num_rounds, and GNUNET_FRAGMENT_Context::task.

Referenced by fragmented_message_done(), free_fragment_message(), and free_session().

511 {
512  if (fc->task != NULL)
514  if (NULL != ack_delay)
515  *ack_delay = fc->ack_delay;
516  if (NULL != msg_delay)
518  fc->num_rounds);
519  GNUNET_free(fc);
520 }
unsigned int num_rounds
How many rounds of transmission have we completed so far?
struct GNUNET_SCHEDULER_Task * task
Task performing work for the fragmenter.
struct GNUNET_TIME_Relative msg_delay
Current expected delay between messages.
Definition: fragmentation.c:59
struct GNUNET_TIME_Relative ack_delay
Current expected delay for ACKs.
Definition: fragmentation.c:54
struct GNUNET_TIME_Relative GNUNET_TIME_relative_saturating_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Saturating multiply relative time by a given factor.
Definition: time.c:499
#define GNUNET_free(ptr)
Wrapper around free.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:956
Here is the call graph for this function:
Here is the caller graph for this function:

◆ GNUNET_FRAGMENT_print_ack()

const char* GNUNET_FRAGMENT_print_ack ( const struct GNUNET_MessageHeader ack)

Convert an ACK message to a printable format suitable for logging.

Parameters
ackmessage to print
Returns
ack in human-readable format

Definition at line 146 of file fragmentation.c.

References FragmentAcknowledgement::bits, buf, FragmentAcknowledgement::fragment_id, GNUNET_ntohll(), GNUNET_snprintf(), and GNUNET_MessageHeader::size.

Referenced by read_process_ack().

147 {
148  static char buf[128];
149  const struct FragmentAcknowledgement *fa;
150 
151  if (sizeof(struct FragmentAcknowledgement) !=
152  htons(ack->size))
153  return "<malformed ack>";
154  fa = (const struct FragmentAcknowledgement *)ack;
155  GNUNET_snprintf(buf,
156  sizeof(buf),
157  "%u-%llX",
158  ntohl(fa->fragment_id),
159  GNUNET_ntohll(fa->bits));
160  return buf;
161 }
uint32_t fragment_id
Unique fragment ID.
Definition: fragmentation.h:72
int GNUNET_snprintf(char *buf, size_t size, const char *format,...)
Like snprintf, just aborts if the buffer is of insufficient size.
uint64_t bits
Bits that are being acknowledged, in big-endian.
Definition: fragmentation.h:79
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
static char buf[2048]
Message fragment acknowledgement.
Definition: fragmentation.h:63
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
Definition: common_endian.c:48
Here is the call graph for this function:
Here is the caller graph for this function:

◆ GNUNET_DEFRAGMENT_context_create()

struct GNUNET_DEFRAGMENT_Context* GNUNET_DEFRAGMENT_context_create ( struct GNUNET_STATISTICS_Handle stats,
uint16_t  mtu,
unsigned int  num_msgs,
void *  cls,
GNUNET_FRAGMENT_MessageProcessor  proc,
GNUNET_DEFRAGMENT_AckProcessor  ackp 
)

Create a defragmentation context.

Parameters
statsstatistics context
mtuthe maximum message size for each fragment
num_msgshow many fragmented messages to we defragment at most at the same time?
clsclosure for proc and ackp
procfunction to call with defragmented messages
ackpfunction to call with acknowledgements (to send back to the other side)
Returns
the defragmentation context

Definition at line 205 of file defragmentation.c.

References GNUNET_DEFRAGMENT_Context::ackp, GNUNET_DEFRAGMENT_Context::cls, dc, GNUNET_new, GNUNET_TIME_UNIT_SECONDS, GNUNET_DEFRAGMENT_Context::latency, GNUNET_DEFRAGMENT_Context::mtu, GNUNET_DEFRAGMENT_Context::num_msgs, GNUNET_DEFRAGMENT_Context::proc, GNUNET_DEFRAGMENT_Context::stats, and stats.

Referenced by create_macendpoint(), and read_process_fragment().

210 {
212 
214  dc->stats = stats;
215  dc->cls = cls;
216  dc->proc = proc;
217  dc->ackp = ackp;
218  dc->num_msgs = num_msgs;
219  dc->mtu = mtu;
220  dc->latency = GNUNET_TIME_UNIT_SECONDS; /* start with likely overestimate */
221  return dc;
222 }
static struct GNUNET_STATISTICS_Handle * stats
Handle for statistics.
#define GNUNET_TIME_UNIT_SECONDS
One second.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
void * cls
Closure for proc and ackp.
GNUNET_DEFRAGMENT_AckProcessor ackp
Function to call with acknowledgements.
unsigned int num_msgs
num_msgs how many fragmented messages to we defragment at most at the same time?
Defragmentation context (one per connection).
struct GNUNET_STATISTICS_Handle * stats
For statistics.
struct GNUNET_TIME_Relative latency
Running average of the latency (delay between messages) for this connection.
GNUNET_FRAGMENT_MessageProcessor proc
Function to call with defragmented messages.
uint16_t mtu
Maximum message size for each fragment.
static struct GNUNET_FS_DownloadContext * dc
Here is the caller graph for this function:

◆ GNUNET_DEFRAGMENT_context_destroy()

void GNUNET_DEFRAGMENT_context_destroy ( struct GNUNET_DEFRAGMENT_Context dc)

Destroy the given defragmentation context.

Parameters
dcdefragmentation context

Definition at line 231 of file defragmentation.c.

References MessageContext::ack_task, GNUNET_assert, GNUNET_CONTAINER_DLL_remove, GNUNET_free, GNUNET_SCHEDULER_cancel(), GNUNET_DEFRAGMENT_Context::head, GNUNET_DEFRAGMENT_Context::list_size, mc, and GNUNET_DEFRAGMENT_Context::tail.

Referenced by ack_proc(), free_macendpoint(), heap_cleanup_iterator(), read_process_fragment(), and udp_disconnect_session().

232 {
233  struct MessageContext *mc;
234 
235  while (NULL != (mc = dc->head))
236  {
237  GNUNET_CONTAINER_DLL_remove(dc->head, dc->tail, mc);
238  dc->list_size--;
239  if (NULL != mc->ack_task)
240  {
242  mc->ack_task = NULL;
243  }
244  GNUNET_free(mc);
245  }
246  GNUNET_assert(0 == dc->list_size);
247  GNUNET_free(dc);
248 }
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
struct MessageContext * tail
Tail of list of messages we&#39;re defragmenting.
struct GNUNET_SCHEDULER_Task * ack_task
Task scheduled for transmitting the next ACK to the other peer.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
unsigned int list_size
Current number of messages in the &#39;struct MessageContext&#39; DLL (smaller or equal to &#39;num_msgs&#39;)...
struct MessageContext * head
Head of list of messages we&#39;re defragmenting.
Information we keep for one message that is being assembled.
static struct GNUNET_TESTBED_Controller * mc
Handle to the master controller.
#define GNUNET_free(ptr)
Wrapper around free.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:956
Here is the call graph for this function:
Here is the caller graph for this function:

◆ GNUNET_DEFRAGMENT_process_fragment()

int GNUNET_DEFRAGMENT_process_fragment ( struct GNUNET_DEFRAGMENT_Context dc,
const struct GNUNET_MessageHeader msg 
)

We have received a fragment.

Process it.

Parameters
dcthe context
msgthe message that was received
Returns
GNUNET_OK on success, GNUNET_NO if this was a duplicate, GNUNET_SYSERR on error

Definition at line 413 of file defragmentation.c.

References _, MessageContext::ack_task, FragTimes::bit, MessageContext::bits, dc, MessageContext::dc, discard_oldest_mc(), estimate_latency(), fh, MessageContext::frag_times, MessageContext::frag_times_start_offset, MessageContext::frag_times_write_offset, FragmentHeader::fragment_id, MessageContext::fragment_id, GNUNET_break_op, GNUNET_CONTAINER_DLL_insert, GNUNET_malloc, GNUNET_memcpy, GNUNET_NO, GNUNET_SCHEDULER_add_delayed(), GNUNET_SCHEDULER_cancel(), GNUNET_STATISTICS_update(), GNUNET_SYSERR, GNUNET_TIME_absolute_get(), GNUNET_TIME_relative_saturating_multiply(), GNUNET_TIME_UNIT_ZERO, GNUNET_YES, MessageContext::last_bit, MessageContext::last_duplicate, MessageContext::last_update, mc, MessageContext::msg, GNUNET_DEFRAGMENT_Context::mtu, MessageContext::next, FragmentHeader::offset, send_ack(), GNUNET_MessageHeader::size, GNUNET_DEFRAGMENT_Context::stats, FragTimes::time, FragmentHeader::total_size, and MessageContext::total_size.

Referenced by process_data(), and read_process_fragment().

415 {
416  struct MessageContext *mc;
417  const struct FragmentHeader *fh;
418  uint16_t msize;
419  uint16_t foff;
420  uint32_t fid;
421  char *mbuf;
422  unsigned int bit;
423  struct GNUNET_TIME_Absolute now;
425  unsigned int bc;
426  unsigned int b;
427  unsigned int n;
428  unsigned int num_fragments;
429  int duplicate;
430  int last;
431 
432  if (ntohs(msg->size) < sizeof(struct FragmentHeader))
433  {
434  GNUNET_break_op(0);
435  return GNUNET_SYSERR;
436  }
437  if (ntohs(msg->size) > dc->mtu)
438  {
439  GNUNET_break_op(0);
440  return GNUNET_SYSERR;
441  }
442  fh = (const struct FragmentHeader *)msg;
443  msize = ntohs(fh->total_size);
444  if (msize < sizeof(struct GNUNET_MessageHeader))
445  {
446  GNUNET_break_op(0);
447  return GNUNET_SYSERR;
448  }
449  fid = ntohl(fh->fragment_id);
450  foff = ntohs(fh->offset);
451  if (foff >= msize)
452  {
453  GNUNET_break_op(0);
454  return GNUNET_SYSERR;
455  }
456  if (0 != (foff % (dc->mtu - sizeof(struct FragmentHeader))))
457  {
458  GNUNET_break_op(0);
459  return GNUNET_SYSERR;
460  }
462  _("# fragments received"),
463  1,
464  GNUNET_NO);
465  num_fragments = (ntohs(msg->size) + dc->mtu - sizeof(struct FragmentHeader) - 1) / (dc->mtu - sizeof(struct FragmentHeader));
466  last = 0;
467  for (mc = dc->head; NULL != mc; mc = mc->next)
468  if (mc->fragment_id > fid)
469  last++;
470 
471  mc = dc->head;
472  while ((NULL != mc) && (fid != mc->fragment_id))
473  mc = mc->next;
474  bit = foff / (dc->mtu - sizeof(struct FragmentHeader));
475  if (bit * (dc->mtu - sizeof(struct FragmentHeader)) + ntohs(msg->size) -
476  sizeof(struct FragmentHeader) > msize)
477  {
478  /* payload extends past total message size */
479  GNUNET_break_op(0);
480  return GNUNET_SYSERR;
481  }
482  if ((NULL != mc) && (msize != mc->total_size))
483  {
484  /* inconsistent message size */
485  GNUNET_break_op(0);
486  return GNUNET_SYSERR;
487  }
488  now = GNUNET_TIME_absolute_get();
489  if (NULL == mc)
490  {
491  mc = GNUNET_malloc(sizeof(struct MessageContext) + msize);
492  mc->msg = (const struct GNUNET_MessageHeader *)&mc[1];
493  mc->dc = dc;
494  mc->total_size = msize;
495  mc->fragment_id = fid;
496  mc->last_update = now;
497  n = (msize + dc->mtu - sizeof(struct FragmentHeader) - 1) / (dc->mtu -
498  sizeof(struct
499  FragmentHeader));
500  if (n == 64)
501  mc->bits = UINT64_MAX; /* set all 64 bit */
502  else
503  mc->bits = (1LLU << n) - 1; /* set lowest 'bits' bit */
504  if (dc->list_size >= dc->num_msgs)
505  discard_oldest_mc(dc);
507  dc->tail,
508  mc);
509  dc->list_size++;
510  }
511 
512  /* copy data to 'mc' */
513  if (0 != (mc->bits & (1LLU << bit)))
514  {
515  mc->bits -= 1LLU << bit;
516  mbuf = (char *)&mc[1];
517  GNUNET_memcpy(&mbuf[bit * (dc->mtu - sizeof(struct FragmentHeader))], &fh[1],
518  ntohs(msg->size) - sizeof(struct FragmentHeader));
519  mc->last_update = now;
520  if (bit < mc->last_bit)
522  mc->last_bit = bit;
523  mc->frag_times[mc->frag_times_write_offset].time = now;
524  mc->frag_times[mc->frag_times_write_offset].bit = bit;
526  duplicate = GNUNET_NO;
527  }
528  else
529  {
530  duplicate = GNUNET_YES;
532  _("# duplicate fragments received"),
533  1,
534  GNUNET_NO);
535  }
536 
537  /* count number of missing fragments after the current one */
538  bc = 0;
539  for (b = bit; b < 64; b++)
540  if (0 != (mc->bits & (1LLU << b)))
541  bc++;
542  else
543  bc = 0;
544 
545  /* notify about complete message */
546  if ((GNUNET_NO == duplicate) &&
547  (0 == mc->bits))
548  {
550  _("# messages defragmented"),
551  1,
552  GNUNET_NO);
553  /* message complete, notify! */
554  dc->proc(dc->cls, mc->msg);
555  }
556  /* send ACK */
558  {
559  dc->latency = estimate_latency(mc);
560  }
562  bc + 1);
563  if ((last + fid == num_fragments) ||
564  (0 == mc->bits) ||
565  (GNUNET_YES == duplicate))
566  {
567  /* message complete or duplicate or last missing fragment in
568  linear sequence; ACK now! */
570  }
571  if (NULL != mc->ack_task)
574  &send_ack,
575  mc);
576  if (GNUNET_YES == duplicate)
577  {
579  return GNUNET_NO;
580  }
581  return GNUNET_YES;
582 }
struct MessageContext * tail
Tail of list of messages we&#39;re defragmenting.
uint32_t fragment_id
Unique fragment ID.
Definition: fragmentation.h:45
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
unsigned int frag_times_start_offset
For the current ACK round, which is the first relevant offset in frag_times?
struct GNUNET_SCHEDULER_Task * ack_task
Task scheduled for transmitting the next ACK to the other peer.
static void send_ack(void *cls)
Send acknowledgement to the other peer now.
uint64_t bits
Which fragments have we gotten yet? bits that are 1 indicate missing fragments.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
uint16_t total_size
Total message size of the original message.
Definition: fragmentation.h:50
#define GNUNET_NO
Definition: gnunet_common.h:78
void * cls
Closure for proc and ackp.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
struct GNUNET_TIME_Absolute last_update
Last time we received any update for this message (least-recently updated message will be discarded i...
uint16_t total_size
Total size of the message that we are assembling.
unsigned int list_size
Current number of messages in the &#39;struct MessageContext&#39; DLL (smaller or equal to &#39;num_msgs&#39;)...
struct GNUNET_TIME_Absolute time
The time the fragment was received.
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
unsigned int num_msgs
num_msgs how many fragmented messages to we defragment at most at the same time?
struct MessageContext * head
Head of list of messages we&#39;re defragmenting.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1237
Information we keep for one message that is being assembled.
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
struct FragTimes frag_times[64]
When did we receive which fragment? Used to calculate the time we should send the ACK...
unsigned int last_bit
Which &#39;bit&#39; did the last fragment we received correspond to?
static int fh
Handle to the unique file.
uint32_t fragment_id
Unique ID for this message.
static struct GNUNET_TESTBED_Controller * mc
Handle to the master controller.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:118
int16_t last_duplicate
Was the last fragment we got a duplicate?
struct GNUNET_DEFRAGMENT_Context * dc
Associated defragmentation context.
struct GNUNET_STATISTICS_Handle * stats
For statistics.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
uint16_t offset
Absolute offset (in bytes) of this fragment in the original message.
Definition: fragmentation.h:56
static struct GNUNET_TIME_Relative delay
When should dkg communication start?
#define GNUNET_TIME_UNIT_ZERO
Relative time zero.
struct GNUNET_TIME_Relative latency
Running average of the latency (delay between messages) for this connection.
static void discard_oldest_mc(struct GNUNET_DEFRAGMENT_Context *dc)
Discard the message context that was inactive for the longest time.
struct MessageContext * next
This is a DLL.
GNUNET_FRAGMENT_MessageProcessor proc
Function to call with defragmented messages.
unsigned int bit
Number of the bit for the fragment (in [0,..,63]).
const struct GNUNET_MessageHeader * msg
Pointer to the assembled message, allocated at the end of this struct.
static struct GNUNET_TIME_Relative estimate_latency(struct MessageContext *mc)
Estimate the latency between messages based on the most recent message time stamps.
Header for all communications.
Time for absolute times used by GNUnet, in microseconds.
#define GNUNET_YES
Definition: gnunet_common.h:77
uint16_t mtu
Maximum message size for each fragment.
unsigned int frag_times_write_offset
Which offset whould we write the next frag value into in the frag_times array? All smaller entries ar...
struct GNUNET_TIME_Relative GNUNET_TIME_relative_saturating_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Saturating multiply relative time by a given factor.
Definition: time.c:499
#define GNUNET_malloc(size)
Wrapper around malloc.
static struct GNUNET_FS_DownloadContext * dc
Time for relative time used by GNUnet, in microseconds.
Header for a message fragment.
Definition: fragmentation.h:36
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:956
Here is the call graph for this function:
Here is the caller graph for this function: