Return-Path: Delivered-To: apmail-jakarta-tomcat-dev-archive@jakarta.apache.org Received: (qmail 5043 invoked by uid 500); 3 May 2001 14:01:03 -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 4812 invoked by uid 500); 3 May 2001 14:00:27 -0000 Delivered-To: apmail-jakarta-tomcat-cvs@apache.org Date: 3 May 2001 13:59:57 -0000 Message-ID: <20010503135957.4376.qmail@apache.org> From: hgomez@apache.org To: jakarta-tomcat-cvs@apache.org Subject: cvs commit: jakarta-tomcat/proposals/web-connector/native/common jk_ajp13.c jk_ajp13.h jk_ajp13_worker.c jk_ajp13_worker.h hgomez 01/05/03 06:59:57 Added: proposals/web-connector/native/common jk_ajp13.c jk_ajp13.h jk_ajp13_worker.c jk_ajp13_worker.h Log: ajp13 protocol handling Revision Changes Path 1.1 jakarta-tomcat/proposals/web-connector/native/common/jk_ajp13.c Index: jk_ajp13.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 * ." * * 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 * ." * * 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 . * */ /*************************************************************************** * Description: Experimental bi-directionl protocol handler. * * Author: Gal Shachor * * Version: $Revision: 1.1 $ * ***************************************************************************/ #include "jk_global.h" #include "jk_util.h" #include "jk_ajp13.h" /* * Conditional request attributes * */ #define SC_A_CONTEXT (unsigned char)1 #define SC_A_SERVLET_PATH (unsigned char)2 #define SC_A_REMOTE_USER (unsigned char)3 #define SC_A_AUTH_TYPE (unsigned char)4 #define SC_A_QUERY_STRING (unsigned char)5 #define SC_A_JVM_ROUTE (unsigned char)6 #define SC_A_SSL_CERT (unsigned char)7 #define SC_A_SSL_CIPHER (unsigned char)8 #define SC_A_SSL_SESSION (unsigned char)9 #define SC_A_REQ_ATTRIBUTE (unsigned char)10 #define SC_A_ARE_DONE (unsigned char)0xFF /* * Request methods, coded as numbers instead of strings. * The list of methods was taken from Section 5.1.1 of RFC 2616, * RFC 2518, and the ACL IETF draft. * Method = "OPTIONS" * | "GET" * | "HEAD" * | "POST" * | "PUT" * | "DELETE" * | "TRACE" * | "PROPFIND" * | "PROPPATCH" * | "MKCOL" * | "COPY" * | "MOVE" * | "LOCK" * | "UNLOCK" * | "ACL" * */ #define SC_M_OPTIONS (unsigned char)1 #define SC_M_GET (unsigned char)2 #define SC_M_HEAD (unsigned char)3 #define SC_M_POST (unsigned char)4 #define SC_M_PUT (unsigned char)5 #define SC_M_DELETE (unsigned char)6 #define SC_M_TRACE (unsigned char)7 #define SC_M_PROPFIND (unsigned char)8 #define SC_M_PROPPATCH (unsigned char)9 #define SC_M_MKCOL (unsigned char)10 #define SC_M_COPY (unsigned char)11 #define SC_M_MOVE (unsigned char)12 #define SC_M_LOCK (unsigned char)13 #define SC_M_UNLOCK (unsigned char)14 #define SC_M_ACL (unsigned char)15 /* * Frequent request headers, these headers are coded as numbers * instead of strings. * * Accept * Accept-Charset * Accept-Encoding * Accept-Language * Authorization * Connection * Content-Type * Content-Length * Cookie * Cookie2 * Host * Pragma * Referer * User-Agent * */ #define SC_ACCEPT (unsigned short)0xA001 #define SC_ACCEPT_CHARSET (unsigned short)0xA002 #define SC_ACCEPT_ENCODING (unsigned short)0xA003 #define SC_ACCEPT_LANGUAGE (unsigned short)0xA004 #define SC_AUTHORIZATION (unsigned short)0xA005 #define SC_CONNECTION (unsigned short)0xA006 #define SC_CONTENT_TYPE (unsigned short)0xA007 #define SC_CONTENT_LENGTH (unsigned short)0xA008 #define SC_COOKIE (unsigned short)0xA009 #define SC_COOKIE2 (unsigned short)0xA00A #define SC_HOST (unsigned short)0xA00B #define SC_PRAGMA (unsigned short)0xA00C #define SC_REFERER (unsigned short)0xA00D #define SC_USER_AGENT (unsigned short)0xA00E /* * Frequent response headers, these headers are coded as numbers * instead of strings. * * Content-Type * Content-Language * Content-Length * Date * Last-Modified * Location * Set-Cookie * Servlet-Engine * Status * WWW-Authenticate * */ #define SC_RESP_CONTENT_TYPE (unsigned short)0xA001 #define SC_RESP_CONTENT_LANGUAGE (unsigned short)0xA002 #define SC_RESP_CONTENT_LENGTH (unsigned short)0xA003 #define SC_RESP_DATE (unsigned short)0xA004 #define SC_RESP_LAST_MODIFIED (unsigned short)0xA005 #define SC_RESP_LOCATION (unsigned short)0xA006 #define SC_RESP_SET_COOKIE (unsigned short)0xA007 #define SC_RESP_SET_COOKIE2 (unsigned short)0xA008 #define SC_RESP_SERVLET_ENGINE (unsigned short)0xA009 #define SC_RESP_STATUS (unsigned short)0xA00A #define SC_RESP_WWW_AUTHENTICATE (unsigned short)0xA00B #define SC_RES_HEADERS_NUM 11 const char *response_trans_headers[] = { "Content-Type", "Content-Language", "Content-Length", "Date", "Last-Modified", "Location", "Set-Cookie", "Set-Cookie2", "Servlet-Engine", "Status", "WWW-Authenticate" }; const char *long_res_header_for_sc(int sc) { const char *rc = NULL; if(sc <= SC_RES_HEADERS_NUM && sc > 0) { rc = response_trans_headers[sc - 1]; } return rc; } int sc_for_req_method(const char *method, unsigned char *sc) { int rc = JK_TRUE; if(0 == strcmp(method, "GET")) { *sc = SC_M_GET; } else if(0 == strcmp(method, "POST")) { *sc = SC_M_POST; } else if(0 == strcmp(method, "HEAD")) { *sc = SC_M_HEAD; } else if(0 == strcmp(method, "PUT")) { *sc = SC_M_PUT; } else if(0 == strcmp(method, "DELETE")) { *sc = SC_M_DELETE; } else if(0 == strcmp(method, "OPTIONS")) { *sc = SC_M_OPTIONS; } else if(0 == strcmp(method, "TRACE")) { *sc = SC_M_TRACE; } else if(0 == strcmp(method, "PROPFIND")) { *sc = SC_M_PROPFIND; } else if(0 == strcmp(method, "PROPPATCH")) { *sc = SC_M_PROPPATCH; } else if(0 == strcmp(method, "MKCOL")) { *sc = SC_M_MKCOL; } else if(0 == strcmp(method, "COPY")) { *sc = SC_M_COPY; } else if(0 == strcmp(method, "MOVE")) { *sc = SC_M_MOVE; } else if(0 == strcmp(method, "LOCK")) { *sc = SC_M_LOCK; } else if(0 == strcmp(method, "UNLOCK")) { *sc = SC_M_UNLOCK; } else if(0 == strcmp(method, "ACL")) { *sc = SC_M_ACL; } else { rc = JK_FALSE; } return rc; } int sc_for_req_header(const char *header_name, unsigned short *sc) { switch(header_name[0]) { case 'a': if('c' ==header_name[1] && 'c' ==header_name[2] && 'e' ==header_name[3] && 'p' ==header_name[4] && 't' ==header_name[5]) { if('-' == header_name[6]) { if(!strcmp(header_name + 7, "charset")) { *sc = SC_ACCEPT_CHARSET; } else if(!strcmp(header_name + 7, "encoding")) { *sc = SC_ACCEPT_ENCODING; } else if(!strcmp(header_name + 7, "language")) { *sc = SC_ACCEPT_LANGUAGE; } else { return JK_FALSE; } } else if('\0' == header_name[6]) { *sc = SC_ACCEPT; } else { return JK_FALSE; } } else if(!strcmp(header_name, "authorization")) { *sc = SC_AUTHORIZATION; } else { return JK_FALSE; } break; case 'c': if(!strcmp(header_name, "cookie")) { *sc = SC_COOKIE; } else if(!strcmp(header_name, "connection")) { *sc = SC_CONNECTION; } else if(!strcmp(header_name, "content-type")) { *sc = SC_CONTENT_TYPE; } else if(!strcmp(header_name, "content-length")) { *sc = SC_CONTENT_LENGTH; } else if(!strcmp(header_name, "cookie2")) { *sc = SC_COOKIE2; } else { return JK_FALSE; } break; case 'h': if(!strcmp(header_name, "host")) { *sc = SC_HOST; } else { return JK_FALSE; } break; case 'p': if(!strcmp(header_name, "pragma")) { *sc = SC_PRAGMA; } else { return JK_FALSE; } break; case 'r': if(!strcmp(header_name, "referer")) { *sc = SC_REFERER; } else { return JK_FALSE; } break; case 'u': if(!strcmp(header_name, "user-agent")) { *sc = SC_USER_AGENT; } else { return JK_FALSE; } break; default: return JK_FALSE; } return JK_TRUE; } /* * Message structure * * AJPV13_REQUEST:= request_prefix (1) (byte) method (byte) protocol (string) req_uri (string) remote_addr (string) remote_host (string) server_name (string) server_port (short) is_ssl (boolean) num_headers (short) num_headers*(req_header_name header_value) ?context (byte)(string) ?servlet_path (byte)(string) ?remote_user (byte)(string) ?auth_type (byte)(string) ?query_string (byte)(string) ?jvm_route (byte)(string) ?ssl_cert (byte)(string) ?ssl_cipher (byte)(string) ?ssl_session (byte)(string) request_terminator (byte) ?body content_length*(var binary) */ int ajp13_marshal_into_msgb(jk_msg_buf_t *msg, jk_ws_service_t *s, jk_logger_t *l) { unsigned char method; unsigned i; jk_log(l, JK_LOG_DEBUG, "Into ajp13_marshal_into_msgb\n"); if(!sc_for_req_method(s->method, &method)) { jk_log(l, JK_LOG_ERROR, "Error ajp13_marshal_into_msgb - No such method %s\n", s->method); return JK_FALSE; } if(0 != jk_b_append_byte(msg, JK_AJP13_FORWARD_REQUEST) || 0 != jk_b_append_byte(msg, method) || 0 != jk_b_append_string(msg, s->protocol) || 0 != jk_b_append_string(msg, s->req_uri) || 0 != jk_b_append_string(msg, s->remote_addr) || 0 != jk_b_append_string(msg, s->remote_host) || 0 != jk_b_append_string(msg, s->server_name) || 0 != jk_b_append_int(msg, (unsigned short)s->server_port) || 0 != jk_b_append_byte(msg, (unsigned char)(s->is_ssl)) || 0 != jk_b_append_int(msg, (unsigned short)(s->num_headers))) { jk_log(l, JK_LOG_ERROR, "Error ajp13_marshal_into_msgb - Error appending the message begining\n"); return JK_FALSE; } for(i = 0 ; i < s->num_headers ; i++) { unsigned short sc; if(sc_for_req_header(s->headers_names[i], &sc) ) { if(0 != jk_b_append_int(msg, sc)) { jk_log(l, JK_LOG_ERROR, "Error ajp13_marshal_into_msgb - Error appending the header name\n"); return JK_FALSE; } } else { if(0 != jk_b_append_string(msg, s->headers_names[i])) { jk_log(l, JK_LOG_ERROR, "Error ajp13_marshal_into_msgb - Error appending the header name\n"); return JK_FALSE; } } if(0 != jk_b_append_string(msg, s->headers_values[i])) { jk_log(l, JK_LOG_ERROR, "Error ajp13_marshal_into_msgb - Error appending the header value\n"); return JK_FALSE; } } if(s->remote_user) { if(0 != jk_b_append_byte(msg, SC_A_REMOTE_USER) || 0 != jk_b_append_string(msg, s->remote_user)) { jk_log(l, JK_LOG_ERROR, "Error ajp13_marshal_into_msgb - Error appending the remote user\n"); return JK_FALSE; } } if(s->auth_type) { if(0 != jk_b_append_byte(msg, SC_A_AUTH_TYPE) || 0 != jk_b_append_string(msg, s->auth_type)) { jk_log(l, JK_LOG_ERROR, "Error ajp13_marshal_into_msgb - Error appending the auth type\n"); return JK_FALSE; } } if(s->query_string) { if(0 != jk_b_append_byte(msg, SC_A_QUERY_STRING) || 0 != jk_b_append_string(msg, s->query_string)) { jk_log(l, JK_LOG_ERROR, "Error ajp13_marshal_into_msgb - Error appending the query string\n"); return JK_FALSE; } } if(s->jvm_route) { if(0 != jk_b_append_byte(msg, SC_A_JVM_ROUTE) || 0 != jk_b_append_string(msg, s->jvm_route)) { jk_log(l, JK_LOG_ERROR, "Error ajp13_marshal_into_msgb - Error appending the jvm route\n"); return JK_FALSE; } } if(s->ssl_cert_len) { if(0 != jk_b_append_byte(msg, SC_A_SSL_CERT) || 0 != jk_b_append_string(msg, s->ssl_cert)) { jk_log(l, JK_LOG_ERROR, "Error ajp13_marshal_into_msgb - Error appending the SSL certificates\n"); return JK_FALSE; } } if(s->ssl_cipher) { if(0 != jk_b_append_byte(msg, SC_A_SSL_CIPHER) || 0 != jk_b_append_string(msg, s->ssl_cipher)) { jk_log(l, JK_LOG_ERROR, "Error ajp13_marshal_into_msgb - Error appending the SSL ciphers\n"); return JK_FALSE; } } if(s->ssl_session) { if(0 != jk_b_append_byte(msg, SC_A_SSL_SESSION) || 0 != jk_b_append_string(msg, s->ssl_session)) { jk_log(l, JK_LOG_ERROR, "Error ajp13_marshal_into_msgb - Error appending the SSL session\n"); return JK_FALSE; } } if(s->num_attributes > 0) { for(i = 0 ; i < s->num_attributes ; i++) { if(0 != jk_b_append_byte(msg, SC_A_REQ_ATTRIBUTE) || 0 != jk_b_append_string(msg, s->attributes_names[i]) || 0 != jk_b_append_string(msg, s->attributes_values[i])) { jk_log(l, JK_LOG_ERROR, "Error ajp13_marshal_into_msgb - Error appending attribute %s=%s\n", s->attributes_names[i], s->attributes_values[i]); return JK_FALSE; } } } if(0 != jk_b_append_byte(msg, SC_A_ARE_DONE)) { jk_log(l, JK_LOG_ERROR, "Error ajp13_marshal_into_msgb - Error appending the message end\n"); return JK_FALSE; } jk_log(l, JK_LOG_DEBUG, "ajp13_marshal_into_msgb - Done\n"); return JK_TRUE; } /* AJPV13_RESPONSE:= response_prefix (2) status (short) status_msg (short) num_headers (short) num_headers*(res_header_name header_value) *body_chunk terminator boolean req_header_name := sc_req_header_name | (string) res_header_name := sc_res_header_name | (string) header_value := (string) body_chunk := length (short) body length*(var binary) */ int ajp13_unmarshal_response(jk_msg_buf_t *msg, jk_res_data_t *d, jk_pool_t *p, jk_logger_t *l) { d->status = jk_b_get_int(msg); if(!d->status) { jk_log(l, JK_LOG_ERROR, "Error ajp13_unmarshal_response - Null status\n"); return JK_FALSE; } d->msg = (char *)jk_b_get_string(msg); jk_log(l, JK_LOG_DEBUG, "ajp13_unmarshal_response: status = %d\n", d->status); d->num_headers = jk_b_get_int(msg); d->header_names = d->header_values = NULL; jk_log(l, JK_LOG_DEBUG, "ajp13_unmarshal_response: Number of headers is = %d\n", d->num_headers); if(d->num_headers) { d->header_names = jk_pool_alloc(p, sizeof(char *) * d->num_headers); d->header_values = jk_pool_alloc(p, sizeof(char *) * d->num_headers); if(d->header_names && d->header_values) { unsigned i; for(i = 0 ; i < d->num_headers ; i++) { unsigned short name = jk_b_pget_int(msg, jk_b_get_pos(msg)) ; if((name & 0XFF00) == 0XA000) { jk_b_get_int(msg); name = name & 0X00FF; if(name <= SC_RES_HEADERS_NUM) { d->header_names[i] = (char *)long_res_header_for_sc(name); } else { jk_log(l, JK_LOG_ERROR, "Error ajp13_unmarshal_response - No such sc (%d)\n", name); return JK_FALSE; } } else { d->header_names[i] = (char *)jk_b_get_string(msg); if(!d->header_names[i]) { jk_log(l, JK_LOG_ERROR, "Error ajp13_unmarshal_response - Null header name\n"); return JK_FALSE; } } d->header_values[i] = (char *)jk_b_get_string(msg); if(!d->header_values[i]) { jk_log(l, JK_LOG_ERROR, "Error ajp13_unmarshal_response - Null header value\n"); return JK_FALSE; } jk_log(l, JK_LOG_DEBUG, "ajp13_unmarshal_response: Header[%d] [%s] = [%s]\n", i, d->header_names[i], d->header_values[i]); } } } return JK_TRUE; } int ajp13_marshal_shutdown_into_msgb(jk_msg_buf_t *msg, jk_pool_t *p, jk_logger_t *l) { jk_log(l, JK_LOG_DEBUG, "Into ajp13_marshal_shutdown_into_msgb\n"); /* To be on the safe side */ jk_b_reset(msg); /* * Just a single byte with s/d command. */ if(0 != jk_b_append_byte(msg, JK_AJP13_SHUTDOWN)) { return JK_FALSE; } return JK_TRUE; } 1.1 jakarta-tomcat/proposals/web-connector/native/common/jk_ajp13.h Index: jk_ajp13.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 * ." * * 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 * ." * * 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 . * */ /*************************************************************************** * Description: Experimental bi-directionl protocol handler. * * Author: Gal Shachor * * Version: $Revision: 1.1 $ * ***************************************************************************/ #ifndef JK_AJP13_H #define JK_AJP13_H #include "jk_service.h" #include "jk_msg_buff.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /* * Message does not have a response (for example, JK_AJP13_END_RESPONSE) */ #define JK_AJP13_ERROR -1 /* * Message does not have a response (for example, JK_AJP13_END_RESPONSE) */ #define JK_AJP13_NO_RESPONSE 0 /* * Message have a response. */ #define JK_AJP13_HAS_RESPONSE 1 /* * Forward a request from the web server to the servlet container. */ #define JK_AJP13_FORWARD_REQUEST (unsigned char)2 /* * Write a body chunk from the servlet container to the web server */ #define JK_AJP13_SEND_BODY_CHUNK (unsigned char)3 /* * Send response headers from the servlet container to the web server. */ #define JK_AJP13_SEND_HEADERS (unsigned char)4 /* * Marks the end of response. */ #define JK_AJP13_END_RESPONSE (unsigned char)5 /* * Marks the end of response. */ #define JK_AJP13_GET_BODY_CHUNK (unsigned char)6 /* * Asks the container to shutdown */ #define JK_AJP13_SHUTDOWN (unsigned char)7 struct jk_res_data { int status; const char *msg; unsigned num_headers; char **header_names; char **header_values; }; typedef struct jk_res_data jk_res_data_t; int ajp13_marshal_into_msgb(jk_msg_buf_t *msg, jk_ws_service_t *s, jk_logger_t *l); int ajp13_unmarshal_response(jk_msg_buf_t *msg, jk_res_data_t *d, jk_pool_t *p, jk_logger_t *l); int ajp13_marshal_shutdown_into_msgb(jk_msg_buf_t *msg, jk_pool_t *p, jk_logger_t *l); #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* JK_AJP13_H */ 1.1 jakarta-tomcat/proposals/web-connector/native/common/jk_ajp13_worker.c Index: jk_ajp13_worker.c =================================================================== /* * Copyright (c) 1997-2001 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 * ." * * 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 * ." * * 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 . * */ /*************************************************************************** * Description: Bi-directional protocol. * * Author: Henri Gomez * * Author: Costin * * Author: Gal Shachor * * Version: $Revision: 1.1 $ * ***************************************************************************/ #include "jk_pool.h" #include "jk_connect.h" #include "jk_util.h" #include "jk_msg_buff.h" #include "jk_ajp13.h" #include "jk_mt.h" #define AJP_DEF_HOST ("localhost") #define AJP_DEF_PORT (8008) #define READ_BUF_SIZE (8*1024) #define DEF_RETRY_ATTEMPTS (1) #define DEF_CACHE_SZ (1) #define JK_INTERNAL_ERROR (-2) #define MAX_SEND_BODY_SZ (DEF_BUFFER_SZ - 6) #define AJP13_HEADER_LEN (4) #define AJP13_HEADER_SZ_LEN (2) struct ajp13_operation; typedef struct ajp13_operation ajp13_operation_t; struct ajp13_endpoint; typedef struct ajp13_endpoint ajp13_endpoint_t; struct ajp13_worker { struct sockaddr_in worker_inet_addr; /* Contains host and port */ unsigned connect_retry_attempts; char *name; /* * Open connections cache... * * 1. Critical section object to protect the cache. * 2. Cache size. * 3. An array of "open" endpoints. */ JK_CRIT_SEC cs; unsigned ep_cache_sz; ajp13_endpoint_t **ep_cache; jk_worker_t worker; }; typedef struct ajp13_worker ajp13_worker_t; struct ajp13_endpoint { ajp13_worker_t *worker; jk_pool_t pool; jk_pool_atom_t buf[BIG_POOL_SIZE]; int sd; int reuse; jk_endpoint_t endpoint; unsigned left_bytes_to_send; }; /* * little struct to avoid multiples ptr passing * this struct is ready to hold upload file fd * to add upload persistant storage */ struct ajp13_operation { jk_msg_buf_t *request; /* original request storage */ jk_msg_buf_t *reply; /* reply storage (chuncked by ajp13 */ int uploadfd; /* future persistant storage id */ int recoverable; /* if exchange could be conducted on another TC */ }; static void reset_endpoint(ajp13_endpoint_t *ep) { ep->reuse = JK_FALSE; jk_reset_pool(&(ep->pool)); } static void close_endpoint(ajp13_endpoint_t *ep) { reset_endpoint(ep); if(ep->sd > 0) { jk_close_socket(ep->sd); } free(ep); } static void reuse_connection(ajp13_endpoint_t *ep, jk_logger_t *l) { ajp13_worker_t *w = ep->worker; if(w->ep_cache_sz) { int rc; JK_ENTER_CS(&w->cs, rc); if(rc) { unsigned i; for(i = 0 ; i < w->ep_cache_sz ; i++) { if(w->ep_cache[i]) { ep->sd = w->ep_cache[i]->sd; w->ep_cache[i]->sd = -1; close_endpoint(w->ep_cache[i]); w->ep_cache[i] = NULL; break; } } JK_LEAVE_CS(&w->cs, rc); } } } static void connect_to_tomcat(ajp13_endpoint_t *ep, jk_logger_t *l) { unsigned attempt; for(attempt = 0 ; attempt < ep->worker->connect_retry_attempts ; attempt++) { ep->sd = jk_open_socket(&ep->worker->worker_inet_addr, JK_TRUE, l); if(ep->sd >= 0) { jk_log(l, JK_LOG_DEBUG, "In jk_endpoint_t::connect_to_tomcat, connected sd = %d\n", ep->sd); return; } } jk_log(l, JK_LOG_ERROR, "In jk_endpoint_t::connect_to_tomcat, failed errno = %d\n", errno); } static int connection_tcp_send_message(ajp13_endpoint_t *ep, jk_msg_buf_t *msg, jk_logger_t *l ) { jk_b_end(msg); jk_dump_buff(l, JK_LOG_DEBUG, "sending to ajp13", msg); if(0 > jk_tcp_socket_sendfull(ep->sd, jk_b_get_buff(msg), jk_b_get_len(msg))) { return JK_FALSE; } return JK_TRUE; } static int connection_tcp_get_message(ajp13_endpoint_t *ep, jk_msg_buf_t *msg, jk_logger_t *l) { unsigned char head[AJP13_HEADER_LEN]; int rc; int msglen; rc = jk_tcp_socket_recvfull(ep->sd, head, AJP13_HEADER_LEN); if(rc < 0) { jk_log(l, JK_LOG_ERROR, "connection_tcp_get_message: Error - jk_tcp_socket_recvfull failed\n"); return JK_FALSE; } if((head[0] != 'A') || (head[1] != 'B' )) { jk_log(l, JK_LOG_ERROR, "connection_tcp_get_message: Error - Wrong message format\n"); return JK_FALSE; } msglen = ((head[2]&0xff)<<8); msglen += (head[3] & 0xFF); if(msglen > jk_b_get_size(msg)) { jk_log(l, JK_LOG_ERROR, "connection_tcp_get_message: Error - Wrong message size\n"); return JK_FALSE; } jk_b_set_len(msg, msglen); jk_b_set_pos(msg, 0); rc = jk_tcp_socket_recvfull(ep->sd, jk_b_get_buff(msg), msglen); if(rc < 0) { jk_log(l, JK_LOG_ERROR, "connection_tcp_get_message: Error - jk_tcp_socket_recvfull failed\n"); return JK_FALSE; } jk_dump_buff(l, JK_LOG_DEBUG, "received from ajp13", msg); return JK_TRUE; } static int read_fully_from_server(jk_ws_service_t *s, unsigned char *buf, unsigned len) { unsigned rdlen = 0; while(rdlen < len) { unsigned this_time = 0; if(!s->read(s, buf + rdlen, len - rdlen, &this_time)) { return -1; } if(0 == this_time) { break; } rdlen += this_time; } return (int)rdlen; } 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); 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) { jk_log(l, JK_LOG_ERROR, "read_into_msg_buff: Error - read_fully_from_server failed\n"); return JK_FALSE; } 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; } jk_b_set_len(msg, jk_b_get_len(msg) + len); return JK_TRUE; } static int ajp13_process_callback(jk_msg_buf_t *msg, ajp13_endpoint_t *ep, jk_ws_service_t *r, jk_logger_t *l) { int code = (int)jk_b_get_byte(msg); switch(code) { case JK_AJP13_SEND_HEADERS: { jk_res_data_t res; if(!ajp13_unmarshal_response(msg, &res, &ep->pool, l)) { jk_log(l, JK_LOG_ERROR, "Error ajp13_process_callback - ajp13_unmarshal_response failed\n"); return JK_AJP13_ERROR; } if(!r->start_response(r, res.status, res.msg, (const char * const *)res.header_names, (const char * const *)res.header_values, res.num_headers)) { jk_log(l, JK_LOG_ERROR, "Error ajp13_process_callback - start_response failed\n"); return JK_INTERNAL_ERROR; } } break; case JK_AJP13_SEND_BODY_CHUNK: { unsigned len = (unsigned)jk_b_get_int(msg); if(!r->write(r, jk_b_get_buff(msg) + jk_b_get_pos(msg), len)) { jk_log(l, JK_LOG_ERROR, "Error ajp13_process_callback - write failed\n"); return JK_INTERNAL_ERROR; } } break; case JK_AJP13_GET_BODY_CHUNK: { unsigned len = (unsigned)jk_b_get_int(msg); if(len > MAX_SEND_BODY_SZ) { len = MAX_SEND_BODY_SZ; } if(len > ep->left_bytes_to_send) { len = ep->left_bytes_to_send; } if(len < 0) { len = 0; } /* the right place to add file storage for upload */ if(read_into_msg_buff(ep, r, msg, l, len)) { r->content_read += len; return JK_AJP13_HAS_RESPONSE; } jk_log(l, JK_LOG_ERROR, "Error ajp13_process_callback - read_into_msg_buff failed\n"); return JK_INTERNAL_ERROR; } break; case JK_AJP13_END_RESPONSE: { ep->reuse = (int)jk_b_get_byte(msg); if((ep->reuse & 0X01) != ep->reuse) { /* * Strange protocol error. */ ep->reuse = JK_FALSE; } } return JK_AJP13_END_RESPONSE; break; default: jk_log(l, JK_LOG_ERROR, "Error ajp13_process_callback - Invalid code: %d\n", code); return JK_AJP13_ERROR; } return JK_AJP13_NO_RESPONSE; } /* -------------------- Method -------------------- */ 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) { ajp13_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 *l) { /* * start the connection cache */ jk_log(l, JK_LOG_DEBUG, "Into jk_worker_t::init\n"); if(pThis && pThis->worker_private) { ajp13_worker_t *p = pThis->worker_private; int cache_sz = jk_get_worker_cache_size(props, p->name, DEF_CACHE_SZ); if(cache_sz > 0) { p->ep_cache = (ajp13_endpoint_t **)malloc(sizeof(ajp13_endpoint_t *) * cache_sz); if(p->ep_cache) { int i; p->ep_cache_sz = cache_sz; for(i = 0 ; i < cache_sz ; i++) { p->ep_cache[i] = NULL; } JK_INIT_CS(&(p->cs), i); if(i) { return JK_TRUE; } } } } else { jk_log(l, JK_LOG_ERROR, "In jk_worker_t::init, 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) { ajp13_worker_t *private_data = (*pThis)->worker_private; free(private_data->name); if(private_data->ep_cache_sz) { unsigned i; for(i = 0 ; i < private_data->ep_cache_sz ; i++) { if(private_data->ep_cache[i]) { reset_endpoint(private_data->ep_cache[i]); close_endpoint(private_data->ep_cache[i]); } } free(private_data->ep_cache); JK_DELETE_CS(&(private_data->cs), i); } free(private_data); return JK_TRUE; } jk_log(l, JK_LOG_ERROR, "In jk_worker_t::destroy, 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) { ajp13_endpoint_t *p = (*e)->endpoint_private; int reuse_ep = p->reuse; reset_endpoint(p); if(reuse_ep) { ajp13_worker_t *w = p->worker; if(w->ep_cache_sz) { int rc; JK_ENTER_CS(&w->cs, rc); if(rc) { unsigned i; for(i = 0 ; i < w->ep_cache_sz ; i++) { if(!w->ep_cache[i]) { w->ep_cache[i] = p; break; } } JK_LEAVE_CS(&w->cs, rc); if(i < w->ep_cache_sz) { return JK_TRUE; } } } } close_endpoint(p); *e = NULL; return JK_TRUE; } jk_log(l, JK_LOG_ERROR, "In jk_endpoint_t::done, NULL parameters\n"); return JK_FALSE; } /* * send request to Tomcat via Ajp13 * - first try to find reuseable socket * - if no one available, try to connect * - send request, but send must be see as asynchronous, * since send() call will return noerror about 95% of time * Hopefully we'll get more information on next read. * * nb: reqmsg is the original request msg buffer * repmsg is the reply msg buffer which could be scratched */ static int send_request(jk_endpoint_t *e, jk_ws_service_t *s, jk_logger_t *l, ajp13_endpoint_t *p, ajp13_operation_t *op) { /* Up to now, we can recover */ op->recoverable = JK_TRUE; /* * First try to reuse open connections... */ while((p->sd > 0) && !connection_tcp_send_message(p, op->request, l)) { jk_log(l, JK_LOG_ERROR, "Error sending request try another pooled connection\n"); jk_close_socket(p->sd); p->sd = -1; reuse_connection(p, l); } /* * If we failed to reuse a connection, try to reconnect. */ if(p->sd < 0) { connect_to_tomcat(p, l); if(p->sd >= 0) { /* * After we are connected, each error that we are going to * have is probably unrecoverable */ if(!connection_tcp_send_message(p, op->request, l)) { jk_log(l, JK_LOG_ERROR, "Error sending request on a fresh connection\n"); return JK_FALSE; } } else { jk_log(l, JK_LOG_ERROR, "Error connecting to the Tomcat process.\n"); return JK_FALSE; } } /* * From now on an error means that we have an internal server error * or Tomcat crashed. In any case we cannot recover this. */ jk_log(l, JK_LOG_DEBUG, "send_request 2: request body to send %d - request body to resend %d\n", p->left_bytes_to_send, jk_b_get_len(op->reply) - AJP13_HEADER_LEN); /* * POST recovery job is done here. * It's not very fine to have posted data in reply but that's the only easy * way to do that for now. Sharing the reply is really a bad solution but * it will works for POST DATA less than 8k. * We send here the first part of data which was sent previously to the * remote Tomcat */ if(jk_b_get_len(op->reply) > AJP13_HEADER_LEN) { if(!connection_tcp_send_message(p, op->reply, l)) { jk_log(l, JK_LOG_ERROR, "Error resending request body\n"); return JK_FALSE; } } else { /* We never sent any POST data and we check it we have to send at * least of block of data (max 8k). These data will be kept in reply * 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) { unsigned len = p->left_bytes_to_send; if(len > MAX_SEND_BODY_SZ) len = MAX_SEND_BODY_SZ; if(!read_into_msg_buff(p, s, op->reply, l, len)) { /* the browser stop sending data, no need to recover */ op->recoverable = JK_FALSE; return JK_FALSE; } s->content_read = len; if(!connection_tcp_send_message(p, op->reply, l)) { jk_log(l, JK_LOG_ERROR, "Error sending request body\n"); return JK_FALSE; } } } return (JK_TRUE); } /* * get replies from Tomcat via Ajp13 * We will know only at read time if the remote host closed * the connection (half-closed state - FIN-WAIT2). In that case * we must close our side of the socket and abort emission. * We will need another connection to send the request * There is need of refactoring here since we mix * reply reception (tomcat -> apache) and request send (apache -> tomcat) * and everything using the same buffer (repmsg) * ajp13 is async but handling read/send this way prevent nice recovery * In fact if tomcat link is broken during upload (browser -> apache -> tomcat) * we'll loose data and we'll have to abort the whole request. */ static int get_reply(jk_endpoint_t *e, jk_ws_service_t *s, jk_logger_t *l, ajp13_endpoint_t *p, ajp13_operation_t *op) { /* Start read all reply message */ while(1) { int rc = 0; if(!connection_tcp_get_message(p, op->reply, l)) { jk_log(l, JK_LOG_ERROR, "Error reading reply\n"); /* we just can't recover, unset recover flag */ return JK_FALSE; } rc = ajp13_process_callback(op->reply, p, s, l); /* no more data to be sent, fine we have finish here */ if(JK_AJP13_END_RESPONSE == rc) return JK_TRUE; else if(JK_AJP13_HAS_RESPONSE == rc) { /* * in upload-mode there is no second chance since * we may have allready send part of uploaded data * to Tomcat. * In this case if Tomcat connection is broken we must * abort request and indicate error. * A possible work-around could be to store the uploaded * data to file and replay for it */ op->recoverable = JK_FALSE; rc = connection_tcp_send_message(p, op->reply, l); if (rc < 0) { jk_log(l, JK_LOG_ERROR, "Error sending request data %d\n", rc); return JK_FALSE; } } else if(rc < 0) { return (JK_FALSE); /* XXX error */ } } } #define JK_RETRIES 3 /* * service is now splitted in send_request and get_reply * much more easier to do errors recovery */ static int JK_METHOD service(jk_endpoint_t *e, jk_ws_service_t *s, jk_logger_t *l, int *is_recoverable_error) { int i; ajp13_operation_t oper; ajp13_operation_t *op = &oper; jk_log(l, JK_LOG_DEBUG, "Into jk_endpoint_t::service\n"); if(e && e->endpoint_private && s && is_recoverable_error) { ajp13_endpoint_t *p = e->endpoint_private; op->request = jk_b_new(&(p->pool)); jk_b_set_buffer_size(op->request, DEF_BUFFER_SZ); jk_b_reset(op->request); op->reply = jk_b_new(&(p->pool)); jk_b_set_buffer_size(op->reply, DEF_BUFFER_SZ); jk_b_reset(op->reply); op->recoverable = JK_TRUE; op->uploadfd = -1; /* not yet used, later ;) */ p->left_bytes_to_send = s->content_length; p->reuse = JK_FALSE; *is_recoverable_error = JK_TRUE; /* * We get here initial request (in reqmsg) */ if(!ajp13_marshal_into_msgb(op->request, s, l)) { *is_recoverable_error = JK_FALSE; return JK_FALSE; } /* * JK_RETRIES could be replaced by the number of workers in * a load-balancing configuration */ for (i = 0; i < JK_RETRIES; i++) { /* * We're using reqmsg which hold initial request * if Tomcat is stopped or restarted, we will pass reqmsg * to next valid tomcat. */ if (send_request(e, s, l, p, op)) { /* If we have the no recoverable error, it's probably because the sender (browser) * stop sending data before the end (certainly in a big post) */ if (! op->recoverable) { *is_recoverable_error = JK_FALSE; jk_log(l, JK_LOG_ERROR, "In jk_endpoint_t::service, send_request failed without recovery in send loop %d\n", i); return JK_FALSE; } /* Up to there we can recover */ *is_recoverable_error = JK_TRUE; op->recoverable = JK_TRUE; if (get_reply(e, s, l, p, op)) return (JK_TRUE); /* if we can't get reply, check if no recover flag was set * if is_recoverable_error is cleared, we have started received * upload data and we must consider that operation is no more recoverable */ if (! op->recoverable) { *is_recoverable_error = JK_FALSE; jk_log(l, JK_LOG_ERROR, "In jk_endpoint_t::service, get_reply failed without recovery in send loop %d\n", i); return JK_FALSE; } jk_log(l, JK_LOG_ERROR, "In jk_endpoint_t::service, get_reply failed in send loop %d\n", i); } else jk_log(l, JK_LOG_ERROR, "In jk_endpoint_t::service, send_request failed in send loop %d\n", i); jk_close_socket(p->sd); p->sd = -1; reuse_connection(p, l); } } else { jk_log(l, JK_LOG_ERROR, "In jk_endpoint_t::service, NULL parameters\n"); } return JK_FALSE; } 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) { ajp13_worker_t *p = pThis->worker_private; ajp13_endpoint_t *ep = NULL; if(p->ep_cache_sz) { int rc; JK_ENTER_CS(&p->cs, rc); if(rc) { unsigned i; for(i = 0 ; i < p->ep_cache_sz ; i++) { if(p->ep_cache[i]) { ep = p->ep_cache[i]; p->ep_cache[i] = NULL; break; } } JK_LEAVE_CS(&p->cs, rc); if(ep) { *pend = &ep->endpoint; return JK_TRUE; } } } ep = (ajp13_endpoint_t *)malloc(sizeof(ajp13_endpoint_t)); if(ep) { ep->sd = -1; ep->reuse = JK_FALSE; jk_open_pool(&ep->pool, ep->buf, sizeof(ep->buf)); ep->worker = pThis->worker_private; ep->endpoint.endpoint_private = ep; ep->endpoint.service = service; ep->endpoint.done = done; *pend = &ep->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; } int JK_METHOD ajp13_worker_factory(jk_worker_t **w, const char *name, jk_logger_t *l) { ajp13_worker_t *private_data = (ajp13_worker_t *)malloc(sizeof(ajp13_worker_t)); jk_log(l, JK_LOG_DEBUG, "Into ajp13_worker_factory\n"); if(NULL == name || NULL == w) { jk_log(l, JK_LOG_ERROR, "In ajp13_worker_factory, NULL parameters\n"); return JK_FALSE; } if(!private_data) { jk_log(l, JK_LOG_ERROR, "In ajp13_worker_factory, NULL parameters\n"); return JK_FALSE; } private_data->name = strdup(name); if(!private_data->name) { free(private_data); jk_log(l, JK_LOG_ERROR, "In ajp13_worker_factory, malloc failed\n"); return JK_FALSE; } private_data->ep_cache_sz = 0; private_data->ep_cache = NULL; 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; } 1.1 jakarta-tomcat/proposals/web-connector/native/common/jk_ajp13_worker.h Index: jk_ajp13_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 * ." * * 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 * ." * * 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 . * */ /*************************************************************************** * Description: ajpv1.3 worker header file * * Author: Gal Shachor * * Version: $Revision: 1.1 $ * ***************************************************************************/ #ifndef JK_AJP13_WORKER_H #define JK_AJP13_WORKER_H #include "jk_logger.h" #include "jk_service.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ #define JK_AJP13_WORKER_NAME ("ajp13") int JK_METHOD ajp13_worker_factory(jk_worker_t **w, const char *name, jk_logger_t *l); #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* JK_AJP13_WORKER_H */