GNUnet  0.17.5
Data Structures | Macros | Enumerations | Functions
service.c File Reference

functions related to starting services More...

#include "platform.h"
#include "gnunet_util_lib.h"
#include "gnunet_protocols.h"
#include "gnunet_constants.h"
#include "gnunet_resolver_service.h"
#include "speedup.h"
Include dependency graph for service.c:

Go to the source code of this file.

Data Structures

struct  ServiceListenContext
 Information the service tracks per listen operation. More...
 
struct  GNUNET_SERVICE_Handle
 Handle to a service. More...
 
struct  GNUNET_SERVICE_Client
 Handle to a client that is connected to a service. More...
 

Macros

#define LOG(kind, ...)   GNUNET_log_from (kind, "util-service", __VA_ARGS__)
 
#define LOG_STRERROR(kind, syscall)    GNUNET_log_from_strerror (kind, "util-service", syscall)
 
#define LOG_STRERROR_FILE(kind, syscall, filename)    GNUNET_log_from_strerror_file (kind, "util-service", syscall, filename)
 

Enumerations

enum  SuspendReason {
  SUSPEND_STATE_NONE = 0 , SUSPEND_STATE_APP = 1 , SUSPEND_STATE_EMFILE = 2 , SUSPEND_STATE_APP_AND_EMFILE = 3 ,
  SUSPEND_STATE_SHUTDOWN = 4
}
 Reasons why we might be suspended. More...
 

Functions

static int have_non_monitor_clients (struct GNUNET_SERVICE_Handle *sh)
 Check if any of the clients we have left are unrelated to monitoring. More...
 
static void do_suspend (struct GNUNET_SERVICE_Handle *sh, enum SuspendReason sr)
 Suspend accepting connections from the listen socket temporarily. More...
 
static void service_shutdown (void *cls)
 Shutdown task triggered when a service should be terminated. More...
 
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. More...
 
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. More...
 
static void do_send (void *cls)
 Task run when we are ready to transmit data to the client. More...
 
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. More...
 
static void service_mq_cancel (struct GNUNET_MQ_Handle *mq, void *impl_state)
 Implementation function that cancels the currently sent message. More...
 
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 creation of the message queue. More...
 
static void warn_no_client_continue (void *cls)
 Task run to warn about missing calls to GNUNET_SERVICE_client_continue(). More...
 
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 a client. More...
 
static void service_client_recv (void *cls)
 A client sent us data. More...
 
static void start_client (struct GNUNET_SERVICE_Handle *sh, struct GNUNET_NETWORK_Handle *csock)
 We have successfully accepted a connection from a client. More...
 
static void accept_client (void *cls)
 We have a client. More...
 
static void do_resume (struct GNUNET_SERVICE_Handle *sh, enum SuspendReason sr)
 Resume accepting connections from the listen socket. More...
 
static void service_main (void *cls)
 First task run by any service. More...
 
static int process_acl4 (struct GNUNET_STRINGS_IPv4NetworkPolicy **ret, struct GNUNET_SERVICE_Handle *sh, const char *option)
 Parse an IPv4 access control list. More...
 
static int process_acl6 (struct GNUNET_STRINGS_IPv6NetworkPolicy **ret, struct GNUNET_SERVICE_Handle *sh, const char *option)
 Parse an IPv6 access control list. More...
 
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). More...
 
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. More...
 
static struct GNUNET_NETWORK_Handleopen_listen_socket (const struct sockaddr *server_addr, socklen_t socklen)
 Create and initialize a listen socket for the server. More...
 
static int setup_service (struct GNUNET_SERVICE_Handle *sh)
 Setup service handle. More...
 
static char * get_user_name (struct GNUNET_SERVICE_Handle *sh)
 Get the name of the user that'll be used to provide the service. More...
 
static int set_user_id (struct GNUNET_SERVICE_Handle *sh)
 Set user ID. More...
 
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. More...
 
static void pid_file_delete (struct GNUNET_SERVICE_Handle *sh)
 Delete the PID file that was created by our parent. More...
 
static int detach_terminal (struct GNUNET_SERVICE_Handle *sh)
 Detach from terminal. More...
 
static void teardown_service (struct GNUNET_SERVICE_Handle *sh)
 Tear down the service, closing the listen sockets and freeing the ACLs. More...
 
static void return_agpl (void *cls, const struct GNUNET_MessageHeader *msg)
 Function to return link to AGPL source upon request. More...
 
struct GNUNET_SERVICE_HandleGNUNET_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. More...
 
void GNUNET_SERVICE_stop (struct GNUNET_SERVICE_Handle *srv)
 Stops a service that was started with GNUNET_SERVICE_start(). More...
 
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. More...
 
void GNUNET_SERVICE_suspend (struct GNUNET_SERVICE_Handle *sh)
 Suspend accepting connections from the listen socket temporarily. More...
 
void GNUNET_SERVICE_resume (struct GNUNET_SERVICE_Handle *sh)
 Resume accepting connections from the listen socket. More...
 
static void resume_client_receive (void *cls)
 Task run to resume receiving data from the client after the client called GNUNET_SERVICE_client_continue(). More...
 
void GNUNET_SERVICE_client_continue (struct GNUNET_SERVICE_Client *c)
 Continue receiving further messages from the given client. More...
 
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. More...
 
static void finish_client_drop (void *cls)
 Asynchronously finish dropping the client. More...
 
void GNUNET_SERVICE_client_drop (struct GNUNET_SERVICE_Client *c)
 Ask the server to disconnect from the given client. More...
 
void GNUNET_SERVICE_shutdown (struct GNUNET_SERVICE_Handle *sh)
 Explicitly stops the service. More...
 
void GNUNET_SERVICE_client_mark_monitor (struct GNUNET_SERVICE_Client *c)
 Set the 'monitor' flag on this client. More...
 
void GNUNET_SERVICE_client_persist (struct GNUNET_SERVICE_Client *c)
 Set the persist option on this client. More...
 
struct GNUNET_MQ_HandleGNUNET_SERVICE_client_get_mq (struct GNUNET_SERVICE_Client *c)
 Obtain the message queue of c. More...
 

Detailed Description

functions related to starting services

functions related to starting services (redesign)

Author
Christian Grothoff
Christian Grothoff
Florian Dold

Definition in file service.c.

Macro Definition Documentation

◆ LOG

#define LOG (   kind,
  ... 
)    GNUNET_log_from (kind, "util-service", __VA_ARGS__)

Definition at line 40 of file service.c.

◆ LOG_STRERROR

#define LOG_STRERROR (   kind,
  syscall 
)     GNUNET_log_from_strerror (kind, "util-service", syscall)

Definition at line 42 of file service.c.

◆ LOG_STRERROR_FILE

#define LOG_STRERROR_FILE (   kind,
  syscall,
  filename 
)     GNUNET_log_from_strerror_file (kind, "util-service", syscall, filename)

Definition at line 45 of file service.c.

Enumeration Type Documentation

◆ SuspendReason

Reasons why we might be suspended.

Enumerator
SUSPEND_STATE_NONE 

We are running normally.

SUSPEND_STATE_APP 

Application requested it.

SUSPEND_STATE_EMFILE 

OS ran out of file descriptors.

SUSPEND_STATE_APP_AND_EMFILE 

Both reasons, APP and EMFILE apply.

SUSPEND_STATE_SHUTDOWN 

Suspension because service was permanently shutdown.

Definition at line 84 of file service.c.

85 {
90 
95 
100 
105 
110 };
@ 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

Function Documentation

◆ have_non_monitor_clients()

static int have_non_monitor_clients ( struct GNUNET_SERVICE_Handle sh)
static

Check if any of the clients we have left are unrelated to monitoring.

Parameters
shservice to check clients for
Returns
GNUNET_YES if we have non-monitoring clients left

Definition at line 361 of file service.c.

362 {
363  for (struct GNUNET_SERVICE_Client *client = sh->clients_head; NULL != client;
364  client = client->next)
365  {
366  if (client->is_monitor)
367  continue;
368  return GNUNET_YES;
369  }
370  return GNUNET_NO;
371 }
static struct SolverHandle * sh
@ GNUNET_YES
@ GNUNET_NO
Definition: gnunet_common.h:98
Handle to a client that is connected to a service.
Definition: service.c:251

References GNUNET_NO, GNUNET_YES, and sh.

Referenced by finish_client_drop(), GNUNET_SERVICE_client_mark_monitor(), and service_shutdown().

Here is the caller graph for this function:

◆ do_suspend()

static void do_suspend ( struct GNUNET_SERVICE_Handle sh,
enum SuspendReason  sr 
)
static

Suspend accepting connections from the listen socket temporarily.

Resume activity using do_resume.

Parameters
shservice to stop accepting connections.
srreason for suspending accepting connections

Definition at line 382 of file service.c.

383 {
384  struct ServiceListenContext *slc;
385 
386  GNUNET_assert (0 == (sh->suspend_state & sr));
387  sh->suspend_state |= sr;
388  for (slc = sh->slc_head; NULL != slc; slc = slc->next)
389  {
390  if (NULL != slc->listen_task)
391  {
393  slc->listen_task = NULL;
394  }
395  }
396 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:957
Information the service tracks per listen operation.
Definition: service.c:53
struct ServiceListenContext * next
Kept in a DLL.
Definition: service.c:57
struct GNUNET_SCHEDULER_Task * listen_task
Task scheduled to do the listening.
Definition: service.c:77

References GNUNET_assert, GNUNET_SCHEDULER_cancel(), ServiceListenContext::listen_task, ServiceListenContext::next, and sh.

Referenced by accept_client(), GNUNET_SERVICE_shutdown(), GNUNET_SERVICE_suspend(), and service_shutdown().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ service_shutdown()

static void service_shutdown ( void *  cls)
static

Shutdown task triggered when a service should be terminated.

This considers active clients and the service options to see how this specific service is to be terminated, and depending on this proceeds with the shutdown logic.

Parameters
clsour struct GNUNET_SERVICE_Handle

Definition at line 408 of file service.c.

409 {
410  struct GNUNET_SERVICE_Handle *sh = cls;
411 
412  switch (sh->options & GNUNET_SERVICE_OPTION_SHUTDOWN_BITMASK)
413  {
416  break;
418  /* This task should never be run if we are using
419  the manual shutdown. */
420  GNUNET_assert (0);
421  break;
423  if (0 == (sh->suspend_state & SUSPEND_STATE_SHUTDOWN))
427  break;
428  }
429 }
void GNUNET_SERVICE_shutdown(struct GNUNET_SERVICE_Handle *sh)
Explicitly stops the service.
Definition: service.c:2388
@ GNUNET_SERVICE_OPTION_MANUAL_SHUTDOWN
Do not trigger server shutdown on signal at all; instead, allow for the user to terminate the server ...
@ GNUNET_SERVICE_OPTION_SHUTDOWN_BITMASK
Bitmask over the shutdown options.
@ GNUNET_SERVICE_OPTION_NONE
Use defaults.
@ GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN
Trigger a SOFT server shutdown on signals, allowing active non-monitor clients to complete their tran...
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:361
static void do_suspend(struct GNUNET_SERVICE_Handle *sh, enum SuspendReason sr)
Suspend accepting connections from the listen socket temporarily.
Definition: service.c:382
Handle to a service.
Definition: service.c:117

References do_suspend(), GNUNET_assert, GNUNET_NO, GNUNET_SERVICE_OPTION_MANUAL_SHUTDOWN, GNUNET_SERVICE_OPTION_NONE, GNUNET_SERVICE_OPTION_SHUTDOWN_BITMASK, GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN, GNUNET_SERVICE_shutdown(), have_non_monitor_clients(), sh, and SUSPEND_STATE_SHUTDOWN.

Referenced by service_main().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_ipv4_listed()

static int check_ipv4_listed ( const struct GNUNET_STRINGS_IPv4NetworkPolicy list,
const struct in_addr *  add 
)
static

Check if the given IP address is in the list of IP addresses.

Parameters
lista list of networks
addthe IP to check (in network byte order)
Returns
GNUNET_NO if the IP is not in the list, GNUNET_YES if it it is

Definition at line 440 of file service.c.

442 {
443  unsigned int i;
444 
445  if (NULL == list)
446  return GNUNET_NO;
447  i = 0;
448  while ((0 != list[i].network.s_addr) || (0 != list[i].netmask.s_addr))
449  {
450  if ((add->s_addr & list[i].netmask.s_addr) ==
451  (list[i].network.s_addr & list[i].netmask.s_addr))
452  return GNUNET_YES;
453  i++;
454  }
455  return GNUNET_NO;
456 }
static int list
Set if we should print a list of currently running services.
Definition: gnunet-arm.c:69
static int add
Desired action is to add a record.

References add, GNUNET_NO, GNUNET_YES, and list.

Referenced by accept_client().

Here is the caller graph for this function:

◆ check_ipv6_listed()

static int check_ipv6_listed ( const struct GNUNET_STRINGS_IPv6NetworkPolicy list,
const struct in6_addr *  ip 
)
static

Check if the given IP address is in the list of IP addresses.

Parameters
lista list of networks
ipthe IP to check (in network byte order)
Returns
GNUNET_NO if the IP is not in the list, GNUNET_YES if it it is

Definition at line 467 of file service.c.

469 {
470  unsigned int i;
471 
472  if (NULL == list)
473  return GNUNET_NO;
474  i = 0;
475 NEXT:
476  while (GNUNET_NO == GNUNET_is_zero (&list[i].network))
477  {
478  for (unsigned int j = 0; j < sizeof(struct in6_addr) / sizeof(int); j++)
479  if (((((int *) ip)[j] & ((int *) &list[i].netmask)[j])) !=
480  (((int *) &list[i].network)[j] & ((int *) &list[i].netmask)[j]))
481  {
482  i++;
483  goto NEXT;
484  }
485  return GNUNET_YES;
486  }
487  return GNUNET_NO;
488 }
#define GNUNET_is_zero(a)
Check that memory in a is all zeros.

References GNUNET_is_zero, GNUNET_NO, GNUNET_YES, consensus-simulation::int, and list.

Referenced by accept_client().

Here is the caller graph for this function:

◆ do_send()

static void do_send ( void *  cls)
static

Task run when we are ready to transmit data to the client.

Parameters
clsthe struct GNUNET_SERVICE_Client * to send to

Definition at line 498 of file service.c.

499 {
500  struct GNUNET_SERVICE_Client *client = cls;
501  ssize_t ret;
502  size_t left;
503  const char *buf;
504 
506  "service: sending message with type %u\n",
507  ntohs (client->msg->type));
508  client->send_task = NULL;
509  buf = (const char *) client->msg;
510  left = ntohs (client->msg->size) - client->msg_pos;
512  &buf[client->msg_pos],
513  left);
514  GNUNET_assert (ret <= (ssize_t) left);
515  if (0 == ret)
516  {
517  LOG (GNUNET_ERROR_TYPE_DEBUG, "no data send");
519  return;
520  }
521  if (-1 == ret)
522  {
523  if ((EAGAIN == errno) || (EINTR == errno))
524  {
525  /* ignore */
526  ret = 0;
527  }
528  else
529  {
530  if (EPIPE != errno)
533  "socket send returned with error code %i",
534  errno);
536  return;
537  }
538  }
539  if (0 == client->msg_pos)
540  {
542  }
543  client->msg_pos += ret;
544  if (left > (size_t) ret)
545  {
546  GNUNET_assert (NULL == client->drop_task);
547  client->send_task =
549  client->sock,
550  &do_send,
551  client);
552  return;
553  }
555 }
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static char buf[2048]
#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...
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_DEBUG
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:267
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:423
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:446
@ GNUNET_MQ_ERROR_WRITE
FIXME: document!
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:760
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:1573
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
static void do_send(void *cls)
Task run when we are ready to transmit data to the client.
Definition: service.c:498
#define LOG(kind,...)
Definition: service.c:40
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.
size_t msg_pos
Current position in msg at which we are transmitting.
Definition: service.c:325
struct GNUNET_SCHEDULER_Task * send_task
Task that transmit data to the client.
Definition: service.c:303
struct GNUNET_SCHEDULER_Task * drop_task
Task run to finish dropping the client after the stack has properly unwound.
Definition: service.c:292
struct GNUNET_NETWORK_Handle * sock
Socket of this client.
Definition: service.c:270
const struct GNUNET_MessageHeader * msg
Pointer to the message to be transmitted by send_task.
Definition: service.c:308
struct GNUNET_MQ_Handle * mq
Message queue for the client.
Definition: service.c:275

References buf, GNUNET_SERVICE_Client::drop_task, GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_log_strerror, GNUNET_MQ_ERROR_WRITE, GNUNET_MQ_impl_send_continue(), GNUNET_MQ_impl_send_in_flight(), GNUNET_MQ_inject_error(), GNUNET_NETWORK_socket_send(), GNUNET_SCHEDULER_add_write_net(), GNUNET_TIME_UNIT_FOREVER_REL, LOG, GNUNET_SERVICE_Client::mq, GNUNET_SERVICE_Client::msg, GNUNET_SERVICE_Client::msg_pos, ret, GNUNET_SERVICE_Client::send_task, GNUNET_MessageHeader::size, GNUNET_SERVICE_Client::sock, and GNUNET_MessageHeader::type.

Referenced by service_mq_send().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ service_mq_send()

static void service_mq_send ( struct GNUNET_MQ_Handle mq,
const struct GNUNET_MessageHeader msg,
void *  impl_state 
)
static

Signature of functions implementing the sending functionality of a message queue.

Parameters
mqthe message queue
msgthe message to send
impl_stateour struct GNUNET_SERVICE_Client *

Definition at line 567 of file service.c.

570 {
571  struct GNUNET_SERVICE_Client *client = impl_state;
572 
573  (void) mq;
574  if (NULL != client->drop_task)
575  return; /* we're going down right now, do not try to send */
576  GNUNET_assert (NULL == client->send_task);
578  "Sending message of type %u and size %u to client\n",
579  ntohs (msg->type),
580  ntohs (msg->size));
581  client->msg = msg;
582  client->msg_pos = 0;
584  client);
585 }
struct GNUNET_MQ_Handle * mq
Definition: 003.c:5
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
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:1281

References do_send(), GNUNET_SERVICE_Client::drop_task, GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_SCHEDULER_add_now(), LOG, mq, msg, GNUNET_SERVICE_Client::msg, GNUNET_SERVICE_Client::msg_pos, GNUNET_SERVICE_Client::send_task, GNUNET_MessageHeader::size, and GNUNET_MessageHeader::type.

Referenced by start_client().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ service_mq_cancel()

static void service_mq_cancel ( struct GNUNET_MQ_Handle mq,
void *  impl_state 
)
static

Implementation function that cancels the currently sent message.

Parameters
mqmessage queue
impl_statestate specific to the implementation

Definition at line 595 of file service.c.

596 {
597  struct GNUNET_SERVICE_Client *client = impl_state;
598 
599  (void) mq;
600  GNUNET_assert (0 == client->msg_pos);
601  client->msg = NULL;
603  client->send_task = NULL;
604 }

References GNUNET_assert, GNUNET_SCHEDULER_cancel(), mq, GNUNET_SERVICE_Client::msg, GNUNET_SERVICE_Client::msg_pos, and GNUNET_SERVICE_Client::send_task.

Referenced by start_client().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ service_mq_error_handler()

static void service_mq_error_handler ( void *  cls,
enum GNUNET_MQ_Error  error 
)
static

Generic error handler, called with the appropriate error code and the same closure specified at the creation of the message queue.

Not every message queue implementation supports an error handler.

Parameters
clsclosure with our struct GNUNET_SERVICE_Client
errorerror code

Definition at line 617 of file service.c.

618 {
619  struct GNUNET_SERVICE_Client *client = cls;
620  struct GNUNET_SERVICE_Handle *sh = client->sh;
621 
622  if ((GNUNET_MQ_ERROR_NO_MATCH == error) && (GNUNET_NO == sh->require_found))
623  {
625  "No handler for message of type %u found\n",
626  (unsigned int) client->warn_type);
628  return; /* ignore error */
629  }
631 }
#define GNUNET_log(kind,...)
@ GNUNET_MQ_ERROR_NO_MATCH
We received a message for which we have no matching handler.
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition: service.c:2329
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2248
uint16_t warn_type
Type of last message processed (for warn_no_receive_done).
Definition: service.c:349
struct GNUNET_SERVICE_Handle * sh
Service that this client belongs to.
Definition: service.c:265

References GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_MQ_ERROR_NO_MATCH, GNUNET_NO, GNUNET_SERVICE_client_continue(), GNUNET_SERVICE_client_drop(), sh, GNUNET_SERVICE_Client::sh, and GNUNET_SERVICE_Client::warn_type.

Referenced by start_client().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ warn_no_client_continue()

static void warn_no_client_continue ( void *  cls)
static

Task run to warn about missing calls to GNUNET_SERVICE_client_continue().

Parameters
clsour struct GNUNET_SERVICE_Client * to process more requests from

Definition at line 640 of file service.c.

641 {
642  struct GNUNET_SERVICE_Client *client = cls;
643 
644  GNUNET_break (
645  0 !=
646  client->warn_type); /* type should never be 0 here, as we don't use 0 */
649  client);
650  LOG (
652  _ (
653  "Processing code for message of type %u did not call `GNUNET_SERVICE_client_continue' after %s\n"),
654  (unsigned int) client->warn_type,
656  client->warn_start),
657  GNUNET_YES));
658 }
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
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:1254
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:435
#define GNUNET_TIME_UNIT_MINUTES
One minute.
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
#define _(String)
GNU gettext support macro.
Definition: platform.h:177
static void warn_no_client_continue(void *cls)
Task run to warn about missing calls to GNUNET_SERVICE_client_continue().
Definition: service.c:640
struct GNUNET_TIME_Absolute warn_start
Time when we last gave a message from this client to the application.
Definition: service.c:320
struct GNUNET_SCHEDULER_Task * warn_task
Task that warns about missing calls to GNUNET_SERVICE_client_continue().
Definition: service.c:286

References _, GNUNET_break, GNUNET_ERROR_TYPE_WARNING, GNUNET_SCHEDULER_add_delayed(), GNUNET_STRINGS_relative_time_to_string(), GNUNET_TIME_absolute_get_duration(), GNUNET_TIME_UNIT_MINUTES, GNUNET_YES, LOG, GNUNET_SERVICE_Client::warn_start, GNUNET_SERVICE_Client::warn_task, and GNUNET_SERVICE_Client::warn_type.

Referenced by service_client_mst_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ service_client_mst_cb()

static int service_client_mst_cb ( void *  cls,
const struct GNUNET_MessageHeader message 
)
static

Functions with this signature are called whenever a complete message is received by the tokenizer for a client.

Do not call GNUNET_MST_destroy() from within the scope of this callback.

Parameters
clsclosure with the struct GNUNET_SERVICE_Client *
messagethe actual message
Returns
GNUNET_OK on success, GNUNET_SYSERR if the client was dropped

Definition at line 673 of file service.c.

675 {
676  struct GNUNET_SERVICE_Client *client = cls;
677 
679  "Received message of type %u and size %u from client\n",
680  ntohs (message->type),
681  ntohs (message->size));
683  client->needs_continue = GNUNET_YES;
684  client->warn_type = ntohs (message->type);
686  GNUNET_assert (NULL == client->warn_task);
689  client);
690  GNUNET_MQ_inject_message (client->mq, message);
691  if (NULL != client->drop_task)
692  return GNUNET_SYSERR;
693  return GNUNET_OK;
694 }
@ GNUNET_OK
Definition: gnunet_common.h:99
@ GNUNET_SYSERR
Definition: gnunet_common.h:97
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:186
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:110
int needs_continue
Are we waiting for the application to call GNUNET_SERVICE_client_continue()?
Definition: service.c:344

References GNUNET_SERVICE_Client::drop_task, GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_MQ_inject_message(), GNUNET_NO, GNUNET_OK, GNUNET_SCHEDULER_add_delayed(), GNUNET_SYSERR, GNUNET_TIME_absolute_get(), GNUNET_TIME_UNIT_MINUTES, GNUNET_YES, LOG, GNUNET_SERVICE_Client::mq, GNUNET_SERVICE_Client::needs_continue, GNUNET_MessageHeader::size, GNUNET_MessageHeader::type, warn_no_client_continue(), GNUNET_SERVICE_Client::warn_start, GNUNET_SERVICE_Client::warn_task, and GNUNET_SERVICE_Client::warn_type.

Referenced by start_client().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ service_client_recv()

static void service_client_recv ( void *  cls)
static

A client sent us data.

Receive and process it. If we are done, reschedule this task.

Parameters
clsthe struct GNUNET_SERVICE_Client that sent us data.

Definition at line 704 of file service.c.

705 {
706  struct GNUNET_SERVICE_Client *client = cls;
708 
709  client->recv_task = NULL;
710  ret = GNUNET_MST_read (client->mst,
711  client->sock,
712  GNUNET_NO,
713  GNUNET_YES);
714  if (GNUNET_SYSERR == ret)
715  {
716  /* client closed connection (or IO error) */
717  if (NULL == client->drop_task)
718  {
721  }
722  return;
723  }
724  if (GNUNET_NO == ret)
725  return; /* more messages in buffer, wait for application
726  to be done processing */
728  if (GNUNET_YES == client->needs_continue)
729  return;
730  if (NULL != client->recv_task)
731  return;
732  /* MST needs more data, re-schedule read job */
733  client->recv_task =
735  client->sock,
737  client);
738 }
GNUNET_GenericReturnValue
Named constants for return values.
Definition: gnunet_common.h:96
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:1502
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:352
static void service_client_recv(void *cls)
A client sent us data.
Definition: service.c:704
struct GNUNET_SCHEDULER_Task * recv_task
Task that receives data from the client to pass it to the handlers.
Definition: service.c:298
struct GNUNET_MessageStreamTokenizer * mst
Tokenizer we use for processing incoming data.
Definition: service.c:280

References GNUNET_SERVICE_Client::drop_task, GNUNET_assert, GNUNET_MST_read(), GNUNET_NO, GNUNET_OK, GNUNET_SCHEDULER_add_read_net(), GNUNET_SERVICE_client_drop(), GNUNET_SYSERR, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, GNUNET_SERVICE_Client::mst, GNUNET_SERVICE_Client::needs_continue, GNUNET_SERVICE_Client::recv_task, ret, and GNUNET_SERVICE_Client::sock.

Referenced by resume_client_receive(), and start_client().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ start_client()

static void start_client ( struct GNUNET_SERVICE_Handle sh,
struct GNUNET_NETWORK_Handle csock 
)
static

We have successfully accepted a connection from a client.

Now setup the client (with the scheduler) and tell the application.

Parameters
shservice that accepted the client
socksocket associated with the client

Definition at line 749 of file service.c.

751 {
752  struct GNUNET_SERVICE_Client *client;
753 
754  client = GNUNET_new (struct GNUNET_SERVICE_Client);
755  GNUNET_CONTAINER_DLL_insert (sh->clients_head, sh->clients_tail, client);
756  client->sh = sh;
757  client->sock = csock;
759  NULL,
761  client,
762  sh->handlers,
764  client);
765  client->mst = GNUNET_MST_create (&service_client_mst_cb, client);
766  if (NULL != sh->connect_cb)
767  client->user_context = sh->connect_cb (sh->cb_cls, client, client->mq);
769  client->recv_task =
771  client->sock,
773  client);
774 }
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
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:467
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:491
struct GNUNET_MessageStreamTokenizer * GNUNET_MST_create(GNUNET_MessageTokenizerCallback cb, void *cb_cls)
Create a message stream tokenizer.
Definition: mst.c:85
static void service_mq_cancel(struct GNUNET_MQ_Handle *mq, void *impl_state)
Implementation function that cancels the currently sent message.
Definition: service.c:595
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:567
static int service_client_mst_cb(void *cls, const struct GNUNET_MessageHeader *message)
Functions with this signature are called whenever a complete message is received by the tokenizer for...
Definition: service.c:673
static 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:617
void * user_context
User context value, value returned from the connect callback.
Definition: service.c:314

References GNUNET_CONTAINER_DLL_insert, GNUNET_MQ_queue_for_callbacks(), GNUNET_MQ_set_handlers_closure(), GNUNET_MST_create(), GNUNET_new, GNUNET_SCHEDULER_add_read_net(), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_SERVICE_Client::mq, GNUNET_SERVICE_Client::mst, GNUNET_SERVICE_Client::recv_task, service_client_mst_cb(), service_client_recv(), service_mq_cancel(), service_mq_error_handler(), service_mq_send(), sh, GNUNET_SERVICE_Client::sh, GNUNET_SERVICE_Client::sock, and GNUNET_SERVICE_Client::user_context.

Referenced by accept_client().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ accept_client()

static void accept_client ( void *  cls)
static

We have a client.

Accept the incoming socket(s) (and reschedule the listen task).

Parameters
clsthe struct ServiceListenContext of the ready listen socket

Definition at line 784 of file service.c.

785 {
786  struct ServiceListenContext *slc = cls;
787  struct GNUNET_SERVICE_Handle *sh = slc->sh;
788 
789  slc->listen_task = NULL;
790  while (1)
791  {
792  struct GNUNET_NETWORK_Handle *sock;
793  const struct sockaddr_in *v4;
794  const struct sockaddr_in6 *v6;
795  struct sockaddr_storage sa;
796  socklen_t addrlen;
797  int ok;
798 
799  addrlen = sizeof(sa);
801  (struct sockaddr *) &sa,
802  &addrlen);
803  if (NULL == sock)
804  {
805  if (EMFILE == errno)
807  else if (EAGAIN != errno)
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, &v4->sin_addr))) &&
818  ((NULL == sh->v4_denied) ||
819  (! check_ipv4_listed (sh->v4_denied, &v4->sin_addr))));
820  break;
821 
822  case AF_INET6:
823  GNUNET_assert (addrlen == sizeof(struct sockaddr_in6));
824  v6 = (const struct sockaddr_in6 *) &sa;
825  ok = (((NULL == sh->v6_allowed) ||
826  (check_ipv6_listed (sh->v6_allowed, &v6->sin6_addr))) &&
827  ((NULL == sh->v6_denied) ||
828  (! check_ipv6_listed (sh->v6_denied, &v6->sin6_addr))));
829  break;
830 
831  case AF_UNIX:
832  ok = GNUNET_OK; /* controlled using file-system ACL now */
833  break;
834 
835  default:
837  _ ("Unknown address family %d\n"),
838  sa.ss_family);
839  return;
840  }
841  if (! ok)
842  {
844  "Service rejected incoming connection from %s due to policy.\n",
845  GNUNET_a2s ((const struct sockaddr *) &sa, addrlen));
847  continue;
848  }
850  "Service accepted incoming connection from %s.\n",
851  GNUNET_a2s ((const struct sockaddr *) &sa, addrlen));
852  start_client (slc->sh, sock);
853  }
854  if (0 != sh->suspend_state)
855  return;
856  slc->listen_task =
858  slc->listen_socket,
859  &accept_client,
860  slc);
861 }
static int ok
Return value from 'main' (0 == success)
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).
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
static void start_client(struct GNUNET_SERVICE_Handle *sh, struct GNUNET_NETWORK_Handle *csock)
We have successfully accepted a connection from a client.
Definition: service.c:749
static 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:467
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:440
static void accept_client(void *cls)
We have a client.
Definition: service.c:784
handle to a socket
Definition: network.c:53
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

References _, check_ipv4_listed(), check_ipv6_listed(), do_suspend(), GNUNET_a2s(), GNUNET_assert, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_log_strerror, GNUNET_NETWORK_socket_accept(), GNUNET_NETWORK_socket_close(), GNUNET_OK, GNUNET_SCHEDULER_add_read_net(), GNUNET_TIME_UNIT_FOREVER_REL, ServiceListenContext::listen_socket, ServiceListenContext::listen_task, LOG, ok, sh, ServiceListenContext::sh, start_client(), and SUSPEND_STATE_EMFILE.

Referenced by do_resume().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ do_resume()

static void do_resume ( struct GNUNET_SERVICE_Handle sh,
enum SuspendReason  sr 
)
static

Resume accepting connections from the listen socket.

Parameters
shservice to resume accepting connections.
srreason that is no longer causing the suspension, or SUSPEND_STATE_NONE on first startup

Definition at line 872 of file service.c.

873 {
874  struct ServiceListenContext *slc;
875 
876  GNUNET_assert ((SUSPEND_STATE_NONE == sr) || (0 != (sh->suspend_state & sr)));
877  sh->suspend_state -= sr;
878  if (SUSPEND_STATE_NONE != sh->suspend_state)
879  return;
880  for (slc = sh->slc_head; NULL != slc; slc = slc->next)
881  {
882  GNUNET_assert (NULL == slc->listen_task);
883  slc->listen_task =
885  slc->listen_socket,
886  &accept_client,
887  slc);
888  }
889 }

References accept_client(), GNUNET_assert, GNUNET_SCHEDULER_add_read_net(), GNUNET_TIME_UNIT_FOREVER_REL, ServiceListenContext::listen_socket, ServiceListenContext::listen_task, ServiceListenContext::next, sh, and SUSPEND_STATE_NONE.

Referenced by finish_client_drop(), GNUNET_SERVICE_resume(), GNUNET_SERVICE_start(), and service_main().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ service_main()

static void service_main ( void *  cls)
static

First task run by any service.

Initializes our shutdown task, starts the listening operation on our listen sockets and launches the custom logic of the application service.

Parameters
clsour struct GNUNET_SERVICE_Handle

Definition at line 900 of file service.c.

901 {
902  struct GNUNET_SERVICE_Handle *sh = cls;
903 
908 
909  if (-1 != sh->ready_confirm_fd)
910  {
911  GNUNET_break (1 == write (sh->ready_confirm_fd, ".", 1));
912  GNUNET_break (0 == close (sh->ready_confirm_fd));
913  sh->ready_confirm_fd = -1;
914  }
915 
916  if (NULL != sh->service_init_cb)
917  sh->service_init_cb (sh->cb_cls, sh->cfg, sh);
918 }
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:1316
static void do_resume(struct GNUNET_SERVICE_Handle *sh, enum SuspendReason sr)
Resume accepting connections from the listen socket.
Definition: service.c:872
static void service_shutdown(void *cls)
Shutdown task triggered when a service should be terminated.
Definition: service.c:408

References do_resume(), GNUNET_break, GNUNET_SCHEDULER_add_shutdown(), GNUNET_SERVICE_OPTION_MANUAL_SHUTDOWN, GNUNET_SERVICE_OPTION_SHUTDOWN_BITMASK, service_shutdown(), sh, and SUSPEND_STATE_NONE.

Referenced by GNUNET_SERVICE_run_().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ process_acl4()

static int process_acl4 ( struct GNUNET_STRINGS_IPv4NetworkPolicy **  ret,
struct GNUNET_SERVICE_Handle sh,
const char *  option 
)
static

Parse an IPv4 access control list.

Parameters
retlocation where to write the ACL (set)
shservice context to use to get the configuration
optionname of the ACL option to parse
Returns
GNUNET_SYSERR on parse error, GNUNET_OK on success (including no ACL configured)

Definition at line 931 of file service.c.

934 {
935  char *opt;
936 
937  if (! GNUNET_CONFIGURATION_have_value (sh->cfg, sh->service_name, option))
938  {
939  *ret = NULL;
940  return GNUNET_OK;
941  }
944  sh->service_name,
945  option,
946  &opt));
947  if (NULL == (*ret = GNUNET_STRINGS_parse_ipv4_policy (opt)))
948  {
950  _ ("Could not parse IPv4 network specification `%s' for `%s:%s'\n"),
951  opt,
952  sh->service_name,
953  option);
954  GNUNET_free (opt);
955  return GNUNET_SYSERR;
956  }
957  GNUNET_free (opt);
958  return GNUNET_OK;
959 }
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_have_value(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Test if we have a value for a particular option.
#define GNUNET_free(ptr)
Wrapper around free.
struct GNUNET_STRINGS_IPv4NetworkPolicy * GNUNET_STRINGS_parse_ipv4_policy(const char *routeListX)
Parse an IPv4 network policy.
Definition: strings.c:1291

References _, GNUNET_break, GNUNET_CONFIGURATION_get_value_string(), GNUNET_CONFIGURATION_have_value(), GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_OK, GNUNET_STRINGS_parse_ipv4_policy(), GNUNET_SYSERR, LOG, ret, and sh.

Referenced by setup_service().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ process_acl6()

static int process_acl6 ( struct GNUNET_STRINGS_IPv6NetworkPolicy **  ret,
struct GNUNET_SERVICE_Handle sh,
const char *  option 
)
static

Parse an IPv6 access control list.

Parameters
retlocation where to write the ACL (set)
shservice context to use to get the configuration
optionname of the ACL option to parse
Returns
GNUNET_SYSERR on parse error, GNUNET_OK on success (including no ACL configured)

Definition at line 972 of file service.c.

975 {
976  char *opt;
977 
978  if (! GNUNET_CONFIGURATION_have_value (sh->cfg, sh->service_name, option))
979  {
980  *ret = NULL;
981  return GNUNET_OK;
982  }
985  sh->service_name,
986  option,
987  &opt));
988  if (NULL == (*ret = GNUNET_STRINGS_parse_ipv6_policy (opt)))
989  {
991  _ ("Could not parse IPv6 network specification `%s' for `%s:%s'\n"),
992  opt,
993  sh->service_name,
994  option);
995  GNUNET_free (opt);
996  return GNUNET_SYSERR;
997  }
998  GNUNET_free (opt);
999  return GNUNET_OK;
1000 }
struct GNUNET_STRINGS_IPv6NetworkPolicy * GNUNET_STRINGS_parse_ipv6_policy(const char *routeListX)
Parse an IPv6 network policy.
Definition: strings.c:1472

References _, GNUNET_break, GNUNET_CONFIGURATION_get_value_string(), GNUNET_CONFIGURATION_have_value(), GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_OK, GNUNET_STRINGS_parse_ipv6_policy(), GNUNET_SYSERR, LOG, ret, and sh.

Referenced by setup_service().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ add_unixpath()

static void add_unixpath ( struct sockaddr **  saddrs,
socklen_t *  saddrlens,
const char *  unixpath 
)
static

Add the given UNIX domain path as an address to the list (as the first entry).

Parameters
saddrsarray to update
saddrlenswhere to store the address length
unixpathpath to add

Definition at line 1012 of file service.c.

1015 {
1016 #ifdef AF_UNIX
1017  struct sockaddr_un *un;
1018 
1019  un = GNUNET_new (struct sockaddr_un);
1020  un->sun_family = AF_UNIX;
1021  GNUNET_strlcpy (un->sun_path, unixpath, sizeof(un->sun_path));
1022 #if HAVE_SOCKADDR_UN_SUN_LEN
1023  un->sun_len = (u_char) sizeof(struct sockaddr_un);
1024 #endif
1025  *saddrs = (struct sockaddr *) un;
1026  *saddrlens = sizeof(struct sockaddr_un);
1027 #else
1028  /* this function should never be called
1029  * unless AF_UNIX is defined! */
1030  GNUNET_assert (0);
1031 #endif
1032 }
size_t GNUNET_strlcpy(char *dst, const char *src, size_t n)
Like strlcpy but portable.
Definition: strings.c:139

References GNUNET_assert, GNUNET_new, and GNUNET_strlcpy().

Referenced by get_server_addresses().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_server_addresses()

static int get_server_addresses ( const char *  service_name,
const struct GNUNET_CONFIGURATION_Handle cfg,
struct sockaddr ***  addrs,
socklen_t **  addr_lens 
)
static

Get the list of addresses that a server for the given service should bind to.

Parameters
service_namename of the service
cfgconfiguration (which specifies the addresses)
addrsset (call by reference) to an array of pointers to the addresses the server should bind to and listen on; the array will be NULL-terminated (on success)
addr_lensset (call by reference) to an array of the lengths of the respective struct sockaddr struct in the addrs array (on success)
Returns
number of addresses found on success, GNUNET_SYSERR if the configuration did not specify reasonable finding information or if it specified a hostname that could not be resolved; GNUNET_NO if the number of addresses configured is zero (in this case, *addrs and *addr_lens will be set to NULL).

Definition at line 1056 of file service.c.

1060 {
1061  int disablev6;
1062  struct GNUNET_NETWORK_Handle *desc;
1063  unsigned long long port;
1064  char *unixpath;
1065  struct addrinfo hints;
1066  struct addrinfo *res;
1067  struct addrinfo *pos;
1068  struct addrinfo *next;
1069  unsigned int i;
1070  int resi;
1071  int ret;
1072  struct sockaddr **saddrs;
1073  socklen_t *saddrlens;
1074  char *hostname;
1075 
1076  *addrs = NULL;
1077  *addr_lens = NULL;
1078  desc = NULL;
1079  disablev6 = GNUNET_NO;
1080  if ((GNUNET_NO == GNUNET_NETWORK_test_pf (PF_INET6)) ||
1081  (GNUNET_YES ==
1083  disablev6 = GNUNET_YES;
1084 
1085  port = 0;
1087  {
1089  service_name,
1090  "PORT",
1091  &port))
1092  {
1094  _ ("Require valid port number for service `%s' in configuration!\n"),
1095  service_name);
1096  }
1097  if (port > 65535)
1098  {
1100  _ ("Require valid port number for service `%s' in configuration!\n"),
1101  service_name);
1102  return GNUNET_SYSERR;
1103  }
1104  }
1105 
1107  {
1110  service_name,
1111  "BINDTO",
1112  &hostname));
1113  }
1114  else
1115  hostname = NULL;
1116 
1117  unixpath = NULL;
1118 #ifdef AF_UNIX
1119  if ((GNUNET_YES ==
1122  service_name,
1123  "UNIXPATH",
1124  &unixpath)) &&
1125  (0 < strlen (unixpath)))
1126  {
1127  /* probe UNIX support */
1128  struct sockaddr_un s_un;
1129 
1130  if (strlen (unixpath) >= sizeof(s_un.sun_path))
1131  {
1133  _ ("UNIXPATH `%s' too long, maximum length is %llu\n"),
1134  unixpath,
1135  (unsigned long long) sizeof(s_un.sun_path));
1136  unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath);
1137  LOG (GNUNET_ERROR_TYPE_INFO, _ ("Using `%s' instead\n"), unixpath);
1138  }
1141  }
1142  if (NULL != unixpath)
1143  {
1144  desc = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_STREAM, 0);
1145  if (NULL == desc)
1146  {
1147  if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) ||
1148  (EACCES == errno))
1149  {
1152  GNUNET_free (unixpath);
1153  return GNUNET_SYSERR;
1154  }
1156  _ (
1157  "Disabling UNIX domain socket support for service `%s', failed to create UNIX domain socket: %s\n"),
1158  service_name,
1159  strerror (errno));
1160  GNUNET_free (unixpath);
1161  unixpath = NULL;
1162  }
1163  else
1164  {
1166  desc = NULL;
1167  }
1168  }
1169 #endif
1170 
1171  if ((0 == port) && (NULL == unixpath))
1172  {
1174  _ (
1175  "Have neither PORT nor UNIXPATH for service `%s', but one is required\n"),
1176  service_name);
1178  return GNUNET_SYSERR;
1179  }
1180  if (0 == port)
1181  {
1182  saddrs = GNUNET_new_array (2, struct sockaddr *);
1183  saddrlens = GNUNET_new_array (2, socklen_t);
1184  add_unixpath (saddrs, saddrlens, unixpath);
1185  GNUNET_free (unixpath);
1187  *addrs = saddrs;
1188  *addr_lens = saddrlens;
1189  return 1;
1190  }
1191 
1192  if (NULL != hostname)
1193  {
1195  "Resolving `%s' since that is where `%s' will bind to.\n",
1196  hostname,
1197  service_name);
1198  memset (&hints, 0, sizeof(struct addrinfo));
1199  if (disablev6)
1200  hints.ai_family = AF_INET;
1201  hints.ai_protocol = IPPROTO_TCP;
1202  if ((0 != (ret = getaddrinfo (hostname, NULL, &hints, &res))) ||
1203  (NULL == res))
1204  {
1206  _ ("Failed to resolve `%s': %s\n"),
1207  hostname,
1208  gai_strerror (ret));
1210  GNUNET_free (unixpath);
1211  return GNUNET_SYSERR;
1212  }
1213  next = res;
1214  i = 0;
1215  while (NULL != (pos = next))
1216  {
1217  next = pos->ai_next;
1218  if ((disablev6) && (pos->ai_family == AF_INET6))
1219  continue;
1220  i++;
1221  }
1222  if (0 == i)
1223  {
1225  _ ("Failed to find %saddress for `%s'.\n"),
1226  disablev6 ? "IPv4 " : "",
1227  hostname);
1228  freeaddrinfo (res);
1230  GNUNET_free (unixpath);
1231  return GNUNET_SYSERR;
1232  }
1233  resi = i;
1234  if (NULL != unixpath)
1235  resi++;
1236  saddrs = GNUNET_new_array (resi + 1, struct sockaddr *);
1237  saddrlens = GNUNET_new_array (resi + 1, socklen_t);
1238  i = 0;
1239  if (NULL != unixpath)
1240  {
1241  add_unixpath (saddrs, saddrlens, unixpath);
1242  i++;
1243  }
1244  next = res;
1245  while (NULL != (pos = next))
1246  {
1247  next = pos->ai_next;
1248  if ((disablev6) && (AF_INET6 == pos->ai_family))
1249  continue;
1250  if ((IPPROTO_TCP != pos->ai_protocol) && (0 != pos->ai_protocol))
1251  continue; /* not TCP */
1252  if ((SOCK_STREAM != pos->ai_socktype) && (0 != pos->ai_socktype))
1253  continue; /* huh? */
1255  "Service `%s' will bind to `%s'\n",
1256  service_name,
1257  GNUNET_a2s (pos->ai_addr, pos->ai_addrlen));
1258  if (AF_INET == pos->ai_family)
1259  {
1260  GNUNET_assert (sizeof(struct sockaddr_in) == pos->ai_addrlen);
1261  saddrlens[i] = pos->ai_addrlen;
1262  saddrs[i] = GNUNET_malloc (saddrlens[i]);
1263  GNUNET_memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
1264  ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
1265  }
1266  else
1267  {
1268  GNUNET_assert (AF_INET6 == pos->ai_family);
1269  GNUNET_assert (sizeof(struct sockaddr_in6) == pos->ai_addrlen);
1270  saddrlens[i] = pos->ai_addrlen;
1271  saddrs[i] = GNUNET_malloc (saddrlens[i]);
1272  GNUNET_memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
1273  ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
1274  }
1275  i++;
1276  }
1278  freeaddrinfo (res);
1279  resi = i;
1280  }
1281  else
1282  {
1283  /* will bind against everything, just set port */
1284  if (disablev6)
1285  {
1286  /* V4-only */
1287  resi = 1;
1288  if (NULL != unixpath)
1289  resi++;
1290  i = 0;
1291  saddrs = GNUNET_new_array (resi + 1, struct sockaddr *);
1292  saddrlens = GNUNET_new_array (resi + 1, socklen_t);
1293  if (NULL != unixpath)
1294  {
1295  add_unixpath (saddrs, saddrlens, unixpath);
1296  i++;
1297  }
1298  saddrlens[i] = sizeof(struct sockaddr_in);
1299  saddrs[i] = GNUNET_malloc (saddrlens[i]);
1300 #if HAVE_SOCKADDR_IN_SIN_LEN
1301  ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[i];
1302 #endif
1303  ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
1304  ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
1305  }
1306  else
1307  {
1308  /* dual stack */
1309  resi = 2;
1310  if (NULL != unixpath)
1311  resi++;
1312  saddrs = GNUNET_new_array (resi + 1, struct sockaddr *);
1313  saddrlens = GNUNET_new_array (resi + 1, socklen_t);
1314  i = 0;
1315  if (NULL != unixpath)
1316  {
1317  add_unixpath (saddrs, saddrlens, unixpath);
1318  i++;
1319  }
1320  saddrlens[i] = sizeof(struct sockaddr_in6);
1321  saddrs[i] = GNUNET_malloc (saddrlens[i]);
1322 #if HAVE_SOCKADDR_IN_SIN_LEN
1323  ((struct sockaddr_in6 *) saddrs[i])->sin6_len = saddrlens[0];
1324 #endif
1325  ((struct sockaddr_in6 *) saddrs[i])->sin6_family = AF_INET6;
1326  ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
1327  i++;
1328  saddrlens[i] = sizeof(struct sockaddr_in);
1329  saddrs[i] = GNUNET_malloc (saddrlens[i]);
1330 #if HAVE_SOCKADDR_IN_SIN_LEN
1331  ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[1];
1332 #endif
1333  ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
1334  ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
1335  }
1336  }
1337  GNUNET_free (unixpath);
1338  *addrs = saddrs;
1339  *addr_lens = saddrlens;
1340  return resi;
1341 }
static const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration we are using.
Definition: gnunet-abd.c:36
static int res
static uint16_t port
Port number.
Definition: gnunet-bcd.c:147
static char * hostname
Our hostname; we give this to all the peers we start.
static char * service_name
Option -s: service name (hash to get service descriptor)
Definition: gnunet-vpn.c:51
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.
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_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:582
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#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_ERROR
@ GNUNET_ERROR_TYPE_INFO
#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.
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_create(int domain, int type, int protocol)
Create a new socket.
Definition: network.c:855
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
enum GNUNET_GenericReturnValue GNUNET_NETWORK_test_pf(int pf)
Test if the given protocol family is supported by this system.
Definition: network.c:79
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:1012
#define LOG_STRERROR(kind, syscall)
Definition: service.c:42

References _, add_unixpath(), cfg, GNUNET_a2s(), GNUNET_assert, GNUNET_break, GNUNET_CONFIGURATION_get_value_filename(), GNUNET_CONFIGURATION_get_value_number(), GNUNET_CONFIGURATION_get_value_string(), GNUNET_CONFIGURATION_get_value_yesno(), GNUNET_CONFIGURATION_have_value(), GNUNET_DISK_directory_create_for_file(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_INFO, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_log_strerror_file, GNUNET_malloc, GNUNET_memcpy, GNUNET_NETWORK_shorten_unixpath(), GNUNET_NETWORK_socket_close(), GNUNET_NETWORK_socket_create(), GNUNET_NETWORK_test_pf(), GNUNET_new_array, GNUNET_NO, GNUNET_OK, GNUNET_SYSERR, GNUNET_YES, hostname, LOG, LOG_STRERROR, port, res, ret, and service_name.

Referenced by setup_service().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ open_listen_socket()

static struct GNUNET_NETWORK_Handle* open_listen_socket ( const struct sockaddr *  server_addr,
socklen_t  socklen 
)
static

Create and initialize a listen socket for the server.

Parameters
server_addraddress to listen on
socklenlength of server_addr
Returns
NULL on error, otherwise the listen socket

Definition at line 1352 of file service.c.

1354 {
1355  struct GNUNET_NETWORK_Handle *sock;
1356  uint16_t port;
1357  int eno;
1358 
1359  switch (server_addr->sa_family)
1360  {
1361  case AF_INET:
1362  port = ntohs (((const struct sockaddr_in *) server_addr)->sin_port);
1363  break;
1364  case AF_INET6:
1365  port = ntohs (((const struct sockaddr_in6 *) server_addr)->sin6_port);
1366  break;
1367  case AF_UNIX:
1368  port = 0;
1369  break;
1370  default:
1371  GNUNET_break (0);
1372  port = 0;
1373  break;
1374  }
1375  sock = GNUNET_NETWORK_socket_create (server_addr->sa_family,
1376  SOCK_STREAM,
1377  0);
1378  if (NULL == sock)
1379  {
1381  "socket");
1382  errno = 0;
1383  return NULL;
1384  }
1385  /* bind the socket */
1386  if (GNUNET_OK !=
1388  server_addr,
1389  socklen))
1390  {
1391  eno = errno;
1392  if (EADDRINUSE != errno)
1393  {
1394  /* we don't log 'EADDRINUSE' here since an IPv4 bind may
1395  * fail if we already took the port on IPv6; if both IPv4 and
1396  * IPv6 binds fail, then our caller will log using the
1397  * errno preserved in 'eno' */
1398  if (0 != port)
1400  _ ("`%s' failed for port %d (%s).\n"),
1401  "bind",
1402  port,
1403  (AF_INET == server_addr->sa_family) ? "IPv4" : "IPv6");
1404  else
1406  eno = 0;
1407  }
1408  else
1409  {
1410  if (0 != port)
1412  _ ("`%s' failed for port %d (%s): address already in use\n"),
1413  "bind",
1414  port,
1415  (AF_INET == server_addr->sa_family) ? "IPv4" : "IPv6");
1416  else if (AF_UNIX == server_addr->sa_family)
1417  {
1419  _ ("`%s' failed for `%s': address already in use\n"),
1420  "bind",
1421  GNUNET_a2s (server_addr, socklen));
1422  }
1423  }
1425  errno = eno;
1426  return NULL;
1427  }
1428  if (GNUNET_OK != GNUNET_NETWORK_socket_listen (sock, 5))
1429  {
1432  errno = 0;
1433  return NULL;
1434  }
1435  if (0 != port)
1437  "Server starts to listen on port %u.\n",
1438  port);
1439  return sock;
1440 }
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:656

References _, GNUNET_a2s(), GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_WARNING, GNUNET_NETWORK_socket_bind(), GNUNET_NETWORK_socket_close(), GNUNET_NETWORK_socket_create(), GNUNET_NETWORK_socket_listen(), GNUNET_OK, LOG, LOG_STRERROR, and port.

Referenced by setup_service().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ setup_service()

static int setup_service ( struct GNUNET_SERVICE_Handle sh)
static

Setup service handle.

Configuration may specify:

  • PORT (where to bind to for TCP)
  • UNIXPATH (where to bind to for UNIX domain sockets)
  • DISABLEV6 (disable support for IPv6, otherwise we use dual-stack)
  • BINDTO (hostname or IP address to bind to, otherwise we take everything)
  • ACCEPT_FROM (only allow connections from specified IPv4 subnets)
  • ACCEPT_FROM6 (only allow connections from specified IPv6 subnets)
  • REJECT_FROM (disallow allow connections from specified IPv4 subnets)
  • REJECT_FROM6 (disallow allow connections from specified IPv6 subnets)
Parameters
shservice context to initialize
Returns
GNUNET_OK if configuration succeeded

Definition at line 1460 of file service.c.

1461 {
1462  int tolerant;
1463  struct GNUNET_NETWORK_Handle **csocks = NULL;
1464  struct GNUNET_NETWORK_Handle **lsocks;
1465  const char *nfds;
1466  unsigned int cnt;
1467  int flags;
1468  char dummy[2];
1469 
1471  sh->service_name,
1472  "TOLERANT"))
1473  {
1474  if (GNUNET_SYSERR ==
1475  (tolerant = GNUNET_CONFIGURATION_get_value_yesno (sh->cfg,
1476  sh->service_name,
1477  "TOLERANT")))
1478  {
1480  _ ("Specified value for `%s' of service `%s' is invalid\n"),
1481  "TOLERANT",
1482  sh->service_name);
1483  return GNUNET_SYSERR;
1484  }
1485  }
1486  else
1487  tolerant = GNUNET_NO;
1488 
1489  lsocks = NULL;
1490  errno = 0;
1491  if ((NULL != (nfds = getenv ("LISTEN_FDS"))) &&
1492  (1 == sscanf (nfds, "%u%1s", &cnt, dummy)) && (cnt > 0) &&
1493  (cnt < FD_SETSIZE) && (cnt + 4 < FD_SETSIZE))
1494  {
1495  lsocks = GNUNET_new_array (cnt + 1, struct GNUNET_NETWORK_Handle *);
1496  while (0 < cnt--)
1497  {
1498  flags = fcntl (3 + cnt, F_GETFD);
1499  if ((flags < 0) || (0 != (flags & FD_CLOEXEC)) ||
1500  (NULL == (lsocks[cnt] = GNUNET_NETWORK_socket_box_native (3 + cnt))))
1501  {
1503  _ (
1504  "Could not access pre-bound socket %u, will try to bind myself\n"),
1505  (unsigned int) 3 + cnt);
1506  cnt++;
1507  while (NULL != lsocks[cnt])
1509  GNUNET_NETWORK_socket_close (lsocks[cnt++]));
1510  GNUNET_free (lsocks);
1511  lsocks = NULL;
1512  break;
1513  }
1514  }
1515  unsetenv ("LISTEN_FDS");
1516  }
1517  if ( (0 != (GNUNET_SERVICE_OPTION_CLOSE_LSOCKS & sh->options)) &&
1518  (NULL != lsocks) )
1519  {
1520  csocks = lsocks;
1521  lsocks = NULL;
1522  }
1523 
1524  if (NULL != lsocks)
1525  {
1526  /* listen only on inherited sockets if we have any */
1527  for (struct GNUNET_NETWORK_Handle **ls = lsocks; NULL != *ls; ls++)
1528  {
1529  struct ServiceListenContext *slc;
1530 
1531  slc = GNUNET_new (struct ServiceListenContext);
1532  slc->sh = sh;
1533  slc->listen_socket = *ls;
1534  GNUNET_CONTAINER_DLL_insert (sh->slc_head, sh->slc_tail, slc);
1535  }
1536  GNUNET_free (lsocks);
1537  }
1538  else
1539  {
1540  struct sockaddr **addrs;
1541  socklen_t *addrlens;
1542  int num;
1543 
1544  num = get_server_addresses (sh->service_name, sh->cfg, &addrs, &addrlens);
1545  if (GNUNET_SYSERR == num)
1546  return GNUNET_SYSERR;
1547 
1548  for (int i = 0; i < num; i++)
1549  {
1550  struct ServiceListenContext *slc;
1551 
1552  slc = GNUNET_new (struct ServiceListenContext);
1553  slc->sh = sh;
1554  slc->listen_socket = open_listen_socket (addrs[i], addrlens[i]);
1555  GNUNET_free (addrs[i]);
1556  if (NULL == slc->listen_socket)
1557  {
1559  GNUNET_free (slc);
1560  continue;
1561  }
1562  GNUNET_CONTAINER_DLL_insert (sh->slc_head, sh->slc_tail, slc);
1563  }
1564  GNUNET_free (addrlens);
1565  GNUNET_free (addrs);
1566  if ((0 != num) && (NULL == sh->slc_head))
1567  {
1568  /* All attempts to bind failed, hard failure */
1569  GNUNET_log (
1571  _ (
1572  "Could not bind to any of the ports I was supposed to, refusing to run!\n"));
1573  GNUNET_free (csocks);
1574  return GNUNET_SYSERR;
1575  }
1576  }
1577  if (NULL != csocks)
1578  {
1579  /* close inherited sockets to signal parent that we are ready */
1580  for (struct GNUNET_NETWORK_Handle **ls = csocks; NULL != *ls; ls++)
1582  GNUNET_free (csocks);
1583  }
1584  sh->require_found = tolerant ? GNUNET_NO : GNUNET_YES;
1585  sh->match_uid = GNUNET_CONFIGURATION_get_value_yesno (sh->cfg,
1586  sh->service_name,
1587  "UNIX_MATCH_UID");
1588  sh->match_gid = GNUNET_CONFIGURATION_get_value_yesno (sh->cfg,
1589  sh->service_name,
1590  "UNIX_MATCH_GID");
1591  process_acl4 (&sh->v4_denied, sh, "REJECT_FROM");
1592  process_acl4 (&sh->v4_allowed, sh, "ACCEPT_FROM");
1593  process_acl6 (&sh->v6_denied, sh, "REJECT_FROM6");
1594  process_acl6 (&sh->v6_allowed, sh, "ACCEPT_FROM6");
1595  return GNUNET_OK;
1596 }
char * getenv()
static struct in_addr dummy
Target "dummy" address of the packet we pretend to respond to.
static struct GNUNET_NETWORK_Handle * ls
Listen socket for STUN processing.
Definition: gnunet-nat.c:85
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:584
@ GNUNET_SERVICE_OPTION_CLOSE_LSOCKS
Instead of listening on lsocks passed by the parent, close them after opening our own listen socket(s...
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:931
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:972
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:1056
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:1352

References _, dummy, get_server_addresses(), getenv(), GNUNET_break, GNUNET_CONFIGURATION_get_value_yesno(), GNUNET_CONFIGURATION_have_value(), GNUNET_CONTAINER_DLL_insert, GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_log, GNUNET_log_strerror, GNUNET_NETWORK_socket_box_native(), GNUNET_NETWORK_socket_close(), GNUNET_new, GNUNET_new_array, GNUNET_NO, GNUNET_OK, GNUNET_SERVICE_OPTION_CLOSE_LSOCKS, GNUNET_SYSERR, GNUNET_YES, ServiceListenContext::listen_socket, LOG, ls, open_listen_socket(), process_acl4(), process_acl6(), sh, and ServiceListenContext::sh.

Referenced by GNUNET_SERVICE_run_(), and GNUNET_SERVICE_start().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_user_name()

static char* get_user_name ( struct GNUNET_SERVICE_Handle sh)
static

Get the name of the user that'll be used to provide the service.

Parameters
shservice context
Returns
value of the 'USERNAME' option

Definition at line 1607 of file service.c.

1608 {
1609  char *un;
1610 
1612  sh->service_name,
1613  "USERNAME",
1614  &un))
1615  return NULL;
1616  return un;
1617 }

References GNUNET_CONFIGURATION_get_value_filename(), GNUNET_OK, and sh.

Referenced by set_user_id().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ set_user_id()

static int set_user_id ( struct GNUNET_SERVICE_Handle sh)
static

Set user ID.

Parameters
shservice context
Returns
GNUNET_OK on success, GNUNET_SYSERR on error

Definition at line 1627 of file service.c.

1628 {
1629  char *user;
1630 
1631  if (NULL == (user = get_user_name (sh)))
1632  return GNUNET_OK; /* keep */
1633 
1634  struct passwd *pws;
1635 
1636  errno = 0;
1637  pws = getpwnam (user);
1638  if (NULL == pws)
1639  {
1641  _ ("Cannot obtain information about user `%s': %s\n"),
1642  user,
1643  errno == 0 ? _ ("No such user") : strerror (errno));
1644  GNUNET_free (user);
1645  return GNUNET_SYSERR;
1646  }
1647  if ((0 != setgid (pws->pw_gid)) || (0 != setegid (pws->pw_gid)) ||
1648 #if HAVE_INITGROUPS
1649  (0 != initgroups (user, pws->pw_gid)) ||
1650 #endif
1651  (0 != setuid (pws->pw_uid)) || (0 != seteuid (pws->pw_uid)))
1652  {
1653  if ((0 != setregid (pws->pw_gid, pws->pw_gid)) ||
1654  (0 != setreuid (pws->pw_uid, pws->pw_uid)))
1655  {
1657  _ ("Cannot change user/group to `%s': %s\n"),
1658  user,
1659  strerror (errno));
1660  GNUNET_free (user);
1661  return GNUNET_SYSERR;
1662  }
1663  }
1664 
1665  GNUNET_free (user);
1666  return GNUNET_OK;
1667 }
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:1607

References _, get_user_name(), GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_OK, GNUNET_SYSERR, LOG, and sh.

Referenced by GNUNET_SERVICE_run_().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_pid_file_name()

static char* get_pid_file_name ( struct GNUNET_SERVICE_Handle sh)
static

Get the name of the file where we will write the PID of the service.

Parameters
shservice context
Returns
name of the file for the process ID

Definition at line 1678 of file service.c.

1679 {
1680  char *pif;
1681 
1683  sh->service_name,
1684  "PIDFILE",
1685  &pif))
1686  return NULL;
1687  return pif;
1688 }

References GNUNET_CONFIGURATION_get_value_filename(), GNUNET_OK, and sh.

Referenced by pid_file_delete().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ pid_file_delete()

static void pid_file_delete ( struct GNUNET_SERVICE_Handle sh)
static

Delete the PID file that was created by our parent.

Parameters
shservice context

Definition at line 1697 of file service.c.

1698 {
1699  char *pif = get_pid_file_name (sh);
1700 
1701  if (NULL == pif)
1702  return; /* no PID file */
1703  if (0 != unlink (pif))
1705  GNUNET_free (pif);
1706 }
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:1678
#define LOG_STRERROR_FILE(kind, syscall, filename)
Definition: service.c:45

References get_pid_file_name(), GNUNET_ERROR_TYPE_WARNING, GNUNET_free, LOG_STRERROR_FILE, and sh.

Referenced by GNUNET_SERVICE_run_().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ detach_terminal()

static int detach_terminal ( struct GNUNET_SERVICE_Handle sh)
static

Detach from terminal.

Parameters
shservice context
Returns
GNUNET_OK on success, GNUNET_SYSERR on error

Definition at line 1716 of file service.c.

1717 {
1718  pid_t pid;
1719  int nullfd;
1720  int filedes[2];
1721 
1722  if (0 != pipe (filedes))
1723  {
1725  return GNUNET_SYSERR;
1726  }
1727  pid = fork ();
1728  if (pid < 0)
1729  {
1731  return GNUNET_SYSERR;
1732  }
1733  if (0 != pid)
1734  {
1735  /* Parent */
1736  char c;
1737 
1738  GNUNET_break (0 == close (filedes[1]));
1739  c = 'X';
1740  if (1 != read (filedes[0], &c, sizeof(char)))
1742  fflush (stdout);
1743  switch (c)
1744  {
1745  case '.':
1746  exit (0);
1747 
1748  case 'I':
1750  _ ("Service process failed to initialize\n"));
1751  break;
1752 
1753  case 'S':
1755  _ ("Service process could not initialize server function\n"));
1756  break;
1757 
1758  case 'X':
1760  _ ("Service process failed to report status\n"));
1761  break;
1762  }
1763  exit (1); /* child reported error */
1764  }
1765  GNUNET_break (0 == close (0));
1766  GNUNET_break (0 == close (1));
1767  GNUNET_break (0 == close (filedes[0]));
1768  nullfd = open ("/dev/null", O_RDWR | O_APPEND);
1769  if (nullfd < 0)
1770  return GNUNET_SYSERR;
1771  /* set stdin/stdout to /dev/null */
1772  if ((dup2 (nullfd, 0) < 0) || (dup2 (nullfd, 1) < 0))
1773  {
1775  (void) close (nullfd);
1776  return GNUNET_SYSERR;
1777  }
1778  (void) close (nullfd);
1779  /* Detach from controlling terminal */
1780  pid = setsid ();
1781  if (-1 == pid)
1783  sh->ready_confirm_fd = filedes[1];
1784 
1785  return GNUNET_OK;
1786 }
static struct GNUNET_PeerIdentity pid
Identity of the peer we transmit to / connect to.

References _, GNUNET_break, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_INFO, GNUNET_ERROR_TYPE_WARNING, GNUNET_OK, GNUNET_SYSERR, LOG, LOG_STRERROR, pid, and sh.

Referenced by GNUNET_SERVICE_run_().

Here is the caller graph for this function:

◆ teardown_service()

static void teardown_service ( struct GNUNET_SERVICE_Handle sh)
static

Tear down the service, closing the listen sockets and freeing the ACLs.

Parameters
shhandle to the service to tear down.

Definition at line 1796 of file service.c.

1797 {
1798  struct ServiceListenContext *slc;
1799 
1800  GNUNET_free (sh->v4_denied);
1801  GNUNET_free (sh->v6_denied);
1802  GNUNET_free (sh->v4_allowed);
1803  GNUNET_free (sh->v6_allowed);
1804  while (NULL != (slc = sh->slc_head))
1805  {
1806  GNUNET_CONTAINER_DLL_remove (sh->slc_head, sh->slc_tail, slc);
1807  if (NULL != slc->listen_task)
1811  GNUNET_free (slc);
1812  }
1813 }
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.

References GNUNET_break, GNUNET_CONTAINER_DLL_remove, GNUNET_free, GNUNET_NETWORK_socket_close(), GNUNET_OK, GNUNET_SCHEDULER_cancel(), ServiceListenContext::listen_socket, ServiceListenContext::listen_task, and sh.

Referenced by GNUNET_SERVICE_run_(), and GNUNET_SERVICE_stop().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ return_agpl()

static void return_agpl ( void *  cls,
const struct GNUNET_MessageHeader msg 
)
static

Function to return link to AGPL source upon request.

Parameters
clsclosure with the identification of the client
msgAGPL request

Definition at line 1823 of file service.c.

1824 {
1825  struct GNUNET_SERVICE_Client *client = cls;
1826  struct GNUNET_MQ_Handle *mq;
1827  struct GNUNET_MQ_Envelope *env;
1828  struct GNUNET_MessageHeader *res;
1829  size_t slen;
1830  const struct GNUNET_OS_ProjectData *pd = GNUNET_OS_project_data_get ();
1831 
1832  (void) msg;
1833  slen = strlen (pd->agpl_url) + 1;
1835  memcpy (&res[1], GNUNET_AGPL_URL, slen);
1836  mq = GNUNET_SERVICE_client_get_mq (client);
1837  GNUNET_MQ_send (mq, env);
1839 }
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
#define GNUNET_AGPL_URL
NOTE: You MUST adjust this URL to point to the location of a publicly accessible repository (or TGZ) ...
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:302
#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:56
const struct GNUNET_OS_ProjectData * GNUNET_OS_project_data_get(void)
#define GNUNET_MESSAGE_TYPE_RESPONSE_AGPL
Source code link.
struct GNUNET_MQ_Handle * GNUNET_SERVICE_client_get_mq(struct GNUNET_SERVICE_Client *c)
Obtain the message queue of c.
Definition: service.c:2442
Handle to a message queue.
Definition: mq.c:86
Header for all communications.
Project-specific data used to help the OS subsystem find installation paths.
char * agpl_url
URL pointing to the source code of the application.

References GNUNET_OS_ProjectData::agpl_url, env, GNUNET_AGPL_URL, GNUNET_MESSAGE_TYPE_RESPONSE_AGPL, GNUNET_MQ_msg_extra, GNUNET_MQ_send(), GNUNET_OS_project_data_get(), GNUNET_SERVICE_client_continue(), GNUNET_SERVICE_client_get_mq(), mq, msg, and res.

Referenced by GNUNET_SERVICE_run_(), and GNUNET_SERVICE_start().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ resume_client_receive()

static void resume_client_receive ( void *  cls)
static

Task run to resume receiving data from the client after the client called GNUNET_SERVICE_client_continue().

Parameters
clsour struct GNUNET_SERVICE_Client

Definition at line 2212 of file service.c.

2213 {
2214  struct GNUNET_SERVICE_Client *c = cls;
2215  int ret;
2216 
2217  c->recv_task = NULL;
2218  /* first, check if there is still something in the buffer */
2220  if (GNUNET_SYSERR == ret)
2221  {
2222  if (NULL == c->drop_task)
2224  return;
2225  }
2226  if (GNUNET_NO == ret)
2227  return; /* done processing, wait for more later */
2229  if (GNUNET_YES == c->needs_continue)
2230  return; /* #GNUNET_MST_next() did give a message to the client */
2231  /* need to receive more data from the network first */
2232  if (NULL != c->recv_task)
2233  return;
2235  c->sock,
2237  c);
2238 }
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:401

References GNUNET_SERVICE_Client::drop_task, GNUNET_assert, GNUNET_MST_next(), GNUNET_NO, GNUNET_OK, GNUNET_SCHEDULER_add_read_net(), GNUNET_SERVICE_client_drop(), GNUNET_SYSERR, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, GNUNET_SERVICE_Client::mst, GNUNET_SERVICE_Client::needs_continue, GNUNET_SERVICE_Client::recv_task, ret, service_client_recv(), and GNUNET_SERVICE_Client::sock.

Referenced by GNUNET_SERVICE_client_continue().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ finish_client_drop()

static void finish_client_drop ( void *  cls)
static

Asynchronously finish dropping the client.

Parameters
clsthe struct GNUNET_SERVICE_Client.

Definition at line 2289 of file service.c.

2290 {
2291  struct GNUNET_SERVICE_Client *c = cls;
2292  struct GNUNET_SERVICE_Handle *sh = c->sh;
2293 
2294  c->drop_task = NULL;
2295  GNUNET_assert (NULL == c->send_task);
2296  GNUNET_assert (NULL == c->recv_task);
2297  GNUNET_assert (NULL == c->warn_task);
2298  GNUNET_MST_destroy (c->mst);
2299  GNUNET_MQ_destroy (c->mq);
2300  if (GNUNET_NO == c->persist)
2301  {
2303  if ((0 != (SUSPEND_STATE_EMFILE & sh->suspend_state)) &&
2304  (0 == (SUSPEND_STATE_SHUTDOWN & sh->suspend_state)))
2306  }
2307  else
2308  {
2310  }
2311  GNUNET_free (c);
2312  if ((0 != (SUSPEND_STATE_SHUTDOWN & sh->suspend_state)) &&
2315 }
void GNUNET_MQ_destroy(struct GNUNET_MQ_Handle *mq)
Destroy the message queue.
Definition: mq.c:685
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:570
void GNUNET_MST_destroy(struct GNUNET_MessageStreamTokenizer *mst)
Destroys a tokenizer.
Definition: mst.c:418
int persist
Persist the file handle for this client no matter what happens, force the OS to close once the proces...
Definition: service.c:332

References do_resume(), GNUNET_SERVICE_Client::drop_task, GNUNET_assert, GNUNET_break, GNUNET_free, GNUNET_MQ_destroy(), GNUNET_MST_destroy(), GNUNET_NETWORK_socket_close(), GNUNET_NETWORK_socket_free_memory_only_(), GNUNET_NO, GNUNET_OK, GNUNET_SERVICE_shutdown(), have_non_monitor_clients(), GNUNET_SERVICE_Client::mq, GNUNET_SERVICE_Client::mst, GNUNET_SERVICE_Client::persist, GNUNET_SERVICE_Client::recv_task, GNUNET_SERVICE_Client::send_task, sh, GNUNET_SERVICE_Client::sh, GNUNET_SERVICE_Client::sock, SUSPEND_STATE_EMFILE, SUSPEND_STATE_SHUTDOWN, and GNUNET_SERVICE_Client::warn_task.

Referenced by GNUNET_SERVICE_client_drop().

Here is the call graph for this function:
Here is the caller graph for this function: