'getting response only on the first time with socket programming

I'm trying to create an HTTP server using C++ 98.

The issue is that, every time I launch my server, I get the response, sending again the request from the same browser tab, and the browser keeps loading. In my kqueue, it seems like the block for checking the read event is not being executed on the second time.

This is my code:

void    webserv::Server::lunch(){

    this->kq.create_event(this->sock.getSocket(), EVFILT_READ);

    while(1)
        this->_lunch_worker();
}
    
void    webserv::Server::_lunch_worker(void)
{
    int     n_ev;
    int     accept_sock;
    int     address_size;
    char    buff[1000];
    webserv::Header header;

    // register the events in ev_list
    std::cout << GREEN << "---- WAITING FOR CONNECTION ----" << RESET << std::endl;
    n_ev = this->kq.get_event();
    for (int i = 0; i < n_ev; i++)
    {
        if (this->kq.get_fd(i) < 0)
            continue;
        if (this->kq.get_fd(i) == this->sock.getSocket())
        {
            std::cout << "--- RECEIVED NEW CONNECTION ---" << std::endl;
            address_size = sizeof(this->sock.getAddress());
            accept_sock = accept(
                    this->sock.getSocket(),
                    (struct sockaddr*)&this->sock.getAddress(),
                    (socklen_t *)&address_size
                    );
            this->sock.test_error(accept_sock);
            this->kq.create_event(accept_sock, EVFILT_READ);
            int flags;
            if ((flags = fcntl(accept_sock, F_GETFL, 0)) < 0) {
                perror("fcntl");
                close(accept_sock);
                close(this->sock.getSocket());
            }
            if (fcntl(accept_sock, F_SETFL, flags | O_NONBLOCK) < 0) {
                perror("fcntl");
                close(accept_sock);
                close(this->sock.getSocket());
            }
            this->kq.create_event(accept_sock, EVFILT_WRITE, EV_ADD | EV_ONESHOT);
        }
        else if (this->kq.is_read_available(i))
        {
            int bytes_read;
            std::cout << "START: is_read_available" << std::endl;
            if ((bytes_read = recv(this->kq.get_fd(i), buff, 999, 0)) > 0)
            {
            }
        }
        else if (this->kq.is_write_available(i))
        {
            std::string hello = "HTTP/1.1 200 OK\nContent-Type: text/plain\nContent-Length: 12\n\nHello world!";
            if (send(this->kq.get_fd(i), hello.c_str(), hello.length(), 0) != 0)
            {
                std::cout << "TEST2" << std::endl;
                this->kq.set_event(this->kq.get_fd(i), EVFILT_WRITE, EV_DELETE);
                this->kq.get_event_list()[i].ident = -1;
                close(this->kq.get_fd(i));
            }
            std::cout << "END: is_write_available" << std::endl;
        }
    }
}

And this is the kqueue class:

/************************ CONSTRUCTORS/DESTRUCTOR ************************/
webserv::Kqueue::Kqueue()
{
    this->_kq = kqueue();
    std::cout << "KQUEUE CREATED" << std::endl;
    this->test_error(this->_kq, "Creating Kqueue :");
    this->_n_ev = 0;
}

webserv::Kqueue::~Kqueue()
{
    close(this->_kq);
}
    
/************************ MEMBER FUNCTIONS ************************/
void    webserv::Kqueue::set_event(int fd, int filter, int flags, void *udata)
{
    EV_SET(&this->_ev_set, fd, filter, flags, 0, 0, udata);
}
    
void    webserv::Kqueue::add_event(void)
{
    int ret;

    ret = kevent(this->_kq, &this->_ev_set, 1, NULL, 0, NULL);
    this->test_error(ret, "Kqueue/add_even functions");
}
    
int     webserv::Kqueue::get_event(void)
{
    this->_n_ev = kevent(this->_kq, NULL, 0, this->_ev_list, __EV_LIST_SIZE__, NULL);
    this->test_error(this->_n_ev, "Kqueue/get_event function:");
    return (this->_n_ev);
}

void    webserv::Kqueue::create_event(int fd, int filter, int flags, void *udata)
{
    this->set_event(fd, filter, flags, udata);
    this->add_event();
}

bool    webserv::Kqueue::isEOF(int index)
{
    if (this->_n_ev <= index)
        this->test_error(-1, "Kqueue/isEOF function:");
    return (this->_ev_list[index].flags & EV_EOF);
}

bool    webserv::Kqueue::is_read_available(int index)
{
    if (this->_n_ev <= index)
        this->test_error(-1, "Kqueue/is_read_available function:");
    return (this->_ev_list[index].filter == EVFILT_READ);
}

bool    webserv::Kqueue::is_write_available(int index)
{
    if (this->_n_ev <= index)
        this->test_error(-1, "Kqueue/is_write_available function:");
    return (this->_ev_list[index].filter == EVFILT_WRITE);
}

void    webserv::Kqueue::test_error(int fd, const std::string &str)
{
    if (fd < 0)
    {
        std::cerr << RED << str << " ";
        perror("The following error occured: ");
        std::cerr << RESET;
        exit(EXIT_FAILURE);
    }
}

/************************ GETTERS/SETTERS ************************/
struct kevent   *webserv::Kqueue::get_event_list()
{
    return (this->_ev_list);
}

int             webserv::Kqueue::get_fd(int index)
{
    if (this->_n_ev <= index)
        this->test_error(-1, "Kqueue/get_ev_list function:");
    return (this->_ev_list[index].ident);
}

void    webserv::Kqueue::set_kqueue(int fd)
{
    this->_kq = fd;
}


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source