* if the close session is called from the channel.
*/
-#ifdef VMX86_TOOLS
-/* We need to have a static session for use of HGFS server inside Tools. */
-struct HgfsStaticSession {
- HgfsSessionInfo *session; /* Session. */
- char *bufferOut; /* Reply buffer. */
- size_t bufferOutLen; /* Reply buffer length. */
-} hgfsStaticSession;
-#endif
-
/* Session related callbacks. */
static void HgfsServerSessionReceive(HgfsPacket *packet,
void *clientData);
}
#endif
-
-#ifdef VMX86_TOOLS
- hgfsStaticSession.session = NULL;
- hgfsStaticSession.bufferOut = NULL;
- hgfsStaticSession.bufferOutLen = 0;
-#endif
-
if (HgfsNotify_Init() == 0) {
hgfsChangeNotificationSupported = TRUE;
}
HgfsServer_ExitState(void)
{
-#ifdef VMX86_TOOLS
- if (hgfsStaticSession.session != NULL) {
- HgfsServerSessionPut(hgfsStaticSession.session);
- }
-#endif
-
if (hgfsChangeNotificationSupported) {
HgfsNotify_Shutdown();
}
}
-#ifdef VMX86_TOOLS
-/*
- *----------------------------------------------------------------------------
- *
- * HgfsServer_ProcessPacket --
- *
- * Process packet not associated with any session.
- *
- * This function is used in the HGFS server inside Tools.
- *
- * Create an internal session if not already created, and process the packet.
- *
- * Results:
- * None
- *
- * Side effects:
- * None
- *
- *----------------------------------------------------------------------------
- */
-
-void
-HgfsServer_ProcessPacket(char const *packetIn, // IN: incoming packet
- char *packetOut, // OUT: outgoing packet
- size_t *packetLen) // IN/OUT: packet length
-{
- HgfsPacket packet;
- ASSERT(packetIn);
- ASSERT(packetOut);
- ASSERT(packetLen);
-
- if (*packetLen == 0) {
- return;
- }
-
- /*
- * Create the session if not already created.
- * This session is destroyed in HgfsServer_ExitState.
- */
-
- if (hgfsStaticSession.session == NULL) {
- if (!HgfsServerSessionConnect(NULL, NULL,
- (void **)&hgfsStaticSession.session)) {
- *packetLen = 0;
-
- return;
- }
-
- /* Mark the session as internal. */
- hgfsStaticSession.session->type = HGFS_SESSION_TYPE_INTERNAL;
- }
-
- memset(&packet, 0, sizeof packet);
- packet.iov[0].va = (void *)packetIn;
- packet.iov[0].len = *packetLen;
- packet.iovCount = 1;
- packet.metaPacket = (void *)packetIn;
- packet.metaPacketSize = *packetLen;
- packet.replyPacket = packetOut;
- packet.replyPacketSize = HGFS_LARGE_PACKET_MAX;
- packet.supportsAsync = FALSE;
-
- HgfsServerSessionReceive(&packet,
- hgfsStaticSession.session);
-
- /*
- * At this point, all the HGFS ops send reply synchronously. So
- * we should have the reply by now.
- * XXX This should change if any async replies are expected.
- */
-
- ASSERT(hgfsStaticSession.bufferOut);
-
- *packetLen = hgfsStaticSession.bufferOutLen;
-
- HgfsServerSessionSendComplete(&packet,
- hgfsStaticSession.session);
- hgfsStaticSession.bufferOut = NULL;
-}
-#endif
-
-
/*
*----------------------------------------------------------------------------
*
if (session->state == HGFS_SESSION_STATE_OPEN) {
packet->replyPacketSize = packetOutLen;
-#ifndef VMX86_TOOLS
ASSERT(session->type == HGFS_SESSION_TYPE_REGULAR);
result = session->channelCbTable->send(session->transportData,
packet, packetOut,
packetOutLen, flags);
-#else
- /* This is internal session. */
- ASSERT(session->type == HGFS_SESSION_TYPE_INTERNAL);
- hgfsStaticSession.bufferOut = packetOut;
- hgfsStaticSession.bufferOutLen = packetOutLen;
- result = TRUE;
-#endif
}
return result;
HgfsSessionInfo *session = (HgfsSessionInfo *)clientData;
HgfsInvalidateSessionObjects(shares, session);
-
-#ifdef VMX86_TOOLS
- if (hgfsStaticSession.session != NULL) {
- HgfsInvalidateSessionObjects(shares, hgfsStaticSession.session);
- }
-#endif
}
libHgfsServerManagerGuest_la_SOURCES =
libHgfsServerManagerGuest_la_SOURCES += hgfsServerManagerGuest.c
+libHgfsServerManagerGuest_la_SOURCES += hgfsChannelGuest.c
+libHgfsServerManagerGuest_la_SOURCES += hgfsChannelGuestBd.c
--- /dev/null
+/*********************************************************
+ * Copyright (C) 2010 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation version 2.1 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *********************************************************/
+
+/*
+ * hgfsChannel.c --
+ *
+ * Channel abstraction for the HGFS server.
+ *
+ */
+
+#include <stdlib.h>
+#include "vm_assert.h"
+#include "vm_atomic.h"
+#include "util.h"
+#if defined(VMTOOLS_USE_GLIB)
+#define G_LOG_DOMAIN "hgfsd"
+#define Debug g_debug
+#define Warning g_warning
+#include "vmware/tools/guestrpc.h"
+#include "vmware/tools/utils.h"
+// #include <glib.h>
+#else
+#include "debug.h"
+#endif
+#include "hgfsChannelGuestInt.h"
+#include "hgfsServer.h"
+#include "hgfsServerManager.h"
+
+
+/* Transport channels context. Static. */
+typedef struct HgfsChannelData {
+ const char *name; /* Channel name. */
+ HgfsGuestChannelCBTable *ops; /* Channel operations. */
+ uint32 state; /* Channel state (see flags below). */
+ struct HgfsGuestConn *connection; /* Opaque server connection */
+} HgfsChannelData;
+
+#define HGFS_CHANNEL_STATE_INIT (1 << 0)
+#define HGFS_CHANNEL_STATE_CBINIT (1 << 1)
+
+typedef uint32 HgfsChannelMgrState; /* Channel state (see flags below). */
+
+#define HGFS_CHANNELMGR_STATE_SERVERINIT (1 << 0)
+#define HGFS_CHANNELMGR_STATE_CHANINIT (1 << 1)
+
+/* Static channel registration - assumes only one for now. */
+static HgfsChannelData gHgfsChannels[] = {
+ { "guest", &gGuestBackdoorOps, 0, NULL },
+};
+
+static HgfsChannelMgrState gHgfsChannelsMgrState = 0;
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * CHANNEL DATA FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsChannelInitChannel --
+ *
+ * Initializes a channel.
+ *
+ * Results:
+ * TRUE if the channel initialized, FALSE otherwise.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static Bool
+HgfsChannelInitChannel(HgfsChannelData *channel) // IN/OUT: channel object
+{
+ channel->state = HGFS_CHANNEL_STATE_INIT;
+ return TRUE;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsChannelExitChannel --
+ *
+ * Teardown the channel.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static void
+HgfsChannelExitChannel(HgfsChannelData *channel) // IN/OUT: channel object
+{
+ if (channel->state & HGFS_CHANNEL_STATE_INIT) {
+ channel->state = 0;
+ }
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsChannelActivateChannel --
+ *
+ * Activate a channel by calling the channels init callback.
+ *
+ * Results:
+ * TRUE if a channel is active.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static Bool
+HgfsChannelActivateChannel(HgfsChannelData *channel, // IN/OUT: channel object
+ HgfsServerSessionCallbacks *serverCBTable, // IN: server callbacks
+ HgfsServerMgrData *mgrData) // IN: mgrData
+{
+ Bool success = FALSE;
+ struct HgfsGuestConn *connData = NULL;
+
+ if (channel->ops->init(serverCBTable, mgrData->rpc, mgrData->rpcCallback, &connData)) {
+ channel->state |= HGFS_CHANNEL_STATE_CBINIT;
+ channel->connection = connData;
+ success = TRUE;
+ }
+ return success;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsChannelDeactivateChannel --
+ *
+ * Deactivate a channel by calling the channels exit callback.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static void
+HgfsChannelDeactivateChannel(HgfsChannelData *channel, // IN/OUT: channel object
+ HgfsServerMgrData *mgrData) // IN: mgr handle
+{
+ channel->ops->exit(channel->connection);
+ channel->state &= ~HGFS_CHANNEL_STATE_CBINIT;
+ channel->connection = NULL;
+ mgrData->connection = NULL;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsChannelIsChannelActive --
+ *
+ * Is the channel active (initialized) for processing requests.
+ *
+ * Results:
+ * TRUE if a channel is active.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static Bool
+HgfsChannelIsChannelActive(HgfsChannelData *channel) // IN/OUT: channel object
+{
+ return (Bool)((channel->state & HGFS_CHANNEL_STATE_INIT) &&
+ (channel->state & HGFS_CHANNEL_STATE_CBINIT));
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsChannelReceive --
+ *
+ * Received a request on a channel pass on to the channel callback.
+ *
+ * Results:
+ * TRUE if a channel ws deactivated.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static Bool
+HgfsChannelReceive(HgfsChannelData *channel, // IN/OUT: channel object
+ char const *packetIn, // IN: incoming packet
+ size_t packetInSize, // IN: incoming packet size
+ char *packetOut, // OUT: outgoing packet
+ size_t *packetOutSize) // IN/OUT: outgoing packet size
+{
+ return channel->ops->receive(channel->connection,
+ packetIn,
+ packetInSize,
+ packetOut,
+ packetOutSize);
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * CHANNEL PUBLIC FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * HgfsChannelGuest_Init --
+ *
+ * Sets up the channel for HGFS.
+ *
+ * Initialize all the defined channels.
+ * At least one channel should succeed it's initialization
+ * completely, else we fail.
+ *
+ * Results:
+ * TRUE on success, FALSE on failure.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+Bool
+HgfsChannelGuest_Init(HgfsServerMgrData *mgrData) // IN/OUT: connection manager object
+{
+ HgfsServerSessionCallbacks *serverCBTable = NULL; // References a read-only global
+ Bool success = FALSE;
+
+ ASSERT(NULL != mgrData);
+ ASSERT(NULL == mgrData->connection);
+
+ gHgfsChannelsMgrState = 0;
+
+ /* If we have a new connection initialize the server session. */
+ if (!HgfsServer_InitState(&serverCBTable, NULL)) {
+ Debug("%s: Could not init Hgfs server.\n", __FUNCTION__);
+ goto exit;
+ }
+ gHgfsChannelsMgrState |= HGFS_CHANNELMGR_STATE_SERVERINIT;
+
+ /* Initialize channels objects. */
+ if (!HgfsChannelInitChannel(&gHgfsChannels[0])) {
+ Debug("%s: Could not init channel.\n", __FUNCTION__);
+ goto exit;
+ }
+ gHgfsChannelsMgrState |= HGFS_CHANNELMGR_STATE_CHANINIT;
+
+ /* Call the channels initializers. */
+ if (!HgfsChannelActivateChannel(&gHgfsChannels[0], serverCBTable, mgrData)) {
+ Debug("%s: Could not activate channel.\n", __FUNCTION__);
+ goto exit;
+ }
+
+ mgrData->connection = &gHgfsChannels[0];
+ success = TRUE;
+
+exit:
+ if (!success) {
+ HgfsChannelGuest_Exit(mgrData);
+ }
+ return success;
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * HgfsChannelGuest_Exit --
+ *
+ * Close the channel for HGFS.
+ *
+ * Close open sessions and close the channels.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Closes the worker group and all the channels.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+void
+HgfsChannelGuest_Exit(HgfsServerMgrData *mgrData) // IN/OUT: connection manager object
+{
+ HgfsChannelData *channel;
+
+ ASSERT(mgrData != NULL);
+
+ channel = mgrData->connection;
+
+ Debug("%s: Channel Exit.\n", __FUNCTION__);
+
+ if (NULL != channel) {
+ if (HgfsChannelIsChannelActive(channel)) {
+ HgfsChannelDeactivateChannel(channel, mgrData);
+ mgrData->connection = NULL;
+ }
+ } else {
+ channel = &gHgfsChannels[0];
+ }
+
+ if (gHgfsChannelsMgrState & HGFS_CHANNELMGR_STATE_CHANINIT) {
+ HgfsChannelExitChannel(channel);
+ gHgfsChannelsMgrState &= ~HGFS_CHANNELMGR_STATE_CHANINIT;
+ }
+
+ if (gHgfsChannelsMgrState & HGFS_CHANNELMGR_STATE_SERVERINIT) {
+ HgfsServer_ExitState();
+ gHgfsChannelsMgrState &= ~HGFS_CHANNELMGR_STATE_SERVERINIT;
+ }
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * HgfsChannelGuest_Receive --
+ *
+ * Process packet not associated with an HGFS only registered callback.
+ *
+ *
+ * Results:
+ * TRUE if successfully processed FALSE otherwise.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------------
+ */
+
+Bool
+HgfsChannelGuest_Receive(HgfsServerMgrData *mgrData, // IN/OUT : conn manager
+ char const *packetIn, // IN: incoming packet
+ size_t packetInSize, // IN: incoming packet size
+ char *packetOut, // OUT: outgoing packet
+ size_t *packetOutSize) // IN/OUT: outgoing packet size
+{
+ HgfsChannelData *channel = NULL;
+ Bool result = FALSE;
+
+ ASSERT(mgrData != NULL);
+ ASSERT(mgrData->connection != NULL);
+
+ channel = mgrData->connection;
+
+ Debug("%s: Channel receive request.\n", __FUNCTION__);
+
+ if (HgfsChannelIsChannelActive(channel)) {
+ result = HgfsChannelReceive(channel,
+ packetIn,
+ packetInSize,
+ packetOut,
+ packetOutSize);
+ }
+
+ return result;
+}
--- /dev/null
+/*********************************************************
+ * Copyright (C) 2010 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation version 2.1 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *********************************************************/
+
+/*
+ * hgfsChannel.c --
+ *
+ * Channel abstraction for the HGFS server.
+ *
+ */
+
+#include <stdlib.h>
+#include "vm_assert.h"
+#include "vm_atomic.h"
+#include "util.h"
+#include "debug.h"
+#include "hgfsChannelGuestInt.h"
+#include "hgfsServer.h"
+#include "hgfsServerManager.h"
+
+typedef enum {
+ HGFS_GST_CONN_UNINITIALIZED,
+ HGFS_GST_CONN_NOTCONNECTED,
+ HGFS_GST_CONN_CONNECTED,
+} HgfsGuestConnState;
+
+
+/* Since there is only one connection we use globals. */
+typedef struct HgfsGuestConn {
+ Atomic_uint32 refCount; /* Reference count. */
+ HgfsGuestConnState state;
+ HgfsServerSessionCallbacks *serverCbTable; /* Server session callbacks. */
+ HgfsServerChannelCallbacks channelCbTable;
+ void *serverSession;
+ size_t packetOutLen;
+ unsigned char *clientPacketOut; /* Client supplied buffer. */
+ unsigned char packetOut[HGFS_LARGE_PACKET_MAX]; /* For RPC msg callbacks. */
+} HgfsGuestConn;
+
+
+/* Callback functions. */
+static Bool HgfsChannelGuestBdInit(HgfsServerSessionCallbacks *serverCBTable,
+ void *rpc,
+ void *rpcCallback,
+ HgfsGuestConn **connection);
+static void HgfsChannelGuestBdExit(HgfsGuestConn *data);
+static Bool HgfsChannelGuestBdSend(void *data,
+ HgfsPacket *packet,
+ char *buffer,
+ size_t bufferLen,
+ HgfsSendFlags flags);
+static Bool HgfsChannelGuestBdReceive(HgfsGuestConn *data,
+ char const *packetIn,
+ size_t packetInSize,
+ char *packetOut,
+ size_t *packetOutSize);
+
+HgfsGuestChannelCBTable gGuestBackdoorOps = {
+ HgfsChannelGuestBdInit,
+ HgfsChannelGuestBdExit,
+ HgfsChannelGuestBdReceive,
+};
+
+/* Private functions. */
+static Bool HgfsChannelGuestConnConnect(HgfsGuestConn *connData);
+static void HgfsChannelGuestConnDestroy(HgfsGuestConn *connData);
+static Bool HgfsChannelGuestReceiveInternal(HgfsGuestConn *connData,
+ char const *packetIn,
+ size_t packetInSize,
+ char *packetOut,
+ size_t *packetOutSize);
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * CONNECTION DATA FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * HgfsChannelGuestConnGet --
+ *
+ * Increment connection reference count.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+static void
+HgfsChannelGuestConnGet(HgfsGuestConn *connData) // IN: connection
+{
+ ASSERT(connData);
+ Atomic_Inc(&connData->refCount);
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * HgfsChannelGuestConnPut --
+ *
+ * Decrement connection reference count.
+ *
+ * Free connection data if this is the last reference.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+static void
+HgfsChannelGuestConnPut(HgfsGuestConn *connData) // IN: connection
+{
+ ASSERT(connData);
+ if (Atomic_FetchAndDec(&connData->refCount) == 1) {
+ HgfsChannelGuestConnDestroy(connData);
+ }
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsChannelGuestConnInit --
+ *
+ * Initializes the connection.
+ *
+ * Results:
+ * TRUE always and the channel initialized.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static Bool
+HgfsChannelGuestConnInit(HgfsGuestConn **connData, // IN/OUT: channel object
+ HgfsServerSessionCallbacks *serverCBTable) // IN: server callbacks
+{
+ HgfsGuestConn *conn = NULL;
+
+ conn = Util_SafeCalloc(1, sizeof *conn);
+
+ /* Give ourselves a reference of one. */
+ HgfsChannelGuestConnGet(conn);
+ conn->serverCbTable = serverCBTable;
+ conn->state = HGFS_GST_CONN_NOTCONNECTED;
+
+ *connData = conn;
+ return TRUE;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsChannelGuestConnExit --
+ *
+ * Teardown the connection.
+ *
+ * Removes the reference and if it is the last will cause the connection
+ * to be destroyed.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static void
+HgfsChannelGuestConnExit(HgfsGuestConn *connData) // IN/OUT: channel object
+{
+ connData->state = HGFS_GST_CONN_UNINITIALIZED;
+
+ HgfsChannelGuestConnPut(connData);
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsChannelGuestConnDestroy --
+ *
+ * Destroy the connection.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static void
+HgfsChannelGuestConnDestroy(HgfsGuestConn *connData) // IN/OUT: channel object
+{
+ /* Make sure the server closes it's own session data. */
+ if (NULL != connData->serverSession) {
+ connData->serverCbTable->close(connData->serverSession);
+ connData->serverSession = NULL;
+ }
+ free(connData);
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsChannelGuestConnCreate --
+ *
+ * Create's the RPC connection for the HGFS guest if asked.
+ *
+ * Create the pseudo connection for the guest - state transition.
+ * (See the comment in the function where the RPC initialization
+ * is expected to be added.
+ * This entails is registering our callback to receive messages for the
+ * connection object passed. We will have the ability to receive
+ * requests until we unregister our callback.)
+ *
+ * NOTE: There is only handler and connction that can be used for
+ * all HGFS guest requests.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static void
+HgfsChannelGuestConnCreate(HgfsGuestConn *connData, // IN: connection
+ void *rpc, // IN: Rpc channel unused
+ void *rpcCallback) // IN: Rpc callback unused
+{
+ ASSERT(connData->state == HGFS_GST_CONN_NOTCONNECTED);
+
+ /*
+ * Rpc may be NULL for some cases. For example, if we
+ * just need to provide an HGFS server connection
+ * not associated with an HGFS only RPC connection.
+ */
+ if (connData->state == HGFS_GST_CONN_NOTCONNECTED) {
+
+ /* XXX - Here is where we would register an RPC callback if required. */
+
+ connData->state = HGFS_GST_CONN_CONNECTED;
+ HgfsChannelGuestConnGet(connData);
+ }
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsChannelGuestConnClose --
+ *
+ * Closes the connection for the HGFS guest.
+ *
+ * If required unregisters the callback will prevent us from
+ * receiving any more requests closing the connection.
+ *
+ * Results:
+ * TRUE if closed, FALSE if was not connected.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static Bool
+HgfsChannelGuestConnClose(HgfsGuestConn *connData, // IN: Connection
+ void *rpc, // IN: Rpc channel unused
+ void *rpcCallback) // IN: Rpc callback unused
+{
+ Bool result = FALSE;
+
+ if (connData->state == HGFS_GST_CONN_CONNECTED) {
+ /* XXX - Here is where we would unregister an RPC callback. */
+
+ /* Clear the connection object since we are unregistered. */
+ connData->state = HGFS_GST_CONN_NOTCONNECTED;
+ HgfsChannelGuestConnPut(connData);
+ result = TRUE;
+ }
+ return result;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsChannelGuestConnConnect --
+ *
+ * Send connection to the server.
+ *
+ * Results:
+ * TRUE if server returns a data object, FALSE if not.
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static Bool
+HgfsChannelGuestConnConnect(HgfsGuestConn *connData) // IN: our connection data
+{
+ Bool result;
+
+ connData->channelCbTable.getWriteVa = NULL;
+ connData->channelCbTable.getReadVa = NULL;
+ connData->channelCbTable.putVa = NULL;
+ connData->channelCbTable.send = HgfsChannelGuestBdSend;
+ result = connData->serverCbTable->connect(connData,
+ &connData->channelCbTable,
+ &connData->serverSession);
+ if (result) {
+ HgfsChannelGuestConnGet(connData);
+ }
+ return result;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsChannelGuestConnDisconnect --
+ *
+ * Send disconnect to the server.
+ *
+ * NOTE: The server data will be maintained until
+ * the connection is totally closed (last reference is gone).
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static void
+HgfsChannelGuestConnDisconnect(HgfsGuestConn *connData) // IN: connection
+{
+ if (connData->serverSession != NULL) {
+ /* Tell the server to to disconnect the session. */
+ connData->serverCbTable->disconnect(connData->serverSession);
+ HgfsChannelGuestConnPut(connData);
+ }
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * HgfsChannelGuestConnCloseInternal --
+ *
+ * Close the client and send a disconnect to the server for the session.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Closes the client connection and empties the queues.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+static void
+HgfsChannelGuestConnCloseInternal(HgfsGuestConn *connData, // IN: Connection data
+ void *rpc, // IN: Rpc channel unused
+ void *rpcCallback) // IN: Rpc callback unused
+{
+ /* Close (unregister the backdoor RPC) connection. */
+ if (HgfsChannelGuestConnClose(connData, rpc, rpcCallback)) {
+ /* Disconnect the connection from the server. */
+ HgfsChannelGuestConnDisconnect(connData);
+ }
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * HgfsChannelGuestReceiveInternal --
+ *
+ * Process packet not associated with any session.
+ *
+ * This function is used in the HGFS server inside Tools.
+ *
+ * Create an internal session if not already created, and process the packet.
+ *
+ * Results:
+ * TRUE if received packet ok and processed, FALSE otherwise.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------------
+ */
+
+static Bool
+HgfsChannelGuestReceiveInternal(HgfsGuestConn *connData, // IN: connection
+ char const *packetIn, // IN: incoming packet
+ size_t packetInSize, // IN: incoming packet size
+ char *packetOut, // OUT: outgoing packet
+ size_t *packetOutSize) // IN/OUT: outgoing packet size
+{
+ HgfsPacket packet;
+
+ ASSERT(packetIn);
+ ASSERT(packetOut);
+ ASSERT(packetOutSize);
+
+ if (connData->state == HGFS_GST_CONN_UNINITIALIZED) {
+ /* The connection was closed as we are exiting, so bail. */
+ *packetOutSize = 0;
+ return FALSE;
+ }
+
+ /* This is just a ping, return nothing. */
+ if (*packetOutSize == 0) {
+ return TRUE;
+ }
+
+ /*
+ * Create the session if not already created.
+ * This session is destroyed in HgfsServer_ExitState.
+ */
+ if (connData->serverSession == NULL) {
+ /* Do our guest connect now which will inform the server. */
+ if (!HgfsChannelGuestConnConnect(connData)) {
+ *packetOutSize = 0;
+ return FALSE;
+ }
+ }
+
+ memset(&packet, 0, sizeof packet);
+ /* For backdoor there is only one iov */
+ packet.iov[0].va = (void *)packetIn;
+ packet.iov[0].len = packetInSize;
+ packet.iovCount = 1;
+ packet.metaPacket = (void *)packetIn;
+ packet.metaPacketSize = packetInSize;
+ packet.replyPacket = packetOut;
+ packet.replyPacketSize = *packetOutSize;
+
+ /* The server will perform a synchronous processing of requests. */
+ connData->serverCbTable->receive(&packet, connData->serverSession);
+
+ *packetOutSize = connData->packetOutLen;
+
+ return TRUE;
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * REGISTERED CALLBACK FUNCTIONS
+ *
+ * XXX - Where we would have any internally registered callback routines.
+ * This routine would call HgfsChannelGuestReceiveInternal to process the
+ * request.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * GUEST CHANNEL CALLBACKS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * HgfsChannelGuestBdReceive --
+ *
+ * Process packet not associated with our registered callback.
+ *
+ *
+ * Results:
+ * TRUE if received packet ok and processed, FALSE otherwise.
+ *
+ * Side effects:
+ * None
+ *
+ *----------------------------------------------------------------------------
+ */
+
+Bool
+HgfsChannelGuestBdReceive(HgfsGuestConn *connData, // IN: connection
+ char const *packetIn, // IN: incoming packet
+ size_t packetInSize, // IN: incoming packet size
+ char *packetOut, // OUT: outgoing packet
+ size_t *packetOutSize) // IN/OUT: outgoing packet size
+{
+ Bool result = TRUE;
+
+ ASSERT(NULL != packetIn);
+ ASSERT(NULL != packetOut);
+ ASSERT(NULL != packetOutSize);
+ ASSERT(NULL != connData);
+
+ if (NULL == connData) {
+ result = FALSE;
+ goto exit;
+ }
+
+ connData->packetOutLen = *packetOutSize;
+ connData->clientPacketOut = packetOut;
+
+ result = HgfsChannelGuestReceiveInternal(connData,
+ packetIn,
+ packetInSize,
+ connData->clientPacketOut,
+ packetOutSize);
+
+ connData->clientPacketOut = NULL;
+ connData->packetOutLen = sizeof connData->packetOut;
+
+exit:
+ return result;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsChannelGuestBdSend --
+ *
+ * Send reply to the request
+ *
+ * Results:
+ * Always TRUE.
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static Bool
+HgfsChannelGuestBdSend(void *conn, // IN: our connection data
+ HgfsPacket *packet, // IN/OUT: Hgfs Packet
+ char *buffer, // IN: buffer to be sent
+ size_t bufferLen, // IN: buffer length
+ HgfsSendFlags flags) // IN: Flags to say how to process
+{
+ HgfsGuestConn *connData = conn;
+ unsigned char *packetOut = &connData->packetOut[0];
+
+ ASSERT(NULL != connData);
+ ASSERT(NULL != packet);
+ ASSERT(NULL != buffer);
+ ASSERT(bufferLen <= HGFS_LARGE_PACKET_MAX &&
+ bufferLen <= packet->replyPacketSize);
+
+ if (connData->clientPacketOut != NULL) {
+ /* Client passed us an out buffer so use it. */
+ packetOut = connData->clientPacketOut;
+ }
+ ASSERT(bufferLen <= connData->packetOutLen);
+ if (bufferLen > connData->packetOutLen) {
+ bufferLen = connData->packetOutLen;
+ }
+ connData->packetOutLen = (uint32)bufferLen;
+
+ if (!(flags & HGFS_SEND_NO_COMPLETE)) {
+ connData->serverCbTable->sendComplete(packet,
+ connData->serverSession);
+ }
+
+ return TRUE;
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * HgfsChannelGuestBdInit --
+ *
+ * Called from channel manager.
+ *
+ * Initializes our channel connections.
+ *
+ * Results:
+ * Always TRUE.
+ *
+ * Side effects:
+ * Registers RPC call.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+static Bool
+HgfsChannelGuestBdInit(HgfsServerSessionCallbacks *serverCBTable, // IN: server callbacks
+ void *rpc, // IN: Rpc channel unused
+ void *rpcCallback, // IN: Rpc callback unused
+ HgfsGuestConn **connection) // OUT: connection object
+{
+ HgfsGuestConn *connData = NULL;
+ Bool result;
+
+ ASSERT(NULL != connection);
+
+ /* Create our connection object. */
+ result = HgfsChannelGuestConnInit(&connData,
+ serverCBTable);
+ if (!result) {
+ Debug("%s: Error: guest connection initialized.\n", __FUNCTION__);
+ goto exit;
+ }
+
+ /*
+ * Create our connection now with any rpc handle and callback.
+ */
+ HgfsChannelGuestConnCreate(connData,
+ rpc,
+ rpcCallback);
+
+exit:
+ if (!result) {
+ if (NULL != connData) {
+ HgfsChannelGuestBdExit(connData);
+ connData = NULL;
+ }
+ }
+ *connection = connData;
+ Debug("%s: guest initialized.\n", __FUNCTION__);
+ return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * HgfsChannelGuestBdExit --
+ *
+ * Tearsdown our channel connections.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Unregisters RPC call.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+static void
+HgfsChannelGuestBdExit(HgfsGuestConn *connData)
+{
+ ASSERT(NULL != connData);
+
+ if (NULL != connData) {
+ /* Currently no rpc to unregister. */
+ HgfsChannelGuestConnCloseInternal(connData, NULL, NULL);
+ HgfsChannelGuestConnExit(connData);
+ }
+}
--- /dev/null
+/*********************************************************
+ * Copyright (C) 2009 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation version 2.1 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *********************************************************/
+
+#ifndef _HGFSCHANNELGUESTINT_H_
+#define _HGFSCHANNELGUESTINT_H_
+
+#include "hgfsServer.h"
+#include "hgfsServerManager.h"
+
+/**
+ * @file hgfsChannelGuestInt.h
+ *
+ * Prototypes of Hgfs channel packet process handler found in
+ * hgfsChannelGuest.c
+ */
+
+/*
+ * Opaque structure owned by the guest channel to hold the connection
+ * data to the HGFS server. Only held by the channel manager to pass
+ * back to the guest channel for requests and teardown.
+ * (Or it would be used with any registered internal callback.)
+ */
+ struct HgfsGuestConn;
+
+/*
+ * Guest channel table of callbacks.
+ */
+typedef struct HgfsGuestChannelCBTable {
+ Bool (*init)(HgfsServerSessionCallbacks *, void *, void *, struct HgfsGuestConn **);
+ void (*exit)(struct HgfsGuestConn *);
+ Bool (*receive)(struct HgfsGuestConn *, char const *, size_t, char *, size_t *);
+} HgfsGuestChannelCBTable;
+
+/* The guest channels callback tables. */
+extern HgfsGuestChannelCBTable gGuestBackdoorOps;
+
+/* For use by HgfsServerManager. */
+Bool HgfsChannelGuest_Init(HgfsServerMgrData *data);
+void HgfsChannelGuest_Exit(HgfsServerMgrData *data);
+Bool HgfsChannelGuest_Receive(HgfsServerMgrData *data,
+ char const *packetIn,
+ size_t packetInSize,
+ char *packetOut,
+ size_t *packetOutSize);
+
+#endif /* _HGFSCHANNELGUESTINT_H_ */
+
*
*/
-#include "rpcout.h"
-#include "rpcin.h"
#include "hgfsServerPolicy.h"
-#include "hgfsServer.h"
-#include "hgfsChannel.h"
+#include "hgfsChannelGuestInt.h"
#include "hgfsServerManager.h"
#include "vm_assert.h"
#include "hgfs.h"
-#include "vmware/guestrpc/tclodefs.h"
-static Bool HgfsServerManagerRpcInDispatch(char const **result,
- size_t *resultLen,
- const char *name,
- const char *args,
- size_t argsSize,
- void *clientData);
-
-
-/*
- *----------------------------------------------------------------------------
- *
- * HgfsChannel_Init --
- *
- * Sets up the channel for HGFS.
- *
- * NOTE: Initialize the Hgfs server for only for now.
- * This will move into a separate file when full interface implemented.
- *
- * Results:
- * TRUE on success, FALSE on failure.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------------
- */
-
-Bool
-HgfsChannel_Init(void *data) // IN: Unused rpc data
-{
- HgfsServerSessionCallbacks *serverCBTable = NULL;
- return HgfsServer_InitState(&serverCBTable, NULL);
-}
-
/*
*----------------------------------------------------------------------------
*
- * HgfsChannel_Exit --
- *
- * Close the channel for HGFS.
+ * HgfsServerManager_ProcessPacket --
*
- * NOTE: Close open sessions in the HGFS server currently.
- * This will move into a separate file when full interface implemented.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Closes the worker group and all the channels.
- *
- *----------------------------------------------------------------------------
- */
-
-void
-HgfsChannel_Exit(void *data) // IN: Unused rpc data
-{
- ASSERT(data != NULL);
- HgfsServer_ExitState();
-}
-
-
-/*
- *----------------------------------------------------------------------------
- *
- * HgfsServerManagerRpcInDispatch --
- *
- * Handles hgfs requests.
+ * Handles hgfs requests from a client not by our
+ * registered RPC callback.
*
* Results:
* TRUE on success, FALSE on error.
*----------------------------------------------------------------------------
*/
-static Bool
-HgfsServerManagerRpcInDispatch(char const **result, // OUT
- size_t *resultLen, // OUT
- const char *name, // IN
- const char *args, // IN
- size_t argsSize, // IN
- void *clientData) // Unused
-{
- size_t packetSize;
- static char packet[HGFS_LARGE_PACKET_MAX];
-
-
- ASSERT(clientData == NULL);
-
- if (argsSize == 0) {
- return RpcIn_SetRetVals(result, resultLen, "1 argument required", FALSE);
- }
-
- ASSERT(args[0] == ' ');
- packetSize = argsSize - 1;
- HgfsServer_ProcessPacket((char const *)(args + 1), packet, &packetSize);
-
- *result = packet;
- *resultLen = packetSize;
- return TRUE;
-}
-
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * HgfsServerManager_CapReg --
- *
- * Tell the vmx that the specified guest app can (or no longer can)
- * receive hgfs requests.
- *
- * Results:
- * TRUE on success, FALSE on failure.
- *
- * Side effects:
- * None.
- *
- *-----------------------------------------------------------------------------
- */
-
-Bool
-HgfsServerManager_CapReg(const char *appName, // IN
- Bool enable) // IN
+Bool HgfsServerManager_ProcessPacket(HgfsServerMgrData *mgrData, // IN: hgfs mgr
+ char const *packetIn, // IN: rqst
+ size_t packetInSize, // IN: rqst size
+ char *packetOut, // OUT: rep
+ size_t *packetOutSize) // IN/OUT: rep buf/data size
{
- /*
- * Register/unregister this channel as an hgfs server.
- */
- if (!RpcOut_sendOne(NULL, NULL, "tools.capability.hgfs_server %s %s",
- appName, enable ? "1" : "0")) {
- return FALSE;
- }
-
- return TRUE;
+ /* Pass to the channel to handle processing and the server. */
+ return HgfsChannelGuest_Receive(mgrData,
+ packetIn,
+ packetInSize,
+ packetOut,
+ packetOutSize);
}
*/
Bool
-HgfsServerManager_Register(void *rpcIn, // IN: RpcIn channel
- const char *appName) // IN: App with HGFS server
+HgfsServerManager_Register(HgfsServerMgrData *data) // IN: RpcIn channel
{
- RpcIn *myRpcIn = (RpcIn *)rpcIn;
- /*
- * myRpcIn may be NULL for some cases. When we run the tools as
- * a guest application in a non-VMware VM, for example, we do not
- * have a backdoor.
- */
- ASSERT(appName);
+ ASSERT(data);
+ ASSERT(data->appName);
+
+
/*
* Passing NULL here is safe because the shares maintained by the guest
return FALSE;
}
- if (!HgfsChannel_Init(myRpcIn)) {
+ if (!HgfsChannelGuest_Init(data)) {
HgfsServerPolicy_Cleanup();
return FALSE;
}
- if (NULL != myRpcIn) {
- RpcIn_RegisterCallback(myRpcIn, HGFS_SYNC_REQREP_CMD,
- HgfsServerManagerRpcInDispatch, NULL);
- }
-
- /*
- * Prior to WS55, the VMX did not know about the "hgfs_server"
- * capability. This doesn't mean that the HGFS server wasn't needed, it's
- * just that the capability was introduced in CS 225439 so that the VMX
- * could decide which HGFS server to communicate with.
- *
- * Long story short, we shouldn't care if this function fails.
- */
- if (NULL != myRpcIn) {
- HgfsServerManager_CapReg(appName, TRUE);
- }
-
return TRUE;
}
*/
void
-HgfsServerManager_Unregister(void *rpcIn, // IN: RpcIn channel
- const char *appName) // IN: App with HGFS server
+HgfsServerManager_Unregister(HgfsServerMgrData *data) // IN: RpcIn channel
{
- RpcIn *myRpcIn = (RpcIn *)rpcIn;
- ASSERT(myRpcIn);
- ASSERT(appName);
+ ASSERT(data);
+ ASSERT(data->appName != NULL);
- HgfsServerManager_CapReg(appName, FALSE);
- RpcIn_UnregisterCallback(myRpcIn, HGFS_SYNC_REQREP_CMD);
- HgfsChannel_Exit(myRpcIn);
+ HgfsChannelGuest_Exit(data);
HgfsServerPolicy_Cleanup();
}
+++ /dev/null
-/*********************************************************
- * Copyright (C) 2009 VMware, Inc. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation version 2.1 and no later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
- * License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- *********************************************************/
-
-/*
- * hgfsChannel.h --
- *
- * Channel abstraction for the HGFS server.
- */
-
-#ifndef _HGFSCHANNEL_H_
-#define _HGFSCHANNEL_H_
-
-#include "vm_basic_types.h"
-#include "dbllnklst.h"
-#include "hgfsServer.h"
-
-/*
- * Handle used by the server to identify files and searches. Used
- * by the driver to match server replies with pending requests.
- */
-
-typedef uint32 HgfsChannelId;
-
-typedef struct HgfsChannelCBTable {
- Bool (*init)(HgfsChannelId, HgfsServerSessionCallbacks *, void **);
- void (*exit)(void *);
- void (*invalidateObjects)(DblLnkLst_Links *, void *);
-} HgfsChannelCBTable;
-
-
-/* For use by HgfsServerManager. */
-Bool HgfsChannel_Init(void *data); /* Optional data, used in guest. */
-void HgfsChannel_Exit(void *data); /* Optional data, used in guest. */
-void HgfsChannel_InvalidateObjects(DblLnkLst_Links *shares);
-#endif
Bool HgfsServerManager_ChangeState(Bool enable);
#else /* VMX86_TOOLS */
-Bool HgfsServerManager_Register(void *rpcIn,
- const char *appName);
-void HgfsServerManager_Unregister(void *rpcIn,
- const char *appName);
-Bool HgfsServerManager_CapReg(const char *appName,
- Bool enable);
+//#include "hgfsServer.h" // For HgfsReceiveFlags
+
+typedef struct HgfsServerMgrData {
+ const char *appName; // Application name to register
+ void *rpc; // RpcChannel unused
+ void *rpcCallback; // RpcChannelCallback unused
+ void *connection; // Connection object returned on success
+} HgfsServerMgrData;
+
+
+#define HgfsServerManager_DataInit(mgr, _name, _rpc, _rpcCallback) \
+ do { \
+ (mgr)->appName = (_name); \
+ (mgr)->rpc = (_rpc); \
+ (mgr)->rpcCallback = (_rpcCallback); \
+ (mgr)->connection = NULL; \
+ } while (0)
+
+Bool HgfsServerManager_Register(HgfsServerMgrData *data);
+void HgfsServerManager_Unregister(HgfsServerMgrData *data);
+Bool HgfsServerManager_ProcessPacket(HgfsServerMgrData *mgrData,
+ char const *packetIn,
+ size_t packetInSize,
+ char *packetOut,
+ size_t *packetOutSize);
#endif
#endif // _HGFS_SERVER_MANAGER_H_
libhgfs_la_LIBADD += ../lib/hgfs/libHgfs.la
libhgfs_la_LIBADD += ../lib/hgfsHelper/libHgfsHelper.la
libhgfs_la_LIBADD += ../lib/hgfsServer/libHgfsServer.la
+libhgfs_la_LIBADD += ../lib/hgfsServerManagerGuest/libHgfsServerManagerGuest.la
libhgfs_la_LIBADD += ../lib/hgfsServerPolicyGuest/libHgfsServerPolicyGuest.la
libhgfs_la_LIBADD += @GLIB2_LIBS@
libhgfs_la_LIBADD += @GTHREAD_LIBS@
#define G_LOG_DOMAIN "hgfsd"
#include "hgfs.h"
-#include "hgfsServerPolicy.h"
-#include "hgfsServer.h"
-#include "hgfsChannel.h"
+#include "hgfsServerManager.h"
#include "vm_assert.h"
#include "vmware/guestrpc/tclodefs.h"
#include "vmware/tools/plugin.h"
#include "vmware/tools/utils.h"
+
#if !defined(__APPLE__)
#include "embed_version.h"
#include "vmtoolsd_version.h"
/**
- * Sets up the channel for HGFS.
- *
- * NOTE: Initialize the Hgfs server for only for now.
- * This will move into a separate file when full interface implemented.
- *
- * @param[in] data Unused RPC request data.
+ * Clean up internal state on shutdown.
*
- * @return TRUE on success, FALSE on error.
- */
-
-Bool
-HgfsChannel_Init(void *data) // IN: Unused data
-{
- HgfsServerSessionCallbacks *serverCBTable = NULL;
- return HgfsServer_InitState(&serverCBTable, NULL);
-}
-
-
-/**
- * Close up the channel for HGFS.
- *
- * NOTE: Close open sessions in the HGFS server currently.
- * This will move into a separate file when full interface implemented.
- *
- * @param[in] data Unused RPC request data.
- *
- * @return None.
+ * @param[in] src The source object.
+ * @param[in] ctx Unused.
+ * @param[in] plugin Plugin registration data.
*/
-void
-HgfsChannel_Exit(void *data)
+static void
+HgfsServerShutdown(gpointer src,
+ ToolsAppCtx *ctx,
+ ToolsPluginData *plugin)
{
- ASSERT(data != NULL);
- HgfsServer_ExitState();
+ HgfsServerMgrData *mgrData = plugin->_private;
+ HgfsServerManager_Unregister(mgrData);
+ g_free(mgrData);
}
*/
static gboolean
-HgfsServerRpcInDispatch(RpcInData *data)
+HgfsServerRpcDispatch(RpcInData *data)
{
- size_t packetSize;
- static char packet[HGFS_LARGE_PACKET_MAX];
+ HgfsServerMgrData *mgrData;
+ size_t replySize;
+ static char reply[HGFS_LARGE_PACKET_MAX];
- ASSERT(data->clientData == NULL);
+ ASSERT(data->clientData != NULL);
+ mgrData = data->clientData;
if (data->argsSize == 0) {
return RPCIN_SETRETVALS(data, "1 argument required", FALSE);
}
- packetSize = data->argsSize - 1;
- HgfsServer_ProcessPacket(data->args + 1, packet, &packetSize);
+ replySize = sizeof reply;
+ HgfsServerManager_ProcessPacket(mgrData, data->args + 1, data->argsSize - 1, reply, &replySize);
- data->result = packet;
- data->resultLen = packetSize;
+ data->result = reply;
+ data->resultLen = replySize;
return TRUE;
}
HgfsServerCapReg(gpointer src,
ToolsAppCtx *ctx,
gboolean set,
- gpointer data)
+ ToolsPluginData *plugin)
{
gchar *msg;
const char *appName = NULL;
NULL,
NULL
};
+ HgfsServerMgrData *mgrData;
if (strcmp(ctx->name, VMTOOLS_GUEST_SERVICE) != 0 &&
strcmp(ctx->name, VMTOOLS_USER_SERVICE) != 0) {
return NULL;
}
- /*
- * Passing NULL here is safe because the shares maintained by the guest
- * policy server never change, invalidating the need for an invalidate
- * function.
- */
- if (!HgfsServerPolicy_Init(NULL)) {
- g_warning("HgfsServerPolicy_Init() failed, aborting HGFS server init.\n");
- return NULL;
- }
+ mgrData = g_malloc0(sizeof *mgrData);
+ HgfsServerManager_DataInit(mgrData,
+ ctx->name,
+ NULL, // rpc channel unused
+ NULL); // no rpc callback
- if (!HgfsChannel_Init(NULL)) {
+ if (!HgfsServerManager_Register(mgrData)) {
g_warning("HgfsServer_InitState() failed, aborting HGFS server init.\n");
- HgfsServerPolicy_Cleanup();
+ g_free(mgrData);
return NULL;
}
{
RpcChannelCallback rpcs[] = {
- { HGFS_SYNC_REQREP_CMD, HgfsServerRpcInDispatch, NULL, NULL, NULL, 0 }
+ { HGFS_SYNC_REQREP_CMD, HgfsServerRpcDispatch, mgrData, NULL, NULL, 0 }
};
ToolsPluginSignalCb sigs[] = {
- { TOOLS_CORE_SIG_CAPABILITIES, HgfsServerCapReg, ®Data }
+ { TOOLS_CORE_SIG_CAPABILITIES, HgfsServerCapReg, ®Data },
+ { TOOLS_CORE_SIG_SHUTDOWN, HgfsServerShutdown, ®Data }
};
ToolsAppReg regs[] = {
{ TOOLS_APP_GUESTRPC, VMTools_WrapArray(rpcs, sizeof *rpcs, ARRAYSIZE(rpcs)) },
regData.regs = VMTools_WrapArray(regs, sizeof *regs, ARRAYSIZE(regs));
}
+ regData._private = mgrData;
return ®Data;
}
#include "printer.h"
#include "base64.h"
#include "syncDriver.h"
-#include "hgfsServer.h"
+#include "hgfsServerManager.h"
#include "hgfs.h"
#include "system.h"
#include "codeset.h"
RpcInRet ToolsDaemonTcloReceiveVixCommand(RpcInData *data);
+static HgfsServerMgrData gFoundryHgfsBkdrConn;
RpcInRet ToolsDaemonHgfsImpersonated(RpcInData *data);
#if defined(linux) || defined(_WIN32)
static Bool thisProcessRunsAsRoot = FALSE;
-
/*
*-----------------------------------------------------------------------------
*
}
#endif
+ /* Register a straight through connection with the Hgfs server. */
+ HgfsServerManager_DataInit(&gFoundryHgfsBkdrConn,
+ VIX_BACKDOORCOMMAND_SEND_HGFS_PACKET,
+ NULL, // rpc - no rpc registered
+ NULL); // rpc callback
+ HgfsServerManager_Register(&gFoundryHgfsBkdrConn);
+
+}
+
+
+/**
+ * Uninitializes internal state of the Foundry daemon.
+ *
+ * @param[in] ctx Application context.
+ */
+
+void
+FoundryToolsDaemon_Uninitialize(ToolsAppCtx *ctx)
+{
+ HgfsServerManager_Unregister(&gFoundryHgfsBkdrConn);
+ VixTools_Uninitialize();
}
{
VixError err;
size_t hgfsPacketSize = 0;
+ size_t hgfsReplySize = 0;
const char *origArgs = data->args;
Bool impersonatingVMWareUser = FALSE;
char *credentialTypeStr = NULL;
&userToken);
if (!impersonatingVMWareUser) {
err = VIX_E_GUEST_USER_PERMISSIONS;
- hgfsPacketSize = 0;
goto abort;
}
}
* Impersonation was okay, so let's give our packet to
* the HGFS server and forward the reply packet back.
*/
- HgfsServer_ProcessPacket(data->args, // packet in buf
- hgfsReplyPacket, // packet out buf
- &hgfsPacketSize); // in/out size
+ hgfsReplySize = sizeof resultPacket - (hgfsReplyPacket - resultPacket);
+ HgfsServerManager_ProcessPacket(&gFoundryHgfsBkdrConn, // hgfs server connection
+ data->args, // packet in buf
+ hgfsPacketSize, // packet in size
+ hgfsReplyPacket, // packet out buf
+ &hgfsReplySize); // reply buf/data size
abort:
if (impersonatingVMWareUser) {
data->result = resultPacket;
data->resultLen = STRLEN_OF_MAX_64_BIT_NUMBER_AS_STRING
+ OTHER_TEXT_SIZE
- + hgfsPacketSize;
+ + hgfsReplySize;
/*
* Render the foundry error codes into the buffer.
void
FoundryToolsDaemon_Initialize(ToolsAppCtx *ctx);
+void
+FoundryToolsDaemon_Uninitialize(ToolsAppCtx *ctx);
#endif /* __VIX_TOOLS_DAEMON_H__ */
VM_EMBED_VERSION(VMTOOLSD_VERSION_STRING);
#endif
+/**
+ * Clean up internal state on shutdown.
+ *
+ * @param[in] src The source object.
+ * @param[in] ctx Unused.
+ * @param[in] plugin Plugin registration data.
+ */
+
+static void
+VixShutdown(gpointer src,
+ ToolsAppCtx *ctx,
+ ToolsPluginData *plugin)
+{
+ FoundryToolsDaemon_Uninitialize(ctx);
+}
+
/**
* Returns the registration data for either the guestd or userd process.
ToolsDaemonTcloSyncDriverThaw, NULL, NULL, NULL, 0 }
#endif
};
+ ToolsPluginSignalCb sigs[] = {
+ { TOOLS_CORE_SIG_SHUTDOWN, VixShutdown, ®Data }
+ };
ToolsAppReg regs[] = {
- { TOOLS_APP_GUESTRPC, VMTools_WrapArray(rpcs, sizeof *rpcs, ARRAYSIZE(rpcs)) }
+ { TOOLS_APP_GUESTRPC, VMTools_WrapArray(rpcs, sizeof *rpcs, ARRAYSIZE(rpcs)) },
+ { TOOLS_APP_SIGNALS, VMTools_WrapArray(sigs, sizeof *sigs, ARRAYSIZE(sigs)) }
};
#if defined(G_PLATFORM_WIN32)
#include "vixCommands.h"
#include "base64.h"
#include "hostinfo.h"
-#include "hgfsServer.h"
+#include "hgfsServerManager.h"
#include "hgfs.h"
#include "system.h"
#include "codeset.h"
*/
static HashTable *userEnvironmentTable = NULL;
#endif
+#if !defined(__FreeBSD__)
+static HgfsServerMgrData gVixHgfsBkdrConn;
+#endif
static VixError VixToolsGetFileInfo(VixCommandRequestHeader *requestMsg,
char **result);
#ifndef _WIN32
VixToolsBuildUserEnvironmentTable(originalEnvp);
#endif
+#if !defined(__FreeBSD__)
+ /* Register a straight through connection with the Hgfs server. */
+ HgfsServerManager_DataInit(&gVixHgfsBkdrConn,
+ VIX_BACKDOORCOMMAND_COMMAND,
+ NULL, // no RPC registration
+ NULL); // rpc callback
+ HgfsServerManager_Register(&gVixHgfsBkdrConn);
+#endif
return(err);
} // VixTools_Initialize
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * VixTools_Uninitialize --
+ *
+ *
+ * Return value:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+VixTools_Uninitialize(void) // IN
+{
+#if !defined(__FreeBSD__)
+ HgfsServerManager_Unregister(&gVixHgfsBkdrConn);
+#endif
+}
+
+
#ifndef _WIN32
/*
*-----------------------------------------------------------------------------
void *userToken = NULL;
Bool impersonatingVMWareUser = FALSE;
char *hgfsPacket;
- size_t hgfsPacketSize = 0;
+ size_t hgfsReplyPacketSize = 0;
static char hgfsReplyPacket[HGFS_LARGE_PACKET_MAX];
if ((NULL == requestMsg) || (0 == requestMsg->hgfsPacketSize)) {
impersonatingVMWareUser = TRUE;
hgfsPacket = ((char *) requestMsg) + sizeof(*requestMsg);
- hgfsPacketSize = requestMsg->hgfsPacketSize;
+ hgfsReplyPacketSize = sizeof hgfsReplyPacket;
#if !defined(__FreeBSD__)
/*
* Impersonation was okay, so let's give our packet to
* the HGFS server and forward the reply packet back.
*/
- HgfsServer_ProcessPacket(hgfsPacket, // packet in buf
- hgfsReplyPacket, // packet out buf
- &hgfsPacketSize); // in/out size
+ HgfsServerManager_ProcessPacket(&gVixHgfsBkdrConn, // connection
+ hgfsPacket, // packet in buf
+ requestMsg->hgfsPacketSize, // packet in size
+ hgfsReplyPacket, // packet out buf
+ &hgfsReplyPacketSize); // in/out size
#endif
if (NULL != resultValueResult) {
- *resultValueResult = hgfsPacketSize;
+ *resultValueResult = hgfsReplyPacketSize;
}
if (NULL != result) {
*result = hgfsReplyPacket;
VixToolsReportProgramDoneProcType reportProgramDoneProc,
void *clientData);
+void VixTools_Uninitialize(void);
+
void VixTools_SetConsoleUserPolicy(Bool allowConsoleUserOpsParam);
void VixTools_SetRunProgramCallback(VixToolsReportProgramDoneProcType reportProgramDoneProc,