예제 #1
0
gboolean
ToolsCore_InitRpc(ToolsServiceState *state)
{
   static RpcChannelCallback rpcs[] = {
      { "Capabilities_Register", ToolsCoreRpcCapReg, NULL, NULL, NULL, 0 },
      { "Set_Option", ToolsCoreRpcSetOption, NULL, NULL, NULL, 0 },
   };

   size_t i;
   const gchar *app;
   GMainContext *mainCtx = g_main_loop_get_context(state->ctx.mainLoop);

   ASSERT(state->ctx.rpc == NULL);

   if (state->debugPlugin != NULL) {
      app = "debug";
      state->ctx.rpc = state->debugData->newDebugChannel(&state->ctx,
                                                         state->debugData);
   } else {
      /*
       * Currently we try to bring up an RpcIn channel, which will only run
       * inside a Virtual Machine. Some plugins may still want to launch and at
       * least begin even in not in a VM (typically because the installation is dual
       * purposed between a VM and Bootcamp) - plugins may wish to undo some state
       * if not in a VM.
       *
       * XXX: this should be relaxed when we try to bring up a VMCI or TCP channel.
       */
      if (!state->ctx.isVMware) {
         g_warning("The %s service needs to run inside a virtual machine.\n",
                   state->name);
         state->ctx.rpc = NULL;
      } else {
         state->ctx.rpc = BackdoorChannel_New();
      }
      app = ToolsCore_GetTcloName(state);
      if (app == NULL) {
         g_warning("Trying to start RPC channel for invalid %s container.", state->name);
         return FALSE;
      }
   }

   if (state->ctx.rpc) {
      RpcChannel_Setup(state->ctx.rpc,
                       app,
                       mainCtx,
                       &state->ctx,
                       ToolsCoreCheckReset,
                       state);

      /* Register the "built in" RPCs. */
      for (i = 0; i < ARRAYSIZE(rpcs); i++) {
         RpcChannelCallback *rpc = &rpcs[i];
         rpc->clientData = state;
         RpcChannel_RegisterCallback(state->ctx.rpc, rpc);
      }
   }

   return TRUE;
}
예제 #2
0
static gboolean
ToolsCoreRegisterRPC(ToolsAppCtx *ctx,
                     ToolsAppProvider *prov,
                     ToolsPluginData *plugin,
                     gpointer reg)
{
   RpcChannel_RegisterCallback(ctx->rpc, reg);
   return TRUE;
}
예제 #3
0
void
RpcChannel_Setup(RpcChannel *chan,
                 const gchar *appName,
                 GMainContext *mainCtx,
                 gpointer appCtx,
                 RpcChannelResetCb resetCb,
                 gpointer resetData)
{
   size_t i;
   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;

   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);

   for (i = 0; i < ARRAYSIZE(gRpcHandlers); i++) {
      RpcChannel_RegisterCallback(chan, &gRpcHandlers[i]);
   }

   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);
   }
}
DnDCPTransportGuestRpc::DnDCPTransportGuestRpc(RpcChannel *chan)
   : mRpcChannel(chan)
#else
DnDCPTransportGuestRpc::DnDCPTransportGuestRpc(void)
#endif
{
   for (int i = 0; i < TRANSPORT_INTERFACE_MAX; i++) {
      mCBCtx[i].transport = this;
      mCBCtx[i].type = (TransportInterfaceType)i;
   }
}


/**
 * Register a rpc callback to an interface.
 *
 * @param[in] rpc rpc which is listening to the message.
 * @param[in] type the interface type rpc is listening to.
 *
 * @return true on success, false otherwise.
 */

bool
DnDCPTransportGuestRpc::RegisterRpc(RpcBase *rpc,
                                    TransportInterfaceType type)
{
   if (mTables.GetRpc(type)) {
      LOG(0, ("%s: the type %d is already registered\n", __FUNCTION__, type));
      UnregisterRpc(type);
   }
   const char *cmdStr = (const char *)mTables.GetCmdStr(type);
   const char *disableStr = mTables.GetDisableStr(type);

   if (!cmdStr || !disableStr) {
      LOG(0, ("%s: can not find valid cmd for %d, cmdStr %s disableStr %s\n", __FUNCTION__, type, (cmdStr ? cmdStr : "NULL"), (disableStr ? disableStr : "NULL")));
      return false;
   }

   ASSERT(mCBCtx);
   ASSERT(type == TRANSPORT_GUEST_CONTROLLER_DND ||
          type == TRANSPORT_GUEST_CONTROLLER_CP ||
          type == TRANSPORT_GUEST_CONTROLLER_FT);
   LOG(4, ("%s: for %s\n", __FUNCTION__, cmdStr));

#ifdef VMX86_TOOLS
   ASSERT(mRpcChannel);
   mRpcChanCBList[type].name = cmdStr;
   mRpcChanCBList[type].callback = RecvMsgCB;
   mRpcChanCBList[type].clientData = &mCBCtx[type];
   mRpcChanCBList[type].xdrIn = NULL;
   mRpcChanCBList[type].xdrOut = NULL;
   mRpcChanCBList[type].xdrInSize = 0;
   RpcChannel_RegisterCallback(mRpcChannel, &mRpcChanCBList[type]);
#else
   GuestRpc_RegisterCommand(mTables.GetCmd(type), disableStr,
                            (const unsigned char *)cmdStr, RecvMsgCB, &mCBCtx[type]);
#endif
   mTables.SetRpc(type, rpc);
   return true;
}


/**
 * Unregister a rpc callback.
 *
 * @param[in] type the interface type rpc is listening to.
 *
 * @return true on success, false otherwise.
 */

bool
DnDCPTransportGuestRpc::UnregisterRpc(TransportInterfaceType type)
{
   if (!mTables.GetRpc(type)) {
      LOG(0, ("%s: the type %d is not registered\n", __FUNCTION__, type));
      return false;
   }
#ifdef VMX86_TOOLS
   ASSERT(mRpcChannel);
   RpcChannel_UnregisterCallback(mRpcChannel, &mRpcChanCBList[type]);
#else
   GuestRpc_UnregisterCommand(mTables.GetCmd(type));
#endif
   mTables.SetRpc(type, NULL);
   return true;
}


/**
 * Wrap the buffer into an rpc and send it to the peer.
 *
 * @param[ignored] destId destination address id
 * @param[in] type transport interface type
 * @param[in] data Payload buffer
 * @param[in] dataSize Payload buffer size
 *
 * @return true on success, false otherwise.
 */

bool
DnDCPTransportGuestRpc::SendPacket(uint32 destId,
                                   TransportInterfaceType type,
                                   const uint8 *msg,
                                   size_t length)
{
   char *rpc = NULL;
   size_t rpcSize = 0;
   size_t nrWritten = 0;
   const char *cmd = mTables.GetCmdStr(type);
   bool ret = true;

   if (!cmd) {
      LOG(0, ("%s: can not find valid cmd for %d\n", __FUNCTION__, type));
      return false;
   }
   rpcSize = strlen(cmd) + 1 + length;
   rpc = (char *)Util_SafeMalloc(rpcSize);
   nrWritten = Str_Sprintf(rpc, rpcSize, "%s ", cmd);

   if (length > 0) {
      ASSERT(nrWritten + length <= rpcSize);
      memcpy(rpc + nrWritten, msg, length);
   }

#ifdef VMX86_TOOLS
   ret = (TRUE == RpcChannel_Send(mRpcChannel, rpc, rpcSize, NULL, NULL));

   if (!ret) {
      LOG(0, ("%s: failed to send msg to host\n", __FUNCTION__));
   }

   free(rpc);
#else
   GuestRpc_SendWithTimeOut((const unsigned char *)TOOLS_DND_NAME,
                            (const unsigned char *)rpc, rpcSize,
                            GuestRpc_GenericCompletionRoutine, rpc,
                            DND_TIMEOUT);
#endif
   return ret;
}