VirtualBox

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

Last change on this file since 69111 was 65158, checked in by vboxsync, 8 years ago

Main: doxygen fixes

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