+#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)
+
+
+/**
+ * Information the service tracks per listen operation.
+ */
+struct ServiceListenContext
+{
+
+ /**
+ * Kept in a DLL.
+ */
+ struct ServiceListenContext *next;
+
+ /**
+ * Kept in a DLL.
+ */
+ struct ServiceListenContext *prev;
+
+ /**
+ * Service this listen context belongs to.
+ */
+ struct GNUNET_SERVICE_Handle *sh;
+
+ /**
+ * Socket we are listening on.
+ */
+ struct GNUNET_NETWORK_Handle *listen_socket;
+
+ /**
+ * Task scheduled to do the listening.
+ */
+ struct GNUNET_SCHEDULER_Task *listen_task;
+
+};
+
+
+/**
+ * Reasons why we might be suspended.
+ */
+enum SuspendReason
+{
+ /**
+ * We are running normally.
+ */
+ SUSPEND_STATE_NONE = 0,
+
+ /**
+ * Application requested it.
+ */
+ SUSPEND_STATE_APP = 1,
+
+ /**
+ * OS ran out of file descriptors.
+ */
+ SUSPEND_STATE_EMFILE = 2,
+
+ /**
+ * Both reasons, APP and EMFILE apply.
+ */
+ SUSPEND_STATE_APP_AND_EMFILE = 3,
+
+ /**
+ * Suspension because service was permanently shutdown.
+ */
+ SUSPEND_STATE_SHUTDOWN = 4
+};
+
+
+/**
+ * Handle to a service.
+ */
+struct GNUNET_SERVICE_Handle
+{
+ /**
+ * Our configuration.
+ */
+ const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+ /**
+ * Name of our service.
+ */
+ const char *service_name;
+
+ /**
+ * Main service-specific task to run.
+ */
+ GNUNET_SERVICE_InitCallback service_init_cb;
+
+ /**
+ * Function to call when clients connect.
+ */
+ GNUNET_SERVICE_ConnectHandler connect_cb;
+
+ /**
+ * Function to call when clients disconnect / are disconnected.
+ */
+ GNUNET_SERVICE_DisconnectHandler disconnect_cb;
+
+ /**
+ * Closure for @e service_init_cb, @e connect_cb, @e disconnect_cb.
+ */
+ void *cb_cls;
+
+ /**
+ * DLL of listen sockets used to accept new connections.
+ */
+ struct ServiceListenContext *slc_head;
+
+ /**
+ * DLL of listen sockets used to accept new connections.
+ */
+ struct ServiceListenContext *slc_tail;
+
+ /**
+ * Our clients, kept in a DLL.
+ */
+ struct GNUNET_SERVICE_Client *clients_head;
+
+ /**
+ * Our clients, kept in a DLL.
+ */
+ struct GNUNET_SERVICE_Client *clients_tail;
+
+ /**
+ * Message handlers to use for all clients.
+ */
+ struct GNUNET_MQ_MessageHandler *handlers;
+
+ /**
+ * Closure for @e task.
+ */
+ void *task_cls;
+
+ /**
+ * IPv4 addresses that are not allowed to connect.
+ */
+ struct GNUNET_STRINGS_IPv4NetworkPolicy *v4_denied;
+
+ /**
+ * IPv6 addresses that are not allowed to connect.
+ */
+ struct GNUNET_STRINGS_IPv6NetworkPolicy *v6_denied;
+
+ /**
+ * IPv4 addresses that are allowed to connect (if not
+ * set, all are allowed).
+ */
+ struct GNUNET_STRINGS_IPv4NetworkPolicy *v4_allowed;
+
+ /**
+ * IPv6 addresses that are allowed to connect (if not
+ * set, all are allowed).
+ */
+ struct GNUNET_STRINGS_IPv6NetworkPolicy *v6_allowed;
+
+ /**
+ * Do we require a matching UID for UNIX domain socket connections?
+ * #GNUNET_NO means that the UID does not have to match (however,
+ * @e match_gid may still impose other access control checks).
+ */
+ int match_uid;
+
+ /**
+ * Do we require a matching GID for UNIX domain socket connections?
+ * Ignored if @e match_uid is #GNUNET_YES. Note that this is about
+ * checking that the client's UID is in our group OR that the
+ * client's GID is our GID. If both "match_gid" and @e match_uid are
+ * #GNUNET_NO, all users on the local system have access.
+ */
+ int match_gid;
+
+ /**
+ * Are we suspended, and if so, why?
+ */
+ enum SuspendReason suspend_state;
+
+ /**
+ * Our options.
+ */
+ enum GNUNET_SERVICE_Options options;