Restructure Storage Module -> Connection module
This commit is contained in:
parent
fa4d1d72dc
commit
e9dbee6667
24 changed files with 121 additions and 354 deletions
25
Connection/CMakeLists.txt
Normal file
25
Connection/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
|
||||
cmake_minimum_required(VERSION 3.2)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 23)
|
||||
|
||||
project(Connection)
|
||||
|
||||
set(BINDINGS_INCLUDE ./../Externals/asio/asio/include)
|
||||
|
||||
### ---------------------- Static Library --------------------- ###
|
||||
file(GLOB SOURCES "./private/*.cpp" "./private/*/*.cpp")
|
||||
file(GLOB HEADERS "./public/*.hpp")
|
||||
add_library(${PROJECT_NAME} STATIC ${SOURCES} ${HEADERS})
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC ./public/)
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE ${BINDINGS_INCLUDE})
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC Strings)
|
||||
|
||||
### -------------------------- Tests -------------------------- ###
|
||||
enable_testing()
|
||||
file(GLOB TEST_SOURCES "./tests/*.cpp")
|
||||
add_executable(${PROJECT_NAME}Tests ${TEST_SOURCES})
|
||||
target_link_libraries(${PROJECT_NAME}Tests ${PROJECT_NAME} Utils)
|
||||
add_test(NAME ${PROJECT_NAME}Tests COMMAND ${PROJECT_NAME}Tests)
|
||||
|
||||
install(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}/lib)
|
||||
9
Connection/private/ConnectionCommon.cpp
Normal file
9
Connection/private/ConnectionCommon.cpp
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
|
||||
#include "ConnectionCommon.hpp"
|
||||
|
||||
static tp::ModuleManifest* sModuleDependencies[] = {
|
||||
&tp::gModuleStrings,
|
||||
nullptr
|
||||
};
|
||||
|
||||
tp::ModuleManifest tp::gModuleConnection = ModuleManifest("Storage", nullptr, nullptr, sModuleDependencies);
|
||||
89
Connection/private/LocalConnection.cpp
Normal file
89
Connection/private/LocalConnection.cpp
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
#include "LocalConnection.hpp"
|
||||
|
||||
#include "bindings/Disk.hpp"
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
using namespace tp;
|
||||
|
||||
bool LocalConnectionLocation::exists() const {
|
||||
FILE* file = fopen(mLocation.read(), "r");
|
||||
if (file) {
|
||||
// File exists, close it and return 1
|
||||
fclose(file);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LocalConnection::connect(const LocalConnectionLocation& location, const LocalConnectionType& connectionInfo) {
|
||||
DEBUG_ASSERT(!mStatus.isOpened());
|
||||
if (mStatus.isOpened()) return false;
|
||||
|
||||
auto handle = new LocalConnectionContext();
|
||||
|
||||
switch (connectionInfo.getType()) {
|
||||
case LocalConnectionType::READ:
|
||||
handle->open(location.getLocation().read(), false);
|
||||
break;
|
||||
|
||||
case LocalConnectionType::WRITE:
|
||||
handle->open(location.getLocation().read(), true);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
if (!handle->isOpen()) {
|
||||
mStatus.setStatus(LocalConnectionStatus::DENIED);
|
||||
delete handle;
|
||||
return false;
|
||||
}
|
||||
|
||||
mStatus.setStatus(LocalConnectionStatus::OPENED);
|
||||
mHandle = handle;
|
||||
mConnectionType = connectionInfo;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LocalConnection::disconnect() {
|
||||
DEBUG_ASSERT(mStatus.isOpened());
|
||||
if (!mStatus.isOpened() || !mHandle) return false;
|
||||
mHandle->close();
|
||||
delete mHandle;
|
||||
mStatus.setStatus(LocalConnectionStatus::CLOSED);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LocalConnection::setPointer(BytePointer pointer) {
|
||||
DEBUG_ASSERT(mStatus.isOpened());
|
||||
if (!mStatus.isOpened()) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LocalConnection::readBytes(Byte* bytes, SizeBytes size) {
|
||||
DEBUG_ASSERT(mStatus.isOpened() && mConnectionType.isWrite());
|
||||
if (!mStatus.isOpened() || !mConnectionType.isWrite()) return false;
|
||||
|
||||
mHandle->seekp(mPointer);
|
||||
mHandle->read(bytes, size);
|
||||
mPointer += size;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LocalConnection::writeBytes(const Byte* bytes, SizeBytes size) {
|
||||
DEBUG_ASSERT(mStatus.isOpened() && mConnectionType.isRead());
|
||||
if (!mStatus.isOpened() || !mConnectionType.isRead()) return false;
|
||||
|
||||
mHandle->seekp(mPointer);
|
||||
mHandle->write(bytes, size);
|
||||
mPointer += size;
|
||||
return true;
|
||||
}
|
||||
|
||||
LocalConnection::SizeBytes LocalConnection::size() {
|
||||
DEBUG_ASSERT(mStatus.isOpened());
|
||||
if (!mStatus.isOpened() || !mHandle) return 0;
|
||||
return mHandle->size();
|
||||
}
|
||||
2
Connection/private/RemoteConnection.cpp
Normal file
2
Connection/private/RemoteConnection.cpp
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
|
||||
#include "RemoteConnection.hpp"
|
||||
57
Connection/private/bindings/Disk.cpp
Normal file
57
Connection/private/bindings/Disk.cpp
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
#include "Disk.hpp"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
using namespace tp;
|
||||
|
||||
ualni tp::LocalConnectionContext::size() {
|
||||
auto strm = (std::fstream*) stream;
|
||||
ualni out = 0;
|
||||
strm->seekg(0, std::ios::beg);
|
||||
out = strm->tellg();
|
||||
strm->seekg(0, std::ios::end);
|
||||
out = (ualni) strm->tellg() - out;
|
||||
return out;
|
||||
}
|
||||
|
||||
LocalConnectionContext::LocalConnectionContext() {
|
||||
stream = new std::fstream();
|
||||
}
|
||||
|
||||
LocalConnectionContext::~LocalConnectionContext() {
|
||||
auto strm = (std::fstream*) stream;
|
||||
delete strm;
|
||||
}
|
||||
|
||||
bool LocalConnectionContext::isOpen() {
|
||||
auto strm = (std::fstream*) stream;
|
||||
return strm->is_open();
|
||||
}
|
||||
|
||||
void LocalConnectionContext::close() {
|
||||
auto strm = (std::fstream*) stream;
|
||||
strm->close();
|
||||
}
|
||||
|
||||
void LocalConnectionContext::seekp(ualni in) {
|
||||
auto strm = (std::fstream*) stream;
|
||||
strm->seekp(in);
|
||||
}
|
||||
|
||||
void LocalConnectionContext::read(int1* in, ualni size) {
|
||||
auto strm = (std::fstream*) stream;
|
||||
strm->read(in, size);
|
||||
}
|
||||
|
||||
void LocalConnectionContext::write(const int1* in, ualni size) {
|
||||
auto strm = (std::fstream*) stream;
|
||||
strm->write(in, size);
|
||||
}
|
||||
|
||||
void LocalConnectionContext::open(const char* path, bool read) {
|
||||
auto strm = (std::fstream*) stream;
|
||||
if (read)
|
||||
strm->open(path, std::ios::in | std::ios::binary | std::ios::app);
|
||||
else
|
||||
strm->open(path, std::ios::out | std::ios::binary | std::ios::trunc);
|
||||
}
|
||||
17
Connection/private/bindings/Disk.hpp
Normal file
17
Connection/private/bindings/Disk.hpp
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
#include "Common.hpp"
|
||||
|
||||
namespace tp {
|
||||
class LocalConnectionContext {
|
||||
void* stream;
|
||||
public:
|
||||
LocalConnectionContext();
|
||||
~LocalConnectionContext();
|
||||
void open(const char*, bool);
|
||||
bool isOpen();
|
||||
void close();
|
||||
void seekp(ualni);
|
||||
void read(int1*, ualni);
|
||||
void write(const int1*, ualni);
|
||||
ualni size();
|
||||
};
|
||||
}
|
||||
130
Connection/private/bindings/Network.cpp
Normal file
130
Connection/private/bindings/Network.cpp
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
#include "Network.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;
|
||||
}
|
||||
}
|
||||
|
||||
36
Connection/private/bindings/Network.hpp
Normal file
36
Connection/private/bindings/Network.hpp
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
#pragma once
|
||||
|
||||
#include "Common.hpp"
|
||||
|
||||
namespace tp {
|
||||
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);
|
||||
};
|
||||
}
|
||||
7
Connection/public/ConnectionCommon.hpp
Normal file
7
Connection/public/ConnectionCommon.hpp
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "Strings.hpp"
|
||||
|
||||
namespace tp {
|
||||
extern ModuleManifest gModuleConnection;
|
||||
};
|
||||
99
Connection/public/LocalConnection.hpp
Normal file
99
Connection/public/LocalConnection.hpp
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
#pragma once
|
||||
|
||||
#include "ConnectionCommon.hpp"
|
||||
|
||||
namespace tp {
|
||||
|
||||
class LocalConnectionContext;
|
||||
|
||||
class LocalConnectionLocation {
|
||||
String mLocation;
|
||||
public:
|
||||
LocalConnectionLocation() : mLocation("tmp") {};
|
||||
explicit LocalConnectionLocation(const String& location) : mLocation(location) {}
|
||||
void setLocation(const String& location) { mLocation = location; }
|
||||
[[nodiscard]] const String& getLocation() const { return mLocation; }
|
||||
[[nodiscard]] bool exists() const;
|
||||
};
|
||||
|
||||
class LocalConnectionType {
|
||||
public:
|
||||
enum HandleType {
|
||||
READ,
|
||||
WRITE,
|
||||
NONE,
|
||||
};
|
||||
|
||||
private:
|
||||
HandleType mHandleType;
|
||||
|
||||
public:
|
||||
LocalConnectionType() : mHandleType(NONE) {}
|
||||
explicit LocalConnectionType(bool read) : mHandleType((HandleType) read) {}
|
||||
explicit LocalConnectionType(HandleType handleType) : mHandleType(handleType) {}
|
||||
[[nodiscard]] HandleType getType() const { return mHandleType; }
|
||||
[[nodiscard]] bool isRead() const { return mHandleType == READ; }
|
||||
[[nodiscard]] bool isWrite() const { return mHandleType == WRITE; }
|
||||
};
|
||||
|
||||
class LocalConnectionStatus {
|
||||
public:
|
||||
enum Status {
|
||||
NONE,
|
||||
OPENED,
|
||||
CLOSED,
|
||||
DENIED,
|
||||
INVALID,
|
||||
};
|
||||
|
||||
private:
|
||||
Status mStatus = NONE;
|
||||
|
||||
public:
|
||||
LocalConnectionStatus() = default;
|
||||
[[nodiscard]] Status getStatus() const { return mStatus; }
|
||||
void setStatus(Status status) { mStatus = status; }
|
||||
[[nodiscard]] bool isOpened() const { return mStatus == OPENED; }
|
||||
};
|
||||
|
||||
class LocalConnection {
|
||||
typedef ualni SizeBytes;
|
||||
typedef ualni BytePointer;
|
||||
typedef int1 Byte;
|
||||
|
||||
private:
|
||||
LocalConnectionContext* mHandle = nullptr;
|
||||
|
||||
LocalConnectionLocation mLocation;
|
||||
LocalConnectionType mConnectionType;
|
||||
LocalConnectionStatus mStatus;
|
||||
|
||||
BytePointer mPointer = 0;
|
||||
|
||||
public:
|
||||
LocalConnection() {
|
||||
MODULE_SANITY_CHECK(gModuleConnection)
|
||||
};
|
||||
|
||||
virtual ~LocalConnection() {
|
||||
if (mStatus.isOpened()) LocalConnection::disconnect();
|
||||
}
|
||||
|
||||
public:
|
||||
virtual bool connect(const LocalConnectionLocation& location, const LocalConnectionType& connectionInfo);
|
||||
virtual bool disconnect();
|
||||
|
||||
public:
|
||||
virtual const LocalConnectionStatus& getConnectionStatus() { return mStatus; }
|
||||
virtual const LocalConnectionType& getConnectionType() { return mConnectionType; }
|
||||
virtual const LocalConnectionLocation& getLocation() { return mLocation; }
|
||||
|
||||
public:
|
||||
virtual bool setPointer(BytePointer pointer);
|
||||
virtual bool readBytes(Byte* bytes, SizeBytes size);
|
||||
virtual bool writeBytes(const Byte* bytes, SizeBytes size);
|
||||
|
||||
public:
|
||||
virtual SizeBytes size();
|
||||
};
|
||||
}
|
||||
0
Connection/public/RemoteConnection.hpp
Normal file
0
Connection/public/RemoteConnection.hpp
Normal file
33
Connection/tests/TestLocal.cpp
Normal file
33
Connection/tests/TestLocal.cpp
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
|
||||
#include "LocalConnection.hpp"
|
||||
#include "Testing.hpp"
|
||||
|
||||
using namespace tp;
|
||||
|
||||
TEST_DEF_STATIC(Simple) {
|
||||
|
||||
const int1* data = "abcde\0";
|
||||
int1 dataRead[6]{};
|
||||
|
||||
{
|
||||
LocalConnection file;
|
||||
file.connect(LocalConnectionLocation(String("tmp2.txt")), LocalConnectionType(false));
|
||||
file.writeBytes(data, 6);
|
||||
file.disconnect();
|
||||
}
|
||||
|
||||
{
|
||||
LocalConnection file;
|
||||
file.connect(LocalConnectionLocation(String("tmp2.txt")), LocalConnectionType(true));
|
||||
file.readBytes(dataRead, 6);
|
||||
file.disconnect();
|
||||
}
|
||||
|
||||
for (auto i = 0; i < 5; i++) {
|
||||
TEST(data[i] == dataRead[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_DEF(LocalConnection) {
|
||||
testSimple();
|
||||
}
|
||||
19
Connection/tests/Tests.cpp
Normal file
19
Connection/tests/Tests.cpp
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
|
||||
#include "ConnectionCommon.hpp"
|
||||
#include "Testing.hpp"
|
||||
|
||||
void testLocalConnection();
|
||||
|
||||
int main() {
|
||||
|
||||
tp::ModuleManifest* deps[] = { &tp::gModuleConnection, nullptr };
|
||||
tp::ModuleManifest testModule("ConnectionTest", nullptr, nullptr, deps);
|
||||
|
||||
if (!testModule.initialize()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
testLocalConnection();
|
||||
|
||||
testModule.deinitialize();
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue