GNUnet  0.10.x
gnunet-service-core.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2009, 2010, 2011, 2016 GNUnet e.V.
4 
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  GNUnet is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Affero General Public License for more details.
14 
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/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19  */
20 
26 #include "platform.h"
27 #include <gcrypt.h>
28 #include "gnunet_util_lib.h"
29 #include "gnunet-service-core.h"
30 #include "gnunet-service-core_kx.h"
33 
40 #define SOFT_MAX_QUEUE 128
41 
47 #define HARD_MAX_QUEUE 256
48 
49 
53 struct GSC_Client {
57  struct GSC_Client *next;
58 
62  struct GSC_Client *prev;
63 
68 
73 
79  uint16_t *types;
80 
86 
91 
96  uint32_t options;
97 
102  int got_init;
103 
108  unsigned int tcnt;
109 };
110 
111 
116 
121 
126 
130 static uint32_t all_client_options;
131 
135 static struct GSC_Client *client_head;
136 
140 static struct GSC_Client *client_tail;
141 
142 
150 static int
151 type_match(uint16_t type, struct GSC_Client *c)
152 {
153  if ((0 == c->tcnt) && (0 != c->options))
154  return GNUNET_YES; /* peer without handlers and inbound/outbond
155  callbacks matches ALL */
156  if (NULL == c->types)
157  return GNUNET_NO;
158  for (unsigned int i = 0; i < c->tcnt; i++)
159  if (type == c->types[i])
160  return GNUNET_YES;
161  return GNUNET_NO;
162 }
163 
164 
172 static int
173 check_client_init(void *cls, const struct InitMessage *im)
174 {
175  return GNUNET_OK;
176 }
177 
178 
185 static void
186 handle_client_init(void *cls, const struct InitMessage *im)
187 {
188  struct GSC_Client *c = cls;
189  struct GNUNET_MQ_Envelope *env;
190  struct InitReplyMessage *irm;
191  uint16_t msize;
192  const uint16_t *types;
193 
194  /* check that we don't have an entry already */
195  msize = ntohs(im->header.size) - sizeof(struct InitMessage);
196  types = (const uint16_t *)&im[1];
197  c->tcnt = msize / sizeof(uint16_t);
198  c->options = ntohl(im->options);
199  c->got_init = GNUNET_YES;
201  c->types = GNUNET_malloc(msize);
204  c->connectmap,
206  NULL,
208  for (unsigned int i = 0; i < c->tcnt; i++)
209  c->types[i] = ntohs(types[i]);
210  GSC_TYPEMAP_add(c->types, c->tcnt);
211  GNUNET_log(
213  "Client connecting to core service is interested in %u message types\n",
214  (unsigned int)c->tcnt);
215  /* send init reply message */
217  irm->reserved = htonl(0);
219  GNUNET_MQ_send(c->mq, env);
222 }
223 
224 
237 void
239  int drop_client)
240 {
242  GNUNET_YES ==
244  &car->target,
245  car));
246  if (GNUNET_YES == drop_client)
248  GNUNET_free(car);
249 }
250 
251 
259 void
261 {
262  struct GSC_Client *c;
263  struct GNUNET_MQ_Envelope *env;
264  struct SendMessageReady *smr;
265  struct GNUNET_TIME_Relative delay;
266  struct GNUNET_TIME_Relative left;
267 
268  c = car->client_handle;
269  if (GNUNET_YES !=
270  GNUNET_CONTAINER_multipeermap_contains(c->connectmap, &car->target))
271  {
272  /* connection has gone down since, drop request */
273  GNUNET_assert(0 != memcmp(&car->target,
275  sizeof(struct GNUNET_PeerIdentity)));
278  return;
279  }
282  if (delay.rel_value_us > GNUNET_CONSTANTS_LATENCY_WARN.rel_value_us)
283  GNUNET_log(
285  "Client waited %s for permission to transmit to `%s'%s (priority %u)\n",
287  GNUNET_i2s(&car->target),
288  (0 == left.rel_value_us) ? " (past deadline)" : "",
289  car->priority);
291  smr->size = htons(car->msize);
292  smr->smr_id = car->smr_id;
293  smr->peer = car->target;
294  GNUNET_MQ_send(c->mq, env);
295 }
296 
297 
304 static void
305 handle_client_send_request(void *cls, const struct SendMessageRequest *req)
306 {
307  struct GSC_Client *c = cls;
308  struct GSC_ClientActiveRequest *car;
309  int is_loopback;
310 
311  if (NULL == c->requests)
314  "Client asked for transmission to `%s'\n",
315  GNUNET_i2s(&req->peer));
316  is_loopback = (0 == memcmp(&req->peer,
318  sizeof(struct GNUNET_PeerIdentity)));
319  if ((!is_loopback) &&
320  (GNUNET_YES !=
322  {
323  /* neighbour must have disconnected since request was issued,
324  * ignore (client will realize it once it processes the
325  * disconnect notification) */
326  GNUNET_STATISTICS_update(GSC_stats,
327  gettext_noop(
328  "# send requests dropped (disconnected)"),
329  1,
330  GNUNET_NO);
332  return;
333  }
334 
336  if (NULL == car)
337  {
338  /* create new entry */
339  car = GNUNET_new(struct GSC_ClientActiveRequest);
342  c->requests,
343  &req->peer,
344  car,
346  car->client_handle = c;
347  }
348  else
349  {
350  /* dequeue and recycle memory from pending request, there can only
351  be at most one per client and peer */
352  GNUNET_STATISTICS_update(GSC_stats,
353  gettext_noop(
354  "# dequeuing CAR (duplicate request)"),
355  1,
356  GNUNET_NO);
359  "Transmission request to `%s' was a duplicate!\n",
360  GNUNET_i2s(&req->peer));
361  }
362  car->target = req->peer;
365  car->priority = (enum GNUNET_MQ_PriorityPreferences)ntohl(req->priority);
366  car->msize = ntohs(req->size);
367  car->smr_id = req->smr_id;
368  car->was_solicited = GNUNET_NO;
370  if (is_loopback)
371  {
372  /* loopback, satisfy immediately */
374  return;
375  }
377 }
378 
379 
388 
393 };
394 
395 
408 static int
409 tokenized_cb(void *cls, const struct GNUNET_MessageHeader *message)
410 {
411  struct TokenizerContext *tc = cls;
412  struct GSC_ClientActiveRequest *car = tc->car;
413  char buf[92];
414 
415  GNUNET_snprintf(buf,
416  sizeof(buf),
417  gettext_noop("# bytes of messages of type %u received"),
418  (unsigned int)ntohs(message->type));
419  GNUNET_STATISTICS_update(GSC_stats, buf, ntohs(message->size), GNUNET_NO);
420  if (0 == memcmp(&car->target,
422  sizeof(struct GNUNET_PeerIdentity)))
423  {
425  "Delivering message of type %u to myself\n",
426  ntohs(message->type));
428  message,
429  ntohs(message->size),
432  message,
433  sizeof(struct GNUNET_MessageHeader),
436  message,
437  ntohs(message->size),
440  message,
441  sizeof(struct GNUNET_MessageHeader),
443  }
444  else
445  {
447  "Delivering message of type %u and size %u to %s\n",
448  ntohs(message->type),
449  ntohs(message->size),
450  GNUNET_i2s(&car->target));
452  message,
453  ntohs(message->size),
456  message,
457  sizeof(struct GNUNET_MessageHeader),
459  GSC_SESSIONS_transmit(car, message, tc->priority);
460  }
461  return GNUNET_OK;
462 }
463 
464 
472 static int
473 check_client_send(void *cls, const struct SendMessage *sm)
474 {
475  return GNUNET_OK;
476 }
477 
478 
485 static void
486 handle_client_send(void *cls, const struct SendMessage *sm)
487 {
488  struct GSC_Client *c = cls;
489  struct TokenizerContext tc;
490  uint16_t msize;
491  struct GNUNET_TIME_Relative delay;
492  struct GNUNET_MessageStreamTokenizer *mst;
493 
494  msize = ntohs(sm->header.size) - sizeof(struct SendMessage);
496  if (NULL == tc.car)
497  {
498  /* Must have been that we first approved the request, then got disconnected
499  * (which triggered removal of the 'car') and now the client gives us a message
500  * just *before* the client learns about the disconnect. Theoretically, we
501  * might also now be *again* connected. So this can happen (but should be
502  * rare). If it does happen, the message is discarded. */
503  GNUNET_STATISTICS_update(GSC_stats,
504  gettext_noop(
505  "# messages discarded (session disconnected)"),
506  1,
507  GNUNET_NO);
509  return;
510  }
512  tc.priority = (enum GNUNET_MQ_PriorityPreferences)ntohl(sm->priority);
513  if (delay.rel_value_us > GNUNET_CONSTANTS_LATENCY_WARN.rel_value_us)
515  "Client waited %s for transmission of %u bytes to `%s'\n",
517  msize,
518  GNUNET_i2s(&sm->peer));
519  else
521  "Client waited %s for transmission of %u bytes to `%s'\n",
523  msize,
524  GNUNET_i2s(&sm->peer));
525 
527  GNUNET_YES ==
529  mst = GNUNET_MST_create(&tokenized_cb, &tc);
531  (const char *)&sm[1],
532  msize,
533  GNUNET_YES,
534  GNUNET_NO);
535  GNUNET_MST_destroy(mst);
537  GNUNET_free(tc.car);
539 }
540 
541 
550 static int
552  const struct GNUNET_PeerIdentity *key,
553  void *value)
554 {
555  struct GSC_ClientActiveRequest *car = value;
556 
558  GNUNET_YES ==
560  &car->target,
561  car));
563  GNUNET_free(car);
564  return GNUNET_YES;
565 }
566 
567 
576 static void *
579  struct GNUNET_MQ_Handle *mq)
580 {
581  struct GSC_Client *c;
582 
583  c = GNUNET_new(struct GSC_Client);
584  c->client = client;
585  c->mq = mq;
587  GNUNET_CONTAINER_DLL_insert(client_head, client_tail, c);
588  return c;
589 }
590 
591 
599 static void
602  void *app_ctx)
603 {
604  struct GSC_Client *c = app_ctx;
605 
607  "Client %p has disconnected from core service.\n",
608  client);
609  GNUNET_CONTAINER_DLL_remove(client_head, client_tail, c);
610  if (NULL != c->requests)
611  {
614  NULL);
616  }
618  c->connectmap = NULL;
619  if (NULL != c->types)
620  {
621  GSC_TYPEMAP_remove(c->types, c->tcnt);
622  GNUNET_free(c->types);
623  }
624  GNUNET_free(c);
625 
626  /* recalculate 'all_client_options' */
627  all_client_options = 0;
628  for (c = client_head; NULL != c; c = c->next)
630 }
631 
632 
643 void
645  struct GSC_Client *client,
646  const struct GNUNET_PeerIdentity *neighbour,
647  const struct GSC_TypeMap *tmap_old,
648  const struct GSC_TypeMap *tmap_new)
649 {
650  struct GNUNET_MQ_Envelope *env;
651  int old_match;
652  int new_match;
653 
654  if (GNUNET_YES != client->got_init)
655  return;
656  old_match = GSC_TYPEMAP_test_match(tmap_old, client->types, client->tcnt);
657  new_match = GSC_TYPEMAP_test_match(tmap_new, client->types, client->tcnt);
659  "Notifying client about neighbour %s (%d/%d)\n",
660  GNUNET_i2s(neighbour),
661  old_match,
662  new_match);
663  if (old_match == new_match)
664  {
666  old_match ==
668  return; /* no change */
669  }
670  if (GNUNET_NO == old_match)
671  {
672  struct ConnectNotifyMessage *cnm;
673 
674  /* send connect */
676  GNUNET_NO ==
680  client->connectmap,
681  neighbour,
682  NULL,
685  cnm->reserved = htonl(0);
687  "Sending NOTIFY_CONNECT message about peer %s to client.\n",
688  GNUNET_i2s(neighbour));
689  cnm->peer = *neighbour;
690  GNUNET_MQ_send(client->mq, env);
691  }
692  else
693  {
694  struct DisconnectNotifyMessage *dcm;
695 
696  /* send disconnect */
698  GNUNET_YES ==
702  neighbour,
703  NULL));
705  dcm->reserved = htonl(0);
707  "Sending NOTIFY_DISCONNECT message about peer %s to client.\n",
708  GNUNET_i2s(neighbour));
709  dcm->peer = *neighbour;
710  GNUNET_MQ_send(client->mq, env);
711  }
712 }
713 
714 
724 void
726  const struct GNUNET_PeerIdentity *neighbour,
727  const struct GSC_TypeMap *tmap_old,
728  const struct GSC_TypeMap *tmap_new)
729 {
730  struct GSC_Client *c;
731 
732  for (c = client_head; NULL != c; c = c->next)
734  neighbour,
735  tmap_old,
736  tmap_new);
737 }
738 
739 
751 void
753  const struct GNUNET_MessageHeader *msg,
754  uint16_t msize,
755  uint32_t options)
756 {
757  size_t size = msize + sizeof(struct NotifyTrafficMessage);
758 
759  if (size >= GNUNET_MAX_MESSAGE_SIZE)
760  {
761  GNUNET_break(0);
762  return;
763  }
764  if (!((0 != (all_client_options & options)) ||
765  (0 != (options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND))))
766  return; /* no client cares about this message notification */
768  "Core service passes message from `%s' of type %u to client.\n",
769  GNUNET_i2s(sender),
770  (unsigned int)ntohs(msg->type));
771  GSC_SESSIONS_add_to_typemap(sender, ntohs(msg->type));
772 
773  for (struct GSC_Client *c = client_head; NULL != c; c = c->next)
774  {
775  struct GNUNET_MQ_Envelope *env;
776  struct NotifyTrafficMessage *ntm;
777  uint16_t mtype;
778  unsigned int qlen;
779  int tm;
780 
781  tm = type_match(ntohs(msg->type), c);
782  if (!((0 != (c->options & options)) ||
783  ((0 != (options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) &&
784  (GNUNET_YES == tm))))
785  continue; /* neither options nor type match permit the message */
786  if ((0 != (options & GNUNET_CORE_OPTION_SEND_HDR_INBOUND)) &&
787  ((0 != (c->options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) ||
788  (GNUNET_YES == tm)))
789  continue;
790  if ((0 != (options & GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND)) &&
791  (0 != (c->options & GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND)))
792  continue;
793 
794  /* Drop messages if:
795  1) We are above the hard limit, or
796  2) We are above the soft limit, and a coin toss limited
797  to the message size (giving larger messages a
798  proportionally higher chance of being queued) falls
799  below the threshold. The threshold is based on where
800  we are between the soft and the hard limit, scaled
801  to match the range of message sizes we usually encounter
802  (i.e. up to 32k); so a 64k message has a 50% chance of
803  being kept if we are just barely below the hard max,
804  and a 99% chance of being kept if we are at the soft max.
805  The reason is to make it more likely to drop control traffic
806  (ACK, queries) which may be cummulative or highly redundant,
807  and cheap to drop than data traffic. */
808  qlen = GNUNET_MQ_get_length(c->mq);
809  if ((qlen >= HARD_MAX_QUEUE) ||
810  ((qlen > SOFT_MAX_QUEUE) &&
812  ntohs(msg->size))) <
813  (qlen - SOFT_MAX_QUEUE) * 0x8000 /
815  {
816  char buf[1024];
817 
818  GNUNET_log(
820  "Dropping decrypted message of type %u as client is too busy (queue full)\n",
821  (unsigned int)ntohs(msg->type));
822  GNUNET_snprintf(buf,
823  sizeof(buf),
824  gettext_noop(
825  "# messages of type %u discarded (client busy)"),
826  (unsigned int)ntohs(msg->type));
827  GNUNET_STATISTICS_update(GSC_stats, buf, 1, GNUNET_NO);
828  continue;
829  }
830 
831  GNUNET_log(
833  "Sending %u message with %u bytes to client interested in messages of type %u.\n",
834  options,
835  ntohs(msg->size),
836  (unsigned int)ntohs(msg->type));
837 
838  if (0 != (options & (GNUNET_CORE_OPTION_SEND_FULL_INBOUND |
839  GNUNET_CORE_OPTION_SEND_HDR_INBOUND)))
841  else
843  env = GNUNET_MQ_msg_extra(ntm, msize, mtype);
844  ntm->peer = *sender;
845  GNUNET_memcpy(&ntm[1], msg, msize);
846 
848  (0 == (c->options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) ||
849  (GNUNET_YES != tm) ||
850  (GNUNET_YES ==
851  GNUNET_CONTAINER_multipeermap_contains(c->connectmap, sender)));
852  GNUNET_MQ_send(c->mq, env);
853  }
854 }
855 
856 
863 static void
864 shutdown_task(void *cls)
865 {
866  struct GSC_Client *c;
867 
868  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Core service shutting down.\n");
869  while (NULL != (c = client_head))
872  GSC_KX_done();
874  if (NULL != GSC_stats)
875  {
877  GSC_stats = NULL;
878  }
879  GSC_cfg = NULL;
880 }
881 
882 
892 static void
894  const struct GNUNET_MessageHeader *message)
895 {
896  struct GSC_Client *c = cls;
897 
900 }
901 
902 
910 static void
911 run(void *cls,
912  const struct GNUNET_CONFIGURATION_Handle *c,
914 {
916  char *keyfile;
917 
918  GSC_cfg = c;
920  "PEER",
921  "PRIVATE_KEY",
922  &keyfile))
923  {
924  GNUNET_log(
926  _("Core service is lacking HOSTKEY configuration setting. Exiting.\n"));
928  return;
929  }
930  GSC_stats = GNUNET_STATISTICS_create("core", GSC_cfg);
932  GNUNET_SERVICE_suspend(service);
935  GNUNET_free(keyfile);
936  GNUNET_assert(NULL != pk);
937  if (GNUNET_OK != GSC_KX_init(pk))
938  {
940  return;
941  }
943  GNUNET_SERVICE_resume(service);
945  _("Core service of `%s' ready.\n"),
947 }
948 
949 
954  "core",
956  &run,
959  NULL,
960  GNUNET_MQ_hd_var_size(client_init,
962  struct InitMessage,
963  NULL),
964  GNUNET_MQ_hd_fixed_size(client_monitor_peers,
966  struct GNUNET_MessageHeader,
967  NULL),
968  GNUNET_MQ_hd_fixed_size(client_send_request,
970  struct SendMessageRequest,
971  NULL),
974  struct SendMessage,
975  NULL),
977 
978 
979 /* end of gnunet-service-core.c */
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
static int check_client_init(void *cls, const struct InitMessage *im)
Check GNUNET_MESSAGE_TYPE_CORE_INIT request.
uint32_t reserved
Always zero.
Definition: core.h:131
unsigned int tcnt
Number of types of incoming messages this client specifically cares about.
struct GNUNET_CONTAINER_MultiPeerMap * connectmap
Map containing all peers that this client knows we&#39;re connected to.
struct GNUNET_TIME_Absolute deadline
By what time would the client want to see this message out?
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
static struct GNUNET_CRYPTO_EddsaPrivateKey * pk
Private key of this peer.
void GSC_SESSIONS_init()
Initialize sessions subsystem.
static int tokenized_cb(void *cls, const struct GNUNET_MessageHeader *message)
Functions with this signature are called whenever a complete message is received by the tokenizer...
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
#define GNUNET_MESSAGE_TYPE_CORE_SEND
Client with message to transmit (after SEND_READY confirmation was received).
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition: time.c:671
void GSC_KX_handle_client_monitor_peers(struct GNUNET_MQ_Handle *mq)
Handle GNUNET_MESSAGE_TYPE_CORE_MONITOR_PEERS request.
uint64_t rel_value_us
The actual value.
struct GSC_Client * next
Clients are kept in a linked list.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
void GNUNET_SERVICE_resume(struct GNUNET_SERVICE_Handle *sh)
Resume accepting connections from the listen socket.
Definition: service.c:2185
Handle to a service.
Definition: service.c:114
uint32_t priority
How important is this message?
Definition: core.h:200
int GNUNET_snprintf(char *buf, size_t size, const char *format,...)
Like snprintf, just aborts if the buffer is of insufficient size.
Closure for the #client_tokenizer_callback().
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received, or when GNUNET_SCHEDULER_shutdown() is being invoked.
Definition: scheduler.c:1284
struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create(const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg)
Get handle for the statistics service.
int client_send(struct GNUNET_ATS_Session *s, struct HTTP_Message *msg)
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.
static struct GNUNET_SCHEDULER_TaskContext tc
Task context of the current task.
Definition: scheduler.c:410
static struct GSC_Client * client_head
Head of linked list of our clients.
Message sent by the service to clients to notify them about a peer connecting.
Definition: core.h:122
int was_solicited
Has this request been solicited yet?
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#define GNUNET_MQ_hd_fixed_size(name, code, str, ctx)
#define GNUNET_CONSTANTS_LATENCY_WARN
After what amount of latency for a message do we print a warning?
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
Definition: gnunet_mq_lib.h:67
int GNUNET_CONTAINER_multipeermap_remove(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, const void *value)
Remove the given key-value pair from the map.
#define GNUNET_NO
Definition: gnunet_common.h:78
#define GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND
Notify clients about incoming P2P messages.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
GNUNET_MQ_PriorityPreferences
Per envelope preferences and priorities.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT
Notify clients about peer disconnecting.
uint16_t smr_id
Unique request ID (in big endian).
uint32_t options
Options, see GNUNET_CORE_OPTION_ values.
Definition: core.h:92
struct GNUNET_PeerIdentity my_identity
Public key of the local peer.
Definition: core.h:114
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
void GNUNET_STATISTICS_destroy(struct GNUNET_STATISTICS_Handle *h, int sync_first)
Destroy a handle (free all state associated with it).
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
void GSC_SESSIONS_queue_request(struct GSC_ClientActiveRequest *car)
Queue a request from a client for transmission to a particular peer.
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:517
struct GNUNET_CONTAINER_MultiPeerMap * GNUNET_CONTAINER_multipeermap_create(unsigned int len, int do_not_copy_keys)
Create a multi peer map (hash map for public keys of peers).
struct GNUNET_STATISTICS_Handle * GSC_stats
For creating statistics.
Handle for the service.
struct GNUNET_PeerIdentity peer
Identity of the intended target.
Definition: core.h:211
Message transmitted core clients to gnunet-service-core to start the interaction. ...
Definition: core.h:83
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
void GNUNET_CONTAINER_multipeermap_destroy(struct GNUNET_CONTAINER_MultiPeerMap *map)
Destroy a hash map.
management of map that specifies which message types this peer supports
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
Message transmitted by the gnunet-service-core process to its clients in response to an INIT message...
Definition: core.h:100
#define GNUNET_MESSAGE_TYPE_CORE_MONITOR_PEERS
Request for connection monitoring from CORE service.
Handle to a client that is connected to a service.
Definition: service.c:246
void GSC_CLIENTS_reject_request(struct GSC_ClientActiveRequest *car, int drop_client)
We will never be ready to transmit the given message in (disconnect or invalid request).
#define GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST
Request from client to transmit message.
static void shutdown_task(void *cls)
Last task run during shutdown.
Data structure for each client connected to the CORE service.
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct...
Definition: gnunet_mq_lib.h:52
#define GNUNET_MESSAGE_TYPE_CORE_INIT
Initial setup message from core client to core.
#define SOFT_MAX_QUEUE
How many messages do we queue up at most for any client? This can cause messages to be dropped if cli...
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
Core notifying client that it is allowed to now transmit a message to the given target (response to G...
Definition: core.h:235
, &#39; bother checking if a value already exists (faster than GNUNET_CONTAINER_MULTIHASHMAPOPTION_...
static char * value
Value of the record to add/remove.
uint16_t size
How large is the message?
Definition: core.h:221
enum GNUNET_MQ_PriorityPreferences priority
How important is this request.
void GNUNET_MST_destroy(struct GNUNET_MessageStreamTokenizer *mst)
Destroys a tokenizer.
Definition: mst.c:410
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
unsigned int GNUNET_MQ_get_length(struct GNUNET_MQ_Handle *mq)
Obtain the current length of the message queue.
Definition: mq.c:333
static void handle_client_send(void *cls, const struct SendMessage *sm)
Handle GNUNET_MESSAGE_TYPE_CORE_SEND request.
static void handle_client_monitor_peers(void *cls, const struct GNUNET_MessageHeader *message)
Handle GNUNET_MESSAGE_TYPE_CORE_MONITOR_PEERS request.
uint16_t smr_id
Counter for this peer to match SMRs to replies.
Definition: core.h:226
Client asking core to transmit a particular message to a particular target (response to GNUNET_MESSAG...
Definition: core.h:265
struct GNUNET_CONTAINER_MultiPeerMap * requests
Map of peer identities to active transmission requests of this client to the peer (of type struct GSC...
struct GNUNET_PeerIdentity peer
Identity of the intended receiver.
Definition: core.h:286
Handle to a message stream tokenizer.
Definition: mst.c:43
const char * GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition: strings.c:686
#define GNUNET_CORE_OPTION_SEND_FULL_INBOUND
Client wants all inbound messages in full.
Definition: core.h:55
static char buf[2048]
struct GNUNET_MessageStreamTokenizer * GNUNET_MST_create(GNUNET_MessageTokenizerCallback cb, void *cb_cls)
Create a message stream tokenizer.
Definition: mst.c:84
Record kept for each request for transmission issued by a client that is still pending.
int 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:113
static int check_client_send(void *cls, const struct SendMessage *sm)
Check GNUNET_MESSAGE_TYPE_CORE_SEND request.
Client notifying core about the maximum-priority message it has in the queue for a particular target...
Definition: core.h:191
struct GNUNET_PeerIdentity peer
Identity of the connecting peer.
Definition: core.h:136
int GSC_KX_init(struct GNUNET_CRYPTO_EddsaPrivateKey *pk)
Initialize KX subsystem.
Internal representation of the hash map.
struct GSC_ClientActiveRequest * car
Active request handle for the message.
static void run(void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_SERVICE_Handle *service)
Initiate core service.
enum GNUNET_MQ_PriorityPreferences priority
How important is this message.
void GSC_CLIENTS_deliver_message(const struct GNUNET_PeerIdentity *sender, const struct GNUNET_MessageHeader *msg, uint16_t msize, uint32_t options)
Deliver P2P message to interested clients.
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition: service.c:2315
Globals for gnunet-service-core.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:118
void GSC_TYPEMAP_init()
Initialize typemap subsystem.
struct GNUNET_PeerIdentity GSC_my_identity
Our identity.
#define GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND
Client wants all outbound messages in full.
Definition: core.h:66
There must only be one value per key; storing a value should fail if a value under the same key alrea...
struct GNUNET_HashCode key
The key used in the DHT.
static unsigned int size
Size of the "table".
Definition: peer.c:66
void GSC_CLIENTS_notify_client_about_neighbour(struct GSC_Client *client, const struct GNUNET_PeerIdentity *neighbour, const struct GSC_TypeMap *tmap_old, const struct GSC_TypeMap *tmap_new)
Notify a particular client about a change to existing connection to one of our neighbours (check if t...
#define GNUNET_MESSAGE_TYPE_CORE_SEND_READY
Confirmation from core that message can now be sent.
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
#define GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT
Notify clients about new peer-to-peer connections (triggered after key exchange). ...
void GSC_SESSIONS_done()
Shutdown sessions subsystem.
code for managing the key exchange (SET_KEY, PING, PONG) with other peers
#define GNUNET_MAX_MESSAGE_SIZE
Largest supported message (to be precise, one byte more than the largest possible message...
static void * client_connect_cb(void *cls, struct GNUNET_SERVICE_Client *client, struct GNUNET_MQ_Handle *mq)
A client connected, set up.
uint16_t smr_id
smr_id from the request.
Definition: core.h:252
Handle to a message queue.
Definition: mq.c:84
int GNUNET_CONTAINER_multipeermap_put(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
struct GNUNET_MessageHeader header
Header with type GNUNET_MESSAGE_TYPE_CORE_SEND.
Definition: core.h:269
Private ECC key encoded for transmission.
void GSC_CLIENTS_solicit_request(struct GSC_ClientActiveRequest *car)
Tell a client that we are ready to receive the message.
static void handle_client_send_request(void *cls, const struct SendMessageRequest *req)
Handle GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST message.
int GNUNET_CONTAINER_multipeermap_iterate(struct GNUNET_CONTAINER_MultiPeerMap *map, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map.
static struct GSC_Client * client_tail
Tail of linked list of our clients.
The identity of the host (wraps the signing key of the peer).
int GSC_TYPEMAP_test_match(const struct GSC_TypeMap *tmap, const uint16_t *types, unsigned int tcnt)
Test if any of the types from the types array is in the given type map.
struct GSC_Client * client_handle
Handle to the client.
#define GNUNET_MESSAGE_TYPE_CORE_NOTIFY_OUTBOUND
Notify clients about outgoing P2P transmissions.
uint32_t reserved
Always zero.
Definition: core.h:153
void GSC_TYPEMAP_done()
Shutdown typemap subsystem.
uint16_t * types
Array of the types of messages this peer cares about (with tcnt entries).
configuration data
Definition: configuration.c:83
static int type_match(uint16_t type, struct GSC_Client *c)
Test if the client is interested in messages of the given type.
uint32_t priority
How important is this message? Contains a enum GNUNET_MQ_PriorityPreferences in NBO.
Definition: core.h:275
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
struct GNUNET_MessageHeader header
Header with type GNUNET_MESSAGE_TYPE_CORE_INIT.
Definition: core.h:87
void GSC_SESSIONS_notify_client_about_sessions(struct GSC_Client *client)
We have a new client, notify it about all current sessions.
void * GNUNET_CONTAINER_multipeermap_get(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key)
Given a key find a value in the map matching the key.
struct GNUNET_SERVICE_Client * client
Handle for the client with the server API.
#define GNUNET_log(kind,...)
void GSC_SESSIONS_transmit(struct GSC_ClientActiveRequest *car, const struct GNUNET_MessageHeader *msg, enum GNUNET_MQ_PriorityPreferences priority)
Transmit a message to a particular peer.
GNUNET_SERVICE_MAIN("core", GNUNET_SERVICE_OPTION_NONE, &run, &client_connect_cb, &client_disconnect_cb, NULL, GNUNET_MQ_hd_var_size(client_init, GNUNET_MESSAGE_TYPE_CORE_INIT, struct InitMessage, NULL), GNUNET_MQ_hd_fixed_size(client_monitor_peers, GNUNET_MESSAGE_TYPE_CORE_MONITOR_PEERS, struct GNUNET_MessageHeader, NULL), GNUNET_MQ_hd_fixed_size(client_send_request, GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST, struct SendMessageRequest, NULL), GNUNET_MQ_hd_var_size(client_send, GNUNET_MESSAGE_TYPE_CORE_SEND, struct SendMessage, NULL), GNUNET_MQ_handler_end())
Define "main" method using service macro.
A type map describing which messages a given neighbour is able to process.
struct GNUNET_CRYPTO_EddsaPrivateKey * GNUNET_CRYPTO_eddsa_key_create_from_file(const char *filename)
Create a new private key by reading it from a file.
int GNUNET_CONFIGURATION_get_value_filename(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be the name of a file or directory.
void GSC_TYPEMAP_remove(const uint16_t *types, unsigned int tlen)
Remove a set of types from our type map.
static void handle_client_init(void *cls, const struct InitMessage *im)
Handle GNUNET_MESSAGE_TYPE_CORE_INIT request.
void GSC_SESSIONS_dequeue_request(struct GSC_ClientActiveRequest *car)
Dequeue a request from a client from transmission to a particular peer.
void GSC_SESSIONS_add_to_typemap(const struct GNUNET_PeerIdentity *peer, uint16_t type)
The given peer send a message of the specified type.
Message sent by the service to clients to notify them about a peer disconnecting. ...
Definition: core.h:144
struct GSC_Client * prev
Clients are kept in a linked list.
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model
Message sent by the service to clients to notify them about messages being received or transmitted...
Definition: core.h:171
struct GNUNET_PeerIdentity peer
Identity of the connecting peer.
Definition: core.h:158
Header for all communications.
static uint32_t all_client_options
Big "or" of all client options.
#define GNUNET_YES
Definition: gnunet_common.h:77
uint32_t reserved
Always zero.
Definition: core.h:109
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition: mq.c:351
struct GNUNET_TIME_Absolute received_time
At what time did we first see this request?
static int destroy_active_client_request(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Free client request records.
#define GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND
Client just wants the 4-byte message headers of all outbound messages.
Definition: core.h:72
void GNUNET_SERVICE_suspend(struct GNUNET_SERVICE_Handle *sh)
Suspend accepting connections from the listen socket temporarily.
Definition: service.c:2173
struct GNUNET_PeerIdentity target
Which peer is the message going to be for?
uint32_t options
Options for messages this client cares about, see GNUNET_CORE_OPTION_ values.
struct GNUNET_TIME_AbsoluteNBO deadline
By what time would the sender really like to see this message transmitted?
Definition: core.h:206
#define GNUNET_CORE_OPTION_SEND_HDR_INBOUND
Client just wants the 4-byte message headers of all inbound messages.
Definition: core.h:61
int GNUNET_CONTAINER_multipeermap_contains(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key)
Check if the map contains any value under the given key (including values that are NULL)...
#define HARD_MAX_QUEUE
How many messages do we queue up at most for any client? This can cause messages to be dropped if cli...
struct GNUNET_PeerIdentity peer
Identity of the intended target.
Definition: core.h:257
#define GNUNET_MESSAGE_TYPE_CORE_INIT_REPLY
Response from core to core client to INIT message.
uint16_t size
How many bytes are allowed for transmission? Guaranteed to be at least as big as the requested size...
Definition: core.h:247
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2234
void GSC_KX_done()
Shutdown KX subsystem.
uint16_t msize
How many bytes does the client intend to send?
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
struct GNUNET_PeerIdentity peer
Identity of the receiver or sender.
Definition: core.h:181
const struct GNUNET_CONFIGURATION_Handle * GSC_cfg
Our configuration.
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).
#define GNUNET_malloc(size)
Wrapper around malloc.
void GSC_CLIENTS_notify_clients_about_neighbour(const struct GNUNET_PeerIdentity *neighbour, const struct GSC_TypeMap *tmap_old, const struct GSC_TypeMap *tmap_new)
Notify all clients about a change to existing session.
void GSC_TYPEMAP_add(const uint16_t *types, unsigned int tlen)
Add a set of types to our type map.
struct GNUNET_MQ_Handle * mq
Message queue to talk to client.
#define GNUNET_free(ptr)
Wrapper around free.
int got_init
Have we gotten the GNUNET_MESSAGE_TYPE_CORE_INIT message from this client already?
static void client_disconnect_cb(void *cls, struct GNUNET_SERVICE_Client *client, void *app_ctx)
A client disconnected, clean up.
Time for relative time used by GNUnet, in microseconds.
#define gettext_noop(String)
Definition: gettext.h:69