📄 mod_gsoap.c
字号:
/** Apache gSOAP module for Apache 2.0 * @file mod_gsoap.c * * author Christian Aberger (http://www.aberger.at) * ported to 2.0 Mick Wall (mick@mickandwendy.com) * updated by Robert van Engelen (engelen@acm.org) * updated by David Viner (dviner@apache.org) * updated by Ryan Troll (patch removed) * * Contributed to the gSOAP package under the terms and conditions of the gSOAP * open source public license. * */#if !defined(__GNUC__) || __GNUC__ < 2 || \ (__GNUC__ == 2 && __GNUC_MINOR__ < 7) ||\ defined(NEXT)#ifndef __attribute__#define __attribute__(__x)#endif#endif#include <stdio.h>#include <assert.h>//#include <ltdl.h>#include <dlfcn.h>#include "apr_strings.h"#include "apr_fnmatch.h"#include "apr_strings.h"#include "apr_lib.h"#include "apr_pools.h"#define APR_WANT_STRFUNC#include "apr_want.h"#include "httpd.h"#include "http_request.h"#include "http_config.h"#include "http_core.h"#include "http_log.h"#include "http_main.h"#include "http_protocol.h"#include "http_request.h"#include "util_script.h"#include "stdsoap2.h" // standard header for gsoap#include "apache_gsoap.h"typedef int bool;#define false 0#define true ((int)0xffff)#define IOBUF_CHUNK_SIZE 8192#define GSOAP_ID "Apache 2.0 mod_gsoap gsoap httpd extension 0.0.6"static char mod_gsoap_id[] = GSOAP_ID;/** A shared library containing a SOAP server. */typedef struct SoapSharedLibrary_S { apr_pool_t *m_pPool;#ifdef WIN32#define DLSYM(a,b) GetProcAddress(a,b)#define DLOPEN(a,b) LoadLibrary(a) HMODULE m_hLibrary;#else#define DLSYM(a,b) dlsym(a,b)#define DLOPEN(a,b) dlopen(a,b) void *m_hLibrary; ///< handle of the loaded libray.#endif const char *m_pszPath; ///< the path of the library, including the name. bool m_bIsSOAPLibrary; ///< is this library a SOAP library that contains the server factory entry point?} SoapSharedLibrary;/** Table of shared libraries that are already loaded. * a singleton. */typedef struct SoapSharedLibraries_S { apr_pool_t *m_pPool; SoapSharedLibrary *m_pSOAPLibrary; ///< the main SOAP library that will serve our requests apr_array_header_t *m_pLibraries; ///< the array where we store our libraries. apache_init_soap_interface_fn m_pfnEntryPoint; struct apache_soap_interface *m_pIntf; bool m_bAllLibrariesLoaded; ///< have all libraries in our libraries collection been already successfully loaded?} SoapSharedLibraries;/** Environment to which record applies (directory, * server, or combination). */typedef enum enConfigurationType { ct_server = 1, ///< used for per-server configuration ct_directory = 2, ///< used for per-directory configuration ct_both = 3 ///< used for both} ConfigurationType;/** Store the configuration information set in the Apache Server configuration directives. * These are set e.g. in the file httpd.conf * It's perfectly reasonable to have two different structures for the two * different environments. The same command handlers will be called for * both, though, so the handlers need to be able to tell them apart. One * possibility is for both structures to start with an int which is zero for * one and 1 for the other. * * Note that while the per-directory and per-server configuration records are * available to most of the module handlers, they should be treated as * READ-ONLY by all except the command and merge handlers. Sometimes handlers * are handed a record that applies to the current location by implication or * inheritance, and modifying it will change the rules for other locations. */typedef struct gsoapConfiguration_S { SoapSharedLibraries *m_pLibraries; ConfigurationType m_Type; ///< the type of configuration environment} gsoapConfiguration;/** Our internal per request soap configuration */typedef struct gsoapRequestConfiguration_S { request_rec *r; ///< the current request record. char *m_pszAllHeaders; ///< all headers received as a string, this is returned to gsoap's http_parse function before we return the body. const char *m_pszCurrentHeaderReadingPosition; ///< the position where the next header read operation will start. unsigned int m_nHeaderLength; ///< total length of all headers concatenated as string char *m_pOutBuf; ///< output buffer size_t m_nOutBufLength; ///< allocated length of output buffer size_t m_nOutBufCount; ///< bytes in output buffer int headers_sent; ///< have http - headers already been sent to client us? int headers_received; ///< have the request headers already been passed to gsoap ? int (*http_parse) (struct soap *); ///< the original gsoap parsing function. struct apache_soap_interface *pIntf;} gsoapRequestConfiguration;/* * To avoid leaking memory from pools other than the per-request one, we * allocate a module-private pool. */static apr_pool_t *the_gsoapPool = NULL;/** @return our apr_pool_tfor gsoapConfiguration */static apr_pool_t *gsoapConfiguration_getModulePool(){ if(NULL == the_gsoapPool) { apr_pool_create_ex(&the_gsoapPool, NULL, NULL, NULL); } return the_gsoapPool;}static gsoapConfiguration *getConfiguration(request_rec * r);static gsoapRequestConfiguration *getRequestConfiguration(struct soap *);/** @param p the apr_pool_tto use for memory allocations. @param pszPath the path of the library.*/static voidSoapSharedLibrary_init(SoapSharedLibrary * This, apr_pool_t * p, const SoapSharedLibrary * pLib){ This->m_pPool = p; This->m_hLibrary = NULL; This->m_pszPath = apr_pstrdup(p, pLib->m_pszPath); This->m_bIsSOAPLibrary = pLib->m_bIsSOAPLibrary;}static voidSoapSharedLibrary_init2(SoapSharedLibrary * This, apr_pool_t * p, const char *pszPath){ This->m_pPool = p; This->m_hLibrary = NULL; This->m_pszPath = apr_pstrdup(p, pszPath); This->m_bIsSOAPLibrary = false;}static voidSoapSharedLibrary_clear(SoapSharedLibrary * This, apr_pool_t * p){ This->m_pPool = p; This->m_hLibrary = NULL; This->m_pszPath = NULL; This->m_bIsSOAPLibrary = false;}static SoapSharedLibrary *SoapSharedLibrary_create(apr_pool_t * p){ SoapSharedLibrary *This = (SoapSharedLibrary *) apr_pcalloc(p, sizeof(SoapSharedLibrary)); SoapSharedLibrary_clear(This, p); return This;}/* * SoapSharedLibrary_assign(SoapSharedLibrary *This, SoapSharedLibrary *pLib) { * This->m_pPool = pLib->m_pPool; * This->m_hLibrary = NULL; * This->m_pszPath = ap_strdup(m_pPool, pLib->m_pszPath); * This->m_bIsSoapLibrary = pLib->m_bIsSoapLibrary; * } *//** * @param pTempPool pool to use for allocating temporary objects (e.g. error message). */static const char *SoapSharedLibrary_load(SoapSharedLibrary * This, apr_pool_t * pTempPool){ const char *pszError = NULL;#ifdef WIN32 This->m_hLibrary = DLOPEN(This->m_pszPath); if(!This->m_hLibrary) { LPVOID lpMsgBuf; FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) & lpMsgBuf, 0, NULL); pszError = apr_psprintf(NULL == pTempPool ? This->m_pPool : pTempPool, "Load of %s failed with %s", This->m_pszPath, lpMsgBuf); LocalFree(lpMsgBuf); }#else const int nFlags = RTLD_LAZY | RTLD_GLOBAL; This->m_hLibrary = (void *)DLOPEN(This->m_pszPath, nFlags); pszError = dlerror();#endif if(NULL == This->m_hLibrary) { pszError = apr_psprintf(NULL == pTempPool ? This->m_pPool : pTempPool, "mod_gsoap: %s loading library %s", pszError, This->m_pszPath); } return pszError;}/*-------------------------------------------------------*/static voidSoapSharedLibraries_init(SoapSharedLibraries * This, apr_pool_t * p){ This->m_pSOAPLibrary = NULL; This->m_pPool = p; This->m_pSOAPLibrary = NULL; This->m_pLibraries = apr_array_make(p, 0, sizeof(SoapSharedLibrary **)); This->m_bAllLibrariesLoaded = false; This->m_pfnEntryPoint = NULL; This->m_pIntf = (struct apache_soap_interface *)apr_pcalloc(p, sizeof(struct apache_soap_interface));}static SoapSharedLibrary *SoapSharedLibraries_getLibrary(SoapSharedLibraries * This, unsigned nIndex){ SoapSharedLibrary **ppLibs = NULL; SoapSharedLibrary *pLib = NULL; assert(NULL != This); assert(NULL != This->m_pLibraries); assert(nIndex >= 0); assert(nIndex < This->m_pLibraries->nelts); ppLibs = (SoapSharedLibrary **) This->m_pLibraries->elts; pLib = ppLibs[nIndex]; return pLib;}/** * @param pszPath the operating system name of the library. */static boolSoapSharedLibraries_contains(SoapSharedLibraries * This, const char *pszPath){ int i = 0; bool bContains = false; for(i = 0; i < This->m_pLibraries->nelts && !bContains; i++) { SoapSharedLibrary *pLib = SoapSharedLibraries_getLibrary(This, i); assert(NULL != pLib); if(0 == strcmp(pszPath, pLib->m_pszPath)) { bContains = true; } } return bContains;}static voidSoapSharedLibraries_addLibrary(SoapSharedLibraries * This, SoapSharedLibrary * pLibrary){ assert(NULL != pLibrary); This->m_bAllLibrariesLoaded = false; if(!SoapSharedLibraries_contains(This, pLibrary->m_pszPath)) { SoapSharedLibrary **ppNewLib = (SoapSharedLibrary **) apr_array_push(This->m_pLibraries); *ppNewLib = pLibrary; if(pLibrary->m_bIsSOAPLibrary) { This->m_pSOAPLibrary = pLibrary; } }}static const char *SoapSharedLibraries_getEntryPoints(SoapSharedLibraries * This, SoapSharedLibrary * pLib, apr_pool_t * pTempPool, request_rec * r){ /* * now we also pass the request record */ (*This->m_pfnEntryPoint) (This->m_pIntf, r); return NULL;}/** * @return the error message if a load failed, NULL on success. */static const char *SoapSharedLibraries_loadAllLibraries(SoapSharedLibraries * This, apr_pool_t * pTempPool, request_rec * r){ bool bAllLibrariesLoaded = false; const char *pszError = NULL; bool bRetry = false; int i = 0; int nRetry = 0; assert(NULL != This); if(This->m_bAllLibrariesLoaded) { return NULL; } for(nRetry = 0; nRetry < 5 && !bAllLibrariesLoaded; nRetry++) { do { pszError = NULL; bRetry = false; // don't try it again. bAllLibrariesLoaded = true; for(i = 0; i < This->m_pLibraries->nelts; i++) { SoapSharedLibrary *pLib = SoapSharedLibraries_getLibrary(This, i); if(NULL == pLib->m_hLibrary) { pszError = SoapSharedLibrary_load(pLib, pTempPool); if(NULL == pszError) { assert(NULL != pLib->m_hLibrary); bRetry = true; ///< we loaded one, lets retry with all others, maybe they depend on that. } else { bAllLibrariesLoaded = false; } if(NULL != pLib->m_hLibrary && pLib->m_bIsSOAPLibrary) { void *pfun = (void *)DLSYM(pLib->m_hLibrary, APACHE_HTTPSERVER_ENTRY_POINT); if(NULL == pfun) { pszError = apr_psprintf(pTempPool, "gsoap: load library \"%s\" success, but failed to find the \"%s\" entry point", pLib->m_pszPath, APACHE_HTTPSERVER_ENTRY_POINT); return pszError; } else { This->m_pfnEntryPoint = (apache_init_soap_interface_fn) pfun; pszError = SoapSharedLibraries_getEntryPoints(This, pLib, pTempPool, r); pszError = apr_psprintf(NULL == pTempPool ? This-> m_pPool : pTempPool, "mod_gsoap: has got entrypoint %s from library", APACHE_HTTPSERVER_ENTRY_POINT); } } } } } while(bRetry); } if(bAllLibrariesLoaded) { This->m_bAllLibrariesLoaded = true; pszError = NULL; } return pszError;}static voidSoapSharedLibraries_merge(SoapSharedLibraries * This, SoapSharedLibraries * pLibs){ int i = 0; assert(NULL != This); if(NULL == pLibs) { return; } This->m_bAllLibrariesLoaded = false; for(i = 0; i < pLibs->m_pLibraries->nelts; i++) { SoapSharedLibrary *pLib = SoapSharedLibraries_getLibrary(pLibs, i); if(!SoapSharedLibraries_contains(This, pLib->m_pszPath)) { SoapSharedLibrary *pNewLib = SoapSharedLibrary_create(This->m_pPool); SoapSharedLibrary_init(pNewLib, This->m_pPool, pLib); SoapSharedLibraries_addLibrary(This, pNewLib); } }}static voidSoapSharedLibraries_merge3(SoapSharedLibraries * This, SoapSharedLibraries * libraries1, SoapSharedLibraries * libraries2){ SoapSharedLibraries_merge(This, libraries1); SoapSharedLibraries_merge(This, libraries2);}static voidgsoapConfiguration_merge(gsoapConfiguration * This, gsoapConfiguration * pParentConfig, gsoapConfiguration * pNewConfig)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -