You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by hg...@apache.org on 2001/05/15 12:00:55 UTC

cvs commit: jakarta-tomcat-connectors/jk/src/native/apache-1.3 mod_jk.c mod_jk.dsp

hgomez      01/05/15 03:00:55

  Added:       jk/src/native/apache-1.3 mod_jk.c mod_jk.dsp
  Log:
  move to apache-1.3
  
  Revision  Changes    Path
  1.1                  jakarta-tomcat-connectors/jk/src/native/apache-1.3/mod_jk.c
  
  Index: mod_jk.c
  ===================================================================
  /*
   * Copyright (c) 1997-1999 The Java Apache Project.  All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    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. All advertising materials mentioning features or use of this
   *    software must display the following acknowledgment:
   *    "This product includes software developed by the Java Apache 
   *    Project for use in the Apache JServ servlet engine project
   *    <http://java.apache.org/>."
   *
   * 4. The names "Apache JServ", "Apache JServ Servlet Engine" and 
   *    "Java Apache Project" must not be used to endorse or promote products 
   *    derived from this software without prior written permission.
   *
   * 5. Products derived from this software may not be called "Apache JServ"
   *    nor may "Apache" nor "Apache JServ" appear in their names without 
   *    prior written permission of the Java Apache Project.
   *
   * 6. Redistributions of any form whatsoever must retain the following
   *    acknowledgment:
   *    "This product includes software developed by the Java Apache 
   *    Project for use in the Apache JServ servlet engine project
   *    <http://java.apache.org/>."
   *    
   * THIS SOFTWARE IS PROVIDED BY THE JAVA APACHE PROJECT "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 JAVA APACHE PROJECT 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
   * individuals on behalf of the Java Apache Group. For more information
   * on the Java Apache Project and the Apache JServ Servlet Engine project,
   * please see <http://java.apache.org/>.
   *
   */
  
  /***************************************************************************
   * Description: Apache 1.3 plugin for Jakarta/Tomcat                       *
   *              See ../common/jk_service.h for general mod_jk info         *
   * Author:      Gal Shachor <sh...@il.ibm.com>                           *
   *              Dan Milstein <da...@shore.net>                            *
   *              Henri Gomez <hg...@slib.fr>                               *
   * Version:     $ $                                                        *
   ***************************************************************************/
  
  /*
   * mod_jk: keeps all servlet/jakarta related ramblings together.
   */
  
  #include "ap_config.h"
  #include "httpd.h"
  #include "http_config.h"
  #include "http_request.h"
  #include "http_core.h"
  #include "http_protocol.h"
  #include "http_main.h"
  #include "http_log.h"
  #include "util_script.h"
  #include "util_date.h"
  #include "http_conf_globals.h"
  
  /*
   * Jakarta (jk_) include files
   */
  #ifdef NETWARE
  #define _SYS_TYPES_H_
  #define _NETDB_H_INCLUDED
  #define _IN_
  #define _INET_
  #define _SYS_TIMEVAL_H_
  #define _SYS_SOCKET_H_
  #endif
  #include "jk_global.h"
  #include "jk_util.h"
  #include "jk_map.h"
  #include "jk_pool.h"
  #include "jk_service.h"
  #include "jk_worker.h"
  #include "jk_uri_worker_map.h"
  
  #define JK_WORKER_ID        ("jakarta.worker")
  #define JK_HANDLER          ("jakarta-servlet")
  #define JK_MAGIC_TYPE       ("application/x-jakarta-servlet")
  #define NULL_FOR_EMPTY(x)   ((x && !strlen(x)) ? NULL : x) 
  
  /*
   * If you are not using SSL, comment out the following line. It will make
   * apache run faster.  
   *
   * Personally, I (DM), think this may be a lie.
   */
  #define ADD_SSL_INFO    
  
  module MODULE_VAR_EXPORT jk_module;
  
  /*
   * Configuration object for the mod_jk module.
   */
  typedef struct {
      char *log_file;
      int  log_level;
      jk_logger_t *log;
  
      char *worker_file;
      int  mountcopy;
      jk_map_t *uri_to_context;
      jk_uri_worker_map_t *uw_map;
  
      /*
       * SSL Support
       */
      int  ssl_enable;
      char *https_indicator;
      char *certs_indicator;
      char *cipher_indicator;
      char *sesion_indicator;
  
      /*
       * Environment variables support
       */
      int envvars_in_use;
      table *envvars;       
  
      server_rec *s;
  } jk_server_conf_t;
  
  
  /*
   * The "private", or subclass portion of the web server service class for
   * Apache 1.3.  An instance of this class is created for each request
   * handled.  See jk_service.h for details about the ws_service object in
   * general.  
   */
  struct apache_private_data {
      /* 
       * For memory management for this request.  Aliased to be identical to
       * the pool in the superclass (jk_ws_service).  
       */
      jk_pool_t p;    
      
      /* True iff response headers have been returned to client */
      int response_started;  
  
      /* True iff request body data has been read from Apache */
      int read_body_started;
  
      /* Apache request structure */
      request_rec *r; 
  };
  typedef struct apache_private_data apache_private_data_t;
  
  static jk_logger_t *main_log = NULL;
  
  static int JK_METHOD ws_start_response(jk_ws_service_t *s,
                                         int status,
                                         const char *reason,
                                         const char * const *header_names,
                                         const char * const *header_values,
                                         unsigned num_of_headers);
  
  static int JK_METHOD ws_read(jk_ws_service_t *s,
                               void *b,
                               unsigned l,
                               unsigned *a);
  
  static int JK_METHOD ws_write(jk_ws_service_t *s,
                                const void *b,
                                unsigned l);
  
  
  /* ====================================================================== */
  /* JK Service step callbacks                                              */
  /* ====================================================================== */
  
  
  /*
   * Send the HTTP response headers back to the browser.
   *
   * Think of this function as a method of the apache1.3-specific subclass of
   * the jk_ws_service class.  Think of the *s param as a "this" or "self"
   * pointer.  
   */
  static int JK_METHOD ws_start_response(jk_ws_service_t *s,
                                         int status,
                                         const char *reason,
                                         const char * const *header_names,
                                         const char * const *header_values,
                                         unsigned num_of_headers)
  {
      if(s && s->ws_private) {
          unsigned h;
  
          /* Obtain a subclass-specific "this" pointer */
          apache_private_data_t *p = s->ws_private;
          request_rec *r = p->r;
          
          if(!reason) {
              reason = "";
          }
          r->status = status;
          r->status_line = ap_psprintf(r->pool, "%d %s", status, reason);
  
          for(h = 0 ; h < num_of_headers ; h++) {
              if(!strcasecmp(header_names[h], "Content-type")) {
                  char *tmp = ap_pstrdup(r->pool, header_values[h]);
                  ap_content_type_tolower(tmp);
                  r->content_type = tmp;
              } else if(!strcasecmp(header_names[h], "Location")) {
                  ap_table_set(r->headers_out, header_names[h], header_values[h]);
              } else if(!strcasecmp(header_names[h], "Content-Length")) {
                  ap_table_set(r->headers_out, header_names[h], header_values[h]);
              } else if(!strcasecmp(header_names[h], "Transfer-Encoding")) {
                  ap_table_set(r->headers_out, header_names[h], header_values[h]);
              } else if(!strcasecmp(header_names[h], "Last-Modified")) {
                  /*
                   * If the script gave us a Last-Modified header, we can't just
                   * pass it on blindly because of restrictions on future values.
                   */
                  ap_update_mtime(r, ap_parseHTTPdate(header_values[h]));
                  ap_set_last_modified(r);
              } else {                
                  ap_table_add(r->headers_out, header_names[h], header_values[h]);
              }
          }
  
          ap_send_http_header(r);
          p->response_started = JK_TRUE;
          
          return JK_TRUE;
      }
      return JK_FALSE;
  }
  
  /*
   * Read a chunk of the request body into a buffer.  Attempt to read len
   * bytes into the buffer.  Write the number of bytes actually read into
   * actually_read.  
   *
   * Think of this function as a method of the apache1.3-specific subclass of
   * the jk_ws_service class.  Think of the *s param as a "this" or "self"
   * pointer.  
   */
  static int JK_METHOD ws_read(jk_ws_service_t *s,
                               void *b,
                               unsigned len,
                               unsigned *actually_read)
  {
      if(s && s->ws_private && b && actually_read) {
          apache_private_data_t *p = s->ws_private;
          if(!p->read_body_started) {
              if(!ap_setup_client_block(p->r, REQUEST_CHUNKED_DECHUNK)) {
                  if(ap_should_client_block(p->r)) { 
                      p->read_body_started = JK_TRUE; 
                  }
              }
          }
  
          if(p->read_body_started) {
              *actually_read = ap_get_client_block(p->r, b, len);
              return JK_TRUE;
          }
      }
      return JK_FALSE;
  }
  
  /*
   * Write a chunk of response data back to the browser.  If the headers
   * haven't yet been sent over, send over default header values (Status =
   * 200, basically).
   *
   * Write len bytes from buffer b.
   *
   * Think of this function as a method of the apache1.3-specific subclass of
   * the jk_ws_service class.  Think of the *s param as a "this" or "self"
   * pointer.  
   */
  static int JK_METHOD ws_write(jk_ws_service_t *s,
                                const void *b,
                                unsigned len)
  {
      if(s && s->ws_private && b) {
          apache_private_data_t *p = s->ws_private;
  
          if(len) {
              BUFF *bf = p->r->connection->client;
              char *buf = (char *)b;
              int w = (int)len;
              int r = 0;
  
              if(!p->response_started) {
                  if(!s->start_response(s, 200, NULL, NULL, NULL, 0)) {
                      return JK_FALSE;
                  }
              }
  
              while(len && !p->r->connection->aborted) {
                  w = ap_bwrite(p->r->connection->client, &buf[r], len);
                  if (w > 0) {
                      /* reset timeout after successful write */
                      ap_reset_timeout(p->r); 
                      r += w;
                      len -= w;
                  } else if (w < 0) {
                      /* Error writing data -- abort */
                      if(!p->r->connection->aborted) {
                          ap_bsetflag(p->r->connection->client, B_EOUT, 1);
                          p->r->connection->aborted = 1;
                      }
                      return JK_FALSE;
                  }
                  
              }
             
              /*
               * To allow server push.
               */
              ap_bflush(bf);
          }
  
          return JK_TRUE;
      }
      return JK_FALSE;
  }
  
  /* ====================================================================== */
  /* Utility functions                                                      */
  /* ====================================================================== */
  
  /* Log something to JK log file then exit */
  static void jk_error_exit(const char *file, 
                            int line, 
                            int level, 
                            const server_rec *s,
                            ap_pool *p,
                            const char *fmt, ...) 
  {
      va_list ap;
      char *res;
  
      va_start(ap, fmt);
      res = ap_pvsprintf(p, fmt, ap);
      va_end(ap);
  
      ap_log_error(file, line, level, s, res);
  
      /* Exit process */
      exit(1);
  }
  
  /* Return the content length associated with an Apache request structure */
  static int get_content_length(request_rec *r)
  {
      if(r->clength > 0) {
          return r->clength;
      } else {
          char *lenp = (char *)ap_table_get(r->headers_in, "Content-Length");
  
          if(lenp) {
              int rc = atoi(lenp);
              if(rc > 0) {
                  return rc;
              }
          }
      }
  
      return 0;
  }
  
  /*
   * Set up an instance of a ws_service object for a single request.  This
   * particular instance will be of the Apache 1.3-specific subclass.  Copies
   * all of the important request information from the Apache request object
   * into the jk_ws_service_t object.
   *
   * Params 
   *
   * private_data: The subclass-specific data structure, already initialized
   * (with a pointer to the Apache request_rec structure, among other things)
   *
   * s: The base class object.
   *
   * conf: Configuration information
   *  
   * Called from jk_handler().  See jk_service.h for explanations of what most
   * of these fields mean.  
   */
  static int init_ws_service(apache_private_data_t *private_data,
                             jk_ws_service_t *s,
                             jk_server_conf_t *conf)
  {
      request_rec *r      = private_data->r;
      char *ssl_temp      = NULL;
      s->jvm_route        = NULL; /* Used for sticky session routing */
      
      /* Copy in function pointers (which are really methods) */
      s->start_response   = ws_start_response;
      s->read             = ws_read;
      s->write            = ws_write;
  
      s->auth_type    = NULL_FOR_EMPTY(r->connection->ap_auth_type);
      s->remote_user  = NULL_FOR_EMPTY(r->connection->user);
  
      s->protocol     = r->protocol;
      s->remote_host  = (char *)ap_get_remote_host(r->connection,
                                                   r->per_dir_config,
                                                   REMOTE_HOST);
  
      s->remote_host  = NULL_FOR_EMPTY(s->remote_host);
  
      s->remote_addr  = NULL_FOR_EMPTY(r->connection->remote_ip);
      /* Wrong:    s->server_name  = (char *)ap_get_server_name( r ); */
      s->server_name= (char *)(r->hostname ? r->hostname : 
                   r->server->server_hostname);
      
      
      s->server_port= htons( r->connection->local_addr.sin_port );
      /* Wrong: s->server_port  = r->server->port; */
  
      
      /*    Winners:  htons( r->connection->local_addr.sin_port )
                        (r->hostname ? r->hostname : 
                               r->server->server_hostname),
      */
      /* printf( "Port %u %u %u %s %s %s %d %d \n", 
          ap_get_server_port( r ), 
          htons( r->connection->local_addr.sin_port ),
          ntohs( r->connection->local_addr.sin_port ),
          ap_get_server_name( r ),
          (r->hostname ? r->hostname : r->server->server_hostname),
          r->hostname,
          r->connection->base_server->port,
          r->server->port
          );
      */
      s->server_software = (char *)ap_get_server_version();
  
      s->method       = (char *)r->method;
      s->content_length = get_content_length(r);
      s->query_string = r->args;
      s->req_uri      = r->uri;
  
      s->is_ssl       = JK_FALSE;
      s->ssl_cert     = NULL;
      s->ssl_cert_len = 0;
      s->ssl_cipher   = NULL;
      s->ssl_session  = NULL;
  
      if(conf->ssl_enable || conf->envvars_in_use) {
          ap_add_common_vars(r);
  
          if(conf->ssl_enable) {
              ssl_temp = (char *)ap_table_get(r->subprocess_env, 
                                              conf->https_indicator);
              if(ssl_temp && !strcasecmp(ssl_temp, "on")) {
                  s->is_ssl       = JK_TRUE;
                  s->ssl_cert     = (char *)ap_table_get(r->subprocess_env, 
                                                         conf->certs_indicator);
                  if(s->ssl_cert) {
                      s->ssl_cert_len = strlen(s->ssl_cert);
                  }
                  s->ssl_cipher   = (char *)ap_table_get(r->subprocess_env, 
                                                         conf->cipher_indicator);
                  s->ssl_session  = (char *)ap_table_get(r->subprocess_env, 
                                                         conf->sesion_indicator);
              }
          }
  
          if(conf->envvars_in_use) {
              array_header *t = ap_table_elts(conf->envvars);        
              if(t && t->nelts) {
                  int i;
                  table_entry *elts = (table_entry *)t->elts;
                  s->attributes_names = ap_palloc(r->pool, sizeof(char *) * t->nelts);
                  s->attributes_values = ap_palloc(r->pool, sizeof(char *) * t->nelts);
  
                  for(i = 0 ; i < t->nelts ; i++) {
                      s->attributes_names[i] = elts[i].key;
                      s->attributes_values[i] = (char *)ap_table_get(r->subprocess_env, 
                                                                     elts[i].key);
                      if(!s->attributes_values[i]) {
                          s->attributes_values[i] = elts[i].val;
                      }
                  }
  
                  s->num_attributes = t->nelts;
              }
          }
      }
  
      s->headers_names    = NULL;
      s->headers_values   = NULL;
      s->num_headers      = 0;
      if(r->headers_in && ap_table_elts(r->headers_in)) {
          array_header *t = ap_table_elts(r->headers_in);        
          if(t && t->nelts) {
              int i;
              table_entry *elts = (table_entry *)t->elts;
              s->num_headers = t->nelts;
              s->headers_names  = ap_palloc(r->pool, sizeof(char *) * t->nelts);
              s->headers_values = ap_palloc(r->pool, sizeof(char *) * t->nelts);
              for(i = 0 ; i < t->nelts ; i++) {
                  char *hname = ap_pstrdup(r->pool, elts[i].key);
                  s->headers_values[i] = ap_pstrdup(r->pool, elts[i].val);
                  s->headers_names[i] = hname;
                  while(*hname) {
                      *hname = tolower(*hname);
                      hname++;
                  }
              }
          }
      }
  
      return JK_TRUE;
  }
  
  /*
   * The JK module command processors
   *
   * The below are all installed so that Apache calls them while it is
   * processing its config files.  This allows configuration info to be
   * copied into a jk_server_conf_t object, which is then used for request
   * filtering/processing.  
   *
   * See jk_cmds definition below for explanations of these options.
   */
  
  static const char *jk_set_mountcopy(cmd_parms *cmd, 
                                      void *dummy, 
                                      int flag) 
  {
      server_rec *s = cmd->server;
      jk_server_conf_t *conf =
          (jk_server_conf_t *)ap_get_module_config(s->module_config, &jk_module);
      
      /* Set up our value */
      conf->mountcopy = flag ? JK_TRUE : JK_FALSE;
  
      return NULL;
  }
  
  static const char *jk_mount_context(cmd_parms *cmd, 
                                      void *dummy, 
                                      char *context,
                                      char *worker,
                                      char *maybe_cookie)
  {
      server_rec *s = cmd->server;
      jk_server_conf_t *conf =
          (jk_server_conf_t *)ap_get_module_config(s->module_config, &jk_module);
  
      /*
       * Add the new worker to the alias map.
       */
      char *old;
      map_put(conf->uri_to_context, context, worker, (void **)&old);
      return NULL;
  }
  
  static const char *jk_set_worker_file(cmd_parms *cmd, 
                                        void *dummy, 
                                        char *worker_file)
  {
      server_rec *s = cmd->server;
      struct stat statbuf;
  
      jk_server_conf_t *conf =
          (jk_server_conf_t *)ap_get_module_config(s->module_config, &jk_module);
  
      conf->worker_file = worker_file;
  
      if (stat(worker_file, &statbuf) == -1)
          return "Can't find the workers file specified";
  
      return NULL;
  }
  
  static const char *jk_set_log_file(cmd_parms *cmd, 
                                     void *dummy, 
                                     char *log_file)
  {
      server_rec *s = cmd->server;
      jk_server_conf_t *conf =
          (jk_server_conf_t *)ap_get_module_config(s->module_config, &jk_module);
  
      conf->log_file = log_file;
  
      return NULL;
  }
  
  static const char *jk_set_enable_ssl(cmd_parms *cmd, 
                                       void *dummy, 
                                       int flag) 
  {
      server_rec *s = cmd->server;
      jk_server_conf_t *conf =
          (jk_server_conf_t *)ap_get_module_config(s->module_config, &jk_module);
      
      /* Set up our value */
      conf->ssl_enable = flag ? JK_TRUE : JK_FALSE;
  
      return NULL;
  }
  
  static const char *jk_set_https_indicator(cmd_parms *cmd, 
                                            void *dummy, 
                                            char *indicator)
  {
      server_rec *s = cmd->server;
      jk_server_conf_t *conf =
          (jk_server_conf_t *)ap_get_module_config(s->module_config, &jk_module);
  
      conf->https_indicator = indicator;
  
      return NULL;
  }
  
  static const char *jk_set_certs_indicator(cmd_parms *cmd, 
                                            void *dummy, 
                                            char *indicator)
  {
      server_rec *s = cmd->server;
      jk_server_conf_t *conf =
          (jk_server_conf_t *)ap_get_module_config(s->module_config, &jk_module);
  
      conf->certs_indicator = indicator;
  
      return NULL;
  }
  
  static const char *jk_set_cipher_indicator(cmd_parms *cmd, 
                                             void *dummy, 
                                             char *indicator)
  {
      server_rec *s = cmd->server;
      jk_server_conf_t *conf =
          (jk_server_conf_t *)ap_get_module_config(s->module_config, &jk_module);
  
      conf->cipher_indicator = indicator;
  
      return NULL;
  }
  
  static const char *jk_set_sesion_indicator(cmd_parms *cmd, 
                                             void *dummy, 
                                             char *indicator)
  {
      server_rec *s = cmd->server;
      jk_server_conf_t *conf =
          (jk_server_conf_t *)ap_get_module_config(s->module_config, &jk_module);
  
      conf->sesion_indicator = indicator;
  
      return NULL;
  }
  
  
  static const char *jk_set_log_level(cmd_parms *cmd, 
                                      void *dummy, 
                                      char *log_level)
  {
      server_rec *s = cmd->server;
      jk_server_conf_t *conf =
          (jk_server_conf_t *)ap_get_module_config(s->module_config, &jk_module);
  
      conf->log_level = jk_parse_log_level(log_level);
  
      return NULL;
  }
  
  
  static const char *jk_add_env_var(cmd_parms *cmd, 
                                    void *dummy, 
                                    char *env_name,
                                    char *default_value)
  {
      server_rec *s = cmd->server;
      jk_server_conf_t *conf =
          (jk_server_conf_t *)ap_get_module_config(s->module_config, &jk_module);
  
      conf->envvars_in_use = JK_TRUE;
      
      ap_table_add(conf->envvars, env_name, default_value);
  
      return NULL;
  }
  
  
  static const char * jk_set_log_fmt(cmd_parms *cmd,
  				   void *dummy,
  				   char * log_format)
  {
  	jk_set_log_format(log_format);
  	return NULL;
  }
  
  static const command_rec jk_cmds[] =
  {
      /*
       * JkWorkersFile specifies a full path to the location of the worker 
       * properties file.
       *
       * This file defines the different workers used by apache to redirect 
       * servlet requests.
       */
      {"JkWorkersFile", jk_set_worker_file, NULL, RSRC_CONF, TAKE1,
       "the name of a worker file for the Jakarta servlet containers"},
      /*
       * JkMount mounts a url prefix to a worker (the worker need to be
       * defined in the worker properties file.
       */
      {"JkMount", jk_mount_context, NULL, RSRC_CONF, TAKE23,
       "A mount point from a context to a Tomcat worker"},
      /*
       * JkMountCopy specifies if mod_jk should copy the mount points
       * from the main server to the virtual servers.
       */
      {"JkMountCopy", jk_set_mountcopy, NULL, RSRC_CONF, FLAG,
       "Should the base server mounts be copied to the virtual server"},
      /*
       * JkLogFile & JkLogLevel specifies to where should the plugin log
       * its information and how much.
       */
      {"JkLogFile", jk_set_log_file, NULL, RSRC_CONF, TAKE1,
       "Full path to the Jakarta Tomcat module log file"},
      {"JkLogLevel", jk_set_log_level, NULL, RSRC_CONF, TAKE1,
       "The Jakarta Tomcat module log level, can be debug, info, error or emerg"},
      {"JkLogStampFormat", jk_set_log_fmt, NULL, RSRC_CONF, TAKE1,
       "The Jakarta Tomcat module log format, follow strftime synthax"},
      /*
       * Apache has multiple SSL modules (for example apache_ssl, stronghold
       * IHS ...). Each of these can have a different SSL environment names
       * The following properties let the administrator specify the envoiroment
       * variables names.
       *
       * HTTPS - indication for SSL 
       * CERTS - Base64-Der-encoded client certificates.
       * CIPHER - A string specifing the ciphers suite in use.
       * SESSION - A string specifing the current SSL session.
       */
      {"JkHTTPSIndicator", jk_set_https_indicator, NULL, RSRC_CONF, TAKE1,
       "Name of the Apache environment that contains SSL indication"},
      {"JkCERTSIndicator", jk_set_certs_indicator, NULL, RSRC_CONF, TAKE1,
       "Name of the Apache environment that contains SSL client certificates"},
      {"JkCIPHERIndicator", jk_set_cipher_indicator, NULL, RSRC_CONF, TAKE1,
       "Name of the Apache environment that contains SSL client cipher"},
      {"JkSESSIONIndicator", jk_set_sesion_indicator, NULL, RSRC_CONF, TAKE1,
       "Name of the Apache environment that contains SSL session"},
      {"JkExtractSSL", jk_set_enable_ssl, NULL, RSRC_CONF, FLAG,
       "Turns on SSL processing and information gathering by mod_jk"},     
  
  
      {"JkEnvVar", jk_add_env_var, NULL, RSRC_CONF, TAKE2,
       "Adds a name of environment variable that should be sent to Tomcat"},     
      {NULL}
  };
  
  /* ====================================================================== */
  /* The JK module handlers                                                 */
  /* ====================================================================== */
  
  /*
   * Called to handle a single request.
   */ 
  static int jk_handler(request_rec *r)
  {   
      /* Retrieve the worker name stored by jk_translate() */
      const char *worker_name = ap_table_get(r->notes, JK_WORKER_ID);
  
      if(r->proxyreq) {
          return HTTP_INTERNAL_SERVER_ERROR;
      }
        
      if(worker_name) {
          jk_server_conf_t *conf =
              (jk_server_conf_t *)ap_get_module_config(r->server->module_config, &jk_module);
          jk_logger_t *l = conf->log ? conf->log : main_log;
  
          jk_worker_t *worker = wc_get_worker_for_name(worker_name, l);
  
          if(worker) {
              int rc = JK_FALSE;
              apache_private_data_t private_data;
              jk_ws_service_t s;
              jk_pool_atom_t buf[SMALL_POOL_SIZE];
              jk_open_pool(&private_data.p, buf, sizeof(buf));
  
              private_data.response_started = JK_FALSE;
              private_data.read_body_started = JK_FALSE;
              private_data.r = r;
  
              jk_init_ws_service(&s);
              s.ws_private = &private_data;
              s.pool = &private_data.p;            
              
              if(init_ws_service(&private_data, &s, conf)) {
                  jk_endpoint_t *end = NULL;
                  if(worker->get_endpoint(worker, &end, l)) {
                      int is_recoverable_error = JK_FALSE;
                      rc = end->service(end, 
                                        &s, 
                                        l, 
                                        &is_recoverable_error);
                  
                      if (s.content_read < s.content_length) {
                          /*
                           * If the servlet engine didn't consume all of the
                           * request data, consume and discard all further
                           * characters left to read from client 
                           */
                          char *buff = ap_palloc(r->pool, 2048);
                          if (buff != NULL) {
                              int rd;
                              while ((rd = ap_get_client_block(r, buff, 2048)) > 0) {
                                  s.content_read += rd;
                              }
                          }
                      }
                      end->done(&end, l);
                  }
              }
  
              if(rc) {
                  return OK;  /* NOT r->status, even if it has changed. */
              }
          }
      }
  
      return HTTP_INTERNAL_SERVER_ERROR;
  }
  
  /*
   * Create a default config object.
   */
  static void *create_jk_config(ap_pool *p, server_rec *s)
  {
      jk_server_conf_t *c =
          (jk_server_conf_t *) ap_pcalloc(p, sizeof(jk_server_conf_t));
  
      c->worker_file = NULL;
      c->log_file    = NULL;
      c->log_level   = -1;
      c->log         = NULL;
      c->mountcopy   = JK_FALSE;
  
      /*
       * By default we will try to gather SSL info. 
       * Disable this functionality through JkExtractSSL
       */
      c->ssl_enable  = JK_TRUE;
      /*
       * The defaults ssl indicators match those in mod_ssl (seems 
       * to be in more use).
       */
      c->https_indicator  = "HTTPS";
      c->certs_indicator  = "SSL_CLIENT_CERT";
      
      /*
       * The following (comented out) environment variables match apache_ssl! 
       * If you are using apache_sslapache_ssl uncomment them (or use the 
       * configuration directives to set them.
       *
      c->cipher_indicator = "HTTPS_CIPHER";
      c->sesion_indicator = NULL;
       */
  
      /*
       * The following environment variables match mod_ssl! If you
       * are using another module (say apache_ssl) comment them out.
       */
      c->cipher_indicator = "SSL_CIPHER";
      c->sesion_indicator = "SSL_SESSION_ID";
  
      if(!map_alloc(&(c->uri_to_context))) {
          jk_error_exit(APLOG_MARK, APLOG_EMERG, s, p, "Memory error");
      }
      c->uw_map = NULL;
  
  
      c->envvars_in_use = JK_FALSE;
      c->envvars = ap_make_table(p, 0);
  
      c->s = s;
  
      return c;
  }
  
  
  static void *merge_jk_config(ap_pool *p, 
                               void *basev, 
                               void *overridesv)
  {
      jk_server_conf_t *base = (jk_server_conf_t *) basev;
      jk_server_conf_t *overrides = (jk_server_conf_t *)overridesv;
  
      if(base->ssl_enable) {
          overrides->ssl_enable       = base->ssl_enable;
          overrides->https_indicator  = base->https_indicator;
          overrides->certs_indicator  = base->certs_indicator;
          overrides->cipher_indicator = base->cipher_indicator;
          overrides->sesion_indicator = base->sesion_indicator;
      }
      
      if(overrides->mountcopy) {
          int sz = map_size(base->uri_to_context);
          int i;
          for(i = 0 ; i < sz ; i++) {
              void *old;
              char *name = map_name_at(base->uri_to_context, i);
              if(NULL == map_get(overrides->uri_to_context, name, NULL)) {
                  if(!map_put(overrides->uri_to_context, 
                              name,
                              ap_pstrdup(p, map_get_string(base->uri_to_context, name, NULL)),
                              &old)) {
                      jk_error_exit(APLOG_MARK, 
                                    APLOG_EMERG, 
                                    overrides->s, 
                                    p, 
                                    "Memory error");
                  }
              }
          }
      }
  
      if(base->envvars_in_use) {
          overrides->envvars_in_use = JK_TRUE;
          
          overrides->envvars = 
                  ap_overlay_tables(p, 
                                    overrides->envvars, 
                                    base->envvars);
  
      }
  
      if(overrides->log_file && overrides->log_level >= 0) {
          if(!jk_open_file_logger(&(overrides->log), 
                                  overrides->log_file, 
                                  overrides->log_level)) {
              overrides->log = NULL;
          }
      }
      if(!uri_worker_map_alloc(&(overrides->uw_map), 
                               overrides->uri_to_context, 
                               overrides->log)) {
          jk_error_exit(APLOG_MARK, 
                        APLOG_EMERG, 
                        overrides->s,  
                        p, 
                        "Memory error");
      }
      
      return overrides;
  }
  
  static void jk_init(server_rec *s, ap_pool *p)
  {
      jk_map_t *init_map = NULL;
      jk_server_conf_t *conf =
          (jk_server_conf_t *)ap_get_module_config(s->module_config, &jk_module);
  
      /* Open up log file */
      if(conf->log_file && conf->log_level >= 0) {
          if(!jk_open_file_logger(&(conf->log), 
                                  conf->log_file, 
                                  conf->log_level)) {
              conf->log = NULL;
          } else {
              main_log = conf->log;
          }
      }
      
      /* Create mapping from uri's to workers, and start up all the workers */
      if(!uri_worker_map_alloc(&(conf->uw_map), conf->uri_to_context, conf->log)) {
          jk_error_exit(APLOG_MARK, 
                        APLOG_EMERG, 
                        s, 
                        p, 
                        "Memory error");
      }
  
      if(map_alloc(&init_map)) {
          if(map_read_properties(init_map, conf->worker_file)) {
              
  #if MODULE_MAGIC_NUMBER >= 19980527
              /* Tell apache we're here */
              ap_add_version_component("mod_jk");
  #endif
              
              if(wc_open(init_map, conf->log)) {
                  /* we don't need this any more so free it */
                  map_free(&init_map);
                  return;
              }            
          }
      }
      
      jk_error_exit(APLOG_MARK, 
                    APLOG_EMERG, 
                    s, 
                    p, 
                    "Error while opening the workers");
  }
  
  /*
   * Perform uri to worker mapping, and store the name of the relevant worker
   * in the notes fields of the request_rec object passed in.  This will then
   * get picked up in jk_handler().
   */
  static int jk_translate(request_rec *r)
  {    
      if(!r->proxyreq) {        
          jk_server_conf_t *conf =
              (jk_server_conf_t *)ap_get_module_config(r->server->module_config, &jk_module);
  
          if(conf) {
              char *worker = map_uri_to_worker(conf->uw_map, 
                                               r->uri, 
                                               conf->log ? conf->log : main_log);
  
              if(worker) {
                  r->handler = ap_pstrdup(r->pool, JK_HANDLER);
                  ap_table_setn(r->notes, JK_WORKER_ID, worker);
              }
          }
      }
  
      return DECLINED;
  }
  
  static void exit_handler (server_rec *s, ap_pool *p)
  {
     jk_server_conf_t *conf =
         (jk_server_conf_t *)ap_get_module_config(s->module_config, &jk_module);
  
     wc_close(conf->log);
     uri_worker_map_free(&(conf->uw_map), conf->log);
     map_free(&(conf->uri_to_context));
     if (conf->log)
        jk_close_file_logger(&(conf->log));
  }
  
  static const handler_rec jk_handlers[] =
  {
      { JK_MAGIC_TYPE, jk_handler },
      { JK_HANDLER, jk_handler },    
      { NULL }
  };
  
  module MODULE_VAR_EXPORT jk_module = {
      STANDARD_MODULE_STUFF,
      jk_init,                    /* module initializer */
      NULL,                       /* per-directory config creator */
      NULL,                       /* dir config merger */
      create_jk_config,           /* server config creator */
      merge_jk_config,            /* server config merger */
      jk_cmds,                    /* command table */
      jk_handlers,                /* [7] list of handlers */
      jk_translate,               /* [2] filename-to-URI translation */
      NULL,                       /* [5] check/validate user_id */
      NULL,                       /* [6] check user_id is valid *here* */
      NULL,                       /* [4] check access by host address */
      NULL,                       /* XXX [7] MIME type checker/setter */
      NULL,                       /* [8] fixups */
      NULL,                       /* [10] logger */
      NULL,                       /* [3] header parser */
      NULL,                       /* apache child process initializer */
      exit_handler,               /* apache child process exit/cleanup */
      NULL                        /* [1] post read_request handling */
  #ifdef EAPI
      /*
       * Extended module APIs, needed when using SSL.
       * STDC say that we do not have to have them as NULL but
       * why take a chance
       */
      ,NULL,                      /* add_module */
      NULL,                       /* remove_module */
      NULL,                       /* rewrite_command */
      NULL,                       /* new_connection */
      NULL                       /* close_connection */
  #endif /* EAPI */
  
  };
  
  
  
  1.1                  jakarta-tomcat-connectors/jk/src/native/apache-1.3/mod_jk.dsp
  
  Index: mod_jk.dsp
  ===================================================================
  # Microsoft Developer Studio Project File - Name="mod_jk" - Package Owner=<4>
  # Microsoft Developer Studio Generated Build File, Format Version 6.00
  # ** DO NOT EDIT **
  
  # TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
  
  CFG=mod_jk - Win32 Debug
  !MESSAGE This is not a valid makefile. To build this project using NMAKE,
  !MESSAGE use the Export Makefile command and run
  !MESSAGE 
  !MESSAGE NMAKE /f "mod_jk.mak".
  !MESSAGE 
  !MESSAGE You can specify a configuration when running NMAKE
  !MESSAGE by defining the macro CFG on the command line. For example:
  !MESSAGE 
  !MESSAGE NMAKE /f "mod_jk.mak" CFG="mod_jk - Win32 Debug"
  !MESSAGE 
  !MESSAGE Possible choices for configuration are:
  !MESSAGE 
  !MESSAGE "mod_jk - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
  !MESSAGE "mod_jk - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
  !MESSAGE 
  
  # Begin Project
  # PROP AllowPerConfigDependencies 0
  # PROP Scc_ProjName ""
  # PROP Scc_LocalPath ""
  CPP=cl.exe
  MTL=midl.exe
  RSC=rc.exe
  
  !IF  "$(CFG)" == "mod_jk - Win32 Release"
  
  # PROP BASE Use_MFC 0
  # PROP BASE Use_Debug_Libraries 0
  # PROP BASE Output_Dir "Release"
  # PROP BASE Intermediate_Dir "Release"
  # PROP BASE Target_Dir ""
  # PROP Use_MFC 0
  # PROP Use_Debug_Libraries 0
  # PROP Output_Dir "Release"
  # PROP Intermediate_Dir "Release"
  # PROP Ignore_Export_Lib 0
  # PROP Target_Dir ""
  # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MOD_JK_EXPORTS" /YX /FD /c
  # ADD CPP /nologo /MT /W3 /GX /O2 /I "..\common" /I "$(APACHE1_HOME)\src\include" /I "$(APACHE1_HOME)\src\os\win32" /I "$(JAVA_HOME)\include" /I "$(JAVA_HOME)\include\win32" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MOD_JK_EXPORTS" /YX /FD /c
  # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
  # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
  # ADD BASE RSC /l 0x409 /d "NDEBUG"
  # ADD RSC /l 0x409 /d "NDEBUG"
  BSC32=bscmake.exe
  # ADD BASE BSC32 /nologo
  # ADD BSC32 /nologo
  LINK32=link.exe
  # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
  # ADD LINK32 ApacheCore.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /libpath:"$(APACHE1_HOME)\src\CoreR" /libpath:"$(APACHE1_HOME)\src\Release"
  
  !ELSEIF  "$(CFG)" == "mod_jk - Win32 Debug"
  
  # PROP BASE Use_MFC 0
  # PROP BASE Use_Debug_Libraries 1
  # PROP BASE Output_Dir "Debug"
  # PROP BASE Intermediate_Dir "Debug"
  # PROP BASE Target_Dir ""
  # PROP Use_MFC 0
  # PROP Use_Debug_Libraries 1
  # PROP Output_Dir "Debug"
  # PROP Intermediate_Dir "Debug"
  # PROP Ignore_Export_Lib 0
  # PROP Target_Dir ""
  # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MOD_JK_EXPORTS" /YX /FD /GZ /c
  # ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\common" /I "$(APACHE1_HOME)\src\include" /I "$(APACHE1_HOME)\src\os\win32" /I "$(JAVA_HOME)\include" /I "$(JAVA_HOME)\include\win32" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MOD_JK_EXPORTS" /FR /YX /FD /GZ /c
  # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
  # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
  # ADD BASE RSC /l 0x409 /d "_DEBUG"
  # ADD RSC /l 0x409 /d "_DEBUG"
  BSC32=bscmake.exe
  # ADD BASE BSC32 /nologo
  # ADD BSC32 /nologo
  LINK32=link.exe
  # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
  # ADD LINK32 ApacheCore.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept /libpath:"$(APACHE1_HOME)\src\CoreD" /libpath:"$(APACHE1_HOME)\src\Debug"
  
  !ENDIF 
  
  # Begin Target
  
  # Name "mod_jk - Win32 Release"
  # Name "mod_jk - Win32 Debug"
  # Begin Group "Source Files"
  
  # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
  # Begin Source File
  
  SOURCE=..\common\jk_ajp12_worker.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_ajp13.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_ajp13_worker.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_connect.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_jni_worker.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_lb_worker.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_map.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_msg_buff.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_pool.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_sockbuf.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_uri_worker_map.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_util.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_worker.c
  # End Source File
  # Begin Source File
  
  SOURCE=.\mod_jk.c
  # End Source File
  # End Group
  # Begin Group "Header Files"
  
  # PROP Default_Filter "h;hpp;hxx;hm;inl"
  # Begin Source File
  
  SOURCE=..\common\jk_ajp12_worker.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_ajp13.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_ajp13_worker.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_connect.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_global.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_jni_worker.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_lb_worker.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_logger.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_map.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_msg_buff.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_mt.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_pool.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_service.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_sockbuf.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_uri_worker_map.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_util.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_worker.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_worker_list.h
  # End Source File
  # End Group
  # Begin Group "Resource Files"
  
  # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
  # End Group
  # End Target
  # End Project