diff --git a/.gitignore b/.gitignore index e968bf6..27e0584 100644 --- a/.gitignore +++ b/.gitignore @@ -1,13 +1,16 @@ * -!srcs/ -!srcs/load/ -!srcs/json/ -!srcs/*/*.cpp -!srcs/*/*.hpp -!srcs/*.hpp -!srcs/*.cpp + !Makefile !LICENCE !README.md !default.json !.gitignore + +!includes/ +!includes/*.hpp + +!srcs/ +!srcs/*.cpp +!srcs/load/ +!srcs/json/ +!srcs/*/*.cpp diff --git a/Makefile b/Makefile index 76b6b63..0f5cb74 100644 --- a/Makefile +++ b/Makefile @@ -1,14 +1,16 @@ NAME= server -SRCS= srcs/webserv.cpp srcs/tools.cpp +SRCS= srcs/webserv.cpp srcs/tools.cpp srcs/load/Env.cpp srcs/load/Server.cpp \ + srcs/load/Socket.cpp srcs/load/Route.cpp \ + srcs/json/Nodes.cpp srcs/json/Token.cpp srcs/json/Parser.cpp OBJS= $(SRCS:.cpp=.o) CXX=c++ -CXXFLAGS= -g -Werror -Wextra -Wall -std=c++98 +CXXFLAGS= -g -I includes -Werror -Wextra -Wall -std=c++98 all : $(NAME) $(NAME): $(OBJS) - $(CXX) -g -fsanitize=address $(OBJS) -o $(NAME) + $(CXX) -g $(OBJS) -o $(NAME) clean: rm -rf $(OBJS) diff --git a/includes/Env.hpp b/includes/Env.hpp new file mode 100644 index 0000000..a24360f --- /dev/null +++ b/includes/Env.hpp @@ -0,0 +1,12 @@ +#pragma once +#include "webserv.hpp" + + +class JSONNode; +class Server; + +class Env { + std::vector _servers; + public: + Env(JSONNode *conf); +}; diff --git a/includes/Nodes.hpp b/includes/Nodes.hpp new file mode 100644 index 0000000..08c0e90 --- /dev/null +++ b/includes/Nodes.hpp @@ -0,0 +1,30 @@ +#pragma once + +class JSONNode { + public: + JSONObject obj(); + JSONList lst(); + string str(); + int nbr(); + + private: + enum Type { OBJECT, LIST, STRING, NUMBER, BOOLEAN, NULL_TYPE }; + union Values { + JSONObject *object; + JSONList *list; + string *str; + int nbr; + bool bValue; + } values; + Type type; + + void setObject(JSONObject *object); + void setList(JSONList *list); + void setString(string *str); + void setNumber(int nbr); + void setBoolean(bool v); + void setNull(); + + string stringify(int indentationLevel); + friend class JSONParser; +}; diff --git a/includes/Parser.hpp b/includes/Parser.hpp new file mode 100644 index 0000000..04e2af8 --- /dev/null +++ b/includes/Parser.hpp @@ -0,0 +1,16 @@ +#include "webserv.hpp" + +class JSONParser { + std::fstream file; + Tokenizer tokenizer; + + public: + JSONParser(const string filename); + JSONNode *parse(); + JSONNode *parseObject(); + JSONNode *parseList(); + JSONNode *parseString(); + JSONNode *parseNumber(); + JSONNode *parseBoolean(); + JSONNode *parseNull(); +}; diff --git a/srcs/load/Route.hpp b/includes/Route.hpp similarity index 77% rename from srcs/load/Route.hpp rename to includes/Route.hpp index 9ce3355..3dd5171 100644 --- a/srcs/load/Route.hpp +++ b/includes/Route.hpp @@ -1,4 +1,5 @@ -#include "../webserv.hpp" +#pragma once +#include "webserv.hpp" class Route { string _root; diff --git a/includes/Server.hpp b/includes/Server.hpp new file mode 100644 index 0000000..21d1a83 --- /dev/null +++ b/includes/Server.hpp @@ -0,0 +1,13 @@ +#pragma once +#include "webserv.hpp" + + +class Server { + string _name; + std::vector _sockets; + std::map _routes; + + public: + Server(JSONNode *server); + void check(); +}; diff --git a/includes/Socket.hpp b/includes/Socket.hpp new file mode 100644 index 0000000..b06f996 --- /dev/null +++ b/includes/Socket.hpp @@ -0,0 +1,26 @@ +#pragma once +#include "webserv.hpp" + +class Socket { + string _ip; + int _port; + int _master_socket; + struct sockaddr_in _address; + int _max_clients; + int _client_socket[30]; + public: + Socket(string def); + void check(); + /* + Socket& operator=(Socket &src) { + _ip = src._ip; + _port = src._port; + _master_socket = src._master_socket; + _address = src._address; + return src; + } +*/ +}; + + + diff --git a/includes/Token.hpp b/includes/Token.hpp new file mode 100644 index 0000000..bb1dee4 --- /dev/null +++ b/includes/Token.hpp @@ -0,0 +1,31 @@ +#include "webserv.hpp" + +enum TOKEN { + CURLY_OPEN, + CURLY_CLOSE, + COLON, + STRING, + NUMBER, + ARRAY_OPEN, + ARRAY_CLOSE, + COMMA, + BOOLEAN, + NULL_TYPE +}; + +typedef struct Token_s { + string value; + TOKEN type; +} Token; + +class Tokenizer { + std::fstream file; + size_t prevPos; + + public: + Tokenizer(string fileName); + bool hasMoreTokens(); + char getWithoutWhiteSpace(); + void rollBackToken(); + Token getToken(); +}; diff --git a/srcs/webserv.hpp b/includes/webserv.hpp similarity index 64% rename from srcs/webserv.hpp rename to includes/webserv.hpp index d32b285..80e5bc3 100644 --- a/srcs/webserv.hpp +++ b/includes/webserv.hpp @@ -1,4 +1,5 @@ #pragma once + #include #include #include @@ -14,16 +15,30 @@ #include #include #include +#include #include #include #include -using std::string; +#define DEBUG 0 + using std::cout; using std::strerror; +using std::string; + +class JSONNode; +typedef std::map JSONObject; +typedef std::vector JSONList; void *ft_memset(void *b, int c, size_t len); bool isInt(string str); -#include "json/Parser.hpp" -#include "load/Env.hpp" +#include "Token.hpp" +#include "Parser.hpp" +#include "Nodes.hpp" + +#include "Env.hpp" +#include "Route.hpp" +#include "Socket.hpp" +#include "Server.hpp" + diff --git a/srcs/json/Nodes.cpp b/srcs/json/Nodes.cpp new file mode 100644 index 0000000..2ca3f49 --- /dev/null +++ b/srcs/json/Nodes.cpp @@ -0,0 +1,106 @@ + +#include "webserv.hpp" + +#define DEBUG 0 + +JSONObject JSONNode::obj() { + if (type == OBJECT) + return *values.object; + throw std::logic_error("Improper return"); +} +JSONList JSONNode::lst() { + if (type == LIST) + return *values.list; + throw std::logic_error("Improper return"); +} +string JSONNode::str() { + if (type == STRING) + return *values.str; + throw std::logic_error("Improper return"); +} +int JSONNode::nbr() { + if (type == NUMBER) + return values.nbr; + throw std::logic_error("Improper return"); +} + +void JSONNode::setObject(JSONObject *object) { + this->values.object = object; + type = OBJECT; +} +void JSONNode::setList(JSONList *list) { + this->values.list = list; + type = LIST; +} +void JSONNode::setString(string *str) { + this->values.str = str; + type = STRING; +} +void JSONNode::setNumber(int nbr) { + this->values.nbr = nbr; + type = NUMBER; +} +void JSONNode::setBoolean(bool v) { + this->values.bValue = v; + type = BOOLEAN; +} +void JSONNode::setNull() { type = NULL_TYPE; } + +string JSONNode::stringify(int indentationLevel) { + string spaceString = string(indentationLevel, ' '); + // sstreams + std::stringstream output; + // cout < type << "\n"; + switch (type) { + case STRING: { + output << spaceString << *values.str; + break; + } + case NUMBER: { + output << spaceString << values.nbr; + break; + } + case BOOLEAN: { + output << spaceString << (values.bValue ? "true" : "false"); + break; + } + case NULL_TYPE: { + output << spaceString << "null"; + break; + } + case LIST: { + // cout << "["; + output << spaceString << "[\n"; + unsigned int index = 0; + for (JSONList::iterator i = (*values.list).begin(); + i != (*values.list).end(); i++) { + output << (*i)->stringify(indentationLevel + 1); + if (index < (*values.list).size() - 1) { + output << ",\n"; + } + index++; + }; + output << "\n" << spaceString << "]\n"; + break; + } + case OBJECT: { + output << spaceString << "{\n"; + for (JSONObject::iterator i = (*values.object).begin(); + i != (*values.object).end(); i++) { + output << spaceString << " " + << "\"" << i->first << "\"" + << ": "; + output << i->second->stringify(indentationLevel + 1); + JSONObject::iterator next = i; + next++; + if ((next) != (*values.object).end()) { + output << ",\n"; + } + output << spaceString << "\n"; + } + output << spaceString << "}"; + return output.str(); + } + } + return output.str(); +} diff --git a/srcs/json/Nodes.hpp b/srcs/json/Nodes.hpp deleted file mode 100644 index 0a756a4..0000000 --- a/srcs/json/Nodes.hpp +++ /dev/null @@ -1,131 +0,0 @@ -#include -#include -#include -#include -#include - -#define DEBUG 0 - -using std::cout; -using std::string; - -class JSONNode; -typedef std::map JSONObject; -typedef std::vector JSONList; - -class JSONNode { - public: - JSONObject obj() { - if (type == OBJECT) - return *values.object; - throw std::logic_error("Improper return"); - } - JSONList lst() { - if (type == LIST) - return *values.list; - throw std::logic_error("Improper return"); - } - string str() { - if (type == STRING) - return *values.str; - throw std::logic_error("Improper return"); - } - int nbr() { - if (type == NUMBER) - return values.nbr; - throw std::logic_error("Improper return"); - } - - private: - enum Type { OBJECT, LIST, STRING, NUMBER, BOOLEAN, NULL_TYPE }; - union Values { - JSONObject *object; - JSONList *list; - string *str; - int nbr; - bool bValue; - } values; - Type type; - - void setObject(JSONObject *object) { - this->values.object = object; - type = OBJECT; - } - void setList(JSONList *list) { - this->values.list = list; - type = LIST; - } - void setString(string *str) { - this->values.str = str; - type = STRING; - } - void setNumber(int nbr) { - this->values.nbr = nbr; - type = NUMBER; - } - void setBoolean(bool v) { - this->values.bValue = v; - type = BOOLEAN; - } - void setNull() { type = NULL_TYPE; } - - string stringify(int indentationLevel) { - string spaceString = string(indentationLevel, ' '); - // sstreams - std::stringstream output; - // cout < type << "\n"; - switch (type) { - case STRING: { - output << spaceString << *values.str; - break; - } - case NUMBER: { - output << spaceString << values.nbr; - break; - } - case BOOLEAN: { - output << spaceString << (values.bValue ? "true" : "false"); - break; - } - case NULL_TYPE: { - output << spaceString << "null"; - break; - } - case LIST: { - // cout << "["; - output << spaceString << "[\n"; - unsigned int index = 0; - for (JSONList::iterator i = (*values.list).begin(); - i != (*values.list).end(); i++) { - output << (*i)->stringify(indentationLevel + 1); - if (index < (*values.list).size() - 1) { - output << ",\n"; - } - index++; - }; - output << "\n" << spaceString << "]\n"; - break; - } - case OBJECT: { - output << spaceString << "{\n"; - for (JSONObject::iterator i = (*values.object).begin(); - i != (*values.object).end(); i++) { - output << spaceString << " " - << "\"" << i->first << "\"" - << ": "; - output << i->second->stringify(indentationLevel + 1); - JSONObject::iterator next = i; - next++; - if ((next) != (*values.object).end()) { - output << ",\n"; - } - output << spaceString << "\n"; - } - output << spaceString << "}"; - return output.str(); - } - } - return output.str(); - } - friend class JSONParser; -}; diff --git a/srcs/json/Parser.cpp b/srcs/json/Parser.cpp new file mode 100644 index 0000000..85bf175 --- /dev/null +++ b/srcs/json/Parser.cpp @@ -0,0 +1,200 @@ +#include "webserv.hpp" + + +JSONParser::JSONParser(const string filename) : tokenizer(filename) {} + +JSONNode *JSONParser::parse() { + string key = ""; + JSONNode *parsed; + while (tokenizer.hasMoreTokens()) { + Token token; + try { + token = tokenizer.getToken(); + switch (token.type) { + case CURLY_OPEN: { + parsed = parseObject(); + break; + } + case ARRAY_OPEN: { + parsed = parseList(); + break; + } + case STRING: { + tokenizer.rollBackToken(); + parsed = parseString(); + break; + } + case NUMBER: { + tokenizer.rollBackToken(); + parsed = parseNumber(); + break; + } + case BOOLEAN: { + tokenizer.rollBackToken(); + parsed = parseBoolean(); + break; + } + default: + break; + } + } catch (std::logic_error &e) { + break; + } + } + return parsed; +} + +JSONNode *JSONParser::parseObject() { + JSONNode *node = new JSONNode; + JSONObject *keyObjectMap = new JSONObject; + while (1) { + if (tokenizer.hasMoreTokens()) { + Token token = tokenizer.getToken(); + string key = token.value; + tokenizer.getToken(); + token = tokenizer.getToken(); + switch (token.type) { + case CURLY_OPEN: { + if (DEBUG) + cout << "=object=|" << key << "|===>>\n"; + (*keyObjectMap)[key] = parseObject(); + if (DEBUG) + cout << "<<===end object\n"; + break; + } + case ARRAY_OPEN: { + if (DEBUG) + cout << "-list-|" << key << "|--->>\n"; + (*keyObjectMap)[key] = parseList(); + if (DEBUG) + cout << "<<---end list\n"; + break; + } + case STRING: { + tokenizer.rollBackToken(); + (*keyObjectMap)[key] = parseString(); + if (DEBUG) + cout << key << "='" << (*keyObjectMap)[key]->str() << "'\n"; + break; + } + case NUMBER: { + tokenizer.rollBackToken(); + (*keyObjectMap)[key] = parseNumber(); + if (DEBUG) + cout << key << "=" << (*keyObjectMap)[key]->nbr() << "\n"; + break; + } + case BOOLEAN: { + tokenizer.rollBackToken(); + (*keyObjectMap)[key] = parseBoolean(); + if (DEBUG) + cout << key << "(BOOL)\n"; + break; + } + case NULL_TYPE: { + (*keyObjectMap)[key] = parseNull(); + break; + } + default: + break; + } + token = tokenizer.getToken(); + if (token.type == CURLY_CLOSE) + break; + + } else { + throw std::logic_error("No more tokens"); + } + } + node->setObject(keyObjectMap); + return node; +} +JSONNode *JSONParser::parseList() { + JSONNode *node = new JSONNode(); + JSONList *list = new JSONList(); + bool hasCompleted = false; + while (!hasCompleted) { + if (!tokenizer.hasMoreTokens()) { + throw std::logic_error("No more tokens"); + } else { + Token token = tokenizer.getToken(); + JSONNode *subNode; + switch (token.type) { + case CURLY_OPEN: { + if (DEBUG) + cout << "=object===>>\n"; + subNode = parseObject(); + if (DEBUG) + cout << "<<===end object\n"; + break; + } + case ARRAY_OPEN: { + if (DEBUG) + cout << "-list--->>\n"; + subNode = parseList(); + if (DEBUG) + cout << "<<---end list\n"; + break; + } + case STRING: { + tokenizer.rollBackToken(); + subNode = parseString(); + if (DEBUG) + cout << "|'" << subNode->str() << "'"; + break; + } + case NUMBER: { + tokenizer.rollBackToken(); + subNode = parseNumber(); + if (DEBUG) + cout << "|" << subNode->nbr(); + break; + } + case BOOLEAN: { + tokenizer.rollBackToken(); + subNode = parseBoolean(); + break; + } + case NULL_TYPE: { + subNode = parseNull(); + break; + } + default: + break; + } + list->push_back(subNode); + token = tokenizer.getToken(); + if (token.type == ARRAY_CLOSE) { + hasCompleted = true; + } + } + } + node->setList(list); + return node; +} +JSONNode *JSONParser::parseString() { + JSONNode *node = new JSONNode(); + Token token = tokenizer.getToken(); + string *sValue = new string(token.value); + node->setString(sValue); + return node; +} +JSONNode *JSONParser::parseNumber() { + JSONNode *node = new JSONNode(); + Token token = tokenizer.getToken(); + string value = token.value; + int nbr = std::atoi(value.c_str()); + node->setNumber(nbr); + return node; +} +JSONNode *JSONParser::parseBoolean() { + JSONNode *node = new JSONNode(); + Token token = tokenizer.getToken(); + node->setBoolean(token.value == "True" ? true : false); + return node; +} +JSONNode *JSONParser::parseNull() { + JSONNode *node = new JSONNode(); + node->setNull(); + return node; +} diff --git a/srcs/json/Parser.hpp b/srcs/json/Parser.hpp deleted file mode 100644 index af4990b..0000000 --- a/srcs/json/Parser.hpp +++ /dev/null @@ -1,211 +0,0 @@ -#include "Token.hpp" -#include - -class JSONParser { - std::fstream file; - Tokenizer tokenizer; - - public: - JSONParser(const string filename) : tokenizer(filename) {} - JSONNode *parse() { - string key = ""; - JSONNode *parsed; - while (tokenizer.hasMoreTokens()) { - Token token; - try { - token = tokenizer.getToken(); - switch (token.type) { - case CURLY_OPEN: { - parsed = parseObject(); - break; - } - case ARRAY_OPEN: { - parsed = parseList(); - break; - } - case STRING: { - tokenizer.rollBackToken(); - parsed = parseString(); - break; - } - case NUMBER: { - tokenizer.rollBackToken(); - parsed = parseNumber(); - break; - } - case BOOLEAN: { - tokenizer.rollBackToken(); - parsed = parseBoolean(); - break; - } - default: - break; - } - } catch (std::logic_error &e) { - break; - } - } - return parsed; - } - - JSONNode *parseObject() { - JSONNode *node = new JSONNode; - JSONObject *keyObjectMap = new JSONObject; - while (1) { - if (tokenizer.hasMoreTokens()) { - Token token = tokenizer.getToken(); - string key = token.value; - tokenizer.getToken(); - token = tokenizer.getToken(); - switch (token.type) { - case CURLY_OPEN: { - if (DEBUG) - cout << "=object=|" << key << "|===>>\n"; - (*keyObjectMap)[key] = parseObject(); - if (DEBUG) - cout << "<<===end object\n"; - break; - } - case ARRAY_OPEN: { - if (DEBUG) - cout << "-list-|" << key << "|--->>\n"; - (*keyObjectMap)[key] = parseList(); - if (DEBUG) - cout << "<<---end list\n"; - break; - } - case STRING: { - tokenizer.rollBackToken(); - (*keyObjectMap)[key] = parseString(); - if (DEBUG) - cout << key << "='" << (*keyObjectMap)[key]->str() - << "'\n"; - break; - } - case NUMBER: { - tokenizer.rollBackToken(); - (*keyObjectMap)[key] = parseNumber(); - if (DEBUG) - cout << key << "=" << (*keyObjectMap)[key]->nbr() - << "\n"; - break; - } - case BOOLEAN: { - tokenizer.rollBackToken(); - (*keyObjectMap)[key] = parseBoolean(); - if (DEBUG) - cout << key << "(BOOL)\n"; - break; - } - case NULL_TYPE: { - (*keyObjectMap)[key] = parseNull(); - break; - } - default: - break; - } - token = tokenizer.getToken(); - if (token.type == CURLY_CLOSE) - break; - - } else { - throw std::logic_error("No more tokens"); - } - } - node->setObject(keyObjectMap); - return node; - } - - JSONNode *parseList() { - JSONNode *node = new JSONNode(); - JSONList *list = new JSONList(); - bool hasCompleted = false; - while (!hasCompleted) { - if (!tokenizer.hasMoreTokens()) { - throw std::logic_error("No more tokens"); - } else { - Token token = tokenizer.getToken(); - JSONNode *subNode; - switch (token.type) { - case CURLY_OPEN: { - if (DEBUG) - cout << "=object===>>\n"; - subNode = parseObject(); - if (DEBUG) - cout << "<<===end object\n"; - break; - } - case ARRAY_OPEN: { - if (DEBUG) - cout << "-list--->>\n"; - subNode = parseList(); - if (DEBUG) - cout << "<<---end list\n"; - break; - } - case STRING: { - tokenizer.rollBackToken(); - subNode = parseString(); - if (DEBUG) - cout << "|'" << subNode->str() << "'"; - break; - } - case NUMBER: { - tokenizer.rollBackToken(); - subNode = parseNumber(); - if (DEBUG) - cout << "|" << subNode->nbr(); - break; - } - case BOOLEAN: { - tokenizer.rollBackToken(); - subNode = parseBoolean(); - break; - } - case NULL_TYPE: { - subNode = parseNull(); - break; - } - default: - break; - } - list->push_back(subNode); - token = tokenizer.getToken(); - if (token.type == ARRAY_CLOSE) { - hasCompleted = true; - } - } - } - node->setList(list); - return node; - } - - JSONNode *parseString() { - JSONNode *node = new JSONNode(); - Token token = tokenizer.getToken(); - string *sValue = new string(token.value); - node->setString(sValue); - return node; - } - - JSONNode *parseNumber() { - JSONNode *node = new JSONNode(); - Token token = tokenizer.getToken(); - string value = token.value; - int nbr = std::atoi(value.c_str()); - node->setNumber(nbr); - return node; - } - JSONNode *parseBoolean() { - JSONNode *node = new JSONNode(); - Token token = tokenizer.getToken(); - node->setBoolean(token.value == "True" ? true : false); - return node; - } - - JSONNode *parseNull() { - JSONNode *node = new JSONNode(); - node->setNull(); - return node; - } -}; diff --git a/srcs/json/Token.cpp b/srcs/json/Token.cpp new file mode 100644 index 0000000..8aa620a --- /dev/null +++ b/srcs/json/Token.cpp @@ -0,0 +1,111 @@ +#include "webserv.hpp" +/* +enum TOKEN { + CURLY_OPEN, + CURLY_CLOSE, + COLON, + STRING, + NUMBER, + ARRAY_OPEN, + ARRAY_CLOSE, + COMMA, + BOOLEAN, + NULL_TYPE +}; +*/ + +Tokenizer::Tokenizer(string fileName) { + file.open(fileName.c_str(), std::ios::in); + if (!file.good()) + cout << "File open error" + << "\n"; +} +bool Tokenizer::hasMoreTokens() { return !file.eof(); } + +char Tokenizer::getWithoutWhiteSpace() { + char c = ' '; + while ((c == ' ' || c == '\n') || c == '\t') { + file.get(c); // check + + if ((c == ' ' || c == '\n') && !file.good()) { + // cout << file.eof() << " " << file.fail() << "\n"; + throw std::logic_error("Ran out of tokens"); + } else if (!file.good()) { + return c; + } + } + + return c; +} +void Tokenizer::rollBackToken() { + if (file.eof()) + file.clear(); + file.seekg(prevPos); +} +Token Tokenizer::getToken() { + char c; + if (file.eof()) { + cout << "Exhaused tokens" + << "\n"; + // throw std::exception("Exhausted tokens"); + } + prevPos = file.tellg(); + c = getWithoutWhiteSpace(); + + Token token; + token.type = NULL_TYPE; + if (c == '"') { + token.type = STRING; + token.value = ""; + file.get(c); + while (c != '"') { + token.value += c; + file.get(c); + } + } else if (c == '{') { + token.type = CURLY_OPEN; + } else if (c == '}') { + token.type = CURLY_CLOSE; + } else if (c == '-' || (c >= '0' && c <= '9')) { + // Check if string is numeric + token.type = NUMBER; + token.value = ""; + token.value += c; + std::streampos prevCharPos = file.tellg(); + while ((c == '-') || (c >= '0' && c <= '9') || c == '.') { + prevCharPos = file.tellg(); + file.get(c); + + if (file.eof()) { + break; + } else { + if ((c == '-') || (c >= '0' && c <= '9') || (c == '.')) { + token.value += c; + } else { + file.seekg(prevCharPos); + } + } + } + } else if (c == 'f') { + token.type = BOOLEAN; + token.value = "False"; + file.seekg(4, std::ios_base::cur); + } else if (c == 't') { + token.type = BOOLEAN; + token.value = "True"; + file.seekg(3, std::ios_base::cur); + } else if (c == 'n') { + token.type = NULL_TYPE; + file.seekg(3, std::ios_base::cur); + } else if (c == '[') { + token.type = ARRAY_OPEN; + } else if (c == ']') { + token.type = ARRAY_CLOSE; + } else if (c == ':') { + token.type = COLON; + } else if (c == ',') { + token.type = COMMA; + } + // cout << token.type << " : " << token.value << "\n"; + return token; +} diff --git a/srcs/json/Token.hpp b/srcs/json/Token.hpp deleted file mode 100644 index d639e25..0000000 --- a/srcs/json/Token.hpp +++ /dev/null @@ -1,158 +0,0 @@ -#include "Nodes.hpp" -#include - -enum TOKEN { - CURLY_OPEN, - CURLY_CLOSE, - COLON, - STRING, - NUMBER, - ARRAY_OPEN, - ARRAY_CLOSE, - COMMA, - BOOLEAN, - NULL_TYPE -}; - -typedef struct Token_s { - string value; - TOKEN type; - string toString() { - switch (type) { - case CURLY_OPEN: { - return "Curly open"; - } - case CURLY_CLOSE: { - return "Curly close"; - } - case COLON: { - return "COLON"; - } - case NUMBER: { - return "Number: " + value; - } - case STRING: { - return "String: " + value; - } - - case ARRAY_OPEN: { - return "Array open"; - } - case ARRAY_CLOSE: { - return "Array close"; - } - case COMMA: { - return "Comma"; - } - case BOOLEAN: { - return "Boolean: " + value; - } - - case NULL_TYPE: { - return "Null"; - } - default: - return "Other..."; - } - } -} Token; - -class Tokenizer { - std::fstream file; - size_t prevPos; - - public: - Tokenizer(string fileName) { - file.open(fileName.c_str(), std::ios::in); - if (!file.good()) - cout << "File open error" - << "\n"; - }; - bool hasMoreTokens() { return !file.eof(); } - char getWithoutWhiteSpace() { - char c = ' '; - while ((c == ' ' || c == '\n') || c == '\t') { - file.get(c); // check - - if ((c == ' ' || c == '\n') && !file.good()) { - // cout << file.eof() << " " << file.fail() << "\n"; - throw std::logic_error("Ran out of tokens"); - } else if (!file.good()) { - return c; - } - } - - return c; - }; - void rollBackToken() { - if (file.eof()) - file.clear(); - file.seekg(prevPos); - }; - Token getToken() { - char c; - if (file.eof()) { - cout << "Exhaused tokens" << "\n"; - // throw std::exception("Exhausted tokens"); - } - prevPos = file.tellg(); - c = getWithoutWhiteSpace(); - - Token token; - token.type = NULL_TYPE; - if (c == '"') { - token.type = STRING; - token.value = ""; - file.get(c); - while (c != '"') { - token.value += c; - file.get(c); - } - } else if (c == '{') { - token.type = CURLY_OPEN; - } else if (c == '}') { - token.type = CURLY_CLOSE; - } else if (c == '-' || (c >= '0' && c <= '9')) { - // Check if string is numeric - token.type = NUMBER; - token.value = ""; - token.value += c; - std::streampos prevCharPos = file.tellg(); - while ((c == '-') || (c >= '0' && c <= '9') || c == '.') { - prevCharPos = file.tellg(); - file.get(c); - - if (file.eof()) { - break; - } else { - if ((c == '-') || (c >= '0' && c <= '9') || (c == '.')) { - token.value += c; - } else { - file.seekg(prevCharPos); - } - } - } - } else if (c == 'f') { - token.type = BOOLEAN; - token.value = "False"; - file.seekg(4, std::ios_base::cur); - } else if (c == 't') { - token.type = BOOLEAN; - token.value = "True"; - file.seekg(3, std::ios_base::cur); - } else if (c == 'n') { - token.type = NULL_TYPE; - file.seekg(3, std::ios_base::cur); - } else if (c == '[') { - token.type = ARRAY_OPEN; - } else if (c == ']') { - token.type = ARRAY_CLOSE; - } else if (c == ':') { - token.type = COLON; - } else if (c == ',') { - token.type = COMMA; - } - // cout << token.type << " : " << token.value << "\n"; - return token; - }; -}; diff --git a/srcs/load/Env.cpp b/srcs/load/Env.cpp new file mode 100644 index 0000000..4a401b4 --- /dev/null +++ b/srcs/load/Env.cpp @@ -0,0 +1,23 @@ +#include "webserv.hpp" + +Env::Env(JSONNode *conf) { + JSONList servers = conf->obj()["servers"]->lst(); + int i = 0; + string th[8] = {"first", "second", "third", "fourth", + "fifth", "sixth", "seventh", "eigth"}; + for (std::vector::iterator it = servers.begin(); + it < servers.end(); it++) { + Server server(*it); + _servers.push_back(server); + // delete *it; + cout << th[i] << " server launched.\n"; + i++; + } + while (1) { + for (std::vector::iterator it = _servers.begin(); + it < _servers.end(); it++) { + (*it).check(); + } + } + // delete conf; +} diff --git a/srcs/load/Env.hpp b/srcs/load/Env.hpp deleted file mode 100644 index 4abc255..0000000 --- a/srcs/load/Env.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#include "../webserv.hpp" -#include "Server.hpp" - -class Env { - //int _max_clients; - std::vector _servers; - public: - Env(JSONNode *conf) { - JSONList servers = conf->obj()["servers"]->lst(); - int i = 0; - string th[8]= {"first", "second", "third", "fourth", "fifth", "sixth", "seventh", "eigth"}; - for (std::vector::iterator it = servers.begin(); - it < servers.end(); it++) { - Server server(*it); - _servers.push_back(server); - //delete *it; - cout << th[i] << " server launched.\n"; - i++; - } - while(1) { - for (std::vector::iterator it = _servers.begin(); - it < _servers.end(); it++) { - (*it).check(); - } - } - //delete conf; - } -}; diff --git a/srcs/load/Route.cpp b/srcs/load/Route.cpp new file mode 100644 index 0000000..8da4649 --- /dev/null +++ b/srcs/load/Route.cpp @@ -0,0 +1 @@ +#include "webserv.hpp" diff --git a/srcs/load/Server.cpp b/srcs/load/Server.cpp new file mode 100644 index 0000000..be32365 --- /dev/null +++ b/srcs/load/Server.cpp @@ -0,0 +1,25 @@ +#include "webserv.hpp" + +Server::Server(JSONNode *server) { + JSONObject datas = server->obj(); + if (datas["server_name"]) + _name = datas["server_name"]->str(); + if (datas["listens"]) { + JSONList listens = datas["listens"]->lst(); + for (JSONList::iterator i = listens.begin(); i < listens.end(); i++) { + //_listens.push_back((*i)->str()); + Socket sock((*i)->str()); + _sockets.push_back(sock); + } + //_port = std::atoi(_listens.front().c_str()); + } + //_routes["default"] = new Route(datas["root"], datas["return"], + //datas["index"], datas["autoindex"]); +} + +void Server::check() { + for (std::vector::iterator it = _sockets.begin(); + it < _sockets.end(); it++) { + (*it).check(); + } +} diff --git a/srcs/load/Server.hpp b/srcs/load/Server.hpp deleted file mode 100644 index 897957f..0000000 --- a/srcs/load/Server.hpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "../webserv.hpp" -#include "Route.hpp" -#include "Socket.hpp" - - -class Server { - string _name; - std::vector _sockets; - std::map _routes; - - public: - Server(JSONNode *server) { - JSONObject datas = server->obj(); - if (datas["server_name"]) - _name = datas["server_name"]->str(); - if (datas["listens"]) { - JSONList listens = datas["listens"]->lst(); - for (JSONList::iterator i = listens.begin(); i < listens.end(); i++) { - //_listens.push_back((*i)->str()); - Socket sock((*i)->str()); - _sockets.push_back(sock); - } - //_port = std::atoi(_listens.front().c_str()); - } - //_routes["default"] = new Route(datas["root"], datas["return"], datas["index"], datas["autoindex"]); - } - - void check() { - for (std::vector::iterator it = _sockets.begin(); it < _sockets.end(); it++){ - (*it).check(); - } - } -}; diff --git a/srcs/load/Socket.cpp b/srcs/load/Socket.cpp new file mode 100644 index 0000000..6be6cc4 --- /dev/null +++ b/srcs/load/Socket.cpp @@ -0,0 +1,117 @@ + +#include "webserv.hpp" + +Socket::Socket(string def) { + size_t split = def.rfind(':'); + + string tmp = def.substr(0, split - 1); + _ip = isInt(tmp) ? "localhost" : tmp; + tmp = def.substr(split + 1, def.length() - split - 1).c_str(); + _port = !isInt(tmp) ? 80 : std::atoi(tmp.c_str()); + + _max_clients = 30; + + int opt = 1; + _master_socket = socket(AF_INET, SOCK_STREAM, 0); + if (_master_socket == 0) { + cout << "Socket creation: " << strerror(errno) << "\n"; + exit(EXIT_FAILURE); + } + int opt_ret = setsockopt(_master_socket, SOL_SOCKET, SO_REUSEADDR, + (char *)&opt, sizeof(opt)); + if (opt_ret < 0) { + cout << "Sockopt: " << strerror(errno) << "\n"; + exit(EXIT_FAILURE); + } + + _address.sin_family = AF_INET; + _address.sin_addr.s_addr = INADDR_ANY; + _address.sin_port = htons(_port); + + if (bind(_master_socket, (struct sockaddr *)&_address, sizeof(_address)) < + 0) { + cout << "Bind: " << strerror(errno) << "\n"; + cout << "Socket destroyed!\n"; + return; + exit(EXIT_FAILURE); + } + cout << "Listener on port " << _port << "\n"; + + if (listen(_master_socket, 3) < 0) { + cout << "Listen: " << strerror(errno) << "\n"; + exit(EXIT_FAILURE); + } + for (int i = 0; i < _max_clients; i++) + _client_socket[i] = 0; +} +void Socket::check() { + int new_socket, activity, i, valread, sd; + char buffer[1024]; + char r404[72] = + "HTTP/1.1 200 OK\nContent-Type: text/plain\nContent-Length: 4\n\n404!"; + + fd_set readfds; + int max_sd = _master_socket; + + int addrlen = sizeof(_address); + FD_ZERO(&readfds); + FD_SET(_master_socket, &readfds); + + for (i = 0; i < _max_clients; i++) { + sd = _client_socket[i]; + if (sd > 0) + FD_SET(sd, &readfds); + if (sd > max_sd) + max_sd = sd; + } + + activity = select(max_sd + 1, &readfds, NULL, NULL, NULL); + + if ((activity < 0) && (errno != EINTR)) + cout << "Select: " << strerror(errno) << "\n"; + + if (FD_ISSET(_master_socket, &readfds)) { + new_socket = accept(_master_socket, (struct sockaddr *)&_address, + (socklen_t *)&addrlen); + if (new_socket < 0) { + cout << "Accept: " << strerror(errno) << "\n"; + exit(EXIT_FAILURE); + } +#ifdef __APPLE__ + fcntl(new_socket, F_GETNOSIGPIPE); +#endif + cout << "New connection, socket fd is " << new_socket + << ", ip is : " << inet_ntoa(_address.sin_addr) + << ", port : " << ntohs(_address.sin_port) << "\n"; + for (i = 0; i < _max_clients; i++) { + if (_client_socket[i] == 0) { + _client_socket[i] = new_socket; + cout << "Adding to list of sockets as " << i << "\n"; + break; + } + } + } + cout << "Socket: " << _ip << ":" << _port << "\n"; + for (i = 0; i < _max_clients; i++) { + sd = _client_socket[i]; + if (FD_ISSET(sd, &readfds)) { + cout << "Client " << i << ": set\n"; + valread = read(sd, buffer, 1024); + if (valread == 0) { + getpeername(sd, (struct sockaddr *)&_address, + (socklen_t *)&addrlen); + cout << "Host disconnected, ip " << inet_ntoa(_address.sin_addr) + << ", port " << ntohs(_address.sin_port) << "\n"; + close(sd); + _client_socket[i] = 0; + } else { + cout << buffer << "\n"; +#ifdef __linux__ + send(sd, r404, strlen(r404), MSG_NOSIGNAL); +#elif __APPLE__ + send(sd, r404, strlen(r404), 0); +#endif + } + } + } +} diff --git a/srcs/load/Socket.hpp b/srcs/load/Socket.hpp deleted file mode 100644 index 6183d89..0000000 --- a/srcs/load/Socket.hpp +++ /dev/null @@ -1,135 +0,0 @@ -#include "../webserv.hpp" - -class Socket { - string _ip; - int _port; - int _master_socket; - struct sockaddr_in _address; - int _max_clients; - int _client_socket[30]; - public: - Socket(string def) { - size_t split = def.rfind(':'); - - string tmp = def.substr(0, split - 1); - _ip = isInt(tmp) ? "localhost" : tmp; - tmp = def.substr(split + 1, def.length() - split - 1).c_str(); - _port = !isInt(tmp) ? 80 : std::atoi(tmp.c_str()); - - _max_clients = 30; - - int opt = 1; - _master_socket = socket(AF_INET, SOCK_STREAM, 0); - if (_master_socket == 0) { - cout << "Socket creation: " << strerror(errno) << "\n"; - exit(EXIT_FAILURE); - } - int opt_ret = setsockopt(_master_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)); - if (opt_ret < 0) { - cout << "Sockopt: " << strerror(errno) << "\n"; - exit(EXIT_FAILURE); - } - - _address.sin_family = AF_INET; - _address.sin_addr.s_addr = INADDR_ANY; - _address.sin_port = htons(_port); - - if (bind(_master_socket, (struct sockaddr *)&_address, sizeof(_address)) < 0) { - cout << "Bind: " << strerror(errno) << "\n"; - cout << "Socket destroyed!\n"; - return ; - exit(EXIT_FAILURE); - } - cout << "Listener on port " << _port << "\n"; - - if (listen(_master_socket, 3) < 0) { - cout << "Listen: " << strerror(errno) << "\n"; - exit(EXIT_FAILURE); - } - for (int i = 0; i < _max_clients; i++) - _client_socket[i] = 0; - } - void check() { - int new_socket, activity, i, valread, sd; - char buffer[1024]; - char r404[72] = "HTTP/1.1 200 OK\nContent-Type: text/plain\nContent-Length: 4\n\n404!"; - - fd_set readfds; - int max_sd = _master_socket; - - int addrlen = sizeof(_address); - FD_ZERO(&readfds); - FD_SET(_master_socket, &readfds); - - for (i = 0; i < _max_clients; i++) { - sd = _client_socket[i]; - if (sd > 0) - FD_SET(sd, &readfds); - if (sd > max_sd) - max_sd = sd; - } - - activity = select(max_sd + 1, &readfds, NULL, NULL, NULL); - - if ((activity < 0) && (errno != EINTR)) - cout << "Select: " << strerror(errno) << "\n"; - - if (FD_ISSET(_master_socket, &readfds)) { - new_socket = accept(_master_socket, (struct sockaddr *)&_address,(socklen_t *)&addrlen); - if (new_socket < 0) { - cout << "Accept: " << strerror(errno) << "\n"; - exit(EXIT_FAILURE); - } -#ifdef __APPLE__ - fcntl(new_socket, F_GETNOSIGPIPE); -#endif - cout << "New connection, socket fd is " << new_socket - << ", ip is : " << inet_ntoa(_address.sin_addr) - << ", port : " << ntohs(_address.sin_port) << "\n"; - for (i = 0; i < _max_clients; i++) { - if (_client_socket[i] == 0) { - _client_socket[i] = new_socket; - cout << "Adding to list of sockets as " << i << "\n"; - break; - } - } - } - cout << "Socket: " << _ip << ":" << _port << "\n"; - for (i = 0; i < _max_clients; i++) { - sd = _client_socket[i]; - if (FD_ISSET(sd, &readfds)) { - cout << "Client " << i << ": set\n"; - valread = read(sd, buffer, 1024); - if (valread == 0) { - getpeername(sd, (struct sockaddr *)&_address, - (socklen_t *)&addrlen); - cout << "Host disconnected, ip " - << inet_ntoa(_address.sin_addr) << ", port " - << ntohs(_address.sin_port) << "\n"; - close(sd); - _client_socket[i] = 0; - } else { - cout << buffer << "\n"; -#ifdef __linux__ - send(sd, r404, strlen(r404), MSG_NOSIGNAL); -#elif __APPLE__ - send(sd, r404, strlen(r404), 0); -#endif - } - - } - } - } - /* - Socket& operator=(Socket &src) { - _ip = src._ip; - _port = src._port; - _master_socket = src._master_socket; - _address = src._address; - return src; - } -*/ -}; - - - diff --git a/srcs/server.cpp b/srcs/server.cpp deleted file mode 100644 index b161aca..0000000 --- a/srcs/server.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#include "webserv.hpp" -#include "json/Parser.hpp" -#include "load/Env.hpp" - -int main(int ac, char **av) { - Env env; - - if (ac > 1) { - - cout << "Parsing configuration file...\n"; - JSONParser parser(av[1]); - JSONNode *conf = parser.parse(); - cout << "Configuration parsed.\n"; - - cout << "Setting environment...\n"; - env.max_clients = conf->obj()["max_clients"]->nbr(); - JSONList servers = conf->obj()["servers"]->lst(); - int i = 0; - string th[8]= {"first", "second", "third", "fourth", "fifth", "sixth", "seventh", "eigth"}; - for (std::vector::iterator it = servers.begin(); - it < servers.end(); it++) { - Server *server = new Server(*it); - delete *it; - server->launch(); - cout << th[i] << " server launched."; - i++; - } - delete conf; - } - return (0); -} diff --git a/srcs/webserv.cpp b/srcs/webserv.cpp index 90de446..8d76b9c 100644 --- a/srcs/webserv.cpp +++ b/srcs/webserv.cpp @@ -10,7 +10,7 @@ int main(int ac, char **av) { cout << "Configuration parsed.\n"; cout << "Setting environment...\n"; - Env env(conf); + Env env(conf); } return (0); }