VirtualBox

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

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

Fixed OS/2 build.

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