Return-Path: Delivered-To: apmail-jakarta-tomcat-dev-archive@jakarta.apache.org Received: (qmail 31472 invoked by uid 500); 3 Sep 2001 12:05:51 -0000 Mailing-List: contact tomcat-dev-help@jakarta.apache.org; run by ezmlm Precedence: bulk list-help: list-unsubscribe: list-post: Reply-To: tomcat-dev@jakarta.apache.org Delivered-To: mailing list tomcat-dev@jakarta.apache.org Received: (qmail 31462 invoked by uid 500); 3 Sep 2001 12:05:51 -0000 Delivered-To: apmail-jakarta-tomcat-cvs@apache.org Date: 3 Sep 2001 12:03:46 -0000 Message-ID: <20010903120346.60280.qmail@icarus.apache.org> From: hgomez@apache.org To: jakarta-tomcat-cvs@apache.org Subject: cvs commit: jakarta-tomcat/src/native/mod_jk/apache2.0 mod_jk.c X-Spam-Rating: daedalus.apache.org 1.6.2 0/1000/N hgomez 01/09/03 05:03:46 Modified: src/native/mod_jk/apache2.0 mod_jk.c Log: Adapted recent change in AJP13 to Apache 2.0. Added also some documentation from Apache 1.3 Revision Changes Path 1.15 +138 -18 jakarta-tomcat/src/native/mod_jk/apache2.0/mod_jk.c Index: mod_jk.c =================================================================== RCS file: /home/cvs/jakarta-tomcat/src/native/mod_jk/apache2.0/mod_jk.c,v retrieving revision 1.14 retrieving revision 1.15 diff -u -r1.14 -r1.15 --- mod_jk.c 2001/07/25 12:54:55 1.14 +++ mod_jk.c 2001/09/03 12:03:45 1.15 @@ -111,15 +111,40 @@ jk_map_t *uri_to_context; jk_uri_worker_map_t *uw_map; + /* + * SSL Support - via mod_ssl, soon :) + */ + int ssl_enable; + char *https_indicator; + char *certs_indicator; + char *cipher_indicator; + char *sesion_indicator; + int was_initialized; server_rec *s; } jk_server_conf_t; +/* + * The "private", or subclass portion of the web server service class for + * Apache 2.0. 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; @@ -142,10 +167,18 @@ const void *b, unsigned l); +/* ====================================================================== */ +/* JK Service step callbacks */ +/* ====================================================================== */ -/* ========================================================================= */ -/* 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, @@ -197,30 +230,55 @@ 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 apache2.0-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 l, - unsigned *a) + unsigned len, + unsigned *actually_read) { - if(s && s->ws_private && b && a) { + 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(ap_should_client_block(p->r)) { + p->read_body_started = JK_TRUE; } } if(p->read_body_started) { - *a = ap_get_client_block(p->r, b, l); + 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; } -/* Works with 4096, fails with 8192 */ +/* + * 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 apache2.0-specific subclass of + * the jk_ws_service class. Think of the *s param as a "this" or "self" + * pointer. + * + * Works with 4096, fails with 8192 + */ + #define CHUNK_SIZE 4096 static int JK_METHOD ws_write(jk_ws_service_t *s, @@ -319,6 +377,24 @@ 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) { @@ -380,6 +456,8 @@ s->method = (char *)r->method; s->content_length = get_content_length(r); + s->is_chunked = r->read_chunked; + s->no_more_chunks = 0; s->query_string = r->args; s->req_uri = r->uri; @@ -393,13 +471,17 @@ s->headers_values = NULL; s->num_headers = 0; if(r->headers_in && apr_table_elts(r->headers_in)) { + int need_content_length_header = (s->content_length == 0) ? JK_TRUE : JK_FALSE; apr_array_header_t *t = apr_table_elts(r->headers_in); if(t && t->nelts) { int i; apr_table_entry_t *elts = (apr_table_entry_t *)t->elts; s->num_headers = t->nelts; - s->headers_names = apr_palloc(r->pool, sizeof(char *) * t->nelts); - s->headers_values = apr_palloc(r->pool, sizeof(char *) * 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); s->headers_values[i] = apr_pstrdup(r->pool, elts[i].val); @@ -408,16 +490,46 @@ *hname = tolower(*hname); hname++; } + if(need_content_length_header && + !strncmp(s->headers_values[i],"content-length",14)) { + need_content_length_header = JK_FALSE; + } + } + /* 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 = ap_palloc(r->pool, sizeof(char *)); + s->headers_values = ap_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++; + } } return JK_TRUE; } -/* ========================================================================= */ -/* The JK module command processors */ -/* ========================================================================= */ +/* + * 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, @@ -534,10 +646,12 @@ static int jk_handler(request_rec *r) { const char *worker_name; + int rc; if(strcmp(r->handler,JK_HANDLER)) /* not for me, try next handler */ return DECLINED; +/* if (1) { jk_server_conf_t *xconf = @@ -545,6 +659,7 @@ jk_logger_t *xl = xconf->log ? xconf->log : main_log; jk_log(xl, JK_LOG_DEBUG, "Into handler r->proxyreq=%d r->handler=%s r->notes=%d\n", r->proxyreq, r->handler, r->notes); } +*/ worker_name = apr_table_get(r->notes, JK_WORKER_ID); @@ -553,6 +668,11 @@ return HTTP_INTERNAL_SERVER_ERROR; } + /* Set up r->read_chunked flags for chunked encoding, if present */ + if(rc = ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK)) { + return rc; + } + if(worker_name) { jk_server_conf_t *conf = (jk_server_conf_t *)ap_get_module_config(r->server->module_config, &jk_module); @@ -603,7 +723,7 @@ l, &is_recoverable_error); - if (s.content_read < s.content_length) { + if (s.content_read < s.content_length || s.is_chunked) { /* Toss all further characters left to read fm client */ char *buff = apr_palloc(r->pool, 2048); if (buff != NULL) {