static int init_ws_service()

in native/apache-2.0/mod_jk.c [803:1215]


static int init_ws_service(apache_private_data_t * private_data,
                           jk_ws_service_t *s, jk_server_conf_t * conf)
{
    int size;
    request_rec *r = private_data->r;
    char *ssl_temp = NULL;
    char *uri = NULL;
    const char *reply_timeout = NULL;
    const char *sticky_ignore = NULL;
    const char *stateless = NULL;
    const char *route = NULL;
    rule_extension_t *e;
    jk_request_conf_t *rconf;
    jk_log_context_t *l = apr_pcalloc(r->pool, sizeof(jk_log_context_t));

    l->logger = conf->log;
    l->id = NULL;

    /* 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;
    s->done = ws_done;
    s->add_log_items = ws_add_log_items;
    s->next_vhost = ws_next_vhost;
    s->vhost_to_text = ws_vhost_to_text;
    s->vhost_to_uw_map = ws_vhost_to_uw_map;

    rconf = (jk_request_conf_t *)ap_get_module_config(r->request_config, &jk_module);
    l->id = rconf->request_id;

    s->auth_type = get_env_string(r, r->ap_auth_type,
                                  conf->auth_type_indicator, 1);
    s->remote_user = get_env_string(r, r->user,
                                    conf->remote_user_indicator, 1);
    s->log_ctx = l;
    s->protocol = r->protocol;
    s->remote_host = (char *)ap_get_remote_host(r->connection,
                                                r->per_dir_config,
                                                REMOTE_HOST, NULL);
    s->remote_host = get_env_string(r, s->remote_host,
                                    conf->remote_host_indicator, 1);
    if (conf->options & JK_OPT_FWDLOCAL) {
        s->remote_addr = r->connection->local_ip;
        /* We don't know the client port of the backend connection. */
        s->remote_port = "0";
    }
    else {
#if (MODULE_MAGIC_NUMBER_MAJOR >= 20111130)
        if (conf->options & JK_OPT_FWDPHYSICAL) {
            s->remote_addr = r->connection->client_ip;
            s->remote_port = apr_itoa(r->pool, r->connection->client_addr->port);
        }
        else {
            s->remote_addr = r->useragent_ip;
            s->remote_port = apr_itoa(r->pool, r->useragent_addr->port);
        }
#else
        s->remote_addr = r->connection->remote_ip;
        s->remote_port = apr_itoa(r->pool, r->connection->remote_addr->port);
#endif
    }
    s->remote_addr = get_env_string(r, s->remote_addr,
                                    conf->remote_addr_indicator, 1);
    s->remote_port = get_env_string(r, s->remote_port,
                                    conf->remote_port_indicator, 1);

    if (conf->options & JK_OPT_FLUSHPACKETS)
        s->flush_packets = 1;
    if (conf->options & JK_OPT_FLUSHEADER)
        s->flush_header = 1;

    e = rconf->rule_extensions;
    if (e) {
        s->extension.reply_timeout = e->reply_timeout;
        s->extension.sticky_ignore = e->sticky_ignore;
        s->extension.stateless = e->stateless;
        s->extension.use_server_error_pages = e->use_server_error_pages;
        if (e->activation) {
            s->extension.activation = apr_palloc(r->pool, e->activation_size * sizeof(int));
            memcpy(s->extension.activation, e->activation, e->activation_size * sizeof(int));
        }
        if (e->fail_on_status_size > 0) {
            s->extension.fail_on_status_size = e->fail_on_status_size;
            s->extension.fail_on_status = apr_palloc(r->pool, e->fail_on_status_size * sizeof(int));
            memcpy(s->extension.fail_on_status, e->fail_on_status, e->fail_on_status_size * sizeof(int));
        }
        if (e->session_cookie) {
            s->extension.session_cookie = apr_pstrdup(r->pool, e->session_cookie);
        }
        if (e->session_path) {
            s->extension.session_path = apr_pstrdup(r->pool, e->session_path);
        }
        if (e->set_session_cookie) {
            s->extension.set_session_cookie = e->set_session_cookie;
        }
        if (e->session_cookie_path) {
            s->extension.session_cookie_path = apr_pstrdup(r->pool, e->session_cookie_path);
        }
    }
    reply_timeout = apr_table_get(r->subprocess_env, JK_ENV_REPLY_TIMEOUT);
    if (reply_timeout) {
        int r = atoi(reply_timeout);
        if (r >= 0)
            s->extension.reply_timeout = r;
    }

    sticky_ignore = apr_table_get(r->subprocess_env, JK_ENV_STICKY_IGNORE);
    if (sticky_ignore) {
        if (*sticky_ignore == '\0') {
            s->extension.sticky_ignore = JK_TRUE;
        }
        else {
            int r = atoi(sticky_ignore);
            if (r) {
                s->extension.sticky_ignore = JK_TRUE;
            }
            else {
                s->extension.sticky_ignore = JK_FALSE;
            }
        }
    }

    stateless = apr_table_get(r->subprocess_env, JK_ENV_STATELESS);
    if (stateless) {
        if (*stateless == '\0') {
            s->extension.stateless = JK_TRUE;
        }
        else {
            int r = atoi(stateless);
            if (r) {
                s->extension.stateless = JK_TRUE;
            }
            else {
                s->extension.stateless = JK_FALSE;
            }
        }
    }

    if (conf->options & JK_OPT_DISABLEREUSE)
        s->disable_reuse = 1;

    /* get route if known */
    route = apr_table_get(r->subprocess_env, JK_ENV_ROUTE);
    if (route && *route) {
        s->route = route;
    }

    /* get server name */
    s->server_name = get_env_string(r, (char *)ap_get_server_name(r),
                                    conf->local_name_indicator, 0);

    /* get the local IP address */
    s->local_addr = get_env_string(r, r->connection->local_ip,
                                   conf->local_addr_indicator, 0);

    /* get the real port (otherwise redirect failed) */
    /* XXX: use apache API for getting server port
     *
     * Pre 1.2.7 versions used:
     * s->server_port = r->connection->local_addr->port;
     */
    s->server_port = get_env_int(r, ap_get_server_port(r),
                                 conf->local_port_indicator);

#if ((AP_MODULE_MAGIC_AT_LEAST(20051115,4)) && !defined(API_COMPATIBILITY)) || (MODULE_MAGIC_NUMBER_MAJOR >= 20060905)
    s->server_software = (char *)ap_get_server_description();
#else
    s->server_software = (char *)ap_get_server_version();
#endif
    s->method = (char *)r->method;
    s->content_length = get_content_length(r);
    s->is_chunked = r->read_chunked;
    if (s->content_length > 0 &&
        get_env_string(r, NULL, conf->ignore_cl_indicator, 0) != NULL) {
        s->content_length = 0;
        s->is_chunked = 1;
    }
    s->no_more_chunks = 0;
#if defined(AS400) && !defined(AS400_UTF8)
    /* Get the query string that is not translated to EBCDIC  */
    s->query_string = ap_get_original_query_string(r);
#else
    s->query_string = r->args;
#endif

    /*
     * The 2.2 servlet spec errata says the uri from
     * HttpServletRequest.getRequestURI() should remain encoded.
     * [http://java.sun.com/products/servlet/errata_042700.html]
     *
     * We use JkOptions to determine which method to be used
     *
     * ap_escape_uri is the latest recommended but require
     *               some java decoding (in TC 3.3 rc2)
     *
     * unparsed_uri is used for strict compliance with spec and
     *              old Tomcat (3.2.3 for example)
     *
     * uri is use for compatibility with mod_rewrite with old Tomcats
     */

    uri = rconf->orig_uri ? rconf->orig_uri : r->uri;

    switch (conf->options & JK_OPT_FWDURIMASK) {

    case JK_OPT_FWDURICOMPATUNPARSED:
        s->req_uri = r->unparsed_uri;
        if (s->req_uri != NULL) {
            char *query_str = strchr(s->req_uri, '?');
            if (query_str != NULL) {
                *query_str = 0;
            }
        }

        break;

    case JK_OPT_FWDURICOMPAT:
        s->req_uri = uri;
        break;

    case JK_OPT_FWDURIPROXY:
        size = 3 * (int)strlen(uri) + 1;
        s->req_uri = apr_palloc(r->pool, size);
        jk_canonenc(uri, s->req_uri, size);
        break;

    case JK_OPT_FWDURIESCAPED:
        s->req_uri = ap_escape_uri(r->pool, uri);
        break;

    default:
        return JK_FALSE;
    }

    if (conf->ssl_enable || conf->envvars) {
        ap_add_common_vars(r);

        if (conf->ssl_enable) {
            ssl_temp =
                (char *)apr_table_get(r->subprocess_env,
                                      conf->https_indicator);
            if (ssl_temp && !strcasecmp(ssl_temp, "on")) {
                s->is_ssl = JK_TRUE;
                s->ssl_cert =
                    (char *)apr_table_get(r->subprocess_env,
                                          conf->certs_indicator);

                if (conf->options & JK_OPT_FWDCERTCHAIN) {
                    const apr_array_header_t *t = apr_table_elts(r->subprocess_env);
                    if (t && t->nelts) {
                        int i;
                        const apr_table_entry_t *elts = (const apr_table_entry_t *) t->elts;
                        apr_array_header_t *certs = apr_array_make(r->pool, 1, sizeof(char *));
                        *(const char **)apr_array_push(certs) = s->ssl_cert;
                        for (i = 0; i < t->nelts; i++) {
                            if (!elts[i].key)
                                continue;
                            if (!strncasecmp(elts[i].key, conf->certchain_prefix,
                                             strlen(conf->certchain_prefix)))
                                *(const char **)apr_array_push(certs) = elts[i].val;
                        }
                        s->ssl_cert = apr_array_pstrcat(r->pool, certs, '\0');
                    }
                }

                if (s->ssl_cert) {
                    s->ssl_cert_len = (unsigned int)strlen(s->ssl_cert);
                    if (JK_IS_DEBUG_LEVEL(l)) {
                        jk_log(l, JK_LOG_DEBUG,
                               "SSL client certificate (%d bytes): %s",
                               s->ssl_cert_len, s->ssl_cert);
                    }
                }
                s->ssl_protocol =
                    (char *)apr_table_get(r->subprocess_env,
                                          conf->ssl_protocol_indicator);
                /* Servlet 2.3 API */
                s->ssl_cipher =
                    (char *)apr_table_get(r->subprocess_env,
                                          conf->cipher_indicator);
                s->ssl_session =
                    (char *)apr_table_get(r->subprocess_env,
                                          conf->session_indicator);

                if (conf->options & JK_OPT_FWDKEYSIZE) {
                    /* Servlet 2.3 API */
                    ssl_temp = (char *)apr_table_get(r->subprocess_env,
                                                     conf->
                                                     key_size_indicator);
                    if (ssl_temp)
                        s->ssl_key_size = atoi(ssl_temp);
                }


            }
        }

        if (conf->envvars) {
            const apr_array_header_t *t = conf->envvar_items;
            if (t && t->nelts) {
                int i;
                int j = 0;
                envvar_item *elts = (envvar_item *) t->elts;
                s->attributes_names = apr_palloc(r->pool,
                                                 sizeof(char *) * t->nelts);
                s->attributes_values = apr_palloc(r->pool,
                                                  sizeof(char *) * t->nelts);

                for (i = 0; i < t->nelts; i++) {
                    s->attributes_names[i - j] = elts[i].name;
                    s->attributes_values[i - j] =
                        (char *)apr_table_get(r->subprocess_env, elts[i].name);
                    if (!s->attributes_values[i - j]) {
                        if (elts[i].has_default) {
                            s->attributes_values[i - j] = elts[i].value;
                        }
                        else {
                            s->attributes_values[i - j] = "";
                            s->attributes_names[i - j] = "";
                            j++;
                        }
                    }
                }

                s->num_attributes = t->nelts - j;
            }
        }
    }

    if (r->headers_in && apr_table_elts(r->headers_in)) {
        int need_content_length_header = (!s->is_chunked
                                          && s->content_length ==
                                          0) ? JK_TRUE : JK_FALSE;
        const apr_array_header_t *t = apr_table_elts(r->headers_in);
        if (t && t->nelts) {
            int i;
            int off = 0;
            apr_table_entry_t *elts = (apr_table_entry_t *) t->elts;
            s->num_headers = t->nelts;
            /* allocate an extra header slot in case we need to add a content-length header */
            s->headers_names =
                apr_palloc(r->pool, sizeof(char *) * (t->nelts + 1));
            s->headers_values =
                apr_palloc(r->pool, sizeof(char *) * (t->nelts + 1));
            if (!s->headers_names || !s->headers_values)
                return JK_FALSE;
            for (i = 0; i < t->nelts; i++) {
                char *hname = apr_pstrdup(r->pool, elts[i].key);
                if (!strcasecmp(hname, "content-length")) {
                    if (need_content_length_header) {
                        need_content_length_header = JK_FALSE;
                    } else if (s->is_chunked) {
                        s->num_headers--;
                        off++;
                        continue;
                    }
                }
                s->headers_values[i - off] = apr_pstrdup(r->pool, elts[i].val);
                s->headers_names[i - off] = hname;
            }
            /* Add a content-length = 0 header if needed.
             * Ajp13 assumes an absent content-length header means an unknown,
             * but non-zero length body.
             */
            if (need_content_length_header) {
                s->headers_names[s->num_headers] = "content-length";
                s->headers_values[s->num_headers] = "0";
                s->num_headers++;
            }
        }
        /* Add a content-length = 0 header if needed. */
        else if (need_content_length_header) {
            s->headers_names = apr_palloc(r->pool, sizeof(char *));
            s->headers_values = apr_palloc(r->pool, sizeof(char *));
            if (!s->headers_names || !s->headers_values)
                return JK_FALSE;
            s->headers_names[0] = "content-length";
            s->headers_values[0] = "0";
            s->num_headers++;
        }
    }
    s->uw_map = conf->uw_map;

    /* Dump all connection param so we can trace what's going to
     * the remote tomcat
     */
    if (JK_IS_DEBUG_LEVEL(l)) {
        jk_log(l, JK_LOG_DEBUG,
               "Service protocol=%s method=%s ssl=%s host=%s addr=%s name=%s port=%d auth=%s user=%s laddr=%s raddr=%s uaddr=%s uri=%s",
               STRNULL_FOR_NULL(s->protocol),
               STRNULL_FOR_NULL(s->method),
               s->is_ssl ? "true" : "false",
               STRNULL_FOR_NULL(s->remote_host),
               STRNULL_FOR_NULL(s->remote_addr),
               STRNULL_FOR_NULL(s->server_name),
               s->server_port,
               STRNULL_FOR_NULL(s->auth_type),
               STRNULL_FOR_NULL(s->remote_user),
               STRNULL_FOR_NULL(r->connection->local_ip),
#if (MODULE_MAGIC_NUMBER_MAJOR >= 20111130)
               STRNULL_FOR_NULL(r->connection->client_ip),
               STRNULL_FOR_NULL(r->useragent_ip),
#else
               STRNULL_FOR_NULL(r->connection->remote_ip),
               STRNULL_FOR_NULL(r->connection->remote_ip),
#endif
               STRNULL_FOR_NULL(s->req_uri));
    }

    return JK_TRUE;
}