VirtualBox

source: vbox/trunk/src/VBox/Main/webservice/vboxweb.h@ 35691

Last change on this file since 35691 was 35458, checked in by vboxsync, 14 years ago

Main/webservice: make global VirtualBox reference static to prevent unintentional unsynchronized accesses in the future, and add changelog for localhost fix

  • Property filesplitter.c set to Makefile.kmk
  • Property svn:eol-style set to native
File size: 12.6 KB
Line 
1/*
2 * vboxweb.h:
3 * header file for "real" web server code.
4 *
5 * Copyright (C) 2006-2011 Oracle Corporation
6 *
7 * This file is part of VirtualBox Open Source Edition (OSE), as
8 * available from http://www.virtualbox.org. This file is free software;
9 * you can redistribute it and/or modify it under the terms of the GNU
10 * General Public License (GPL) as published by the Free Software
11 * Foundation, in version 2 as it comes in the "COPYING" file of the
12 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
13 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
14 */
15
16/****************************************************************************
17 *
18 * debug macro
19 *
20 ****************************************************************************/
21
22void WebLog(const char *pszFormat, ...);
23
24#define WEBDEBUG(a) if (g_fVerbose) { WebLog a; }
25
26#ifdef DEBUG
27#define LOG_GROUP LOG_GROUP_WEBSERVICE
28#include <VBox/log.h>
29#endif
30
31#include <VBox/com/VirtualBox.h>
32#include <VBox/com/Guid.h>
33#include <VBox/com/AutoLock.h>
34
35#include <VBox/err.h>
36
37#include <iprt/stream.h>
38
39#include <string>
40
41/****************************************************************************
42 *
43 * typedefs
44 *
45 ****************************************************************************/
46
47// type used by gSOAP-generated code
48typedef std::string WSDLT_ID; // combined managed object ref (session ID plus object ID)
49typedef std::string vbox__uuid;
50
51/****************************************************************************
52 *
53 * global variables
54 *
55 ****************************************************************************/
56
57extern bool g_fVerbose;
58
59extern PRTSTREAM g_pstrLog;
60
61extern util::WriteLockHandle *g_pAuthLibLockHandle;
62extern util::WriteLockHandle *g_pSessionsLockHandle;
63
64extern const WSDLT_ID g_EmptyWSDLID;
65
66/****************************************************************************
67 *
68 * SOAP exceptions
69 *
70 ****************************************************************************/
71
72void RaiseSoapInvalidObjectFault(struct soap *soap, WSDLT_ID obj);
73
74void RaiseSoapRuntimeFault2(struct soap *soap, HRESULT apirc, IUnknown *pObj, const com::Guid &iid);
75
76/**
77 * Template function called everywhere from methodmaps.cpp which calls
78 * RaiseSoapRuntimeFault2() with the correct COM interface ID.
79 * @param soap
80 * @param apirc
81 * @param pObj
82 */
83template <class T>
84void RaiseSoapRuntimeFault(struct soap *soap, HRESULT apirc, const ComPtr<T> &pObj)
85{
86 RaiseSoapRuntimeFault2(soap, apirc, pObj, COM_IIDOF(T));
87}
88
89/****************************************************************************
90 *
91 * conversion helpers
92 *
93 ****************************************************************************/
94
95std::string ConvertComString(const com::Bstr &bstr);
96
97std::string ConvertComString(const com::Guid &bstr);
98
99/****************************************************************************
100 *
101 * managed object reference classes
102 *
103 ****************************************************************************/
104
105class WebServiceSessionPrivate;
106class ManagedObjectRef;
107
108/**
109 * An instance of this gets created for every client that logs onto the
110 * webservice (via the special IWebsessionManager::logon() SOAP API) and
111 * maintains the managed object references for that session.
112 */
113class WebServiceSession
114{
115 friend class ManagedObjectRef;
116
117 private:
118 uint64_t _uSessionID;
119 WebServiceSessionPrivate *_pp; // opaque data struct (defined in vboxweb.cpp)
120 bool _fDestructing;
121
122 ManagedObjectRef *_pISession;
123
124 time_t _tLastObjectLookup;
125
126 // hide the copy constructor because we're not copyable
127 WebServiceSession(const WebServiceSession &copyFrom);
128
129 public:
130 WebServiceSession();
131
132 ~WebServiceSession();
133
134 int authenticate(const char *pcszUsername,
135 const char *pcszPassword,
136 IVirtualBox **ppVirtualBox);
137
138 ManagedObjectRef* findRefFromPtr(const IUnknown *pObject);
139
140 uint64_t getID() const
141 {
142 return _uSessionID;
143 }
144
145 const WSDLT_ID& getSessionWSDLID() const;
146
147 void touch();
148
149 time_t getLastObjectLookup() const
150 {
151 return _tLastObjectLookup;
152 }
153
154 static WebServiceSession* findSessionFromRef(const WSDLT_ID &id);
155
156 void DumpRefs();
157};
158
159/**
160 * ManagedObjectRef is used to map COM pointers to object IDs
161 * within a session. Such object IDs are 64-bit integers.
162 *
163 * When a webservice method call is invoked on an object, it
164 * has an opaque string called a "managed object reference". Such
165 * a string consists of a session ID combined with an object ID.
166 *
167 */
168class ManagedObjectRef
169{
170 protected:
171 // owning session:
172 WebServiceSession &_session;
173
174
175 IUnknown *_pobjUnknown; // pointer to IUnknown interface for this MOR
176
177 void *_pobjInterface; // pointer to COM interface represented by _guidInterface, for which this MOR
178 // was created; this may be an IUnknown or something more specific
179 com::Guid _guidInterface; // the interface which _pvObj represents
180
181 const char *_pcszInterface; // string representation of that interface (e.g. "IMachine")
182
183 // keys:
184 uint64_t _id;
185 uintptr_t _ulp;
186
187 // long ID as string
188 WSDLT_ID _strID;
189
190 public:
191 ManagedObjectRef(WebServiceSession &session,
192 IUnknown *pobjUnknown,
193 void *pobjInterface,
194 const com::Guid &guidInterface,
195 const char *pcszInterface);
196 ~ManagedObjectRef();
197
198 uint64_t getID()
199 {
200 return _id;
201 }
202
203 /**
204 * Returns the contained COM pointer and the UUID of the COM interface
205 * which it supports.
206 * @param
207 * @return
208 */
209 const com::Guid& getPtr(void **ppobjInterface,
210 IUnknown **ppobjUnknown)
211 {
212 *ppobjInterface = _pobjInterface;
213 *ppobjUnknown = _pobjUnknown;
214 return _guidInterface;
215 }
216
217 /**
218 * Returns the ID of this managed object reference to string
219 * form, for returning with SOAP data or similar.
220 *
221 * @return The ID in string form.
222 */
223 const WSDLT_ID& getWSDLID() const
224 {
225 return _strID;
226 }
227
228 const char* getInterfaceName() const
229 {
230 return _pcszInterface;
231 }
232
233 static int findRefFromId(const WSDLT_ID &id,
234 ManagedObjectRef **pRef,
235 bool fNullAllowed);
236
237 static ManagedObjectRef* findFromPtr(ComPtr<IUnknown> pcu);
238 static ManagedObjectRef* create(const WSDLT_ID &idParent,
239 ComPtr<IUnknown> pcu);
240
241};
242
243/**
244 * Template function that resolves a managed object reference to a COM pointer
245 * of the template class T.
246 *
247 * This gets called only from tons of generated code in methodmaps.cpp to
248 * resolve objects in *input* parameters to COM methods (i.e. translate
249 * MOR strings to COM objects which should exist already).
250 *
251 * This is a template function so that we can support ComPtr's for arbitrary
252 * interfaces and automatically verify that the managed object reference on
253 * the internal stack actually is of the expected interface. We also now avoid
254 * calling QueryInterface for the case that the interface desired by the caller
255 * is the same as the interface for which the MOR was originally created. In
256 * that case, the lookup is very fast.
257 *
258 * @param soap
259 * @param id in: integer managed object reference, as passed in by web service client
260 * @param pComPtr out: reference to COM pointer object that receives the com pointer,
261 * if SOAP_OK is returned
262 * @param fNullAllowed in: if true, then this func returns a NULL COM pointer if an
263 * empty MOR is passed in (i.e. NULL pointers are allowed). If false,
264 * then this fails; this will be false when called for the "this"
265 * argument of method calls, which really shouldn't be NULL.
266 * @return error code or SOAP_OK if no error
267 */
268template <class T>
269int findComPtrFromId(struct soap *soap,
270 const WSDLT_ID &id,
271 ComPtr<T> &pComPtr,
272 bool fNullAllowed)
273{
274 // findRefFromId requires thelock
275 util::AutoWriteLock lock(g_pSessionsLockHandle COMMA_LOCKVAL_SRC_POS);
276
277 int rc;
278 ManagedObjectRef *pRef;
279 if ((rc = ManagedObjectRef::findRefFromId(id, &pRef, fNullAllowed)))
280 // error:
281 RaiseSoapInvalidObjectFault(soap, id);
282 else
283 {
284 if (fNullAllowed && pRef == NULL)
285 {
286 WEBDEBUG((" %s(): returning NULL object as permitted\n", __FUNCTION__));
287 pComPtr.setNull();
288 return 0;
289 }
290
291 const com::Guid &guidCaller = COM_IIDOF(T);
292
293 // pRef->getPtr returns both a void* for its specific interface pointer as well as a generic IUnknown*
294 void *pobjInterface;
295 IUnknown *pobjUnknown;
296 const com::Guid &guidInterface = pRef->getPtr(&pobjInterface, &pobjUnknown);
297
298 if (guidInterface == guidCaller)
299 {
300 // same interface: then no QueryInterface needed
301 WEBDEBUG((" %s(): returning original %s*=0x%lX (IUnknown*=0x%lX)\n", __FUNCTION__, pRef->getInterfaceName(), pobjInterface, pobjUnknown));
302 pComPtr = (T*)pobjInterface; // this calls AddRef() once
303 return 0;
304 }
305
306 // QueryInterface tests whether p actually supports the templated T interface desired by caller
307 T *pT;
308 pobjUnknown->QueryInterface(guidCaller.ref(), (void**)&pT); // this adds a reference count
309 if (pT)
310 {
311 // assign to caller's ComPtr<T>; use asOutParam() to avoid adding another reference, QueryInterface() already added one
312 WEBDEBUG((" %s(): returning pointer 0x%lX for queried interface %RTuuid (IUnknown*=0x%lX)\n", __FUNCTION__, pT, guidCaller.raw(), pobjUnknown));
313 *(pComPtr.asOutParam()) = pT;
314 return 0;
315 }
316
317 WEBDEBUG((" Interface not supported for object reference %s, which is of class %s\n", id.c_str(), pRef->getInterfaceName()));
318 rc = VERR_WEB_UNSUPPORTED_INTERFACE;
319 RaiseSoapInvalidObjectFault(soap, id); // @todo better message
320 }
321
322 return rc;
323}
324
325/**
326 * Creates a new managed object for the given COM pointer. If a reference already exists
327 * for the given pointer, then that reference's ID is returned instead.
328 *
329 * This gets called from tons of generated code in methodmaps.cpp to
330 * resolve objects *returned* from COM methods (i.e. create MOR strings from COM objects
331 * which might have been newly created).
332 *
333 * @param idParent managed object reference of calling object; used to extract session ID
334 * @param pc COM object for which to create a reference
335 * @return existing or new managed object reference
336 */
337template <class T>
338const WSDLT_ID& createOrFindRefFromComPtr(const WSDLT_ID &idParent,
339 const char *pcszInterface,
340 ComPtr<T> &pc)
341{
342 // NULL comptr should return NULL MOR
343 if (pc.isNull())
344 {
345 WEBDEBUG((" createOrFindRefFromComPtr(): returning empty MOR for NULL COM pointer\n"));
346 return g_EmptyWSDLID;
347 }
348
349 util::AutoWriteLock lock(g_pSessionsLockHandle COMMA_LOCKVAL_SRC_POS);
350 WebServiceSession *pSession;
351 if ((pSession = WebServiceSession::findSessionFromRef(idParent)))
352 {
353 ManagedObjectRef *pRef;
354
355 // we need an IUnknown pointer for the MOR
356 ComPtr<IUnknown> pobjUnknown = pc;
357
358 if ( ((pRef = pSession->findRefFromPtr(pobjUnknown)))
359 || ((pRef = new ManagedObjectRef(*pSession,
360 pobjUnknown, // IUnknown *pobjUnknown
361 pc, // void *pobjInterface
362 COM_IIDOF(T),
363 pcszInterface)))
364 )
365 return pRef->getWSDLID();
366 }
367
368 // session has expired, return an empty MOR instead of allocating a
369 // new reference which couldn't be used anyway.
370 return g_EmptyWSDLID;
371}
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