📄 mod_gsoap.c
字号:
/** Apache SOAP module for Apache 1.3.x * @file mod_gsoap.c * @author Christian Aberger (http://www.aberger.at) * updated by David Viner (dviner@apache.org) */#if !defined(__GNUC__) || __GNUC__ < 2 || \ (__GNUC__ == 2 && __GNUC_MINOR__ < 7) ||\ defined(NEXT)#ifndef __attribute__#define __attribute__(__x)#endif#endif/* * Moved gsoap include to top. Without this, there's a parse error * introduced if gsoap was compiled with -DWITH_OPENSSL. */#include "stdsoap2.h" // standard header for gsoap#include <stdio.h>#include <assert.h>#include "httpd.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 "apache_gsoap.h"typedef int bool;#define false 0#define true ((int)0xffff)#define IOBUF_CHUNK_SIZE 8192#define GSOAP_ID "Apache mod_gsoap gsoap httpd extension 0.0.6"/** A shared library containing a SOAP server. */typedef struct SoapSharedLibrary_S { pool *m_pPool; void *m_hLibrary; ///< handle of the loaded libray. 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 { pool *m_pPool; SoapSharedLibrary *m_pSOAPLibrary; ///< the main SOAP library that will serve our requests array_header *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 pool *the_gsoapPool = NULL;/** @return our pool for gsoapConfiguration */static pool *gsoapConfiguration_getModulePool(){ if(NULL == the_gsoapPool) { the_gsoapPool = ap_make_sub_pool(NULL); } return the_gsoapPool;}static gsoapConfiguration *getConfiguration(request_rec * r);static gsoapRequestConfiguration *getRequestConfiguration(struct soap *);/** @param p the pool to use for memory allocations. @param pszPath the path of the library.*/static voidSoapSharedLibrary_init(SoapSharedLibrary * This, pool * p, const SoapSharedLibrary * pLib){ This->m_pPool = p; This->m_hLibrary = NULL; This->m_pszPath = ap_pstrdup(p, pLib->m_pszPath); This->m_bIsSOAPLibrary = pLib->m_bIsSOAPLibrary;}static voidSoapSharedLibrary_init2(SoapSharedLibrary * This, pool * p, const char *pszPath){ This->m_pPool = p; This->m_hLibrary = NULL; This->m_pszPath = ap_pstrdup(p, pszPath); This->m_bIsSOAPLibrary = false;}static voidSoapSharedLibrary_clear(SoapSharedLibrary * This, pool * p){ This->m_pPool = p; This->m_hLibrary = NULL; This->m_pszPath = NULL; This->m_bIsSOAPLibrary = false;}static SoapSharedLibrary *SoapSharedLibrary_create(pool * p){ SoapSharedLibrary *This = (SoapSharedLibrary *) ap_pcalloc(p, sizeof(SoapSharedLibrary)); SoapSharedLibrary_clear(This, p); return This;}/** * @param pTempPool pool to use for allocating temporary objects (e.g. error message). */static const char *SoapSharedLibrary_load(SoapSharedLibrary * This, pool * pTempPool){ const char *pszError = NULL; const int nFlags = RTLD_LAZY | RTLD_GLOBAL; This->m_hLibrary = (void *)dlopen(This->m_pszPath, nFlags); pszError = dlerror(); if(NULL == This->m_hLibrary) { pszError = ap_psprintf(NULL == pTempPool ? This->m_pPool : pTempPool, "mod_gsoap: %s loading library %s", pszError, This->m_pszPath); } return pszError;}/*-------------------------------------------------------*/static voidSoapSharedLibraries_init(SoapSharedLibraries * This, pool * p){ This->m_pPool = p; This->m_pSOAPLibrary = NULL; This->m_pLibraries = ap_make_array(p, 0, sizeof(SoapSharedLibrary **)); This->m_bAllLibrariesLoaded = false; This->m_pfnEntryPoint = NULL; This->m_pIntf = (struct apache_soap_interface *)ap_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 **) ap_push_array(This->m_pLibraries); *ppNewLib = pLibrary; if(pLibrary->m_bIsSOAPLibrary) { This->m_pSOAPLibrary = pLibrary; } }}static const char *SoapSharedLibraries_getEntryPoints(SoapSharedLibraries * This, SoapSharedLibrary * pLib, pool * 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, pool * 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 = ap_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); } } } } } 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 =
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -