Skip to content

Commit

Permalink
Merge branch 'master' into 47-loop-per-ticks-for-datatransfer
Browse files Browse the repository at this point in the history
  • Loading branch information
NoelSabia authored Dec 16, 2024
2 parents 5c100a4 + 7e8dd8e commit 4ba2be3
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 32 deletions.
4 changes: 2 additions & 2 deletions include/Config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class Config
void parseServerName(const std::string & line);
void parseRoot(const std::string & line);
void parseIndex(const std::string & line);
void parsemaxPackageSize(const std::string & line);
void parseMaxPackageSize(const std::string & line);
void parseErrorPage(const std::string & line);
void parseClientTimeout(const std::string & line);

Expand Down Expand Up @@ -77,7 +77,7 @@ class Config
int getPort() const { return _port; }
std::string getRootDir() const { return _root_dir; }
FilePath getIndexFile() const { return *_index_file; }
unsigned int getmaxPackageSize() const { return _max_package_size; }
unsigned int getMaxPackageSize() const { return _client_max_body_size; }
std::map<int, FilePath> getErrorPages() const { return _error_pages; }
int getClientTimeout() const { return _client_timeout; }
std::vector<t_location> getLocations() const { return _locations; }
Expand Down
6 changes: 3 additions & 3 deletions src/Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ Config::Config(std::string data)
extractConfigFromBrackets(lines, static_cast<const std::string&>(data));

// 2. parse each line, based on starting keyword
std::array<std::string, CONFIG_KEYWORD_COUNT> keywords = {"listen", "server_name", "root", "index", "max_package_size", "error_page", "location", "client_timeout"};
std::array<void (Config::*)(const std::string&), CONFIG_KEYWORD_COUNT> parsers = {&Config::parseListen, &Config::parseServerName, &Config::parseRoot, &Config::parseIndex, &Config::parsemaxPackageSize, &Config::parseErrorPage, &Config::parseLocation, &Config::parseClientTimeout};
std::array<std::string, CONFIG_KEYWORD_COUNT> keywords = {"listen", "server_name", "root", "index", "client_max_body_size", "error_page", "location", "client_timeout"};
std::array<void (Config::*)(const std::string&), CONFIG_KEYWORD_COUNT> parsers = {&Config::parseListen, &Config::parseServerName, &Config::parseRoot, &Config::parseIndex, &Config::parseMaxPackageSize, &Config::parseErrorPage, &Config::parseLocation, &Config::parseClientTimeout};
for (std::string &line : lines)
{
std::string keyword = line.substr(0, line.find(' '));
Expand Down Expand Up @@ -138,7 +138,7 @@ void Config::parseIndex(const std::string & line)
#endif
}

void Config::parsemaxPackageSize(const std::string & line)
void Config::parseMaxPackageSize(const std::string & line)
{
std::regex size_regex(R"(max_package_size\s+(\d+)\s*([KMG]?B);)", std::regex::icase);
std::smatch match;
Expand Down
85 changes: 81 additions & 4 deletions src/Packets/Methods/Delete.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,85 @@
#include "Response.hpp"
#include <dirent.h>

void Response::handleDelete(Request& req, Config &config)
{
(void)config;
(void)req;
std::cout << "DELETE request received" << std::endl;
}
std::string content = req.getBody();
std::string path = req.getPath();

setVersion("HTTP/1.1");

t_location location = get_location(config, Path(path, Path::Type::URL, config).asFilePath());

if (!get_location(config, Path(path, Path::Type::URL, config).asUrl()).allowed_methods[static_cast<int>(Method::DELETE)])
{
std::cerr << "DELETE method not allowed" << std::endl;
setStatus(Status::Forbidden);
setBody("DELETE method not allowed");
return;
}

// FIXME: sometimes the path is corrent and sometimes not
path = "." + location.root_dir + path;
std::cout << "Path: " << path << std::endl;

// delete file
if(path[path.length() - 1] != '/')
{
std::cout << "Trying to delete file: " << path << std::endl;
if (remove(path.c_str()) != 0)
{
std::cerr << "Error deleting file" << std::endl;
setStatus(Status::Forbidden);
setBody("Error deleting file");
}
else
{
setStatus(Status::OK);
setBody("File deleted");
}
return;
}

// delete directory
DIR *dir;
struct dirent *ent;

std::cout << "Trying to delete directory: " << path << std::endl;

if ((dir = opendir(path.c_str())) != NULL)
{
while ((ent = readdir(dir)) != NULL)
{
std::string file = ent->d_name;
if (file != "." && file != "..")
{
std::string filepath = path + file;
if (remove(filepath.c_str()) != 0)
{
std::cerr << "Error deleting file" << std::endl;
setStatus(Status::Forbidden);
setBody("Error deleting file");
return;
}
}
}
closedir(dir);
if (rmdir(path.c_str()) != 0)
{
std::cerr << "Error deleting directory" << std::endl;
setStatus(Status::Forbidden);
setBody("Error deleting directory");
}
else
{
setStatus(Status::OK);
setBody("Directory deleted");
}
}
else
{
std::cerr << "Error opening directory" << std::endl;
setStatus(Status::Forbidden);
setBody("Error opening directory");
}
}
17 changes: 8 additions & 9 deletions src/Packets/Methods/Post.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,11 @@

void Response::handlePost(Request& req, Config &config)
{
(void)config;

// TODO: Check if on route POST is allowed
// reutrn 405 (FORBIDDEN) if not allowed
std::cout << "Handling POST request" << std::endl;

std::string content = req.getBody();
std::string path = req.getPath();
int content_length;
size_t content_length;

setVersion("HTTP/1.1");

Expand All @@ -35,7 +32,7 @@ void Response::handlePost(Request& req, Config &config)
return;
}

content_length = std::stoi(req.getHeaders()["Content-Length"]);
content_length = std::stoul(req.getHeaders()["Content-Length"]);

if (req.getHeaders().find("Content-Type") == req.getHeaders().end())
{
Expand All @@ -49,8 +46,8 @@ void Response::handlePost(Request& req, Config &config)
try
{
Path filepath = Path(req.getPath(), Path::Type::URL, config);
if (req.getHeaders().find("X-Filename") != req.getHeaders().end())
filename = filepath.asFilePath() + req.getHeaders()["X-Filename"];
if (req.getHeaders().find("Content-Filename") != req.getHeaders().end())
filename = filepath.asFilePath() + req.getHeaders()["Content-Filename"];
else
filename = filepath.asFilePath() + "default";
}
Expand Down Expand Up @@ -81,6 +78,7 @@ void Response::handlePost(Request& req, Config &config)
return ;
}
filename += "." + extension;
filename = "." + filename;

std::cout << "Filename: " << filename << std::endl;

Expand All @@ -100,7 +98,8 @@ void Response::handlePost(Request& req, Config &config)
if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
throw std::runtime_error("Failed to set non-blocking mode");

if (write(fd, content.c_str(), content_length) == -1)
(void)content_length; // TODO: use content_length instead of content.length() for it to be technically correct cuz we gotta use that what it says in the header
if (write(fd, content.c_str(), content.length()) == -1)
{
close(fd);
std::cerr << "Error writing to file" << std::endl;
Expand Down
23 changes: 10 additions & 13 deletions src/Server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ void Server::updatePoll()
fds.push_back(listen_pfd);

// poll
int ret = poll(fds.data(), fds.size(), 100);
int ret = poll(fds.data(), fds.size(), 10);
if (ret < 0)
{
Logger::Log(LogLevel::ERROR, "Poll error: " + std::string(strerror(errno)) + " -> means that there is no data to read.");
Expand All @@ -52,20 +52,15 @@ void Server::updatePoll()
bool Server::isDataComplete(t_socket_data &socket)
{
std::string data = socket.buffer.str();

// Step 1: Ensure buffer is not giant
if (data.size() > _config.getmaxPackageSize())
throw std::runtime_error("Client data size exceeded maximum body size");

size_t headerEnd = data.find("\r\n\r\n");
if (headerEnd == std::string::npos)
return false;

// Step 2: Check for complete content (chunked transfer encoding)
// Chunked transfer encoding
if (data.find("Transfer-Encoding: chunked") != std::string::npos)
return data.find("0\r\n\r\n") != std::string::npos;

// Step 3: Check for complete content (normal packets)
// Normal packet
if (data.find("Content-Length: ") != std::string::npos)
{
size_t headerEnd = data.find("\r\n\r\n");
Expand All @@ -79,11 +74,7 @@ bool Server::isDataComplete(t_socket_data &socket)
}
}

// Step 4: Check for stale packet
// ...
// TODO

return true; // Step 5: No body & header is done
return true;
}

void Server::acceptNewConnections()
Expand Down Expand Up @@ -123,6 +114,12 @@ void Server::handleExistingConnections()
try
{
_sockets[i].buffer << _sockets[i].socket.receiveData();
if (_sockets[i].buffer.str().size() > _config.getMaxPackageSize())
{
Logger::Log(LogLevel::ERROR, "Client data size exceeded maximum body size");
_sockets.erase(_sockets.begin() + i);
continue;
}
_sockets[i].last_activity = std::chrono::steady_clock::now();
}
catch(const std::runtime_error &e)
Expand Down
2 changes: 1 addition & 1 deletion src/Socket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ void Socket::sendData(Response &response)
std::string Socket::receiveData()
{
std::string data;
int size = std::min(1024, static_cast<int>(_config.getmaxPackageSize() + 1));
int size = std::min(1048576, static_cast<int>(_config.getMaxPackageSize() + 1));
char buffer[size];
ssize_t received;

Expand Down

0 comments on commit 4ba2be3

Please sign in to comment.