GNUnet debian-0.24.3
service.c
Go to the documentation of this file.
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2016, 2024 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
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_protocols.h"
30#include "gnunet_constants.h"
32#include "speedup.h"
33
34#if HAVE_MALLINFO2
35#include <malloc.h>
36#endif
37
38
39#define LOG(kind, ...) GNUNET_log_from (kind, "util-service", __VA_ARGS__)
40
41#define LOG_STRERROR(kind, syscall) \
42 GNUNET_log_from_strerror (kind, "util-service", syscall)
43
44#define LOG_STRERROR_FILE(kind, syscall, filename) \
45 GNUNET_log_from_strerror_file (kind, "util-service", syscall, filename)
46
47
52{
57
62
67
72
77};
78
79
84{
89
94
99
104
110
111
116{
121
126
130 const char *service_name;
131
136
141
146
150 void *cb_cls;
151
156
161
166
171
176
180 void *task_cls;
181
186
191
197
203
210
219
224
229
236
242};
243
244
249{
254
259
264
269
274
279
285
291
297
302
307
313
319
323 size_t msg_pos;
324
331
338
343
347 uint16_t warn_type;
348};
349
350
360{
361 for (struct GNUNET_SERVICE_Client *client = sh->clients_head;
362 NULL != client;
363 client = client->next)
364 {
365 if (NULL != client->drop_task)
366 continue;
367 if (client->is_monitor)
368 continue;
369 return true;
370 }
371 return false;
372}
373
374
382static void
384 enum SuspendReason sr)
385{
386 GNUNET_assert (0 == (sh->suspend_state & sr));
387 sh->suspend_state |= sr;
388 for (struct ServiceListenContext *slc = sh->slc_head;
389 NULL != slc;
390 slc = slc->next)
391 {
392 if (NULL != slc->listen_task)
393 {
394 GNUNET_SCHEDULER_cancel (slc->listen_task);
395 slc->listen_task = NULL;
396 }
397 }
398}
399
400
409static void
411{
412 struct GNUNET_SERVICE_Handle *sh = cls;
413
415 {
418 break;
420 /* This task should never be run if we are using
421 the manual shutdown. */
422 GNUNET_assert (0);
423 break;
425 if (0 == (sh->suspend_state & SUSPEND_STATE_SHUTDOWN))
429 break;
430 }
431}
432
433
441static bool
443 const struct in_addr *add)
444{
445 for (unsigned int i = 0;
446 0 != list[i].network.s_addr;
447 i++)
448 {
449 if ( (add->s_addr & list[i].netmask.s_addr) ==
450 (list[i].network.s_addr & list[i].netmask.s_addr) )
451 return true;
452 }
453 return false;
454}
455
456
464static bool
466 const struct in6_addr *ip)
467{
468 for (unsigned int i = 0;
469 ! GNUNET_is_zero (&list[i].network);
470 i++)
471 {
472 bool match = true;
473
474 for (unsigned int j = 0; j < sizeof(struct in6_addr) / sizeof(int); j++)
475 if (((((int *) ip)[j] & ((int *) &list[i].netmask)[j])) !=
476 (((int *) &list[i].network)[j] & ((int *) &list[i].netmask)[j]))
477 {
478 match = false;
479 break;
480 }
481 if (match)
482 return true;
483 }
484 return false;
485}
486
487
494static void
495do_send (void *cls)
496{
497 struct GNUNET_SERVICE_Client *client = cls;
498 ssize_t ret;
499 size_t left;
500 const char *buf;
501
503 "service: sending message with type %u\n",
504 ntohs (client->msg->type));
505 client->send_task = NULL;
506 buf = (const char *) client->msg;
507 left = ntohs (client->msg->size) - client->msg_pos;
509 &buf[client->msg_pos],
510 left);
511 GNUNET_assert (ret <= (ssize_t) left);
512 if (0 == ret)
513 {
514 LOG (GNUNET_ERROR_TYPE_DEBUG, "no data send");
516 return;
517 }
518 if (-1 == ret)
519 {
520 if ((EAGAIN == errno) || (EINTR == errno))
521 {
522 /* ignore */
523 ret = 0;
524 }
525 else
526 {
527 if (EPIPE != errno)
530 "socket send returned with error code %i",
531 errno);
533 return;
534 }
535 }
536 if (0 == client->msg_pos)
537 {
539 }
540 client->msg_pos += ret;
541 if (left > (size_t) ret)
542 {
543 GNUNET_assert (NULL == client->drop_task);
544 client->send_task =
546 client->sock,
547 &do_send,
548 client);
549 return;
550 }
552}
553
554
563static void
565 const struct GNUNET_MessageHeader *msg,
566 void *impl_state)
567{
568 struct GNUNET_SERVICE_Client *client = impl_state;
569
570 (void) mq;
571 if (NULL != client->drop_task)
572 return; /* we're going down right now, do not try to send */
573 GNUNET_assert (NULL == client->send_task);
575 "Sending message of type %u and size %u to client\n",
576 ntohs (msg->type),
577 ntohs (msg->size));
578 client->msg = msg;
579 client->msg_pos = 0;
581 client);
582}
583
584
591static void
593 void *impl_state)
594{
595 struct GNUNET_SERVICE_Client *client = impl_state;
596
597 (void) mq;
598 GNUNET_assert (0 == client->msg_pos);
599 client->msg = NULL;
601 client->send_task = NULL;
602}
603
604
614static void
616 enum GNUNET_MQ_Error error)
617{
618 struct GNUNET_SERVICE_Client *client = cls;
619 struct GNUNET_SERVICE_Handle *sh = client->sh;
620
621 if ( (GNUNET_MQ_ERROR_NO_MATCH == error) &&
622 (! sh->require_found) )
623 {
625 "No handler for message of type %u found\n",
626 (unsigned int) client->warn_type);
628 return; /* ignore error */
629 }
631}
632
633
639static void
641{
642 struct GNUNET_SERVICE_Client *client = cls;
643
645 0 !=
646 client->warn_type); /* type should never be 0 here, as we don't use 0 */
649 client);
650 LOG (
652 _ (
653 "Processing code for message of type %u did not call `GNUNET_SERVICE_client_continue' after %s\n"),
654 (unsigned int) client->warn_type,
656 client->warn_start),
657 GNUNET_YES));
658}
659
660
672static int
674 const struct GNUNET_MessageHeader *message)
675{
676 struct GNUNET_SERVICE_Client *client = cls;
677
679 "Received message of type %u and size %u from client\n",
680 ntohs (message->type),
681 ntohs (message->size));
682 GNUNET_assert (! client->needs_continue);
683 client->needs_continue = true;
684 client->warn_type = ntohs (message->type);
686 GNUNET_assert (NULL == client->warn_task);
689 client);
690 GNUNET_MQ_inject_message (client->mq, message);
691 if (NULL != client->drop_task)
692 return GNUNET_SYSERR;
693 return GNUNET_OK;
694}
695
696
703static void
705{
706 struct GNUNET_SERVICE_Client *client = cls;
708
709 client->recv_task = NULL;
710 ret = GNUNET_MST_read (client->mst,
711 client->sock,
712 GNUNET_NO,
713 GNUNET_YES);
714 if (GNUNET_SYSERR == ret)
715 {
716 /* client closed connection (or IO error) */
717 if (NULL == client->drop_task)
718 {
719 GNUNET_assert (! client->needs_continue);
721 }
722 return;
723 }
724 if (GNUNET_NO == ret)
725 return; /* more messages in buffer, wait for application
726 to be done processing */
728 if (client->needs_continue)
729 return;
730 if (NULL != client->recv_task)
731 return;
732 /* MST needs more data, re-schedule read job */
733 client->recv_task =
735 client->sock,
737 client);
738}
739
740
748static void
750 struct GNUNET_NETWORK_Handle *csock)
751{
752 struct GNUNET_SERVICE_Client *client;
753
754 client = GNUNET_new (struct GNUNET_SERVICE_Client);
755 GNUNET_CONTAINER_DLL_insert (sh->clients_head,
756 sh->clients_tail,
757 client);
758 client->sh = sh;
759 client->sock = csock;
761 NULL,
763 client,
764 sh->handlers,
766 client);
767 client->mst = GNUNET_MST_create (&service_client_mst_cb, client);
768 if (NULL != sh->connect_cb)
769 client->user_context = sh->connect_cb (sh->cb_cls, client, client->mq);
771 client->recv_task =
773 client->sock,
775 client);
776}
777
778
785static void
786accept_client (void *cls)
787{
788 struct ServiceListenContext *slc = cls;
789 struct GNUNET_SERVICE_Handle *sh = slc->sh;
790
791 slc->listen_task = NULL;
792 while (1)
793 {
794 struct GNUNET_NETWORK_Handle *sock;
795 const struct sockaddr_in *v4;
796 const struct sockaddr_in6 *v6;
797 struct sockaddr_storage sa;
798 socklen_t addrlen;
799 int ok;
800
801 addrlen = sizeof(sa);
803 (struct sockaddr *) &sa,
804 &addrlen);
805 if (NULL == sock)
806 {
807 if (EMFILE == errno)
809 else if (EAGAIN != errno)
811 "accept");
812 break;
813 }
814 switch (sa.ss_family)
815 {
816 case AF_INET:
817 GNUNET_assert (addrlen == sizeof(struct sockaddr_in));
818 v4 = (const struct sockaddr_in *) &sa;
819 ok = (((NULL == sh->v4_allowed) ||
820 (check_ipv4_listed (sh->v4_allowed,
821 &v4->sin_addr))) &&
822 ((NULL == sh->v4_denied) ||
823 (! check_ipv4_listed (sh->v4_denied,
824 &v4->sin_addr))));
825 break;
826
827 case AF_INET6:
828 GNUNET_assert (addrlen == sizeof(struct sockaddr_in6));
829 v6 = (const struct sockaddr_in6 *) &sa;
830 ok = (((NULL == sh->v6_allowed) ||
831 (check_ipv6_listed (sh->v6_allowed,
832 &v6->sin6_addr))) &&
833 ((NULL == sh->v6_denied) ||
834 (! check_ipv6_listed (sh->v6_denied,
835 &v6->sin6_addr))));
836 break;
837
838 case AF_UNIX:
839 ok = GNUNET_OK; /* controlled using file-system ACL now */
840 break;
841
842 default:
844 _ ("Unknown address family %d\n"),
845 sa.ss_family);
846 return;
847 }
848 if (! ok)
849 {
851 "Service rejected incoming connection from %s due to policy.\n",
852 GNUNET_a2s ((const struct sockaddr *) &sa, addrlen));
854 continue;
855 }
857 "Service accepted incoming connection from %s.\n",
858 GNUNET_a2s ((const struct sockaddr *) &sa, addrlen));
859 start_client (slc->sh,
860 sock);
861 }
862 if (0 != sh->suspend_state)
863 return;
864 slc->listen_task =
866 slc->listen_socket,
868 slc);
869}
870
871
879static void
881 enum SuspendReason sr)
882{
883 GNUNET_assert ((SUSPEND_STATE_NONE == sr) || (0 != (sh->suspend_state & sr)));
884 sh->suspend_state -= sr;
885 if (SUSPEND_STATE_NONE != sh->suspend_state)
886 return;
887 for (struct ServiceListenContext *slc = sh->slc_head;
888 NULL != slc;
889 slc = slc->next)
890 {
891 GNUNET_assert (NULL == slc->listen_task);
892 slc->listen_task =
894 slc->listen_socket,
896 slc);
897 }
898}
899
900
908static void
909service_main (void *cls)
910{
911 struct GNUNET_SERVICE_Handle *sh = cls;
912
917
918 if (-1 != sh->ready_confirm_fd)
919 {
920 GNUNET_break (1 == write (sh->ready_confirm_fd, ".", 1));
921 GNUNET_break (0 == close (sh->ready_confirm_fd));
922 sh->ready_confirm_fd = -1;
923 }
924
925 if (NULL != sh->service_init_cb)
926 sh->service_init_cb (sh->cb_cls, sh->cfg, sh);
927}
928
929
942 const char *option)
943{
944 char *opt;
945
946 if (! GNUNET_CONFIGURATION_have_value (sh->cfg, sh->service_name, option))
947 {
948 *ret = NULL;
949 return GNUNET_OK;
950 }
953 sh->service_name,
954 option,
955 &opt));
956 if (NULL == (*ret = GNUNET_STRINGS_parse_ipv4_policy (opt)))
957 {
959 _ ("Could not parse IPv4 network specification `%s' for `%s:%s'\n"),
960 opt,
961 sh->service_name,
962 option);
963 GNUNET_free (opt);
964 return GNUNET_SYSERR;
965 }
966 GNUNET_free (opt);
967 return GNUNET_OK;
968}
969
970
983 const char *option)
984{
985 char *opt;
986
987 if (! GNUNET_CONFIGURATION_have_value (sh->cfg, sh->service_name, option))
988 {
989 *ret = NULL;
990 return GNUNET_OK;
991 }
994 sh->service_name,
995 option,
996 &opt));
997 if (NULL == (*ret = GNUNET_STRINGS_parse_ipv6_policy (opt)))
998 {
1000 _ ("Could not parse IPv6 network specification `%s' for `%s:%s'\n"),
1001 opt,
1002 sh->service_name,
1003 option);
1004 GNUNET_free (opt);
1005 return GNUNET_SYSERR;
1006 }
1007 GNUNET_free (opt);
1008 return GNUNET_OK;
1009}
1010
1011
1020static void
1021add_unixpath (struct sockaddr **saddrs,
1022 socklen_t *saddrlens,
1023 const char *unixpath)
1024{
1025#ifdef AF_UNIX
1026 struct sockaddr_un *un;
1027
1028 un = GNUNET_new (struct sockaddr_un);
1029 un->sun_family = AF_UNIX;
1030 GNUNET_strlcpy (un->sun_path, unixpath, sizeof(un->sun_path));
1031#if HAVE_SOCKADDR_UN_SUN_LEN
1032 un->sun_len = (u_char) sizeof(struct sockaddr_un);
1033#endif
1034 *saddrs = (struct sockaddr *) un;
1035 *saddrlens = sizeof(struct sockaddr_un);
1036#else
1037 /* this function should never be called
1038 * unless AF_UNIX is defined! */
1039 GNUNET_assert (0);
1040#endif
1041}
1042
1043
1064static int
1066 const struct GNUNET_CONFIGURATION_Handle *cfg,
1067 struct sockaddr ***addrs,
1068 socklen_t **addr_lens)
1069{
1070 bool disablev6;
1071 struct GNUNET_NETWORK_Handle *desc;
1072 unsigned long long port;
1073 char *unixpath;
1074 struct addrinfo hints;
1075 struct addrinfo *res;
1076 struct addrinfo *pos;
1077 struct addrinfo *next;
1078 unsigned int i;
1079 int resi;
1080 int ret;
1081 struct sockaddr **saddrs;
1082 socklen_t *saddrlens;
1083 char *hostname;
1084
1085 *addrs = NULL;
1086 *addr_lens = NULL;
1087 desc = NULL;
1088 disablev6 = false;
1089 if ((GNUNET_NO ==
1090 GNUNET_NETWORK_test_pf (PF_INET6)) ||
1091 (GNUNET_YES ==
1094 "DISABLEV6")))
1095 disablev6 = true;
1096
1097 port = 0;
1098 if (GNUNET_SYSERR ==
1101 "PORT",
1102 &port))
1103 {
1105 _ ("Require valid port number for service `%s' in configuration!\n"),
1106 service_name);
1107 }
1108 if (port > 65535)
1109 {
1111 _ ("Require valid port number for service `%s' in configuration!\n"),
1112 service_name);
1113 return GNUNET_SYSERR;
1114 }
1115
1116 hostname = NULL;
1120 "BINDTO",
1121 &hostname));
1122
1123 unixpath = NULL;
1124#ifdef AF_UNIX
1125 if ( (GNUNET_OK ==
1128 "UNIXPATH",
1129 &unixpath)) &&
1130 (0 < strlen (unixpath)) )
1131 {
1132 /* probe UNIX support */
1133 struct sockaddr_un s_un;
1134
1135 if (strlen (unixpath) >= sizeof(s_un.sun_path))
1136 {
1138 "UNIXPATH `%s' too long, maximum length is %llu\n",
1139 unixpath,
1140 (unsigned long long) sizeof(s_un.sun_path));
1141 unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath);
1143 _ ("Using `%s' instead\n"),
1144 unixpath);
1145 }
1146 if (GNUNET_OK !=
1149 "mkdir",
1150 unixpath);
1151 }
1152 if (NULL != unixpath)
1153 {
1154 desc = GNUNET_NETWORK_socket_create (AF_UNIX,
1155 SOCK_STREAM,
1156 0);
1157 if (NULL == desc)
1158 {
1159 if ((ENOBUFS == errno) ||
1160 (ENOMEM == errno) ||
1161 (ENFILE == errno) ||
1162 (EACCES == errno))
1163 {
1165 "socket");
1166 GNUNET_free (hostname);
1167 GNUNET_free (unixpath);
1168 return GNUNET_SYSERR;
1169 }
1171 "Failed to create UNIX domain socket for service %s: %s\n",
1173 strerror (errno));
1174 GNUNET_free (unixpath);
1175 unixpath = NULL;
1176 }
1177 else
1178 {
1181 desc = NULL;
1182 }
1183 }
1184#endif
1185
1186 if ( (0 == port) &&
1187 (NULL == unixpath) )
1188 {
1190 "Have neither PORT nor UNIXPATH for service `%s', but one is required\n",
1191 service_name);
1192 GNUNET_free (hostname);
1193 return GNUNET_SYSERR;
1194 }
1195 if (0 == port)
1196 {
1197 saddrs = GNUNET_new_array (2, struct sockaddr *);
1198 saddrlens = GNUNET_new_array (2, socklen_t);
1199 add_unixpath (saddrs, saddrlens, unixpath);
1200 GNUNET_free (unixpath);
1201 GNUNET_free (hostname);
1202 *addrs = saddrs;
1203 *addr_lens = saddrlens;
1204 return 1;
1205 }
1206
1207 if (NULL != hostname)
1208 {
1210 "Resolving `%s' since that is where `%s' will bind to.\n",
1211 hostname,
1212 service_name);
1213 memset (&hints, 0, sizeof(struct addrinfo));
1214 if (disablev6)
1215 hints.ai_family = AF_INET;
1216 hints.ai_protocol = IPPROTO_TCP;
1217 if ((0 != (ret = getaddrinfo (hostname, NULL, &hints, &res))) ||
1218 (NULL == res))
1219 {
1221 _ ("Failed to resolve `%s': %s\n"),
1222 hostname,
1223 gai_strerror (ret));
1224 GNUNET_free (hostname);
1225 GNUNET_free (unixpath);
1226 return GNUNET_SYSERR;
1227 }
1228 next = res;
1229 i = 0;
1230 while (NULL != (pos = next))
1231 {
1232 next = pos->ai_next;
1233 if ((disablev6) && (pos->ai_family == AF_INET6))
1234 continue;
1235 i++;
1236 }
1237 if (0 == i)
1238 {
1240 _ ("Failed to find %saddress for `%s'.\n"),
1241 disablev6 ? "IPv4 " : "",
1242 hostname);
1243 freeaddrinfo (res);
1244 GNUNET_free (hostname);
1245 GNUNET_free (unixpath);
1246 return GNUNET_SYSERR;
1247 }
1248 resi = i;
1249 if (NULL != unixpath)
1250 resi++;
1251 saddrs = GNUNET_new_array (resi + 1, struct sockaddr *);
1252 saddrlens = GNUNET_new_array (resi + 1, socklen_t);
1253 i = 0;
1254 if (NULL != unixpath)
1255 {
1256 add_unixpath (saddrs, saddrlens, unixpath);
1257 i++;
1258 }
1259 next = res;
1260 while (NULL != (pos = next))
1261 {
1262 next = pos->ai_next;
1263 if ((disablev6) && (AF_INET6 == pos->ai_family))
1264 continue;
1265 if ((IPPROTO_TCP != pos->ai_protocol) && (0 != pos->ai_protocol))
1266 continue; /* not TCP */
1267 if ((SOCK_STREAM != pos->ai_socktype) && (0 != pos->ai_socktype))
1268 continue; /* huh? */
1270 "Service `%s' will bind to `%s'\n",
1272 GNUNET_a2s (pos->ai_addr, pos->ai_addrlen));
1273 if (AF_INET == pos->ai_family)
1274 {
1275 GNUNET_assert (sizeof(struct sockaddr_in) == pos->ai_addrlen);
1276 saddrlens[i] = pos->ai_addrlen;
1277 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1278 GNUNET_memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
1279 ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
1280 }
1281 else
1282 {
1283 GNUNET_assert (AF_INET6 == pos->ai_family);
1284 GNUNET_assert (sizeof(struct sockaddr_in6) == pos->ai_addrlen);
1285 saddrlens[i] = pos->ai_addrlen;
1286 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1287 GNUNET_memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
1288 ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
1289 }
1290 i++;
1291 }
1292 GNUNET_free (hostname);
1293 freeaddrinfo (res);
1294 resi = i;
1295 }
1296 else
1297 {
1298 /* will bind against everything, just set port */
1299 if (disablev6)
1300 {
1301 /* V4-only */
1302 resi = 1;
1303 if (NULL != unixpath)
1304 resi++;
1305 i = 0;
1306 saddrs = GNUNET_new_array (resi + 1, struct sockaddr *);
1307 saddrlens = GNUNET_new_array (resi + 1, socklen_t);
1308 if (NULL != unixpath)
1309 {
1310 add_unixpath (saddrs, saddrlens, unixpath);
1311 i++;
1312 }
1313 saddrlens[i] = sizeof(struct sockaddr_in);
1314 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1315#if HAVE_SOCKADDR_IN_SIN_LEN
1316 ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[i];
1317#endif
1318 ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
1319 ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
1320 }
1321 else
1322 {
1323 /* dual stack */
1324 resi = 2;
1325 if (NULL != unixpath)
1326 resi++;
1327 saddrs = GNUNET_new_array (resi + 1, struct sockaddr *);
1328 saddrlens = GNUNET_new_array (resi + 1, socklen_t);
1329 i = 0;
1330 if (NULL != unixpath)
1331 {
1332 add_unixpath (saddrs, saddrlens, unixpath);
1333 i++;
1334 }
1335 saddrlens[i] = sizeof(struct sockaddr_in6);
1336 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1337#if HAVE_SOCKADDR_IN_SIN_LEN
1338 ((struct sockaddr_in6 *) saddrs[i])->sin6_len = saddrlens[0];
1339#endif
1340 ((struct sockaddr_in6 *) saddrs[i])->sin6_family = AF_INET6;
1341 ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
1342 i++;
1343 saddrlens[i] = sizeof(struct sockaddr_in);
1344 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1345#if HAVE_SOCKADDR_IN_SIN_LEN
1346 ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[1];
1347#endif
1348 ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
1349 ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
1350 }
1351 }
1352 GNUNET_free (unixpath);
1353 *addrs = saddrs;
1354 *addr_lens = saddrlens;
1355 return resi;
1356}
1357
1358
1366static struct GNUNET_NETWORK_Handle *
1367open_listen_socket (const struct sockaddr *server_addr,
1368 socklen_t socklen)
1369{
1370 struct GNUNET_NETWORK_Handle *sock;
1371 uint16_t port;
1372 int eno;
1373
1374 switch (server_addr->sa_family)
1375 {
1376 case AF_INET:
1377 port = ntohs (((const struct sockaddr_in *) server_addr)->sin_port);
1378 break;
1379 case AF_INET6:
1380 port = ntohs (((const struct sockaddr_in6 *) server_addr)->sin6_port);
1381 break;
1382 case AF_UNIX:
1383 port = 0;
1384 break;
1385 default:
1386 GNUNET_break (0);
1387 port = 0;
1388 break;
1389 }
1390 sock = GNUNET_NETWORK_socket_create (server_addr->sa_family,
1391 SOCK_STREAM,
1392 0);
1393 if (NULL == sock)
1394 {
1396 "socket");
1397 errno = 0;
1398 return NULL;
1399 }
1400 /* bind the socket */
1401 if (GNUNET_OK !=
1403 server_addr,
1404 socklen))
1405 {
1406 eno = errno;
1407 if (EADDRINUSE != errno)
1408 {
1409 /* we don't log 'EADDRINUSE' here since an IPv4 bind may
1410 * fail if we already took the port on IPv6; if both IPv4 and
1411 * IPv6 binds fail, then our caller will log using the
1412 * errno preserved in 'eno' */
1413 if (0 != port)
1415 _ ("`%s' failed for port %d (%s).\n"),
1416 "bind",
1417 port,
1418 (AF_INET == server_addr->sa_family) ? "IPv4" : "IPv6");
1419 else
1421 eno = 0;
1422 }
1423 else
1424 {
1425 if (0 != port)
1427 _ ("`%s' failed for port %d (%s): address already in use\n"),
1428 "bind",
1429 port,
1430 (AF_INET == server_addr->sa_family) ? "IPv4" : "IPv6");
1431 else if (AF_UNIX == server_addr->sa_family)
1432 {
1434 _ ("`%s' failed for `%s': address already in use\n"),
1435 "bind",
1436 GNUNET_a2s (server_addr, socklen));
1437 }
1438 }
1440 errno = eno;
1441 return NULL;
1442 }
1443 if (GNUNET_OK != GNUNET_NETWORK_socket_listen (sock, 5))
1444 {
1447 errno = 0;
1448 return NULL;
1449 }
1450 if (0 != port)
1452 "Server starts to listen on port %u.\n",
1453 port);
1454 return sock;
1455}
1456
1457
1475static enum GNUNET_GenericReturnValue
1477 struct GNUNET_SERVICE_Handle *sh)
1478{
1479 int tolerant;
1480 struct GNUNET_NETWORK_Handle **csocks = NULL;
1481 struct GNUNET_NETWORK_Handle **lsocks;
1482 const char *nfds;
1483 const char *fdns;
1484 unsigned int cnt;
1485 int flags;
1486 char dummy;
1487
1489 sh->service_name,
1490 "TOLERANT"))
1491 {
1492 if (GNUNET_SYSERR ==
1494 sh->service_name,
1495 "TOLERANT")))
1496 {
1498 _ ("Specified value for `%s' of service `%s' is invalid\n"),
1499 "TOLERANT",
1500 sh->service_name);
1501 return GNUNET_SYSERR;
1502 }
1503 }
1504 else
1505 tolerant = GNUNET_NO;
1506
1507 lsocks = NULL;
1508 errno = 0;
1509 if ( (NULL != (nfds = getenv ("LISTEN_FDS"))) &&
1510 (NULL != (fdns = getenv ("LISTEN_FDNAMES"))) &&
1511 (1 == sscanf (nfds,
1512 "%u%c",
1513 &cnt,
1514 &dummy)) &&
1515 (cnt > 0) &&
1516 (cnt < FD_SETSIZE) )
1517 {
1518 char *fdnames;
1519 unsigned int pos;
1520
1521 lsocks = GNUNET_new_array (cnt + 1,
1522 struct GNUNET_NETWORK_Handle *);
1523 fdnames = GNUNET_strdup (fdns);
1524 pos = 0;
1525 for (const char *tok = strtok (fdnames,
1526 ":");
1527 NULL != tok;
1528 tok = strtok (NULL, ":"))
1529 {
1530 unsigned int fd;
1531
1532 if (pos == cnt)
1533 {
1535 "More than LISTEN_FDS sockets given in LISTEN_FDNAMES\n");
1536 break;
1537 }
1538 if (1 != sscanf (tok,
1539 "%u%c",
1540 &fd,
1541 &dummy))
1542 {
1544 "Malformed socket given in LISTEN_FDNAMES than in LISTEN_FDS\n");
1545 break;
1546 }
1547 if (fd >= FD_SETSIZE)
1548 {
1550 "Socket given in LISTEN_FDNAMES outside of select()able range\n");
1551 break;
1552 }
1553 flags = fcntl ((int) fd,
1554 F_GETFD);
1555 if ((flags < 0) ||
1556 (0 != (flags & FD_CLOEXEC)) ||
1557 (NULL == (lsocks[pos] = GNUNET_NETWORK_socket_box_native ((int) fd))))
1558 {
1560 "Could not access pre-bound socket %u\n",
1561 fd);
1562 break;
1563 }
1564 pos++;
1565 }
1566 if (0 == pos)
1567 {
1568 for (unsigned int i=0; i<cnt; i++)
1570 GNUNET_NETWORK_socket_close (lsocks[i]));
1571 GNUNET_free (lsocks);
1572 }
1573 unsetenv ("LISTEN_FDS");
1574 cnt = pos;
1575 }
1576 if ( (0 != (GNUNET_SERVICE_OPTION_CLOSE_LSOCKS & sh->options)) &&
1577 (NULL != lsocks) )
1578 {
1579 csocks = lsocks;
1580 lsocks = NULL;
1581 }
1582
1583 if (NULL != lsocks)
1584 {
1585 /* listen only on inherited sockets if we have any */
1586 for (struct GNUNET_NETWORK_Handle **ls = lsocks; NULL != *ls; ls++)
1587 {
1588 struct ServiceListenContext *slc;
1589
1590 slc = GNUNET_new (struct ServiceListenContext);
1591 slc->sh = sh;
1592 slc->listen_socket = *ls;
1594 sh->slc_tail,
1595 slc);
1596 }
1597 GNUNET_free (lsocks);
1598 }
1599 else
1600 {
1601 struct sockaddr **addrs;
1602 socklen_t *addrlens;
1603 int num;
1604
1605 num = get_server_addresses (sh->service_name,
1606 sh->cfg,
1607 &addrs,
1608 &addrlens);
1609 if (GNUNET_SYSERR == num)
1610 {
1611 GNUNET_free (csocks);
1612 return GNUNET_SYSERR;
1613 }
1614
1615 for (int i = 0; i < num; i++)
1616 {
1617 struct ServiceListenContext *slc;
1618
1619 slc = GNUNET_new (struct ServiceListenContext);
1620 slc->sh = sh;
1621 slc->listen_socket = open_listen_socket (addrs[i],
1622 addrlens[i]);
1623 GNUNET_free (addrs[i]);
1624 if (NULL == slc->listen_socket)
1625 {
1627 GNUNET_free (slc);
1628 continue;
1629 }
1631 sh->slc_tail,
1632 slc);
1633 }
1634 GNUNET_free (addrlens);
1635 GNUNET_free (addrs);
1636 if ((0 != num) && (NULL == sh->slc_head))
1637 {
1638 /* All attempts to bind failed, hard failure */
1639 GNUNET_log (
1641 "Could not bind to any of the ports I was supposed to, refusing to run!\n");
1642 GNUNET_free (csocks);
1643 return GNUNET_SYSERR;
1644 }
1645 }
1646 if (NULL != csocks)
1647 {
1648 /* close inherited sockets to signal parent that we are ready */
1649 for (struct GNUNET_NETWORK_Handle **ls = csocks; NULL != *ls; ls++)
1651 GNUNET_free (csocks);
1652 }
1653 sh->require_found = (GNUNET_NO == tolerant);
1655 sh->service_name,
1656 "UNIX_MATCH_UID");
1658 sh->service_name,
1659 "UNIX_MATCH_GID");
1660 process_acl4 (&sh->v4_denied, sh, "REJECT_FROM");
1661 process_acl4 (&sh->v4_allowed, sh, "ACCEPT_FROM");
1662 process_acl6 (&sh->v6_denied, sh, "REJECT_FROM6");
1663 process_acl6 (&sh->v6_allowed, sh, "ACCEPT_FROM6");
1664 return GNUNET_OK;
1665}
1666
1667
1675static char *
1677{
1678 char *un;
1679
1680 if (GNUNET_OK !=
1682 sh->service_name,
1683 "USERNAME",
1684 &un))
1685 return NULL;
1686 return un;
1687}
1688
1689
1696static enum GNUNET_GenericReturnValue
1698{
1699 char *user;
1700 struct passwd *pws;
1701
1702 if (NULL == (user = get_user_name (sh)))
1703 return GNUNET_OK; /* keep */
1704 errno = 0;
1705 pws = getpwnam (user);
1706 if (NULL == pws)
1707 {
1709 _ ("Cannot obtain information about user `%s': %s\n"),
1710 user,
1711 errno == 0 ? _ ("No such user") : strerror (errno));
1712 GNUNET_free (user);
1713 return GNUNET_SYSERR;
1714 }
1715 if ((0 != setgid (pws->pw_gid)) || (0 != setegid (pws->pw_gid)) ||
1716#if HAVE_INITGROUPS
1717 (0 != initgroups (user, pws->pw_gid)) ||
1718#endif
1719 (0 != setuid (pws->pw_uid)) ||
1720 (0 != seteuid (pws->pw_uid)))
1721 {
1722 if ((0 != setregid (pws->pw_gid, pws->pw_gid)) ||
1723 (0 != setreuid (pws->pw_uid, pws->pw_uid)))
1724 {
1726 _ ("Cannot change user/group to `%s': %s\n"),
1727 user,
1728 strerror (errno));
1729 GNUNET_free (user);
1730 return GNUNET_SYSERR;
1731 }
1732 }
1733
1734 GNUNET_free (user);
1735 return GNUNET_OK;
1736}
1737
1738
1746static char *
1748{
1749 char *pif;
1750
1751 if (GNUNET_OK !=
1753 sh->service_name,
1754 "PIDFILE",
1755 &pif))
1756 return NULL;
1757 return pif;
1758}
1759
1760
1766static void
1768{
1769 char *pif = get_pid_file_name (sh);
1770
1771 if (NULL == pif)
1772 return; /* no PID file */
1773 if (0 != unlink (pif))
1775 "unlink",
1776 pif);
1777 GNUNET_free (pif);
1778}
1779
1780
1787static enum GNUNET_GenericReturnValue
1789{
1790 pid_t pid;
1791 int nullfd;
1792 int filedes[2];
1793
1794 if (0 != pipe (filedes))
1795 {
1797 "pipe");
1798 return GNUNET_SYSERR;
1799 }
1800 pid = fork ();
1801 if (pid < 0)
1802 {
1804 "fork");
1805 return GNUNET_SYSERR;
1806 }
1807 if (0 != pid)
1808 {
1809 /* Parent */
1810 char c;
1811
1812 GNUNET_break (0 == close (filedes[1]));
1813 c = 'X';
1814 if (1 != read (filedes[0], &c, sizeof(char)))
1816 "read");
1817 fflush (stdout);
1818 switch (c)
1819 {
1820 case '.':
1821 exit (0);
1822
1823 case 'I':
1825 _ ("Service process failed to initialize\n"));
1826 break;
1827
1828 case 'S':
1830 _ ("Service process could not initialize server function\n"));
1831 break;
1832
1833 case 'X':
1835 _ ("Service process failed to report status\n"));
1836 break;
1837 }
1838 exit (1); /* child reported error */
1839 }
1840 GNUNET_break (0 == close (0));
1841 GNUNET_break (0 == close (1));
1842 GNUNET_break (0 == close (filedes[0]));
1843 nullfd = open ("/dev/null", O_RDWR | O_APPEND);
1844 if (nullfd < 0)
1845 return GNUNET_SYSERR;
1846 /* set stdin/stdout to /dev/null */
1847 if ((dup2 (nullfd, 0) < 0) || (dup2 (nullfd, 1) < 0))
1848 {
1850 (void) close (nullfd);
1851 return GNUNET_SYSERR;
1852 }
1853 (void) close (nullfd);
1854 /* Detach from controlling terminal */
1855 pid = setsid ();
1856 if (-1 == pid)
1858 "setsid");
1859 sh->ready_confirm_fd = filedes[1];
1860
1861 return GNUNET_OK;
1862}
1863
1864
1871static void
1873{
1874 struct ServiceListenContext *slc;
1875
1876 GNUNET_free (sh->v4_denied);
1877 GNUNET_free (sh->v6_denied);
1878 GNUNET_free (sh->v4_allowed);
1879 GNUNET_free (sh->v6_allowed);
1880 while (NULL != (slc = sh->slc_head))
1881 {
1883 sh->slc_tail,
1884 slc);
1885 if (NULL != slc->listen_task)
1889 GNUNET_free (slc);
1890 }
1891}
1892
1893
1900static void
1901return_agpl (void *cls,
1902 const struct GNUNET_MessageHeader *msg)
1903{
1904 struct GNUNET_SERVICE_Client *client = cls;
1905 const struct GNUNET_OS_ProjectData *pd = client->sh->pd;
1906 struct GNUNET_MQ_Handle *mq;
1907 struct GNUNET_MQ_Envelope *env;
1908 struct GNUNET_MessageHeader *res;
1909 size_t slen;
1910
1911 (void) msg;
1912 slen = strlen (pd->agpl_url) + 1;
1915 slen);
1916 memcpy (&res[1],
1918 slen);
1921 env);
1923}
1924
1925
1926struct GNUNET_SERVICE_Handle *
1928 const char *service_name,
1929 const struct GNUNET_CONFIGURATION_Handle *cfg,
1932 void *cls,
1933 const struct GNUNET_MQ_MessageHandler *handlers)
1934{
1935 struct GNUNET_SERVICE_Handle *sh;
1936
1938 sh->pd = pd;
1939 sh->service_name = service_name;
1940 sh->cfg = cfg;
1941 sh->connect_cb = connect_cb;
1942 sh->disconnect_cb = disconnect_cb;
1943 sh->cb_cls = cls;
1945 &return_agpl,
1946 NULL);
1947 if (GNUNET_OK !=
1949 sh))
1950 {
1951 GNUNET_free (sh->handlers);
1952 GNUNET_free (sh);
1953 return NULL;
1954 }
1955 do_resume (sh,
1957 return sh;
1958}
1959
1960
1966static void
1968{
1969 struct GNUNET_SERVICE_Client *c = cls;
1970 struct GNUNET_SERVICE_Handle *sh = c->sh;
1971
1972 c->drop_task = NULL;
1973 GNUNET_CONTAINER_DLL_remove (sh->clients_head,
1974 sh->clients_tail,
1975 c);
1976 GNUNET_assert (NULL == c->send_task);
1977 GNUNET_assert (NULL == c->recv_task);
1978 GNUNET_assert (NULL == c->warn_task);
1980 GNUNET_MQ_destroy (c->mq);
1981 if (! c->persist)
1982 {
1985 if ((0 != (SUSPEND_STATE_EMFILE & sh->suspend_state)) &&
1986 (0 == (SUSPEND_STATE_SHUTDOWN & sh->suspend_state)))
1987 do_resume (sh,
1989 }
1990 else
1991 {
1993 }
1994 GNUNET_free (c);
1995 if ((0 != (SUSPEND_STATE_SHUTDOWN & sh->suspend_state)) &&
1998}
1999
2000
2001void
2003{
2004 struct GNUNET_SERVICE_Client *client;
2005
2007 while (NULL != (client = srv->clients_head))
2008 {
2009 if (NULL == client->drop_task)
2012 finish_client_drop (client);
2013 }
2014 teardown_service (srv);
2015 GNUNET_free (srv->handlers);
2016 GNUNET_free (srv);
2017}
2018
2019
2020int
2022 int argc,
2023 char *const *argv,
2024 const char *service_name,
2026 GNUNET_SERVICE_InitCallback service_init_cb,
2029 void *cls,
2030 const struct GNUNET_MQ_MessageHandler *handlers)
2031{
2033
2034#if ENABLE_NLS
2035 char *path;
2036#endif
2037 char *cfg_filename;
2038 char *opt_cfg_filename;
2039 char *loglev;
2040 const char *xdg;
2041 char *logfile;
2042 int do_daemonize;
2043 unsigned long long skew_offset;
2044 unsigned long long skew_variance;
2045 long long clock_offset;
2047 int ret;
2048 int err;
2049 struct GNUNET_GETOPT_CommandLineOption service_options[] = {
2050 GNUNET_GETOPT_option_cfgfile (&opt_cfg_filename),
2052 "daemonize",
2053 gettext_noop (
2054 "do daemonize (detach from terminal)"),
2055 &do_daemonize),
2057 NULL),
2062 };
2063
2064 err = 1;
2065 memset (&sh, 0, sizeof(sh));
2066 xdg = getenv ("XDG_CONFIG_HOME");
2067 if (NULL != xdg)
2069 "%s%s%s",
2070 xdg,
2072 pd->config_file);
2073 else
2075 sh.pd = pd;
2076 sh.ready_confirm_fd = -1;
2077 sh.options = options;
2079 sh.service_init_cb = service_init_cb;
2080 sh.connect_cb = connect_cb;
2081 sh.disconnect_cb = disconnect_cb;
2082 sh.cb_cls = cls;
2083 sh.handlers = (NULL == pd->agpl_url)
2086 &return_agpl,
2087 NULL);
2088 sh.service_name = service_name;
2089 /* setup subsystems */
2090 loglev = NULL;
2091 logfile = NULL;
2092 opt_cfg_filename = NULL;
2093 do_daemonize = 0;
2094#if ENABLE_NLS
2095 if (NULL != pd->gettext_domain)
2096 {
2097 setlocale (LC_ALL, "");
2098 path = (NULL == pd->gettext_path)
2102 if (NULL != path)
2103 {
2104 bindtextdomain (pd->gettext_domain, path);
2105 GNUNET_free (path);
2106 }
2108 }
2109#endif
2111 service_options,
2112 argc,
2113 argv);
2114 if (GNUNET_SYSERR == ret)
2115 goto shutdown;
2116 if (GNUNET_NO == ret)
2117 {
2118 err = 0;
2119 goto shutdown;
2120 }
2122 loglev,
2123 logfile))
2124 {
2125 GNUNET_break (0);
2126 goto shutdown;
2127 }
2128 if (NULL != opt_cfg_filename)
2129 {
2130 if ((GNUNET_YES != GNUNET_DISK_file_test (opt_cfg_filename)) ||
2131 (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, opt_cfg_filename)))
2132 {
2134 _ ("Malformed configuration file `%s', exit ...\n"),
2135 opt_cfg_filename);
2136 goto shutdown;
2137 }
2138 }
2139 else
2140 {
2141 if (GNUNET_YES ==
2143 {
2144 if (GNUNET_SYSERR ==
2146 cfg_filename))
2147 {
2149 _ ("Malformed configuration file `%s', exit ...\n"),
2150 cfg_filename);
2151 goto shutdown;
2152 }
2153 }
2154 else
2155 {
2156 if (GNUNET_SYSERR ==
2158 NULL))
2159 {
2161 _ ("Malformed configuration, exit ...\n"));
2162 goto shutdown;
2163 }
2164 }
2165 }
2166 if (GNUNET_OK !=
2167 setup_service (pd,
2168 &sh))
2169 goto shutdown;
2170 if ( (1 == do_daemonize) &&
2171 (GNUNET_OK !=
2172 detach_terminal (&sh)) )
2173 {
2174 GNUNET_break (0);
2175 goto shutdown;
2176 }
2177 if (GNUNET_OK != set_user_id (&sh))
2178 goto shutdown;
2180 "Service `%s' runs with configuration from `%s'\n",
2182 (NULL != opt_cfg_filename) ? opt_cfg_filename : cfg_filename);
2183 if ( (GNUNET_OK ==
2185 "TESTING",
2186 "SKEW_OFFSET",
2187 &skew_offset)) &&
2188 (GNUNET_OK ==
2190 "TESTING",
2191 "SKEW_VARIANCE",
2192 &skew_variance)) )
2193 {
2194 clock_offset = skew_offset - skew_variance;
2195 GNUNET_TIME_set_offset (clock_offset);
2197 "Skewing clock by %lld ms\n",
2198 (long long) clock_offset);
2199 }
2201
2202 /* actually run service */
2203 err = 0;
2205 /* shutdown */
2206 if (1 == do_daemonize)
2208
2209shutdown:
2210 if (-1 != sh.ready_confirm_fd)
2211 {
2212 if (1 != write (sh.ready_confirm_fd, err ? "I" : "S", 1))
2214 GNUNET_break (0 == close (sh.ready_confirm_fd));
2215 }
2217 GNUNET_free (sh.handlers);
2220 GNUNET_free (logfile);
2221 GNUNET_free (loglev);
2223 GNUNET_free (opt_cfg_filename);
2224
2225 return err ? GNUNET_SYSERR : 0;
2226}
2227
2228
2234{
2235 /* DLL */
2237
2238 /* DLL */
2240
2241 /* Handle to the service to launch */
2243};
2244
2245/* The service list */
2247
2248/* The service list */
2250
2251
2252int
2254 const char *service_name,
2256 GNUNET_SERVICE_InitCallback service_init_cb,
2259 void *cls,
2260 const struct GNUNET_MQ_MessageHandler *handlers)
2261{
2262 struct ServiceHandleList *hle;
2264
2265 sh->pd = pd;
2266 sh->ready_confirm_fd = -1;
2267 sh->options = options;
2268 sh->service_init_cb = service_init_cb;
2269 sh->connect_cb = connect_cb;
2270 sh->disconnect_cb = disconnect_cb;
2271 sh->cb_cls = cls;
2272 sh->handlers = (NULL == pd->agpl_url)
2275 sh->service_name = service_name;
2276 hle = GNUNET_new (struct ServiceHandleList);
2277 hle->sh = sh;
2279 hll_tail,
2280 hle);
2281 return 0;
2282}
2283
2284
2285static void
2287{
2288 while (NULL != hll_head)
2289 {
2290 struct ServiceHandleList *shl = hll_head;
2291 struct GNUNET_SERVICE_Handle *sh = shl->sh;
2292
2294 hll_tail,
2295 shl);
2296 GNUNET_free (shl);
2297 if (-1 != sh->ready_confirm_fd)
2298 {
2299 if (1 != write (sh->ready_confirm_fd, "S", 1))
2301 "write");
2302 GNUNET_break (0 ==
2303 close (sh->ready_confirm_fd));
2304 }
2306 GNUNET_free (sh->handlers);
2307 GNUNET_free (sh);
2308 }
2309}
2310
2311
2313{
2316};
2317
2318
2319static void
2321{
2322 struct LaunchContext *lc = cls;
2323 struct GNUNET_CONFIGURATION_Handle *cfg = lc->cfg;
2324 const struct GNUNET_OS_ProjectData *pd = lc->pd;
2325
2326 for (struct ServiceHandleList *shl = hll_head;
2327 NULL != shl;
2328 shl = shl->next)
2329 {
2330 shl->sh->cfg = cfg;
2331 if (GNUNET_OK !=
2332 setup_service (pd,
2333 shl->sh))
2334 continue;
2335 if (GNUNET_OK !=
2336 set_user_id (shl->sh))
2337 continue;
2339 shl->sh);
2340 }
2342 NULL);
2343}
2344
2345
2346void
2348 int argc,
2349 char *const *argv,
2351 enum GNUNET_GenericReturnValue with_scheduler)
2352{
2353 struct LaunchContext lc = {
2354 .pd = pd,
2355 .cfg = cfg
2356 };
2357
2359 "Entering GNUNET_SERVICE_main\n");
2360 if (GNUNET_YES == with_scheduler)
2361 {
2362 if (GNUNET_YES !=
2364 argc,
2365 argv,
2366 cfg))
2367 return;
2369 &lc);
2370 }
2371 else
2372 {
2375 }
2376}
2377
2378
2379void
2381{
2382 do_suspend (sh,
2384}
2385
2386
2387void
2389{
2390 do_resume (sh,
2392}
2393
2394
2401static void
2403{
2404 struct GNUNET_SERVICE_Client *c = cls;
2405 int ret;
2406
2407 c->recv_task = NULL;
2408 /* first, check if there is still something in the buffer */
2409 ret = GNUNET_MST_next (c->mst,
2410 GNUNET_YES);
2411 if (GNUNET_SYSERR == ret)
2412 {
2413 if (NULL == c->drop_task)
2415 return;
2416 }
2417 if (GNUNET_NO == ret)
2418 return; /* done processing, wait for more later */
2420 if (c->needs_continue)
2421 return; /* #GNUNET_MST_next() did give a message to the client */
2422 /* need to receive more data from the network first */
2423 if (NULL != c->recv_task)
2424 return;
2426 c->sock,
2428 c);
2429}
2430
2431
2432void
2434{
2435 GNUNET_assert (NULL == c->drop_task);
2437 GNUNET_assert (NULL == c->recv_task);
2438 c->needs_continue = false;
2439 if (NULL != c->warn_task)
2440 {
2442 c->warn_task = NULL;
2443 }
2445 c);
2446}
2447
2448
2449void
2451{
2452 GNUNET_break (NULL != c->warn_task);
2453 if (NULL != c->warn_task)
2454 {
2456 c->warn_task = NULL;
2457 }
2458}
2459
2460
2461void
2463{
2464 struct GNUNET_SERVICE_Handle *sh = c->sh;
2465
2467 "Client dropped: %p (MQ: %p)\n",
2468 c,
2469 c->mq);
2470#if EXECINFO
2471 {
2472 void *backtrace_array[MAX_TRACE_DEPTH];
2473 int num_backtrace_strings = backtrace (backtrace_array,
2474 MAX_TRACE_DEPTH);
2475 char **backtrace_strings =
2476 backtrace_symbols (backtrace_array,
2477 t->num_backtrace_strings);
2478 for (unsigned int i = 0; i < num_backtrace_strings; i++)
2480 "client drop trace %u: %s\n",
2481 i,
2482 backtrace_strings[i]);
2483 }
2484#endif
2485 GNUNET_assert (NULL == c->drop_task);
2486 if (NULL != sh->disconnect_cb)
2487 sh->disconnect_cb (sh->cb_cls,
2488 c,
2489 c->user_context);
2490 if (NULL != c->warn_task)
2491 {
2493 c->warn_task = NULL;
2494 }
2495 if (NULL != c->recv_task)
2496 {
2498 c->recv_task = NULL;
2499 }
2500 if (NULL != c->send_task)
2501 {
2503 c->send_task = NULL;
2504 }
2506 c);
2507}
2508
2509
2510void
2512{
2513 if (0 == (sh->suspend_state & SUSPEND_STATE_SHUTDOWN))
2514 do_suspend (sh,
2516 for (struct GNUNET_SERVICE_Client *client = sh->clients_head;
2517 NULL != client;
2518 client = client->next)
2519 {
2520 if (NULL == client->drop_task)
2522 }
2523}
2524
2525
2526void
2528{
2529 c->is_monitor = true;
2530 if (((0 != (SUSPEND_STATE_SHUTDOWN & c->sh->suspend_state)) &&
2531 (! have_non_monitor_clients (c->sh))))
2533}
2534
2535
2536void
2538{
2539 c->persist = true;
2540}
2541
2542
2543struct GNUNET_MQ_Handle *
2545{
2546 return c->mq;
2547}
2548
2549
2550/* end of service.c */
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_OPTION_END
Definition: 002.c:13
struct GNUNET_GETOPT_CommandLineOption options[]
Definition: 002.c:5
struct GNUNET_MQ_MessageHandlers handlers[]
Definition: 003.c:1
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
char * getenv()
#define gettext_noop(String)
Definition: gettext.h:74
#define textdomain(Domainname)
Definition: gettext.h:61
#define bindtextdomain(Domainname, Dirname)
Definition: gettext.h:62
static int list
Set if we should print a list of currently running services.
Definition: gnunet-arm.c:68
static int ret
Final status code.
Definition: gnunet-arm.c:93
static struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition: gnunet-arm.c:108
static char * cfg_filename
Name of the configuration file.
static uint16_t port
Port number.
Definition: gnunet-bcd.c:146
static struct in_addr dummy
Target "dummy" address of the packet we pretend to respond to.
static struct GNUNET_IDENTITY_Handle * sh
Handle to IDENTITY service.
static char * res
Currently read line or NULL on EOF.
static int add
Desired action is to add a record.
static struct GNUNET_NETWORK_Handle * ls
Listen socket for STUN processing.
Definition: gnunet-nat.c:85
static void disconnect_cb(void *cls, const struct GNUNET_CADET_Channel *channel)
Function called by cadet when a client disconnects.
static void * connect_cb(void *cls, struct GNUNET_CADET_Channel *channel, const struct GNUNET_PeerIdentity *initiator)
Functions of this type are called upon new cadet connection from other peers.
static struct GNUNET_PeerIdentity pid
Identity of the peer we transmit to / connect to.
static char * service_name
Option -s: service name (hash to get service descriptor)
Definition: gnunet-vpn.c:50
static struct GNUNET_SCHEDULER_Task * t
Main task.
Constants for network protocols.
Functions related to doing DNS lookups.
#define GNUNET_AGPL_URL
NOTE: You MUST adjust this URL to point to the location of a publicly accessible repository (or TGZ) ...
struct GNUNET_CONFIGURATION_Handle * GNUNET_CONFIGURATION_create(const struct GNUNET_OS_ProjectData *pd)
Create a new configuration object.
enum GNUNET_GenericReturnValue 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.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_number(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *number)
Get a configuration value that should be a number.
void GNUNET_CONFIGURATION_destroy(struct GNUNET_CONFIGURATION_Handle *cfg)
Destroy configuration object.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_load(struct GNUNET_CONFIGURATION_Handle *cfg, const char *filename)
Load configuration.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_have_value(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Test if we have a value for a particular option.
enum GNUNET_GenericReturnValue GNUNET_DISK_file_test(const char *fil)
Check that fil corresponds to a filename (of a file that exists and that is not a directory).
Definition: disk.c:523
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:623
#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.
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_cfgfile(char **fn)
Allow user to specify configuration file name (-c option)
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_logfile(char **logfn)
Allow user to specify log file name (-l option)
int GNUNET_GETOPT_run(const char *binaryOptions, const struct GNUNET_GETOPT_CommandLineOption *allOptions, unsigned int argc, char *const *argv)
Parse the command line.
Definition: getopt.c:884
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_help(const struct GNUNET_OS_ProjectData *pd, const char *about)
Defining the option to print the command line help text (-h option).
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_loglevel(char **level)
Define the '-L' log level option.
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_flag(char shortName, const char *name, const char *description, int *val)
Allow user to specify a flag (which internally means setting an integer to 1/GNUNET_YES/GNUNET_OK.
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_version(const char *version)
Define the option to print the version of the application (-v option)
#define GNUNET_is_zero(a)
Check that memory in a is all zeros.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
#define GNUNET_log(kind,...)
#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
@ GNUNET_SYSERR
#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.
enum GNUNET_GenericReturnValue GNUNET_log_setup(const char *comp, const char *loglevel, const char *logfile)
Setup logging.
const char * GNUNET_a2s(const struct sockaddr *addr, socklen_t addrlen)
Convert a "struct sockaddr*" (IPv4 or IPv6 address) to a string (for printing debug messages).
#define GNUNET_log_strerror(level, cmd)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
#define GNUNET_log_strerror_file(level, cmd, filename)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.
#define GNUNET_free(ptr)
Wrapper around free.
GNUNET_MQ_Error
Error codes for the queue.
void GNUNET_MQ_inject_error(struct GNUNET_MQ_Handle *mq, enum GNUNET_MQ_Error error)
Call the error handler of a message queue with the given error code.
Definition: mq.c:269
struct GNUNET_MQ_Handle * GNUNET_MQ_queue_for_callbacks(GNUNET_MQ_SendImpl send, GNUNET_MQ_DestroyImpl destroy, GNUNET_MQ_CancelImpl cancel, void *impl_state, const struct GNUNET_MQ_MessageHandler *handlers, GNUNET_MQ_ErrorHandler error_handler, void *cls)
Create a message queue for the specified handlers.
Definition: mq.c:482
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_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
struct GNUNET_MQ_MessageHandler * GNUNET_MQ_copy_handlers2(const struct GNUNET_MQ_MessageHandler *handlers, GNUNET_MQ_MessageCallback agpl_handler, void *agpl_cls)
Copy an array of handlers, appending AGPL handler.
Definition: mq.c:992
struct GNUNET_MQ_MessageHandler * GNUNET_MQ_copy_handlers(const struct GNUNET_MQ_MessageHandler *handlers)
Copy an array of handlers.
Definition: mq.c:974
void GNUNET_MQ_impl_send_continue(struct GNUNET_MQ_Handle *mq)
Call the send implementation for the next queued message, if any.
Definition: mq.c:437
void GNUNET_MQ_inject_message(struct GNUNET_MQ_Handle *mq, const struct GNUNET_MessageHeader *mh)
Call the message message handler that was registered for the type of the given message in the given m...
Definition: mq.c:187
void GNUNET_MQ_impl_send_in_flight(struct GNUNET_MQ_Handle *mq)
Call the send notification for the current message, but do not try to send the next message until #gn...
Definition: mq.c:461
void GNUNET_MQ_set_handlers_closure(struct GNUNET_MQ_Handle *mq, void *handlers_cls)
Change the closure argument in all of the handlers of the mq.
Definition: mq.c:506
void GNUNET_MQ_destroy(struct GNUNET_MQ_Handle *mq)
Destroy the message queue.
Definition: mq.c:700
@ GNUNET_MQ_ERROR_NO_MATCH
We received a message for which we have no matching handler.
@ GNUNET_MQ_ERROR_WRITE
FIXME: document!
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_accept(const struct GNUNET_NETWORK_Handle *desc, struct sockaddr *address, socklen_t *address_len)
Accept a new connection on a socket.
Definition: network.c:392
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition: network.c:508
char * GNUNET_NETWORK_shorten_unixpath(char *unixpath)
Given a unixpath that is too long (larger than UNIX_PATH_MAX), shorten it to an acceptable length whi...
Definition: network.c:143
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_box_native(int fd)
Box a native socket (and check that it is a socket).
Definition: network.c:580
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_create(int domain, int type, int protocol)
Create a new socket.
Definition: network.c:833
void GNUNET_NETWORK_socket_free_memory_only_(struct GNUNET_NETWORK_Handle *desc)
Only free memory of a socket, keep the file descriptor untouched.
Definition: network.c:566
ssize_t GNUNET_NETWORK_socket_send(const struct GNUNET_NETWORK_Handle *desc, const void *buffer, size_t length)
Send data (always non-blocking).
Definition: network.c:738
enum GNUNET_GenericReturnValue GNUNET_NETWORK_test_pf(int pf)
Test if the given protocol family is supported by this system.
Definition: network.c:79
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_bind(struct GNUNET_NETWORK_Handle *desc, const struct sockaddr *address, socklen_t address_len)
Bind a socket to a particular address.
Definition: network.c:439
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_listen(const struct GNUNET_NETWORK_Handle *desc, int backlog)
Listen on a socket.
Definition: network.c:652
char * GNUNET_OS_installation_get_path(const struct GNUNET_OS_ProjectData *pd, enum GNUNET_OS_InstallationPathKind dirkind)
Get the path to a specific GNUnet installation directory or, with GNUNET_OS_IPK_SELF_PREFIX,...
@ GNUNET_OS_IPK_LOCALEDIR
Return the directory where translations are installed (share/locale/)
enum GNUNET_GenericReturnValue GNUNET_PROGRAM_conf_and_options(const struct GNUNET_OS_ProjectData *pd, int argc, char *const *argv, struct GNUNET_CONFIGURATION_Handle *cfg)
Create configuration handle from options and configuration file.
Definition: program.c:429
#define GNUNET_MESSAGE_TYPE_RESPONSE_AGPL
Source code link.
void GNUNET_RESOLVER_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Create the connection to the resolver service.
Definition: resolver_api.c:258
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_net(struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition: scheduler.c:1511
void GNUNET_SCHEDULER_run(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Initialize and run scheduler.
Definition: scheduler.c:725
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_write_net(struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *wfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition: scheduler.c:1582
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
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:980
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1304
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1277
enum GNUNET_GenericReturnValue GNUNET_MST_next(struct GNUNET_MessageStreamTokenizer *mst, int one_shot)
Obtain the next message from the mst, assuming that there are more unprocessed messages in the intern...
Definition: mst.c:387
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
enum GNUNET_GenericReturnValue GNUNET_MST_read(struct GNUNET_MessageStreamTokenizer *mst, struct GNUNET_NETWORK_Handle *sock, int purge, int one_shot)
Add incoming data to the receive buffer and call the callback for all complete messages.
Definition: mst.c:338
void GNUNET_SERVICE_suspend(struct GNUNET_SERVICE_Handle *sh)
Suspend accepting connections from the listen socket temporarily.
Definition: service.c:2380
void GNUNET_SERVICE_stop(struct GNUNET_SERVICE_Handle *srv)
Stops a service that was started with GNUNET_SERVICE_start().
Definition: service.c:2002
void GNUNET_SERVICE_shutdown(struct GNUNET_SERVICE_Handle *sh)
Explicitly stops the service.
Definition: service.c:2511
int GNUNET_SERVICE_run_(const struct GNUNET_OS_ProjectData *pd, int argc, char *const *argv, const char *service_name, enum GNUNET_SERVICE_Options options, GNUNET_SERVICE_InitCallback service_init_cb, GNUNET_SERVICE_ConnectHandler connect_cb, GNUNET_SERVICE_DisconnectHandler disconnect_cb, void *cls, const struct GNUNET_MQ_MessageHandler *handlers)
Creates the "main" function for a GNUnet service.
Definition: service.c:2021
GNUNET_SERVICE_Options
Options for the service (bitmask).
void GNUNET_SERVICE_client_mark_monitor(struct GNUNET_SERVICE_Client *c)
Set the 'monitor' flag on this client.
Definition: service.c:2527
int GNUNET_SERVICE_register_(const struct GNUNET_OS_ProjectData *pd, const char *service_name, enum GNUNET_SERVICE_Options options, GNUNET_SERVICE_InitCallback service_init_cb, GNUNET_SERVICE_ConnectHandler connect_cb, GNUNET_SERVICE_DisconnectHandler disconnect_cb, void *cls, const struct GNUNET_MQ_MessageHandler *handlers)
Registers the GNUnet service to be scheduled as part of a monilithic libgnunet.
Definition: service.c:2253
void(* GNUNET_SERVICE_DisconnectHandler)(void *cls, struct GNUNET_SERVICE_Client *c, void *internal_cls)
Callback to be called when a client disconnected from the service.
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition: service.c:2462
struct GNUNET_SERVICE_Handle * GNUNET_SERVICE_start(const struct GNUNET_OS_ProjectData *pd, const char *service_name, const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_SERVICE_ConnectHandler connect_cb, GNUNET_SERVICE_DisconnectHandler disconnect_cb, void *cls, const struct GNUNET_MQ_MessageHandler *handlers)
Low-level function to start a service if the scheduler is already running.
Definition: service.c:1927
void GNUNET_SERVICE_client_persist(struct GNUNET_SERVICE_Client *c)
Set the persist option on this client.
Definition: service.c:2537
void GNUNET_SERVICE_client_disable_continue_warning(struct GNUNET_SERVICE_Client *c)
Disable the warning the server issues if a message is not acknowledged in a timely fashion.
Definition: service.c:2450
void GNUNET_SERVICE_main(const struct GNUNET_OS_ProjectData *pd, int argc, char *const *argv, struct GNUNET_CONFIGURATION_Handle *cfg, enum GNUNET_GenericReturnValue with_scheduler)
Run the mainloop in a monolithic libgnunet.
Definition: service.c:2347
void(* GNUNET_SERVICE_InitCallback)(void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_SERVICE_Handle *sh)
Callback to initialize a service, called exactly once when the service is run.
void *(* GNUNET_SERVICE_ConnectHandler)(void *cls, struct GNUNET_SERVICE_Client *c, struct GNUNET_MQ_Handle *mq)
Callback to be called when a client connects to the service.
struct GNUNET_MQ_Handle * GNUNET_SERVICE_client_get_mq(struct GNUNET_SERVICE_Client *c)
Obtain the message queue of c.
Definition: service.c:2544
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_MANUAL_SHUTDOWN
Do not trigger server shutdown on signal at all; instead, allow for the user to terminate the server ...
@ GNUNET_SERVICE_OPTION_SHUTDOWN_BITMASK
Bitmask over the shutdown options.
@ GNUNET_SERVICE_OPTION_CLOSE_LSOCKS
Instead of listening on lsocks passed by the parent, close them after opening our own listen socket(s...
@ GNUNET_SERVICE_OPTION_NONE
Use defaults.
@ GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN
Trigger a SOFT server shutdown on signals, allowing active non-monitor clients to complete their tran...
struct GNUNET_STRINGS_IPv6NetworkPolicy * GNUNET_STRINGS_parse_ipv6_policy(const char *routeListX)
Parse an IPv6 network policy.
Definition: strings.c:1455
struct GNUNET_STRINGS_IPv4NetworkPolicy * GNUNET_STRINGS_parse_ipv4_policy(const char *routeListX)
Parse an IPv4 network policy.
Definition: strings.c:1280
size_t GNUNET_strlcpy(char *dst, const char *src, size_t n)
Like strlcpy but portable.
Definition: strings.c:137
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
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:585
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:111
#define GNUNET_TIME_UNIT_MINUTES
One minute.
void GNUNET_TIME_set_offset(long long offset)
Set the timestamp offset for this instance.
Definition: time.c:49
#define DIR_SEPARATOR_STR
Definition: platform.h:167
#define _(String)
GNU gettext support macro.
Definition: platform.h:179
static void do_registered_services_shutdown(void *cls)
Definition: service.c:2286
static char * get_pid_file_name(struct GNUNET_SERVICE_Handle *sh)
Get the name of the file where we will write the PID of the service.
Definition: service.c:1747
static void do_resume(struct GNUNET_SERVICE_Handle *sh, enum SuspendReason sr)
Resume accepting connections from the listen socket.
Definition: service.c:880
static bool check_ipv6_listed(const struct GNUNET_STRINGS_IPv6NetworkPolicy *list, const struct in6_addr *ip)
Check if the given IP address is in the list of IP addresses.
Definition: service.c:465
static void return_agpl(void *cls, const struct GNUNET_MessageHeader *msg)
Function to return link to AGPL source upon request.
Definition: service.c:1901
static void teardown_service(struct GNUNET_SERVICE_Handle *sh)
Tear down the service, closing the listen sockets and freeing the ACLs.
Definition: service.c:1872
static void service_client_recv(void *cls)
A client sent us data.
Definition: service.c:704
static void service_mq_cancel(struct GNUNET_MQ_Handle *mq, void *impl_state)
Implementation function that cancels the currently sent message.
Definition: service.c:592
static void service_shutdown(void *cls)
Shutdown task triggered when a service should be terminated.
Definition: service.c:410
static void resume_client_receive(void *cls)
Task run to resume receiving data from the client after the client called GNUNET_SERVICE_client_conti...
Definition: service.c:2402
static enum GNUNET_GenericReturnValue detach_terminal(struct GNUNET_SERVICE_Handle *sh)
Detach from terminal.
Definition: service.c:1788
static void launch_registered_services(void *cls)
Definition: service.c:2320
static struct ServiceHandleList * hll_head
Definition: service.c:2246
static void service_mq_send(struct GNUNET_MQ_Handle *mq, const struct GNUNET_MessageHeader *msg, void *impl_state)
Signature of functions implementing the sending functionality of a message queue.
Definition: service.c:564
static char * get_user_name(struct GNUNET_SERVICE_Handle *sh)
Get the name of the user that'll be used to provide the service.
Definition: service.c:1676
#define LOG_STRERROR_FILE(kind, syscall, filename)
Definition: service.c:44
static void start_client(struct GNUNET_SERVICE_Handle *sh, struct GNUNET_NETWORK_Handle *csock)
We have successfully accepted a connection from a client.
Definition: service.c:749
static void do_send(void *cls)
Task run when we are ready to transmit data to the client.
Definition: service.c:495
static enum GNUNET_GenericReturnValue process_acl4(struct GNUNET_STRINGS_IPv4NetworkPolicy **ret, struct GNUNET_SERVICE_Handle *sh, const char *option)
Parse an IPv4 access control list.
Definition: service.c:940
static enum GNUNET_GenericReturnValue setup_service(const struct GNUNET_OS_ProjectData *pd, struct GNUNET_SERVICE_Handle *sh)
Setup service handle.
Definition: service.c:1476
static void finish_client_drop(void *cls)
Asynchronously finish dropping the client.
Definition: service.c:1967
static int service_client_mst_cb(void *cls, const struct GNUNET_MessageHeader *message)
Functions with this signature are called whenever a complete message is received by the tokenizer for...
Definition: service.c:673
static bool check_ipv4_listed(const struct GNUNET_STRINGS_IPv4NetworkPolicy *list, const struct in_addr *add)
Check if the given IP address is in the list of IP addresses.
Definition: service.c:442
static void pid_file_delete(struct GNUNET_SERVICE_Handle *sh)
Delete the PID file that was created by our parent.
Definition: service.c:1767
static int get_server_addresses(const char *service_name, const struct GNUNET_CONFIGURATION_Handle *cfg, struct sockaddr ***addrs, socklen_t **addr_lens)
Get the list of addresses that a server for the given service should bind to.
Definition: service.c:1065
static void do_suspend(struct GNUNET_SERVICE_Handle *sh, enum SuspendReason sr)
Suspend accepting connections from the listen socket temporarily.
Definition: service.c:383
static void warn_no_client_continue(void *cls)
Task run to warn about missing calls to GNUNET_SERVICE_client_continue().
Definition: service.c:640
static enum GNUNET_GenericReturnValue set_user_id(struct GNUNET_SERVICE_Handle *sh)
Set user ID.
Definition: service.c:1697
static void service_mq_error_handler(void *cls, enum GNUNET_MQ_Error error)
Generic error handler, called with the appropriate error code and the same closure specified at the c...
Definition: service.c:615
static void add_unixpath(struct sockaddr **saddrs, socklen_t *saddrlens, const char *unixpath)
Add the given UNIX domain path as an address to the list (as the first entry).
Definition: service.c:1021
static void service_main(void *cls)
First task run by any service.
Definition: service.c:909
static enum GNUNET_GenericReturnValue process_acl6(struct GNUNET_STRINGS_IPv6NetworkPolicy **ret, struct GNUNET_SERVICE_Handle *sh, const char *option)
Parse an IPv6 access control list.
Definition: service.c:981
static enum GNUNET_GenericReturnValue have_non_monitor_clients(struct GNUNET_SERVICE_Handle *sh)
Check if any of the clients we have left are unrelated to monitoring.
Definition: service.c:359
#define LOG(kind,...)
Definition: service.c:39
#define LOG_STRERROR(kind, syscall)
Definition: service.c:41
static void accept_client(void *cls)
We have a client.
Definition: service.c:786
SuspendReason
Reasons why we might be suspended.
Definition: service.c:84
@ SUSPEND_STATE_SHUTDOWN
Suspension because service was permanently shutdown.
Definition: service.c:108
@ SUSPEND_STATE_APP
Application requested it.
Definition: service.c:93
@ SUSPEND_STATE_NONE
We are running normally.
Definition: service.c:88
@ SUSPEND_STATE_APP_AND_EMFILE
Both reasons, APP and EMFILE apply.
Definition: service.c:103
@ SUSPEND_STATE_EMFILE
OS ran out of file descriptors.
Definition: service.c:98
static struct ServiceHandleList * hll_tail
Definition: service.c:2249
static struct GNUNET_NETWORK_Handle * open_listen_socket(const struct sockaddr *server_addr, socklen_t socklen)
Create and initialize a listen socket for the server.
Definition: service.c:1367
void GNUNET_SPEEDUP_stop_()
Stop tasks that modify clock behavior.
Definition: speedup.c:100
Definition of a command line option.
const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration to use.
Definition: identity_api.c:101
void * cb_cls
Closure for cb.
Definition: identity_api.c:122
Handle to a message queue.
Definition: mq.c:87
Message handler for a specific message type.
Header for all communications.
Handle to a message stream tokenizer.
Definition: mst.c:45
handle to a socket
Definition: network.c:53
Project-specific data used to help the OS subsystem find installation paths.
const char * gettext_path
Gettext directory, e.g.
const char * gettext_domain
Gettext domain for localisation, e.g.
const char * agpl_url
URL pointing to the source code of the application.
const char * user_config_file
Configuration file name to use (if $XDG_CONFIG_HOME is not set).
const char * config_file
Configuration file name (in $XDG_CONFIG_HOME) to use.
const char * version
String identifying the current project version.
Entry in list of pending tasks.
Definition: scheduler.c:136
Handle to a client that is connected to a service.
Definition: service.c:249
bool persist
Persist the file handle for this client no matter what happens, force the OS to close once the proces...
Definition: service.c:330
size_t msg_pos
Current position in msg at which we are transmitting.
Definition: service.c:323
struct GNUNET_SCHEDULER_Task * send_task
Task that transmit data to the client.
Definition: service.c:301
struct GNUNET_SCHEDULER_Task * drop_task
Task run to finish dropping the client after the stack has properly unwound.
Definition: service.c:290
struct GNUNET_TIME_Absolute warn_start
Time when we last gave a message from this client to the application.
Definition: service.c:318
struct GNUNET_NETWORK_Handle * sock
Socket of this client.
Definition: service.c:268
uint16_t warn_type
Type of last message processed (for warn_no_receive_done).
Definition: service.c:347
const struct GNUNET_MessageHeader * msg
Pointer to the message to be transmitted by send_task.
Definition: service.c:306
struct GNUNET_SCHEDULER_Task * warn_task
Task that warns about missing calls to GNUNET_SERVICE_client_continue().
Definition: service.c:284
struct GNUNET_SCHEDULER_Task * recv_task
Task that receives data from the client to pass it to the handlers.
Definition: service.c:296
struct GNUNET_SERVICE_Handle * sh
Service that this client belongs to.
Definition: service.c:263
struct GNUNET_SERVICE_Client * next
Kept in a DLL.
Definition: service.c:253
void * user_context
User context value, value returned from the connect callback.
Definition: service.c:312
bool needs_continue
Are we waiting for the application to call GNUNET_SERVICE_client_continue()?
Definition: service.c:342
bool is_monitor
Is this client a 'monitor' client that should not be counted when deciding on destroying the server d...
Definition: service.c:337
struct GNUNET_SERVICE_Client * prev
Kept in a DLL.
Definition: service.c:258
struct GNUNET_MQ_Handle * mq
Message queue for the client.
Definition: service.c:273
struct GNUNET_MessageStreamTokenizer * mst
Tokenizer we use for processing incoming data.
Definition: service.c:278
Handle to a service.
Definition: service.c:116
void * task_cls
Closure for task.
Definition: service.c:180
struct GNUNET_STRINGS_IPv6NetworkPolicy * v6_denied
IPv6 addresses that are not allowed to connect.
Definition: service.c:190
GNUNET_SERVICE_ConnectHandler connect_cb
Function to call when clients connect.
Definition: service.c:140
GNUNET_SERVICE_InitCallback service_init_cb
Main service-specific task to run.
Definition: service.c:135
int ready_confirm_fd
If we are daemonizing, this FD is set to the pipe to the parent.
Definition: service.c:235
struct GNUNET_SERVICE_Client * clients_tail
Our clients, kept in a DLL.
Definition: service.c:170
struct GNUNET_MQ_MessageHandler * handlers
Message handlers to use for all clients.
Definition: service.c:175
void * cb_cls
Closure for service_init_cb, connect_cb, disconnect_cb.
Definition: service.c:150
struct GNUNET_STRINGS_IPv4NetworkPolicy * v4_denied
IPv4 addresses that are not allowed to connect.
Definition: service.c:185
struct GNUNET_STRINGS_IPv6NetworkPolicy * v6_allowed
IPv6 addresses that are allowed to connect (if not set, all are allowed).
Definition: service.c:202
const char * service_name
Name of our service.
Definition: service.c:130
struct GNUNET_SERVICE_Client * clients_head
Our clients, kept in a DLL.
Definition: service.c:165
bool require_found
If true, consider unknown message types an error where the client is disconnected.
Definition: service.c:241
GNUNET_SERVICE_DisconnectHandler disconnect_cb
Function to call when clients disconnect / are disconnected.
Definition: service.c:145
enum GNUNET_SERVICE_Options options
Our options.
Definition: service.c:228
int match_uid
Do we require a matching UID for UNIX domain socket connections? GNUNET_NO means that the UID does no...
Definition: service.c:209
int match_gid
Do we require a matching GID for UNIX domain socket connections? Ignored if match_uid is GNUNET_YES.
Definition: service.c:218
struct ServiceListenContext * slc_head
DLL of listen sockets used to accept new connections.
Definition: service.c:155
const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition: service.c:120
enum SuspendReason suspend_state
Are we suspended, and if so, why?
Definition: service.c:223
const struct GNUNET_OS_ProjectData * pd
Project data of this service.
Definition: service.c:125
struct ServiceListenContext * slc_tail
DLL of listen sockets used to accept new connections.
Definition: service.c:160
struct GNUNET_STRINGS_IPv4NetworkPolicy * v4_allowed
IPv4 addresses that are allowed to connect (if not set, all are allowed).
Definition: service.c:196
IPV4 network in CIDR notation.
network in CIDR notation for IPV6.
Time for absolute times used by GNUnet, in microseconds.
struct GNUNET_CONFIGURATION_Handle * cfg
Definition: service.c:2314
const struct GNUNET_OS_ProjectData * pd
Definition: service.c:2315
A list of service to be launched when GNUNET_SERVICE_main() is called.
Definition: service.c:2234
struct GNUNET_SERVICE_Handle * sh
Definition: service.c:2242
struct ServiceHandleList * next
Definition: service.c:2239
struct ServiceHandleList * prev
Definition: service.c:2236
Information the service tracks per listen operation.
Definition: service.c:52
struct ServiceListenContext * next
Kept in a DLL.
Definition: service.c:56
struct ServiceListenContext * prev
Kept in a DLL.
Definition: service.c:61
struct GNUNET_SCHEDULER_Task * listen_task
Task scheduled to do the listening.
Definition: service.c:76
struct GNUNET_NETWORK_Handle * listen_socket
Socket we are listening on.
Definition: service.c:71
struct GNUNET_SERVICE_Handle * sh
Service this listen context belongs to.
Definition: service.c:66