summaryrefslogtreecommitdiffstats
path: root/rubbos/app/tomcat-connectors-1.2.32-src/native/common/jk_ajp12_worker.c
diff options
context:
space:
mode:
Diffstat (limited to 'rubbos/app/tomcat-connectors-1.2.32-src/native/common/jk_ajp12_worker.c')
-rw-r--r--rubbos/app/tomcat-connectors-1.2.32-src/native/common/jk_ajp12_worker.c682
1 files changed, 682 insertions, 0 deletions
diff --git a/rubbos/app/tomcat-connectors-1.2.32-src/native/common/jk_ajp12_worker.c b/rubbos/app/tomcat-connectors-1.2.32-src/native/common/jk_ajp12_worker.c
new file mode 100644
index 00000000..c10ef0b4
--- /dev/null
+++ b/rubbos/app/tomcat-connectors-1.2.32-src/native/common/jk_ajp12_worker.c
@@ -0,0 +1,682 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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: ajpv1.2 worker, used to call local or remote jserv hosts *
+ * This worker is deprecated *
+ * Author: Gal Shachor <shachor@il.ibm.com> *
+ * Based on: jserv_ajpv12.c from Jserv *
+ * Version: $Revision: 747878 $ *
+ ***************************************************************************/
+
+#include "jk_ajp12_worker.h"
+#include "jk_pool.h"
+#include "jk_connect.h"
+#include "jk_util.h"
+#include "jk_sockbuf.h"
+#if defined(AS400) && !defined(AS400_UTF8)
+#include "util_ebcdic.h"
+#include <string.h>
+#endif
+
+#define AJP_DEF_HOST ("localhost")
+#define AJP_DEF_PORT (8007)
+#define READ_BUF_SIZE (8*1024)
+#define DEF_RETRY_ATTEMPTS (1)
+
+struct ajp12_worker
+{
+ struct sockaddr_in worker_inet_addr;
+ unsigned connect_retry_attempts;
+ char *name;
+ jk_worker_t worker;
+};
+
+typedef struct ajp12_worker ajp12_worker_t;
+
+struct ajp12_endpoint
+{
+ ajp12_worker_t *worker;
+
+ jk_sock_t sd;
+ jk_sockbuf_t sb;
+
+ jk_endpoint_t endpoint;
+};
+typedef struct ajp12_endpoint ajp12_endpoint_t;
+
+static int ajpv12_mark(ajp12_endpoint_t * p, unsigned char type);
+
+#if defined(AS400) && !defined(AS400_UTF8)
+static int ajpv12_sendasciistring(ajp12_endpoint_t * p, char *buffer);
+#endif
+
+#if defined(AS400) && !defined(AS400_UTF8)
+static int ajpv12_sendstring(ajp12_endpoint_t * p, char *buffer);
+#else
+static int ajpv12_sendstring(ajp12_endpoint_t * p, const char *buffer);
+#endif
+
+static int ajpv12_sendint(ajp12_endpoint_t * p, int d);
+
+static int ajpv12_sendnbytes(ajp12_endpoint_t * p,
+ const void *buffer, int bufferlen);
+
+static int ajpv12_flush(ajp12_endpoint_t * p);
+
+static int ajpv12_handle_response(ajp12_endpoint_t * p,
+ jk_ws_service_t *s, jk_logger_t *l);
+
+static int ajpv12_handle_request(ajp12_endpoint_t * p,
+ jk_ws_service_t *s, jk_logger_t *l);
+
+/*
+ * Return values of service() method for ajp12 worker:
+ * return value is_error reason
+ * JK_FALSE JK_HTTP_SERVER_ERROR Invalid parameters (null values)
+ * Error during connect to the backend
+ * ajpv12_handle_request() returns false:
+ * Any error during reading a request body from the client or
+ * sending the request to the backend
+ * JK_FALSE JK_HTTP_OK ajpv12_handle_response() returns false:
+ * Any error during reading parts of response from backend or
+ * sending to client
+ * JK_TRUE JK_HTTP_OK All other cases
+ */
+static int JK_METHOD service(jk_endpoint_t *e,
+ jk_ws_service_t *s,
+ jk_logger_t *l, int *is_error)
+{
+ ajp12_endpoint_t *p;
+ unsigned int attempt;
+ int rc = -1;
+ /*
+ * AJP12 protocol is not recoverable.
+ */
+
+ JK_TRACE_ENTER(l);
+
+ if (!e || !e->endpoint_private || !s || !is_error) {
+ JK_LOG_NULL_PARAMS(l);
+ if (is_error)
+ *is_error = JK_HTTP_SERVER_ERROR;
+ JK_TRACE_EXIT(l);
+ return JK_FALSE;
+ }
+
+ p = e->endpoint_private;
+
+ /* Set returned error to OK */
+ *is_error = JK_HTTP_OK;
+
+ for (attempt = 0; attempt < p->worker->connect_retry_attempts;
+ attempt++) {
+ p->sd =
+ jk_open_socket(&p->worker->worker_inet_addr,
+ JK_FALSE, 0, 0, 0, l);
+
+ jk_log(l, JK_LOG_DEBUG, "In jk_endpoint_t::service, sd = %d",
+ p->sd);
+ if (IS_VALID_SOCKET(p->sd)) {
+ break;
+ }
+ }
+ if (IS_VALID_SOCKET(p->sd)) {
+
+ jk_sb_open(&p->sb, p->sd);
+ if (ajpv12_handle_request(p, s, l)) {
+ jk_log(l, JK_LOG_DEBUG,
+ "In jk_endpoint_t::service, sent request");
+ rc = ajpv12_handle_response(p, s, l);
+ JK_TRACE_EXIT(l);
+ return rc;
+ }
+ }
+ jk_log(l, JK_LOG_ERROR, "In jk_endpoint_t::service, Error sd = %d",
+ p->sd);
+ *is_error = JK_HTTP_SERVER_ERROR;
+
+ JK_TRACE_EXIT(l);
+ return JK_FALSE;
+}
+
+static int JK_METHOD done(jk_endpoint_t **e, jk_logger_t *l)
+{
+ jk_log(l, JK_LOG_DEBUG, "Into jk_endpoint_t::done");
+ if (e && *e && (*e)->endpoint_private) {
+ ajp12_endpoint_t *p = (*e)->endpoint_private;
+ if (IS_VALID_SOCKET(p->sd)) {
+ jk_shutdown_socket(p->sd, l);
+ }
+ free(p);
+ *e = NULL;
+ return JK_TRUE;
+ }
+
+ jk_log(l, JK_LOG_ERROR, "In jk_endpoint_t::done, NULL parameters");
+ return JK_FALSE;
+}
+
+static int JK_METHOD validate(jk_worker_t *pThis,
+ jk_map_t *props,
+ jk_worker_env_t *we, jk_logger_t *l)
+{
+ jk_log(l, JK_LOG_DEBUG, "Into jk_worker_t::validate");
+
+ if (pThis && pThis->worker_private) {
+ ajp12_worker_t *p = pThis->worker_private;
+ int port = jk_get_worker_port(props,
+ p->name,
+ AJP_DEF_PORT);
+
+ const char *host = jk_get_worker_host(props,
+ p->name,
+ AJP_DEF_HOST);
+
+ jk_log(l, JK_LOG_DEBUG,
+ "In jk_worker_t::validate for worker %s contact is %s:%d",
+ p->name, host, port);
+
+ if (host) {
+ if (jk_resolve(host, port, &p->worker_inet_addr, we->pool, l)) {
+ return JK_TRUE;
+ }
+ jk_log(l, JK_LOG_ERROR,
+ "In jk_worker_t::validate, resolve failed");
+ }
+ jk_log(l, JK_LOG_ERROR, "In jk_worker_t::validate, Error %s %d",
+ host, port);
+ }
+ else {
+ jk_log(l, JK_LOG_ERROR,
+ "In jk_worker_t::validate, NULL parameters");
+ }
+
+ return JK_FALSE;
+}
+
+static int JK_METHOD init(jk_worker_t *pThis,
+ jk_map_t *props,
+ jk_worker_env_t *we, jk_logger_t *log)
+{
+ /* Nothing to do for now */
+ return JK_TRUE;
+}
+
+static int JK_METHOD get_endpoint(jk_worker_t *pThis,
+ jk_endpoint_t **pend, jk_logger_t *l)
+{
+ jk_log(l, JK_LOG_DEBUG, "Into jk_worker_t::get_endpoint");
+
+ if (pThis && pThis->worker_private && pend) {
+ ajp12_endpoint_t *p =
+ (ajp12_endpoint_t *) malloc(sizeof(ajp12_endpoint_t));
+ if (p) {
+ p->sd = JK_INVALID_SOCKET;
+ p->worker = pThis->worker_private;
+ p->endpoint.endpoint_private = p;
+ p->endpoint.service = service;
+ p->endpoint.done = done;
+ *pend = &p->endpoint;
+ return JK_TRUE;
+ }
+ jk_log(l, JK_LOG_ERROR,
+ "In jk_worker_t::get_endpoint, malloc failed");
+ }
+ else {
+ jk_log(l, JK_LOG_ERROR,
+ "In jk_worker_t::get_endpoint, NULL parameters");
+ }
+
+ return JK_FALSE;
+}
+
+static int JK_METHOD destroy(jk_worker_t **pThis, jk_logger_t *l)
+{
+ jk_log(l, JK_LOG_DEBUG, "Into jk_worker_t::destroy");
+ if (pThis && *pThis && (*pThis)->worker_private) {
+ ajp12_worker_t *private_data = (*pThis)->worker_private;
+ free(private_data->name);
+ free(private_data);
+
+ return JK_TRUE;
+ }
+
+ jk_log(l, JK_LOG_ERROR, "In jk_worker_t::destroy, NULL parameters");
+ return JK_FALSE;
+}
+
+int JK_METHOD ajp12_worker_factory(jk_worker_t **w,
+ const char *name, jk_logger_t *l)
+{
+ jk_log(l, JK_LOG_DEBUG, "Into ajp12_worker_factory");
+ if (NULL != name && NULL != w) {
+ ajp12_worker_t *private_data =
+ (ajp12_worker_t *) malloc(sizeof(ajp12_worker_t));
+
+ if (private_data) {
+ private_data->name = strdup(name);
+
+ if (private_data->name) {
+ private_data->connect_retry_attempts = DEF_RETRY_ATTEMPTS;
+ private_data->worker.worker_private = private_data;
+
+ private_data->worker.validate = validate;
+ private_data->worker.init = init;
+ private_data->worker.get_endpoint = get_endpoint;
+ private_data->worker.destroy = destroy;
+ private_data->worker.maintain = NULL;
+
+ *w = &private_data->worker;
+ return JK_AJP12_WORKER_TYPE;
+ }
+
+ free(private_data);
+ }
+ jk_log(l, JK_LOG_ERROR, "In ajp12_worker_factory, malloc failed");
+ }
+ else {
+ jk_log(l, JK_LOG_ERROR, "In ajp12_worker_factory, NULL parameters");
+ }
+
+ return 0;
+}
+
+static int ajpv12_sendnbytes(ajp12_endpoint_t * p,
+ const void *buffer, int bufferlen)
+{
+ unsigned char bytes[2];
+ static const unsigned char null_b[2] =
+ { (unsigned char)0xff, (unsigned char)0xff };
+
+ if (buffer) {
+ bytes[0] = (unsigned char)((bufferlen >> 8) & 0xff);
+ bytes[1] = (unsigned char)(bufferlen & 0xff);
+
+ if (jk_sb_write(&p->sb, bytes, 2)) {
+ return jk_sb_write(&p->sb, buffer, bufferlen);
+ }
+ else {
+ return JK_FALSE;
+ }
+ }
+ else {
+ return jk_sb_write(&p->sb, null_b, 2);
+ }
+}
+
+#if defined(AS400) && !defined(AS400_UTF8)
+static int ajpv12_sendasciistring(ajp12_endpoint_t * p, const char *buffer)
+{
+ int bufferlen;
+
+ if (buffer && (bufferlen = strlen(buffer))) {
+ return ajpv12_sendnbytes(p, buffer, bufferlen);
+ }
+ else {
+ return ajpv12_sendnbytes(p, NULL, 0);
+ }
+}
+#endif
+
+static int ajpv12_sendstring(ajp12_endpoint_t * p, const char *buffer)
+{
+ int bufferlen;
+
+ if (buffer && (bufferlen = (int)strlen(buffer))) {
+#if (defined(AS400) && !defined(AS400_UTF8)) || defined(_OSD_POSIX)
+ char buf[2048];
+ if (bufferlen < 2048) {
+ memcpy(buf, buffer, bufferlen);
+ jk_xlate_to_ascii(buf, bufferlen);
+ return ajpv12_sendnbytes(p, buf, bufferlen);
+ }
+ else
+ return -1;
+#else
+ return ajpv12_sendnbytes(p, buffer, bufferlen);
+#endif
+ }
+ else {
+ return ajpv12_sendnbytes(p, NULL, 0);
+ }
+}
+
+static int ajpv12_mark(ajp12_endpoint_t * p, unsigned char type)
+{
+ if (jk_sb_write(&p->sb, &type, 1)) {
+ return JK_TRUE;
+ }
+ else {
+ return JK_FALSE;
+ }
+}
+
+static int ajpv12_sendint(ajp12_endpoint_t * p, int d)
+{
+ char buf[20];
+ sprintf(buf, "%d", d);
+ return ajpv12_sendstring(p, buf);
+}
+
+static int ajpv12_flush(ajp12_endpoint_t * p)
+{
+ return jk_sb_flush(&p->sb);
+}
+
+static int ajpv12_handle_request(ajp12_endpoint_t * p,
+ jk_ws_service_t *s, jk_logger_t *l)
+{
+ int ret;
+
+ jk_log(l, JK_LOG_DEBUG, "Into ajpv12_handle_request");
+ /*
+ * Start the ajp 12 service sequence
+ */
+ jk_log(l, JK_LOG_DEBUG,
+ "ajpv12_handle_request, sending the ajp12 start sequence");
+
+ ret = (ajpv12_mark(p, 1) && ajpv12_sendstring(p, s->method) && ajpv12_sendstring(p, 0) && /* zone */
+ ajpv12_sendstring(p, 0) && /* servlet */
+ ajpv12_sendstring(p, s->server_name) && ajpv12_sendstring(p, 0) && /* doc root */
+ ajpv12_sendstring(p, 0) && /* path info */
+ ajpv12_sendstring(p, 0) && /* path translated */
+#if defined(AS400) && !defined(AS400_UTF8)
+ ajpv12_sendasciistring(p, s->query_string) &&
+#else
+ ajpv12_sendstring(p, s->query_string) &&
+#endif
+ ajpv12_sendstring(p, s->remote_addr) &&
+ ajpv12_sendstring(p, s->remote_host) &&
+ ajpv12_sendstring(p, s->remote_user) &&
+ ajpv12_sendstring(p, s->auth_type) &&
+ ajpv12_sendint(p, s->server_port) &&
+#if defined(AS400) && !defined(AS400_UTF8)
+ ajpv12_sendasciistring(p, s->method) &&
+#else
+ ajpv12_sendstring(p, s->method) &&
+#endif
+ ajpv12_sendstring(p, s->req_uri) && ajpv12_sendstring(p, 0) && /* */
+ ajpv12_sendstring(p, 0) && /* SCRIPT_NAME */
+#if defined(AS400) && !defined(AS400_UTF8)
+ ajpv12_sendasciistring(p, s->server_name) &&
+#else
+ ajpv12_sendstring(p, s->server_name) &&
+#endif
+ ajpv12_sendint(p, s->server_port) && ajpv12_sendstring(p, s->protocol) && ajpv12_sendstring(p, 0) && /* SERVER_SIGNATURE */
+ ajpv12_sendstring(p, s->server_software) && ajpv12_sendstring(p, s->route) && /* JSERV_ROUTE */
+ ajpv12_sendstring(p, "") && /* JSERV ajpv12 compatibility */
+ ajpv12_sendstring(p, "")); /* JSERV ajpv12 compatibility */
+
+ if (!ret) {
+ jk_log(l, JK_LOG_ERROR,
+ "In ajpv12_handle_request, failed to send the ajp12 start sequence");
+ return JK_FALSE;
+ }
+
+ if (s->num_attributes > 0) {
+ unsigned i;
+ jk_log(l, JK_LOG_DEBUG,
+ "ajpv12_handle_request, sending the environment variables");
+
+ for (i = 0; i < s->num_attributes; i++) {
+ ret = (ajpv12_mark(p, 5) &&
+ ajpv12_sendstring(p, s->attributes_names[i]) &&
+ ajpv12_sendstring(p, s->attributes_values[i]));
+ if (!ret) {
+ jk_log(l, JK_LOG_ERROR,
+ "In ajpv12_handle_request, failed to send environment");
+ return JK_FALSE;
+ }
+ }
+ }
+
+ jk_log(l, JK_LOG_DEBUG, "ajpv12_handle_request, sending the headers");
+
+ /* Send the request headers */
+ if (s->num_headers) {
+ unsigned i;
+ for (i = 0; i < s->num_headers; ++i) {
+ ret = (ajpv12_mark(p, 3) &&
+ ajpv12_sendstring(p, s->headers_names[i]) &&
+ ajpv12_sendstring(p, s->headers_values[i]));
+
+ if (!ret) {
+ jk_log(l, JK_LOG_ERROR,
+ "In ajpv12_handle_request, failed to send headers");
+ return JK_FALSE;
+ }
+ }
+ }
+
+ jk_log(l, JK_LOG_DEBUG,
+ "ajpv12_handle_request, sending the terminating mark");
+
+ ret = (ajpv12_mark(p, 4) && ajpv12_flush(p));
+ if (!ret) {
+ jk_log(l, JK_LOG_ERROR,
+ "In ajpv12_handle_request, failed to send the terminating mark");
+ return JK_FALSE;
+ }
+
+ if (s->content_length) {
+ char buf[READ_BUF_SIZE];
+ jk_uint64_t so_far = 0;
+
+ jk_log(l, JK_LOG_DEBUG,
+ "ajpv12_handle_request, sending the request body");
+
+ while (so_far < s->content_length) {
+ unsigned this_time = 0;
+ unsigned to_read;
+ if (s->content_length > so_far + READ_BUF_SIZE) {
+ to_read = READ_BUF_SIZE;
+ }
+ else {
+ to_read = (unsigned int)(s->content_length - so_far);
+ }
+
+ if (!s->read(s, buf, to_read, &this_time)) {
+ jk_log(l, JK_LOG_ERROR,
+ "In ajpv12_handle_request, failed to read from the web server");
+ return JK_FALSE;
+ }
+ jk_log(l, JK_LOG_DEBUG, "ajpv12_handle_request, read %d bytes",
+ this_time);
+ if (this_time > 0) {
+ so_far += this_time;
+ if ((int)this_time != send(p->sd, buf, this_time, 0)) {
+ jk_log(l, JK_LOG_ERROR,
+ "In ajpv12_handle_request, failed to write to the container");
+ return JK_FALSE;
+ }
+ jk_log(l, JK_LOG_DEBUG,
+ "ajpv12_handle_request, sent %d bytes", this_time);
+ }
+ else if (this_time == 0) {
+ jk_log(l, JK_LOG_ERROR,
+ "In ajpv12_handle_request, Error: short read. content length is %" JK_UINT64_T_FMT ", read %" JK_UINT64_T_FMT,
+ s->content_length, so_far);
+ return JK_FALSE;
+ }
+ }
+ }
+
+ jk_log(l, JK_LOG_DEBUG, "ajpv12_handle_request done");
+ return JK_TRUE;
+}
+
+static int ajpv12_handle_response(ajp12_endpoint_t * p,
+ jk_ws_service_t *s, jk_logger_t *l)
+{
+ int status = 200;
+ char *reason = NULL;
+ char **names = NULL;
+ char **values = NULL;
+ int headers_capacity = 0;
+ int headers_len = 0;
+ int write_to_ws;
+
+ jk_log(l, JK_LOG_DEBUG, "Into ajpv12_handle_response");
+ /*
+ * Read headers ...
+ */
+ while (1) {
+ char *line = NULL;
+ char *name = NULL;
+ char *value = NULL;
+#ifdef _MT_CODE_PTHREAD
+ char *lasts;
+#endif
+
+ if (!jk_sb_gets(&p->sb, &line)) {
+ jk_log(l, JK_LOG_ERROR,
+ "ajpv12_handle_response, error reading header line");
+ return JK_FALSE;
+ }
+#if (defined(AS400) && !defined(AS400_UTF8)) || defined(_OSD_POSIX)
+ jk_xlate_from_ascii(line, strlen(line));
+#endif
+
+ jk_log(l, JK_LOG_DEBUG, "ajpv12_handle_response, read %s", line);
+ if (0 == strlen(line)) {
+ jk_log(l, JK_LOG_DEBUG,
+ "ajpv12_handle_response, headers are done");
+ break; /* Empty line -> end of headers */
+ }
+
+ name = line;
+ while (isspace((int)(*name)) && *name) {
+ name++; /* Skip leading white chars */
+ }
+ if (!*name) { /* Empty header name */
+ jk_log(l, JK_LOG_ERROR,
+ "ajpv12_handle_response, empty header name");
+ return JK_FALSE;
+ }
+ if (!(value = strchr(name, ':'))) {
+ jk_log(l, JK_LOG_ERROR,
+ "ajpv12_handle_response, no value supplied");
+ return JK_FALSE; /* No value !!! */
+ }
+ *value = '\0';
+ value++;
+ while (isspace((int)(*value)) && *value) {
+ value++; /* Skip leading white chars */
+ }
+ if (!*value) { /* Empty header value */
+ jk_log(l, JK_LOG_ERROR,
+ "ajpv12_handle_response, empty header value");
+ return JK_FALSE;
+ }
+
+ jk_log(l, JK_LOG_DEBUG, "ajpv12_handle_response, read %s=%s", name,
+ value);
+ if (0 == strcmp("Status", name)) {
+#ifdef _MT_CODE_PTHREAD
+ char *numeric = strtok_r(value, " \t", &lasts);
+#else
+ char *numeric = strtok(value, " \t");
+#endif
+
+ status = atoi(numeric);
+ if (status < 100 || status > 999) {
+ jk_log(l, JK_LOG_ERROR,
+ "ajpv12_handle_response, invalid status code");
+ return JK_FALSE;
+ }
+#ifdef _MT_CODE_PTHREAD
+ reason = jk_pool_strdup(s->pool, strtok_r(NULL, " \t", &lasts));
+#else
+ reason = jk_pool_strdup(s->pool, strtok(NULL, " \t"));
+#endif
+ }
+ else {
+ if (headers_capacity == headers_len) {
+ jk_log(l, JK_LOG_DEBUG,
+ "ajpv12_handle_response, allocating header arrays");
+ names =
+ (char **)jk_pool_realloc(s->pool,
+ sizeof(char *) *
+ (headers_capacity + 5), names,
+ sizeof(char *) *
+ headers_capacity);
+ values =
+ (char **)jk_pool_realloc(s->pool,
+ sizeof(char *) *
+ (headers_capacity + 5), values,
+ sizeof(char *) *
+ headers_capacity);
+ if (!values || !names) {
+ jk_log(l, JK_LOG_ERROR,
+ "ajpv12_handle_response, malloc error");
+ return JK_FALSE;
+ }
+ headers_capacity = headers_capacity + 5;
+ }
+ names[headers_len] = jk_pool_strdup(s->pool, name);
+ values[headers_len] = jk_pool_strdup(s->pool, value);
+ headers_len++;
+ }
+ }
+
+ jk_log(l, JK_LOG_DEBUG, "ajpv12_handle_response, starting response");
+ if (!s->start_response(s,
+ status,
+ reason,
+ (const char *const *)names,
+ (const char *const *)values, headers_len)) {
+ jk_log(l, JK_LOG_ERROR,
+ "ajpv12_handle_response, error starting response");
+ return JK_FALSE;
+ }
+
+ jk_log(l, JK_LOG_DEBUG,
+ "ajpv12_handle_response, reading response body");
+ /*
+ * Read response body
+ */
+ write_to_ws = JK_TRUE;
+ while (1) {
+ unsigned to_read = READ_BUF_SIZE;
+ unsigned acc = 0;
+ char *buf = NULL;
+
+ if (!jk_sb_read(&p->sb, &buf, to_read, &acc)) {
+ jk_log(l, JK_LOG_ERROR,
+ "ajpv12_handle_response, error reading from ");
+ return JK_FALSE;
+ }
+
+ if (!acc) {
+ jk_log(l, JK_LOG_DEBUG,
+ "ajpv12_handle_response, response body is done");
+ break;
+ }
+
+ if (write_to_ws) {
+ if (!s->write(s, buf, acc)) {
+ jk_log(l, JK_LOG_ERROR,
+ "ajpv12_handle_response, error writing back to server");
+ write_to_ws = JK_FALSE;
+ }
+ }
+ }
+
+ jk_log(l, JK_LOG_DEBUG, "ajpv12_handle_response done");
+ return JK_TRUE;
+}