This commit is contained in:
milek7
2018-12-03 23:12:33 +01:00
parent 18ad14bc53
commit f525a77e23
13 changed files with 386 additions and 5 deletions

View File

@@ -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()

View File

@@ -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.

3
Logs.h
View File

@@ -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 );

View File

@@ -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;
}

View File

@@ -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<GLFWwindow *> m_windows;
std::optional<network::manager> m_network;
};
extern eu07_application Application;

12
network/manager.cpp Normal file
View File

@@ -0,0 +1,12 @@
#include "network/manager.h"
#include "network/tcp.h"
network::manager::manager()
{
servers.emplace_back(std::make_shared<tcp_server>(io_context));
}
void network::manager::poll()
{
io_context.poll();
}

18
network/manager.h Normal file
View File

@@ -0,0 +1,18 @@
#pragma once
#include <asio.hpp>
#include <memory>
#include "network/network.h"
namespace network
{
class manager
{
asio::io_context io_context;
std::vector<std::shared_ptr<server>> servers;
public:
manager();
void poll();
};
}

18
network/message.cpp Normal file
View File

@@ -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});
}

23
network/message.h Normal file
View File

@@ -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);
};
}

18
network/network.cpp Normal file
View File

@@ -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)
{
}

29
network/network.h Normal file
View File

@@ -0,0 +1,29 @@
#pragma once
#include <asio.hpp>
#include <memory>
#include <functional>
#include <optional>
#include "network/message.h"
namespace network
{
class connection : public std::enable_shared_from_this<connection>
{
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<std::shared_ptr<connection>> clients;
};
}

111
network/tcp.cpp Normal file
View File

@@ -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<tcp_conn> conn = std::make_shared<tcp_conn>(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<tcp_conn> 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();
}

45
network/tcp.h Normal file
View File

@@ -0,0 +1,45 @@
#pragma once
#include <asio.hpp>
#include <memory>
#include <array>
#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<tcp_conn> conn, const asio::error_code &err);
asio::ip::tcp::acceptor m_acceptor;
};
}