mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-08-22 23:21:29 +00:00
[client] transport: track video component availability
This commit is contained in:
@@ -63,6 +63,11 @@ struct Pure
|
||||
atomic_bool connectOK;
|
||||
atomic_bool callReady;
|
||||
atomic_bool blockConnect;
|
||||
atomic_bool enterConnect;
|
||||
atomic_bool allowConnect;
|
||||
atomic_bool blockChannelConnect;
|
||||
atomic_bool enterChannelConnect;
|
||||
atomic_bool channelCancel[PS_CHANNEL_MAX];
|
||||
atomic_bool cancel;
|
||||
atomic_bool drop;
|
||||
PSStatus dropStatus;
|
||||
@@ -136,8 +141,18 @@ void purespice_init(const PSInit * init)
|
||||
(void)init;
|
||||
}
|
||||
|
||||
void purespice_beginConnect(void)
|
||||
{
|
||||
atomic_store_explicit(&ps.cancel, false, memory_order_release);
|
||||
}
|
||||
|
||||
bool purespice_connect(const PSConfig * config)
|
||||
{
|
||||
while (!atomic_load_explicit(&ps.allowConnect, memory_order_acquire) &&
|
||||
!atomic_load_explicit(&ps.cancel, memory_order_acquire))
|
||||
usleep(1000);
|
||||
atomic_store_explicit(&ps.enterConnect, true, memory_order_release);
|
||||
|
||||
ps.config = *config;
|
||||
ps.connectOrder = nextOrder();
|
||||
atomic_fetch_add(&ps.connectN, 1);
|
||||
@@ -152,6 +167,23 @@ bool purespice_connect(const PSConfig * config)
|
||||
return true;
|
||||
}
|
||||
|
||||
void purespice_cancelConnect(void)
|
||||
{
|
||||
atomic_store_explicit(&ps.cancel, true, memory_order_release);
|
||||
}
|
||||
|
||||
void purespice_beginChannelConnect(PSChannelType channel)
|
||||
{
|
||||
atomic_store_explicit(
|
||||
&ps.channelCancel[channel], false, memory_order_release);
|
||||
}
|
||||
|
||||
void purespice_cancelChannelConnect(PSChannelType channel)
|
||||
{
|
||||
atomic_store_explicit(
|
||||
&ps.channelCancel[channel], true, memory_order_release);
|
||||
}
|
||||
|
||||
void purespice_disconnect(void)
|
||||
{
|
||||
ps.disconnectOrder = nextOrder();
|
||||
@@ -201,6 +233,18 @@ bool purespice_channelConnected(PSChannelType channel)
|
||||
bool purespice_connectChannel(PSChannelType channel)
|
||||
{
|
||||
++ps.connectChannelN[channel];
|
||||
atomic_store_explicit(
|
||||
&ps.enterChannelConnect, true, memory_order_release);
|
||||
while (atomic_load_explicit(
|
||||
&ps.blockChannelConnect, memory_order_acquire) &&
|
||||
!atomic_load_explicit(&ps.cancel, memory_order_acquire) &&
|
||||
!atomic_load_explicit(
|
||||
&ps.channelCancel[channel], memory_order_acquire))
|
||||
usleep(1000);
|
||||
if (atomic_load_explicit(&ps.cancel, memory_order_acquire) ||
|
||||
atomic_load_explicit(
|
||||
&ps.channelCancel[channel], memory_order_acquire))
|
||||
return false;
|
||||
if (!ps.connectResult[channel])
|
||||
return false;
|
||||
ps.connected[channel] = true;
|
||||
@@ -335,6 +379,12 @@ static void resetPure(void)
|
||||
atomic_init(&ps.connectOK, true);
|
||||
atomic_init(&ps.callReady, true);
|
||||
atomic_init(&ps.blockConnect, false);
|
||||
atomic_init(&ps.enterConnect, false);
|
||||
atomic_init(&ps.allowConnect, true);
|
||||
atomic_init(&ps.blockChannelConnect, false);
|
||||
atomic_init(&ps.enterChannelConnect, false);
|
||||
for(unsigned int i = 0; i < PS_CHANNEL_MAX; ++i)
|
||||
atomic_init(&ps.channelCancel[i], false);
|
||||
atomic_init(&ps.cancel, false);
|
||||
atomic_init(&ps.drop, false);
|
||||
atomic_init(&ps.connectN, 0);
|
||||
@@ -485,10 +535,16 @@ static bool cancel(void * opaque)
|
||||
{
|
||||
unsigned int * calls = opaque;
|
||||
++*calls;
|
||||
atomic_store(&ps.cancel, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool cancelBeforeEntry(void * opaque)
|
||||
{
|
||||
unsigned int * calls = opaque;
|
||||
++*calls;
|
||||
return !atomic_load_explicit(&ps.enterConnect, memory_order_acquire);
|
||||
}
|
||||
|
||||
static void testConnectFail(void)
|
||||
{
|
||||
resetPure();
|
||||
@@ -560,6 +616,19 @@ static void testCancel(void)
|
||||
CHECK(f.clipboard.offN == 1);
|
||||
CHECK(!atomic_load(&cbTarget));
|
||||
freeFixture(&f);
|
||||
|
||||
resetPure();
|
||||
atomic_store_explicit(&ps.allowConnect, false, memory_order_release);
|
||||
atomic_store_explicit(&ps.enterConnect, false, memory_order_release);
|
||||
initFixture(&f);
|
||||
cancelN = 0;
|
||||
CHECK(LGT_SPICE.connectCancellable(&f.transport, &session,
|
||||
cancelBeforeEntry, &cancelN) == LG_TRANSPORT_DISCONNECTED);
|
||||
CHECK(cancelN == 1);
|
||||
CHECK(!f.transport.thread);
|
||||
CHECK(!LGT_SPICE.sessionValid(&f.transport));
|
||||
CHECK(atomic_load_explicit(&ps.cancel, memory_order_acquire));
|
||||
freeFixture(&f);
|
||||
}
|
||||
|
||||
static void testReadyDrop(void)
|
||||
@@ -704,6 +773,148 @@ static void testSurfaceActive(void)
|
||||
freeFixture(&f);
|
||||
}
|
||||
|
||||
struct ActiveCall
|
||||
{
|
||||
const LG_SwSurfaceOps * ops;
|
||||
LG_Transport * transport;
|
||||
atomic_bool done;
|
||||
bool result;
|
||||
};
|
||||
|
||||
static void * activateSurface(void * opaque)
|
||||
{
|
||||
struct ActiveCall * call = opaque;
|
||||
call->result = call->ops->setActive(call->transport, true);
|
||||
atomic_store_explicit(&call->done, true, memory_order_release);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void * holdActivationLock(void * opaque)
|
||||
{
|
||||
LG_Transport * transport = opaque;
|
||||
spiceSurface_testLockActivation(transport->surface);
|
||||
atomic_store_explicit(
|
||||
&ps.enterChannelConnect, true, memory_order_release);
|
||||
while (atomic_load_explicit(
|
||||
&ps.blockChannelConnect, memory_order_acquire))
|
||||
usleep(1000);
|
||||
spiceSurface_testUnlockActivation(transport->surface);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void testSurfaceCancel(void)
|
||||
{
|
||||
resetPure();
|
||||
struct Fixture f;
|
||||
initFixture(&f);
|
||||
const LG_SwSurfaceOps * sw = spiceSurface_getVideoOps()->swSurface;
|
||||
CHECK(sw->attach(&f.transport, &surfaceEvents, &f.log));
|
||||
atomic_store_explicit(
|
||||
&f.transport.sessionValid, true, memory_order_release);
|
||||
atomic_store_explicit(
|
||||
&ps.blockChannelConnect, true, memory_order_release);
|
||||
|
||||
struct ActiveCall call =
|
||||
{
|
||||
.ops = sw,
|
||||
.transport = &f.transport,
|
||||
};
|
||||
atomic_init(&call.done, false);
|
||||
pthread_t thread;
|
||||
CHECK(pthread_create(&thread, NULL, activateSurface, &call) == 0);
|
||||
waitBool(&ps.enterChannelConnect);
|
||||
|
||||
sw->cancelPending(&f.transport);
|
||||
waitBool(&call.done);
|
||||
CHECK(pthread_join(thread, NULL) == 0);
|
||||
CHECK(!call.result);
|
||||
CHECK(atomic_load_explicit(
|
||||
&ps.channelCancel[PS_CHANNEL_DISPLAY], memory_order_acquire));
|
||||
CHECK(!atomic_load_explicit(&ps.cancel, memory_order_acquire));
|
||||
CHECK(ps.connectChannelN[PS_CHANNEL_DISPLAY] == 1);
|
||||
CHECK(ps.connectChannelN[PS_CHANNEL_CURSOR] == 0);
|
||||
CHECK(LGT_SPICE.sessionValid(&f.transport));
|
||||
|
||||
atomic_store_explicit(
|
||||
&ps.blockChannelConnect, false, memory_order_release);
|
||||
CHECK(sw->setActive(&f.transport, true));
|
||||
CHECK(LGT_SPICE.sessionValid(&f.transport));
|
||||
CHECK(sw->setActive(&f.transport, false));
|
||||
|
||||
sw->detach(&f.transport);
|
||||
freeFixture(&f);
|
||||
|
||||
resetPure();
|
||||
initFixture(&f);
|
||||
sw = spiceSurface_getVideoOps()->swSurface;
|
||||
CHECK(sw->attach(&f.transport, &surfaceEvents, &f.log));
|
||||
atomic_store_explicit(
|
||||
&f.transport.sessionValid, true, memory_order_release);
|
||||
atomic_store_explicit(
|
||||
&ps.blockChannelConnect, true, memory_order_release);
|
||||
|
||||
pthread_t holdThread;
|
||||
CHECK(pthread_create(
|
||||
&holdThread, NULL, holdActivationLock, &f.transport) == 0);
|
||||
waitBool(&ps.enterChannelConnect);
|
||||
|
||||
call = (struct ActiveCall)
|
||||
{
|
||||
.ops = sw,
|
||||
.transport = &f.transport,
|
||||
};
|
||||
atomic_init(&call.done, false);
|
||||
CHECK(pthread_create(&thread, NULL, activateSurface, &call) == 0);
|
||||
usleep(10000);
|
||||
sw->cancelPending(&f.transport);
|
||||
atomic_store_explicit(
|
||||
&ps.blockChannelConnect, false, memory_order_release);
|
||||
CHECK(pthread_join(holdThread, NULL) == 0);
|
||||
waitBool(&call.done);
|
||||
CHECK(pthread_join(thread, NULL) == 0);
|
||||
CHECK(!call.result);
|
||||
CHECK(ps.connectChannelN[PS_CHANNEL_DISPLAY] == 0);
|
||||
|
||||
sw->detach(&f.transport);
|
||||
freeFixture(&f);
|
||||
|
||||
resetPure();
|
||||
initFixture(&f);
|
||||
sw = spiceSurface_getVideoOps()->swSurface;
|
||||
CHECK(sw->attach(&f.transport, &surfaceEvents, &f.log));
|
||||
atomic_store_explicit(
|
||||
&f.transport.sessionValid, true, memory_order_release);
|
||||
atomic_store_explicit(
|
||||
&ps.blockChannelConnect, true, memory_order_release);
|
||||
|
||||
call = (struct ActiveCall)
|
||||
{
|
||||
.ops = sw,
|
||||
.transport = &f.transport,
|
||||
};
|
||||
atomic_init(&call.done, false);
|
||||
CHECK(pthread_create(&thread, NULL, activateSurface, &call) == 0);
|
||||
waitBool(&ps.enterChannelConnect);
|
||||
|
||||
atomic_store_explicit(
|
||||
&f.transport.sessionValid, false, memory_order_release);
|
||||
spiceSurface_sessionStopped(f.transport.surface);
|
||||
waitBool(&call.done);
|
||||
CHECK(pthread_join(thread, NULL) == 0);
|
||||
CHECK(!call.result);
|
||||
CHECK(atomic_load_explicit(
|
||||
&ps.channelCancel[PS_CHANNEL_DISPLAY], memory_order_acquire));
|
||||
CHECK(atomic_load_explicit(
|
||||
&ps.channelCancel[PS_CHANNEL_CURSOR], memory_order_acquire));
|
||||
CHECK(!atomic_load_explicit(&ps.cancel, memory_order_acquire));
|
||||
CHECK(sw->setActive(&f.transport, false));
|
||||
|
||||
atomic_store_explicit(
|
||||
&ps.blockChannelConnect, false, memory_order_release);
|
||||
sw->detach(&f.transport);
|
||||
freeFixture(&f);
|
||||
}
|
||||
|
||||
static void testSurfaceEvents(void)
|
||||
{
|
||||
resetPure();
|
||||
@@ -864,6 +1075,7 @@ static const struct Test tests[] =
|
||||
{ "ready-drop" , testReadyDrop },
|
||||
{ "session-order" , testSessionOrder },
|
||||
{ "surface-active", testSurfaceActive },
|
||||
{ "surface-cancel", testSurfaceCancel },
|
||||
{ "surface-events", testSurfaceEvents },
|
||||
{ "surface-detach", testSurfaceDetach },
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user