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
54 {
58  struct GSC_Client *next;
59 
63  struct GSC_Client *prev;
64 
69 
74 
80  uint16_t *types;
81 
87 
92 
97  uint32_t options;
98 
103  int got_init;
104 
109  unsigned int tcnt;
110 };
111 
112 
117 
122 
127 
131 static uint32_t all_client_options;
132 
136 static struct GSC_Client *client_head;
137 
141 static struct GSC_Client *client_tail;
142 
143 
151 static int
152 type_match (uint16_t type, struct GSC_Client *c)
153 {
154  if ((0 == c->tcnt) && (0 != c->options))
155  return GNUNET_YES; /* peer without handlers and inbound/outbond
156  callbacks matches ALL */
157  if (NULL == c->types)
158  return GNUNET_NO;
159  for (unsigned int i = 0; i < c->tcnt; i++)
160  if (type == c->types[i])
161  return GNUNET_YES;
162  return GNUNET_NO;
163 }
164 
165 
173 static int
174 check_client_init (void *cls, const struct InitMessage *im)
175 {
176  return GNUNET_OK;
177 }
178 
179 
186 static void
187 handle_client_init (void *cls, const struct InitMessage *im)
188 {
189  struct GSC_Client *c = cls;
190  struct GNUNET_MQ_Envelope *env;
191  struct InitReplyMessage *irm;
192  uint16_t msize;
193  const uint16_t *types;
194 
195  /* check that we don't have an entry already */
196  msize = ntohs (im->header.size) - sizeof (struct InitMessage);
197  types = (const uint16_t *) &im[1];
198  c->tcnt = msize / sizeof (uint16_t);
199  c->options = ntohl (im->options);
200  c->got_init = GNUNET_YES;
202  c->types = GNUNET_malloc (msize);
205  c->connectmap,
207  NULL,
209  for (unsigned int i = 0; i < c->tcnt; i++)
210  c->types[i] = ntohs (types[i]);
211  GSC_TYPEMAP_add (c->types, c->tcnt);
212  GNUNET_log (
214  "Client connecting to core service is interested in %u message types\n",
215  (unsigned int) c->tcnt);
216  /* send init reply message */
218  irm->reserved = htonl (0);
220  GNUNET_MQ_send (c->mq, env);
223 }
224 
225 
238 void
240  int drop_client)
241 {
242  GNUNET_assert (
243  GNUNET_YES ==
245  &car->target,
246  car));
247  if (GNUNET_YES == drop_client)
249  GNUNET_free (car);
250 }
251 
252 
260 void
262 {
263  struct GSC_Client *c;
264  struct GNUNET_MQ_Envelope *env;
265  struct SendMessageReady *smr;
266  struct GNUNET_TIME_Relative delay;
267  struct GNUNET_TIME_Relative left;
268 
269  c = car->client_handle;
270  if (GNUNET_YES !=
271  GNUNET_CONTAINER_multipeermap_contains (c->connectmap, &car->target))
272  {
273  /* connection has gone down since, drop request */
274  GNUNET_assert (0 != memcmp (&car->target,
276  sizeof (struct GNUNET_PeerIdentity)));
279  return;
280  }
283  if (delay.rel_value_us > GNUNET_CONSTANTS_LATENCY_WARN.rel_value_us)
284  GNUNET_log (
286  "Client waited %s for permission to transmit to `%s'%s (priority %u)\n",
288  GNUNET_i2s (&car->target),
289  (0 == left.rel_value_us) ? " (past deadline)" : "",
290  car->priority);
292  smr->size = htons (car->msize);
293  smr->smr_id = car->smr_id;
294  smr->peer = car->target;
295  GNUNET_MQ_send (c->mq, env);
296 }
297 
298 
305 static void
306 handle_client_send_request (void *cls, const struct SendMessageRequest *req)
307 {
308  struct GSC_Client *c = cls;
309  struct GSC_ClientActiveRequest *car;
310  int is_loopback;
311 
312  if (NULL == c->requests)
315  "Client asked for transmission to `%s'\n",
316  GNUNET_i2s (&req->peer));
317  is_loopback = (0 == memcmp (&req->peer,
319  sizeof (struct GNUNET_PeerIdentity)));
320  if ((! is_loopback) &&
321  (GNUNET_YES !=
323  {
324  /* neighbour must have disconnected since request was issued,
325  * ignore (client will realize it once it processes the
326  * disconnect notification) */
327  GNUNET_STATISTICS_update (GSC_stats,
328  gettext_noop (
329  "# send requests dropped (disconnected)"),
330  1,
331  GNUNET_NO);
333  return;
334  }
335 
337  if (NULL == car)
338  {
339  /* create new entry */
340  car = GNUNET_new (struct GSC_ClientActiveRequest);
343  c->requests,
344  &req->peer,
345  car,
347  car->client_handle = c;
348  }
349  else
350  {
351  /* dequeue and recycle memory from pending request, there can only
352  be at most one per client and peer */
353  GNUNET_STATISTICS_update (GSC_stats,
354  gettext_noop (
355  "# dequeuing CAR (duplicate request)"),
356  1,
357  GNUNET_NO);
360  "Transmission request to `%s' was a duplicate!\n",
361  GNUNET_i2s (&req->peer));
362  }
363  car->target = req->peer;
366  car->priority = (enum GNUNET_MQ_PriorityPreferences) ntohl (req->priority);
367  car->msize = ntohs (req->size);
368  car->smr_id = req->smr_id;
369  car->was_solicited = GNUNET_NO;
371  if (is_loopback)
372  {
373  /* loopback, satisfy immediately */
375  return;
376  }
378 }
379 
380 
385 {
386 
391 
396 };
397 
398 
411 static int
412 tokenized_cb (void *cls, const struct GNUNET_MessageHeader *message)
413 {
414  struct TokenizerContext *tc = cls;
415  struct GSC_ClientActiveRequest *car = tc->car;
416  char buf[92];
417 
418  GNUNET_snprintf (buf,
419  sizeof (buf),
420  gettext_noop ("# bytes of messages of type %u received"),
421  (unsigned int) ntohs (message->type));
422  GNUNET_STATISTICS_update (GSC_stats, buf, ntohs (message->size), GNUNET_NO);
423  if (0 == memcmp (&car->target,
425  sizeof (struct GNUNET_PeerIdentity)))
426  {
428  "Delivering message of type %u to myself\n",
429  ntohs (message->type));
431  message,
432  ntohs (message->size),
435  message,
436  sizeof (struct GNUNET_MessageHeader),
439  message,
440  ntohs (message->size),
443  message,
444  sizeof (struct GNUNET_MessageHeader),
446  }
447  else
448  {
450  "Delivering message of type %u and size %u to %s\n",
451  ntohs (message->type),
452  ntohs (message->size),
453  GNUNET_i2s (&car->target));
455  message,
456  ntohs (message->size),
459  message,
460  sizeof (struct GNUNET_MessageHeader),
462  GSC_SESSIONS_transmit (car, message, tc->priority);
463  }
464  return GNUNET_OK;
465 }
466 
467 
475 static int
476 check_client_send (void *cls, const struct SendMessage *sm)
477 {
478  return GNUNET_OK;
479 }
480 
481 
488 static void
489 handle_client_send (void *cls, const struct SendMessage *sm)
490 {
491  struct GSC_Client *c = cls;
492  struct TokenizerContext tc;
493  uint16_t msize;
494  struct GNUNET_TIME_Relative delay;
495  struct GNUNET_MessageStreamTokenizer *mst;
496 
497  msize = ntohs (sm->header.size) - sizeof (struct SendMessage);
499  if (NULL == tc.car)
500  {
501  /* Must have been that we first approved the request, then got disconnected
502  * (which triggered removal of the 'car') and now the client gives us a message
503  * just *before* the client learns about the disconnect. Theoretically, we
504  * might also now be *again* connected. So this can happen (but should be
505  * rare). If it does happen, the message is discarded. */
506  GNUNET_STATISTICS_update (GSC_stats,
507  gettext_noop (
508  "# messages discarded (session disconnected)"),
509  1,
510  GNUNET_NO);
512  return;
513  }
515  tc.priority = (enum GNUNET_MQ_PriorityPreferences) ntohl (sm->priority);
516  if (delay.rel_value_us > GNUNET_CONSTANTS_LATENCY_WARN.rel_value_us)
518  "Client waited %s for transmission of %u bytes to `%s'\n",
520  msize,
521  GNUNET_i2s (&sm->peer));
522  else
524  "Client waited %s for transmission of %u bytes to `%s'\n",
526  msize,
527  GNUNET_i2s (&sm->peer));
528 
529  GNUNET_assert (
530  GNUNET_YES ==
532  mst = GNUNET_MST_create (&tokenized_cb, &tc);
534  (const char *) &sm[1],
535  msize,
536  GNUNET_YES,
537  GNUNET_NO);
538  GNUNET_MST_destroy (mst);
540  GNUNET_free (tc.car);
542 }
543 
544 
553 static int
555  const struct GNUNET_PeerIdentity *key,
556  void *value)
557 {
558  struct GSC_ClientActiveRequest *car = value;
559 
560  GNUNET_assert (
561  GNUNET_YES ==
563  &car->target,
564  car));
566  GNUNET_free (car);
567  return GNUNET_YES;
568 }
569 
570 
579 static void *
580 client_connect_cb (void *cls,
582  struct GNUNET_MQ_Handle *mq)
583 {
584  struct GSC_Client *c;
585 
586  c = GNUNET_new (struct GSC_Client);
587  c->client = client;
588  c->mq = mq;
590  GNUNET_CONTAINER_DLL_insert (client_head, client_tail, c);
591  return c;
592 }
593 
594 
602 static void
605  void *app_ctx)
606 {
607  struct GSC_Client *c = app_ctx;
608 
610  "Client %p has disconnected from core service.\n",
611  client);
612  GNUNET_CONTAINER_DLL_remove (client_head, client_tail, c);
613  if (NULL != c->requests)
614  {
617  NULL);
619  }
621  c->connectmap = NULL;
622  if (NULL != c->types)
623  {
624  GSC_TYPEMAP_remove (c->types, c->tcnt);
625  GNUNET_free (c->types);
626  }
627  GNUNET_free (c);
628 
629  /* recalculate 'all_client_options' */
630  all_client_options = 0;
631  for (c = client_head; NULL != c; c = c->next)
633 }
634 
635 
646 void
648  struct GSC_Client *client,
649  const struct GNUNET_PeerIdentity *neighbour,
650  const struct GSC_TypeMap *tmap_old,
651  const struct GSC_TypeMap *tmap_new)
652 {
653  struct GNUNET_MQ_Envelope *env;
654  int old_match;
655  int new_match;
656 
657  if (GNUNET_YES != client->got_init)
658  return;
659  old_match = GSC_TYPEMAP_test_match (tmap_old, client->types, client->tcnt);
660  new_match = GSC_TYPEMAP_test_match (tmap_new, client->types, client->tcnt);
662  "Notifying client about neighbour %s (%d/%d)\n",
663  GNUNET_i2s (neighbour),
664  old_match,
665  new_match);
666  if (old_match == new_match)
667  {
668  GNUNET_assert (
669  old_match ==
671  return; /* no change */
672  }
673  if (GNUNET_NO == old_match)
674  {
675  struct ConnectNotifyMessage *cnm;
676 
677  /* send connect */
678  GNUNET_assert (
679  GNUNET_NO ==
683  client->connectmap,
684  neighbour,
685  NULL,
688  cnm->reserved = htonl (0);
690  "Sending NOTIFY_CONNECT message about peer %s to client.\n",
691  GNUNET_i2s (neighbour));
692  cnm->peer = *neighbour;
693  GNUNET_MQ_send (client->mq, env);
694  }
695  else
696  {
697  struct DisconnectNotifyMessage *dcm;
698 
699  /* send disconnect */
700  GNUNET_assert (
701  GNUNET_YES ==
705  neighbour,
706  NULL));
708  dcm->reserved = htonl (0);
710  "Sending NOTIFY_DISCONNECT message about peer %s to client.\n",
711  GNUNET_i2s (neighbour));
712  dcm->peer = *neighbour;
713  GNUNET_MQ_send (client->mq, env);
714  }
715 }
716 
717 
727 void
729  const struct GNUNET_PeerIdentity *neighbour,
730  const struct GSC_TypeMap *tmap_old,
731  const struct GSC_TypeMap *tmap_new)
732 {
733  struct GSC_Client *c;
734 
735  for (c = client_head; NULL != c; c = c->next)
737  neighbour,
738  tmap_old,
739  tmap_new);
740 }
741 
742 
754 void
756  const struct GNUNET_MessageHeader *msg,
757  uint16_t msize,
758  uint32_t options)
759 {
760  size_t size = msize + sizeof (struct NotifyTrafficMessage);
761 
762  if (size >= GNUNET_MAX_MESSAGE_SIZE)
763  {
764  GNUNET_break (0);
765  return;
766  }
767  if (! ((0 != (all_client_options & options)) ||
768  (0 != (options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND))))
769  return; /* no client cares about this message notification */
771  "Core service passes message from `%s' of type %u to client.\n",
772  GNUNET_i2s (sender),
773  (unsigned int) ntohs (msg->type));
774  GSC_SESSIONS_add_to_typemap (sender, ntohs (msg->type));
775 
776  for (struct GSC_Client *c = client_head; NULL != c; c = c->next)
777  {
778  struct GNUNET_MQ_Envelope *env;
779  struct NotifyTrafficMessage *ntm;
780  uint16_t mtype;
781  unsigned int qlen;
782  int tm;
783 
784  tm = type_match (ntohs (msg->type), c);
785  if (! ((0 != (c->options & options)) ||
786  ((0 != (options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) &&
787  (GNUNET_YES == tm))))
788  continue; /* neither options nor type match permit the message */
789  if ((0 != (options & GNUNET_CORE_OPTION_SEND_HDR_INBOUND)) &&
790  ((0 != (c->options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) ||
791  (GNUNET_YES == tm)))
792  continue;
793  if ((0 != (options & GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND)) &&
794  (0 != (c->options & GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND)))
795  continue;
796 
797  /* Drop messages if:
798  1) We are above the hard limit, or
799  2) We are above the soft limit, and a coin toss limited
800  to the message size (giving larger messages a
801  proportionally higher chance of being queued) falls
802  below the threshold. The threshold is based on where
803  we are between the soft and the hard limit, scaled
804  to match the range of message sizes we usually encounter
805  (i.e. up to 32k); so a 64k message has a 50% chance of
806  being kept if we are just barely below the hard max,
807  and a 99% chance of being kept if we are at the soft max.
808  The reason is to make it more likely to drop control traffic
809  (ACK, queries) which may be cummulative or highly redundant,
810  and cheap to drop than data traffic. */
811  qlen = GNUNET_MQ_get_length (c->mq);
812  if ((qlen >= HARD_MAX_QUEUE) ||
813  ((qlen > SOFT_MAX_QUEUE) &&
815  ntohs (msg->size))) <
816  (qlen - SOFT_MAX_QUEUE) * 0x8000 /
818  {
819  char buf[1024];
820 
821  GNUNET_log (
823  "Dropping decrypted message of type %u as client is too busy (queue full)\n",
824  (unsigned int) ntohs (msg->type));
825  GNUNET_snprintf (buf,
826  sizeof (buf),
827  gettext_noop (
828  "# messages of type %u discarded (client busy)"),
829  (unsigned int) ntohs (msg->type));
830  GNUNET_STATISTICS_update (GSC_stats, buf, 1, GNUNET_NO);
831  continue;
832  }
833 
834  GNUNET_log (
836  "Sending %u message with %u bytes to client interested in messages of type %u.\n",
837  options,
838  ntohs (msg->size),
839  (unsigned int) ntohs (msg->type));
840 
841  if (0 != (options & (GNUNET_CORE_OPTION_SEND_FULL_INBOUND |
842  GNUNET_CORE_OPTION_SEND_HDR_INBOUND)))
844  else
846  env = GNUNET_MQ_msg_extra (ntm, msize, mtype);
847  ntm->peer = *sender;
848  GNUNET_memcpy (&ntm[1], msg, msize);
849 
850  GNUNET_assert (
851  (0 == (c->options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) ||
852  (GNUNET_YES != tm) ||
853  (GNUNET_YES ==
854  GNUNET_CONTAINER_multipeermap_contains (c->connectmap, sender)));
855  GNUNET_MQ_send (c->mq, env);
856  }
857 }
858 
859 
866 static void
867 shutdown_task (void *cls)
868 {
869  struct GSC_Client *c;
870 
871  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Core service shutting down.\n");
872  while (NULL != (c = client_head))
875  GSC_KX_done ();
876  GSC_TYPEMAP_done ();
877  if (NULL != GSC_stats)
878  {
880  GSC_stats = NULL;
881  }
882  GSC_cfg = NULL;
883 }
884 
885 
895 static void
897  const struct GNUNET_MessageHeader *message)
898 {
899  struct GSC_Client *c = cls;
900 
903 }
904 
905 
913 static void
914 run (void *cls,
915  const struct GNUNET_CONFIGURATION_Handle *c,
917 {
919  char *keyfile;
920 
921  GSC_cfg = c;
923  "PEER",
924  "PRIVATE_KEY",
925  &keyfile))
926  {
927  GNUNET_log (
929  _ ("Core service is lacking HOSTKEY configuration setting. Exiting.\n"));
931  return;
932  }
933  GSC_stats = GNUNET_STATISTICS_create ("core", GSC_cfg);
935  GNUNET_SERVICE_suspend (service);
936  GSC_TYPEMAP_init ();
938  GNUNET_free (keyfile);
939  GNUNET_assert (NULL != pk);
940  if (GNUNET_OK != GSC_KX_init (pk))
941  {
943  return;
944  }
946  GNUNET_SERVICE_resume (service);
948  _ ("Core service of `%s' ready.\n"),
950 }
951 
952 
957  "core",
959  &run,
962  NULL,
963  GNUNET_MQ_hd_var_size (client_init,
965  struct InitMessage,
966  NULL),
967  GNUNET_MQ_hd_fixed_size (client_monitor_peers,
969  struct GNUNET_MessageHeader,
970  NULL),
971  GNUNET_MQ_hd_fixed_size (client_send_request,
973  struct SendMessageRequest,
974  NULL),
977  struct SendMessage,
978  NULL),
980 
981 
982 /* 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:136
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:670
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:2481
Handle to a service.
Definition: service.c:116
uint32_t priority
How important is this message?
Definition: core.h:208
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:1293
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:417
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:126
int was_solicited
Has this request been solicited yet?
#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:81
#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:78
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:94
struct GNUNET_PeerIdentity my_identity
Public key of the local peer.
Definition: core.h:118
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:524
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:219
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:208
Message transmitted by the gnunet-service-core process to its clients in response to an INIT message...
Definition: core.h:102
#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:249
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:243
#define GNUNET_memcpy(dst, src, n)
, &#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:229
enum GNUNET_MQ_PriorityPreferences priority
How important is this request.
void GNUNET_MST_destroy(struct GNUNET_MessageStreamTokenizer *mst)
Destroys a tokenizer.
Definition: mst.c:413
#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:335
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:234
Client asking core to transmit a particular message to a particular target (response to GNUNET_MESSAG...
Definition: core.h:274
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:296
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:727
#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:87
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:116
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:198
struct GNUNET_PeerIdentity peer
Identity of the connecting peer.
Definition: core.h:141
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:2618
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:67
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:261
Handle to a message queue.
Definition: mq.c:85
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:279
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:159
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:85
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:285
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:89
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:149
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:177
struct GNUNET_PeerIdentity peer
Identity of the connecting peer.
Definition: core.h:164
Header for all communications.
static uint32_t all_client_options
Big "or" of all client options.
#define GNUNET_YES
Definition: gnunet_common.h:80
uint32_t reserved
Always zero.
Definition: core.h:113
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:353
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:2468
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:214
#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:266
#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:256
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:2533
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:188
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