VirtualBox

source: vbox/trunk/src/VBox/Main/xpcom/server_module.cpp@ 8768

Last change on this file since 8768 was 8768, checked in by vboxsync, 17 years ago

while I'm at it - moving the non-linux stuff to xpcom.

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