From f525a77e23f1b9f952c63b9ed6178bdb3479a51f Mon Sep 17 00:00:00 2001 From: milek7 Date: Mon, 3 Dec 2018 23:12:33 +0100 Subject: [PATCH] work --- CMakeLists.txt | 30 ++++++++-- CMake_modules/FindASIO.cmake | 70 ++++++++++++++++++++++ Logs.h | 3 +- application.cpp | 10 ++++ application.h | 4 ++ network/manager.cpp | 12 ++++ network/manager.h | 18 ++++++ network/message.cpp | 18 ++++++ network/message.h | 23 ++++++++ network/network.cpp | 18 ++++++ network/network.h | 29 +++++++++ network/tcp.cpp | 111 +++++++++++++++++++++++++++++++++++ network/tcp.h | 45 ++++++++++++++ 13 files changed, 386 insertions(+), 5 deletions(-) create mode 100644 CMake_modules/FindASIO.cmake create mode 100644 network/manager.cpp create mode 100644 network/manager.h create mode 100644 network/message.cpp create mode 100644 network/message.h create mode 100644 network/network.cpp create mode 100644 network/network.h create mode 100644 network/tcp.cpp create mode 100644 network/tcp.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 13c3dbc6..c543bf71 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,13 +1,28 @@ cmake_minimum_required(VERSION 3.0) +if(POLICY CMP0058) + cmake_policy(SET CMP0058 NEW) +endif() +if(POLICY CMP0074) + cmake_policy(SET CMP0074 NEW) +endif() + set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/CMake_modules/") -#include(PrecompiledHeader) include(cotire) set(DEPS_DIR ${DEPS_DIR} "${CMAKE_SOURCE_DIR}/ref") project("eu07") set(CMAKE_CXX_STANDARD 17) -include_directories("." "Console" "McZapkie" "gl" "ref/glad/include") -file(GLOB HEADERS "*.h" "Console/*.h" "McZapkie/*.h" "gl/*.h") +include_directories("." +"Console" +"McZapkie" +"gl" +"ref/glad/include") + +file(GLOB HEADERS "*.h" +"Console/*.h" +"McZapkie/*.h" +"gl/*.h" +"network/*.h") set(SOURCES "Texture.cpp" @@ -98,6 +113,11 @@ set(SOURCES "texturewindow.cpp" "map.cpp" +"network/network.cpp" +"network/message.cpp" +"network/tcp.cpp" +"network/manager.cpp" + "ref/glad/src/glad.c" "gl/shader.cpp" @@ -173,7 +193,6 @@ add_executable(${PROJECT_NAME} ${SOURCES} ${HEADERS}) set_target_properties(${PROJECT_NAME} PROPERTIES COTIRE_CXX_PREFIX_HEADER_INIT "stdafx.h") set_target_properties(${PROJECT_NAME} PROPERTIES COTIRE_ADD_UNITY_BUILD FALSE) cotire(${PROJECT_NAME}) -#add_precompiled_header(${PROJECT_NAME} stdafx.h FORCEINCLUDE SOURCE_CXX stdafx.cpp) if (${CMAKE_CXX_COMPILER_ID} STREQUAL MSVC) # /wd4996: disable "deprecation" warnings @@ -229,6 +248,9 @@ find_package(libserialport REQUIRED) include_directories(${libserialport_INCLUDE_DIR}) target_link_libraries(${PROJECT_NAME} ${libserialport_LIBRARY}) +find_package(ASIO REQUIRED) +target_link_libraries(${PROJECT_NAME} ASIO::ASIO) + if (WIN32) target_link_libraries(${PROJECT_NAME} ws2_32) endif() diff --git a/CMake_modules/FindASIO.cmake b/CMake_modules/FindASIO.cmake new file mode 100644 index 00000000..6b986cc0 --- /dev/null +++ b/CMake_modules/FindASIO.cmake @@ -0,0 +1,70 @@ +#@PURPOSE: Provide access to Chris Kohlhoff's ASIO library. +# +#@TARGETS: +# ASIO::ASIO Chris Kohlhoff's ASIO library +# +#@DESCRIPTION: This module produces a single target 'ASIO::ASIO', that can be +# used to link to the asio library. The behavior of this module is undefined +# unless the asio library is in '../../asio' relative to this file. +# +# The 'asio' target generated by this module uses the "standalone" version of +# asio in that it doesn't depend on any Boost libraries. + +set(ASIO_FOUND FALSE) + +if(TARGET ASIO::ASIO) + set(ASIO_FOUND TRUE) +else() + find_package(Threads QUIET) + if(NOT Threads_FOUND) + if(ASIO_FIND_REQUIRED) + message(FATAL_ERROR "ASIO requires thread support, but it wasn't found.") + else() + if(ASIO_FIND_QUIETLY) + message(STATUS "ASIO requires thread support, but it wasn't found.") + endif() + endif() + else() + find_path(ASIO_ROOT include/asio.hpp + PATHS + # Where asio lives relative to it's official repository + ${CMAKE_CURRENT_LIST_DIR}/../../asio/asio + + # Where asio should live + ${CMAKE_CURRENT_LIST_DIR}/../../asio + ) + if(NOT ASIO_ROOT) + if(ASIO_FIND_REQUIRED) + message(FATAL_ERROR "ASIO headers could not be found.") + else() + if(ASIO_FIND_QUIETLY) + message(STATUS "ASIO headers could not be found.") + endif() + endif() + else() + add_library(ASIO::ASIO INTERFACE IMPORTED GLOBAL) + set_target_properties(ASIO::ASIO PROPERTIES + INTERFACE_COMPILE_DEFINITIONS "ASIO_STANDALONE" + INTERFACE_INCLUDE_DIRECTORIES "${ASIO_ROOT}/include" + ) + target_link_libraries(ASIO::ASIO INTERFACE Threads::Threads) + set(ASIO_FOUND TRUE) + endif() + endif() +endif() + +# ---------------------------------------------------------------------------- +# Copyright 2017 Bloomberg Finance L.P. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + diff --git a/Logs.h b/Logs.h index 9a846db4..9edab21f 100644 --- a/Logs.h +++ b/Logs.h @@ -17,7 +17,8 @@ enum class logtype : unsigned int { texture = ( 1 << 3 ), lua = ( 1 << 4 ), material = ( 1 << 5 ), - shader = (1 << 6 ) + shader = (1 << 6 ), + net = (1 << 7) }; void WriteLog( const char *str, logtype const Type = logtype::generic ); diff --git a/application.cpp b/application.cpp index 0741aa00..1d668550 100644 --- a/application.cpp +++ b/application.cpp @@ -138,6 +138,9 @@ eu07_application::init( int Argc, char *Argv[] ) { return result; } + if (!init_network()) + return -1; + return result; } @@ -173,6 +176,8 @@ eu07_application::run() { } Timer::subsystem.mainloop_total.stop(); + + m_network->poll(); } return 0; @@ -585,3 +590,8 @@ eu07_application::init_modes() { return 0; } + +bool eu07_application::init_network() { + m_network.emplace(); + return true; +} diff --git a/application.h b/application.h index 81dce2a2..b24da297 100644 --- a/application.h +++ b/application.h @@ -11,6 +11,7 @@ http://mozilla.org/MPL/2.0/. #include "applicationmode.h" #include "PyInt.h" +#include "network/manager.h" class eu07_application { @@ -89,6 +90,7 @@ private: int init_gfx(); int init_audio(); int init_modes(); + bool init_network(); // members bool m_screenshot_queued = false; @@ -97,6 +99,8 @@ private: mode_stack m_modestack; // current behaviour mode python_taskqueue m_taskqueue; std::vector m_windows; + + std::optional m_network; }; extern eu07_application Application; diff --git a/network/manager.cpp b/network/manager.cpp new file mode 100644 index 00000000..9f99529c --- /dev/null +++ b/network/manager.cpp @@ -0,0 +1,12 @@ +#include "network/manager.h" +#include "network/tcp.h" + +network::manager::manager() +{ + servers.emplace_back(std::make_shared(io_context)); +} + +void network::manager::poll() +{ + io_context.poll(); +} diff --git a/network/manager.h b/network/manager.h new file mode 100644 index 00000000..d76464f3 --- /dev/null +++ b/network/manager.h @@ -0,0 +1,18 @@ +#pragma once +#include +#include +#include "network/network.h" + +namespace network +{ + class manager + { + asio::io_context io_context; + std::vector> servers; + + public: + manager(); + + void poll(); + }; +} diff --git a/network/message.cpp b/network/message.cpp new file mode 100644 index 00000000..f8f42378 --- /dev/null +++ b/network/message.cpp @@ -0,0 +1,18 @@ +#include "network/message.h" +#include "sn_utils.h" + +void network::message::serialize(std::ostream &stream) +{ + sn_utils::ls_uint16(stream, (uint16_t)type); +} + +network::message network::message::deserialize(std::istream &stream) +{ + type_e type = (type_e)sn_utils::ld_uint16(stream); + if ((int)type > (int)message::TYPE_MAX) + { + type = message::TYPE_MAX; + } + + return message({type}); +} diff --git a/network/message.h b/network/message.h new file mode 100644 index 00000000..3b365db9 --- /dev/null +++ b/network/message.h @@ -0,0 +1,23 @@ +#pragma once +#include "network/message.h" + +namespace network +{ + struct message + { + enum type_e + { + CONNECT_REQUEST = 0, + CONNECT_ACCEPT, + STEP_INFO, + VEHICLE_COMMAND, + TYPE_MAX + }; + + type_e type; + + void serialize(std::ostream &stream); + + static message deserialize(std::istream &stream); + }; +} diff --git a/network/network.cpp b/network/network.cpp new file mode 100644 index 00000000..9be157c8 --- /dev/null +++ b/network/network.cpp @@ -0,0 +1,18 @@ +#include "network/network.h" +#include "network/message.h" +#include "Logs.h" + +void network::connection::connected() +{ + WriteLog("net: socket connected", logtype::net); +} + +void network::connection::message_received(message msg) +{ + +} + +void network::connection::data_received(uint8_t *buffer, size_t len) +{ + +} diff --git a/network/network.h b/network/network.h new file mode 100644 index 00000000..eebb0d6b --- /dev/null +++ b/network/network.h @@ -0,0 +1,29 @@ +#pragma once +#include +#include +#include +#include +#include "network/message.h" + +namespace network +{ + class connection : public std::enable_shared_from_this + { + private: + void message_received(message msg); + + protected: + virtual void disconnect() = 0; + virtual void send_data(uint8_t *buffer, size_t len) = 0; + void data_received(uint8_t *buffer, size_t len); + + public: + virtual void connected(); + }; + + class server + { + protected: + std::vector> clients; + }; +} diff --git a/network/tcp.cpp b/network/tcp.cpp new file mode 100644 index 00000000..ce028f18 --- /dev/null +++ b/network/tcp.cpp @@ -0,0 +1,111 @@ +#include "network/tcp.h" +#include "Logs.h" +#include "sn_utils.h" + +network::tcp_conn::tcp_conn(asio::io_context &io_ctx) + : m_socket(io_ctx) +{ + m_header_buffer.resize(12); +} + +void network::tcp_conn::disconnect() +{ + m_socket.close(); +} + +void network::tcp_conn::connected() +{ + read_header(); +} + +void network::tcp_conn::read_header() +{ + asio::async_read(m_socket, asio::buffer(m_header_buffer), + std::bind(&tcp_conn::handle_header, this, std::placeholders::_1)); +} + +void network::tcp_conn::send_data(uint8_t *buffer, size_t len) +{ + +} + +void network::tcp_conn::handle_header(const asio::error_code &err) +{ + std::istringstream header(m_header_buffer); + uint32_t sig = sn_utils::ld_uint32(header); + if (sig != 0x37305545) + { + disconnect(); + return; + } + + uint32_t len = sn_utils::ld_uint32(header); + m_body_buffer.resize(len); + if (len > 10000) + { + disconnect(); + return; + } + + asio::async_read(m_socket, asio::buffer(m_body_buffer), + std::bind(&tcp_conn::handle_data, this, std::placeholders::_1)); +} + +void network::tcp_conn::handle_data(const asio::error_code &err) +{ + std::istringstream body(m_body_buffer); + message msg = message::deserialize(body); + + if (msg.type == message::TYPE_MAX) + { + disconnect(); + return; + } + + if (msg.type == message::CONNECT_REQUEST) + { + message reply({message::CONNECT_ACCEPT}); + + std::string reply_buf; + std::ostringstream stream(reply_buf); + reply.serialize(stream); + } + + read_header(); +} + +asio::ip::tcp::socket& network::tcp_conn::socket() +{ + return m_socket; +} + +network::tcp_server::tcp_server(asio::io_context &io_ctx) + : m_acceptor(io_ctx, asio::ip::tcp::endpoint(asio::ip::tcp::v6(), 7424)) +{ + asio::ip::v6_only v6_only(false); + m_acceptor.set_option(v6_only); + + accept_conn(); +} + +void network::tcp_server::accept_conn() +{ + std::shared_ptr conn = std::make_shared(m_acceptor.get_executor().context()); + + m_acceptor.async_accept(conn->socket(), std::bind(&tcp_server::handle_accept, this, conn, std::placeholders::_1)); +} + +void network::tcp_server::handle_accept(std::shared_ptr conn, const asio::error_code &err) +{ + if (!err) + { + clients.emplace_back(conn); + conn->connected(); + } + else + { + WriteLog(std::string("net: failed to accept client: " + err.message()), logtype::net); + } + + accept_conn(); +} diff --git a/network/tcp.h b/network/tcp.h new file mode 100644 index 00000000..d49efc96 --- /dev/null +++ b/network/tcp.h @@ -0,0 +1,45 @@ +#pragma once + +#include +#include +#include +#include "network/network.h" + +namespace network +{ + class tcp_conn + : public connection + { + private: + asio::ip::tcp::socket m_socket; + + std::string m_header_buffer; + std::string m_body_buffer; + + void read_header(); + void handle_header(const asio::error_code &err); + void handle_data(const asio::error_code &err); + + protected: + void disconnect() override; + void send_data(uint8_t *buffer, size_t len) override; + + public: + tcp_conn(asio::io_context &io_ctx); + asio::ip::tcp::socket& socket(); + + void connected() override; + }; + + class tcp_server : public server + { + public: + tcp_server(asio::io_context &io_ctx); + + private: + void accept_conn(); + void handle_accept(std::shared_ptr conn, const asio::error_code &err); + + asio::ip::tcp::acceptor m_acceptor; + }; +}