GNUnet  0.11.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 {
390 
395 };
396 
397 
410 static int
411 tokenized_cb (void *cls, const struct GNUNET_MessageHeader *message)
412 {
413  struct TokenizerContext *tc = cls;
414  struct GSC_ClientActiveRequest *car = tc->car;
415  char buf[92];
416 
417  GNUNET_snprintf (buf,
418  sizeof(buf),
419  gettext_noop ("# bytes of messages of type %u received"),
420  (unsigned int) ntohs (message->type));
421  GNUNET_STATISTICS_update (GSC_stats, buf, ntohs (message->size), GNUNET_NO);
422  if (0 == memcmp (&car->target,
424  sizeof(struct GNUNET_PeerIdentity)))
425  {
427  "Delivering message of type %u to myself\n",
428  ntohs (message->type));
430  message,
431  ntohs (message->size),
434  message,
435  sizeof(struct GNUNET_MessageHeader),
438  message,
439  ntohs (message->size),
442  message,
443  sizeof(struct GNUNET_MessageHeader),
445  }
446  else
447  {
449  "Delivering message of type %u and size %u to %s\n",
450  ntohs (message->type),
451  ntohs (message->size),
452  GNUNET_i2s (&car->target));
454  message,
455  ntohs (message->size),
458  message,
459  sizeof(struct GNUNET_MessageHeader),
461  GSC_SESSIONS_transmit (car, message, tc->priority);
462  }
463  return GNUNET_OK;
464 }
465 
466 
474 static int
475 check_client_send (void *cls, const struct SendMessage *sm)
476 {
477  return GNUNET_OK;
478 }
479 
480 
487 static void
488 handle_client_send (void *cls, const struct SendMessage *sm)
489 {
490  struct GSC_Client *c = cls;
491  struct TokenizerContext tc;
492  uint16_t msize;
493  struct GNUNET_TIME_Relative delay;
494  struct GNUNET_MessageStreamTokenizer *mst;
495 
496  msize = ntohs (sm->header.size) - sizeof(struct SendMessage);
498  if (NULL == tc.car)
499  {
500  /* Must have been that we first approved the request, then got disconnected
501  * (which triggered removal of the 'car') and now the client gives us a message
502  * just *before* the client learns about the disconnect. Theoretically, we
503  * might also now be *again* connected. So this can happen (but should be
504  * rare). If it does happen, the message is discarded. */GNUNET_STATISTICS_update (GSC_stats,
505  gettext_noop (
506  "# messages discarded (session disconnected)"),
507  1,
508  GNUNET_NO);
510  return;
511  }
513  tc.priority = (enum GNUNET_MQ_PriorityPreferences) ntohl (sm->priority);
514  if (delay.rel_value_us > GNUNET_CONSTANTS_LATENCY_WARN.rel_value_us)
516  "Client waited %s for transmission of %u bytes to `%s'\n",
518  msize,
519  GNUNET_i2s (&sm->peer));
520  else
522  "Client waited %s for transmission of %u bytes to `%s'\n",
524  msize,
525  GNUNET_i2s (&sm->peer));
526 
527  GNUNET_assert (
528  GNUNET_YES ==
530  mst = GNUNET_MST_create (&tokenized_cb, &tc);
532  (const char *) &sm[1],
533  msize,
534  GNUNET_YES,
535  GNUNET_NO);
536  GNUNET_MST_destroy (mst);
538  GNUNET_free (tc.car);
540 }
541 
542 
551 static int
553  const struct GNUNET_PeerIdentity *key,
554  void *value)
555 {
556  struct GSC_ClientActiveRequest *car = value;
557 
558  GNUNET_assert (
559  GNUNET_YES ==
561  &car->target,
562  car));
564  GNUNET_free (car);
565  return GNUNET_YES;
566 }
567 
568 
577 static void *
578 client_connect_cb (void *cls,
580  struct GNUNET_MQ_Handle *mq)
581 {
582  struct GSC_Client *c;
583 
584  c = GNUNET_new (struct GSC_Client);
585  c->client = client;
586  c->mq = mq;
588  GNUNET_CONTAINER_DLL_insert (client_head, client_tail, c);
589  return c;
590 }
591 
592 
600 static void
603  void *app_ctx)
604 {
605  struct GSC_Client *c = app_ctx;
606 
608  "Client %p has disconnected from core service.\n",
609  client);
610  GNUNET_CONTAINER_DLL_remove (client_head, client_tail, c);
611  if (NULL != c->requests)
612  {
615  NULL);
617  }
619  c->connectmap = NULL;
620  if (NULL != c->types)
621  {
622  GSC_TYPEMAP_remove (c->types, c->tcnt);
623  GNUNET_free (c->types);
624  }
625  GNUNET_free (c);
626 
627  /* recalculate 'all_client_options' */
628  all_client_options = 0;
629  for (c = client_head; NULL != c; c = c->next)
631 }
632 
633 
644 void
646  struct GSC_Client *client,
647  const struct GNUNET_PeerIdentity *neighbour,
648  const struct GSC_TypeMap *tmap_old,
649  const struct GSC_TypeMap *tmap_new)
650 {
651  struct GNUNET_MQ_Envelope *env;
652  int old_match;
653  int new_match;
654 
655  if (GNUNET_YES != client->got_init)
656  return;
657  old_match = GSC_TYPEMAP_test_match (tmap_old, client->types, client->tcnt);
658  new_match = GSC_TYPEMAP_test_match (tmap_new, client->types, client->tcnt);
660  "Notifying client about neighbour %s (%d/%d)\n",
661  GNUNET_i2s (neighbour),
662  old_match,
663  new_match);
664  if (old_match == new_match)
665  {
666  GNUNET_assert (
667  old_match ==
669  return; /* no change */
670  }
671  if (GNUNET_NO == old_match)
672  {
673  struct ConnectNotifyMessage *cnm;
674 
675  /* send connect */
676  GNUNET_assert (
677  GNUNET_NO ==
681  client->connectmap,
682  neighbour,
683  NULL,
686  cnm->reserved = htonl (0);
688  "Sending NOTIFY_CONNECT message about peer %s to client.\n",
689  GNUNET_i2s (neighbour));
690  cnm->peer = *neighbour;
691  GNUNET_MQ_send (client->mq, env);
692  }
693  else
694  {
695  struct DisconnectNotifyMessage *dcm;
696 
697  /* send disconnect */
698  GNUNET_assert (
699  GNUNET_YES ==
703  neighbour,
704  NULL));
706  dcm->reserved = htonl (0);
708  "Sending NOTIFY_DISCONNECT message about peer %s to client.\n",
709  GNUNET_i2s (neighbour));
710  dcm->peer = *neighbour;
711  GNUNET_MQ_send (client->mq, env);
712  }
713 }
714 
715 
725 void
727  const struct GNUNET_PeerIdentity *neighbour,
728  const struct GSC_TypeMap *tmap_old,
729  const struct GSC_TypeMap *tmap_new)
730 {
731  struct GSC_Client *c;
732 
733  for (c = client_head; NULL != c; c = c->next)
735  neighbour,
736  tmap_old,
737  tmap_new);
738 }
739 
740 
752 void
754  const struct GNUNET_MessageHeader *msg,
755  uint16_t msize,
756  uint32_t options)
757 {
758  size_t size = msize + sizeof(struct NotifyTrafficMessage);
759 
760  if (size >= GNUNET_MAX_MESSAGE_SIZE)
761  {
762  GNUNET_break (0);
763  return;
764  }
765  if (! ((0 != (all_client_options & options)) ||
766  (0 != (options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND))))
767  return; /* no client cares about this message notification */
769  "Core service passes message from `%s' of type %u to client.\n",
770  GNUNET_i2s (sender),
771  (unsigned int) ntohs (msg->type));
772  GSC_SESSIONS_add_to_typemap (sender, ntohs (msg->type));
773 
774  for (struct GSC_Client *c = client_head; NULL != c; c = c->next)
775  {
776  struct GNUNET_MQ_Envelope *env;
777  struct NotifyTrafficMessage *ntm;
778  uint16_t mtype;
779  unsigned int qlen;
780  int tm;
781 
782  tm = type_match (ntohs (msg->type), c);
783  if (! ((0 != (c->options & options)) ||
784  ((0 != (options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) &&
785  (GNUNET_YES == tm))))
786  continue; /* neither options nor type match permit the message */
787  if ((0 != (options & GNUNET_CORE_OPTION_SEND_HDR_INBOUND)) &&
788  ((0 != (c->options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) ||
789  (GNUNET_YES == tm)))
790  continue;
791  if ((0 != (options & GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND)) &&
792  (0 != (c->options & GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND)))
793  continue;
794 
795  /* Drop messages if:
796  1) We are above the hard limit, or
797  2) We are above the soft limit, and a coin toss limited
798  to the message size (giving larger messages a
799  proportionally higher chance of being queued) falls
800  below the threshold. The threshold is based on where
801  we are between the soft and the hard limit, scaled
802  to match the range of message sizes we usually encounter
803  (i.e. up to 32k); so a 64k message has a 50% chance of
804  being kept if we are just barely below the hard max,
805  and a 99% chance of being kept if we are at the soft max.
806  The reason is to make it more likely to drop control traffic
807  (ACK, queries) which may be cummulative or highly redundant,
808  and cheap to drop than data traffic. */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 
847  GNUNET_assert (
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 ();
873  GSC_TYPEMAP_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);
933  GSC_TYPEMAP_init ();
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:134
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:673
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:2194
Handle to a service.
Definition: service.c:116
uint32_t priority
How important is this message?
Definition: core.h:206
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:1300
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:418
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:124
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:93
struct GNUNET_PeerIdentity my_identity
Public key of the local peer.
Definition: core.h:116
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:526
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:217
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:101
#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:250
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:241
, &#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:227
enum GNUNET_MQ_PriorityPreferences priority
How important is this request.
void GNUNET_MST_destroy(struct GNUNET_MessageStreamTokenizer *mst)
Destroys a tokenizer.
Definition: mst.c:411
#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:232
Client asking core to transmit a particular message to a particular target (response to GNUNET_MESSAG...
Definition: core.h:272
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:294
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:687
#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:85
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:114
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:196
struct GNUNET_PeerIdentity peer
Identity of the connecting peer.
Definition: core.h:139
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:2324
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:259
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:277
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:157
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:283
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
struct GNUNET_MessageHeader header
Header with type GNUNET_MESSAGE_TYPE_CORE_INIT.
Definition: core.h:88
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:147
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:175
struct GNUNET_PeerIdentity peer
Identity of the connecting peer.
Definition: core.h:162
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:111
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:2182
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:212
#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:264
#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:254
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:2243
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:186
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