GNUnet  0.19.4
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 
111 };
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 
309  const struct GNUNET_MessageHeader *msg;
310 
316 
322 
326  size_t msg_pos;
327 
333  int persist;
334 
341 
346 
350  uint16_t warn_type;
351 };
352 
353 
361 static 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 
382 static 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 
408 static void
409 service_shutdown (void *cls)
410 {
411  struct GNUNET_SERVICE_Handle *sh = cls;
412 
413  switch (sh->options & GNUNET_SERVICE_OPTION_SHUTDOWN_BITMASK)
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 
440 static 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 
467 static int
469  const struct in6_addr *ip)
470 {
471  unsigned int i;
472 
473  if (NULL == list)
474  return GNUNET_NO;
475  i = 0;
476 NEXT:
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 
498 static void
499 do_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 
567 static 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 
595 static void
596 service_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 
617 static 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 
640 static void
642 {
643  struct GNUNET_SERVICE_Client *client = cls;
644 
645  GNUNET_break (
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 
673 static 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 
704 static 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 
749 static 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 
784 static void
785 accept_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,
860  &accept_client,
861  slc);
862 }
863 
864 
872 static 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,
887  &accept_client,
888  slc);
889  }
890 }
891 
892 
900 static void
901 service_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 
931 static int
933  struct GNUNET_SERVICE_Handle *sh,
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 
972 static int
974  struct GNUNET_SERVICE_Handle *sh,
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 
1012 static void
1013 add_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 
1056 static 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  {
1090  service_name,
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  {
1111  service_name,
1112  "BINDTO",
1113  &hostname));
1114  }
1115  else
1116  hostname = NULL;
1117 
1118  unixpath = NULL;
1119 #ifdef AF_UNIX
1120  if ((GNUNET_YES ==
1123  service_name,
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  {
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"),
1159  service_name,
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);
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);
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));
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);
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",
1257  service_name,
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  }
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 
1352 static struct GNUNET_NETWORK_Handle *
1353 open_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 
1460 static 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 ==
1476  (tolerant = GNUNET_CONFIGURATION_get_value_yesno (sh->cfg,
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;
1586  sh->match_uid = GNUNET_CONFIGURATION_get_value_yesno (sh->cfg,
1587  sh->service_name,
1588  "UNIX_MATCH_UID");
1589  sh->match_gid = GNUNET_CONFIGURATION_get_value_yesno (sh->cfg,
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 
1607 static char *
1609 {
1610  char *un;
1611 
1613  sh->service_name,
1614  "USERNAME",
1615  &un))
1616  return NULL;
1617  return un;
1618 }
1619 
1620 
1627 static 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 
1678 static char *
1680 {
1681  char *pif;
1682 
1684  sh->service_name,
1685  "PIDFILE",
1686  &pif))
1687  return NULL;
1688  return pif;
1689 }
1690 
1691 
1697 static 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 
1716 static 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 
1796 static 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 
1823 static void
1824 return_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;
1831  const struct GNUNET_OS_ProjectData *pd = GNUNET_OS_project_data_get ();
1832 
1833  (void) msg;
1834  slen = strlen (pd->agpl_url) + 1;
1836  memcpy (&res[1], GNUNET_AGPL_URL, slen);
1837  mq = GNUNET_SERVICE_client_get_mq (client);
1838  GNUNET_MQ_send (mq, env);
1840 }
1841 
1842 
1879 struct 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 
1889  sh = GNUNET_new (struct GNUNET_SERVICE_Handle);
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 
1912 void
1914 {
1915  struct GNUNET_SERVICE_Client *client;
1916 
1917  GNUNET_SERVICE_suspend (srv);
1918  while (NULL != (client = srv->clients_head))
1919  GNUNET_SERVICE_client_drop (client);
1920  teardown_service (srv);
1921  GNUNET_free (srv->handlers);
1922  GNUNET_free (srv);
1923 }
1924 
1925 
1967 int
1969  char *const *argv,
1970  const char *service_name,
1972  GNUNET_SERVICE_InitCallback service_init_cb,
1975  void *cls,
1976  const struct GNUNET_MQ_MessageHandler *handlers)
1977 {
1978  struct GNUNET_SERVICE_Handle sh;
1979 
1980 #if ENABLE_NLS
1981  char *path;
1982 #endif
1983  char *cfg_filename;
1984  char *opt_cfg_filename;
1985  char *loglev;
1986  const char *xdg;
1987  char *logfile;
1988  int do_daemonize;
1989  unsigned long long skew_offset;
1990  unsigned long long skew_variance;
1991  long long clock_offset;
1993  int ret;
1994  int err;
1995  const struct GNUNET_OS_ProjectData *pd = GNUNET_OS_project_data_get ();
1996  struct GNUNET_GETOPT_CommandLineOption service_options[] = {
1997  GNUNET_GETOPT_option_cfgfile (&opt_cfg_filename),
1999  "daemonize",
2000  gettext_noop (
2001  "do daemonize (detach from terminal)"),
2002  &do_daemonize),
2005  GNUNET_GETOPT_option_logfile (&logfile),
2008  };
2009 
2010  err = 1;
2011  memset (&sh, 0, sizeof(sh));
2012  xdg = getenv ("XDG_CONFIG_HOME");
2013  if (NULL != xdg)
2015  "%s%s%s",
2016  xdg,
2018  pd->config_file);
2019  else
2021  sh.ready_confirm_fd = -1;
2022  sh.options = options;
2023  sh.cfg = cfg = GNUNET_CONFIGURATION_create ();
2024  sh.service_init_cb = service_init_cb;
2025  sh.connect_cb = connect_cb;
2026  sh.disconnect_cb = disconnect_cb;
2027  sh.cb_cls = cls;
2028  sh.handlers = (NULL == pd->agpl_url)
2031  sh.service_name = service_name;
2032  sh.ret = 0;
2033  /* setup subsystems */
2034  loglev = NULL;
2035  logfile = NULL;
2036  opt_cfg_filename = NULL;
2037  do_daemonize = 0;
2038 #if ENABLE_NLS
2039  if (NULL != pd->gettext_domain)
2040  {
2041  setlocale (LC_ALL, "");
2042  path = (NULL == pd->gettext_path) ?
2045  if (NULL != path)
2046  {
2047  bindtextdomain (pd->gettext_domain, path);
2048  GNUNET_free (path);
2049  }
2050  textdomain (pd->gettext_domain);
2051  }
2052 #endif
2054  service_options,
2055  argc,
2056  argv);
2057  if (GNUNET_SYSERR == ret)
2058  goto shutdown;
2059  if (GNUNET_NO == ret)
2060  {
2061  err = 0;
2062  goto shutdown;
2063  }
2065  loglev,
2066  logfile))
2067  {
2068  GNUNET_break (0);
2069  goto shutdown;
2070  }
2071  if (NULL != opt_cfg_filename)
2072  {
2073  if ((GNUNET_YES != GNUNET_DISK_file_test (opt_cfg_filename)) ||
2074  (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, opt_cfg_filename)))
2075  {
2077  _ ("Malformed configuration file `%s', exit ...\n"),
2078  opt_cfg_filename);
2079  goto shutdown;
2080  }
2081  }
2082  else
2083  {
2085  {
2087  {
2089  _ ("Malformed configuration file `%s', exit ...\n"),
2090  cfg_filename);
2091  goto shutdown;
2092  }
2093  }
2094  else
2095  {
2097  {
2099  _ ("Malformed configuration, exit ...\n"));
2100  goto shutdown;
2101  }
2102  }
2103  }
2104  if (GNUNET_OK != setup_service (&sh))
2105  goto shutdown;
2106  if ((1 == do_daemonize) && (GNUNET_OK != detach_terminal (&sh)))
2107  {
2108  GNUNET_break (0);
2109  goto shutdown;
2110  }
2111  if (GNUNET_OK != set_user_id (&sh))
2112  goto shutdown;
2114  "Service `%s' runs with configuration from `%s'\n",
2115  service_name,
2116  (NULL != opt_cfg_filename) ? opt_cfg_filename : cfg_filename);
2118  "TESTING",
2119  "SKEW_OFFSET",
2120  &skew_offset)) &&
2122  "TESTING",
2123  "SKEW_VARIANCE",
2124  &skew_variance)))
2125  {
2126  clock_offset = skew_offset - skew_variance;
2127  GNUNET_TIME_set_offset (clock_offset);
2129  "Skewing clock by %lld ms\n",
2130  (long long) clock_offset);
2131  }
2133 
2134  /* actually run service */
2135  err = 0;
2137  /* shutdown */
2138  if (1 == do_daemonize)
2139  pid_file_delete (&sh);
2140 
2141 shutdown:
2142  if (-1 != sh.ready_confirm_fd)
2143  {
2144  if (1 != write (sh.ready_confirm_fd, err ? "I" : "S", 1))
2146  GNUNET_break (0 == close (sh.ready_confirm_fd));
2147  }
2148 #if HAVE_MALLINFO2
2149  {
2150  char *counter;
2151 
2153  service_name,
2154  "GAUGER_HEAP")) &&
2156  service_name,
2157  "GAUGER_HEAP",
2158  &counter)))
2159  {
2160  struct mallinfo2 mi;
2161 
2162  mi = mallinfo2 ();
2163  GAUGER (service_name, counter, mi.usmblks, "blocks");
2164  GNUNET_free (counter);
2165  }
2166  }
2167 #endif
2168  teardown_service (&sh);
2169  GNUNET_free (sh.handlers);
2172  GNUNET_free (logfile);
2173  GNUNET_free (loglev);
2175  GNUNET_free (opt_cfg_filename);
2176 
2177  return err ? GNUNET_SYSERR : sh.ret;
2178 }
2179 
2180 
2187 void
2189 {
2191 }
2192 
2193 
2199 void
2201 {
2203 }
2204 
2205 
2212 static void
2214 {
2215  struct GNUNET_SERVICE_Client *c = cls;
2216  int ret;
2217 
2218  c->recv_task = NULL;
2219  /* first, check if there is still something in the buffer */
2221  if (GNUNET_SYSERR == ret)
2222  {
2223  if (NULL == c->drop_task)
2225  return;
2226  }
2227  if (GNUNET_NO == ret)
2228  return; /* done processing, wait for more later */
2230  if (GNUNET_YES == c->needs_continue)
2231  return; /* #GNUNET_MST_next() did give a message to the client */
2232  /* need to receive more data from the network first */
2233  if (NULL != c->recv_task)
2234  return;
2236  c->sock,
2238  c);
2239 }
2240 
2241 
2248 void
2250 {
2251  GNUNET_assert (NULL == c->drop_task);
2253  GNUNET_assert (NULL == c->recv_task);
2255  if (NULL != c->warn_task)
2256  {
2258  c->warn_task = NULL;
2259  }
2261 }
2262 
2263 
2272 void
2274 {
2275  GNUNET_break (NULL != c->warn_task);
2276  if (NULL != c->warn_task)
2277  {
2279  c->warn_task = NULL;
2280  }
2281 }
2282 
2283 
2289 static void
2291 {
2292  struct GNUNET_SERVICE_Client *c = cls;
2293  struct GNUNET_SERVICE_Handle *sh = c->sh;
2294 
2295  c->drop_task = NULL;
2296  GNUNET_assert (NULL == c->send_task);
2297  GNUNET_assert (NULL == c->recv_task);
2298  GNUNET_assert (NULL == c->warn_task);
2299  GNUNET_MST_destroy (c->mst);
2300  GNUNET_MQ_destroy (c->mq);
2301  if (GNUNET_NO == c->persist)
2302  {
2304  if ((0 != (SUSPEND_STATE_EMFILE & sh->suspend_state)) &&
2305  (0 == (SUSPEND_STATE_SHUTDOWN & sh->suspend_state)))
2307  }
2308  else
2309  {
2311  }
2312  GNUNET_free (c);
2313  if ((0 != (SUSPEND_STATE_SHUTDOWN & sh->suspend_state)) &&
2316 }
2317 
2318 
2329 void
2331 {
2332  struct GNUNET_SERVICE_Handle *sh = c->sh;
2333 
2335  "Client dropped: %p (MQ: %p)\n",
2336  c,
2337  c->mq);
2338 #if EXECINFO
2339  {
2340  void *backtrace_array[MAX_TRACE_DEPTH];
2341  int num_backtrace_strings = backtrace (backtrace_array, MAX_TRACE_DEPTH);
2342  char **backtrace_strings =
2343  backtrace_symbols (backtrace_array, t->num_backtrace_strings);
2344  for (unsigned int i = 0; i < num_backtrace_strings; i++)
2346  "client drop trace %u: %s\n",
2347  i,
2348  backtrace_strings[i]);
2349  }
2350 #endif
2351  if (NULL != c->drop_task)
2352  {
2353  /* asked to drop twice! */
2354  GNUNET_assert (0);
2355  return;
2356  }
2357  GNUNET_CONTAINER_DLL_remove (sh->clients_head,
2358  sh->clients_tail,
2359  c);
2360  if (NULL != sh->disconnect_cb)
2361  sh->disconnect_cb (sh->cb_cls,
2362  c,
2363  c->user_context);
2364  if (NULL != c->warn_task)
2365  {
2367  c->warn_task = NULL;
2368  }
2369  if (NULL != c->recv_task)
2370  {
2372  c->recv_task = NULL;
2373  }
2374  if (NULL != c->send_task)
2375  {
2377  c->send_task = NULL;
2378  }
2380 }
2381 
2382 
2388 void
2390 {
2391  struct GNUNET_SERVICE_Client *client;
2392 
2393  if (0 == (sh->suspend_state & SUSPEND_STATE_SHUTDOWN))
2395  while (NULL != (client = sh->clients_head))
2396  GNUNET_SERVICE_client_drop (client);
2397 }
2398 
2399 
2412 void
2414 {
2415  c->is_monitor = GNUNET_YES;
2416  if (((0 != (SUSPEND_STATE_SHUTDOWN & c->sh->suspend_state)) &&
2419 }
2420 
2421 
2429 void
2431 {
2432  c->persist = GNUNET_YES;
2433 }
2434 
2435 
2442 struct GNUNET_MQ_Handle *
2444 {
2445  return c->mq;
2446 }
2447 
2448 
2449 /* 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_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 const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration we are using.
Definition: gnunet-abd.c:36
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static int list
Set if we should print a list of currently running services.
Definition: gnunet-arm.c:69
static int res
static struct SolverHandle * sh
static char * cfg_filename
Name of the configuration file.
static uint16_t port
Port number.
Definition: gnunet-bcd.c:147
static struct GNUNET_CADET_MessageHandler handlers[]
Handlers, for diverse services.
static struct in_addr dummy
Target "dummy" address of the packet we pretend to respond to.
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 int ok
Return value from 'main' (0 == success)
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 char * hostname
Our hostname; we give this to all the peers we start.
static char buf[2048]
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.
struct GNUNET_CONFIGURATION_Handle * GNUNET_CONFIGURATION_create(void)
Create a new configuration object.
void GNUNET_CONFIGURATION_destroy(struct GNUNET_CONFIGURATION_Handle *cfg)
Destroy configuration object.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_load(struct GNUNET_CONFIGURATION_Handle *cfg, const char *filename)
Load configuration.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_have_value(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Test if we have a value for a particular option.
enum GNUNET_GenericReturnValue GNUNET_DISK_file_test(const char *fil)
Check that fil corresponds to a filename (of a file that exists and that is not a directory).
Definition: disk.c: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
int GNUNET_log_setup(const char *comp, const char *loglevel, const char *logfile)
Setup logging.
#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.
#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...
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_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
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
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
#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:62
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
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_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!
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition: network.c:508
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
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
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
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
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
const struct GNUNET_OS_ProjectData * GNUNET_OS_project_data_get(void)
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,...
@ 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
void GNUNET_SCHEDULER_run(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Initialize and run scheduler.
Definition: scheduler.c:720
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:1299
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:1577
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:1506
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:1334
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:975
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:1272
int 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
int 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_MST_destroy(struct GNUNET_MessageStreamTokenizer *mst)
Destroys a tokenizer.
Definition: mst.c:404
struct GNUNET_MessageStreamTokenizer * GNUNET_MST_create(GNUNET_MessageTokenizerCallback cb, void *cb_cls)
Create a message stream tokenizer.
Definition: mst.c:86
void GNUNET_SERVICE_suspend(struct GNUNET_SERVICE_Handle *sh)
Suspend accepting connections from the listen socket temporarily.
Definition: service.c:2188
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:2389
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:2413
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_ConnectHandler)(void *cls, struct GNUNET_SERVICE_Client *c, struct GNUNET_MQ_Handle *mq)
Callback to be called when a client connects to the service.
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition: service.c:2330
struct GNUNET_MQ_Handle * GNUNET_SERVICE_client_get_mq(struct GNUNET_SERVICE_Client *c)
Obtain the message queue of c.
Definition: service.c:2443
void GNUNET_SERVICE_client_persist(struct GNUNET_SERVICE_Client *c)
Set the persist option on this client.
Definition: service.c:2430
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:2273
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_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_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2249
void GNUNET_SERVICE_resume(struct GNUNET_SERVICE_Handle *sh)
Resume accepting connections from the listen socket.
Definition: service.c:2200
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:1968
@ 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:1471
struct GNUNET_STRINGS_IPv4NetworkPolicy * GNUNET_STRINGS_parse_ipv4_policy(const char *routeListX)
Parse an IPv4 network policy.
Definition: strings.c:1290
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
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
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:569
#define DIR_SEPARATOR_STR
Definition: platform.h:165
#define _(String)
GNU gettext support macro.
Definition: platform.h:177
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 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 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:2213
static int set_user_id(struct GNUNET_SERVICE_Handle *sh)
Set user ID.
Definition: service.c:1628
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
#define LOG_STRERROR_FILE(kind, syscall, filename)
Definition: service.c:46
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
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:2290
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
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
#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
void GNUNET_SPEEDUP_stop_()
Stop tasks that modify clock behavior.
Definition: speedup.c:100
Definition of a command line option.
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.
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