From 4ab099ee4d406fe51e30c04278a0ffe678b440e2 Mon Sep 17 00:00:00 2001 From: LuckyLaszlo Date: Sun, 7 Aug 2022 05:41:01 +0200 Subject: [PATCH] redone _read_request(). Should work with any BUFSIZE. + WIP in some aspects. Need to adjust parse_request() among others things. + update memo.txt --- memo.txt | 14 ++++++++-- srcs/Client.cpp | 11 +++++++- srcs/Client.hpp | 3 ++ srcs/webserv/request.cpp | 60 +++++++++++++++++++++++++++++++++------- 4 files changed, 75 insertions(+), 13 deletions(-) diff --git a/memo.txt b/memo.txt index dd03cec..03ec750 100644 --- a/memo.txt +++ b/memo.txt @@ -1,6 +1,16 @@ - -- do correct handling of special character in url (/rfc2119_files/errata.js.t%C3%A9l%C3%A9chargement -> /rfc2119_files/errata.js.téléchargement) +IN 42 SUBJECT, PRIORITY : +- 505 HTTP Version Not Supported +- CGI - handle redirection +- index and autoindex +- gestion memoire en cas de bad_alloc +- Ecrire des tests ! +----------------------------- +- replace atoi() with a better function +- 408 Request Timeout +- gerer le champ "Accept" du client +- gerer les ".." dans un URL (verifier que l'on ne sort pas du dossier "root") +- do correct handling of special character in url (/rfc2119_files/errata.js.t%C3%A9l%C3%A9chargement -> /rfc2119_files/errata.js.téléchargement) - maybe add a "last_action_time" in Client for timeout handling little global timeout on epoll, like 100ms, then find client that actualy need to timeout if (actual_time - client.last_action_time > 10000ms){timeout(client)} diff --git a/srcs/Client.cpp b/srcs/Client.cpp index c63cc91..0d7b7d7 100644 --- a/srcs/Client.cpp +++ b/srcs/Client.cpp @@ -5,7 +5,12 @@ * COPLIENS *********************************************/ -Client::Client() : fd(0), status(0) { +Client::Client() + : fd(0), + status(0), + header_complete(false), + read_body_size(0) +{ return; } @@ -52,6 +57,8 @@ void Client::parse_request() void Client::clear() { clear_request(); + header_complete = false; + read_body_size = 0; raw_request.clear(); response.clear(); status = 0; @@ -125,6 +132,8 @@ void Client::_parse_request_headers( std::vector list ) void Client::_parse_request_body( size_t pos ) { + // TODO : a revoir avec une std::string, + // pour ne pas avoir le probleme d'un '0' qui marque la fin des données std::string body = &raw_request[pos]; _request.body = body; diff --git a/srcs/Client.hpp b/srcs/Client.hpp index eee05aa..84eb82d 100644 --- a/srcs/Client.hpp +++ b/srcs/Client.hpp @@ -31,6 +31,9 @@ class Client unsigned int status; listen_socket *lsocket; + bool header_complete; + size_t read_body_size; + // const functions ? http_method get_method(); std::string &get_path(); diff --git a/srcs/webserv/request.cpp b/srcs/webserv/request.cpp index 34338fb..4f5c39f 100644 --- a/srcs/webserv/request.cpp +++ b/srcs/webserv/request.cpp @@ -2,6 +2,8 @@ #include "Webserv.hpp" #define BUFSIZE 8192 +#define MAX_HEADER_SIZE 42000 +#define MAX_BODY_SIZE 500000 // test macro, replace with server config void Webserv::_request(Client *client) { @@ -12,9 +14,10 @@ void Webserv::_request(Client *client) void Webserv::_read_request(Client *client) { - char buf[BUFSIZE+1]; + char buf[BUFSIZE]; ssize_t ret; + std::cerr << "call recv()" << "\n" ; ret = ::recv(client->fd, buf, BUFSIZE, 0); std::cerr << "recv() on fd(" << client->fd << ") returned = " << ret << "\n" ; if (ret == -1) @@ -25,20 +28,57 @@ void Webserv::_read_request(Client *client) _close_client(client->fd); return ; } - if (ret == 0) // Not sure what to do in case of 0. Just close ? + if (ret == 0) { _close_client(client->fd); return ; } - /* - if (ret == BUFSIZE) - // send error like "request too long" to client - */ - buf[ret] = '\0'; - client->raw_request.append(buf); - client->parse_request(); + client->raw_request.append(buf, ret); + if (!client->header_complete) + { + if (client->raw_request.find(CRLF CRLF) != std::string::npos) + { + client->header_complete = true; + client->parse_request(); // TODO : split function to avoid useless parsing ? + // TODO : determine server here for body size limit + if (!client->get_headers("Content-Length").empty() + && ::atoi(client->get_headers("Content-Length").c_str()) > MAX_BODY_SIZE) + { + client->status = 413; + _epoll_update(client->fd, EPOLLOUT, EPOLL_CTL_MOD); + return; + } + } + else if (client->raw_request.size() > MAX_HEADER_SIZE) + { + client->status = 400; + _epoll_update(client->fd, EPOLLOUT, EPOLL_CTL_MOD); + return; + } + } + else if (client->header_complete) + { + client->read_body_size += ret; + if (client->read_body_size > MAX_BODY_SIZE) + { + client->status = 413; + _epoll_update(client->fd, EPOLLOUT, EPOLL_CTL_MOD); + return; + } + if ((int)client->read_body_size > ::atoi(client->get_headers("Content-Length").c_str())) + { + client->parse_request(); // reparse for the body + _epoll_update(client->fd, EPOLLOUT, EPOLL_CTL_MOD); + return; + } + } - _epoll_update(client->fd, EPOLLOUT, EPOLL_CTL_MOD); + + if (client->header_complete && client->get_headers("Content-Type").empty() && client->get_headers("Content-Length").empty() ) + { + _epoll_update(client->fd, EPOLLOUT, EPOLL_CTL_MOD); + return; + } }