GNUnet 0.22.2
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...
 
struct  LaunchContext
 

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 (const struct GNUNET_OS_ProjectData *pd, 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 struct GNUNET_OS_ProjectData *pd, 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_ (const struct GNUNET_OS_ProjectData *pd, 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 struct GNUNET_OS_ProjectData *pd, 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 (const struct GNUNET_OS_ProjectData *pd, int argc, char *const *argv, struct GNUNET_CONFIGURATION_Handle *cfg, enum GNUNET_GenericReturnValue with_scheduler)
 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 39 of file service.c.

◆ LOG_STRERROR

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

Definition at line 41 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 44 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 83 of file service.c.

84{
89
94
99
104
109};
@ SUSPEND_STATE_SHUTDOWN
Suspension because service was permanently shutdown.
Definition: service.c:108
@ SUSPEND_STATE_APP
Application requested it.
Definition: service.c:93
@ SUSPEND_STATE_NONE
We are running normally.
Definition: service.c:88
@ SUSPEND_STATE_APP_AND_EMFILE
Both reasons, APP and EMFILE apply.
Definition: service.c:103
@ SUSPEND_STATE_EMFILE
OS ran out of file descriptors.
Definition: service.c:98

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

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

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

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

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

411{
412 struct GNUNET_SERVICE_Handle *sh = cls;
413
415 {
418 break;
420 /* This task should never be run if we are using
421 the manual shutdown. */
422 GNUNET_assert (0);
423 break;
425 if (0 == (sh->suspend_state & SUSPEND_STATE_SHUTDOWN))
429 break;
430 }
431}
void GNUNET_SERVICE_shutdown(struct GNUNET_SERVICE_Handle *sh)
Explicitly stops the service.
Definition: service.c:2467
@ 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:383
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:359
Handle to a service.
Definition: service.c:116

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

444{
445 for (unsigned int i = 0;
446 0 != list[i].network.s_addr;
447 i++)
448 {
449 if ( (add->s_addr & list[i].netmask.s_addr) ==
450 (list[i].network.s_addr & list[i].netmask.s_addr) )
451 return true;
452 }
453 return false;
454}
static int list
Set if we should print a list of currently running services.
Definition: gnunet-arm.c:68
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 465 of file service.c.

467{
468 for (unsigned int i = 0;
469 ! GNUNET_is_zero (&list[i].network);
470 i++)
471 {
472 bool match = true;
473
474 for (unsigned int j = 0; j < sizeof(struct in6_addr) / sizeof(int); j++)
475 if (((((int *) ip)[j] & ((int *) &list[i].netmask)[j])) !=
476 (((int *) &list[i].network)[j] & ((int *) &list[i].netmask)[j]))
477 {
478 match = false;
479 break;
480 }
481 if (match)
482 return true;
483 }
484 return false;
485}
#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 495 of file service.c.

496{
497 struct GNUNET_SERVICE_Client *client = cls;
498 ssize_t ret;
499 size_t left;
500 const char *buf;
501
503 "service: sending message with type %u\n",
504 ntohs (client->msg->type));
505 client->send_task = NULL;
506 buf = (const char *) client->msg;
507 left = ntohs (client->msg->size) - client->msg_pos;
509 &buf[client->msg_pos],
510 left);
511 GNUNET_assert (ret <= (ssize_t) left);
512 if (0 == ret)
513 {
514 LOG (GNUNET_ERROR_TYPE_DEBUG, "no data send");
516 return;
517 }
518 if (-1 == ret)
519 {
520 if ((EAGAIN == errno) || (EINTR == errno))
521 {
522 /* ignore */
523 ret = 0;
524 }
525 else
526 {
527 if (EPIPE != errno)
530 "socket send returned with error code %i",
531 errno);
533 return;
534 }
535 }
536 if (0 == client->msg_pos)
537 {
539 }
540 client->msg_pos += ret;
541 if (left > (size_t) ret)
542 {
543 GNUNET_assert (NULL == client->drop_task);
544 client->send_task =
546 client->sock,
547 &do_send,
548 client);
549 return;
550 }
552}
static int ret
Final status code.
Definition: gnunet-arm.c:93
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.
#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:437
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:461
@ 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:738
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:1582
#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:495
#define LOG(kind,...)
Definition: service.c:39
size_t msg_pos
Current position in msg at which we are transmitting.
Definition: service.c:323
struct GNUNET_SCHEDULER_Task * send_task
Task that transmit data to the client.
Definition: service.c:301
struct GNUNET_SCHEDULER_Task * drop_task
Task run to finish dropping the client after the stack has properly unwound.
Definition: service.c:290
struct GNUNET_NETWORK_Handle * sock
Socket of this client.
Definition: service.c:268
const struct GNUNET_MessageHeader * msg
Pointer to the message to be transmitted by send_task.
Definition: service.c:306
struct GNUNET_MQ_Handle * mq
Message queue for the client.
Definition: service.c:273

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

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

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

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

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

617{
618 struct GNUNET_SERVICE_Client *client = cls;
619 struct GNUNET_SERVICE_Handle *sh = client->sh;
620
621 if ( (GNUNET_MQ_ERROR_NO_MATCH == error) &&
622 (! 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:2418
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2389
uint16_t warn_type
Type of last message processed (for warn_no_receive_done).
Definition: service.c:347
struct GNUNET_SERVICE_Handle * sh
Service that this client belongs to.
Definition: service.c:263

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

641{
642 struct GNUNET_SERVICE_Client *client = cls;
643
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}
@ 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:1277
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:438
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:579
#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:640
struct GNUNET_TIME_Absolute warn_start
Time when we last gave a message from this client to the application.
Definition: service.c:318
struct GNUNET_SCHEDULER_Task * warn_task
Task that warns about missing calls to GNUNET_SERVICE_client_continue().
Definition: service.c:284

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 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));
682 GNUNET_assert (! client->needs_continue);
683 client->needs_continue = true;
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
@ 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:342

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 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 {
719 GNUNET_assert (! client->needs_continue);
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 (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.
@ 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:1511
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:704
struct GNUNET_SCHEDULER_Task * recv_task
Task that receives data from the client to pass it to the handlers.
Definition: service.c:296
struct GNUNET_MessageStreamTokenizer * mst
Tokenizer we use for processing incoming data.
Definition: service.c:278

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 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,
756 sh->clients_tail,
757 client);
758 client->sh = sh;
759 client->sock = csock;
761 NULL,
763 client,
764 sh->handlers,
766 client);
767 client->mst = GNUNET_MST_create (&service_client_mst_cb, client);
768 if (NULL != sh->connect_cb)
769 client->user_context = sh->connect_cb (sh->cb_cls, client, client->mq);
771 client->recv_task =
773 client->sock,
775 client);
776}
#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:482
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:506
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:592
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:564
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:615
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:312

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

787{
788 struct ServiceListenContext *slc = cls;
789 struct GNUNET_SERVICE_Handle *sh = slc->sh;
790
791 slc->listen_task = NULL;
792 while (1)
793 {
794 struct GNUNET_NETWORK_Handle *sock;
795 const struct sockaddr_in *v4;
796 const struct sockaddr_in6 *v6;
797 struct sockaddr_storage sa;
798 socklen_t addrlen;
799 int ok;
800
801 addrlen = sizeof(sa);
803 (struct sockaddr *) &sa,
804 &addrlen);
805 if (NULL == sock)
806 {
807 if (EMFILE == errno)
809 else if (EAGAIN != errno)
811 "accept");
812 break;
813 }
814 switch (sa.ss_family)
815 {
816 case AF_INET:
817 GNUNET_assert (addrlen == sizeof(struct sockaddr_in));
818 v4 = (const struct sockaddr_in *) &sa;
819 ok = (((NULL == sh->v4_allowed) ||
820 (check_ipv4_listed (sh->v4_allowed,
821 &v4->sin_addr))) &&
822 ((NULL == sh->v4_denied) ||
823 (! check_ipv4_listed (sh->v4_denied,
824 &v4->sin_addr))));
825 break;
826
827 case AF_INET6:
828 GNUNET_assert (addrlen == sizeof(struct sockaddr_in6));
829 v6 = (const struct sockaddr_in6 *) &sa;
830 ok = (((NULL == sh->v6_allowed) ||
831 (check_ipv6_listed (sh->v6_allowed,
832 &v6->sin6_addr))) &&
833 ((NULL == sh->v6_denied) ||
834 (! check_ipv6_listed (sh->v6_denied,
835 &v6->sin6_addr))));
836 break;
837
838 case AF_UNIX:
839 ok = GNUNET_OK; /* controlled using file-system ACL now */
840 break;
841
842 default:
844 _ ("Unknown address family %d\n"),
845 sa.ss_family);
846 return;
847 }
848 if (! ok)
849 {
851 "Service rejected incoming connection from %s due to policy.\n",
852 GNUNET_a2s ((const struct sockaddr *) &sa, addrlen));
854 continue;
855 }
857 "Service accepted incoming connection from %s.\n",
858 GNUNET_a2s ((const struct sockaddr *) &sa, addrlen));
859 start_client (slc->sh,
860 sock);
861 }
862 if (0 != sh->suspend_state)
863 return;
864 slc->listen_task =
866 slc->listen_socket,
868 slc);
869}
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:465
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 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:442
static void accept_client(void *cls)
We have a client.
Definition: service.c:786
handle to a socket
Definition: network.c:53
struct GNUNET_SCHEDULER_Task * listen_task
Task scheduled to do the listening.
Definition: service.c:76
struct GNUNET_NETWORK_Handle * listen_socket
Socket we are listening on.
Definition: service.c:71
struct GNUNET_SERVICE_Handle * sh
Service this listen context belongs to.
Definition: service.c:66

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

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

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

910{
911 struct GNUNET_SERVICE_Handle *sh = cls;
912
917
918 if (-1 != sh->ready_confirm_fd)
919 {
920 GNUNET_break (1 == write (sh->ready_confirm_fd, ".", 1));
921 GNUNET_break (0 == close (sh->ready_confirm_fd));
922 sh->ready_confirm_fd = -1;
923 }
924
925 if (NULL != sh->service_init_cb)
926 sh->service_init_cb (sh->cb_cls, sh->cfg, sh);
927}
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:1339
static void do_resume(struct GNUNET_SERVICE_Handle *sh, enum SuspendReason sr)
Resume accepting connections from the listen socket.
Definition: service.c:880
static void service_shutdown(void *cls)
Shutdown task triggered when a service should be terminated.
Definition: service.c:410
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 940 of file service.c.

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

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

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

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

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

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

1069{
1070 bool disablev6;
1071 struct GNUNET_NETWORK_Handle *desc;
1072 unsigned long long port;
1073 char *unixpath;
1074 struct addrinfo hints;
1075 struct addrinfo *res;
1076 struct addrinfo *pos;
1077 struct addrinfo *next;
1078 unsigned int i;
1079 int resi;
1080 int ret;
1081 struct sockaddr **saddrs;
1082 socklen_t *saddrlens;
1083 char *hostname;
1084
1085 *addrs = NULL;
1086 *addr_lens = NULL;
1087 desc = NULL;
1088 disablev6 = false;
1089 if ((GNUNET_NO ==
1090 GNUNET_NETWORK_test_pf (PF_INET6)) ||
1091 (GNUNET_YES ==
1094 "DISABLEV6")))
1095 disablev6 = true;
1096
1097 port = 0;
1098 if (GNUNET_SYSERR ==
1101 "PORT",
1102 &port))
1103 {
1105 _ ("Require valid port number for service `%s' in configuration!\n"),
1106 service_name);
1107 }
1108 if (port > 65535)
1109 {
1111 _ ("Require valid port number for service `%s' in configuration!\n"),
1112 service_name);
1113 return GNUNET_SYSERR;
1114 }
1115
1116 hostname = NULL;
1120 "BINDTO",
1121 &hostname));
1122
1123 unixpath = NULL;
1124#ifdef AF_UNIX
1125 if ( (GNUNET_OK ==
1128 "UNIXPATH",
1129 &unixpath)) &&
1130 (0 < strlen (unixpath)) )
1131 {
1132 /* probe UNIX support */
1133 struct sockaddr_un s_un;
1134
1135 if (strlen (unixpath) >= sizeof(s_un.sun_path))
1136 {
1138 "UNIXPATH `%s' too long, maximum length is %llu\n",
1139 unixpath,
1140 (unsigned long long) sizeof(s_un.sun_path));
1141 unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath);
1143 _ ("Using `%s' instead\n"),
1144 unixpath);
1145 }
1146 if (GNUNET_OK !=
1149 "mkdir",
1150 unixpath);
1151 }
1152 if (NULL != unixpath)
1153 {
1154 desc = GNUNET_NETWORK_socket_create (AF_UNIX,
1155 SOCK_STREAM,
1156 0);
1157 if (NULL == desc)
1158 {
1159 if ((ENOBUFS == errno) ||
1160 (ENOMEM == errno) ||
1161 (ENFILE == errno) ||
1162 (EACCES == errno))
1163 {
1165 "socket");
1166 GNUNET_free (hostname);
1167 GNUNET_free (unixpath);
1168 return GNUNET_SYSERR;
1169 }
1171 "Failed to create UNIX domain socket for service %s: %s\n",
1173 strerror (errno));
1174 GNUNET_free (unixpath);
1175 unixpath = NULL;
1176 }
1177 else
1178 {
1181 desc = NULL;
1182 }
1183 }
1184#endif
1185
1186 if ( (0 == port) &&
1187 (NULL == unixpath) )
1188 {
1190 "Have neither PORT nor UNIXPATH for service `%s', but one is required\n",
1191 service_name);
1192 GNUNET_free (hostname);
1193 return GNUNET_SYSERR;
1194 }
1195 if (0 == port)
1196 {
1197 saddrs = GNUNET_new_array (2, struct sockaddr *);
1198 saddrlens = GNUNET_new_array (2, socklen_t);
1199 add_unixpath (saddrs, saddrlens, unixpath);
1200 GNUNET_free (unixpath);
1201 GNUNET_free (hostname);
1202 *addrs = saddrs;
1203 *addr_lens = saddrlens;
1204 return 1;
1205 }
1206
1207 if (NULL != hostname)
1208 {
1210 "Resolving `%s' since that is where `%s' will bind to.\n",
1211 hostname,
1212 service_name);
1213 memset (&hints, 0, sizeof(struct addrinfo));
1214 if (disablev6)
1215 hints.ai_family = AF_INET;
1216 hints.ai_protocol = IPPROTO_TCP;
1217 if ((0 != (ret = getaddrinfo (hostname, NULL, &hints, &res))) ||
1218 (NULL == res))
1219 {
1221 _ ("Failed to resolve `%s': %s\n"),
1222 hostname,
1223 gai_strerror (ret));
1224 GNUNET_free (hostname);
1225 GNUNET_free (unixpath);
1226 return GNUNET_SYSERR;
1227 }
1228 next = res;
1229 i = 0;
1230 while (NULL != (pos = next))
1231 {
1232 next = pos->ai_next;
1233 if ((disablev6) && (pos->ai_family == AF_INET6))
1234 continue;
1235 i++;
1236 }
1237 if (0 == i)
1238 {
1240 _ ("Failed to find %saddress for `%s'.\n"),
1241 disablev6 ? "IPv4 " : "",
1242 hostname);
1243 freeaddrinfo (res);
1244 GNUNET_free (hostname);
1245 GNUNET_free (unixpath);
1246 return GNUNET_SYSERR;
1247 }
1248 resi = i;
1249 if (NULL != unixpath)
1250 resi++;
1251 saddrs = GNUNET_new_array (resi + 1, struct sockaddr *);
1252 saddrlens = GNUNET_new_array (resi + 1, socklen_t);
1253 i = 0;
1254 if (NULL != unixpath)
1255 {
1256 add_unixpath (saddrs, saddrlens, unixpath);
1257 i++;
1258 }
1259 next = res;
1260 while (NULL != (pos = next))
1261 {
1262 next = pos->ai_next;
1263 if ((disablev6) && (AF_INET6 == pos->ai_family))
1264 continue;
1265 if ((IPPROTO_TCP != pos->ai_protocol) && (0 != pos->ai_protocol))
1266 continue; /* not TCP */
1267 if ((SOCK_STREAM != pos->ai_socktype) && (0 != pos->ai_socktype))
1268 continue; /* huh? */
1270 "Service `%s' will bind to `%s'\n",
1272 GNUNET_a2s (pos->ai_addr, pos->ai_addrlen));
1273 if (AF_INET == pos->ai_family)
1274 {
1275 GNUNET_assert (sizeof(struct sockaddr_in) == 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_in *) saddrs[i])->sin_port = htons (port);
1280 }
1281 else
1282 {
1283 GNUNET_assert (AF_INET6 == pos->ai_family);
1284 GNUNET_assert (sizeof(struct sockaddr_in6) == pos->ai_addrlen);
1285 saddrlens[i] = pos->ai_addrlen;
1286 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1287 GNUNET_memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
1288 ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
1289 }
1290 i++;
1291 }
1292 GNUNET_free (hostname);
1293 freeaddrinfo (res);
1294 resi = i;
1295 }
1296 else
1297 {
1298 /* will bind against everything, just set port */
1299 if (disablev6)
1300 {
1301 /* V4-only */
1302 resi = 1;
1303 if (NULL != unixpath)
1304 resi++;
1305 i = 0;
1306 saddrs = GNUNET_new_array (resi + 1, struct sockaddr *);
1307 saddrlens = GNUNET_new_array (resi + 1, socklen_t);
1308 if (NULL != unixpath)
1309 {
1310 add_unixpath (saddrs, saddrlens, unixpath);
1311 i++;
1312 }
1313 saddrlens[i] = sizeof(struct sockaddr_in);
1314 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1315#if HAVE_SOCKADDR_IN_SIN_LEN
1316 ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[i];
1317#endif
1318 ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
1319 ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
1320 }
1321 else
1322 {
1323 /* dual stack */
1324 resi = 2;
1325 if (NULL != unixpath)
1326 resi++;
1327 saddrs = GNUNET_new_array (resi + 1, struct sockaddr *);
1328 saddrlens = GNUNET_new_array (resi + 1, socklen_t);
1329 i = 0;
1330 if (NULL != unixpath)
1331 {
1332 add_unixpath (saddrs, saddrlens, unixpath);
1333 i++;
1334 }
1335 saddrlens[i] = sizeof(struct sockaddr_in6);
1336 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1337#if HAVE_SOCKADDR_IN_SIN_LEN
1338 ((struct sockaddr_in6 *) saddrs[i])->sin6_len = saddrlens[0];
1339#endif
1340 ((struct sockaddr_in6 *) saddrs[i])->sin6_family = AF_INET6;
1341 ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
1342 i++;
1343 saddrlens[i] = sizeof(struct sockaddr_in);
1344 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1345#if HAVE_SOCKADDR_IN_SIN_LEN
1346 ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[1];
1347#endif
1348 ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
1349 ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
1350 }
1351 }
1352 GNUNET_free (unixpath);
1353 *addrs = saddrs;
1354 *addr_lens = saddrlens;
1355 return resi;
1356}
static struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition: gnunet-arm.c:108
static uint16_t port
Port number.
Definition: gnunet-bcd.c:146
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:606
#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:833
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:1021
#define LOG_STRERROR(kind, syscall)
Definition: service.c:41

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

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

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 ( const struct GNUNET_OS_ProjectData pd,
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
pdproject data to use for the service
shservice context to initialize
Returns
GNUNET_OK if configuration succeeded

Definition at line 1476 of file service.c.

1478{
1479 int tolerant;
1480 struct GNUNET_NETWORK_Handle **csocks = NULL;
1481 struct GNUNET_NETWORK_Handle **lsocks;
1482 const char *nfds;
1483 unsigned int cnt;
1484 int flags;
1485 char dummy[2];
1486
1488 sh->service_name,
1489 "TOLERANT"))
1490 {
1491 if (GNUNET_SYSERR ==
1493 sh->service_name,
1494 "TOLERANT")))
1495 {
1497 _ ("Specified value for `%s' of service `%s' is invalid\n"),
1498 "TOLERANT",
1499 sh->service_name);
1500 return GNUNET_SYSERR;
1501 }
1502 }
1503 else
1504 tolerant = GNUNET_NO;
1505
1506 lsocks = NULL;
1507 errno = 0;
1508 if ( (NULL != (nfds = getenv ("LISTEN_FDS"))) &&
1509 (1 == sscanf (nfds, "%u%1s", &cnt, dummy)) && (cnt > 0) &&
1510 (cnt < FD_SETSIZE) && (cnt + 4 < FD_SETSIZE))
1511 {
1512 lsocks = GNUNET_new_array (cnt + 1, struct GNUNET_NETWORK_Handle *);
1513 while (0 < cnt--)
1514 {
1515 flags = fcntl (3 + cnt, F_GETFD);
1516 if ((flags < 0) || (0 != (flags & FD_CLOEXEC)) ||
1517 (NULL == (lsocks[cnt] = GNUNET_NETWORK_socket_box_native (3 + cnt))))
1518 {
1520 _ (
1521 "Could not access pre-bound socket %u, will try to bind myself\n"),
1522 (unsigned int) 3 + cnt);
1523 cnt++;
1524 while (NULL != lsocks[cnt])
1526 GNUNET_NETWORK_socket_close (lsocks[cnt++]));
1527 GNUNET_free (lsocks);
1528 lsocks = NULL;
1529 break;
1530 }
1531 }
1532 unsetenv ("LISTEN_FDS");
1533 }
1534 if ( (0 != (GNUNET_SERVICE_OPTION_CLOSE_LSOCKS & sh->options)) &&
1535 (NULL != lsocks) )
1536 {
1537 csocks = lsocks;
1538 lsocks = NULL;
1539 }
1540
1541 if (NULL != lsocks)
1542 {
1543 /* listen only on inherited sockets if we have any */
1544 for (struct GNUNET_NETWORK_Handle **ls = lsocks; NULL != *ls; ls++)
1545 {
1546 struct ServiceListenContext *slc;
1547
1548 slc = GNUNET_new (struct ServiceListenContext);
1549 slc->sh = sh;
1550 slc->listen_socket = *ls;
1552 sh->slc_tail,
1553 slc);
1554 }
1555 GNUNET_free (lsocks);
1556 }
1557 else
1558 {
1559 struct sockaddr **addrs;
1560 socklen_t *addrlens;
1561 int num;
1562
1563 num = get_server_addresses (sh->service_name, sh->cfg, &addrs, &addrlens);
1564 if (GNUNET_SYSERR == num)
1565 {
1566 GNUNET_free (csocks);
1567 return GNUNET_SYSERR;
1568 }
1569
1570 for (int i = 0; i < num; i++)
1571 {
1572 struct ServiceListenContext *slc;
1573
1574 slc = GNUNET_new (struct ServiceListenContext);
1575 slc->sh = sh;
1576 slc->listen_socket = open_listen_socket (addrs[i],
1577 addrlens[i]);
1578 GNUNET_free (addrs[i]);
1579 if (NULL == slc->listen_socket)
1580 {
1582 GNUNET_free (slc);
1583 continue;
1584 }
1586 sh->slc_tail,
1587 slc);
1588 }
1589 GNUNET_free (addrlens);
1590 GNUNET_free (addrs);
1591 if ((0 != num) && (NULL == sh->slc_head))
1592 {
1593 /* All attempts to bind failed, hard failure */
1594 GNUNET_log (
1596 _ (
1597 "Could not bind to any of the ports I was supposed to, refusing to run!\n"));
1598 GNUNET_free (csocks);
1599 return GNUNET_SYSERR;
1600 }
1601 }
1602 if (NULL != csocks)
1603 {
1604 /* close inherited sockets to signal parent that we are ready */
1605 for (struct GNUNET_NETWORK_Handle **ls = csocks; NULL != *ls; ls++)
1607 GNUNET_free (csocks);
1608 }
1609 sh->require_found = (GNUNET_NO == tolerant);
1611 sh->service_name,
1612 "UNIX_MATCH_UID");
1614 sh->service_name,
1615 "UNIX_MATCH_GID");
1616 process_acl4 (&sh->v4_denied, sh, "REJECT_FROM");
1617 process_acl4 (&sh->v4_allowed, sh, "ACCEPT_FROM");
1618 process_acl6 (&sh->v6_denied, sh, "REJECT_FROM6");
1619 process_acl6 (&sh->v6_allowed, sh, "ACCEPT_FROM6");
1620 return GNUNET_OK;
1621}
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:580
@ 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:940
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:1065
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:981
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:1367

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

1633{
1634 char *un;
1635
1636 if (GNUNET_OK !=
1638 sh->service_name,
1639 "USERNAME",
1640 &un))
1641 return NULL;
1642 return un;
1643}

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

1654{
1655 char *user;
1656 struct passwd *pws;
1657
1658 if (NULL == (user = get_user_name (sh)))
1659 return GNUNET_OK; /* keep */
1660 errno = 0;
1661 pws = getpwnam (user);
1662 if (NULL == pws)
1663 {
1665 _ ("Cannot obtain information about user `%s': %s\n"),
1666 user,
1667 errno == 0 ? _ ("No such user") : strerror (errno));
1668 GNUNET_free (user);
1669 return GNUNET_SYSERR;
1670 }
1671 if ((0 != setgid (pws->pw_gid)) || (0 != setegid (pws->pw_gid)) ||
1672#if HAVE_INITGROUPS
1673 (0 != initgroups (user, pws->pw_gid)) ||
1674#endif
1675 (0 != setuid (pws->pw_uid)) ||
1676 (0 != seteuid (pws->pw_uid)))
1677 {
1678 if ((0 != setregid (pws->pw_gid, pws->pw_gid)) ||
1679 (0 != setreuid (pws->pw_uid, pws->pw_uid)))
1680 {
1682 _ ("Cannot change user/group to `%s': %s\n"),
1683 user,
1684 strerror (errno));
1685 GNUNET_free (user);
1686 return GNUNET_SYSERR;
1687 }
1688 }
1689
1690 GNUNET_free (user);
1691 return GNUNET_OK;
1692}
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:1632

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

1704{
1705 char *pif;
1706
1707 if (GNUNET_OK !=
1709 sh->service_name,
1710 "PIDFILE",
1711 &pif))
1712 return NULL;
1713 return pif;
1714}

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

1724{
1725 char *pif = get_pid_file_name (sh);
1726
1727 if (NULL == pif)
1728 return; /* no PID file */
1729 if (0 != unlink (pif))
1731 "unlink",
1732 pif);
1733 GNUNET_free (pif);
1734}
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:1703
#define LOG_STRERROR_FILE(kind, syscall, filename)
Definition: service.c:44

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

1745{
1746 pid_t pid;
1747 int nullfd;
1748 int filedes[2];
1749
1750 if (0 != pipe (filedes))
1751 {
1753 "pipe");
1754 return GNUNET_SYSERR;
1755 }
1756 pid = fork ();
1757 if (pid < 0)
1758 {
1760 "fork");
1761 return GNUNET_SYSERR;
1762 }
1763 if (0 != pid)
1764 {
1765 /* Parent */
1766 char c;
1767
1768 GNUNET_break (0 == close (filedes[1]));
1769 c = 'X';
1770 if (1 != read (filedes[0], &c, sizeof(char)))
1772 "read");
1773 fflush (stdout);
1774 switch (c)
1775 {
1776 case '.':
1777 exit (0);
1778
1779 case 'I':
1781 _ ("Service process failed to initialize\n"));
1782 break;
1783
1784 case 'S':
1786 _ ("Service process could not initialize server function\n"));
1787 break;
1788
1789 case 'X':
1791 _ ("Service process failed to report status\n"));
1792 break;
1793 }
1794 exit (1); /* child reported error */
1795 }
1796 GNUNET_break (0 == close (0));
1797 GNUNET_break (0 == close (1));
1798 GNUNET_break (0 == close (filedes[0]));
1799 nullfd = open ("/dev/null", O_RDWR | O_APPEND);
1800 if (nullfd < 0)
1801 return GNUNET_SYSERR;
1802 /* set stdin/stdout to /dev/null */
1803 if ((dup2 (nullfd, 0) < 0) || (dup2 (nullfd, 1) < 0))
1804 {
1806 (void) close (nullfd);
1807 return GNUNET_SYSERR;
1808 }
1809 (void) close (nullfd);
1810 /* Detach from controlling terminal */
1811 pid = setsid ();
1812 if (-1 == pid)
1814 "setsid");
1815 sh->ready_confirm_fd = filedes[1];
1816
1817 return GNUNET_OK;
1818}
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 1828 of file service.c.

1829{
1830 struct ServiceListenContext *slc;
1831
1832 GNUNET_free (sh->v4_denied);
1833 GNUNET_free (sh->v6_denied);
1834 GNUNET_free (sh->v4_allowed);
1835 GNUNET_free (sh->v6_allowed);
1836 while (NULL != (slc = sh->slc_head))
1837 {
1839 sh->slc_tail,
1840 slc);
1841 if (NULL != slc->listen_task)
1845 GNUNET_free (slc);
1846 }
1847}
#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 1857 of file service.c.

1859{
1860 struct GNUNET_SERVICE_Client *client = cls;
1861 const struct GNUNET_OS_ProjectData *pd = client->sh->pd;
1862 struct GNUNET_MQ_Handle *mq;
1863 struct GNUNET_MQ_Envelope *env;
1864 struct GNUNET_MessageHeader *res;
1865 size_t slen;
1866
1867 (void) msg;
1868 slen = strlen (pd->agpl_url) + 1;
1871 slen);
1872 memcpy (&res[1],
1874 slen);
1877 env);
1879}
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:305
#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:61
#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:2500
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.
const char * agpl_url
URL pointing to the source code of the application.
const struct GNUNET_OS_ProjectData * pd
Project data of this service.
Definition: service.c:125

References GNUNET_OS_ProjectData::agpl_url, env, GNUNET_AGPL_URL, GNUNET_MESSAGE_TYPE_RESPONSE_AGPL, GNUNET_MQ_msg_extra, GNUNET_MQ_send(), GNUNET_SERVICE_client_continue(), GNUNET_SERVICE_client_get_mq(), mq, msg, GNUNET_SERVICE_Handle::pd, res, and GNUNET_SERVICE_Client::sh.

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

1924{
1925 struct GNUNET_SERVICE_Client *c = cls;
1926 struct GNUNET_SERVICE_Handle *sh = c->sh;
1927
1928 c->drop_task = NULL;
1929 GNUNET_CONTAINER_DLL_remove (sh->clients_head,
1930 sh->clients_tail,
1931 c);
1932 GNUNET_assert (NULL == c->send_task);
1933 GNUNET_assert (NULL == c->recv_task);
1934 GNUNET_assert (NULL == c->warn_task);
1936 GNUNET_MQ_destroy (c->mq);
1937 if (! c->persist)
1938 {
1941 if ((0 != (SUSPEND_STATE_EMFILE & sh->suspend_state)) &&
1942 (0 == (SUSPEND_STATE_SHUTDOWN & sh->suspend_state)))
1943 do_resume (sh,
1945 }
1946 else
1947 {
1949 }
1950 GNUNET_free (c);
1951 if ((0 != (SUSPEND_STATE_SHUTDOWN & sh->suspend_state)) &&
1954}
void GNUNET_MQ_destroy(struct GNUNET_MQ_Handle *mq)
Destroy the message queue.
Definition: mq.c:700
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:566
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:330

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

2243{
2244 while (NULL != hll_head)
2245 {
2246 struct ServiceHandleList *shl = hll_head;
2247 struct GNUNET_SERVICE_Handle *sh = shl->sh;
2248
2250 hll_tail,
2251 shl);
2252 GNUNET_free (shl);
2253 if (-1 != sh->ready_confirm_fd)
2254 {
2255 if (1 != write (sh->ready_confirm_fd, "S", 1))
2257 "write");
2258 GNUNET_break (0 ==
2259 close (sh->ready_confirm_fd));
2260 }
2262 GNUNET_free (sh->handlers);
2263 GNUNET_free (sh);
2264 }
2265}
static void teardown_service(struct GNUNET_SERVICE_Handle *sh)
Tear down the service, closing the listen sockets and freeing the ACLs.
Definition: service.c:1828
static struct ServiceHandleList * hll_head
Definition: service.c:2202
static struct ServiceHandleList * hll_tail
Definition: service.c:2205
A list of service to be launched when GNUNET_SERVICE_main() is called.
Definition: service.c:2190
struct GNUNET_SERVICE_Handle * sh
Definition: service.c:2198

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

2277{
2278 struct LaunchContext *lc = cls;
2279 struct GNUNET_CONFIGURATION_Handle *cfg = lc->cfg;
2280 const struct GNUNET_OS_ProjectData *pd = lc->pd;
2281
2282 for (struct ServiceHandleList *shl = hll_head;
2283 NULL != shl;
2284 shl = shl->next)
2285 {
2286 shl->sh->cfg = cfg;
2287 if (GNUNET_OK !=
2288 setup_service (pd,
2289 shl->sh))
2290 continue;
2291 if (GNUNET_OK !=
2292 set_user_id (shl->sh))
2293 continue;
2295 shl->sh);
2296 }
2298 NULL);
2299}
static void do_registered_services_shutdown(void *cls)
Definition: service.c:2242
static enum GNUNET_GenericReturnValue setup_service(const struct GNUNET_OS_ProjectData *pd, struct GNUNET_SERVICE_Handle *sh)
Setup service handle.
Definition: service.c:1476
static enum GNUNET_GenericReturnValue set_user_id(struct GNUNET_SERVICE_Handle *sh)
Set user ID.
Definition: service.c:1653
static void service_main(void *cls)
First task run by any service.
Definition: service.c:909
struct GNUNET_CONFIGURATION_Handle * cfg
Definition: service.c:2270
const struct GNUNET_OS_ProjectData * pd
Definition: service.c:2271
struct ServiceHandleList * next
Definition: service.c:2195

References cfg, LaunchContext::cfg, do_registered_services_shutdown(), GNUNET_OK, GNUNET_SCHEDULER_add_now(), GNUNET_SCHEDULER_add_shutdown(), hll_head, ServiceHandleList::next, LaunchContext::pd, 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 2358 of file service.c.

2359{
2360 struct GNUNET_SERVICE_Client *c = cls;
2361 int ret;
2362
2363 c->recv_task = NULL;
2364 /* first, check if there is still something in the buffer */
2365 ret = GNUNET_MST_next (c->mst,
2366 GNUNET_YES);
2367 if (GNUNET_SYSERR == ret)
2368 {
2369 if (NULL == c->drop_task)
2371 return;
2372 }
2373 if (GNUNET_NO == ret)
2374 return; /* done processing, wait for more later */
2376 if (c->needs_continue)
2377 return; /* #GNUNET_MST_next() did give a message to the client */
2378 /* need to receive more data from the network first */
2379 if (NULL != c->recv_task)
2380 return;
2382 c->sock,
2384 c);
2385}
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 2205 of file service.c.

Referenced by do_registered_services_shutdown(), and GNUNET_SERVICE_register_().