aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoralpine <[email protected]>2020-06-04 16:13:19 +0200
committeralpine <[email protected]>2020-06-04 16:13:19 +0200
commit28f66dee8a9fe49aadb5c1d67de48d9232363963 (patch)
tree00f6bfd0c2120d005c833301830d167b0753feb3
downloadloader-28f66dee8a9fe49aadb5c1d67de48d9232363963.tar.xz
loader-28f66dee8a9fe49aadb5c1d67de48d9232363963.zip
Initial commit
-rw-r--r--.gitignore42
-rw-r--r--.gitmodules6
-rw-r--r--CMakeLists.txt31
-rw-r--r--client/CMakeLists.txt14
-rw-r--r--client/src/client/client.cpp35
-rw-r--r--client/src/client/client.h47
-rw-r--r--client/src/client/packet.h45
-rw-r--r--client/src/include.h63
-rw-r--r--client/src/main.cpp29
-rw-r--r--client/src/util/events.h24
-rw-r--r--client/src/util/io.cpp12
-rw-r--r--client/src/util/io.h7
-rw-r--r--server/CMakeLists.txt15
-rw-r--r--server/src/include.h41
-rw-r--r--server/src/main.cpp14
-rw-r--r--server/src/server/packet.h10
-rw-r--r--server/src/server/server.cpp52
-rw-r--r--server/src/server/server.h12
-rw-r--r--server/src/server/ssl.h1
-rw-r--r--server/src/util/commands.h21
-rw-r--r--server/src/util/events.h24
-rw-r--r--server/src/util/io.cpp41
-rw-r--r--server/src/util/io.h8
m---------shared/cpr0
m---------shared/spdlog0
25 files changed, 594 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..981986a
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,42 @@
+#Auto generated files
+build/*
+bin/*
+
+#Visual studio files
+*.tlog
+
+# Prerequisites
+*.d
+
+# Compiled Object files
+*.slo
+*.lo
+*.o
+*.obj
+*.ipch
+*.suo
+*.db
+
+# Precompiled Headers
+*.gch
+*.pch
+
+# Compiled Dynamic libraries
+*.so
+*.dylib
+*.dll
+
+# Fortran module files
+*.mod
+*.smod
+
+# Compiled Static libraries
+*.lai
+*.la
+*.a
+*.lib
+
+# Executables
+*.exe
+*.out
+*.app \ No newline at end of file
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..8b0d96f
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,6 @@
+[submodule "shared/spdlog"]
+ path = shared/spdlog
+ url = https://github.com/gabime/spdlog.git
+[submodule "shared/cpr"]
+ path = shared/cpr
+ url = https://github.com/whoshuu/cpr.git
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..facc157
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,31 @@
+cmake_minimum_required(VERSION 3.14)
+
+project(server-client)
+
+if(NOT CMAKE_BUILD_TYPE)
+ set(CMAKE_BUILD_TYPE Release)
+endif()
+
+set(CMAKE_CXX_STANDARD 17)
+set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
+
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
+
+set(USE_SYSTEM_CURL ON CACHE BOOL "" FORCE)
+set(BUILD_CPR_TESTS OFF CACHE BOOL "" FORCE)
+set(SPDLOG_BUILD_TESTING OFF CACHE BOOL "" FORCE)
+
+find_package(OpenSSL REQUIRED)
+
+set(OPENSSL_USE_STATIC_LIBS TRUE)
+
+add_subdirectory(shared/spdlog)
+add_subdirectory(shared/cpr)
+add_subdirectory(server)
+add_subdirectory(client)
+
+target_include_directories(server PRIVATE ${PROJECT_SOURCE_DIR}/shared ${OPENSSL_INCLUDE_DIR} ${CPR_INCLUDE_DIRS})
+target_link_libraries(server PRIVATE spdlog ${OPENSSL_LIBRARIES} ${CPR_LIBRARIES})
+
+target_include_directories(client PRIVATE ${PROJECT_SOURCE_DIR}/shared)
+target_link_libraries(client PRIVATE spdlog)
diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt
new file mode 100644
index 0000000..2eff688
--- /dev/null
+++ b/client/CMakeLists.txt
@@ -0,0 +1,14 @@
+cmake_minimum_required(VERSION 3.10)
+
+project(client)
+
+set(source_dir "${PROJECT_SOURCE_DIR}/src")
+
+file(GLOB_RECURSE source_files "${source_dir}/*.cpp")
+file(GLOB_RECURSE header_files "${source_dir}/*.h")
+
+add_executable(
+ client
+ ${source_files}
+ ${header_files}
+)
diff --git a/client/src/client/client.cpp b/client/src/client/client.cpp
new file mode 100644
index 0000000..9fe2e36
--- /dev/null
+++ b/client/src/client/client.cpp
@@ -0,0 +1,35 @@
+#include "../include.h"
+#include "client.h"
+
+bool tcp::client::start(const std::string_view server_ip,
+ const uint16_t &port) {
+#ifdef WINDOWS
+ WSADATA data;
+ int res = WSAStartup(MAKEWORD(2, 2), &data);
+ if (res != 0) {
+ io::logger->error("failed to initialize WSA.");
+ return false;
+ }
+#endif
+
+ m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (m_socket == -1) {
+ io::logger->error("failed to create socket.");
+ return false;
+ }
+
+ sockaddr_in server_addr;
+
+ server_addr.sin_family = AF_INET;
+ server_addr.sin_addr.s_addr = inet_addr(server_ip.data());
+ server_addr.sin_port = htons(port);
+
+ int ret = connect(m_socket, reinterpret_cast<sockaddr *>(&server_addr),
+ sizeof(server_addr));
+ if (ret < 0) {
+ io::logger->error("failed to connect to server.");
+ return false;
+ }
+
+ return true;
+}
diff --git a/client/src/client/client.h b/client/src/client/client.h
new file mode 100644
index 0000000..8f14071
--- /dev/null
+++ b/client/src/client/client.h
@@ -0,0 +1,47 @@
+#pragma once
+#include "../util/io.h"
+#include "../util/events.h"
+
+namespace tcp {
+
+enum client_state : uint8_t {
+ idle = 0,
+ active,
+ standby
+};
+
+class client {
+ int m_socket;
+ std::atomic<uint8_t> m_state;
+
+ event<std::string> receive_event;
+
+ public:
+ client() : m_socket{-1}, m_state{0} {}
+ bool start(const std::string_view server_ip, const uint16_t &port);
+
+ bool send_message(const std::string_view msg) {
+ int ret = send(m_socket, msg.data(), msg.size(), 0);
+ return ret == msg.size();
+ }
+
+ int get_socket() { return m_socket; }
+ bool is_active() { return m_state == client_state::active; }
+ void set_state(const uint8_t &state) { m_state = state; }
+ auto &on_recv() { return receive_event; }
+
+ static void read(client &client) {
+ std::array<char, 256> buf;
+ while (client.is_active()) {
+ int ret = recv(client.get_socket(), &buf[0], buf.size(), 0);
+ if (ret <= 0) {
+ io::logger->error("connection lost.");
+ break;
+ }
+
+ std::string msg(buf.data(), ret);
+ client.on_recv().call(msg);
+ }
+ }
+};
+} // namespace tcp
diff --git a/client/src/client/packet.h b/client/src/client/packet.h
new file mode 100644
index 0000000..b61c4e2
--- /dev/null
+++ b/client/src/client/packet.h
@@ -0,0 +1,45 @@
+#pragma once
+
+namespace tcp {
+ constexpr size_t uid_len = 10;
+ struct packet_t {
+ std::string message;
+ char action;
+ std::array<char, uid_len> uid;
+
+ // parse packet from server message after decryption
+ bool parse(const std::string msg) {
+ // first 10 bytes is the uid
+ bool res = set_uid(msg.substr(0, uid_len));
+ if(!res) {
+ return false;
+ }
+
+ action = msg[uid_len];
+ const bool stream = static_cast<bool>(msg[uid_len + 1]);
+ if(stream) {
+ const size_t size = std::stoll(msg.substr(uid_len + 2));
+
+ // receive stream
+
+ return true;
+ }
+
+ message = msg.substr(uid_len + 2);
+ return true;
+ }
+ bool set_uid(const std::string_view uid_str) {
+ const size_t uid_str_len = uid_str_len.size();
+ if(uid_str_len != uid_len) {
+ io::logger->error("packet uid len mismatch!");
+ return false;
+ }
+
+ for(size_t i = 0; i < uid_len; ++i) {
+ uid[i] = uid_str[i];
+ }
+
+ return true;
+ }
+ };
+};
diff --git a/client/src/include.h b/client/src/include.h
new file mode 100644
index 0000000..e2c647b
--- /dev/null
+++ b/client/src/include.h
@@ -0,0 +1,63 @@
+#pragma once
+
+#if defined(_WIN32) || defined(_WIN64)
+#define WINDOWS
+#endif
+
+#ifdef WINDOWS
+#define _CRT_SECURE_NO_WARNINGS
+#define _WINSOCK_DEPRECATED_NO_WARNINGS
+#define WIN32_LEAN_AND_MEAN
+#define NOMINMAX
+
+#include <windows.h>
+#include <stdio.h>
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <iphlpapi.h>
+
+#pragma comment( lib, "ws2_32.lib" )
+#endif
+
+#include <stdio.h>
+#include <algorithm>
+#include <array>
+#include <chrono>
+#include <cstring>
+#include <fstream>
+#include <functional>
+#include <iostream>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <system_error>
+#include <thread>
+#include <vector>
+#include <unordered_map>
+#include <optional>
+#include <iomanip>
+#include <map>
+#include <random>
+#include <list>
+#include <utility>
+#include <atomic>
+#include <mutex>
+#include <future>
+#include <any>
+
+#ifndef WINDOWS
+
+#define closesocket(socket) close(socket)
+
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+
+#include <spdlog/fmt/fmt.h>
+#include <spdlog/spdlog.h>
+#include <spdlog/sinks/basic_file_sink.h>
+#include <spdlog/sinks/stdout_color_sinks.h> \ No newline at end of file
diff --git a/client/src/main.cpp b/client/src/main.cpp
new file mode 100644
index 0000000..1dc9db2
--- /dev/null
+++ b/client/src/main.cpp
@@ -0,0 +1,29 @@
+#include "include.h"
+#include "util/io.h"
+#include "client/client.h"
+
+int main(int argc, char *argv[]) {
+ tcp::client client;
+ if (client.start("127.0.0.1", 6666)) {
+ io::logger->info("connected.");
+ client.set_state(tcp::client_state::active);
+ }
+
+ client.on_recv().add([&](std::string msg) {
+ io::logger->info(msg);
+ });
+
+ std::thread t{tcp::client::read, std::ref(client)};
+
+ while (client.is_active()) {
+ std::string p;
+ getline(std::cin, p);
+
+ bool ret = client.send_message(p);
+ if (!ret) {
+ break;
+ }
+ }
+
+ t.join();
+}
diff --git a/client/src/util/events.h b/client/src/util/events.h
new file mode 100644
index 0000000..b8d7781
--- /dev/null
+++ b/client/src/util/events.h
@@ -0,0 +1,24 @@
+#pragma once
+
+template <typename... Args>
+class event {
+ using func_type = std::function<void(Args...)>;
+
+ std::mutex event_lock;
+ std::list<func_type> m_funcs;
+
+ public:
+ void add(const func_type& func) {
+ std::lock_guard<std::mutex> lock(event_lock);
+
+ m_funcs.push_back(std::move(func));
+ }
+
+ void call(Args... params) {
+ std::lock_guard<std::mutex> lock(event_lock);
+
+ for (auto& func : m_funcs) {
+ if (func) func(std::forward<Args>(params)...);
+ }
+ }
+}; \ No newline at end of file
diff --git a/client/src/util/io.cpp b/client/src/util/io.cpp
new file mode 100644
index 0000000..06d2b9a
--- /dev/null
+++ b/client/src/util/io.cpp
@@ -0,0 +1,12 @@
+#include "../include.h"
+#include "io.h"
+
+std::shared_ptr<spdlog::logger> io::logger;
+
+void io::init() {
+ spdlog::sink_ptr sink =
+ std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
+ sink->set_pattern("%^~>%$ %v");
+
+ logger = std::make_shared<spdlog::logger>("client", sink);
+}
diff --git a/client/src/util/io.h b/client/src/util/io.h
new file mode 100644
index 0000000..8eae321
--- /dev/null
+++ b/client/src/util/io.h
@@ -0,0 +1,7 @@
+#pragma once
+
+namespace io {
+extern std::shared_ptr<spdlog::logger> logger;
+
+void init();
+}; // namespace io
diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt
new file mode 100644
index 0000000..0461d8b
--- /dev/null
+++ b/server/CMakeLists.txt
@@ -0,0 +1,15 @@
+cmake_minimum_required(VERSION 3.14)
+
+project(server)
+
+set(CMAKE_CXX_STANDARD 17)
+set(source_dir "${PROJECT_SOURCE_DIR}/src")
+
+file(GLOB_RECURSE source_files "${source_dir}/*.cpp")
+file(GLOB_RECURSE header_files "${source_dir}/*.h")
+
+add_executable(
+ server
+ ${source_files}
+ ${header_files}
+) \ No newline at end of file
diff --git a/server/src/include.h b/server/src/include.h
new file mode 100644
index 0000000..eb31336
--- /dev/null
+++ b/server/src/include.h
@@ -0,0 +1,41 @@
+#pragma once
+
+#include <algorithm>
+#include <array>
+#include <chrono>
+#include <cstring>
+#include <fstream>
+#include <functional>
+#include <iostream>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <system_error>
+#include <thread>
+#include <vector>
+#include <unordered_map>
+#include <unordered_set>
+#include <optional>
+#include <map>
+#include <random>
+#include <list>
+#include <utility>
+#include <atomic>
+#include <mutex>
+#include <filesystem>
+
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <cpr/cpr.h>
+
+#include <spdlog/fmt/fmt.h>
+#include <spdlog/spdlog.h>
+#include <spdlog/sinks/basic_file_sink.h>
+#include <spdlog/sinks/stdout_color_sinks.h>
+
+#include <openssl/ssl.h>
diff --git a/server/src/main.cpp b/server/src/main.cpp
new file mode 100644
index 0000000..f34c433
--- /dev/null
+++ b/server/src/main.cpp
@@ -0,0 +1,14 @@
+#include "include.h"
+#include "util/io.h"
+#include "util/commands.h"
+#include "server/server.h"
+
+int main(int argc, char *argv[]) {
+ io::init(false);
+
+ tcp::server server;
+ server.start("6666");
+ server.start("8981");
+
+ std::cin.get();
+}
diff --git a/server/src/server/packet.h b/server/src/server/packet.h
new file mode 100644
index 0000000..02d90d1
--- /dev/null
+++ b/server/src/server/packet.h
@@ -0,0 +1,10 @@
+#pragma once
+
+namespace tcp {
+ constexpr uint8_t uid_len = 10;
+
+ struct packet_t {
+ std::string message;
+ std::array<char, uid_len> uid;
+ }
+}
diff --git a/server/src/server/server.cpp b/server/src/server/server.cpp
new file mode 100644
index 0000000..2f684e1
--- /dev/null
+++ b/server/src/server/server.cpp
@@ -0,0 +1,52 @@
+#include "../include.h"
+#include "../util/io.h"
+#include "server.h"
+
+bool tcp::server::start(const std::string_view port) {
+ io::logger->info("starting server on port {}...", port.data());
+
+ m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (m_socket < 0) {
+ io::logger->critical("failed to create socket.");
+ return false;
+ }
+ struct addrinfo hints, *addrinfo = nullptr;
+
+ memset(&hints, 0, sizeof hints);
+
+ hints.ai_family = AF_INET;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+ hints.ai_flags = AI_PASSIVE;
+
+ int ret = getaddrinfo(nullptr, port.data(), &hints, &addrinfo);
+ if (ret != 0) {
+ io::logger->critical("failed to get address info.");
+ close(m_socket);
+ return false;
+ }
+
+ ret = bind(m_socket, addrinfo->ai_addr, addrinfo->ai_addrlen);
+ if (ret < 0) {
+ io::logger->critical("failed to bind port.");
+ close(m_socket);
+ return false;
+ }
+ io::logger->info("port bound.");
+ freeaddrinfo(addrinfo);
+
+ ret = listen(m_socket, SOMAXCONN);
+ if (ret < 0) {
+ io::logger->critical("failed to listen on port {}.", port.data());
+ close(m_socket);
+ return false;
+ }
+ io::logger->info("listening on {}.", port.data());
+
+ return true;
+}
+
+void tcp::server::stop() {
+ io::logger->info("stopping server on port {}.", m_port);
+ close(m_socket);
+} \ No newline at end of file
diff --git a/server/src/server/server.h b/server/src/server/server.h
new file mode 100644
index 0000000..f848ae2
--- /dev/null
+++ b/server/src/server/server.h
@@ -0,0 +1,12 @@
+#pragma once
+
+namespace tcp {
+class server {
+ int m_socket;
+
+ public:
+
+ bool start(const std::string_view port);
+ void stop();
+};
+}; // namespace tcp
diff --git a/server/src/server/ssl.h b/server/src/server/ssl.h
new file mode 100644
index 0000000..7b9637e
--- /dev/null
+++ b/server/src/server/ssl.h
@@ -0,0 +1 @@
+#pragma once \ No newline at end of file
diff --git a/server/src/util/commands.h b/server/src/util/commands.h
new file mode 100644
index 0000000..1e5ae0f
--- /dev/null
+++ b/server/src/util/commands.h
@@ -0,0 +1,21 @@
+#pragma once
+
+class commands {
+ using func = std::function<void()>;
+ std::unordered_map<std::string_view, func> m_cmds;
+
+ public:
+ bool parse_input(const std::string_view str) {
+ auto it = m_cmds.find(str);
+ if (it != m_cmds.end()) {
+ it->second();
+ return true;
+ }
+ return false;
+ }
+
+ void add(const std::string_view cmd, const func &cb) {
+
+ m_cmds[cmd] = cb;
+ }
+};
diff --git a/server/src/util/events.h b/server/src/util/events.h
new file mode 100644
index 0000000..e6f053d
--- /dev/null
+++ b/server/src/util/events.h
@@ -0,0 +1,24 @@
+#pragma once
+
+template <typename... Args>
+class event {
+ using func_type = std::function<void(Args...)>;
+
+ std::mutex event_lock;
+ std::list<func_type> m_funcs;
+
+ public:
+ void add(const func_type& func) {
+ std::lock_guard<std::mutex> lock(event_lock);
+
+ m_funcs.emplace_back(std::move(func));
+ }
+
+ void call(Args... params) {
+ std::lock_guard<std::mutex> lock(event_lock);
+
+ for (auto& func : m_funcs) {
+ if (func) func(std::forward<Args>(params)...);
+ }
+ }
+};
diff --git a/server/src/util/io.cpp b/server/src/util/io.cpp
new file mode 100644
index 0000000..1f9bca6
--- /dev/null
+++ b/server/src/util/io.cpp
@@ -0,0 +1,41 @@
+#include "../include.h"
+#include "io.h"
+
+std::shared_ptr<spdlog::logger> io::logger;
+
+void io::init(const bool &trunc) {
+ auto sink =
+ std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
+ sink->set_pattern("[%R][%^%l%$] %v");
+
+ auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>("server.log", trunc);
+
+ std::vector<spdlog::sink_ptr> log_sinks;
+ log_sinks.emplace_back(sink);
+ log_sinks.emplace_back(file_sink);
+
+ logger = std::make_shared<spdlog::logger>("server", log_sinks.begin(), log_sinks.end());
+ spdlog::register_logger(logger);
+
+ spdlog::flush_every(std::chrono::seconds(1));
+}
+
+void io::read_file(const std::string_view name, std::vector<char> &out) {
+ std::ifstream file(name.data());
+ if (!file.good()) {
+ io::logger->error("failed to load {}.", name.data());
+ return;
+ }
+
+ file.unsetf(std::ios::skipws);
+
+ file.seekg(0, std::ios::end);
+ const size_t size = file.tellg();
+ file.seekg(0, std::ios::beg);
+
+ out.resize(size);
+
+ file.read(out.data(), size);
+
+ file.close();
+}
diff --git a/server/src/util/io.h b/server/src/util/io.h
new file mode 100644
index 0000000..437b465
--- /dev/null
+++ b/server/src/util/io.h
@@ -0,0 +1,8 @@
+#pragma once
+
+namespace io {
+extern std::shared_ptr<spdlog::logger> logger;
+
+void init(const bool &trunc);
+void read_file(const std::string_view name, std::vector<char> &out);
+}; // namespace io
diff --git a/shared/cpr b/shared/cpr
new file mode 160000
+Subproject 7e4a803fff0787b8a961527016f1060373a7ce6
diff --git a/shared/spdlog b/shared/spdlog
new file mode 160000
+Subproject 22a169bc319ac06948e7ee0be6b9b0ac8138660