GNUnet debian-0.24.3-24-gfea921bd2
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"
32#include "gnunet_constants.h"
33
40#define SOFT_MAX_QUEUE 128
41
47#define HARD_MAX_QUEUE 256
48
49
50struct GSC_ServicesInfo;
51
56{
61
66
71
76
82 uint16_t *types;
83
89
94
99 uint32_t options;
100
106
111 unsigned int tcnt;
112};
113
114
119
124
129
134
139
143static uint32_t all_client_options;
144
148static struct GSC_Client *client_head;
149
153static struct GSC_Client *client_tail;
154
155// TODO
157
158/*************************************
159 * Services Info Utils *
160 ************************************/
161
162// TODO put into gnunet-service-core_services_info.[h|c]
163// TODO write its own test
164// TODO rewrite: don't keep the big string, have only a known data structure
165// (DLL? array?) have a from_string() and a to_string()
166
167// TODO
169{
170 // TODO
171 // pointer to the beginning of service name
172 char *name; // TODO find syntax to set array size to num_entries
173 // TODO
174 uint32_t name_len;
175 // TODO
176 // pointer to the beginning of service version
177 char *version; // TODO find syntax to set array size to num_entries
178 // TODO
179 uint32_t version_len;
180};
181
182// TODO
184{
185 // TODO
186 uint32_t num_entries;
187
188 // TODO
190};
191
192// TODO
193// (?) _remove()
194// (?) _iter()
195
196// TODO
197static struct GSC_ServicesInfo *
199{
200 struct GSC_ServicesInfo *services_info = GNUNET_new (struct GSC_ServicesInfo);
201 services_info->num_entries = 0;
202 services_info->entries = NULL;
203 return services_info;
204}
205
206// TODO
207static void
208GSC_SVCI_destroy (struct GSC_ServicesInfo * services_info)
209{
210 GNUNET_assert (NULL != services_info);
211 GNUNET_free (services_info);
212}
213
214
215// TODO
216// todo check string size while adding!
217static void
219 char *name, uint32_t name_len,
220 char *version, uint32_t version_len)
221{
222 struct GSC_ServicesInfo_Entry *entry;
223
224 GNUNET_array_grow (services->entries, services->num_entries, 1);
225 entry = &services->entries[services->num_entries - 1];
226 entry->name = GNUNET_strdup (name);
227 entry->name_len = name_len;
228 entry->version = GNUNET_strdup (version);
229 entry->version_len = version_len;
230}
231
232// TODO
233static void
235 char *name, uint32_t name_len)
236{
237 struct GSC_ServicesInfo_Entry *entry;
238 uint64_t i_entry;
239
240 /* Find element */
241 entry = NULL;
242 for (uint64_t i = 0; i < services->num_entries; i++)
243 {
244 if (services->entries[i].name_len != name_len)
245 continue;
246 if (0 == memcmp (&services->entries[i].name, name, name_len))
247 {
248 entry = &services->entries[i];
249 i_entry = i;
250 break;
251 }
252 }
253 if (NULL == entry)
254 {
255 /* No matching entry was found!*/
257 "No matching service entry `%s' was found in services info.\n",
258 name);
259 return;
260 }
261
262 /* Remove element */
263 GNUNET_free (entry->name);
264 GNUNET_free (entry->version);
265 for (uint64_t i = i_entry; i < services->num_entries - 1; i++)
266 {
267 GNUNET_memcpy (&services->entries[i],
268 &services->entries[i+1],
269 sizeof (services->entries[i+1]));
270 }
271 GNUNET_array_grow (services->entries,
272 services->num_entries,
273 services->num_entries -1);
274}
275
277//static enum GNUNET_GenericReturnValue
278//GSC_SVCI_iter (char *service)
279//{
280//}
281
282// TODO
283// TODO compare version
286 char *name,
287 uint32_t name_len)
288{
289 for (uint32_t i = 0; i < services->num_entries; i++)
290 {
291 if (name_len != services->entries[i].name_len)
292 continue;
293 if (0 == memcmp (services->entries[i].name,
294 name,
295 services->entries[i].name_len))
296 return GNUNET_YES;
297 }
298 return GNUNET_NO;
299}
300
301// TODO
302static char *
304{
306 char *cursor = ret_string;
307
308 for (uint32_t i = 0; i < services->num_entries; i++)
309 {
310 struct GSC_ServicesInfo_Entry *entry = &services->entries[i];
311 GNUNET_memcpy (&cursor, entry->name, entry->name_len);
312 cursor = cursor + entry->name_len;
313 memset (&cursor, ':', 1);
314 cursor = cursor + 1;
315 GNUNET_memcpy (&cursor, entry->version, entry->version_len);
316 cursor = cursor + entry->version_len;
317 memset (&cursor, ';', 1);
318 cursor = cursor + 1;
319 }
320 // TODO check bounds!
321 memset (cursor, '\0', 1);
322 return ret_string;
323}
324
325// TODO
326static struct GSC_ServicesInfo *
327GSC_SVCI_from_string (char *services_str)
328{
329 struct GSC_ServicesInfo *services_ret =
330 GNUNET_malloc (sizeof (struct GSC_ServicesInfo));
331 char *cursor = services_str;
332 int8_t done = GNUNET_NO;
333 char *name = services_str; /* We start parsing expecting with a name */
334 uint32_t name_len = 0;
335 char *version = NULL; /* We start parsing with signifying that we're not
336 expecting/parsing the version */
337 uint32_t version_len = 0;
338
339 while ((cursor < services_str + GNUNET_CORE_SVC_INFO_LEN) &&
340 (GNUNET_YES != done))
341 {
342 switch (*cursor)
343 {
344 case '\0':
345 done = GNUNET_YES;
346 if ((NULL != version) ||
347 (name_len != 0))
348 {
350 "Reached end of service info string in unclean state\n");
351 }
352 break;
353 case ':':
354 if (NULL == name)
355 {
357 "Not able to parse service name before `:'\n");
358 return NULL;
359 }
360 /* Finished parsing name, start parsing version */
361 version = cursor + 1;
362 break;
363 case ';':
364 if (NULL == version)
365 {
367 "Not able to parse service version before `;'\n");
368 return NULL;
369 }
370 if (NULL == name)
371 {
373 "Not able to parse service entry before `;'\n");
374 return NULL;
375 }
376 /* Finished parsing version, start parsing next entry */
377 GSC_SVCI_add (services_ret, name, name_len, version, version_len);
378 name = cursor + 1;
379 name_len = 0;
380 version = NULL;
381 version_len = 0;
382 break;
383 default:
384 // TODO check ascii-range 65 - 90, 97 - 122
385 if (NULL == version) /* We're scanning the name */
386 {
387 GNUNET_assert (NULL != name);
388 GNUNET_assert (0 != name_len);
389 name_len = name_len + 1;
390 }
391 if (NULL != version) /* We're scanning the version */
392 {
393 GNUNET_assert (NULL != name);
394 GNUNET_assert (NULL != version);
395 version_len = version_len + 1;;
396 }
397 break;
398 }
399 }
400 return services_ret;
401}
402
403/*************************************
404 * End of Services Info Utils *
405 ************************************/
406
407
415static int
416type_match (uint16_t type, struct GSC_Client *c)
417{
418 if ((0 == c->tcnt) && (0 != c->options))
419 return GNUNET_YES; /* peer without handlers and inbound/outbond
420 callbacks matches ALL */
421 if (NULL == c->types)
422 return GNUNET_NO;
423 for (unsigned int i = 0; i < c->tcnt; i++)
424 if (type == c->types[i])
425 return GNUNET_YES;
426 return GNUNET_NO;
427}
428
429
437static int
438check_client_init (void *cls, const struct InitMessage *im)
439{
440 return GNUNET_OK;
441}
442
443
450static void
451handle_client_init (void *cls, const struct InitMessage *im)
452{
453 struct GSC_Client *c = cls;
454 struct GNUNET_MQ_Envelope *env;
455 struct InitReplyMessage *irm;
456 uint16_t msize;
457 const uint16_t *types;
458
459 /* check that we don't have an entry already */
460 msize = ntohs (im->header.size) - sizeof(struct InitMessage);
461 types = (const uint16_t *) &im[1];
462 c->tcnt = msize / sizeof(uint16_t);
463 c->options = ntohl (im->options);
464 c->got_init = GNUNET_YES;
466 c->types = GNUNET_malloc (msize);
469 c->connectmap,
471 NULL,
473 for (unsigned int i = 0; i < c->tcnt; i++)
474 c->types[i] = ntohs (types[i]);
475 // TODO
476 GSC_SVCI_add (own_services, "example", 7, "0.1", 3);
477 GNUNET_log (
479 "Client connecting to core service is interested in %u message types\n",
480 (unsigned int) c->tcnt);
481 for (unsigned int i = 0; i < c->tcnt; i++)
483 " type[%u]: %u\n",
484 i,
485 c->types[i]);
486 /* send init reply message */
488 irm->reserved = htonl (0);
490 irm->class = GSC_peer_class;
491 GNUNET_MQ_send (c->mq, env);
494}
495
496
509void
511 int drop_client)
512{
514 GNUNET_YES ==
516 &car->target,
517 car));
518 if (GNUNET_YES == drop_client)
520 GNUNET_free (car);
521}
522
523
531void
533{
534 struct GSC_Client *c;
535 struct GNUNET_MQ_Envelope *env;
536 struct SendMessageReady *smr;
537 struct GNUNET_TIME_Relative delay;
538 struct GNUNET_TIME_Relative left;
539
540 c = car->client_handle;
541 if (GNUNET_YES !=
543 {
544 /* connection has gone down since, drop request */
545 GNUNET_assert (0 !=
546 GNUNET_memcmp (&car->target,
550 return;
551 }
554 if (delay.rel_value_us > GNUNET_CONSTANTS_LATENCY_WARN.rel_value_us)
555 GNUNET_log (
557 "Client waited %s for permission to transmit to `%s'%s (priority %u)\n",
559 GNUNET_i2s (&car->target),
560 (0 == left.rel_value_us) ? " (past deadline)" : "",
561 car->priority);
563 smr->size = htons (car->msize);
564 smr->smr_id = car->smr_id;
565 smr->peer = car->target;
566 GNUNET_MQ_send (c->mq, env);
567}
568
569
576static void
577handle_client_send_request (void *cls, const struct SendMessageRequest *req)
578{
579 struct GSC_Client *c = cls;
580 struct GSC_ClientActiveRequest *car;
581 int is_loopback;
582
583 if (NULL == c->requests)
586 "Client asked for transmission to `%s'\n",
587 GNUNET_i2s (&req->peer));
588 is_loopback = (0 == GNUNET_memcmp (&req->peer,
590 if ((! is_loopback) &&
591 (GNUNET_YES !=
593 {
594 /* neighbour must have disconnected since request was issued,
595 * ignore (client will realize it once it processes the
596 * disconnect notification) */
599 "# send requests dropped (disconnected)"),
600 1,
601 GNUNET_NO);
603 return;
604 }
605
607 if (NULL == car)
608 {
609 /* create new entry */
610 car = GNUNET_new (struct GSC_ClientActiveRequest);
613 c->requests,
614 &req->peer,
615 car,
617 car->client_handle = c;
618 }
619 else
620 {
621 /* dequeue and recycle memory from pending request, there can only
622 be at most one per client and peer */
625 "# dequeuing CAR (duplicate request)"),
626 1,
627 GNUNET_NO);
630 "Transmission request to `%s' was a duplicate!\n",
631 GNUNET_i2s (&req->peer));
632 }
633 car->target = req->peer;
636 car->priority = ntohl (req->priority);
637 car->msize = ntohs (req->size);
638 car->smr_id = req->smr_id;
641 if (is_loopback)
642 {
643 /* loopback, satisfy immediately */
645 return;
646 }
648}
649
650
655{
660
665};
666
667
680static int
681tokenized_cb (void *cls, const struct GNUNET_MessageHeader *message)
682{
683 struct TokenizerContext *tc = cls;
684 struct GSC_ClientActiveRequest *car = tc->car;
685 char buf[92];
686
687 GNUNET_snprintf (buf,
688 sizeof(buf),
689 gettext_noop ("# bytes of messages of type %u received"),
690 (unsigned int) ntohs (message->type));
691 GNUNET_STATISTICS_update (GSC_stats, buf, ntohs (message->size), GNUNET_NO);
692 if (0 == GNUNET_memcmp (&car->target,
694 {
696 "Delivering message of type %u to myself\n",
697 ntohs (message->type));
699 message,
700 ntohs (message->size),
703 message,
704 sizeof(struct GNUNET_MessageHeader),
707 message,
708 ntohs (message->size),
711 message,
712 sizeof(struct GNUNET_MessageHeader),
714 }
715 else
716 {
718 "Delivering message of type %u and size %u to %s\n",
719 ntohs (message->type),
720 ntohs (message->size),
721 GNUNET_i2s (&car->target));
723 message,
724 ntohs (message->size),
727 message,
728 sizeof(struct GNUNET_MessageHeader),
730 GSC_SESSIONS_transmit (car, message, tc->priority);
731 }
732 return GNUNET_OK;
733}
734
735
743static int
744check_client_send (void *cls, const struct SendMessage *sm)
745{
746 return GNUNET_OK;
747}
748
749
756static void
757handle_client_send (void *cls, const struct SendMessage *sm)
758{
759 struct GSC_Client *c = cls;
760 struct TokenizerContext tc;
761 uint16_t msize;
762 struct GNUNET_TIME_Relative delay;
764
765 msize = ntohs (sm->header.size) - sizeof(struct SendMessage);
767 if (NULL == tc.car)
768 {
769 /* Must have been that we first approved the request, then got disconnected
770 * (which triggered removal of the 'car') and now the client gives us a message
771 * just *before* the client learns about the disconnect. Theoretically, we
772 * might also now be *again* connected. So this can happen (but should be
773 * rare). If it does happen, the message is discarded. */
776 "# messages discarded (session disconnected)"),
777 1,
778 GNUNET_NO);
780 return;
781 }
782 delay = GNUNET_TIME_absolute_get_duration (tc.car->received_time);
783 tc.priority = ntohl (sm->priority);
784 if (delay.rel_value_us > GNUNET_CONSTANTS_LATENCY_WARN.rel_value_us)
786 "Client waited %s for transmission of %u bytes to `%s'\n",
788 msize,
789 GNUNET_i2s (&sm->peer));
790 else
792 "Client waited %s for transmission of %u bytes to `%s'\n",
794 msize,
795 GNUNET_i2s (&sm->peer));
796
798 GNUNET_YES ==
802 (const char *) &sm[1],
803 msize,
805 GNUNET_NO);
806 GNUNET_MST_destroy (mst);
808 GNUNET_free (tc.car);
810}
811
812
821static int
823 const struct GNUNET_PeerIdentity *key,
824 void *value)
825{
826 struct GSC_ClientActiveRequest *car = value;
827
829 GNUNET_YES ==
831 &car->target,
832 car));
834 GNUNET_free (car);
835 return GNUNET_YES;
836}
837
838
847static void *
849 struct GNUNET_SERVICE_Client *client,
850 struct GNUNET_MQ_Handle *mq)
851{
852 struct GSC_Client *c;
853
854 c = GNUNET_new (struct GSC_Client);
855 c->client = client;
856 c->mq = mq;
859 return c;
860}
861
862
870static void
873 void *app_ctx)
874{
875 struct GSC_Client *c = app_ctx;
876
878 "Client %p has disconnected from core service.\n",
879 client);
881 if (NULL != c->requests)
882 {
885 NULL);
887 }
889 c->connectmap = NULL;
890 //TODO
891 GSC_SVCI_remove (own_services, "example", 7);
892
893 /* recalculate 'all_client_options' */
895 for (c = client_head; NULL != c; c = c->next)
897}
898
899
911void
913 struct GSC_Client *client,
914 const struct GNUNET_PeerIdentity *neighbour,
915 enum GNUNET_CORE_PeerClass class)
916{
917 struct GNUNET_MQ_Envelope *env;
918 struct ConnectNotifyMessage *cnm;
919
920 if (GNUNET_YES != client->got_init)
921 return;
922 // TODO
923 GSC_SVCI_contains (own_services, "example", 7);
925 "Notifying client about neighbour %s\n",
926 GNUNET_i2s (neighbour));
927
928 /* send connect */
929 // TODO this used to be an assert. evaluate what handling makes sense here.
931 neighbour))
932 {
933 return;
934 }
937 client->connectmap,
938 neighbour,
939 NULL,
942 cnm->reserved = htonl (0);
944 "Sending NOTIFY_CONNECT message about peer %s to client.\n",
945 GNUNET_i2s (neighbour));
946 cnm->peer = *neighbour;
947 cnm->peer_class = class;
948 GNUNET_MQ_send (client->mq, env);
949}
950
951
957void
959{
963 _ ("Core service of `%s' ready.\n"),
965}
966
967
978void
980 const struct GNUNET_PeerIdentity *neighbour,
981 enum GNUNET_CORE_PeerClass class)
982{
983 struct GSC_Client *c;
984
985 for (c = client_head; NULL != c; c = c->next)
987 neighbour,
988 class);
989}
990
991
1003void
1005 const struct GNUNET_MessageHeader *msg,
1006 uint16_t msize,
1007 uint32_t options)
1008{
1009 size_t size = msize + sizeof(struct NotifyTrafficMessage);
1010
1012 {
1013 GNUNET_break (0);
1014 return;
1015 }
1016 if (! ((0 != (all_client_options & options)) ||
1018 {
1019 return; /* no client cares about this message notification */
1020 }
1022 "Core service passes message from `%s' of type %u to client.\n",
1023 GNUNET_i2s (sender),
1024 (unsigned int) ntohs (msg->type));
1025 // TODO
1026 //GSC_SVCI_add (sender->services, "example", 7, "0.1", 3);
1027
1028 for (struct GSC_Client *c = client_head; NULL != c; c = c->next)
1029 {
1030 struct GNUNET_MQ_Envelope *env;
1031 struct NotifyTrafficMessage *ntm;
1032 uint16_t mtype;
1033 unsigned int qlen;
1034 int tm;
1035
1036 tm = type_match (ntohs (msg->type), c);
1037 if (! ((0 != (c->options & options)) ||
1039 (GNUNET_YES == tm))))
1040 continue; /* neither options nor type match permit the message */
1042 ((0 != (c->options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) ||
1043 (GNUNET_YES == tm)))
1044 continue;
1046 (0 != (c->options & GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND)))
1047 continue;
1048
1049 /* Drop messages if:
1050 1) We are above the hard limit, or
1051 2) We are above the soft limit, and a coin toss limited
1052 to the message size (giving larger messages a
1053 proportionally higher chance of being queued) falls
1054 below the threshold. The threshold is based on where
1055 we are between the soft and the hard limit, scaled
1056 to match the range of message sizes we usually encounter
1057 (i.e. up to 32k); so a 64k message has a 50% chance of
1058 being kept if we are just barely below the hard max,
1059 and a 99% chance of being kept if we are at the soft max.
1060 The reason is to make it more likely to drop control traffic
1061 (ACK, queries) which may be cumulative or highly redundant,
1062 and cheap to drop than data traffic. */qlen = GNUNET_MQ_get_length (c->mq);
1063 if ((qlen >= HARD_MAX_QUEUE) ||
1064 ((qlen > SOFT_MAX_QUEUE) &&
1066 ntohs (msg->size))) <
1067 (qlen - SOFT_MAX_QUEUE) * 0x8000
1069 {
1070 char buf[1024];
1071
1072 GNUNET_log (
1074 "Dropping decrypted message of type %u as client is too busy (queue full)\n",
1075 (unsigned int) ntohs (msg->type));
1076 GNUNET_snprintf (buf,
1077 sizeof(buf),
1078 gettext_noop (
1079 "# messages of type %u discarded (client busy)"),
1080 (unsigned int) ntohs (msg->type));
1082 continue;
1083 }
1084
1085 GNUNET_log (
1087 "Sending %u message with %u bytes to client interested in messages of type %u.\n",
1088 options,
1089 ntohs (msg->size),
1090 (unsigned int) ntohs (msg->type));
1091
1095 else
1097 env = GNUNET_MQ_msg_extra (ntm, msize, mtype);
1098 ntm->peer = *sender;
1099 GNUNET_memcpy (&ntm[1], msg, msize);
1100
1102 (0 == (c->options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) ||
1103 (GNUNET_YES != tm) ||
1104 (GNUNET_YES ==
1105 GNUNET_CONTAINER_multipeermap_contains (c->connectmap, sender)));
1106 GNUNET_MQ_send (c->mq, env);
1107 }
1108}
1109
1110
1117static void
1118shutdown_task (void *cls)
1119{
1120 struct GSC_Client *c;
1121
1122 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Core service shutting down.\n");
1123 while (NULL != (c = client_head))
1126 GSC_KX_done ();
1128 if (NULL != GSC_stats)
1129 {
1131 GSC_stats = NULL;
1132 }
1133 GSC_cfg = NULL;
1134}
1135
1136
1146static void
1148 const struct GNUNET_MessageHeader *message)
1149{
1150 struct GSC_Client *c = cls;
1151
1154}
1155
1156
1164static void
1165run (void *cls,
1166 const struct GNUNET_CONFIGURATION_Handle *c,
1168{
1169 GSC_cfg = c;
1172 {
1173 /* Read the peer class from the configuration */
1174 const char *peer_class_str = {'\0' * 10};
1175 const char *choices[] = {
1176 "UNKNOWN",
1177 "UNWILLING",
1178 "MOBILE",
1179 "DESKTOP",
1180 "ROUTER",
1181 "SERVER",
1182 NULL
1183 };
1185 "Starting CORE service\n");
1186 if (GNUNET_OK !=
1188 "core",
1189 "CLASS",
1190 choices,
1191 &peer_class_str))
1192 {
1194 "No class found in configuration! (Continuing with unknown class)");
1196 }
1197 if (0 == strcasecmp (peer_class_str, "UNKNOWN"))
1199 else if (0 == strcasecmp (peer_class_str, "UNWILLING"))
1201 else if (0 == strcasecmp (peer_class_str, "MOBILE"))
1203 else if (0 == strcasecmp (peer_class_str, "DESKTOP"))
1205 else if (0 == strcasecmp (peer_class_str, "ROUTER"))
1207 else if (0 == strcasecmp (peer_class_str, "SERVER"))
1209 else
1210 GNUNET_assert (0);
1211 }
1215 if (GNUNET_OK != GSC_KX_init ())
1216 {
1218 return;
1219 }
1220}
1221
1222
1228 "core",
1230 &run,
1233 NULL,
1234 GNUNET_MQ_hd_var_size (client_init,
1236 struct InitMessage,
1237 NULL),
1238 GNUNET_MQ_hd_fixed_size (client_monitor_peers,
1240 struct GNUNET_MessageHeader,
1241 NULL),
1242 GNUNET_MQ_hd_fixed_size (client_send_request,
1244 struct SendMessageRequest,
1245 NULL),
1246 GNUNET_MQ_hd_var_size (client_send,
1248 struct SendMessage,
1249 NULL),
1251
1252
1253/* end of gnunet-service-core.c */
struct GNUNET_GETOPT_CommandLineOption options[]
Definition: 002.c:5
struct GNUNET_MQ_Handle * mq
Definition: 003.c:5
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
#define GNUNET_CORE_OPTION_SEND_FULL_INBOUND
Client wants all inbound messages in full.
Definition: core.h:53
#define GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND
Client just wants the 4-byte message headers of all outbound messages.
Definition: core.h:70
#define GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND
Client wants all outbound messages in full.
Definition: core.h:64
#define GNUNET_CORE_OPTION_SEND_HDR_INBOUND
Client just wants the 4-byte message headers of all inbound messages.
Definition: core.h:59
#define gettext_noop(String)
Definition: gettext.h:74
static const char * ret_string(enum GNUNET_ARM_Result result)
Returns a string interpretation of the result.
Definition: gnunet-arm.c:244
static struct GNUNET_CONTAINER_MultiHashMap * services
This hashmaps saves interesting things about the configured services.
struct GNUNET_HashCode key
The key used in the DHT.
static char * name
Name (label) of the records to list.
static char * value
Value of the record to add/remove.
static uint32_t type
Type string converted to DNS type value.
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
const struct GNUNET_CONFIGURATION_Handle * GSC_cfg
Our configuration.
static struct GSC_ServicesInfo * GSC_SVCI_from_string(char *services_str)
static struct GSC_ServicesInfo * own_services
static struct GSC_Client * client_head
Head of linked list of our clients.
static struct GSC_ServicesInfo * GSC_SVCI_init()
static void handle_client_monitor_peers(void *cls, const struct GNUNET_MessageHeader *message)
Handle GNUNET_MESSAGE_TYPE_CORE_MONITOR_PEERS request.
static void handle_client_init(void *cls, const struct InitMessage *im)
Handle GNUNET_MESSAGE_TYPE_CORE_INIT request.
static int type_match(uint16_t type, struct GSC_Client *c)
Test if the client is interested in messages of the given type.
static enum GNUNET_GenericReturnValue GSC_SVCI_contains(struct GSC_ServicesInfo *services, char *name, uint32_t name_len)
static void GSC_SVCI_destroy(struct GSC_ServicesInfo *services_info)
struct GNUNET_SERVICE_Handle * service_h
Handle to the running service.
static uint32_t all_client_options
Big "or" of all client options.
void GSC_complete_initialization_cb(void)
This function is called from GSC_KX_init() once it got its peer id from pils.
struct GNUNET_PeerIdentity GSC_my_identity
Our identity.
static void shutdown_task(void *cls)
Last task run during shutdown.
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.
GNUNET_SERVICE_MAIN(GNUNET_OS_project_data_gnunet(), "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.
static void * client_connect_cb(void *cls, struct GNUNET_SERVICE_Client *client, struct GNUNET_MQ_Handle *mq)
A client connected, set up.
static int destroy_active_client_request(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Free client request records.
static void GSC_SVCI_add(struct GSC_ServicesInfo *services, char *name, uint32_t name_len, char *version, uint32_t version_len)
static void run(void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_SERVICE_Handle *service)
Initiate core service.
static void handle_client_send_request(void *cls, const struct SendMessageRequest *req)
Handle GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST message.
#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...
static void handle_client_send(void *cls, const struct SendMessage *sm)
Handle GNUNET_MESSAGE_TYPE_CORE_SEND request.
static enum GNUNET_CORE_PeerClass GSC_peer_class
Our peer class.
static int check_client_init(void *cls, const struct InitMessage *im)
Check GNUNET_MESSAGE_TYPE_CORE_INIT request.
void GSC_CLIENTS_notify_client_about_neighbour(struct GSC_Client *client, const struct GNUNET_PeerIdentity *neighbour, enum GNUNET_CORE_PeerClass class)
Notify a particular client about a change to existing connection to one of our neighbours (check if t...
static int check_client_send(void *cls, const struct SendMessage *sm)
Check GNUNET_MESSAGE_TYPE_CORE_SEND request.
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).
static struct GSC_Client * client_tail
Tail of linked list of our clients.
static void client_disconnect_cb(void *cls, struct GNUNET_SERVICE_Client *client, void *app_ctx)
A client disconnected, clean up.
void GSC_CLIENTS_notify_clients_about_neighbour(const struct GNUNET_PeerIdentity *neighbour, enum GNUNET_CORE_PeerClass class)
Notify all clients about a change to existing session.
struct GNUNET_STATISTICS_Handle * GSC_stats
For creating statistics.
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.
void GSC_CLIENTS_solicit_request(struct GSC_ClientActiveRequest *car)
Tell a client that we are ready to receive the message.
static char * GSC_SVCI_to_string(struct GSC_ServicesInfo *services)
#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...
static void GSC_SVCI_remove(struct GSC_ServicesInfo *services, char *name, uint32_t name_len)
Globals for gnunet-service-core.
void GSC_KX_handle_client_monitor_peers(struct GNUNET_MQ_Handle *mq)
Handle GNUNET_MESSAGE_TYPE_CORE_MONITOR_PEERS request.
void GSC_KX_done()
Shutdown KX subsystem.
int GSC_KX_init(void)
Initialize KX subsystem.
code for managing the key exchange (SET_KEY, PING, PONG) with other peers
void GSC_SESSIONS_dequeue_request(struct GSC_ClientActiveRequest *car)
Dequeue a request from a client from transmission to a particular peer.
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.
void GSC_SESSIONS_notify_client_about_sessions(struct GSC_Client *client)
We have a new client, notify it about all current sessions.
void GSC_SESSIONS_init()
Initialize sessions subsystem.
void GSC_SESSIONS_queue_request(struct GSC_ClientActiveRequest *car)
Queue a request from a client for transmission to a particular peer.
void GSC_SESSIONS_done()
Shutdown sessions subsystem.
#define GNUNET_MAX_MESSAGE_SIZE
Largest supported message (to be precise, one byte more than the largest possible message,...
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_choice(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, const char *const *choices, const char **value)
Get a configuration value that should be in a set of predefined strings.
#define GNUNET_CONSTANTS_LATENCY_WARN
After what amount of latency for a message do we print a warning?
GNUNET_CORE_PeerClass
The peer class gives a hint about the capabilities of a peer.
#define GNUNET_CORE_SVC_INFO_LEN
Size of the services info field in the cake handshake TODO.
@ GNUNET_CORE_CLASS_SERVER
This is something like a server.
@ GNUNET_CORE_CLASS_UNKNOWN
The device's capabilities are currently unknown.
@ GNUNET_CORE_CLASS_ROUTER
This is a piece of network infrastructure.
@ GNUNET_CORE_CLASS_MOBILE
This is a mobile device.
@ GNUNET_CORE_CLASS_DESKTOP
This is a desktop computer.
@ GNUNET_CORE_CLASS_UNWILLING
This device is currently unwilling to spend more then the absolutely necessary ressources.
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
@ GNUNET_CRYPTO_QUALITY_WEAK
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
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.
enum GNUNET_GenericReturnValue 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).
void GNUNET_CONTAINER_multipeermap_destroy(struct GNUNET_CONTAINER_MultiPeerMap *map)
Destroy a hash map.
int GNUNET_CONTAINER_multipeermap_iterate(struct GNUNET_CONTAINER_MultiPeerMap *map, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map.
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).
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.
enum GNUNET_GenericReturnValue 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.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST
, ' bother checking if a value already exists (faster than GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE...
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY
There must only be one value per key; storing a value should fail if a value under the same key alrea...
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
#define GNUNET_log(kind,...)
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
GNUNET_GenericReturnValue
Named constants for return values.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_BULK
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_array_grow(arr, size, tsize)
Grow a well-typed (!) array.
int GNUNET_snprintf(char *buf, size_t size, const char *format,...) __attribute__((format(printf
Like snprintf, just aborts if the buffer is of insufficient size.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
unsigned int GNUNET_MQ_get_length(struct GNUNET_MQ_Handle *mq)
Obtain the current length of the message queue.
Definition: mq.c:293
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:305
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
#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:61
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
Definition: gnunet_mq_lib.h:76
GNUNET_MQ_PriorityPreferences
Per envelope preferences and priorities.
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
#define GNUNET_MQ_hd_fixed_size(name, code, str, ctx)
const struct GNUNET_OS_ProjectData * GNUNET_OS_project_data_gnunet(void)
Return default project data used by 'libgnunetutil' for GNUnet.
#define GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST
Request from client to transmit message.
#define GNUNET_MESSAGE_TYPE_CORE_NOTIFY_OUTBOUND
Notify clients about outgoing P2P transmissions.
#define GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT
Notify clients about new peer-to-peer connections (triggered after key exchange).
#define GNUNET_MESSAGE_TYPE_CORE_MONITOR_PEERS
Request for connection monitoring from CORE service.
#define GNUNET_MESSAGE_TYPE_CORE_INIT
Initial setup message from core client to core.
#define GNUNET_MESSAGE_TYPE_CORE_SEND
Client with message to transmit (after SEND_READY confirmation was received).
#define GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND
Notify clients about incoming P2P messages.
#define GNUNET_MESSAGE_TYPE_CORE_INIT_REPLY
Response from core to core client to INIT message.
#define GNUNET_MESSAGE_TYPE_CORE_SEND_READY
Confirmation from core that message can now be sent.
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:567
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,...
Definition: scheduler.c:1339
enum GNUNET_GenericReturnValue GNUNET_MST_from_buffer(struct GNUNET_MessageStreamTokenizer *mst, const char *buf, size_t size, int purge, int one_shot)
Add incoming data to the receive buffer and call the callback for all complete messages.
Definition: mst.c:101
struct GNUNET_MessageStreamTokenizer * GNUNET_MST_create(GNUNET_MessageTokenizerCallback cb, void *cb_cls)
Create a message stream tokenizer.
Definition: mst.c:86
void GNUNET_MST_destroy(struct GNUNET_MessageStreamTokenizer *mst)
Destroys a tokenizer.
Definition: mst.c:404
void GNUNET_SERVICE_suspend(struct GNUNET_SERVICE_Handle *sh)
Suspend accepting connections from the listen socket temporarily.
Definition: service.c:2380
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition: service.c:2462
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2433
void GNUNET_SERVICE_resume(struct GNUNET_SERVICE_Handle *sh)
Resume accepting connections from the listen socket.
Definition: service.c:2388
@ GNUNET_SERVICE_OPTION_NONE
Use defaults.
struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create(const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg)
Get handle for the statistics service.
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 GNUNET_STATISTICS_destroy(struct GNUNET_STATISTICS_Handle *h, int sync_first)
Destroy a handle (free all state associated with it).
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:438
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:599
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:111
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition: time.c:741
static unsigned int size
Size of the "table".
Definition: peer.c:68
#define _(String)
GNU gettext support macro.
Definition: platform.h:179
static struct GNUNET_SCHEDULER_TaskContext tc
Task context of the current task.
Definition: scheduler.c:431
Message sent by the service to clients to notify them about a peer connecting.
Definition: core.h:129
struct GNUNET_PeerIdentity peer
Identity of the connecting peer.
Definition: core.h:143
uint32_t reserved
Always zero.
Definition: core.h:138
enum GNUNET_CORE_PeerClass peer_class
Class of the connecting peer TODO is it correct to send an enum like this?
Definition: core.h:149
Internal representation of the hash map.
Handle to a message queue.
Definition: mq.c:87
Header for all communications.
Handle to a message stream tokenizer.
Definition: mst.c:45
The identity of the host (wraps the signing key of the peer).
Handle to a client that is connected to a service.
Definition: service.c:249
Handle to a service.
Definition: service.c:116
Handle for the service.
Time for relative time used by GNUnet, in microseconds.
uint64_t rel_value_us
The actual value.
Record kept for each request for transmission issued by a client that is still pending.
uint16_t smr_id
Unique request ID (in big endian).
struct GNUNET_TIME_Absolute deadline
By what time would the client want to see this message out?
struct GNUNET_TIME_Absolute received_time
At what time did we first see this request?
struct GNUNET_PeerIdentity target
Which peer is the message going to be for?
int was_solicited
Has this request been solicited yet?
uint16_t msize
How many bytes does the client intend to send?
struct GSC_Client * client_handle
Handle to the client.
enum GNUNET_MQ_PriorityPreferences priority
How important is this request.
Data structure for each client connected to the CORE service.
uint32_t options
Options for messages this client cares about, see GNUNET_CORE_OPTION_ values.
unsigned int tcnt
Number of types of incoming messages this client specifically cares about.
struct GNUNET_SERVICE_Client * client
Handle for the client with the server API.
struct GSC_Client * next
Clients are kept in a linked list.
struct GNUNET_MQ_Handle * mq
Message queue to talk to client.
struct GNUNET_CONTAINER_MultiPeerMap * requests
Map of peer identities to active transmission requests of this client to the peer (of type struct GSC...
struct GSC_Client * prev
Clients are kept in a linked list.
struct GNUNET_CONTAINER_MultiPeerMap * connectmap
Map containing all peers that this client knows we're connected to.
int got_init
Have we gotten the GNUNET_MESSAGE_TYPE_CORE_INIT message from this client already?
uint16_t * types
Array of the types of messages this peer cares about (with tcnt entries).
char * name
uint32_t name_len
uint32_t version_len
char * version
struct GSC_ServicesInfo_Entry * entries
Message transmitted core clients to gnunet-service-core to start the interaction.
Definition: core.h:82
struct GNUNET_MessageHeader header
Header with type GNUNET_MESSAGE_TYPE_CORE_INIT.
Definition: core.h:86
uint32_t options
Options, see GNUNET_CORE_OPTION_ values.
Definition: core.h:91
Message transmitted by the gnunet-service-core process to its clients in response to an INIT message.
Definition: core.h:100
enum GNUNET_CORE_PeerClass class
Class of the peer TODO is it correct to send an enum like this?
Definition: core.h:120
struct GNUNET_PeerIdentity my_identity
Public key of the local peer.
Definition: core.h:114
uint32_t reserved
Always zero.
Definition: core.h:109
Message sent by the service to clients to notify them about messages being received or transmitted.
Definition: core.h:186
struct GNUNET_PeerIdentity peer
Identity of the receiver or sender.
Definition: core.h:196
Core notifying client that it is allowed to now transmit a message to the given target (response to G...
Definition: core.h:252
uint16_t smr_id
smr_id from the request.
Definition: core.h:269
struct GNUNET_PeerIdentity peer
Identity of the intended target.
Definition: core.h:274
uint16_t size
How many bytes are allowed for transmission? Guaranteed to be at least as big as the requested size,...
Definition: core.h:264
Client notifying core about the maximum-priority message it has in the queue for a particular target.
Definition: core.h:207
uint32_t priority
How important is this message?
Definition: core.h:216
struct GNUNET_PeerIdentity peer
Identity of the intended target.
Definition: core.h:227
uint16_t size
How large is the message?
Definition: core.h:237
uint16_t smr_id
Counter for this peer to match SMRs to replies.
Definition: core.h:242
struct GNUNET_TIME_AbsoluteNBO deadline
By what time would the sender really like to see this message transmitted?
Definition: core.h:222
Client asking core to transmit a particular message to a particular target (response to GNUNET_MESSAG...
Definition: core.h:283
struct GNUNET_MessageHeader header
Header with type GNUNET_MESSAGE_TYPE_CORE_SEND.
Definition: core.h:287
uint32_t priority
How important is this message? Contains a enum GNUNET_MQ_PriorityPreferences in NBO.
Definition: core.h:293
struct GNUNET_PeerIdentity peer
Identity of the intended receiver.
Definition: core.h:304
Closure for the #client_tokenizer_callback().
struct GSC_ClientActiveRequest * car
Active request handle for the message.
enum GNUNET_MQ_PriorityPreferences priority
How important is this message.