GNUnet 0.21.1
service.c File Reference

functions related to starting services (redesign) More...

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

Go to the source code of this file.

Data Structures

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

Macros

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

Enumerations

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

Functions

static int have_non_monitor_clients (struct GNUNET_SERVICE_Handle *sh)
 Check if any of the clients we have left are unrelated to monitoring. More...
 
static void do_suspend (struct GNUNET_SERVICE_Handle *sh, enum SuspendReason sr)
 Suspend accepting connections from the listen socket temporarily. More...
 
static void service_shutdown (void *cls)
 Shutdown task triggered when a service should be terminated. More...
 
static int check_ipv4_listed (const struct GNUNET_STRINGS_IPv4NetworkPolicy *list, const struct in_addr *add)
 Check if the given IP address is in the list of IP addresses. More...
 
static int check_ipv6_listed (const struct GNUNET_STRINGS_IPv6NetworkPolicy *list, const struct in6_addr *ip)
 Check if the given IP address is in the list of IP addresses. More...
 
static void do_send (void *cls)
 Task run when we are ready to transmit data to the client. More...
 
static void service_mq_send (struct GNUNET_MQ_Handle *mq, const struct GNUNET_MessageHeader *msg, void *impl_state)
 Signature of functions implementing the sending functionality of a message queue. More...
 
static void service_mq_cancel (struct GNUNET_MQ_Handle *mq, void *impl_state)
 Implementation function that cancels the currently sent message. More...
 
static void service_mq_error_handler (void *cls, enum GNUNET_MQ_Error error)
 Generic error handler, called with the appropriate error code and the same closure specified at the creation of the message queue. More...
 
static void warn_no_client_continue (void *cls)
 Task run to warn about missing calls to GNUNET_SERVICE_client_continue(). More...
 
static int service_client_mst_cb (void *cls, const struct GNUNET_MessageHeader *message)
 Functions with this signature are called whenever a complete message is received by the tokenizer for a client. More...
 
static void service_client_recv (void *cls)
 A client sent us data. More...
 
static void start_client (struct GNUNET_SERVICE_Handle *sh, struct GNUNET_NETWORK_Handle *csock)
 We have successfully accepted a connection from a client. More...
 
static void accept_client (void *cls)
 We have a client. More...
 
static void do_resume (struct GNUNET_SERVICE_Handle *sh, enum SuspendReason sr)
 Resume accepting connections from the listen socket. More...
 
static void service_main (void *cls)
 First task run by any service. More...
 
static int process_acl4 (struct GNUNET_STRINGS_IPv4NetworkPolicy **ret, struct GNUNET_SERVICE_Handle *sh, const char *option)
 Parse an IPv4 access control list. More...
 
static int process_acl6 (struct GNUNET_STRINGS_IPv6NetworkPolicy **ret, struct GNUNET_SERVICE_Handle *sh, const char *option)
 Parse an IPv6 access control list. More...
 
static void add_unixpath (struct sockaddr **saddrs, socklen_t *saddrlens, const char *unixpath)
 Add the given UNIX domain path as an address to the list (as the first entry). More...
 
static int get_server_addresses (const char *service_name, const struct GNUNET_CONFIGURATION_Handle *cfg, struct sockaddr ***addrs, socklen_t **addr_lens)
 Get the list of addresses that a server for the given service should bind to. More...
 
static struct GNUNET_NETWORK_Handleopen_listen_socket (const struct sockaddr *server_addr, socklen_t socklen)
 Create and initialize a listen socket for the server. More...
 
static int setup_service (struct GNUNET_SERVICE_Handle *sh)
 Setup service handle. More...
 
static char * get_user_name (struct GNUNET_SERVICE_Handle *sh)
 Get the name of the user that'll be used to provide the service. More...
 
static int set_user_id (struct GNUNET_SERVICE_Handle *sh)
 Set user ID. More...
 
static char * get_pid_file_name (struct GNUNET_SERVICE_Handle *sh)
 Get the name of the file where we will write the PID of the service. More...
 
static void pid_file_delete (struct GNUNET_SERVICE_Handle *sh)
 Delete the PID file that was created by our parent. More...
 
static int detach_terminal (struct GNUNET_SERVICE_Handle *sh)
 Detach from terminal. More...
 
static void teardown_service (struct GNUNET_SERVICE_Handle *sh)
 Tear down the service, closing the listen sockets and freeing the ACLs. More...
 
static void return_agpl (void *cls, const struct GNUNET_MessageHeader *msg)
 Function to return link to AGPL source upon request. More...
 
struct GNUNET_SERVICE_HandleGNUNET_SERVICE_start (const char *service_name, const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_SERVICE_ConnectHandler connect_cb, GNUNET_SERVICE_DisconnectHandler disconnect_cb, void *cls, const struct GNUNET_MQ_MessageHandler *handlers)
 Low-level function to start a service if the scheduler is already running. More...
 
void GNUNET_SERVICE_stop (struct GNUNET_SERVICE_Handle *srv)
 Stops a service that was started with GNUNET_SERVICE_start(). More...
 
int GNUNET_SERVICE_run_ (int argc, char *const *argv, const char *service_name, enum GNUNET_SERVICE_Options options, GNUNET_SERVICE_InitCallback service_init_cb, GNUNET_SERVICE_ConnectHandler connect_cb, GNUNET_SERVICE_DisconnectHandler disconnect_cb, void *cls, const struct GNUNET_MQ_MessageHandler *handlers)
 Creates the "main" function for a GNUnet service. More...
 
int GNUNET_SERVICE_register_ (const char *service_name, enum GNUNET_SERVICE_Options options, GNUNET_SERVICE_InitCallback service_init_cb, GNUNET_SERVICE_ConnectHandler connect_cb, GNUNET_SERVICE_DisconnectHandler disconnect_cb, void *cls, const struct GNUNET_MQ_MessageHandler *handlers)
 Registers the GNUnet service to be scheduled as part of a monilithic libgnunet. More...
 
static void do_registered_services_shutdown (void *cls)
 
static void launch_registered_services (void *cls)
 
void GNUNET_SERVICE_main (int argc, char *const *argv)
 Run the mainloop in a monolithic libgnunet. More...
 
void GNUNET_SERVICE_suspend (struct GNUNET_SERVICE_Handle *sh)
 Suspend accepting connections from the listen socket temporarily. More...
 
void GNUNET_SERVICE_resume (struct GNUNET_SERVICE_Handle *sh)
 Resume accepting connections from the listen socket. More...
 
static void resume_client_receive (void *cls)
 Task run to resume receiving data from the client after the client called GNUNET_SERVICE_client_continue(). More...
 
void GNUNET_SERVICE_client_continue (struct GNUNET_SERVICE_Client *c)
 Continue receiving further messages from the given client. More...
 
void GNUNET_SERVICE_client_disable_continue_warning (struct GNUNET_SERVICE_Client *c)
 Disable the warning the server issues if a message is not acknowledged in a timely fashion. More...
 
static void finish_client_drop (void *cls)
 Asynchronously finish dropping the client. More...
 
void GNUNET_SERVICE_client_drop (struct GNUNET_SERVICE_Client *c)
 Ask the server to disconnect from the given client. More...
 
void GNUNET_SERVICE_shutdown (struct GNUNET_SERVICE_Handle *sh)
 Explicitly stops the service. More...
 
void GNUNET_SERVICE_client_mark_monitor (struct GNUNET_SERVICE_Client *c)
 Set the 'monitor' flag on this client. More...
 
void GNUNET_SERVICE_client_persist (struct GNUNET_SERVICE_Client *c)
 Set the persist option on this client. More...
 
struct GNUNET_MQ_HandleGNUNET_SERVICE_client_get_mq (struct GNUNET_SERVICE_Client *c)
 Obtain the message queue of c. More...
 

Variables

static struct ServiceHandleListhll_head = NULL
 
static struct ServiceHandleListhll_tail = NULL
 

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

◆ LOG_STRERROR

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

Definition at line 43 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 46 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 85 of file service.c.

86{
91
96
101
106
111};
@ SUSPEND_STATE_SHUTDOWN
Suspension because service was permanently shutdown.
Definition: service.c:110
@ SUSPEND_STATE_APP
Application requested it.
Definition: service.c:95
@ SUSPEND_STATE_NONE
We are running normally.
Definition: service.c:90
@ SUSPEND_STATE_APP_AND_EMFILE
Both reasons, APP and EMFILE apply.
Definition: service.c:105
@ SUSPEND_STATE_EMFILE
OS ran out of file descriptors.
Definition: service.c:100

Function Documentation

◆ have_non_monitor_clients()

static int have_non_monitor_clients ( struct GNUNET_SERVICE_Handle sh)
static

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

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

Definition at line 362 of file service.c.

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

References GNUNET_NO, GNUNET_YES, and sh.

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

Here is the caller graph for this function:

◆ do_suspend()

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

Suspend accepting connections from the listen socket temporarily.

Resume activity using do_resume.

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

Definition at line 383 of file service.c.

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

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

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

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

◆ service_shutdown()

static void service_shutdown ( void *  cls)
static

Shutdown task triggered when a service should be terminated.

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

Parameters
clsour struct GNUNET_SERVICE_Handle

Definition at line 409 of file service.c.

410{
411 struct GNUNET_SERVICE_Handle *sh = cls;
412
414 {
417 break;
419 /* This task should never be run if we are using
420 the manual shutdown. */
421 GNUNET_assert (0);
422 break;
424 if (0 == (sh->suspend_state & SUSPEND_STATE_SHUTDOWN))
428 break;
429 }
430}
void GNUNET_SERVICE_shutdown(struct GNUNET_SERVICE_Handle *sh)
Explicitly stops the service.
Definition: service.c:2548
@ GNUNET_SERVICE_OPTION_MANUAL_SHUTDOWN
Do not trigger server shutdown on signal at all; instead, allow for the user to terminate the server ...
@ GNUNET_SERVICE_OPTION_SHUTDOWN_BITMASK
Bitmask over the shutdown options.
@ GNUNET_SERVICE_OPTION_NONE
Use defaults.
@ GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN
Trigger a SOFT server shutdown on signals, allowing active non-monitor clients to complete their tran...
static int have_non_monitor_clients(struct GNUNET_SERVICE_Handle *sh)
Check if any of the clients we have left are unrelated to monitoring.
Definition: service.c:362
static void do_suspend(struct GNUNET_SERVICE_Handle *sh, enum SuspendReason sr)
Suspend accepting connections from the listen socket temporarily.
Definition: service.c:383
Handle to a service.
Definition: service.c:118

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

Referenced by service_main().

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

◆ check_ipv4_listed()

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

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

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

Definition at line 441 of file service.c.

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

References add, GNUNET_NO, GNUNET_YES, and list.

Referenced by accept_client().

Here is the caller graph for this function:

◆ check_ipv6_listed()

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

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

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

Definition at line 468 of file service.c.

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

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

Referenced by accept_client().

Here is the caller graph for this function:

◆ do_send()

static void do_send ( void *  cls)
static

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

Parameters
clsthe struct GNUNET_SERVICE_Client * to send to

Definition at line 499 of file service.c.

500{
501 struct GNUNET_SERVICE_Client *client = cls;
502 ssize_t ret;
503 size_t left;
504 const char *buf;
505
507 "service: sending message with type %u\n",
508 ntohs (client->msg->type));
509 client->send_task = NULL;
510 buf = (const char *) client->msg;
511 left = ntohs (client->msg->size) - client->msg_pos;
513 &buf[client->msg_pos],
514 left);
515 GNUNET_assert (ret <= (ssize_t) left);
516 if (0 == ret)
517 {
518 LOG (GNUNET_ERROR_TYPE_DEBUG, "no data send");
520 return;
521 }
522 if (-1 == ret)
523 {
524 if ((EAGAIN == errno) || (EINTR == errno))
525 {
526 /* ignore */
527 ret = 0;
528 }
529 else
530 {
531 if (EPIPE != errno)
534 "socket send returned with error code %i",
535 errno);
537 return;
538 }
539 }
540 if (0 == client->msg_pos)
541 {
543 }
544 client->msg_pos += ret;
545 if (left > (size_t) ret)
546 {
547 GNUNET_assert (NULL == client->drop_task);
548 client->send_task =
550 client->sock,
551 &do_send,
552 client);
553 return;
554 }
556}
static int ret
Final status code.
Definition: gnunet-arm.c:94
#define GNUNET_log_strerror(level, cmd)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_DEBUG
void GNUNET_MQ_inject_error(struct GNUNET_MQ_Handle *mq, enum GNUNET_MQ_Error error)
Call the error handler of a message queue with the given error code.
Definition: mq.c:269
void GNUNET_MQ_impl_send_continue(struct GNUNET_MQ_Handle *mq)
Call the send implementation for the next queued message, if any.
Definition: mq.c:421
void GNUNET_MQ_impl_send_in_flight(struct GNUNET_MQ_Handle *mq)
Call the send notification for the current message, but do not try to send the next message until #gn...
Definition: mq.c:444
@ GNUNET_MQ_ERROR_WRITE
FIXME: document!
ssize_t GNUNET_NETWORK_socket_send(const struct GNUNET_NETWORK_Handle *desc, const void *buffer, size_t length)
Send data (always non-blocking).
Definition: network.c:737
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_write_net(struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *wfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition: scheduler.c:1583
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
static void do_send(void *cls)
Task run when we are ready to transmit data to the client.
Definition: service.c:499
#define LOG(kind,...)
Definition: service.c:41
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
size_t msg_pos
Current position in msg at which we are transmitting.
Definition: service.c:326
struct GNUNET_SCHEDULER_Task * send_task
Task that transmit data to the client.
Definition: service.c:304
struct GNUNET_SCHEDULER_Task * drop_task
Task run to finish dropping the client after the stack has properly unwound.
Definition: service.c:293
struct GNUNET_NETWORK_Handle * sock
Socket of this client.
Definition: service.c:271
const struct GNUNET_MessageHeader * msg
Pointer to the message to be transmitted by send_task.
Definition: service.c:309
struct GNUNET_MQ_Handle * mq
Message queue for the client.
Definition: service.c:276

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

571{
572 struct GNUNET_SERVICE_Client *client = impl_state;
573
574 (void) mq;
575 if (NULL != client->drop_task)
576 return; /* we're going down right now, do not try to send */
577 GNUNET_assert (NULL == client->send_task);
579 "Sending message of type %u and size %u to client\n",
580 ntohs (msg->type),
581 ntohs (msg->size));
582 client->msg = msg;
583 client->msg_pos = 0;
585 client);
586}
struct GNUNET_MQ_Handle * mq
Definition: 003.c:5
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1305

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

Referenced by start_client().

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

◆ service_mq_cancel()

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

Implementation function that cancels the currently sent message.

Parameters
mqmessage queue
impl_statestate specific to the implementation

Definition at line 596 of file service.c.

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

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

619{
620 struct GNUNET_SERVICE_Client *client = cls;
621 struct GNUNET_SERVICE_Handle *sh = client->sh;
622
623 if ((GNUNET_MQ_ERROR_NO_MATCH == error) && (GNUNET_NO == sh->require_found))
624 {
626 "No handler for message of type %u found\n",
627 (unsigned int) client->warn_type);
629 return; /* ignore error */
630 }
632}
#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:2489
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2408
uint16_t warn_type
Type of last message processed (for warn_no_receive_done).
Definition: service.c:350
struct GNUNET_SERVICE_Handle * sh
Service that this client belongs to.
Definition: service.c:266

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

Referenced by start_client().

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

◆ warn_no_client_continue()

static void warn_no_client_continue ( void *  cls)
static

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

Parameters
clsour struct GNUNET_SERVICE_Client * to process more requests from

Definition at line 641 of file service.c.

642{
643 struct GNUNET_SERVICE_Client *client = cls;
644
646 0 !=
647 client->warn_type); /* type should never be 0 here, as we don't use 0 */
650 client);
651 LOG (
653 _ (
654 "Processing code for message of type %u did not call `GNUNET_SERVICE_client_continue' after %s\n"),
655 (unsigned int) client->warn_type,
657 client->warn_start),
658 GNUNET_YES));
659}
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1278
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_duration(struct GNUNET_TIME_Absolute whence)
Get the duration of an operation as the difference of the current time and the given start time "henc...
Definition: time.c:436
const char * GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition: strings.c:570
#define GNUNET_TIME_UNIT_MINUTES
One minute.
#define _(String)
GNU gettext support macro.
Definition: platform.h:178
static void warn_no_client_continue(void *cls)
Task run to warn about missing calls to GNUNET_SERVICE_client_continue().
Definition: service.c:641
struct GNUNET_TIME_Absolute warn_start
Time when we last gave a message from this client to the application.
Definition: service.c:321
struct GNUNET_SCHEDULER_Task * warn_task
Task that warns about missing calls to GNUNET_SERVICE_client_continue().
Definition: service.c:287

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

676{
677 struct GNUNET_SERVICE_Client *client = cls;
678
680 "Received message of type %u and size %u from client\n",
681 ntohs (message->type),
682 ntohs (message->size));
684 client->needs_continue = GNUNET_YES;
685 client->warn_type = ntohs (message->type);
687 GNUNET_assert (NULL == client->warn_task);
690 client);
691 GNUNET_MQ_inject_message (client->mq, message);
692 if (NULL != client->drop_task)
693 return GNUNET_SYSERR;
694 return GNUNET_OK;
695}
@ 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
int needs_continue
Are we waiting for the application to call GNUNET_SERVICE_client_continue()?
Definition: service.c:345

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

Referenced by start_client().

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

◆ service_client_recv()

static void service_client_recv ( void *  cls)
static

A client sent us data.

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

Parameters
clsthe struct GNUNET_SERVICE_Client that sent us data.

Definition at line 705 of file service.c.

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

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

752{
753 struct GNUNET_SERVICE_Client *client;
754
755 client = GNUNET_new (struct GNUNET_SERVICE_Client);
756 GNUNET_CONTAINER_DLL_insert (sh->clients_head, sh->clients_tail, client);
757 client->sh = sh;
758 client->sock = csock;
760 NULL,
762 client,
763 sh->handlers,
765 client);
766 client->mst = GNUNET_MST_create (&service_client_mst_cb, client);
767 if (NULL != sh->connect_cb)
768 client->user_context = sh->connect_cb (sh->cb_cls, client, client->mq);
770 client->recv_task =
772 client->sock,
774 client);
775}
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
struct GNUNET_MQ_Handle * GNUNET_MQ_queue_for_callbacks(GNUNET_MQ_SendImpl send, GNUNET_MQ_DestroyImpl destroy, GNUNET_MQ_CancelImpl cancel, void *impl_state, const struct GNUNET_MQ_MessageHandler *handlers, GNUNET_MQ_ErrorHandler error_handler, void *cls)
Create a message queue for the specified handlers.
Definition: mq.c:465
void GNUNET_MQ_set_handlers_closure(struct GNUNET_MQ_Handle *mq, void *handlers_cls)
Change the closure argument in all of the handlers of the mq.
Definition: mq.c:489
struct GNUNET_MessageStreamTokenizer * GNUNET_MST_create(GNUNET_MessageTokenizerCallback cb, void *cb_cls)
Create a message stream tokenizer.
Definition: mst.c:86
static void service_mq_cancel(struct GNUNET_MQ_Handle *mq, void *impl_state)
Implementation function that cancels the currently sent message.
Definition: service.c:596
static void service_mq_send(struct GNUNET_MQ_Handle *mq, const struct GNUNET_MessageHeader *msg, void *impl_state)
Signature of functions implementing the sending functionality of a message queue.
Definition: service.c:568
static int service_client_mst_cb(void *cls, const struct GNUNET_MessageHeader *message)
Functions with this signature are called whenever a complete message is received by the tokenizer for...
Definition: service.c:674
static void service_mq_error_handler(void *cls, enum GNUNET_MQ_Error error)
Generic error handler, called with the appropriate error code and the same closure specified at the c...
Definition: service.c:618
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:315

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

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

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

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

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

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

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

◆ service_main()

static void service_main ( void *  cls)
static

First task run by any service.

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

Parameters
clsour struct GNUNET_SERVICE_Handle

Definition at line 901 of file service.c.

902{
903 struct GNUNET_SERVICE_Handle *sh = cls;
904
909
910 if (-1 != sh->ready_confirm_fd)
911 {
912 GNUNET_break (1 == write (sh->ready_confirm_fd, ".", 1));
913 GNUNET_break (0 == close (sh->ready_confirm_fd));
914 sh->ready_confirm_fd = -1;
915 }
916
917 if (NULL != sh->service_init_cb)
918 sh->service_init_cb (sh->cb_cls, sh->cfg, sh);
919}
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received,...
Definition: scheduler.c:1340
static void do_resume(struct GNUNET_SERVICE_Handle *sh, enum SuspendReason sr)
Resume accepting connections from the listen socket.
Definition: service.c:873
static void service_shutdown(void *cls)
Shutdown task triggered when a service should be terminated.
Definition: service.c:409
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 int process_acl4 ( struct GNUNET_STRINGS_IPv4NetworkPolicy **  ret,
struct GNUNET_SERVICE_Handle sh,
const char *  option 
)
static

Parse an IPv4 access control list.

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

Definition at line 932 of file service.c.

935{
936 char *opt;
937
938 if (! GNUNET_CONFIGURATION_have_value (sh->cfg, sh->service_name, option))
939 {
940 *ret = NULL;
941 return GNUNET_OK;
942 }
945 sh->service_name,
946 option,
947 &opt));
948 if (NULL == (*ret = GNUNET_STRINGS_parse_ipv4_policy (opt)))
949 {
951 _ ("Could not parse IPv4 network specification `%s' for `%s:%s'\n"),
952 opt,
953 sh->service_name,
954 option);
955 GNUNET_free (opt);
956 return GNUNET_SYSERR;
957 }
958 GNUNET_free (opt);
959 return GNUNET_OK;
960}
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 int process_acl6 ( struct GNUNET_STRINGS_IPv6NetworkPolicy **  ret,
struct GNUNET_SERVICE_Handle sh,
const char *  option 
)
static

Parse an IPv6 access control list.

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

Definition at line 973 of file service.c.

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

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

1061{
1062 int disablev6;
1063 struct GNUNET_NETWORK_Handle *desc;
1064 unsigned long long port;
1065 char *unixpath;
1066 struct addrinfo hints;
1067 struct addrinfo *res;
1068 struct addrinfo *pos;
1069 struct addrinfo *next;
1070 unsigned int i;
1071 int resi;
1072 int ret;
1073 struct sockaddr **saddrs;
1074 socklen_t *saddrlens;
1075 char *hostname;
1076
1077 *addrs = NULL;
1078 *addr_lens = NULL;
1079 desc = NULL;
1080 disablev6 = GNUNET_NO;
1081 if ((GNUNET_NO == GNUNET_NETWORK_test_pf (PF_INET6)) ||
1082 (GNUNET_YES ==
1084 disablev6 = GNUNET_YES;
1085
1086 port = 0;
1088 {
1091 "PORT",
1092 &port))
1093 {
1095 _ ("Require valid port number for service `%s' in configuration!\n"),
1096 service_name);
1097 }
1098 if (port > 65535)
1099 {
1101 _ ("Require valid port number for service `%s' in configuration!\n"),
1102 service_name);
1103 return GNUNET_SYSERR;
1104 }
1105 }
1106
1108 {
1112 "BINDTO",
1113 &hostname));
1114 }
1115 else
1116 hostname = NULL;
1117
1118 unixpath = NULL;
1119#ifdef AF_UNIX
1120 if ((GNUNET_YES ==
1124 "UNIXPATH",
1125 &unixpath)) &&
1126 (0 < strlen (unixpath)))
1127 {
1128 /* probe UNIX support */
1129 struct sockaddr_un s_un;
1130
1131 if (strlen (unixpath) >= sizeof(s_un.sun_path))
1132 {
1134 _ ("UNIXPATH `%s' too long, maximum length is %llu\n"),
1135 unixpath,
1136 (unsigned long long) sizeof(s_un.sun_path));
1137 unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath);
1138 LOG (GNUNET_ERROR_TYPE_INFO, _ ("Using `%s' instead\n"), unixpath);
1139 }
1142 }
1143 if (NULL != unixpath)
1144 {
1145 desc = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_STREAM, 0);
1146 if (NULL == desc)
1147 {
1148 if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) ||
1149 (EACCES == errno))
1150 {
1152 GNUNET_free (hostname);
1153 GNUNET_free (unixpath);
1154 return GNUNET_SYSERR;
1155 }
1157 _ (
1158 "Disabling UNIX domain socket support for service `%s', failed to create UNIX domain socket: %s\n"),
1160 strerror (errno));
1161 GNUNET_free (unixpath);
1162 unixpath = NULL;
1163 }
1164 else
1165 {
1167 desc = NULL;
1168 }
1169 }
1170#endif
1171
1172 if ((0 == port) && (NULL == unixpath))
1173 {
1175 _ (
1176 "Have neither PORT nor UNIXPATH for service `%s', but one is required\n"),
1177 service_name);
1178 GNUNET_free (hostname);
1179 return GNUNET_SYSERR;
1180 }
1181 if (0 == port)
1182 {
1183 saddrs = GNUNET_new_array (2, struct sockaddr *);
1184 saddrlens = GNUNET_new_array (2, socklen_t);
1185 add_unixpath (saddrs, saddrlens, unixpath);
1186 GNUNET_free (unixpath);
1187 GNUNET_free (hostname);
1188 *addrs = saddrs;
1189 *addr_lens = saddrlens;
1190 return 1;
1191 }
1192
1193 if (NULL != hostname)
1194 {
1196 "Resolving `%s' since that is where `%s' will bind to.\n",
1197 hostname,
1198 service_name);
1199 memset (&hints, 0, sizeof(struct addrinfo));
1200 if (disablev6)
1201 hints.ai_family = AF_INET;
1202 hints.ai_protocol = IPPROTO_TCP;
1203 if ((0 != (ret = getaddrinfo (hostname, NULL, &hints, &res))) ||
1204 (NULL == res))
1205 {
1207 _ ("Failed to resolve `%s': %s\n"),
1208 hostname,
1209 gai_strerror (ret));
1210 GNUNET_free (hostname);
1211 GNUNET_free (unixpath);
1212 return GNUNET_SYSERR;
1213 }
1214 next = res;
1215 i = 0;
1216 while (NULL != (pos = next))
1217 {
1218 next = pos->ai_next;
1219 if ((disablev6) && (pos->ai_family == AF_INET6))
1220 continue;
1221 i++;
1222 }
1223 if (0 == i)
1224 {
1226 _ ("Failed to find %saddress for `%s'.\n"),
1227 disablev6 ? "IPv4 " : "",
1228 hostname);
1229 freeaddrinfo (res);
1230 GNUNET_free (hostname);
1231 GNUNET_free (unixpath);
1232 return GNUNET_SYSERR;
1233 }
1234 resi = i;
1235 if (NULL != unixpath)
1236 resi++;
1237 saddrs = GNUNET_new_array (resi + 1, struct sockaddr *);
1238 saddrlens = GNUNET_new_array (resi + 1, socklen_t);
1239 i = 0;
1240 if (NULL != unixpath)
1241 {
1242 add_unixpath (saddrs, saddrlens, unixpath);
1243 i++;
1244 }
1245 next = res;
1246 while (NULL != (pos = next))
1247 {
1248 next = pos->ai_next;
1249 if ((disablev6) && (AF_INET6 == pos->ai_family))
1250 continue;
1251 if ((IPPROTO_TCP != pos->ai_protocol) && (0 != pos->ai_protocol))
1252 continue; /* not TCP */
1253 if ((SOCK_STREAM != pos->ai_socktype) && (0 != pos->ai_socktype))
1254 continue; /* huh? */
1256 "Service `%s' will bind to `%s'\n",
1258 GNUNET_a2s (pos->ai_addr, pos->ai_addrlen));
1259 if (AF_INET == pos->ai_family)
1260 {
1261 GNUNET_assert (sizeof(struct sockaddr_in) == pos->ai_addrlen);
1262 saddrlens[i] = pos->ai_addrlen;
1263 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1264 GNUNET_memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
1265 ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
1266 }
1267 else
1268 {
1269 GNUNET_assert (AF_INET6 == pos->ai_family);
1270 GNUNET_assert (sizeof(struct sockaddr_in6) == pos->ai_addrlen);
1271 saddrlens[i] = pos->ai_addrlen;
1272 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1273 GNUNET_memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
1274 ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
1275 }
1276 i++;
1277 }
1278 GNUNET_free (hostname);
1279 freeaddrinfo (res);
1280 resi = i;
1281 }
1282 else
1283 {
1284 /* will bind against everything, just set port */
1285 if (disablev6)
1286 {
1287 /* V4-only */
1288 resi = 1;
1289 if (NULL != unixpath)
1290 resi++;
1291 i = 0;
1292 saddrs = GNUNET_new_array (resi + 1, struct sockaddr *);
1293 saddrlens = GNUNET_new_array (resi + 1, socklen_t);
1294 if (NULL != unixpath)
1295 {
1296 add_unixpath (saddrs, saddrlens, unixpath);
1297 i++;
1298 }
1299 saddrlens[i] = sizeof(struct sockaddr_in);
1300 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1301#if HAVE_SOCKADDR_IN_SIN_LEN
1302 ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[i];
1303#endif
1304 ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
1305 ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
1306 }
1307 else
1308 {
1309 /* dual stack */
1310 resi = 2;
1311 if (NULL != unixpath)
1312 resi++;
1313 saddrs = GNUNET_new_array (resi + 1, struct sockaddr *);
1314 saddrlens = GNUNET_new_array (resi + 1, socklen_t);
1315 i = 0;
1316 if (NULL != unixpath)
1317 {
1318 add_unixpath (saddrs, saddrlens, unixpath);
1319 i++;
1320 }
1321 saddrlens[i] = sizeof(struct sockaddr_in6);
1322 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1323#if HAVE_SOCKADDR_IN_SIN_LEN
1324 ((struct sockaddr_in6 *) saddrs[i])->sin6_len = saddrlens[0];
1325#endif
1326 ((struct sockaddr_in6 *) saddrs[i])->sin6_family = AF_INET6;
1327 ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
1328 i++;
1329 saddrlens[i] = sizeof(struct sockaddr_in);
1330 saddrs[i] = GNUNET_malloc (saddrlens[i]);
1331#if HAVE_SOCKADDR_IN_SIN_LEN
1332 ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[1];
1333#endif
1334 ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
1335 ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
1336 }
1337 }
1338 GNUNET_free (unixpath);
1339 *addrs = saddrs;
1340 *addr_lens = saddrlens;
1341 return resi;
1342}
static struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition: gnunet-arm.c:109
static uint16_t port
Port number.
Definition: gnunet-bcd.c:147
static char * res
Currently read line or NULL on EOF.
static char * service_name
Option -s: service name (hash to get service descriptor)
Definition: gnunet-vpn.c:50
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_filename(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be the name of a file or directory.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_number(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *number)
Get a configuration value that should be a number.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:582
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#define GNUNET_log_strerror_file(level, cmd, filename)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_INFO
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.
char * GNUNET_NETWORK_shorten_unixpath(char *unixpath)
Given a unixpath that is too long (larger than UNIX_PATH_MAX), shorten it to an acceptable length whi...
Definition: network.c:143
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_create(int domain, int type, int protocol)
Create a new socket.
Definition: network.c:832
enum GNUNET_GenericReturnValue GNUNET_NETWORK_test_pf(int pf)
Test if the given protocol family is supported by this system.
Definition: network.c:79
static void add_unixpath(struct sockaddr **saddrs, socklen_t *saddrlens, const char *unixpath)
Add the given UNIX domain path as an address to the list (as the first entry).
Definition: service.c:1013
#define LOG_STRERROR(kind, syscall)
Definition: service.c:43

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

Referenced by setup_service().

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

◆ open_listen_socket()

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

Create and initialize a listen socket for the server.

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

Definition at line 1353 of file service.c.

1355{
1356 struct GNUNET_NETWORK_Handle *sock;
1357 uint16_t port;
1358 int eno;
1359
1360 switch (server_addr->sa_family)
1361 {
1362 case AF_INET:
1363 port = ntohs (((const struct sockaddr_in *) server_addr)->sin_port);
1364 break;
1365 case AF_INET6:
1366 port = ntohs (((const struct sockaddr_in6 *) server_addr)->sin6_port);
1367 break;
1368 case AF_UNIX:
1369 port = 0;
1370 break;
1371 default:
1372 GNUNET_break (0);
1373 port = 0;
1374 break;
1375 }
1376 sock = GNUNET_NETWORK_socket_create (server_addr->sa_family,
1377 SOCK_STREAM,
1378 0);
1379 if (NULL == sock)
1380 {
1382 "socket");
1383 errno = 0;
1384 return NULL;
1385 }
1386 /* bind the socket */
1387 if (GNUNET_OK !=
1389 server_addr,
1390 socklen))
1391 {
1392 eno = errno;
1393 if (EADDRINUSE != errno)
1394 {
1395 /* we don't log 'EADDRINUSE' here since an IPv4 bind may
1396 * fail if we already took the port on IPv6; if both IPv4 and
1397 * IPv6 binds fail, then our caller will log using the
1398 * errno preserved in 'eno' */
1399 if (0 != port)
1401 _ ("`%s' failed for port %d (%s).\n"),
1402 "bind",
1403 port,
1404 (AF_INET == server_addr->sa_family) ? "IPv4" : "IPv6");
1405 else
1407 eno = 0;
1408 }
1409 else
1410 {
1411 if (0 != port)
1413 _ ("`%s' failed for port %d (%s): address already in use\n"),
1414 "bind",
1415 port,
1416 (AF_INET == server_addr->sa_family) ? "IPv4" : "IPv6");
1417 else if (AF_UNIX == server_addr->sa_family)
1418 {
1420 _ ("`%s' failed for `%s': address already in use\n"),
1421 "bind",
1422 GNUNET_a2s (server_addr, socklen));
1423 }
1424 }
1426 errno = eno;
1427 return NULL;
1428 }
1429 if (GNUNET_OK != GNUNET_NETWORK_socket_listen (sock, 5))
1430 {
1433 errno = 0;
1434 return NULL;
1435 }
1436 if (0 != port)
1438 "Server starts to listen on port %u.\n",
1439 port);
1440 return sock;
1441}
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_bind(struct GNUNET_NETWORK_Handle *desc, const struct sockaddr *address, socklen_t address_len)
Bind a socket to a particular address.
Definition: network.c:439
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_listen(const struct GNUNET_NETWORK_Handle *desc, int backlog)
Listen on a socket.
Definition: network.c:651

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

Referenced by setup_service().

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

◆ setup_service()

static int setup_service ( struct GNUNET_SERVICE_Handle sh)
static

Setup service handle.

Configuration may specify:

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

Definition at line 1461 of file service.c.

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

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, GNUNET_YES, 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 1608 of file service.c.

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

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 int set_user_id ( struct GNUNET_SERVICE_Handle sh)
static

Set user ID.

Parameters
shservice context
Returns
GNUNET_OK on success, GNUNET_SYSERR on error

Definition at line 1628 of file service.c.

1629{
1630 char *user;
1631
1632 if (NULL == (user = get_user_name (sh)))
1633 return GNUNET_OK; /* keep */
1634
1635 struct passwd *pws;
1636
1637 errno = 0;
1638 pws = getpwnam (user);
1639 if (NULL == pws)
1640 {
1642 _ ("Cannot obtain information about user `%s': %s\n"),
1643 user,
1644 errno == 0 ? _ ("No such user") : strerror (errno));
1645 GNUNET_free (user);
1646 return GNUNET_SYSERR;
1647 }
1648 if ((0 != setgid (pws->pw_gid)) || (0 != setegid (pws->pw_gid)) ||
1649#if HAVE_INITGROUPS
1650 (0 != initgroups (user, pws->pw_gid)) ||
1651#endif
1652 (0 != setuid (pws->pw_uid)) || (0 != seteuid (pws->pw_uid)))
1653 {
1654 if ((0 != setregid (pws->pw_gid, pws->pw_gid)) ||
1655 (0 != setreuid (pws->pw_uid, pws->pw_uid)))
1656 {
1658 _ ("Cannot change user/group to `%s': %s\n"),
1659 user,
1660 strerror (errno));
1661 GNUNET_free (user);
1662 return GNUNET_SYSERR;
1663 }
1664 }
1665
1666 GNUNET_free (user);
1667 return GNUNET_OK;
1668}
static char * get_user_name(struct GNUNET_SERVICE_Handle *sh)
Get the name of the user that'll be used to provide the service.
Definition: service.c:1608

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

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

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

1699{
1700 char *pif = get_pid_file_name (sh);
1701
1702 if (NULL == pif)
1703 return; /* no PID file */
1704 if (0 != unlink (pif))
1706 GNUNET_free (pif);
1707}
static char * get_pid_file_name(struct GNUNET_SERVICE_Handle *sh)
Get the name of the file where we will write the PID of the service.
Definition: service.c:1679
#define LOG_STRERROR_FILE(kind, syscall, filename)
Definition: service.c:46

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

Referenced by GNUNET_SERVICE_run_().

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

◆ detach_terminal()

static int detach_terminal ( struct GNUNET_SERVICE_Handle sh)
static

Detach from terminal.

Parameters
shservice context
Returns
GNUNET_OK on success, GNUNET_SYSERR on error

Definition at line 1717 of file service.c.

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

1798{
1799 struct ServiceListenContext *slc;
1800
1801 GNUNET_free (sh->v4_denied);
1802 GNUNET_free (sh->v6_denied);
1803 GNUNET_free (sh->v4_allowed);
1804 GNUNET_free (sh->v6_allowed);
1805 while (NULL != (slc = sh->slc_head))
1806 {
1807 GNUNET_CONTAINER_DLL_remove (sh->slc_head, sh->slc_tail, slc);
1808 if (NULL != slc->listen_task)
1812 GNUNET_free (slc);
1813 }
1814}
#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 1824 of file service.c.

1825{
1826 struct GNUNET_SERVICE_Client *client = cls;
1827 struct GNUNET_MQ_Handle *mq;
1828 struct GNUNET_MQ_Envelope *env;
1829 struct GNUNET_MessageHeader *res;
1830 size_t slen;
1832
1833 (void) msg;
1834 slen = strlen (pd->agpl_url) + 1;
1836 memcpy (&res[1], GNUNET_AGPL_URL, slen);
1840}
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
#define GNUNET_AGPL_URL
NOTE: You MUST adjust this URL to point to the location of a publicly accessible repository (or TGZ) ...
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition: mq.c:304
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct.
Definition: gnunet_mq_lib.h:63
const struct GNUNET_OS_ProjectData * GNUNET_OS_project_data_get(void)
#define GNUNET_MESSAGE_TYPE_RESPONSE_AGPL
Source code link.
struct GNUNET_MQ_Handle * GNUNET_SERVICE_client_get_mq(struct GNUNET_SERVICE_Client *c)
Obtain the message queue of c.
Definition: service.c:2602
Handle to a message queue.
Definition: mq.c:87
Header for all communications.
Project-specific data used to help the OS subsystem find installation paths.
char * agpl_url
URL pointing to the source code of the application.

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

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

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

◆ do_registered_services_shutdown()

static void do_registered_services_shutdown ( void *  cls)
static

Definition at line 2193 of file service.c.

2194{
2195 struct GNUNET_SERVICE_Handle *sh;
2196 struct ServiceHandleList *shl;
2197
2198 for (shl = hll_head; NULL != shl;)
2199 {
2200 sh = shl->sh;
2202 GNUNET_free (shl);
2203 if (-1 != sh->ready_confirm_fd)
2204 {
2205 if (1 != write (sh->ready_confirm_fd, "S", 1))
2207 GNUNET_break (0 == close (sh->ready_confirm_fd));
2208 }
2210 GNUNET_free (sh->handlers);
2211 GNUNET_free (sh);
2212 }
2213}
static void teardown_service(struct GNUNET_SERVICE_Handle *sh)
Tear down the service, closing the listen sockets and freeing the ACLs.
Definition: service.c:1797
static struct ServiceHandleList * hll_head
Definition: service.c:2156
static struct ServiceHandleList * hll_tail
Definition: service.c:2159
struct GNUNET_SERVICE_Handle * sh
Definition: service.c:2152

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

2218{
2219 struct ServiceHandleList *shl;
2220 struct GNUNET_CONFIGURATION_Handle *cfg = cls;
2221
2222 for (shl = hll_head; NULL != shl; shl = shl->next)
2223 {
2224 shl->sh->cfg = cfg;
2225 if (GNUNET_OK != setup_service (shl->sh))
2226 continue;
2227 if (GNUNET_OK != set_user_id (shl->sh))
2228 continue;
2229
2231 }
2233}
static void do_registered_services_shutdown(void *cls)
Definition: service.c:2193
static int set_user_id(struct GNUNET_SERVICE_Handle *sh)
Set user ID.
Definition: service.c:1628
static int setup_service(struct GNUNET_SERVICE_Handle *sh)
Setup service handle.
Definition: service.c:1461
static void service_main(void *cls)
First task run by any service.
Definition: service.c:901
const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition: service.c:122
struct ServiceHandleList * next
Definition: service.c:2149

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

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

2373{
2374 struct GNUNET_SERVICE_Client *c = cls;
2375 int ret;
2376
2377 c->recv_task = NULL;
2378 /* first, check if there is still something in the buffer */
2380 if (GNUNET_SYSERR == ret)
2381 {
2382 if (NULL == c->drop_task)
2384 return;
2385 }
2386 if (GNUNET_NO == ret)
2387 return; /* done processing, wait for more later */
2389 if (GNUNET_YES == c->needs_continue)
2390 return; /* #GNUNET_MST_next() did give a message to the client */
2391 /* need to receive more data from the network first */
2392 if (NULL != c->recv_task)
2393 return;
2395 c->sock,
2397 c);
2398}
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:

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

2450{
2451 struct GNUNET_SERVICE_Client *c = cls;
2452 struct GNUNET_SERVICE_Handle *sh = c->sh;
2453
2454 c->drop_task = NULL;
2455 GNUNET_assert (NULL == c->send_task);
2456 GNUNET_assert (NULL == c->recv_task);
2457 GNUNET_assert (NULL == c->warn_task);
2459 GNUNET_MQ_destroy (c->mq);
2460 if (GNUNET_NO == c->persist)
2461 {
2463 if ((0 != (SUSPEND_STATE_EMFILE & sh->suspend_state)) &&
2464 (0 == (SUSPEND_STATE_SHUTDOWN & sh->suspend_state)))
2466 }
2467 else
2468 {
2470 }
2471 GNUNET_free (c);
2472 if ((0 != (SUSPEND_STATE_SHUTDOWN & sh->suspend_state)) &&
2475}
void GNUNET_MQ_destroy(struct GNUNET_MQ_Handle *mq)
Destroy the message queue.
Definition: mq.c:683
void GNUNET_NETWORK_socket_free_memory_only_(struct GNUNET_NETWORK_Handle *desc)
Only free memory of a socket, keep the file descriptor untouched.
Definition: network.c:565
void GNUNET_MST_destroy(struct GNUNET_MessageStreamTokenizer *mst)
Destroys a tokenizer.
Definition: mst.c:404
int persist
Persist the file handle for this client no matter what happens, force the OS to close once the proces...
Definition: service.c:333

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

Referenced by GNUNET_SERVICE_client_drop().

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

Variable Documentation

◆ hll_head

struct ServiceHandleList* hll_head = NULL
static

◆ hll_tail

struct ServiceHandleList* hll_tail = NULL
static

Definition at line 2159 of file service.c.

Referenced by do_registered_services_shutdown(), and GNUNET_SERVICE_register_().