GNUnet 0.22.0
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, 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 355 of file service.c.

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

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

381{
382 GNUNET_assert (0 == (sh->suspend_state & sr));
383 sh->suspend_state |= sr;
384 for (struct ServiceListenContext *slc = sh->slc_head;
385 NULL != slc;
386 slc = slc->next)
387 {
388 if (NULL != slc->listen_task)
389 {
390 GNUNET_SCHEDULER_cancel (slc->listen_task);
391 slc->listen_task = NULL;
392 }
393 }
394}
#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:979
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 406 of file service.c.

407{
408 struct GNUNET_SERVICE_Handle *sh = cls;
409
411 {
414 break;
416 /* This task should never be run if we are using
417 the manual shutdown. */
418 GNUNET_assert (0);
419 break;
421 if (0 == (sh->suspend_state & SUSPEND_STATE_SHUTDOWN))
425 break;
426 }
427}
void GNUNET_SERVICE_shutdown(struct GNUNET_SERVICE_Handle *sh)
Explicitly stops the service.
Definition: service.c:2426
@ 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:379
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:355
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 438 of file service.c.

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

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

492{
493 struct GNUNET_SERVICE_Client *client = cls;
494 ssize_t ret;
495 size_t left;
496 const char *buf;
497
499 "service: sending message with type %u\n",
500 ntohs (client->msg->type));
501 client->send_task = NULL;
502 buf = (const char *) client->msg;
503 left = ntohs (client->msg->size) - client->msg_pos;
505 &buf[client->msg_pos],
506 left);
507 GNUNET_assert (ret <= (ssize_t) left);
508 if (0 == ret)
509 {
510 LOG (GNUNET_ERROR_TYPE_DEBUG, "no data send");
512 return;
513 }
514 if (-1 == ret)
515 {
516 if ((EAGAIN == errno) || (EINTR == errno))
517 {
518 /* ignore */
519 ret = 0;
520 }
521 else
522 {
523 if (EPIPE != errno)
526 "socket send returned with error code %i",
527 errno);
529 return;
530 }
531 }
532 if (0 == client->msg_pos)
533 {
535 }
536 client->msg_pos += ret;
537 if (left > (size_t) ret)
538 {
539 GNUNET_assert (NULL == client->drop_task);
540 client->send_task =
542 client->sock,
543 &do_send,
544 client);
545 return;
546 }
548}
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:1581
#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:491
#define LOG(kind,...)
Definition: service.c:39
size_t msg_pos
Current position in msg at which we are transmitting.
Definition: service.c:319
struct GNUNET_SCHEDULER_Task * send_task
Task that transmit data to the client.
Definition: service.c:297
struct GNUNET_SCHEDULER_Task * drop_task
Task run to finish dropping the client after the stack has properly unwound.
Definition: service.c:286
struct GNUNET_NETWORK_Handle * sock
Socket of this client.
Definition: service.c:264
const struct GNUNET_MessageHeader * msg
Pointer to the message to be transmitted by send_task.
Definition: service.c:302
struct GNUNET_MQ_Handle * mq
Message queue for the client.
Definition: service.c:269

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

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

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

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

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

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

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

637{
638 struct GNUNET_SERVICE_Client *client = cls;
639
641 0 !=
642 client->warn_type); /* type should never be 0 here, as we don't use 0 */
645 client);
646 LOG (
648 _ (
649 "Processing code for message of type %u did not call `GNUNET_SERVICE_client_continue' after %s\n"),
650 (unsigned int) client->warn_type,
652 client->warn_start),
653 GNUNET_YES));
654}
@ 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:1276
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: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:636
struct GNUNET_TIME_Absolute warn_start
Time when we last gave a message from this client to the application.
Definition: service.c:314
struct GNUNET_SCHEDULER_Task * warn_task
Task that warns about missing calls to GNUNET_SERVICE_client_continue().
Definition: service.c:280

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

671{
672 struct GNUNET_SERVICE_Client *client = cls;
673
675 "Received message of type %u and size %u from client\n",
676 ntohs (message->type),
677 ntohs (message->size));
678 GNUNET_assert (! client->needs_continue);
679 client->needs_continue = true;
680 client->warn_type = ntohs (message->type);
682 GNUNET_assert (NULL == client->warn_task);
685 client);
686 GNUNET_MQ_inject_message (client->mq, message);
687 if (NULL != client->drop_task)
688 return GNUNET_SYSERR;
689 return GNUNET_OK;
690}
@ 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:338

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

701{
702 struct GNUNET_SERVICE_Client *client = cls;
704
705 client->recv_task = NULL;
706 ret = GNUNET_MST_read (client->mst,
707 client->sock,
708 GNUNET_NO,
709 GNUNET_YES);
710 if (GNUNET_SYSERR == ret)
711 {
712 /* client closed connection (or IO error) */
713 if (NULL == client->drop_task)
714 {
715 GNUNET_assert (! client->needs_continue);
717 }
718 return;
719 }
720 if (GNUNET_NO == ret)
721 return; /* more messages in buffer, wait for application
722 to be done processing */
724 if (client->needs_continue)
725 return;
726 if (NULL != client->recv_task)
727 return;
728 /* MST needs more data, re-schedule read job */
729 client->recv_task =
731 client->sock,
733 client);
734}
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:1510
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:700
struct GNUNET_SCHEDULER_Task * recv_task
Task that receives data from the client to pass it to the handlers.
Definition: service.c:292
struct GNUNET_MessageStreamTokenizer * mst
Tokenizer we use for processing incoming data.
Definition: service.c:274

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

747{
748 struct GNUNET_SERVICE_Client *client;
749
750 client = GNUNET_new (struct GNUNET_SERVICE_Client);
751 GNUNET_CONTAINER_DLL_insert (sh->clients_head,
752 sh->clients_tail,
753 client);
754 client->sh = sh;
755 client->sock = csock;
757 NULL,
759 client,
760 sh->handlers,
762 client);
763 client->mst = GNUNET_MST_create (&service_client_mst_cb, client);
764 if (NULL != sh->connect_cb)
765 client->user_context = sh->connect_cb (sh->cb_cls, client, client->mq);
767 client->recv_task =
769 client->sock,
771 client);
772}
#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:588
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:560
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:669
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:611
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:308

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

783{
784 struct ServiceListenContext *slc = cls;
785 struct GNUNET_SERVICE_Handle *sh = slc->sh;
786
787 slc->listen_task = NULL;
788 while (1)
789 {
790 struct GNUNET_NETWORK_Handle *sock;
791 const struct sockaddr_in *v4;
792 const struct sockaddr_in6 *v6;
793 struct sockaddr_storage sa;
794 socklen_t addrlen;
795 int ok;
796
797 addrlen = sizeof(sa);
799 (struct sockaddr *) &sa,
800 &addrlen);
801 if (NULL == sock)
802 {
803 if (EMFILE == errno)
805 else if (EAGAIN != errno)
807 "accept");
808 break;
809 }
810 switch (sa.ss_family)
811 {
812 case AF_INET:
813 GNUNET_assert (addrlen == sizeof(struct sockaddr_in));
814 v4 = (const struct sockaddr_in *) &sa;
815 ok = (((NULL == sh->v4_allowed) ||
816 (check_ipv4_listed (sh->v4_allowed,
817 &v4->sin_addr))) &&
818 ((NULL == sh->v4_denied) ||
819 (! check_ipv4_listed (sh->v4_denied,
820 &v4->sin_addr))));
821 break;
822
823 case AF_INET6:
824 GNUNET_assert (addrlen == sizeof(struct sockaddr_in6));
825 v6 = (const struct sockaddr_in6 *) &sa;
826 ok = (((NULL == sh->v6_allowed) ||
827 (check_ipv6_listed (sh->v6_allowed,
828 &v6->sin6_addr))) &&
829 ((NULL == sh->v6_denied) ||
830 (! check_ipv6_listed (sh->v6_denied,
831 &v6->sin6_addr))));
832 break;
833
834 case AF_UNIX:
835 ok = GNUNET_OK; /* controlled using file-system ACL now */
836 break;
837
838 default:
840 _ ("Unknown address family %d\n"),
841 sa.ss_family);
842 return;
843 }
844 if (! ok)
845 {
847 "Service rejected incoming connection from %s due to policy.\n",
848 GNUNET_a2s ((const struct sockaddr *) &sa, addrlen));
850 continue;
851 }
853 "Service accepted incoming connection from %s.\n",
854 GNUNET_a2s ((const struct sockaddr *) &sa, addrlen));
855 start_client (slc->sh,
856 sock);
857 }
858 if (0 != sh->suspend_state)
859 return;
860 slc->listen_task =
862 slc->listen_socket,
864 slc);
865}
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:461
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:745
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:438
static void accept_client(void *cls)
We have a client.
Definition: service.c:782
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 876 of file service.c.

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

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

906{
907 struct GNUNET_SERVICE_Handle *sh = cls;
908
913
914 if (-1 != sh->ready_confirm_fd)
915 {
916 GNUNET_break (1 == write (sh->ready_confirm_fd, ".", 1));
917 GNUNET_break (0 == close (sh->ready_confirm_fd));
918 sh->ready_confirm_fd = -1;
919 }
920
921 if (NULL != sh->service_init_cb)
922 sh->service_init_cb (sh->cb_cls, sh->cfg, sh);
923}
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:1338
static void do_resume(struct GNUNET_SERVICE_Handle *sh, enum SuspendReason sr)
Resume accepting connections from the listen socket.
Definition: service.c:876
static void service_shutdown(void *cls)
Shutdown task triggered when a service should be terminated.
Definition: service.c:406
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 936 of file service.c.

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

980{
981 char *opt;
982
983 if (! GNUNET_CONFIGURATION_have_value (sh->cfg, sh->service_name, option))
984 {
985 *ret = NULL;
986 return GNUNET_OK;
987 }
990 sh->service_name,
991 option,
992 &opt));
993 if (NULL == (*ret = GNUNET_STRINGS_parse_ipv6_policy (opt)))
994 {
996 _ ("Could not parse IPv6 network specification `%s' for `%s:%s'\n"),
997 opt,
998 sh->service_name,
999 option);
1000 GNUNET_free (opt);
1001 return GNUNET_SYSERR;
1002 }
1003 GNUNET_free (opt);
1004 return GNUNET_OK;
1005}
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 1017 of file service.c.

1020{
1021#ifdef AF_UNIX
1022 struct sockaddr_un *un;
1023
1024 un = GNUNET_new (struct sockaddr_un);
1025 un->sun_family = AF_UNIX;
1026 GNUNET_strlcpy (un->sun_path, unixpath, sizeof(un->sun_path));
1027#if HAVE_SOCKADDR_UN_SUN_LEN
1028 un->sun_len = (u_char) sizeof(struct sockaddr_un);
1029#endif
1030 *saddrs = (struct sockaddr *) un;
1031 *saddrlens = sizeof(struct sockaddr_un);
1032#else
1033 /* this function should never be called
1034 * unless AF_UNIX is defined! */
1035 GNUNET_assert (0);
1036#endif
1037}
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 1061 of file service.c.

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

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

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

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

1627{
1628 char *un;
1629
1630 if (GNUNET_OK !=
1632 sh->service_name,
1633 "USERNAME",
1634 &un))
1635 return NULL;
1636 return un;
1637}

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

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

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

1698{
1699 char *pif;
1700
1701 if (GNUNET_OK !=
1703 sh->service_name,
1704 "PIDFILE",
1705 &pif))
1706 return NULL;
1707 return pif;
1708}

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

1718{
1719 char *pif = get_pid_file_name (sh);
1720
1721 if (NULL == pif)
1722 return; /* no PID file */
1723 if (0 != unlink (pif))
1725 "unlink",
1726 pif);
1727 GNUNET_free (pif);
1728}
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:1697
#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 1738 of file service.c.

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

1823{
1824 struct ServiceListenContext *slc;
1825
1826 GNUNET_free (sh->v4_denied);
1827 GNUNET_free (sh->v6_denied);
1828 GNUNET_free (sh->v4_allowed);
1829 GNUNET_free (sh->v6_allowed);
1830 while (NULL != (slc = sh->slc_head))
1831 {
1833 sh->slc_tail,
1834 slc);
1835 if (NULL != slc->listen_task)
1839 GNUNET_free (slc);
1840 }
1841}
#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 1851 of file service.c.

1853{
1854 struct GNUNET_SERVICE_Client *client = cls;
1855 struct GNUNET_MQ_Handle *mq;
1856 struct GNUNET_MQ_Envelope *env;
1857 struct GNUNET_MessageHeader *res;
1858 size_t slen;
1860
1861 (void) msg;
1862 slen = strlen (pd->agpl_url) + 1;
1865 memcpy (&res[1],
1867 slen);
1871}
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: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:2459
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.

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

1912{
1913 struct GNUNET_SERVICE_Client *c = cls;
1914 struct GNUNET_SERVICE_Handle *sh = c->sh;
1915
1916 c->drop_task = NULL;
1917 GNUNET_CONTAINER_DLL_remove (sh->clients_head,
1918 sh->clients_tail,
1919 c);
1920 GNUNET_assert (NULL == c->send_task);
1921 GNUNET_assert (NULL == c->recv_task);
1922 GNUNET_assert (NULL == c->warn_task);
1924 GNUNET_MQ_destroy (c->mq);
1925 if (! c->persist)
1926 {
1929 if ((0 != (SUSPEND_STATE_EMFILE & sh->suspend_state)) &&
1930 (0 == (SUSPEND_STATE_SHUTDOWN & sh->suspend_state)))
1931 do_resume (sh,
1933 }
1934 else
1935 {
1937 }
1938 GNUNET_free (c);
1939 if ((0 != (SUSPEND_STATE_SHUTDOWN & sh->suspend_state)) &&
1942}
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:326

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

2222{
2223 while (NULL != hll_head)
2224 {
2225 struct ServiceHandleList *shl = hll_head;
2226 struct GNUNET_SERVICE_Handle *sh = shl->sh;
2227
2229 hll_tail,
2230 shl);
2231 GNUNET_free (shl);
2232 if (-1 != sh->ready_confirm_fd)
2233 {
2234 if (1 != write (sh->ready_confirm_fd, "S", 1))
2236 "write");
2237 GNUNET_break (0 ==
2238 close (sh->ready_confirm_fd));
2239 }
2241 GNUNET_free (sh->handlers);
2242 GNUNET_free (sh);
2243 }
2244}
static void teardown_service(struct GNUNET_SERVICE_Handle *sh)
Tear down the service, closing the listen sockets and freeing the ACLs.
Definition: service.c:1822
static struct ServiceHandleList * hll_head
Definition: service.c:2182
static struct ServiceHandleList * hll_tail
Definition: service.c:2185
A list of service to be launched when GNUNET_SERVICE_main() is called.
Definition: service.c:2170
struct GNUNET_SERVICE_Handle * sh
Definition: service.c:2178

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

2249{
2250 struct GNUNET_CONFIGURATION_Handle *cfg = cls;
2251
2252 for (struct ServiceHandleList *shl = hll_head;
2253 NULL != shl;
2254 shl = shl->next)
2255 {
2256 shl->sh->cfg = cfg;
2257 if (GNUNET_OK != setup_service (shl->sh))
2258 continue;
2259 if (GNUNET_OK != set_user_id (shl->sh))
2260 continue;
2262 shl->sh);
2263 }
2265 NULL);
2266}
static void do_registered_services_shutdown(void *cls)
Definition: service.c:2221
static enum GNUNET_GenericReturnValue setup_service(struct GNUNET_SERVICE_Handle *sh)
Setup service handle.
Definition: service.c:1471
static enum GNUNET_GenericReturnValue set_user_id(struct GNUNET_SERVICE_Handle *sh)
Set user ID.
Definition: service.c:1647
static void service_main(void *cls)
First task run by any service.
Definition: service.c:905
struct ServiceHandleList * next
Definition: service.c:2175

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

2318{
2319 struct GNUNET_SERVICE_Client *c = cls;
2320 int ret;
2321
2322 c->recv_task = NULL;
2323 /* first, check if there is still something in the buffer */
2324 ret = GNUNET_MST_next (c->mst,
2325 GNUNET_YES);
2326 if (GNUNET_SYSERR == ret)
2327 {
2328 if (NULL == c->drop_task)
2330 return;
2331 }
2332 if (GNUNET_NO == ret)
2333 return; /* done processing, wait for more later */
2335 if (c->needs_continue)
2336 return; /* #GNUNET_MST_next() did give a message to the client */
2337 /* need to receive more data from the network first */
2338 if (NULL != c->recv_task)
2339 return;
2341 c->sock,
2343 c);
2344}
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 2185 of file service.c.

Referenced by do_registered_services_shutdown(), and GNUNET_SERVICE_register_().