VirtualBox

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

Last change on this file since 56372 was 54266, checked in by vboxsync, 10 years ago

Main/webservice: change code to support multiple ISession instances per websession, lots of cleanup and wording changes
Main/idl,doc: matching updates

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