You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by mt...@apache.org on 2005/03/15 09:23:38 UTC

cvs commit: jakarta-tomcat-connectors/jk/native/common jk_connect.c

mturk       2005/03/15 00:23:38

  Modified:    jk/native/common jk_connect.c
  Log:
  Add non blocking connect to Tomcat. It enables the true socket_timeout
  for connect call.
  
  Revision  Changes    Path
  1.47      +177 -77   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.46
  retrieving revision 1.47
  diff -u -r1.46 -r1.47
  --- jk_connect.c	25 Feb 2005 08:26:03 -0000	1.46
  +++ jk_connect.c	15 Mar 2005 08:23:38 -0000	1.47
  @@ -45,6 +45,169 @@
   #define JK_GET_SOCKET_ERRNO() ((void)0)
   #endif /* WIN32 */
   
  +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;
  +}
  +
  +#if defined (WIN32)
  +/* WIN32 implementation */
  +static int nb_connect(int sock, struct sockaddr *addr, int timeout)
  +{
  +    int rc;
  +    if (timeout < 1)
  +        return connect(sock, addr, sizeof(struct sockaddr_in));
  +
  +    if ((rc = sononblock(sock)))
  +        return -1;
  +    if (connect(sock, addr, sizeof(struct sockaddr_in)) == SOCKET_ERROR) {
  +        struct timeval tv;
  +        fd_set wfdset, efdset;
  +
  +        if ((rc = WSAGetLastError()) != WSAEWOULDBLOCK) {
  +            soblock(sock);
  +            WSASetLastError(rc);
  +            return -1;
  +        }
  +        /* wait for the connect to complete or timeout */
  +        FD_ZERO(&wfdset);
  +        FD_SET(sock, &wfdset);
  +        FD_ZERO(&efdset);
  +        FD_SET(sock, &efdset);
  +
  +        tv.tv_sec  = timeout;
  +        tv.tv_usec = 0;
  +        rc = select(FD_SETSIZE+1, NULL, &wfdset, &efdset, &tv);
  +        if (rc == SOCKET_ERROR || rc == 0) {
  +            rc = WSAGetLastError();
  +            soblock(sock);
  +            WSASetLastError(rc);
  +            return -1;
  +        }
  +        /* Evaluate the efdset */
  +        if (FD_ISSET(sock, &efdset)) {
  +            /* The connect failed. */
  +            int rclen = sizeof(rc);
  +            if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (char*) &rc, &rclen))
  +                rc = 0;
  +            soblock(sock);
  +            if (rc)
  +                WSASetLastError(rc);
  +            return -1;
  +        }
  +    }
  +    soblock(sock);
  +    return 0;
  +}
  +
  +#elif !defined(NETWARE)
  +/* POSIX implementation */
  +static int nb_connect(int sock, struct sockaddr *addr, int timeout)
  +{
  +    int rc = 0;
  +
  +    if (timeout > 0) {
  +        if (sononblock(sock))
  +            return -1;
  +    }
  +    do {
  +        rc = connect(sock, addr, sizeof(struct sockaddr_in));
  +    } while (rc == -1 && errno == EINTR);
  +
  +    if ((rc == -1) && (errno == EINPROGRESS || errno == EALREADY)
  +                   && (timeout > 0)) {
  +        fd_set wfdset;
  +        struct timeval tv;
  +        int rclen = sizeof(rc);
  +
  +        FD_ZERO(&wfdset);
  +        FD_SET(sock, &wfdset);
  +        tv.tv_sec  = timeout;
  +        tv.tv_usec = 0;
  +        rc = select(sock+1, NULL, &wfdset, NULL, &tv);
  +        if (rc <= 0) {
  +            /* Save errno */
  +            int err = errno;
  +            soblock(sock);
  +            errno = err;
  +            return -1;
  +        }
  +        rc = 0;
  +#ifdef SO_ERROR
  +        if (!FD_ISSET(sock, &wfdset) ||
  +            (getsockopt(sock, SOL_SOCKET, SO_ERROR,
  +                        (char *)&rc, &rclen) < 0) || rc) {
  +            if (rc)
  +                errno = rc;
  +            rc = -1;
  +        }
  +#endif /* SO_ERROR */
  +    }
  +    /* Not sure we can be already connected */
  +    if (rc == -1 && errno == EISCONN)
  +        rc = 0;
  +    soblock(sock);
  +    return rc;
  +}
  +#else
  +/* NETWARE implementation - blocking for now */
  +static int nb_connect(int sock, struct sockaddr *addr, int timeout)
  +{
  +    return connect(sock, addr, sizeof(struct sockaddr_in));
  +}
  +#endif
   
   /** resolve the host IP */
   
  @@ -204,7 +367,7 @@
                      (const char *) &timeout, sizeof(int));
           setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO,
                      (const char *) &timeout, sizeof(int));
  -#elif defined(SO_RCVTIMEO) && defined(USE_SO_RCVTIMEO) && defined(SO_SNDTIMEO) && defined(USE_SO_SNDTIMEO) 
  +#elif defined(SO_RCVTIMEO) && defined(USE_SO_RCVTIMEO) && defined(SO_SNDTIMEO) && defined(USE_SO_SNDTIMEO)
           struct timeval tv;
           tv.tv_sec  = timeout;
           tv.tv_usec = 0;
  @@ -248,31 +411,28 @@
       }
   #endif
       /* Tries to connect to Tomcat (continues trying while error is EINTR) */
  -    do {
  -        if (JK_IS_DEBUG_LEVEL(l))
  -            jk_log(l, JK_LOG_DEBUG,
  -                   "trying to connect socket %d to %s", sock,
  -                   jk_dump_hinfo(addr, buf));
  +    if (JK_IS_DEBUG_LEVEL(l))
  +        jk_log(l, JK_LOG_DEBUG,
  +                "trying to connect socket %d to %s", sock,
  +                jk_dump_hinfo(addr, buf));
   
   /* Need more infos for BSD 4.4 and Unix 98 defines, for now only
   iSeries when Unix98 is required at compil time */
   #if (_XOPEN_SOURCE >= 520) && defined(AS400)
  -        ((struct sockaddr *)addr)->sa_len = sizeof(struct sockaddr_in);
  +    ((struct sockaddr *)addr)->sa_len = sizeof(struct sockaddr_in);
   #endif
  -        ret = connect(sock, (struct sockaddr *)addr,
  -                      sizeof(struct sockaddr_in));
  +    ret = nb_connect(sock, (struct sockaddr *)addr, timeout);
   #if defined(WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))
  -        if (ret == SOCKET_ERROR) {
  -            errno = WSAGetLastError() - WSABASEERR;
  -        }
  +    if (ret == SOCKET_ERROR) {
  +        errno = WSAGetLastError() - WSABASEERR;
  +    }
   #endif /* WIN32 */
  -    } while (ret == -1 && errno == EINTR);
   
       /* Check if we are connected */
  -    if (ret == -1) {
  +    if (ret) {
           jk_log(l, JK_LOG_INFO,
  -                "connect to %s failed with errno=%d",
  -                jk_dump_hinfo(addr, buf), errno);
  +               "connect to %s failed with errno=%d",
  +               jk_dump_hinfo(addr, buf), errno);
           jk_close_socket(sock);
           sock = -1;
       }
  @@ -388,66 +548,6 @@
       return buf;
   }
   
  -#if 0
  -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;
  -}
  -
  -#endif
  -
   int jk_is_socket_connected(int sd, int timeout)
   {
       fd_set fd;
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: tomcat-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tomcat-dev-help@jakarta.apache.org