mirror of https://github.com/infosecn1nja/C3.git
Merge branch 'master' into PerformanceUpgrades
commit
89ffafa210
|
@ -83,7 +83,6 @@ size_t MWR::C3::Interfaces::Channels::UncShareFile::OnSendToChannel(ByteView dat
|
|||
}
|
||||
std::filesystem::rename(tmpFilePath, filePath);
|
||||
|
||||
Log({ OBF("OnSend() called for UncShareFile carrying ") + std::to_string(data.size()) + OBF(" bytes"), LogMessage::Severity::DebugInformation });
|
||||
return data.size();
|
||||
}
|
||||
catch (std::exception& exception)
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
namespace MWR::C3
|
||||
{
|
||||
|
||||
/// Template class handling registration of Interface before main function.
|
||||
/// @tparam Iface. Interface to be registered.
|
||||
template <typename Iface, typename AbstractType, HashT clousureConnectorHash = 0>
|
||||
|
@ -43,21 +42,7 @@ namespace MWR::C3
|
|||
template <>
|
||||
static std::string GetCapability<false>()
|
||||
{
|
||||
return R"_(
|
||||
{
|
||||
"create":
|
||||
{
|
||||
"arguments":
|
||||
[
|
||||
{
|
||||
"type": "binary",
|
||||
"description": "Blob of data that will be provided to Channel constructor.",
|
||||
"name": "arguments"
|
||||
}
|
||||
]
|
||||
},
|
||||
"commands": []
|
||||
})_";
|
||||
return "{}";
|
||||
}
|
||||
|
||||
template <>
|
||||
|
@ -104,128 +89,131 @@ namespace MWR::C3
|
|||
constexpr HashT Register<T, T2, u32>::s_InterfaceHash = Hash::Fnv1aType<T>();
|
||||
#pragma warning( pop )
|
||||
|
||||
/// Specialization of Registration mechanism for Channel type Interface.
|
||||
template <typename Iface>
|
||||
class Channel : public Register<Iface, AbstractChannel>
|
||||
namespace Interfaces
|
||||
{
|
||||
public:
|
||||
constexpr static std::chrono::milliseconds s_MinUpdateFrequency = 30ms;
|
||||
constexpr static std::chrono::milliseconds s_MaxUpdateFrequency = 30ms;
|
||||
|
||||
/// Constructor setting default update frequency for channel
|
||||
Channel()
|
||||
/// Specialization of Registration mechanism for Channel type Interface.
|
||||
template <typename Iface>
|
||||
class Channel : public Register<Iface, AbstractChannel>
|
||||
{
|
||||
static_assert(Iface::s_MinUpdateFrequency >= 30ms && Iface::s_MinUpdateFrequency <= Iface::s_MaxUpdateFrequency, "The frequency is set incorrectly");
|
||||
m_MinUpdateFrequency = Iface::s_MinUpdateFrequency;
|
||||
m_MaxUpdateFrequency = Iface::s_MaxUpdateFrequency;
|
||||
}
|
||||
public:
|
||||
constexpr static std::chrono::milliseconds s_MinUpdateFrequency = 30ms;
|
||||
constexpr static std::chrono::milliseconds s_MaxUpdateFrequency = 30ms;
|
||||
|
||||
/// Callback that is periodically called for every Device to update itself.
|
||||
/// This is point where dynamic polymorphisms is replaced by static one with recognition of returned value.
|
||||
/// Types using Channel CRTP should implement MWR::ByteVector OnReceiveFromChannel(), or std::vector<MWR::ByteVector> OnReceiveFromChannel()
|
||||
/// @return std::vector<ByteVector> that contains all packets retrieved from Channel.
|
||||
std::vector<ByteVector> OnReceiveFromChannelInternal() override final
|
||||
{
|
||||
static_assert(CanRecive<>::value, "OnReceiveFromChannel is not implemented");
|
||||
static_assert(std::is_same_v<ReceiveReturnType<Iface>, ByteVector> || std::is_same_v<ReceiveReturnType<Iface>, std::vector<ByteVector>>, "OnReceiveFromChannel should return ByteVector or std::vector<ByteVector>");
|
||||
return ReceiveWrapper<Iface>();
|
||||
}
|
||||
/// Constructor setting default update frequency for channel
|
||||
Channel()
|
||||
{
|
||||
static_assert(Iface::s_MinUpdateFrequency >= 30ms && Iface::s_MinUpdateFrequency <= Iface::s_MaxUpdateFrequency, "The frequency is set incorrectly");
|
||||
m_MinUpdateFrequency = Iface::s_MinUpdateFrequency;
|
||||
m_MaxUpdateFrequency = Iface::s_MaxUpdateFrequency;
|
||||
}
|
||||
|
||||
/// Called every time Relay wants to send a packet through this Channel Device.
|
||||
/// This is point where dynamic polymorphisms is replaced by static one.
|
||||
/// Types using Channel CRTP should implement size_t OnSendToChannel(ByteView).
|
||||
/// @param blob buffer containing data to send.
|
||||
size_t OnSendToChannelInternal(ByteView packet) override final
|
||||
{
|
||||
static_assert(CanSend<ByteView>::value, "OnSendToChannel is not implemented");
|
||||
auto self = static_cast<Iface*>(this);
|
||||
return self->OnSendToChannel(packet);
|
||||
}
|
||||
/// Callback that is periodically called for every Device to update itself.
|
||||
/// This is point where dynamic polymorphisms is replaced by static one with recognition of returned value.
|
||||
/// Types using Channel CRTP should implement MWR::ByteVector OnReceiveFromChannel(), or std::vector<MWR::ByteVector> OnReceiveFromChannel()
|
||||
/// @return std::vector<ByteVector> that contains all packets retrieved from Channel.
|
||||
std::vector<ByteVector> OnReceiveFromChannelInternal() override final
|
||||
{
|
||||
static_assert(CanRecive<>::value, "OnReceiveFromChannel is not implemented");
|
||||
static_assert(std::is_same_v<ReceiveReturnType<Iface>, ByteVector> || std::is_same_v<ReceiveReturnType<Iface>, std::vector<ByteVector>>, "OnReceiveFromChannel should return ByteVector or std::vector<ByteVector>");
|
||||
return ReceiveWrapper<Iface>();
|
||||
}
|
||||
|
||||
private:
|
||||
/// Alias to get result of OnReceiveFromChannel call.
|
||||
/// Use in form ReceiveReturnType<Iface> to obtain type.
|
||||
/// Can fail if function is not implemented.
|
||||
template<class T, class...Ts>
|
||||
using ReceiveReturnType = decltype(std::declval<T>().OnReceiveFromChannel(std::declval<Ts>()...));
|
||||
/// Called every time Relay wants to send a packet through this Channel Device.
|
||||
/// This is point where dynamic polymorphisms is replaced by static one.
|
||||
/// Types using Channel CRTP should implement size_t OnSendToChannel(ByteView).
|
||||
/// @param blob buffer containing data to send.
|
||||
size_t OnSendToChannelInternal(ByteView packet) override final
|
||||
{
|
||||
static_assert(CanSend<ByteView>::value, "OnSendToChannel is not implemented");
|
||||
auto self = static_cast<Iface*>(this);
|
||||
return self->OnSendToChannel(packet);
|
||||
}
|
||||
|
||||
/// Alias to test if OnReceiveFromChannel is implemented.
|
||||
/// Use in form CanRecive<Iface>::value to obtain bool value with information.
|
||||
template<class...Ts>
|
||||
using CanRecive = MWR::Utils::CanApply<ReceiveReturnType, Iface, Ts...>;
|
||||
private:
|
||||
/// Alias to get result of OnReceiveFromChannel call.
|
||||
/// Use in form ReceiveReturnType<Iface> to obtain type.
|
||||
/// Can fail if function is not implemented.
|
||||
template<class T, class...Ts>
|
||||
using ReceiveReturnType = decltype(std::declval<T>().OnReceiveFromChannel(std::declval<Ts>()...));
|
||||
|
||||
/// Alias to get result of OnSendToChannel call.
|
||||
/// Use in form SendReturnType<Iface, ByteView> to obtain type.
|
||||
/// Can fail if function is not implemented.
|
||||
template<class T, class...Ts>
|
||||
using SendReturnType = decltype(std::declval<T>().OnSendToChannel(std::declval<Ts>()...));
|
||||
/// Alias to test if OnReceiveFromChannel is implemented.
|
||||
/// Use in form CanRecive<Iface>::value to obtain bool value with information.
|
||||
template<class...Ts>
|
||||
using CanRecive = MWR::Utils::CanApply<ReceiveReturnType, Iface, Ts...>;
|
||||
|
||||
/// Alias to test if OnSendToChannel is implemented.
|
||||
/// Use in form CanSend<Iface>::value to obtain bool value with information.
|
||||
template<class...Ts>
|
||||
using CanSend = MWR::Utils::CanApply<SendReturnType, Iface, Ts...>;
|
||||
/// Alias to get result of OnSendToChannel call.
|
||||
/// Use in form SendReturnType<Iface, ByteView> to obtain type.
|
||||
/// Can fail if function is not implemented.
|
||||
template<class T, class...Ts>
|
||||
using SendReturnType = decltype(std::declval<T>().OnSendToChannel(std::declval<Ts>()...));
|
||||
|
||||
/// Virtual OnSendToChannelInternal cannot be templated.
|
||||
/// This function will be available for call if OnReceiveFromChannel returns ByteVector.
|
||||
/// @returns std::vector<ByteVector> one packet pushed on collection if it is not empty..
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_same_v<ReceiveReturnType<T>, ByteVector>, std::vector<ByteVector>> ReceiveWrapper()
|
||||
{
|
||||
auto self = static_cast<Iface*>(this);
|
||||
std::vector<ByteVector> ret;
|
||||
if (auto packet = self->OnReceiveFromChannel(); !packet.empty())
|
||||
ret.push_back(std::move(packet));
|
||||
/// Alias to test if OnSendToChannel is implemented.
|
||||
/// Use in form CanSend<Iface>::value to obtain bool value with information.
|
||||
template<class...Ts>
|
||||
using CanSend = MWR::Utils::CanApply<SendReturnType, Iface, Ts...>;
|
||||
|
||||
return ret;
|
||||
}
|
||||
/// Virtual OnSendToChannelInternal cannot be templated.
|
||||
/// This function will be available for call if OnReceiveFromChannel returns ByteVector.
|
||||
/// @returns std::vector<ByteVector> one packet pushed on collection if it is not empty..
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_same_v<ReceiveReturnType<T>, ByteVector>, std::vector<ByteVector>> ReceiveWrapper()
|
||||
{
|
||||
auto self = static_cast<Iface*>(this);
|
||||
std::vector<ByteVector> ret;
|
||||
if (auto packet = self->OnReceiveFromChannel(); !packet.empty())
|
||||
ret.push_back(std::move(packet));
|
||||
|
||||
/// Virtual OnSendToChannelInternal cannot be templated.
|
||||
/// This function will be available for call if OnReceiveFromChannel returns std::vector<ByteVector>.
|
||||
/// @returns std::vector<ByteVector> many packets that are not empty.
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_same_v<ReceiveReturnType<T>, std::vector<ByteVector>>, std::vector<ByteVector>> ReceiveWrapper()
|
||||
{
|
||||
auto self = static_cast<Iface*>(this);
|
||||
auto ret = self->OnReceiveFromChannel();
|
||||
static_cast<void>(std::remove_if(ret.begin(), ret.end(), [](auto&& e) { return e.empty(); }));
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// Virtual OnSendToChannelInternal cannot be templated.
|
||||
/// This function will be available for call if OnReceiveFromChannel returns std::vector<ByteVector>.
|
||||
/// @returns std::vector<ByteVector> many packets that are not empty.
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_same_v<ReceiveReturnType<T>, std::vector<ByteVector>>, std::vector<ByteVector>> ReceiveWrapper()
|
||||
{
|
||||
auto self = static_cast<Iface*>(this);
|
||||
auto ret = self->OnReceiveFromChannel();
|
||||
static_cast<void>(std::remove_if(ret.begin(), ret.end(), [](auto&& e) { return e.empty(); }));
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef C3_IS_GATEWAY
|
||||
/// Specialization of Registration mechanism for Connector type Interface.
|
||||
template <typename Iface>
|
||||
class Connector : public Register<Iface, AbstractConnector>
|
||||
{
|
||||
public:
|
||||
// connector in fact does not need those values. They are here to satisfy template requirements.
|
||||
constexpr static std::chrono::milliseconds s_MinUpdateFrequency = 0ms;
|
||||
constexpr static std::chrono::milliseconds s_MaxUpdateFrequency = 0ms;
|
||||
};
|
||||
/// Specialization of Registration mechanism for Connector type Interface.
|
||||
template <typename Iface>
|
||||
class Connector : public Register<Iface, AbstractConnector>
|
||||
{
|
||||
public:
|
||||
// connector in fact does not need those values. They are here to satisfy template requirements.
|
||||
constexpr static std::chrono::milliseconds s_MinUpdateFrequency = 0ms;
|
||||
constexpr static std::chrono::milliseconds s_MaxUpdateFrequency = 0ms;
|
||||
};
|
||||
#else
|
||||
/// Don't register the connectors in node builds
|
||||
template <typename Iface>
|
||||
class Connector : public AbstractConnector
|
||||
{
|
||||
};
|
||||
/// Don't register the connectors in node builds
|
||||
template <typename Iface>
|
||||
class Connector : public AbstractConnector
|
||||
{
|
||||
};
|
||||
#endif C3_IS_GATEWAY
|
||||
|
||||
#pragma warning( push )
|
||||
#pragma warning( disable : 4307)
|
||||
/// Specialization of Registration mechanism for Peripheral type Interface.
|
||||
template <typename Iface, typename Closure>
|
||||
class Peripheral : public Register<Iface, AbstractPeripheral, Hash::Fnv1aType<Closure>()>
|
||||
{
|
||||
public:
|
||||
constexpr static std::chrono::milliseconds s_MinUpdateFrequency = 30ms;
|
||||
constexpr static std::chrono::milliseconds s_MaxUpdateFrequency = 30ms;
|
||||
|
||||
Peripheral()
|
||||
/// Specialization of Registration mechanism for Peripheral type Interface.
|
||||
template <typename Iface, typename Closure>
|
||||
class Peripheral : public Register<Iface, AbstractPeripheral, Hash::Fnv1aType<Closure>()>
|
||||
{
|
||||
static_assert(Iface::s_MinUpdateFrequency >= 30ms && Iface::s_MinUpdateFrequency <= Iface::s_MaxUpdateFrequency, "The frequency is set incorrectly");
|
||||
m_MinUpdateFrequency = Iface::s_MinUpdateFrequency;
|
||||
m_MaxUpdateFrequency = Iface::s_MaxUpdateFrequency;
|
||||
}
|
||||
};
|
||||
public:
|
||||
constexpr static std::chrono::milliseconds s_MinUpdateFrequency = 30ms;
|
||||
constexpr static std::chrono::milliseconds s_MaxUpdateFrequency = 30ms;
|
||||
|
||||
Peripheral()
|
||||
{
|
||||
static_assert(Iface::s_MinUpdateFrequency >= 30ms && Iface::s_MinUpdateFrequency <= Iface::s_MaxUpdateFrequency, "The frequency is set incorrectly");
|
||||
m_MinUpdateFrequency = Iface::s_MinUpdateFrequency;
|
||||
m_MaxUpdateFrequency = Iface::s_MaxUpdateFrequency;
|
||||
}
|
||||
};
|
||||
#pragma warning( pop )
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,9 +23,6 @@ std::string MWR::C3::InterfaceFactory::GetCapability()
|
|||
{
|
||||
json entry;
|
||||
entry["type"] = e.first;
|
||||
if (e.second.m_Capability.empty() || e.second.m_Name.empty())
|
||||
continue;
|
||||
|
||||
entry["name"] = e.second.m_Name;
|
||||
auto pin = json::parse(e.second.m_Capability);
|
||||
for (const auto& j : pin.items())
|
||||
|
|
|
@ -117,7 +117,7 @@ MWR::ByteVector MWR::C3::Core::Profiler::TranslateArguments(json const& argument
|
|||
if (!argument.is_array())
|
||||
translate(argument);
|
||||
else
|
||||
for (auto subargument : argument)
|
||||
for (auto const subargument : argument)
|
||||
translate(subargument);
|
||||
}
|
||||
|
||||
|
@ -821,6 +821,20 @@ json MWR::C3::Core::Profiler::Gateway::GetCapability()
|
|||
// Construct the InitialPacket.
|
||||
json initialPacket = json::parse(gateway->m_InterfaceFactory.GetCapability());
|
||||
|
||||
for (auto& interface : initialPacket["channels"])
|
||||
if (!interface.contains("create"))
|
||||
interface["create"] = json::parse(R"(
|
||||
{
|
||||
"arguments" :
|
||||
[
|
||||
{
|
||||
"type": "binary",
|
||||
"description": "Blob of data that will be provided to Channel constructor.",
|
||||
"name": "arguments"
|
||||
}
|
||||
]
|
||||
})");
|
||||
|
||||
// Create method in interface is constructor. It must be a relay/gateway command.
|
||||
// initialPacket is copied to original to prevent iterator invalidation.
|
||||
// last 256 commands will be reserved for common commands.
|
||||
|
@ -829,14 +843,13 @@ json MWR::C3::Core::Profiler::Gateway::GetCapability()
|
|||
auto idToErase = 0;
|
||||
std::vector<std::unordered_map<std::string, std::vector<json>>> buffer;
|
||||
buffer.resize(prefix.size());
|
||||
for (auto&& e : oryginal[interfaceType])
|
||||
for (auto&& element : oryginal[interfaceType])
|
||||
{
|
||||
try
|
||||
{
|
||||
for (auto i = 0u; i < prefix.size(); ++i)
|
||||
{
|
||||
|
||||
auto arguments = e.at("create").at("arguments");
|
||||
auto arguments = element.at("create").at("arguments");
|
||||
if (i) // NegotiationChannel command
|
||||
{
|
||||
if (arguments.empty() || arguments[0].size() != 2)
|
||||
|
@ -846,7 +859,7 @@ json MWR::C3::Core::Profiler::Gateway::GetCapability()
|
|||
}
|
||||
|
||||
for (auto&& relayType : relayTypes)
|
||||
buffer[i][relayType].push_back(json{ {"name", prefix[i] + e["name"].get<std::string>()}, {"arguments", arguments}, {"id", id} });
|
||||
buffer[i][relayType].push_back(json{ {"name", prefix[i] + element["name"].get<std::string>()}, {"arguments", arguments}, {"id", id} });
|
||||
|
||||
m_CreateCommands.push_back({ id, initialPacket[interfaceType][idToErase]["type"].get<uint32_t>(), isDevice, !!i }); // store command id and hash.
|
||||
--id;
|
||||
|
@ -856,7 +869,7 @@ json MWR::C3::Core::Profiler::Gateway::GetCapability()
|
|||
initialPacket[interfaceType][idToErase].erase("create");
|
||||
initialPacket[interfaceType][idToErase]["commands"].push_back(json{ {"name", isDevice ? "Close" : "TurnOff"}, {"id", static_cast<std::underlying_type_t<NodeRelay::Command>>(NodeRelay::Command::Close) }, {"arguments", json::array()} });
|
||||
if (isDevice)
|
||||
initialPacket[interfaceType][idToErase]["commands"].push_back(json{ {"name", "UpdateDelayJitter"}, {"description", "Set delay between receiving function calls."}, {"id", static_cast<std::underlying_type_t<NodeRelay::Command>>(NodeRelay::Command::UpdateJitter) },
|
||||
initialPacket[interfaceType][idToErase]["commands"].push_back(json{ {"name", "Set UpdateDelayJitter"}, {"description", "Set delay between receiving function calls."}, {"id", static_cast<std::underlying_type_t<NodeRelay::Command>>(NodeRelay::Command::UpdateJitter) },
|
||||
{"arguments", {
|
||||
{{"type", "float"}, {"name", "Min"}, {"description", "Minimal delay in seconds"}, {"min", 0.03}},
|
||||
{{"type", "float"}, {"name", "Max"}, {"description", "Maximal delay in seconds. "}, {"min", 0.03}}
|
||||
|
|
Loading…
Reference in New Issue