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; }
static void ToolsCoreCheckReset(struct RpcChannel *chan, gboolean success, gpointer _state) { ToolsServiceState *state = _state; ASSERT(state != NULL); if (success) { const gchar *app; gchar *msg; app = ToolsCore_GetTcloName(state); if (app == NULL) { app = state->name; } msg = g_strdup_printf("vmx.capability.unified_loop %s", app); if (!RpcChannel_Send(state->ctx.rpc, msg, strlen(msg) + 1, NULL, NULL)) { g_warning("VMX doesn't support the Tools unified loop.\n" "Some functionality (like setting options) may not work.\n"); } g_free(msg); /* * Log the Tools build number to the VMX log file. We don't really care * if sending the message fails. */ msg = g_strdup_printf("log %s: Version: %s", app, BUILD_NUMBER); RpcChannel_Send(state->ctx.rpc, msg, strlen(msg) + 1, NULL, NULL); g_free(msg); g_signal_emit_by_name(state->ctx.serviceObj, TOOLS_CORE_SIG_RESET, &state->ctx); } else { VMTOOLSAPP_ERROR(&state->ctx, EXIT_FAILURE); } }
static int ToolsCoreRunLoop(ToolsServiceState *state) { if (!ToolsCore_InitRpc(state)) { return 1; } /* * Start the RPC channel if it's been created. The channel may be NULL if this is * not running in the context of a VM. */ if (state->ctx.rpc && !RpcChannel_Start(state->ctx.rpc)) { return 1; } if (!ToolsCore_LoadPlugins(state)) { return 1; } /* * The following criteria needs to hold for the main loop to be run: * * . no plugin has requested the service to shut down during initialization. * . we're either on a VMware hypervisor, or running an unknown service name. * . we're running in debug mode. * * In the non-VMware hypervisor case, just exit with a '0' return status (see * bug 297528 for why '0'). */ if (state->ctx.errorCode == 0 && (state->ctx.isVMware || ToolsCore_GetTcloName(state) == NULL || state->debugPlugin != NULL)) { ToolsCore_RegisterPlugins(state); /* * Listen for the I/O freeze signal. We have to disable the config file * check when I/O is frozen or the (Win32) sync driver may cause the service * to hang (and make the VM unusable until it times out). */ if (g_signal_lookup(TOOLS_CORE_SIG_IO_FREEZE, G_OBJECT_TYPE(state->ctx.serviceObj)) != 0) { g_signal_connect(state->ctx.serviceObj, TOOLS_CORE_SIG_IO_FREEZE, G_CALLBACK(ToolsCoreIOFreezeCb), state); } state->configCheckTask = g_timeout_add(CONF_POLL_TIME * 10, ToolsCoreConfFileCb, state); #if defined(__APPLE__) ToolsCore_CFRunLoop(state); #else g_main_loop_run(state->ctx.mainLoop); #endif } ToolsCoreCleanup(state); return state->ctx.errorCode; }