⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mod_jk.c

📁 精通tomcat书籍原代码,希望大家共同学习
💻 C
字号:
/*
 *  Copyright 1999-2004 The Apache Software Foundation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

/***************************************************************************
 * Description: Apache 1.3 plugin for Jakarta/Tomcat                       *
 *              See ../common/jk_service.h for general mod_jk info         *
 * Author:      Gal Shachor <shachor@il.ibm.com>                           *
 *              Dan Milstein <danmil@shore.net>                            *
 *              Henri Gomez <hgomez@apache.org>                            *
 * Version:     $Revision: 301032 $                                          *
 ***************************************************************************/

/*
 * 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"
#include "jk_ajp13.h"
#include "jk_shm.h"

#define JK_WORKER_ID        ("jakarta.worker")
#define JK_HANDLER          ("jakarta-servlet")
#define JK_DURATION         ("jakarta.worker.duration")
#define JK_MAGIC_TYPE       ("application/x-jakarta-servlet")
#define NULL_FOR_EMPTY(x)   ((x && !strlen(x)) ? NULL : x)
#define STRNULL_FOR_NULL(x) ((x) ? (x) : "(null)")

/*
 * 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;
#ifdef WIN32
extern __declspec(dllimport) module dir_module;
#else
extern module dir_module;
#endif

/*
 * Configuration object for the mod_jk module.
 */
typedef struct
{

    /*
     * Log stuff
     */
    char *log_file;
    int log_level;
    jk_logger_t *log;

    /*
     * Worker stuff
     */
    jk_map_t *worker_properties;
    char *worker_file;
    char *mount_file;
    jk_map_t *uri_to_context;

    int mountcopy;
    char *secret_key;
    jk_map_t *automount;

    jk_uri_worker_map_t *uw_map;

    /*
     * Automatic context path apache alias
     */
    char *alias_dir;

    /*
     * Request Logging
     */

    char *format_string;
    array_header *format;

    /*
     * SSL Support
     */
    int ssl_enable;
    char *https_indicator;
    char *certs_indicator;
    char *cipher_indicator;
    char *session_indicator;
    char *key_size_indicator;

    /*
     * Jk Options
     */
    int options;

    /*
     * 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;

typedef struct dir_config_struct
{
    array_header *index_names;
} dir_config_rec;

static jk_logger_t *main_log = NULL;
static jk_worker_env_t worker_env;
static char *jk_shm_file = NULL;
static size_t jk_shm_size = JK_SHM_DEF_SIZE;

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);
/* srevilak - new function prototypes */
static void jk_server_cleanup(void *data);
static void jk_generic_cleanup(server_rec * s);



/* ====================================================================== */
/* 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_should_client_block(p->r)) {
                p->read_body_started = JK_TRUE;
            }
        }

        if (p->read_body_started) {
            long rv;
            if ((rv = ap_get_client_block(p->r, b, len)) < 0) {
                *actually_read = 0;
            }
            else {
                *actually_read = (unsigned)rv;
            }
            return JK_TRUE;
        }
    }
    return JK_FALSE;
}

static void JK_METHOD ws_flush(jk_ws_service_t *s)
{
    if (s && s->ws_private) {
        apache_private_data_t *p = s->ws_private;
        BUFF *bf = p->r->connection->client;
        ap_bflush(bf);
    }
}

/*
 * 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) {
            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;
                }
            }

            if (p->r->header_only) {
                BUFF *bf = p->r->connection->client;
                ap_bflush(bf);
                return JK_TRUE;
            }

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

            }
        }

        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->flush = ws_flush;

    /* Clear RECO status */
    s->reco_status = RECO_NONE;

    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);
    
    if (conf->options & JK_OPT_FWDLOCAL)
        s->remote_addr = NULL_FOR_EMPTY(r->connection->local_ip);
    else
        s->remote_addr = NULL_FOR_EMPTY(r->connection->remote_ip);

    if (conf->options & JK_OPT_FLUSHPACKETS)
        s->flush_packets = 1;
    else
        s->flush_packets = 0;
    /* get server name */
    /* s->server_name  = (char *)(r->hostname ? r->hostname : r->server->server_hostname); */
    /* XXX : 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -