GNUnet 0.21.1
service.c
Go to the documentation of this file.
1/*
2 This file is part of GNUnet.
3 Copyright (C) 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
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_protocols.h"
31#include "gnunet_constants.h"
33#include "speedup.h"
34
35#if HAVE_MALLINFO2
36#include <malloc.h>
37#include "gauger.h"
38#endif
39
40
41#define LOG(kind, ...) GNUNET_log_from (kind, "util-service", __VA_ARGS__)
42
43#define LOG_STRERROR(kind, syscall) \
44 GNUNET_log_from_strerror (kind, "util-service", syscall)
45
46#define LOG_STRERROR_FILE(kind, syscall, filename) \
47 GNUNET_log_from_strerror_file (kind, "util-service", syscall, filename)
48
49
54{
59
64
69
74
79};
80
81
86{
91
96
101
106
112
113
118{
123
127 const char *service_name;
128
133
138
143
147 void *cb_cls;
148
153
158
163
168
173
177 void *task_cls;
178
179
184
189
195
201
208
217
222
227
234
238 int ret;
239
245};
246
247
252{
257
262
267
272
277
282
288
294
300
305
310
316
322
326 size_t msg_pos;
327
334
341
346
350 uint16_t warn_type;
351};
352
353
361static int
363{
364 for (struct GNUNET_SERVICE_Client *client = sh->clients_head; NULL != client;
365 client = client->next)
366 {
367 if (client->is_monitor)
368 continue;
369 return GNUNET_YES;
370 }
371 return GNUNET_NO;
372}
373
374
382static void
384{
385 struct ServiceListenContext *slc;
386
387 GNUNET_assert (0 == (sh->suspend_state & sr));
388 sh->suspend_state |= sr;
389 for (slc = sh->slc_head; NULL != slc; slc = slc->next)
390 {
391 if (NULL != slc->listen_task)
392 {
394 slc->listen_task = NULL;
395 }
396 }
397}
398
399
408static void
410{
411 struct GNUNET_SERVICE_Handle *sh = cls;
412
414 {
417 break;
419 /* This task should never be run if we are using
420 the manual shutdown. */
421 GNUNET_assert (0);
422 break;
424 if (0 == (sh->suspend_state & SUSPEND_STATE_SHUTDOWN))
428 break;
429 }
430}
431
432
440static int
442 const struct in_addr *add)
443{
444 unsigned int i;
445
446 if (NULL == list)
447 return GNUNET_NO;
448 i = 0;
449 while ((0 != list[i].network.s_addr) || (0 != list[i].netmask.s_addr))
450 {
451 if ((add->s_addr & list[i].netmask.s_addr) ==
452 (list[i].network.s_addr & list[i].netmask.s_addr))
453 return GNUNET_YES;
454 i++;
455 }
456 return GNUNET_NO;
457}
458
459
467static int
469 const struct in6_addr *ip)
470{
471 unsigned int i;
472
473 if (NULL == list)
474 return GNUNET_NO;
475 i = 0;
476NEXT:
477 while (GNUNET_NO == GNUNET_is_zero (&list[i].network))
478 {
479 for (unsigned int j = 0; j < sizeof(struct in6_addr) / sizeof(int); j++)
480 if (((((int *) ip)[j] & ((int *) &list[i].netmask)[j])) !=
481 (((int *) &list[i].network)[j] & ((int *) &list[i].netmask)[j]))
482 {
483 i++;
484 goto NEXT;
485 }
486 return GNUNET_YES;
487 }
488 return GNUNET_NO;
489}
490
491
498static void
499do_send (void *cls)
500{
501 struct GNUNET_SERVICE_Client *client = cls;
502 ssize_t ret;
503 size_t left;
504 const char *buf;
505
507 "service: sending message with type %u\n",
508 ntohs (client->msg->type));
509 client->send_task = NULL;
510 buf = (const char *) client->msg;
511 left = ntohs (client->msg->size) - client->msg_pos;
513 &buf[client->msg_pos],
514 left);
515 GNUNET_assert (ret <= (ssize_t) left);
516 if (0 == ret)
517 {
518 LOG (GNUNET_ERROR_TYPE_DEBUG, "no data send");
520 return;
521 }
522 if (-1 == ret)
523 {
524 if ((EAGAIN == errno) || (EINTR == errno))
525 {
526 /* ignore */
527 ret = 0;
528 }
529 else
530 {
531 if (EPIPE != errno)
534 "socket send returned with error code %i",
535 errno);
537 return;
538 }
539 }
540 if (0 == client->msg_pos)
541 {
543 }
544 client->msg_pos += ret;
545 if (left > (size_t) ret)
546 {
547 GNUNET_assert (NULL == client->drop_task);
548 client->send_task =
550 client->sock,
551 &do_send,
552 client);
553 return;
554 }
556}
557
558
567static void
569 const struct GNUNET_MessageHeader *msg,
570 void *impl_state)
571{
572 struct GNUNET_SERVICE_Client *client = impl_state;
573
574 (void) mq;
575 if (NULL != client->drop_task)
576 return; /* we're going down right now, do not try to send */
577 GNUNET_assert (NULL == client->send_task);
579 "Sending message of type %u and size %u to client\n",
580 ntohs (msg->type),
581 ntohs (msg->size));
582 client->msg = msg;
583 client->msg_pos = 0;
585 client);
586}
587
588
595static void
596service_mq_cancel (struct GNUNET_MQ_Handle *mq, void *impl_state)
597{
598 struct GNUNET_SERVICE_Client *client = impl_state;
599
600 (void) mq;
601 GNUNET_assert (0 == client->msg_pos);
602 client->msg = NULL;
604 client->send_task = NULL;
605}
606
607
617static void
619{
620 struct GNUNET_SERVICE_Client *client = cls;
621 struct GNUNET_SERVICE_Handle *sh = client->sh;
622
623 if ((GNUNET_MQ_ERROR_NO_MATCH == error) && (GNUNET_NO == sh->require_found))
624 {
626 "No handler for message of type %u found\n",
627 (unsigned int) client->warn_type);
629 return; /* ignore error */
630 }
632}
633
634
640static void
642{
643 struct GNUNET_SERVICE_Client *client = cls;
644
646 0 !=
647 client->warn_type); /* type should never be 0 here, as we don't use 0 */
650 client);
651 LOG (
653 _ (
654 "Processing code for message of type %u did not call `GNUNET_SERVICE_client_continue' after %s\n"),
655 (unsigned int) client->warn_type,
657 client->warn_start),
658 GNUNET_YES));
659}
660
661
673static int
675 const struct GNUNET_MessageHeader *message)
676{
677 struct GNUNET_SERVICE_Client *client = cls;
678
680 "Received message of type %u and size %u from client\n",
681 ntohs (message->type),
682 ntohs (message->size));
684 client->needs_continue = GNUNET_YES;
685 client->warn_type = ntohs (message->type);
687 GNUNET_assert (NULL == client->warn_task);
690 client);
691 GNUNET_MQ_inject_message (client->mq, message);
692 if (NULL != client->drop_task)
693 return GNUNET_SYSERR;
694 return GNUNET_OK;
695}
696
697
704static void
706{
707 struct GNUNET_SERVICE_Client *client = cls;
709
710 client->recv_task = NULL;
711 ret = GNUNET_MST_read (client->mst,
712 client->sock,
713 GNUNET_NO,
714 GNUNET_YES);
715 if (GNUNET_SYSERR == ret)
716 {
717 /* client closed connection (or IO error) */
718 if (NULL == client->drop_task)
719 {
722 }
723 return;
724 }
725 if (GNUNET_NO == ret)
726 return; /* more messages in buffer, wait for application
727 to be done processing */
729 if (GNUNET_YES == client->needs_continue)
730 return;
731 if (NULL != client->recv_task)
732 return;
733 /* MST needs more data, re-schedule read job */
734 client->recv_task =
736 client->sock,
738 client);
739}
740
741
749static void
751 struct GNUNET_NETWORK_Handle *csock)
752{
753 struct GNUNET_SERVICE_Client *client;
754
755 client = GNUNET_new (struct GNUNET_SERVICE_Client);
756 GNUNET_CONTAINER_DLL_insert (sh->clients_head, sh->clients_tail, client);
757 client->sh = sh;
758 client->sock = csock;
760 NULL,
762 client,
763 sh->handlers,
765 client);
766 client->mst = GNUNET_MST_create (&service_client_mst_cb, client);
767 if (NULL != sh->connect_cb)
768 client->user_context = sh->connect_cb (sh->cb_cls, client, client->mq);
770 client->recv_task =
772 client->sock,
774 client);
775}
776
777
784static void
785accept_client (void *cls)
786{
787 struct ServiceListenContext *slc = cls;
788 struct GNUNET_SERVICE_Handle *sh = slc->sh;
789
790 slc->listen_task = NULL;
791 while (1)
792 {
793 struct GNUNET_NETWORK_Handle *sock;
794 const struct sockaddr_in *v4;
795 const struct sockaddr_in6 *v6;
796 struct sockaddr_storage sa;
797 socklen_t addrlen;
798 int ok;
799
800 addrlen = sizeof(sa);
802 (struct sockaddr *) &sa,
803 &addrlen);
804 if (NULL == sock)
805 {
806 if (EMFILE == errno)
808 else if (EAGAIN != errno)
810 break;
811 }
812 switch (sa.ss_family)
813 {
814 case AF_INET:
815 GNUNET_assert (addrlen == sizeof(struct sockaddr_in));
816 v4 = (const struct sockaddr_in *) &sa;
817 ok = (((NULL == sh->v4_allowed) ||
818 (check_ipv4_listed (sh->v4_allowed, &v4->sin_addr))) &&
819 ((NULL == sh->v4_denied) ||
820 (! check_ipv4_listed (sh->v4_denied, &v4->sin_addr))));
821 break;
822
823 case AF_INET6:
824 GNUNET_assert (addrlen == sizeof(struct sockaddr_in6));
825 v6 = (const struct sockaddr_in6 *) &sa;
826 ok = (((NULL == sh->v6_allowed) ||
827 (check_ipv6_listed (sh->v6_allowed, &v6->sin6_addr))) &&
828 ((NULL == sh->v6_denied) ||
829 (! check_ipv6_listed (sh->v6_denied, &v6->sin6_addr))));
830 break;
831
832 case AF_UNIX:
833 ok = GNUNET_OK; /* controlled using file-system ACL now */
834 break;
835
836 default:
838 _ ("Unknown address family %d\n"),
839 sa.ss_family);
840 return;
841 }
842 if (! ok)
843 {
845 "Service rejected incoming connection from %s due to policy.\n",
846 GNUNET_a2s ((const struct sockaddr *) &sa, addrlen));
848 continue;
849 }
851 "Service accepted incoming connection from %s.\n",
852 GNUNET_a2s ((const struct sockaddr *) &sa, addrlen));
853 start_client (slc->sh, sock);
854 }
855 if (0 != sh->suspend_state)
856 return;
857 slc->listen_task =
859 slc->listen_socket,
861 slc);
862}
863
864
872static void
874{
875 struct ServiceListenContext *slc;
876
877 GNUNET_assert ((SUSPEND_STATE_NONE == sr) || (0 != (sh->suspend_state & sr)));
878 sh->suspend_state -= sr;
879 if (SUSPEND_STATE_NONE != sh->suspend_state)
880 return;
881 for (slc = sh->slc_head; NULL != slc; slc = slc->next)
882 {
883 GNUNET_assert (NULL == slc->listen_task);
884 slc->listen_task =
886 slc->listen_socket,
888 slc);
889 }
890}
891
892
900static void
901service_main (void *cls)
902{
903 struct GNUNET_SERVICE_Handle *sh = cls;
904
909
910 if (-1 != sh->ready_confirm_fd)
911 {
912 GNUNET_break (1 == write (sh->ready_confirm_fd, ".", 1));
913 GNUNET_break (0 == close (sh->ready_confirm_fd));
914 sh->ready_confirm_fd = -1;
915 }
916
917 if (NULL != sh->service_init_cb)
918 sh->service_init_cb (sh->cb_cls, sh->cfg, sh);
919}
920
921
931static int
934 const char *option)
935{
936 char *opt;
937
938 if (! GNUNET_CONFIGURATION_have_value (sh->cfg, sh->service_name, option))
939 {
940 *ret = NULL;
941 return GNUNET_OK;
942 }
945 sh->service_name,
946 option,
947 &opt));
948 if (NULL == (*ret = GNUNET_STRINGS_parse_ipv4_policy (opt)))
949 {
951 _ ("Could not parse IPv4 network specification `%s' for `%s:%s'\n"),
952 opt,
953 sh->service_name,
954 option);
955 GNUNET_free (opt);
956 return GNUNET_SYSERR;
957 }
958 GNUNET_free (opt);
959 return GNUNET_OK;
960}
961
962
972static int
975 const char *option)
976{
977 char *opt;
978
979 if (! GNUNET_CONFIGURATION_have_value (sh->cfg, sh->service_name, option))
980 {
981 *ret = NULL;
982 return GNUNET_OK;
983 }
986 sh->service_name,
987 option,
988 &opt));
989 if (NULL == (*ret = GNUNET_STRINGS_parse_ipv6_policy (opt)))
990 {
992 _ ("Could not parse IPv6 network specification `%s' for `%s:%s'\n"),
993 opt,
994 sh->service_name,
995 option);
996 GNUNET_free (opt);
997 return GNUNET_SYSERR;
998 }
999 GNUNET_free (opt);
1000 return GNUNET_OK;
1001}
1002
1003
1012static void
1013add_unixpath (struct sockaddr **saddrs,
1014 socklen_t *saddrlens,
1015 const char *unixpath)
1016{
1017#ifdef AF_UNIX
1018 struct sockaddr_un *un;
1019
1020 un = GNUNET_new (struct sockaddr_un);
1021 un->sun_family = AF_UNIX;
1022 GNUNET_strlcpy (un->sun_path, unixpath, sizeof(un->sun_path));
1023#if HAVE_SOCKADDR_UN_SUN_LEN
1024 un->sun_len = (u_char) sizeof(struct sockaddr_un);
1025#endif
1026 *saddrs = (struct sockaddr *) un;
1027 *saddrlens = sizeof(struct sockaddr_un);
1028#else
1029 /* this function should never be called
1030 * unless AF_UNIX is defined! */
1031 GNUNET_assert (0);
1032#endif
1033}
1034
1035
1056static int
1058 const struct GNUNET_CONFIGURATION_Handle *cfg,
1059 struct sockaddr ***addrs,
1060 socklen_t **addr_lens)
1061{
1062 int disablev6;
1063 struct GNUNET_NETWORK_Handle *desc;
1064 unsigned long long port;
1065 char *unixpath;
1066 struct addrinfo hints;
1067 struct addrinfo *res;
1068 struct addrinfo *pos;
1069 struct addrinfo *next;
1070 unsigned int i;
1071 int resi;
1072 int ret;
1073 struct sockaddr **saddrs;
1074 socklen_t *saddrlens;
1075 char *hostname;
1076
1077 *addrs = NULL;
1078 *addr_lens = NULL;
1079 desc = NULL;
1080 disablev6 = GNUNET_NO;
1081 if ((GNUNET_NO == GNUNET_NETWORK_test_pf (PF_INET6)) ||
1082 (GNUNET_YES ==
1084 disablev6 = GNUNET_YES;
1085
1086 port = 0;
1088 {
1091 "PORT",
1092 &port))
1093 {
1095 _ ("Require valid port number for service `%s' in configuration!\n"),
1096 service_name);
1097 }
1098 if (port > 65535)
1099 {
1101 _ ("Require valid port number for service `%s' in configuration!\n"),
1102 service_name);
1103 return GNUNET_SYSERR;
1104 }
1105 }
1106
1108 {
1112 "BINDTO",
1113 &hostname));
1114 }
1115 else
1116 hostname = NULL;
1117
1118 unixpath = NULL;
1119#ifdef AF_UNIX
1120 if ((GNUNET_YES ==
1124 "UNIXPATH",
1125 &unixpath)) &&
1126 (0 < strlen (unixpath)))
1127 {
1128 /* probe UNIX support */
1129 struct sockaddr_un s_un;
1130
1131 if (strlen (unixpath) >= sizeof(s_un.sun_path))
1132 {
1134 _ ("UNIXPATH `%s' too long, maximum length is %llu\n"),
1135 unixpath,
1136 (unsigned long long) sizeof(s_un.sun_path));
1137 unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath);
1138 LOG (GNUNET_ERROR_TYPE_INFO, _ ("Using `%s' instead\n"), unixpath);
1139 }
1142 }
1143 if (NULL != unixpath)
1144 {
1145 desc = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_STREAM, 0);
1146 if (NULL == desc)
1147 {
1148 if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) ||
1149 (EACCES == errno))
1150 {
1152 GNUNET_free (hostname);
1153 GNUNET_free (unixpath);
1154 return GNUNET_SYSERR;
1155 }
1157 _ (
1158 "Disabling UNIX domain socket support for service `%s', failed to create UNIX domain socket: %s\n"),
1160 strerror (errno));
1161 GNUNET_free (unixpath);
1162 unixpath = NULL;
1163 }
1164 else
1165 {
1167 desc = NULL;
1168 }
1169 }
1170#endif
1171
1172 if ((0 == port) && (NULL == unixpath))
1173 {
1175 _ (
1176 "Have neither PORT nor UNIXPATH for service `%s', but one is required\n"),
1177 service_name);
1178 GNUNET_free (hostname);
1179 return GNUNET_SYSERR;
1180 }
1181 if (0 == port)
1182 {
1183 saddrs = GNUNET_new_array (2, struct sockaddr *);
1184 saddrlens = GNUNET_new_array (2, socklen_t);
1185 add_unixpath (saddrs, saddrlens, unixpath);
1186 GNUNET_free (unixpath);
1187 GNUNET_free (hostname);
1188 *addrs = saddrs;
1189 *addr_lens = saddrlens;
1190 return 1;
1191 }
1192
1193 if (NULL != hostname)
1194 {
1196 "Resolving `%s' since that is where `%s' will bind to.\n",
1197 hostname,
1198 service_name);
1199 memset (&hints, 0, sizeof(struct addrinfo));
1200 if (disablev6)
1201 hints.ai_family = AF_INET;
1202 hints.ai_protocol = IPPROTO_TCP;
1203 if ((0 != (ret = getaddrinfo (hostname, NULL, &hints, &res))) ||
1204 (NULL == res))
1205 {
1207 _ ("Failed to resolve `%s': %s\n"),
1208 hostname,
1209 gai_strerror (ret));
1210 GNUNET_free (hostname);
1211 GNUNET_free (unixpath);
1212 return GNUNET_SYSERR;
1213 }
1214 next = res;
1215 i = 0;
1216 while (NULL != (pos = next))
1217 {
1218 next = pos->ai_next;
1219 if ((disablev6) && (pos->ai_family == AF_INET6))
1220 continue;
1221 i++;
1222 }
1223 if (0 == i)
1224 {
1226 _ ("Failed to find %saddress for `%s'.\n"),
1227 disablev6 ? "IPv4 " : "",
1228 hostname);
1229 freeaddrinfo (res);
1230 GNUNET_free (hostname);
1231 GNUNET_free (unixpath);
1232 return GNUNET_SYSERR;
1233 }
1234 resi = i;
1235 if (NULL != unixpath)
1236 resi++;
1237 saddrs = GNUNET_new_array (resi + 1, struct sockaddr *);
1238 saddrlens = GNUNET_new_array (resi + 1, socklen_t);
1239 i = 0;
1240 if (NULL != unixpath)
1241 {
1242 add_unixpath (saddrs, saddrlens, unixpath);
1243 i++;
1244 }
1245 next = res;
1246 while (NULL != (pos = next))
1247 {
1248 next = pos->ai_next;
1249 if ((disablev6) && (AF_INET6 == pos->ai_family))
1250 continue;
1251 if ((IPPROTO_TCP != pos->ai_protocol) && (0 != pos->ai_protocol))
1252 continue; /* not TCP */
1253 if ((SOCK_STREAM != pos->ai_socktype) && (0 != pos->ai_socktype))
1254 continue; /* huh? */
1256 "Service `%s' will bind to `%s'\n",
1258 GNUNET_a2s (pos->ai_addr, pos->ai_addrlen));
1259 if (AF_INET == pos->ai_family)
1260 {
1261 GNUNET_assert (sizeof(struct sockaddr_in) == pos->ai_addrlen);
1262 saddrlens[i] = pos->ai_addrlen;
1263 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1264 GNUNET_memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
1265 ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
1266 }
1267 else
1268 {
1269 GNUNET_assert (AF_INET6 == pos->ai_family);
1270 GNUNET_assert (sizeof(struct sockaddr_in6) == pos->ai_addrlen);
1271 saddrlens[i] = pos->ai_addrlen;
1272 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1273 GNUNET_memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
1274 ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
1275 }
1276 i++;
1277 }
1278 GNUNET_free (hostname);
1279 freeaddrinfo (res);
1280 resi = i;
1281 }
1282 else
1283 {
1284 /* will bind against everything, just set port */
1285 if (disablev6)
1286 {
1287 /* V4-only */
1288 resi = 1;
1289 if (NULL != unixpath)
1290 resi++;
1291 i = 0;
1292 saddrs = GNUNET_new_array (resi + 1, struct sockaddr *);
1293 saddrlens = GNUNET_new_array (resi + 1, socklen_t);
1294 if (NULL != unixpath)
1295 {
1296 add_unixpath (saddrs, saddrlens, unixpath);
1297 i++;
1298 }
1299 saddrlens[i] = sizeof(struct sockaddr_in);
1300 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1301#if HAVE_SOCKADDR_IN_SIN_LEN
1302 ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[i];
1303#endif
1304 ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
1305 ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
1306 }
1307 else
1308 {
1309 /* dual stack */
1310 resi = 2;
1311 if (NULL != unixpath)
1312 resi++;
1313 saddrs = GNUNET_new_array (resi + 1, struct sockaddr *);
1314 saddrlens = GNUNET_new_array (resi + 1, socklen_t);
1315 i = 0;
1316 if (NULL != unixpath)
1317 {
1318 add_unixpath (saddrs, saddrlens, unixpath);
1319 i++;
1320 }
1321 saddrlens[i] = sizeof(struct sockaddr_in6);
1322 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1323#if HAVE_SOCKADDR_IN_SIN_LEN
1324 ((struct sockaddr_in6 *) saddrs[i])->sin6_len = saddrlens[0];
1325#endif
1326 ((struct sockaddr_in6 *) saddrs[i])->sin6_family = AF_INET6;
1327 ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
1328 i++;
1329 saddrlens[i] = sizeof(struct sockaddr_in);
1330 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1331#if HAVE_SOCKADDR_IN_SIN_LEN
1332 ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[1];
1333#endif
1334 ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
1335 ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
1336 }
1337 }
1338 GNUNET_free (unixpath);
1339 *addrs = saddrs;
1340 *addr_lens = saddrlens;
1341 return resi;
1342}
1343
1344
1352static struct GNUNET_NETWORK_Handle *
1353open_listen_socket (const struct sockaddr *server_addr,
1354 socklen_t socklen)
1355{
1356 struct GNUNET_NETWORK_Handle *sock;
1357 uint16_t port;
1358 int eno;
1359
1360 switch (server_addr->sa_family)
1361 {
1362 case AF_INET:
1363 port = ntohs (((const struct sockaddr_in *) server_addr)->sin_port);
1364 break;
1365 case AF_INET6:
1366 port = ntohs (((const struct sockaddr_in6 *) server_addr)->sin6_port);
1367 break;
1368 case AF_UNIX:
1369 port = 0;
1370 break;
1371 default:
1372 GNUNET_break (0);
1373 port = 0;
1374 break;
1375 }
1376 sock = GNUNET_NETWORK_socket_create (server_addr->sa_family,
1377 SOCK_STREAM,
1378 0);
1379 if (NULL == sock)
1380 {
1382 "socket");
1383 errno = 0;
1384 return NULL;
1385 }
1386 /* bind the socket */
1387 if (GNUNET_OK !=
1389 server_addr,
1390 socklen))
1391 {
1392 eno = errno;
1393 if (EADDRINUSE != errno)
1394 {
1395 /* we don't log 'EADDRINUSE' here since an IPv4 bind may
1396 * fail if we already took the port on IPv6; if both IPv4 and
1397 * IPv6 binds fail, then our caller will log using the
1398 * errno preserved in 'eno' */
1399 if (0 != port)
1401 _ ("`%s' failed for port %d (%s).\n"),
1402 "bind",
1403 port,
1404 (AF_INET == server_addr->sa_family) ? "IPv4" : "IPv6");
1405 else
1407 eno = 0;
1408 }
1409 else
1410 {
1411 if (0 != port)
1413 _ ("`%s' failed for port %d (%s): address already in use\n"),
1414 "bind",
1415 port,
1416 (AF_INET == server_addr->sa_family) ? "IPv4" : "IPv6");
1417 else if (AF_UNIX == server_addr->sa_family)
1418 {
1420 _ ("`%s' failed for `%s': address already in use\n"),
1421 "bind",
1422 GNUNET_a2s (server_addr, socklen));
1423 }
1424 }
1426 errno = eno;
1427 return NULL;
1428 }
1429 if (GNUNET_OK != GNUNET_NETWORK_socket_listen (sock, 5))
1430 {
1433 errno = 0;
1434 return NULL;
1435 }
1436 if (0 != port)
1438 "Server starts to listen on port %u.\n",
1439 port);
1440 return sock;
1441}
1442
1443
1460static int
1462{
1463 int tolerant;
1464 struct GNUNET_NETWORK_Handle **csocks = NULL;
1465 struct GNUNET_NETWORK_Handle **lsocks;
1466 const char *nfds;
1467 unsigned int cnt;
1468 int flags;
1469 char dummy[2];
1470
1472 sh->service_name,
1473 "TOLERANT"))
1474 {
1475 if (GNUNET_SYSERR ==
1477 sh->service_name,
1478 "TOLERANT")))
1479 {
1481 _ ("Specified value for `%s' of service `%s' is invalid\n"),
1482 "TOLERANT",
1483 sh->service_name);
1484 return GNUNET_SYSERR;
1485 }
1486 }
1487 else
1488 tolerant = GNUNET_NO;
1489
1490 lsocks = NULL;
1491 errno = 0;
1492 if ((NULL != (nfds = getenv ("LISTEN_FDS"))) &&
1493 (1 == sscanf (nfds, "%u%1s", &cnt, dummy)) && (cnt > 0) &&
1494 (cnt < FD_SETSIZE) && (cnt + 4 < FD_SETSIZE))
1495 {
1496 lsocks = GNUNET_new_array (cnt + 1, struct GNUNET_NETWORK_Handle *);
1497 while (0 < cnt--)
1498 {
1499 flags = fcntl (3 + cnt, F_GETFD);
1500 if ((flags < 0) || (0 != (flags & FD_CLOEXEC)) ||
1501 (NULL == (lsocks[cnt] = GNUNET_NETWORK_socket_box_native (3 + cnt))))
1502 {
1504 _ (
1505 "Could not access pre-bound socket %u, will try to bind myself\n"),
1506 (unsigned int) 3 + cnt);
1507 cnt++;
1508 while (NULL != lsocks[cnt])
1510 GNUNET_NETWORK_socket_close (lsocks[cnt++]));
1511 GNUNET_free (lsocks);
1512 lsocks = NULL;
1513 break;
1514 }
1515 }
1516 unsetenv ("LISTEN_FDS");
1517 }
1518 if ( (0 != (GNUNET_SERVICE_OPTION_CLOSE_LSOCKS & sh->options)) &&
1519 (NULL != lsocks) )
1520 {
1521 csocks = lsocks;
1522 lsocks = NULL;
1523 }
1524
1525 if (NULL != lsocks)
1526 {
1527 /* listen only on inherited sockets if we have any */
1528 for (struct GNUNET_NETWORK_Handle **ls = lsocks; NULL != *ls; ls++)
1529 {
1530 struct ServiceListenContext *slc;
1531
1532 slc = GNUNET_new (struct ServiceListenContext);
1533 slc->sh = sh;
1534 slc->listen_socket = *ls;
1535 GNUNET_CONTAINER_DLL_insert (sh->slc_head, sh->slc_tail, slc);
1536 }
1537 GNUNET_free (lsocks);
1538 }
1539 else
1540 {
1541 struct sockaddr **addrs;
1542 socklen_t *addrlens;
1543 int num;
1544
1545 num = get_server_addresses (sh->service_name, sh->cfg, &addrs, &addrlens);
1546 if (GNUNET_SYSERR == num)
1547 return GNUNET_SYSERR;
1548
1549 for (int i = 0; i < num; i++)
1550 {
1551 struct ServiceListenContext *slc;
1552
1553 slc = GNUNET_new (struct ServiceListenContext);
1554 slc->sh = sh;
1555 slc->listen_socket = open_listen_socket (addrs[i], addrlens[i]);
1556 GNUNET_free (addrs[i]);
1557 if (NULL == slc->listen_socket)
1558 {
1560 GNUNET_free (slc);
1561 continue;
1562 }
1563 GNUNET_CONTAINER_DLL_insert (sh->slc_head, sh->slc_tail, slc);
1564 }
1565 GNUNET_free (addrlens);
1566 GNUNET_free (addrs);
1567 if ((0 != num) && (NULL == sh->slc_head))
1568 {
1569 /* All attempts to bind failed, hard failure */
1570 GNUNET_log (
1572 _ (
1573 "Could not bind to any of the ports I was supposed to, refusing to run!\n"));
1574 GNUNET_free (csocks);
1575 return GNUNET_SYSERR;
1576 }
1577 }
1578 if (NULL != csocks)
1579 {
1580 /* close inherited sockets to signal parent that we are ready */
1581 for (struct GNUNET_NETWORK_Handle **ls = csocks; NULL != *ls; ls++)
1583 GNUNET_free (csocks);
1584 }
1585 sh->require_found = tolerant ? GNUNET_NO : GNUNET_YES;
1587 sh->service_name,
1588 "UNIX_MATCH_UID");
1590 sh->service_name,
1591 "UNIX_MATCH_GID");
1592 process_acl4 (&sh->v4_denied, sh, "REJECT_FROM");
1593 process_acl4 (&sh->v4_allowed, sh, "ACCEPT_FROM");
1594 process_acl6 (&sh->v6_denied, sh, "REJECT_FROM6");
1595 process_acl6 (&sh->v6_allowed, sh, "ACCEPT_FROM6");
1596 return GNUNET_OK;
1597}
1598
1599
1607static char *
1609{
1610 char *un;
1611
1613 sh->service_name,
1614 "USERNAME",
1615 &un))
1616 return NULL;
1617 return un;
1618}
1619
1620
1627static int
1629{
1630 char *user;
1631
1632 if (NULL == (user = get_user_name (sh)))
1633 return GNUNET_OK; /* keep */
1634
1635 struct passwd *pws;
1636
1637 errno = 0;
1638 pws = getpwnam (user);
1639 if (NULL == pws)
1640 {
1642 _ ("Cannot obtain information about user `%s': %s\n"),
1643 user,
1644 errno == 0 ? _ ("No such user") : strerror (errno));
1645 GNUNET_free (user);
1646 return GNUNET_SYSERR;
1647 }
1648 if ((0 != setgid (pws->pw_gid)) || (0 != setegid (pws->pw_gid)) ||
1649#if HAVE_INITGROUPS
1650 (0 != initgroups (user, pws->pw_gid)) ||
1651#endif
1652 (0 != setuid (pws->pw_uid)) || (0 != seteuid (pws->pw_uid)))
1653 {
1654 if ((0 != setregid (pws->pw_gid, pws->pw_gid)) ||
1655 (0 != setreuid (pws->pw_uid, pws->pw_uid)))
1656 {
1658 _ ("Cannot change user/group to `%s': %s\n"),
1659 user,
1660 strerror (errno));
1661 GNUNET_free (user);
1662 return GNUNET_SYSERR;
1663 }
1664 }
1665
1666 GNUNET_free (user);
1667 return GNUNET_OK;
1668}
1669
1670
1678static char *
1680{
1681 char *pif;
1682
1684 sh->service_name,
1685 "PIDFILE",
1686 &pif))
1687 return NULL;
1688 return pif;
1689}
1690
1691
1697static void
1699{
1700 char *pif = get_pid_file_name (sh);
1701
1702 if (NULL == pif)
1703 return; /* no PID file */
1704 if (0 != unlink (pif))
1706 GNUNET_free (pif);
1707}
1708
1709
1716static int
1718{
1719 pid_t pid;
1720 int nullfd;
1721 int filedes[2];
1722
1723 if (0 != pipe (filedes))
1724 {
1726 return GNUNET_SYSERR;
1727 }
1728 pid = fork ();
1729 if (pid < 0)
1730 {
1732 return GNUNET_SYSERR;
1733 }
1734 if (0 != pid)
1735 {
1736 /* Parent */
1737 char c;
1738
1739 GNUNET_break (0 == close (filedes[1]));
1740 c = 'X';
1741 if (1 != read (filedes[0], &c, sizeof(char)))
1743 fflush (stdout);
1744 switch (c)
1745 {
1746 case '.':
1747 exit (0);
1748
1749 case 'I':
1751 _ ("Service process failed to initialize\n"));
1752 break;
1753
1754 case 'S':
1756 _ ("Service process could not initialize server function\n"));
1757 break;
1758
1759 case 'X':
1761 _ ("Service process failed to report status\n"));
1762 break;
1763 }
1764 exit (1); /* child reported error */
1765 }
1766 GNUNET_break (0 == close (0));
1767 GNUNET_break (0 == close (1));
1768 GNUNET_break (0 == close (filedes[0]));
1769 nullfd = open ("/dev/null", O_RDWR | O_APPEND);
1770 if (nullfd < 0)
1771 return GNUNET_SYSERR;
1772 /* set stdin/stdout to /dev/null */
1773 if ((dup2 (nullfd, 0) < 0) || (dup2 (nullfd, 1) < 0))
1774 {
1776 (void) close (nullfd);
1777 return GNUNET_SYSERR;
1778 }
1779 (void) close (nullfd);
1780 /* Detach from controlling terminal */
1781 pid = setsid ();
1782 if (-1 == pid)
1784 sh->ready_confirm_fd = filedes[1];
1785
1786 return GNUNET_OK;
1787}
1788
1789
1796static void
1798{
1799 struct ServiceListenContext *slc;
1800
1801 GNUNET_free (sh->v4_denied);
1802 GNUNET_free (sh->v6_denied);
1803 GNUNET_free (sh->v4_allowed);
1804 GNUNET_free (sh->v6_allowed);
1805 while (NULL != (slc = sh->slc_head))
1806 {
1807 GNUNET_CONTAINER_DLL_remove (sh->slc_head, sh->slc_tail, slc);
1808 if (NULL != slc->listen_task)
1812 GNUNET_free (slc);
1813 }
1814}
1815
1816
1823static void
1824return_agpl (void *cls, const struct GNUNET_MessageHeader *msg)
1825{
1826 struct GNUNET_SERVICE_Client *client = cls;
1827 struct GNUNET_MQ_Handle *mq;
1828 struct GNUNET_MQ_Envelope *env;
1829 struct GNUNET_MessageHeader *res;
1830 size_t slen;
1832
1833 (void) msg;
1834 slen = strlen (pd->agpl_url) + 1;
1836 memcpy (&res[1], GNUNET_AGPL_URL, slen);
1840}
1841
1842
1879struct GNUNET_SERVICE_Handle *
1881 const struct GNUNET_CONFIGURATION_Handle *cfg,
1884 void *cls,
1885 const struct GNUNET_MQ_MessageHandler *handlers)
1886{
1887 struct GNUNET_SERVICE_Handle *sh;
1888
1890 sh->service_name = service_name;
1891 sh->cfg = cfg;
1892 sh->connect_cb = connect_cb;
1893 sh->disconnect_cb = disconnect_cb;
1894 sh->cb_cls = cls;
1895 sh->handlers = GNUNET_MQ_copy_handlers2 (handlers, &return_agpl, NULL);
1896 if (GNUNET_OK != setup_service (sh))
1897 {
1898 GNUNET_free (sh->handlers);
1899 GNUNET_free (sh);
1900 return NULL;
1901 }
1903 return sh;
1904}
1905
1906
1912void
1914{
1915 struct GNUNET_SERVICE_Client *client;
1916
1918 while (NULL != (client = srv->clients_head))
1920 teardown_service (srv);
1921 GNUNET_free (srv->handlers);
1922 GNUNET_free (srv);
1923}
1924
1925
1926int
1928 char *const *argv,
1929 const char *service_name,
1931 GNUNET_SERVICE_InitCallback service_init_cb,
1934 void *cls,
1935 const struct GNUNET_MQ_MessageHandler *handlers)
1936{
1938
1939#if ENABLE_NLS
1940 char *path;
1941#endif
1942 char *cfg_filename;
1943 char *opt_cfg_filename;
1944 char *loglev;
1945 const char *xdg;
1946 char *logfile;
1947 int do_daemonize;
1948 unsigned long long skew_offset;
1949 unsigned long long skew_variance;
1950 long long clock_offset;
1952 int ret;
1953 int err;
1955 struct GNUNET_GETOPT_CommandLineOption service_options[] = {
1956 GNUNET_GETOPT_option_cfgfile (&opt_cfg_filename),
1958 "daemonize",
1959 gettext_noop (
1960 "do daemonize (detach from terminal)"),
1961 &do_daemonize),
1967 };
1968
1969 err = 1;
1970 memset (&sh, 0, sizeof(sh));
1971 xdg = getenv ("XDG_CONFIG_HOME");
1972 if (NULL != xdg)
1974 "%s%s%s",
1975 xdg,
1977 pd->config_file);
1978 else
1980 sh.ready_confirm_fd = -1;
1981 sh.options = options;
1983 sh.service_init_cb = service_init_cb;
1984 sh.connect_cb = connect_cb;
1985 sh.disconnect_cb = disconnect_cb;
1986 sh.cb_cls = cls;
1987 sh.handlers = (NULL == pd->agpl_url)
1990 sh.service_name = service_name;
1991 sh.ret = 0;
1992 /* setup subsystems */
1993 loglev = NULL;
1994 logfile = NULL;
1995 opt_cfg_filename = NULL;
1996 do_daemonize = 0;
1997#if ENABLE_NLS
1998 if (NULL != pd->gettext_domain)
1999 {
2000 setlocale (LC_ALL, "");
2001 path = (NULL == pd->gettext_path) ?
2004 if (NULL != path)
2005 {
2006 bindtextdomain (pd->gettext_domain, path);
2007 GNUNET_free (path);
2008 }
2010 }
2011#endif
2013 service_options,
2014 argc,
2015 argv);
2016 if (GNUNET_SYSERR == ret)
2017 goto shutdown;
2018 if (GNUNET_NO == ret)
2019 {
2020 err = 0;
2021 goto shutdown;
2022 }
2024 loglev,
2025 logfile))
2026 {
2027 GNUNET_break (0);
2028 goto shutdown;
2029 }
2030 if (NULL != opt_cfg_filename)
2031 {
2032 if ((GNUNET_YES != GNUNET_DISK_file_test (opt_cfg_filename)) ||
2033 (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, opt_cfg_filename)))
2034 {
2036 _ ("Malformed configuration file `%s', exit ...\n"),
2037 opt_cfg_filename);
2038 goto shutdown;
2039 }
2040 }
2041 else
2042 {
2044 {
2046 {
2048 _ ("Malformed configuration file `%s', exit ...\n"),
2049 cfg_filename);
2050 goto shutdown;
2051 }
2052 }
2053 else
2054 {
2056 {
2058 _ ("Malformed configuration, exit ...\n"));
2059 goto shutdown;
2060 }
2061 }
2062 }
2063 if (GNUNET_OK != setup_service (&sh))
2064 goto shutdown;
2065 if ((1 == do_daemonize) && (GNUNET_OK != detach_terminal (&sh)))
2066 {
2067 GNUNET_break (0);
2068 goto shutdown;
2069 }
2070 if (GNUNET_OK != set_user_id (&sh))
2071 goto shutdown;
2073 "Service `%s' runs with configuration from `%s'\n",
2075 (NULL != opt_cfg_filename) ? opt_cfg_filename : cfg_filename);
2077 "TESTING",
2078 "SKEW_OFFSET",
2079 &skew_offset)) &&
2081 "TESTING",
2082 "SKEW_VARIANCE",
2083 &skew_variance)))
2084 {
2085 clock_offset = skew_offset - skew_variance;
2086 GNUNET_TIME_set_offset (clock_offset);
2088 "Skewing clock by %lld ms\n",
2089 (long long) clock_offset);
2090 }
2092
2093 /* actually run service */
2094 err = 0;
2096 /* shutdown */
2097 if (1 == do_daemonize)
2099
2100shutdown:
2101 if (-1 != sh.ready_confirm_fd)
2102 {
2103 if (1 != write (sh.ready_confirm_fd, err ? "I" : "S", 1))
2105 GNUNET_break (0 == close (sh.ready_confirm_fd));
2106 }
2107#if HAVE_MALLINFO2
2108 {
2109 char *counter;
2110
2113 "GAUGER_HEAP")) &&
2116 "GAUGER_HEAP",
2117 &counter)))
2118 {
2119 struct mallinfo2 mi;
2120
2121 mi = mallinfo2 ();
2122 GAUGER (service_name, counter, mi.usmblks, "blocks");
2123 GNUNET_free (counter);
2124 }
2125 }
2126#endif
2128 GNUNET_free (sh.handlers);
2131 GNUNET_free (logfile);
2132 GNUNET_free (loglev);
2134 GNUNET_free (opt_cfg_filename);
2135
2136 return err ? GNUNET_SYSERR : sh.ret;
2137}
2138
2139
2140/* A list of service to be launched when GNUNET_SERVICE_main()
2141 * is called
2142 */
2144{
2145 /* DLL */
2147
2148 /* DLL */
2150
2151 /* Handle to the service to launch */
2153};
2154
2155/* The service list */
2156static struct ServiceHandleList *hll_head = NULL;
2157
2158/* The service list */
2159static struct ServiceHandleList *hll_tail = NULL;
2160
2161int
2164 GNUNET_SERVICE_InitCallback service_init_cb,
2167 void *cls,
2168 const struct GNUNET_MQ_MessageHandler *handlers)
2169{
2170 struct ServiceHandleList *hle;
2173
2174 sh->ready_confirm_fd = -1;
2175 sh->options = options;
2176 sh->service_init_cb = service_init_cb;
2177 sh->connect_cb = connect_cb;
2178 sh->disconnect_cb = disconnect_cb;
2179 sh->cb_cls = cls;
2180 sh->handlers = (NULL == pd->agpl_url)
2183 sh->service_name = service_name;
2184 sh->ret = 0;
2185 hle = GNUNET_new (struct ServiceHandleList);
2186 hle->sh = sh;
2188 return GNUNET_OK;
2189}
2190
2191
2192static void
2194{
2195 struct GNUNET_SERVICE_Handle *sh;
2196 struct ServiceHandleList *shl;
2197
2198 for (shl = hll_head; NULL != shl;)
2199 {
2200 sh = shl->sh;
2202 GNUNET_free (shl);
2203 if (-1 != sh->ready_confirm_fd)
2204 {
2205 if (1 != write (sh->ready_confirm_fd, "S", 1))
2207 GNUNET_break (0 == close (sh->ready_confirm_fd));
2208 }
2210 GNUNET_free (sh->handlers);
2211 GNUNET_free (sh);
2212 }
2213}
2214
2215
2216static void
2218{
2219 struct ServiceHandleList *shl;
2220 struct GNUNET_CONFIGURATION_Handle *cfg = cls;
2221
2222 for (shl = hll_head; NULL != shl; shl = shl->next)
2223 {
2224 shl->sh->cfg = cfg;
2225 if (GNUNET_OK != setup_service (shl->sh))
2226 continue;
2227 if (GNUNET_OK != set_user_id (shl->sh))
2228 continue;
2229
2231 }
2233}
2234
2235
2236void
2238 char *const *argv)
2239{
2240 char *cfg_filename;
2241 char *opt_cfg_filename;
2242 char *logfile;
2243 char *loglev;
2244 const char *xdg;
2245 int do_daemonize;
2246 int ret;
2249
2250 struct GNUNET_GETOPT_CommandLineOption service_options[] = {
2251 GNUNET_GETOPT_option_cfgfile (&opt_cfg_filename),
2253 "daemonize",
2254 gettext_noop (
2255 "do daemonize (detach from terminal)"),
2256 &do_daemonize),
2262 };
2263 xdg = getenv ("XDG_CONFIG_HOME");
2264 if (NULL != xdg)
2266 "%s%s%s",
2267 xdg,
2269 pd->config_file);
2270 else
2273 // FIXME we need to set this up for each service!
2274 ret = GNUNET_GETOPT_run ("libgnunet",
2275 service_options,
2276 argc,
2277 argv);
2278 if (GNUNET_SYSERR == ret)
2279 goto shutdown;
2280 if (GNUNET_NO == ret)
2281 {
2282 goto shutdown;
2283 }
2284 // FIXME we need to set this up for each service!
2285 if (GNUNET_OK != GNUNET_log_setup ("libgnunet",
2286 loglev,
2287 logfile))
2288 {
2289 GNUNET_break (0);
2290 goto shutdown;
2291 }
2292 if (NULL != opt_cfg_filename)
2293 {
2294 if ((GNUNET_YES != GNUNET_DISK_file_test (opt_cfg_filename)) ||
2295 (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, opt_cfg_filename)))
2296 {
2298 _ ("Malformed configuration file `%s', exit ...\n"),
2299 opt_cfg_filename);
2300 goto shutdown;
2301 }
2302 }
2303 else
2304 {
2306 {
2308 {
2310 _ ("Malformed configuration file `%s', exit ...\n"),
2311 cfg_filename);
2313 return;
2314 }
2315 }
2316 else
2317 {
2319 {
2321 _ ("Malformed configuration, exit ...\n"));
2323 return;
2324 }
2325 }
2326 }
2328
2330shutdown:
2333 GNUNET_free (logfile);
2334 GNUNET_free (loglev);
2336 GNUNET_free (opt_cfg_filename);
2337}
2338
2339
2346void
2348{
2350}
2351
2352
2358void
2360{
2362}
2363
2364
2371static void
2373{
2374 struct GNUNET_SERVICE_Client *c = cls;
2375 int ret;
2376
2377 c->recv_task = NULL;
2378 /* first, check if there is still something in the buffer */
2380 if (GNUNET_SYSERR == ret)
2381 {
2382 if (NULL == c->drop_task)
2384 return;
2385 }
2386 if (GNUNET_NO == ret)
2387 return; /* done processing, wait for more later */
2389 if (GNUNET_YES == c->needs_continue)
2390 return; /* #GNUNET_MST_next() did give a message to the client */
2391 /* need to receive more data from the network first */
2392 if (NULL != c->recv_task)
2393 return;
2395 c->sock,
2397 c);
2398}
2399
2400
2407void
2409{
2410 GNUNET_assert (NULL == c->drop_task);
2412 GNUNET_assert (NULL == c->recv_task);
2414 if (NULL != c->warn_task)
2415 {
2417 c->warn_task = NULL;
2418 }
2420}
2421
2422
2431void
2433{
2434 GNUNET_break (NULL != c->warn_task);
2435 if (NULL != c->warn_task)
2436 {
2438 c->warn_task = NULL;
2439 }
2440}
2441
2442
2448static void
2450{
2451 struct GNUNET_SERVICE_Client *c = cls;
2452 struct GNUNET_SERVICE_Handle *sh = c->sh;
2453
2454 c->drop_task = NULL;
2455 GNUNET_assert (NULL == c->send_task);
2456 GNUNET_assert (NULL == c->recv_task);
2457 GNUNET_assert (NULL == c->warn_task);
2459 GNUNET_MQ_destroy (c->mq);
2460 if (GNUNET_NO == c->persist)
2461 {
2463 if ((0 != (SUSPEND_STATE_EMFILE & sh->suspend_state)) &&
2464 (0 == (SUSPEND_STATE_SHUTDOWN & sh->suspend_state)))
2466 }
2467 else
2468 {
2470 }
2471 GNUNET_free (c);
2472 if ((0 != (SUSPEND_STATE_SHUTDOWN & sh->suspend_state)) &&
2475}
2476
2477
2488void
2490{
2491 struct GNUNET_SERVICE_Handle *sh = c->sh;
2492
2494 "Client dropped: %p (MQ: %p)\n",
2495 c,
2496 c->mq);
2497#if EXECINFO
2498 {
2499 void *backtrace_array[MAX_TRACE_DEPTH];
2500 int num_backtrace_strings = backtrace (backtrace_array, MAX_TRACE_DEPTH);
2501 char **backtrace_strings =
2502 backtrace_symbols (backtrace_array, t->num_backtrace_strings);
2503 for (unsigned int i = 0; i < num_backtrace_strings; i++)
2505 "client drop trace %u: %s\n",
2506 i,
2507 backtrace_strings[i]);
2508 }
2509#endif
2510 if (NULL != c->drop_task)
2511 {
2512 /* asked to drop twice! */
2513 GNUNET_assert (0);
2514 return;
2515 }
2516 GNUNET_CONTAINER_DLL_remove (sh->clients_head,
2517 sh->clients_tail,
2518 c);
2519 if (NULL != sh->disconnect_cb)
2520 sh->disconnect_cb (sh->cb_cls,
2521 c,
2522 c->user_context);
2523 if (NULL != c->warn_task)
2524 {
2526 c->warn_task = NULL;
2527 }
2528 if (NULL != c->recv_task)
2529 {
2531 c->recv_task = NULL;
2532 }
2533 if (NULL != c->send_task)
2534 {
2536 c->send_task = NULL;
2537 }
2539}
2540
2541
2547void
2549{
2550 struct GNUNET_SERVICE_Client *client;
2551
2552 if (0 == (sh->suspend_state & SUSPEND_STATE_SHUTDOWN))
2554 while (NULL != (client = sh->clients_head))
2556}
2557
2558
2571void
2573{
2575 if (((0 != (SUSPEND_STATE_SHUTDOWN & c->sh->suspend_state)) &&
2578}
2579
2580
2588void
2590{
2591 c->persist = GNUNET_YES;
2592}
2593
2594
2601struct GNUNET_MQ_Handle *
2603{
2604 return c->mq;
2605}
2606
2607
2608/* 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
#define GAUGER(category, counter, value, unit)
Definition: gauger.h:19
char * getenv()
#define gettext_noop(String)
Definition: gettext.h:70
#define textdomain(Domainname)
Definition: gettext.h:57
#define bindtextdomain(Domainname, Dirname)
Definition: gettext.h:58
static int list
Set if we should print a list of currently running services.
Definition: gnunet-arm.c:69
static int ret
Final status code.
Definition: gnunet-arm.c:94
static struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition: gnunet-arm.c:109
static char * cfg_filename
Name of the configuration file.
static uint16_t port
Port number.
Definition: gnunet-bcd.c:147
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) ...
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.
struct GNUNET_CONFIGURATION_Handle * GNUNET_CONFIGURATION_create(void)
Create a new configuration object.
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:482
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:582
#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 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.
#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.
@ 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:465
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:304
#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:63
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:975
struct GNUNET_MQ_MessageHandler * GNUNET_MQ_copy_handlers(const struct GNUNET_MQ_MessageHandler *handlers)
Copy an array of handlers.
Definition: mq.c:957
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:421
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:444
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:489
void GNUNET_MQ_destroy(struct GNUNET_MQ_Handle *mq)
Destroy the message queue.
Definition: mq.c:683
@ 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:579
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_create(int domain, int type, int protocol)
Create a new socket.
Definition: network.c:832
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:565
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:737
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:651
char * GNUNET_OS_installation_get_path(enum GNUNET_OS_InstallationPathKind dirkind)
Get the path to a specific GNUnet installation directory or, with GNUNET_OS_IPK_SELF_PREFIX,...
const struct GNUNET_OS_ProjectData * GNUNET_OS_project_data_get(void)
@ GNUNET_OS_IPK_LOCALEDIR
Return the directory where translations are installed (share/locale/)
#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:1512
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:1583
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:1340
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:981
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:1305
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:1278
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:2347
void GNUNET_SERVICE_stop(struct GNUNET_SERVICE_Handle *srv)
Stops a service that was started with GNUNET_SERVICE_start().
Definition: service.c:1913
void GNUNET_SERVICE_shutdown(struct GNUNET_SERVICE_Handle *sh)
Explicitly stops the service.
Definition: service.c:2548
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:2572
struct GNUNET_SERVICE_Handle * GNUNET_SERVICE_start(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:1880
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:2489
void GNUNET_SERVICE_client_persist(struct GNUNET_SERVICE_Client *c)
Set the persist option on this client.
Definition: service.c:2589
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:2432
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.
int GNUNET_SERVICE_register_(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:2162
struct GNUNET_MQ_Handle * GNUNET_SERVICE_client_get_mq(struct GNUNET_SERVICE_Client *c)
Obtain the message queue of c.
Definition: service.c:2602
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2408
void GNUNET_SERVICE_main(int argc, char *const *argv)
Run the mainloop in a monolithic libgnunet.
Definition: service.c:2237
void GNUNET_SERVICE_resume(struct GNUNET_SERVICE_Handle *sh)
Resume accepting connections from the listen socket.
Definition: service.c:2359
int GNUNET_SERVICE_run_(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:1927
@ 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:1473
struct GNUNET_STRINGS_IPv4NetworkPolicy * GNUNET_STRINGS_parse_ipv4_policy(const char *routeListX)
Parse an IPv4 network policy.
Definition: strings.c:1298
size_t GNUNET_strlcpy(char *dst, const char *src, size_t n)
Like strlcpy but portable.
Definition: strings.c:138
#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:436
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:570
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:166
#define _(String)
GNU gettext support macro.
Definition: platform.h:178
static void do_registered_services_shutdown(void *cls)
Definition: service.c:2193
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:1679
static void do_resume(struct GNUNET_SERVICE_Handle *sh, enum SuspendReason sr)
Resume accepting connections from the listen socket.
Definition: service.c:873
static int detach_terminal(struct GNUNET_SERVICE_Handle *sh)
Detach from terminal.
Definition: service.c:1717
static void return_agpl(void *cls, const struct GNUNET_MessageHeader *msg)
Function to return link to AGPL source upon request.
Definition: service.c:1824
static int process_acl4(struct GNUNET_STRINGS_IPv4NetworkPolicy **ret, struct GNUNET_SERVICE_Handle *sh, const char *option)
Parse an IPv4 access control list.
Definition: service.c:932
static void teardown_service(struct GNUNET_SERVICE_Handle *sh)
Tear down the service, closing the listen sockets and freeing the ACLs.
Definition: service.c:1797
static void service_client_recv(void *cls)
A client sent us data.
Definition: service.c:705
static void service_mq_cancel(struct GNUNET_MQ_Handle *mq, void *impl_state)
Implementation function that cancels the currently sent message.
Definition: service.c:596
static int process_acl6(struct GNUNET_STRINGS_IPv6NetworkPolicy **ret, struct GNUNET_SERVICE_Handle *sh, const char *option)
Parse an IPv6 access control list.
Definition: service.c:973
static void service_shutdown(void *cls)
Shutdown task triggered when a service should be terminated.
Definition: service.c:409
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:2372
static int set_user_id(struct GNUNET_SERVICE_Handle *sh)
Set user ID.
Definition: service.c:1628
static void launch_registered_services(void *cls)
Definition: service.c:2217
static struct ServiceHandleList * hll_head
Definition: service.c:2156
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:568
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:1608
#define LOG_STRERROR_FILE(kind, syscall, filename)
Definition: service.c:46
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:750
static void do_send(void *cls)
Task run when we are ready to transmit data to the client.
Definition: service.c:499
static int 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:362
static void finish_client_drop(void *cls)
Asynchronously finish dropping the client.
Definition: service.c:2449
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:674
static void pid_file_delete(struct GNUNET_SERVICE_Handle *sh)
Delete the PID file that was created by our parent.
Definition: service.c:1698
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:1057
static int 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:468
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:641
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:618
static int setup_service(struct GNUNET_SERVICE_Handle *sh)
Setup service handle.
Definition: service.c:1461
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:1013
static void service_main(void *cls)
First task run by any service.
Definition: service.c:901
static int 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:441
#define LOG(kind,...)
Definition: service.c:41
#define LOG_STRERROR(kind, syscall)
Definition: service.c:43
static void accept_client(void *cls)
We have a client.
Definition: service.c:785
SuspendReason
Reasons why we might be suspended.
Definition: service.c:86
@ SUSPEND_STATE_SHUTDOWN
Suspension because service was permanently shutdown.
Definition: service.c:110
@ SUSPEND_STATE_APP
Application requested it.
Definition: service.c:95
@ SUSPEND_STATE_NONE
We are running normally.
Definition: service.c:90
@ SUSPEND_STATE_APP_AND_EMFILE
Both reasons, APP and EMFILE apply.
Definition: service.c:105
@ SUSPEND_STATE_EMFILE
OS ran out of file descriptors.
Definition: service.c:100
static struct ServiceHandleList * hll_tail
Definition: service.c:2159
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:1353
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.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
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.
char * gettext_path
Gettext directory, e.g.
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.
char * gettext_domain
Gettext domain for localisation, e.g.
const char * version
String identifying the current project version.
char * agpl_url
URL pointing to the source code of the application.
Entry in list of pending tasks.
Definition: scheduler.c:136
Handle to a client that is connected to a service.
Definition: service.c:252
int needs_continue
Are we waiting for the application to call GNUNET_SERVICE_client_continue()?
Definition: service.c:345
size_t msg_pos
Current position in msg at which we are transmitting.
Definition: service.c:326
int is_monitor
Is this client a 'monitor' client that should not be counted when deciding on destroying the server d...
Definition: service.c:340
struct GNUNET_SCHEDULER_Task * send_task
Task that transmit data to the client.
Definition: service.c:304
struct GNUNET_SCHEDULER_Task * drop_task
Task run to finish dropping the client after the stack has properly unwound.
Definition: service.c:293
struct GNUNET_TIME_Absolute warn_start
Time when we last gave a message from this client to the application.
Definition: service.c:321
struct GNUNET_NETWORK_Handle * sock
Socket of this client.
Definition: service.c:271
uint16_t warn_type
Type of last message processed (for warn_no_receive_done).
Definition: service.c:350
const struct GNUNET_MessageHeader * msg
Pointer to the message to be transmitted by send_task.
Definition: service.c:309
int persist
Persist the file handle for this client no matter what happens, force the OS to close once the proces...
Definition: service.c:333
struct GNUNET_SCHEDULER_Task * warn_task
Task that warns about missing calls to GNUNET_SERVICE_client_continue().
Definition: service.c:287
struct GNUNET_SCHEDULER_Task * recv_task
Task that receives data from the client to pass it to the handlers.
Definition: service.c:299
struct GNUNET_SERVICE_Handle * sh
Service that this client belongs to.
Definition: service.c:266
struct GNUNET_SERVICE_Client * next
Kept in a DLL.
Definition: service.c:256
void * user_context
User context value, value returned from the connect callback.
Definition: service.c:315
struct GNUNET_SERVICE_Client * prev
Kept in a DLL.
Definition: service.c:261
struct GNUNET_MQ_Handle * mq
Message queue for the client.
Definition: service.c:276
struct GNUNET_MessageStreamTokenizer * mst
Tokenizer we use for processing incoming data.
Definition: service.c:281
Handle to a service.
Definition: service.c:118
void * task_cls
Closure for task.
Definition: service.c:177
struct GNUNET_STRINGS_IPv6NetworkPolicy * v6_denied
IPv6 addresses that are not allowed to connect.
Definition: service.c:188
GNUNET_SERVICE_ConnectHandler connect_cb
Function to call when clients connect.
Definition: service.c:137
GNUNET_SERVICE_InitCallback service_init_cb
Main service-specific task to run.
Definition: service.c:132
int ready_confirm_fd
If we are daemonizing, this FD is set to the pipe to the parent.
Definition: service.c:233
int ret
Overall success/failure of the service start.
Definition: service.c:238
struct GNUNET_SERVICE_Client * clients_tail
Our clients, kept in a DLL.
Definition: service.c:167
struct GNUNET_MQ_MessageHandler * handlers
Message handlers to use for all clients.
Definition: service.c:172
void * cb_cls
Closure for service_init_cb, connect_cb, disconnect_cb.
Definition: service.c:147
struct GNUNET_STRINGS_IPv4NetworkPolicy * v4_denied
IPv4 addresses that are not allowed to connect.
Definition: service.c:183
struct GNUNET_STRINGS_IPv6NetworkPolicy * v6_allowed
IPv6 addresses that are allowed to connect (if not set, all are allowed).
Definition: service.c:200
const char * service_name
Name of our service.
Definition: service.c:127
struct GNUNET_SERVICE_Client * clients_head
Our clients, kept in a DLL.
Definition: service.c:162
GNUNET_SERVICE_DisconnectHandler disconnect_cb
Function to call when clients disconnect / are disconnected.
Definition: service.c:142
enum GNUNET_SERVICE_Options options
Our options.
Definition: service.c:226
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:207
int match_gid
Do we require a matching GID for UNIX domain socket connections? Ignored if match_uid is GNUNET_YES.
Definition: service.c:216
struct ServiceListenContext * slc_head
DLL of listen sockets used to accept new connections.
Definition: service.c:152
int require_found
If GNUNET_YES, consider unknown message types an error where the client is disconnected.
Definition: service.c:244
const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition: service.c:122
enum SuspendReason suspend_state
Are we suspended, and if so, why?
Definition: service.c:221
struct ServiceListenContext * slc_tail
DLL of listen sockets used to accept new connections.
Definition: service.c:157
struct GNUNET_STRINGS_IPv4NetworkPolicy * v4_allowed
IPv4 addresses that are allowed to connect (if not set, all are allowed).
Definition: service.c:194
IPV4 network in CIDR notation.
network in CIDR notation for IPV6.
Time for absolute times used by GNUnet, in microseconds.
struct GNUNET_SERVICE_Handle * sh
Definition: service.c:2152
struct ServiceHandleList * next
Definition: service.c:2149
struct ServiceHandleList * prev
Definition: service.c:2146
Information the service tracks per listen operation.
Definition: service.c:54
struct ServiceListenContext * next
Kept in a DLL.
Definition: service.c:58
struct ServiceListenContext * prev
Kept in a DLL.
Definition: service.c:63
struct GNUNET_SCHEDULER_Task * listen_task
Task scheduled to do the listening.
Definition: service.c:78
struct GNUNET_NETWORK_Handle * listen_socket
Socket we are listening on.
Definition: service.c:73
struct GNUNET_SERVICE_Handle * sh
Service this listen context belongs to.
Definition: service.c:68