OK.. this time I sent a test before posting... and the post still has problems.... it seems the list server (or something) is wrapping long lines..... how do I deal with this?
---------------------------- .-. | Steven Velez oo| | Software Engineer /`'\ | alventive (\_;/) | 678-202-2226 -----Original Message----- From: Steven Velez [mailto:svelez@;alventive.com] Sent: Tuesday, November 12, 2002 12:23 PM To: 'Tomcat Developers List' Subject: RE: [PATCH] Fixing Interoperability problem in iis connector This should, hopefully, be correctly formatted. Index: isapi.dsp =================================================================== RCS file: /home/cvspublic/jakarta-tomcat-connectors/jk/native/iis/isapi.dsp,v retrieving revision 1.9 diff -u -r1.9 isapi.dsp --- isapi.dsp 9 Apr 2002 23:06:52 -0000 1.9 +++ isapi.dsp 12 Nov 2002 16:58:07 -0000 @@ -170,6 +170,10 @@ SOURCE=..\common\jk_worker.c # End Source File +# Begin Source File + +SOURCE=.\req_info.c +# End Source File # End Group # Begin Group "Header Files" @@ -265,6 +269,10 @@ # Begin Source File SOURCE=..\common\jk_worker.h +# End Source File +# Begin Source File + +SOURCE=.\req_info.h # End Source File # End Group # Begin Group "Resource Files" Index: jk_isapi_plugin.c =================================================================== RCS file: /home/cvspublic/jakarta-tomcat-connectors/jk/native/iis/jk_isapi_plugin.c,v retrieving revision 1.18 diff -u -r1.18 jk_isapi_plugin.c --- jk_isapi_plugin.c 25 Sep 2002 00:49:40 -0000 1.18 +++ jk_isapi_plugin.c 12 Nov 2002 16:58:07 -0000 @@ -78,6 +78,8 @@ #include "jk_worker.h" #include "jk_uri_worker_map.h" +#include "req_info.h" + #define VERSION_STRING "Jakarta/ISAPI/" JK_VERSTRING #define DEFAULT_WORKER_NAME ("ajp13") @@ -109,6 +111,8 @@ #define URI_SELECT_UNPARSED_VERB ("unparsed") #define URI_SELECT_ESCAPED_VERB ("escaped") +#define SHMEM_REQUEST_INFO_TAG ("use_shared_mem") + #define BAD_REQUEST -1 #define BAD_PATH -2 #define MAX_SERVERNAME 128 @@ -142,6 +146,17 @@ } \ }\ +#define GET_REQ_INFO_VALUE(ri, name, var) { \ + char *temp; \ + if (temp = rinfo_get_##name (ri)) \ + { \ + (var) = jk_pool_strdup(&private_data->p, temp); \ + } else { \ + (var) = NULL; \ + } \ +} \ + + static char ini_file_name[MAX_PATH]; static int using_ini_file = JK_FALSE; static int is_inited = JK_FALSE; @@ -159,6 +174,7 @@ static int log_level = JK_LOG_EMERG_LEVEL; static char worker_file[MAX_PATH * 2]; static char worker_mount_file[MAX_PATH * 2]; +static int shmem_enabled = JK_FALSE; #define URI_SELECT_OPT_PARSED 0 #define URI_SELECT_OPT_UNPARSED 1 @@ -670,6 +686,7 @@ char Host[INTERNET_MAX_URL_LENGTH]=""; char Port[INTERNET_MAX_URL_LENGTH]=""; char Translate[INTERNET_MAX_URL_LENGTH]; + char target_uri_buff[INTERNET_MAX_URL_LENGTH]=""; BOOL (WINAPI * GetHeader) (struct _HTTP_FILTER_CONTEXT * pfc, LPSTR lpszName, LPVOID lpvBuffer, LPDWORD lpdwSize ); BOOL (WINAPI * SetHeader) @@ -681,6 +698,8 @@ DWORD szHost = sizeof(Host); DWORD szPort = sizeof(Port); DWORD szTranslate = sizeof(Translate); + request_information_t *p_request_info = NULL; + request_info_name_t info_name = 0; if (iis5) { GetHeader=((PHTTP_FILTER_AUTH_COMPLETE_INFO)pvNotification)->GetHeader; @@ -700,11 +719,13 @@ /* * Just in case somebody set these headers in the request! */ - SetHeader(pfc, URI_HEADER_NAME, NULL); - SetHeader(pfc, QUERY_HEADER_NAME, NULL); - SetHeader(pfc, WORKER_HEADER_NAME, NULL); - SetHeader(pfc, TOMCAT_TRANSLATE_HEADER_NAME, NULL); - + if (!shmem_enabled) { + SetHeader(pfc, URI_HEADER_NAME, NULL); + SetHeader(pfc, QUERY_HEADER_NAME, NULL); + SetHeader(pfc, WORKER_HEADER_NAME, NULL); + SetHeader(pfc, TOMCAT_TRANSLATE_HEADER_NAME, NULL); + } + if (!GetHeader(pfc, "url", (LPVOID)uri, (LPDWORD)&sz)) { jk_log(logger, JK_LOG_ERROR, "HttpFilterProc error while getting the url\n"); @@ -802,14 +823,30 @@ forwardURI = uri; } - if(!AddHeader(pfc, URI_HEADER_NAME, forwardURI) || - ( (query != NULL && strlen(query) > 0) - ? !AddHeader(pfc, QUERY_HEADER_NAME, query) : FALSE ) || - !AddHeader(pfc, WORKER_HEADER_NAME, worker) || - !SetHeader(pfc, "url", extension_uri)) { - jk_log(logger, JK_LOG_ERROR, - "HttpFilterProc error while adding request headers\n"); - return SF_STATUS_REQ_ERROR; + if (!shmem_enabled) { + if(!AddHeader(pfc, URI_HEADER_NAME, forwardURI) || + ( (query != NULL && strlen(query) > 0) + ? !AddHeader(pfc, QUERY_HEADER_NAME, query) : FALSE ) || + !AddHeader(pfc, WORKER_HEADER_NAME, worker) || + !SetHeader(pfc, "url", extension_uri)) { + jk_log(logger, JK_LOG_ERROR, + "HttpFilterProc error while adding request headers\n"); + return SF_STATUS_REQ_ERROR; + } + } + else { + p_request_info = rinfo_new(); + if (p_request_info == NULL) { + jk_log(logger, JK_LOG_ERROR, "HttpFilterProc failed allocating memory " + "for request information\n"); + return SF_STATUS_REQ_ERROR; + } + + rinfo_set_uri(p_request_info, forwardURI); + if (query != NULL && strlen(query) > 0) { + rinfo_set_query_string(p_request_info, query); + } + rinfo_set_worker(p_request_info, worker); } /* Move Translate: header to a temporary header so @@ -821,9 +858,33 @@ if (!AddHeader(pfc, TOMCAT_TRANSLATE_HEADER_NAME, Translate)) { jk_log(logger, JK_LOG_ERROR, "HttpFilterProc error while adding Tomcat-Translate headers\n"); + rinfo_delete(p_request_info); return SF_STATUS_REQ_ERROR; } - SetHeader(pfc, "Translate:", NULL); + + SetHeader(pfc, "Translate:", NULL); + } + + + if (shmem_enabled) { + if ((info_name = rinfo_map_insert(p_request_info)) == REQUEST_INFO_ERR_NAME) { + rinfo_delete(p_request_info); + jk_log(logger, JK_LOG_ERROR, + "HttpFilterProc failed to set the request info\n"); + return SF_STATUS_REQ_ERROR; + } + + if (!SetHeader(pfc, "url", + rinfo_append_name_to_uri(extension_uri, info_name, + target_uri_buff, + INTERNET_MAX_URL_LENGTH) + )) { + + rinfo_delete(p_request_info); + jk_log(logger, JK_LOG_ERROR, + "HttpFilterProc error while adding request headers\n"); + return SF_STATUS_REQ_ERROR; + } } } else { jk_log(logger, JK_LOG_DEBUG, @@ -961,6 +1022,12 @@ uri_worker_map_free(&uw_map, logger); is_mapread = JK_FALSE; } + + if (shmem_enabled) + { + rinfo_close_map(); + } + wc_close(logger); if (logger) { jk_close_file_logger(&logger); @@ -1023,6 +1090,10 @@ jk_log(logger, JK_LOG_DEBUG, "Using worker file %s.\n", worker_file); jk_log(logger, JK_LOG_DEBUG, "Using worker mount file %s.\n", worker_mount_file); jk_log(logger, JK_LOG_DEBUG, "Using uri select %d.\n", uri_select_option); + if (shmem_enabled) { + jk_log(logger, JK_LOG_DEBUG, "Using shared memory to pass information from " + "the filter to the extension.\n"); + } if (map_alloc(&map)) { if (map_read_properties(map, worker_mount_file)) { @@ -1079,6 +1150,11 @@ } } + if (rc && shmem_enabled) + { + rc = rinfo_init_map(logger); + } + return rc; } @@ -1108,6 +1184,32 @@ return -1; } + +int parse_enable_shmem(const char *shmem) +{ + char *shmem_indicators[] = {"on", "true", "enable", NULL}; + int ret = JK_FALSE; + int sh_mem_int = 0; + char **cur_indicator = shmem_indicators; + + if (sscanf(shmem, "%d", &sh_mem_int) != EOF && sh_mem_int) + { + ret = JK_TRUE; + } + + + while (!ret && *cur_indicator) + { + if (stricmp(shmem, *(cur_indicator++)) == 0) + { + ret = JK_TRUE; + } + } + + return ret; +} + + static int read_registry_init_data(void) { char tmpbuf[INTERNET_MAX_URL_LENGTH]; @@ -1162,6 +1264,10 @@ ok = JK_FALSE; } } + tmp = map_get_string(map, SHMEM_REQUEST_INFO_TAG, NULL); + if (tmp) { + shmem_enabled = parse_enable_shmem(tmp); + } } else { rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, @@ -1230,6 +1336,13 @@ } } + if (get_registry_config_parameter(hkey, + SHMEM_REQUEST_INFO_TAG, + tmpbuf, + sizeof(tmpbuf))) { + shmem_enabled = parse_enable_shmem(tmpbuf); + } + RegCloseKey(hkey); } return ok; @@ -1263,6 +1376,8 @@ char **worker_name) { char huge_buf[16 * 1024]; /* should be enough for all */ + request_information_t *preq_info = NULL; + request_info_name_t name = 0; DWORD huge_buf_sz; @@ -1272,17 +1387,40 @@ s->read = read; s->write = write; - GET_SERVER_VARIABLE_VALUE(HTTP_WORKER_HEADER_NAME, (*worker_name)); - GET_SERVER_VARIABLE_VALUE(HTTP_URI_HEADER_NAME, s->req_uri); - GET_SERVER_VARIABLE_VALUE(HTTP_QUERY_HEADER_NAME, s->query_string); - - if (s->req_uri == NULL) { - s->query_string = private_data->lpEcb->lpszQueryString; - *worker_name = DEFAULT_WORKER_NAME; - GET_SERVER_VARIABLE_VALUE("URL", s->req_uri); - if (unescape_url(s->req_uri) < 0) + if (! shmem_enabled) { + GET_SERVER_VARIABLE_VALUE(HTTP_WORKER_HEADER_NAME, (*worker_name)); + GET_SERVER_VARIABLE_VALUE(HTTP_URI_HEADER_NAME, s->req_uri); + GET_SERVER_VARIABLE_VALUE(HTTP_QUERY_HEADER_NAME, s->query_string); + + if (s->req_uri == NULL) { + s->query_string = private_data->lpEcb->lpszQueryString; + *worker_name = DEFAULT_WORKER_NAME; + GET_SERVER_VARIABLE_VALUE("URL", s->req_uri); + if (unescape_url(s->req_uri) < 0) + return JK_FALSE; + getparents(s->req_uri); + } + } + else { + + if ((name = rinfo_name_from_query(private_data->lpEcb->lpszQueryString)) == + REQUEST_INFO_ERR_NAME) { + + jk_log(logger, JK_LOG_ERROR, "Failed to read request name from " + "query string\n"); return JK_FALSE; - getparents(s->req_uri); + } + + if (!(preq_info = rinfo_map_remove_at(name))) { + + jk_log(logger, JK_LOG_ERROR, "Failed to find and remove the named " + "request: %d.\n", name); + return JK_FALSE; + } + + GET_REQ_INFO_VALUE(preq_info, worker, (*worker_name)); + GET_REQ_INFO_VALUE(preq_info, uri, s->req_uri); + GET_REQ_INFO_VALUE(preq_info, query_string, s->query_string); } GET_SERVER_VARIABLE_VALUE("AUTH_TYPE", s->auth_type); @@ -1406,7 +1544,10 @@ unsigned len_of_http_prefix = strlen("HTTP_"); BOOL need_content_length_header = (s->content_length == 0); - cnt -= 2; /* For our two special headers */ + if (!shmem_enabled) { + cnt -= 2; /* For our two special headers */ + } + /* allocate an extra header slot in case we need to add a content-length header */ s->headers_names = jk_pool_alloc(&private_data->p, (cnt + 1) * sizeof(char *)); s->headers_values = jk_pool_alloc(&private_data->p, (cnt + 1) * sizeof(char *)); File: /home/cvspublic/jakarta-tomcat-connectors/jk/native/iis/req_info.h /* ========================================================================= * * * * The Apache Software License, Version 1.1 * * * * Copyright (c) 1999-2001 The Apache Software Foundation. * * All rights reserved. * * * * ========================================================================= * * * * Redistribution and use in source and binary forms, with or without modi- * * fication, are permitted provided that the following conditions are met: * * * * 1. Redistributions of source code must retain the above copyright notice * * notice, this list of conditions and the following disclaimer. * * * * 2. Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * * * 3. The end-user documentation included with the redistribution, if any, * * must include the following acknowlegement: * * * * "This product includes software developed by the Apache Software * * Foundation <http://www.apache.org/>." * * * * Alternately, this acknowlegement may appear in the software itself, if * * and wherever such third-party acknowlegements normally appear. * * * * 4. The names "The Jakarta Project", "Jk", and "Apache Software * * Foundation" must not be used to endorse or promote products derived * * from this software without prior written permission. For written * * permission, please contact <[EMAIL PROTECTED]>. * * * * 5. Products derived from this software may not be called "Apache" nor may * * "Apache" appear in their names without prior written permission of the * * Apache Software Foundation. * * * * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES * * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * * THE APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY * * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * * POSSIBILITY OF SUCH DAMAGE. * * * * ========================================================================= * * * * This software consists of voluntary contributions made by many indivi- * * duals on behalf of the Apache Software Foundation. For more information * * on the Apache Software Foundation, please see <http://www.apache.org/>. * * * * ========================================================================= */ /*************************************************************************** * Description: Utilities to to keep track of request information * * Author: Steven Velez <[EMAIL PROTECTED]> * * Version: $Revision: $ * ***************************************************************************/ #ifndef REQ_INFO_H #define REQ_INFO_H #include "jk_pool.h" #include "jk_logger.h" #ifdef __cpluplus extern "C" { #endif /* * The information 'class' that will store information * for a particular request. This information will be set in the filter * and read in the extension. */ struct _request_information { /* The name of the worker selected by the filter. * Relaces "TOMCATWORKER:" */ char *worker_name; /* The uri of the original request. * Replaces "TOMCATURI:" */ char *uri; /* The query string of the original request. * Replaces "TOMCATQUERY:" */ char *query_string; /** For keeping track of the various allocations of member data */ jk_pool_t p; jk_pool_atom_t buff[BIG_POOL_SIZE]; }; typedef struct _request_information request_information_t; typedef unsigned long request_info_name_t; #define REQUEST_INFO_ERR_NAME (0) /* Management functions to intialize and destroy a global request info map */ int rinfo_init_map(jk_logger_t *log); int rinfo_close_map(); /* Insert a request information object in the map */ request_info_name_t rinfo_map_insert(request_information_t * ri); /* Find the request information object related to the given request. * This function returns 'NULL' if the object can not be found */ request_information_t *rinfo_map_at(request_info_name_t req); /* Find the requwst information object related to the give request. * This function will also remove the object from the map. */ request_information_t *rinfo_map_remove_at(request_info_name_t req); /* utility function to append a request info name to a uri * the return value of the function is a pointer to the caller-supplied * buffer */ char *rinfo_append_name_to_uri(char *uri, request_info_name_t req, char *buff, size_t size); /* Utiltity function to retreive a request info name from * a query string */ request_info_name_t rinfo_name_from_query(char *query); /* Object lifetime management functions... these should be used to * create and destroy a request_info object */ request_information_t *rinfo_new(); void rinfo_delete(request_information_t * ri); /* functions to set data in the request info object. These functions * duplicate the parameters, so it will remain the responsibility of * the caller to manage the memory pointed to in the second parameter. */ void rinfo_set_worker(request_information_t * ri, char *name); void rinfo_set_uri(request_information_t * ri, char *uri); void rinfo_set_query_string(request_information_t * ri, char *qs); /* functions to access data in the request info object. * They return poitners to internal buffers, so callers should not manipulate * them directly. */ char *rinfo_get_worker(request_information_t * ri); char *rinfo_get_uri(request_information_t * ri); char *rinfo_get_query_string(request_information_t * ri); #ifdef __cplusplus } #endif #endif File: /home/cvspublic/jakarta-tomcat-connectors/jk/native/iis/req_info.c /* ========================================================================= * * * * The Apache Software License, Version 1.1 * * * * Copyright (c) 1999-2001 The Apache Software Foundation. * * All rights reserved. * * * * ========================================================================= * * * * Redistribution and use in source and binary forms, with or without modi- * * fication, are permitted provided that the following conditions are met: * * * * 1. Redistributions of source code must retain the above copyright notice * * notice, this list of conditions and the following disclaimer. * * * * 2. Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * * * 3. The end-user documentation included with the redistribution, if any, * * must include the following acknowlegement: * * * * "This product includes software developed by the Apache Software * * Foundation <http://www.apache.org/>." * * * * Alternately, this acknowlegement may appear in the software itself, if * * and wherever such third-party acknowlegements normally appear. * * * * 4. The names "The Jakarta Project", "Jk", and "Apache Software * * Foundation" must not be used to endorse or promote products derived * * from this software without prior written permission. For written * * permission, please contact <[EMAIL PROTECTED]>. * * * * 5. Products derived from this software may not be called "Apache" nor may * * "Apache" appear in their names without prior written permission of the * * Apache Software Foundation. * * * * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES * * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * * THE APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY * * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * * POSSIBILITY OF SUCH DAMAGE. * * * * ========================================================================= * * * * This software consists of voluntary contributions made by many indivi- * * duals on behalf of the Apache Software Foundation. For more information * * on the Apache Software Foundation, please see <http://www.apache.org/>. * * * * ========================================================================= */ /*************************************************************************** * Description: Utilities to to keep track of request information * * Author: Steven Velez <[EMAIL PROTECTED]> * * Version: $Revision: $ * ***************************************************************************/ #include "req_info.h" #include "jk_mt.h" #include "jk_util.h" #include <limits.h> #include <stddef.h> /* * A node defination for a linked list * that will implement a custom map data structure. * I am using this as opposed to the jk_map because we need more * precise control of memory allocation for the sake of iffeciency since * this will be used as a global structure. */ static struct _request_map_node { request_info_name_t name; request_information_t *ri; struct _request_map_node *next; }; /* use a define instead of a typedef so that this definition * will not be accessible outside this file */ #define NODE_T struct _request_map_node /* The querystring variable that will hold a request_info_name */ #define QUERY_VAR "REQ_INFO_NAME" #if defined(_DEBUG) /* Helper macros for logging */ #define LOG_CRIT_SEC(action, result) {\ if (!result) { \ jk_log(logger, JK_LOG_INFO, "Did not " #action \ " the critical section\n"); \ } \ } \ #define LOG_ENTER(func_name) { \ jk_log(logger, JK_LOG_DEBUG, "--> ENTERING " #func_name " <---\n");\ }\ #define LOG_EXIT(func_name) { \ jk_log(logger, JK_LOG_DEBUG, "--> EXITING " #func_name " <---\n");\ }\ #else #define LOG_CRIT_SEC(action, result) #define LOG_ENTER(func_name) #define LOG_EXIT(func_name) #endif /* The root of the map */ static NODE_T *g_map_head = NULL; /* The insertion point of the map */ static NODE_T *g_map_tail = NULL; /* Synchronization structure */ static JK_CRIT_SEC g_crit_sec; /* The next name value */ static request_info_name_t g_next_name = 0; /* logging object */ jk_logger_t *logger = NULL; int rinfo_init_map(jk_logger_t *l) { int success = JK_FALSE; LOG_ENTER(rinfo_init_map); if (l == NULL) { LOG_EXIT(rinfo_init_map); return JK_FALSE; } logger = l; JK_INIT_CS(&g_crit_sec, success); if (success == JK_FALSE) { jk_log(logger, JK_LOG_ERROR, "Failed to initialize the map critical " "section\n"); LOG_EXIT(rinfo_init_map); return JK_FALSE; } g_map_head = NULL; g_map_tail = g_map_head; LOG_EXIT(rinfo_init_map); return JK_TRUE; } int rinfo_close_map() { int success = JK_FALSE; NODE_T *pcurrent = g_map_head; NODE_T *ptemp = NULL; LOG_ENTER(rinfo_init_map); /* remove the current entries */ JK_ENTER_CS(&g_crit_sec, success); if (success == JK_FALSE) { /* we are in big trouble; however, I guess a memory leak on shutdown * is better than a crash */ jk_log(logger, JK_LOG_INFO, "Did not obtain a critical section object " "for freeing map resources.\n"); LOG_EXIT(rinfo_init_map); return JK_FALSE; } while (pcurrent != NULL) { rinfo_delete(pcurrent->ri); ptemp = pcurrent; pcurrent = pcurrent->next; if (ptemp != NULL) { free((void *) ptemp); } } g_map_head = NULL; g_map_tail = NULL; JK_LEAVE_CS(&g_crit_sec, success); LOG_CRIT_SEC(leave, success); /* get rid of the critical section */ JK_DELETE_CS(&g_crit_sec, success); if (!success) { jk_log(logger, JK_LOG_INFO, "Failed to delete critical section object " "after freeing map resources.\n"); } LOG_EXIT(rinfo_init_map); return JK_TRUE; } request_info_name_t rinfo_map_insert(request_information_t * ri) { int success = JK_FALSE; request_info_name_t new_name = REQUEST_INFO_ERR_NAME; NODE_T *new_node = NULL; LOG_ENTER(rinfo_map_insert); JK_ENTER_CS(&g_crit_sec, success); if (success == JK_FALSE) { LOG_CRIT_SEC(enter, success); LOG_EXIT(rinfo_map_insert); return REQUEST_INFO_ERR_NAME; } g_next_name = (++g_next_name) % ULONG_MAX; g_next_name = REQUEST_INFO_ERR_NAME == g_next_name ? g_next_name++ : g_next_name; new_name = g_next_name; new_node = (NODE_T *) malloc(sizeof(NODE_T)); if (new_node == NULL) { jk_log(logger, JK_LOG_EMERG, "Failed to allocate memory for a " "new map entry\n"); JK_LEAVE_CS(&g_crit_sec, success); LOG_CRIT_SEC(leave, success); LOG_EXIT(rinfo_map_insert); return REQUEST_INFO_ERR_NAME; } new_node->name = new_name; new_node->ri = ri; new_node->next = NULL; if (g_map_head == NULL) { g_map_head = new_node; } else { g_map_tail->next = new_node; } g_map_tail = new_node; jk_log(logger, JK_LOG_DEBUG, "Added req: %d\nhead = 0x%x tail = 0x%x\n", new_name, g_map_head, g_map_tail); JK_LEAVE_CS(&g_crit_sec, success); LOG_CRIT_SEC(leave, success); LOG_EXIT(rinfo_map_insert); return new_name; } /* centralize the retrieval of data */ static NODE_T **internal_map_at(request_info_name_t req) { NODE_T **ppreturn = NULL; NODE_T **ppcurrent = &g_map_head; while (*ppcurrent) { if ((*ppcurrent)->name == req) { ppreturn = ppcurrent; break; } ppcurrent = &((*ppcurrent)->next); } if (!ppreturn) { jk_log(logger, JK_LOG_DEBUG, "Did not find info named: %d\n", req); } return ppreturn; } request_information_t *rinfo_map_at(request_info_name_t req) { int success = JK_FALSE; NODE_T **ppresult = NULL; LOG_ENTER(rinfo_map_at); JK_ENTER_CS(&g_crit_sec, success); if (success == JK_FALSE) { LOG_CRIT_SEC(enter, success); LOG_EXIT(rinfo_map_at); return NULL; } ppresult = internal_map_at(req); JK_LEAVE_CS(&g_crit_sec, success); LOG_CRIT_SEC(leave, success); LOG_EXIT(rinfo_map_at); return ppresult ? (*ppresult)->ri : NULL; } request_information_t *rinfo_map_remove_at(request_info_name_t req) { int success = JK_FALSE; NODE_T **ppresult = NULL; NODE_T *ptemp; request_information_t *preturn = NULL; LOG_ENTER(rinfo_map_remove_at); JK_ENTER_CS(&g_crit_sec, success); if (success == JK_FALSE) { LOG_CRIT_SEC(enter, success); LOG_EXIT(rinfo_map_remove_at); return NULL; } ppresult = internal_map_at(req); if (ppresult) { jk_log(logger, JK_LOG_DEBUG, "Removing request: %d\nhead = 0x%x tail = 0x%x\n", req, g_map_head, g_map_tail); preturn = (*ppresult)->ri; /* * This removal part is a little tricky, so here I try to explain it. * If someone finds out that it's not doing what it's supposed to, * then keep these notes in mind. * * What we are getting from the search function is not a * pointer to a node, but instead a pointer to a pointer to a node. * The reasoning for this return value is so that the node can be * removed without having to return two pointers: a pointer to the * found node and a pointer to the node before that. In my opinion, * this allows for a more graceful implementation... even though the * pointer stuff is a little hard to manage. * * So, it's established that we have a pointer to a pointer. * To remove the node, we first need to create a temporary reference to * it. A simple pointer will do here. We just don't want to lose a * handle on the node. Once we have safely stored a reference to the * node, we check to see if the found node is the last node in list. * If it is, then we check for the special case: that there is a * one-element list. The tail pointer is zeroed. In the more general * case (the list is two or more nodes long), we need to back the * tail up. Since what we have is a pointer to a pointer to a node, * we can't just assign the value of ppresult to the tail. We need to * find the memory location of the node that contains the "next" * pointer that ppresult is pointing to. We use the the offsetof * macro to find out how far back from the next pointer the node * pointer needs to be. Then we calculate the location of the node * pointer based on the location of the next pointer. This should * be safe because the search function can only return a pointer to * head or to a next field (which is in a node) and we already checked * for the first case. * * Once we deal with the tail, the rest just falls out. The value * of the pointer that ppresult points to (be it head or next field), * is reassigned to point to the next node in the list. * * The node is then deleted. */ ptemp = *ppresult; if (ptemp == g_map_tail) { if (g_map_tail == g_map_head) { g_map_tail = NULL; } else { g_map_tail = (NODE_T *)( ((jk_uintptr_t)(ppresult)) - offsetof(NODE_T, next)); } } *ppresult = (*ppresult)->next; free((void *) ptemp); jk_log(logger, JK_LOG_DEBUG, "Removed request: %d\nhead = 0x%x tail = 0x%x\n", req, g_map_head, g_map_tail); } JK_LEAVE_CS(&g_crit_sec, success); LOG_CRIT_SEC(leave, success); LOG_EXIT(rinfo_map_remove_at); return preturn; } char *rinfo_append_name_to_uri(char *uri, request_info_name_t req, char *buff, size_t size) { char sep = '?'; LOG_ENTER(rinfo_append_name_to_uri); if (buff == NULL) { LOG_EXIT(rinfo_append_name_to_uri); return NULL; } if (strchr(uri, sep)) { sep = '&'; } snprintf(buff, size, "%s%c" QUERY_VAR "=%d", uri, sep, req); LOG_EXIT(rinfo_append_name_to_uri); return buff; } request_info_name_t rinfo_name_from_query(char *query) { int numconverted = 0; request_info_name_t name = REQUEST_INFO_ERR_NAME; LOG_ENTER(rinfo_name_from_query); query = strstr(query, QUERY_VAR); if (!query) { jk_log(logger, JK_LOG_ERROR, "Did not find the variable \"" QUERY_VAR "\" in the query string.\n"); LOG_EXIT(rinfo_name_from_query); return REQUEST_INFO_ERR_NAME; } if (sscanf(query, QUERY_VAR "=%d", &name) != 1) { jk_log(logger, JK_LOG_ERROR, "Query string could not be scanned " "for a name.\n"); LOG_EXIT(rinfo_name_from_query); return REQUEST_INFO_ERR_NAME; } LOG_EXIT(rinfo_name_from_query); return name; } /* Create a new request info object */ request_information_t *rinfo_new() { request_information_t *pinfo = (request_information_t *) malloc(sizeof(request_information_t)); LOG_ENTER(rinfo_new); if (pinfo == NULL) { jk_log(logger, JK_LOG_EMERG, "Failed to allocate memory for a " "new request information object.\n"); LOG_EXIT(rinfo_new); return NULL; } memset((void *) pinfo, 0, sizeof(request_information_t)); jk_open_pool(&pinfo->p, pinfo->buff, sizeof(pinfo->buff)); LOG_EXIT(rinfo_new); return pinfo; } /* destroy a request info object */ void rinfo_delete(request_information_t * ri) { LOG_ENTER(rinfo_delete); if (ri == NULL) { LOG_EXIT(rinfo_delete); return; } jk_close_pool(&ri->p); free((void *) ri); /* This is not sufficient, caller must do this too */ ri = NULL; LOG_EXIT(rinfo_delete); } /* helper to set string memebers */ static internal_set_string(request_information_t * ri, char **member, char *value) { if (value) { *member = jk_pool_strdup(&ri->p, value); } else { *member = NULL; } } void rinfo_set_worker(request_information_t * ri, char *name) { LOG_ENTER(rinfo_set_worker); /* protection */ if (ri == NULL) { LOG_EXIT(rinfo_set_worker); return; } internal_set_string(ri, &(ri->worker_name), name); LOG_EXIT(rinfo_set_worker); } void rinfo_set_uri(request_information_t * ri, char *uri) { LOG_ENTER(rinfo_set_uri); /* protection */ if (ri == NULL) { LOG_EXIT(rinfo_set_uri); return; } internal_set_string(ri, &(ri->uri), uri); LOG_EXIT(rinfo_set_uri); } void rinfo_set_query_string(request_information_t * ri, char *qs) { LOG_ENTER(rinfo_set_query_string); /* protection */ if (ri == NULL) { LOG_EXIT(rinfo_set_query_string); return; } internal_set_string(ri, &(ri->query_string), qs); LOG_EXIT(rinfo_set_query_string); } char *rinfo_get_worker(request_information_t * ri) { LOG_ENTER(rinfo_get_worker); if (ri == NULL) { LOG_EXIT(rinfo_get_worker); return NULL; } jk_log(logger, JK_LOG_DEBUG, "Retreived: %s\n", ri->worker_name); LOG_EXIT(rinfo_get_worker); return ri->worker_name; } char *rinfo_get_uri(request_information_t * ri) { LOG_ENTER(rinfo_get_uri); if (ri == NULL) { LOG_EXIT(rinfo_get_uri); return NULL; } jk_log(logger, JK_LOG_DEBUG, "Retreived: %s\n", ri->uri); LOG_EXIT(rinfo_get_uri); return ri->uri; } char *rinfo_get_query_string(request_information_t * ri) { LOG_ENTER(rinfo_get_query_string); if (ri == NULL) { LOG_EXIT(rinfo_get_query_string); return NULL; } jk_log(logger, JK_LOG_DEBUG, "Retreived: %s\n", ri->query_string); LOG_EXIT(rinfo_get_query_string); return ri->query_string; } ---------------------------- .-. | Steven Velez oo| | Software Engineer /`'\ | alventive (\_;/) | 678-202-2226 -----Original Message----- From: Steven Velez [mailto:svelez@;alventive.com] Sent: Tuesday, November 12, 2002 12:15 PM To: 'Tomcat Developers List' Subject: RE: [PATCH] Fixing Interoperability problem in iis connector :( My mail client warpped the code inappropriately.. I will remedy this and re-post. Thanks, Steven ---------------------------- .-. | Steven Velez oo| | Software Engineer /`'\ | alventive (\_;/) | 678-202-2226 -----Original Message----- From: Steven Velez [mailto:svelez@;alventive.com] Sent: Tuesday, November 12, 2002 12:15 PM To: 'Tomcat Developers List' Subject: RE: [PATCH] Fixing Interoperability problem in iis connector :( My mail client warpped the code inappropriately.. I will remedy this and re-post. Thanks, Steven