own-redis/src/server.cpp
Илья Глазунов c0228b0c12 logger added
2026-01-11 00:23:04 +03:00

122 lines
3.6 KiB
C++

#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <iostream>
#include "server.hpp"
#include "net_util.hpp"
#include "constants.hpp"
#include "utils.hpp"
#include "logger.hpp"
Server::Server(const Config& config)
: address(config.get_address()), port(config.get_port()), sockfd(-1) {
}
Server::~Server() {
if (sockfd != -1) {
close(sockfd);
}
}
void Server::setup() {
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
throw std::runtime_error("Error creating socket");
}
int val = 1;
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
sockaddr_in addr{};
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
if (inet_pton(AF_INET, address.c_str(), &addr.sin_addr) != 1) {
throw std::runtime_error("Error parsing address: " + address);
}
if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
throw std::runtime_error("Error binding to " + address + ":" + std::to_string(port));
}
if (listen(sockfd, SOMAXCONN) < 0) {
throw std::runtime_error("Error listening for connections");
}
Logger::log_info("Server started on " + address + ":" + std::to_string(port));
}
int32_t Server::handle_connection(int connectionfd) {
Logger::log_debug("Waiting for data from fd=" + std::to_string(connectionfd));
uint32_t len_net = 0;
errno = 0;
if (read_full(connectionfd, &len_net, sizeof(len_net)) != 0) {
if (errno == 0) {
Logger::log_info("Client disconnected (EOF) from fd=" + std::to_string(connectionfd));
} else {
Logger::log_error("Error reading length from fd=" + std::to_string(connectionfd) + ": " + std::strerror(errno));
}
return -1;
}
uint32_t len = ntohl(len_net);
if (len > k_max_message_size) {
Logger::log_error("Message length is too long: " + std::to_string(len) + " (max: " + std::to_string(k_max_message_size) + ")");
return -1;
}
std::string message(len, '\0');
if (len > 0) {
if (read_full(connectionfd, message.data(), len) != 0) {
Logger::log_error("Error reading payload from fd=" + std::to_string(connectionfd));
return -1;
}
}
Logger::log_info("Client (fd=" + std::to_string(connectionfd) + ") says: " + message);
const std::string reply = "world";
uint32_t reply_len_net = htonl(static_cast<uint32_t>(reply.size()));
if (write_all(connectionfd, &reply_len_net, sizeof(reply_len_net)) != 0) return -1;
if (write_all(connectionfd, reply.data(), reply.size()) != 0) return -1;
return 0;
}
void Server::run() {
setup();
while (true) {
struct sockaddr_in client_addr = {};
socklen_t addrlen = sizeof(client_addr);
int connectionfd = accept(sockfd, (struct sockaddr *)&client_addr, &addrlen);
if (connectionfd < 0) {
Logger::log_error("accept() error: " + std::string(std::strerror(errno)));
continue;
}
Logger::log_info("Accepted connection from " + std::string(inet_ntoa(client_addr.sin_addr)) + ":" + std::to_string(ntohs(client_addr.sin_port)) + " (fd=" + std::to_string(connectionfd) + ")");
while (true) {
int32_t err = handle_connection(connectionfd);
if (err) {
break;
}
}
Logger::log_info("Closing connection from " + std::to_string(connectionfd));
close(connectionfd);
}
}