#include "Webserv.hpp" #define BUFSIZE 8192 #define MAX_HEADER_SIZE 42000 // arbitrary enum read_return { READ_IN_PROGRESS, READ_COMPLETE, READ_CLOSE, }; void Webserv::_request(Client *client) { int ret = _read_request(client); if (g_last_signal) _handle_last_signal(); if (ret == READ_CLOSE) { _close_client(client->get_cl_fd()); } else if (ret == READ_COMPLETE) { _epoll_update(client->get_cl_fd(), EPOLLOUT, EPOLL_CTL_MOD); } } int Webserv::_read_request(Client *client) // Messy, Need refactoring { char buf[BUFSIZE]; ssize_t ret; std::cerr << "call recv()" << "\n" ; ret = ::recv(client->get_cl_fd(), buf, BUFSIZE, 0); std::cerr << "recv() on fd(" << client->get_cl_fd() << ") returned = " << ret << "\n" ; if (ret == -1) { std::perror("err recv()"); std::cerr << "client ptr =" << client << "\n"; // DEBUG std::cerr << "client.fd =" << client->get_cl_fd() << "\n"; // DEBUG return READ_CLOSE; } if (ret == 0) { std::cerr << "recv() read 0, then close client" << "\n"; // DEBUG return READ_CLOSE; } client->raw_request.append(buf, ret); if (!client->header_complete) { if (client->raw_request.find(CRLF CRLF) != std::string::npos) { // std::cerr << "Raw_request :\n|||||||||||||||||||||||||||||\n " << client->raw_request << "\n|||||||||||||||||||||||||||||\n"; // DEBUG client->header_complete = true; client->parse_request(); // TODO : split function to avoid useless parsing ? if (client->status) // WIP, need to change client->parse_request() for status update return READ_COMPLETE; client->assigned_server = _determine_process_server(client); client->assigned_location = _determine_location(*client->assigned_server, client->get_rq_abs_path()); if (client->get_rq_version().compare(0, sizeof("HTTP/1") - 1, "HTTP/1") != 0) { // TODO : move in Client parsing ? client->status = 505; return READ_COMPLETE; } if (!client->get_rq_headers("Content-Length").empty() && ::atoi(client->get_rq_headers("Content-Length").c_str()) > (int)client->assigned_server->client_body_limit) { client->status = 413; return READ_COMPLETE; } } else if (client->raw_request.size() > MAX_HEADER_SIZE) { client->status = 400; return READ_COMPLETE; } } else if (client->header_complete) { client->read_body_size += ret; if (client->read_body_size > client->assigned_server->client_body_limit) { client->status = 413; return READ_COMPLETE; } if ((int)client->read_body_size >= ::atoi(client->get_rq_headers("Content-Length").c_str())) { client->parse_request(); // reparse for the body return READ_COMPLETE; } } if (client->header_complete && client->get_rq_headers("Content-Type").empty() && client->get_rq_headers("Content-Length").empty() ) { return READ_COMPLETE; } return READ_IN_PROGRESS; }