🏗️」 wip: Socket creation should be working

This commit is contained in:
2025-04-17 13:12:46 +02:00
parent a407ee51a3
commit b98bec117b
8 changed files with 178 additions and 79 deletions

View File

@ -6,8 +6,7 @@
# By: adjoly <adjoly@student.42angouleme.fr> +#+ +:+ +#+ # # By: adjoly <adjoly@student.42angouleme.fr> +#+ +:+ +#+ #
# +#+#+#+#+#+ +#+ # # +#+#+#+#+#+ +#+ #
# Created: 2024/10/25 16:09:27 by adjoly #+# #+# # # Created: 2024/10/25 16:09:27 by adjoly #+# #+# #
# Updated: 2025/04/10 11:52:13 by mmoussou ### ########.fr # # Updated: 2025/04/15 17:53:00 by adjoly ### ########.fr #
# Updated: 2025/03/25 18:13:53 by adjoly ### ########.fr #
# # # #
# **************************************************************************** # # **************************************************************************** #

View File

@ -1,8 +1,9 @@
log_file = "test.log"
[server] [server]
server_names = { "localhost", "2B5.local" } server_names = { "localhost", "2B5.local" }
host = "localhost" host = "localhost"
port = 8080 port = 8080
log_file = "test.log"
[server.error_pages] [server.error_pages]
404 = "not_found.html" 404 = "not_found.html"

View File

@ -1,12 +1,12 @@
/* ************************************************************************** */ /* ************************************************************************** */
/* */ /* */
/* ::: :::::::: */ /* ::: :::::::: */
/* server.hpp :+: :+: :+: */ /* Server.hpp :+: :+: :+: */
/* +:+ +:+ +:+ */ /* +:+ +:+ +:+ */
/* By: adjoly <adjoly@student.42angouleme.fr> +#+ +:+ +#+ */ /* By: adjoly <adjoly@student.42angouleme.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2025/04/11 17:45:43 by adjoly #+# #+# */ /* Created: 2025/04/11 17:45:43 by adjoly #+# #+# */
/* Updated: 2025/04/14 14:21:41 by adjoly ### ########.fr */ /* Updated: 2025/04/17 11:48:36 by adjoly ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@ -45,11 +45,26 @@ class Server {
*/ */
void _handle_client(Client); void _handle_client(Client);
/**
* @brief Can be used to fill the vector passed as parameters with all the
* port and host in the config
* @param The vector of host
* @param The vector of port
*/
int _fillHostsPorts(std::vector<std::string> &, std::vector<int> &);
/**
* @brief Can be used to open a socket with a specific port and host
* @param The host
* @param The port
*/
int _createSocket(std::string, int);
config::Config config::Config
*_conf; ///> Pointer to the configuration class (with all config in) *_conf; // Pointer to the configuration class (with all config in)
Logger *_log; ///> Pointer to the log class Logger *_log; // Pointer to the log class
int _fd_server; ///> The fd of the socket std::vector<int> _fds_server; // The fds of the sockets
std::vector<struct pollfd> _client_fds; ///> A vector of all the poll fd std::vector<struct pollfd> _client_fds; // A vector of all the poll fd
}; };
}; // namespace webserv }; // namespace webserv

View File

@ -6,13 +6,14 @@
/* By: mmoussou <mmoussou@student.42angouleme.fr +#+ +:+ +#+ */ /* By: mmoussou <mmoussou@student.42angouleme.fr +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2025/02/11 13:29:05 by mmoussou #+# #+# */ /* Created: 2025/02/11 13:29:05 by mmoussou #+# #+# */
/* Updated: 2025/04/11 18:06:05 by adjoly ### ########.fr */ /* Updated: 2025/04/17 11:05:59 by adjoly ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#pragma once #pragma once
#include "server.hpp" #include "Server.hpp"
#include "Client.hpp"
namespace webserv { namespace webserv {

20
src/Client.cpp Normal file
View File

@ -0,0 +1,20 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* Client.cpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: adjoly <adjoly@student.42angouleme.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/04/15 14:44:55 by adjoly #+# #+# */
/* Updated: 2025/04/15 18:38:42 by adjoly ### ########.fr */
/* */
/* ************************************************************************** */
#include <config/default.hpp>
#include <netinet/in.h>
#include <server/Client.hpp>
Client::Client(int fd, sockaddr_in sockData, config::Config *conf)
: _fd(fd), _client_addr(sockData) {
}

View File

@ -6,7 +6,7 @@
/* By: adjoly <adjoly@student.42angouleme.fr> +#+ +:+ +#+ */ /* By: adjoly <adjoly@student.42angouleme.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2025/03/24 15:10:07 by adjoly #+# #+# */ /* Created: 2025/03/24 15:10:07 by adjoly #+# #+# */
/* Updated: 2025/04/14 12:57:30 by adjoly ### ########.fr */ /* Updated: 2025/04/17 11:22:20 by adjoly ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@ -29,7 +29,7 @@ Server::Server(toml::ANode *node, Logger *log) : _table(node), _log(log) {
} }
// port parsing // port parsing
void *port = accessValue("port", toml::INT, _table, _log); void *port = accessValue("port", toml::INT, _table, _log);
if (host != not_nullptr) { if (port != not_nullptr) {
_port = *static_cast<unsigned short *>(port); _port = *static_cast<unsigned short *>(port);
} else { } else {
delete _table; delete _table;

View File

@ -6,100 +6,98 @@
/* By: adjoly <adjoly@student.42angouleme.fr> +#+ +:+ +#+ */ /* By: adjoly <adjoly@student.42angouleme.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2025/04/11 16:11:40 by adjoly #+# #+# */ /* Created: 2025/04/11 16:11:40 by adjoly #+# #+# */
/* Updated: 2025/04/14 14:07:36 by adjoly ### ########.fr */ /* Updated: 2025/04/17 12:37:45 by adjoly ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include <cmath> #include <cmath>
#include <log.hpp> #include <log.hpp>
#include <netinet/in.h> #include <netinet/in.h>
#include <requests/default.hpp>
#include <server/default.hpp> #include <server/default.hpp>
#include <sstream>
#include <stdexcept> #include <stdexcept>
#include <sys/socket.h> #include <sys/socket.h>
#include <webserv.hpp> #include <webserv.hpp>
#include <requests/default.hpp>
using namespace webserv; using namespace webserv;
std::string getMethod(std::string &data) std::string getMethod(std::string &data) {
{
return (data.substr(0, data.substr(0, 4).find_last_not_of(" ") + 1)); return (data.substr(0, data.substr(0, 4).find_last_not_of(" ") + 1));
} }
void Server::_handle_client(int fd) void Server::_handle_client(int fd) {
{
(void) fd;
std::string received_data; std::string received_data;
char buffer[BUFFER_SIZE]; char buffer[BUFFER_SIZE];
ssize_t bytes_received; ssize_t bytes_received;
do do {
{
std::memset(buffer, 0, BUFFER_SIZE); std::memset(buffer, 0, BUFFER_SIZE);
bytes_received = recv(fd, buffer, BUFFER_SIZE - 1, 0); bytes_received = recv(fd, buffer, BUFFER_SIZE - 1, 0);
if (bytes_received == -1) if (bytes_received == -1) {
{
_log->error("failed to receive request"); _log->error("failed to receive request");
continue; continue;
} }
received_data += std::string(buffer, bytes_received); received_data += std::string(buffer, bytes_received);
} } while (buffer[bytes_received]);
while (buffer[bytes_received]);
std::string response; std::string response;
if (getMethod(received_data) == "GET") if (getMethod(received_data) == "GET") {
{
_log->info("get request received"); _log->info("get request received");
http::Get request(received_data); http::Get request(received_data);
response = request.execute().str(); response = request.execute().str();
} } else if (getMethod(received_data) == "DELETE") {
else if (getMethod(received_data) == "DELETE")
{
_log->info("delete request received"); _log->info("delete request received");
http::Delete request(received_data); http::Delete request(received_data);
response = request.execute().str(); response = request.execute().str();
} } else if (getMethod(received_data) == "POST") {
else if (getMethod(received_data) == "POST")
{
_log->info("post request received"); _log->info("post request received");
http::Post request(received_data); http::Post request(received_data);
response = request.execute().str(); response = request.execute().str();
} } else {
else response = "HTTP/1.1 501 Not Implemented\r\nContent-Type: "
{ "text/html\r\n\r\n<html><body><h1>501 Not "
response = "HTTP/1.1 501 Not Implemented\r\nContent-Type: text/html\r\n\r\n<html><body><h1>501 Not Implemented</h1></body></html>"; "Implemented</h1></body></html>";
} }
send(fd, response.c_str(), response.length(), 0); send(fd, response.c_str(), response.length(), 0);
} }
void Server::_setup(void) { int Server::_fillHostsPorts(std::vector<std::string> &hosts,
_fd_server = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); std::vector<int> &ports) {
if (_fd_server == -1) std::vector<config::Server *> *config = _conf->getServers();
throw std::runtime_error("error at socket setup");
struct sockaddr_in addr; for (std::vector<config::Server *>::iterator it = config->begin();
addr.sin_family = AF_INET; it != config->end(); it++) {
addr.sin_addr.s_addr = INADDR_ANY; hosts.push_back((*it)->getHost());
addr.sin_port = htons(_conf->getPort()); ports.push_back((*it)->getPort());
if (bind(_fd_server, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
close(_fd_server);
throw std::runtime_error("error when binding address");
} }
return config->size();
}
if (listen(_fd_server, SOMAXCONN) < 0) { void Server::_setup(void) {
close(_fd_server); std::vector<std::string> hosts;
throw std::runtime_error("error when listening"); std::vector<int> ports;
int size = _fillHostsPorts(hosts, ports);
if (size < 1)
throw std::runtime_error("no server present in the config file");
std::vector<std::string>::iterator itH = hosts.begin();
for (std::vector<int>::iterator itP = ports.begin(); itP != ports.end(); itP++, itH++) {
try {
int fd = _createSocket(*itH, *itP);
_fds_server.push_back(fd);
} catch (std::exception &e) {
throw e;
}
} }
} }
void Server::_run(void) void Server::_run(void) {
{
struct pollfd fd; struct pollfd fd;
fd.fd = _fd_server; fd.fd = _fd_server;
@ -109,22 +107,19 @@ void Server::_run(void)
int nbr_client = 0; int nbr_client = 0;
while (727) while (727) {
{
int ret = poll(_client_fds.data(), nbr_client + 1, -1); int ret = poll(_client_fds.data(), nbr_client + 1, -1);
if (ret < 0) if (ret < 0) {
{
close(_fd_server); close(_fd_server);
throw std::runtime_error("poll failed :("); throw std::runtime_error("poll failed :(");
} }
if (_client_fds[0].revents & POLLIN) if (_client_fds[0].revents & POLLIN) {
{
struct sockaddr_in client_addr; struct sockaddr_in client_addr;
socklen_t addrlen = sizeof(client_addr); socklen_t addrlen = sizeof(client_addr);
int client_fd = accept(_fd_server, (struct sockaddr *)&client_addr, &addrlen); int client_fd =
if (client_fd < 0) accept(_fd_server, (struct sockaddr *)&client_addr, &addrlen);
{ if (client_fd < 0) {
_log->error("accept failed"); _log->error("accept failed");
continue; continue;
} }
@ -136,16 +131,13 @@ void Server::_run(void)
// if (nbr_client) TODO do we need a max client probably not :D // if (nbr_client) TODO do we need a max client probably not :D
} }
for (int i = 1; i <= nbr_client; ) for (int i = 1; i <= nbr_client;) {
{ if (_client_fds[i].revents & POLLIN) {
if (_client_fds[i].revents & POLLIN)
{
_handle_client(_client_fds[i].fd); _handle_client(_client_fds[i].fd);
close(_client_fds[i].fd); close(_client_fds[i].fd);
_client_fds[i] = _client_fds[nbr_client--]; _client_fds[i] = _client_fds[nbr_client--];
_client_fds.pop_back(); _client_fds.pop_back();
} } else
else
++i; ++i;
} }
} }

71
src/socket.cpp Normal file
View File

@ -0,0 +1,71 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* socket.cpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: adjoly <adjoly@student.42angouleme.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/04/17 11:58:42 by adjoly #+# #+# */
/* Updated: 2025/04/17 12:35:31 by adjoly ### ########.fr */
/* */
/* ************************************************************************** */
#include <server/default.hpp>
#include <sys/socket.h>
using namespace webserv;
bool convertStringToIP(const char *ip_str, struct in_addr *addr) {
// Split the IP string into four octets
unsigned int a, b, c, d;
if (sscanf(ip_str, "%u.%u.%u.%u", &a, &b, &c, &d) != 4) {
return false;
}
// Check if each octet is within the valid range
if (a > 255 || b > 255 || c > 255 || d > 255) {
return false;
}
// Combine the octets into a single 32-bit address
addr->s_addr = htonl((a << 24) | (b << 16) | (c << 8) | d);
return true;
}
int Server::_createSocket(std::string host, int port) {
int fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
if (fd == -1) {
std::ostringstream str;
str << port;
throw std::runtime_error("socket binding failed for : " + host + ":" +
str.str());
}
return -1;
int opt = 1;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
close(fd);
throw std::runtime_error("setsockopt failed");
}
struct sockaddr_in addr;
addr.sin_family = AF_INET;
convertStringToIP(host.c_str(), &addr.sin_addr);
addr.sin_port = htons(port);
if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
close(fd);
std::ostringstream str;
str << port;
throw std::runtime_error("bind failed for : " + host + ":" + str.str());
}
if (listen(fd, SOMAXCONN) < 0) {
close(fd);
std::ostringstream str;
str << port;
throw std::runtime_error("listen failed for : " + host + ":" + str.str());
}
return (fd);
}