nktr-cp / webserv

Implementation of a simple HTTP server in C++
3 stars 0 forks source link

Event loop structure #9

Closed Wolframike closed 5 months ago

Wolframike commented 5 months ago

https://github.com/cclaude42/webserv/blob/master/srcs/server/Cluster.cpp#L60

int         n = 0;

while (1)
{
fd_set      reading_set;
fd_set      writing_set;
struct timeval  timeout;
int             ret = 0;

while (ret == 0)
{
    timeout.tv_sec  = 1;
    timeout.tv_usec = 0;
    ft_memcpy(&reading_set, &_fd_set, sizeof(_fd_set));
    FD_ZERO(&writing_set);
    for (std::vector<int>::iterator it = _ready.begin() ; it != _ready.end() ; it++)
        FD_SET(*it, &writing_set);

    std::cout << "\rWaiting on a connection" << dot[n++] << std::flush;
    if (n == 3)
        n = 0;

    ret = select(_max_fd + 1, &reading_set, &writing_set, NULL, &timeout);
}

if (ret > 0)
{
    for (std::vector<int>::iterator it = _ready.begin() ; ret && it != _ready.end() ; it++)
    {
        if (FD_ISSET(*it, &writing_set))
        {
            long    ret = _sockets[*it]->send(*it);

            if (ret == 0)
                _ready.erase(it);
            else if (ret == -1)
            {
                FD_CLR(*it, &_fd_set);
                FD_CLR(*it, &reading_set);
                _sockets.erase(*it);
                _ready.erase(it);
            }

            ret = 0;
            break;
        }
    }

    if (ret)
        std::cout << "\rReceived a connection !   " << std::flush;

    for (std::map<long, Server *>::iterator it = _sockets.begin() ; ret && it != _sockets.end() ; it++)
    {
        long    socket = it->first;

        if (FD_ISSET(socket, &reading_set))
        {
            long    ret = it->second->recv(socket);

            if (ret == 0)
            {
                it->second->process(socket, _config);
                _ready.push_back(socket);
            }
            else if (ret == -1)
            {
                FD_CLR(socket, &_fd_set);
                FD_CLR(socket, &reading_set);
                _sockets.erase(socket);
                it = _sockets.begin();
            }
            ret = 0;
            break;
        }
    }

    for (std::map<long, Server>::iterator it = _servers.begin() ; ret && it != _servers.end() ; it++)
    {
        long    fd = it->first;

        if (FD_ISSET(fd, &reading_set))
        {
            long    socket = it->second.accept();

            if (socket != -1)
            {
                FD_SET(socket, &_fd_set);
                _sockets.insert(std::make_pair(socket, &(it->second)));
                if (socket > _max_fd)
                    _max_fd = socket;
            }
            ret = 0;
            break;
        }
    }
}
else
{
    std::cerr << RED << "Problem with select !" << RESET << std::endl;
    for (std::map<long, Server *>::iterator it = _sockets.begin() ; it != _sockets.end() ; it++)
        it->second->close(it->first);
    _sockets.clear();
    _ready.clear();
    FD_ZERO(&_fd_set);
    for (std::map<long, Server>::iterator it = _servers.begin() ; it != _servers.end() ; it++)
        FD_SET(it->first, &_fd_set);
}

n = 0;

https://github.com/Kaydooo/Webserv_42/blob/main/src/ServerManager.cpp#L46

fd_set  recv_set_cpy;
fd_set  write_set_cpy;
int     select_ret;

_biggest_fd = 0;
initializeSets();
struct timeval timer;
while (true)
{
    timer.tv_sec = 1;
    timer.tv_usec = 0;
    recv_set_cpy = _recv_fd_pool;
    write_set_cpy = _write_fd_pool;

    if ( (select_ret = select(_biggest_fd + 1, &recv_set_cpy, &write_set_cpy, NULL, &timer)) < 0 )
    {
        Logger::logMsg(RED, CONSOLE_OUTPUT, "webserv: select error %s   Closing ....", strerror(errno));
        exit(1);
        continue ;
    }
    for (int i = 0; i <= _biggest_fd; ++i)
    {
        if (FD_ISSET(i, &recv_set_cpy) && _servers_map.count(i))
            acceptNewConnection(_servers_map.find(i)->second);
        else if (FD_ISSET(i, &recv_set_cpy) && _clients_map.count(i))
            readRequest(i, _clients_map[i]);
        else if (FD_ISSET(i, &write_set_cpy) && _clients_map.count(i))
        {
            int cgi_state = _clients_map[i].response.getCgiState(); // 0->NoCGI 1->CGI write/read to/from script 2-CGI read/write done
            if (cgi_state == 1 && FD_ISSET(_clients_map[i].response._cgi_obj.pipe_in[1], &write_set_cpy))
                sendCgiBody(_clients_map[i], _clients_map[i].response._cgi_obj);
            else if (cgi_state == 1 && FD_ISSET(_clients_map[i].response._cgi_obj.pipe_out[0], &recv_set_cpy))
                readCgiResponse(_clients_map[i], _clients_map[i].response._cgi_obj);
            else if ((cgi_state == 0 || cgi_state == 2)  && FD_ISSET(i, &write_set_cpy))
                sendResponse(i, _clients_map[i]);
        }
    }
    checkTimeout();
}

https://github.com/JUNNETWORKS/42-webserv/blob/main/srcs/server/event_loop.cpp#L12

while (1) {
    std::vector<FdEventEvent> timeouts = epoll.RetrieveTimeouts();
    for (std::vector<FdEventEvent>::const_iterator it = timeouts.begin();
        it != timeouts.end(); ++it) {
    FdEvent *fde = it->fde;
    unsigned int events = it->events;
    InvokeFdEvent(fde, events, &epoll);
    }

    Result<std::vector<FdEventEvent> > result = epoll.WaitEvents(100);
    if (result.IsErr()) {
    utils::ErrExit("WaitEvents");
    }

    std::vector<FdEventEvent> fdees = result.Ok();
    for (std::vector<FdEventEvent>::const_iterator it = fdees.begin();
        it != fdees.end(); ++it) {
    FdEvent *fde = it->fde;
    unsigned int events = it->events;
    InvokeFdEvent(fde, events, &epoll);
    }
}