📄 server.c
字号:
svz_server_t *server; /* Create server instance itself. */ server = (svz_server_t *) svz_malloc (sizeof (svz_server_t)); server->name = svz_strdup (name); server->type = stype; /* Transfer callbacks. */ server->detect_proto = stype->detect_proto; server->connect_socket = stype->connect_socket; server->handle_request = stype->handle_request; server->init = stype->init; server->finalize = stype->finalize; server->info_client = stype->info_client; server->info_server = stype->info_server; server->notify = stype->notify; server->description = stype->description; return server;}/* * Create an array (@code{svz_array_t}) of integers. The given integer * array @var{intarray} is a list of integers where its first element which * is @code{intarray[0]} contains the actual length of the given array. */svz_array_t *svz_config_intarray_create (int *intarray){ int i; svz_array_t *array = svz_array_create (1); if (intarray) { for (i = 0; i < intarray[0]; i++) svz_array_add (array, (void *) ((long) intarray[i + 1])); } return array;}/* * Destroy the given integer array @var{intarray}. This function is the * counter part of @code{svz_config_intarray_create()}. */voidsvz_config_intarray_destroy (svz_array_t *intarray){ if (intarray) { svz_array_destroy (intarray); }}/* * Make a plain copy of the given integer array @var{intarray}. If this * value is @code{NULL} no operation is performed and the return value * is @code{NULL} too. */svz_array_t *svz_config_intarray_dup (svz_array_t *intarray){ int i; void *value; svz_array_t *array = NULL; if (intarray) { array = svz_array_create (svz_array_size (intarray)); svz_array_foreach (intarray, value, i) svz_array_add (array, value); } return array;}/* * Create an array of strings. The given list of strings @var{strarray} * must be @code{NULL} terminated in order to indicate its end. */svz_array_t *svz_config_strarray_create (char **strarray){ int i; svz_array_t *array = svz_array_create (1); if (strarray) { for (i = 0; strarray[i] != NULL; i++) svz_array_add (array, svz_strdup (strarray[i])); } return array;}/* * Destroy the given string array @var{strarray}. */voidsvz_config_strarray_destroy (svz_array_t *strarray){ int i; char *string; if (strarray) { svz_array_foreach (strarray, string, i) svz_free (string); svz_array_destroy (strarray); }}/* * Duplicate the given array of strings @var{strarray}. Return @code{NULL} * if @var{strarray} equals @code{NULL}. */svz_array_t *svz_config_strarray_dup (svz_array_t *strarray){ int i; char *value; svz_array_t *array = NULL; if (strarray) { array = svz_array_create (svz_array_size (strarray)); svz_array_foreach (strarray, value, i) svz_array_add (array, svz_strdup (value)); } return array;}/* * Create a hash table from the given array of strings @var{strarray} which * must be @code{NULL} terminated in order to indicate the end of the list. * The array consists of pairs of strings where the first one specifies a * key and the following the associated string value. This function is * useful when creating default values for server type configurations. */svz_hash_t *svz_config_hash_create (char **strarray){ int i; svz_hash_t *hash = svz_hash_create (4); if (strarray) { for (i = 0; strarray[i] != NULL; i += 2) { if (strarray[i + 1]) { svz_hash_put (hash, strarray[i], svz_strdup (strarray[i + 1])); } } } return hash;}/* * This function is the counter part of @code{svz_config_hash_create()}. It * destroys the given hash table @var{strhash} assuming it is a hash * associating strings with strings. */voidsvz_config_hash_destroy (svz_hash_t *strhash){ char **strarray; int i; if (strhash) { svz_hash_foreach_value (strhash, strarray, i) svz_free (strarray[i]); svz_hash_destroy (strhash); }}/* * Duplicate the given hash table @var{strhash} assuming it is a hash * associating strings with strings. Return @code{NULL} if @var{strhash} is * @code{NULL} too. */svz_hash_t *svz_config_hash_dup (svz_hash_t *strhash){ svz_hash_t *hash = NULL; int i; char **keys; if (strhash) { hash = svz_hash_create (4); svz_hash_foreach_key (strhash, keys, i) { svz_hash_put (hash, keys[i], svz_strdup (svz_hash_get (strhash, keys[i]))); } } return hash;}/* * This function configures a server instance by modifying its default * configuration by the @var{configure} callbacks. Therefore you need to pass * the type of server in @var{server}, the @var{name} of the server instance * and the (optional) modifier callback structure @var{configure}. The * @var{arg} argument is passed to each of the callbacks (e.g. specifying * a scheme cell). The function returns either a valid server instance * configuration or @code{NULL} on errors. */void *svz_server_configure (svz_servertype_t *server, char *name, void *arg, svz_server_config_t *configure){ int e, n, error = 0; int hasdef; void *cfg = NULL, *def, *target = NULL; unsigned long offset; /* Run the 'before' callback first. */ if (configure && configure->before) if (SVZ_ITEM_OK != configure->before (name, arg)) return NULL; /* Make a simple copy of the example configuration structure definition for that server instance. */ if (server->prototype_size == 0) goto out; cfg = svz_malloc (server->prototype_size); memcpy (cfg, server->prototype_start, server->prototype_size); /* Clear all server configuration items which are pointers. Thus we are able to reverse the changes below. */ svz_config_clobber (server, cfg); /* Go through list of configuration items. */ for (n = 0; server->items[n].type != SVZ_ITEM_END; n++) { /* Calculate the target address. */ offset = (char *) server->items[n].address - (char *) server->prototype_start; hasdef = server->items[n].defaultable; def = server->items[n].address; target = (char *) cfg + offset; e = SVZ_ITEM_DEFAULT_ERRMSG; /* Check the address of the target. */ if ((unsigned long) target < (unsigned long) cfg || (unsigned long) target >= ((unsigned long) cfg + (unsigned long) server->prototype_size)) { svz_log (LOG_FATAL, "%s: invalid target address for %s `%s'\n", server->prefix, SVZ_ITEM_TEXT (server->items[n].type), server->items[n].name); error = -1; continue; } /* Depending on the type of configuration item we need at this point we call the given callbacks and check their return values. */ switch (server->items[n].type) { /* Integer value. */ case SVZ_ITEM_INT: if (configure && configure->integer) e = configure->integer (name, arg, server->items[n].name, (int *) target, hasdef, *(int *) def); break; /* Boolean value. */ case SVZ_ITEM_BOOL: if (configure && configure->boolean) e = configure->boolean (name, arg, server->items[n].name, (int *) target, hasdef, *(int *) def); break; /* Integer array. */ case SVZ_ITEM_INTARRAY: if (configure && configure->intarray) e = configure->intarray (name, arg, server->items[n].name, (svz_array_t **) target, hasdef, *(svz_array_t **) def); break; /* Simple string. */ case SVZ_ITEM_STR: if (configure && configure->string) e = configure->string (name, arg, server->items[n].name, (char **) target, hasdef, *(char **) def); break; /* Array of strings. */ case SVZ_ITEM_STRARRAY: if (configure && configure->strarray) e = configure->strarray (name, arg, server->items[n].name, (svz_array_t **) target, hasdef, *(svz_array_t **) def); break; /* Hash table. */ case SVZ_ITEM_HASH: if (configure && configure->hash) e = configure->hash (name, arg, server->items[n].name, (svz_hash_t **) target, hasdef, *(svz_hash_t **) def); break; /* Port configuration. */ case SVZ_ITEM_PORTCFG: if (configure && configure->portcfg) e = configure->portcfg (name, arg, server->items[n].name, (svz_portcfg_t **) target, hasdef, *(svz_portcfg_t **) def); break; /* Unknown configuration item. */ default: svz_log (LOG_FATAL, "inconsistent ITEM_ data in server type `%s'\n", server->description); error = -1; e = -1; /* special */ } /* Check the return value of the configure functions. */ switch (e) { /* Special case: skip. */ case -1: break; /* Successfully configured. */ case SVZ_ITEM_OK: break; /* Use the default value, if any. */ case SVZ_ITEM_DEFAULT: case SVZ_ITEM_DEFAULT_ERRMSG: /* Target not configured. Defaultable ? */ if (!server->items[n].defaultable) { if (SVZ_ITEM_DEFAULT_ERRMSG == e) svz_log (LOG_ERROR, "`%s' lacks a default %s for `%s' in `%s'\n", server->description, SVZ_ITEM_TEXT (server->items[n].type), server->items[n].name, name); error = -1; break; } /* Go on, using default values. */ switch (server->items[n].type) { case SVZ_ITEM_INT: /* Normal integer. */ *(int *) target = *(int *) def; break; case SVZ_ITEM_BOOL: /* Boolean value. */ *(int *) target = *(int *) def; break; case SVZ_ITEM_INTARRAY: /* Integer array. */ *(svz_array_t **) target = svz_config_intarray_dup (*(svz_array_t **) def); break; case SVZ_ITEM_STR: /* Character string. */ *(char **) target = (char *) svz_strdup (*(char **) def); break; case SVZ_ITEM_STRARRAY: /* Array of strings. */ *(svz_array_t **) target = svz_config_strarray_dup (*(svz_array_t **) def); break; case SVZ_ITEM_HASH: /* Hash table. */ *(svz_hash_t **) target = svz_config_hash_dup (*(svz_hash_t **) def); break; case SVZ_ITEM_PORTCFG: /* Port configuration. */ *(svz_portcfg_t **) target = svz_portcfg_dup (*(svz_portcfg_t **) def); break; } break; /* Configuring failed. Skip error messages. */ case SVZ_ITEM_FAILED: error = -1; break; /* Configuring failed. Print error messages. */ case SVZ_ITEM_FAILED_ERRMSG: svz_log (LOG_ERROR, "invalid %s value for `%s' in `%s'\n", SVZ_ITEM_TEXT (server->items[n].type), server->items[n].name, name); error = -1; break; /* Special case: Configure callback invalid. */ default: svz_log (LOG_FATAL, "invalid SVZ_ITEM_ value (%d) returned by %s " "callback for `%s'\n", e, SVZ_ITEM_TEXT (server->items[n].type), server->items[n].name); error = -1; } } out: /* Run the 'after' callback last. */ if (configure && configure->after) if (SVZ_ITEM_OK != configure->after (name, arg)) error = -1; /* Release memory reserved for configuration on errors. This means to reverse the above changes. */ if (error) { svz_config_free (server, cfg); cfg = NULL; } return cfg;}/* * Run the initializers of all servers, return -1 if some server did not * think it is a good idea to run. */intsvz_server_init_all (void){ int errneous = 0, i; svz_server_t **server; svz_log (LOG_NOTICE, "initializing all server instances\n"); svz_hash_foreach_value (svz_servers, server, i) { if (server[i]->init != NULL) if (server[i]->init (server[i]) < 0) { errneous = -1; svz_log (LOG_ERROR, "error initializing `%s'\n", server[i]->name); } } return errneous;}/* * Run the local finalizers for all server instances. */intsvz_server_finalize_all (void){ int i, n; svz_server_t **server; svz_log (LOG_NOTICE, "running all server finalizers\n"); n = svz_hash_size (svz_servers) - 1; svz_hash_foreach_value (svz_servers, server, i) { if (server[n]->finalize != NULL) server[n]->finalize (server[n]); svz_server_del (server[n]->name); i--; n--; } svz_hash_destroy (svz_servers); svz_servers = NULL; return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -