HostChannel.cpp revision f17aa73b10e13ac2061271144c7cbaa5133605dc
/** @file
* Host channel.
*/
/*
* Copyright (C) 2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
#include "HostChannel.h"
/* A registered provider of channels. */
typedef struct VBOXHOSTCHPROVIDER
{
char *pszName;
/* An established channel. */
typedef struct VBOXHOSTCHINSTANCE
{
RTLISTNODE nodeProvider; /* In the provider, needed for cleanup when the provider is unregistered. */
void *pvChannel; /* Provider's context of the channel. */
struct VBOXHOSTCHCTX
{
bool fInitialized;
};
/* Only one service instance is supported. */
static VBOXHOSTCHCTX g_ctx = { false };
static VBOXHOSTCHANNELCALLBACKS g_callbacks =
{
};
/*
* Provider management.
*/
{
}
{
}
{
Assert(c >= 0);
if (c == 0)
{
}
}
{
int rc = vboxHostChannelLock();
if (RT_SUCCESS(rc))
{
{
{
break;
}
}
}
return pProvider;
}
{
int rc = vboxHostChannelLock();
if (RT_SUCCESS(rc))
{
/* @todo check a duplicate. */
}
if (RT_FAILURE(rc))
{
}
return rc;
}
{
int rc = vboxHostChannelLock();
if (RT_SUCCESS(rc))
{
/* @todo check that the provider is in the list. */
/* @todo mark the provider as invalid in each instance. also detach channels? */
}
return rc;
}
/*
* Select an unique handle for the new channel.
* Works under the lock.
*/
{
bool fOver = false;
for(;;)
{
if (u32Handle == 0)
{
if (fOver)
{
return VERR_NOT_SUPPORTED;
}
fOver = true;
continue;
}
{
{
pDuplicate = pIter;
break;
}
}
if (pDuplicate == NULL)
{
*pu32Handle = u32Handle;
break;
}
}
return VINF_SUCCESS;
}
/*
* Channel instance management.
*/
{
/* @todo free u32Handle? */
}
{
}
{
Assert(c >= 0);
if (c == 0)
{
}
}
{
int rc = VINF_SUCCESS;
if (pInstance)
{
rc = vboxHostChannelLock();
if (RT_SUCCESS(rc))
{
if (RT_SUCCESS(rc))
{
*ppInstance = pInstance;
}
}
if (RT_FAILURE(rc))
{
}
}
else
{
rc = VERR_NO_MEMORY;
}
return rc;
}
{
int rc = vboxHostChannelLock();
if (RT_SUCCESS(rc))
{
{
{
break;
}
}
}
return pInstance;
}
{
int rc = vboxHostChannelLock();
if (RT_SUCCESS(rc))
{
{
{
break;
}
}
}
return pInstance;
}
{
{
}
}
/*
* Host channel service functions.
*/
int vboxHostChannelInit(void)
{
if (pCtx->fInitialized)
{
return VERR_NOT_SUPPORTED;
}
pCtx->fInitialized = true;
return VINF_SUCCESS;
}
void vboxHostChannelDestroy(void)
{
{
}
pCtx->fInitialized = false;
}
{
/* A guest client is connecting to the service.
* Later the client will use Attach calls to connect to channel providers.
* pClient is already zeroed.
*/
return VINF_SUCCESS;
}
{
/* If there are attached channels, detach them. */
{
}
}
const char *pszName,
{
int rc = VINF_SUCCESS;
/* Look if there is a provider. */
if (pProvider)
{
if (RT_SUCCESS(rc))
{
&g_callbacks, pClient);
if (RT_SUCCESS(rc))
{
}
}
}
else
{
}
return rc;
}
{
int rc = VINF_SUCCESS;
if (pInstance)
{
}
else
{
}
return rc;
}
const void *pvData,
{
HOSTCHLOG(("HostChannel: Send: (%d) handle %d, %d bytes\n", pClient->u32ClientID, u32Handle, cbData));
int rc = VINF_SUCCESS;
if ( pInstance
{
}
else
{
}
return rc;
}
void *pvData,
{
HOSTCHLOG(("HostChannel: Recv: (%d) handle %d, cbData %d\n", pClient->u32ClientID, u32Handle, cbData));
int rc = VINF_SUCCESS;
if ( pInstance
{
HOSTCHLOG(("HostChannel: Recv: (%d) handle %d, rc %Rrc, recv %d, rem %d\n",
}
else
{
}
return rc;
}
void *pvParm,
void *pvData,
{
HOSTCHLOG(("HostChannel: Control: (%d) handle %d, cbData %d\n", pClient->u32ClientID, u32Handle, cbData));
int rc = VINF_SUCCESS;
if ( pInstance
{
}
else
{
}
return rc;
}
typedef struct VBOXHOSTCHANNELEVENT
{
void *pvEvent;
/* This is called under the lock. */
bool *pfEvent,
void *pvParm,
{
/* Check if there is something in the client's event queue. */
VBOXHOSTCHANNELEVENT *pEvent = RTListGetFirst(&pClient->listEvents, VBOXHOSTCHANNELEVENT, NodeEvent);
if (pEvent)
{
/* Report the event. */
*pfEvent = true;
HOSTCHLOG(("HostChannel: QueryEvent: (%d), cbParm %d, cbEvent %d\n",
if (cbToCopy > 0)
{
}
*pcbParmOut = cbToCopy;
}
else
{
/* Tell the caller that there is no event. */
*pfEvent = false;
}
return VINF_SUCCESS;
}
{
HOSTCHLOG(("HostChannel: CallbackEvent: (%d) instance %p\n",
if (!pInstance)
{
#ifdef DEBUG_sunlover
AssertFailed();
#endif
return;
}
int rc = vboxHostChannelLock();
if (RT_FAILURE(rc))
{
return;
}
HOSTCHLOG(("HostChannel: CallbackEvent: (%d) handle %d, async %d, cbEvent %d\n",
/* Check whether the event is waited. */
{
/* Report the event. */
}
else
{
/* Put it to the queue. */
VBOXHOSTCHANNELEVENT *pEvent = (VBOXHOSTCHANNELEVENT *)RTMemAlloc(sizeof(VBOXHOSTCHANNELEVENT) + cbEvent);
if (pEvent)
{
if (cbEvent)
{
}
else
{
}
if (RT_SUCCESS(rc))
{
}
else
{
}
}
}
}
int vboxHostChannelRegister(const char *pszName,
const VBOXHOSTCHANNELINTERFACE *pInterface,
{
int rc = VINF_SUCCESS;
if (pProvider)
{
{
}
else
{
rc = VERR_NO_MEMORY;
}
}
else
{
rc = VERR_NO_MEMORY;
}
return rc;
}
int vboxHostChannelUnregister(const char *pszName)
{
int rc = VINF_SUCCESS;
if (pProvider)
{
}
return rc;
}