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]

Reply via email to