Post the patch as an attachment.

----- Original Message -----
From: "Steven Velez" <[EMAIL PROTECTED]>
To: "'Tomcat Developers List'" <[EMAIL PROTECTED]>
Sent: Tuesday, November 12, 2002 10:00 AM
Subject: RE: [PATCH] Fixing Interoperability problem in iis connector


> 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
>
>


--
To unsubscribe, e-mail:   <mailto:tomcat-dev-unsubscribe@;jakarta.apache.org>
For additional commands, e-mail: <mailto:tomcat-dev-help@;jakarta.apache.org>

Reply via email to