From b7541420f10cbd17aae160698456bfbd66f52cc9 Mon Sep 17 00:00:00 2001 From: kalipso Date: Sat, 23 Apr 2022 04:53:18 +0200 Subject: [PATCH] adding client/server prototype --- CMakeLists.txt | 8 ++++- include/client.hpp | 29 ++++++++++++++++++ include/protocol.hpp | 72 ++++++++++++++++++++++---------------------- include/server.hpp | 65 +++++++++++++++++++++++++++++++++++++++ src/client.cpp | 65 +++++++++++++++++++++++++++++++++++++++ src/main.cpp | 62 +++++++++++++++++++++++++++----------- src/server.cpp | 1 + 7 files changed, 248 insertions(+), 54 deletions(-) create mode 100644 include/client.hpp create mode 100644 include/server.hpp create mode 100644 src/client.cpp create mode 100644 src/server.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index d6adeaf..ed227d1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ set(CMAKE_BUILD_TYPE Release) project("commons" CXX) -add_definitions("-std=c++2a -g") +add_definitions("-lpthread -std=c++2a -g") include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) conan_basic_setup() @@ -14,6 +14,8 @@ conan_basic_setup() add_library(commons_lib include/commons.cpp src/protocol.cpp + src/server.cpp + src/client.cpp ) target_include_directories (commons_lib @@ -29,6 +31,10 @@ target_link_libraries(commons_lib add_executable(commons src/main.cpp + include/commons.cpp + src/protocol.cpp + src/server.cpp + src/client.cpp ) target_include_directories(commons diff --git a/include/client.hpp b/include/client.hpp new file mode 100644 index 0000000..2e256b8 --- /dev/null +++ b/include/client.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include +#include "boost/bind.hpp" +#include +#include +#include +#include + +class client +{ +public: + client(boost::asio::io_service& io_service, + const boost::asio::ip::address& multicast_address, + short multicast_port, + unsigned short tcp_port); + + void init(); + void set_outbound_interface(const boost::asio::ip::address_v4& address); + void handle_send_to(const boost::system::error_code& error); + void handle_timeout(const boost::system::error_code& error); + +private: + boost::asio::ip::udp::endpoint endpoint_; + boost::asio::ip::udp::socket socket_; + boost::asio::deadline_timer timer_; + std::string message_; + unsigned short port_; +}; diff --git a/include/protocol.hpp b/include/protocol.hpp index 6718e55..8abb098 100644 --- a/include/protocol.hpp +++ b/include/protocol.hpp @@ -91,12 +91,12 @@ struct composed_message : public generic_message struct vec2 { - float x,y; + int x,y; }; struct vec3 { - float x,y,z; + int x,y,z; }; struct draw_rectangle : public generic_message @@ -126,42 +126,42 @@ struct draw_pixel : public generic_message vec3 color; }; -uint32_t get_size(Type type) -{ - static std::map type_map{}; - - //initalizes map on first run - static bool run_once = [&](){ - type_map.emplace(Type::DRAW_PIXEL, sizeof(draw_pixel)); - type_map.emplace(Type::DRAW_RECTANGLE, sizeof(draw_rectangle)); - type_map.emplace(Type::COMPOSED_MESSAGE, sizeof(composed_message)); - return true; - }(); - - return type_map[type]; -} +//uint32_t get_size(Type type) +//{ +// static std::map type_map{}; +// +// //initalizes map on first run +// static bool run_once = [&](){ +// type_map.emplace(Type::DRAW_PIXEL, sizeof(draw_pixel)); +// type_map.emplace(Type::DRAW_RECTANGLE, sizeof(draw_rectangle)); +// type_map.emplace(Type::COMPOSED_MESSAGE, sizeof(composed_message)); +// return true; +// }(); +// +// return type_map[type]; +//} -generic_message_base* get_object(Type type, generic_message_base* msg) -{ - switch(type) - { - case Type::COMPOSED_MESSAGE: - { - return reinterpret_cast(msg); - } - case Type::DRAW_RECTANGLE: - { - return reinterpret_cast(msg); - } - case Type::DRAW_PIXEL: - { - return reinterpret_cast(msg); - } - default: - return nullptr; - } -} +//generic_message_base* get_object(Type type, generic_message_base* msg) +//{ +// switch(type) +// { +// case Type::COMPOSED_MESSAGE: +// { +// return reinterpret_cast(msg); +// } +// case Type::DRAW_RECTANGLE: +// { +// return reinterpret_cast(msg); +// } +// case Type::DRAW_PIXEL: +// { +// return reinterpret_cast(msg); +// } +// default: +// return nullptr; +// } +//} //template //auto* get_object(generic_message_base* msg) diff --git a/include/server.hpp b/include/server.hpp new file mode 100644 index 0000000..781eac8 --- /dev/null +++ b/include/server.hpp @@ -0,0 +1,65 @@ +#pragma once + +#include +#include +#include + +#include "protocol.hpp" + +using boost::asio::ip::udp; + +class server +{ +public: + server(boost::asio::io_context& io_context, short port) + : socket_(io_context, udp::endpoint(udp::v4(), port)) + { + do_receive(); + } + + void do_receive() + { + std::cout << "do_receive\n"; + socket_.async_receive_from( + boost::asio::buffer(data_, max_length), sender_endpoint_, + [this](boost::system::error_code ec, std::size_t bytes_recvd) + { + if (!ec && bytes_recvd > 0) + { + std::cout << data_ << std::endl; + + auto* msg_obj = reinterpret_cast(data_); + + std::cout << "Received Type: " << static_cast(msg_obj->get_type()) << "\n"; + std::cout << "Received Size: " << msg_obj->get_size() << "\n"; + + auto* casted_obj = reinterpret_cast(msg_obj); + + std::cout << "Positon: X = " << casted_obj->position.x + << " Y = " << casted_obj->position.y << std::endl; + + do_send(bytes_recvd); + } + else + { + do_receive(); + } + }); + } + + void do_send(std::size_t length) + { + socket_.async_send_to( + boost::asio::buffer(data_, length), sender_endpoint_, + [this](boost::system::error_code /*ec*/, std::size_t /*bytes_sent*/) + { + do_receive(); + }); + } + +private: + udp::socket socket_; + udp::endpoint sender_endpoint_; + enum { max_length = 1024 }; + char data_[max_length]; +}; diff --git a/src/client.cpp b/src/client.cpp new file mode 100644 index 0000000..fe4f595 --- /dev/null +++ b/src/client.cpp @@ -0,0 +1,65 @@ +#include "client.hpp" + +#include "protocol.hpp" + +#include + +client::client(boost::asio::io_service& io_service, + const boost::asio::ip::address& multicast_address, + short multicast_port, + unsigned short tcp_port) + : endpoint_(multicast_address, multicast_port) + , socket_(io_service, endpoint_.protocol()) + , timer_(io_service) + , port_(tcp_port) +{} + +void client::init() +{ + std::cout << "Send test msg\n"; + + auto msg = std::make_unique(); + msg->position = commons::protocol::vec2{3, 2}; + + void* void_ptr = reinterpret_cast(msg.get()); + auto size = sizeof(*msg.get()); + std::cout << "Object Type: " << static_cast(msg->get_type()) << "\n"; + std::cout << "Object size: " << size << "\n"; + + std::cout << "Positon: X = " << msg->position.x + << " Y = " << msg->position.y << std::endl; + + socket_.async_send_to( + boost::asio::buffer(void_ptr, size), endpoint_, + std::bind(&client::handle_send_to, this, + std::placeholders::_1)); +} + +void client::set_outbound_interface(const boost::asio::ip::address_v4& address) +{ + boost::asio::ip::multicast::outbound_interface option(address); + socket_.set_option(option); +} + +void client::handle_send_to(const boost::system::error_code& error) +{ + if(!error) + { + timer_.expires_from_now(boost::posix_time::seconds(1)); + timer_.async_wait( std::bind(&client::handle_timeout, this, + std::placeholders::_1)); + } +} + +void client::handle_timeout(const boost::system::error_code& error) +{ + if (!error) + { + //spdlog::trace("Resending Message: '{}'", "TestMessage"); + std::cout << "done\n"; + //socket_.async_send_to( + // boost::asio::buffer("TestMessage"), endpoint_, + // std::bind(&client::handle_send_to, this, + // std::placeholders::_1)); + } +} diff --git a/src/main.cpp b/src/main.cpp index a7f6d8b..b7645f9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,27 +1,55 @@ #include -#include #include "protocol.hpp" +#include "server.hpp" +#include "client.hpp" -int main() + +int main(int argc, char* argv[]) { - using namespace commons::protocol; - auto draw_msg = draw_rectangle{}; + try + { + boost::asio::io_context io_context; + if(argc == 1) + { + std::cout << "Running client\n"; + client s(io_context, boost::asio::ip::make_address("0.0.0.0"), 9000, 0); + s.init(); + io_context.run(); + } - for(int i = 0; i < 3; ++i) - { - std::cout << "Size of " << i << " is " << get_size(static_cast(i)) << "\n"; - } + if(argc == 2) + { + std::cout << "Running server\n"; + server s(io_context, 9000); + io_context.run(); + } - auto rectangle = std::make_unique(); - void* void_ptr = reinterpret_cast(rectangle.get()); + } + catch (std::exception& e) + { + std::cerr << "Exception: " << e.what() << "\n"; + } - generic_message_base* rectangle_ptr = reinterpret_cast(void_ptr); + return 0; - std::cout << "Type: " << static_cast(rectangle_ptr->get_type()) << "\n"; - std::cout << "Size: " << static_cast(rectangle_ptr->get_size()) << "\n"; - - auto* final_msg = get_object(rectangle_ptr->get_type(), rectangle_ptr); - - return 0; +// using namespace commons::protocol; +// auto draw_msg = draw_rectangle{}; +// +// for(int i = 0; i < 3; ++i) +// { +// std::cout << "Size of " << i << " is " << get_size(static_cast(i)) << "\n"; +// } +// +// auto rectangle = std::make_unique(); +// void* void_ptr = reinterpret_cast(rectangle.get()); +// +// generic_message_base* rectangle_ptr = reinterpret_cast(void_ptr); +// +// std::cout << "Type: " << static_cast(rectangle_ptr->get_type()) << "\n"; +// std::cout << "Size: " << static_cast(rectangle_ptr->get_size()) << "\n"; +// +// auto* final_msg = get_object(rectangle_ptr->get_type(), rectangle_ptr); +// +// return 0; } diff --git a/src/server.cpp b/src/server.cpp new file mode 100644 index 0000000..8573dc5 --- /dev/null +++ b/src/server.cpp @@ -0,0 +1 @@ +#include "server.hpp"