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 <[EMAIL PROTECTED]> + * @author Mladen Turk <[EMAIL PROTECTED]> * @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: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]