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

Initial commit

parents
/*
ResponseError
0 : Header already sent
-1 : SocketError
*/
#ifndef RESPONSE_H_INCLUDED
#define RESPONSE_H_INCLUDED
#include <string>
#include <cstring>
#include <time.h>
#include "Socket.h"
class Response
{
private:
char header[2048] = "";
bool headerSended = false;
char* content = 0;
int contentLength = 0;
bool contentHosted = false; // A sup ?
Socket& sock;
public:
int code = 200;
Response(Socket& sock);
~Response();
void addHeader(const char* field, const char* value);
void setContent(char* ptrContent, int length);
char* createContent(int length); // A sup ?
int sendHeader();
int send();
};
#endif // RESPONSE_H_INCLUDED
/* ----Socket ver3.0(05/02/2016)---- */
#include "Socket.h"
using namespace std;
#ifdef SSLSOCKET
mbedtls_entropy_context Socket::entropy;
mbedtls_ctr_drbg_context Socket::ctr_drbg;
#endif
int Socket::init() {
#ifdef WIN32
WSADATA wsa;
if(WSAStartup(MAKEWORD(2, 2), &wsa) < 0)
{
return -1;
}
#endif
#ifdef SSLSOCKET
//SLL Entropy
mbedtls_ctr_drbg_init(&ctr_drbg);
mbedtls_entropy_init(&entropy);
const char* custom = "customseedgenerator";
int e;
if ((e = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char*)custom, strlen(custom))) != 0)
return e;
//To avoid SIGPIE signal when peer closing connection prematuraly with SSL
signal(SIGPIPE, SIG_IGN);
#endif
return 0;
}
void Socket::end() {
#ifdef WIN32
WSACleanup();
#endif
#ifdef SSLSOCKET
mbedtls_ctr_drbg_free(&ctr_drbg);
mbedtls_entropy_free(&entropy);
#endif
}
SocketAddress Socket::Address(u_long addr, int port) {
SocketAddress address = {0};
address.sin_family = AF_INET;
AddressSetIP(address, addr);
AddressSetPort(address, port);
return address;
}
int Socket::AddressSetIP(SocketAddress& address, u_long addr) {
address.sin_addr.s_addr = htonl(addr);
return 0;
}
int Socket::AddressSetPort(SocketAddress& address, int port) {
address.sin_port = htons(port);
return 0;
}
u_long Socket::AddressGetIP(SocketAddress& address) {
return ntohl(address.sin_addr.s_addr);
}
int Socket::AddressGetPort(SocketAddress& address) {
return ntohs(address.sin_port);
}
int Socket::GetLastSocketError() {
#ifdef WIN32
return WSAGetLastError();
#elif defined (LINUX)
return errno;
#endif
}
Socket::Socket(short protocol) {
sock = socket(AF_INET, protocol, 0);
timeout.tv_sec = 0;
timeout.tv_usec = 0;
}
Socket::Socket(SOCKET so) : sock(so) {
timeout.tv_sec = 0;
timeout.tv_usec = 0;
}
Socket::Socket(short protocol, u_long addr, int port) : Socket(protocol) {
if (IsValid())
{
SocketAddress address = Address(addr, port);
BindAddress(address);
}
}
Socket::~Socket() {
//Close();
#ifdef SSLSOCKET
delete ssl;
#endif
}
int Socket::BindAddress(SocketAddress address) {
if(bind(sock, (SOCKADDR*) &address, sizeof address) == SOCKET_ERROR)
{
return -1;
}
return 0;
}
SocketAddress Socket::GetAddress() {
SocketAddress address = {};
int len = sizeof address;
if (getsockname(sock, (SOCKADDR*) &address, (socklen_t*)&len) < 0)
{
return {0};
}
return address;
}
int Socket::SetTimeout(long millisec) {
timeout.tv_sec = millisec/1000;
timeout.tv_usec = (millisec%1000)*1000;
return 0;
}
bool Socket::IsValid() {
return sock != INVALID_SOCKET;
}
int Socket::Listen(int num) {
if(listen(sock, num) == SOCKET_ERROR)
{
return -1;
}
return 0;
}
Socket Socket::Accept() {
if(timeout.tv_usec > 0 || timeout.tv_sec > 0)
{
fd_set readfs;
FD_ZERO(&readfs);
FD_SET(sock, &readfs);
timeval ctimeout = timeout;
int s = select(sock + 1, &readfs, NULL, NULL, &ctimeout);
if(s < 0)
{
return Socket(INVALID_SOCKET);
}
if(s == 0)
return Socket(INVALID_SOCKET);
}
SocketAddress clientAddress = { 0 };
SOCKET csock;
int len = sizeof clientAddress;
csock = accept(sock, (SOCKADDR*) &clientAddress, (socklen_t*)&len);
return Socket(csock);
}
int Socket::Connect(u_long addr, int port) {
SocketAddress address = { 0 };
address.sin_addr.s_addr = htonl(addr);
address.sin_family = AF_INET;
address.sin_port = htons(port);
if(connect(sock,(SOCKADDR*) &address, sizeof address) == SOCKET_ERROR)
{
return -1;
}
return 0;
}
int Socket::Recive(char* data, int length) {
if(timeout.tv_usec > 0 || timeout.tv_sec > 0)
{
fd_set readfs;
FD_ZERO(&readfs);
FD_SET(sock, &readfs);
timeval ctimeout = timeout;
int s = select(sock + 1, &readfs, NULL, NULL, &ctimeout);
if(s < 0)
{
return -1;
}
if(s == 0)
return 0;
}
#ifdef SSLSOCKET
if(ssl != 0)
return mbedtls_ssl_read(ssl, (unsigned char*)data, length);
#endif
return recv(sock, data, length, 0);
}
int Socket::ReciveFrom(char* data, int length, SocketAddress& address) {
if(timeout.tv_usec > 0 || timeout.tv_sec > 0)
{
fd_set readfs;
FD_ZERO(&readfs);
FD_SET(sock, &readfs);
timeval ctimeout = timeout;
int s = select(sock + 1, &readfs, NULL, NULL, &ctimeout);
if(s < 0)
{
return -1;
}
if(s == 0)
return 0;
}
int len = sizeof address;
return recvfrom(sock, data, length, 0, (SOCKADDR*) &address, (socklen_t*)&len);
}
int Socket::Send(const char* data, int length) {
#ifdef SSLSOCKET
if (ssl != 0) {
int ret = mbedtls_ssl_write(ssl, (const unsigned char*)data, length);
if (ret > 0 && ret < length)
return mbedtls_ssl_write(ssl, (const unsigned char*)data+ret, length-ret);
else
return ret;
}
#endif
if(send(sock, data, length, 0) < 0)
{
return -1;
}
return 0;
}
int Socket::SendTo(const char* data, int length, const SocketAddress& address) {
if(sendto(sock, data, length, 0, (SOCKADDR*) &address, sizeof address) < 0)
{
return -1;
}
return 0;
}
void Socket::Close() {
#ifdef SSLSOCKET
mbedtls_ssl_close_notify(ssl);
mbedtls_ssl_free(ssl);
#endif
closesocket(sock);
}
#ifdef SSLSOCKET
int Socket::SSL(SSLConfig& sslconfig) {
ssl = new mbedtls_ssl_context();
mbedtls_ssl_init(ssl);
int e;
if ((e = mbedtls_ssl_setup( ssl, &(sslconfig.conf))) != 0)
return e;
mbedtls_ssl_session_reset(ssl);
mbedtls_ssl_set_bio( ssl, &sock, mbedtls_net_send, mbedtls_net_recv, NULL);
if ((e = mbedtls_ssl_handshake(ssl)) != 0) //while...
return e;
return 0;
}
#endif
\ No newline at end of file
/* ----Socket ver3.0(05/02/2016)----
Win 32 / Linux
Represent and control a socket (TCP or UDP) in server or client mode
Define WIN32 if compile for Windows 32 bit or LINUX if compile for Linux
Define SSLSOCKET for SSL supported socket (Not finished).
For Windows:
Lib: -lws2_32
For SSL:
Lib: -lmbedtls -lmbedx509 -lmbedcrypto
Errors:
>0 No Error
0 Timeout (Or no error)
-1 Socket error (call GetLastSocketError)
<-1 mbedtls error
*/
#ifndef SOCKET_H_INCLUDED
#define SOCKET_H_INCLUDED
#ifdef WIN32 /* Windows */
#include <winsock2.h>
#define socklen_t int
#elif defined LINUX /* Linux */
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h> /* close */
#include <netdb.h> /* gethostbyname */
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define closesocket(s) close(s)
typedef int SOCKET;
typedef struct sockaddr_in SOCKADDR_IN;
typedef struct sockaddr SOCKADDR;
typedef struct in_addr IN_ADDR;
#else /* Not supported */
#error Please define WIN32 or LINUX to compile
#endif
#ifdef SSLSOCKET
#include "mbedtls/ssl.h"
#include "mbedtls/net.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/certs.h"
#include <signal.h>
#include <cstring>
#endif
typedef struct sockaddr_in SocketAddress;
class Socket
{
#ifdef SSLSOCKET
private:
static mbedtls_entropy_context entropy;
static mbedtls_ctr_drbg_context ctr_drbg;
#endif
public:
static int init();
static void end();
static SocketAddress Address(u_long addr, int port);
static int AddressSetIP(SocketAddress& address, u_long addr);
static int AddressSetPort(SocketAddress& address, int port);
static u_long AddressGetIP(SocketAddress& address);
static int AddressGetPort(SocketAddress& address);
static int GetLastSocketError();
static const short TCP = 1;
static const short UDP = 2;
static const short CLIENT = 0;
static const short SERVER = 1;
#ifdef SSLSOCKET
struct SSLConfig {
mbedtls_ssl_config conf;
mbedtls_x509_crt srvcert;
mbedtls_pk_context pkey;
/*static void my_debug(void *ctx, int level, const char *file, int line, const char *str) {
((void) level);
fprintf((FILE *) ctx, "%s:%04d: %s", file, line, str);
fflush((FILE *) ctx); }*/
SSLConfig() { mbedtls_ssl_config_init(&conf); mbedtls_x509_crt_init(&srvcert); mbedtls_pk_init(&pkey); }
int LoadCrtFile(const char* crtfile) { return mbedtls_x509_crt_parse_file(&srvcert, crtfile); }
int LoadCrtPath(const char* crtpath) { return mbedtls_x509_crt_parse_path(&srvcert, crtpath); }
int Config(short type, short protocol, const char* pkeyfile) {
int e;
if ((e = mbedtls_ssl_config_defaults(&conf, type, protocol-1, MBEDTLS_SSL_PRESET_DEFAULT)) != 0 )
return e;
mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg);
//mbedtls_ssl_conf_dbg(&conf, my_debug, stdout);
//mbedtls_ssl_conf_ca_chain(&conf, srvcert.next, NULL);
if ((e = mbedtls_pk_parse_keyfile(&pkey, pkeyfile, NULL)) != 0)
return e;
if ((e = mbedtls_ssl_conf_own_cert(&conf, &srvcert, &pkey)) != 0)
return e;
return 0;
}
~SSLConfig() { mbedtls_ssl_config_free(&conf); mbedtls_x509_crt_free(&srvcert); mbedtls_pk_free(&pkey); }
};
#endif
private:
SOCKET sock;
struct timeval timeout;
#ifdef SSLSOCKET
mbedtls_ssl_context* ssl = 0;
#endif
public:
Socket(short protocol);
Socket(SOCKET sock);
Socket(short protocol, u_long addr, int port);
~Socket();
int BindAddress(SocketAddress address); /* Bind the socket withe the specified address */
SocketAddress GetAddress(); /* Get the socket address */
int SetTimeout(long millisec); /* Set timeout in millisec, no timeout if 0 */
bool IsValid(); /* Test if the socket is a valid one */
int Listen(int num); /* Prepare the socket to listen with the num pendding queue */
Socket Accept(); /* Wait for connection and accept it */
int Connect(u_long addr, int port);
int Recive(char* data, int length); /* Wait for data and store them in data */
int ReciveFrom(char* data, int length, SocketAddress& address);
int Send(const char* data, int length); /* Send data */
int SendTo(const char* data, int length, const SocketAddress& address);
void Close(); /* Close the socket (the connection) */
#ifdef SSLSOCKET
int SSL(SSLConfig& sslconfig);
#endif
};
#endif // SOCKET_H_INCLUDED
#include "WebConsole.h"
using namespace std;
vector<WebConsole::ListenedPort> WebConsole::listPort;
int WebConsole::init() {
Socket::init();
Log::init();
Log::print("WebConsole Dev (build 014)", Log::INFO);
Client::init();
if(FileSystem::init() != 0)
Log::print("Impossible to load mime.type file !", Log::ERR);
AppModule::init();
return 0;
}
int WebConsole::server(int port, onRequest_func onRequest, Socket::SSLConfig* sslconfig) {
Socket serv = Socket(Socket::TCP, 0, port);
if(!serv.IsValid() || serv.Listen(5) < 0)
{
Log::print("Impossible to start server on port" + to_string(port) + ". SocketError : " + to_string(Socket::GetLastSocketError()), Log::ERR);
return -1;
}
serv.SetTimeout(1000); //1sec
listPort.push_back(ListenedPort());
vector<ListenedPort>::iterator thisPort = listPort.end() - 1;
thisPort->port = port;
thisPort->acceptClient = true;
Log::print("Server listening on port " + to_string(port), Log::INFO);
while (thisPort->acceptClient)
{
Socket clt = serv.Accept();
if (clt.IsValid())
{
if (Client::newClient(clt, onRequest, sslconfig) < 0)
{
clt.Close();
Log::print("Overload : Client rejected !", Log::WARNING);
}
}
}
serv.Close();
listPort.erase(thisPort);
Log::print("Stop listening on port " + to_string(port), Log::INFO);
return 0;
}
int WebConsole::end() {
AppModule::end();
FileSystem::end();
Client::end();
Log::print("WebConsole ended", Log::INFO);
Log::end();
return 0;
}
void WebConsole::stop(int port) {
if (port == 0)
{
for(int i = 0; i < listPort.size(); i++)
listPort[i].acceptClient = false;
}
else
{
for(int i = 0; i < listPort.size(); i++)
if(listPort[i].port == port)
{
listPort[i].acceptClient = false;
break;
}
}
}
#ifndef WEBCONSOLE_H_INCLUDED
#define WEBCONSOLE_H_INCLUDED
#include <thread>
#include <vector>
#include "Client.h"
#include "Request.h"
#include "Response.h"
#include "AppModule.h"
class WebConsole {
private:
typedef void (*onRequest_func)(Request& requ, Response& resp);
struct ListenedPort { int port; bool acceptClient; };
static std::vector<ListenedPort> listPort;
public:
static int init();
static int server(int port, onRequest_func onRequest, Socket::SSLConfig* sslconfig = 0);
static int end();
static void stop(int port = 0);
};
#endif // WEBCONSOLE_H_INCLUDED
#!/bin/bash
if [ $# -ge 1 ] && [ $1 = "clean" ]
then
cd ./WebConsoleCore/obj/ && rm *.o && cd ../../WebConsole/obj/ && rm *.o
echo "Clean";
else
cd WebConsoleCore && make && cp bin/libWebConsoleCore.so ../WebConsole/bin/ && cd ../WebConsole && make && cd bin && build="ok"
if [ $# -ge 1 ] && [ $1 = "exec" ] && [ $build = "ok" ]
then
terminology -e "LD_LIBRARY_PATH=. ./WebConsole"
fi
fi
#!/bin/bash
keyfile="./WebConsole/bin/privatekey.key"
crtfile="./WebConsole/bin/serv.crt"
#Certificates
name="localhost"
organisation="Martin HEBANT"
country="FR"
serial=1
not_before=20160101000000
not_after=20260101000000
if [ $# -ge 1 ] && [ $1 = "regenpkey" ]
then
mbedtls-2.2.1/programs/pkey/gen_key type=rsa rsa_keysize=4096 filename=$keyfile
fi
mbedtls-2.2.1/programs/x509/cert_write selfsign=1 issuer_key="$keyfile" issuer_name=CN="$name",O="$organisation",C="$country" serial=$serial not_before=$not_before not_after=$not_after output_file="$crtfile"
\ No newline at end of file
File added
#if !defined(MBEDTLS_CONFIG_FILE)