You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ke...@apache.org on 2001/09/01 03:53:25 UTC
cvs commit: jakarta-tomcat/src/share/org/apache/tomcat/modules/server Ajp13.java
keith 01/08/31 18:53:25
Modified: src/native/mod_jk/apache1.3 mod_jk.c
src/native/mod_jk/common jk_ajp13_worker.c jk_service.h
jk_util.c
src/share/org/apache/tomcat/modules/server Ajp13.java
Log:
Upgrade mod_jk to support chunked input from Apache 1.3.
TODO: port to Apache 2.0 module. (And forward port to j-t-c)
Revision Changes Path
1.10 +22 -11 jakarta-tomcat/src/native/mod_jk/apache1.3/mod_jk.c
Index: mod_jk.c
===================================================================
RCS file: /home/cvs/jakarta-tomcat/src/native/mod_jk/apache1.3/mod_jk.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- mod_jk.c 2001/06/01 08:41:13 1.9
+++ mod_jk.c 2001/09/01 01:53:25 1.10
@@ -267,16 +267,19 @@
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) {
- *actually_read = ap_get_client_block(p->r, b, len);
- return 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;
@@ -454,7 +457,9 @@
s->server_software = (char *)ap_get_server_version();
s->method = (char *)r->method;
- s->content_length = get_content_length(r);
+ 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;
@@ -784,10 +789,16 @@
{
/* Retrieve the worker name stored by jk_translate() */
const char *worker_name = ap_table_get(r->notes, JK_WORKER_ID);
+ int rc;
if(r->proxyreq) {
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 =
@@ -820,12 +831,12 @@
l,
&is_recoverable_error);
- if (s.content_read < s.content_length) {
+ if (s.content_read < s.content_length || s.is_chunked) {
/*
* 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;
1.11 +40 -21 jakarta-tomcat/src/native/mod_jk/common/jk_ajp13_worker.c
Index: jk_ajp13_worker.c
===================================================================
RCS file: /home/cvs/jakarta-tomcat/src/native/mod_jk/common/jk_ajp13_worker.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- jk_ajp13_worker.c 2001/08/23 15:41:20 1.10
+++ jk_ajp13_worker.c 2001/09/01 01:53:25 1.11
@@ -263,6 +263,10 @@
unsigned len)
{
unsigned rdlen = 0;
+
+ if (s->is_chunked && s->no_more_chunks) {
+ return 0;
+ }
while(rdlen < len) {
unsigned this_time = 0;
@@ -270,45 +274,60 @@
return -1;
}
- if(0 == this_time) {
+ if(0 == this_time) {
+ if (s->is_chunked) {
+ s->no_more_chunks = 1; /* read no more */
+ }
break;
}
- rdlen += this_time;
+ rdlen += this_time;
}
return (int)rdlen;
}
-
+
+/* Returns -1 on error, else number of bytes read */
static int read_into_msg_buff(ajp13_endpoint_t *ep,
jk_ws_service_t *r,
jk_msg_buf_t *msg,
jk_logger_t *l,
unsigned len)
{
- unsigned char *read_buf = jk_b_get_buff(msg);
+ unsigned char *read_buf = jk_b_get_buff(msg);
jk_b_reset(msg);
read_buf += AJP13_HEADER_LEN; /* leave some space for the buffer headers */
read_buf += AJP13_HEADER_SZ_LEN; /* leave some space for the read length */
-
- if(read_fully_from_server(r, read_buf, len) < 0) {
+
+ /* Pick the max size since we don't know the content_length */
+ if (r->is_chunked && len == 0) {
+ len = MAX_SEND_BODY_SZ;
+ }
+
+ if((len = read_fully_from_server(r, read_buf, len)) < 0) {
jk_log(l, JK_LOG_ERROR,
"read_into_msg_buff: Error - read_fully_from_server failed\n");
- return JK_FALSE;
+ return -1;
}
-
- ep->left_bytes_to_send -= len;
-
- if(0 != jk_b_append_int(msg, (unsigned short)len)) {
- jk_log(l, JK_LOG_ERROR,
- "read_into_msg_buff: Error - jk_b_append_int failed\n");
- return JK_FALSE;
+
+ if (!r->is_chunked) {
+ ep->left_bytes_to_send -= len;
}
- jk_b_set_len(msg, jk_b_get_len(msg) + len);
+ if (len > 0) {
+ /* Recipient recognizes empty packet as end of stream, not
+ an empty body packet */
+ if(0 != jk_b_append_int(msg, (unsigned short)len)) {
+ jk_log(l, JK_LOG_ERROR,
+ "read_into_msg_buff: Error - jk_b_append_int failed\n");
+ return -1;
+ }
+ }
+
+ jk_b_set_len(msg, jk_b_get_len(msg) + len);
- return JK_TRUE;
+ return len;
}
static int ajp13_process_callback(jk_msg_buf_t *msg,
@@ -370,7 +389,7 @@
}
/* the right place to add file storage for upload */
- if(read_into_msg_buff(ep, r, pmsg, l, len)) {
+ if((len = read_into_msg_buff(ep, r, pmsg, l, len)) >= 0) {
r->content_read += len;
return JK_AJP13_HAS_RESPONSE;
}
@@ -636,11 +655,11 @@
* for resend if the remote Tomcat is down, a fact we will learn only
* doing a read (not yet)
*/
- if(p->left_bytes_to_send > 0) {
+ if(s->is_chunked || p->left_bytes_to_send > 0) {
unsigned len = p->left_bytes_to_send;
- if(len > MAX_SEND_BODY_SZ)
+ if(len > MAX_SEND_BODY_SZ)
len = MAX_SEND_BODY_SZ;
- if(!read_into_msg_buff(p, s, op->post, l, len)) {
+ if((len = read_into_msg_buff(p, s, op->post, l, len)) < 0) {
/* the browser stop sending data, no need to recover */
op->recoverable = JK_FALSE;
return JK_FALSE;
1.5 +5 -3 jakarta-tomcat/src/native/mod_jk/common/jk_service.h
Index: jk_service.h
===================================================================
RCS file: /home/cvs/jakarta-tomcat/src/native/mod_jk/common/jk_service.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- jk_service.h 2001/03/06 20:21:58 1.4
+++ jk_service.h 2001/09/01 01:53:25 1.5
@@ -142,8 +142,10 @@
unsigned server_port;
char *server_software;
unsigned content_length; /* integer that represents the content */
- /* length should be 0 if unknown. */
- unsigned content_read;
+ /* length should be 0 if unknown. */
+ unsigned is_chunked; /* 1 if content length is unknown (chunked rq) */
+ unsigned no_more_chunks; /* 1 if last chunk has been read */
+ unsigned content_read; /* number of bytes read */
/*
* SSL information
1.7 +4 -2 jakarta-tomcat/src/native/mod_jk/common/jk_util.c
Index: jk_util.c
===================================================================
RCS file: /home/cvs/jakarta-tomcat/src/native/mod_jk/common/jk_util.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- jk_util.c 2001/04/23 10:45:05 1.6
+++ jk_util.c 2001/09/01 01:53:25 1.7
@@ -736,7 +736,9 @@
s->server_name = NULL;
s->server_port = 80;
s->server_software = NULL;
- s->content_length = 0;
+ s->content_length = 0;
+ s->is_chunked = 0;
+ s->no_more_chunks = 0;
s->content_read = 0;
s->is_ssl = JK_FALSE;
s->ssl_cert = NULL;
1.24 +11 -4 jakarta-tomcat/src/share/org/apache/tomcat/modules/server/Ajp13.java
Index: Ajp13.java
===================================================================
RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/modules/server/Ajp13.java,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -r1.23 -r1.24
--- Ajp13.java 2001/08/29 05:08:07 1.23
+++ Ajp13.java 2001/09/01 01:53:25 1.24
@@ -201,6 +201,8 @@
int blen; // Length of current chunk of body data in buffer
int pos; // Current read position within that buffer
+ boolean end_of_stream; // true if we've received an empty packet
+
public Ajp13()
{
super();
@@ -211,6 +213,7 @@
// This is a touch cargo-cultish, but I think wise.
blen = 0;
pos = 0;
+ end_of_stream = false;
if( dL>0 ) d( "recycle()");
headersWriter.recycle();
}
@@ -384,7 +387,7 @@
MessageBytes clB=headers.getValue("content-length");
int contentLength = (clB==null) ? -1 : clB.getInt();
if( dL > 0 ) d("Content-Length: " + contentLength );
- if(contentLength > 0) {
+ if(contentLength != 0) {
req.setContentLength( contentLength );
/* Read present data */
int err = receive(inBuf);
@@ -455,7 +458,7 @@
return len;
}
- // Not enough data (blen < pos + len)
+ // Not enough data (blen < pos + len) or chunked encoded
int toCopy = len;
while(toCopy > 0) {
int bytesRemaining = blen - pos;
@@ -465,8 +468,8 @@
System.arraycopy(bodyBuff, pos, b, off, c);
if( dL > 0 ) d("doRead2: " + pos + " " + len + " " + blen + " " + c +
- " " + new String( b, off, len ) + " " +
- new String( bodyBuff, pos, len ));
+ " " + new String( b, off, c ) + " " +
+ new String( bodyBuff, pos, c ));
toCopy -= c;
@@ -492,6 +495,9 @@
{
// If the server returns an empty packet, assume that that end of
// the stream has been reached (yuck -- fix protocol??).
+ if (end_of_stream) {
+ return false;
+ }
// Why not use outBuf??
inBuf.reset();
@@ -509,6 +515,7 @@
if( inBuf.getLen() == 0 ) {
pos=0;
blen=0;
+ end_of_stream = true;
return false;
}
blen = inBuf.peekInt();