diff --git a/CMakeLists.txt b/CMakeLists.txt
index e792c5f..081bcb9 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -4,21 +4,35 @@ project(tablo)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
-# Tablo shared libraries
+# Build options
-# libtabcrypt
-add_subdirectory(lib/libtabcrypt)
+option(DEF_LIBTABCRYPT "Build libtabcrypt" ON)
+option(DEF_LIBTABNET "Build libtabnet" ON)
-# libtabnet
-add_subdirectory(lib/libtabnet)
+option(DEF_CLIENT "Build TabloClient" ON)
+option(DEF_MASTER "Build TabloMaster" ON)
+option(DEF_NODE "Build TabloNode" ON)
-# Test executables
+# Shared libraries
-add_subdirectory(TCTest)
+if(DEF_LIBTABCRYPT)
+ add_subdirectory(lib/libtabcrypt)
+endif()
+if(DEF_LIBTABNET)
+ add_subdirectory(lib/libtabnet)
+endif()
-# TabloClient, TabloMaster and TabloNode executables (provided by own CMakeLists.txt files)
+# Executables
-add_subdirectory(TabloClient)
-add_subdirectory(TabloMaster)
-add_subdirectory(TabloNode)
+if(DEF_CLIENT)
+ add_subdirectory(TabloClient)
+endif()
+
+if(DEF_MASTER)
+ add_subdirectory(TabloMaster)
+endif()
+
+if(DEF_NODE)
+ add_subdirectory(TabloNode)
+endif()
diff --git a/README.md b/README.md
index 3471a24..fc618c1 100644
--- a/README.md
+++ b/README.md
@@ -14,11 +14,11 @@ The following ports are used to establish the network tablo needs:
### 2 Deploy
```cmd
-nix shell
-./build-image-nix.sh
-tablo-master --interface YOURINTERFACE
-tablo-node --interface YOURINTERFACE
-tablo-client --master YOURMASTERSIP
+sudo nix-collect-garbage -d
+nix build --log-format bar-with-logs
+nix run .#tablo-master -- --interface INTERFACENAME
+nix run .#tablo-node -- --interface INTERFACENAME
+nix run .#tablo-client -- --master MASTERIPV4
```
## Deploy with DOCKER
@@ -45,3 +45,7 @@ The flake in this repository allowes you to build minimal docker images that avo
To use this feature, you NEED to use nix. Download available at: https://nixos.org/
+# Take a look at Tablos networking libs:
+Tablo Transfer Protocol:TTP2
+
+Tablo UDP Discovery: TUD
diff --git a/TCTest/CMakeLists.txt b/TCTest/CMakeLists.txt
deleted file mode 100644
index 9eee444..0000000
--- a/TCTest/CMakeLists.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-cmake_minimum_required(VERSION 3.10)
-project(tablo)
-
-set(CMAKE_CXX_STANDARD 17)
-set(CMAKE_CXX_STANDARD_REQUIRED ON)
-
-file(GLOB_RECURSE SOURCES "src/*.cpp" "src/*.h")
-
-add_executable(tabcrypt-test ${SOURCES})
-
-# Link against the tabcrypt library
-target_link_libraries(tabcrypt-test PRIVATE tabcrypt)
-
-install(TARGETS tabcrypt-test DESTINATION bin)
diff --git a/TCTest/src/main.cpp b/TCTest/src/main.cpp
deleted file mode 100644
index 3d7b702..0000000
--- a/TCTest/src/main.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-#include
-#include
-#include "tabcrypt_test.h"
-
-
-void handleLine(const std::string& line) {
- if (encrypt_mode) {
- std::cout << tabcrypt::encrypt(line, secret) << "\n";
- } else {
- try {
- std::cout << tabcrypt::decrypt(line, secret) << "\n";
- } catch (const std::exception& e) {
- std::cerr << "Decryption failed: " << e.what() << "\n";
- }
- }
-}
-
-
-/*
- * Arguments:
- * tabcrypt_test [-d|-e]
- * Messages via stdin/stdout
- */
-int main(int argc, char *argv[]) {
- if (argc < 2) {
- std::cerr << "Usage: " << argv[0] << " [-d|-e]\n"
- " -d: decrypt (default)\n"
- " -e: encrypt\n";
- return EXIT_FAILURE;
- };
- std::string secret = argv[1];
-
- // parse argv[2]
-
- if (std::string(argv[2]) == "-e") {
- encrypt_mode = true;
- } else if (std::string(argv[2]) != "-d") {
- std::cerr << "Unknown option: " << argv[2] << "\n";
- return EXIT_FAILURE;
- }
-
- std::string line;
-
- while (std::getline(std::cin, line)) {
- if (line.empty()) {
- break; // Exit on empty line
- }
- handleLine(line);
- }
-}
diff --git a/TCTest/src/tabcrypt_test.h b/TCTest/src/tabcrypt_test.h
deleted file mode 100644
index 4762f02..0000000
--- a/TCTest/src/tabcrypt_test.h
+++ /dev/null
@@ -1,13 +0,0 @@
-//
-// Created by Tureb on 22.07.2025.
-//
-
-#ifndef TABCRYPT_TEST_H
-#define TABCRYPT_TEST_H
-
-inline bool encrypt_mode = false;
-inline std::string secret;
-
-void handleLine(const std::string& line);
-
-#endif //TABCRYPT_TEST_H
diff --git a/TabloClient/CMakeLists.txt b/TabloClient/CMakeLists.txt
index b1ce592..2d2bfc0 100644
--- a/TabloClient/CMakeLists.txt
+++ b/TabloClient/CMakeLists.txt
@@ -8,8 +8,9 @@ file(GLOB_RECURSE SOURCES "src/*.cpp" "src/*.h")
add_executable(tablo-client ${SOURCES})
-# Link against the tabcrypt library
+# Link against libs
target_link_libraries(tablo-client PRIVATE tabcrypt)
target_link_libraries(tablo-client PRIVATE tabnet)
+target_link_libraries(tablo-client PRIVATE ttp2)
install(TARGETS tablo-client DESTINATION bin)
diff --git a/TabloClient/src/tabloClient.cpp b/TabloClient/src/tabloClient.cpp
index 32c1080..d76a410 100644
--- a/TabloClient/src/tabloClient.cpp
+++ b/TabloClient/src/tabloClient.cpp
@@ -3,18 +3,27 @@
#include
#include "utils/cli.h"
+#include "utils/argv_struct.h"
int main(int argc, char *argv[])
{
if (argc > 0) {
+ struct Argv commandLineArguments;
+
for(int index = 0; index < argc; index++) {
if (std::string(argv[index]).rfind("--master", 0) == 0) {
- Cli cli(argv[index+1]);
+ commandLineArguments.tabloMaster = argv[index+1];
+ } else if (std::string(argv[index]).rfind("--file", 0) == 0) {
+ commandLineArguments.filePath = argv[index+1];
}
}
+
+ if (commandLineArguments.tabloMaster.length() != 0) {
+ Cli cli(commandLineArguments);
+ }
} else {
// Use config file (TODO)
- Cli cli("");
+ std::wcout << "failed" << std::endl;
}
return 0;
diff --git a/TabloClient/src/utils/argv_struct.h b/TabloClient/src/utils/argv_struct.h
new file mode 100644
index 0000000..e73304c
--- /dev/null
+++ b/TabloClient/src/utils/argv_struct.h
@@ -0,0 +1,11 @@
+#ifndef ARGV_STRUCT_H
+#define ARGV_STRUCT_H
+
+#include
+
+struct Argv {
+ std::string tabloMaster;
+ std::string filePath;
+};
+
+#endif
diff --git a/TabloClient/src/utils/cli.cpp b/TabloClient/src/utils/cli.cpp
index 19238b4..ad8fae3 100644
--- a/TabloClient/src/utils/cli.cpp
+++ b/TabloClient/src/utils/cli.cpp
@@ -1,40 +1,134 @@
#include "cli.h"
-#include
+#include
#include
#include
-#include
+#include
#include
+#include
-#include "networking.h"
+#include "network_manager.h"
-Cli::Cli(std::string tabloMaster) {
+Cli::Cli(struct Argv argv) {
+ std::string tabloMaster = argv.tabloMaster;
+ std::string filePath = argv.filePath;
+
std::wcout << "Client! Tablo master at: " << tabloMaster.c_str() << std::endl;
- Networking networking;
+
+ NetworkManager networkManager;
+
+ if (networkManager.createSocket(tabloMaster) < 0) {
+ std::wcout << "Create network manager failed!" << std::endl;
+ return;
+ }
- std::thread networkingThread(
- &Networking::networkingCycle,
- &networking,
- tabloMaster
- );
+ sendFile(filePath, &networkManager);
while (true) {
- int method;
- std::wcout << "Method: ";
- std::cin >> method;
- std::wcout << std::endl;
+ std::wcout << "Choose option\n(1) send Packet\n(2) read Packets\n(3) send File\n(4) get Viewport\noption:";
+ std::string option = "";
+ std::cin >> option;
+ if (option == "1") {
+ std::string content;
+ std::wcout << "Content: ";
+ std::cin >> content;
- std::string content;
- std::wcout << "Content: ";
- std::cin >> content;
- std::wcout << std::endl;
+ ttp2::Networking::Packet packet;
- networking.pushOrder(method, content);
+ ttp2::Networking::Standard payload;
+ payload.payload = content;
+ packet.payload = payload;
- std::wcout << "Waiting for solution..." << std::endl;
- while (!networking.hasSolution()) {} // Wait for solution
+ networkManager.pushRequest(packet);
+ } else if (option == "2") {
+ if (networkManager.hasResponse()) {
+ while (networkManager.hasResponse()) {
+ ttp2::ClientSessionController::Packet response = networkManager.popResponse();
+
+ if (std::holds_alternative(response.payload)) {
+ ttp2::ClientSessionController::Standard responsePayload = std::get(response.payload);
+ std::wcout << "Response:\nID: " << response.id << "\nPayload: " << responsePayload.payload.c_str() << std::endl;
+ } else if (std::holds_alternative(response.payload)) {
+ ttp2::ClientSessionController::File responsePayload = std::get(response.payload);
+ std::wcout << "Response:\nID: " << response.id
+ << "\n----payload----\nFilePath: " << responsePayload.filePath.c_str()
+ << "\nStart: " << responsePayload.start
+ << "\nEnd: " << responsePayload.end
+ << "\nPayload: " << responsePayload.payload.c_str()
+ << "\n---------------" << std::endl;
+ } else if (std::holds_alternative(response.payload)) {
+ ttp2::ClientSessionController::Viewport responseViewport = std::get(response.payload);
+ if (responseViewport.payload.length() > 0) {
+ std::wcout << responseViewport.payload.c_str() << std::endl;
+ } else {
+ std::wcout << "Empty Viewport" << std::endl;
+ }
+ }
+ }
+ } else {
+ std::wcout << "There are currently no packets to read!" << std::endl;
+ }
+ } else if (option == "3") {
+ std::string filePath;
+ std::wcout << "CSV Filepath:";
+ std::cin >> filePath;
+
+ sendFile(filePath, &networkManager);
+ } else if (option == "4") {
+ int xStart;
+ int xEnd;
+ int yStart;
+ int yEnd;
- std::wcout << networking.popSolution().c_str() << std::endl;
+ std::wcout << "xStart:";
+ std::cin >> xStart;
+ std::wcout << "xEnd:";
+ std::cin >> xEnd;
+ std::wcout << "yStart:";
+ std::cin >> yStart;
+ std::wcout << "yEnd:";
+ std::cin >> yEnd;
+
+ ttp2::Networking::Packet packet;
+ ttp2::Networking::Viewport payload;
+ payload.xStart = xStart;
+ payload.xEnd = xEnd;
+ payload.yStart = yStart;
+ payload.yEnd = yEnd;
+ packet.payload = payload;
+
+ networkManager.pushRequest(packet);
+ std::wcout << "Send Viewport request!" << std::endl;
+ } else {
+ std::wcout << "invalid" << std::endl;
+ }
}
}
+void Cli::sendFile(std::string filePath, NetworkManager* networkManager) {
+ if (filePath.length() != 0) {
+ std::ifstream file(filePath);
+
+ if (file.is_open()) {
+ std::string fileContent;
+ std::string line;
+ int lineCount = 0;
+ while (std::getline(file, line)) {
+ lineCount++;
+ fileContent = fileContent + line.c_str() + "\n";
+ }
+ file.close();
+
+ ttp2::Networking::Packet packet;
+ ttp2::Networking::File payload;
+ payload.filePath = filePath;
+ payload.start = 0;
+ payload.end = lineCount;
+ payload.payload = fileContent;
+ packet.payload = payload;
+
+ networkManager->pushRequest(packet);
+ std::wcout << "Send file with FilePath: " << filePath.c_str() << std::endl;
+ }
+ }
+}
diff --git a/TabloClient/src/utils/cli.h b/TabloClient/src/utils/cli.h
index a1783a4..812198f 100644
--- a/TabloClient/src/utils/cli.h
+++ b/TabloClient/src/utils/cli.h
@@ -1,12 +1,17 @@
#ifndef CLI_H
#define CLI_H
-#include
+#include "network_manager.h"
+
+#include "argv_struct.h"
class Cli
{
public:
- Cli(std::string tabloMaster);
+ Cli(struct Argv argv);
+
+ private:
+ void sendFile(std::string filePath, NetworkManager* networkManager);
};
#endif
diff --git a/TabloClient/src/utils/network_manager.cpp b/TabloClient/src/utils/network_manager.cpp
new file mode 100644
index 0000000..0b96e43
--- /dev/null
+++ b/TabloClient/src/utils/network_manager.cpp
@@ -0,0 +1,51 @@
+#include "network_manager.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+NetworkManager::NetworkManager() {}
+
+int NetworkManager::createSocket(std::string tabloMaster) {
+ int serverSocket = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
+
+ sockaddr_in serverAddress;
+ serverAddress.sin_family = AF_INET;
+ serverAddress.sin_port = htons(4003);
+ serverAddress.sin_addr.s_addr = inet_addr(tabloMaster.c_str());
+
+ int connectionResult = connect(serverSocket, (struct sockaddr*) &serverAddress, sizeof(serverAddress));
+
+ // Wait for server to accept
+ if (connectionResult < 0 && errno != EINPROGRESS) {
+ std::wcout << "Connection failed!" << std::endl;
+ return -1;
+ }
+
+ clientSessionController = std::make_shared(serverSocket);
+
+ std::thread networkThread([this]() {
+ clientSessionController->networkingSession();
+ });
+ networkThread.detach();
+
+ return 0;
+}
+
+bool NetworkManager::hasResponse() {
+ return clientSessionController->hasResponse();
+}
+
+ttp2::ClientSessionController::Packet NetworkManager::popResponse() {
+ return clientSessionController->popResponse();
+}
+
+void NetworkManager::pushRequest(ttp2::Networking::Packet packet) {
+ clientSessionController->pushRequest(packet);
+}
diff --git a/TabloClient/src/utils/network_manager.h b/TabloClient/src/utils/network_manager.h
new file mode 100644
index 0000000..dfec037
--- /dev/null
+++ b/TabloClient/src/utils/network_manager.h
@@ -0,0 +1,25 @@
+#ifndef NETWORK_MANAGER_H
+#define NETWORK_MANAGER_H
+
+#include
+#include
+#include
+#include
+#include
+
+class NetworkManager
+{
+ public:
+ NetworkManager();
+
+ int createSocket(std::string tabloMaster);
+
+ bool hasResponse();
+ ttp2::ClientSessionController::Packet popResponse();
+ void pushRequest(ttp2::ClientSessionController::Packet packet);
+
+ private:
+ std::shared_ptr clientSessionController;
+};
+
+#endif
diff --git a/TabloClient/src/utils/networking.cpp b/TabloClient/src/utils/networking.cpp
deleted file mode 100644
index d67d8d0..0000000
--- a/TabloClient/src/utils/networking.cpp
+++ /dev/null
@@ -1,109 +0,0 @@
-#include "networking.h"
-
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "tabnet.h"
-#include "methods.h"
-
-Networking::Networking() {}
-
-void Networking::networkingCycle(std::string tabloMaster) {
- // creating socket
- int clientSocket = socket(AF_INET, SOCK_STREAM, 0);
-
- // specifying address
- sockaddr_in serverAddress;
- serverAddress.sin_family = AF_INET;
- serverAddress.sin_port = htons(4003);
- serverAddress.sin_addr.s_addr = inet_addr(tabloMaster.c_str());
-
- // sending connection request
- connect(clientSocket, (struct sockaddr*)&serverAddress, sizeof(serverAddress));
-
- while(true) {
- int orderCollectionSize = orderCollection.size();
- tabnet::sendMessage(clientSocket, Methods::size, std::to_string(orderCollectionSize));
- tabnet::Packet response = tabnet::receiveMessage(clientSocket);
- if (response.method == Methods::success) {
- for(int index = 0; index < orderCollectionSize; index++) {
- std::map order = orderCollection[0];
- orderCollection.erase(orderCollection.begin());
- int method = order.begin()->first;
-
- // Send data
- tabnet::sendMessage(clientSocket, method, order[method]);
- tabnet::Packet response = tabnet::receiveMessage(clientSocket);
- if (response.method == Methods::success) {
- std::wcout << "Send succeded!" << std::endl;
- } else {
- std::wcout << "Expected: " << Methods::success << " (success) or " << Methods::failed << " (failed), but got " << response.method << std::endl;
- std::wcout << "With following payload" << response.payload.c_str() << std::endl;
- }
- }
- } else if (response.method == Methods::failed) {
- std::wcout << "Something went wrong while sending the size! Master response: " << response.payload.c_str() << std::endl;
- } else {
- std::wcout << "Expected: " << Methods::success << " (success) or " << Methods::failed << " (failed), but got " << response.method << std::endl;
- std::wcout << "With following payload" << response.payload.c_str() << std::endl;
- }
-
- //receive
- tabnet::Packet receivedPacket = tabnet::receiveMessage(clientSocket);
- if (receivedPacket.method == Methods::size) {
- int count = std::stoi(receivedPacket.payload);
- if (count != 0) {
- tabnet::sendMessage(clientSocket, Methods::success, "");
- for(int i = 0; i < count; i++) {
- tabnet::Packet response = tabnet::receiveMessage(clientSocket);
- if (response.method == Methods::response) {
- solutionCollection.push_back(response.payload);
- tabnet::sendMessage(clientSocket, Methods::success, "");
- } else {
- std::wcout << "Expected: " << Methods::response << " (response) got: " << receivedPacket.method << std::endl;
- tabnet::sendMessage(clientSocket, Methods::failed, "Expected method response");
- }
- }
- }
- } else {
- std::wcout << "Expected: " << Methods::size << " (size) got: " << receivedPacket.method << std::endl;
- tabnet::sendMessage(clientSocket, Methods::failed, "Expected method size");
- }
- }
-}
-
-bool Networking::hasSolution() {
- std::lock_guard lock(mtx);
- return !solutionCollection.empty();
-}
-
-std::string Networking::popSolution() {
- std::lock_guard lock(mtx);
- std::string solution = solutionCollection[0];
- solutionCollection.erase(solutionCollection.begin());
- return solution;
-}
-
-void Networking::pushOrder(int method, std::string content) {
- std::lock_guard lock(mtx);
- std::map order;
- order[method] = content;
- orderCollection.push_back(order);
-}
-
-bool Networking::isNumeric(const std::string& string) {
- static const std::regex number_regex(
- R"(^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][-+]?\d+)?$)"
- );
- return std::regex_match(string, number_regex);
-}
-
diff --git a/TabloClient/src/utils/networking.h b/TabloClient/src/utils/networking.h
deleted file mode 100644
index b2f3c3f..0000000
--- a/TabloClient/src/utils/networking.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef NETWORKING_H
-#define NETWORKING_H
-
-#include
-#include