コード例 #1
0
ファイル: jk_connect.c プロジェクト: AneesShaik/Apache
/** Connect to Tomcat
 * @param addr      address to connect to
 * @param keepalive should we set SO_KEEPALIVE (if !=0)
 * @param timeout   connect timeout in seconds
 *                  (<=0: no timeout=blocking)
 * @param sock_buf  size of send and recv buffer
 *                  (<=0: use default)
 * @param l         logger
 * @return          JK_INVALID_SOCKET: some kind of error occured
 *                  created socket: success
 * @remark          Cares about errno
 */
jk_sock_t jk_open_socket(jk_sockaddr_t *addr, jk_sockaddr_t *source,
                         int keepalive,
                         int timeout, int connect_timeout,
                         int sock_buf, jk_logger_t *l)
{
    char buf[DUMP_SINFO_BUF_SZ];
    jk_sock_t sd;
    int set = 1;
    int ret = 0;
    int flags = 0;
#ifdef SO_LINGER
    struct linger li;
#endif

    JK_TRACE_ENTER(l);

    errno = 0;
#if defined(SOCK_CLOEXEC) && defined(USE_SOCK_CLOEXEC)
    flags |= SOCK_CLOEXEC;
#endif
    sd = socket(addr->family, SOCK_STREAM | flags, 0);
    if (!IS_VALID_SOCKET(sd)) {
        JK_GET_SOCKET_ERRNO();
        jk_log(l, JK_LOG_ERROR,
               "socket() failed (errno=%d)", errno);
        JK_TRACE_EXIT(l);
        return JK_INVALID_SOCKET;
    }
#if defined(FD_CLOEXEC) && !defined(USE_SOCK_CLOEXEC)
    if ((flags = fcntl(sd, F_GETFD)) == -1) {
        JK_GET_SOCKET_ERRNO();
        jk_log(l, JK_LOG_ERROR,
               "fcntl() failed (errno=%d)", errno);
        jk_close_socket(sd, l);
        JK_TRACE_EXIT(l);
        return JK_INVALID_SOCKET;
    }
    flags |= FD_CLOEXEC;
    if (fcntl(sd, F_SETFD, flags) == -1) {
        JK_GET_SOCKET_ERRNO();
        jk_log(l, JK_LOG_ERROR,
               "fcntl() failed (errno=%d)", errno);
        jk_close_socket(sd, l);
        JK_TRACE_EXIT(l);
        return JK_INVALID_SOCKET;
    }
#endif

    /* Disable Nagle algorithm */
    if (setsockopt(sd, IPPROTO_TCP, TCP_NODELAY, (SET_TYPE)&set,
                   sizeof(set))) {
        JK_GET_SOCKET_ERRNO();
        jk_log(l, JK_LOG_ERROR,
                "failed setting TCP_NODELAY (errno=%d)", errno);
        jk_close_socket(sd, l);
        JK_TRACE_EXIT(l);
        return JK_INVALID_SOCKET;
    }
    if (JK_IS_DEBUG_LEVEL(l))
        jk_log(l, JK_LOG_DEBUG,
               "socket TCP_NODELAY set to On");
    if (keepalive) {
#if defined(WIN32) && !defined(NETWARE)
        DWORD dw;
        struct tcp_keepalive ka = { 0 }, ks = { 0 };
        if (timeout)
            ka.keepalivetime = timeout * 10000;
        else
            ka.keepalivetime = 60 * 10000; /* 10 minutes */
        ka.keepaliveinterval = 1000;
        ka.onoff = 1;
        if (WSAIoctl(sd, SIO_KEEPALIVE_VALS, &ka, sizeof(ka),
                     &ks, sizeof(ks), &dw, NULL, NULL)) {
            JK_GET_SOCKET_ERRNO();
            jk_log(l, JK_LOG_ERROR,
                   "failed setting SIO_KEEPALIVE_VALS (errno=%d)", errno);
            jk_close_socket(sd, l);
            JK_TRACE_EXIT(l);
            return JK_INVALID_SOCKET;
        }
        if (JK_IS_DEBUG_LEVEL(l))
            jk_log(l, JK_LOG_DEBUG,
                   "socket SO_KEEPALIVE set to %d seconds",
                   ka.keepalivetime / 1000);
#else
        set = 1;
        if (setsockopt(sd, SOL_SOCKET, SO_KEEPALIVE, (SET_TYPE)&set,
                       sizeof(set))) {
            JK_GET_SOCKET_ERRNO();
            jk_log(l, JK_LOG_ERROR,
                   "failed setting SO_KEEPALIVE (errno=%d)", errno);
            jk_close_socket(sd, l);
            JK_TRACE_EXIT(l);
            return JK_INVALID_SOCKET;
        }
        if (JK_IS_DEBUG_LEVEL(l))
            jk_log(l, JK_LOG_DEBUG,
                   "socket SO_KEEPALIVE set to On");
#endif
    }

    if (sock_buf > 0) {
        set = sock_buf;
        /* Set socket send buffer size */
        if (setsockopt(sd, SOL_SOCKET, SO_SNDBUF, (SET_TYPE)&set,
                        sizeof(set))) {
            JK_GET_SOCKET_ERRNO();
            jk_log(l, JK_LOG_ERROR,
                    "failed setting SO_SNDBUF (errno=%d)", errno);
            jk_close_socket(sd, l);
            JK_TRACE_EXIT(l);
            return JK_INVALID_SOCKET;
        }
        set = sock_buf;
        /* Set socket receive buffer size */
        if (setsockopt(sd, SOL_SOCKET, SO_RCVBUF, (SET_TYPE)&set,
                                sizeof(set))) {
            JK_GET_SOCKET_ERRNO();
            jk_log(l, JK_LOG_ERROR,
                    "failed setting SO_RCVBUF (errno=%d)", errno);
            jk_close_socket(sd, l);
            JK_TRACE_EXIT(l);
            return JK_INVALID_SOCKET;
        }
        if (JK_IS_DEBUG_LEVEL(l))
            jk_log(l, JK_LOG_DEBUG,
                   "socket SO_SNDBUF and SO_RCVBUF set to %d",
                   sock_buf);
    }

    if (timeout > 0) {
#if defined(WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))
        int tmout = timeout * 1000;
        setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO,
                   (const char *) &tmout, sizeof(int));
        setsockopt(sd, SOL_SOCKET, SO_SNDTIMEO,
                   (const char *) &tmout, sizeof(int));
        JK_GET_SOCKET_ERRNO();
#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;
        setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO,
                   (const void *) &tv, sizeof(tv));
        setsockopt(sd, SOL_SOCKET, SO_SNDTIMEO,
                   (const void *) &tv, sizeof(tv));
#endif
        if (JK_IS_DEBUG_LEVEL(l))
            jk_log(l, JK_LOG_DEBUG,
                   "timeout %d set for socket=%d",
                   timeout, sd);
    }
#ifdef SO_NOSIGPIPE
    /* The preferred method on Mac OS X (10.2 and later) to prevent SIGPIPEs when
     * sending data to a dead peer. Possibly also existing and in use on other BSD
     * systems?
    */
    set = 1;
    if (setsockopt(sd, SOL_SOCKET, SO_NOSIGPIPE, (const char *)&set,
                   sizeof(int))) {
        JK_GET_SOCKET_ERRNO();
        jk_log(l, JK_LOG_ERROR,
                "failed setting SO_NOSIGPIPE (errno=%d)", errno);
        jk_close_socket(sd, l);
        JK_TRACE_EXIT(l);
        return JK_INVALID_SOCKET;
    }
#endif
#ifdef SO_LINGER
    /* Make hard closesocket by disabling lingering */
    li.l_linger = li.l_onoff = 0;
    if (setsockopt(sd, SOL_SOCKET, SO_LINGER, (SET_TYPE)&li,
                   sizeof(li))) {
        JK_GET_SOCKET_ERRNO();
        jk_log(l, JK_LOG_ERROR,
                "failed setting SO_LINGER (errno=%d)", errno);
        jk_close_socket(sd, l);
        JK_TRACE_EXIT(l);
        return JK_INVALID_SOCKET;
    }
#endif
    /* Tries to connect to Tomcat (continues trying while error is EINTR) */
    if (JK_IS_DEBUG_LEVEL(l))
        jk_log(l, JK_LOG_DEBUG,
                "trying to connect socket %d to %s", sd,
                jk_dump_hinfo(addr, buf, sizeof(buf)));

/* Need more infos for BSD 4.4 and Unix 98 defines, for now only
iSeries when Unix98 is required at compile time */
#if (_XOPEN_SOURCE >= 520) && defined(AS400)
    ((struct sockaddr *)addr)->sa.sin.sa_len = sizeof(struct sockaddr_in);
#endif
    ret = nb_connect(sd, addr, source, connect_timeout, l);
#if defined(WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))
    if (JK_IS_SOCKET_ERROR(ret)) {
        JK_GET_SOCKET_ERRNO();
    }
#endif /* WIN32 */

    /* Check if we are connected */
    if (ret) {
        jk_log(l, JK_LOG_INFO,
               "connect to %s failed (errno=%d)",
               jk_dump_hinfo(addr, buf, sizeof(buf)), errno);
        jk_close_socket(sd, l);
        sd = JK_INVALID_SOCKET;
    }
    else {
        if (JK_IS_DEBUG_LEVEL(l))
            jk_log(l, JK_LOG_DEBUG, "socket %d [%s] connected",
                   sd, jk_dump_sinfo(sd, buf, sizeof(buf)));
    }
    JK_TRACE_EXIT(l);
    return sd;
}
コード例 #2
0
ファイル: jk_connect.c プロジェクト: AneesShaik/Apache
/** Drain and close the socket
 * @param sd        socket to close
 * @param l         logger
 * @return          -1: socket to close is invalid
 *                  -1: some kind of error occured (!WIN32)
 *                  SOCKET_ERROR: some kind of error occured  (WIN32)
 *                  0: success
 * @remark          Does not change errno
 */
int jk_shutdown_socket(jk_sock_t sd, jk_logger_t *l)
{
    char dummy[512];
    char buf[DUMP_SINFO_BUF_SZ];
    char *sb = NULL;
    int rc = 0;
    size_t rd = 0;
    size_t rp = 0;
    int save_errno;
    int timeout = MS_TO_LINGER;
    time_t start = time(NULL);

    JK_TRACE_ENTER(l);

    if (!IS_VALID_SOCKET(sd)) {
        JK_TRACE_EXIT(l);
        return -1;
    }

    save_errno = errno;
    if (JK_IS_DEBUG_LEVEL(l)) {
        sb = jk_dump_sinfo(sd, buf, sizeof(buf));
        jk_log(l, JK_LOG_DEBUG, "About to shutdown socket %d [%s]",
               sd, sb);
    }
    /* Shut down the socket for write, which will send a FIN
     * to the peer.
     */
    if (shutdown(sd, SHUT_WR)) {
        rc = jk_close_socket(sd, l);
        if (JK_IS_DEBUG_LEVEL(l))
            jk_log(l, JK_LOG_DEBUG,
                   "Failed sending SHUT_WR for socket %d [%s]",
                   sd, sb);
        errno = save_errno;
        JK_TRACE_EXIT(l);
        return rc;
    }

    do {
        rp = 0;
        if (jk_is_input_event(sd, timeout, l)) {
            /* Do a restartable read on the socket
             * draining out all the data currently in the socket buffer.
             */
            int num = 0;
            do {
                num++;
#if defined(WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))
                rc = recv(sd, &dummy[0], sizeof(dummy), 0);
                if (JK_IS_SOCKET_ERROR(rc))
                    JK_GET_SOCKET_ERRNO();
#else
                rc = read(sd, &dummy[0], sizeof(dummy));
#endif
                if (rc > 0)
                    rp += rc;
            } while (JK_IS_SOCKET_ERROR(rc) && (errno == EINTR || errno == EAGAIN) && num < MAX_READ_RETRY);

            if (rc < 0) {
                /* Read failed.
                 * Bail out from the loop.
                 */
                break;
            }
        }
        else {
            /* Error or timeout (reason is logged within jk_is_input_event)
             * Exit the drain loop
             */
            break;
        }
        rd += rp;
        if (rp < sizeof(dummy)) {
            if (timeout > MS_TO_LINGER_LAST) {
                /* Try one last time with a short timeout
                */
                timeout = MS_TO_LINGER_LAST;
                continue;
            }
            /* We have read less then size of buffer
             * It's a good chance there will be no more data
             * to read.
             */
            if ((rc = sononblock(sd))) {
                rc = jk_close_socket(sd, l);
                if (JK_IS_DEBUG_LEVEL(l))
                    jk_log(l, JK_LOG_DEBUG,
                           "error setting socket %d [%s] to nonblocking",
                           sd, sb);
                errno = save_errno;
                JK_TRACE_EXIT(l);
                return rc;
            }
            if (JK_IS_DEBUG_LEVEL(l))
                jk_log(l, JK_LOG_DEBUG,
                       "shutting down the read side of socket %d [%s]",
                       sd, sb);
            shutdown(sd, SHUT_RD);
            break;
        }
        timeout = MS_TO_LINGER;
    } while ((rd < MAX_LINGER_BYTES) && (difftime(time(NULL), start) < MAX_SECS_TO_LINGER));

    rc = jk_close_socket(sd, l);
    if (JK_IS_DEBUG_LEVEL(l))
        jk_log(l, JK_LOG_DEBUG,
               "Shutdown socket %d [%s] and read %d lingering bytes in %d sec.",
               sd, sb, rd, (int)difftime(time(NULL), start));
    errno = save_errno;
    JK_TRACE_EXIT(l);
    return rc;
}
コード例 #3
0
ファイル: jk_connect.c プロジェクト: devjin24/howtomcatworks
int jk_open_socket(struct sockaddr_in *addr, 
                   int ndelay,
                   int keepalive,
                   jk_logger_t *l)
{
    int sock;

    jk_log(l, JK_LOG_DEBUG, "Into jk_open_socket\n");

    sock = socket(AF_INET, SOCK_STREAM, 0);
    if(sock > -1) {
        int ret;
        /* Tries to connect to JServ (continues trying while error is EINTR) */
        do {
            jk_log(l, JK_LOG_DEBUG, "jk_open_socket, try to connect socket = %d\n", sock);
            ret = connect(sock,
                          (struct sockaddr *)addr,
                          sizeof(struct sockaddr_in));
#if defined(WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))
            if(SOCKET_ERROR == ret) { 
                errno = WSAGetLastError() - WSABASEERR;
            }
#endif /* WIN32 */
            jk_log(l, JK_LOG_DEBUG, "jk_open_socket, after connect ret = %d\n", ret);
        } while (-1 == ret && EINTR == errno);

        /* Check if we connected */
        if(0 == ret) {
                                                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));
            }   

            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));
            }

            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);
    } else {
#if defined(WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))
        errno = WSAGetLastError() - WSABASEERR;
#endif /* WIN32 */
        jk_log(l, JK_LOG_ERROR, "jk_open_socket, socket() failed errno = %d\n", errno);
    }    

    return -1;
}