Commit 3e04ee23 authored by PierreEngelstein's avatar PierreEngelstein
Browse files

Initial commit

parents
.DEFAULT_GOAL := build_linux
src = $(wildcard src/*.cpp\
src/thread/*.cpp\
src/thread/Socket/*.cpp\
src/thread/Delay/*.cpp)
obj_linux = $(src:.cpp=.ol)
obj_windows = $(src:.cpp=.ow)
B = g++
LINUX_FLAGS = -std=c++17 -lpthread -Wall -Werror
LINUX_BUILD = build/linux/server
LINUX_INCLUDE = -Isrc/
MINGW = x86_64-w64-mingw32-g++
WINDOWS_FLAGS = -std=c++17 -lws2_32 -pthread
WINDOWS_BUILD = build/windows/server.exe
build_linux: $(obj_linux)
mkdir -p build/linux
$(B) $^ -o $(LINUX_BUILD) $(LINUX_FLAGS)
rm -f $(obj_linux)
%.ol:%.cpp
$(B) -Wall -c $^ -o $@ $(LINUX_INCLUDE)
run_linux:build_linux
build/linux/server
build_windows: $(obj_windows)
mkdir -p build/windows
$(MINGW) $^ -o $(WINDOWS_BUILD) $(WINDOWS_FLAGS)
cp lib/libwinpthread-1.dll build/windows/libwinpthread-1.dll
rm -f $(obj_windows)
%.ow:%.cpp
$(MINGW) -Wall -c $^ -o $@
run_windows:build_windows
wine build/windows/server.exe
clean:
rm -f $(obj_linux)
rm -f $(obj_windows)
rm -rf build/
\ No newline at end of file
#include "closer.hpp"
namespace server
{
Closer::Closer()
{
}
Closer::~Closer()
{
}
void Closer::Init(threads::DelayThread *delay, threads::ThreadPool *pool)
{
}
void Closer::Handle(int signal_num)
{
}
}
\ No newline at end of file
#include "thread/Delay/DelayThread.hpp"
#include "thread/ThreadPool.hpp"
namespace server
{
class Closer
{
public:
Closer();
~Closer();
void Init(threads::DelayThread *delay, threads::ThreadPool *pool);
void Handle(int signal_num);
private:
threads::DelayThread *delay;
threads::ThreadPool *pool;
};
}
\ No newline at end of file
#include <iostream>
#include <thread/Socket/SocketThread.hpp>
#include <thread/Delay/DelayThread.hpp>
#include <thread/ThreadPool.hpp>
#include <memory>
std::shared_ptr<threads::DelayThread> delay;
void handle_close(int signal_num)
{
delay->End();
delay->Join();
}
int main()
{
printf("Hello World !\n");
int server_socket = threads::SocketThread::CreateServerSocket(9999, "tcp", 10);
// threads::DelayThread delay;
// delay.Create();
delay = std::make_shared<threads::DelayThread>();
delay->Create();
// threads::ThreadPool pool(5);
// std::shared_ptr<threads::ThreadPool> pool = std::make_shared<threads::ThreadPool>(5);
threads::ThreadPool pool(5);
while(1)
{
// threads::SocketThread _socket;
std::shared_ptr<threads::SocketThread> _socket = std::make_shared<threads::SocketThread>();
_socket->CreateSocket(server_socket);
if(!pool.AddThread(_socket, delay))
{
_socket->Create();
_socket->RegisterPool(&pool);
}else
{
_socket->End();
}
}
}
\ No newline at end of file
#include "DelayThread.hpp"
namespace threads
{
DelayThread::DelayThread() : IThread(0){}
DelayThread::~DelayThread(){
// Join();
}
std::string DelayThread::ToString()
{
return "";
}
void DelayThread::Run()
{
printf("Started delay thread !\n");
while(DelayThread::Running())
{
DelayThread::Decrease_All();
}
}
void DelayThread::Decrease_All()
{
for(auto iter = cooldown_list.begin(); iter != cooldown_list.end(); iter++)
{
if(iter->cooldown > 0)
iter->cooldown--;
else
iter = cooldown_list.erase(iter);
}
}
int DelayThread::IsOnCooldown(std::string ip)
{
for(auto iter = cooldown_list.begin(); iter != cooldown_list.end(); iter++)
if(!(iter->ip.compare(ip)))
return iter->cooldown;
return -1;
}
}
#ifndef DELAYTHREAD_H
#define DELAYTHREAD_H
#include "../IThread.hpp"
#include "../Socket/SocketThread.hpp"
#include <vector>
namespace threads
{
class ip_cooldown
{
public:
std::string ip;
int cooldown;
};
class DelayThread : public IThread
{
public:
DelayThread();
~DelayThread();
void Run() override;
std::string ToString() override;
int IsOnCooldown(std::string ip);
protected:
private:
std::vector<ip_cooldown> cooldown_list;
void Decrease_All();
};
}
#endif
\ No newline at end of file
#include <thread/IThread.hpp>
namespace threads
{
IThread::IThread(int id)
{
printf("Creating thread of id %d\n", id);
IThread::_id = id;
IThread::_running = false;
}
IThread::~IThread()
{
if(IThread::_running)
{
IThread::_running = false;
_thread.join();
}
}
int IThread::Create()
{
IThread::_thread = std::thread([this] { this->Run(); });
if(!IThread::_thread.joinable())
{
fprintf(stderr, "Thread %lu is not joinable !\n", IThread::_thread.native_handle());
fprintf(stderr, "%s\n", strerror(errno));
return 1;
}
fprintf(stdout, "Created thread %lu\n", IThread::_thread.native_handle());
IThread::_running = true;
return 0;
}
int IThread::Join()
{
if(IThread::_thread.joinable())
{
IThread::_thread.join();
fprintf(stdout, "Joined thread !\n");
return 0;
}
fprintf(stderr, "Thread is not joinable\n");
return 1;
}
void IThread::Run(){}
bool IThread::Running()
{
return IThread::_running;
}
void IThread::End()
{
IThread::_running = false;
}
}
\ No newline at end of file
#ifndef ITHREAD_H
#define ITHREAD_H
#include <thread>
#include <string>
#include <cstring>
namespace threads
{
class IThread
{
public:
IThread(int id);
virtual ~IThread();
virtual void Run();
bool Running();
void End();
virtual std::string ToString() = 0;
int Create();
int Join();
protected:
bool _running;
int _id;
private:
std::thread _thread;
};
}
#endif
#include "Client.hpp"
namespace threads
{
Client::Client()
{
Client::port = 0;
Client::socket = 0;
}
Client::~Client()
{
}
std::string Client::IP()
{
return Client::ip;
}
uint16_t Client::Port()
{
return Client::port;
}
int Client::Socket()
{
return Client::socket;
}
__socklen_t Client::Socket_Length()
{
return Client::socket_length;
}
void Client::Set()
{
#ifdef __linux
char ip[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &(socket_address.sin_addr), ip, INET_ADDRSTRLEN);
#elif defined __WIN32
char *ip = inet_ntoa(address.sin_addr);
#endif
Client::ip = std::string(ip);
Client::port = (int16_t) ntohs(socket_address.sin_port);
}
int Client::SetSocket(int server_socket)
{
Client::socket = accept(server_socket, (struct sockaddr *)&(Client::socket_address), &(Client::socket_length));
if(Client::socket < 1)
{
fprintf(stderr, "Accept failed ! (%d)\n", Client::socket);
fprintf(stderr, "%s\n", strerror(errno));
return 1;
}
return 0;
}
std::string Client::ToString()
{
std::string str = "Client connected from ";
str.append(Client::ip);
str.append(" : ");
str.append(std::to_string(Client::port));
str.append("\n");
return str;
}
}
\ No newline at end of file
#ifndef CLIENT_H
#define CLIENT_H
#include <memory>
#include <string>
#include <cstring>
#ifdef __linux
#include <netdb.h>
#include <arpa/inet.h>
#elif defined __WIN32
#include <winsock2.h>
#endif
typedef struct sockaddr_in address_t;
namespace threads
{
class Client
{
public:
Client();
virtual ~Client();
std::string IP();
uint16_t Port();
int Socket();
__socklen_t Socket_Length();
/* Set the ip and port on which the client is connected */
void Set();
/* Set the client socket */
int SetSocket(int server_socket);
std::string ToString();
private:
std::string ip;
uint16_t port;
int socket;
__socklen_t socket_length;
struct sockaddr_in socket_address;
};
}
#endif
\ No newline at end of file
#include "SocketThread.hpp"
#include "../ThreadPool.hpp"
namespace threads
{
SocketThread::SocketThread() : IThread(0)
{
SocketThread::_inPool = false;
SocketThread::_inDelay = false;
memset(buffer_in, 0, sizeof(buffer_in));
}
SocketThread::~SocketThread()
{
Join();
}
int SocketThread::CreateServerSocket(uint16_t port, std::string protocol, int maxqueue)
{
int serv_socket;
struct sockaddr_in server_address;
struct protoent *p_protocol; //try to avoid raw pointers, but here I can't.
/* Clean server_address structure */
memset((char *)&server_address, 0, sizeof(server_address));
if(port < 0)
{
fprintf(stderr, "incorrect server port ! (%d)\n", port);
return -1;
}
server_address.sin_family = AF_INET;
server_address.sin_port = htons(port);
/* Set protocol name */
p_protocol = getprotobyname(protocol.c_str());
if(!p_protocol)
{
fprintf(stderr, "%s protocol error !\n", protocol.c_str());
return -1;
}
/* Create the server listening socket */
serv_socket = socket(PF_INET, SOCK_STREAM, p_protocol->p_proto);
if(serv_socket < 0)
{
fprintf(stderr, "Listening socket creation failed ! (%d)\n", serv_socket);
fprintf(stderr, "%s\n", strerror(errno));
return -1;
}
/* Set socket options */
#ifdef __linux__
int bOptVal1 = 1;
int res = setsockopt(serv_socket, SOL_SOCKET, SO_REUSEADDR, &bOptVal1, sizeof(int));
#elif defined __WIN32
BOOL bOptVal1 = TRUE;
int res = setsockopt(serv_socket, SOL_SOCKET, SO_REUSEADDR, (char *)(&bOptVal1), sizeof(int));
#endif
if(res < 0)
{
fprintf(stderr, "Failed to set socket option SO_REUSEADDR ! (%d)\n", res);
fprintf(stderr, "%s\n", strerror(errno));
return -1;
}
/* bind the server socket */
res = bind(serv_socket, (struct sockaddr *)&server_address, sizeof(server_address));
if(res < 0)
{
fprintf(stderr, "Failed to bind server_address ! (%d)\n", res);
fprintf(stderr, "%s\n", strerror(errno));
return -1;
}
/* Start listening */
if(maxqueue <= 0)
res = listen(serv_socket, 10);
else
res = listen(serv_socket, maxqueue);
if(res < 0)
{
fprintf(stderr, "Listening error ! (%d)\n", res);
fprintf(stderr, "%s\n", strerror(errno));
return -1;
}
return serv_socket;
}
int SocketThread::CreateSocket(int server_socket)
{
SocketThread::client = Client();
if(SocketThread::client.SetSocket(server_socket))
return 1;
SocketThread::client.Set();
return 0;
}
std::string SocketThread::ToString()
{
return "Coucou";
}
bool SocketThread::EqualIP(std::shared_ptr<threads::SocketThread> thread1)
{
if(!thread1->client.IP().compare(SocketThread::client.IP()))
return true;
return false;
}
std::string SocketThread::IP()
{
return SocketThread::client.IP();
}
void SocketThread::SetID(int id)
{
SocketThread::_id = id;
}
void SocketThread::Run()
{
printf("Started client thread !\n");
int recv_result = 0;
while(SocketThread::Running())
{
/* Receive the data of the client */
recv_result = recv(client.Socket(), buffer_in, 1450, 0);
/* Treat the data of the client */
printf("%s\n", buffer_in);
if(recv_result == 0)
{
fprintf(stdout, "Client %s disconnected !\n", client.IP().c_str());
SocketThread::End();
}
if(recv_result == -1)
{
fprintf(stderr, "recv failed ! (%d)\n", recv_result);
fprintf(stderr, "%s\n", strerror(errno));
SocketThread::End();
}
}
printf("Ended client %s thread !\n", SocketThread::IP().c_str());
if(SocketThread::_inPool)
{
_pool->RemoveIP(client.IP());
}
printf("Pool = %s", _pool->ToString().c_str());
}
void SocketThread::RegisterPool(ThreadPool *pool)
{
SocketThread::_pool = pool;
SocketThread::_inPool = true;
printf("Registered pool\n");
}
void SocketThread::RegisterDelay(DelayThread *delay)
{
SocketThread::_delay = delay;
SocketThread::_inDelay = true;
}
}
#ifndef SOCKETTHREAD_H
#define SOCKETTHREAD_H
#include "../IThread.hpp"
#include "../ThreadPool.hpp"
#include "../Delay/DelayThread.hpp"
#include "Client.hpp"
#include <vector>
#define MTU 1450
namespace threads
{
class ThreadPool;
class SocketThread : public IThread
{
public:
SocketThread();
virtual ~SocketThread();
static int CreateServerSocket(uint16_t port, std::string protocol, int maxqueue);