diff --git a/curls.sh b/curls.sh new file mode 100644 index 0000000..9c615c5 --- /dev/null +++ b/curls.sh @@ -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 diff --git a/src/Client/Client.cpp b/src/Client/Client.cpp index cda7671..d34b27c 100644 --- a/src/Client/Client.cpp +++ b/src/Client/Client.cpp @@ -5,22 +5,29 @@ Client::Client() { allRead = false; + done = false; this->_fd = -1; this->_sended = 0; + _to_send_char = NULL; } Client::Client(char *str) { allRead = false; + done = false; this->_fd = -1; this->_buff = str; this->_sended = 0; + _to_send_char = NULL; + } Client::Client(char *str, ServerConfig *config) { + _to_send_char = NULL; allRead = false; + done = false; this->_fd = -1; this->_config = config; this->_buff = str; @@ -40,9 +47,9 @@ Response Client::getResponse(void) return (_response); } -std::string Client::getStrToSend(void) +char *Client::getStrToSend(void) { - return (_toSend); + return (_to_send_char); } int Client::getFd(void) @@ -98,8 +105,8 @@ bool Client::isChunked(void) bool Client::allSended(void) { if (_toSend.size() <= _sended) - return (true); - return (false); + done = true; + return (done); } bool Client::allRecved(void) @@ -134,12 +141,21 @@ int Client::sendResponse(int fd) std::string Client::generateRespons(void) { + size_t len; + _response.setData(_request, _config); _response.generate(); _headerToSend = _response.getHeader(); _bodyToSend = _response.getBody(); _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); } @@ -222,8 +238,11 @@ void Client::clear(void) _bodyToSend = ""; _headerToSend = ""; _toSend = ""; + if (_to_send_char) + free(_to_send_char); } Client::~Client() { + DBOUT << "client destructor called" << ENDL; } diff --git a/src/Client/Client.hpp b/src/Client/Client.hpp index dcd92c5..32927ed 100644 --- a/src/Client/Client.hpp +++ b/src/Client/Client.hpp @@ -6,6 +6,7 @@ #include "ServerConfig.hpp" #include "Request.hpp" #include "Response.hpp" +#include class Client { @@ -25,15 +26,28 @@ private: std::string _bodyToSend; std::string _headerToSend; std::string _toSend; + char *_to_send_char; std::map _errorCode; public: 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: Request getRequest(void); Response getResponse(void); - std::string getStrToSend(void); + char *getStrToSend(void); unsigned int getCounter(void) const; void setRawData(char *); void setFd(int); diff --git a/src/Client/Location.cpp b/src/Client/Location.cpp new file mode 100644 index 0000000..612e228 --- /dev/null +++ b/src/Client/Location.cpp @@ -0,0 +1,9 @@ +#include "Location.hpp" + +Location::Location() +{ +} + +Location::~Location() +{ +} \ No newline at end of file diff --git a/src/Client/Location.hpp b/src/Client/Location.hpp new file mode 100644 index 0000000..b62fe3f --- /dev/null +++ b/src/Client/Location.hpp @@ -0,0 +1,22 @@ +#ifndef LOCATION_HPP +#define LOCATION_HPP + +#include "webserv.hpp" +#include "ServerConfig.hpp" + +class Location +{ +private: + location *loc; + +public: + Location(); + ~Location(); + + void setLocation(location *location); + bool checkLocation(std::string URI); +private: + +}; + +#endif \ No newline at end of file diff --git a/src/Client/Response.cpp b/src/Client/Response.cpp index e254282..d1ec40f 100644 --- a/src/Client/Response.cpp +++ b/src/Client/Response.cpp @@ -66,7 +66,7 @@ std::string Response::getTime(void) gettimeofday(&currTime, NULL); 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); } @@ -141,6 +141,7 @@ void Response::generateHeader(void) if (_request.getConnection() == "keep-alive") ss << "Keep-Alive: timeout=" << _request.getLifeTime() << "\r\n"; ss << "Date: " << getTime() << "\r\n"; + ss << "Cache-Control: no-store, no-cache, must-revalidate\r\n"; ss << "\r\n"; _header = ss.str(); } diff --git a/src/Server/Server.cpp b/src/Server/Server.cpp index d314b23..dbdeabd 100644 --- a/src/Server/Server.cpp +++ b/src/Server/Server.cpp @@ -11,14 +11,24 @@ Server::Server() { bzero(_events, sizeof(_events)); - _client = 0; } Server::Server(std::string path) { (void)path; - _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-------------------------------------------------------------------------------------------- @@ -43,60 +53,81 @@ void Server::readConfig(void) _configs.push_back(new ServerConfig(*it)); ++it; } + + clean_parsed(root); } void Server::sendData(Client &client, int fd) { - std::string tmp = client.getStrToSend(); - unsigned int size_diff = tmp.size() - client.getCounter(); - + /* std::string tmp = client.getStrToSend(); */ + char *tmp = client.getStrToSend(); + size_t size_diff = client.response_len - client.getCounter(); + size_t send_len; if (size_diff < BUFFSIZE) - { - tmp = tmp.substr(client.getCounter(), size_diff); - } + send_len = size_diff; else - tmp = tmp.substr(client.getCounter(), BUFFSIZE); + send_len = BUFFSIZE; - /* std::cout << YELLO << tmp << RESET << std::endl; */ - /* std::cout << GREEN << client.getCounter() << RESET << std::endl; */ + /* DBOUT << YELLO << tmp << ENDL; */ + /* DBOUT << GREEN << client.getCounter() << 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(); } -void Server::readSocket(int fd, std::map &client_map) +void Server::readSocket(Client &client, int fd) { int status; int bytes_read; - char buf[BUFFSIZE + 1] = {0}; + char buf[BUFFSIZE + 1]; - std::cout << TURQ << "IN readSocket" << RESET << std::endl; + DBOUT << TURQ << "IN readSocket" << ENDL; + DBOUT << "client in readSocket "<< &client << ENDL; bytes_read = recv(fd, buf, BUFFSIZE, 0); if (bytes_read == 0) { - client_map[fd].allRead = true; + client.allRead = true; return; } - client_map[fd].setRawData(buf); - client_map[fd].increaseRecvCounter(bytes_read); - status = client_map[fd].parseRequest(); + buf[bytes_read + 1] = '\0'; + client.setRawData(buf); + client.increaseRecvCounter(bytes_read); + status = client.parseRequest(); // 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 << "contentLength " << client_map[fd].getRequest().getContentLength() << std::endl; - std::cerr << "allRead " << client_map[fd].allRead << std::endl; + DBOUT << GREEN << "recvCounter " << client.getRecvCounter() << ENDL; + DBOUT << GREEN << "contentLength " << client.getRequest().getContentLength() << ENDL; + DBOUT << GREEN << "allRead " << client.allRead << ENDL; - std::cout << BLUE << "status is " << Response::getReasonPhrase(status) << RESET << std::endl; - bzero(buf, BUFFSIZE); + DBOUT << BLUE << "status is " << Response::getReasonPhrase(status) << ENDL; +} + +int Server::delete_client(std::map &client_map, int fd) +{ + int ret; + ret = epoll_ctl(_epoll_fd, EPOLL_CTL_DEL, fd, NULL); + close(fd); + client_map[fd]->clear(); + delete (client_map[fd]); + client_map.erase(fd); + DBOUT << RED << + "deleting client " + << fd + << ENDL; + return (ret); } void Server::setupConfig(void) @@ -118,78 +149,45 @@ void Server::add_to_epoll_list(int fd, unsigned int ep_events) ev.data.fd = fd; assert(epoll_ctl(_epoll_fd, EPOLL_CTL_ADD, fd, &ev) == 0); - _client++; - std::cerr << YELLO + DBOUT << YELLO << "add socket " << fd << " to epoll_list" - << RESET << std::endl; + << ENDL; } void Server::start(void) { Socket server_sock(AF_INET, SOCK_STREAM, 0, _port, "127.0.0.1"); - std::map client_map; - std::map::iterator client_it; + std::map client_map; int fd; int ready_num = 0; - unsigned int client_events = EPOLLIN | EPOLLOUT | EPOLLET; - unsigned int server_events = EPOLLIN | EPOLLOUT | EPOLLET; + unsigned int client_events = EPOLLIN; + unsigned int server_events = EPOLLIN; _epoll_fd = epoll_create(1337); checkError(server_sock.init(MAX_CLIENT), "Socket init"); setNonBlock(server_sock.getSocketFd()); 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); while (1) { - // sending - 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; */ + ready_num = epoll_wait(_epoll_fd, _events, MAX_CLIENT, -1); + /* DBOUT << TURQ << "ready_num " << ready_num << ENDL; */ if (ready_num < 0) throw std::logic_error("epoll_ret"); for (int i = 0; i < ready_num; i++) { fd = _events[i].data.fd; + unsigned int events = _events[i].events; + + /* DBOUT << "FD is " << fd << ENDL; */ + /* print_epoll_events(events); */ if (fd == server_sock.getSocketFd()) { @@ -202,16 +200,41 @@ void Server::start(void) } else { - std::cout << TURQ << "IN FOR LOOP" << RESET << std::endl; - /* _client--; */ - readSocket(fd, client_map); + if (client_map.find(fd) == client_map.end()) + client_map[fd] = new Client(); + if (events & EPOLLIN) + { + 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; + } + if (client_map[fd]->isEmpty()) + delete_client(client_map, fd); + } + else if (events & EPOLLOUT) + { + /* DBOUT << GREEN << "doing sendData" << ENDL; */ + /* client_map[fd].printClientInfo(); */ + sendData(*client_map[fd], fd); + if (client_map[fd]->allSended()) + { + delete_client(client_map, fd); + } + } } } - ready_num = 0; } close(server_sock.getSocketFd()); - std::cerr << "end;" << std::endl; + DBOUT << RED << "end;" << ENDL; } @@ -243,14 +266,110 @@ void Server::checkError(int fd, std::string str) { if (fd < 0) { - std::cout << RED << "Server ERROR: " << str << ZERO_C << std::endl; + DBOUT << RED << "Server ERROR: " << str << ENDL; exit(1); } else - std::cout << GREEN << "Server SUCCESS: " << str << ZERO_C << std::endl; + DBOUT << GREEN << "Server SUCCESS: " << str << ENDL; +} + +void Server::clean_generic(toml_node *node) +{ + switch (node->type) + { + case toml_node::STRING: + { + DBOUT << "cleaning string" << ENDL; + delete node->getString(); + } + break; + case toml_node::MAPARRAY: + { + DBOUT << "cleaning MAPARRAY" << ENDL; + TOMLMapArray *map_array = node->getMapArray(); + for (TOMLMapArray::iterator it = map_array->begin(); + it != map_array->end(); ++it) + { + DBOUT << "cleaning a MAP of MAPARRAY" << ENDL; + TOMLMap *map = *it; + TOMLMap::iterator map_it = map->begin(); + for (map_it = map->begin(); + map_it != map->end(); ++map_it) + { + DBOUT << "cleaning a MAP item " << map_it->first << ENDL; + clean_generic(map_it->second); + /* map->erase(map_it); */ + } + map->clear(); + delete map; + } + map_array->clear(); + delete map_array; + DBOUT << "end cleaning MAPARRAY" << ENDL; + } + break; + case toml_node::MAP: + { + DBOUT << "cleaning MAP" << ENDL; + TOMLMap *map = node->getMap(); + for (TOMLMap::iterator it = map->begin(); it != map->end(); ++it) + { + DBOUT << "key is " << it->first << ENDL; + clean_generic(it->second); + /* map->erase(it); */ + } + map->clear(); + delete map; + } + break; + + case toml_node::ARRAY: + { + DBOUT << "cleaning ARRAY" << ENDL; + TOMLArray *arr = node->getArray(); + for (TOMLArray::iterator it = arr->begin(); + it != arr->end(); ++it) + { + clean_generic(*it); + } + arr->clear(); + delete arr; + DBOUT << "end cleaning MAP" << ENDL; + } + break; + + default: + { + DBOUT << "Cleaning type " << node->type << " not implemented :)" << ENDL; + } + } + delete node; + +} + +void Server::clean_parsed(TOMLMap *root) +{ + TOMLMap::iterator it; + + DBOUT << ">>> cleaning up: <<<" << std::endl; + for (it = root->begin(); it != root->end(); ++it) + { + /* DBOUT << RED << it->first */ + /* << ": " << GREEN */ + /* << *(it->second->toString()); */ + + clean_generic(it->second); + /* delete it->second; */ + std::cout << ", " << std::endl; + } + DBOUT << YELLO << "end of clean" << ENDL; + root->clear(); + delete root; + root = NULL; } Server::~Server() { + } diff --git a/src/Server/Server.hpp b/src/Server/Server.hpp index e418a9d..f0495a9 100644 --- a/src/Server/Server.hpp +++ b/src/Server/Server.hpp @@ -7,37 +7,60 @@ #include "Socket.hpp" #include "parse.hpp" + class Client; class Server { -private: - int _port; - int _epoll_fd; - int _client; - struct epoll_event _events[MAX_CLIENT]; - struct sockaddr_in _addres; - std::string _ip; - std::vector _configs; - void add_to_epoll_list(int fd, unsigned int ep_events); + private: + int _port; + int _epoll_fd; + struct epoll_event _events[MAX_CLIENT]; + struct sockaddr_in _addres; + std::string _ip; + std::vector _configs; + void add_to_epoll_list(int fd, unsigned int ep_events); -private: - void checkError(int fd, std::string str); - void sendFile(std::string str); - void sendClient(Client head, int); - void sendResponse(Client head, int); - void setNonBlock(int fd); - void sendData(Client &client, int fd); - void readSocket(int fd, std::map &client_map); -public: - Server(); - Server(std::string path); + static void print_epoll_events(unsigned int events); - void readConfig(void); - void setupConfig(void); - void start(void); - void end(void); - ~Server(); + private: + void checkError(int fd, std::string str); + void sendFile(std::string str); + void sendClient(Client head, int); + void sendResponse(Client head, int); + void setNonBlock(int fd); + void sendData(Client &client, int fd); + void readSocket(Client &client, int fd); + int delete_client(std::map &map, int fd); + + static void clean_generic(toml_node *node); + static void clean_parsed(TOMLMap *root); + + 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: + Server(); + Server(std::string path); + + void readConfig(void); + void setupConfig(void); + void start(void); + void end(void); + ~Server(); }; diff --git a/src/config/TOMLParser.cpp b/src/config/TOMLParser.cpp index 6830962..bb2316c 100644 --- a/src/config/TOMLParser.cpp +++ b/src/config/TOMLParser.cpp @@ -444,6 +444,7 @@ namespace config } else (it->second)->getMapArray()->push_back(map_node->getMap()); + delete map_node; } else if (type == toml_node::MAP) { @@ -460,13 +461,13 @@ namespace config { it = local_root->find(*subname); - toml_node *map_node2; - map_node2 = new toml_node; - TOMLMap *map = new TOMLMap; - map_node2->setObject(map); /* subname not found in local_root */ if (it == local_root->end()) { + toml_node *map_node2; + map_node2 = new toml_node; + TOMLMap *map = new TOMLMap; + map_node2->setObject(map); (*local_root)[*subname] = map_node2; local_root = map; } diff --git a/www/errorFolder/images/168.png b/www/errorFolder/images/168.png new file mode 100644 index 0000000..f4b8d1f Binary files /dev/null and b/www/errorFolder/images/168.png differ diff --git a/www/g-series-15-3579-laptop_service-manual_en-us.pdf b/www/g-series-15-3579-laptop_service-manual_en-us.pdf new file mode 100644 index 0000000..9086ea0 Binary files /dev/null and b/www/g-series-15-3579-laptop_service-manual_en-us.pdf differ