Skip to content

Commit

Permalink
add(server): add recv_request() and test recv message from client
Browse files Browse the repository at this point in the history
  • Loading branch information
ak0327 committed Aug 25, 2023
1 parent f2dbd50 commit 0f85fd6
Show file tree
Hide file tree
Showing 9 changed files with 268 additions and 54 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/gtest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
cmake --build build
- name: run all tests on Linux
run: ./build/unit_test
run: ./build/unit_test 2>/dev/null

- uses: sarisia/actions-status-discord@v1
if: always()
Expand All @@ -32,7 +32,7 @@ jobs:
cmake --build build
- name: run all tests on macOS
run: ./build/unit_test
run: ./build/unit_test 2>/dev/null

- uses: sarisia/actions-status-discord@v1
if: always()
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ add_executable(webserv
set (unit_test_srcs
test/unit_test/is_valid_file_path/test_get_valid_config_file_path.cpp
test/unit_test/TestSocket.cpp
srcs/Server/Server.cpp srcs/Server/Server.hpp)
srcs/Server/Server.cpp srcs/Server/Server.hpp test/unit_test/TestServer.cpp)

add_executable(unit_test
${webserv_srcs}
Expand Down
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ unit :
#rm -rf build
cmake -S . -B build
cmake --build build
#./build/unit_test 2>/dev/null
./build/unit_test
./build/unit_test 2>/dev/null
#./build/unit_test
#cd build && ctest

-include $(DEPS)
147 changes: 117 additions & 30 deletions srcs/Server/Server.cpp
Original file line number Diff line number Diff line change
@@ -1,92 +1,179 @@
#include <netdb.h>
#include <errno.h>
#include <sys/socket.h>
#include <unistd.h>
#include <cstdio>
#include <cstring>
#include <iostream>
#include "Server.hpp"
#include "webserv.hpp"
#include "Color.hpp"

Server::Server(const char *server_ip,
const char *server_port)
: _socket(server_ip, server_port),
_connect_fd(ERROR) {
_connect_fd(ERROR),
_recv_message() {
if (this->_socket.get_status() == ERROR) {
throw std::runtime_error("[Error] server initialization error");
}
}

Server::Server() {}

Server::~Server() { close_connection(); }
Server::~Server() {
if (this->_connect_fd != ERROR) {
close_connection(this->_connect_fd);
this->_connect_fd = ERROR;
}
}

void Server::process_client_connection() {
char *buf = NULL;

void Server::run() {
char buf[BUF_SIZE]; // tmp
// select
// todo

// accept
if (accept_connection() == ERROR) {
this->_connect_fd = accept_connection(this->_socket.get_socket_fd(), this->_socket.get_addr_info());
if (this->_connect_fd == ERROR) {
throw std::runtime_error("[Error] accept");
}

// recv
if (recv_request(buf) == ERROR) {
if (recv_request(this->_connect_fd, &buf) == ERROR) {
throw std::runtime_error("[Error] recv");
}

this->_recv_message = std::string(buf);
// std::cout << YELLOW "recv_msg(string):[" << this->_recv_message << "]" RESET << std::endl;
// printf(YELLOW "recv_msg(buf):[%s]\n" RESET , buf);

delete buf;

return;

// request, response
HttpRequest request = HttpRequest(buf);
HttpResponse response = HttpResponse(request);

// send
if (send_response(response) == ERROR) {
if (send_response(this->_connect_fd, response) == ERROR) {
throw std::runtime_error("[Error] send");
}
}

int Server::accept_connection() {
int Server::accept_connection(int socket_fd, struct addrinfo *addr_info) {
int connect_fd;
struct sockaddr *ai_addr = addr_info->ai_addr;
socklen_t ai_addrlen = addr_info->ai_addrlen;

errno = 0;
this->_connect_fd = accept(this->_socket.get_socket_fd(), NULL, NULL); // todo: arg
if (this->_connect_fd == ERROR) {
connect_fd = accept(socket_fd, ai_addr, &ai_addrlen); // todo: arg
// connect_fd = accept(socket_fd, NULL, NULL); // todo: arg
if (connect_fd == ERROR) {
std::cerr << strerror(errno) << std::endl;
return ERROR;
}
return OK;
return connect_fd;
}

static size_t ft_strlen(const char *str) {
size_t i;

i = 0;
while (str && str[i])
i++;
return (i);
}

static char *ft_strjoin_dst2src(char **dst, const char *src)
{
char *newdst;
size_t i, j;
size_t len;

len = ft_strlen(*dst) + ft_strlen(src);
// newdst = (char *)malloc(sizeof(char) * (len + 1));
try {
newdst = new char[len + 1];
}
catch (std::bad_alloc const &e) {
std::cerr << e.what() << std::endl;
return NULL;
}

i = 0;
while (*dst && (*dst)[i])
{
newdst[i] = (*dst)[i];
i++;
}

j = 0;
while (src && src[j])
{
newdst[i + j] = src[j];
j++;
}
newdst[i + j] = '\0';

delete *dst;
*dst = newdst;
return (*dst);
}

// todo: while (size)
// use read?
int Server::recv_request(char *buf) const {
int Server::recv_request(int connect_fd, char **received_request) {
ssize_t recv_size;
char *buf;
char *save = NULL;

errno = 0;
recv_size = recv(this->_connect_fd, buf, BUF_SIZE, FLAG_NONE);
if (recv_size == ERROR) {
std::cerr << strerror(errno) << std::endl;
try {
buf = new char[BUFSIZ + 1];
}
catch (std::bad_alloc const &e) {
std::cerr << e.what() << std::endl;
return ERROR;
}
buf[recv_size] = '\0';

while (true) {
errno = 0;
recv_size = recv(connect_fd, buf, BUFSIZ, FLAG_NONE);
if (recv_size == ERROR) {
std::cerr << strerror(errno) << std::endl;
return ERROR;
}
buf[recv_size] = '\0';
if (ft_strjoin_dst2src(&save, buf) == NULL) {
return ERROR;
}
if (recv_size == 0) {
break;
}
}
*received_request = save;
return OK;
}

// todo: while
// use write(fd)?
int Server::send_response(const HttpResponse &response) const {
// todo: while?
int Server::send_response(int connect_fd, const HttpResponse &response) {
char *response_message = response.get_response_message();
size_t message_len = response.get_response_size();

errno = 0;
if (send(this->_connect_fd, response_message, message_len, FLAG_NONE) == ERROR) {
if (send(connect_fd, response_message, message_len, FLAG_NONE) == ERROR) {
std::cerr << strerror(errno) << std::endl;
return ERROR;
}
return OK;
}

void Server::close_connection() {
if (this->_connect_fd != ERROR) { // todo: check here?
errno = 0;
if (close(this->_connect_fd) == ERROR) {
std::cerr << strerror(errno) << std::endl;
this->_connect_fd = ERROR;
}
void Server::close_connection(int connect_fd) {
errno = 0;
if (close(connect_fd) == ERROR) {
std::cerr << strerror(errno) << std::endl;
}
}

std::string Server::get_recv_message() const { return this->_recv_message; }
struct addrinfo *Server::get_addr() const { return this->_socket.get_addr_info(); }
18 changes: 10 additions & 8 deletions srcs/Server/Server.hpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#pragma once

# include <string>
# include "Socket.hpp"

# define FLAG_NONE 0
# define BUF_SIZE 1024 // todo:tmp

// tmp
////////////////////////////////////////////////
Expand All @@ -24,18 +24,20 @@ class Server {
public:
Server();
Server(const char *server_ip, const char *server_port); // tmp
// Server(const Config config);
// Server(const Config config); // todo
~Server();

void run();
void process_client_connection();
std::string get_recv_message() const; // for debug
struct addrinfo *get_addr() const; // for debug

private:
Socket _socket;
int _connect_fd;
std::string _recv_message;

int accept_connection();
int recv_request(char *buf) const;
int send_response(const HttpResponse &response) const;

void close_connection();
static int accept_connection(int socket_fd, struct addrinfo *addr_info);
static int recv_request(int connect_fd, char **buf);
static int send_response(int connect_fd, const HttpResponse &response);
static void close_connection(int connect_fd);
};
16 changes: 10 additions & 6 deletions srcs/Socket/Socket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ Socket::Socket() : _status(ERROR),
if (listen_socket() == ERROR) {
return;
}
if (set_fd_to_nonblock() == ERROR) {
return;
}
// todo: accept error if nonblock
// if (set_fd_to_nonblock() == ERROR) {
// return;
// }
this->_status = OK;
}

Expand All @@ -33,6 +34,7 @@ Socket::Socket(const char *server_ip, const char *server_port) : _status(ERROR),
_addr_info(NULL),
_server_ip(server_ip),
_server_port(server_port) {
// std::cout << "ip:" << server_ip << ", port:" << server_port << std::endl;
if (create_socket() == ERROR) {
return;
}
Expand All @@ -42,9 +44,10 @@ Socket::Socket(const char *server_ip, const char *server_port) : _status(ERROR),
if (listen_socket() == ERROR) {
return;
}
if (set_fd_to_nonblock() == ERROR) {
return;
}
// todo: accept error if nonblock
// if (set_fd_to_nonblock() == ERROR) {
// return;
// }
this->_status = OK;
}

Expand Down Expand Up @@ -176,3 +179,4 @@ int Socket::get_socket_fd() const { return this->_socket_fd; }
int Socket::get_status() const { return this->_status; }
// std::string Socket::get_server_port() const { return this->_server_port; }
// std::string Socket::get_server_ip() const { return this->_server_ip; }
struct addrinfo *Socket::get_addr_info() const { return this->_addr_info; }
2 changes: 2 additions & 0 deletions srcs/Socket/Socket.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

# define SERVER_IP "127.0.0.1"
// # define SERVER_PORT "8080"
# define SERVER_PORT "8080"

// todo: config -> port, protocol
Expand All @@ -15,6 +16,7 @@ class Socket {

int get_socket_fd() const;
int get_status() const;
struct addrinfo *get_addr_info() const; // for debug
// std::string get_server_ip() const; // for debug
// std::string get_server_port() const; // for debug

Expand Down
8 changes: 3 additions & 5 deletions srcs/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,16 @@ static void validate_argc(int argc) {
int main(int argc, char **argv) {
std::string config_file_path;
// Configuration config; // todo
Server server; // todo
// Server server;

try {
validate_argc(argc);
config_file_path = get_valid_config_file_path(argv[CONFIG_FILE_INDEX]);
std::cout << "config_file_path=[" << config_file_path << "]" << std::endl;

// if path is 'default', config set to default
// config = Configuration(config_file_path);

server = Server(SERVER_IP, SERVER_PORT); // load config and setup socket
server.run();
Server server = Server(SERVER_IP, SERVER_PORT); // load config and setup socket
server.process_client_connection();
}
catch (std::exception const &e) {
std::cerr << e.what() << std::endl;
Expand Down
Loading

0 comments on commit 0f85fd6

Please sign in to comment.