VirtualBox

source: vbox/trunk/src/VBox/Main/linux/server_module.cpp@ 1713

Last change on this file since 1713 was 1471, checked in by vboxsync, 18 years ago

Main: XPCOM: Initial implementation of auto-startable "out-of-proc" VirtualBox component (VBoxSVC).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Revision Author Id
File size: 8.6 KB
Line 
1/** @file
2 *
3 * XPCOM server process hepler module implementation functions
4 */
5
6/*
7 * Copyright (C) 2006 InnoTek Systemberatung GmbH
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License as published by the Free Software Foundation,
13 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14 * distribution. VirtualBox OSE is distributed in the hope that it will
15 * be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * If you received this file as part of a commercial VirtualBox
18 * distribution, then only the terms of your commercial VirtualBox
19 * license agreement apply instead of the previous paragraph.
20 */
21
22#include <nsMemory.h>
23#include <nsString.h>
24#include <nsCOMPtr.h>
25#include <nsIFile.h>
26#include <nsIGenericFactory.h>
27#include <nsIServiceManagerUtils.h>
28#include <nsICategoryManager.h>
29#include <nsDirectoryServiceDefs.h>
30
31#include <ipcIService.h>
32#include <ipcIDConnectService.h>
33#include <ipcCID.h>
34#include <ipcdclient.h>
35
36// official XPCOM headers don't define it yet
37#define IPC_DCONNECTSERVICE_CONTRACTID \
38 "@mozilla.org/ipc/dconnect-service;1"
39
40// generated file
41#include <VirtualBox_XPCOM.h>
42
43#include "Logging.h"
44
45#include <VBox/err.h>
46
47#include <iprt/param.h>
48#include <iprt/path.h>
49#include <iprt/process.h>
50#include <iprt/thread.h>
51
52#include <string.h>
53
54
55/// @todo move this to RT headers (and use them in MachineImpl.cpp as well)
56#if defined(__WIN__) || defined(__OS2__)
57#define HOSTSUFF_EXE ".exe"
58#else /* !__WIN__ */
59#define HOSTSUFF_EXE ""
60#endif /* !__WIN__ */
61
62
63/** Name of the server executable. */
64const char VBoxSVC_exe[] = RTPATH_SLASH_STR "VBoxSVC" HOSTSUFF_EXE;
65
66enum
67{
68 /** Amount of time to wait for the server to establish a connection, ms */
69 VBoxSVC_Timeout = 30000,
70 /** How often to perform a connection check, ms */
71 VBoxSVC_WaitSlice = 100,
72};
73
74/*
75 * The following macros define the method necessary to provide a list of
76 * interfaces implemented by the VirtualBox component. Note that this must be
77 * in sync with macros used for VirtualBox in server.cpp for the same purpose.
78 */
79
80NS_DECL_CLASSINFO (VirtualBox)
81NS_IMPL_CI_INTERFACE_GETTER1 (VirtualBox, IVirtualBox)
82
83/**
84 * Name of the VBoxSVC server-side IPC client.
85 *
86 * This name simply matches the full path to the VBoxSVC executable (to
87 * guarantee unicity) so it is also used to start the VBoxSVC process when it
88 * is not started.
89 */
90static char VBoxSVCName [RTPATH_MAX];
91static bool IsVBoxSVCNameSet = false;
92
93/**
94 * VirtualBox component constructor.
95 *
96 * This constructor is responsible for starting the VirtualBox server
97 * process, connecting to it, and redirecting the constructor request to the
98 * VirtualBox component defined on the server.
99 */
100static NS_IMETHODIMP
101VirtualBoxConstructor (nsISupports *aOuter, REFNSIID aIID,
102 void **aResult)
103{
104 LogFlowFuncEnter();
105
106 nsresult rc = NS_OK;
107 int vrc = VINF_SUCCESS;
108
109 do
110 {
111 *aResult = NULL;
112 if (NULL != aOuter)
113 {
114 rc = NS_ERROR_NO_AGGREGATION;
115 break;
116 }
117
118 if (!IsVBoxSVCNameSet)
119 {
120 /* Get the directory containing XPCOM components -- the VBoxSVC
121 * executable is expected in the parent directory. */
122 nsCOMPtr <nsIProperties> dirServ = do_GetService (NS_DIRECTORY_SERVICE_CONTRACTID, &rc);
123 if (NS_SUCCEEDED (rc))
124 {
125 nsCOMPtr <nsIFile> componentDir;
126 rc = dirServ->Get (NS_XPCOM_COMPONENT_DIR,
127 NS_GET_IID (nsIFile), getter_AddRefs (componentDir));
128
129 if (NS_SUCCEEDED (rc))
130 {
131 nsCAutoString path;
132 componentDir->GetNativePath (path);
133
134 LogFlowFunc (("components path = \"%s\"\n", path.get()));
135 AssertBreak (path.Length() + strlen (VBoxSVC_exe) < RTPATH_MAX,
136 rc = NS_ERROR_FAILURE);
137
138 strcpy (VBoxSVCName, path.get());
139 RTPathStripFilename (VBoxSVCName);
140 strcat (VBoxSVCName, VBoxSVC_exe);
141 }
142 }
143 if (NS_FAILED (rc))
144 break;
145 }
146
147 nsCOMPtr <ipcIService> ipcServ = do_GetService (IPC_SERVICE_CONTRACTID, &rc);
148 if (NS_FAILED (rc))
149 break;
150
151 /* connect to the VBoxSVC server process */
152
153 bool startedOnce = false;
154 unsigned timeLeft = VBoxSVC_Timeout;
155
156 do
157 {
158 LogFlowFunc (("Resolving server name \"%s\"...\n", VBoxSVCName));
159
160 PRUint32 serverID = 0;
161 rc = ipcServ->ResolveClientName (VBoxSVCName, &serverID);
162 if (NS_FAILED (rc))
163 {
164 LogFlowFunc (("Starting server...\n", VBoxSVCName));
165
166 startedOnce = true;
167
168 RTPROCESS pid = NIL_RTPROCESS;
169 const char *args[] = { VBoxSVCName, "--automate", 0 };
170 vrc = RTProcCreate (VBoxSVCName, args, NULL, 0, &pid);
171 if (VBOX_FAILURE (vrc))
172 {
173 rc = NS_ERROR_FAILURE;
174 break;
175 }
176
177 /* wait for the server process to establish a connection */
178 do
179 {
180 RTThreadSleep (VBoxSVC_WaitSlice);
181 rc = ipcServ->ResolveClientName (VBoxSVCName, &serverID);
182 if (NS_SUCCEEDED (rc))
183 break;
184 if (timeLeft <= VBoxSVC_WaitSlice)
185 {
186 timeLeft = 0;
187 break;
188 }
189 timeLeft -= VBoxSVC_WaitSlice;
190 }
191 while (1);
192
193 if (!timeLeft)
194 {
195 rc = IPC_ERROR_WOULD_BLOCK;
196 break;
197 }
198 }
199
200 LogFlowFunc (("Connecting to server (ID=%d)...\n", serverID));
201
202 nsCOMPtr <ipcIDConnectService> dconServ =
203 do_GetService (IPC_DCONNECTSERVICE_CONTRACTID, &rc);
204 if (NS_FAILED (rc))
205 break;
206
207 rc = dconServ->CreateInstance (serverID,
208 (nsCID) NS_VIRTUALBOX_CID,
209 aIID, aResult);
210 if (NS_SUCCEEDED (rc))
211 break;
212
213 /* It's possible that the server gets shut down after we
214 * successfully resolve the server name but before it
215 * receives our CreateInstance() request. So, check for the
216 * name again, and restart the cycle if it fails. */
217 if (!startedOnce && NS_FAILED (rc))
218 {
219 nsresult rc2 =
220 ipcServ->ResolveClientName (VBoxSVCName, &serverID);
221 if (NS_SUCCEEDED (rc2))
222 break;
223 }
224 }
225 while (1);
226 }
227 while (0);
228
229 LogFlowFunc (("rc=%08X, vrc=%Vrc\n", rc, vrc));
230 LogFlowFuncLeave();
231
232 return rc;
233}
234
235#if 0
236/// @todo not really necessary for the moment
237/**
238 *
239 * @param aCompMgr
240 * @param aPath
241 * @param aLoaderStr
242 * @param aType
243 * @param aInfo
244 *
245 * @return
246 */
247static NS_IMETHODIMP
248VirtualBoxRegistration (nsIComponentManager *aCompMgr,
249 nsIFile *aPath,
250 const char *aLoaderStr,
251 const char *aType,
252 const nsModuleComponentInfo *aInfo)
253{
254 nsCAutoString modulePath;
255 aPath->GetNativePath (modulePath);
256 nsCAutoString moduleTarget;
257 aPath->GetNativeTarget (moduleTarget);
258
259 LogFlowFunc (("aPath=%s, aTarget=%s, aLoaderStr=%s, aType=%s\n",
260 modulePath.get(), moduleTarget.get(), aLoaderStr, aType));
261
262 nsresult rc = NS_OK;
263
264 return rc;
265}
266#endif
267
268/**
269 * Component definition table.
270 * Lists all components defined in this module.
271 */
272static const nsModuleComponentInfo components[] =
273{
274 {
275 "VirtualBox component", // description
276 NS_VIRTUALBOX_CID, NS_VIRTUALBOX_CONTRACTID, // CID/ContractID
277 VirtualBoxConstructor, // constructor function
278 NULL, /* VirtualBoxRegistration, */ // registration function
279 NULL, // deregistration function
280 NULL, // destructor function
281 /// @todo
282 NS_CI_INTERFACE_GETTER_NAME(VirtualBox), // interfaces function
283 NULL, // language helper
284 /// @todo
285 &NS_CLASSINFO_NAME(VirtualBox) // global class info & flags
286 }
287};
288
289NS_IMPL_NSGETMODULE (VirtualBox_Server_Module, components)
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette