/*********************************************************
- * Copyright (C) 2008-2016 VMware, Inc. All rights reserved.
+ * Copyright (C) 2008-2016,2018 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
* Common functions to all RPC channel implementations.
*/
+#include <stdlib.h>
#include <string.h>
-#include "vm_assert.h"
-#include "dynxdr.h"
+#include "debug.h"
#include "rpcChannelInt.h"
-#include "str.h"
-#include "strutil.h"
+
+#if defined(NEED_RPCIN)
+#include "dynxdr.h"
#include "vmxrpc.h"
#include "xdrutil.h"
#include "rpcin.h"
-#include "debug.h"
+#endif
+
+#include "str.h"
+#include "strutil.h"
+#include "util.h"
+#include "vm_assert.h"
/** Internal state of a channel. */
typedef struct RpcChannelInt {
RpcChannel impl;
+#if defined(NEED_RPCIN)
gchar *appName;
GHashTable *rpcs;
GMainContext *mainCtx;
gpointer resetData;
gboolean rpcError;
guint rpcErrorCount;
+#endif
} RpcChannelInt;
-/** Max number of times to attempt a channel restart. */
-#define RPCIN_MAX_RESTARTS 60
-
#define LGPFX "RpcChannel: "
-static gboolean
-RpcChannelPing(RpcInData *data);
-
-static RpcChannelCallback gRpcHandlers[] = {
- { "ping", RpcChannelPing, NULL, NULL, NULL, 0 }
-};
-
static gboolean gUseBackdoorOnly = FALSE;
/*
static void RpcChannelStopNoLock(RpcChannel *chan);
+
+#if defined(NEED_RPCIN)
+/** Max number of times to attempt a channel restart. */
+#define RPCIN_MAX_RESTARTS 60
+
+static gboolean
+RpcChannelPing(RpcInData *data);
+
+static RpcChannelCallback gRpcHandlers[] = {
+ { "ping", RpcChannelPing, NULL, NULL, NULL, 0 }
+};
+
/**
* Handler for a "ping" message. Does nothing.
*
}
-/**
- * Creates a new RpcChannel without any implementation.
- *
- * This is mainly for use of code that is implementing a custom RpcChannel.
- * Such implementations should provide their own "constructor"-type function
- * which should then call this function to get an RpcChannel instance. They
- * should then fill in the function pointers that provide the implementation
- * for the channel before making the channel available to the callers.
- *
- * @return A new RpcChannel instance.
- */
-
-RpcChannel *
-RpcChannel_Create(void)
-{
- RpcChannelInt *chan = g_new0(RpcChannelInt, 1);
- return &chan->impl;
-}
-
-
/**
* Dispatches the given RPC to the registered handler. This mimics the behavior
* of the RpcIn library (but is not tied to that particular implementation of
/**
- * Shuts down an RPC channel and release any held resources.
+ * Initializes the RPC channel for inbound operations.
*
- * @param[in] chan The RPC channel.
+ * This function must be called before starting the channel if the application
+ * wants to receive messages on the channel. Applications don't need to call it
+ * if only using the outbound functionality.
*
- * @return Whether the channel was shut down successfully.
+ * @param[in] chan The RPC channel.
+ * @param[in] appName TCLO application name.
+ * @param[in] mainCtx Application event context.
+ * @param[in] appCtx Application context.
+ * @param[in] resetCb Callback for when a reset occurs.
+ * @param[in] resetData Client data for the reset callback.
*/
-gboolean
-RpcChannel_Destroy(RpcChannel *chan)
+void
+RpcChannel_Setup(RpcChannel *chan,
+ const gchar *appName,
+ GMainContext *mainCtx,
+ gpointer appCtx,
+ RpcChannelResetCb resetCb,
+ gpointer resetData)
{
size_t i;
RpcChannelInt *cdata = (RpcChannelInt *) chan;
- if (cdata->impl.funcs != NULL && cdata->impl.funcs->shutdown != NULL) {
- cdata->impl.funcs->shutdown(chan);
- }
+ cdata->appName = g_strdup(appName);
+ cdata->appCtx = appCtx;
+ cdata->mainCtx = g_main_context_ref(mainCtx);
+ cdata->resetCb = resetCb;
+ cdata->resetData = resetData;
+
+ cdata->resetReg.name = "reset";
+ cdata->resetReg.callback = RpcChannelReset;
+ cdata->resetReg.clientData = chan;
+
+ /* Register the callbacks handled by the rpcChannel library. */
+ RpcChannel_RegisterCallback(chan, &cdata->resetReg);
- RpcChannel_UnregisterCallback(chan, &cdata->resetReg);
for (i = 0; i < ARRAYSIZE(gRpcHandlers); i++) {
- RpcChannel_UnregisterCallback(chan, &gRpcHandlers[i]);
+ RpcChannel_RegisterCallback(chan, &gRpcHandlers[i]);
}
- if (cdata->rpcs != NULL) {
- g_hash_table_destroy(cdata->rpcs);
- cdata->rpcs = NULL;
+ if (chan->funcs != NULL && chan->funcs->setup != NULL) {
+ chan->funcs->setup(chan, mainCtx, appName, appCtx);
+ } else {
+ chan->mainCtx = g_main_context_ref(mainCtx);
+ chan->in = RpcIn_Construct(mainCtx, RpcChannel_Dispatch, chan);
+ ASSERT(chan->in != NULL);
}
+}
- cdata->resetCb = NULL;
- cdata->resetData = NULL;
- cdata->appCtx = NULL;
- g_free(cdata->appName);
- cdata->appName = NULL;
+/**
+ * Registers a new RPC handler in the given RPC channel. This function is
+ * not thread-safe.
+ *
+ * @param[in] chan The channel instance.
+ * @param[in] rpc Info about the RPC being registered.
+ */
- if (cdata->mainCtx != NULL) {
- g_main_context_unref(cdata->mainCtx);
- cdata->mainCtx = NULL;
+void
+RpcChannel_RegisterCallback(RpcChannel *chan,
+ RpcChannelCallback *rpc)
+{
+ RpcChannelInt *cdata = (RpcChannelInt *) chan;
+ ASSERT(rpc->name != NULL && strlen(rpc->name) > 0);
+ ASSERT(rpc->callback);
+ ASSERT(rpc->xdrIn == NULL || rpc->xdrInSize > 0);
+ if (cdata->rpcs == NULL) {
+ cdata->rpcs = g_hash_table_new(g_str_hash, g_str_equal);
}
-
- if (cdata->resetCheck != NULL) {
- g_source_destroy(cdata->resetCheck);
- cdata->resetCheck = NULL;
+ if (g_hash_table_lookup(cdata->rpcs, rpc->name) != NULL) {
+ Panic("Trying to overwrite existing RPC registration for %s!\n", rpc->name);
}
+ g_hash_table_insert(cdata->rpcs, (gpointer) rpc->name, rpc);
+}
- g_free(cdata);
- return TRUE;
+
+/**
+ * Unregisters a new RPC handler from the given RPC channel. This function is
+ * not thread-safe.
+ *
+ * @param[in] chan The channel instance.
+ * @param[in] rpc Info about the RPC being unregistered.
+ */
+
+void
+RpcChannel_UnregisterCallback(RpcChannel *chan,
+ RpcChannelCallback *rpc)
+{
+ RpcChannelInt *cdata = (RpcChannelInt *) chan;
+ if (cdata->rpcs != NULL) {
+ g_hash_table_remove(cdata->rpcs, rpc->name);
+ }
}
* @param[in] status Error description.
*/
-void
-RpcChannel_Error(void *_chan,
+static void
+RpcChannelError(void *_chan,
char const *status)
{
RpcChannelInt *chan = _chan;
g_source_attach(chan->resetCheck, chan->mainCtx);
}
}
+#endif
/**
- * Initializes the RPC channel for inbound operations.
+ * Creates a new RpcChannel without any implementation.
*
- * This function must be called before starting the channel if the application
- * wants to receive messages on the channel. Applications don't need to call it
- * if only using the outbound functionality.
+ * This is mainly for use of code that is implementing a custom RpcChannel.
+ * Such implementations should provide their own "constructor"-type function
+ * which should then call this function to get an RpcChannel instance. They
+ * should then fill in the function pointers that provide the implementation
+ * for the channel before making the channel available to the callers.
*
- * @param[in] chan The RPC channel.
- * @param[in] appName TCLO application name.
- * @param[in] mainCtx Application event context.
- * @param[in] appCtx Application context.
- * @param[in] resetCb Callback for when a reset occurs.
- * @param[in] resetData Client data for the reset callback.
+ * @return A new RpcChannel instance.
*/
-void
-RpcChannel_Setup(RpcChannel *chan,
- const gchar *appName,
- GMainContext *mainCtx,
- gpointer appCtx,
- RpcChannelResetCb resetCb,
- gpointer resetData)
+RpcChannel *
+RpcChannel_Create(void)
{
+ RpcChannelInt *chan = g_new0(RpcChannelInt, 1);
+ return &chan->impl;
+}
+
+
+/**
+ * Shuts down an RPC channel and release any held resources.
+ *
+ * @param[in] chan The RPC channel.
+ *
+ * @return Whether the channel was shut down successfully.
+ */
+
+gboolean
+RpcChannel_Destroy(RpcChannel *chan)
+{
+#if defined(NEED_RPCIN)
size_t i;
+#endif
RpcChannelInt *cdata = (RpcChannelInt *) chan;
- cdata->appName = g_strdup(appName);
- cdata->appCtx = appCtx;
- cdata->mainCtx = g_main_context_ref(mainCtx);
- cdata->resetCb = resetCb;
- cdata->resetData = resetData;
+ if (cdata->impl.funcs != NULL && cdata->impl.funcs->shutdown != NULL) {
+ cdata->impl.funcs->shutdown(chan);
+ }
- cdata->resetReg.name = "reset";
- cdata->resetReg.callback = RpcChannelReset;
- cdata->resetReg.clientData = chan;
+#if defined(NEED_RPCIN)
+ RpcChannel_UnregisterCallback(chan, &cdata->resetReg);
+ for (i = 0; i < ARRAYSIZE(gRpcHandlers); i++) {
+ RpcChannel_UnregisterCallback(chan, &gRpcHandlers[i]);
+ }
- /* Register the callbacks handled by the rpcChannel library. */
- RpcChannel_RegisterCallback(chan, &cdata->resetReg);
+ if (cdata->rpcs != NULL) {
+ g_hash_table_destroy(cdata->rpcs);
+ cdata->rpcs = NULL;
+ }
- for (i = 0; i < ARRAYSIZE(gRpcHandlers); i++) {
- RpcChannel_RegisterCallback(chan, &gRpcHandlers[i]);
+ cdata->resetCb = NULL;
+ cdata->resetData = NULL;
+ cdata->appCtx = NULL;
+
+ g_free(cdata->appName);
+ cdata->appName = NULL;
+
+ if (cdata->mainCtx != NULL) {
+ g_main_context_unref(cdata->mainCtx);
+ cdata->mainCtx = NULL;
}
- if (chan->funcs != NULL && chan->funcs->setup != NULL) {
- chan->funcs->setup(chan, mainCtx, appName, appCtx);
- } else {
- chan->mainCtx = g_main_context_ref(mainCtx);
- chan->in = RpcIn_Construct(mainCtx, RpcChannel_Dispatch, chan);
- ASSERT(chan->in != NULL);
+ if (cdata->resetCheck != NULL) {
+ g_source_destroy(cdata->resetCheck);
+ cdata->resetCheck = NULL;
}
+#endif
+
+ g_free(cdata);
+ return TRUE;
}
}
-/**
- * Registers a new RPC handler in the given RPC channel. This function is
- * not thread-safe.
- *
- * @param[in] chan The channel instance.
- * @param[in] rpc Info about the RPC being registered.
- */
-
-void
-RpcChannel_RegisterCallback(RpcChannel *chan,
- RpcChannelCallback *rpc)
-{
- RpcChannelInt *cdata = (RpcChannelInt *) chan;
- ASSERT(rpc->name != NULL && strlen(rpc->name) > 0);
- ASSERT(rpc->callback);
- ASSERT(rpc->xdrIn == NULL || rpc->xdrInSize > 0);
- if (cdata->rpcs == NULL) {
- cdata->rpcs = g_hash_table_new(g_str_hash, g_str_equal);
- }
- if (g_hash_table_lookup(cdata->rpcs, rpc->name) != NULL) {
- Panic("Trying to overwrite existing RPC registration for %s!\n", rpc->name);
- }
- g_hash_table_insert(cdata->rpcs, (gpointer) rpc->name, rpc);
-}
-
-
-/**
- * Unregisters a new RPC handler from the given RPC channel. This function is
- * not thread-safe.
- *
- * @param[in] chan The channel instance.
- * @param[in] rpc Info about the RPC being unregistered.
- */
-
-void
-RpcChannel_UnregisterCallback(RpcChannel *chan,
- RpcChannelCallback *rpc)
-{
- RpcChannelInt *cdata = (RpcChannelInt *) chan;
- if (cdata->rpcs != NULL) {
- g_hash_table_remove(cdata->rpcs, rpc->name);
- }
-}
-
-
/**
* Force to create backdoor channels only.
* This provides a kill-switch to disable vsocket channels if needed.
}
if (chan != NULL && chan->funcs != NULL && chan->funcs->shutdown != NULL) {
+#if defined(NEED_RPCIN)
if (chan->in != NULL) {
if (chan->inStarted) {
RpcIn_stop(chan->in);
if (chan->mainCtx != NULL) {
g_main_context_unref(chan->mainCtx);
}
+#endif
chan->funcs->shutdown(chan);
}
}
}
if (chan->outStarted) {
+#if defined(NEED_RPCIN)
/* Already started. Make sure both channels are in sync and return. */
ASSERT(chan->in == NULL || chan->inStarted);
+#endif
return TRUE;
}
+#if defined(NEED_RPCIN)
if (chan->in != NULL && !chan->inStarted) {
- ok = RpcIn_start(chan->in, RPCIN_MAX_DELAY, RpcChannel_Error, chan);
+ ok = RpcIn_start(chan->in, RPCIN_MAX_DELAY, RpcChannelError, chan);
chan->inStarted = ok;
}
+#endif
funcs = chan->funcs;
ok = funcs->start(chan);
static void
RpcChannelStopNoLock(RpcChannel *chan)
{
- g_return_if_fail(chan != NULL);
- g_return_if_fail(chan->funcs != NULL);
- g_return_if_fail(chan->funcs->stop != NULL);
+ if (chan == NULL || chan->funcs == NULL || chan->funcs->stop == NULL) {
+ return;
+ }
chan->funcs->stop(chan);
+#if defined(NEED_RPCIN)
if (chan->in != NULL) {
if (chan->inStarted) {
RpcIn_stop(chan->in);
} else {
ASSERT(!chan->inStarted);
}
+#endif
}