<commit_before>/*
 * Copyright(c) 2010, <NAME>, All rights reserved.
 */

#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <errno.h>

#include "mod_websocket_socket.h"

int mod_websocket_connect(const char *host, const char *service) {
    struct addrinfo hints;
    struct addrinfo *res = NULL;
    struct addrinfo *ai = NULL;
    struct fdlist {
        int fd;
        struct fdlist *next;
    };
    struct fdlist *head = NULL, *p, *pn, *fde = NULL;
    int flags, fd, maxfd = -1, connfd = -1, sockret = -1;
    socklen_t socklen = sizeof(sockret);
    fd_set fds;
    struct timeval tv;

    memset(&hints, 0, sizeof(hints));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = 0;

    if (getaddrinfo(host, service, &hints, &res) != 0) {
        return -1;
    }
    FD_ZERO(&fds);
    for (ai = res; ai; ai = ai->ai_next) {
        fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
        if (fd < 0) {
            goto go_out;
        }
        if ((flags = fcntl(fd, F_GETFL, 0)) < 0 ||
            fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {
            close(fd);
            goto go_out;
        }
        fde = (struct fdlist *)malloc(sizeof(struct fdlist));
        if (!fde) {
            close(fd);
            goto go_out;
        }
        fde->fd = fd;
        fde->next = head;
        head = fde;
        /**
         * for https://github.com/nori0428/mod_websocket/issues/40
         * 'FD_SET' occurs buffer overflow when fd > 1024
         *
         * mod_websocket set only one fd into 'fd_set' in most cases,
         * but fd number takes over 1024 when many websocket connection exist.
         *
         * http://stackoverflow.com/questions/7976388/increasing-limit-of-fd-setsize-and-select
         */
        if ((fde->fd % FD_SETSIZE) > maxfd) {
            maxfd = fde->fd % FD_SETSIZE;
        }
        FD_SET((fde->fd % FD_SETSIZE), &fds);
        if (connect(fde->fd, ai->ai_addr, ai->ai_addrlen) < 0) {
            if (errno != EINPROGRESS) {
                goto go_out;
            }
        }
    }
    /* connect timeout is to set 5 secs */
    tv.tv_sec = 5;
    tv.tv_usec = 0;
    if (select(maxfd + 1, NULL, &fds, NULL, &tv) == 0) {
        goto go_out;
    } else {
        for (p = head; p; p = p->next) {
            if (!FD_ISSET((p->fd % FD_SETSIZE), &fds)) {
                continue;
            }
            if (getsockopt(p->fd, SOL_SOCKET, SO_ERROR,
                           &sockret, &socklen) == 0 &&
                sockret == 0) {
                connfd = p->fd;
                break;
            }
        }
    }

 go_out:
    p = head;
    while (p) {
        if (p->fd != connfd) {
            close(p->fd);
        }
        pn = p->next;
        free(p);
        p = pn;
    }
    freeaddrinfo(res);
    return connfd;
}

void mod_websocket_disconnect(int fd) {
    close(fd);
}

static void store_sockinfo(struct sockaddr_storage *sa, mod_websocket_addrinfo_t *info) {
    assert(sa != NULL && info != NULL);
    if (sa->ss_family == AF_INET) {
        struct sockaddr_in *s = (struct sockaddr_in *)sa;
        info->port = ntohs(s->sin_port);
        inet_ntop(AF_INET, &s->sin_addr, info->addr, sizeof(info->addr));<commit_msg>resolve issue #40 by using poll. And revise algorithm to connect.(for IPv6)<commit_after>/*
 * Copyright(c) 2010, <NAME>, All rights reserved.
 */

#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <errno.h>
#include <poll.h>

#include "mod_websocket_socket.h"

int mod_websocket_connect(const char *host, const char *service) {
    struct addrinfo hints;
    struct addrinfo *res = NULL;
    struct addrinfo *ai = NULL;
    int flags, fd = -1, sockret = -1;
    socklen_t socklen = sizeof(sockret);
    struct pollfd pollfd;

    memset(&hints, 0, sizeof(hints));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = 0;
    if (getaddrinfo(host, service, &hints, &res) != 0) {
        return -1;
    }
    for (ai = res; ai; ai = ai->ai_next) {
        fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
        if (fd < 0) {
          break;
        }
        if ((flags = fcntl(fd, F_GETFL, 0)) < 0 ||
            fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {
            close(fd);
            fd = -1;
            continue;
        }
        pollfd.fd = fd;
        pollfd.events = POLLOUT;
        if (connect(fd, ai->ai_addr, ai->ai_addrlen) < 0 &&
            errno != EINPROGRESS) {
            close(fd);
            fd = -1;
            continue;
        }
        if (poll(&pollfd, 1, 5000) == 0) {
            close(fd);
            fd = -1;
            continue;
        }
        if ((pollfd.revents & POLLOUT) &&
            getsockopt(fd, SOL_SOCKET, SO_ERROR, &sockret, &socklen) == 0 &&
            sockret == 0 ) {
            break;
        }
        close(fd);
        fd = -1;
    }
    freeaddrinfo(res);
    return fd;
}

void mod_websocket_disconnect(int fd) {
    close(fd);
}

static void store_sockinfo(struct sockaddr_storage *sa, mod_websocket_addrinfo_t *info) {
    assert(sa != NULL && info != NULL);
    if (sa->ss_family == AF_INET) {
        struct sockaddr_in *s = (struct sockaddr_in *)sa;
        info->port = ntohs(s->sin_port);
        inet_ntop(AF_INET, &s->sin_addr, info->addr, sizeof(info->addr));
{'fraction_non_alphanumeric': 0.14283182704235337, 'fraction_numerical': 0.013113592060960482, 'mean_word_length': 1.9503397804495557, 'pattern_counts': {'":': 0, '<': 34, '<?xml version=': 0, '>': 65, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '211306', 'n_tokens_mistral': 2110, 'n_tokens_neox': 2010, 'n_words': 474}