From 28f66dee8a9fe49aadb5c1d67de48d9232363963 Mon Sep 17 00:00:00 2001 From: alpine Date: Thu, 4 Jun 2020 16:13:19 +0200 Subject: Initial commit --- client/src/client/client.cpp | 35 ++++++++++++++++++++++++ client/src/client/client.h | 47 +++++++++++++++++++++++++++++++++ client/src/client/packet.h | 45 +++++++++++++++++++++++++++++++ client/src/include.h | 63 ++++++++++++++++++++++++++++++++++++++++++++ client/src/main.cpp | 29 ++++++++++++++++++++ client/src/util/events.h | 24 +++++++++++++++++ client/src/util/io.cpp | 12 +++++++++ client/src/util/io.h | 7 +++++ 8 files changed, 262 insertions(+) create mode 100644 client/src/client/client.cpp create mode 100644 client/src/client/client.h create mode 100644 client/src/client/packet.h create mode 100644 client/src/include.h create mode 100644 client/src/main.cpp create mode 100644 client/src/util/events.h create mode 100644 client/src/util/io.cpp create mode 100644 client/src/util/io.h (limited to 'client/src') 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(&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 m_state; + + event 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 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 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(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 +#include +#include +#include +#include + +#pragma comment( lib, "ws2_32.lib" ) +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef WINDOWS + +#define closesocket(socket) close(socket) + +#include +#include +#include +#include +#include +#include +#endif + +#include +#include +#include +#include \ 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 +class event { + using func_type = std::function; + + std::mutex event_lock; + std::list m_funcs; + + public: + void add(const func_type& func) { + std::lock_guard lock(event_lock); + + m_funcs.push_back(std::move(func)); + } + + void call(Args... params) { + std::lock_guard lock(event_lock); + + for (auto& func : m_funcs) { + if (func) func(std::forward(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 io::logger; + +void io::init() { + spdlog::sink_ptr sink = + std::make_shared(); + sink->set_pattern("%^~>%$ %v"); + + logger = std::make_shared("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 logger; + +void init(); +}; // namespace io -- cgit v1.2.3