GNUnet 0.21.1
service.c File Reference

functions related to starting services (redesign) 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...
 
struct  ServiceHandleList
 A list of service to be launched when GNUNET_SERVICE_main() is called. 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 enum GNUNET_GenericReturnValue have_non_monitor_clients (struct GNUNET_SERVICE_Handle *sh)
 Check if any of the clients we have left are unrelated to monitoring. 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 bool check_ipv4_listed (const struct GNUNET_STRINGS_IPv4NetworkPolicy *list, const struct in_addr *add)
 Check if the given IP address is in the list of IP addresses. More...
 
static bool check_ipv6_listed (const struct GNUNET_STRINGS_IPv6NetworkPolicy *list, const struct in6_addr *ip)
 Check if the given IP address is in the list of IP addresses. 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 enum GNUNET_GenericReturnValue process_acl4 (struct GNUNET_STRINGS_IPv4NetworkPolicy **ret, struct GNUNET_SERVICE_Handle *sh, const char *option)
 Parse an IPv4 access control list. More...
 
static enum GNUNET_GenericReturnValue process_acl6 (struct GNUNET_STRINGS_IPv6NetworkPolicy **ret, struct GNUNET_SERVICE_Handle *sh, const char *option)
 Parse an IPv6 access control list. 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 enum GNUNET_GenericReturnValue 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 enum GNUNET_GenericReturnValue 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 enum GNUNET_GenericReturnValue 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...
 
static void finish_client_drop (void *cls)
 Asynchronously finish dropping the client. 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...
 
int GNUNET_SERVICE_register_ (const char *service_name, enum GNUNET_SERVICE_Options options, GNUNET_SERVICE_InitCallback service_init_cb, GNUNET_SERVICE_ConnectHandler connect_cb, GNUNET_SERVICE_DisconnectHandler disconnect_cb, void *cls, const struct GNUNET_MQ_MessageHandler *handlers)
 Registers the GNUnet service to be scheduled as part of a monilithic libgnunet. More...
 
static void do_registered_services_shutdown (void *cls)
 
static void launch_registered_services (void *cls)
 
void GNUNET_SERVICE_main (int argc, char *const *argv)
 Run the mainloop in a monolithic libgnunet. 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...
 
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...
 

Variables

static struct ServiceHandleListhll_head
 
static struct ServiceHandleListhll_tail
 

Detailed Description

functions related to starting services (redesign)

Author
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 enum GNUNET_GenericReturnValue 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
true if we have non-monitoring clients left

Definition at line 356 of file service.c.

357{
358 for (struct GNUNET_SERVICE_Client *client = sh->clients_head;
359 NULL != client;
360 client = client->next)
361 {
362 if (NULL != client->drop_task)
363 continue;
364 if (client->is_monitor)
365 continue;
366 return true;
367 }
368 return false;
369}
static struct GNUNET_IDENTITY_Handle * sh
Handle to IDENTITY service.
Handle to a client that is connected to a service.
Definition: service.c:246

References 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 380 of file service.c.

382{
383 GNUNET_assert (0 == (sh->suspend_state & sr));
384 sh->suspend_state |= sr;
385 for (struct ServiceListenContext *slc = sh->slc_head;
386 NULL != slc;
387 slc = slc->next)
388 {
389 if (NULL != slc->listen_task)
390 {
391 GNUNET_SCHEDULER_cancel (slc->listen_task);
392 slc->listen_task = NULL;
393 }
394 }
395}
#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:981
Information the service tracks per listen operation.
Definition: service.c:53

References GNUNET_assert, GNUNET_SCHEDULER_cancel(), 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 407 of file service.c.

408{
409 struct GNUNET_SERVICE_Handle *sh = cls;
410
412 {
415 break;
417 /* This task should never be run if we are using
418 the manual shutdown. */
419 GNUNET_assert (0);
420 break;
422 if (0 == (sh->suspend_state & SUSPEND_STATE_SHUTDOWN))
426 break;
427 }
428}
void GNUNET_SERVICE_shutdown(struct GNUNET_SERVICE_Handle *sh)
Explicitly stops the service.
Definition: service.c:2533
@ 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 void do_suspend(struct GNUNET_SERVICE_Handle *sh, enum SuspendReason sr)
Suspend accepting connections from the listen socket temporarily.
Definition: service.c:380
static enum GNUNET_GenericReturnValue have_non_monitor_clients(struct GNUNET_SERVICE_Handle *sh)
Check if any of the clients we have left are unrelated to monitoring.
Definition: service.c:356
Handle to a service.
Definition: service.c:117

References do_suspend(), GNUNET_assert, 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 bool 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
false if the IP is not in the list, true if it it is

Definition at line 439 of file service.c.

441{
442 for (unsigned int i = 0;
443 0 != list[i].network.s_addr;
444 i++)
445 {
446 if ( (add->s_addr & list[i].netmask.s_addr) ==
447 (list[i].network.s_addr & list[i].netmask.s_addr) )
448 return true;
449 }
450 return false;
451}
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, and list.

Referenced by accept_client().

Here is the caller graph for this function:

◆ check_ipv6_listed()

static bool 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
false if the IP is not in the list, true if it it is

Definition at line 462 of file service.c.

464{
465 for (unsigned int i = 0;
466 ! GNUNET_is_zero (&list[i].network);
467 i++)
468 {
469 bool match = true;
470
471 for (unsigned int j = 0; j < sizeof(struct in6_addr) / sizeof(int); j++)
472 if (((((int *) ip)[j] & ((int *) &list[i].netmask)[j])) !=
473 (((int *) &list[i].network)[j] & ((int *) &list[i].netmask)[j]))
474 {
475 match = false;
476 break;
477 }
478 if (match)
479 return true;
480 }
481 return false;
482}
#define GNUNET_is_zero(a)
Check that memory in a is all zeros.

References GNUNET_is_zero, 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 492 of file service.c.

493{
494 struct GNUNET_SERVICE_Client *client = cls;
495 ssize_t ret;
496 size_t left;
497 const char *buf;
498
500 "service: sending message with type %u\n",
501 ntohs (client->msg->type));
502 client->send_task = NULL;
503 buf = (const char *) client->msg;
504 left = ntohs (client->msg->size) - client->msg_pos;
506 &buf[client->msg_pos],
507 left);
508 GNUNET_assert (ret <= (ssize_t) left);
509 if (0 == ret)
510 {
511 LOG (GNUNET_ERROR_TYPE_DEBUG, "no data send");
513 return;
514 }
515 if (-1 == ret)
516 {
517 if ((EAGAIN == errno) || (EINTR == errno))
518 {
519 /* ignore */
520 ret = 0;
521 }
522 else
523 {
524 if (EPIPE != errno)
527 "socket send returned with error code %i",
528 errno);
530 return;
531 }
532 }
533 if (0 == client->msg_pos)
534 {
536 }
537 client->msg_pos += ret;
538 if (left > (size_t) ret)
539 {
540 GNUNET_assert (NULL == client->drop_task);
541 client->send_task =
543 client->sock,
544 &do_send,
545 client);
546 return;
547 }
549}
static int ret
Final status code.
Definition: gnunet-arm.c:94
#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:269
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_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
@ 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:737
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_write_net(struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *wfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition: scheduler.c:1583
#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:492
#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:320
struct GNUNET_SCHEDULER_Task * send_task
Task that transmit data to the client.
Definition: service.c:298
struct GNUNET_SCHEDULER_Task * drop_task
Task run to finish dropping the client after the stack has properly unwound.
Definition: service.c:287
struct GNUNET_NETWORK_Handle * sock
Socket of this client.
Definition: service.c:265
const struct GNUNET_MessageHeader * msg
Pointer to the message to be transmitted by send_task.
Definition: service.c:303
struct GNUNET_MQ_Handle * mq
Message queue for the client.
Definition: service.c:270

References do_send(), 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 do_send(), and 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 561 of file service.c.

564{
565 struct GNUNET_SERVICE_Client *client = impl_state;
566
567 (void) mq;
568 if (NULL != client->drop_task)
569 return; /* we're going down right now, do not try to send */
570 GNUNET_assert (NULL == client->send_task);
572 "Sending message of type %u and size %u to client\n",
573 ntohs (msg->type),
574 ntohs (msg->size));
575 client->msg = msg;
576 client->msg_pos = 0;
578 client);
579}
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:1305

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 589 of file service.c.

591{
592 struct GNUNET_SERVICE_Client *client = impl_state;
593
594 (void) mq;
595 GNUNET_assert (0 == client->msg_pos);
596 client->msg = NULL;
598 client->send_task = NULL;
599}

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 612 of file service.c.

614{
615 struct GNUNET_SERVICE_Client *client = cls;
616 struct GNUNET_SERVICE_Handle *sh = client->sh;
617
618 if ( (GNUNET_MQ_ERROR_NO_MATCH == error) &&
619 (! sh->require_found) )
620 {
622 "No handler for message of type %u found\n",
623 (unsigned int) client->warn_type);
625 return; /* ignore error */
626 }
628}
#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:2484
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2455
uint16_t warn_type
Type of last message processed (for warn_no_receive_done).
Definition: service.c:344
struct GNUNET_SERVICE_Handle * sh
Service that this client belongs to.
Definition: service.c:260

References GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_MQ_ERROR_NO_MATCH, 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 637 of file service.c.

638{
639 struct GNUNET_SERVICE_Client *client = cls;
640
642 0 !=
643 client->warn_type); /* type should never be 0 here, as we don't use 0 */
646 client);
647 LOG (
649 _ (
650 "Processing code for message of type %u did not call `GNUNET_SERVICE_client_continue' after %s\n"),
651 (unsigned int) client->warn_type,
653 client->warn_start),
654 GNUNET_YES));
655}
@ GNUNET_YES
#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:1278
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_duration(struct GNUNET_TIME_Absolute whence)
Get the duration of an operation as the difference of the current time and the given start time "henc...
Definition: time.c:436
const char * GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition: strings.c:570
#define GNUNET_TIME_UNIT_MINUTES
One minute.
#define _(String)
GNU gettext support macro.
Definition: platform.h:178
static void warn_no_client_continue(void *cls)
Task run to warn about missing calls to GNUNET_SERVICE_client_continue().
Definition: service.c:637
struct GNUNET_TIME_Absolute warn_start
Time when we last gave a message from this client to the application.
Definition: service.c:315
struct GNUNET_SCHEDULER_Task * warn_task
Task that warns about missing calls to GNUNET_SERVICE_client_continue().
Definition: service.c:281

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, warn_no_client_continue(), GNUNET_SERVICE_Client::warn_start, GNUNET_SERVICE_Client::warn_task, and GNUNET_SERVICE_Client::warn_type.

Referenced by service_client_mst_cb(), and warn_no_client_continue().

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 670 of file service.c.

672{
673 struct GNUNET_SERVICE_Client *client = cls;
674
676 "Received message of type %u and size %u from client\n",
677 ntohs (message->type),
678 ntohs (message->size));
679 GNUNET_assert (! client->needs_continue);
680 client->needs_continue = true;
681 client->warn_type = ntohs (message->type);
683 GNUNET_assert (NULL == client->warn_task);
686 client);
687 GNUNET_MQ_inject_message (client->mq, message);
688 if (NULL != client->drop_task)
689 return GNUNET_SYSERR;
690 return GNUNET_OK;
691}
@ GNUNET_OK
@ GNUNET_SYSERR
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
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:111
bool needs_continue
Are we waiting for the application to call GNUNET_SERVICE_client_continue()?
Definition: service.c:339

References GNUNET_SERVICE_Client::drop_task, GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_MQ_inject_message(), GNUNET_OK, GNUNET_SCHEDULER_add_delayed(), GNUNET_SYSERR, GNUNET_TIME_absolute_get(), GNUNET_TIME_UNIT_MINUTES, 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 701 of file service.c.

702{
703 struct GNUNET_SERVICE_Client *client = cls;
705
706 client->recv_task = NULL;
707 ret = GNUNET_MST_read (client->mst,
708 client->sock,
709 GNUNET_NO,
710 GNUNET_YES);
711 if (GNUNET_SYSERR == ret)
712 {
713 /* client closed connection (or IO error) */
714 if (NULL == client->drop_task)
715 {
716 GNUNET_assert (! client->needs_continue);
718 }
719 return;
720 }
721 if (GNUNET_NO == ret)
722 return; /* more messages in buffer, wait for application
723 to be done processing */
725 if (client->needs_continue)
726 return;
727 if (NULL != client->recv_task)
728 return;
729 /* MST needs more data, re-schedule read job */
730 client->recv_task =
732 client->sock,
734 client);
735}
GNUNET_GenericReturnValue
Named constants for return values.
@ GNUNET_NO
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_net(struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition: scheduler.c:1512
enum GNUNET_GenericReturnValue GNUNET_MST_read(struct GNUNET_MessageStreamTokenizer *mst, struct GNUNET_NETWORK_Handle *sock, int purge, int one_shot)
Add incoming data to the receive buffer and call the callback for all complete messages.
Definition: mst.c:338
static void service_client_recv(void *cls)
A client sent us data.
Definition: service.c:701
struct GNUNET_SCHEDULER_Task * recv_task
Task that receives data from the client to pass it to the handlers.
Definition: service.c:293
struct GNUNET_MessageStreamTokenizer * mst
Tokenizer we use for processing incoming data.
Definition: service.c:275

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, service_client_recv(), and GNUNET_SERVICE_Client::sock.

Referenced by resume_client_receive(), service_client_recv(), 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
csocksocket associated with the client

Definition at line 746 of file service.c.

748{
749 struct GNUNET_SERVICE_Client *client;
750
751 client = GNUNET_new (struct GNUNET_SERVICE_Client);
752 GNUNET_CONTAINER_DLL_insert (sh->clients_head,
753 sh->clients_tail,
754 client);
755 client->sh = sh;
756 client->sock = csock;
758 NULL,
760 client,
761 sh->handlers,
763 client);
764 client->mst = GNUNET_MST_create (&service_client_mst_cb, client);
765 if (NULL != sh->connect_cb)
766 client->user_context = sh->connect_cb (sh->cb_cls, client, client->mq);
768 client->recv_task =
770 client->sock,
772 client);
773}
#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:465
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_MessageStreamTokenizer * GNUNET_MST_create(GNUNET_MessageTokenizerCallback cb, void *cb_cls)
Create a message stream tokenizer.
Definition: mst.c:86
static void service_mq_cancel(struct GNUNET_MQ_Handle *mq, void *impl_state)
Implementation function that cancels the currently sent message.
Definition: service.c:589
static void service_mq_send(struct GNUNET_MQ_Handle *mq, const struct GNUNET_MessageHeader *msg, void *impl_state)
Signature of functions implementing the sending functionality of a message queue.
Definition: service.c:561
static int service_client_mst_cb(void *cls, const struct GNUNET_MessageHeader *message)
Functions with this signature are called whenever a complete message is received by the tokenizer for...
Definition: service.c:670
static void service_mq_error_handler(void *cls, enum GNUNET_MQ_Error error)
Generic error handler, called with the appropriate error code and the same closure specified at the c...
Definition: service.c:612
void * cb_cls
Closure for cb.
Definition: identity_api.c:122
void * user_context
User context value, value returned from the connect callback.
Definition: service.c:309

References GNUNET_IDENTITY_Handle::cb_cls, 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 783 of file service.c.

784{
785 struct ServiceListenContext *slc = cls;
786 struct GNUNET_SERVICE_Handle *sh = slc->sh;
787
788 slc->listen_task = NULL;
789 while (1)
790 {
791 struct GNUNET_NETWORK_Handle *sock;
792 const struct sockaddr_in *v4;
793 const struct sockaddr_in6 *v6;
794 struct sockaddr_storage sa;
795 socklen_t addrlen;
796 int ok;
797
798 addrlen = sizeof(sa);
800 (struct sockaddr *) &sa,
801 &addrlen);
802 if (NULL == sock)
803 {
804 if (EMFILE == errno)
806 else if (EAGAIN != errno)
808 "accept");
809 break;
810 }
811 switch (sa.ss_family)
812 {
813 case AF_INET:
814 GNUNET_assert (addrlen == sizeof(struct sockaddr_in));
815 v4 = (const struct sockaddr_in *) &sa;
816 ok = (((NULL == sh->v4_allowed) ||
817 (check_ipv4_listed (sh->v4_allowed,
818 &v4->sin_addr))) &&
819 ((NULL == sh->v4_denied) ||
820 (! check_ipv4_listed (sh->v4_denied,
821 &v4->sin_addr))));
822 break;
823
824 case AF_INET6:
825 GNUNET_assert (addrlen == sizeof(struct sockaddr_in6));
826 v6 = (const struct sockaddr_in6 *) &sa;
827 ok = (((NULL == sh->v6_allowed) ||
828 (check_ipv6_listed (sh->v6_allowed,
829 &v6->sin6_addr))) &&
830 ((NULL == sh->v6_denied) ||
831 (! check_ipv6_listed (sh->v6_denied,
832 &v6->sin6_addr))));
833 break;
834
835 case AF_UNIX:
836 ok = GNUNET_OK; /* controlled using file-system ACL now */
837 break;
838
839 default:
841 _ ("Unknown address family %d\n"),
842 sa.ss_family);
843 return;
844 }
845 if (! ok)
846 {
848 "Service rejected incoming connection from %s due to policy.\n",
849 GNUNET_a2s ((const struct sockaddr *) &sa, addrlen));
851 continue;
852 }
854 "Service accepted incoming connection from %s.\n",
855 GNUNET_a2s ((const struct sockaddr *) &sa, addrlen));
856 start_client (slc->sh,
857 sock);
858 }
859 if (0 != sh->suspend_state)
860 return;
861 slc->listen_task =
863 slc->listen_socket,
865 slc);
866}
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).
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_accept(const struct GNUNET_NETWORK_Handle *desc, struct sockaddr *address, socklen_t *address_len)
Accept a new connection on a socket.
Definition: network.c:392
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition: network.c:508
static bool check_ipv6_listed(const struct GNUNET_STRINGS_IPv6NetworkPolicy *list, const struct in6_addr *ip)
Check if the given IP address is in the list of IP addresses.
Definition: service.c:462
static void start_client(struct GNUNET_SERVICE_Handle *sh, struct GNUNET_NETWORK_Handle *csock)
We have successfully accepted a connection from a client.
Definition: service.c:746
static bool check_ipv4_listed(const struct GNUNET_STRINGS_IPv4NetworkPolicy *list, const struct in_addr *add)
Check if the given IP address is in the list of IP addresses.
Definition: service.c:439
static void accept_client(void *cls)
We have a client.
Definition: service.c:783
handle to a socket
Definition: network.c:53
struct GNUNET_SCHEDULER_Task * listen_task
Task scheduled to do the listening.
Definition: service.c:77
struct GNUNET_NETWORK_Handle * listen_socket
Socket we are listening on.
Definition: service.c:72
struct GNUNET_SERVICE_Handle * sh
Service this listen context belongs to.
Definition: service.c:67

References _, accept_client(), 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, sh, ServiceListenContext::sh, start_client(), and SUSPEND_STATE_EMFILE.

Referenced by accept_client(), and 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 877 of file service.c.

879{
880 GNUNET_assert ((SUSPEND_STATE_NONE == sr) || (0 != (sh->suspend_state & sr)));
881 sh->suspend_state -= sr;
882 if (SUSPEND_STATE_NONE != sh->suspend_state)
883 return;
884 for (struct ServiceListenContext *slc = sh->slc_head;
885 NULL != slc;
886 slc = slc->next)
887 {
888 GNUNET_assert (NULL == slc->listen_task);
889 slc->listen_task =
891 slc->listen_socket,
893 slc);
894 }
895}

References accept_client(), GNUNET_assert, GNUNET_SCHEDULER_add_read_net(), GNUNET_TIME_UNIT_FOREVER_REL, 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 906 of file service.c.

907{
908 struct GNUNET_SERVICE_Handle *sh = cls;
909
914
915 if (-1 != sh->ready_confirm_fd)
916 {
917 GNUNET_break (1 == write (sh->ready_confirm_fd, ".", 1));
918 GNUNET_break (0 == close (sh->ready_confirm_fd));
919 sh->ready_confirm_fd = -1;
920 }
921
922 if (NULL != sh->service_init_cb)
923 sh->service_init_cb (sh->cb_cls, sh->cfg, sh);
924}
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received,...
Definition: scheduler.c:1340
static void do_resume(struct GNUNET_SERVICE_Handle *sh, enum SuspendReason sr)
Resume accepting connections from the listen socket.
Definition: service.c:877
static void service_shutdown(void *cls)
Shutdown task triggered when a service should be terminated.
Definition: service.c:407
const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration to use.
Definition: identity_api.c:101

References GNUNET_IDENTITY_Handle::cb_cls, GNUNET_IDENTITY_Handle::cfg, 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_(), and launch_registered_services().

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

◆ process_acl4()

static enum GNUNET_GenericReturnValue 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 937 of file service.c.

940{
941 char *opt;
942
943 if (! GNUNET_CONFIGURATION_have_value (sh->cfg, sh->service_name, option))
944 {
945 *ret = NULL;
946 return GNUNET_OK;
947 }
950 sh->service_name,
951 option,
952 &opt));
953 if (NULL == (*ret = GNUNET_STRINGS_parse_ipv4_policy (opt)))
954 {
956 _ ("Could not parse IPv4 network specification `%s' for `%s:%s'\n"),
957 opt,
958 sh->service_name,
959 option);
960 GNUNET_free (opt);
961 return GNUNET_SYSERR;
962 }
963 GNUNET_free (opt);
964 return GNUNET_OK;
965}
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:1298

References _, GNUNET_IDENTITY_Handle::cfg, 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 enum GNUNET_GenericReturnValue 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 978 of file service.c.

981{
982 char *opt;
983
984 if (! GNUNET_CONFIGURATION_have_value (sh->cfg, sh->service_name, option))
985 {
986 *ret = NULL;
987 return GNUNET_OK;
988 }
991 sh->service_name,
992 option,
993 &opt));
994 if (NULL == (*ret = GNUNET_STRINGS_parse_ipv6_policy (opt)))
995 {
997 _ ("Could not parse IPv6 network specification `%s' for `%s:%s'\n"),
998 opt,
999 sh->service_name,
1000 option);
1001 GNUNET_free (opt);
1002 return GNUNET_SYSERR;
1003 }
1004 GNUNET_free (opt);
1005 return GNUNET_OK;
1006}
struct GNUNET_STRINGS_IPv6NetworkPolicy * GNUNET_STRINGS_parse_ipv6_policy(const char *routeListX)
Parse an IPv6 network policy.
Definition: strings.c:1473

References _, GNUNET_IDENTITY_Handle::cfg, 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 1018 of file service.c.

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

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 1062 of file service.c.

1066{
1067 int disablev6;
1068 struct GNUNET_NETWORK_Handle *desc;
1069 unsigned long long port;
1070 char *unixpath;
1071 struct addrinfo hints;
1072 struct addrinfo *res;
1073 struct addrinfo *pos;
1074 struct addrinfo *next;
1075 unsigned int i;
1076 int resi;
1077 int ret;
1078 struct sockaddr **saddrs;
1079 socklen_t *saddrlens;
1080 char *hostname;
1081
1082 *addrs = NULL;
1083 *addr_lens = NULL;
1084 desc = NULL;
1085 disablev6 = GNUNET_NO;
1086 if ((GNUNET_NO == GNUNET_NETWORK_test_pf (PF_INET6)) ||
1087 (GNUNET_YES ==
1089 disablev6 = GNUNET_YES;
1090
1091 port = 0;
1093 {
1096 "PORT",
1097 &port))
1098 {
1100 _ ("Require valid port number for service `%s' in configuration!\n"),
1101 service_name);
1102 }
1103 if (port > 65535)
1104 {
1106 _ ("Require valid port number for service `%s' in configuration!\n"),
1107 service_name);
1108 return GNUNET_SYSERR;
1109 }
1110 }
1111
1113 {
1117 "BINDTO",
1118 &hostname));
1119 }
1120 else
1121 hostname = NULL;
1122
1123 unixpath = NULL;
1124#ifdef AF_UNIX
1125 if ((GNUNET_YES ==
1129 "UNIXPATH",
1130 &unixpath)) &&
1131 (0 < strlen (unixpath)))
1132 {
1133 /* probe UNIX support */
1134 struct sockaddr_un s_un;
1135
1136 if (strlen (unixpath) >= sizeof(s_un.sun_path))
1137 {
1139 _ ("UNIXPATH `%s' too long, maximum length is %llu\n"),
1140 unixpath,
1141 (unsigned long long) sizeof(s_un.sun_path));
1142 unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath);
1143 LOG (GNUNET_ERROR_TYPE_INFO, _ ("Using `%s' instead\n"), unixpath);
1144 }
1147 }
1148 if (NULL != unixpath)
1149 {
1150 desc = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_STREAM, 0);
1151 if (NULL == desc)
1152 {
1153 if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) ||
1154 (EACCES == errno))
1155 {
1157 GNUNET_free (hostname);
1158 GNUNET_free (unixpath);
1159 return GNUNET_SYSERR;
1160 }
1162 _ (
1163 "Disabling UNIX domain socket support for service `%s', failed to create UNIX domain socket: %s\n"),
1165 strerror (errno));
1166 GNUNET_free (unixpath);
1167 unixpath = NULL;
1168 }
1169 else
1170 {
1172 desc = NULL;
1173 }
1174 }
1175#endif
1176
1177 if ((0 == port) && (NULL == unixpath))
1178 {
1180 _ (
1181 "Have neither PORT nor UNIXPATH for service `%s', but one is required\n"),
1182 service_name);
1183 GNUNET_free (hostname);
1184 return GNUNET_SYSERR;
1185 }
1186 if (0 == port)
1187 {
1188 saddrs = GNUNET_new_array (2, struct sockaddr *);
1189 saddrlens = GNUNET_new_array (2, socklen_t);
1190 add_unixpath (saddrs, saddrlens, unixpath);
1191 GNUNET_free (unixpath);
1192 GNUNET_free (hostname);
1193 *addrs = saddrs;
1194 *addr_lens = saddrlens;
1195 return 1;
1196 }
1197
1198 if (NULL != hostname)
1199 {
1201 "Resolving `%s' since that is where `%s' will bind to.\n",
1202 hostname,
1203 service_name);
1204 memset (&hints, 0, sizeof(struct addrinfo));
1205 if (disablev6)
1206 hints.ai_family = AF_INET;
1207 hints.ai_protocol = IPPROTO_TCP;
1208 if ((0 != (ret = getaddrinfo (hostname, NULL, &hints, &res))) ||
1209 (NULL == res))
1210 {
1212 _ ("Failed to resolve `%s': %s\n"),
1213 hostname,
1214 gai_strerror (ret));
1215 GNUNET_free (hostname);
1216 GNUNET_free (unixpath);
1217 return GNUNET_SYSERR;
1218 }
1219 next = res;
1220 i = 0;
1221 while (NULL != (pos = next))
1222 {
1223 next = pos->ai_next;
1224 if ((disablev6) && (pos->ai_family == AF_INET6))
1225 continue;
1226 i++;
1227 }
1228 if (0 == i)
1229 {
1231 _ ("Failed to find %saddress for `%s'.\n"),
1232 disablev6 ? "IPv4 " : "",
1233 hostname);
1234 freeaddrinfo (res);
1235 GNUNET_free (hostname);
1236 GNUNET_free (unixpath);
1237 return GNUNET_SYSERR;
1238 }
1239 resi = i;
1240 if (NULL != unixpath)
1241 resi++;
1242 saddrs = GNUNET_new_array (resi + 1, struct sockaddr *);
1243 saddrlens = GNUNET_new_array (resi + 1, socklen_t);
1244 i = 0;
1245 if (NULL != unixpath)
1246 {
1247 add_unixpath (saddrs, saddrlens, unixpath);
1248 i++;
1249 }
1250 next = res;
1251 while (NULL != (pos = next))
1252 {
1253 next = pos->ai_next;
1254 if ((disablev6) && (AF_INET6 == pos->ai_family))
1255 continue;
1256 if ((IPPROTO_TCP != pos->ai_protocol) && (0 != pos->ai_protocol))
1257 continue; /* not TCP */
1258 if ((SOCK_STREAM != pos->ai_socktype) && (0 != pos->ai_socktype))
1259 continue; /* huh? */
1261 "Service `%s' will bind to `%s'\n",
1263 GNUNET_a2s (pos->ai_addr, pos->ai_addrlen));
1264 if (AF_INET == pos->ai_family)
1265 {
1266 GNUNET_assert (sizeof(struct sockaddr_in) == pos->ai_addrlen);
1267 saddrlens[i] = pos->ai_addrlen;
1268 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1269 GNUNET_memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
1270 ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
1271 }
1272 else
1273 {
1274 GNUNET_assert (AF_INET6 == pos->ai_family);
1275 GNUNET_assert (sizeof(struct sockaddr_in6) == pos->ai_addrlen);
1276 saddrlens[i] = pos->ai_addrlen;
1277 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1278 GNUNET_memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
1279 ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
1280 }
1281 i++;
1282 }
1283 GNUNET_free (hostname);
1284 freeaddrinfo (res);
1285 resi = i;
1286 }
1287 else
1288 {
1289 /* will bind against everything, just set port */
1290 if (disablev6)
1291 {
1292 /* V4-only */
1293 resi = 1;
1294 if (NULL != unixpath)
1295 resi++;
1296 i = 0;
1297 saddrs = GNUNET_new_array (resi + 1, struct sockaddr *);
1298 saddrlens = GNUNET_new_array (resi + 1, socklen_t);
1299 if (NULL != unixpath)
1300 {
1301 add_unixpath (saddrs, saddrlens, unixpath);
1302 i++;
1303 }
1304 saddrlens[i] = sizeof(struct sockaddr_in);
1305 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1306#if HAVE_SOCKADDR_IN_SIN_LEN
1307 ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[i];
1308#endif
1309 ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
1310 ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
1311 }
1312 else
1313 {
1314 /* dual stack */
1315 resi = 2;
1316 if (NULL != unixpath)
1317 resi++;
1318 saddrs = GNUNET_new_array (resi + 1, struct sockaddr *);
1319 saddrlens = GNUNET_new_array (resi + 1, socklen_t);
1320 i = 0;
1321 if (NULL != unixpath)
1322 {
1323 add_unixpath (saddrs, saddrlens, unixpath);
1324 i++;
1325 }
1326 saddrlens[i] = sizeof(struct sockaddr_in6);
1327 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1328#if HAVE_SOCKADDR_IN_SIN_LEN
1329 ((struct sockaddr_in6 *) saddrs[i])->sin6_len = saddrlens[0];
1330#endif
1331 ((struct sockaddr_in6 *) saddrs[i])->sin6_family = AF_INET6;
1332 ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
1333 i++;
1334 saddrlens[i] = sizeof(struct sockaddr_in);
1335 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1336#if HAVE_SOCKADDR_IN_SIN_LEN
1337 ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[1];
1338#endif
1339 ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
1340 ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
1341 }
1342 }
1343 GNUNET_free (unixpath);
1344 *addrs = saddrs;
1345 *addr_lens = saddrlens;
1346 return resi;
1347}
static struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition: gnunet-arm.c:109
static uint16_t port
Port number.
Definition: gnunet-bcd.c:147
static char * res
Currently read line or NULL on EOF.
static char * service_name
Option -s: service name (hash to get service descriptor)
Definition: gnunet-vpn.c:50
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.
char * GNUNET_NETWORK_shorten_unixpath(char *unixpath)
Given a unixpath that is too long (larger than UNIX_PATH_MAX), shorten it to an acceptable length whi...
Definition: network.c:143
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_create(int domain, int type, int protocol)
Create a new socket.
Definition: network.c:832
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:1018
#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, 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 1358 of file service.c.

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

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 enum GNUNET_GenericReturnValue 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 1466 of file service.c.

1467{
1468 int tolerant;
1469 struct GNUNET_NETWORK_Handle **csocks = NULL;
1470 struct GNUNET_NETWORK_Handle **lsocks;
1471 const char *nfds;
1472 unsigned int cnt;
1473 int flags;
1474 char dummy[2];
1475
1477 sh->service_name,
1478 "TOLERANT"))
1479 {
1480 if (GNUNET_SYSERR ==
1482 sh->service_name,
1483 "TOLERANT")))
1484 {
1486 _ ("Specified value for `%s' of service `%s' is invalid\n"),
1487 "TOLERANT",
1488 sh->service_name);
1489 return GNUNET_SYSERR;
1490 }
1491 }
1492 else
1493 tolerant = GNUNET_NO;
1494
1495 lsocks = NULL;
1496 errno = 0;
1497 if ( (NULL != (nfds = getenv ("LISTEN_FDS"))) &&
1498 (1 == sscanf (nfds, "%u%1s", &cnt, dummy)) && (cnt > 0) &&
1499 (cnt < FD_SETSIZE) && (cnt + 4 < FD_SETSIZE))
1500 {
1501 lsocks = GNUNET_new_array (cnt + 1, struct GNUNET_NETWORK_Handle *);
1502 while (0 < cnt--)
1503 {
1504 flags = fcntl (3 + cnt, F_GETFD);
1505 if ((flags < 0) || (0 != (flags & FD_CLOEXEC)) ||
1506 (NULL == (lsocks[cnt] = GNUNET_NETWORK_socket_box_native (3 + cnt))))
1507 {
1509 _ (
1510 "Could not access pre-bound socket %u, will try to bind myself\n"),
1511 (unsigned int) 3 + cnt);
1512 cnt++;
1513 while (NULL != lsocks[cnt])
1515 GNUNET_NETWORK_socket_close (lsocks[cnt++]));
1516 GNUNET_free (lsocks);
1517 lsocks = NULL;
1518 break;
1519 }
1520 }
1521 unsetenv ("LISTEN_FDS");
1522 }
1523 if ( (0 != (GNUNET_SERVICE_OPTION_CLOSE_LSOCKS & sh->options)) &&
1524 (NULL != lsocks) )
1525 {
1526 csocks = lsocks;
1527 lsocks = NULL;
1528 }
1529
1530 if (NULL != lsocks)
1531 {
1532 /* listen only on inherited sockets if we have any */
1533 for (struct GNUNET_NETWORK_Handle **ls = lsocks; NULL != *ls; ls++)
1534 {
1535 struct ServiceListenContext *slc;
1536
1537 slc = GNUNET_new (struct ServiceListenContext);
1538 slc->sh = sh;
1539 slc->listen_socket = *ls;
1541 sh->slc_tail,
1542 slc);
1543 }
1544 GNUNET_free (lsocks);
1545 }
1546 else
1547 {
1548 struct sockaddr **addrs;
1549 socklen_t *addrlens;
1550 int num;
1551
1552 num = get_server_addresses (sh->service_name, sh->cfg, &addrs, &addrlens);
1553 if (GNUNET_SYSERR == num)
1554 return GNUNET_SYSERR;
1555
1556 for (int i = 0; i < num; i++)
1557 {
1558 struct ServiceListenContext *slc;
1559
1560 slc = GNUNET_new (struct ServiceListenContext);
1561 slc->sh = sh;
1562 slc->listen_socket = open_listen_socket (addrs[i],
1563 addrlens[i]);
1564 GNUNET_free (addrs[i]);
1565 if (NULL == slc->listen_socket)
1566 {
1568 GNUNET_free (slc);
1569 continue;
1570 }
1572 sh->slc_tail,
1573 slc);
1574 }
1575 GNUNET_free (addrlens);
1576 GNUNET_free (addrs);
1577 if ((0 != num) && (NULL == sh->slc_head))
1578 {
1579 /* All attempts to bind failed, hard failure */
1580 GNUNET_log (
1582 _ (
1583 "Could not bind to any of the ports I was supposed to, refusing to run!\n"));
1584 GNUNET_free (csocks);
1585 return GNUNET_SYSERR;
1586 }
1587 }
1588 if (NULL != csocks)
1589 {
1590 /* close inherited sockets to signal parent that we are ready */
1591 for (struct GNUNET_NETWORK_Handle **ls = csocks; NULL != *ls; ls++)
1593 GNUNET_free (csocks);
1594 }
1595 sh->require_found = (GNUNET_NO == tolerant);
1597 sh->service_name,
1598 "UNIX_MATCH_UID");
1600 sh->service_name,
1601 "UNIX_MATCH_GID");
1602 process_acl4 (&sh->v4_denied, sh, "REJECT_FROM");
1603 process_acl4 (&sh->v4_allowed, sh, "ACCEPT_FROM");
1604 process_acl6 (&sh->v6_denied, sh, "REJECT_FROM6");
1605 process_acl6 (&sh->v6_allowed, sh, "ACCEPT_FROM6");
1606 return GNUNET_OK;
1607}
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:579
@ GNUNET_SERVICE_OPTION_CLOSE_LSOCKS
Instead of listening on lsocks passed by the parent, close them after opening our own listen socket(s...
static enum GNUNET_GenericReturnValue process_acl4(struct GNUNET_STRINGS_IPv4NetworkPolicy **ret, struct GNUNET_SERVICE_Handle *sh, const char *option)
Parse an IPv4 access control list.
Definition: service.c:937
static int get_server_addresses(const char *service_name, const struct GNUNET_CONFIGURATION_Handle *cfg, struct sockaddr ***addrs, socklen_t **addr_lens)
Get the list of addresses that a server for the given service should bind to.
Definition: service.c:1062
static enum GNUNET_GenericReturnValue process_acl6(struct GNUNET_STRINGS_IPv6NetworkPolicy **ret, struct GNUNET_SERVICE_Handle *sh, const char *option)
Parse an IPv6 access control list.
Definition: service.c:978
static struct GNUNET_NETWORK_Handle * open_listen_socket(const struct sockaddr *server_addr, socklen_t socklen)
Create and initialize a listen socket for the server.
Definition: service.c:1358

References _, GNUNET_IDENTITY_Handle::cfg, 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, ServiceListenContext::listen_socket, LOG, ls, open_listen_socket(), process_acl4(), process_acl6(), sh, and ServiceListenContext::sh.

Referenced by GNUNET_SERVICE_run_(), GNUNET_SERVICE_start(), and launch_registered_services().

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 1618 of file service.c.

1619{
1620 char *un;
1621
1622 if (GNUNET_OK !=
1624 sh->service_name,
1625 "USERNAME",
1626 &un))
1627 return NULL;
1628 return un;
1629}

References GNUNET_IDENTITY_Handle::cfg, 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 enum GNUNET_GenericReturnValue 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 1639 of file service.c.

1640{
1641 char *user;
1642 struct passwd *pws;
1643
1644 if (NULL == (user = get_user_name (sh)))
1645 return GNUNET_OK; /* keep */
1646 errno = 0;
1647 pws = getpwnam (user);
1648 if (NULL == pws)
1649 {
1651 _ ("Cannot obtain information about user `%s': %s\n"),
1652 user,
1653 errno == 0 ? _ ("No such user") : strerror (errno));
1654 GNUNET_free (user);
1655 return GNUNET_SYSERR;
1656 }
1657 if ((0 != setgid (pws->pw_gid)) || (0 != setegid (pws->pw_gid)) ||
1658#if HAVE_INITGROUPS
1659 (0 != initgroups (user, pws->pw_gid)) ||
1660#endif
1661 (0 != setuid (pws->pw_uid)) ||
1662 (0 != seteuid (pws->pw_uid)))
1663 {
1664 if ((0 != setregid (pws->pw_gid, pws->pw_gid)) ||
1665 (0 != setreuid (pws->pw_uid, pws->pw_uid)))
1666 {
1668 _ ("Cannot change user/group to `%s': %s\n"),
1669 user,
1670 strerror (errno));
1671 GNUNET_free (user);
1672 return GNUNET_SYSERR;
1673 }
1674 }
1675
1676 GNUNET_free (user);
1677 return GNUNET_OK;
1678}
static char * get_user_name(struct GNUNET_SERVICE_Handle *sh)
Get the name of the user that'll be used to provide the service.
Definition: service.c:1618

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

Referenced by GNUNET_SERVICE_run_(), and launch_registered_services().

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 1689 of file service.c.

1690{
1691 char *pif;
1692
1693 if (GNUNET_OK !=
1695 sh->service_name,
1696 "PIDFILE",
1697 &pif))
1698 return NULL;
1699 return pif;
1700}

References GNUNET_IDENTITY_Handle::cfg, 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 1709 of file service.c.

1710{
1711 char *pif = get_pid_file_name (sh);
1712
1713 if (NULL == pif)
1714 return; /* no PID file */
1715 if (0 != unlink (pif))
1717 "unlink",
1718 pif);
1719 GNUNET_free (pif);
1720}
static char * get_pid_file_name(struct GNUNET_SERVICE_Handle *sh)
Get the name of the file where we will write the PID of the service.
Definition: service.c:1689
#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 enum GNUNET_GenericReturnValue 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 1730 of file service.c.

1731{
1732 pid_t pid;
1733 int nullfd;
1734 int filedes[2];
1735
1736 if (0 != pipe (filedes))
1737 {
1739 "pipe");
1740 return GNUNET_SYSERR;
1741 }
1742 pid = fork ();
1743 if (pid < 0)
1744 {
1746 "fork");
1747 return GNUNET_SYSERR;
1748 }
1749 if (0 != pid)
1750 {
1751 /* Parent */
1752 char c;
1753
1754 GNUNET_break (0 == close (filedes[1]));
1755 c = 'X';
1756 if (1 != read (filedes[0], &c, sizeof(char)))
1758 "read");
1759 fflush (stdout);
1760 switch (c)
1761 {
1762 case '.':
1763 exit (0);
1764
1765 case 'I':
1767 _ ("Service process failed to initialize\n"));
1768 break;
1769
1770 case 'S':
1772 _ ("Service process could not initialize server function\n"));
1773 break;
1774
1775 case 'X':
1777 _ ("Service process failed to report status\n"));
1778 break;
1779 }
1780 exit (1); /* child reported error */
1781 }
1782 GNUNET_break (0 == close (0));
1783 GNUNET_break (0 == close (1));
1784 GNUNET_break (0 == close (filedes[0]));
1785 nullfd = open ("/dev/null", O_RDWR | O_APPEND);
1786 if (nullfd < 0)
1787 return GNUNET_SYSERR;
1788 /* set stdin/stdout to /dev/null */
1789 if ((dup2 (nullfd, 0) < 0) || (dup2 (nullfd, 1) < 0))
1790 {
1792 (void) close (nullfd);
1793 return GNUNET_SYSERR;
1794 }
1795 (void) close (nullfd);
1796 /* Detach from controlling terminal */
1797 pid = setsid ();
1798 if (-1 == pid)
1800 "setsid");
1801 sh->ready_confirm_fd = filedes[1];
1802
1803 return GNUNET_OK;
1804}
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 1814 of file service.c.

1815{
1816 struct ServiceListenContext *slc;
1817
1818 GNUNET_free (sh->v4_denied);
1819 GNUNET_free (sh->v6_denied);
1820 GNUNET_free (sh->v4_allowed);
1821 GNUNET_free (sh->v6_allowed);
1822 while (NULL != (slc = sh->slc_head))
1823 {
1825 sh->slc_tail,
1826 slc);
1827 if (NULL != slc->listen_task)
1831 GNUNET_free (slc);
1832 }
1833}
#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 do_registered_services_shutdown(), 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 1843 of file service.c.

1845{
1846 struct GNUNET_SERVICE_Client *client = cls;
1847 struct GNUNET_MQ_Handle *mq;
1848 struct GNUNET_MQ_Envelope *env;
1849 struct GNUNET_MessageHeader *res;
1850 size_t slen;
1852
1853 (void) msg;
1854 slen = strlen (pd->agpl_url) + 1;
1857 memcpy (&res[1],
1859 slen);
1863}
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:304
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct.
Definition: gnunet_mq_lib.h:63
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:2566
Handle to a message queue.
Definition: mq.c:87
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_register_(), GNUNET_SERVICE_run_(), and GNUNET_SERVICE_start().

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 1903 of file service.c.

1904{
1905 struct GNUNET_SERVICE_Client *c = cls;
1906 struct GNUNET_SERVICE_Handle *sh = c->sh;
1907
1908 c->drop_task = NULL;
1909 GNUNET_CONTAINER_DLL_remove (sh->clients_head,
1910 sh->clients_tail,
1911 c);
1912 GNUNET_assert (NULL == c->send_task);
1913 GNUNET_assert (NULL == c->recv_task);
1914 GNUNET_assert (NULL == c->warn_task);
1916 GNUNET_MQ_destroy (c->mq);
1917 if (! c->persist)
1918 {
1921 if ((0 != (SUSPEND_STATE_EMFILE & sh->suspend_state)) &&
1922 (0 == (SUSPEND_STATE_SHUTDOWN & sh->suspend_state)))
1923 do_resume (sh,
1925 }
1926 else
1927 {
1929 }
1930 GNUNET_free (c);
1931 if ((0 != (SUSPEND_STATE_SHUTDOWN & sh->suspend_state)) &&
1934}
void GNUNET_MQ_destroy(struct GNUNET_MQ_Handle *mq)
Destroy the message queue.
Definition: mq.c:683
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
void GNUNET_MST_destroy(struct GNUNET_MessageStreamTokenizer *mst)
Destroys a tokenizer.
Definition: mst.c:404
bool persist
Persist the file handle for this client no matter what happens, force the OS to close once the proces...
Definition: service.c:327

References do_resume(), GNUNET_SERVICE_Client::drop_task, GNUNET_assert, GNUNET_break, GNUNET_CONTAINER_DLL_remove, GNUNET_free, GNUNET_MQ_destroy(), GNUNET_MST_destroy(), GNUNET_NETWORK_socket_close(), GNUNET_NETWORK_socket_free_memory_only_(), 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(), and GNUNET_SERVICE_stop().

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

◆ do_registered_services_shutdown()

static void do_registered_services_shutdown ( void *  cls)
static

Definition at line 2238 of file service.c.

2239{
2240 while (NULL != hll_head)
2241 {
2242 struct ServiceHandleList *shl = hll_head;
2243 struct GNUNET_SERVICE_Handle *sh = shl->sh;
2244
2246 hll_tail,
2247 shl);
2248 GNUNET_free (shl);
2249 if (-1 != sh->ready_confirm_fd)
2250 {
2251 if (1 != write (sh->ready_confirm_fd, "S", 1))
2253 "write");
2254 GNUNET_break (0 ==
2255 close (sh->ready_confirm_fd));
2256 }
2258 GNUNET_free (sh->handlers);
2259 GNUNET_free (sh);
2260 }
2261}
static void teardown_service(struct GNUNET_SERVICE_Handle *sh)
Tear down the service, closing the listen sockets and freeing the ACLs.
Definition: service.c:1814
static struct ServiceHandleList * hll_head
Definition: service.c:2199
static struct ServiceHandleList * hll_tail
Definition: service.c:2202
A list of service to be launched when GNUNET_SERVICE_main() is called.
Definition: service.c:2187
struct GNUNET_SERVICE_Handle * sh
Definition: service.c:2195

References GNUNET_break, GNUNET_CONTAINER_DLL_remove, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, hll_head, hll_tail, LOG_STRERROR, sh, ServiceHandleList::sh, and teardown_service().

Referenced by launch_registered_services().

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

◆ launch_registered_services()

static void launch_registered_services ( void *  cls)
static

Definition at line 2265 of file service.c.

2266{
2267 struct GNUNET_CONFIGURATION_Handle *cfg = cls;
2268
2269 for (struct ServiceHandleList *shl = hll_head;
2270 NULL != shl;
2271 shl = shl->next)
2272 {
2273 shl->sh->cfg = cfg;
2274 if (GNUNET_OK != setup_service (shl->sh))
2275 continue;
2276 if (GNUNET_OK != set_user_id (shl->sh))
2277 continue;
2279 shl->sh);
2280 }
2282 NULL);
2283}
static void do_registered_services_shutdown(void *cls)
Definition: service.c:2238
static enum GNUNET_GenericReturnValue setup_service(struct GNUNET_SERVICE_Handle *sh)
Setup service handle.
Definition: service.c:1466
static enum GNUNET_GenericReturnValue set_user_id(struct GNUNET_SERVICE_Handle *sh)
Set user ID.
Definition: service.c:1639
static void service_main(void *cls)
First task run by any service.
Definition: service.c:906
struct ServiceHandleList * next
Definition: service.c:2192

References cfg, do_registered_services_shutdown(), GNUNET_OK, GNUNET_SCHEDULER_add_now(), GNUNET_SCHEDULER_add_shutdown(), hll_head, ServiceHandleList::next, service_main(), set_user_id(), and setup_service().

Referenced by GNUNET_SERVICE_main().

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 2424 of file service.c.

2425{
2426 struct GNUNET_SERVICE_Client *c = cls;
2427 int ret;
2428
2429 c->recv_task = NULL;
2430 /* first, check if there is still something in the buffer */
2431 ret = GNUNET_MST_next (c->mst,
2432 GNUNET_YES);
2433 if (GNUNET_SYSERR == ret)
2434 {
2435 if (NULL == c->drop_task)
2437 return;
2438 }
2439 if (GNUNET_NO == ret)
2440 return; /* done processing, wait for more later */
2442 if (c->needs_continue)
2443 return; /* #GNUNET_MST_next() did give a message to the client */
2444 /* need to receive more data from the network first */
2445 if (NULL != c->recv_task)
2446 return;
2448 c->sock,
2450 c);
2451}
enum GNUNET_GenericReturnValue GNUNET_MST_next(struct GNUNET_MessageStreamTokenizer *mst, int one_shot)
Obtain the next message from the mst, assuming that there are more unprocessed messages in the intern...
Definition: mst.c:387

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:

Variable Documentation

◆ hll_head

struct ServiceHandleList* hll_head
static

◆ hll_tail

struct ServiceHandleList* hll_tail
static

Definition at line 2202 of file service.c.

Referenced by do_registered_services_shutdown(), and GNUNET_SERVICE_register_().