From 7470d58b135e48c1825d193783c125aa22e5bb77 Mon Sep 17 00:00:00 2001
From: Hoop77 <p.badenhoop@gmx.de>
Date: Sat, 20 Jan 2018 11:30:48 +0100
Subject: [PATCH] platoon should be standard confirm now

---
 NetworkingLib/include/Frame.h     |  5 +-
 NetworkingLib/include/Utils.h     | 21 ++++++--
 NetworkingLib/src/Socket.cpp      |  2 +-
 NetworkingLib/src/Stream.cpp      |  2 +-
 Protocol/README.md                |  6 +++
 Protocol/include/PlatoonMessage.h | 80 ++++++++++++++++++-------------
 6 files changed, 72 insertions(+), 44 deletions(-)

diff --git a/NetworkingLib/include/Frame.h b/NetworkingLib/include/Frame.h
index 26c840b1..380ed364 100644
--- a/NetworkingLib/include/Frame.h
+++ b/NetworkingLib/include/Frame.h
@@ -22,10 +22,7 @@ public:
     Frame(const std::uint8_t * data, std::uint32_t numDataBytes)
         : data(data), numDataBytes(numDataBytes)
     {
-        header[0] = utils::byte<0>(numDataBytes);
-        header[1] = utils::byte<1>(numDataBytes);
-        header[2] = utils::byte<2>(numDataBytes);
-        header[3] = utils::byte<3>(numDataBytes);
+        utils::toBigEndian<4>(header, numDataBytes);
     }
 
     Frame(const Frame &) = delete;
diff --git a/NetworkingLib/include/Utils.h b/NetworkingLib/include/Utils.h
index b4bb54cd..5635b287 100644
--- a/NetworkingLib/include/Utils.h
+++ b/NetworkingLib/include/Utils.h
@@ -12,16 +12,27 @@ namespace networking
 namespace utils
 {
 
-template<std::size_t index, typename Int>
-inline std::uint8_t byte(Int var)
-{ return (std::uint8_t) ((var >> 8*index) & 0x000000ff); }
+template<std::size_t numBytes, typename Int>
+inline void toBigEndian(std::uint8_t * dest, Int src)
+{
+    std::size_t bitsToShift = numBytes * 8;
+    for (std::size_t i = 0; i < numBytes; i++)
+    {
+        bitsToShift -= 8;
+        dest[i] = (std::uint8_t) ((src >> bitsToShift) & 0x000000ff);
+    }
+};
 
 template<std::size_t numBytes, typename Int>
-inline Int bytesToInt(const std::uint8_t * bytes)
+inline Int fromBigEndian(const std::uint8_t * bytes)
 {
     Int result = 0;
+    std::size_t bitsToShift = numBytes * 8;
     for (std::size_t i = 0; i < numBytes; i++)
-        result += ((Int) bytes[i]) << (i*8);
+    {
+        bitsToShift -= 8;
+        result += ((Int) bytes[i]) << bitsToShift;
+    }
     return result;
 }
 
diff --git a/NetworkingLib/src/Socket.cpp b/NetworkingLib/src/Socket.cpp
index 20a21e96..d21db207 100644
--- a/NetworkingLib/src/Socket.cpp
+++ b/NetworkingLib/src/Socket.cpp
@@ -16,7 +16,7 @@ bool stringFromBuffer(std::string & data, std::vector<char> & buffer, std::size_
     if (bytesTransferred < 4)
         return false;
 
-    auto numDataBytes = utils::bytesToInt<4, std::uint32_t>((const std::uint8_t *) buffer.data());
+    auto numDataBytes = utils::fromBigEndian<4, std::uint32_t>((const std::uint8_t *) buffer.data());
     if (bytesTransferred < 4 + numDataBytes)
         return false;
 
diff --git a/NetworkingLib/src/Stream.cpp b/NetworkingLib/src/Stream.cpp
index f4be80af..3884231f 100644
--- a/NetworkingLib/src/Stream.cpp
+++ b/NetworkingLib/src/Stream.cpp
@@ -23,7 +23,7 @@ std::string stringFromStreambuf(boost::asio::streambuf & streambuf, std::size_t
 std::uint32_t numDataBytesFromBuffer(boost::asio::streambuf & streambuf)
 {
     auto numDataBytesStr = stringFromStreambuf(streambuf, 4);
-    return utils::bytesToInt<4, std::uint32_t>((const std::uint8_t *) numDataBytesStr.c_str());
+    return utils::fromBigEndian<4, std::uint32_t>((const std::uint8_t *) numDataBytesStr.c_str());
 }
 
 std::size_t getNumRemainingBytes(std::size_t numBytesTransferred, std::uint32_t numDataBytes)
diff --git a/Protocol/README.md b/Protocol/README.md
index 22d71294..69ada00b 100644
--- a/Protocol/README.md
+++ b/Protocol/README.md
@@ -16,6 +16,9 @@ Here we suppose to run a platoon as leader:
 networking::Networking net;
 // Create a leader.
 auto leader = protocol::LeaderVehicle::create(net, 1);  // 1 = vehicleId
+// Add endpoints which we may request a platoon to create with.
+leader->addVehicleEndpoint(2, "192.168.100.30);
+leader->addVehicleEndpoint(3, "192.168.134.5);
 // Set the initial platoon configuration.
 // This can be set at anytime and will be send to the following vehicles.
 leader->setPlatoonConfig(protocol::PlatoonConfig{10.0f, 20.0f});
@@ -35,6 +38,9 @@ And on another machine, we're running a follower:
 networking::Networking net;
 // Create a leader.
 auto follower = protocol::FollowerVehicle::create(net, 2);  // 2 = vehicleId
+// Add endpoints which we may request a platoon to create with.
+follower->addVehicleEndpoint(2, "192.168.100.30);
+follower->addVehicleEndpoint(3, "192.168.134.5);
 // Register a callback to receive platoon configuration updates (ps and ipd).
 follower->setOnUpdatePlatoonConfigCallback(
     [](const protocol::PlatoonConfig & config){/* Received updated platoonConfig. */});
diff --git a/Protocol/include/PlatoonMessage.h b/Protocol/include/PlatoonMessage.h
index eb4777ae..86c1268e 100644
--- a/Protocol/include/PlatoonMessage.h
+++ b/Protocol/include/PlatoonMessage.h
@@ -10,12 +10,14 @@
 #include "Protocol.h"
 #include "json.hpp"
 #include <NetworkingLib/Message.h>
+#include <unordered_set>
 
 namespace protocol
 {
 
 namespace messageTypes
 {
+
 constexpr MessageType LV_BROADCAST = 0x00000001;
 constexpr MessageType FV_HEARTBEAT = 0x00000002;
 constexpr MessageType LV_REQUEST = 0x00000004;
@@ -23,11 +25,20 @@ constexpr MessageType FV_REQUEST = 0x00000008;
 constexpr MessageType ACCEPT_RESPONSE = 0x00000010;
 constexpr MessageType REJECT_RESPONSE = 0x00000020;
 constexpr MessageType LEAVE_PLATOON = 0x00000040;
+
+const std::unordered_set<MessageType> standardMessageTypes{
+    LV_BROADCAST, FV_HEARTBEAT, LV_REQUEST, FV_REQUEST, ACCEPT_RESPONSE, REJECT_RESPONSE, LEAVE_PLATOON};
+
+inline bool isStandardMessageType(MessageType messageType)
+{
+    return messageTypes::standardMessageTypes.find(messageType) != messageTypes::standardMessageTypes.end();
+}
+
 }
 
 struct PlatoonMessage
 {
-    static constexpr std::size_t MAX_SIZE = 512;
+    static constexpr std::size_t MAX_SIZE = 256;
 
     PlatoonMessage()
     {}
@@ -75,31 +86,6 @@ struct PlatoonMessage
     PlatoonSpeed platoonSpeed;
     InnerPlatoonDistance innerPlatoonDistance;
 };
-}
-
-namespace nlohmann
-{
-
-template<>
-struct adl_serializer<protocol::PlatoonMessage>
-{
-    static void to_json(json & j, const protocol::PlatoonMessage & message)
-    {
-        j = json{{"vehicleId",            message.vehicleId},
-                 {"platoonId",            message.platoonId},
-                 {"platoonSpeed",         message.platoonSpeed},
-                 {"innerPlatoonDistance", message.innerPlatoonDistance}};
-    }
-
-    static void from_json(const json & j, protocol::PlatoonMessage & message)
-    {
-        using namespace protocol;
-        message.vehicleId = j.at("vehicleId").get<VehicleId>();
-        message.platoonId = j.at("platoonId").get<PlatoonId>();
-        message.platoonSpeed = j.at("platoonSpeed").get<PlatoonSpeed>();
-        message.innerPlatoonDistance = j.at("innerPlatoonDistance").get<InnerPlatoonDistance>();
-    }
-};
 
 }
 
@@ -116,15 +102,29 @@ struct Encoder<protocol::PlatoonMessage>
         using namespace protocol;
 
         auto messageType = message.messageType;
+
+        if (!messageTypes::isStandardMessageType(messageType))
+            throw 0;    // Throw something to signal a failed encoding.
+
         // 4 bytes for message type
         data = std::string(4, '\0');
-        data[0] = networking::utils::byte<0>(messageType);
-        data[1] = networking::utils::byte<1>(messageType);
-        data[2] = networking::utils::byte<2>(messageType);
-        data[3] = networking::utils::byte<3>(messageType);
+
+        std::uint8_t numDataBytes[sizeof(MessageType)];
+        networking::utils::toBigEndian<4>(numDataBytes, messageType);
+
+        for (std::size_t i = 0; i < sizeof(MessageType); i++)
+            data[i] = numDataBytes[i];
 
         using json = nlohmann::json;
-        json j = message;
+        auto j = json{{"vehicleId", message.vehicleId},
+                      {"platoonId", message.platoonId}};
+
+        if (messageType == messageTypes::LV_BROADCAST)
+        {
+            j["ps"] = message.platoonSpeed;
+            j["ipd"] = message.innerPlatoonDistance;
+        }
+
         data.append(j.dump());
     }
 };
@@ -141,9 +141,23 @@ struct Decoder<protocol::PlatoonMessage>
 
         using json = nlohmann::json;
         auto j = json::parse(data.begin() + sizeof(MessageType), data.end());
-        message = j;
-        message.messageType = networking::utils::bytesToInt<sizeof(MessageType), MessageType>(
+
+        auto messageType = networking::utils::fromBigEndian<sizeof(MessageType), MessageType>(
             (const std::uint8_t *) data.c_str());
+
+        // We only know message types conforming to the standard protocol specification.
+        if (!messageTypes::isStandardMessageType(messageType))
+            throw 0;
+
+        message.messageType = messageType;
+        message.vehicleId = j.at("vehicleId").get<VehicleId>();
+        message.platoonId = j.at("platoonId").get<PlatoonId>();
+
+        if (messageType == messageTypes::LV_BROADCAST)
+        {
+            message.platoonSpeed = j.at("ps").get<PlatoonSpeed>();
+            message.innerPlatoonDistance = j.at("ipd").get<InnerPlatoonDistance>();
+        }
     };
 };
 
-- 
GitLab