Restructure

This commit is contained in:
IlushaShurupov 2023-07-19 23:52:07 +03:00
parent 576a3565f7
commit a543568e1d
12 changed files with 289 additions and 190 deletions

View file

@ -4,7 +4,7 @@
using namespace tp; using namespace tp;
static ModuleManifest* sModuleDependencies[] = { &gModuleTokenizer, &gModuleStorage, nullptr }; static ModuleManifest* sModuleDependencies[] = { &gModuleTokenizer, &gModuleStorage, nullptr };
ModuleManifest tp::gModuleStorage = ModuleManifest("CommandLine", nullptr, nullptr, sModuleDependencies); ModuleManifest tp::gModuleCommandLine = ModuleManifest("CommandLine", nullptr, nullptr, sModuleDependencies);
const char* regexSpace = "\n|\t| |\r"; const char* regexSpace = "\n|\t| |\r";
const char* regexFalse = "N|n|(False)|(false)"; const char* regexFalse = "N|n|(False)|(false)";

View file

@ -5,11 +5,14 @@ set(CMAKE_CXX_STANDARD 23)
project(Storage) project(Storage)
set(ASIO_INCLUDE ./../Externals/asio/asio/include)
### ---------------------- Static Library --------------------- ### ### ---------------------- Static Library --------------------- ###
file(GLOB SOURCES "./private/*.cpp" "./private/*/*.cpp") file(GLOB SOURCES "./private/*.cpp" "./private/*/*.cpp")
file(GLOB HEADERS "./public/*.hpp") file(GLOB HEADERS "./public/*.hpp")
add_library(${PROJECT_NAME} STATIC ${SOURCES} ${HEADERS}) add_library(${PROJECT_NAME} STATIC ${SOURCES} ${HEADERS})
target_include_directories(${PROJECT_NAME} PUBLIC ./public/) target_include_directories(${PROJECT_NAME} PUBLIC ./public/)
target_include_directories(${PROJECT_NAME} PRIVATE ${ASIO_INCLUDE})
target_link_libraries(${PROJECT_NAME} PUBLIC Strings) target_link_libraries(${PROJECT_NAME} PUBLIC Strings)

View file

@ -3,15 +3,11 @@ cmake_minimum_required(VERSION 3.2)
project(Applications) project(Applications)
file(GLOB SOURCES_CLIENT ./Client.cpp) file(GLOB SOURCES_CLIENT ./Client.cpp ./SystemAPI.cpp)
file(GLOB SOURCES_SERVER ./Server.cpp) file(GLOB SOURCES_SERVER ./Server.cpp ./SystemAPI.cpp)
set(ASIO_INCLUDE ./../../Externals/asio/asio/include)
add_executable(Client ${SOURCES_CLIENT}) add_executable(Client ${SOURCES_CLIENT})
include_directories(Client ${ASIO_INCLUDE}) target_link_libraries(Client Storage CommandLine)
#link_libraries(Client Storage CommandLine)
add_executable(Server ${SOURCES_SERVER}) add_executable(Server ${SOURCES_SERVER})
include_directories(Server ${ASIO_INCLUDE}) target_link_libraries(Server Storage CommandLine)
#link_libraries(Server Storage CommandLine)

View file

@ -1,81 +1,64 @@
#include "asio.hpp" #include "SystemAPI.hpp"
#include <iostream> #include "Strings.hpp"
#include <string>
#include <mutex>
// #include <unistd.h> #include <pthread.h>
// #include <cstring>
constexpr int PORT = 3333; using namespace tp;
const char* SERVER_IP = "127.0.0.1";
std::mutex mutex; class CharClient {
void* readServerBroadcast(void* clientSocketPtr) { typedef void* (*ThreadFunction)(void *);
auto socket = ((asio::ip::tcp::socket*)clientSocketPtr);
while (true) { Client client;
pthread_mutex_t mutex;
short messageSize; public:
asio::read(*socket, asio::buffer(&messageSize, 2)); CharClient(int port, const char* ip) {
pthread_mutex_unlock(&mutex);
mutex.lock(); client.connect(ip, port);
auto message = new char[messageSize + 1];
message[messageSize] = 0;
asio::read(*socket, asio::buffer(message, messageSize));
std::cerr << "Broadcast : " << message << std::endl;
delete[] message;
mutex.unlock();
} }
return nullptr; void start() {
}
int main() {
asio::io_context ioContext;
// Create a TCP socket
asio::ip::tcp::socket socket(ioContext);
// Connect to a server
asio::ip::tcp::endpoint endpoint(asio::ip::address::from_string(SERVER_IP), PORT);
socket.connect(endpoint);
// Create a new thread to handle the client // Create a new thread to handle the client
pthread_t threadId; pthread_t threadId;
if (pthread_create(&threadId, nullptr, readServerBroadcast, (void*) &socket) != 0) { if (pthread_create(&threadId, nullptr, (ThreadFunction) readServerBroadcast, this)) {
std::cerr << "Failed to create thread for client" << std::endl; printf("Failed to create thread for client\n");
return 1; return;
} }
// Detach the thread so it can run independently // Detach the thread so it can run independently
pthread_detach(threadId); pthread_detach(threadId);
while (true) { while (true) {
std::string message; const auto length = 1024;
std::cout << " >> "; static char message[length];
std::cin >> message;
mutex.lock(); printf(" >> ");
fgets(message, length, stdin);
// Send a message to the server if (String::Logic::isEqualLogic(message, "exit")) return;
auto messageSize = (short) message.size();
asio::write(socket, asio::buffer(&messageSize, 2));
// Send a message to the server pthread_mutex_lock(&mutex);
asio::write(socket, asio::buffer(message + "\n")); client.write(message);
pthread_mutex_unlock(&mutex);
mutex.unlock(); }
} }
// Close socket static void* readServerBroadcast(CharClient* self) {
// close(clientSocket); while (true) {
auto message = self->client.read();
pthread_mutex_lock(&self->mutex);
printf("Broadcast : %s \n", message);
delete[] message;
pthread_mutex_unlock(&self->mutex);
}
return nullptr;
}
};
int main() {
CharClient client(5555, "127.0.0.1");
client.start();
return 0; return 0;
} }

View file

@ -1,140 +1,92 @@
#include <asio.hpp>
#include <cstring> #include "SystemAPI.hpp"
#include <iostream> #include "Strings.hpp"
#include <list> #include "List.hpp"
#include <mutex>
#include <pthread.h> #include <pthread.h>
class Server { using namespace tp;
class ChatServer {
struct SharedData { struct SharedData {
std::list<asio::ip::tcp::socket*> clients; List<Server::Socket> clients;
std::mutex mutex; pthread_mutex_t mutex;
}; };
SharedData mSharedData; SharedData mSharedData;
Server server;
//int serverSocket;
int port;
public: public:
Server(int port) : port(port) {} explicit ChatServer(int port) {
~Server() { assert(0); } server.start(port);
}
~ChatServer() {
DEBUG_ASSERT(false)
}
bool start() { bool start() {
// Create socket
asio::io_context io_context;
asio::ip::tcp::acceptor serverSocket(io_context);
// Bind socket to port
serverSocket.open(asio::ip::tcp::v4());
// serverSocket.set_option(asio::ip::tcp::acceptor::reuse_address(true));
serverSocket.bind(asio::ip::tcp::endpoint(asio::ip::tcp::v4(), port));
// Listen for connections
serverSocket.listen();
std::cout << "Server listening on port " << port << std::endl;
// Start accepting clients
while (true) { while (true) {
// Accept client connection auto clientSocket = server.accept();
auto clientSocket = new asio::ip::tcp::socket(io_context);
serverSocket.accept(*clientSocket);
// add client // add client
mSharedData.mutex.lock(); pthread_mutex_lock(&mSharedData.mutex);
mSharedData.clients.push_back(clientSocket); mSharedData.clients.pushBack(clientSocket);
mSharedData.mutex.unlock(); pthread_mutex_unlock(&mSharedData.mutex);
// Create a new thread to handle the client // Create a new thread to handle the client
pthread_t threadId; pthread_t threadId;
if (pthread_create(&threadId, nullptr, handleClient, this) != 0) { if (pthread_create(&threadId, nullptr, (void* (*)(void*)) handleClient, this)) {
std::cerr << "Failed to create thread for client" << std::endl; printf("Failed to create thread for client\n");
return false; return false;
} }
// Detach the thread so it can run independently // Detach the thread so it can run independently
pthread_detach(threadId); pthread_detach(threadId);
} }
// Close server socket
serverSocket.close();
return true; return true;
} }
static void* handleClient(void* in) { static void* handleClient(ChatServer* self) {
auto self = (Server*) in;
// read shared data - current client id // read shared data - current client id
self->mSharedData.mutex.lock(); pthread_mutex_lock(&self->mSharedData.mutex);
auto clientSocket = self->mSharedData.clients.back(); auto clientSocket = self->mSharedData.clients.last();
self->mSharedData.mutex.unlock(); pthread_mutex_unlock(&self->mSharedData.mutex);
MESSAGE: MESSAGE:
// wait for a message request1 // wait for a message request
short messageSize; auto message = Server::read(clientSocket);
{
auto bytesRead = asio::read(*clientSocket, asio::buffer(&messageSize, 2));
if (bytesRead == -1) {
std::cerr << "Failed to read from socket" << std::endl;
(*clientSocket).close();
return nullptr;
}
}
self->mSharedData.mutex.lock();
// Receive client message
auto message = new char[messageSize + 1];
message[messageSize] = '\0';
{
auto bytesRead = asio::read(*clientSocket, asio::buffer(message, messageSize));
if (bytesRead == -1) {
std::cerr << "Failed to read from socket" << std::endl;
memcpy(message, "Cant wanna say something but i cant read", 100);
}
}
// Broadcast to all clients // Broadcast to all clients
for (auto client : self->mSharedData.clients) { for (auto client : self->mSharedData.clients) {
auto bytesWritten = asio::write(*client, asio::buffer(&messageSize, 2)); Server::write(client.data(), message);
if (bytesWritten == -1) {
std::cerr << "Failed to write to socket" << std::endl;
} }
bytesWritten = write(*client, asio::buffer(message, messageSize)); auto exit = memCompare(message, "exit", 5) == 0;
if (bytesWritten == -1) {
std::cerr << "Failed to write to socket" << std::endl;
}
}
auto exit = memcmp(message, "exit", strlen("exit")) == 0;
// Close socket
delete[] message; delete[] message;
if (exit) { if (exit) {
(*clientSocket).close(); // TODO : disconnect
self->mSharedData.clients.remove(clientSocket); for (auto iter : self->mSharedData.clients) {
if (clientSocket == iter.data()) {
self->mSharedData.clients.removeNode(iter.node());
break;
}
}
} }
self->mSharedData.mutex.unlock(); pthread_mutex_unlock(&self->mSharedData.mutex);
if (exit) { if (exit) return nullptr;
return nullptr;
}
goto MESSAGE; goto MESSAGE;
} }
}; };
int main() { int main() {
Server server(3333); ChatServer server(5555);
server.start(); server.start();
return 0; return 0;
} }

View file

@ -1,6 +1,6 @@
#include "LocalStorage.hpp" #include "LocalStorage.hpp"
#include "SystemHandle.hpp" #include "SystemAPI.hpp"
#include <cstdio> #include <cstdio>

View file

View file

@ -1,4 +1,4 @@
#include "SystemHandle.hpp" #include "SystemAPI.hpp"
#include <fstream> #include <fstream>

View file

@ -0,0 +1,130 @@
#include "SystemAPI.hpp"
#include "asio.hpp"
#include <iostream>
using namespace tp;
class tp::ServerContext {
friend class Server;
asio::io_context context;
asio::ip::tcp::acceptor socket;
typedef asio::ip::tcp::socket Socket;
ServerContext() : socket(context) {}
~ServerContext() {
context.stop();
socket.close();
}
};
class tp::ClientContext {
friend Client;
asio::io_context context;
asio::ip::tcp::socket socket;
public:
ClientContext() : socket(context) {}
~ClientContext() {
context.stop();
socket.close();
}
};
// --------------------------------------------------------------------------------------- //
Server::Server() {
mContext = new ServerContext();
}
Server::~Server() {
delete mContext;
assert(0);
}
void Server::start(ualni port) {
mContext->socket.open(asio::ip::tcp::v4());
mContext->socket.bind(asio::ip::tcp::endpoint(asio::ip::tcp::v4(), port));
mContext->socket.listen();
std::cout << "Server listening on port " << port << std::endl;
}
Server::Socket Server::accept() {
auto clientSocket = new asio::ip::tcp::socket(mContext->context);
mContext->socket.accept(*clientSocket);
std::cout << "New client accepted "<< std::endl;
return clientSocket;
}
int1* Server::read(Socket client) {
short messageSize;
if (asio::read(*(ServerContext::Socket*)client, asio::buffer(&messageSize, 2)) == -1) {
std::cerr << "Failed to read from socket" << std::endl;
((ServerContext::Socket*)client)->close();
return nullptr;
}
auto message = new char[messageSize + 1];
message[messageSize] = '\0';
if (asio::read(*(ServerContext::Socket*)client, asio::buffer(message, messageSize)) == -1) {
std::cerr << "Failed to read from socket" << std::endl;
memcpy(message, "Client wanna say something but i cant read", 100);
}
return message;
}
void Server::write(Socket client, const char* message) {
auto messageSize = (short) strlen(message);
if (asio::write(*(ServerContext::Socket*)client, asio::buffer(&messageSize, 2)) == -1) {
std::cerr << "Failed to write to socket" << std::endl;
}
if (asio::write(*(ServerContext::Socket*)client, asio::buffer(message, messageSize)) == -1) {
std::cerr << "Failed to write to socket" << std::endl;
}
}
// --------------------------------------------------------------------------------------- //
Client::Client() {
mContext = new ClientContext();
}
Client::~Client() {
delete mContext;
assert(0);
}
void Client::connect(const char* IP, ualni PORT) {
asio::ip::tcp::endpoint endpoint(asio::ip::address::from_string(IP), PORT);
mContext->socket.connect(endpoint);
}
char* Client::read() {
short messageSize;
if (asio::read(mContext->socket, asio::buffer(&messageSize, 2)) == -1) {
std::cerr << "Failed to read from socket" << std::endl;
return nullptr;
}
auto message = new char[messageSize + 1];
message[messageSize] = '\0';
if (asio::read(mContext->socket, asio::buffer(message, messageSize)) == -1) {
std::cerr << "Failed to read from socket" << std::endl;
memcpy(message, "Cant wanna say something but i cant read", 100);
}
return message;
}
void Client::write( const char* message ) {
auto messageSize = (short) strlen(message);
if (asio::write(mContext->socket, asio::buffer(&messageSize, 2)) == -1) {
std::cerr << "Failed to write to socket" << std::endl;
}
if (asio::write(mContext->socket, asio::buffer(message, messageSize)) == -1) {
std::cerr << "Failed to write to socket" << std::endl;
}
}

View file

@ -1,19 +0,0 @@
#pragma once
#include "Common.hpp"
namespace tp {
class FileSystemHandle {
void* stream;
public:
FileSystemHandle();
~FileSystemHandle();
void open(const char*, bool);
bool isOpen();
void close();
void seekp(ualni);
void read(int1*, ualni);
void write(const int1*, ualni);
ualni size();
};
}

View file

@ -1,8 +1,10 @@
#pragma once #pragma once
#include "Storage.hpp" #include "SystemAPI.hpp"
namespace tp { namespace tp {
/*
class Client : public Storage { class Client : public Storage {
// same as local storage file but transfers all commands to server // same as local storage file but transfers all commands to server
}; };
@ -11,4 +13,5 @@ namespace tp {
// opens local storage and transfers all client command to it // opens local storage and transfers all client command to it
// manages multiple clients // manages multiple clients
}; };
*/
} }

View file

@ -0,0 +1,51 @@
#pragma once
#include "Common.hpp"
namespace tp {
class FileSystemHandle {
void* stream;
public:
FileSystemHandle();
~FileSystemHandle();
void open(const char*, bool);
bool isOpen();
void close();
void seekp(ualni);
void read(int1*, ualni);
void write(const int1*, ualni);
ualni size();
};
class ServerContext;
class ClientContext;
class Server {
ServerContext* mContext;
public:
typedef void* Socket;
public:
Server();
~Server();
void start(ualni port);
Socket accept();
static int1* read(Socket client);
static void write(Socket client, const int1* message);
};
class Client {
ClientContext* mContext;
public:
Client();
~Client();
void connect(const int1* IP, ualni PORT);
int1* read();
void write(const int1* message);
};
}