Commit 73ecc26c authored by Hebant Martin's avatar Hebant Martin
Browse files

Initial commit

parents
#include "AppModule.h"
using namespace std;
int AppModule::errorCode = 0;
AppModule* AppModule::appModule[MAXAPPMODULE];
int AppModule::init() {
int i = 0;
#ifdef WIN32
HANDLE dir;
WIN32_FIND_DATA file_data;
if ((dir = FindFirstFile("./app/*", &file_data)) != INVALID_HANDLE_VALUE)
{
do {
const string file_name = file_data.cFileName;
const bool is_directory = (file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
#elif defined LINUX
DIR *dir;
class dirent *ent;
class stat st;
if ((dir = opendir("./app/")) != NULL)
while ((ent = readdir(dir)) != NULL) {
const string file_name = ent->d_name;
const bool is_directory = (st.st_mode & S_IFDIR) != 0;
/*if (stat(full_file_name.c_str(), &st) == -1)
continue;*/
if (stat(file_name.c_str(), &st) == -1)
continue;
#endif
if (file_name[0] == '.' || file_name.substr(file_name.length()-strlen(EXTENSION), strlen(EXTENSION)) != EXTENSION)
continue;
if (is_directory)
continue;
if(i < MAXAPPMODULE)
{
appModule[i] = new AppModule("./app/" + file_name);
if(!appModule[i]->info.wellInit)
{
delete appModule[i];
appModule[i] = 0;
Log::print("Error loading an AppModule. File: " + file_name + " AppModuleError: " + to_string(errorCode), Log::ERR);
continue;
}
else
i++;
}
else
{
Log::print("Too many AppModule loaded !", Log::WARNING);
errorCode = -3;
break;
}
#ifdef WIN32
} while (FindNextFile(dir, &file_data));
}
FindClose(dir);
#elif defined LINUX
}
closedir(dir);
#endif
string msg = "";
i = 0;
while(appModule[i] != 0)
{
if(i == 0)
msg.append("AppModule correctly loaded: " + appModule[i]->info.name);
else
msg.append(", " + appModule[i]->info.name);
i++;
}
if(msg != "")
Log::print(msg, Log::INFO);
return 0;
}
int AppModule::end() {
for(int i = 0; i < MAXAPPMODULE; i++)
{
if(appModule[i] == 0)
delete appModule[i];
}
return 0;
}
int AppModule::getLastError() {
return errorCode;
}
int AppModule::load(const string& name) {
for(int i = 0; i < MAXAPPMODULE; i++)
{
if(appModule[i]==0)
{
appModule[i] = new AppModule("./app/" + name + EXTENSION);
if(!appModule[i]->info.wellInit)
{
delete appModule[i];
appModule[i] = 0;
return errorCode;
}
else
return 0;
}
}
return -3;
}
int AppModule::unload(const string& name) {
for(int i = 0; i < MAXAPPMODULE; i++)
{
if(appModule[i] != 0 && appModule[i]->info.name == name)
{
delete appModule[i];
appModule[i] = 0;
return 0;
}
}
return -4;
}
AppModule::AppModule(const string& path) {
init_func = 0;
end_func = 0;
lib = LoadLibrary(path.c_str());
if(lib == 0)
{
errorCode = -1;
info.wellInit = false;
return;
}
init_func = (init_info (*)(void)) GetProcAddress(lib, "init");
end_func = (void (*)(void)) GetProcAddress(lib, "end");
if(init_func == 0 || end_func == 0)
{
errorCode = -2;
info.wellInit = false;
return;
}
info = init_func();
if(!info.wellInit)
{
errorCode = -5;
return;
}
}
AppModule::~AppModule() {
if(end_func != 0)
end_func();
if(lib != 0)
FreeLibrary(lib);
}
/* AppModuleError:
0 : No error
-1 : Unable to load the library
-2 : Unable to extract function
-3 : Too many AppModule loaded (more than MAXAPPMODULE)
-4 : There is no loaded AppModule named this way (AppModule not loaded)
-5 : Initialization of the module failed
*/
#ifndef APP_H_INCLUDED
#define APP_H_INCLUDED
#ifdef WIN32 /* Windows */
#include <windows.h>
#define EXTENSION ".dll"
#elif defined LINUX /* Linux */
#include <dlfcn.h>
//#include <sys/types.h>
#include <dirent.h>
#define HMODULE void*
#define FARPROC void*
#define LoadLibrary(s) dlopen(s, RTLD_LAZY)
#define GetProcAddress(l, s) dlsym(l, s)
#define FreeLibrary(l) dlclose(l)
#define EXTENSION ".so"
#else
#error Please define WIN32 or LINUX to compile
#endif
#include <string>
#include "Log.h"
#define MAXAPPMODULE 10
class AppModule{
public:
struct init_info {std::string name; bool wellInit;};
private:
static int errorCode;
static AppModule* appModule[MAXAPPMODULE];
public:
static int init();
static int end();
static int getLastError();
static int load(const std::string& name);
static int unload(const std::string& name);
private:
HMODULE lib;
std::string name;
init_info (*init_func)(void);
void (*end_func)(void);
init_info info;
public:
AppModule(const std::string& path);
~AppModule();
};
#endif // APP_H_INCLUDED
#include "Client.h"
using namespace std;
Client* Client::clients[MAXCLIENT];
stack<int> Client::freeSlot;
stack<int> Client::toFree;
thread Client::freeMemoryTh;
bool Client::continueFreeMemory;
void Client::init() {
for(int i = 0; i < MAXCLIENT; i++)
{
clients[i] = 0;
freeSlot.push(i);
}
continueFreeMemory = true;
freeMemoryTh = thread(freeMemory); //Delete if you dont care about memory
}
void Client::end() {
for(int i = 0; i < MAXCLIENT; i++)
delete clients[i];
continueFreeMemory = false;
freeMemoryTh.join(); //Delete if you dont care about memory
}
void Client::freeClient(Client* client) {
int i;
for(i = 0; i < MAXCLIENT; i++)
if(clients[i] == client)
break;
if(i < MAXCLIENT)
toFree.push(i);
else
Log::print("ClientManager failed (free inexistent client) (this error may not appears !!)", Log::ERR);
}
int Client::newClient(Socket clt, onRequest_func func, Socket::SSLConfig* conf) {
if(!toFree.empty())
{
int i = toFree.top();
toFree.pop();
delete clients[i];
clients[i] = new Client(clt, func, conf);
return 0;
}
else if(!freeSlot.empty())
{
clients[freeSlot.top()] = new Client(clt, func, conf);
freeSlot.pop();
return 0;
}
else
return -1;
}
void Client::freeMemory() {
while(continueFreeMemory)
{
while(!toFree.empty())
{
int i = toFree.top();
toFree.pop();
delete clients[i];
clients[i] = 0;
freeSlot.push(i);
}
this_thread::sleep_for(chrono::microseconds(1000000));
}
}
int Client::getNumClient() {
return MAXCLIENT - (freeSlot.size() + toFree.size());
}
Client::Client(Socket clt, onRequest_func func, Socket::SSLConfig* conf) : client(clt), onRequest(func), sslconfig(conf) {
th = thread(&Client::takeOver, this);
}
Client::~Client() {
if(th.joinable())
th.join();
}
void Client::takeOver() {
client.SetTimeout(5000); // 5sec
int e;
if (sslconfig == 0 || (e=client.SSL(*sslconfig)) == 0)
while(true)
{
Request request(client);
Response response(client);
e = request.download();
if (e > 0)
{
onRequest(request, response);
if(sslconfig == 0)
Log::print("HTTP request for " + request.url + " Status: " + to_string(response.code), Log::INFO);
else
Log::print("HTTPS request for " + request.url + " Status: " + to_string(response.code), Log::INFO);
if(request.getHeaderField("Connection") == "keep-alive")
continue;
else
break;
}
if(e == 0) // TimeOut
break;
if(e == -1) // Socket Error
{
Log::print("Failed downloading request. SocketError : " + to_string(Socket::GetLastSocketError()) , Log::ERR);
break;
}
if(e == -2) // Connection aborted
break;
if(e == -3) // Request Invalid
{
Log::print("Invalid request received", Log::WARNING);
response.code = 400;
response.send();
continue;
}
if(e < -10)
{
Log::print("Failed downloading request. mbedtls : " + to_string(e) , Log::ERR);
break;
}
}
else
Log::print("Failed opening SSL connection. mbedtls error: " + to_string(e), Log::WARNING);
client.Close();
Client::freeClient(this);
}
#ifndef CLIENT_H_INCLUDED
#define CLIENT_H_INCLUDED
#include <thread>
#include <iostream>
#include <stack>
#include "Log.h"
#include "Socket.h"
#include "Request.h"
#include "Response.h"
#define MAXCLIENT 10
class Client {
private:
typedef void (*onRequest_func)(Request& requ, Response& resp);
static Client* clients[MAXCLIENT];
static std::stack<int> freeSlot;
static std::stack<int> toFree;
static std::thread freeMemoryTh;
static bool continueFreeMemory;
static void freeMemory();
public:
static void init();
static void end();
static void freeClient(Client* client);
static int newClient(Socket clt, onRequest_func onRequest, Socket::SSLConfig* conf);
static int getNumClient();
private:
Socket client;
onRequest_func onRequest;
Socket::SSLConfig* sslconfig;
std::thread th;
public:
Client(Socket client, onRequest_func, Socket::SSLConfig* conf);
~Client();
void takeOver();
};
#endif // CLIENT_H_INCLUDED
#include "FileSystem.h"
using namespace std;
vector<FileSystem::Mime> FileSystem::mimeTypes;
int FileSystem::init() {
return loadMimeType();
}
void FileSystem::end() {
}
int FileSystem::loadMimeType() {
mimeTypes = vector<Mime>();
ifstream file("mime.type");
if(!file.good()) {
return -1; // ERROR -1 : Impossible to read mime.type file
}
int l = 0;
string line;
while(getline(file, line))
{
l++;
Mime m;
int i = line.find_first_of(' ');
if(i == string::npos) {
return -2; // ERROR -2 : Invalid file line
}
m.ext = line.substr(0, i);
m.type = line.substr(i+1, line.length()-i-2);
mimeTypes.push_back(m);
}
file.close();
return 0;
}
bool FileSystem::exist(const string& path) {
return access( path.c_str(), F_OK ) != -1;
}
bool FileSystem::isDirectory(const string& path) {
struct stat s;
if(stat(path.c_str(), &s) == 0 )
return s.st_mode & S_IFDIR;
else
return false; // ERROR !!
}
size_t FileSystem::sizeFile(const string& path) {
struct stat s;
if(stat(path.c_str(), &s) != 0)
return 0; // ERROR
return s.st_size;
}
time_t FileSystem::mTimeFile(const string& path) {
struct stat s;
if(stat(path.c_str(), &s) != 0)
return 0; // ERROR
return s.st_mtime;
}
string FileSystem::getMimeType(const string& path) {
int i = path.find_last_of('.');
if(i == string::npos)
i = 0;
else
i++;
string ext = path.substr(i);
if(mimeTypes.size() == 0)
return "";
i = 0;
while(mimeTypes[i].ext != ext)
{
i++;
if(i == mimeTypes.size())
return "";
}
return mimeTypes[i].type;
}
/* ----File ver0.1(28/07/2015)----
Win 32 / Linux
Represent
Define WIN32 if compile for Windows 32 bit or LINUX if compile for Linux
*/
#ifndef FILE_H_INCLUDED
#define FILE_H_INCLUDED
/*#ifdef WIN32
#include <windows.h>
#elif defined LINUX
#include
#else
#endif*/
#include <string>
#include <vector>
#include <fstream>
#include <unistd.h>
#include <time.h>
#include <sys/stat.h>
class FileSystem {
private:
struct Mime { std::string ext; std::string type; };
static std::vector<Mime> mimeTypes;
public:
static int init();
static void end();
static int loadMimeType();
static bool exist(const std::string& path);
static bool isDirectory(const std::string& path);
static size_t sizeFile(const std::string& path);
static time_t mTimeFile(const std::string& path);
static std::string getMimeType(const std::string& path);
};
#endif // FILE_H_INCLUDED
#include "Helper.h"
using namespace std;
string Helper::chartohex(const char dec) {
char dig1 = (dec&0xF0)>>4;
char dig2 = (dec&0x0F);
if ( 0<= dig1 && dig1<= 9) dig1+=48; //0,48 in ascii
else if (10<= dig1 && dig1<=15) dig1+=65-10; //A,65 in ascii
if ( 0<= dig2 && dig2<= 9) dig2+=48;
else if (10<= dig2 && dig2<=15) dig2+=65-10;
string hex;
hex.append( &dig1, 1);
hex.append( &dig2, 1);
return hex;
}
char Helper::hextochar(const char* hex) {
char dig1 = hex[0];
char dig2 = hex[1];
if(48 <= dig1 && dig1 <= 57) dig1=-48;
else if(65 <= dig1 && dig1 <= 73) dig1=-65+10;
if(48 <= dig2 && dig2 <= 57) dig2=-48;
else if(65 <= dig2 && dig2 <= 73) dig2=-65+10;
char dec;
dec = (dig1<<4)&dig2;
return dec;
}
string Helper::url_encode(const string& str) {
string url;
int max = str.length();
for(int i=0; i < max; i++)
{
if (
(48 <= str[i] && str[i] <= 57) ||//0-9
(65 <= str[i] && str[i] <= 90) ||//ABC...XYZ
(97 <= str[i] && str[i] <= 122) || //abc...xyz
(str[i]=='~' || str[i]=='-' || str[i]=='_' || str[i]=='.')
)
url.append(&str[i], 1);
else
{
url.append("%");
url.append(chartohex(str[i]));//converts char 255 to string "FF"
}
}
return url;
}
string Helper::url_decode(const string& url) {
string str;
int max = url.length();
for(int i=0; i < max; i++)
{
if(url[i] != '%')
str.append(&url[i], 1);
else
{