C3/Src/Core/DeviceBridge.cpp

202 lines
9.3 KiB
C++

#include "StdAfx.h"
#include "DeviceBridge.h"
#include "Relay.h"
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
FSecure::C3::Core::DeviceBridge::DeviceBridge(std::shared_ptr<Relay>&& relay, DeviceId did, HashT typeNameHash, std::shared_ptr<Device>&& device, bool isNegotiationChannel, bool isSlave, ByteVector args /*= ByteVector()*/)
: m_IsNegotiationChannel(isNegotiationChannel)
, m_IsSlave(isSlave)
, m_Did{ did }
, m_TypeNameHash(typeNameHash)
, m_Relay{ relay }
, m_Device{ std::move(device) }
{
if (!isNegotiationChannel)
return;
auto readView = ByteView{ args };
std::tie(m_InputId, m_OutpuId) = readView.Read<ByteVector, ByteVector>();
m_NonNegotiatiedArguments = readView;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void FSecure::C3::Core::DeviceBridge::OnAttach()
{
GetDevice()->OnAttach(shared_from_this());
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void FSecure::C3::Core::DeviceBridge::Detach()
{
m_IsAlive = false;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void FSecure::C3::Core::DeviceBridge::Close()
{
auto relay = GetRelay();
relay->DetachDevice(GetDid());
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void FSecure::C3::Core::DeviceBridge::OnReceive()
{
GetDevice()->OnReceive();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void FSecure::C3::Core::DeviceBridge::PassNetworkPacket(ByteView packet)
{
if (m_IsNegotiationChannel && !m_IsSlave) // negotiation channel does not support chunking. Just pass packet and leave.
return GetRelay()->OnPacketReceived(packet, shared_from_this());
m_QoS.PushReceivedChunk(packet);
auto nextPacket = m_QoS.GetNextPacket();
if (!nextPacket.empty())
GetRelay()->OnPacketReceived(nextPacket, shared_from_this());
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void FSecure::C3::Core::DeviceBridge::OnPassNetworkPacket(ByteView packet)
{
auto lock = std::lock_guard<std::mutex>{ m_ProtectWriteInConcurrentThreads };
if (m_IsNegotiationChannel) // negotiation channel does not support chunking. Just pass packet and leave.
{
auto sent = GetDevice()->OnSendToChannelInternal(packet);
if (sent != packet.size())
throw std::runtime_error{OBF("Negotiation channel does not support chunking. Packet size: ") + std::to_string(packet.size()) + OBF(" Channel sent: ") + std::to_string(sent)};
return;
}
auto packetSplitter = m_QoS.GetPacketSplitter(packet);
while (packetSplitter.HasMore())
packetSplitter.Update(GetDevice()->OnSendToChannelInternal(packetSplitter.NextChunk()));
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void FSecure::C3::Core::DeviceBridge::PostCommandToConnector(ByteView packet)
{
GetRelay()->PostCommandToConnector(packet, shared_from_this());
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void FSecure::C3::Core::DeviceBridge::OnCommandFromConnector(ByteView command)
{
auto lock = std::lock_guard<std::mutex>{ m_ProtectWriteInConcurrentThreads };
GetDevice()->OnCommandFromConnector(command);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
FSecure::ByteVector FSecure::C3::Core::DeviceBridge::RunCommand(ByteView command)
{
return GetDevice()->OnRunCommand(command);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
FSecure::ByteVector FSecure::C3::Core::DeviceBridge::WhoAreYou()
{
return GetDevice()->OnWhoAmI();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void FSecure::C3::Core::DeviceBridge::Log(LogMessage const& message)
{
GetRelay()->Log(message, GetDid());
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
FSecure::C3::DeviceId FSecure::C3::Core::DeviceBridge::GetDid() const
{
return m_Did;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void FSecure::C3::Core::DeviceBridge::StartUpdatingInSeparateThread()
{
std::thread{
[this, self = shared_from_this()]()
{
WinTools::StructuredExceptionHandling::SehWrapper([&]()
{
while (m_IsAlive)
try
{
std::this_thread::sleep_for(GetDevice()->GetUpdateDelay());
OnReceive();
}
catch (std::exception const& exception)
{
Log({ OBF_SEC("std::exception while updating: ") + exception.what(), LogMessage::Severity::Error });
}
catch (...)
{
Log({ OBF_SEC("Unknown exception while updating."), LogMessage::Severity::Error });
}
}, [this]()
{
# if defined _DEBUG
Log({ "Signal captured, ending thread execution.", LogMessage::Severity::Error });
# endif
});
}}.detach();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void FSecure::C3::Core::DeviceBridge::SetUpdateDelay(std::chrono::milliseconds minUpdateDelayInMs, std::chrono::milliseconds maxUpdateDelayInMs)
{
GetDevice()->SetUpdateDelay(minUpdateDelayInMs, maxUpdateDelayInMs);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void FSecure::C3::Core::DeviceBridge::SetUpdateDelay(std::chrono::milliseconds frequencyInMs)
{
GetDevice()->SetUpdateDelay(frequencyInMs);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
std::shared_ptr<FSecure::C3::Device> FSecure::C3::Core::DeviceBridge::GetDevice() const
{
return m_Device;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
std::shared_ptr<FSecure::C3::Core::Relay> FSecure::C3::Core::DeviceBridge::GetRelay() const
{
return m_Relay;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
FSecure::HashT FSecure::C3::Core::DeviceBridge::GetTypeNameHash() const
{
return m_TypeNameHash;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool FSecure::C3::Core::DeviceBridge::IsChannel() const
{
auto device = GetDevice();
return device ? device->IsChannel() : false;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool FSecure::C3::Core::DeviceBridge::IsNegotiationChannel() const
{
return m_IsNegotiationChannel && IsChannel();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void FSecure::C3::Core::DeviceBridge::SetErrorStatus(std::string_view errorMessage)
{
m_Error = errorMessage;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
std::string FSecure::C3::Core::DeviceBridge::GetErrorStatus()
{
return m_Error;
}