VirtualBox

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

Last change on this file since 75902 was 69500, checked in by vboxsync, 7 years ago

*: scm --update-copyright-year

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