mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-08-22 15:11:31 +00:00
[idd] clipboard: remove stream payload restaging
Keep inbound stream payloads in the bounded stream-target window while the Helper channel is busy and publish directly from those buffers. Retain the pending target only for LGMP queue controls. Their credits remain outstanding across retries. This removes one full payload copy per client-to-Helper record without changing delivery order, backpressure, or reset behavior.
This commit is contained in:
@@ -596,8 +596,9 @@ void CLGMPClipboardTransport::QueueFileDisconnect()
|
|||||||
bool CLGMPClipboardTransport::QueueInternalTarget(
|
bool CLGMPClipboardTransport::QueueInternalTarget(
|
||||||
const KVMFRClipboardMessage& record)
|
const KVMFRClipboardMessage& record)
|
||||||
{
|
{
|
||||||
if (!m_pendingTarget.valid && !m_internalTargetCount)
|
if (!m_pendingTarget.valid && !m_streamTargetBusy &&
|
||||||
return BeginTarget(record, nullptr, false);
|
!m_internalTargetCount)
|
||||||
|
return BeginTarget(record, false);
|
||||||
if (m_internalTargetCount == INTERNAL_TARGET_COUNT)
|
if (m_internalTargetCount == INTERNAL_TARGET_COUNT)
|
||||||
{
|
{
|
||||||
m_failed = true;
|
m_failed = true;
|
||||||
@@ -609,14 +610,15 @@ bool CLGMPClipboardTransport::QueueInternalTarget(
|
|||||||
|
|
||||||
bool CLGMPClipboardTransport::PumpInternalTarget()
|
bool CLGMPClipboardTransport::PumpInternalTarget()
|
||||||
{
|
{
|
||||||
if (m_pendingTarget.valid || !m_internalTargetCount)
|
if (m_pendingTarget.valid || m_streamTargetBusy ||
|
||||||
|
!m_internalTargetCount)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
const KVMFRClipboardMessage record = m_internalTarget[0];
|
const KVMFRClipboardMessage record = m_internalTarget[0];
|
||||||
for (unsigned i = 1; i < m_internalTargetCount; ++i)
|
for (unsigned i = 1; i < m_internalTargetCount; ++i)
|
||||||
m_internalTarget[i - 1] = m_internalTarget[i];
|
m_internalTarget[i - 1] = m_internalTarget[i];
|
||||||
m_internalTarget[--m_internalTargetCount] = {};
|
m_internalTarget[--m_internalTargetCount] = {};
|
||||||
return BeginTarget(record, nullptr, false);
|
return BeginTarget(record, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CLGMPClipboardTransport::ClearStreamTargets()
|
void CLGMPClipboardTransport::ClearStreamTargets()
|
||||||
@@ -625,6 +627,24 @@ void CLGMPClipboardTransport::ClearStreamTargets()
|
|||||||
target.Clear();
|
target.Clear();
|
||||||
m_streamTargetHead = 0;
|
m_streamTargetHead = 0;
|
||||||
m_streamTargetCount = 0;
|
m_streamTargetCount = 0;
|
||||||
|
m_streamTargetBusy = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CLGMPClipboardTransport::ClearQueuedStreamTargets()
|
||||||
|
{
|
||||||
|
if (!m_streamTargetBusy)
|
||||||
|
{
|
||||||
|
ClearStreamTargets();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The BUSY head has already crossed the target boundary and must receive
|
||||||
|
// the same drain treatment as a BUSY PendingTarget. Only discard records
|
||||||
|
// which have not yet been presented to the target.
|
||||||
|
for (unsigned i = 1; i < m_streamTargetCount; ++i)
|
||||||
|
m_streamTarget[
|
||||||
|
(m_streamTargetHead + i) % STREAM_TARGET_COUNT].Clear();
|
||||||
|
m_streamTargetCount = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CLGMPClipboardTransport::QueueStreamTarget(
|
bool CLGMPClipboardTransport::QueueStreamTarget(
|
||||||
@@ -643,17 +663,79 @@ bool CLGMPClipboardTransport::QueueStreamTarget(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CLGMPClipboardTransport::ProcessStreamTarget(
|
void CLGMPClipboardTransport::PopStreamTarget()
|
||||||
const KVMFRClipboardMessage& record, const uint8_t * data)
|
|
||||||
{
|
{
|
||||||
|
StreamTarget& target = m_streamTarget[m_streamTargetHead];
|
||||||
|
target.Clear();
|
||||||
|
m_streamTargetHead =
|
||||||
|
(m_streamTargetHead + 1) % STREAM_TARGET_COUNT;
|
||||||
|
--m_streamTargetCount;
|
||||||
|
m_streamTargetBusy = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CLGMPClipboardTransport::PublishStreamTarget()
|
||||||
|
{
|
||||||
|
StreamTarget& target = m_streamTarget[m_streamTargetHead];
|
||||||
|
const ClipboardChannelResult result = m_target ?
|
||||||
|
m_target->SendClipboard(target.record,
|
||||||
|
target.record.length ? target.data : nullptr) :
|
||||||
|
ClipboardChannelResult::FAILED;
|
||||||
|
if (result == ClipboardChannelResult::BUSY)
|
||||||
|
{
|
||||||
|
m_streamTargetBusy = true;
|
||||||
|
if (m_ownerClientID)
|
||||||
|
RenewLease();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == ClipboardChannelResult::ACCEPTED)
|
||||||
|
{
|
||||||
|
ApplyInbound(target.record);
|
||||||
|
if (m_ownerClientID && !m_ownerReleasing)
|
||||||
|
RenewLease();
|
||||||
|
}
|
||||||
|
PopStreamTarget();
|
||||||
|
|
||||||
|
if (result == ClipboardChannelResult::FAILED)
|
||||||
|
{
|
||||||
|
ReleaseOwner("Helper delivery failed", false);
|
||||||
|
m_failed = true;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CLGMPClipboardTransport::RetryStreamTarget()
|
||||||
|
{
|
||||||
|
if (!m_streamTargetBusy || m_pendingTarget.valid)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// The retained head is already validated and stamped. Retry it exactly;
|
||||||
|
// owner-release state may have changed while the target was BUSY.
|
||||||
|
m_streamTargetBusy = false;
|
||||||
|
return PublishStreamTarget();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CLGMPClipboardTransport::ProcessStreamTarget()
|
||||||
|
{
|
||||||
|
StreamTarget& target = m_streamTarget[m_streamTargetHead];
|
||||||
|
const KVMFRClipboardMessage record = target.record;
|
||||||
if (!m_ownerClientID)
|
if (!m_ownerClientID)
|
||||||
|
{
|
||||||
|
PopStreamTarget();
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
if (m_ownerReleasing && !m_releaseClearHelper)
|
if (m_ownerReleasing && !m_releaseClearHelper)
|
||||||
|
{
|
||||||
|
PopStreamTarget();
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (record.type == KVMFR_CLIPBOARD_MESSAGE_DATA &&
|
if (record.type == KVMFR_CLIPBOARD_MESSAGE_DATA &&
|
||||||
record.transfer == m_discardClientToHelper)
|
record.transfer == m_discardClientToHelper)
|
||||||
|
{
|
||||||
|
PopStreamTarget();
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
const bool fileData =
|
const bool fileData =
|
||||||
record.type == KVMFR_CLIPBOARD_MESSAGE_FILE_DATA;
|
record.type == KVMFR_CLIPBOARD_MESSAGE_FILE_DATA;
|
||||||
@@ -666,6 +748,7 @@ bool CLGMPClipboardTransport::ProcessStreamTarget(
|
|||||||
ValidateChunk(m_clientToHelper, record));
|
ValidateChunk(m_clientToHelper, record));
|
||||||
if (!validData)
|
if (!validData)
|
||||||
{
|
{
|
||||||
|
PopStreamTarget();
|
||||||
ReleaseOwner("invalid clipboard stream data", true);
|
ReleaseOwner("invalid clipboard stream data", true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -673,32 +756,21 @@ bool CLGMPClipboardTransport::ProcessStreamTarget(
|
|||||||
if (!m_ownerReleasing)
|
if (!m_ownerReleasing)
|
||||||
RenewLease();
|
RenewLease();
|
||||||
if (staleFileData)
|
if (staleFileData)
|
||||||
return true;
|
|
||||||
|
|
||||||
KVMFRClipboardMessage forwarded = record;
|
|
||||||
forwarded.generation = m_endpointGeneration;
|
|
||||||
if (!BeginTarget(forwarded, data, false))
|
|
||||||
{
|
{
|
||||||
ReleaseOwner("failed to stage clipboard stream data", true);
|
PopStreamTarget();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
|
target.record.generation = m_endpointGeneration;
|
||||||
|
return PublishStreamTarget();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CLGMPClipboardTransport::PumpStreamTarget()
|
bool CLGMPClipboardTransport::PumpStreamTarget()
|
||||||
{
|
{
|
||||||
while (!m_pendingTarget.valid && m_streamTargetCount)
|
while (!m_pendingTarget.valid && !m_streamTargetBusy &&
|
||||||
{
|
m_streamTargetCount)
|
||||||
StreamTarget& target = m_streamTarget[m_streamTargetHead];
|
if (!ProcessStreamTarget())
|
||||||
const KVMFRClipboardMessage record = target.record;
|
|
||||||
const uint8_t * data = record.length ? target.data : nullptr;
|
|
||||||
target.Clear();
|
|
||||||
m_streamTargetHead =
|
|
||||||
(m_streamTargetHead + 1) % STREAM_TARGET_COUNT;
|
|
||||||
--m_streamTargetCount;
|
|
||||||
if (!ProcessStreamTarget(record, data))
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -820,7 +892,7 @@ void CLGMPClipboardTransport::FinishOwnerRelease()
|
|||||||
m_ownerDeadline = 0;
|
m_ownerDeadline = 0;
|
||||||
m_ownerDrainDeadline = 0;
|
m_ownerDrainDeadline = 0;
|
||||||
m_replayPending = false;
|
m_replayPending = false;
|
||||||
ClearStreamTargets();
|
ClearQueuedStreamTargets();
|
||||||
m_discardClientToHelper = 0;
|
m_discardClientToHelper = 0;
|
||||||
m_clientToHelper.Clear();
|
m_clientToHelper.Clear();
|
||||||
m_helperToClient.Clear();
|
m_helperToClient.Clear();
|
||||||
@@ -1312,19 +1384,14 @@ void CLGMPClipboardTransport::ApplyOutbound(
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool CLGMPClipboardTransport::BeginTarget(
|
bool CLGMPClipboardTransport::BeginTarget(
|
||||||
const KVMFRClipboardMessage& message, const uint8_t * data,
|
const KVMFRClipboardMessage& message, bool acknowledge)
|
||||||
bool acknowledge)
|
|
||||||
{
|
{
|
||||||
if (m_pendingTarget.valid ||
|
if (m_pendingTarget.valid || message.length)
|
||||||
(message.length && !data) ||
|
|
||||||
message.length > KVMFR_CLIPBOARD_DATA_BYTES)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
m_pendingTarget.valid = true;
|
m_pendingTarget.valid = true;
|
||||||
m_pendingTarget.acknowledge = acknowledge;
|
m_pendingTarget.acknowledge = acknowledge;
|
||||||
m_pendingTarget.record = message;
|
m_pendingTarget.record = message;
|
||||||
if (message.length)
|
|
||||||
memcpy(m_pendingTarget.data, data, message.length);
|
|
||||||
return RetryTarget();
|
return RetryTarget();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1352,10 +1419,8 @@ bool CLGMPClipboardTransport::RetryTarget()
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
const bool acknowledge = m_pendingTarget.acknowledge;
|
const bool acknowledge = m_pendingTarget.acknowledge;
|
||||||
const uint8_t * data = m_pendingTarget.record.length ?
|
|
||||||
m_pendingTarget.data : nullptr;
|
|
||||||
const ClipboardChannelResult result = m_target ?
|
const ClipboardChannelResult result = m_target ?
|
||||||
m_target->SendClipboard(m_pendingTarget.record, data) :
|
m_target->SendClipboard(m_pendingTarget.record, nullptr) :
|
||||||
ClipboardChannelResult::FAILED;
|
ClipboardChannelResult::FAILED;
|
||||||
if (result == ClipboardChannelResult::BUSY)
|
if (result == ClipboardChannelResult::BUSY)
|
||||||
{
|
{
|
||||||
@@ -1493,7 +1558,7 @@ bool CLGMPClipboardTransport::ProcessMessage(
|
|||||||
KVMFRClipboardMessage forwarded = message;
|
KVMFRClipboardMessage forwarded = message;
|
||||||
forwarded.generation = m_endpointGeneration;
|
forwarded.generation = m_endpointGeneration;
|
||||||
RenewLease();
|
RenewLease();
|
||||||
BeginTarget(forwarded, nullptr, true);
|
BeginTarget(forwarded, true);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1896,6 +1961,7 @@ void CLGMPClipboardTransport::Thread()
|
|||||||
if (m_ownerClientID && !OwnerSubscribed())
|
if (m_ownerClientID && !OwnerSubscribed())
|
||||||
{
|
{
|
||||||
DropPendingTarget();
|
DropPendingTarget();
|
||||||
|
ClearStreamTargets();
|
||||||
ReleaseOwner("subscriber disappeared", true, true);
|
ReleaseOwner("subscriber disappeared", true, true);
|
||||||
}
|
}
|
||||||
else if (m_ownerClientID && !m_ownerReleasing &&
|
else if (m_ownerClientID && !m_ownerReleasing &&
|
||||||
@@ -1904,9 +1970,11 @@ void CLGMPClipboardTransport::Thread()
|
|||||||
|
|
||||||
// A restarted client can reuse dataset and transfer IDs. Deliver every
|
// A restarted client can reuse dataset and transfer IDs. Deliver every
|
||||||
// old-owner cleanup record before admitting messages from a new owner.
|
// old-owner cleanup record before admitting messages from a new owner.
|
||||||
if (!RetryTarget() || !PumpInternalTarget() ||
|
if (!RetryTarget() || !RetryStreamTarget() ||
|
||||||
|
!PumpInternalTarget() ||
|
||||||
!PumpStreamTarget() ||
|
!PumpStreamTarget() ||
|
||||||
(m_internalTargetCount == 0 && !DrainMessage()) ||
|
(!m_streamTargetBusy && m_internalTargetCount == 0 &&
|
||||||
|
!DrainMessage()) ||
|
||||||
!DrainStream(streamReceived) ||
|
!DrainStream(streamReceived) ||
|
||||||
!RetryOwnerRelease() ||
|
!RetryOwnerRelease() ||
|
||||||
!PublishStatus() ||
|
!PublishStatus() ||
|
||||||
@@ -1986,6 +2054,7 @@ void CLGMPClipboardTransport::Thread()
|
|||||||
{
|
{
|
||||||
CSRWExclusiveLock lock(m_lock);
|
CSRWExclusiveLock lock(m_lock);
|
||||||
DropPendingTarget();
|
DropPendingTarget();
|
||||||
|
ClearStreamTargets();
|
||||||
if (m_ownerClientID)
|
if (m_ownerClientID)
|
||||||
ReleaseOwner("transport stopped", false, true);
|
ReleaseOwner("transport stopped", false, true);
|
||||||
target = m_target;
|
target = m_target;
|
||||||
|
|||||||
@@ -83,7 +83,6 @@ private:
|
|||||||
bool valid = false;
|
bool valid = false;
|
||||||
bool acknowledge = false;
|
bool acknowledge = false;
|
||||||
KVMFRClipboardMessage record = {};
|
KVMFRClipboardMessage record = {};
|
||||||
uint8_t data[KVMFR_CLIPBOARD_DATA_BYTES] = {};
|
|
||||||
|
|
||||||
void Clear()
|
void Clear()
|
||||||
{
|
{
|
||||||
@@ -150,6 +149,7 @@ private:
|
|||||||
StreamTarget m_streamTarget[STREAM_TARGET_COUNT];
|
StreamTarget m_streamTarget[STREAM_TARGET_COUNT];
|
||||||
unsigned m_streamTargetHead = 0;
|
unsigned m_streamTargetHead = 0;
|
||||||
unsigned m_streamTargetCount = 0;
|
unsigned m_streamTargetCount = 0;
|
||||||
|
bool m_streamTargetBusy = false;
|
||||||
KVMFRClipboardMessage m_internalTarget[INTERNAL_TARGET_COUNT] = {};
|
KVMFRClipboardMessage m_internalTarget[INTERNAL_TARGET_COUNT] = {};
|
||||||
unsigned m_internalTargetCount = 0;
|
unsigned m_internalTargetCount = 0;
|
||||||
CLGMPClipboardFiles m_files;
|
CLGMPClipboardFiles m_files;
|
||||||
@@ -187,12 +187,15 @@ private:
|
|||||||
bool QueueInternalTarget(const KVMFRClipboardMessage& record);
|
bool QueueInternalTarget(const KVMFRClipboardMessage& record);
|
||||||
bool PumpInternalTarget();
|
bool PumpInternalTarget();
|
||||||
void ClearStreamTargets();
|
void ClearStreamTargets();
|
||||||
|
void ClearQueuedStreamTargets();
|
||||||
bool QueueStreamTarget(const KVMFRClipboardMessage& record,
|
bool QueueStreamTarget(const KVMFRClipboardMessage& record,
|
||||||
const uint8_t * data);
|
const uint8_t * data);
|
||||||
|
void PopStreamTarget();
|
||||||
|
bool PublishStreamTarget();
|
||||||
|
bool RetryStreamTarget();
|
||||||
bool PumpStreamTarget();
|
bool PumpStreamTarget();
|
||||||
bool DrainStream(bool& received);
|
bool DrainStream(bool& received);
|
||||||
bool ProcessStreamTarget(const KVMFRClipboardMessage& record,
|
bool ProcessStreamTarget();
|
||||||
const uint8_t * data);
|
|
||||||
|
|
||||||
PLGMPMemory FindAvailable(PLGMPMemory (&memory)[MEMORY_COUNT]) const;
|
PLGMPMemory FindAvailable(PLGMPMemory (&memory)[MEMORY_COUNT]) const;
|
||||||
PostResult PostForOwner(uint64_t udata, PLGMPMemory memory);
|
PostResult PostForOwner(uint64_t udata, PLGMPMemory memory);
|
||||||
@@ -217,7 +220,7 @@ private:
|
|||||||
void ApplyInbound(const KVMFRClipboardMessage& message);
|
void ApplyInbound(const KVMFRClipboardMessage& message);
|
||||||
void ApplyOutbound(const KVMFRClipboardMessage& message);
|
void ApplyOutbound(const KVMFRClipboardMessage& message);
|
||||||
bool BeginTarget(const KVMFRClipboardMessage& message,
|
bool BeginTarget(const KVMFRClipboardMessage& message,
|
||||||
const uint8_t * data, bool acknowledge);
|
bool acknowledge);
|
||||||
|
|
||||||
ClipboardChannelResult SendControl(
|
ClipboardChannelResult SendControl(
|
||||||
const KVMFRClipboardMessage& record);
|
const KVMFRClipboardMessage& record);
|
||||||
|
|||||||
Reference in New Issue
Block a user