nicolas-arnaud
2 years ago
25 changed files with 747 additions and 742 deletions
@ -1,13 +1,16 @@ |
|||||
* |
* |
||||
!srcs/ |
|
||||
!srcs/load/ |
|
||||
!srcs/json/ |
|
||||
!srcs/*/*.cpp |
|
||||
!srcs/*/*.hpp |
|
||||
!srcs/*.hpp |
|
||||
!srcs/*.cpp |
|
||||
!Makefile |
!Makefile |
||||
!LICENCE |
!LICENCE |
||||
!README.md |
!README.md |
||||
!default.json |
!default.json |
||||
!.gitignore |
!.gitignore |
||||
|
|
||||
|
!includes/ |
||||
|
!includes/*.hpp |
||||
|
|
||||
|
!srcs/ |
||||
|
!srcs/*.cpp |
||||
|
!srcs/load/ |
||||
|
!srcs/json/ |
||||
|
!srcs/*/*.cpp |
||||
|
@ -0,0 +1,12 @@ |
|||||
|
#pragma once |
||||
|
#include "webserv.hpp" |
||||
|
|
||||
|
|
||||
|
class JSONNode; |
||||
|
class Server; |
||||
|
|
||||
|
class Env { |
||||
|
std::vector<Server> _servers; |
||||
|
public: |
||||
|
Env(JSONNode *conf); |
||||
|
}; |
@ -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; |
||||
|
}; |
@ -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(); |
||||
|
}; |
@ -1,4 +1,5 @@ |
|||||
#include "../webserv.hpp" |
#pragma once |
||||
|
#include "webserv.hpp" |
||||
|
|
||||
class Route { |
class Route { |
||||
string _root; |
string _root; |
@ -0,0 +1,13 @@ |
|||||
|
#pragma once |
||||
|
#include "webserv.hpp" |
||||
|
|
||||
|
|
||||
|
class Server { |
||||
|
string _name; |
||||
|
std::vector<Socket> _sockets; |
||||
|
std::map<string, Route *> _routes; |
||||
|
|
||||
|
public: |
||||
|
Server(JSONNode *server); |
||||
|
void check(); |
||||
|
}; |
@ -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; |
||||
|
} |
||||
|
*/ |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
|
@ -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(); |
||||
|
}; |
@ -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(); |
||||
|
} |
@ -1,131 +0,0 @@ |
|||||
#include <iostream> |
|
||||
#include <map> |
|
||||
#include <sstream> |
|
||||
#include <string> |
|
||||
#include <vector> |
|
||||
|
|
||||
#define DEBUG 0 |
|
||||
|
|
||||
using std::cout; |
|
||||
using std::string; |
|
||||
|
|
||||
class JSONNode; |
|
||||
typedef std::map<string, JSONNode *> JSONObject; |
|
||||
typedef std::vector<JSONNode *> 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; |
|
||||
}; |
|
@ -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; |
||||
|
} |
@ -1,211 +0,0 @@ |
|||||
#include "Token.hpp" |
|
||||
#include <cstdlib> |
|
||||
|
|
||||
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; |
|
||||
} |
|
||||
}; |
|
@ -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; |
||||
|
} |
@ -1,158 +0,0 @@ |
|||||
#include "Nodes.hpp" |
|
||||
#include <fstream> |
|
||||
|
|
||||
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; |
|
||||
}; |
|
||||
}; |
|
@ -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<JSONNode *>::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<Server>::iterator it = _servers.begin(); |
||||
|
it < _servers.end(); it++) { |
||||
|
(*it).check(); |
||||
|
} |
||||
|
} |
||||
|
// delete conf;
|
||||
|
} |
@ -1,28 +0,0 @@ |
|||||
#include "../webserv.hpp" |
|
||||
#include "Server.hpp" |
|
||||
|
|
||||
class Env { |
|
||||
//int _max_clients;
|
|
||||
std::vector<Server> _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<JSONNode *>::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<Server>::iterator it = _servers.begin(); |
|
||||
it < _servers.end(); it++) { |
|
||||
(*it).check(); |
|
||||
} |
|
||||
} |
|
||||
//delete conf;
|
|
||||
} |
|
||||
}; |
|
@ -0,0 +1 @@ |
|||||
|
#include "webserv.hpp" |
@ -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<Socket>::iterator it = _sockets.begin(); |
||||
|
it < _sockets.end(); it++) { |
||||
|
(*it).check(); |
||||
|
} |
||||
|
} |
@ -1,33 +0,0 @@ |
|||||
#include "../webserv.hpp" |
|
||||
#include "Route.hpp" |
|
||||
#include "Socket.hpp" |
|
||||
|
|
||||
|
|
||||
class Server { |
|
||||
string _name; |
|
||||
std::vector<Socket> _sockets; |
|
||||
std::map<string, Route *> _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<Socket>::iterator it = _sockets.begin(); it < _sockets.end(); it++){ |
|
||||
(*it).check(); |
|
||||
} |
|
||||
} |
|
||||
}; |
|
@ -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 |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
@ -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; |
|
||||
} |
|
||||
*/ |
|
||||
}; |
|
||||
|
|
||||
|
|
||||
|
|
@ -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<JSONNode *>::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); |
|
||||
} |
|
Loading…
Reference in new issue