Merge remote-tracking branch 'origin/test-client-handle' into fara

This commit is contained in:
Talyx
2022-02-05 15:24:15 +03:00
11 changed files with 178 additions and 102 deletions

View File

@@ -6,7 +6,7 @@ SANFLAGS = -fsanitize=address
# SANFLAGS = -fsanitize=leak # SANFLAGS = -fsanitize=leak
CXXFLAGS = -Wall -Wextra -Werror -g -std=c++98 -fno-limit-debug-info $(SANFLAGS) CXXFLAGS = -Wall -Wextra -Werror -g -std=c++98 -fno-limit-debug-info $(SANFLAGS) -DDEBUG
CPPFLAGS += -MD -MP CPPFLAGS += -MD -MP

8
curls.sh Normal file
View File

@@ -0,0 +1,8 @@
#!/bin/bash
I=0
while [[ I -lt $1 ]]
do
curl --location --request GET 'http://localhost:8080/g-series-15-3579-laptop_service-manual_en-us.pdf' > /dev/null &
I=$((I + 1));
done

View File

@@ -49,4 +49,13 @@
#include <algorithm> #include <algorithm>
#include <cctype> #include <cctype>
#ifdef DEBUG
#define DBOUT std::cerr << TURQ
#define ENDL RESET << std::endl
#else
#define DBOUT 0 && std::cerr
#define ENDL RESET << std::endl
#endif
#endif #endif

View File

@@ -5,6 +5,7 @@
Client::Client() Client::Client()
{ {
allRead = false; allRead = false;
done = false;
this->_fd = -1; this->_fd = -1;
this->_sended = 0; this->_sended = 0;
} }
@@ -12,6 +13,7 @@ Client::Client()
Client::Client(char *str) Client::Client(char *str)
{ {
allRead = false; allRead = false;
done = false;
this->_fd = -1; this->_fd = -1;
this->_buff = str; this->_buff = str;
this->_sended = 0; this->_sended = 0;
@@ -21,6 +23,7 @@ Client::Client(char *str)
Client::Client(char *str, ServerConfig *config) Client::Client(char *str, ServerConfig *config)
{ {
allRead = false; allRead = false;
done = false;
this->_fd = -1; this->_fd = -1;
this->_config = config; this->_config = config;
this->_buff = str; this->_buff = str;
@@ -40,9 +43,9 @@ Response Client::getResponse(void)
return (_response); return (_response);
} }
std::string Client::getStrToSend(void) char *Client::getStrToSend(void)
{ {
return (_toSend); return (_to_send_char);
} }
int Client::getFd(void) int Client::getFd(void)
@@ -98,8 +101,8 @@ bool Client::isChunked(void)
bool Client::allSended(void) bool Client::allSended(void)
{ {
if (_toSend.size() <= _sended) if (_toSend.size() <= _sended)
return (true); done = true;
return (false); return (done);
} }
bool Client::allRecved(void) bool Client::allRecved(void)
@@ -134,12 +137,21 @@ int Client::sendResponse(int fd)
std::string Client::generateRespons(void) std::string Client::generateRespons(void)
{ {
size_t len;
_response.setData(_request, _config); _response.setData(_request, _config);
_response.generate(); _response.generate();
_headerToSend = _response.getHeader(); _headerToSend = _response.getHeader();
_bodyToSend = _response.getBody(); _bodyToSend = _response.getBody();
_toSend = _headerToSend + _bodyToSend; _toSend = _headerToSend + _bodyToSend;
len = _toSend.size();
response_len = len;
/* _to_send_char = new char[len + 1]; */
_to_send_char = (char *)malloc(sizeof(char) * (len + 1));
std::memcpy(_to_send_char, _toSend.c_str(), len + 1);
return (_toSend); return (_toSend);
} }
@@ -222,8 +234,10 @@ void Client::clear(void)
_bodyToSend = ""; _bodyToSend = "";
_headerToSend = ""; _headerToSend = "";
_toSend = ""; _toSend = "";
free(_to_send_char);
} }
Client::~Client() Client::~Client()
{ {
DBOUT << "client destructor called" << ENDL;
} }

View File

@@ -6,6 +6,7 @@
#include "ServerConfig.hpp" #include "ServerConfig.hpp"
#include "Request.hpp" #include "Request.hpp"
#include "Response.hpp" #include "Response.hpp"
#include <cstring>
class Client class Client
{ {
@@ -25,15 +26,28 @@ private:
std::string _bodyToSend; std::string _bodyToSend;
std::string _headerToSend; std::string _headerToSend;
std::string _toSend; std::string _toSend;
char *_to_send_char;
std::map<std::string, std::string> _errorCode; std::map<std::string, std::string> _errorCode;
public: public:
bool allRead; bool allRead;
enum e_req_status
{
READING,
WRITING,
ENDED
} req_status;
int serverfd;
size_t readn;
size_t left;
bool done;
size_t response_len;
public: public:
Request getRequest(void); Request getRequest(void);
Response getResponse(void); Response getResponse(void);
std::string getStrToSend(void); char *getStrToSend(void);
unsigned int getCounter(void) const; unsigned int getCounter(void) const;
void setRawData(char *); void setRawData(char *);
void setFd(int); void setFd(int);

View File

@@ -66,7 +66,7 @@ std::string Response::getTime(void)
gettimeofday(&currTime, NULL); gettimeofday(&currTime, NULL);
t = gmtime(&currTime.tv_sec); t = gmtime(&currTime.tv_sec);
strftime(buff, 1337, "%a, %d %b %Y %H:%M:%S GTM", t); strftime(buff, 1337, "%a, %d %b %Y %H:%M:%S GMT", t);
return (buff); return (buff);
} }

View File

@@ -21,6 +21,18 @@ Server::Server(std::string path)
_client = 0; _client = 0;
} }
void Server::print_epoll_events(unsigned int events)
{
DBOUT << "Epoll events: ";
if (events & EPOLLIN)
DBOUT << "EPOLLIN ";
if (events & EPOLLOUT)
DBOUT << "EPOLLOUT ";
if (events & EPOLLET)
DBOUT << "EPOLLET ";
DBOUT << ENDL;
}
//----------------------------------------------Send-------------------------------------------------------------------------------------------- //----------------------------------------------Send--------------------------------------------------------------------------------------------
//----------------------------------------------Configuration----------------------------------------------------------------------------------- //----------------------------------------------Configuration-----------------------------------------------------------------------------------
@@ -47,55 +59,58 @@ void Server::readConfig(void)
void Server::sendData(Client &client, int fd) void Server::sendData(Client &client, int fd)
{ {
std::string tmp = client.getStrToSend(); /* std::string tmp = client.getStrToSend(); */
unsigned int size_diff = tmp.size() - client.getCounter(); char *tmp = client.getStrToSend();
size_t size_diff = client.response_len - client.getCounter();
size_t send_len;
if (size_diff < BUFFSIZE) if (size_diff < BUFFSIZE)
{ send_len = size_diff;
tmp = tmp.substr(client.getCounter(), size_diff);
}
else else
tmp = tmp.substr(client.getCounter(), BUFFSIZE); send_len = BUFFSIZE;
/* std::cout << YELLO << tmp << RESET << std::endl; */ /* std::cout << YELLO << tmp << RESET << std::endl; */
/* std::cout << GREEN << client.getCounter() << RESET << std::endl; */ /* std::cout << GREEN << client.getCounter() << RESET << std::endl; */
send(fd, tmp.c_str(), tmp.size(), 0); if (send(fd, tmp + client.getCounter(), send_len, MSG_NOSIGNAL) < 0)
{
DBOUT << RED << "SEND FAILED !@!!!" << ENDL;
client.done = true;
}
client.increaseCounter(); client.increaseCounter();
} }
void Server::readSocket(int fd, std::map<int, Client> &client_map) void Server::readSocket(Client &client, int fd)
{ {
int status; int status;
int bytes_read; int bytes_read;
char buf[BUFFSIZE + 1] = {0}; char buf[BUFFSIZE + 1] = {0};
std::cout << TURQ << "IN readSocket" << RESET << std::endl; DBOUT << TURQ << "IN readSocket" << RESET << std::endl;
bytes_read = recv(fd, buf, BUFFSIZE, 0); bytes_read = recv(fd, buf, BUFFSIZE, 0);
if (bytes_read == 0) if (bytes_read == 0)
{ {
client_map[fd].allRead = true; client.allRead = true;
return; return;
} }
client_map[fd].setRawData(buf); client.setRawData(buf);
client_map[fd].increaseRecvCounter(bytes_read); client.increaseRecvCounter(bytes_read);
status = client_map[fd].parseRequest(); status = client.parseRequest();
// client_map[fd].printClientInfo(); // client_map[fd].printClientInfo();
if ((bytes_read < BUFFSIZE) && client_map[fd].allRecved()) if ((bytes_read < BUFFSIZE) && client.allRecved())
{ {
client_map[fd].allRead = true; client.allRead = true;
} }
std::cerr << "recvCounter " << client_map[fd].getRecvCounter() << std::endl; std::cerr << "recvCounter " << client.getRecvCounter() << std::endl;
std::cerr << "contentLength " << client_map[fd].getRequest().getContentLength() << std::endl; std::cerr << "contentLength " << client.getRequest().getContentLength() << std::endl;
std::cerr << "allRead " << client_map[fd].allRead << std::endl; std::cerr << "allRead " << client.allRead << std::endl;
std::cout << BLUE << "status is " << Response::getReasonPhrase(status) << RESET << std::endl; DBOUT << BLUE << "status is " << Response::getReasonPhrase(status) << RESET << std::endl;
bzero(buf, BUFFSIZE); bzero(buf, BUFFSIZE);
} }
@@ -130,72 +145,34 @@ void Server::start(void)
{ {
Socket server_sock(AF_INET, SOCK_STREAM, 0, _port, "127.0.0.1"); Socket server_sock(AF_INET, SOCK_STREAM, 0, _port, "127.0.0.1");
std::map<int, Client> client_map; std::map<int, Client> client_map;
std::map<int, Client>::iterator client_it;
int fd; int fd;
int ready_num = 0; int ready_num = 0;
unsigned int client_events = EPOLLIN | EPOLLOUT | EPOLLET; unsigned int client_events = EPOLLIN;
unsigned int server_events = EPOLLIN | EPOLLOUT | EPOLLET; unsigned int server_events = EPOLLIN;
_epoll_fd = epoll_create(1337); _epoll_fd = epoll_create(1337);
checkError(server_sock.init(MAX_CLIENT), "Socket init"); checkError(server_sock.init(MAX_CLIENT), "Socket init");
setNonBlock(server_sock.getSocketFd()); setNonBlock(server_sock.getSocketFd());
setNonBlock(_epoll_fd); setNonBlock(_epoll_fd);
std::cerr << YELLO << "adding server_sock..." << RESET << std::endl; DBOUT << YELLO << "adding server_sock..." << ENDL;
add_to_epoll_list(server_sock.getSocketFd(), server_events); add_to_epoll_list(server_sock.getSocketFd(), server_events);
while (1) while (1)
{ {
// sending ready_num = epoll_wait(_epoll_fd, _events, MAX_CLIENT, -1);
for (client_it = client_map.begin();
client_it != client_map.end(); ++client_it)
{
std::cout << TURQ << "IN SEND LOOP" << RESET << std::endl;
Client &client = client_it->second;
if (!client.allRead && !client.isEmpty())
{
readSocket(client_it->first, client_map);
}
if (client.readyToSend())
{
epoll_ctl(_epoll_fd, EPOLL_CTL_DEL, client_it->first, NULL);
std::cout << TURQ << "readyToSend " << client_it->first << RESET << std::endl;
client.generateRespons();
sendData(client, client_it->first);
}
if ((client.readyToSend() && client.allSended()) || client.isEmpty())
{
client_map[fd].printClientInfo();
close(client_it->first);
std::cerr << RED <<
"deleting client "
<< client_it->first
<<
RESET
<< std::endl;
client_map.erase(client_it);
}
}
ready_num = epoll_wait(_epoll_fd, _events, MAX_CLIENT, 100);
/* std::cout << TURQ << "ready_num " << ready_num << RESET << std::endl; */ /* std::cout << TURQ << "ready_num " << ready_num << RESET << std::endl; */
if (ready_num < 0) if (ready_num < 0)
throw std::logic_error("epoll_ret"); throw std::logic_error("epoll_ret");
for (int i = 0; i < ready_num; i++) for (int i = 0; i < ready_num; i++)
{ {
/* if (_events[i].events == 0) */
/* continue; */
fd = _events[i].data.fd; fd = _events[i].data.fd;
/* if (_events[i].data.fd == 0) */ unsigned int events = _events[i].events;
/* { */
/* continue; */ /* DBOUT << "FD is " << fd << ENDL; */
/* } */ /* print_epoll_events(events); */
if (fd == server_sock.getSocketFd()) if (fd == server_sock.getSocketFd())
{ {
@@ -208,16 +185,49 @@ void Server::start(void)
} }
else else
{ {
std::cout << TURQ << "IN FOR LOOP" << RESET << std::endl; /* DBOUT << TURQ << "IN FOR LOOP" << RESET << std::endl; */
/* _client--; */ /* _client--; */
readSocket(fd, client_map); /* client_map[fd]; */
/* client_map.insert(std::make_pair(fd, Client())); */
if (events & EPOLLIN)
{
DBOUT << GREEN << "doing readSocket" << ENDL;
readSocket(client_map[fd], fd);
if (client_map[fd].readyToSend())
{
client_map[fd].generateRespons();
struct epoll_event ev;
ev.events = EPOLLOUT;
ev.data.fd = fd;
assert( epoll_ctl(_epoll_fd, EPOLL_CTL_MOD, fd, &ev) == 0);
DBOUT << GREEN << "rearmed to EPOLLOUT" << ENDL;
}
}
else if (events & EPOLLOUT)
{
/* DBOUT << GREEN << "doing sendData" << ENDL; */
/* client_map[fd].printClientInfo(); */
sendData(client_map[fd], fd);
if (client_map[fd].allSended())
{
epoll_ctl(_epoll_fd, EPOLL_CTL_DEL, fd, NULL);
close(fd);
client_map[fd].clear();
client_map.erase(fd);
DBOUT << RED <<
"deleting client "
<< fd
<< ENDL;
}
}
} }
} }
ready_num = 0;
} }
close(server_sock.getSocketFd()); close(server_sock.getSocketFd());
std::cerr << "end;" << std::endl; DBOUT << RED << "end;" << ENDL;
} }

View File

@@ -7,6 +7,7 @@
#include "Socket.hpp" #include "Socket.hpp"
#include "parse.hpp" #include "parse.hpp"
class Client; class Client;
class Server class Server
@@ -21,6 +22,8 @@ private:
std::vector<ServerConfig *> _configs; std::vector<ServerConfig *> _configs;
void add_to_epoll_list(int fd, unsigned int ep_events); void add_to_epoll_list(int fd, unsigned int ep_events);
static void print_epoll_events(unsigned int events);
private: private:
void checkError(int fd, std::string str); void checkError(int fd, std::string str);
void sendFile(std::string str); void sendFile(std::string str);
@@ -28,7 +31,24 @@ private:
void sendResponse(Client head, int); void sendResponse(Client head, int);
void setNonBlock(int fd); void setNonBlock(int fd);
void sendData(Client &client, int fd); void sendData(Client &client, int fd);
void readSocket(int fd, std::map<int, Client> &client_map); void readSocket(Client &client, int fd);
enum e_req_status
{
READING,
WRITING,
ENDED
};
typedef struct s_client_status
{
int fd;
int serverfd;
size_t readn;
size_t left;
enum e_req_status req_status;
} t_client_status;
public: public:
Server(); Server();
Server(std::string path); Server(std::string path);

View File

@@ -2,6 +2,7 @@
#include "parse.hpp" #include "parse.hpp"
#include "Server.hpp" #include "Server.hpp"
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
(void)argc; (void)argc;

Binary file not shown.

After

Width:  |  Height:  |  Size: 381 KiB

Binary file not shown.