Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Asio C++ Networking clients and Message structure #41

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Protobuf/updateProtos.bat
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ SET flightComputerSrc="..\Subsurface\FlightComputer\src"

SET PDS="..\OnLand\PDS"
SET FLASK="..\OnLand\ControlLaptop"
SET TESTTOOLS="..\Subsurface\FlightComputer\tools\net_servers"

REM Force copy the files, replacing existing ones
REM /Y - Suppress confirm prompt
Expand All @@ -40,5 +41,7 @@ COPY /Y Paradigm\cpp\*.pb.cc %flightComputerSrc%

COPY /Y Paradigm\py\* %PDS%
COPY /Y Paradigm\py\* %FLASK%
COPY /Y Paradigm\py\* %TESTTOOLS%


echo Proto Update Complete
2 changes: 2 additions & 0 deletions Protobuf/updateProtos.sh
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,14 @@ flightComputerSrc="../Subsurface/FlightComputer/src"

PDS="../OnLand/PDS"
FLASK="../OnLand/ControlLaptop"
TESTTOOLS="..\Subsurface\FlightComputer\tools\net_servers"

# Force copy the files, replacing existing ones
cp -f Paradigm/cpp/*.pb.h $flightComputer
cp -f Paradigm/cpp/*.pb.cc $flightComputerSrc

cp -f Paradigm/py/* $PDS
cp -f Paradigm/py/* $FLASK
cp -f Paradigm/py/* $TESTTOOLS

echo "Proto Update Complete"
25 changes: 18 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,25 @@ Prerequisites:
- Windows - Visual Studio 2019 cl.exe should work fine
- Note: Ensure that C++ Cmake tools for Windows is installed along with Desktop development with C++

Compiling Protobuf:
- Unfortunately compiling protobuf and getting it to link properly can be a bit of a pain, so these instructions are a bit more manual for now
- On Windows:
- The easiest way to install is to use the vcpkg package manager for C++ libraries to install protobuf and the protoc compiler. The instructions [here](https://github.com/microsoft/vcpkg#quick-start-windows) shows you how to install vcpkg, and the instructions [here](https://github.com/protocolbuffers/protobuf/blob/master/src/README.md) under the header "C++ Installation - Windows" will show you how to install the packages under vcpkg.
- Note that when cmake is invoked for the FlightComputer project, the cmake toolchain file will have to be set so that protobuf is found
- As well, the protoc compiler binary will have to be added to the system PATH, which can be done by adding the path to the folder where vcpkg has installed protoc to the PATH variable, as shown [here](https://www.architectryan.com/2018/03/17/add-to-the-path-on-windows-10/)
- On Linux/MacOS:
- The Unix build instructions [here](https://github.com/protocolbuffers/protobuf/blob/master/src/README.md) can be used to build from source, just clone the repo somewhere locally and then follow the instructions. If all goes well, protobuf libraries and includes should be added to the proper directories under /usr/local, and protoc should be invokable from the terminal.

Setup:
1. In a command prompt (Windows)/terminal (MacOS/Linux), navigate to `comp1-software/Subsurface/FlightComputer`
2. Make a build directory, and enter it
3. Building for Raspberry pi:
Invoke cmake using `cmake -DCMAKE_TOOLCHAIN_FILE=../arm-linux-gnueabihf-gcc.cmake ..`, this should automatically find the cross compiler (assuming it has been added to your PATH), and generate a Makefile.
Building for everything else:
Invoke cmake using `cmake ..`, this should generate a Visual Studio Solution (Windows), or a Makefile (MacOS/Linux)
4. On Windows: Open the .sln file in Visual Studio, and in the solution explorer set the FlightComputer project as the startup project (right click, "set as startup project"), then build and run.
1. In a command prompt (Windows)/terminal (MacOS/Linux), navigate to `comp1-software/Protobuf`
2. On Windows, run `updateProtos.bat`, and on MacOS/Linux run `updateProtos.sh`. This will compiler the sample `Paradigm.proto` and copy the source files to the correct directories.
3. Navigate to `comp1-software/Subsurface/FlightComputer`
4. Make a build directory, and enter it
5. Building for Raspberry pi:
- Invoke cmake using `cmake -DCMAKE_TOOLCHAIN_FILE=../arm-linux-gnueabihf-gcc.cmake ..`, this should automatically find the cross compiler (assuming it has been added to your PATH), and generate a Makefile.
- Building for Windows: Invoke cmake using `cmake -DCMAKE_TOOLCHAIN_FILE=<path-to-vcpkg.cmake> ..`, this will ensure that the protobuf libraries are picked up correctly.
- Building for MacOS/Linux: Invoke cmake using `cmake ..`, this should generate a Makefile (MacOS/Linux)
6. On Windows: Open the .sln file in Visual Studio, and in the solution explorer set the FlightComputer project as the startup project (right click, "set as startup project"), then build and run.
On Linux/MacOS/Arm64 Linux: Run `make`, and this should build the project, and then run the executable with `./FlightComputer`


Expand Down
27 changes: 27 additions & 0 deletions Subsurface/FlightComputer/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,50 @@ project(FlightComputer)

set(CMAKE_CXX_STANDARD 17)

if (WIN32)
# Get Protobuf Library
find_package(Protobuf CONFIG REQUIRED)
else ()
set(Protobuf_INCLUDE_DIR /usr/local/include)
set(Protobuf_LIBRARIES /usr/local/lib/libprotobuf.a)
endif (WIN32)

include_directories(${Protobuf_INCLUDE_DIR})

include_directories(vendors/asio-1.18.0/include)
include_directories(vendors/EasyLogger)
include_directories(include)
include_directories(src)

set(HEADERS
include/FlightComputer.h
include/Message.h
include/NetClient.h
include/Paradigm.pb.h
)

set(SOURCES
src/Paradigm.pb.cc
src/FlightComputer.cpp
vendors/EasyLogger/easylogging++.cc
)

find_package(Threads REQUIRED)

include_directories(${CMAKE_CURRENT_BINARY_DIR})

if (WIN32)
add_executable(FlightComputer ${SOURCES} ${HEADERS})
target_compile_definitions(FlightComputer PUBLIC _WIN32_WINNT=0x0601)
target_compile_definitions(FlightComputer PUBLIC ELPP_WINSOCK2)
else ()
add_executable(FlightComputer ${SOURCES})
endif (WIN32)

target_include_directories(FlightComputer PRIVATE ${CMAKE_BINARY_DIR})

if (WIN32)
target_link_libraries(FlightComputer protobuf::libprotobuf)
else ()
target_link_Libraries(FlightComputer ${Protobuf_LIBRARIES} Threads::Threads)
endif (WIN32)
27 changes: 16 additions & 11 deletions Subsurface/FlightComputer/Tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,32 @@ include_directories(../vendors/proto/include)
include_directories(../include)
include_directories(../src)

set(Proto_Root ${CMAKE_SOURCE_DIR}/../vendors/proto)
if (WIN32)
# Get Protobuf Library
find_package(Protobuf CONFIG REQUIRED)
else ()
set(Protobuf_INCLUDE_DIR /usr/local/include)
set(Protobuf_LIBRARIES /usr/local/lib/libprotobuf.a)
endif (WIN32)

file(GLOB_RECURSE PROTO_SOURCES ../src/*.pb.cc)
file(GLOB_RECURSE HEADERS ../include/*.h ../include/*.hpp ../include/*.pb.h)

set(SOURCES
FlightComputerTest.cpp
../vendors/EasyLogger/easylogging++.cc
)

include_directories(${CMAKE_CURRENT_BINARY_DIR})

add_executable(FlightComputerTest ${SOURCES})
add_executable(FlightComputerTest ${SOURCES} ${PROTO_SOURCES} ${HEADERS} FlightComputerTest.cpp catch.hpp)

target_compile_definitions(FlightComputerTest PUBLIC _WIN32_WINNT=0x0601)
target_compile_definitions(FlightComputerTest PUBLIC ELPP_WINSOCK2)

target_include_directories(FlightComputerTest PRIVATE ${CMAKE_BINARY_DIR})

if (WIN32)
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
set_property(TARGET FlightComputerTest PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreadedDebug")
target_link_libraries(FlightComputerTest ${Proto_Root}/windows/Debug/libprotobuf-lited.lib)
else ()
set_property(TARGET FlightComputerTest PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded")
target_link_libraries(FlightComputerTest ${Proto_Root}/windows/Release/libprotobuf-lite.lib)
endif ()
target_link_libraries(FlightComputerTest protobuf::libprotobuf)
else ()
target_link_libraries(FlightComputerTest ${Proto_Root}/linux/libprotobuf-lite.a)
target_link_libraries(FlightComputerTest ${Protobuf_LIBRARIES} Threads::Threads)
endif (WIN32)
40 changes: 35 additions & 5 deletions Subsurface/FlightComputer/Tests/FlightComputerTest.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,40 @@
#define CATCH_CONFIG_MAIN
#include "catch.hpp"

TEST_CASE("This is a test unit test")
#include "Message.h"
#include "Paradigm.pb.h"

#include "easylogging++.h"
#include <iostream>
#include <vector>

INITIALIZE_EASYLOGGINGPP

TEST_CASE("Check that sizes are correct in message struct")
{
SECTION("This is a test section")
{
REQUIRE(true == true);
}
Person person;
person.set_name("Daniel Burke");
person.set_email("[email protected]");
auto serialized = person.SerializeAsString();
char size[5];
sprintf(size, "%4d", static_cast<uint32_t>(serialized.length()));

Message<Person> message(person);

SECTION("Check sizes are equal")
{
REQUIRE(serialized.size() == message.bodyLength());
REQUIRE(serialized.size() + sizeof(uint32_t) == message.length());
}

SECTION("Check contents are equal")
{
REQUIRE(*(serialized.data()) == *(message.body()));
}

SECTION("Check that protobuf is deserialized correctly")
{
Person person1;
REQUIRE(message.deserialize(person1) == true);
}
}
3 changes: 2 additions & 1 deletion Subsurface/FlightComputer/include/FlightComputer.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#ifndef FLIGHTCOMPUTER_H
#define FLIGHTCOMPUTER_H


#define FLIGHTCOMPUTER_H
#endif
74 changes: 74 additions & 0 deletions Subsurface/FlightComputer/include/Message.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#pragma once

#include <cstdint>
#include <cstring>
#include <string>
#include <vector>

// Template parameter must be a protobuf message

template<typename Protobuf>
class Message
{
public:
static constexpr int headerLength = sizeof(uint32_t);
static constexpr int maxBodyLength = 1024;

Message()
: m_bodyLength(0)
{
m_data.resize(256);
}

Message(const Protobuf& message)
{
m_data.resize(256);
serialize(message);
}

Message(const Message&) = default;

std::size_t length() const { return headerLength + m_bodyLength; }

const char* data() const { return m_data.data(); }
char* data() { return m_data.data(); }

std::size_t bodyLength() const { return m_bodyLength; }

const char* body() const { return m_data.data() + headerLength; }
char* body() { return m_data.data() + headerLength; }

bool decodeHeader()
{
std::memcpy(&m_bodyLength, m_data.data(), headerLength);
if (m_bodyLength > maxBodyLength)
{
m_bodyLength = 0;
return false;
}
return true;
}

bool serialize(const Protobuf& message)
{
std::string serialized;
bool success = message.SerializeToString(&serialized);
m_bodyLength = serialized.length();

std::memcpy(m_data.data(), &m_bodyLength, sizeof(m_bodyLength));

m_data.resize(headerLength + m_bodyLength);
std::memcpy(m_data.data() + headerLength, serialized.data(), serialized.length());

return success;
}

bool deserialize(Protobuf& message) const
{
return message.ParseFromString(std::string(body(), body() + bodyLength()));
}

private:
std::vector<char> m_data;
std::size_t m_bodyLength;
};
Loading