GNUnet 0.21.2
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
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#include "gauger.h"
37#endif
38
39
40#define LOG(kind, ...) GNUNET_log_from (kind, "util-service", __VA_ARGS__)
41
42#define LOG_STRERROR(kind, syscall) \
43 GNUNET_log_from_strerror (kind, "util-service", syscall)
44
45#define LOG_STRERROR_FILE(kind, syscall, filename) \
46 GNUNET_log_from_strerror_file (kind, "util-service", syscall, filename)
47
48
53{
58
63
68
73
78};
79
80
85{
90
95
100
105
111
112
117{
122
126 const char *service_name;
127
132
137
142
146 void *cb_cls;
147
152
157
162
167
172
176 void *task_cls;
177
178
183
188
194
200
207
216
221
226
233
239};
240
241
246{
251
256
261
266
271
276
282
288
294
299
304
310
316
320 size_t msg_pos;
321
328
335
340
344 uint16_t warn_type;
345};
346
347
357{
358 for (struct GNUNET_SERVICE_Client *client = sh->clients_head;
359 NULL != client;
360 client = client->next)
361 {
362 if (NULL != client->drop_task)
363 continue;
364 if (client->is_monitor)
365 continue;
366 return true;
367 }
368 return false;
369}
370
371
379static void
381 enum SuspendReason sr)
382{
383 GNUNET_assert (0 == (sh->suspend_state & sr));
384 sh->suspend_state |= sr;
385 for (struct ServiceListenContext *slc = sh->slc_head;
386 NULL != slc;
387 slc = slc->next)
388 {
389 if (NULL != slc->listen_task)
390 {
391 GNUNET_SCHEDULER_cancel (slc->listen_task);
392 slc->listen_task = NULL;
393 }
394 }
395}
396
397
406static void
408{
409 struct GNUNET_SERVICE_Handle *sh = cls;
410
412 {
415 break;
417 /* This task should never be run if we are using
418 the manual shutdown. */
419 GNUNET_assert (0);
420 break;
422 if (0 == (sh->suspend_state & SUSPEND_STATE_SHUTDOWN))
426 break;
427 }
428}
429
430
438static bool
440 const struct in_addr *add)
441{
442 for (unsigned int i = 0;
443 0 != list[i].network.s_addr;
444 i++)
445 {
446 if ( (add->s_addr & list[i].netmask.s_addr) ==
447 (list[i].network.s_addr & list[i].netmask.s_addr) )
448 return true;
449 }
450 return false;
451}
452
453
461static bool
463 const struct in6_addr *ip)
464{
465 for (unsigned int i = 0;
466 ! GNUNET_is_zero (&list[i].network);
467 i++)
468 {
469 bool match = true;
470
471 for (unsigned int j = 0; j < sizeof(struct in6_addr) / sizeof(int); j++)
472 if (((((int *) ip)[j] & ((int *) &list[i].netmask)[j])) !=
473 (((int *) &list[i].network)[j] & ((int *) &list[i].netmask)[j]))
474 {
475 match = false;
476 break;
477 }
478 if (match)
479 return true;
480 }
481 return false;
482}
483
484
491static void
492do_send (void *cls)
493{
494 struct GNUNET_SERVICE_Client *client = cls;
495 ssize_t ret;
496 size_t left;
497 const char *buf;
498
500 "service: sending message with type %u\n",
501 ntohs (client->msg->type));
502 client->send_task = NULL;
503 buf = (const char *) client->msg;
504 left = ntohs (client->msg->size) - client->msg_pos;
506 &buf[client->msg_pos],
507 left);
508 GNUNET_assert (ret <= (ssize_t) left);
509 if (0 == ret)
510 {
511 LOG (GNUNET_ERROR_TYPE_DEBUG, "no data send");
513 return;
514 }
515 if (-1 == ret)
516 {
517 if ((EAGAIN == errno) || (EINTR == errno))
518 {
519 /* ignore */
520 ret = 0;
521 }
522 else
523 {
524 if (EPIPE != errno)
527 "socket send returned with error code %i",
528 errno);
530 return;
531 }
532 }
533 if (0 == client->msg_pos)
534 {
536 }
537 client->msg_pos += ret;
538 if (left > (size_t) ret)
539 {
540 GNUNET_assert (NULL == client->drop_task);
541 client->send_task =
543 client->sock,
544 &do_send,
545 client);
546 return;
547 }
549}
550
551
560static void
562 const struct GNUNET_MessageHeader *msg,
563 void *impl_state)
564{
565 struct GNUNET_SERVICE_Client *client = impl_state;
566
567 (void) mq;
568 if (NULL != client->drop_task)
569 return; /* we're going down right now, do not try to send */
570 GNUNET_assert (NULL == client->send_task);
572 "Sending message of type %u and size %u to client\n",
573 ntohs (msg->type),
574 ntohs (msg->size));
575 client->msg = msg;
576 client->msg_pos = 0;
578 client);
579}
580
581
588static void
590 void *impl_state)
591{
592 struct GNUNET_SERVICE_Client *client = impl_state;
593
594 (void) mq;
595 GNUNET_assert (0 == client->msg_pos);
596 client->msg = NULL;
598 client->send_task = NULL;
599}
600
601
611static void
613 enum GNUNET_MQ_Error error)
614{
615 struct GNUNET_SERVICE_Client *client = cls;
616 struct GNUNET_SERVICE_Handle *sh = client->sh;
617
618 if ( (GNUNET_MQ_ERROR_NO_MATCH == error) &&
619 (! sh->require_found) )
620 {
622 "No handler for message of type %u found\n",
623 (unsigned int) client->warn_type);
625 return; /* ignore error */
626 }
628}
629
630
636static void
638{
639 struct GNUNET_SERVICE_Client *client = cls;
640
642 0 !=
643 client->warn_type); /* type should never be 0 here, as we don't use 0 */
646 client);
647 LOG (
649 _ (
650 "Processing code for message of type %u did not call `GNUNET_SERVICE_client_continue' after %s\n"),
651 (unsigned int) client->warn_type,
653 client->warn_start),
654 GNUNET_YES));
655}
656
657
669static int
671 const struct GNUNET_MessageHeader *message)
672{
673 struct GNUNET_SERVICE_Client *client = cls;
674
676 "Received message of type %u and size %u from client\n",
677 ntohs (message->type),
678 ntohs (message->size));
679 GNUNET_assert (! client->needs_continue);
680 client->needs_continue = true;
681 client->warn_type = ntohs (message->type);
683 GNUNET_assert (NULL == client->warn_task);
686 client);
687 GNUNET_MQ_inject_message (client->mq, message);
688 if (NULL != client->drop_task)
689 return GNUNET_SYSERR;
690 return GNUNET_OK;
691}
692
693
700static void
702{
703 struct GNUNET_SERVICE_Client *client = cls;
705
706 client->recv_task = NULL;
707 ret = GNUNET_MST_read (client->mst,
708 client->sock,
709 GNUNET_NO,
710 GNUNET_YES);
711 if (GNUNET_SYSERR == ret)
712 {
713 /* client closed connection (or IO error) */
714 if (NULL == client->drop_task)
715 {
716 GNUNET_assert (! client->needs_continue);
718 }
719 return;
720 }
721 if (GNUNET_NO == ret)
722 return; /* more messages in buffer, wait for application
723 to be done processing */
725 if (client->needs_continue)
726 return;
727 if (NULL != client->recv_task)
728 return;
729 /* MST needs more data, re-schedule read job */
730 client->recv_task =
732 client->sock,
734 client);
735}
736
737
745static void
747 struct GNUNET_NETWORK_Handle *csock)
748{
749 struct GNUNET_SERVICE_Client *client;
750
751 client = GNUNET_new (struct GNUNET_SERVICE_Client);
752 GNUNET_CONTAINER_DLL_insert (sh->clients_head,
753 sh->clients_tail,
754 client);
755 client->sh = sh;
756 client->sock = csock;
758 NULL,
760 client,
761 sh->handlers,
763 client);
764 client->mst = GNUNET_MST_create (&service_client_mst_cb, client);
765 if (NULL != sh->connect_cb)
766 client->user_context = sh->connect_cb (sh->cb_cls, client, client->mq);
768 client->recv_task =
770 client->sock,
772 client);
773}
774
775
782static void
783accept_client (void *cls)
784{
785 struct ServiceListenContext *slc = cls;
786 struct GNUNET_SERVICE_Handle *sh = slc->sh;
787
788 slc->listen_task = NULL;
789 while (1)
790 {
791 struct GNUNET_NETWORK_Handle *sock;
792 const struct sockaddr_in *v4;
793 const struct sockaddr_in6 *v6;
794 struct sockaddr_storage sa;
795 socklen_t addrlen;
796 int ok;
797
798 addrlen = sizeof(sa);
800 (struct sockaddr *) &sa,
801 &addrlen);
802 if (NULL == sock)
803 {
804 if (EMFILE == errno)
806 else if (EAGAIN != errno)
808 "accept");
809 break;
810 }
811 switch (sa.ss_family)
812 {
813 case AF_INET:
814 GNUNET_assert (addrlen == sizeof(struct sockaddr_in));
815 v4 = (const struct sockaddr_in *) &sa;
816 ok = (((NULL == sh->v4_allowed) ||
817 (check_ipv4_listed (sh->v4_allowed,
818 &v4->sin_addr))) &&
819 ((NULL == sh->v4_denied) ||
820 (! check_ipv4_listed (sh->v4_denied,
821 &v4->sin_addr))));
822 break;
823
824 case AF_INET6:
825 GNUNET_assert (addrlen == sizeof(struct sockaddr_in6));
826 v6 = (const struct sockaddr_in6 *) &sa;
827 ok = (((NULL == sh->v6_allowed) ||
828 (check_ipv6_listed (sh->v6_allowed,
829 &v6->sin6_addr))) &&
830 ((NULL == sh->v6_denied) ||
831 (! check_ipv6_listed (sh->v6_denied,
832 &v6->sin6_addr))));
833 break;
834
835 case AF_UNIX:
836 ok = GNUNET_OK; /* controlled using file-system ACL now */
837 break;
838
839 default:
841 _ ("Unknown address family %d\n"),
842 sa.ss_family);
843 return;
844 }
845 if (! ok)
846 {
848 "Service rejected incoming connection from %s due to policy.\n",
849 GNUNET_a2s ((const struct sockaddr *) &sa, addrlen));
851 continue;
852 }
854 "Service accepted incoming connection from %s.\n",
855 GNUNET_a2s ((const struct sockaddr *) &sa, addrlen));
856 start_client (slc->sh,
857 sock);
858 }
859 if (0 != sh->suspend_state)
860 return;
861 slc->listen_task =
863 slc->listen_socket,
865 slc);
866}
867
868
876static void
878 enum SuspendReason sr)
879{
880 GNUNET_assert ((SUSPEND_STATE_NONE == sr) || (0 != (sh->suspend_state & sr)));
881 sh->suspend_state -= sr;
882 if (SUSPEND_STATE_NONE != sh->suspend_state)
883 return;
884 for (struct ServiceListenContext *slc = sh->slc_head;
885 NULL != slc;
886 slc = slc->next)
887 {
888 GNUNET_assert (NULL == slc->listen_task);
889 slc->listen_task =
891 slc->listen_socket,
893 slc);
894 }
895}
896
897
905static void
906service_main (void *cls)
907{
908 struct GNUNET_SERVICE_Handle *sh = cls;
909
914
915 if (-1 != sh->ready_confirm_fd)
916 {
917 GNUNET_break (1 == write (sh->ready_confirm_fd, ".", 1));
918 GNUNET_break (0 == close (sh->ready_confirm_fd));
919 sh->ready_confirm_fd = -1;
920 }
921
922 if (NULL != sh->service_init_cb)
923 sh->service_init_cb (sh->cb_cls, sh->cfg, sh);
924}
925
926
939 const char *option)
940{
941 char *opt;
942
943 if (! GNUNET_CONFIGURATION_have_value (sh->cfg, sh->service_name, option))
944 {
945 *ret = NULL;
946 return GNUNET_OK;
947 }
950 sh->service_name,
951 option,
952 &opt));
953 if (NULL == (*ret = GNUNET_STRINGS_parse_ipv4_policy (opt)))
954 {
956 _ ("Could not parse IPv4 network specification `%s' for `%s:%s'\n"),
957 opt,
958 sh->service_name,
959 option);
960 GNUNET_free (opt);
961 return GNUNET_SYSERR;
962 }
963 GNUNET_free (opt);
964 return GNUNET_OK;
965}
966
967
980 const char *option)
981{
982 char *opt;
983
984 if (! GNUNET_CONFIGURATION_have_value (sh->cfg, sh->service_name, option))
985 {
986 *ret = NULL;
987 return GNUNET_OK;
988 }
991 sh->service_name,
992 option,
993 &opt));
994 if (NULL == (*ret = GNUNET_STRINGS_parse_ipv6_policy (opt)))
995 {
997 _ ("Could not parse IPv6 network specification `%s' for `%s:%s'\n"),
998 opt,
999 sh->service_name,
1000 option);
1001 GNUNET_free (opt);
1002 return GNUNET_SYSERR;
1003 }
1004 GNUNET_free (opt);
1005 return GNUNET_OK;
1006}
1007
1008
1017static void
1018add_unixpath (struct sockaddr **saddrs,
1019 socklen_t *saddrlens,
1020 const char *unixpath)
1021{
1022#ifdef AF_UNIX
1023 struct sockaddr_un *un;
1024
1025 un = GNUNET_new (struct sockaddr_un);
1026 un->sun_family = AF_UNIX;
1027 GNUNET_strlcpy (un->sun_path, unixpath, sizeof(un->sun_path));
1028#if HAVE_SOCKADDR_UN_SUN_LEN
1029 un->sun_len = (u_char) sizeof(struct sockaddr_un);
1030#endif
1031 *saddrs = (struct sockaddr *) un;
1032 *saddrlens = sizeof(struct sockaddr_un);
1033#else
1034 /* this function should never be called
1035 * unless AF_UNIX is defined! */
1036 GNUNET_assert (0);
1037#endif
1038}
1039
1040
1061static int
1063 const struct GNUNET_CONFIGURATION_Handle *cfg,
1064 struct sockaddr ***addrs,
1065 socklen_t **addr_lens)
1066{
1067 int disablev6;
1068 struct GNUNET_NETWORK_Handle *desc;
1069 unsigned long long port;
1070 char *unixpath;
1071 struct addrinfo hints;
1072 struct addrinfo *res;
1073 struct addrinfo *pos;
1074 struct addrinfo *next;
1075 unsigned int i;
1076 int resi;
1077 int ret;
1078 struct sockaddr **saddrs;
1079 socklen_t *saddrlens;
1080 char *hostname;
1081
1082 *addrs = NULL;
1083 *addr_lens = NULL;
1084 desc = NULL;
1085 disablev6 = GNUNET_NO;
1086 if ((GNUNET_NO == GNUNET_NETWORK_test_pf (PF_INET6)) ||
1087 (GNUNET_YES ==
1089 disablev6 = GNUNET_YES;
1090
1091 port = 0;
1093 {
1096 "PORT",
1097 &port))
1098 {
1100 _ ("Require valid port number for service `%s' in configuration!\n"),
1101 service_name);
1102 }
1103 if (port > 65535)
1104 {
1106 _ ("Require valid port number for service `%s' in configuration!\n"),
1107 service_name);
1108 return GNUNET_SYSERR;
1109 }
1110 }
1111
1113 {
1117 "BINDTO",
1118 &hostname));
1119 }
1120 else
1121 hostname = NULL;
1122
1123 unixpath = NULL;
1124#ifdef AF_UNIX
1125 if ((GNUNET_YES ==
1129 "UNIXPATH",
1130 &unixpath)) &&
1131 (0 < strlen (unixpath)))
1132 {
1133 /* probe UNIX support */
1134 struct sockaddr_un s_un;
1135
1136 if (strlen (unixpath) >= sizeof(s_un.sun_path))
1137 {
1139 _ ("UNIXPATH `%s' too long, maximum length is %llu\n"),
1140 unixpath,
1141 (unsigned long long) sizeof(s_un.sun_path));
1142 unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath);
1143 LOG (GNUNET_ERROR_TYPE_INFO, _ ("Using `%s' instead\n"), unixpath);
1144 }
1147 }
1148 if (NULL != unixpath)
1149 {
1150 desc = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_STREAM, 0);
1151 if (NULL == desc)
1152 {
1153 if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) ||
1154 (EACCES == errno))
1155 {
1157 GNUNET_free (hostname);
1158 GNUNET_free (unixpath);
1159 return GNUNET_SYSERR;
1160 }
1162 _ (
1163 "Disabling UNIX domain socket support for service `%s', failed to create UNIX domain socket: %s\n"),
1165 strerror (errno));
1166 GNUNET_free (unixpath);
1167 unixpath = NULL;
1168 }
1169 else
1170 {
1172 desc = NULL;
1173 }
1174 }
1175#endif
1176
1177 if ((0 == port) && (NULL == unixpath))
1178 {
1180 _ (
1181 "Have neither PORT nor UNIXPATH for service `%s', but one is required\n"),
1182 service_name);
1183 GNUNET_free (hostname);
1184 return GNUNET_SYSERR;
1185 }
1186 if (0 == port)
1187 {
1188 saddrs = GNUNET_new_array (2, struct sockaddr *);
1189 saddrlens = GNUNET_new_array (2, socklen_t);
1190 add_unixpath (saddrs, saddrlens, unixpath);
1191 GNUNET_free (unixpath);
1192 GNUNET_free (hostname);
1193 *addrs = saddrs;
1194 *addr_lens = saddrlens;
1195 return 1;
1196 }
1197
1198 if (NULL != hostname)
1199 {
1201 "Resolving `%s' since that is where `%s' will bind to.\n",
1202 hostname,
1203 service_name);
1204 memset (&hints, 0, sizeof(struct addrinfo));
1205 if (disablev6)
1206 hints.ai_family = AF_INET;
1207 hints.ai_protocol = IPPROTO_TCP;
1208 if ((0 != (ret = getaddrinfo (hostname, NULL, &hints, &res))) ||
1209 (NULL == res))
1210 {
1212 _ ("Failed to resolve `%s': %s\n"),
1213 hostname,
1214 gai_strerror (ret));
1215 GNUNET_free (hostname);
1216 GNUNET_free (unixpath);
1217 return GNUNET_SYSERR;
1218 }
1219 next = res;
1220 i = 0;
1221 while (NULL != (pos = next))
1222 {
1223 next = pos->ai_next;
1224 if ((disablev6) && (pos->ai_family == AF_INET6))
1225 continue;
1226 i++;
1227 }
1228 if (0 == i)
1229 {
1231 _ ("Failed to find %saddress for `%s'.\n"),
1232 disablev6 ? "IPv4 " : "",
1233 hostname);
1234 freeaddrinfo (res);
1235 GNUNET_free (hostname);
1236 GNUNET_free (unixpath);
1237 return GNUNET_SYSERR;
1238 }
1239 resi = i;
1240 if (NULL != unixpath)
1241 resi++;
1242 saddrs = GNUNET_new_array (resi + 1, struct sockaddr *);
1243 saddrlens = GNUNET_new_array (resi + 1, socklen_t);
1244 i = 0;
1245 if (NULL != unixpath)
1246 {
1247 add_unixpath (saddrs, saddrlens, unixpath);
1248 i++;
1249 }
1250 next = res;
1251 while (NULL != (pos = next))
1252 {
1253 next = pos->ai_next;
1254 if ((disablev6) && (AF_INET6 == pos->ai_family))
1255 continue;
1256 if ((IPPROTO_TCP != pos->ai_protocol) && (0 != pos->ai_protocol))
1257 continue; /* not TCP */
1258 if ((SOCK_STREAM != pos->ai_socktype) && (0 != pos->ai_socktype))
1259 continue; /* huh? */
1261 "Service `%s' will bind to `%s'\n",
1263 GNUNET_a2s (pos->ai_addr, pos->ai_addrlen));
1264 if (AF_INET == pos->ai_family)
1265 {
1266 GNUNET_assert (sizeof(struct sockaddr_in) == pos->ai_addrlen);
1267 saddrlens[i] = pos->ai_addrlen;
1268 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1269 GNUNET_memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
1270 ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
1271 }
1272 else
1273 {
1274 GNUNET_assert (AF_INET6 == pos->ai_family);
1275 GNUNET_assert (sizeof(struct sockaddr_in6) == 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_in6 *) saddrs[i])->sin6_port = htons (port);
1280 }
1281 i++;
1282 }
1283 GNUNET_free (hostname);
1284 freeaddrinfo (res);
1285 resi = i;
1286 }
1287 else
1288 {
1289 /* will bind against everything, just set port */
1290 if (disablev6)
1291 {
1292 /* V4-only */
1293 resi = 1;
1294 if (NULL != unixpath)
1295 resi++;
1296 i = 0;
1297 saddrs = GNUNET_new_array (resi + 1, struct sockaddr *);
1298 saddrlens = GNUNET_new_array (resi + 1, socklen_t);
1299 if (NULL != unixpath)
1300 {
1301 add_unixpath (saddrs, saddrlens, unixpath);
1302 i++;
1303 }
1304 saddrlens[i] = sizeof(struct sockaddr_in);
1305 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1306#if HAVE_SOCKADDR_IN_SIN_LEN
1307 ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[i];
1308#endif
1309 ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
1310 ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
1311 }
1312 else
1313 {
1314 /* dual stack */
1315 resi = 2;
1316 if (NULL != unixpath)
1317 resi++;
1318 saddrs = GNUNET_new_array (resi + 1, struct sockaddr *);
1319 saddrlens = GNUNET_new_array (resi + 1, socklen_t);
1320 i = 0;
1321 if (NULL != unixpath)
1322 {
1323 add_unixpath (saddrs, saddrlens, unixpath);
1324 i++;
1325 }
1326 saddrlens[i] = sizeof(struct sockaddr_in6);
1327 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1328#if HAVE_SOCKADDR_IN_SIN_LEN
1329 ((struct sockaddr_in6 *) saddrs[i])->sin6_len = saddrlens[0];
1330#endif
1331 ((struct sockaddr_in6 *) saddrs[i])->sin6_family = AF_INET6;
1332 ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
1333 i++;
1334 saddrlens[i] = sizeof(struct sockaddr_in);
1335 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1336#if HAVE_SOCKADDR_IN_SIN_LEN
1337 ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[1];
1338#endif
1339 ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
1340 ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
1341 }
1342 }
1343 GNUNET_free (unixpath);
1344 *addrs = saddrs;
1345 *addr_lens = saddrlens;
1346 return resi;
1347}
1348
1349
1357static struct GNUNET_NETWORK_Handle *
1358open_listen_socket (const struct sockaddr *server_addr,
1359 socklen_t socklen)
1360{
1361 struct GNUNET_NETWORK_Handle *sock;
1362 uint16_t port;
1363 int eno;
1364
1365 switch (server_addr->sa_family)
1366 {
1367 case AF_INET:
1368 port = ntohs (((const struct sockaddr_in *) server_addr)->sin_port);
1369 break;
1370 case AF_INET6:
1371 port = ntohs (((const struct sockaddr_in6 *) server_addr)->sin6_port);
1372 break;
1373 case AF_UNIX:
1374 port = 0;
1375 break;
1376 default:
1377 GNUNET_break (0);
1378 port = 0;
1379 break;
1380 }
1381 sock = GNUNET_NETWORK_socket_create (server_addr->sa_family,
1382 SOCK_STREAM,
1383 0);
1384 if (NULL == sock)
1385 {
1387 "socket");
1388 errno = 0;
1389 return NULL;
1390 }
1391 /* bind the socket */
1392 if (GNUNET_OK !=
1394 server_addr,
1395 socklen))
1396 {
1397 eno = errno;
1398 if (EADDRINUSE != errno)
1399 {
1400 /* we don't log 'EADDRINUSE' here since an IPv4 bind may
1401 * fail if we already took the port on IPv6; if both IPv4 and
1402 * IPv6 binds fail, then our caller will log using the
1403 * errno preserved in 'eno' */
1404 if (0 != port)
1406 _ ("`%s' failed for port %d (%s).\n"),
1407 "bind",
1408 port,
1409 (AF_INET == server_addr->sa_family) ? "IPv4" : "IPv6");
1410 else
1412 eno = 0;
1413 }
1414 else
1415 {
1416 if (0 != port)
1418 _ ("`%s' failed for port %d (%s): address already in use\n"),
1419 "bind",
1420 port,
1421 (AF_INET == server_addr->sa_family) ? "IPv4" : "IPv6");
1422 else if (AF_UNIX == server_addr->sa_family)
1423 {
1425 _ ("`%s' failed for `%s': address already in use\n"),
1426 "bind",
1427 GNUNET_a2s (server_addr, socklen));
1428 }
1429 }
1431 errno = eno;
1432 return NULL;
1433 }
1434 if (GNUNET_OK != GNUNET_NETWORK_socket_listen (sock, 5))
1435 {
1438 errno = 0;
1439 return NULL;
1440 }
1441 if (0 != port)
1443 "Server starts to listen on port %u.\n",
1444 port);
1445 return sock;
1446}
1447
1448
1465static enum GNUNET_GenericReturnValue
1467{
1468 int tolerant;
1469 struct GNUNET_NETWORK_Handle **csocks = NULL;
1470 struct GNUNET_NETWORK_Handle **lsocks;
1471 const char *nfds;
1472 unsigned int cnt;
1473 int flags;
1474 char dummy[2];
1475
1477 sh->service_name,
1478 "TOLERANT"))
1479 {
1480 if (GNUNET_SYSERR ==
1482 sh->service_name,
1483 "TOLERANT")))
1484 {
1486 _ ("Specified value for `%s' of service `%s' is invalid\n"),
1487 "TOLERANT",
1488 sh->service_name);
1489 return GNUNET_SYSERR;
1490 }
1491 }
1492 else
1493 tolerant = GNUNET_NO;
1494
1495 lsocks = NULL;
1496 errno = 0;
1497 if ( (NULL != (nfds = getenv ("LISTEN_FDS"))) &&
1498 (1 == sscanf (nfds, "%u%1s", &cnt, dummy)) && (cnt > 0) &&
1499 (cnt < FD_SETSIZE) && (cnt + 4 < FD_SETSIZE))
1500 {
1501 lsocks = GNUNET_new_array (cnt + 1, struct GNUNET_NETWORK_Handle *);
1502 while (0 < cnt--)
1503 {
1504 flags = fcntl (3 + cnt, F_GETFD);
1505 if ((flags < 0) || (0 != (flags & FD_CLOEXEC)) ||
1506 (NULL == (lsocks[cnt] = GNUNET_NETWORK_socket_box_native (3 + cnt))))
1507 {
1509 _ (
1510 "Could not access pre-bound socket %u, will try to bind myself\n"),
1511 (unsigned int) 3 + cnt);
1512 cnt++;
1513 while (NULL != lsocks[cnt])
1515 GNUNET_NETWORK_socket_close (lsocks[cnt++]));
1516 GNUNET_free (lsocks);
1517 lsocks = NULL;
1518 break;
1519 }
1520 }
1521 unsetenv ("LISTEN_FDS");
1522 }
1523 if ( (0 != (GNUNET_SERVICE_OPTION_CLOSE_LSOCKS & sh->options)) &&
1524 (NULL != lsocks) )
1525 {
1526 csocks = lsocks;
1527 lsocks = NULL;
1528 }
1529
1530 if (NULL != lsocks)
1531 {
1532 /* listen only on inherited sockets if we have any */
1533 for (struct GNUNET_NETWORK_Handle **ls = lsocks; NULL != *ls; ls++)
1534 {
1535 struct ServiceListenContext *slc;
1536
1537 slc = GNUNET_new (struct ServiceListenContext);
1538 slc->sh = sh;
1539 slc->listen_socket = *ls;
1541 sh->slc_tail,
1542 slc);
1543 }
1544 GNUNET_free (lsocks);
1545 }
1546 else
1547 {
1548 struct sockaddr **addrs;
1549 socklen_t *addrlens;
1550 int num;
1551
1552 num = get_server_addresses (sh->service_name, sh->cfg, &addrs, &addrlens);
1553 if (GNUNET_SYSERR == num)
1554 return GNUNET_SYSERR;
1555
1556 for (int i = 0; i < num; i++)
1557 {
1558 struct ServiceListenContext *slc;
1559
1560 slc = GNUNET_new (struct ServiceListenContext);
1561 slc->sh = sh;
1562 slc->listen_socket = open_listen_socket (addrs[i],
1563 addrlens[i]);
1564 GNUNET_free (addrs[i]);
1565 if (NULL == slc->listen_socket)
1566 {
1568 GNUNET_free (slc);
1569 continue;
1570 }
1572 sh->slc_tail,
1573 slc);
1574 }
1575 GNUNET_free (addrlens);
1576 GNUNET_free (addrs);
1577 if ((0 != num) && (NULL == sh->slc_head))
1578 {
1579 /* All attempts to bind failed, hard failure */
1580 GNUNET_log (
1582 _ (
1583 "Could not bind to any of the ports I was supposed to, refusing to run!\n"));
1584 GNUNET_free (csocks);
1585 return GNUNET_SYSERR;
1586 }
1587 }
1588 if (NULL != csocks)
1589 {
1590 /* close inherited sockets to signal parent that we are ready */
1591 for (struct GNUNET_NETWORK_Handle **ls = csocks; NULL != *ls; ls++)
1593 GNUNET_free (csocks);
1594 }
1595 sh->require_found = (GNUNET_NO == tolerant);
1597 sh->service_name,
1598 "UNIX_MATCH_UID");
1600 sh->service_name,
1601 "UNIX_MATCH_GID");
1602 process_acl4 (&sh->v4_denied, sh, "REJECT_FROM");
1603 process_acl4 (&sh->v4_allowed, sh, "ACCEPT_FROM");
1604 process_acl6 (&sh->v6_denied, sh, "REJECT_FROM6");
1605 process_acl6 (&sh->v6_allowed, sh, "ACCEPT_FROM6");
1606 return GNUNET_OK;
1607}
1608
1609
1617static char *
1619{
1620 char *un;
1621
1622 if (GNUNET_OK !=
1624 sh->service_name,
1625 "USERNAME",
1626 &un))
1627 return NULL;
1628 return un;
1629}
1630
1631
1638static enum GNUNET_GenericReturnValue
1640{
1641 char *user;
1642 struct passwd *pws;
1643
1644 if (NULL == (user = get_user_name (sh)))
1645 return GNUNET_OK; /* keep */
1646 errno = 0;
1647 pws = getpwnam (user);
1648 if (NULL == pws)
1649 {
1651 _ ("Cannot obtain information about user `%s': %s\n"),
1652 user,
1653 errno == 0 ? _ ("No such user") : strerror (errno));
1654 GNUNET_free (user);
1655 return GNUNET_SYSERR;
1656 }
1657 if ((0 != setgid (pws->pw_gid)) || (0 != setegid (pws->pw_gid)) ||
1658#if HAVE_INITGROUPS
1659 (0 != initgroups (user, pws->pw_gid)) ||
1660#endif
1661 (0 != setuid (pws->pw_uid)) ||
1662 (0 != seteuid (pws->pw_uid)))
1663 {
1664 if ((0 != setregid (pws->pw_gid, pws->pw_gid)) ||
1665 (0 != setreuid (pws->pw_uid, pws->pw_uid)))
1666 {
1668 _ ("Cannot change user/group to `%s': %s\n"),
1669 user,
1670 strerror (errno));
1671 GNUNET_free (user);
1672 return GNUNET_SYSERR;
1673 }
1674 }
1675
1676 GNUNET_free (user);
1677 return GNUNET_OK;
1678}
1679
1680
1688static char *
1690{
1691 char *pif;
1692
1693 if (GNUNET_OK !=
1695 sh->service_name,
1696 "PIDFILE",
1697 &pif))
1698 return NULL;
1699 return pif;
1700}
1701
1702
1708static void
1710{
1711 char *pif = get_pid_file_name (sh);
1712
1713 if (NULL == pif)
1714 return; /* no PID file */
1715 if (0 != unlink (pif))
1717 "unlink",
1718 pif);
1719 GNUNET_free (pif);
1720}
1721
1722
1729static enum GNUNET_GenericReturnValue
1731{
1732 pid_t pid;
1733 int nullfd;
1734 int filedes[2];
1735
1736 if (0 != pipe (filedes))
1737 {
1739 "pipe");
1740 return GNUNET_SYSERR;
1741 }
1742 pid = fork ();
1743 if (pid < 0)
1744 {
1746 "fork");
1747 return GNUNET_SYSERR;
1748 }
1749 if (0 != pid)
1750 {
1751 /* Parent */
1752 char c;
1753
1754 GNUNET_break (0 == close (filedes[1]));
1755 c = 'X';
1756 if (1 != read (filedes[0], &c, sizeof(char)))
1758 "read");
1759 fflush (stdout);
1760 switch (c)
1761 {
1762 case '.':
1763 exit (0);
1764
1765 case 'I':
1767 _ ("Service process failed to initialize\n"));
1768 break;
1769
1770 case 'S':
1772 _ ("Service process could not initialize server function\n"));
1773 break;
1774
1775 case 'X':
1777 _ ("Service process failed to report status\n"));
1778 break;
1779 }
1780 exit (1); /* child reported error */
1781 }
1782 GNUNET_break (0 == close (0));
1783 GNUNET_break (0 == close (1));
1784 GNUNET_break (0 == close (filedes[0]));
1785 nullfd = open ("/dev/null", O_RDWR | O_APPEND);
1786 if (nullfd < 0)
1787 return GNUNET_SYSERR;
1788 /* set stdin/stdout to /dev/null */
1789 if ((dup2 (nullfd, 0) < 0) || (dup2 (nullfd, 1) < 0))
1790 {
1792 (void) close (nullfd);
1793 return GNUNET_SYSERR;
1794 }
1795 (void) close (nullfd);
1796 /* Detach from controlling terminal */
1797 pid = setsid ();
1798 if (-1 == pid)
1800 "setsid");
1801 sh->ready_confirm_fd = filedes[1];
1802
1803 return GNUNET_OK;
1804}
1805
1806
1813static void
1815{
1816 struct ServiceListenContext *slc;
1817
1818 GNUNET_free (sh->v4_denied);
1819 GNUNET_free (sh->v6_denied);
1820 GNUNET_free (sh->v4_allowed);
1821 GNUNET_free (sh->v6_allowed);
1822 while (NULL != (slc = sh->slc_head))
1823 {
1825 sh->slc_tail,
1826 slc);
1827 if (NULL != slc->listen_task)
1831 GNUNET_free (slc);
1832 }
1833}
1834
1835
1842static void
1843return_agpl (void *cls,
1844 const struct GNUNET_MessageHeader *msg)
1845{
1846 struct GNUNET_SERVICE_Client *client = cls;
1847 struct GNUNET_MQ_Handle *mq;
1848 struct GNUNET_MQ_Envelope *env;
1849 struct GNUNET_MessageHeader *res;
1850 size_t slen;
1852
1853 (void) msg;
1854 slen = strlen (pd->agpl_url) + 1;
1857 memcpy (&res[1],
1859 slen);
1863}
1864
1865
1866struct GNUNET_SERVICE_Handle *
1868 const struct GNUNET_CONFIGURATION_Handle *cfg,
1871 void *cls,
1872 const struct GNUNET_MQ_MessageHandler *handlers)
1873{
1874 struct GNUNET_SERVICE_Handle *sh;
1875
1877 sh->service_name = service_name;
1878 sh->cfg = cfg;
1879 sh->connect_cb = connect_cb;
1880 sh->disconnect_cb = disconnect_cb;
1881 sh->cb_cls = cls;
1883 &return_agpl,
1884 NULL);
1885 if (GNUNET_OK != setup_service (sh))
1886 {
1887 GNUNET_free (sh->handlers);
1888 GNUNET_free (sh);
1889 return NULL;
1890 }
1891 do_resume (sh,
1893 return sh;
1894}
1895
1896
1902static void
1904{
1905 struct GNUNET_SERVICE_Client *c = cls;
1906 struct GNUNET_SERVICE_Handle *sh = c->sh;
1907
1908 c->drop_task = NULL;
1909 GNUNET_CONTAINER_DLL_remove (sh->clients_head,
1910 sh->clients_tail,
1911 c);
1912 GNUNET_assert (NULL == c->send_task);
1913 GNUNET_assert (NULL == c->recv_task);
1914 GNUNET_assert (NULL == c->warn_task);
1916 GNUNET_MQ_destroy (c->mq);
1917 if (! c->persist)
1918 {
1921 if ((0 != (SUSPEND_STATE_EMFILE & sh->suspend_state)) &&
1922 (0 == (SUSPEND_STATE_SHUTDOWN & sh->suspend_state)))
1923 do_resume (sh,
1925 }
1926 else
1927 {
1929 }
1930 GNUNET_free (c);
1931 if ((0 != (SUSPEND_STATE_SHUTDOWN & sh->suspend_state)) &&
1934}
1935
1936
1937void
1939{
1940 struct GNUNET_SERVICE_Client *client;
1941
1943 while (NULL != (client = srv->clients_head))
1944 {
1945 if (NULL == client->drop_task)
1948 finish_client_drop (client);
1949 }
1950 teardown_service (srv);
1951 GNUNET_free (srv->handlers);
1952 GNUNET_free (srv);
1953}
1954
1955
1956int
1958 char *const *argv,
1959 const char *service_name,
1961 GNUNET_SERVICE_InitCallback service_init_cb,
1964 void *cls,
1965 const struct GNUNET_MQ_MessageHandler *handlers)
1966{
1968
1969#if ENABLE_NLS
1970 char *path;
1971#endif
1972 char *cfg_filename;
1973 char *opt_cfg_filename;
1974 char *loglev;
1975 const char *xdg;
1976 char *logfile;
1977 int do_daemonize;
1978 unsigned long long skew_offset;
1979 unsigned long long skew_variance;
1980 long long clock_offset;
1982 int ret;
1983 int err;
1985 struct GNUNET_GETOPT_CommandLineOption service_options[] = {
1986 GNUNET_GETOPT_option_cfgfile (&opt_cfg_filename),
1988 "daemonize",
1989 gettext_noop (
1990 "do daemonize (detach from terminal)"),
1991 &do_daemonize),
1997 };
1998
1999 err = 1;
2000 memset (&sh, 0, sizeof(sh));
2001 xdg = getenv ("XDG_CONFIG_HOME");
2002 if (NULL != xdg)
2004 "%s%s%s",
2005 xdg,
2007 pd->config_file);
2008 else
2010 sh.ready_confirm_fd = -1;
2011 sh.options = options;
2013 sh.service_init_cb = service_init_cb;
2014 sh.connect_cb = connect_cb;
2015 sh.disconnect_cb = disconnect_cb;
2016 sh.cb_cls = cls;
2017 sh.handlers = (NULL == pd->agpl_url)
2020 sh.service_name = service_name;
2021 /* setup subsystems */
2022 loglev = NULL;
2023 logfile = NULL;
2024 opt_cfg_filename = NULL;
2025 do_daemonize = 0;
2026#if ENABLE_NLS
2027 if (NULL != pd->gettext_domain)
2028 {
2029 setlocale (LC_ALL, "");
2030 path = (NULL == pd->gettext_path) ?
2033 if (NULL != path)
2034 {
2035 bindtextdomain (pd->gettext_domain, path);
2036 GNUNET_free (path);
2037 }
2039 }
2040#endif
2042 service_options,
2043 argc,
2044 argv);
2045 if (GNUNET_SYSERR == ret)
2046 goto shutdown;
2047 if (GNUNET_NO == ret)
2048 {
2049 err = 0;
2050 goto shutdown;
2051 }
2053 loglev,
2054 logfile))
2055 {
2056 GNUNET_break (0);
2057 goto shutdown;
2058 }
2059 if (NULL != opt_cfg_filename)
2060 {
2061 if ((GNUNET_YES != GNUNET_DISK_file_test (opt_cfg_filename)) ||
2062 (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, opt_cfg_filename)))
2063 {
2065 _ ("Malformed configuration file `%s', exit ...\n"),
2066 opt_cfg_filename);
2067 goto shutdown;
2068 }
2069 }
2070 else
2071 {
2072 if (GNUNET_YES ==
2074 {
2075 if (GNUNET_SYSERR ==
2077 cfg_filename))
2078 {
2080 _ ("Malformed configuration file `%s', exit ...\n"),
2081 cfg_filename);
2082 goto shutdown;
2083 }
2084 }
2085 else
2086 {
2087 if (GNUNET_SYSERR ==
2089 NULL))
2090 {
2092 _ ("Malformed configuration, exit ...\n"));
2093 goto shutdown;
2094 }
2095 }
2096 }
2097 if (GNUNET_OK != setup_service (&sh))
2098 goto shutdown;
2099 if ( (1 == do_daemonize) &&
2100 (GNUNET_OK != detach_terminal (&sh)) )
2101 {
2102 GNUNET_break (0);
2103 goto shutdown;
2104 }
2105 if (GNUNET_OK != set_user_id (&sh))
2106 goto shutdown;
2108 "Service `%s' runs with configuration from `%s'\n",
2110 (NULL != opt_cfg_filename) ? opt_cfg_filename : cfg_filename);
2111 if ( (GNUNET_OK ==
2113 "TESTING",
2114 "SKEW_OFFSET",
2115 &skew_offset)) &&
2116 (GNUNET_OK ==
2118 "TESTING",
2119 "SKEW_VARIANCE",
2120 &skew_variance)) )
2121 {
2122 clock_offset = skew_offset - skew_variance;
2123 GNUNET_TIME_set_offset (clock_offset);
2125 "Skewing clock by %lld ms\n",
2126 (long long) clock_offset);
2127 }
2129
2130 /* actually run service */
2131 err = 0;
2133 /* shutdown */
2134 if (1 == do_daemonize)
2136
2137shutdown:
2138 if (-1 != sh.ready_confirm_fd)
2139 {
2140 if (1 != write (sh.ready_confirm_fd, err ? "I" : "S", 1))
2142 GNUNET_break (0 == close (sh.ready_confirm_fd));
2143 }
2144#if HAVE_MALLINFO2
2145 {
2146 char *counter;
2147
2148 if ( (GNUNET_YES ==
2151 "GAUGER_HEAP")) &&
2152 (GNUNET_OK ==
2155 "GAUGER_HEAP",
2156 &counter)))
2157 {
2158 struct mallinfo2 mi;
2159
2160 mi = mallinfo2 ();
2162 counter,
2163 mi.usmblks,
2164 "blocks");
2165 GNUNET_free (counter);
2166 }
2167 }
2168#endif
2170 GNUNET_free (sh.handlers);
2173 GNUNET_free (logfile);
2174 GNUNET_free (loglev);
2176 GNUNET_free (opt_cfg_filename);
2177
2178 return err ? GNUNET_SYSERR : 0;
2179}
2180
2181
2187{
2188 /* DLL */
2190
2191 /* DLL */
2193
2194 /* Handle to the service to launch */
2196};
2197
2198/* The service list */
2200
2201/* The service list */
2203
2204
2205int
2208 GNUNET_SERVICE_InitCallback service_init_cb,
2211 void *cls,
2212 const struct GNUNET_MQ_MessageHandler *handlers)
2213{
2214 struct ServiceHandleList *hle;
2217
2218 sh->ready_confirm_fd = -1;
2219 sh->options = options;
2220 sh->service_init_cb = service_init_cb;
2221 sh->connect_cb = connect_cb;
2222 sh->disconnect_cb = disconnect_cb;
2223 sh->cb_cls = cls;
2224 sh->handlers = (NULL == pd->agpl_url)
2227 sh->service_name = service_name;
2228 hle = GNUNET_new (struct ServiceHandleList);
2229 hle->sh = sh;
2231 hll_tail,
2232 hle);
2233 return 0;
2234}
2235
2236
2237static void
2239{
2240 while (NULL != hll_head)
2241 {
2242 struct ServiceHandleList *shl = hll_head;
2243 struct GNUNET_SERVICE_Handle *sh = shl->sh;
2244
2246 hll_tail,
2247 shl);
2248 GNUNET_free (shl);
2249 if (-1 != sh->ready_confirm_fd)
2250 {
2251 if (1 != write (sh->ready_confirm_fd, "S", 1))
2253 "write");
2254 GNUNET_break (0 ==
2255 close (sh->ready_confirm_fd));
2256 }
2258 GNUNET_free (sh->handlers);
2259 GNUNET_free (sh);
2260 }
2261}
2262
2263
2264static void
2266{
2267 struct GNUNET_CONFIGURATION_Handle *cfg = cls;
2268
2269 for (struct ServiceHandleList *shl = hll_head;
2270 NULL != shl;
2271 shl = shl->next)
2272 {
2273 shl->sh->cfg = cfg;
2274 if (GNUNET_OK != setup_service (shl->sh))
2275 continue;
2276 if (GNUNET_OK != set_user_id (shl->sh))
2277 continue;
2279 shl->sh);
2280 }
2282 NULL);
2283}
2284
2285
2286void
2288 char *const *argv)
2289{
2290 char *cfg_filename;
2291 char *opt_cfg_filename;
2292 char *logfile;
2293 char *loglev;
2294 const char *xdg;
2295 int do_daemonize;
2296 int ret;
2299 struct GNUNET_GETOPT_CommandLineOption service_options[] = {
2300 GNUNET_GETOPT_option_cfgfile (&opt_cfg_filename),
2302 "daemonize",
2303 gettext_noop (
2304 "do daemonize (detach from terminal)"),
2305 &do_daemonize),
2311 };
2312
2313 xdg = getenv ("XDG_CONFIG_HOME");
2314 if (NULL != xdg)
2316 "%s%s%s",
2317 xdg,
2319 pd->config_file);
2320 else
2323 // FIXME we need to set this up for each service!
2324 ret = GNUNET_GETOPT_run ("libgnunet",
2325 service_options,
2326 argc,
2327 argv);
2328 if (GNUNET_SYSERR == ret)
2329 goto shutdown;
2330 if (GNUNET_NO == ret)
2331 {
2332 goto shutdown;
2333 }
2334 // FIXME we need to set this up for each service!
2335 // NOTE: that was not the idea. What are you proposing? -CG
2336 if (GNUNET_OK !=
2337 GNUNET_log_setup ("libgnunet",
2338 loglev,
2339 logfile))
2340 {
2341 GNUNET_break (0);
2342 goto shutdown;
2343 }
2344 if (NULL != opt_cfg_filename)
2345 {
2346 if ( (GNUNET_YES !=
2347 GNUNET_DISK_file_test (opt_cfg_filename)) ||
2348 (GNUNET_SYSERR ==
2350 opt_cfg_filename)) )
2351 {
2353 _ ("Malformed configuration file `%s', exit ...\n"),
2354 opt_cfg_filename);
2355 goto shutdown;
2356 }
2357 }
2358 else
2359 {
2360 if (GNUNET_YES ==
2362 {
2363 if (GNUNET_SYSERR ==
2365 cfg_filename))
2366 {
2368 _ ("Malformed configuration file `%s', exit ...\n"),
2369 cfg_filename);
2371 return;
2372 }
2373 }
2374 else
2375 {
2376 if (GNUNET_SYSERR ==
2378 NULL))
2379 {
2381 _ ("Malformed configuration, exit ...\n"));
2383 return;
2384 }
2385 }
2386 }
2388
2390 cfg);
2391shutdown:
2394 GNUNET_free (logfile);
2395 GNUNET_free (loglev);
2397 GNUNET_free (opt_cfg_filename);
2398}
2399
2400
2401void
2403{
2404 do_suspend (sh,
2406}
2407
2408
2409void
2411{
2412 do_resume (sh,
2414}
2415
2416
2423static void
2425{
2426 struct GNUNET_SERVICE_Client *c = cls;
2427 int ret;
2428
2429 c->recv_task = NULL;
2430 /* first, check if there is still something in the buffer */
2431 ret = GNUNET_MST_next (c->mst,
2432 GNUNET_YES);
2433 if (GNUNET_SYSERR == ret)
2434 {
2435 if (NULL == c->drop_task)
2437 return;
2438 }
2439 if (GNUNET_NO == ret)
2440 return; /* done processing, wait for more later */
2442 if (c->needs_continue)
2443 return; /* #GNUNET_MST_next() did give a message to the client */
2444 /* need to receive more data from the network first */
2445 if (NULL != c->recv_task)
2446 return;
2448 c->sock,
2450 c);
2451}
2452
2453
2454void
2456{
2457 GNUNET_assert (NULL == c->drop_task);
2459 GNUNET_assert (NULL == c->recv_task);
2460 c->needs_continue = false;
2461 if (NULL != c->warn_task)
2462 {
2464 c->warn_task = NULL;
2465 }
2467 c);
2468}
2469
2470
2471void
2473{
2474 GNUNET_break (NULL != c->warn_task);
2475 if (NULL != c->warn_task)
2476 {
2478 c->warn_task = NULL;
2479 }
2480}
2481
2482
2483void
2485{
2486 struct GNUNET_SERVICE_Handle *sh = c->sh;
2487
2489 "Client dropped: %p (MQ: %p)\n",
2490 c,
2491 c->mq);
2492#if EXECINFO
2493 {
2494 void *backtrace_array[MAX_TRACE_DEPTH];
2495 int num_backtrace_strings = backtrace (backtrace_array,
2496 MAX_TRACE_DEPTH);
2497 char **backtrace_strings =
2498 backtrace_symbols (backtrace_array,
2499 t->num_backtrace_strings);
2500 for (unsigned int i = 0; i < num_backtrace_strings; i++)
2502 "client drop trace %u: %s\n",
2503 i,
2504 backtrace_strings[i]);
2505 }
2506#endif
2507 GNUNET_assert (NULL == c->drop_task);
2508 if (NULL != sh->disconnect_cb)
2509 sh->disconnect_cb (sh->cb_cls,
2510 c,
2511 c->user_context);
2512 if (NULL != c->warn_task)
2513 {
2515 c->warn_task = NULL;
2516 }
2517 if (NULL != c->recv_task)
2518 {
2520 c->recv_task = NULL;
2521 }
2522 if (NULL != c->send_task)
2523 {
2525 c->send_task = NULL;
2526 }
2528 c);
2529}
2530
2531
2532void
2534{
2535 if (0 == (sh->suspend_state & SUSPEND_STATE_SHUTDOWN))
2536 do_suspend (sh,
2538 for (struct GNUNET_SERVICE_Client *client = sh->clients_head;
2539 NULL != client;
2540 client = client->next)
2541 {
2542 if (NULL == client->drop_task)
2544 }
2545}
2546
2547
2548void
2550{
2551 c->is_monitor = true;
2552 if (((0 != (SUSPEND_STATE_SHUTDOWN & c->sh->suspend_state)) &&
2553 (! have_non_monitor_clients (c->sh))))
2555}
2556
2557
2558void
2560{
2561 c->persist = true;
2562}
2563
2564
2565struct GNUNET_MQ_Handle *
2567{
2568 return c->mq;
2569}
2570
2571
2572/* 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: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: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.
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: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:2402
void GNUNET_SERVICE_stop(struct GNUNET_SERVICE_Handle *srv)
Stops a service that was started with GNUNET_SERVICE_start().
Definition: service.c:1938
void GNUNET_SERVICE_shutdown(struct GNUNET_SERVICE_Handle *sh)
Explicitly stops the service.
Definition: service.c:2533
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:2549
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:1867
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:2484
void GNUNET_SERVICE_client_persist(struct GNUNET_SERVICE_Client *c)
Set the persist option on this client.
Definition: service.c:2559
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:2472
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:2206
struct GNUNET_MQ_Handle * GNUNET_SERVICE_client_get_mq(struct GNUNET_SERVICE_Client *c)
Obtain the message queue of c.
Definition: service.c:2566
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2455
void GNUNET_SERVICE_main(int argc, char *const *argv)
Run the mainloop in a monolithic libgnunet.
Definition: service.c:2287
void GNUNET_SERVICE_resume(struct GNUNET_SERVICE_Handle *sh)
Resume accepting connections from the listen socket.
Definition: service.c:2410
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:1957
@ 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:2238
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:1689
static void do_resume(struct GNUNET_SERVICE_Handle *sh, enum SuspendReason sr)
Resume accepting connections from the listen socket.
Definition: service.c:877
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:462
static void return_agpl(void *cls, const struct GNUNET_MessageHeader *msg)
Function to return link to AGPL source upon request.
Definition: service.c:1843
static void teardown_service(struct GNUNET_SERVICE_Handle *sh)
Tear down the service, closing the listen sockets and freeing the ACLs.
Definition: service.c:1814
static void service_client_recv(void *cls)
A client sent us data.
Definition: service.c:701
static void service_mq_cancel(struct GNUNET_MQ_Handle *mq, void *impl_state)
Implementation function that cancels the currently sent message.
Definition: service.c:589
static void service_shutdown(void *cls)
Shutdown task triggered when a service should be terminated.
Definition: service.c:407
static enum GNUNET_GenericReturnValue setup_service(struct GNUNET_SERVICE_Handle *sh)
Setup service handle.
Definition: service.c:1466
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:2424
static enum GNUNET_GenericReturnValue detach_terminal(struct GNUNET_SERVICE_Handle *sh)
Detach from terminal.
Definition: service.c:1730
static void launch_registered_services(void *cls)
Definition: service.c:2265
static struct ServiceHandleList * hll_head
Definition: service.c:2199
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:561
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:1618
#define LOG_STRERROR_FILE(kind, syscall, filename)
Definition: service.c:45
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:746
static void do_send(void *cls)
Task run when we are ready to transmit data to the client.
Definition: service.c:492
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:937
static void finish_client_drop(void *cls)
Asynchronously finish dropping the client.
Definition: service.c:1903
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:670
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:439
static void pid_file_delete(struct GNUNET_SERVICE_Handle *sh)
Delete the PID file that was created by our parent.
Definition: service.c:1709
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:1062
static void do_suspend(struct GNUNET_SERVICE_Handle *sh, enum SuspendReason sr)
Suspend accepting connections from the listen socket temporarily.
Definition: service.c:380
static void warn_no_client_continue(void *cls)
Task run to warn about missing calls to GNUNET_SERVICE_client_continue().
Definition: service.c:637
static enum GNUNET_GenericReturnValue set_user_id(struct GNUNET_SERVICE_Handle *sh)
Set user ID.
Definition: service.c:1639
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:612
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:1018
static void service_main(void *cls)
First task run by any service.
Definition: service.c:906
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:978
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:356
#define LOG(kind,...)
Definition: service.c:40
#define LOG_STRERROR(kind, syscall)
Definition: service.c:42
static void accept_client(void *cls)
We have a client.
Definition: service.c:783
SuspendReason
Reasons why we might be suspended.
Definition: service.c:85
@ SUSPEND_STATE_SHUTDOWN
Suspension because service was permanently shutdown.
Definition: service.c:109
@ SUSPEND_STATE_APP
Application requested it.
Definition: service.c:94
@ SUSPEND_STATE_NONE
We are running normally.
Definition: service.c:89
@ SUSPEND_STATE_APP_AND_EMFILE
Both reasons, APP and EMFILE apply.
Definition: service.c:104
@ SUSPEND_STATE_EMFILE
OS ran out of file descriptors.
Definition: service.c:99
static struct ServiceHandleList * hll_tail
Definition: service.c:2202
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:1358
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.
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:246
bool persist
Persist the file handle for this client no matter what happens, force the OS to close once the proces...
Definition: service.c:327
size_t msg_pos
Current position in msg at which we are transmitting.
Definition: service.c:320
struct GNUNET_SCHEDULER_Task * send_task
Task that transmit data to the client.
Definition: service.c:298
struct GNUNET_SCHEDULER_Task * drop_task
Task run to finish dropping the client after the stack has properly unwound.
Definition: service.c:287
struct GNUNET_TIME_Absolute warn_start
Time when we last gave a message from this client to the application.
Definition: service.c:315
struct GNUNET_NETWORK_Handle * sock
Socket of this client.
Definition: service.c:265
uint16_t warn_type
Type of last message processed (for warn_no_receive_done).
Definition: service.c:344
const struct GNUNET_MessageHeader * msg
Pointer to the message to be transmitted by send_task.
Definition: service.c:303
struct GNUNET_SCHEDULER_Task * warn_task
Task that warns about missing calls to GNUNET_SERVICE_client_continue().
Definition: service.c:281
struct GNUNET_SCHEDULER_Task * recv_task
Task that receives data from the client to pass it to the handlers.
Definition: service.c:293
struct GNUNET_SERVICE_Handle * sh
Service that this client belongs to.
Definition: service.c:260
struct GNUNET_SERVICE_Client * next
Kept in a DLL.
Definition: service.c:250
void * user_context
User context value, value returned from the connect callback.
Definition: service.c:309
bool needs_continue
Are we waiting for the application to call GNUNET_SERVICE_client_continue()?
Definition: service.c:339
bool is_monitor
Is this client a 'monitor' client that should not be counted when deciding on destroying the server d...
Definition: service.c:334
struct GNUNET_SERVICE_Client * prev
Kept in a DLL.
Definition: service.c:255
struct GNUNET_MQ_Handle * mq
Message queue for the client.
Definition: service.c:270
struct GNUNET_MessageStreamTokenizer * mst
Tokenizer we use for processing incoming data.
Definition: service.c:275
Handle to a service.
Definition: service.c:117
void * task_cls
Closure for task.
Definition: service.c:176
struct GNUNET_STRINGS_IPv6NetworkPolicy * v6_denied
IPv6 addresses that are not allowed to connect.
Definition: service.c:187
GNUNET_SERVICE_ConnectHandler connect_cb
Function to call when clients connect.
Definition: service.c:136
GNUNET_SERVICE_InitCallback service_init_cb
Main service-specific task to run.
Definition: service.c:131
int ready_confirm_fd
If we are daemonizing, this FD is set to the pipe to the parent.
Definition: service.c:232
struct GNUNET_SERVICE_Client * clients_tail
Our clients, kept in a DLL.
Definition: service.c:166
struct GNUNET_MQ_MessageHandler * handlers
Message handlers to use for all clients.
Definition: service.c:171
void * cb_cls
Closure for service_init_cb, connect_cb, disconnect_cb.
Definition: service.c:146
struct GNUNET_STRINGS_IPv4NetworkPolicy * v4_denied
IPv4 addresses that are not allowed to connect.
Definition: service.c:182
struct GNUNET_STRINGS_IPv6NetworkPolicy * v6_allowed
IPv6 addresses that are allowed to connect (if not set, all are allowed).
Definition: service.c:199
const char * service_name
Name of our service.
Definition: service.c:126
struct GNUNET_SERVICE_Client * clients_head
Our clients, kept in a DLL.
Definition: service.c:161
bool require_found
If true, consider unknown message types an error where the client is disconnected.
Definition: service.c:238
GNUNET_SERVICE_DisconnectHandler disconnect_cb
Function to call when clients disconnect / are disconnected.
Definition: service.c:141
enum GNUNET_SERVICE_Options options
Our options.
Definition: service.c:225
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:206
int match_gid
Do we require a matching GID for UNIX domain socket connections? Ignored if match_uid is GNUNET_YES.
Definition: service.c:215
struct ServiceListenContext * slc_head
DLL of listen sockets used to accept new connections.
Definition: service.c:151
const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition: service.c:121
enum SuspendReason suspend_state
Are we suspended, and if so, why?
Definition: service.c:220
struct ServiceListenContext * slc_tail
DLL of listen sockets used to accept new connections.
Definition: service.c:156
struct GNUNET_STRINGS_IPv4NetworkPolicy * v4_allowed
IPv4 addresses that are allowed to connect (if not set, all are allowed).
Definition: service.c:193
IPV4 network in CIDR notation.
network in CIDR notation for IPV6.
Time for absolute times used by GNUnet, in microseconds.
A list of service to be launched when GNUNET_SERVICE_main() is called.
Definition: service.c:2187
struct GNUNET_SERVICE_Handle * sh
Definition: service.c:2195
struct ServiceHandleList * next
Definition: service.c:2192
struct ServiceHandleList * prev
Definition: service.c:2189
Information the service tracks per listen operation.
Definition: service.c:53
struct ServiceListenContext * next
Kept in a DLL.
Definition: service.c:57
struct ServiceListenContext * prev
Kept in a DLL.
Definition: service.c:62
struct GNUNET_SCHEDULER_Task * listen_task
Task scheduled to do the listening.
Definition: service.c:77
struct GNUNET_NETWORK_Handle * listen_socket
Socket we are listening on.
Definition: service.c:72
struct GNUNET_SERVICE_Handle * sh
Service this listen context belongs to.
Definition: service.c:67