costin 01/12/12 13:23:57 Modified: jk/native2/include jk_msg.h Added: jk/native2/common jk_msg_ajp.c Removed: jk/native2/common jk_msg_buff.c jk_msg_buff.h Log: Better abstraction for message serializing/deserializing, protecting the internal data ( the buf is no longer used/useable outside ). This is supposed to allow other encodings/protocols to be added with minimal effort and without changes in mod_jk. In addition, this is supposed to work with JNI as well - each 'appendFoo' can be translated to converting to java and saving it in a jobject[], with send() implemented as a jni call. It also cleans up a lot of code that used 'dirty' tricks. Revision Changes Path 1.2 +75 -24 jakarta-tomcat-connectors/jk/native2/include/jk_msg.h Index: jk_msg.h =================================================================== RCS file: /home/cvs/jakarta-tomcat-connectors/jk/native2/include/jk_msg.h,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- jk_msg.h 2001/12/01 22:30:57 1.1 +++ jk_msg.h 2001/12/12 21:23:57 1.2 @@ -61,14 +61,25 @@ #include "jk_global.h" #include "jk_logger.h" #include "jk_pool.h" -#include "jk_msg_buff.h" +#include "jk_endpoint.h" +#include "jk_service.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ +struct jk_msg; +typedef struct jk_msg jk_msg_t; + +struct jk_endpoint; +struct jk_ws_service; +struct jk_logger; + +#define DEF_BUFFER_SZ (8 * 1024) +#define AJP13_MAX_SEND_BODY_SZ (DEF_BUFFER_SZ - 6) + /** - * Abstract interface to jk marshalling. Different encodings and + * Abstract interface to marshalling. Different encodings and * communication mechanisms can be supported. * * This object is recyclable, but is not thread safe - it can @@ -94,14 +105,6 @@ */ int id; - /** List of properties. The handler can be configured. - * ( password for login, etc ). - */ - /* - char **supportedProperties; - jk_map_t *properties; - */ - /* * Prepare the buffer for a new invocation */ @@ -116,37 +119,85 @@ * Dump the buffer header * @param err Message text */ - void (*dump)(struct jk_msg *_this, char *err); + void (*dump)(struct jk_msg *_this, struct jk_logger *log, char *err); - void (*appendByte)(struct jk_msg *_this, unsigned char val); + int (*appendByte)(struct jk_msg *_this, unsigned char val); - void (*appendBytes)(struct jk_msg *_this, - const unsigned char * param, - const int len); + int (*appendBytes)(struct jk_msg *_this, + const unsigned char * param, + const int len); - void (*appendInt)(struct jk_msg *_this, - const unsigned short val); + int (*appendInt)(struct jk_msg *_this, + const unsigned short val); - void (*appendLong)(struct jk_msg *_this, + int (*appendLong)(struct jk_msg *_this, const unsigned long val); - void (*appendString)(struct jk_msg *_this, + int (*appendString)(struct jk_msg *_this, const char *param); unsigned char (*getByte)(struct jk_msg *_this); unsigned short (*getInt)(struct jk_msg *_this); + /** Look at the next int, without reading it + */ + unsigned short (*peekInt)(struct jk_msg *_this); + unsigned long (*getLong)(struct jk_msg *_this); + + /** Return a string. + The buffer is internal to the message, you must save + or make sure the message lives long enough. + */ + unsigned char *(*getString)(struct jk_msg *_this); + + /** Return a byte[] and it's length. + The buffer is internal to the message, you must save + or make sure the message lives long enough. + */ + unsigned char *(*getBytes)(struct jk_msg *_this, int *len); + + + /* + * Receive a message from endpoint + */ + int (*receive)(jk_msg_t *_this, struct jk_endpoint *ae ); + + /* + * Send a message to endpoint + */ + int (*send)(jk_msg_t *_this, struct jk_endpoint *ae ); - char * (*getString)(struct jk_msg *_this); - + /** + * Special method. Will read data from the server and add them as + * bytes. It is equivalent with jk_requtil_readFully() in a buffer + * and then jk_msg_appendBytes(), except that we use directly the + * internal buffer. + * + * Returns -1 on error, else number of bytes read + */ + int (*appendFromServer)(struct jk_msg *_this, + struct jk_ws_service *r, + struct jk_endpoint *ae, + int len ); + + void *_privatePtr; - void (*getBytes)(struct jk_msg *_this, char *buf, int len); - + /* Temporary, don't use */ + struct jk_pool *pool; + struct jk_logger *l; - void *_privatePtr; + unsigned char *buf; + int pos; + int len; + int maxlen; + }; + +/* Temp */ +jk_msg_t *jk_msg_ajp_create(struct jk_pool *p, + struct jk_logger *l, int buffSize); #ifdef __cplusplus } 1.1 jakarta-tomcat-connectors/jk/native2/common/jk_msg_ajp.c Index: jk_msg_ajp.c =================================================================== /* ========================================================================= * * * * The Apache Software License, Version 1.1 * * * * Copyright (c) 1999-2001 The Apache Software Foundation. * * All rights reserved. * * * * ========================================================================= * * * * Redistribution and use in source and binary forms, with or without modi- * * fication, are permitted provided that the following conditions are met: * * * * 1. Redistributions of source code must retain the above copyright notice * * 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. The end-user documentation included with the redistribution, if any, * * must include the following acknowlegement: * * * * "This product includes software developed by the Apache Software * * Foundation <http://www.apache.org/>." * * * * Alternately, this acknowlegement may appear in the software itself, if * * and wherever such third-party acknowlegements normally appear. * * * * 4. The names "The Jakarta Project", "Jk", and "Apache Software * * Foundation" must not be used to endorse or promote products derived * * from this software without prior written permission. For written * * permission, please contact <[EMAIL PROTECTED]>. * * * * 5. Products derived from this software may not be called "Apache" nor may * * "Apache" appear in their names without prior written permission of the * * Apache Software Foundation. * * * * THIS SOFTWARE IS PROVIDED "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 APACHE SOFTWARE FOUNDATION 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 indivi- * * duals on behalf of the Apache Software Foundation. For more information * * on the Apache Software Foundation, please see <http://www.apache.org/>. * * * * ========================================================================= */ /*************************************************************************** * Description: Data marshaling. XDR like * * Author: Costin Manolache * Author: Gal Shachor <[EMAIL PROTECTED]> * * Author: Henri Gomez <[EMAIL PROTECTED]> * * Version: $Revision: 1.1 $ * ***************************************************************************/ #include "jk_pool.h" #include "jk_msg.h" #include "jk_logger.h" #include "jk_endpoint.h" #include "jk_channel.h" #include "jk_requtil.h" #define AJP13_WS_HEADER 0x1234 #define AJP_HEADER_LEN (4) #define AJP_HEADER_SZ_LEN (2) /* * Simple marshaling code. */ static void jk_msg_ajp_dump(struct jk_msg *_this, struct jk_logger *log, char *err) { int i=0; log->jkLog( log, JK_LOG_INFO, "%s pos=%d len=%d max=%d " "%x %x %x %x - %x %x %x %x -" "%x %x %x %x - %x %x %x %x\n", err, _this->pos, _this->len, _this->maxlen, _this->buf[i++],_this->buf[i++],_this->buf[i++],_this->buf[i++], _this->buf[i++],_this->buf[i++],_this->buf[i++],_this->buf[i++], _this->buf[i++],_this->buf[i++],_this->buf[i++],_this->buf[i++], _this->buf[i++],_this->buf[i++],_this->buf[i++],_this->buf[i++]); i = _this->pos - 4; if(i < 0) { i=0; } log->jkLog( log, JK_LOG_INFO, " %x %x %x %x - %x %x %x %x --- %x %x %x %x - %x %x %x %x\n", _this->buf[i++],_this->buf[i++],_this->buf[i++],_this->buf[i++], _this->buf[i++],_this->buf[i++],_this->buf[i++],_this->buf[i++], _this->buf[i++],_this->buf[i++],_this->buf[i++],_this->buf[i++], _this->buf[i++],_this->buf[i++],_this->buf[i++],_this->buf[i++]); } static void jk_msg_ajp_reset(jk_msg_t *_this) { _this->len = 4; _this->pos = 4; } static void jk_msg_ajp_end(jk_msg_t *msg) { unsigned short len=msg->len - 4; msg->buf[0]=0x12; msg->buf[1]=0x34; msg->buf[2]=(unsigned char)((len >> 8) & 0xFF); msg->buf[3]=(unsigned char)(len & 0xFF); } static int jk_msg_ajp_appendLong(jk_msg_t *msg, unsigned long val) { int len=msg->len; if(len + 4 > msg->maxlen) { return -1; } msg->buf[len] = (unsigned char)((val >> 24) & 0xFF); msg->buf[len + 1] = (unsigned char)((val >> 16) & 0xFF); msg->buf[len + 2] = (unsigned char)((val >> 8) & 0xFF); msg->buf[len + 3] = (unsigned char)(val & 0xFF); msg->len += 4; return 0; } static int jk_msg_ajp_appendInt(jk_msg_t *msg, unsigned short val) { int len=msg->len; if(len + 2 > msg->maxlen) { return -1; } msg->buf[len] = (unsigned char)((val >> 8) & 0xFF); msg->buf[len + 1] = (unsigned char)(val & 0xFF); msg->len += 2; return 0; } static int jk_msg_ajp_appendByte(jk_msg_t *msg, unsigned char val) { int len=msg->len; if(len + 1 > msg->maxlen) { return -1; } msg->buf[len]= val; msg->len += 1; return 0; } static int jk_msg_ajp_appendString(jk_msg_t *msg, const char *param) { int len; if(!param) { msg->appendInt( msg, 0xFFFF ); return 0; } len = strlen(param); if(msg->len + len + 2 > msg->maxlen) { return -1; } /* ignore error - we checked once */ msg->appendInt(msg, (unsigned short )len); /* We checked for space !! */ strncpy((char *)msg->buf + msg->len , param, len+1); /* including \0 */ jk_xlate_to_ascii((char *)msg->buf + msg->len, len+1); /* convert from EBCDIC if needed */ msg->len += len + 1; return 0; } static int jk_msg_ajp_appendBytes(jk_msg_t *msg, const unsigned char *param, int len) { if (! len) { return 0; } if (msg->len + len > msg->maxlen) { return -1; } /* We checked for space !! */ memcpy((char *)msg->buf + msg->len, param, len); msg->len += len; return 0; } static unsigned long jk_msg_ajp_getLong(jk_msg_t *msg) { unsigned long i; if(msg->pos + 3 > msg->len) { msg->l->jkLog( msg->l, JK_LOG_ERROR, "Error: try to get data past end of the buffer\n"); return -1; } i = ((msg->buf[(msg->pos++)] & 0xFF)<<24); i |= ((msg->buf[(msg->pos++)] & 0xFF)<<16); i |= ((msg->buf[(msg->pos++)] & 0xFF)<<8); i |= ((msg->buf[(msg->pos++)] & 0xFF)); return i; } static unsigned short jk_msg_ajp_getInt(jk_msg_t *msg) { int i; if(msg->pos + 1 > msg->len) { msg->l->jkLog( msg->l, JK_LOG_ERROR, "Error: try to get data past end of the buffer\n"); return -1; } i = ((msg->buf[(msg->pos++)] & 0xFF)<<8); i += ((msg->buf[(msg->pos++)] & 0xFF)); return i; } static unsigned short jk_msg_ajp_peekInt(jk_msg_t *msg) { int i; if(msg->pos + 1 > msg->len) { msg->l->jkLog( msg->l, JK_LOG_ERROR, "Error: try to get data past end of the buffer\n"); return -1; } i = ((msg->buf[(msg->pos)] & 0xFF)<<8); i += ((msg->buf[(msg->pos+1)] & 0xFF)); return i; } static unsigned char jk_msg_ajp_getByte(jk_msg_t *msg) { unsigned char rc; if(msg->pos > msg->len) { msg->l->jkLog( msg->l, JK_LOG_ERROR, "Error: try to get data past end of the buffer\n"); return -1; } rc = msg->buf[msg->pos++]; return rc; } static unsigned char *jk_msg_ajp_getString(jk_msg_t *msg) { int size = jk_msg_ajp_getInt(msg); int start = msg->pos; if((size < 0 ) || (size + start > msg->maxlen)) { msg->l->jkLog( msg->l, JK_LOG_ERROR, "Error: try to get data past end of the buffer\n"); return (unsigned char *)"ERROR"; /* XXX */ } msg->pos += size; msg->pos++; /* terminating NULL */ return (unsigned char *)(msg->buf + start); } static unsigned char *jk_msg_ajp_getBytes(jk_msg_t *msg, int *lenP) { int size = jk_msg_ajp_getInt(msg); int start = msg->pos; *lenP=size; if((size < 0 ) || (size + start > msg->maxlen)) { msg->l->jkLog( msg->l, JK_LOG_ERROR, "Error: try to get data past end of the buffer\n"); return (unsigned char *)"ERROR"; /* XXX */ } msg->pos += size; msg->pos++; /* terminating NULL */ return (unsigned char *)(msg->buf + start); } /** Shame-less copy from somewhere. assert (src != dst) */ static void swap_16(unsigned char *src, unsigned char *dst) { *dst++ = *(src + 1 ); *dst= *src; } /* * Send a message to endpoint, using corresponding PROTO HEADER */ static int jk_msg_ajp_send(jk_msg_t *msg, jk_endpoint_t *ae ) { int err; jk_channel_t *channel=ae->worker->channel; jk_msg_ajp_end(msg); /* jk_msg_ajp_dump(l, JK_LOG_DEBUG, "sending to ajp13", msg); */ err=channel->send( channel, ae, msg->buf, msg->len ); if( err!=JK_TRUE ) { return err; } return JK_TRUE; } /* * Receive a message from endpoint */ static int jk_msg_ajp_receive(jk_msg_t *msg, jk_endpoint_t *ae ) { unsigned char head[4]; int rc; int msglen; jk_channel_t *channel=ae->worker->channel; jk_logger_t *l=msg->l; rc=channel->recv( channel, ae, head, 4 ); if(rc < 0) { l->jkLog(l, JK_LOG_ERROR, "msgAjp.receive(): Read head failed %d %d\n", rc, errno); return JK_FALSE; } if( head[0] != 0x41 || head[1] != 0x42 ) { l->jkLog(l, JK_LOG_ERROR, "msgAjp.receive(): Bad signature %x%x\n", head[0], head[1]); return JK_FALSE; } msglen = ((head[2]&0xff)<<8); msglen += (head[3] & 0xFF); if(msglen > msg->maxlen ) { l->jkLog(l, JK_LOG_ERROR, "msgAjp.receive(): Incoming message is too big %d\n", msglen); return JK_FALSE; } msg->len=msglen; msg->pos=0; rc=channel->recv( channel, ae, msg->buf, msglen); if(rc < 0) { l->jkLog(l, JK_LOG_ERROR, "msgAjp.receive(): Error receiving message body %d %d\n", rc, errno); return JK_FALSE; } l->jkLog(l, JK_LOG_INFO, "msgAjp.receive(): Received len=%d type=%d\n", msglen, (int)msg->buf[0]); return JK_TRUE; } /** * Special method. Will read data from the server and add them as * bytes. It is equivalent with jk_requtil_readFully() in a buffer * and then jk_msg_appendBytes(), except that we use directly the * internal buffer. * * Returns -1 on error, else number of bytes read */ static int jk_msg_ajp_appendFromServer(jk_msg_t *msg, jk_ws_service_t *r, jk_endpoint_t *ae, int len ) { unsigned char *read_buf = msg->buf; jk_logger_t *l=msg->l; jk_msg_ajp_reset(msg); read_buf += AJP_HEADER_LEN; /* leave some space for the buffer headers */ read_buf += AJP_HEADER_SZ_LEN; /* leave some space for the read length */ /* Pick the max size since we don't know the content_length */ if (r->is_chunked && len == 0) { len = AJP13_MAX_SEND_BODY_SZ; } if ((len = jk_requtil_readFully(r, read_buf, len)) < 0) { l->jkLog(l, JK_LOG_ERROR, "msgAjp.appendFromServer() error reading from server\n"); return -1; } if (!r->is_chunked) { r->left_bytes_to_send -= len; } if (len > 0) { /* Recipient recognizes empty packet as end of stream, not an empty body packet */ if(0 != jk_msg_ajp_appendInt(msg, (unsigned short)len)) { l->jkLog(l, JK_LOG_ERROR, "read_into_msg_buff: Error - jk_b_append_int failed\n"); return -1; } } msg->len= msg->len + len; return len; } jk_msg_t *jk_msg_ajp_create(jk_pool_t *p, jk_logger_t *log, int buffSize) { jk_msg_t *msg = (jk_msg_t *)p->calloc(p, sizeof(jk_msg_t)); if( buffSize==0 ) buffSize=DEF_BUFFER_SZ; if(!msg) { return NULL; } msg->pool = p; msg->buf= (unsigned char *)msg->pool->alloc(msg->pool, buffSize); if(msg->buf==NULL) { return NULL; } msg->l=log; msg->maxlen=buffSize; msg->len=0; msg->reset=jk_msg_ajp_reset; msg->end=jk_msg_ajp_end; msg->dump=jk_msg_ajp_dump; msg->appendByte=jk_msg_ajp_appendByte; msg->appendBytes=jk_msg_ajp_appendBytes; msg->appendInt=jk_msg_ajp_appendInt; msg->appendLong=jk_msg_ajp_appendLong; msg->appendString=jk_msg_ajp_appendString; msg->appendFromServer=jk_msg_ajp_appendFromServer; msg->getByte=jk_msg_ajp_getByte; msg->getInt=jk_msg_ajp_getInt; msg->peekInt=jk_msg_ajp_peekInt; msg->getLong=jk_msg_ajp_getLong; msg->getString=jk_msg_ajp_getString; msg->getBytes=jk_msg_ajp_getBytes; msg->send=jk_msg_ajp_send; msg->receive=jk_msg_ajp_receive; return msg; }
-- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>