reactie van server

This commit is contained in:
2026-09-13 13:13:33 +02:00
parent 72d072bb6c
commit 2114e11f90
5 changed files with 110 additions and 28 deletions
+2 -2
View File
@@ -56,7 +56,7 @@ SRCS := src/Log.cpp src/main.cpp src/Server.cpp \
src/config/Config.cpp src/config/ConfigurationParser.cpp src/config/LocationConfig.cpp src/config/ServerConfig.cpp \
src/event/Epoll.cpp src/event/EventToken.cpp \
src/net/ByteBuffer.cpp src/net/Connection.cpp src/net/FileDescriptor.cpp src/net/Listener.cpp src/net/ListenerPlan.cpp src/net/PauseMask.cpp src/net/SlotPool.cpp \
src/http/Request.cpp src/http/RequestParser.cpp
src/http/Request.cpp src/http/RequestParser.cpp src/http/Response.cpp
OBJS := $(SRCS:$(SRC_DIR)/%.cpp=$(OBJ_DIR)/%.o)
@@ -66,7 +66,7 @@ SRCS := src/Log.cpp src/main.cpp src/Server.cpp \
DEPS := $(OBJS:.o=.d)
HDRS := include/config/Config.hpp include/config/ConfigurationParser.hpp include/config/LocationConfig.hpp include/config/ServerConfig.hpp \
include/event/Epoll.hpp include/event/EventToken.hpp \
include/http/HttpStatus.hpp include/http/Request.hpp include/http/RequestParser.hpp \
include/http/HttpStatus.hpp include/http/Request.hpp include/http/RequestParser.hpp include/http/Response.hpp \
include/net/ByteBuffer.hpp include/net/Connection.hpp include/net/FileDescriptor.hpp include/net/Listener.hpp include/net/ListenerPlan.hpp include/net/PauseMask.hpp include/net/SlotPool.hpp \
include/Log.hpp include/Result.hpp include/Server.hpp \
+30
View File
@@ -0,0 +1,30 @@
/*********************************/
/* */
/* o.riabenkyi@gmail.com */
/* */
/*********************************/
#ifndef RESPONSE_HPP
#define RESPONSE_HPP
#include <string>
#include <utility>
#include <vector>
#include "http/HttpStatus.hpp"
namespace webserv {
const char* reasonPhrase(HttpStatus status) noexcept;
struct Response {
HttpStatus status;
std::vector<std::pair<std::string, std::string>> headers;
std::vector<char> body;
};
std::vector<char> serialize(const Response& response);
} // namespace webserv
#endif
-12
View File
@@ -29,15 +29,9 @@ class Connection final {
std::uint32_t desiredEvents;
};
// ByteBuffer::CAPACITY is 64 KiB.
// At most 16 KiB are copied per 48 KiB appended: 16 / 48 = 1 / 3.
// A lower threshold reduces copying but leaves less unread work available.
// The 16 KiB value is a fixed compromise, not a measured optimum.
static constexpr std::size_t LOW_WATERMARK = 16uz * 1024;
explicit Connection(FileDescriptor socket);
// Each Connection has a unique identity and remains in its original slot.
Connection(const Connection&) = delete;
Connection& operator=(const Connection&) = delete;
Connection(Connection&&) = delete;
@@ -52,14 +46,8 @@ class Connection final {
void close() noexcept { socket_.reset(); }
private:
// recv() returning zero means the client has finished sending data.
// readClosed_ records this. receive() still returns true because this
// is not an error and the socket may still send its buffered response.
// Only a recv() error returns false.
bool receive();
bool transmit();
// TEMP echo path: queues received bytes unchanged for sending back to
// the client.
void forwardReceivedBytes();
FileDescriptor socket_;
+78
View File
@@ -0,0 +1,78 @@
/*********************************/
/* */
/* o.riabenkyi@gmail.com */
/* */
/*********************************/
#include "http/Response.hpp"
#include <format>
namespace webserv {
const char* reasonPhrase(HttpStatus status) noexcept {
switch (status) {
case HttpStatus::Ok:
return "OK";
case HttpStatus::Created:
return "Created";
case HttpStatus::NoContent:
return "No Content";
case HttpStatus::MovedPermanently:
return "Moved Permanently";
case HttpStatus::Found:
return "Found";
case HttpStatus::SeeOther:
return "See Other";
case HttpStatus::TemporaryRedirect:
return "Temporary Redirect";
case HttpStatus::PermanentRedirect:
return "Permanent Redirect";
case HttpStatus::BadRequest:
return "Bad Request";
case HttpStatus::Forbidden:
return "Forbidden";
case HttpStatus::NotFound:
return "Not Found";
case HttpStatus::MethodNotAllowed:
return "Method Not Allowed";
case HttpStatus::RequestTimeout:
return "Request Timeout";
case HttpStatus::LengthRequired:
return "Length Required";
case HttpStatus::ContentTooLarge:
return "Content Too Large";
case HttpStatus::UriTooLong:
return "URI Too Long";
case HttpStatus::RequestHeaderFieldsTooLarge:
return "Request Header Fields Too Large";
case HttpStatus::InternalServerError:
return "Internal Server Error";
case HttpStatus::NotImplemented:
return "Not Implemented";
case HttpStatus::BadGateway:
return "Bad Gateway";
case HttpStatus::ServiceUnavailable:
return "Service Unavailable";
case HttpStatus::GatewayTimeout:
return "Gateway Timeout";
case HttpStatus::HttpVersionNotSupported:
return "HTTP Version Not Supported";
}
return "Unknown Status";
}
std::vector<char> serialize(const Response& response) {
std::string head = std::format("HTTP/1.1 {} {}\r\n", static_cast<int>(response.status),
reasonPhrase(response.status));
for (const auto& [name, value] : response.headers) {
head += std::format("{}: {}\r\n", name, value);
}
head += std::format("Content-Length: {}\r\n\r\n", response.body.size());
std::vector<char> bytes(head.begin(), head.end());
bytes.insert(bytes.end(), response.body.begin(), response.body.end());
return bytes;
}
} // namespace webserv
-14
View File
@@ -24,16 +24,6 @@ namespace webserv {
namespace {
// Writable tail still has space -> keep using it
//
// Writable tail is exhausted, but more than 16 KiB are still live
// -> wait for more bytes to be consumed because moving them is not worth it
//
// Writable tail is exhausted and at most 16 KiB are still live
// -> move the live bytes to the start and recover the writable tail
//
// Before: [ 48 KiB consumed ][ 16 KiB live ]
// After: [ 16 KiB live ][ 48 KiB writable tail ]
void compactIfDrained(ByteBuffer& buffer) {
if (buffer.writableTail().empty() &&
buffer.readable().size() <= Connection::LOW_WATERMARK) {
@@ -45,10 +35,6 @@ void compactIfDrained(ByteBuffer& buffer) {
Connection::Connection(FileDescriptor socket) : socket_(std::move(socket)) {}
// Client can still send data -> Alive
// Read side closed, buffered data remains -> Alive
// Read side closed, both buffers empty -> Done
// recv() or send() failed -> Fatal
Connection::Outcome Connection::onClientEvent(std::uint32_t events) {
// 1) Interpret the readiness reported by epoll.
// EPOLLIN says recv() may progress.