You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by co...@apache.org on 2002/01/26 08:05:19 UTC
cvs commit: jakarta-tomcat-connectors/jk/native2/common jk_channel_apr_socket.c jk_channel_socket.c
costin 02/01/25 23:05:19
Modified: jk/native2/common jk_channel_socket.c
Added: jk/native2/common jk_channel_apr_socket.c
Log:
Update the channels.
I moved the apr_socket in the same dir - apr is not a special case, it'll be the
default. If jni is here, apr should be too - I would rather move the 'old'
socket in a special dir ( or just remove it later ).
Revision Changes Path
1.12 +58 -6 jakarta-tomcat-connectors/jk/native2/common/jk_channel_socket.c
Index: jk_channel_socket.c
===================================================================
RCS file: /home/cvs/jakarta-tomcat-connectors/jk/native2/common/jk_channel_socket.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- jk_channel_socket.c 17 Dec 2001 07:17:08 -0000 1.11
+++ jk_channel_socket.c 26 Jan 2002 07:05:19 -0000 1.12
@@ -165,7 +165,7 @@
host = jk_map_getStrProp( env, props,
"worker", worker_name, "host", host);
tmp = jk_map_getStrProp( env, props,
- "worker", worker_name, "port", NULL );
+ "worker", worker_name, "port", "8007" );
if( tmp != NULL )
port=jk_map_str2int( env, tmp);
@@ -344,14 +344,20 @@
*/
static int JK_METHOD jk_channel_socket_send(jk_env_t *env, jk_channel_t *_this,
jk_endpoint_t *endpoint,
- char *b, int len)
+ jk_msg_t *msg)
{
+ char *b;
+ int len;
int sd;
int sent=0;
-
jk_channel_socket_data_t *chD=endpoint->channelData;
+
if( chD==NULL )
return JK_FALSE;
+
+ msg->end( env, msg );
+ len=msg->len;
+ b=msg->buf;
sd=chD->sock;
while(sent < len) {
@@ -378,9 +384,10 @@
* >0: length of the received data.
* Was: tcp_socket_recvfull
*/
-static int JK_METHOD jk_channel_socket_recv( jk_env_t *env, jk_channel_t *_this,
- jk_endpoint_t *endpoint,
- char *b, int len )
+static int JK_METHOD jk_channel_socket_readN( jk_env_t *env,
+ jk_channel_t *_this,
+ jk_endpoint_t *endpoint,
+ char *b, int len )
{
jk_channel_socket_data_t *chD=endpoint->channelData;
int sd;
@@ -417,6 +424,49 @@
}
+/** receive len bytes.
+ * @param sd opened socket.
+ * @param b buffer to store the data.
+ * @param len length to receive.
+ * @return -1: receive failed or connection closed.
+ * >0: length of the received data.
+ * Was: tcp_socket_recvfull
+ */
+static int JK_METHOD jk_channel_socket_recv( jk_env_t *env, jk_channel_t *_this,
+ jk_endpoint_t *endpoint,
+ jk_msg_t *msg )
+{
+ int hlen=msg->headerLength;
+ int blen;
+ int rc;
+
+
+ jk_channel_socket_readN( env, _this, endpoint, msg->buf, hlen );
+
+ blen=msg->checkHeader( env, msg, endpoint );
+ if( blen < 0 ) {
+ env->l->jkLog(env, env->l, JK_LOG_ERROR,
+ "channelSocket.receive(): Bad header\n" );
+ return JK_FALSE;
+ }
+
+ rc= jk_channel_socket_readN( env, _this, endpoint, msg->buf + hlen, blen);
+
+ if(rc < 0) {
+ env->l->jkLog(env, env->l, JK_LOG_ERROR,
+ "channelSocket.receive(): Error receiving message body %d %d\n",
+ rc, errno);
+ return JK_FALSE;
+ }
+
+ env->l->jkLog(env, env->l, JK_LOG_INFO,
+ "channelSocket.receive(): Received len=%d type=%d\n",
+ blen, (int)msg->buf[hlen]);
+ return JK_TRUE;
+
+}
+
+
int JK_METHOD jk_channel_socket_factory(jk_env_t *env,
jk_pool_t *pool,
@@ -452,6 +502,8 @@
_this->name="file";
+ _this->is_stream=JK_TRUE;
+
*result= _this;
return JK_TRUE;
1.1 jakarta-tomcat-connectors/jk/native2/common/jk_channel_apr_socket.c
Index: jk_channel_apr_socket.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 <ap...@apache.org>. *
* *
* 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/>. *
* *
* ========================================================================= */
/**
* Channel using 'plain' TCP sockets or UNIX sockets.
* Based on jk_sockbuf. It uses a an APR-based mechanism.
* The UNIX sockets are not yet in APR (the code has to been written).
*
* Properties:
* - host/filename
* - port
* - ndelay (Where the hell we set it?)
*
* This channel should 'live' as much as the workerenv. It is stateless.
* It allocates memory for endpoint private data ( using endpoint's pool ).
*
* @author: Gal Shachor <sh...@il.ibm.com>
* @author: Costin Manolache
* @author: Jean-Frederic Clere <jf...@fujitsu-siemens.com>
*/
#include "jk_map.h"
#include "jk_env.h"
#include "jk_channel.h"
#include "jk_global.h"
#include <string.h>
#include "jk_registry.h"
#include "apr_network_io.h"
#include "apr_errno.h"
#include "apr_general.h"
#define DEFAULT_HOST "127.0.0.1"
#define TYPE_UNIX 1 /* to be move in APR. */
#define TYPE_NET 2 /* to be move in APR. */
/** Information specific for the socket channel
*/
struct jk_channel_socket_private {
int ndelay;
apr_sockaddr_t *addr;
struct sockaddr_un unix_addr;
int type; /* AF_INET or AF_UNIX */
char *host;
short port;
};
/** Informations for each connection
*/
typedef struct jk_channel_socket_data {
int type; /* AF_INET or AF_UNIX */
apr_socket_t *sock;
int unixsock;
} jk_channel_socket_data_t;
typedef struct jk_channel_socket_private jk_channel_socket_private_t;
/*
We use the _privateInt field directly. Long term we can define our own
jk_channel_socket_t structure and use the _private field, etc - but we
just need to store an int.
XXX We could also use properties or 'notes'
*/
int JK_METHOD jk_channel_socket_factory(jk_env_t *env, jk_pool_t *pool,
void **result,
const char *type, const char *name);
static int JK_METHOD jk_channel_socket_resolve(jk_env_t *env, char *host,
short port,
jk_channel_socket_private_t *rc);
static int JK_METHOD jk_channel_socket_close(jk_env_t *env, jk_channel_t *_this,
jk_endpoint_t *endpoint);
static int JK_METHOD jk_channel_socket_getProperty(jk_env_t *env,
jk_channel_t *_this,
char *name, char **value)
{
return JK_FALSE;
}
static int JK_METHOD jk_channel_socket_setProperty(jk_env_t *env,
jk_channel_t *_this,
char *name, char *value)
{
jk_channel_socket_private_t *socketInfo=
(jk_channel_socket_private_t *)(_this->_privatePtr);
if( strcmp( "host", name ) != 0 ) {
socketInfo->host=value;
} else if( strcmp( "defaultPort", name ) != 0 ) {
} else if( strcmp( "port", name ) != 0 ) {
} else {
return JK_FALSE;
}
return JK_TRUE;
}
/** resolve the host IP ( jk_resolve ) and initialize the channel.
*/
static int JK_METHOD jk_channel_socket_init(jk_env_t *env,
jk_channel_t *_this,
jk_map_t *props,
char *worker_name,
jk_worker_t *worker )
{
int err;
jk_channel_socket_private_t *socketInfo=
(jk_channel_socket_private_t *)(_this->_privatePtr);
char *host=socketInfo->host;
short port=socketInfo->port;
jk_workerEnv_t *workerEnv=worker->workerEnv;
char *tmp;
host = jk_map_getStrProp( env, props,
"worker", worker_name, "host", host);
tmp = jk_map_getStrProp( env, props,
"worker", worker_name, "port", NULL );
if( tmp != NULL )
port=jk_map_str2int( env, tmp);
_this->worker=worker;
_this->properties=props;
if( host==NULL )
host=DEFAULT_HOST;
err=jk_channel_socket_resolve( env, host, port, socketInfo );
if( err!= JK_TRUE ) {
env->l->jkLog(env, env->l, JK_LOG_ERROR, "jk_channel_socket_init: "
"can't resolve %s:%d errno=%d\n", host, port, errno );
}
env->l->jkLog(env, env->l, JK_LOG_INFO,
"channel_socket.init(): %s:%d for %s\n", host,
port, worker->name );
return err;
}
/** private: resolve the address on init
*/
static int JK_METHOD jk_channel_socket_resolve(jk_env_t *env,
char *host, short port,
jk_channel_socket_private_t *rc)
{
/*
* If the hostname is an absolut path, we want a UNIX socket.
* otherwise it is a TCP/IP socket.
*/
env->l->jkLog(env, env->l, JK_LOG_ERROR,
"jk_channel_socket_resolve: %s %d\n",
host, port);
if (host[0]=='/') {
rc->type = TYPE_UNIX;
memset(&rc->unix_addr, 0, sizeof(struct sockaddr_un));
rc->unix_addr.sun_family = AF_UNIX;
strcpy(rc->unix_addr.sun_path, host);
} else {
rc->type = TYPE_NET;
if ( apr_sockaddr_info_get(&rc->addr, host, APR_UNSPEC, port, 0,
(apr_pool_t *)env->globalPool->_private)!=APR_SUCCESS) {
return JK_FALSE;
}
}
return JK_TRUE;
}
/** connect to Tomcat (jk_open_socket)
*/
static int JK_METHOD jk_channel_socket_open(jk_env_t *env,
jk_channel_t *_this,
jk_endpoint_t *endpoint)
{
int err;
jk_channel_socket_private_t *socketInfo=
(jk_channel_socket_private_t *)(_this->_privatePtr);
apr_sockaddr_t *remote_sa=socketInfo->addr;
int ndelay=socketInfo->ndelay;
jk_channel_socket_data_t *sd=endpoint->channelData;
apr_socket_t *sock;
apr_status_t ret;
apr_interval_time_t timeout = 2 * APR_USEC_PER_SEC;
char msg[128];
int unixsock;
/* UNIX socket (to be moved in APR) */
if (socketInfo->type==TYPE_UNIX) {
unixsock = socket(AF_UNIX, SOCK_STREAM, 0);
if (unixsock<0) {
env->l->jkLog(env, env->l, JK_LOG_ERROR,
"channelSocket.open(): can't create socket %d %s\n",
errno, strerror( errno ) );
return JK_FALSE;
}
if (connect(unixsock,(struct sockaddr *)&(socketInfo->unix_addr),
sizeof(struct sockaddr_un))<0) {
close(unixsock);
env->l->jkLog(env, env->l, JK_LOG_ERROR,
"channelSocket.connect() connect failed %d %s\n",
errno, strerror( errno ) );
return JK_FALSE;
}
/* store the channel information */
if( sd==NULL ) {
sd=(jk_channel_socket_data_t *)
endpoint->pool->calloc( env, endpoint->pool,
sizeof( jk_channel_socket_data_t ));
endpoint->channelData=sd;
}
sd->unixsock = unixsock;
sd->type = socketInfo->type;
return JK_TRUE;
}
if (apr_socket_create(&sock, remote_sa->family, SOCK_STREAM,
(apr_pool_t *)env->globalPool->_private)
!= APR_SUCCESS) {
env->l->jkLog(env, env->l, JK_LOG_ERROR,
"channelSocket.open(): can't create socket %d %s\n",
errno, strerror( errno ) );
return JK_FALSE;
}
if (apr_setsocketopt(sock, APR_SO_TIMEOUT, timeout)!= APR_SUCCESS) {
env->l->jkLog(env, env->l, JK_LOG_ERROR,
"channelSocket.open(): can't set timeout %d %s\n",
errno, strerror( errno ) );
return JK_FALSE;
}
/* Tries to connect to JServ (continues trying while error is EINTR) */
do {
env->l->jkLog(env, env->l, JK_LOG_INFO,
"channelSocket.open() connect on %d\n",sock);
ret = apr_connect(sock, remote_sa);
env->l->jkLog(env, env->l, JK_LOG_ERROR,
"jk_channel_socket_open:%d\n",ret);
} while (ret == APR_EINTR);
/* Check if we connected */
if(ret != APR_SUCCESS ) {
apr_socket_close(sock);
env->l->jkLog(env, env->l, JK_LOG_ERROR,
"channelSocket.connect() connect failed %d %s\n",
ret, apr_strerror( ret, msg, sizeof(msg) ) );
return JK_FALSE;
}
/* XXX needed?
if(ndelay) {
int set = 1;
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,(char *)&set,sizeof(set));
}
env->l->jkLog(env, env->l, JK_LOG_INFO,
"channelSocket.connect(), sock = %d\n", sock);
*/
/* store the channel information */
if( sd==NULL ) {
sd=(jk_channel_socket_data_t *)
endpoint->pool->calloc( env, endpoint->pool,
sizeof( jk_channel_socket_data_t ));
endpoint->channelData=sd;
}
sd->sock = sock;
sd->type = socketInfo->type; /* APR should handle it. */
return JK_TRUE;
}
/** close the socket ( was: jk_close_socket )
*/
static int JK_METHOD jk_channel_socket_close(jk_env_t *env,jk_channel_t *_this,
jk_endpoint_t *endpoint)
{
apr_socket_t *sd;
jk_channel_socket_data_t *chD=endpoint->channelData;
if( chD==NULL )
return JK_FALSE;
if (chD->type==TYPE_UNIX) {
close( chD->unixsock );
return 0;
}
sd=chD->sock;
chD->sock=NULL; /* XXX check it. */
/* nothing else to clean, the socket_data was allocated ouf of
* endpoint's pool
*/
if (apr_socket_close(sd)==APR_SUCCESS)
return(0);
else
return(-1);
}
/** send a long message
* @param sd opened socket.
* @param b buffer containing the data.
* @param len length to send.
* @return -2: send returned 0 ? what this that ?
* -3: send failed.
* >0: total size send.
* @bug this fails on Unixes if len is too big for the underlying
* protocol.
* @was: jk_tcp_socket_sendfull
*/
static int JK_METHOD jk_channel_socket_send(jk_env_t *env, jk_channel_t *_this,
jk_endpoint_t *endpoint,
jk_msg_t *msg)
{
char *b;
int len;
apr_socket_t *sock;
apr_status_t stat;
apr_size_t length;
char data[128];
int sent=0;
int this_time;
int unixsock;
jk_channel_socket_data_t *chD=endpoint->channelData;
if( chD==NULL )
return JK_FALSE;
msg->end( env, msg );
len=msg->len;
b=msg->buf;
sock=chD->sock;
unixsock=chD->unixsock;
env->l->jkLog(env, env->l, JK_LOG_ERROR,
"jk_channel_socket_send %d\n",chD->type);
if (chD->type==TYPE_NET) {
length = (apr_size_t) len;
stat = apr_send(sock, b, &length);
if (stat!= APR_SUCCESS) {
env->l->jkLog(env, env->l, JK_LOG_ERROR,
"jk_channel_socket_send send failed %d %s\n",
stat, apr_strerror( stat, data, sizeof(data) ) );
return -3; /* -2 is not possible... */
}
return JK_TRUE;
}
while(sent < len) {
this_time = send(unixsock, (char *)b + sent , len - sent, 0);
if(0 == this_time) {
return -2;
}
if(this_time < 0) {
return -3;
}
sent += this_time;
}
/* return sent; */
return JK_TRUE;
}
/** receive len bytes.
* @param sd opened socket.
* @param b buffer to store the data.
* @param len length to receive.
* @return -1: receive failed or connection closed.
* >0: length of the received data.
* Was: tcp_socket_recvfull
*/
static int JK_METHOD jk_channel_apr_readN( jk_env_t *env,
jk_channel_t *_this,
jk_endpoint_t *endpoint,
char *b, int len )
{
jk_channel_socket_data_t *chD=endpoint->channelData;
apr_socket_t *sock;
apr_size_t length;
apr_status_t stat;
int sd;
int rdlen;
if( chD==NULL )
return JK_FALSE;
sd=chD->unixsock;
sock=chD->sock;
rdlen = 0;
/* this should be moved in APR */
if (chD->type==TYPE_UNIX) {
while(rdlen < len) {
int this_time = recv(sd,
(char *)b + rdlen,
len - rdlen,
0);
if(-1 == this_time) {
if(EAGAIN == errno) {
continue;
}
return -1;
}
if(0 == this_time) {
return -1;
}
rdlen += this_time;
}
return rdlen;
}
length = (apr_size_t) len;
stat = apr_recv(sock, b, &length);
if ( stat == APR_EOF)
return -1; /* socket closed. */
else if ( stat == APR_SUCCESS) {
rdlen = (int) length;
return rdlen;
} else
return -1; /* any error. */
}
/** receive len bytes.
* @param sd opened socket.
* @param b buffer to store the data.
* @param len length to receive.
* @return -1: receive failed or connection closed.
* >0: length of the received data.
* Was: tcp_socket_recvfull
*/
static int JK_METHOD jk_channel_socket_recv( jk_env_t *env, jk_channel_t *_this,
jk_endpoint_t *endpoint,
jk_msg_t *msg )
{
int hlen=msg->headerLength;
int blen;
int rc;
jk_channel_apr_readN( env, _this, endpoint, msg->buf, hlen );
blen=msg->checkHeader( env, msg, endpoint );
if( blen < 0 ) {
env->l->jkLog(env, env->l, JK_LOG_ERROR,
"channelSocket.receive(): Bad header\n" );
return JK_FALSE;
}
rc= jk_channel_apr_readN( env, _this, endpoint, msg->buf + hlen, blen);
if(rc < 0) {
env->l->jkLog(env, env->l, JK_LOG_ERROR,
"channelSocket.receive(): Error receiving message body %d %d\n",
rc, errno);
return JK_FALSE;
}
env->l->jkLog(env, env->l, JK_LOG_INFO,
"channelSocket.receive(): Received len=%d type=%d\n",
blen, (int)msg->buf[hlen]);
return JK_TRUE;
}
int JK_METHOD jk_channel_apr_socket_factory(jk_env_t *env,
jk_pool_t *pool,
void **result,
const char *type, const char *name)
{
jk_channel_t *_this;
if( strcmp( "channel", type ) != 0 ) {
/* Wrong type XXX throw */
*result=NULL;
return JK_FALSE;
}
_this=(jk_channel_t *)pool->calloc(env, pool, sizeof( jk_channel_t));
_this->_privatePtr= (jk_channel_socket_private_t *)
pool->calloc( env, pool, sizeof( jk_channel_socket_private_t));
_this->recv= jk_channel_socket_recv;
_this->send= jk_channel_socket_send;
_this->init= jk_channel_socket_init;
_this->open= jk_channel_socket_open;
_this->close= jk_channel_socket_close;
_this->getProperty= jk_channel_socket_getProperty;
_this->setProperty= jk_channel_socket_setProperty;
_this->supportedProperties=( char ** )pool->alloc( env, pool,
4 * sizeof( char * ));
_this->supportedProperties[0]="host";
_this->supportedProperties[1]="port";
_this->supportedProperties[2]="defaultPort";
_this->supportedProperties[3]="\0";
_this->name="file";
*result= _this;
_this->is_stream=JK_TRUE;
return JK_TRUE;
}
--
To unsubscribe, e-mail: <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>