mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-11-12 14:57:20 +00:00
[client/idd] network: publish guest information
This commit is contained in:
@@ -191,6 +191,7 @@ struct NetworkConnection
|
||||
bool authResultReceived;
|
||||
bool authKeyValid;
|
||||
bool capabilitiesComplete;
|
||||
bool guestInfoReceived;
|
||||
bool connectFailed;
|
||||
uint32_t expectedCapabilities;
|
||||
uint32_t receivedCapabilities;
|
||||
@@ -263,6 +264,50 @@ static char * networkEndpoint(const char * address, uint16_t port)
|
||||
return endpoint;
|
||||
}
|
||||
|
||||
static bool networkGuestText(char * destination, size_t capacity,
|
||||
const uint8_t * source, uint16_t length)
|
||||
{
|
||||
if (!destination || !capacity || length >= capacity ||
|
||||
(length && (!source || memchr(source, 0, length))))
|
||||
return false;
|
||||
|
||||
if (length)
|
||||
memcpy(destination, source, length);
|
||||
destination[length] = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool networkGuestOS(LGNetCoreGuestOS source,
|
||||
LG_TransportGuestOS * destination)
|
||||
{
|
||||
if (!destination)
|
||||
return false;
|
||||
|
||||
switch (source)
|
||||
{
|
||||
case LG_NET_CORE_GUEST_OS_LINUX:
|
||||
*destination = LG_TRANSPORT_OS_LINUX;
|
||||
return true;
|
||||
|
||||
case LG_NET_CORE_GUEST_OS_BSD:
|
||||
*destination = LG_TRANSPORT_OS_BSD;
|
||||
return true;
|
||||
|
||||
case LG_NET_CORE_GUEST_OS_OSX:
|
||||
*destination = LG_TRANSPORT_OS_OSX;
|
||||
return true;
|
||||
|
||||
case LG_NET_CORE_GUEST_OS_WINDOWS:
|
||||
*destination = LG_TRANSPORT_OS_WINDOWS;
|
||||
return true;
|
||||
|
||||
case LG_NET_CORE_GUEST_OS_OTHER:
|
||||
*destination = LG_TRANSPORT_OS_OTHER;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool networkCapabilityOfferValid(
|
||||
const LGNetCapability * capability)
|
||||
{
|
||||
@@ -1086,6 +1131,7 @@ static bool networkConnectionReadyToActivateNL(
|
||||
return this->helloAcknowledged &&
|
||||
this->authenticationComplete &&
|
||||
this->capabilitiesComplete &&
|
||||
this->guestInfoReceived &&
|
||||
this->receivedCapabilities == this->expectedCapabilities &&
|
||||
networkConnectionRequiredCapabilitiesSelected(this);
|
||||
}
|
||||
@@ -1438,16 +1484,75 @@ static bool networkConnectionHandleCore(NetworkConnection * this,
|
||||
if (packet->envelope.flags != responseFlags ||
|
||||
packet->envelope.requestID != NETWORK_HELLO_REQUEST_ID ||
|
||||
packet->envelope.componentEpoch != 0 ||
|
||||
packet->envelope.sessionEpoch != sessionEpoch)
|
||||
packet->envelope.sessionEpoch != sessionEpoch ||
|
||||
packet->envelope.serviceVersion != LG_NET_CORE_VERSION_CURRENT)
|
||||
return false;
|
||||
return networkConnectionHandleCapability(this, packet);
|
||||
|
||||
case LG_NET_CORE_MESSAGE_GUEST_INFO:
|
||||
{
|
||||
LGNetCoreGuestInfo info;
|
||||
if (packet->envelope.flags != responseFlags ||
|
||||
packet->envelope.requestID != NETWORK_HELLO_REQUEST_ID ||
|
||||
packet->envelope.componentEpoch != 0 ||
|
||||
packet->envelope.sessionEpoch != sessionEpoch ||
|
||||
packet->envelope.serviceVersion != LG_NET_CORE_VERSION_CURRENT ||
|
||||
lgNetCoreGuestInfoDecode(&info,
|
||||
packet->payload, packet->payloadLength) != LG_NET_PARSE_OK)
|
||||
return false;
|
||||
|
||||
LG_TransportSession guest = { 0 };
|
||||
if (!networkGuestOS(info.os, &guest.os) ||
|
||||
!networkGuestText(guest.version, sizeof(guest.version),
|
||||
info.version, info.versionLength) ||
|
||||
!networkGuestText(guest.osName, sizeof(guest.osName),
|
||||
info.osName, info.osNameLength) ||
|
||||
!networkGuestText(guest.capture, sizeof(guest.capture),
|
||||
info.capture, info.captureLength) ||
|
||||
!networkGuestText(guest.cpuModel, sizeof(guest.cpuModel),
|
||||
info.cpuModel, info.cpuModelLength))
|
||||
return false;
|
||||
memcpy(guest.uuid, info.uuid, sizeof(guest.uuid));
|
||||
guest.uuidValid = networkBytesNonzero(guest.uuid, sizeof(guest.uuid));
|
||||
guest.cpus = info.processors;
|
||||
guest.cores = info.cores;
|
||||
guest.sockets = info.sockets;
|
||||
|
||||
LG_LOCK(this->lock);
|
||||
const bool valid = this->helloAcknowledged &&
|
||||
this->authenticationComplete && !this->capabilitiesComplete &&
|
||||
!this->guestInfoReceived &&
|
||||
this->receivedCapabilities == this->expectedCapabilities &&
|
||||
networkConnectionRequiredCapabilitiesSelected(this);
|
||||
if (valid)
|
||||
{
|
||||
memcpy(this->session.version, guest.version,
|
||||
sizeof(this->session.version));
|
||||
memcpy(this->session.uuid, guest.uuid, sizeof(this->session.uuid));
|
||||
memcpy(this->session.osName, guest.osName,
|
||||
sizeof(this->session.osName));
|
||||
memcpy(this->session.capture, guest.capture,
|
||||
sizeof(this->session.capture));
|
||||
memcpy(this->session.cpuModel, guest.cpuModel,
|
||||
sizeof(this->session.cpuModel));
|
||||
this->session.uuidValid = guest.uuidValid;
|
||||
this->session.os = guest.os;
|
||||
this->session.cpus = guest.cpus;
|
||||
this->session.cores = guest.cores;
|
||||
this->session.sockets = guest.sockets;
|
||||
this->guestInfoReceived = true;
|
||||
}
|
||||
LG_UNLOCK(this->lock);
|
||||
return valid;
|
||||
}
|
||||
|
||||
case LG_NET_CORE_MESSAGE_CAPABILITIES_DONE:
|
||||
{
|
||||
if (packet->envelope.flags != responseFlags ||
|
||||
packet->envelope.requestID != NETWORK_HELLO_REQUEST_ID ||
|
||||
packet->envelope.componentEpoch != 0 ||
|
||||
packet->envelope.sessionEpoch != sessionEpoch ||
|
||||
packet->envelope.serviceVersion != LG_NET_CORE_VERSION_CURRENT ||
|
||||
packet->payloadLength)
|
||||
return false;
|
||||
|
||||
@@ -1455,6 +1560,7 @@ static bool networkConnectionHandleCore(NetworkConnection * this,
|
||||
LG_LOCK(this->lock);
|
||||
const bool valid = !this->capabilitiesComplete &&
|
||||
this->helloAcknowledged &&
|
||||
this->guestInfoReceived &&
|
||||
this->receivedCapabilities == this->expectedCapabilities &&
|
||||
networkConnectionRequiredCapabilitiesSelected(this);
|
||||
this->capabilitiesComplete = valid;
|
||||
@@ -2689,6 +2795,7 @@ LG_TransportStatus networkConnectionConnect(NetworkConnection * this,
|
||||
this->helloAcknowledged = false;
|
||||
this->authenticationComplete = false;
|
||||
this->capabilitiesComplete = false;
|
||||
this->guestInfoReceived = false;
|
||||
this->connectFailed = false;
|
||||
this->expectedCapabilities = 0;
|
||||
this->receivedCapabilities = 0;
|
||||
@@ -2713,8 +2820,6 @@ LG_TransportStatus networkConnectionConnect(NetworkConnection * this,
|
||||
memset(this->serviceMaxDatagram, 0, sizeof(this->serviceMaxDatagram));
|
||||
lgNetStreamParserReset(&this->receiveParser);
|
||||
memset(&this->session, 0, sizeof(this->session));
|
||||
snprintf(this->session.version, sizeof(this->session.version),
|
||||
"LG network protocol %u", LG_NET_PROTOCOL_VERSION_CURRENT);
|
||||
snprintf(this->session.name, sizeof(this->session.name),
|
||||
"%s", this->endpoint);
|
||||
this->session.os = LG_TRANSPORT_OS_OTHER;
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
#include "CDebug.h"
|
||||
#include "CSRWLock.h"
|
||||
#include "platform/CPlatformInfo.h"
|
||||
#include "VersionInfo.h"
|
||||
#include <LGProtocol/NetworkAuth.h>
|
||||
#include <LGProtocol/NetworkIdentity.h>
|
||||
@@ -174,6 +175,35 @@ namespace
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t UTF8PrefixLength(const uint8_t * value, size_t length,
|
||||
size_t maximum)
|
||||
{
|
||||
size_t prefix = (std::min)(length, maximum);
|
||||
while (prefix && prefix < length &&
|
||||
(value[prefix] & UINT8_C(0xC0)) == UINT8_C(0x80))
|
||||
--prefix;
|
||||
|
||||
return prefix;
|
||||
}
|
||||
|
||||
size_t ConsumeUTF8Field(const uint8_t * value, size_t length,
|
||||
size_t fieldMaximum, size_t& remaining)
|
||||
{
|
||||
const size_t maximum = (std::min)(fieldMaximum, remaining);
|
||||
const size_t result = UTF8PrefixLength(value, length, maximum);
|
||||
remaining -= result;
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t TopologyCount(int count)
|
||||
{
|
||||
if (count <= 0)
|
||||
return 0;
|
||||
|
||||
return static_cast<uint8_t>((std::min)(count,
|
||||
static_cast<int>(UINT8_MAX)));
|
||||
}
|
||||
|
||||
bool MakeAddress(const std::wstring& source, uint16_t port,
|
||||
QUIC_ADDR& address)
|
||||
{
|
||||
@@ -2059,6 +2089,71 @@ retry:
|
||||
return sent;
|
||||
}
|
||||
|
||||
bool SendGuestInformation(Connection& connection, uint64_t requestID)
|
||||
{
|
||||
static const char CAPTURE[] = "Looking Glass IDD Driver";
|
||||
|
||||
uint32_t maxPayload;
|
||||
{
|
||||
CSRWSharedLock guard(connection.lock);
|
||||
if (connection.closing)
|
||||
return false;
|
||||
maxPayload = connection.maxPayload;
|
||||
}
|
||||
if (maxPayload < LG_NET_CORE_GUEST_INFO_HEADER_WIRE_SIZE)
|
||||
return false;
|
||||
|
||||
const std::string& osName = CPlatformInfo::GetProductName();
|
||||
const std::string& cpuModel = CPlatformInfo::GetCPUModel();
|
||||
LGNetCoreGuestInfo info = {};
|
||||
memcpy(info.uuid, CPlatformInfo::GetUUID(), sizeof(info.uuid));
|
||||
info.os = LG_NET_CORE_GUEST_OS_WINDOWS;
|
||||
info.processors = TopologyCount(CPlatformInfo::GetProcCount());
|
||||
info.cores = TopologyCount(CPlatformInfo::GetCoreCount());
|
||||
info.sockets = TopologyCount(CPlatformInfo::GetSocketCount());
|
||||
info.version = reinterpret_cast<const uint8_t *>(LG_VERSION_STR);
|
||||
info.osName = reinterpret_cast<const uint8_t *>(osName.data());
|
||||
info.capture = reinterpret_cast<const uint8_t *>(CAPTURE);
|
||||
info.cpuModel = reinterpret_cast<const uint8_t *>(cpuModel.data());
|
||||
|
||||
size_t remaining = maxPayload -
|
||||
LG_NET_CORE_GUEST_INFO_HEADER_WIRE_SIZE;
|
||||
info.versionLength = static_cast<uint16_t>(ConsumeUTF8Field(
|
||||
info.version, strlen(LG_VERSION_STR),
|
||||
LG_NET_CORE_GUEST_MAX_VERSION_LENGTH, remaining));
|
||||
info.osNameLength = static_cast<uint16_t>(ConsumeUTF8Field(
|
||||
info.osName, osName.size(), LG_NET_CORE_GUEST_MAX_OS_NAME_LENGTH,
|
||||
remaining));
|
||||
info.captureLength = static_cast<uint16_t>(ConsumeUTF8Field(
|
||||
info.capture, strlen(CAPTURE), LG_NET_CORE_GUEST_MAX_CAPTURE_LENGTH,
|
||||
remaining));
|
||||
info.cpuModelLength = static_cast<uint16_t>(ConsumeUTF8Field(
|
||||
info.cpuModel, cpuModel.size(),
|
||||
LG_NET_CORE_GUEST_MAX_CPU_MODEL_LENGTH, remaining));
|
||||
|
||||
const size_t payloadSize = lgNetCoreGuestInfoSize(&info);
|
||||
if (!payloadSize || payloadSize > maxPayload)
|
||||
return false;
|
||||
|
||||
std::vector<uint8_t> payload;
|
||||
try
|
||||
{
|
||||
payload.resize(payloadSize);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return lgNetCoreGuestInfoEncode(
|
||||
payload.data(), payload.size(), &info) &&
|
||||
SendPacket(connection, LG_NET_SERVICE_CORE,
|
||||
LG_NET_CORE_MESSAGE_GUEST_INFO,
|
||||
LG_NET_ENVELOPE_RESPONSE | LG_NET_ENVELOPE_FINAL,
|
||||
0, requestID, payload.data(),
|
||||
static_cast<uint32_t>(payload.size()));
|
||||
}
|
||||
|
||||
bool PublishCapabilities(Connection& connection)
|
||||
{
|
||||
LGNetCapability selected[NETWORK_SERVICE_COUNT] = {};
|
||||
@@ -2148,6 +2243,8 @@ retry:
|
||||
return false;
|
||||
if (videoSelected && !video.PeerConnected(VideoPeer(connection)))
|
||||
return false;
|
||||
if (!SendGuestInformation(connection, requestID))
|
||||
return false;
|
||||
if (!SendPacket(connection, LG_NET_SERVICE_CORE,
|
||||
LG_NET_CORE_MESSAGE_CAPABILITIES_DONE,
|
||||
LG_NET_ENVELOPE_RESPONSE | LG_NET_ENVELOPE_FINAL,
|
||||
|
||||
Submodule repos/LGProtocol updated: 82f05ec664...a2a41197d0
Reference in New Issue
Block a user