From: Oliver Kurth Date: Tue, 6 Mar 2018 18:38:43 +0000 (-0800) Subject: Enhancements for rpcChannel library. X-Git-Tag: stable-10.3.0~85 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2438cefba37d37de65bf2003b1880f47b529ef47;p=thirdparty%2Fopen-vm-tools.git Enhancements for rpcChannel library. rpcChannel.c file contains the code for building rpcChannel library. A good amount of the same code is duplicated in rpcChannelSimple.c file to build a simplified version (no glib dependency) of the rpcChannel library. It's recommended to remove the duplication and maintain only one single file which can be used to build both 'glib-dependent rpcChannel' and 'glib independent rpcChannel' library. This changeset implements the following changes: * Removed rpcChannelSimple.c * Renamed I_USE_SIMPLE_RPC make variable to USE_RPCI_ONLY. If this flag is specified, rpcChannel library will be built using only RPCI. No dependencies on rpcIn will be added. This inturn will remove dependencies on dynxdr, xdr and glib. * Modified the RpcChannelInt structure to have only the necessary attributes when USE_RPCI_ONLY is defined. * Modified a bunch of functions into '#if defined(NEED_RPCIN)' block to make available only when necessary. * Modified guestrpc.h to provide the declarations for few RpcChannel_* functions only when needed. * Modified rpcChannel library to implement necessary stub files / functions when it has to be built 'with rpci only' setting. * Removed various copies of 'glib_stubs.c' maintained by different consumers of rpcChannel (appmonitorlib, vmGuestLib, 'imgcust' components). * Modified the make files of various consumers (vmGuestLib, appmonitorlib, imgcust components [linux-pkg-deployer, guestcustutil, UnitTest]) to remove the dependencies for dynxdr library. * Did some code refactoring. - Removed some dead code in some make files. --- diff --git a/open-vm-tools/lib/include/vmware/tools/guestrpc.h b/open-vm-tools/lib/include/vmware/tools/guestrpc.h index 73a750c4d..e6fee26d8 100644 --- a/open-vm-tools/lib/include/vmware/tools/guestrpc.h +++ b/open-vm-tools/lib/include/vmware/tools/guestrpc.h @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2008,2014-2016 VMware, Inc. All rights reserved. + * Copyright (C) 2008,2014-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 @@ -144,22 +144,13 @@ RpcChannel_Send(RpcChannel *chan, void RpcChannel_Free(void *ptr); +#if !defined(USE_RPCI_ONLY) gboolean RpcChannel_BuildXdrCommand(const char *cmd, void *xdrProc, void *xdrData, char **result, size_t *resultLen); - -RpcChannel * -RpcChannel_Create(void); - -void -RpcChannel_Shutdown(RpcChannel *chan); - -gboolean -RpcChannel_Destroy(RpcChannel *chan); - gboolean RpcChannel_Dispatch(RpcInData *data); @@ -175,6 +166,20 @@ void RpcChannel_RegisterCallback(RpcChannel *chan, RpcChannelCallback *rpc); +void +RpcChannel_UnregisterCallback(RpcChannel *chan, + RpcChannelCallback *rpc); +#endif + +RpcChannel * +RpcChannel_Create(void); + +void +RpcChannel_Shutdown(RpcChannel *chan); + +gboolean +RpcChannel_Destroy(RpcChannel *chan); + gboolean RpcChannel_SetRetVals(RpcInData *data, char const *result, @@ -185,10 +190,6 @@ RpcChannel_SetRetValsF(RpcInData *data, char *result, gboolean retVal); -void -RpcChannel_UnregisterCallback(RpcChannel *chan, - RpcChannelCallback *rpc); - gboolean RpcChannel_SendOneRaw(const char *data, size_t dataLen, diff --git a/open-vm-tools/lib/rpcChannel/bdoorChannel.c b/open-vm-tools/lib/rpcChannel/bdoorChannel.c index a91652bc4..f8886fa32 100644 --- a/open-vm-tools/lib/rpcChannel/bdoorChannel.c +++ b/open-vm-tools/lib/rpcChannel/bdoorChannel.c @@ -1,5 +1,5 @@ /********************************************************* - * 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 @@ -25,7 +25,9 @@ #include "vm_assert.h" #include "rpcChannelInt.h" +#if defined(NEED_RPCIN) #include "rpcin.h" +#endif #include "rpcout.h" #include "util.h" #include "debug.h" @@ -51,6 +53,7 @@ BkdoorChannelStart(RpcChannel *chan) gboolean ret = TRUE; BackdoorChannel *bdoor = chan->_private; +#if defined(NEED_RPCIN) ret = chan->in == NULL || chan->inStarted; if (ret) { ret = RpcOut_start(bdoor->out); @@ -61,6 +64,9 @@ BkdoorChannelStart(RpcChannel *chan) } } } +#else + ret = RpcOut_start(bdoor->out); +#endif chan->outStarted = ret; return ret; } @@ -258,7 +264,9 @@ BackdoorChannel_New(void) bdoor->out = RpcOut_Construct(); ASSERT(bdoor->out != NULL); +#if defined(NEED_RPCIN) ret->inStarted = FALSE; +#endif ret->outStarted = FALSE; BackdoorChannelSetCallbacks(ret); diff --git a/open-vm-tools/lib/rpcChannel/rpcChannel.c b/open-vm-tools/lib/rpcChannel/rpcChannel.c index 7a97d08ff..e6c7e0db7 100644 --- a/open-vm-tools/lib/rpcChannel/rpcChannel.c +++ b/open-vm-tools/lib/rpcChannel/rpcChannel.c @@ -1,5 +1,5 @@ /********************************************************* - * 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 @@ -22,20 +22,27 @@ * Common functions to all RPC channel implementations. */ +#include #include -#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; @@ -46,20 +53,11 @@ typedef struct RpcChannelInt { 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; /* @@ -71,6 +69,18 @@ static gboolean gVSocketFailed = 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. * @@ -345,26 +355,6 @@ exit: } -/** - * 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 @@ -426,52 +416,100 @@ exit: /** - * 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); + } } @@ -483,8 +521,8 @@ RpcChannel_Destroy(RpcChannel *chan) * @param[in] status Error description. */ -void -RpcChannel_Error(void *_chan, +static void +RpcChannelError(void *_chan, char const *status) { RpcChannelInt *chan = _chan; @@ -501,58 +539,80 @@ RpcChannel_Error(void *_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; } @@ -609,51 +669,6 @@ RpcChannel_SetRetValsF(RpcInData *data, } -/** - * 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. @@ -706,6 +721,7 @@ RpcChannel_Shutdown(RpcChannel *chan) } 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); @@ -720,6 +736,7 @@ RpcChannel_Shutdown(RpcChannel *chan) if (chan->mainCtx != NULL) { g_main_context_unref(chan->mainCtx); } +#endif chan->funcs->shutdown(chan); } } @@ -745,15 +762,19 @@ RpcChannel_Start(RpcChannel *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); @@ -784,12 +805,13 @@ RpcChannel_Start(RpcChannel *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); @@ -798,6 +820,7 @@ RpcChannelStopNoLock(RpcChannel *chan) } else { ASSERT(!chan->inStarted); } +#endif } diff --git a/open-vm-tools/lib/rpcChannel/rpcChannelInt.h b/open-vm-tools/lib/rpcChannel/rpcChannelInt.h index 510999088..7d2d2a546 100644 --- a/open-vm-tools/lib/rpcChannel/rpcChannelInt.h +++ b/open-vm-tools/lib/rpcChannel/rpcChannelInt.h @@ -1,5 +1,5 @@ /********************************************************* - * 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 @@ -27,10 +27,19 @@ #include "vmware/tools/guestrpc.h" +#if defined(USE_RPCI_ONLY) + +#undef NEED_RPCIN + +#else + +#define NEED_RPCIN + /** Max amount of time (in .01s) that the RpcIn loop will sleep for. */ #define RPCIN_MAX_DELAY 10 struct RpcIn; +#endif /** a list of interface functions for a channel implementation */ typedef struct _RpcChannelFuncs{ @@ -55,18 +64,19 @@ typedef struct _RpcChannelFuncs{ struct _RpcChannel { const RpcChannelFuncs *funcs; gpointer _private; +#if defined(NEED_RPCIN) GMainContext *mainCtx; const char *appName; gpointer appCtx; +#endif GStaticMutex outLock; +#if defined(NEED_RPCIN) struct RpcIn *in; gboolean inStarted; +#endif gboolean outStarted; }; -void -RpcChannel_Error(void *_state, - char const *status); RpcChannel *VSockChannel_New(void); RpcChannel *BackdoorChannel_New(void); gboolean diff --git a/open-vm-tools/lib/rpcChannel/vsockChannel.c b/open-vm-tools/lib/rpcChannel/vsockChannel.c index ac2f624ac..6e054b8ba 100644 --- a/open-vm-tools/lib/rpcChannel/vsockChannel.c +++ b/open-vm-tools/lib/rpcChannel/vsockChannel.c @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2013-2016 VMware, Inc. All rights reserved. + * Copyright (C) 2013-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 @@ -28,7 +28,6 @@ #include "simpleSocket.h" #include "rpcChannelInt.h" -#include "rpcin.h" #include "util.h" #include "debug.h" @@ -345,7 +344,9 @@ VSockChannelStart(RpcChannel *chan) // IN gboolean ret = TRUE; VSockChannel *vsock = chan->_private; +#if defined(NEED_RPCIN) ret = chan->in == NULL || chan->inStarted; +#endif if (ret) { ret = VSockOutStart(vsock->out); @@ -580,7 +581,9 @@ VSockChannel_New(void) vsock->out = VSockOutConstruct(); ASSERT(vsock->out != NULL); +#if defined(NEED_RPCIN) chan->inStarted = FALSE; +#endif chan->outStarted = FALSE; chan->_private = vsock;