GNUnet  0.19.0
Server library

Library for tokenizing a message stream. More...

Collaboration diagram for Server library:

Typedefs

typedef int(* GNUNET_MessageTokenizerCallback) (void *cls, const struct GNUNET_MessageHeader *message)
 Functions with this signature are called whenever a complete message is received by the tokenizer. More...
 

Functions

struct GNUNET_MessageStreamTokenizerGNUNET_MST_create (GNUNET_MessageTokenizerCallback cb, void *cb_cls)
 Create a message stream tokenizer. More...
 
enum GNUNET_GenericReturnValue GNUNET_MST_from_buffer (struct GNUNET_MessageStreamTokenizer *mst, const char *buf, size_t size, int purge, int one_shot)
 Add incoming data to the receive buffer and call the callback for all complete messages. More...
 
int GNUNET_MST_read (struct GNUNET_MessageStreamTokenizer *mst, struct GNUNET_NETWORK_Handle *sock, int purge, int one_shot)
 Add incoming data to the receive buffer and call the callback for all complete messages. More...
 
int GNUNET_MST_next (struct GNUNET_MessageStreamTokenizer *mst, int one_shot)
 Obtain the next message from the mst, assuming that there are more unprocessed messages in the internal buffer of the mst. More...
 
void GNUNET_MST_destroy (struct GNUNET_MessageStreamTokenizer *mst)
 Destroys a tokenizer. More...
 

Detailed Description

Library for tokenizing a message stream.

See also
Documentation

Typedef Documentation

◆ GNUNET_MessageTokenizerCallback

typedef int(* GNUNET_MessageTokenizerCallback) (void *cls, const struct GNUNET_MessageHeader *message)

Functions with this signature are called whenever a complete message is received by the tokenizer.

Do not call #GNUNET_mst_destroy from within the scope of this callback.

Parameters
clsclosure
messagethe actual message
Returns
GNUNET_OK on success, GNUNET_NO to stop further processing due to disconnect (no error) GNUNET_SYSERR to stop further processing due to error

Definition at line 77 of file gnunet_mst_lib.h.

Function Documentation

◆ GNUNET_MST_create()

struct GNUNET_MessageStreamTokenizer* GNUNET_MST_create ( GNUNET_MessageTokenizerCallback  cb,
void *  cb_cls 
)

Create a message stream tokenizer.

Parameters
cbfunction to call on completed messages
cb_clsclosure for cb
Returns
handle to tokenizer

Definition at line 86 of file mst.c.

88 {
90 
93  ret->curr_buf = GNUNET_MIN_MESSAGE_SIZE;
94  ret->cb = cb;
95  ret->cb_cls = cb_cls;
96  return ret;
97 }
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
#define GNUNET_MIN_MESSAGE_SIZE
Smallest supported message.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
Handle to a message stream tokenizer.
Definition: mst.c:45
void * cb_cls
Closure for cb.
Definition: mst.c:54
GNUNET_MessageTokenizerCallback cb
Function to call on completed messages.
Definition: mst.c:49

References GNUNET_MessageStreamTokenizer::cb, GNUNET_MessageStreamTokenizer::cb_cls, GNUNET_malloc, GNUNET_MIN_MESSAGE_SIZE, GNUNET_new, and ret.

Referenced by client_receive(), GCT_create_tunnel(), get_app(), GNUNET_CLIENT_connect(), GNUNET_HELPER_start(), handle_client_send(), handle_transport_notify_connect(), load(), main(), run(), server_access_cb(), start_client(), udp_broadcast_receive(), and udp_plugin_create_session().

Here is the caller graph for this function:

◆ GNUNET_MST_from_buffer()

enum GNUNET_GenericReturnValue GNUNET_MST_from_buffer ( struct GNUNET_MessageStreamTokenizer mst,
const char *  buf,
size_t  size,
int  purge,
int  one_shot 
)

Add incoming data to the receive buffer and call the callback for all complete messages.

Parameters
msttokenizer to use
bufinput data to add
sizenumber of bytes in buf
purgeshould any excess bytes in the buffer be discarded (i.e. for packet-based services like UDP)
one_shotonly call callback once, keep rest of message in buffer
Returns
GNUNET_OK if we are done processing (need more data) GNUNET_NO if one_shot was set and we have another message ready GNUNET_SYSERR if the data stream is corrupt

Definition at line 86 of file mst.c.

106 {
107  const struct GNUNET_MessageHeader *hdr;
108  size_t delta;
109  uint16_t want;
110  char *ibuf;
111  int ret;
112  int cbret;
113 
114  GNUNET_assert (mst->off <= mst->pos);
115  GNUNET_assert (mst->pos <= mst->curr_buf);
117  "MST receives %u bytes with %u (%u/%u) bytes already in private buffer\n",
118  (unsigned int) size,
119  (unsigned int) (mst->pos - mst->off),
120  (unsigned int) mst->pos,
121  (unsigned int) mst->off);
122  ret = GNUNET_OK;
123  ibuf = (char *) mst->hdr;
124  while (mst->pos > 0)
125  {
126 do_align:
127  GNUNET_assert (mst->pos >= mst->off);
128  if ((mst->curr_buf - mst->off < sizeof(struct GNUNET_MessageHeader)) ||
129  (0 != (mst->off % ALIGN_FACTOR)))
130  {
131  /* need to align or need more space */
132  mst->pos -= mst->off;
133  memmove (ibuf,
134  &ibuf[mst->off],
135  mst->pos);
136  mst->off = 0;
137  }
138  if (mst->pos - mst->off < sizeof(struct GNUNET_MessageHeader))
139  {
140  delta
141  = GNUNET_MIN (sizeof(struct GNUNET_MessageHeader)
142  - (mst->pos - mst->off),
143  size);
144  GNUNET_memcpy (&ibuf[mst->pos],
145  buf,
146  delta);
147  mst->pos += delta;
148  buf += delta;
149  size -= delta;
150  }
151  if (mst->pos - mst->off < sizeof(struct GNUNET_MessageHeader))
152  {
153  if (purge)
154  {
155  mst->off = 0;
156  mst->pos = 0;
157  }
158  return GNUNET_OK;
159  }
160  hdr = (const struct GNUNET_MessageHeader *) &ibuf[mst->off];
161  want = ntohs (hdr->size);
163  "We want to read message of size %u\n",
164  want);
165  if (want < sizeof(struct GNUNET_MessageHeader))
166  {
167  GNUNET_break_op (0);
168  return GNUNET_SYSERR;
169  }
170  if ((mst->curr_buf - mst->off < want) &&
171  (mst->off > 0))
172  {
173  /* can get more space by moving */
174  mst->pos -= mst->off;
175  memmove (ibuf,
176  &ibuf[mst->off],
177  mst->pos);
178  mst->off = 0;
179  }
180  if (mst->curr_buf < want)
181  {
182  /* need to get more space by growing buffer */
183  GNUNET_assert (0 == mst->off);
184  mst->hdr = GNUNET_realloc (mst->hdr,
185  want);
186  ibuf = (char *) mst->hdr;
187  mst->curr_buf = want;
188  }
189  hdr = (const struct GNUNET_MessageHeader *) &ibuf[mst->off];
190  if (mst->pos - mst->off < want)
191  {
192  delta = GNUNET_MIN (want - (mst->pos - mst->off),
193  size);
194  GNUNET_assert (mst->pos + delta <= mst->curr_buf);
195  GNUNET_memcpy (&ibuf[mst->pos],
196  buf,
197  delta);
198  mst->pos += delta;
199  buf += delta;
200  size -= delta;
201  }
202  if (mst->pos - mst->off < want)
203  {
204  if (purge)
205  {
206  mst->off = 0;
207  mst->pos = 0;
208  }
209  return GNUNET_OK;
210  }
211  if (one_shot == GNUNET_SYSERR)
212  {
213  /* cannot call callback again, but return value saying that
214  * we have another full message in the buffer */
215  ret = GNUNET_NO;
216  goto copy;
217  }
218  if (one_shot == GNUNET_YES)
219  one_shot = GNUNET_SYSERR;
220  mst->off += want;
221  if (GNUNET_OK !=
222  (cbret = mst->cb (mst->cb_cls,
223  hdr)))
224  {
225  if (GNUNET_SYSERR == cbret)
227  "Failure processing message of type %u and size %u\n",
228  ntohs (hdr->type),
229  ntohs (hdr->size));
230  return GNUNET_SYSERR;
231  }
232  if (mst->off == mst->pos)
233  {
234  /* reset to beginning of buffer, it's free right now! */
235  mst->off = 0;
236  mst->pos = 0;
237  }
238  }
239  GNUNET_assert (0 == mst->pos);
240  while (size > 0)
241  {
242  unsigned long offset = (unsigned long) buf;
243  bool need_align = (0 != (offset % ALIGN_FACTOR));
244 
246  "Server-mst has %u bytes left in inbound buffer\n",
247  (unsigned int) size);
248  if (size < sizeof(struct GNUNET_MessageHeader))
249  break;
250  if (! need_align)
251  {
252  /* can try to do zero-copy and process directly from original buffer */
253  hdr = (const struct GNUNET_MessageHeader *) buf;
254  want = ntohs (hdr->size);
255  if (want < sizeof(struct GNUNET_MessageHeader))
256  {
257  GNUNET_break_op (0);
258  mst->off = 0;
259  return GNUNET_SYSERR;
260  }
261  if (size < want)
262  break; /* or not: buffer incomplete, so copy to private buffer... */
263  if (one_shot == GNUNET_SYSERR)
264  {
265  /* cannot call callback again, but return value saying that
266  * we have another full message in the buffer */
267  ret = GNUNET_NO;
268  goto copy;
269  }
270  if (GNUNET_YES == one_shot)
271  one_shot = GNUNET_SYSERR;
272  if (GNUNET_OK !=
273  (cbret = mst->cb (mst->cb_cls,
274  hdr)))
275  {
276  if (GNUNET_SYSERR == cbret)
278  "Failure processing message of type %u and size %u\n",
279  ntohs (hdr->type),
280  ntohs (hdr->size));
281  return GNUNET_SYSERR;
282  }
283  buf += want;
284  size -= want;
285  }
286  else
287  {
288  /* need to copy to private buffer to align;
289  * yes, we go a bit more spaghetti than usual here */
290  goto do_align;
291  }
292  }
293 copy:
294  if ((size > 0) && (! purge))
295  {
296  if (size + mst->pos > mst->curr_buf)
297  {
298  mst->hdr = GNUNET_realloc (mst->hdr,
299  size + mst->pos);
300  ibuf = (char *) mst->hdr;
301  mst->curr_buf = size + mst->pos;
302  }
303  GNUNET_assert (size + mst->pos <= mst->curr_buf);
304  GNUNET_memcpy (&ibuf[mst->pos],
305  buf,
306  size);
307  mst->pos += size;
308  }
309  if (purge)
310  {
311  mst->off = 0;
312  mst->pos = 0;
313  }
315  "Server-mst leaves %u (%u/%u) bytes in private buffer\n",
316  (unsigned int) (mst->pos - mst->off),
317  (unsigned int) mst->pos,
318  (unsigned int) mst->off);
319  return ret;
320 }
static size_t do_align(size_t start_position, size_t end_position)
Given the start and end position of a block of data, return the end position of that data after align...
Definition: fs_directory.c:488
static char buf[2048]
#define GNUNET_log(kind,...)
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#define GNUNET_MIN(a, b)
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_DEBUG
#define GNUNET_realloc(ptr, size)
Wrapper around realloc.
#define ALIGN_FACTOR
Definition: mst.c:35
#define LOG(kind,...)
Definition: mst.c:38
static unsigned int size
Size of the "table".
Definition: peer.c:68
static struct GNUNET_TIME_Relative delta
Definition: speedup.c:36
Header for all communications.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
size_t curr_buf
Size of the buffer (starting at hdr).
Definition: mst.c:59
size_t pos
How many bytes in buffer are valid right now?
Definition: mst.c:69
struct GNUNET_MessageHeader * hdr
Beginning of the buffer.
Definition: mst.c:74
size_t off
How many bytes in buffer have we already processed?
Definition: mst.c:64

Referenced by client_receive(), GCT_handle_encrypted(), GNUNET_HELPER_wait(), gnunet_read(), handle_client_send(), handle_encrypted(), helper_read(), load(), main(), process_udp_message(), read_task(), server_access_cb(), and udp_broadcast_receive().

Here is the caller graph for this function:

◆ GNUNET_MST_read()

int GNUNET_MST_read ( struct GNUNET_MessageStreamTokenizer mst,
struct GNUNET_NETWORK_Handle sock,
int  purge,
int  one_shot 
)

Add incoming data to the receive buffer and call the callback for all complete messages.

Parameters
msttokenizer to use
bufinput data to add
sizenumber of bytes in buf
purgeshould any excess bytes in the buffer be discarded (i.e. for packet-based services like UDP)
one_shotonly call callback once, keep rest of message in buffer
Returns
GNUNET_OK if we are done processing (need more data) GNUNET_NO if one_shot was set and we have another message ready GNUNET_SYSERR if the data stream is corrupt

Definition at line 86 of file mst.c.

342 {
343  ssize_t ret;
344  size_t left;
345  char *buf;
346 
347  left = mst->curr_buf - mst->pos;
348  buf = (char *) mst->hdr;
350  &buf[mst->pos],
351  left);
352  if (-1 == ret)
353  {
354  if ((EAGAIN == errno) ||
355  (EINTR == errno))
356  return GNUNET_OK;
358  "recv");
359  return GNUNET_SYSERR;
360  }
361  if (0 == ret)
362  {
363  /* other side closed connection, treat as error */
364  return GNUNET_SYSERR;
365  }
366  mst->pos += ret;
367  return GNUNET_MST_from_buffer (mst,
368  NULL,
369  0,
370  purge,
371  one_shot);
372 }
#define GNUNET_log_strerror(level, cmd)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
@ GNUNET_ERROR_TYPE_INFO
ssize_t GNUNET_NETWORK_socket_recv(const struct GNUNET_NETWORK_Handle *desc, void *buffer, size_t length)
Read data from a connected socket (always non-blocking).
Definition: network.c:716
enum GNUNET_GenericReturnValue GNUNET_MST_from_buffer(struct GNUNET_MessageStreamTokenizer *mst, const char *buf, size_t size, int purge, int one_shot)
Add incoming data to the receive buffer and call the callback for all complete messages.
Definition: mst.c:101

Referenced by receive_ready(), and service_client_recv().

Here is the caller graph for this function:

◆ GNUNET_MST_next()

int GNUNET_MST_next ( struct GNUNET_MessageStreamTokenizer mst,
int  one_shot 
)

Obtain the next message from the mst, assuming that there are more unprocessed messages in the internal buffer of the mst.

Parameters
msttokenizer to use
one_shotonly call callback once, keep rest of message in buffer
Returns
GNUNET_OK if we are done processing (need more data) GNUNET_NO if one_shot was set and we have another message ready GNUNET_SYSERR if the data stream is corrupt

Definition at line 86 of file mst.c.

389 {
390  return GNUNET_MST_from_buffer (mst,
391  NULL,
392  0,
393  GNUNET_NO,
394  one_shot);
395 }

Referenced by resume_client_receive().

Here is the caller graph for this function:

◆ GNUNET_MST_destroy()

void GNUNET_MST_destroy ( struct GNUNET_MessageStreamTokenizer mst)

Destroys a tokenizer.

Parameters
msttokenizer to destroy

Definition at line 404 of file mst.c.

405 {
406  GNUNET_free (mst->hdr);
407  GNUNET_free (mst);
408 }
#define GNUNET_free(ptr)
Wrapper around free.

References GNUNET_free, and GNUNET_MessageStreamTokenizer::hdr.

Referenced by client_delete_session(), connection_client_destroy_impl(), destroy_tunnel(), do_shutdown(), finish_client_drop(), free_session(), GNUNET_HELPER_destroy(), handle_client_send(), handle_transport_notify_disconnect(), load(), main(), server_delete_session(), server_disconnect_cb(), shutdown_task(), and udp_broadcast_receive().

Here is the caller graph for this function: