mturk 2004/11/08 05:39:27
Modified: jk/native/common jk_connect.c
Log:
Use socket timeout, and use read/write on unix platforms.
Use macros for WIN32/Netware socket errors.
Revision Changes Path
1.28 +204 -56 jakarta-tomcat-connectors/jk/native/common/jk_connect.c
Index: jk_connect.c
===================================================================
RCS file: /home/cvs/jakarta-tomcat-connectors/jk/native/common/jk_connect.c,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -r1.27 -r1.28
--- jk_connect.c 8 Oct 2004 07:50:39 -0000 1.27
+++ jk_connect.c 8 Nov 2004 13:39:27 -0000 1.28
@@ -21,6 +21,7 @@
/**
* @package jk_connect
* @author Gal Shachor <shachor@il.ibm.com>
+ * @author Mladen Turk <mturk@apache.org>
* @version $Revision$
*/
@@ -38,6 +39,14 @@
typedef u_long in_addr_t;
#endif
+#if defined(WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))
+#define JK_IS_SOCKET_ERROR(x) ((x) == SOCKET_ERROR)
+#define JK_GET_SOCKET_ERRNO() errno = WSAGetLastError() - WSABASEERR
+#else
+#define JK_IS_SOCKET_ERROR(x) ((x) == -1)
+#define JK_GET_SOCKET_ERRNO() ((void)0)
+#endif /* WIN32 */
+
/** resolve the host IP */
@@ -125,8 +134,8 @@
/** connect to Tomcat */
-int jk_open_socket(struct sockaddr_in *addr,
- int ndelay, int keepalive, jk_logger_t *l)
+int jk_open_socket(struct sockaddr_in *addr, int ndelay,
+ int keepalive, int timeout, jk_logger_t *l)
{
char buf[32];
int sock;
@@ -134,8 +143,23 @@
jk_log(l, JK_LOG_DEBUG, "Into jk_open_socket\n");
sock = socket(AF_INET, SOCK_STREAM, 0);
- if (sock > -1) {
- int ret;
+ if (sock >= 0) {
+ int ret, len;
+ if (timeout != -1) {
+ ret = jk_socket_timeout_set(sock, -1, timeout);
+ if (ret) {
+ jk_close_socket(sock);
+ jk_log(l, JK_LOG_INFO,
+ "jk_open_socket, timeout_set failed errno = %d\n",
+ ret);
+ return -1;
+ }
+ jk_log(l, JK_LOG_DEBUG,
+ "jk_open_socket, set timeout to %d with status %d\n",
+ timeout, ret);
+
+ }
+
/* Tries to connect to Tomcat (continues trying while error is EINTR) */
do {
jk_log(l, JK_LOG_DEBUG,
@@ -149,7 +173,7 @@
#endif
ret = connect(sock,
(struct sockaddr *)addr,
- sizeof(struct sockaddr_in));
+ sizeof(struct sockaddr_in));
#if defined(WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))
if (SOCKET_ERROR == ret) {
errno = WSAGetLastError() - WSABASEERR;
@@ -160,41 +184,57 @@
} while (-1 == ret && EINTR == errno);
/* Check if we connected */
- if (0 == ret) {
+ if (ret == -1) {
+ jk_log(l, JK_LOG_INFO,
+ "jk_open_socket, connect() failed errno = %d\n", errno);
+ jk_close_socket(sock);
+ return -1;
+ }
+ if (ndelay) {
+ int set = 1;
+ jk_log(l, JK_LOG_DEBUG,
+ "jk_open_socket, set TCP_NODELAY to on\n");
+ setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&set,
+ sizeof(set));
+ }
+ if (keepalive) {
int keep = 1;
- if (ndelay) {
- int set = 1;
-
- jk_log(l, JK_LOG_DEBUG,
- "jk_open_socket, set TCP_NODELAY to on\n");
- setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&set,
- sizeof(set));
- }
+ jk_log(l, JK_LOG_DEBUG,
+ "jk_open_socket, set SO_KEEPALIVE to on\n");
+ setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&keep,
+ sizeof(keep));
+ }
+ len = 8*1024; /* Default AJP packet size */
- if (keepalive) {
- jk_log(l, JK_LOG_DEBUG,
- "jk_open_socket, set SO_KEEPALIVE to on\n");
- setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&keep,
- sizeof(keep));
- }
+ /* Set socket send buffer size */
+ if (setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *)&len,
+ sizeof(len))) {
+ JK_GET_SOCKET_ERRNO();
+ jk_log(l, JK_LOG_ERROR,
+ "ERROR: jk_open_socket, failed setting sndbuf errno = %d\n", errno);
+ jk_close_socket(sock);
+ return -1;
+ }
+ /* Set socket receive buffer size */
+ if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)&len,
+ sizeof(len))) {
+ JK_GET_SOCKET_ERRNO();
+ jk_log(l, JK_LOG_ERROR,
+ "ERROR: jk_open_socket, failed setting rcvbuf errno = %d\n", errno);
+ jk_close_socket(sock);
+ return -1;
+ }
- jk_log(l, JK_LOG_DEBUG, "jk_open_socket, return, sd = %d\n",
- sock);
- return sock;
- }
- jk_log(l, JK_LOG_INFO,
- "jk_open_socket, connect() failed errno = %d\n", errno);
- jk_close_socket(sock);
+ jk_log(l, JK_LOG_DEBUG, "jk_open_socket, return, sd = %d\n",
+ sock);
}
else {
-#if defined(WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))
- errno = WSAGetLastError() - WSABASEERR;
-#endif /* WIN32 */
+ JK_GET_SOCKET_ERRNO();
jk_log(l, JK_LOG_ERROR,
"jk_open_socket, socket() failed errno = %d\n", errno);
}
- return -1;
+ return sock;
}
/** close the socket */
@@ -227,20 +267,27 @@
int jk_tcp_socket_sendfull(int sd, const unsigned char *b, int len)
{
int sent = 0;
+ int wr;
while (sent < len) {
- int this_time = send(sd,
- (char *)b + sent,
- len - sent,
- 0);
+ do {
+#if defined(WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))
+ wr = send(sd, (char *)b + sent,
+ len - sent, 0);
+ if (wr == SOCKET_ERROR)
+ errno = WSAGetLastError() - WSABASEERR;
+#else
+ wr = write(sd, (char *)b + sent , len - sent);
+#endif
+ } while (wr == -1 && errno == EINTR);
- if (0 == this_time) {
- return -2;
- }
- if (this_time < 0) {
+ if (wr == -1) {
return -3;
}
- sent += this_time;
+ else if (wr == 0) {
+ return -2;
+ }
+ sent += wr;
}
return sent;
@@ -256,30 +303,35 @@
int jk_tcp_socket_recvfull(int sd, unsigned char *b, int len)
{
int rdlen = 0;
+ int rd;
while (rdlen < len) {
- int this_time = recv(sd,
- (char *)b + rdlen,
- len - rdlen,
- 0);
- if (-1 == this_time) {
+ do {
#if defined(WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))
- /* I assume SOCKET_ERROR == -1 */
- if (SOCKET_ERROR == this_time) {
+ rd = recv(sd, (char *)b + rdlen,
+ len - rdlen, 0);
+ /* Assuming SOCKET_ERROR is -1 on NETWARE too */
+ if (rd == SOCKET_ERROR)
errno = WSAGetLastError() - WSABASEERR;
- }
-#endif /* WIN32 */
-
- if (EAGAIN == errno) {
+#else
+ rd = read(sd, (char *)b + rdlen, len - rdlen);
+#endif
+ } while (rd == -1 && errno == EINTR);
+
+ if (rd == -1) {
+ /* XXX: EAGAIN is reported only on nonblocking sockets */
+ if (errno == EAGAIN)
continue;
+ else {
+ /** Pass the errno to the caller */
+ return (errno > 0) ? -errno : errno;
}
- /** Pass the errno to the caller */
- return (errno > 0) ? -errno : errno;
}
- if (0 == this_time) {
+ else if (rd == 0) {
+ /** XXX: Return EOF? */
return -1;
}
- rdlen += this_time;
+ rdlen += rd;
}
return rdlen;
@@ -299,4 +351,100 @@
(int)((laddr >> 8) & 0xff), (int)(laddr & 0xff), (int)lport);
return buf;
+}
+
+static int soblock(int sd)
+{
+/* BeOS uses setsockopt at present for non blocking... */
+#ifndef WIN32
+ int fd_flags;
+
+ fd_flags = fcntl(sd, F_GETFL, 0);
+#if defined(O_NONBLOCK)
+ fd_flags &= ~O_NONBLOCK;
+#elif defined(O_NDELAY)
+ fd_flags &= ~O_NDELAY;
+#elif defined(FNDELAY)
+ fd_flags &= ~FNDELAY;
+#else
+#error Please teach JK how to make sockets blocking on your platform.
+#endif
+ if (fcntl(sd, F_SETFL, fd_flags) == -1) {
+ return errno;
+ }
+#else
+ u_long on = 0;
+ if (ioctlsocket(sd, FIONBIO, &on) == SOCKET_ERROR) {
+ errno = WSAGetLastError() - WSABASEERR;
+ return errno;
+ }
+#endif /* WIN32 */
+ return 0;
+}
+
+static int sononblock(int sd)
+{
+#ifndef WIN32
+ int fd_flags;
+
+ fd_flags = fcntl(sd, F_GETFL, 0);
+#if defined(O_NONBLOCK)
+ fd_flags |= O_NONBLOCK;
+#elif defined(O_NDELAY)
+ fd_flags |= O_NDELAY;
+#elif defined(FNDELAY)
+ fd_flags |= FNDELAY;
+#else
+#error Please teach JK how to make sockets non-blocking on your platform.
+#endif
+ if (fcntl(sd, F_SETFL, fd_flags) == -1) {
+ return errno;
+ }
+#else
+ u_long on = 1;
+ if (ioctlsocket(sd, FIONBIO, &on) == SOCKET_ERROR) {
+ errno = WSAGetLastError() - WSABASEERR;
+ return errno;
+ }
+#endif /* WIN32 */
+ return 0;
+}
+
+
+int jk_socket_timeout_set(int sd, int timeout, int t)
+{
+
+ int rc = 0;
+
+ if (t == 0) {
+ /* Set the socket non-blocking if it was previously blocking */
+ if (timeout != 0)
+ rc = sononblock(sd);
+ }
+ else if (t > 0) {
+ /* Set the socket to blocking if it was previously non-blocking */
+ if (timeout == 0) {
+ if ((rc = soblock(sd)) != 0)
+ return rc;
+ }
+ /* Reset socket timeouts if the new timeout differs from the old timeout */
+ if (timeout != t) {
+ /* Timeouts are in msec, represented as int */
+ setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO,
+ (char *) &t, sizeof(int));
+ setsockopt(sd, SOL_SOCKET, SO_SNDTIMEO,
+ (char *) &t, sizeof(int));
+ }
+ }
+ else if (t < 0) {
+ int zero = 0;
+ /* Set the socket to blocking with infinite timeouts */
+ if ((rc = soblock(sd)) != 0)
+ return rc;
+ setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO,
+ (char *) &zero, sizeof(zero));
+ setsockopt(sd, SOL_SOCKET, SO_SNDTIMEO,
+ (char *) &zero, sizeof(zero));
+ }
+ return rc;
}
---------------------------------------------------------------------
To unsubscribe, e-mail: tomcat-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tomcat-dev-help@jakarta.apache.org
|