costin 01/11/20 16:02:32 Added: jk/native/common/ajp12 jk_ajp12_worker.c jk_ajp12_worker.h jk_sockbuf.c jk_sockbuf.h Log: Part 2 of Ajp12 removal ( or sort of :-). It seems some people still need ajp12 - it's the only way to use JServ with Apache2, and people still have 'legacy' servlet2.0 applications on jserv... The code will not be compiled by default and probably we can actually remove it in the second release of mod_jk, but for now it doesn't hurt too much to keep it. Revision Changes Path 1.1 jakarta-tomcat-connectors/jk/native/common/ajp12/jk_ajp12_worker.c Index: jk_ajp12_worker.c =================================================================== /* * Copyright (c) 1997-1999 The Java Apache Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. All advertising materials mentioning features or use of this * software must display the following acknowledgment: * "This product includes software developed by the Java Apache * Project for use in the Apache JServ servlet engine project * <http://java.apache.org/>." * * 4. The names "Apache JServ", "Apache JServ Servlet Engine" and * "Java Apache Project" must not be used to endorse or promote products * derived from this software without prior written permission. * * 5. Products derived from this software may not be called "Apache JServ" * nor may "Apache" nor "Apache JServ" appear in their names without * prior written permission of the Java Apache Project. * * 6. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by the Java Apache * Project for use in the Apache JServ servlet engine project * <http://java.apache.org/>." * * THIS SOFTWARE IS PROVIDED BY THE JAVA APACHE PROJECT "AS IS" AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE JAVA APACHE PROJECT OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * This software consists of voluntary contributions made by many * individuals on behalf of the Java Apache Group. For more information * on the Java Apache Project and the Apache JServ Servlet Engine project, * please see <http://java.apache.org/>. * */ /*************************************************************************** * Description: ajpv1.2 worker, used to call local or remote jserv hosts * * Author: Gal Shachor <[EMAIL PROTECTED]> * * Based on: jserv_ajpv12.c from Jserv * * Version: $Revision: 1.1 $ * ***************************************************************************/ #include "jk_ajp12_worker.h" #include "jk_pool.h" #include "jk_connect.h" #include "jk_util.h" #include "jk_sockbuf.h" #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; int 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); static int ajpv12_sendstring(ajp12_endpoint_t *p, const char *buffer); 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); static int JK_METHOD service(jk_endpoint_t *e, jk_ws_service_t *s, jk_logger_t *l, int *is_recoverable_error) { jk_log(l, JK_LOG_DEBUG, "Into jk_endpoint_t::service\n"); if(e && e->endpoint_private && s && is_recoverable_error) { ajp12_endpoint_t *p = e->endpoint_private; unsigned attempt; *is_recoverable_error = JK_TRUE; for(attempt = 0 ; attempt < p->worker->connect_retry_attempts ; attempt++) { p->sd = jk_open_socket(&p->worker->worker_inet_addr, JK_TRUE, l); jk_log(l, JK_LOG_DEBUG, "In jk_endpoint_t::service, sd = %d\n", p->sd); if(p->sd >= 0) { break; } } if(p->sd >= 0) { /* * After we are connected, each error that we are going to * have is probably unrecoverable */ *is_recoverable_error = JK_FALSE; 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\n"); return ajpv12_handle_response(p, s, l); } } jk_log(l, JK_LOG_ERROR, "In jk_endpoint_t::service, Error sd = %d\n", p->sd); } else { jk_log(l, JK_LOG_ERROR, "In jk_endpoint_t::service, NULL parameters\n"); } 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\n"); if(e && *e && (*e)->endpoint_private) { ajp12_endpoint_t *p = (*e)->endpoint_private; if(p->sd > 0) { jk_close_socket(p->sd); } free(p); *e = NULL; return JK_TRUE; } jk_log(l, JK_LOG_ERROR, "In jk_endpoint_t::done, NULL parameters\n"); return JK_FALSE; } static int JK_METHOD validate(jk_worker_t *pThis, jk_map_t *props, jk_logger_t *l) { jk_log(l, JK_LOG_DEBUG, "Into jk_worker_t::validate\n"); if(pThis && pThis->worker_private) { ajp12_worker_t *p = pThis->worker_private; int port = jk_get_worker_port(props, p->name, AJP_DEF_PORT); 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\n", p->name, host, port); if(port > 1024 && host) { if(jk_resolve(host, (short)port, &p->worker_inet_addr)) { return JK_TRUE; } jk_log(l, JK_LOG_ERROR, "In jk_worker_t::validate, resolve failed\n"); } jk_log(l, JK_LOG_ERROR, "In jk_worker_t::validate, Error %s %d\n", host, port); } else { jk_log(l, JK_LOG_ERROR, "In jk_worker_t::validate, NULL parameters\n"); } return JK_FALSE; } static int JK_METHOD init(jk_worker_t *pThis, jk_map_t *props, 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\n"); if(pThis && pThis->worker_private && pend) { ajp12_endpoint_t *p = (ajp12_endpoint_t *)malloc(sizeof(ajp12_endpoint_t)); if(p) { p->sd = -1; 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\n"); } else { jk_log(l, JK_LOG_ERROR, "In jk_worker_t::get_endpoint, NULL parameters\n"); } 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\n"); 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\n"); 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\n"); 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; *w = &private_data->worker; return JK_TRUE; } free(private_data); } jk_log(l, JK_LOG_ERROR, "In ajp12_worker_factory, malloc failed\n"); } else { jk_log(l, JK_LOG_ERROR, "In ajp12_worker_factory, NULL parameters\n"); } return JK_FALSE; } 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); } } static int ajpv12_sendstring(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); } } 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\n"); /* * Start the ajp 12 service sequence */ jk_log(l, JK_LOG_DEBUG, "ajpv12_handle_request, sending the ajp12 start sequence\n"); 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 */ ajpv12_sendstring(p, s->query_string)&& 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) && ajpv12_sendstring(p, s->method) && ajpv12_sendstring(p, s->req_uri) && ajpv12_sendstring(p, 0) && /* */ ajpv12_sendstring(p, 0) && /* SCRIPT_NAME */ ajpv12_sendstring(p, s->server_name) && 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->jvm_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\n"); return JK_FALSE; } if(s->num_attributes > 0) { unsigned i; jk_log(l, JK_LOG_DEBUG, "ajpv12_handle_request, sending the environment variables\n"); 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\n"); return JK_FALSE; } } } jk_log(l, JK_LOG_DEBUG, "ajpv12_handle_request, sending the headers\n"); /* 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\n"); return JK_FALSE; } } } jk_log(l, JK_LOG_DEBUG, "ajpv12_handle_request, sending the terminating mark\n"); 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\n"); return JK_FALSE; } if(s->content_length) { char buf[READ_BUF_SIZE]; unsigned so_far = 0; jk_log(l, JK_LOG_DEBUG, "ajpv12_handle_request, sending the request body\n"); while(so_far < s->content_length) { unsigned this_time = 0; unsigned to_read = s->content_length - so_far; if(to_read > READ_BUF_SIZE) { to_read = READ_BUF_SIZE; } 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\n"); return JK_FALSE; } jk_log(l, JK_LOG_DEBUG, "ajpv12_handle_request, read %d bytes\n", 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\n"); return JK_FALSE; } jk_log(l, JK_LOG_DEBUG, "ajpv12_handle_request, sent %d bytes\n", this_time); } else if (this_time == 0) { jk_log(l, JK_LOG_ERROR, "In ajpv12_handle_request, Error: short read. content length is %d, read %d\n", s->content_length, so_far); return JK_FALSE; } } } jk_log(l, JK_LOG_DEBUG, "ajpv12_handle_request done\n"); 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\n"); /* * Read headers ... */ while(1) { char *line = NULL; char *name = NULL; char *value = NULL; if(!jk_sb_gets(&p->sb, &line)) { jk_log(l, JK_LOG_ERROR, "ajpv12_handle_response, error reading header line\n"); return JK_FALSE; } jk_log(l, JK_LOG_DEBUG, "ajpv12_handle_response, read %s\n", line); if(0 == strlen(line)) { jk_log(l, JK_LOG_DEBUG, "ajpv12_handle_response, headers are done\n"); break; /* Empty line -> end of headers */ } name = line; while(isspace(*name) && *name) { name++; /* Skip leading white chars */ } if(!*name) { /* Empty header name */ jk_log(l, JK_LOG_ERROR, "ajpv12_handle_response, empty header name\n"); return JK_FALSE; } if(!(value = strchr(name, ':'))) { jk_log(l, JK_LOG_ERROR, "ajpv12_handle_response, no value supplied\n"); return JK_FALSE; /* No value !!! */ } *value = '\0'; value++; while(isspace(*value) && *value) { value++; /* Skip leading white chars */ } if(!*value) { /* Empty header value */ jk_log(l, JK_LOG_ERROR, "ajpv12_handle_response, empty header value\n"); return JK_FALSE; } jk_log(l, JK_LOG_DEBUG, "ajpv12_handle_response, read %s=%s\n", name, value); if(0 == strcmp("Status", name)) { char *numeric = strtok(value, " \t"); status = atoi(numeric); if(status < 100 || status > 999) { jk_log(l, JK_LOG_ERROR, "ajpv12_handle_response, invalid status code\n"); return JK_FALSE; } reason = jk_pool_strdup(s->pool, strtok(NULL, " \t")); } else { if(headers_capacity == headers_len) { jk_log(l, JK_LOG_DEBUG, "ajpv12_handle_response, allocating header arrays\n"); 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\n"); 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\n"); 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\n"); return JK_FALSE; } jk_log(l, JK_LOG_DEBUG, "ajpv12_handle_response, reading response body\n"); /* * 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 \n"); return JK_FALSE; } if(!acc) { jk_log(l, JK_LOG_DEBUG, "ajpv12_handle_response, response body is done\n"); 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\n"); write_to_ws = JK_FALSE; } } } jk_log(l, JK_LOG_DEBUG, "ajpv12_handle_response done\n"); return JK_TRUE; } 1.1 jakarta-tomcat-connectors/jk/native/common/ajp12/jk_ajp12_worker.h Index: jk_ajp12_worker.h =================================================================== /* * Copyright (c) 1997-1999 The Java Apache Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. All advertising materials mentioning features or use of this * software must display the following acknowledgment: * "This product includes software developed by the Java Apache * Project for use in the Apache JServ servlet engine project * <http://java.apache.org/>." * * 4. The names "Apache JServ", "Apache JServ Servlet Engine" and * "Java Apache Project" must not be used to endorse or promote products * derived from this software without prior written permission. * * 5. Products derived from this software may not be called "Apache JServ" * nor may "Apache" nor "Apache JServ" appear in their names without * prior written permission of the Java Apache Project. * * 6. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by the Java Apache * Project for use in the Apache JServ servlet engine project * <http://java.apache.org/>." * * THIS SOFTWARE IS PROVIDED BY THE JAVA APACHE PROJECT "AS IS" AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE JAVA APACHE PROJECT OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * This software consists of voluntary contributions made by many * individuals on behalf of the Java Apache Group. For more information * on the Java Apache Project and the Apache JServ Servlet Engine project, * please see <http://java.apache.org/>. * */ /*************************************************************************** * Description: ajpv1.2 worker header file * * Author: Gal Shachor <[EMAIL PROTECTED]> * * Version: $Revision: 1.1 $ * ***************************************************************************/ #ifndef JK_AJP12_WORKER_H #define JK_AJP12_WORKER_H #include "jk_logger.h" #include "jk_service.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ #define JK_AJP12_WORKER_NAME ("ajp12") int JK_METHOD ajp12_worker_factory(jk_worker_t **w, const char *name, jk_logger_t *l); #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* JK_AJP12_WORKER_H */ 1.1 jakarta-tomcat-connectors/jk/native/common/ajp12/jk_sockbuf.c Index: jk_sockbuf.c =================================================================== /* * Copyright (c) 1997-1999 The Java Apache Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. All advertising materials mentioning features or use of this * software must display the following acknowledgment: * "This product includes software developed by the Java Apache * Project for use in the Apache JServ servlet engine project * <http://java.apache.org/>." * * 4. The names "Apache JServ", "Apache JServ Servlet Engine" and * "Java Apache Project" must not be used to endorse or promote products * derived from this software without prior written permission. * * 5. Products derived from this software may not be called "Apache JServ" * nor may "Apache" nor "Apache JServ" appear in their names without * prior written permission of the Java Apache Project. * * 6. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by the Java Apache * Project for use in the Apache JServ servlet engine project * <http://java.apache.org/>." * * THIS SOFTWARE IS PROVIDED BY THE JAVA APACHE PROJECT "AS IS" AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE JAVA APACHE PROJECT OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * This software consists of voluntary contributions made by many * individuals on behalf of the Java Apache Group. For more information * on the Java Apache Project and the Apache JServ Servlet Engine project, * please see <http://java.apache.org/>. * */ /*************************************************************************** * Description: Simple buffer object to handle buffered socket IO * * Author: Gal Shachor <[EMAIL PROTECTED]> * * Version: $Revision: 1.1 $ * ***************************************************************************/ #include "jk_global.h" #include "jk_sockbuf.h" static int fill_buffer(jk_sockbuf_t *sb); int jk_sb_open(jk_sockbuf_t *sb, int sd) { if(sb && sd > 0) { sb->end = 0; sb->start = 0; sb->sd = sd; return JK_TRUE; } return JK_FALSE; } int jk_sb_write(jk_sockbuf_t *sb, const void *buf, unsigned sz) { if(sb && buf && sz) { if((SOCKBUF_SIZE - sb->end) >= sz) { memcpy(sb->buf + sb->end, buf, sz); sb->end += sz; } else { if(!jk_sb_flush(sb)) { return JK_FALSE; } if(sz > SOCKBUF_SIZE) { return (send(sb->sd, buf, sz, 0) == (int)sz); } memcpy(sb->buf + sb->end, buf, sz); sb->end += sz; } return JK_TRUE; } return JK_FALSE; } int jk_sb_flush(jk_sockbuf_t *sb) { if(sb) { int save_out = sb->end; sb->end = sb->start = 0; if(save_out) { return send(sb->sd, sb->buf, save_out, 0) == save_out; } return JK_TRUE; } return JK_FALSE; } int jk_sb_read(jk_sockbuf_t *sb, char **buf, unsigned sz, unsigned *ac) { if(sb && buf && ac) { unsigned avail; *ac = 0; *buf = NULL; if(sb->end == sb->start) { sb->end = sb->start = 0; if(fill_buffer(sb) < 0) { return JK_FALSE; } } *buf = sb->buf + sb->start; avail = sb->end - sb->start; if(avail > sz) { *ac = sz; } else { *ac = avail; } sb->start += *ac; return JK_TRUE; } return JK_FALSE; } int jk_sb_gets(jk_sockbuf_t *sb, char **ps) { int ret; if(sb) { while(1) { unsigned i; for(i = sb->start ; i < sb->end ; i++) { if(JK_LF == sb->buf[i]) { if(i > sb->start && JK_CR == sb->buf[i - 1]) { sb->buf[i - 1] = '\0'; } else { sb->buf[i] = '\0'; } *ps = sb->buf + sb->start; sb->start = (i + 1); return JK_TRUE; } } if((ret = fill_buffer(sb)) < 0) { return JK_FALSE; } else if (ret == 0) { *ps = sb->buf + sb->start; if ((SOCKBUF_SIZE - sb->end) > 0) { sb->buf[sb->end] = '\0'; } else { sb->buf[sb->end-1] = '\0'; } return JK_TRUE; } } } return JK_FALSE; } /* * Read data from the socket into the associated buffer, and update the * start and end indices. May move the data currently in the buffer. If * new data is read into the buffer (or if it is already full), returns 1. * If EOF is received on the socket, returns 0. In case of error returns * -1. */ static int fill_buffer(jk_sockbuf_t *sb) { int ret; /* * First move the current data to the beginning of the buffer */ if(sb->start < sb->end) { if(sb->start > 0) { unsigned to_copy = sb->end - sb->start; memmove(sb->buf, sb->buf + sb->start, to_copy); sb->start = 0; sb->end = to_copy; } } else { sb->start = sb->end = 0; } /* * In the unlikely case where the buffer is already full, we won't be * reading anything and we'd be calling recv with a 0 count. */ if ((SOCKBUF_SIZE - sb->end) > 0) { /* * Now, read more data */ ret = recv(sb->sd, sb->buf + sb->end, SOCKBUF_SIZE - sb->end, 0); // 0 is EOF/SHUTDOWN, -1 is SOCK_ERROR if (ret <= 0) { return ret; } sb->end += ret; } return 1; } 1.1 jakarta-tomcat-connectors/jk/native/common/ajp12/jk_sockbuf.h Index: jk_sockbuf.h =================================================================== /* * Copyright (c) 1997-1999 The Java Apache Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. All advertising materials mentioning features or use of this * software must display the following acknowledgment: * "This product includes software developed by the Java Apache * Project for use in the Apache JServ servlet engine project * <http://java.apache.org/>." * * 4. The names "Apache JServ", "Apache JServ Servlet Engine" and * "Java Apache Project" must not be used to endorse or promote products * derived from this software without prior written permission. * * 5. Products derived from this software may not be called "Apache JServ" * nor may "Apache" nor "Apache JServ" appear in their names without * prior written permission of the Java Apache Project. * * 6. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by the Java Apache * Project for use in the Apache JServ servlet engine project * <http://java.apache.org/>." * * THIS SOFTWARE IS PROVIDED BY THE JAVA APACHE PROJECT "AS IS" AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE JAVA APACHE PROJECT OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * This software consists of voluntary contributions made by many * individuals on behalf of the Java Apache Group. For more information * on the Java Apache Project and the Apache JServ Servlet Engine project, * please see <http://java.apache.org/>. * */ /*************************************************************************** * Description: Socket buffer header file * * Author: Gal Shachor <[EMAIL PROTECTED]> * * Version: $Revision: 1.1 $ * ***************************************************************************/ #include "jk_global.h" #define SOCKBUF_SIZE (8*1024) struct jk_sockbuf { char buf[SOCKBUF_SIZE]; unsigned start; unsigned end; int sd; }; typedef struct jk_sockbuf jk_sockbuf_t; int jk_sb_open(jk_sockbuf_t *sb, int sd); int jk_sb_write(jk_sockbuf_t *sb, const void *buf, unsigned sz); int jk_sb_read(jk_sockbuf_t *sb, char **buf, unsigned sz, unsigned *ac); int jk_sb_flush(jk_sockbuf_t *sb); int jk_sb_gets(jk_sockbuf_t *sb, char **ps);
-- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>