summaryrefslogtreecommitdiff
path: root/src/VBox/HostServices/HostChannel
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/HostServices/HostChannel')
-rw-r--r--src/VBox/HostServices/HostChannel/HostChannel.cpp388
-rw-r--r--src/VBox/HostServices/HostChannel/HostChannel.h28
-rw-r--r--src/VBox/HostServices/HostChannel/service.cpp102
3 files changed, 362 insertions, 156 deletions
diff --git a/src/VBox/HostServices/HostChannel/HostChannel.cpp b/src/VBox/HostServices/HostChannel/HostChannel.cpp
index 989b0796..5b07aa48 100644
--- a/src/VBox/HostServices/HostChannel/HostChannel.cpp
+++ b/src/VBox/HostServices/HostChannel/HostChannel.cpp
@@ -21,8 +21,10 @@
#include "HostChannel.h"
+
static DECLCALLBACK(void) HostChannelCallbackEvent(void *pvCallbacks, void *pvInstance,
uint32_t u32Id, const void *pvEvent, uint32_t cbEvent);
+static DECLCALLBACK(void) HostChannelCallbackDeleted(void *pvCallbacks, void *pvChannel);
/* A registered provider of channels. */
@@ -62,12 +64,23 @@ struct VBOXHOSTCHCTX
RTLISTANCHOR listProviders;
};
+/* The channel callbacks context. The provider passes the pointer as a callback parameter.
+ * Created for the provider and deleted when the provider says so.
+ */
+typedef struct VBOXHOSTCHCALLBACKCTX
+{
+ RTLISTNODE nodeClient; /* In the client, for cleanup when a client disconnects. */
+
+ VBOXHOSTCHCLIENT *pClient; /* The client which uses the channel, NULL when the client does not exist. */
+} VBOXHOSTCHCALLBACKCTX;
+
/* Only one service instance is supported. */
static VBOXHOSTCHCTX g_ctx = { false };
-static VBOXHOSTCHANNELCALLBACKS g_callbacks =
+static VBOXHOSTCHANNELCALLBACKS g_callbacks =
{
- HostChannelCallbackEvent
+ HostChannelCallbackEvent,
+ HostChannelCallbackDeleted
};
@@ -215,17 +228,19 @@ static int vhcHandleCreate(VBOXHOSTCHCLIENT *pClient, uint32_t *pu32Handle)
static void vhcInstanceDestroy(VBOXHOSTCHINSTANCE *pInstance)
{
- /* @todo free u32Handle? */
+ HOSTCHLOG(("HostChannel: destroy %p\n", pInstance));
}
static int32_t vhcInstanceAddRef(VBOXHOSTCHINSTANCE *pInstance)
{
+ HOSTCHLOG(("INST: %p %d addref\n", pInstance, pInstance->cRefs));
return ASMAtomicIncS32(&pInstance->cRefs);
}
static void vhcInstanceRelease(VBOXHOSTCHINSTANCE *pInstance)
{
int32_t c = ASMAtomicDecS32(&pInstance->cRefs);
+ HOSTCHLOG(("INST: %p %d release\n", pInstance, pInstance->cRefs));
Assert(c >= 0);
if (c == 0)
{
@@ -250,8 +265,13 @@ static int vhcInstanceCreate(VBOXHOSTCHCLIENT *pClient, VBOXHOSTCHINSTANCE **ppI
if (RT_SUCCESS(rc))
{
+ /* Used by the client, that is in the list of channels. */
vhcInstanceAddRef(pInstance);
+ /* Add to the list of created channel instances. It is inactive while pClient is 0. */
+ RTListAppend(&pClient->listChannels, &pInstance->nodeClient);
+ /* Return to the caller. */
+ vhcInstanceAddRef(pInstance);
*ppInstance = pInstance;
}
@@ -282,7 +302,8 @@ static VBOXHOSTCHINSTANCE *vhcInstanceFind(VBOXHOSTCHCLIENT *pClient, uint32_t u
VBOXHOSTCHINSTANCE *pIter;
RTListForEach(&pClient->listChannels, pIter, VBOXHOSTCHINSTANCE, nodeClient)
{
- if (pIter->u32Handle == u32Handle)
+ if ( pIter->pClient
+ && pIter->u32Handle == u32Handle)
{
pInstance = pIter;
@@ -302,6 +323,11 @@ static VBOXHOSTCHINSTANCE *vhcInstanceFindByChannelPtr(VBOXHOSTCHCLIENT *pClient
{
VBOXHOSTCHINSTANCE *pInstance = NULL;
+ if (pvChannel == NULL)
+ {
+ return NULL;
+ }
+
int rc = vboxHostChannelLock();
if (RT_SUCCESS(rc))
@@ -309,7 +335,8 @@ static VBOXHOSTCHINSTANCE *vhcInstanceFindByChannelPtr(VBOXHOSTCHCLIENT *pClient
VBOXHOSTCHINSTANCE *pIter;
RTListForEach(&pClient->listChannels, pIter, VBOXHOSTCHINSTANCE, nodeClient)
{
- if (pIter->pvChannel == pvChannel)
+ if ( pIter->pClient
+ && pIter->pvChannel == pvChannel)
{
pInstance = pIter;
@@ -327,18 +354,118 @@ static VBOXHOSTCHINSTANCE *vhcInstanceFindByChannelPtr(VBOXHOSTCHCLIENT *pClient
static void vhcInstanceDetach(VBOXHOSTCHINSTANCE *pInstance)
{
+ HOSTCHLOG(("HostChannel: detach %p\n", pInstance));
+
if (pInstance->pProvider)
{
pInstance->pProvider->iface.HostChannelDetach(pInstance->pvChannel);
RTListNodeRemove(&pInstance->nodeProvider);
vhcProviderRelease(pInstance->pProvider);
- vhcInstanceRelease(pInstance); /* Not in the list anymore. */
+ pInstance->pProvider = NULL;
+ vhcInstanceRelease(pInstance); /* Not in the provider's list anymore. */
+ }
+
+ int rc = vboxHostChannelLock();
+
+ if (RT_SUCCESS(rc))
+ {
+ RTListNodeRemove(&pInstance->nodeClient);
+
+ vboxHostChannelUnlock();
+
+ vhcInstanceRelease(pInstance); /* Not used by the client anymore. */
+ }
+}
+
+/*
+ * Channel callback contexts.
+ */
+static int vhcCallbackCtxCreate(VBOXHOSTCHCLIENT *pClient, VBOXHOSTCHCALLBACKCTX **ppCallbackCtx)
+{
+ int rc = VINF_SUCCESS;
+
+ VBOXHOSTCHCALLBACKCTX *pCallbackCtx = (VBOXHOSTCHCALLBACKCTX *)RTMemAllocZ(sizeof(VBOXHOSTCHCALLBACKCTX));
+
+ if (pCallbackCtx != NULL)
+ {
+ /* The callback context is accessed by the providers threads. */
+ rc = vboxHostChannelLock();
+ if (RT_SUCCESS(rc))
+ {
+ RTListAppend(&pClient->listContexts, &pCallbackCtx->nodeClient);
+ pCallbackCtx->pClient = pClient;
+
+ vboxHostChannelUnlock();
+ }
+ else
+ {
+ RTMemFree(pCallbackCtx);
+ }
+ }
+ else
+ {
+ rc = VERR_NO_MEMORY;
+ }
+
+ if (RT_SUCCESS(rc))
+ {
+ *ppCallbackCtx = pCallbackCtx;
}
- RTListNodeRemove(&pInstance->nodeClient);
- vhcInstanceRelease(pInstance); /* Not in the list anymore. */
+ return rc;
}
+static int vhcCallbackCtxDelete(VBOXHOSTCHCALLBACKCTX *pCallbackCtx)
+{
+ int rc = vboxHostChannelLock();
+ if (RT_SUCCESS(rc))
+ {
+ VBOXHOSTCHCLIENT *pClient = pCallbackCtx->pClient;
+
+ if (pClient != NULL)
+ {
+ /* The callback is associated with a client.
+ * Check that the callback is in the list and remove it from the list.
+ */
+ bool fFound = false;
+
+ VBOXHOSTCHCALLBACKCTX *pIter;
+ RTListForEach(&pClient->listContexts, pIter, VBOXHOSTCHCALLBACKCTX, nodeClient)
+ {
+ if (pIter == pCallbackCtx)
+ {
+ fFound = true;
+ break;
+ }
+ }
+
+ if (fFound)
+ {
+ RTListNodeRemove(&pCallbackCtx->nodeClient);
+ }
+ else
+ {
+ AssertFailed();
+ rc = VERR_INVALID_PARAMETER;
+ }
+ }
+ else
+ {
+ /* It is not in the clients anymore. May be the client has been disconnected.
+ * Just free the memory.
+ */
+ }
+
+ vboxHostChannelUnlock();
+ }
+
+ if (RT_SUCCESS(rc))
+ {
+ RTMemFree(pCallbackCtx);
+ }
+
+ return rc;
+}
/*
* Host channel service functions.
@@ -382,12 +509,28 @@ int vboxHostChannelClientConnect(VBOXHOSTCHCLIENT *pClient)
RTListInit(&pClient->listChannels);
RTListInit(&pClient->listEvents);
+ RTListInit(&pClient->listContexts);
return VINF_SUCCESS;
}
void vboxHostChannelClientDisconnect(VBOXHOSTCHCLIENT *pClient)
{
+ /* Clear the list of contexts and prevent acceess to the client. */
+ int rc = vboxHostChannelLock();
+ if (RT_SUCCESS(rc))
+ {
+ VBOXHOSTCHCALLBACKCTX *pIter;
+ VBOXHOSTCHCALLBACKCTX *pNext;
+ RTListForEachSafe(&pClient->listContexts, pIter, pNext, VBOXHOSTCHCALLBACKCTX, nodeClient)
+ {
+ pIter->pClient = NULL;
+ RTListNodeRemove(&pIter->nodeClient);
+ }
+
+ vboxHostChannelUnlock();
+ }
+
/* If there are attached channels, detach them. */
VBOXHOSTCHINSTANCE *pIter;
VBOXHOSTCHINSTANCE *pIterNext;
@@ -417,28 +560,44 @@ int vboxHostChannelAttach(VBOXHOSTCHCLIENT *pClient,
if (RT_SUCCESS(rc))
{
- void *pvChannel = NULL;
- rc = pProvider->iface.HostChannelAttach(pProvider->iface.pvProvider,
- &pvChannel,
- u32Flags,
- &g_callbacks, pClient);
+ VBOXHOSTCHCALLBACKCTX *pCallbackCtx = NULL;
+ rc = vhcCallbackCtxCreate(pClient, &pCallbackCtx);
+
if (RT_SUCCESS(rc))
{
- vhcProviderAddRef(pProvider);
- pInstance->pProvider = pProvider;
+ void *pvChannel = NULL;
+ rc = pProvider->iface.HostChannelAttach(pProvider->iface.pvProvider,
+ &pvChannel,
+ u32Flags,
+ &g_callbacks, pCallbackCtx);
- pInstance->pClient = pClient;
- pInstance->pvChannel = pvChannel;
+ if (RT_SUCCESS(rc))
+ {
+ vhcProviderAddRef(pProvider);
+ pInstance->pProvider = pProvider;
- vhcInstanceAddRef(pInstance); /* Referenced by the list client's channels. */
- RTListAppend(&pClient->listChannels, &pInstance->nodeClient);
+ pInstance->pClient = pClient;
+ pInstance->pvChannel = pvChannel;
+
+ /* It is already in the channels list of the client. */
+
+ vhcInstanceAddRef(pInstance); /* Referenced by the list of provider's channels. */
+ RTListAppend(&pProvider->listChannels, &pInstance->nodeProvider);
- vhcInstanceAddRef(pInstance); /* Referenced by the list of provider's channels. */
- RTListAppend(&pProvider->listChannels, &pInstance->nodeProvider);
+ *pu32Handle = pInstance->u32Handle;
- *pu32Handle = pInstance->u32Handle;
+ HOSTCHLOG(("HostChannel: Attach: (%d) handle %d\n", pClient->u32ClientID, pInstance->u32Handle));
+ }
- HOSTCHLOG(("HostChannel: Attach: (%d) handle %d\n", pClient->u32ClientID, pInstance->u32Handle));
+ if (RT_FAILURE(rc))
+ {
+ vhcCallbackCtxDelete(pCallbackCtx);
+ }
+ }
+
+ if (RT_FAILURE(rc))
+ {
+ vhcInstanceDetach(pInstance);
}
vhcInstanceRelease(pInstance);
@@ -488,10 +647,12 @@ int vboxHostChannelSend(VBOXHOSTCHCLIENT *pClient,
VBOXHOSTCHINSTANCE *pInstance = vhcInstanceFind(pClient, u32Handle);
- if ( pInstance
- && pInstance->pProvider)
+ if (pInstance)
{
- pInstance->pProvider->iface.HostChannelSend(pInstance->pvChannel, pvData, cbData);
+ if (pInstance->pProvider)
+ {
+ pInstance->pProvider->iface.HostChannelSend(pInstance->pvChannel, pvData, cbData);
+ }
vhcInstanceRelease(pInstance);
}
@@ -516,14 +677,16 @@ int vboxHostChannelRecv(VBOXHOSTCHCLIENT *pClient,
VBOXHOSTCHINSTANCE *pInstance = vhcInstanceFind(pClient, u32Handle);
- if ( pInstance
- && pInstance->pProvider)
+ if (pInstance)
{
- rc = pInstance->pProvider->iface.HostChannelRecv(pInstance->pvChannel, pvData, cbData,
- pu32SizeReceived, pu32SizeRemaining);
+ if (pInstance->pProvider)
+ {
+ rc = pInstance->pProvider->iface.HostChannelRecv(pInstance->pvChannel, pvData, cbData,
+ pu32SizeReceived, pu32SizeRemaining);
- HOSTCHLOG(("HostChannel: Recv: (%d) handle %d, rc %Rrc, recv %d, rem %d\n",
- pClient->u32ClientID, u32Handle, rc, cbData, *pu32SizeReceived, *pu32SizeRemaining));
+ HOSTCHLOG(("HostChannel: Recv: (%d) handle %d, rc %Rrc, recv %d, rem %d\n",
+ pClient->u32ClientID, u32Handle, rc, cbData, *pu32SizeReceived, *pu32SizeRemaining));
+ }
vhcInstanceRelease(pInstance);
}
@@ -550,12 +713,14 @@ int vboxHostChannelControl(VBOXHOSTCHCLIENT *pClient,
VBOXHOSTCHINSTANCE *pInstance = vhcInstanceFind(pClient, u32Handle);
- if ( pInstance
- && pInstance->pProvider)
+ if (pInstance)
{
- pInstance->pProvider->iface.HostChannelControl(pInstance->pvChannel, u32Code,
- pvParm, cbParm,
- pvData, cbData, pu32SizeDataReturned);
+ if (pInstance->pProvider)
+ {
+ pInstance->pProvider->iface.HostChannelControl(pInstance->pvChannel, u32Code,
+ pvParm, cbParm,
+ pvData, cbData, pu32SizeDataReturned);
+ }
vhcInstanceRelease(pInstance);
}
@@ -578,17 +743,25 @@ typedef struct VBOXHOSTCHANNELEVENT
uint32_t cbEvent;
} VBOXHOSTCHANNELEVENT;
-/* This is called under the lock. */
-int vboxHostChannelQueryEvent(VBOXHOSTCHCLIENT *pClient,
- bool *pfEvent,
- uint32_t *pu32Handle,
- uint32_t *pu32Id,
- void *pvParm,
- uint32_t cbParm,
- uint32_t *pcbParmOut)
+int vboxHostChannelEventWait(VBOXHOSTCHCLIENT *pClient,
+ bool *pfEvent,
+ VBOXHGCMCALLHANDLE callHandle,
+ VBOXHGCMSVCPARM *paParms)
{
- /* Check if there is something in the client's event queue. */
+ int rc = vboxHostChannelLock();
+ if (RT_FAILURE(rc))
+ {
+ return rc;
+ }
+ if (pClient->fAsync)
+ {
+ /* If there is a wait request already, cancel it. */
+ vboxHostChannelReportAsync(pClient, 0, VBOX_HOST_CHANNEL_EVENT_CANCELLED, NULL, 0);
+ pClient->fAsync = false;
+ }
+
+ /* Check if there is something in the client's event queue. */
VBOXHOSTCHANNELEVENT *pEvent = RTListGetFirst(&pClient->listEvents, VBOXHOSTCHANNELEVENT, NodeEvent);
HOSTCHLOG(("HostChannel: QueryEvent: (%d), event %p\n", pClient->u32ClientID, pEvent));
@@ -598,61 +771,119 @@ int vboxHostChannelQueryEvent(VBOXHOSTCHCLIENT *pClient,
/* Report the event. */
RTListNodeRemove(&pEvent->NodeEvent);
- *pfEvent = true;
- *pu32Handle = pEvent->u32ChannelHandle;
- *pu32Id = pEvent->u32Id;
-
- uint32_t cbToCopy = RT_MIN(cbParm, pEvent->cbEvent);
-
- HOSTCHLOG(("HostChannel: QueryEvent: (%d), cbParm %d, cbEvent %d\n",
- pClient->u32ClientID, cbParm, pEvent->cbEvent));
+ HOSTCHLOG(("HostChannel: QueryEvent: (%d), cbEvent %d\n",
+ pClient->u32ClientID, pEvent->cbEvent));
- if (cbToCopy > 0)
- {
- memcpy(pvParm, pEvent->pvEvent, cbToCopy);
- }
+ vboxHostChannelEventParmsSet(paParms, pEvent->u32ChannelHandle,
+ pEvent->u32Id, pEvent->pvEvent, pEvent->cbEvent);
- *pcbParmOut = cbToCopy;
+ *pfEvent = true;
RTMemFree(pEvent);
}
else
{
+ /* No event available at the time. Process asynchronously. */
+ pClient->fAsync = true;
+ pClient->async.callHandle = callHandle;
+ pClient->async.paParms = paParms;
+
/* Tell the caller that there is no event. */
*pfEvent = false;
}
- return VINF_SUCCESS;
+ vboxHostChannelUnlock();
+ return rc;
+}
+
+int vboxHostChannelEventCancel(VBOXHOSTCHCLIENT *pClient)
+{
+ int rc = vboxHostChannelLock();
+
+ if (RT_SUCCESS(rc))
+ {
+ if (pClient->fAsync)
+ {
+ /* If there is a wait request alredy, cancel it. */
+ vboxHostChannelReportAsync(pClient, 0, VBOX_HOST_CHANNEL_EVENT_CANCELLED, NULL, 0);
+
+ pClient->fAsync = false;
+ }
+
+ vboxHostChannelUnlock();
+ }
+
+ return rc;
}
+/* @thread provider */
static DECLCALLBACK(void) HostChannelCallbackEvent(void *pvCallbacks, void *pvChannel,
uint32_t u32Id, const void *pvEvent, uint32_t cbEvent)
{
- VBOXHOSTCHCLIENT *pClient = (VBOXHOSTCHCLIENT *)pvCallbacks;
+ VBOXHOSTCHCALLBACKCTX *pCallbackCtx = (VBOXHOSTCHCALLBACKCTX *)pvCallbacks;
- VBOXHOSTCHINSTANCE *pInstance = vhcInstanceFindByChannelPtr(pClient, pvChannel);
+ int rc = vboxHostChannelLock();
+ if (RT_FAILURE(rc))
+ {
+ return;
+ }
- HOSTCHLOG(("HostChannel: CallbackEvent: (%d) instance %p\n",
- pClient->u32ClientID, pInstance));
+ /* Check that the structure is still associated with a client.
+ * The client can disconnect and will be invalid.
+ */
+ VBOXHOSTCHCLIENT *pClient = pCallbackCtx->pClient;
- if (!pInstance)
+ if (pClient == NULL)
+ {
+ vboxHostChannelUnlock();
+
+ HOSTCHLOG(("HostChannel: CallbackEvent[%p]: client gone.\n"));
+
+ /* The client does not exist anymore, skip the event. */
+ return;
+ }
+
+ bool fFound = false;
+
+ VBOXHOSTCHCALLBACKCTX *pIter;
+ RTListForEach(&pClient->listContexts, pIter, VBOXHOSTCHCALLBACKCTX, nodeClient)
+ {
+ if (pIter == pCallbackCtx)
+ {
+ fFound = true;
+ break;
+ }
+ }
+
+ if (!fFound)
{
-#ifdef DEBUG_sunlover
AssertFailed();
-#endif
+
+ vboxHostChannelUnlock();
+
+ HOSTCHLOG(("HostChannel: CallbackEvent[%p]: client does not have the context.\n"));
+
+ /* The context is not in the list of contexts. Skip the event. */
return;
}
- int rc = vboxHostChannelLock();
- if (RT_FAILURE(rc))
+ VBOXHOSTCHINSTANCE *pInstance = vhcInstanceFindByChannelPtr(pClient, pvChannel);
+
+ HOSTCHLOG(("HostChannel: CallbackEvent[%p]: (%d) instance %p\n",
+ pCallbackCtx, pClient->u32ClientID, pInstance));
+
+ if (!pInstance)
{
+ /* Instance was already detached. Skip the event. */
+ vboxHostChannelUnlock();
+
return;
}
uint32_t u32ChannelHandle = pInstance->u32Handle;
HOSTCHLOG(("HostChannel: CallbackEvent: (%d) handle %d, async %d, cbEvent %d\n",
- pClient->u32ClientID, u32ChannelHandle, pClient->fAsync, cbEvent));
+ pClient->u32ClientID, u32ChannelHandle, pClient->fAsync, cbEvent));
/* Check whether the event is waited. */
if (pClient->fAsync)
@@ -684,18 +915,19 @@ static DECLCALLBACK(void) HostChannelCallbackEvent(void *pvCallbacks, void *pvCh
pEvent->cbEvent = cbEvent;
- if (RT_SUCCESS(rc))
- {
- RTListAppend(&pClient->listEvents, &pEvent->NodeEvent);
- }
- else
- {
- RTMemFree(pEvent);
- }
+ RTListAppend(&pClient->listEvents, &pEvent->NodeEvent);
}
}
vboxHostChannelUnlock();
+
+ vhcInstanceRelease(pInstance);
+}
+
+/* @thread provider */
+static DECLCALLBACK(void) HostChannelCallbackDeleted(void *pvCallbacks, void *pvChannel)
+{
+ vhcCallbackCtxDelete((VBOXHOSTCHCALLBACKCTX *)pvCallbacks);
}
int vboxHostChannelQuery(VBOXHOSTCHCLIENT *pClient,
diff --git a/src/VBox/HostServices/HostChannel/HostChannel.h b/src/VBox/HostServices/HostChannel/HostChannel.h
index 173faf2c..190f4b98 100644
--- a/src/VBox/HostServices/HostChannel/HostChannel.h
+++ b/src/VBox/HostServices/HostChannel/HostChannel.h
@@ -45,6 +45,8 @@ typedef struct VBOXHOSTCHCLIENT
RTLISTANCHOR listChannels;
uint32_t volatile u32HandleSrc;
+ RTLISTANCHOR listContexts; /* Callback contexts. */
+
RTLISTANCHOR listEvents;
bool fAsync; /* Guest is waiting for a message. */
@@ -95,13 +97,12 @@ int vboxHostChannelControl(VBOXHOSTCHCLIENT *pClient,
uint32_t cbData,
uint32_t *pu32SizeDataReturned);
-int vboxHostChannelQueryEvent(VBOXHOSTCHCLIENT *pClient,
- bool *pfEvent,
- uint32_t *pu32Handle,
- uint32_t *pu32Id,
- void *pvParm,
- uint32_t cbParm,
- uint32_t *pcbParmOut);
+int vboxHostChannelEventWait(VBOXHOSTCHCLIENT *pClient,
+ bool *pfEvent,
+ VBOXHGCMCALLHANDLE callHandle,
+ VBOXHGCMSVCPARM *paParms);
+
+int vboxHostChannelEventCancel(VBOXHOSTCHCLIENT *pClient);
int vboxHostChannelQuery(VBOXHOSTCHCLIENT *pClient,
const char *pszName,
@@ -118,7 +119,16 @@ int vboxHostChannelRegister(const char *pszName,
int vboxHostChannelUnregister(const char *pszName);
-void vboxHostChannelReportAsync(VBOXHOSTCHCLIENT *pClient, uint32_t u32ChannelHandle,
- uint32_t u32Id, const void *pvEvent, uint32_t cbEvent);
+void vboxHostChannelEventParmsSet(VBOXHGCMSVCPARM *paParms,
+ uint32_t u32ChannelHandle,
+ uint32_t u32Id,
+ const void *pvEvent,
+ uint32_t cbEvent);
+
+void vboxHostChannelReportAsync(VBOXHOSTCHCLIENT *pClient,
+ uint32_t u32ChannelHandle,
+ uint32_t u32Id,
+ const void *pvEvent,
+ uint32_t cbEvent);
#endif /* __VBOXHOSTCHANNEL__H */
diff --git a/src/VBox/HostServices/HostChannel/service.cpp b/src/VBox/HostServices/HostChannel/service.cpp
index c632d9d0..a2042985 100644
--- a/src/VBox/HostServices/HostChannel/service.cpp
+++ b/src/VBox/HostServices/HostChannel/service.cpp
@@ -106,30 +106,46 @@ void vboxHostChannelUnlock(void)
RTCritSectLeave(&g_critsect);
}
-/* This is called under the lock. */
-void vboxHostChannelReportAsync(VBOXHOSTCHCLIENT *pClient,
- uint32_t u32ChannelHandle,
- uint32_t u32Id,
- const void *pvEvent,
- uint32_t cbEvent)
+void vboxHostChannelEventParmsSet(VBOXHGCMSVCPARM *paParms,
+ uint32_t u32ChannelHandle,
+ uint32_t u32Id,
+ const void *pvEvent,
+ uint32_t cbEvent)
{
if (cbEvent > 0)
{
void *pvParm = NULL;
uint32_t cbParm = 0;
- VBoxHGCMParmPtrGet(&pClient->async.paParms[2], &pvParm, &cbParm);
+ VBoxHGCMParmPtrGet(&paParms[2], &pvParm, &cbParm);
uint32_t cbToCopy = RT_MIN(cbParm, cbEvent);
if (cbToCopy > 0)
{
+ Assert(pvParm);
memcpy(pvParm, pvEvent, cbToCopy);
}
}
- VBoxHGCMParmUInt32Set(&pClient->async.paParms[0], u32ChannelHandle);
- VBoxHGCMParmUInt32Set(&pClient->async.paParms[1], u32Id);
- VBoxHGCMParmUInt32Set(&pClient->async.paParms[3], cbEvent);
+ VBoxHGCMParmUInt32Set(&paParms[0], u32ChannelHandle);
+ VBoxHGCMParmUInt32Set(&paParms[1], u32Id);
+ VBoxHGCMParmUInt32Set(&paParms[3], cbEvent);
+}
+
+/* This is called under the lock. */
+void vboxHostChannelReportAsync(VBOXHOSTCHCLIENT *pClient,
+ uint32_t u32ChannelHandle,
+ uint32_t u32Id,
+ const void *pvEvent,
+ uint32_t cbEvent)
+{
+ Assert(RTCritSectIsOwner(&g_critsect));
+
+ vboxHostChannelEventParmsSet(pClient->async.paParms,
+ u32ChannelHandle,
+ u32Id,
+ pvEvent,
+ cbEvent);
LogRelFlow(("svcCall: CallComplete for pending\n"));
@@ -437,56 +453,18 @@ static DECLCALLBACK(void) svcCall(void *pvService,
}
else
{
- void *pvParm;
- uint32_t cbParm;
+ bool fEvent = false;
- rc = VBoxHGCMParmPtrGet(&paParms[2], &pvParm, &cbParm);
+ rc = vboxHostChannelEventWait(pClient, &fEvent, callHandle, paParms);
if (RT_SUCCESS(rc))
{
- /* This is accessed from the SVC thread and other threads. */
- rc = vboxHostChannelLock();
-
- if (RT_SUCCESS(rc))
+ if (!fEvent)
{
- if (pClient->fAsync)
- {
- /* If there is a wait request already, cancel it. */
- vboxHostChannelReportAsync(pClient, 0, VBOX_HOST_CHANNEL_EVENT_CANCELLED, NULL, 0);
-
- pClient->fAsync = false;
- }
-
- bool fEvent = false;
- uint32_t u32Handle = 0;
- uint32_t u32Id = 0;
- uint32_t cbParmOut = 0;
-
- rc = vboxHostChannelQueryEvent(pClient, &fEvent, &u32Handle, &u32Id,
- pvParm, cbParm, &cbParmOut);
-
- if (RT_SUCCESS(rc))
- {
- if (fEvent)
- {
- VBoxHGCMParmUInt32Set(&paParms[0], u32Handle);
- VBoxHGCMParmUInt32Set(&paParms[1], u32Id);
- VBoxHGCMParmUInt32Set(&paParms[3], cbParmOut);
- }
- else
- {
- /* No event available at the time. Process asynchronously. */
- fAsynchronousProcessing = true;
-
- pClient->fAsync = true;
- pClient->async.callHandle = callHandle;
- pClient->async.paParms = paParms;
+ /* No event available at the time. Process asynchronously. */
+ fAsynchronousProcessing = true;
- LogRel2(("svcCall: async.\n"));
- }
- }
-
- vboxHostChannelUnlock();
+ LogRel2(("svcCall: async.\n"));
}
}
}
@@ -502,21 +480,7 @@ static DECLCALLBACK(void) svcCall(void *pvService,
}
else
{
- /* This is accessed from the SVC thread and other threads. */
- rc = vboxHostChannelLock();
-
- if (RT_SUCCESS(rc))
- {
- if (pClient->fAsync)
- {
- /* If there is a wait request alredy, cancel it. */
- vboxHostChannelReportAsync(pClient, 0, VBOX_HOST_CHANNEL_EVENT_CANCELLED, NULL, 0);
-
- pClient->fAsync = false;
- }
-
- vboxHostChannelUnlock();
- }
+ rc = vboxHostChannelEventCancel(pClient);
}
} break;