mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-08-22 15:11:31 +00:00
[idd] transport: configure active instances
This commit is contained in:
@@ -64,6 +64,7 @@
|
|||||||
<ClCompile Include="transport\CFrameHub.cpp" />
|
<ClCompile Include="transport\CFrameHub.cpp" />
|
||||||
<ClCompile Include="transport\CInputHub.cpp" />
|
<ClCompile Include="transport\CInputHub.cpp" />
|
||||||
<ClCompile Include="transport\CTransportManager.cpp" />
|
<ClCompile Include="transport\CTransportManager.cpp" />
|
||||||
|
<ClCompile Include="transport\TransportConfig.cpp" />
|
||||||
<ClCompile Include="transport\TransportFactory.cpp" />
|
<ClCompile Include="transport\TransportFactory.cpp" />
|
||||||
<ClCompile Include="transport\lgmp\CIVSHMEM.cpp" />
|
<ClCompile Include="transport\lgmp\CIVSHMEM.cpp" />
|
||||||
<ClCompile Include="transport\lgmp\CRecovery.cpp" />
|
<ClCompile Include="transport\lgmp\CRecovery.cpp" />
|
||||||
@@ -123,6 +124,7 @@
|
|||||||
<ClInclude Include="transport\IInputTransport.h" />
|
<ClInclude Include="transport\IInputTransport.h" />
|
||||||
<ClInclude Include="transport\IInputSource.h" />
|
<ClInclude Include="transport\IInputSource.h" />
|
||||||
<ClInclude Include="transport\ITransport.h" />
|
<ClInclude Include="transport\ITransport.h" />
|
||||||
|
<ClInclude Include="transport\TransportConfig.h" />
|
||||||
<ClInclude Include="transport\PreparedFrameBuffer.h" />
|
<ClInclude Include="transport\PreparedFrameBuffer.h" />
|
||||||
<ClInclude Include="transport\TransportFactory.h" />
|
<ClInclude Include="transport\TransportFactory.h" />
|
||||||
<ClInclude Include="transport\lgmp\CIVSHMEM.h" />
|
<ClInclude Include="transport\lgmp\CIVSHMEM.h" />
|
||||||
|
|||||||
@@ -193,6 +193,9 @@
|
|||||||
<ClInclude Include="transport\ITransport.h">
|
<ClInclude Include="transport\ITransport.h">
|
||||||
<Filter>Transport</Filter>
|
<Filter>Transport</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="transport\TransportConfig.h">
|
||||||
|
<Filter>Transport</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="transport\PreparedFrameBuffer.h">
|
<ClInclude Include="transport\PreparedFrameBuffer.h">
|
||||||
<Filter>Transport</Filter>
|
<Filter>Transport</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
@@ -324,6 +327,9 @@
|
|||||||
<ClCompile Include="transport\CTransportManager.cpp">
|
<ClCompile Include="transport\CTransportManager.cpp">
|
||||||
<Filter>Transport</Filter>
|
<Filter>Transport</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="transport\TransportConfig.cpp">
|
||||||
|
<Filter>Transport</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="transport\TransportFactory.cpp">
|
<ClCompile Include="transport\TransportFactory.cpp">
|
||||||
<Filter>Transport</Filter>
|
<Filter>Transport</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|||||||
@@ -80,6 +80,21 @@ CSettings::DisplayModes CSettings::LoadModes()
|
|||||||
return displayModes;
|
return displayModes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TransportInstances CSettings::LoadTransportInstances() const
|
||||||
|
{
|
||||||
|
std::vector<std::wstring> entries;
|
||||||
|
if (!ReadMultiStringValue(L"TransportInstances", entries))
|
||||||
|
return DefaultTransportInstances();
|
||||||
|
|
||||||
|
TransportInstances instances;
|
||||||
|
if (!ParseTransportInstances(entries, instances))
|
||||||
|
{
|
||||||
|
DEBUG_WARN("Invalid transport instance configuration; using defaults");
|
||||||
|
return DefaultTransportInstances();
|
||||||
|
}
|
||||||
|
return instances;
|
||||||
|
}
|
||||||
|
|
||||||
bool CSettings::SetExtraMode(const DisplayMode& mode)
|
bool CSettings::SetExtraMode(const DisplayMode& mode)
|
||||||
{
|
{
|
||||||
WCHAR buf[64];
|
WCHAR buf[64];
|
||||||
@@ -272,7 +287,8 @@ unsigned CSettings::GetDefaultRefreshMilliHz() const
|
|||||||
return refreshMilliHz ? refreshMilliHz : 60000;
|
return refreshMilliHz ? refreshMilliHz : 60000;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CSettings::ReadModesValue(std::vector<std::wstring> &out) const
|
bool CSettings::ReadMultiStringValue(const wchar_t * name,
|
||||||
|
std::vector<std::wstring>& out) const
|
||||||
{
|
{
|
||||||
HKEY hKey = nullptr;
|
HKEY hKey = nullptr;
|
||||||
LONG st = RegOpenKeyExW(HKEY_LOCAL_MACHINE, LGIDD_REGKEY, 0, KEY_QUERY_VALUE, &hKey);
|
LONG st = RegOpenKeyExW(HKEY_LOCAL_MACHINE, LGIDD_REGKEY, 0, KEY_QUERY_VALUE, &hKey);
|
||||||
@@ -280,29 +296,44 @@ bool CSettings::ReadModesValue(std::vector<std::wstring> &out) const
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
DWORD type = 0, cb = 0;
|
DWORD type = 0, cb = 0;
|
||||||
st = RegGetValueW(hKey, nullptr, L"Modes", RRF_RT_REG_MULTI_SZ, &type, nullptr, &cb);
|
st = RegGetValueW(hKey, nullptr, name, RRF_RT_REG_MULTI_SZ,
|
||||||
|
&type, nullptr, &cb);
|
||||||
if (st != ERROR_SUCCESS || cb == 0)
|
if (st != ERROR_SUCCESS || cb == 0)
|
||||||
{
|
{
|
||||||
RegCloseKey(hKey);
|
RegCloseKey(hKey);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<wchar_t> buf(cb / sizeof(wchar_t));
|
const DWORD capacity = cb;
|
||||||
st = RegGetValueW(hKey, nullptr, L"Modes", RRF_RT_REG_MULTI_SZ, &type, buf.data(), &cb);
|
std::vector<wchar_t> buf(
|
||||||
|
capacity / sizeof(wchar_t) + 2, L'\0');
|
||||||
|
st = RegGetValueW(hKey, nullptr, name, RRF_RT_REG_MULTI_SZ,
|
||||||
|
&type, buf.data(), &cb);
|
||||||
RegCloseKey(hKey);
|
RegCloseKey(hKey);
|
||||||
if (st != ERROR_SUCCESS)
|
if (st != ERROR_SUCCESS || cb > capacity || cb % sizeof(wchar_t))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const wchar_t* p = buf.data();
|
const size_t length = cb / sizeof(wchar_t);
|
||||||
while (*p)
|
size_t begin = 0;
|
||||||
|
while (begin < length && buf[begin])
|
||||||
{
|
{
|
||||||
out.emplace_back(p);
|
size_t end = begin;
|
||||||
p += (wcslen(p) + 1);
|
while (end < length && buf[end])
|
||||||
|
++end;
|
||||||
|
if (end == length)
|
||||||
|
return false;
|
||||||
|
out.emplace_back(buf.data() + begin, end - begin);
|
||||||
|
begin = end + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return !out.empty();
|
return !out.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CSettings::ReadModesValue(std::vector<std::wstring> &out) const
|
||||||
|
{
|
||||||
|
return ReadMultiStringValue(L"Modes", out);
|
||||||
|
}
|
||||||
|
|
||||||
static std::wstring trim(const std::wstring &s)
|
static std::wstring trim(const std::wstring &s)
|
||||||
{
|
{
|
||||||
size_t b = 0, e = s.size();
|
size_t b = 0, e = s.size();
|
||||||
|
|||||||
@@ -19,6 +19,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include "transport/TransportConfig.h"
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -39,6 +41,7 @@ class CSettings
|
|||||||
CSettings();
|
CSettings();
|
||||||
|
|
||||||
DisplayModes LoadModes();
|
DisplayModes LoadModes();
|
||||||
|
TransportInstances LoadTransportInstances() const;
|
||||||
bool SetExtraMode(const DisplayMode & mode);
|
bool SetExtraMode(const DisplayMode & mode);
|
||||||
bool GetExtraMode(DisplayMode & mode);
|
bool GetExtraMode(DisplayMode & mode);
|
||||||
unsigned GetDefaultRefreshMilliHz() const;
|
unsigned GetDefaultRefreshMilliHz() const;
|
||||||
@@ -47,6 +50,8 @@ class CSettings
|
|||||||
bool ReadBoolValue(const wchar_t* name, bool defaultValue = false);
|
bool ReadBoolValue(const wchar_t* name, bool defaultValue = false);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool ReadMultiStringValue(const wchar_t * name,
|
||||||
|
std::vector<std::wstring>& out) const;
|
||||||
bool ReadModesValue(std::vector<std::wstring> &out) const;
|
bool ReadModesValue(std::vector<std::wstring> &out) const;
|
||||||
bool ParseModeString(const std::wstring& in, DisplayMode& out);
|
bool ParseModeString(const std::wstring& in, DisplayMode& out);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -238,29 +238,34 @@ void CTransportManager::EndCall(Entry& entry,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CTransportManager::Add(BackendId id, const char * name, bool required,
|
bool CTransportManager::Add(TransportInstance config, bool primary,
|
||||||
bool primary, CreateFn create)
|
CreateFn create)
|
||||||
{
|
{
|
||||||
CSRWExclusiveLock managerLock(m_lock);
|
CSRWExclusiveLock managerLock(m_lock);
|
||||||
if (!m_phaseIdle || !m_stoppedEvent || m_phase != Phase::IDLE ||
|
if (!m_phaseIdle || !m_stoppedEvent || m_phase != Phase::IDLE ||
|
||||||
m_started || m_stopping ||
|
m_started || m_stopping ||
|
||||||
m_stopped || !id || !name || !create ||
|
m_stopped || !config.enabled || !config.id || config.kind.empty() ||
|
||||||
|
(config.services & ~TRANSPORT_SERVICE_ALL) || !create ||
|
||||||
m_entryCount == FRAME_MAX_SINKS || (primary && m_primary))
|
m_entryCount == FRAME_MAX_SINKS || (primary && m_primary))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (primary && (!config.required ||
|
||||||
|
!(config.services & TRANSPORT_SERVICE_FRAME)))
|
||||||
|
return false;
|
||||||
|
|
||||||
for (unsigned i = 0; i < m_entryCount; ++i)
|
for (unsigned i = 0; i < m_entryCount; ++i)
|
||||||
if (m_entries[i]->id == id)
|
if (m_entries[i]->id == config.id)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
std::unique_ptr<Entry> entry(new (std::nothrow) Entry);
|
std::unique_ptr<Entry> entry(new (std::nothrow) Entry);
|
||||||
if (!entry || !entry->idleEvent)
|
if (!entry || !entry->idleEvent)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
entry->id = id;
|
entry->id = config.id;
|
||||||
entry->name = name;
|
entry->required = config.required;
|
||||||
entry->required = required;
|
|
||||||
entry->primary = primary;
|
entry->primary = primary;
|
||||||
entry->create = create;
|
entry->create = create;
|
||||||
|
entry->config = std::move(config);
|
||||||
|
|
||||||
Entry * raw = entry.get();
|
Entry * raw = entry.get();
|
||||||
m_entries[m_entryCount++] = std::move(entry);
|
m_entries[m_entryCount++] = std::move(entry);
|
||||||
@@ -273,15 +278,17 @@ ITransport::OpenResult CTransportManager::OpenEntry(Entry& entry)
|
|||||||
{
|
{
|
||||||
std::shared_ptr<ITransport> transport;
|
std::shared_ptr<ITransport> transport;
|
||||||
CreateFn create = nullptr;
|
CreateFn create = nullptr;
|
||||||
|
TransportInstance config;
|
||||||
{
|
{
|
||||||
CSRWSharedLock entryLock(entry.lock);
|
CSRWSharedLock entryLock(entry.lock);
|
||||||
transport = entry.transport;
|
transport = entry.transport;
|
||||||
create = entry.create;
|
create = entry.create;
|
||||||
|
config = entry.config;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!transport)
|
if (!transport)
|
||||||
{
|
{
|
||||||
std::unique_ptr<ITransport> created = create();
|
std::unique_ptr<ITransport> created = create(config);
|
||||||
transport.reset(created.release());
|
transport.reset(created.release());
|
||||||
CSRWExclusiveLock entryLock(entry.lock);
|
CSRWExclusiveLock entryLock(entry.lock);
|
||||||
entry.transport = transport;
|
entry.transport = transport;
|
||||||
@@ -353,6 +360,8 @@ bool CTransportManager::AddServices(Entry& entry)
|
|||||||
BackendId id = 0;
|
BackendId id = 0;
|
||||||
uint32_t epoch = 0;
|
uint32_t epoch = 0;
|
||||||
bool primary = false;
|
bool primary = false;
|
||||||
|
bool required = false;
|
||||||
|
uint32_t services = 0;
|
||||||
bool controlAdded = false;
|
bool controlAdded = false;
|
||||||
bool controlFailed = false;
|
bool controlFailed = false;
|
||||||
bool controlAbsent = false;
|
bool controlAbsent = false;
|
||||||
@@ -368,6 +377,8 @@ bool CTransportManager::AddServices(Entry& entry)
|
|||||||
id = entry.id;
|
id = entry.id;
|
||||||
epoch = entry.epoch;
|
epoch = entry.epoch;
|
||||||
primary = entry.primary;
|
primary = entry.primary;
|
||||||
|
required = entry.required;
|
||||||
|
services = entry.config.services;
|
||||||
controlAdded = entry.controlAdded;
|
controlAdded = entry.controlAdded;
|
||||||
controlFailed = entry.controlFailed;
|
controlFailed = entry.controlFailed;
|
||||||
controlAbsent = entry.controlAbsent;
|
controlAbsent = entry.controlAbsent;
|
||||||
@@ -380,14 +391,16 @@ bool CTransportManager::AddServices(Entry& entry)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!transport)
|
if (!transport)
|
||||||
return !primary;
|
return !required;
|
||||||
|
|
||||||
const uint64_t now = GetTickCount64();
|
const uint64_t now = GetTickCount64();
|
||||||
const bool attach = now >= retryAt;
|
const bool attach = now >= retryAt;
|
||||||
bool controlRetry = false;
|
bool controlRetry = false;
|
||||||
bool frameRetry = false;
|
bool frameRetry = false;
|
||||||
bool inputRetry = false;
|
bool inputRetry = false;
|
||||||
if (attach && !controlAdded && !controlFailed && !controlAbsent)
|
if (!(services & TRANSPORT_SERVICE_CONTROL))
|
||||||
|
controlAbsent = true;
|
||||||
|
else if (attach && !controlAdded && !controlFailed && !controlAbsent)
|
||||||
{
|
{
|
||||||
IControlSink * control = transport->Control();
|
IControlSink * control = transport->Control();
|
||||||
if (control && m_control.Add(id, epoch, *control))
|
if (control && m_control.Add(id, epoch, *control))
|
||||||
@@ -406,7 +419,9 @@ bool CTransportManager::AddServices(Entry& entry)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attach && !frameAdded && !frameAbsent)
|
if (!(services & TRANSPORT_SERVICE_FRAME))
|
||||||
|
frameAbsent = true;
|
||||||
|
else if (attach && !frameAdded && !frameAbsent)
|
||||||
{
|
{
|
||||||
IFrameSink * frame = transport->FrameSink();
|
IFrameSink * frame = transport->FrameSink();
|
||||||
if (frame && m_frames.Bind(id, epoch, primary, *frame))
|
if (frame && m_frames.Bind(id, epoch, primary, *frame))
|
||||||
@@ -425,7 +440,9 @@ bool CTransportManager::AddServices(Entry& entry)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attach && !inputAdded && !inputFailed && !inputAbsent)
|
if (!(services & TRANSPORT_SERVICE_INPUT))
|
||||||
|
inputAbsent = true;
|
||||||
|
else if (attach && !inputAdded && !inputFailed && !inputAbsent)
|
||||||
{
|
{
|
||||||
IInputSource * input = transport->Input();
|
IInputSource * input = transport->Input();
|
||||||
if (input && m_input.Bind(id, epoch, *input))
|
if (input && m_input.Bind(id, epoch, *input))
|
||||||
@@ -450,7 +467,11 @@ bool CTransportManager::AddServices(Entry& entry)
|
|||||||
entry.serviceRetryAt = now + SERVICE_RETRY_DELAY_MS;
|
entry.serviceRetryAt = now + SERVICE_RETRY_DELAY_MS;
|
||||||
}
|
}
|
||||||
|
|
||||||
return !primary || frameAdded;
|
const bool servicesReady =
|
||||||
|
(!(services & TRANSPORT_SERVICE_FRAME) || frameAdded) &&
|
||||||
|
(!(services & TRANSPORT_SERVICE_CONTROL) || controlAdded) &&
|
||||||
|
(!(services & TRANSPORT_SERVICE_INPUT) || inputAdded);
|
||||||
|
return !required || servicesReady;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CTransportManager::HandleServiceFailures()
|
void CTransportManager::HandleServiceFailures()
|
||||||
@@ -650,26 +671,25 @@ void CTransportManager::HandleProcessResult(
|
|||||||
|
|
||||||
bool exposed = false;
|
bool exposed = false;
|
||||||
bool primary = false;
|
bool primary = false;
|
||||||
bool required = false;
|
std::wstring name;
|
||||||
const char * name = nullptr;
|
|
||||||
{
|
{
|
||||||
CSRWSharedLock entryLock(entry.lock);
|
CSRWSharedLock entryLock(entry.lock);
|
||||||
exposed = entry.exposed;
|
exposed = entry.exposed;
|
||||||
primary = entry.primary;
|
primary = entry.primary;
|
||||||
required = entry.required;
|
name = entry.config.kind;
|
||||||
name = entry.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (primary && exposed)
|
|
||||||
{
|
|
||||||
(void)name;
|
|
||||||
DEBUG_WARN("Transport %s requested a restart while its frame interfaces "
|
|
||||||
"are active", name);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RemoveServices(entry);
|
RemoveServices(entry);
|
||||||
if (result == ProcessResult::RETRY || !required)
|
if (primary && exposed)
|
||||||
|
{
|
||||||
|
DEBUG_WARN("Transport %ls stopped while its frame interfaces are active",
|
||||||
|
name.c_str());
|
||||||
|
CSRWExclusiveLock entryLock(entry.lock);
|
||||||
|
entry.state = State::FAILED;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == ProcessResult::RETRY)
|
||||||
{
|
{
|
||||||
ScheduleRetry(entry);
|
ScheduleRetry(entry);
|
||||||
return;
|
return;
|
||||||
@@ -774,6 +794,9 @@ bool CTransportManager::Initialize()
|
|||||||
{
|
{
|
||||||
CSRWSharedLock entryLock(entry.lock);
|
CSRWSharedLock entryLock(entry.lock);
|
||||||
transport = entry.transport;
|
transport = entry.transport;
|
||||||
|
if (entry.required && entry.state != State::INITIALIZED &&
|
||||||
|
entry.state != State::READY)
|
||||||
|
success = false;
|
||||||
}
|
}
|
||||||
EndCall(entry, transport);
|
EndCall(entry, transport);
|
||||||
}
|
}
|
||||||
@@ -818,7 +841,7 @@ bool CTransportManager::Setup(size_t alignment)
|
|||||||
Entry& entry = *entries[i];
|
Entry& entry = *entries[i];
|
||||||
if (!BeginCall(entry, Call::LIFECYCLE, true))
|
if (!BeginCall(entry, Call::LIFECYCLE, true))
|
||||||
{
|
{
|
||||||
if (entry.primary)
|
if (entry.required)
|
||||||
success = false;
|
success = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -831,14 +854,18 @@ bool CTransportManager::Setup(size_t alignment)
|
|||||||
transport = entry.transport;
|
transport = entry.transport;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((state == State::INITIALIZED || state == State::READY) &&
|
if (state != State::INITIALIZED && state != State::READY)
|
||||||
!SetupEntry(entry, alignment))
|
{
|
||||||
|
if (entry.required)
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
else if (!SetupEntry(entry, alignment))
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
CSRWSharedLock entryLock(entry.lock);
|
CSRWSharedLock entryLock(entry.lock);
|
||||||
state = entry.state;
|
state = entry.state;
|
||||||
}
|
}
|
||||||
if (entry.primary)
|
if (entry.required)
|
||||||
success = false;
|
success = false;
|
||||||
else if (state == State::FAILED)
|
else if (state == State::FAILED)
|
||||||
ScheduleRetry(entry);
|
ScheduleRetry(entry);
|
||||||
|
|||||||
@@ -25,13 +25,18 @@
|
|||||||
#include "transport/CFrameHub.h"
|
#include "transport/CFrameHub.h"
|
||||||
#include "transport/CInputHub.h"
|
#include "transport/CInputHub.h"
|
||||||
#include "transport/ITransport.h"
|
#include "transport/ITransport.h"
|
||||||
|
#include "transport/TransportConfig.h"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
static_assert(TRANSPORT_MAX_INSTANCES == FRAME_MAX_SINKS,
|
||||||
|
"The transport and frame limits must match");
|
||||||
|
|
||||||
class CTransportManager final
|
class CTransportManager final
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using CreateFn = std::unique_ptr<ITransport> (*)();
|
using CreateFn = std::unique_ptr<ITransport> (*)(
|
||||||
|
const TransportInstance& config);
|
||||||
using OpenResult = ITransport::OpenResult;
|
using OpenResult = ITransport::OpenResult;
|
||||||
using ProcessResult = ITransport::ProcessResult;
|
using ProcessResult = ITransport::ProcessResult;
|
||||||
using Recovery = ITransport::Recovery;
|
using Recovery = ITransport::Recovery;
|
||||||
@@ -90,7 +95,7 @@ private:
|
|||||||
DWORD callOwner = 0;
|
DWORD callOwner = 0;
|
||||||
bool stopRequested = false;
|
bool stopRequested = false;
|
||||||
BackendId id = 0;
|
BackendId id = 0;
|
||||||
const char * name = nullptr;
|
TransportInstance config;
|
||||||
bool required = false;
|
bool required = false;
|
||||||
bool primary = false;
|
bool primary = false;
|
||||||
CreateFn create = nullptr;
|
CreateFn create = nullptr;
|
||||||
@@ -166,8 +171,7 @@ public:
|
|||||||
CTransportManager(const CTransportManager&) = delete;
|
CTransportManager(const CTransportManager&) = delete;
|
||||||
CTransportManager& operator=(const CTransportManager&) = delete;
|
CTransportManager& operator=(const CTransportManager&) = delete;
|
||||||
|
|
||||||
bool Add(BackendId id, const char * name, bool required, bool primary,
|
bool Add(TransportInstance config, bool primary, CreateFn create);
|
||||||
CreateFn create);
|
|
||||||
|
|
||||||
OpenResult Open();
|
OpenResult Open();
|
||||||
bool Initialize();
|
bool Initialize();
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#include "transport/DirectFrameBufferMemory.h"
|
#include "transport/DirectFrameBufferMemory.h"
|
||||||
#include "transport/FrameMemoryLimits.h"
|
#include "transport/FrameMemoryLimits.h"
|
||||||
|
#include "transport/TransportConfig.h"
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@@ -30,8 +31,6 @@ class IControlSink;
|
|||||||
class IFrameSink;
|
class IFrameSink;
|
||||||
class IInputSource;
|
class IInputSource;
|
||||||
|
|
||||||
using BackendId = uint32_t;
|
|
||||||
|
|
||||||
struct SourceKey
|
struct SourceKey
|
||||||
{
|
{
|
||||||
BackendId backend = 0;
|
BackendId backend = 0;
|
||||||
|
|||||||
373
idd/LGIdd/transport/TransportConfig.cpp
Normal file
373
idd/LGIdd/transport/TransportConfig.cpp
Normal file
@@ -0,0 +1,373 @@
|
|||||||
|
/**
|
||||||
|
* Looking Glass
|
||||||
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
|
* https://looking-glass.io
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
|
* Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc., 59
|
||||||
|
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "transport/TransportConfig.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <wctype.h>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
enum Field : unsigned
|
||||||
|
{
|
||||||
|
FIELD_ID = 1U << 0,
|
||||||
|
FIELD_KIND = 1U << 1,
|
||||||
|
FIELD_ENABLED = 1U << 2,
|
||||||
|
FIELD_REQUIRED = 1U << 3,
|
||||||
|
FIELD_SERVICES = 1U << 4,
|
||||||
|
FIELD_PRIORITY = 1U << 5,
|
||||||
|
FIELD_SETTINGS = 1U << 6,
|
||||||
|
};
|
||||||
|
|
||||||
|
std::wstring Trim(const std::wstring& value)
|
||||||
|
{
|
||||||
|
size_t begin = 0;
|
||||||
|
size_t end = value.size();
|
||||||
|
while (begin < end && iswspace(value[begin]))
|
||||||
|
++begin;
|
||||||
|
while (end > begin && iswspace(value[end - 1]))
|
||||||
|
--end;
|
||||||
|
return value.substr(begin, end - begin);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Equal(const std::wstring& left, const wchar_t * right)
|
||||||
|
{
|
||||||
|
if (!right)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
size_t index = 0;
|
||||||
|
for (; index < left.size() && right[index]; ++index)
|
||||||
|
if (towlower(left[index]) != towlower(right[index]))
|
||||||
|
return false;
|
||||||
|
return index == left.size() && !right[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParseBool(const std::wstring& value, bool& result)
|
||||||
|
{
|
||||||
|
if (Equal(value, L"true") || value == L"1")
|
||||||
|
{
|
||||||
|
result = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Equal(value, L"false") || value == L"0")
|
||||||
|
{
|
||||||
|
result = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParseId(const std::wstring& value, BackendId& result)
|
||||||
|
{
|
||||||
|
if (value.empty() || value[0] == L'-')
|
||||||
|
return false;
|
||||||
|
|
||||||
|
wchar_t * end = nullptr;
|
||||||
|
errno = 0;
|
||||||
|
const unsigned long long parsed = wcstoull(value.c_str(), &end, 10);
|
||||||
|
if (errno == ERANGE || !end || *end || !parsed || parsed > UINT32_MAX)
|
||||||
|
return false;
|
||||||
|
result = static_cast<BackendId>(parsed);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParsePriority(const std::wstring& value, int32_t& result)
|
||||||
|
{
|
||||||
|
if (value.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
wchar_t * end = nullptr;
|
||||||
|
errno = 0;
|
||||||
|
const long long parsed = wcstoll(value.c_str(), &end, 10);
|
||||||
|
if (errno == ERANGE || !end || *end || parsed < INT32_MIN ||
|
||||||
|
parsed > INT32_MAX)
|
||||||
|
return false;
|
||||||
|
result = static_cast<int32_t>(parsed);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParseKind(const std::wstring& value, std::wstring& result)
|
||||||
|
{
|
||||||
|
if (value.empty() || value.size() > 32)
|
||||||
|
return false;
|
||||||
|
for (wchar_t character : value)
|
||||||
|
if (!iswalnum(character) && character != L'_' && character != L'-')
|
||||||
|
return false;
|
||||||
|
result = value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AddService(const std::wstring& name, uint32_t& services)
|
||||||
|
{
|
||||||
|
uint32_t service = 0;
|
||||||
|
if (Equal(name, L"frame"))
|
||||||
|
service = TRANSPORT_SERVICE_FRAME;
|
||||||
|
else if (Equal(name, L"control"))
|
||||||
|
service = TRANSPORT_SERVICE_CONTROL;
|
||||||
|
else if (Equal(name, L"input"))
|
||||||
|
service = TRANSPORT_SERVICE_INPUT;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (services & service)
|
||||||
|
return false;
|
||||||
|
services |= service;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParseServices(const std::wstring& value, uint32_t& services)
|
||||||
|
{
|
||||||
|
if (Equal(value, L"all"))
|
||||||
|
{
|
||||||
|
services = TRANSPORT_SERVICE_ALL;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Equal(value, L"none"))
|
||||||
|
{
|
||||||
|
services = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
services = 0;
|
||||||
|
size_t begin = 0;
|
||||||
|
while (begin < value.size())
|
||||||
|
{
|
||||||
|
const size_t separator = value.find(L',', begin);
|
||||||
|
const size_t end = separator == std::wstring::npos ?
|
||||||
|
value.size() : separator;
|
||||||
|
if (!AddService(Trim(value.substr(begin, end - begin)), services))
|
||||||
|
return false;
|
||||||
|
if (separator == std::wstring::npos)
|
||||||
|
return true;
|
||||||
|
begin = separator + 1;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SetField(const std::wstring& key, const std::wstring& value,
|
||||||
|
TransportInstance& instance, unsigned& fields)
|
||||||
|
{
|
||||||
|
unsigned field = 0;
|
||||||
|
bool valid = false;
|
||||||
|
if (Equal(key, L"id"))
|
||||||
|
{
|
||||||
|
field = FIELD_ID;
|
||||||
|
valid = ParseId(Trim(value), instance.id);
|
||||||
|
}
|
||||||
|
else if (Equal(key, L"kind"))
|
||||||
|
{
|
||||||
|
field = FIELD_KIND;
|
||||||
|
valid = ParseKind(Trim(value), instance.kind);
|
||||||
|
}
|
||||||
|
else if (Equal(key, L"enabled"))
|
||||||
|
{
|
||||||
|
field = FIELD_ENABLED;
|
||||||
|
valid = ParseBool(Trim(value), instance.enabled);
|
||||||
|
}
|
||||||
|
else if (Equal(key, L"required"))
|
||||||
|
{
|
||||||
|
field = FIELD_REQUIRED;
|
||||||
|
valid = ParseBool(Trim(value), instance.required);
|
||||||
|
}
|
||||||
|
else if (Equal(key, L"services"))
|
||||||
|
{
|
||||||
|
field = FIELD_SERVICES;
|
||||||
|
valid = ParseServices(Trim(value), instance.services);
|
||||||
|
}
|
||||||
|
else if (Equal(key, L"priority"))
|
||||||
|
{
|
||||||
|
field = FIELD_PRIORITY;
|
||||||
|
valid = ParsePriority(Trim(value), instance.priority);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!field || (fields & field) || !valid)
|
||||||
|
return false;
|
||||||
|
fields |= field;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParseInstance(const std::wstring& source,
|
||||||
|
TransportInstance& instance)
|
||||||
|
{
|
||||||
|
const std::wstring& line = source;
|
||||||
|
if (Trim(line).empty() || line.size() > 4096)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
unsigned fields = 0;
|
||||||
|
size_t begin = 0;
|
||||||
|
while (begin < line.size())
|
||||||
|
{
|
||||||
|
const size_t separator = line.find(L';', begin);
|
||||||
|
const size_t end = separator == std::wstring::npos ?
|
||||||
|
line.size() : separator;
|
||||||
|
const std::wstring field = line.substr(begin, end - begin);
|
||||||
|
const size_t equals = field.find(L'=');
|
||||||
|
if (equals == std::wstring::npos)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const std::wstring key = Trim(field.substr(0, equals));
|
||||||
|
if (Equal(key, L"settings"))
|
||||||
|
{
|
||||||
|
if (fields & FIELD_SETTINGS)
|
||||||
|
return false;
|
||||||
|
instance.settings = line.substr(begin + equals + 1);
|
||||||
|
fields |= FIELD_SETTINGS;
|
||||||
|
begin = line.size();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SetField(key, field.substr(equals + 1), instance, fields))
|
||||||
|
return false;
|
||||||
|
if (separator == std::wstring::npos)
|
||||||
|
break;
|
||||||
|
begin = separator + 1;
|
||||||
|
if (begin == line.size())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (fields & (FIELD_ID | FIELD_KIND)) ==
|
||||||
|
(FIELD_ID | FIELD_KIND);
|
||||||
|
}
|
||||||
|
|
||||||
|
int FindKind(const std::wstring& name,
|
||||||
|
const TransportKind * kinds, unsigned kindCount)
|
||||||
|
{
|
||||||
|
for (unsigned i = 0; i < kindCount; ++i)
|
||||||
|
if (kinds[i].name && Equal(name, kinds[i].name))
|
||||||
|
return static_cast<int>(i);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TryResolve(const TransportInstances& instances,
|
||||||
|
const TransportKind * kinds, unsigned kindCount,
|
||||||
|
ResolvedTransportInstances& resolved)
|
||||||
|
{
|
||||||
|
if (!kinds || !kindCount || instances.empty() ||
|
||||||
|
instances.size() > TRANSPORT_MAX_INSTANCES)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ResolvedTransportInstances result;
|
||||||
|
int primary = -1;
|
||||||
|
for (const TransportInstance& instance : instances)
|
||||||
|
{
|
||||||
|
if (!instance.id || instance.kind.empty() ||
|
||||||
|
(instance.services & ~TRANSPORT_SERVICE_ALL))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (const TransportInstance& other : instances)
|
||||||
|
if (&other != &instance && other.id == instance.id)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const int kindIndex = FindKind(instance.kind, kinds, kindCount);
|
||||||
|
if (kindIndex < 0 || !kinds[kindIndex].activeLimit)
|
||||||
|
return false;
|
||||||
|
if (!instance.enabled)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
unsigned active = 0;
|
||||||
|
for (const ResolvedTransportInstance& existing : result)
|
||||||
|
if (existing.kindIndex == static_cast<unsigned>(kindIndex))
|
||||||
|
++active;
|
||||||
|
if (active == kinds[kindIndex].activeLimit ||
|
||||||
|
result.size() == TRANSPORT_MAX_INSTANCES)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ResolvedTransportInstance selected;
|
||||||
|
selected.config = instance;
|
||||||
|
selected.kindIndex = static_cast<unsigned>(kindIndex);
|
||||||
|
if (instance.required &&
|
||||||
|
(instance.services & TRANSPORT_SERVICE_FRAME) &&
|
||||||
|
(primary < 0 || instance.priority >
|
||||||
|
result[primary].config.priority))
|
||||||
|
primary = static_cast<int>(result.size());
|
||||||
|
result.push_back(selected);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (primary < 0)
|
||||||
|
return false;
|
||||||
|
result[primary].primary = true;
|
||||||
|
resolved.swap(result);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TransportInstances DefaultTransportInstances()
|
||||||
|
{
|
||||||
|
TransportInstance instance;
|
||||||
|
instance.id = 1;
|
||||||
|
instance.kind = L"LGMP";
|
||||||
|
instance.enabled = true;
|
||||||
|
instance.required = true;
|
||||||
|
instance.services = TRANSPORT_SERVICE_ALL;
|
||||||
|
instance.priority = 0;
|
||||||
|
|
||||||
|
TransportInstances instances;
|
||||||
|
instances.push_back(instance);
|
||||||
|
return instances;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParseTransportInstances(const std::vector<std::wstring>& entries,
|
||||||
|
TransportInstances& instances)
|
||||||
|
{
|
||||||
|
TransportInstances parsed;
|
||||||
|
if (entries.empty() || entries.size() > TRANSPORT_MAX_INSTANCES)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool hasRequiredFrame = false;
|
||||||
|
for (const std::wstring& entry : entries)
|
||||||
|
{
|
||||||
|
TransportInstance instance;
|
||||||
|
if (!ParseInstance(entry, instance))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (const TransportInstance& existing : parsed)
|
||||||
|
if (existing.id == instance.id)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (instance.enabled && instance.required &&
|
||||||
|
(instance.services & TRANSPORT_SERVICE_FRAME))
|
||||||
|
hasRequiredFrame = true;
|
||||||
|
parsed.push_back(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasRequiredFrame)
|
||||||
|
return false;
|
||||||
|
instances.swap(parsed);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ResolveTransportInstances(const TransportInstances& configured,
|
||||||
|
const TransportKind * kinds, unsigned kindCount,
|
||||||
|
ResolvedTransportInstances& resolved, bool& usedDefaults)
|
||||||
|
{
|
||||||
|
usedDefaults = false;
|
||||||
|
if (TryResolve(configured, kinds, kindCount, resolved))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
usedDefaults = true;
|
||||||
|
const TransportInstances defaults = DefaultTransportInstances();
|
||||||
|
if (TryResolve(defaults, kinds, kindCount, resolved))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
resolved.clear();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
74
idd/LGIdd/transport/TransportConfig.h
Normal file
74
idd/LGIdd/transport/TransportConfig.h
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
/**
|
||||||
|
* Looking Glass
|
||||||
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
|
* https://looking-glass.io
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
|
* Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc., 59
|
||||||
|
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
using BackendId = uint32_t;
|
||||||
|
|
||||||
|
enum TransportService : uint32_t
|
||||||
|
{
|
||||||
|
TRANSPORT_SERVICE_FRAME = 1U << 0,
|
||||||
|
TRANSPORT_SERVICE_CONTROL = 1U << 1,
|
||||||
|
TRANSPORT_SERVICE_INPUT = 1U << 2,
|
||||||
|
TRANSPORT_SERVICE_ALL = TRANSPORT_SERVICE_FRAME |
|
||||||
|
TRANSPORT_SERVICE_CONTROL | TRANSPORT_SERVICE_INPUT,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TransportInstance
|
||||||
|
{
|
||||||
|
BackendId id = 0;
|
||||||
|
std::wstring kind;
|
||||||
|
bool enabled = true;
|
||||||
|
bool required = false;
|
||||||
|
uint32_t services = TRANSPORT_SERVICE_ALL;
|
||||||
|
int32_t priority = 0;
|
||||||
|
std::wstring settings;
|
||||||
|
};
|
||||||
|
|
||||||
|
using TransportInstances = std::vector<TransportInstance>;
|
||||||
|
|
||||||
|
static const unsigned TRANSPORT_MAX_INSTANCES = 8;
|
||||||
|
|
||||||
|
struct TransportKind
|
||||||
|
{
|
||||||
|
const wchar_t * name;
|
||||||
|
unsigned activeLimit;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ResolvedTransportInstance
|
||||||
|
{
|
||||||
|
TransportInstance config;
|
||||||
|
unsigned kindIndex = 0;
|
||||||
|
bool primary = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
using ResolvedTransportInstances =
|
||||||
|
std::vector<ResolvedTransportInstance>;
|
||||||
|
|
||||||
|
TransportInstances DefaultTransportInstances();
|
||||||
|
bool ParseTransportInstances(const std::vector<std::wstring>& entries,
|
||||||
|
TransportInstances& instances);
|
||||||
|
bool ResolveTransportInstances(const TransportInstances& configured,
|
||||||
|
const TransportKind * kinds, unsigned kindCount,
|
||||||
|
ResolvedTransportInstances& resolved, bool& usedDefaults);
|
||||||
@@ -20,21 +20,66 @@
|
|||||||
|
|
||||||
#include "transport/TransportFactory.h"
|
#include "transport/TransportFactory.h"
|
||||||
|
|
||||||
|
#include "CDebug.h"
|
||||||
|
#include "config/CSettings.h"
|
||||||
#include "transport/CTransportManager.h"
|
#include "transport/CTransportManager.h"
|
||||||
#include "transport/lgmp/CLGMPTransport.h"
|
#include "transport/lgmp/CLGMPTransport.h"
|
||||||
|
|
||||||
#include <new>
|
#include <new>
|
||||||
|
|
||||||
static std::unique_ptr<ITransport> CreateLGMP()
|
namespace
|
||||||
{
|
{
|
||||||
return std::unique_ptr<ITransport>(new (std::nothrow) CLGMPTransport());
|
struct Provider
|
||||||
|
{
|
||||||
|
CTransportManager::CreateFn create;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::unique_ptr<ITransport> CreateLGMP(
|
||||||
|
const TransportInstance& config)
|
||||||
|
{
|
||||||
|
return std::unique_ptr<ITransport>(
|
||||||
|
new (std::nothrow) CLGMPTransport(config));
|
||||||
|
}
|
||||||
|
|
||||||
|
const TransportKind KINDS[] =
|
||||||
|
{
|
||||||
|
{ L"LGMP", 1 },
|
||||||
|
};
|
||||||
|
|
||||||
|
const Provider PROVIDERS[] =
|
||||||
|
{
|
||||||
|
{ CreateLGMP },
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(ARRAYSIZE(KINDS) == ARRAYSIZE(PROVIDERS),
|
||||||
|
"Every transport kind must have a provider");
|
||||||
|
|
||||||
|
std::unique_ptr<CTransportManager> Build(
|
||||||
|
const ResolvedTransportInstances& instances)
|
||||||
|
{
|
||||||
|
std::unique_ptr<CTransportManager> manager(
|
||||||
|
new (std::nothrow) CTransportManager());
|
||||||
|
if (!manager)
|
||||||
|
return std::unique_ptr<CTransportManager>();
|
||||||
|
|
||||||
|
for (const ResolvedTransportInstance& instance : instances)
|
||||||
|
if (!manager->Add(instance.config, instance.primary,
|
||||||
|
PROVIDERS[instance.kindIndex].create))
|
||||||
|
return std::unique_ptr<CTransportManager>();
|
||||||
|
return manager;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<CTransportManager> CreateTransport()
|
std::unique_ptr<CTransportManager> CreateTransport()
|
||||||
{
|
{
|
||||||
std::unique_ptr<CTransportManager> manager(
|
TransportInstances instances = g_settings.LoadTransportInstances();
|
||||||
new (std::nothrow) CTransportManager());
|
ResolvedTransportInstances resolved;
|
||||||
if (!manager || !manager->Add(1, "LGMP", true, true, CreateLGMP))
|
bool usedDefaults = false;
|
||||||
|
if (!ResolveTransportInstances(instances, KINDS, ARRAYSIZE(KINDS),
|
||||||
|
resolved, usedDefaults))
|
||||||
return std::unique_ptr<CTransportManager>();
|
return std::unique_ptr<CTransportManager>();
|
||||||
return manager;
|
if (usedDefaults)
|
||||||
|
DEBUG_WARN("Unsupported transport instance configuration; using defaults");
|
||||||
|
|
||||||
|
return Build(resolved);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,7 +48,8 @@ static bool TranslateFrameScheduleFlags(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
CLGMPTransport::CLGMPTransport() :
|
CLGMPTransport::CLGMPTransport(const TransportInstance& config) :
|
||||||
|
m_config(config),
|
||||||
m_control(m_host),
|
m_control(m_host),
|
||||||
m_frames(m_host, m_ivshmem),
|
m_frames(m_host, m_ivshmem),
|
||||||
m_input(m_host)
|
m_input(m_host)
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
class CLGMPTransport final : public ITransport
|
class CLGMPTransport final : public ITransport
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
TransportInstance m_config;
|
||||||
// Keep this declaration order. Destruction must release frame and control
|
// Keep this declaration order. Destruction must release frame and control
|
||||||
// allocations before the LGMP host and its IVSHMEM mapping are destroyed.
|
// allocations before the LGMP host and its IVSHMEM mapping are destroyed.
|
||||||
CIVSHMEM m_ivshmem;
|
CIVSHMEM m_ivshmem;
|
||||||
@@ -44,7 +45,7 @@ private:
|
|||||||
std::atomic<bool> m_ready = false;
|
std::atomic<bool> m_ready = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CLGMPTransport();
|
explicit CLGMPTransport(const TransportInstance& config);
|
||||||
~CLGMPTransport() override = default;
|
~CLGMPTransport() override = default;
|
||||||
|
|
||||||
CLGMPTransport(const CLGMPTransport&) = delete;
|
CLGMPTransport(const CLGMPTransport&) = delete;
|
||||||
|
|||||||
Reference in New Issue
Block a user