📄 server.c
字号:
/* * server.c - server object functions * * Copyright (C) 2000, 2001 Stefan Jahn <stefan@lkcc.org> * Copyright (C) 2000 Raimund Jacob <raimi@lkcc.org> * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * $Id: server.c,v 1.28 2001/08/17 13:54:15 ela Exp $ * */#if HAVE_CONFIG_H# include <config.h>#endif#define _GNU_SOURCE#include <stdio.h>#include <string.h>#ifdef __MINGW32__# include <winsock2.h>#else# include <sys/types.h># include <sys/socket.h># include <netinet/in.h># include <arpa/inet.h>#endif#include "libserveez/alloc.h"#include "libserveez/hash.h"#include "libserveez/util.h"#include "libserveez/core.h"#include "libserveez/array.h"#include "libserveez/socket.h"#include "libserveez/server-core.h"#include "libserveez/server.h"#include "libserveez/binding.h"#include "libserveez/dynload.h"/* * The list of registered server. Feel free to add yours. */svz_array_t *svz_servertypes = NULL;/* * Add the server type @var{server} to the currently registered servers. */voidsvz_servertype_add (svz_servertype_t *server){ int n; svz_servertype_t *stype; /* Check if the server definition is valid. */ if (!server || !server->prefix || !server->description) { svz_log (LOG_ERROR, "invalid server type\n"); return; } /* Check if the server is already registered. */ svz_array_foreach (svz_servertypes, stype, n) { if (!strcmp (server->prefix, stype->prefix)) { svz_log (LOG_ERROR, "server type `%s' already registered\n", server->description); return; } } /* Run the global server type initializer. */ if (server->global_init != NULL) if (server->global_init (server) < 0) { svz_log (LOG_ERROR, "error running global init for `%s'\n", server->description); return; } /* Add this definition to the registered servers. */ if (svz_servertypes == NULL) if ((svz_servertypes = svz_array_create (1)) == NULL) return; svz_array_add (svz_servertypes, server);}/* * Delete the server type with the index @var{index} from the list of * known server types and run its global finalizer if necessary. Moreover * we remove and finalize each server instance of this server type. */voidsvz_servertype_del (unsigned long index){ svz_servertype_t *stype; svz_server_t **server; int n, i; /* Return here if there is no such server type. */ if (svz_servertypes == NULL || index >= svz_array_size (svz_servertypes)) return; /* Run the server type's global finalizer if necessary and delete it from the list of known servers then. */ if ((stype = svz_array_get (svz_servertypes, index)) != NULL) { /* Find server instance of this server type and remove and finalize them if necessary. */ n = svz_hash_size (svz_servers) - 1; svz_hash_foreach_value (svz_servers, server, i) { if (server[n]->type == stype) { svz_server_del (server[n]->name); i--; } n--; } if (stype->global_finalize != NULL) stype->global_finalize (stype); svz_array_del (svz_servertypes, index); }}/* * Find a servertype definition by its short name. If @var{dynamic} is set * to non-zero an attempt is made to load a shared library that provides * that servertype. Returns @code{NULL} if no server with the given variable * prefix @var{name} has been found. */svz_servertype_t *svz_servertype_get (char *name, int dynamic){ svz_servertype_t *stype; int n; /* first, try with already loaded ones */ svz_array_foreach (svz_servertypes, stype, n) { if (!strcmp (name, stype->prefix)) return stype; } /* now, try dynamically */ if (dynamic) { if (NULL != (stype = svz_servertype_load (name))) { svz_servertype_add (stype); return stype; } } return NULL;}/* * Run the global finalizers of each server type and delete all server * types. */voidsvz_servertype_finalize (void){ int i; svz_servertype_t *stype; svz_log (LOG_NOTICE, "running global server type finalizers\n"); svz_array_foreach (svz_servertypes, stype, i) { if (stype->global_finalize != NULL) stype->global_finalize (stype); } if (svz_servertypes != NULL) { svz_array_destroy (svz_servertypes); svz_servertypes = NULL; }}/* * Find a given server instances @var{server} server type. Return @code{NULL} * if there is no such server type (which should never occur since a server is * a child of an server type. */svz_servertype_t *svz_servertype_find (svz_server_t *server){ return server ? server->type : NULL;}#if ENABLE_DEBUG/* * Debug helper function to traverse all currently known server types. */voidsvz_servertype_print (void){ int s, i; svz_servertype_t *stype; svz_array_foreach (svz_servertypes, stype, s) { printf ("[%d] - %s\n", s, stype->description); printf (" detect_proto() at %p" " connect_socket() at %p\n", (void *) stype->detect_proto, (void *) stype->connect_socket); if (stype->prototype_start != NULL) { printf (" configblock %d byte at %p: \n", stype->prototype_size, stype->prototype_start); for (i = 0; stype->items[i].type != SVZ_ITEM_END; i++) { long offset = (char *) stype->items[i].address - (char *) stype->prototype_start; printf (" variable `%s' at offset %d, %sdefaultable: ", stype->items[i].name, (int) offset, stype->items[i].defaultable ? "" : "not "); switch (stype->items[i].type) { case SVZ_ITEM_BOOL: printf ("bool\n"); break; case SVZ_ITEM_INT: printf ("int\n"); break; case SVZ_ITEM_INTARRAY: printf ("int array\n"); break; case SVZ_ITEM_STR: printf ("string\n"); break; case SVZ_ITEM_STRARRAY: printf ("string array\n"); break; case SVZ_ITEM_HASH: printf ("hash\n"); break; case SVZ_ITEM_PORTCFG: printf ("port configuration\n"); break; default: printf ("unknown\n"); } } } else { printf (" no configuration option\n"); } }}#endif /* ENABLE_DEBUG *//* * This is the list of actually instantiated servers. The hash table * associates the servers' names with the server instances. */svz_hash_t *svz_servers = NULL;/* * Run all the server instances's notify routines. This should be regularly * called within the @code{svz_periodic_tasks()} function. */voidsvz_server_notifiers (void){ int n; svz_server_t **server; svz_hash_foreach_value (svz_servers, server, n) { if (server[n]->notify) server[n]->notify (server[n]); }}/* * Find a server instance by the given configuration structure @var{cfg}. * Return @code{NULL} if there is no such configuration in any server * instance. */svz_server_t *svz_server_find (void *cfg){ int n; svz_server_t **servers, *server = NULL; svz_hash_foreach_value (svz_servers, servers, n) { if (servers[n]->cfg == cfg) server = servers[n]; } return server;}/* * Add the server instance @var{server} to the list of instantiated * servers. Returns the previous value of that server if any or @code{NULL} * otherwise. */svz_server_t *svz_server_add (svz_server_t *server){ if (svz_servers == NULL) svz_servers = svz_hash_create (4); return svz_hash_put (svz_servers, server->name, server);}/* * Get the server instance with the given instance name @var{name}. * Return @code{NULL} if there is no such server yet. */svz_server_t *svz_server_get (char *name){ if (svz_servers == NULL || name == NULL) return NULL; return svz_hash_get (svz_servers, name);}/* * Remove the server instance identified by the name @var{name}. */voidsvz_server_del (char *name){ svz_server_t *server; if (svz_servers == NULL) return; if ((server = svz_hash_delete (svz_servers, name)) != NULL) { svz_server_unbind (server); svz_server_free (server); }}/* * Release the configuration @var{cfg} of the given server type @var{server}. * If the servers configuration equals @code{NULL} no operation is * performed. */voidsvz_config_free (svz_servertype_t *server, void *cfg){ int n; void **target; /* Return here if there nothing to do. */ if (server == NULL || cfg == NULL) return; /* Go through the list of configuration items. */ for (n = 0; server->items[n].type != SVZ_ITEM_END; n++) { /* Calculate the target address. */ target = (void **) ((long) cfg + (long) ((long) server->items[n].address - (long) server->prototype_start)); /* Depending on the type of configuration item we need to free different data structures. */ switch (server->items[n].type) { /* Integer array. */ case SVZ_ITEM_INTARRAY: if (*target) svz_config_intarray_destroy (*target); break; /* Simple character string. */ case SVZ_ITEM_STR: if (*target) svz_free (*target); break; /* Array of strings. */ case SVZ_ITEM_STRARRAY: if (*target) svz_config_strarray_destroy (*target); break; /* Hash table. */ case SVZ_ITEM_HASH: if (*target) svz_config_hash_destroy (*target); break; /* Port configuration. */ case SVZ_ITEM_PORTCFG: if (*target) svz_portcfg_destroy (*target); break; } } svz_free (cfg);}/* * Clear each configuration item within the given configuration @var{cfg} of * the server type @var{server}. This function is used by * @code{svz_server_configure()} after copying the default configuration. */static voidsvz_config_clobber (svz_servertype_t *server, void *cfg){ int n; void **target; /* Return here if there nothing to do. */ if (server == NULL || cfg == NULL) return; /* Go through the list of configuration items. */ for (n = 0; server->items[n].type != SVZ_ITEM_END; n++) { /* Calculate the target address. */ target = (void **) ((long) cfg + (long) ((long) server->items[n].address - (long) server->prototype_start)); /* Clobber only configuration items which are pointers. */ if (server->items[n].type == SVZ_ITEM_INTARRAY || server->items[n].type == SVZ_ITEM_STR || server->items[n].type == SVZ_ITEM_STRARRAY || server->items[n].type == SVZ_ITEM_HASH || server->items[n].type == SVZ_ITEM_PORTCFG) { *target = NULL; } }}/* * Completely destroy the given server instance @var{server}. This * especially means to go through each item of the server instances * configuration. */voidsvz_server_free (svz_server_t *server){ svz_config_free (server->type, server->cfg); svz_free (server->name); svz_free (server);}/* * Create a new server instance of the server type @var{stype} with the * instance name @var{name}. */svz_server_t *svz_server_instantiate (svz_servertype_t *stype, char *name){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -