<commit_before>// vim:cindent:cino=\:0:et:fenc=utf-8:ff=unix:sw=4:ts=4:

#include <cstddef>
#include <cstring>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

#ifdef _WIN32
# include <winsock2.h>
# include <ws2tcpip.h>
#else
# include <netinet/in.h>
# include <netdb.h>
# include <sys/select.h>
# include <sys/socket.h>
#endif

#include "connectionprivate.h"
#include "socketconnectionprivate.h"
#include <conveyor/exceptions.h>

namespace conveyor
{
    SocketConnectionPrivate *
    SocketConnectionPrivate::connectTcp
        ( std::string const & host
        , int const port
        )
    {
        SocketConnectionPrivate::socket_t const fd
            ( socket (PF_INET, SOCK_STREAM, IPPROTO_TCP)
            );
        if (SocketConnectionPrivate::invalidSocket (fd))
        {
            throw SocketCreateError();
        }
        else
        {
            struct sockaddr_in address;
            memset (& address, 0, sizeof (struct sockaddr_in));
            address.sin_family = AF_INET;
            address.sin_port = htons (port);
            struct hostent * hostent;
            hostent = gethostbyname (host.c_str ());
            if (0 == hostent)
            {
                throw HostLookupError(host);
            }
            else
            {
                std::memcpy
                    ( & address.sin_addr.s_addr
                    , hostent->h_addr_list[0]
                    , hostent->h_length
                    );
                if (0 != connect
                    ( fd
                    , reinterpret_cast <struct sockaddr *> (& address)
                    , sizeof (struct sockaddr_in)
                    ))
                {
                    throw SocketConnectError(host, port);
                }
                else
                {
                    SocketConnectionPrivate * const private_
                        ( new SocketConnectionPrivate (fd)
                        );
                    return private_;
                }
            }
        }
    }

    SocketConnectionPrivate::SocketConnectionPrivate (socket_t const fd)
        : m_fd (fd)
        , m_eof (false)
        , m_cancel (false)
    {
    }

    SocketConnectionPrivate::~SocketConnectionPrivate (void)
    {
        close (this->m_fd);
    }

    bool
    SocketConnectionPrivate::eof (void)
    {
        return this->m_eof;
    }

    ssize_t
    SocketConnectionPrivate::read
        ( char * const buffer
        , std::size_t const length
        )
    {
        fd_set readfds;
        FD_ZERO (& readfds);
        FD_SET (this->m_fd, & readfds);

        struct timeval timeval;

        for (;;)
        {
            /* Linux select() modifies timeval to contain the time
               remaining until timeout. It must be reset on subsequent
               calls. */
            timeval.tv_sec = 1u;
            timeval.tv_usec = 0u;<commit_msg>Fix another issue with select()<commit_after>// vim:cindent:cino=\:0:et:fenc=utf-8:ff=unix:sw=4:ts=4:

#include <cstddef>
#include <cstring>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

#ifdef _WIN32
# include <winsock2.h>
# include <ws2tcpip.h>
#else
# include <netinet/in.h>
# include <netdb.h>
# include <sys/select.h>
# include <sys/socket.h>
#endif

#include "connectionprivate.h"
#include "socketconnectionprivate.h"
#include <conveyor/exceptions.h>

namespace conveyor
{
    SocketConnectionPrivate *
    SocketConnectionPrivate::connectTcp
        ( std::string const & host
        , int const port
        )
    {
        SocketConnectionPrivate::socket_t const fd
            ( socket (PF_INET, SOCK_STREAM, IPPROTO_TCP)
            );
        if (SocketConnectionPrivate::invalidSocket (fd))
        {
            throw SocketCreateError();
        }
        else
        {
            struct sockaddr_in address;
            memset (& address, 0, sizeof (struct sockaddr_in));
            address.sin_family = AF_INET;
            address.sin_port = htons (port);
            struct hostent * hostent;
            hostent = gethostbyname (host.c_str ());
            if (0 == hostent)
            {
                throw HostLookupError(host);
            }
            else
            {
                std::memcpy
                    ( & address.sin_addr.s_addr
                    , hostent->h_addr_list[0]
                    , hostent->h_length
                    );
                if (0 != connect
                    ( fd
                    , reinterpret_cast <struct sockaddr *> (& address)
                    , sizeof (struct sockaddr_in)
                    ))
                {
                    throw SocketConnectError(host, port);
                }
                else
                {
                    SocketConnectionPrivate * const private_
                        ( new SocketConnectionPrivate (fd)
                        );
                    return private_;
                }
            }
        }
    }

    SocketConnectionPrivate::SocketConnectionPrivate (socket_t const fd)
        : m_fd (fd)
        , m_eof (false)
        , m_cancel (false)
    {
    }

    SocketConnectionPrivate::~SocketConnectionPrivate (void)
    {
        close (this->m_fd);
    }

    bool
    SocketConnectionPrivate::eof (void)
    {
        return this->m_eof;
    }

    ssize_t
    SocketConnectionPrivate::read
        ( char * const buffer
        , std::size_t const length
        )
    {
        fd_set readfds;

        struct timeval timeval;

        for (;;)
        {
            /* Linux select() modifies timeval to contain the time
               remaining until timeout. It must be reset on subsequent
               calls. */
            timeval.tv_sec = 1u;
            timeval.tv_usec = 0u;
            /* select() may also invalidate the file descriptor set. */
            FD_ZERO (& readfds);
            FD_SET (this->m_fd, & readfds);
{'fraction_non_alphanumeric': 0.09558327714093054, 'fraction_numerical': 0.004720161834120027, 'mean_word_length': 1.4516528925619834, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 39, 'https://': 0, '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': '6332255', 'n_tokens_mistral': 1737, 'n_tokens_neox': 1663, 'n_words': 351}