diff --git a/' b/' new file mode 100644 index 0000000..9dc2200 --- /dev/null +++ b/' @@ -0,0 +1,210 @@ +#include "Token.hpp" +#include + +class JSONParser { + std::fstream file; + JSONNode *root; + JSONNode *current; + Tokenizer tokenizer; + + public: + JSONParser(const string filename) : tokenizer(filename) {} + void parse() { + string key = ""; + while (tokenizer.hasMoreTokens()) { + Token *token; + JSONNode *parsed; + try { + token = tokenizer.getToken(); + switch (token->type) { + case CURLY_OPEN: { + parsed = parseObject(); + if (!root) { + root = parsed; + } + break; + } + case ARRAY_OPEN: { + parsed = parseList(); + if (!root) { + root = parsed; + } + break; + } + + case STRING: { + tokenizer.rollBackToken(); + parsed = parseString(); + break; + } + case NUMBER: { + tokenizer.rollBackToken(); + parsed = parseNumber(); + break; + } + + case BOOLEAN: { + tokenizer.rollBackToken(); + parsed = parseBoolean(); + break; + } + default: + break; + } + parsed->stringify(0); + } + catch (std::logic_error &e) { + break; + } + delete token; + } + // assert token not valid + } + + JSONNode *parseObject() { + //cout << "Parse Object\n"; + JSONNode *node = new JSONNode(); + JSONObject *keyObjectMap = new JSONObject(); + bool hasCompleted = false; + Token *token = tokenizer.getToken(); + while (!hasCompleted) { + if (tokenizer.hasMoreTokens()) { + string key = token->value; + tokenizer.getToken(); + token = tokenizer.getToken(); + switch (token->type) { + case STRING: { + tokenizer.rollBackToken(); + (*keyObjectMap)[key] = parseString(); + break; + } + case ARRAY_OPEN: { + (*keyObjectMap)[key] = parseList(); + break; + } + case NUMBER: { + tokenizer.rollBackToken(); + (*keyObjectMap)[key] = parseNumber(); + break; + } + case CURLY_OPEN: { + (*keyObjectMap)[key] = parseObject(); + break; + } + case BOOLEAN: { + tokenizer.rollBackToken(); + (*keyObjectMap)[key] = parseBoolean(); + break; + } + case NULL_TYPE: { + (*keyObjectMap)[key] = parseNull(); + break; + } + default: + break; + } + delete token; + token = tokenizer.getToken(); + if (token->type == CURLY_CLOSE) { + hasCompleted = true; + delete token; + break; + } + } else { + throw std::logic_error("No more tokens"); + } + } + node->setObject(keyObjectMap); + return node; + } + + JSONNode *parseList() { + //cout << "Parse List\n"; + JSONNode *node = new JSONNode(); + JSONList *list = new JSONList(); + bool hasCompleted = false; + Token *token = tokenizer.getToken(); + while (!hasCompleted) { + if (!tokenizer.hasMoreTokens()) { + throw std::logic_error("No more tokens"); + } else { + JSONNode *node; + switch (token->type) { + case ARRAY_OPEN: { + node = parseList(); + break; + } + case CURLY_OPEN: { + node = parseObject(); + break; + } + case STRING: { + tokenizer.rollBackToken(); + node = parseString(); + break; + } + case NUMBER: { + tokenizer.rollBackToken(); + node = parseNumber(); + break; + } + case BOOLEAN: { + tokenizer.rollBackToken(); + node = parseBoolean(); + break; + } + case NULL_TYPE: { + node = parseNull(); + break; + } + default: + break; + } + list->push_back(node); + delete token; + token = tokenizer.getToken(); + if (token->type == ARRAY_CLOSE) { + hasCompleted = true; + } + } + } + delete token; + node->setList(list); + return node; + } + + JSONNode *parseString() { + //cout << "Parse string\n"; + JSONNode *node = new JSONNode(); + Token *token = tokenizer.getToken(); + string *sValue = new string(token->value); + delete token; + node->setString(sValue); + return node; + } + + JSONNode *parseNumber() { + //cout << "Parse number\n"; + JSONNode *node = new JSONNode(); + Token *token = tokenizer.getToken(); + string value = token->value; + delete token; + // cout << value << "\n"; + 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); + delete token; + return node; + } + + JSONNode *parseNull() { + JSONNode *node = new JSONNode(); + node->setNull(); + return node; + } +}; diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..649871c --- /dev/null +++ b/.clang-format @@ -0,0 +1,192 @@ +--- +Language: Cpp +# BasedOnStyle: LLVM +AccessModifierOffset: -2 +AlignAfterOpenBracket: Align +AlignArrayOfStructures: None +AlignConsecutiveMacros: None +AlignConsecutiveAssignments: None +AlignConsecutiveBitFields: None +AlignConsecutiveDeclarations: None +AlignEscapedNewlines: Right +AlignOperands: Align +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortEnumsOnASingleLine: true +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: All +AllowShortLambdasOnASingleLine: All +AllowShortIfStatementsOnASingleLine: Never +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: MultiLine +AttributeMacros: + - __capability +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterControlStatement: Never + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeConceptDeclarations: true +BreakBeforeBraces: Attach +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeColon +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' +QualifierAlignment: Leave +CompactNamespaces: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DeriveLineEnding: true +DerivePointerAlignment: false +DisableFormat: false +EmptyLineAfterAccessModifier: Never +EmptyLineBeforeAccessModifier: LogicalBlock +ExperimentalAutoDetectBinPacking: false +PackConstructorInitializers: BinPack +BasedOnStyle: '' +ConstructorInitializerAllOnOneLineOrOnePerLine: false +AllowAllConstructorInitializersOnNextLine: true +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IfMacros: + - KJ_IF_MAYBE +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: '^(<|"(gtest|gmock|isl|json)/)' + Priority: 3 + SortPriority: 0 + CaseSensitive: false + - Regex: '.*' + Priority: 1 + SortPriority: 0 + CaseSensitive: false +IncludeIsMainRegex: '(Test)?$' +IncludeIsMainSourceRegex: '' +IndentAccessModifiers: false +IndentCaseLabels: false +IndentCaseBlocks: false +IndentGotoLabels: true +IndentPPDirectives: None +IndentExternBlock: AfterExternBlock +IndentRequires: false +IndentWidth: 4 +IndentWrappedFunctionNames: false +InsertTrailingCommas: None +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: true +LambdaBodyIndentation: Signature +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 2 +ObjCBreakBeforeNestedBlockParam: true +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakOpenParenthesis: 0 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 60 +PenaltyIndentedWhitespace: 0 +PointerAlignment: Right +PPIndentWidth: -1 +ReferenceAlignment: Pointer +ReflowComments: true +RemoveBracesLLVM: false +SeparateDefinitionBlocks: Leave +ShortNamespaceLines: 1 +SortIncludes: CaseSensitive +SortJavaStaticImport: Before +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeParensOptions: + AfterControlStatements: true + AfterForeachMacros: true + AfterFunctionDefinitionName: false + AfterFunctionDeclarationName: false + AfterIfMacros: true + AfterOverloadedOperator: false + BeforeNonEmptyParentheses: false +SpaceAroundPointerQualifiers: Default +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: Never +SpacesInConditionalStatement: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInLineCommentPrefix: + Minimum: 1 + Maximum: -1 +SpacesInParentheses: false +SpacesInSquareBrackets: false +SpaceBeforeSquareBrackets: false +BitFieldColonSpacing: Both +Standard: Latest +StatementAttributeLikeMacros: + - Q_EMIT +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 4 +UseCRLF: false +UseTab: Never +WhitespaceSensitiveMacros: + - STRINGIZE + - PP_STRINGIZE + - BOOST_PP_STRINGIZE + - NS_SWIFT_NAME + - CF_SWIFT_NAME +... + diff --git a/Makefile b/Makefile index 8e87798..420352c 100644 --- a/Makefile +++ b/Makefile @@ -1,14 +1,14 @@ NAME= server -SRCS= srcs/server.cpp srcs/tools.cpp srcs/read_conf.cpp +SRCS= srcs/server.cpp srcs/tools.cpp OBJS= $(SRCS:.cpp=.o) CXX=c++ -CXXFLAGS= -Wextra -Wall -std=c++98 +CXXFLAGS= -g -Werror -Wextra -Wall -std=c++98 all : $(NAME) $(NAME): $(OBJS) - $(CXX) $(OBJS) -o $(NAME) + $(CXX) -g $(OBJS) -o $(NAME) clean: rm -rf $(OBJS) diff --git a/conf.d/default.json b/conf.d/default.json new file mode 100644 index 0000000..806cd4f --- /dev/null +++ b/conf.d/default.json @@ -0,0 +1,32 @@ +{ + "max_clients": 30, + "servers": + [ + { + "listen": ["80", "[::]:80"], + "server_name": "localhost", + "return": "301 https://$host$uri" + + }, + { + "listen": ["443", "[::]:443"], + "server_name": "localhost", + "root": "datas", + "locations": + { + "/site": + { + "root": "datas/website", + "index": ["index.html", "index.php"], + "try_files": "$uri /$uri =404" + }, + "/img": + { + "index": ["datas/gallery.html"], + "autoindex": true + }, + "/": {"return": "404"} + } + } + ] +} diff --git a/server b/server new file mode 100755 index 0000000..dcca65c Binary files /dev/null and b/server differ diff --git a/srcs/conf_parser/Nodes.hpp b/srcs/conf_parser/Nodes.hpp new file mode 100644 index 0000000..0a756a4 --- /dev/null +++ b/srcs/conf_parser/Nodes.hpp @@ -0,0 +1,131 @@ +#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/conf_parser/Parser.hpp b/srcs/conf_parser/Parser.hpp new file mode 100644 index 0000000..a024071 --- /dev/null +++ b/srcs/conf_parser/Parser.hpp @@ -0,0 +1,213 @@ +#include "Token.hpp" +#include + +class JSONParser { + std::fstream file; + JSONNode *root; + JSONNode *current; + 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/conf_parser/Token.hpp b/srcs/conf_parser/Token.hpp new file mode 100644 index 0000000..43a3ccd --- /dev/null +++ b/srcs/conf_parser/Token.hpp @@ -0,0 +1,159 @@ +#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/read_conf.cpp b/srcs/read_conf.cpp deleted file mode 100644 index 7176675..0000000 --- a/srcs/read_conf.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "server.hpp" - - diff --git a/srcs/server.cpp b/srcs/server.cpp index 6a75ebc..835d3ed 100644 --- a/srcs/server.cpp +++ b/srcs/server.cpp @@ -1,110 +1,131 @@ -#include "server.hpp" +#include "webserv.hpp" #define PORT 80 -int main(void) -{ +int main(int ac, char **av) { + Env env; int opt = 1; - int master_socket, addrlen, new_socket, client_socket[30], max_clients = 30, activity, i, valread, sd; - int max_sd; + int master_socket, addrlen, new_socket, client_socket[30], + max_clients = 30, activity, i, valread, sd; + int max_sd; struct sockaddr_in address; - + char buffer[30000]; - + fd_set readfds; - - char _404[72] = "HTTP/1.1 200 OK\nContent-Type: text/plain\nContent-Length: 4\n\n404!"; - - for (i = 0; i < max_clients; i++) client_socket[i] = 0; - - if( (master_socket = socket(AF_INET, SOCK_STREAM, 0)) == 0) - { - std::cout << std::strerror(errno) << std::endl; + + char _404[72] = + "HTTP/1.1 200 OK\nContent-Type: text/plain\nContent-Length: 4\n\n404!"; + + 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(); + for (std::vector::iterator i = servers.begin(); + i < servers.end(); i++) { + JSONObject datas = (*i)->obj(); + Server *server = + new Server(datas["server_name"]->str(), datas["root"]->str(), + datas["return"]->str(), datas["listen"], + datas["index"], datas["location"]); + delete *i; + } + delete conf; + cout << "Environment setup.\n"; + } + + for (i = 0; i < max_clients; i++) + client_socket[i] = 0; + + if ((master_socket = socket(AF_INET, SOCK_STREAM, 0)) == 0) { + std::cout << std::strerror(errno) << std::endl; exit(EXIT_FAILURE); } - - if ( setsockopt(master_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)) < 0 ) - { - std::cout << std::strerror(errno) << std::endl; + + if (setsockopt(master_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, + sizeof(opt)) < 0) { + std::cout << std::strerror(errno) << std::endl; 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) - { - std::cout << std::strerror(errno) << std::endl; + address.sin_port = htons(PORT); + + if (bind(master_socket, (struct sockaddr *)&address, sizeof(address)) < 0) { + std::cout << std::strerror(errno) << std::endl; exit(EXIT_FAILURE); } - std::cout << "Listener on port " << PORT << std::endl; - - if (listen(master_socket, 3) < 0) - { - std::cout << std::strerror(errno) << std::endl; + std::cout << "Listener on port " << PORT << std::endl; + + if (listen(master_socket, 3) < 0) { + std::cout << std::strerror(errno) << std::endl; exit(EXIT_FAILURE); } - + addrlen = sizeof(address); std::cout << "Waiting for connections ..." << std::endl; - - while(1) - { + + while (1) { FD_ZERO(&readfds); FD_SET(master_socket, &readfds); max_sd = master_socket; - - 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; + + 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)) + + activity = select(max_sd + 1, &readfds, NULL, NULL, NULL); + + if ((activity < 0) && (errno != EINTR)) std::cout << std::strerror(errno) << std::endl; - - if (FD_ISSET(master_socket, &readfds)) - { - if ((new_socket = accept(master_socket, (struct sockaddr *)&address, (socklen_t*)&addrlen))<0) - { - std::cout << std::strerror(errno) << std::endl; + + if (FD_ISSET(master_socket, &readfds)) { + if ((new_socket = accept(master_socket, (struct sockaddr *)&address, + (socklen_t *)&addrlen)) < 0) { + std::cout << std::strerror(errno) << std::endl; exit(EXIT_FAILURE); } - fcntl(new_socket, F_GETNOSIGPIPE); - - std::cout << "New connection, socket fd is " << new_socket \ - << ", ip is : " << inet_ntoa(address.sin_addr) \ - << ", port : " << ntohs(address.sin_port) << std::endl; - - for (i = 0; i < max_clients; i++) - { - if( client_socket[i] == 0 ) - { +#ifdef __APPLE__ + fcntl(new_socket, F_GETNOSIGPIPE); +#endif + std::cout << "New connection, socket fd is " << new_socket + << ", ip is : " << inet_ntoa(address.sin_addr) + << ", port : " << ntohs(address.sin_port) << std::endl; + + for (i = 0; i < max_clients; i++) { + if (client_socket[i] == 0) { client_socket[i] = new_socket; - std::cout << "Adding to list of sockets as " << i << std::endl; - break; + std::cout << "Adding to list of sockets as " << i + << std::endl; + break; } } } - - for (i = 0; i < max_clients; i++) - { + + for (i = 0; i < max_clients; i++) { sd = client_socket[i]; - if (FD_ISSET( sd, &readfds)) - { - valread = read(sd, buffer,30000); - if (valread == 0) - { - getpeername(sd, (struct sockaddr*)&address, (socklen_t*)&addrlen); - std::cout << "Host disconnected, ip " << inet_ntoa(address.sin_addr)\ - << ", port " << ntohs(address.sin_port) << std::endl; - close( sd ); + if (FD_ISSET(sd, &readfds)) { + valread = read(sd, buffer, 30000); + if (valread == 0) { + getpeername(sd, (struct sockaddr *)&address, + (socklen_t *)&addrlen); + std::cout << "Host disconnected, ip " + << inet_ntoa(address.sin_addr) << ", port " + << ntohs(address.sin_port) << std::endl; + close(sd); client_socket[i] = 0; - } - else send(sd, _404, strlen(_404), 0); + } else + send(sd, _404, strlen(_404), MSG_NOSIGNAL); } } } diff --git a/srcs/server.hpp b/srcs/server.hpp deleted file mode 100644 index eee344e..0000000 --- a/srcs/server.hpp +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include //FD_SET, FD_ISSET, FD_ZERO macros -#include - -#include -#include -#include -#include -#include -#include - -class Route { - std::string _location; - std::string _root; - std::string _index; - public: - Route(std::string location, std::string root, std::string index); - ~Route(); -}; - -class Server { - unsigned int _port; - std::string _server_name; - std::vector _routes; - public: - Server(char *filename); - ~Server(); -}; - -void *ft_memset(void *b, int c, size_t len); - diff --git a/srcs/server.o b/srcs/server.o new file mode 100644 index 0000000..33cad16 Binary files /dev/null and b/srcs/server.o differ diff --git a/srcs/tools.cpp b/srcs/tools.cpp index 602e368..e459e9c 100644 --- a/srcs/tools.cpp +++ b/srcs/tools.cpp @@ -1,13 +1,12 @@ -#include "server.hpp" +#include "webserv.hpp" -void *ft_memset(void *b, int c, size_t len) -{ - size_t i; - unsigned char * b_cpy; +void *ft_memset(void *b, int c, size_t len) { + size_t i; + unsigned char *b_cpy; - b_cpy = (unsigned char *)b; - i = 0; - while (i < len) - *(unsigned char *)(b_cpy + i++) = (unsigned char)c; - return ((void *)b); + b_cpy = (unsigned char *)b; + i = 0; + while (i < len) + *(unsigned char *)(b_cpy + i++) = (unsigned char)c; + return ((void *)b); } diff --git a/srcs/tools.o b/srcs/tools.o new file mode 100644 index 0000000..fe10042 Binary files /dev/null and b/srcs/tools.o differ diff --git a/srcs/webserv.cpp b/srcs/webserv.cpp new file mode 100644 index 0000000..8da4649 --- /dev/null +++ b/srcs/webserv.cpp @@ -0,0 +1 @@ +#include "webserv.hpp" diff --git a/srcs/webserv.hpp b/srcs/webserv.hpp new file mode 100644 index 0000000..b806da1 --- /dev/null +++ b/srcs/webserv.hpp @@ -0,0 +1,49 @@ +#pragma once +#include "conf_parser/Parser.hpp" + +#include +#include +#include +#include +#include //FD_SET, FD_ISSET, FD_ZERO macros +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class Route { + std::vector _location; + std::vector _index; + std::string _root; + + public: + Route(std::string location, std::string root, std::string index); + ~Route(); +}; + +class Server { + unsigned int _port; + std::string _server_name; + std::vector *_routes; + + public: + Server(std::string name, std::string root, std::string return, + JSONNode *listens, JSONNode *indexs, JSONNode *locations); + ~Server(); +}; + +class Env { + public: + std::vector *servers; + int max_clients; +}; + +void *ft_memset(void *b, int c, size_t len); diff --git a/vgcore.1971358 b/vgcore.1971358 new file mode 100644 index 0000000..93772ec Binary files /dev/null and b/vgcore.1971358 differ diff --git a/vgcore.2047517 b/vgcore.2047517 new file mode 100644 index 0000000..ea494dc Binary files /dev/null and b/vgcore.2047517 differ diff --git a/vgcore.2587640 b/vgcore.2587640 new file mode 100644 index 0000000..cc7d6f4 Binary files /dev/null and b/vgcore.2587640 differ