GNUnet  0.11.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 311 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().

319 {
320  struct GNUNET_FRAGMENT_Context *fc;
321  size_t size;
322  uint64_t bits;
323 
325  _ ("# messages fragmented"),
326  1,
327  GNUNET_NO);
328  GNUNET_assert (mtu >= 1024 + sizeof(struct FragmentHeader));
329  size = ntohs (msg->size);
331  _ ("# total size of fragmented messages"),
332  size, GNUNET_NO);
333  GNUNET_assert (size >= sizeof(struct GNUNET_MessageHeader));
334  fc = GNUNET_malloc (sizeof(struct GNUNET_FRAGMENT_Context) + size);
335  fc->stats = stats;
336  fc->mtu = mtu;
337  fc->tracker = tracker;
338  fc->ack_delay = ack_delay;
339  fc->msg_delay = msg_delay;
340  fc->msg = (const struct GNUNET_MessageHeader *) &fc[1];
341  fc->proc = proc;
342  fc->proc_cls = proc_cls;
343  fc->fragment_id =
345  UINT32_MAX);
346  GNUNET_memcpy (&fc[1], msg, size);
347  bits =
348  (size + mtu - sizeof(struct FragmentHeader) - 1) / (mtu
349  - sizeof(struct
350  FragmentHeader));
351  GNUNET_assert (bits <= 64);
352  if (bits == 64)
353  fc->acks_mask = UINT64_MAX; /* set all 64 bit */
354  else
355  fc->acks_mask = (1LLU << bits) - 1; /* set lowest 'bits' bit */
356  fc->acks = fc->acks_mask;
358  return fc;
359 }
uint64_t acks
Bitfield, set to 1 for each unacknowledged fragment.
Definition: fragmentation.c:91
struct GNUNET_SCHEDULER_Task * task
Task performing work for the fragmenter.
struct GNUNET_STATISTICS_Handle * stats
Statistics to use.
Definition: fragmentation.c:46
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:61
GNUNET_FRAGMENT_MessageProcessor proc
Function to call for transmissions.
Definition: fragmentation.c:81
#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:97
#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:51
void * proc_cls
Closure for proc.
Definition: fragmentation.c:86
#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:41
struct GNUNET_STATISTICS_Handle * stats
Handle to the statistics service.
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:1280
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:76
static unsigned int size
Size of the "table".
Definition: peer.c:67
Header for all communications.
struct GNUNET_TIME_Relative ack_delay
Current expected delay for ACKs.
Definition: fragmentation.c:56
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 370 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().

371 {
373  fc->proc_busy = GNUNET_NO;
374  GNUNET_assert (fc->task == NULL);
375  fc->task =
377  &transmit_next,
378  fc);
379 }
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:1230
struct GNUNET_TIME_Absolute delay_until
Next allowed transmission time.
Definition: fragmentation.c:66
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 394 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().

396 {
397  const struct FragmentAcknowledgement *fa;
398  uint64_t abits;
399  struct GNUNET_TIME_Relative ndelay;
400  unsigned int ack_cnt;
401  unsigned int snd_cnt;
402  unsigned int i;
403 
404  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;
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++)
426  {
427  if (1 == (fc->acks_mask & (1ULL << i)))
428  {
429  snd_cnt++;
430  if (0 == (abits & (1ULL << i)))
431  ack_cnt++;
432  }
433  }
434  if (0 == ack_cnt)
435  {
436  /* complete loss */
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)
447  {
448  fc->msg_delay.rel_value_us =
449  (ndelay.rel_value_us / fc->num_transmissions + 3
450  * fc->msg_delay.rel_value_us) / 5;
451  }
452  fc->num_transmissions = 0;
457  }
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! */
466  _ ("# bits removed from fragmentation ACKs"), 1,
467  GNUNET_NO);
468  }
469  fc->acks = abits & fc->acks_mask;
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... */
478  }
479  else
480  {
481  /* only case where there is no task should be if we're waiting
482  * for the right to transmit again (proc_busy set to YES) */
484  }
485  return GNUNET_NO;
486  }
487 
488  /* all done */
490  _ ("# fragmentation transmissions completed"),
491  1,
492  GNUNET_NO);
493  if (NULL != fc->task)
494  {
496  fc->task = NULL;
497  }
498  return GNUNET_OK;
499 }
uint32_t fragment_id
Unique fragment ID.
Definition: fragmentation.h:74
uint64_t acks
Bitfield, set to 1 for each unacknowledged fragment.
Definition: fragmentation.c:91
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:71
uint64_t bits
Bits that are being acknowledged, in big-endian.
Definition: fragmentation.h:81
struct GNUNET_STATISTICS_Handle * stats
Statistics to use.
Definition: fragmentation.c:46
#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:61
uint64_t acks_mask
Bitfield with all possible bits for acks (used to mask the ack we get back).
Definition: fragmentation.c:97
#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:1280
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:375
Message fragment acknowledgement.
Definition: fragmentation.h:64
struct GNUNET_TIME_Relative ack_delay
Current expected delay for ACKs.
Definition: fragmentation.c:56
#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:501
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:966
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 513 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().

516 {
517  if (fc->task != NULL)
519  if (NULL != ack_delay)
520  *ack_delay = fc->ack_delay;
521  if (NULL != msg_delay)
523  fc->num_rounds);
524  GNUNET_free (fc);
525 }
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:61
struct GNUNET_TIME_Relative ack_delay
Current expected delay for ACKs.
Definition: fragmentation.c:56
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:501
#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:966
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 148 of file fragmentation.c.

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

Referenced by read_process_ack().

149 {
150  static char buf[128];
151  const struct FragmentAcknowledgement *fa;
152 
153  if (sizeof(struct FragmentAcknowledgement) !=
154  htons (ack->size))
155  return "<malformed ack>";
156  fa = (const struct FragmentAcknowledgement *) ack;
157  GNUNET_snprintf (buf,
158  sizeof(buf),
159  "%u-%llX",
160  ntohl (fa->fragment_id),
161  GNUNET_ntohll (fa->bits));
162  return buf;
163 }
uint32_t fragment_id
Unique fragment ID.
Definition: fragmentation.h:74
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:81
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:64
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 208 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, stats, and GNUNET_DEFRAGMENT_Context::stats.

Referenced by create_macendpoint(), and read_process_fragment().

213 {
215 
217  dc->stats = stats;
218  dc->cls = cls;
219  dc->proc = proc;
220  dc->ackp = ackp;
221  dc->num_msgs = num_msgs;
222  dc->mtu = mtu;
223  dc->latency = GNUNET_TIME_UNIT_SECONDS; /* start with likely overestimate */
224  return dc;
225 }
#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?
struct GNUNET_STATISTICS_Handle * stats
Handle to the statistics service.
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 234 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().

235 {
236  struct MessageContext *mc;
237 
238  while (NULL != (mc = dc->head))
239  {
240  GNUNET_CONTAINER_DLL_remove (dc->head, dc->tail, mc);
241  dc->list_size--;
242  if (NULL != mc->ack_task)
243  {
245  mc->ack_task = NULL;
246  }
247  GNUNET_free (mc);
248  }
249  GNUNET_assert (0 == dc->list_size);
250  GNUNET_free (dc);
251 }
#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:966
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 416 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().

418 {
419  struct MessageContext *mc;
420  const struct FragmentHeader *fh;
421  uint16_t msize;
422  uint16_t foff;
423  uint32_t fid;
424  char *mbuf;
425  unsigned int bit;
426  struct GNUNET_TIME_Absolute now;
428  unsigned int bc;
429  unsigned int b;
430  unsigned int n;
431  unsigned int num_fragments;
432  int duplicate;
433  int last;
434 
435  if (ntohs (msg->size) < sizeof(struct FragmentHeader))
436  {
437  GNUNET_break_op (0);
438  return GNUNET_SYSERR;
439  }
440  if (ntohs (msg->size) > dc->mtu)
441  {
442  GNUNET_break_op (0);
443  return GNUNET_SYSERR;
444  }
445  fh = (const struct FragmentHeader *) msg;
446  msize = ntohs (fh->total_size);
447  if (msize < sizeof(struct GNUNET_MessageHeader))
448  {
449  GNUNET_break_op (0);
450  return GNUNET_SYSERR;
451  }
452  fid = ntohl (fh->fragment_id);
453  foff = ntohs (fh->offset);
454  if (foff >= msize)
455  {
456  GNUNET_break_op (0);
457  return GNUNET_SYSERR;
458  }
459  if (0 != (foff % (dc->mtu - sizeof(struct FragmentHeader))))
460  {
461  GNUNET_break_op (0);
462  return GNUNET_SYSERR;
463  }
465  _ ("# fragments received"),
466  1,
467  GNUNET_NO);
468  num_fragments = (ntohs (msg->size) + dc->mtu - sizeof(struct FragmentHeader)
469  - 1) / (dc->mtu - sizeof(struct FragmentHeader));
470  last = 0;
471  for (mc = dc->head; NULL != mc; mc = mc->next)
472  if (mc->fragment_id > fid)
473  last++;
474 
475  mc = dc->head;
476  while ((NULL != mc) && (fid != mc->fragment_id))
477  mc = mc->next;
478  bit = foff / (dc->mtu - sizeof(struct FragmentHeader));
479  if (bit * (dc->mtu - sizeof(struct FragmentHeader)) + ntohs (msg->size)
480  - sizeof(struct FragmentHeader) > msize)
481  {
482  /* payload extends past total message size */
483  GNUNET_break_op (0);
484  return GNUNET_SYSERR;
485  }
486  if ((NULL != mc) && (msize != mc->total_size))
487  {
488  /* inconsistent message size */
489  GNUNET_break_op (0);
490  return GNUNET_SYSERR;
491  }
492  now = GNUNET_TIME_absolute_get ();
493  if (NULL == mc)
494  {
495  mc = GNUNET_malloc (sizeof(struct MessageContext) + msize);
496  mc->msg = (const struct GNUNET_MessageHeader *) &mc[1];
497  mc->dc = dc;
498  mc->total_size = msize;
499  mc->fragment_id = fid;
500  mc->last_update = now;
501  n = (msize + dc->mtu - sizeof(struct FragmentHeader) - 1) / (dc->mtu
502  - sizeof(struct
503  FragmentHeader));
504  if (n == 64)
505  mc->bits = UINT64_MAX; /* set all 64 bit */
506  else
507  mc->bits = (1LLU << n) - 1; /* set lowest 'bits' bit */
508  if (dc->list_size >= dc->num_msgs)
509  discard_oldest_mc (dc);
511  dc->tail,
512  mc);
513  dc->list_size++;
514  }
515 
516  /* copy data to 'mc' */
517  if (0 != (mc->bits & (1LLU << bit)))
518  {
519  mc->bits -= 1LLU << bit;
520  mbuf = (char *) &mc[1];
521  GNUNET_memcpy (&mbuf[bit * (dc->mtu - sizeof(struct FragmentHeader))],
522  &fh[1],
523  ntohs (msg->size) - sizeof(struct FragmentHeader));
524  mc->last_update = now;
525  if (bit < mc->last_bit)
527  mc->last_bit = bit;
528  mc->frag_times[mc->frag_times_write_offset].time = now;
529  mc->frag_times[mc->frag_times_write_offset].bit = bit;
531  duplicate = GNUNET_NO;
532  }
533  else
534  {
535  duplicate = GNUNET_YES;
537  _ ("# duplicate fragments received"),
538  1,
539  GNUNET_NO);
540  }
541 
542  /* count number of missing fragments after the current one */
543  bc = 0;
544  for (b = bit; b < 64; b++)
545  if (0 != (mc->bits & (1LLU << b)))
546  bc++;
547  else
548  bc = 0;
549 
550  /* notify about complete message */
551  if ((GNUNET_NO == duplicate) &&
552  (0 == mc->bits))
553  {
555  _ ("# messages defragmented"),
556  1,
557  GNUNET_NO);
558  /* message complete, notify! */
559  dc->proc (dc->cls, mc->msg);
560  }
561  /* send ACK */
563  {
564  dc->latency = estimate_latency (mc);
565  }
567  bc + 1);
568  if ((last + fid == num_fragments) ||
569  (0 == mc->bits) ||
570  (GNUNET_YES == duplicate))
571  {
572  /* message complete or duplicate or last missing fragment in
573  linear sequence; ACK now! */
575  }
576  if (NULL != mc->ack_task)
579  &send_ack,
580  mc);
581  if (GNUNET_YES == duplicate)
582  {
584  return GNUNET_NO;
585  }
586  return GNUNET_YES;
587 }
struct MessageContext * tail
Tail of list of messages we&#39;re defragmenting.
uint32_t fragment_id
Unique fragment ID.
Definition: fragmentation.h:46
#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:51
#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:1253
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:57
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:501
#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:966
Here is the call graph for this function:
Here is the caller graph for this function: