aboutsummaryrefslogtreecommitdiff
path: root/src/util/service.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/service.c')
-rw-r--r--src/util/service.c142
1 files changed, 99 insertions, 43 deletions
diff --git a/src/util/service.c b/src/util/service.c
index 2c280f5a1..194251af2 100644
--- a/src/util/service.c
+++ b/src/util/service.c
@@ -41,10 +41,10 @@
41#define LOG(kind, ...) GNUNET_log_from (kind, "util-service", __VA_ARGS__) 41#define LOG(kind, ...) GNUNET_log_from (kind, "util-service", __VA_ARGS__)
42 42
43#define LOG_STRERROR(kind, syscall) \ 43#define LOG_STRERROR(kind, syscall) \
44 GNUNET_log_from_strerror (kind, "util-service", syscall) 44 GNUNET_log_from_strerror (kind, "util-service", syscall)
45 45
46#define LOG_STRERROR_FILE(kind, syscall, filename) \ 46#define LOG_STRERROR_FILE(kind, syscall, filename) \
47 GNUNET_log_from_strerror_file (kind, "util-service", syscall, filename) 47 GNUNET_log_from_strerror_file (kind, "util-service", syscall, filename)
48 48
49 49
50/** 50/**
@@ -1923,47 +1923,6 @@ GNUNET_SERVICE_stop (struct GNUNET_SERVICE_Handle *srv)
1923} 1923}
1924 1924
1925 1925
1926/**
1927 * Creates the "main" function for a GNUnet service. You
1928 * should almost always use the #GNUNET_SERVICE_MAIN macro
1929 * instead of calling this function directly (except
1930 * for ARM, which should call this function directly).
1931 *
1932 * The function will launch the service with the name @a service_name
1933 * using the @a service_options to configure its shutdown
1934 * behavior. Once the service is ready, the @a init_cb will be called
1935 * for service-specific initialization. @a init_cb will be given the
1936 * service handler which can be used to control the service's
1937 * availability. When clients connect or disconnect, the respective
1938 * @a connect_cb or @a disconnect_cb functions will be called. For
1939 * messages received from the clients, the respective @a handlers will
1940 * be invoked; for the closure of the handlers we use the return value
1941 * from the @a connect_cb invocation of the respective client.
1942 *
1943 * Each handler MUST call #GNUNET_SERVICE_client_continue() after each
1944 * message to receive further messages from this client. If
1945 * #GNUNET_SERVICE_client_continue() is not called within a short
1946 * time, a warning will be logged. If delays are expected, services
1947 * should call #GNUNET_SERVICE_client_disable_continue_warning() to
1948 * disable the warning.
1949 *
1950 * Clients sending invalid messages (based on @a handlers) will be
1951 * dropped. Additionally, clients can be dropped at any time using
1952 * #GNUNET_SERVICE_client_drop().
1953 *
1954 * @param argc number of command-line arguments in @a argv
1955 * @param argv array of command-line arguments
1956 * @param service_name name of the service to run
1957 * @param options options controlling shutdown of the service
1958 * @param service_init_cb function to call once the service is ready
1959 * @param connect_cb function to call whenever a client connects
1960 * @param disconnect_cb function to call whenever a client disconnects
1961 * @param cls closure argument for @a service_init_cb, @a connect_cb and @a disconnect_cb
1962 * @param handlers NULL-terminated array of message handlers for the service,
1963 * the closure will be set to the value returned by
1964 * the @a connect_cb for the respective connection
1965 * @return 0 on success, non-zero on error
1966 */
1967int 1926int
1968GNUNET_SERVICE_run_ (int argc, 1927GNUNET_SERVICE_run_ (int argc,
1969 char *const *argv, 1928 char *const *argv,
@@ -2177,6 +2136,103 @@ shutdown:
2177 return err ? GNUNET_SYSERR : sh.ret; 2136 return err ? GNUNET_SYSERR : sh.ret;
2178} 2137}
2179 2138
2139struct ServiceHandleList
2140{
2141 struct ServiceHandleList *prev;
2142 struct ServiceHandleList *next;
2143
2144 struct GNUNET_SERVICE_Handle *sh;
2145};
2146
2147int
2148GNUNET_SERVICE_register_ (const char *service_name,
2149 enum GNUNET_SERVICE_Options options,
2150 GNUNET_SERVICE_InitCallback service_init_cb,
2151 GNUNET_SERVICE_ConnectHandler connect_cb,
2152 GNUNET_SERVICE_DisconnectHandler disconnect_cb,
2153 void *cls,
2154 const struct GNUNET_MQ_MessageHandler *handlers)
2155{
2156 static struct ServiceHandleList *hll_head = NULL;
2157 static struct ServiceHandleList *hll_tail = NULL;
2158 struct ServiceHandleList *hle;
2159 struct GNUNET_CONFIGURATION_Handle *cfg;
2160 struct GNUNET_SERVICE_Handle *sh = GNUNET_new (struct GNUNET_SERVICE_Handle);
2161 const char *xdg;
2162 char *cfg_filename;
2163 const struct GNUNET_OS_ProjectData *pd = GNUNET_OS_project_data_get ();
2164 int err;
2165
2166 err = 1;
2167 xdg = getenv ("XDG_CONFIG_HOME");
2168 if (NULL != xdg)
2169 GNUNET_asprintf (&cfg_filename,
2170 "%s%s%s",
2171 xdg,
2172 DIR_SEPARATOR_STR,
2173 pd->config_file);
2174 else
2175 cfg_filename = GNUNET_strdup (pd->user_config_file);
2176 sh->ready_confirm_fd = -1;
2177 sh->options = options;
2178 cfg = GNUNET_CONFIGURATION_create ();
2179 sh->cfg = cfg;
2180 sh->service_init_cb = service_init_cb;
2181 sh->connect_cb = connect_cb;
2182 sh->disconnect_cb = disconnect_cb;
2183 sh->cb_cls = cls;
2184 sh->handlers = (NULL == pd->agpl_url)
2185 ? GNUNET_MQ_copy_handlers (handlers)
2186 : GNUNET_MQ_copy_handlers2 (handlers, &return_agpl, NULL);
2187 sh->service_name = service_name;
2188 sh->ret = 0;
2189 if (GNUNET_YES == GNUNET_DISK_file_test (cfg_filename))
2190 {
2191 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, cfg_filename))
2192 {
2193 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2194 _ ("Malformed configuration file `%s', exit ...\n"),
2195 cfg_filename);
2196 goto fail;
2197 }
2198 }
2199 else
2200 {
2201 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, NULL))
2202 {
2203 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2204 _ ("Malformed configuration, exit ...\n"));
2205 goto fail;
2206 }
2207 }
2208 if (GNUNET_OK != setup_service (sh))
2209 goto fail;
2210 if (GNUNET_OK != set_user_id (sh))
2211 goto fail;
2212 GNUNET_RESOLVER_connect (sh->cfg);
2213
2214 /* actually run service */
2215 err = 0;
2216 hle = GNUNET_new (struct ServiceHandleList);
2217 hle->sh = sh;
2218 GNUNET_CONTAINER_DLL_insert (hll_head, hll_tail, hle);
2219 /* shutdown */
2220fail:
2221 if (-1 != sh->ready_confirm_fd)
2222 {
2223 if (1 != write (sh->ready_confirm_fd, err ? "I" : "S", 1))
2224 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "write");
2225 GNUNET_break (0 == close (sh->ready_confirm_fd));
2226 }
2227 teardown_service (sh);
2228 GNUNET_free (sh->handlers);
2229 GNUNET_SPEEDUP_stop_ ();
2230 GNUNET_CONFIGURATION_destroy (cfg);
2231 GNUNET_free (cfg_filename);
2232 GNUNET_free (sh);
2233 return err ? GNUNET_SYSERR : sh->ret;
2234}
2235
2180 2236
2181/** 2237/**
2182 * Suspend accepting connections from the listen socket temporarily. 2238 * Suspend accepting connections from the listen socket temporarily.