axis-java-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From nand...@apache.org
Subject svn commit: r813537 - /webservices/axis2/trunk/c/src/core/transport/http/server/apache2/apache2_stream.c
Date Thu, 10 Sep 2009 18:20:30 GMT
Author: nandika
Date: Thu Sep 10 18:20:29 2009
New Revision: 813537

URL: http://svn.apache.org/viewvc?rev=813537&view=rev
Log:
applied patch attached to jira 1387

Modified:
    webservices/axis2/trunk/c/src/core/transport/http/server/apache2/apache2_stream.c

Modified: webservices/axis2/trunk/c/src/core/transport/http/server/apache2/apache2_stream.c
URL: http://svn.apache.org/viewvc/webservices/axis2/trunk/c/src/core/transport/http/server/apache2/apache2_stream.c?rev=813537&r1=813536&r2=813537&view=diff
==============================================================================
--- webservices/axis2/trunk/c/src/core/transport/http/server/apache2/apache2_stream.c (original)
+++ webservices/axis2/trunk/c/src/core/transport/http/server/apache2/apache2_stream.c Thu
Sep 10 18:20:29 2009
@@ -55,6 +55,11 @@
     axutil_stream_t * stream,
     const axutil_env_t * env);
 
+AP_DECLARE(long) apache2_ap_get_client_block(
+    request_rec *r,
+    char* buffer, 
+    apr_size_t bufsiz);
+
 AXIS2_EXTERN axutil_stream_t *AXIS2_CALL
 axutil_stream_create_apache2(
     const axutil_env_t * env,
@@ -93,15 +98,17 @@
     size_t count)
 {
     apache2_stream_impl_t *stream_impl = NULL;
-    size_t read = 0;
+    ssize_t read = 0;
     size_t len = 0;
+
     AXIS2_ENV_CHECK(env, AXIS2_CRITICAL_FAILURE);
 
     stream_impl = AXIS2_INTF_TO_IMPL(stream);
 
     while(count - len > 0)
     {
-        read = ap_get_client_block(stream_impl->request, (char *)buffer + len, count -
len);
+        read = apache2_ap_get_client_block(stream_impl->request, (char *) buffer + len,
+                                   count - len);
         if(read > 0)
         {
             len += read;
@@ -157,7 +164,7 @@
         AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
         return -1;
     }
-    len = ap_get_client_block(stream_impl->request, tmp_buffer, count);
+    len = apache2_ap_get_client_block(stream_impl->request, tmp_buffer, count);
     AXIS2_FREE(env->allocator, tmp_buffer);
     return len;
 
@@ -182,3 +189,99 @@
     AXIS2_ENV_CHECK(env, AXIS2_CRITICAL_FAILURE);
     return AXIS2_INTF_TO_IMPL(stream)->stream_type;
 }
+
+/*
+ * This is a re-write of get_client_block found in http_filters.c in httpd
+ * which does not work when dealing with compressed payloads (or any other input
+ * filters that could potentially return 0 bytes of filtered data and not be at
+ * the end of the stream).
+ * get_client_block is called in a loop to get the request message body.
+ * This is quite simple if the client includes a content-length
+ * (the normal case), but gets messy if the body is chunked. Note that
+ * r->remaining is used to maintain state across calls and that
+ * r->read_length is the total number of bytes given to the caller
+ * across all invocations.  It is messy because we have to be careful not
+ * to read past the data provided by the client, since these reads block.
+ * Returns 0 on End-of-body, -1 on error or premature chunk end.
+ *
+ */
+AP_DECLARE(long) apache2_ap_get_client_block (request_rec *r, char *buffer,
+        apr_size_t bufsiz)
+{
+    apr_status_t rv;
+    apr_bucket_brigade *bb;
+    int loop = 1;
+    int origBufSize = bufsiz;
+
+    if (r->remaining < 0 || (!r->read_chunked && r->remaining == 0))
{
+        return 0;
+    }
+
+    bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
+    if (bb == NULL) {
+        r->connection->keepalive = AP_CONN_CLOSE;
+        return -1;
+    }
+
+    /* we need to loop until the input filters (if any) give us data */
+    while (loop) {
+        rv = ap_get_brigade(r->input_filters, bb, AP_MODE_READBYTES,
+                APR_BLOCK_READ, bufsiz);
+
+        /* We lose the failure code here.  This is why ap_get_client_block should
+         * not be used.
+         */
+        if (rv != APR_SUCCESS) {
+            /* if we actually fail here, we want to just return and
+             * stop trying to read data from the client.
+             */
+            r->connection->keepalive = AP_CONN_CLOSE;
+            apr_brigade_destroy(bb);
+            return -1;
+        }
+
+        /* If this fails, it means that a filter is written incorrectly and that
+         * it needs to learn how to properly handle APR_BLOCK_READ requests by
+         * returning data when requested.
+         */
+        AP_DEBUG_ASSERT(!APR_BRIGADE_EMPTY(bb));
+
+        /* Check to see if EOS in the brigade.
+         *
+         * If so, we have to leave a nugget for the *next* ap_get_client_block
+         * call to return 0.
+         */
+        if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb))) {
+            if (r->read_chunked) {
+                r->remaining = -1;
+            } else {
+                r->remaining = 0;
+            }
+        }
+
+        rv = apr_brigade_flatten(bb, buffer, &bufsiz);
+        if (rv != APR_SUCCESS) {
+            apr_brigade_destroy(bb);
+            return -1;
+        }
+
+        /* XXX yank me? */
+        r->read_length += bufsiz;
+
+        /* it is possible that the entire bucket brigade is exhausted, but no data
+         * has been produced by the input filter (mod_deflate, for example)....
+         * in this scenario, we really need to keep looping
+         */
+        if (bufsiz != 0 || r->remaining <= 0) {
+            loop = 0;
+            apr_brigade_destroy(bb);
+        } else {
+            if (bufsiz == 0) {
+                bufsiz = origBufSize;
+            }
+        }
+
+    }
+
+    return bufsiz;
+}



Mime
View raw message