redone _read_request(). Should work with any BUFSIZE.

+ WIP in some aspects. Need to adjust parse_request() among others things.
+ update memo.txt
This commit is contained in:
LuckyLaszlo
2022-08-07 05:41:01 +02:00
parent 8ec1353723
commit 4ab099ee4d
4 changed files with 75 additions and 13 deletions

View File

@@ -1,6 +1,16 @@
IN 42 SUBJECT, PRIORITY :
- do correct handling of special character in url (/rfc2119_files/errata.js.t%C3%A9l%C3%A9chargement -> /rfc2119_files/errata.js.téléchargement) - 505 HTTP Version Not Supported
- CGI
- handle redirection - 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 - 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 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)} if (actual_time - client.last_action_time > 10000ms){timeout(client)}

View File

@@ -5,7 +5,12 @@
* COPLIENS * COPLIENS
*********************************************/ *********************************************/
Client::Client() : fd(0), status(0) { Client::Client()
: fd(0),
status(0),
header_complete(false),
read_body_size(0)
{
return; return;
} }
@@ -52,6 +57,8 @@ void Client::parse_request()
void Client::clear() void Client::clear()
{ {
clear_request(); clear_request();
header_complete = false;
read_body_size = 0;
raw_request.clear(); raw_request.clear();
response.clear(); response.clear();
status = 0; status = 0;
@@ -125,6 +132,8 @@ void Client::_parse_request_headers( std::vector<std::string> list )
void Client::_parse_request_body( size_t pos ) 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]; std::string body = &raw_request[pos];
_request.body = body; _request.body = body;

View File

@@ -31,6 +31,9 @@ class Client
unsigned int status; unsigned int status;
listen_socket *lsocket; listen_socket *lsocket;
bool header_complete;
size_t read_body_size;
// const functions ? // const functions ?
http_method get_method(); http_method get_method();
std::string &get_path(); std::string &get_path();

View File

@@ -2,6 +2,8 @@
#include "Webserv.hpp" #include "Webserv.hpp"
#define BUFSIZE 8192 #define BUFSIZE 8192
#define MAX_HEADER_SIZE 42000
#define MAX_BODY_SIZE 500000 // test macro, replace with server config
void Webserv::_request(Client *client) void Webserv::_request(Client *client)
{ {
@@ -12,9 +14,10 @@ void Webserv::_request(Client *client)
void Webserv::_read_request(Client *client) void Webserv::_read_request(Client *client)
{ {
char buf[BUFSIZE+1]; char buf[BUFSIZE];
ssize_t ret; ssize_t ret;
std::cerr << "call recv()" << "\n" ;
ret = ::recv(client->fd, buf, BUFSIZE, 0); ret = ::recv(client->fd, buf, BUFSIZE, 0);
std::cerr << "recv() on fd(" << client->fd << ") returned = " << ret << "\n" ; std::cerr << "recv() on fd(" << client->fd << ") returned = " << ret << "\n" ;
if (ret == -1) if (ret == -1)
@@ -25,20 +28,57 @@ void Webserv::_read_request(Client *client)
_close_client(client->fd); _close_client(client->fd);
return ; return ;
} }
if (ret == 0) // Not sure what to do in case of 0. Just close ? if (ret == 0)
{ {
_close_client(client->fd); _close_client(client->fd);
return ; return ;
} }
/*
if (ret == BUFSIZE)
// send error like "request too long" to client
*/
buf[ret] = '\0'; client->raw_request.append(buf, ret);
client->raw_request.append(buf); if (!client->header_complete)
client->parse_request(); {
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;
}
} }