VirtualBox

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

Last change on this file since 98694 was 98297, checked in by vboxsync, 2 years ago

Main: rc -> hrc/vrc for all but testcases. Enabled scm rc checks accordingly. bugref:10223

  • Property filesplitter.c set to Makefile.kmk
  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 13.0 KB
Line 
1/* $Id: vboxweb.h 98297 2023-01-25 01:59:25Z vboxsync $ */
2/** @file
3 * vboxweb.h - header file for "real" web server code.
4 */
5
6/*
7 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28#ifndef MAIN_INCLUDED_SRC_webservice_vboxweb_h
29#define MAIN_INCLUDED_SRC_webservice_vboxweb_h
30#ifndef RT_WITHOUT_PRAGMA_ONCE
31# pragma once
32#endif
33
34#define LOG_GROUP LOG_GROUP_WEBSERVICE
35#include <VBox/log.h>
36#include <VBox/err.h>
37
38#include <VBox/com/VirtualBox.h>
39#include <VBox/com/Guid.h>
40#include <VBox/com/AutoLock.h>
41
42#include <iprt/asm.h>
43
44#include <iprt/sanitized/string>
45
46/****************************************************************************
47 *
48 * debug macro
49 *
50 ****************************************************************************/
51
52#define WEBDEBUG(a) do { if (g_fVerbose) { LogRel(a); } } while (0)
53
54/****************************************************************************
55 *
56 * typedefs
57 *
58 ****************************************************************************/
59
60// type used by gSOAP-generated code
61typedef std::string WSDLT_ID; // combined managed object ref (websession ID plus object ID)
62typedef std::string vbox__uuid;
63
64/****************************************************************************
65 *
66 * global variables
67 *
68 ****************************************************************************/
69
70extern bool g_fVerbose;
71
72extern util::WriteLockHandle *g_pWebsessionsLockHandle;
73
74extern const WSDLT_ID g_EmptyWSDLID;
75
76/****************************************************************************
77 *
78 * SOAP exceptions
79 *
80 ****************************************************************************/
81
82extern void RaiseSoapInvalidObjectFault(struct soap *soap, WSDLT_ID obj);
83
84extern void RaiseSoapRuntimeFault(struct soap *soap, const WSDLT_ID &idThis, const char *pcszMethodName, HRESULT apirc, IUnknown *pObj, const com::Guid &iid);
85
86/****************************************************************************
87 *
88 * conversion helpers
89 *
90 ****************************************************************************/
91
92extern std::string ConvertComString(const com::Bstr &bstr);
93
94extern std::string ConvertComString(const com::Guid &bstr);
95
96extern std::string Base64EncodeByteArray(ComSafeArrayIn(BYTE, aData));
97
98extern 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);
99
100/****************************************************************************
101 *
102 * managed object reference classes
103 *
104 ****************************************************************************/
105
106class WebServiceSessionPrivate;
107class ManagedObjectRef;
108
109/**
110 * An instance of this gets created for every client that logs onto the
111 * webservice (via the special IWebsessionManager::logon() SOAP API) and
112 * maintains the managed object references for that websession.
113 */
114class WebServiceSession
115{
116 friend class ManagedObjectRef;
117
118 private:
119 uint64_t _uWebsessionID;
120 uint64_t _uNextObjectID;
121 WebServiceSessionPrivate *_pp; // opaque data struct (defined in vboxweb.cpp)
122 bool _fDestructing;
123
124 uint32_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 _uWebsessionID;
143 }
144
145 uint64_t createObjectID()
146 {
147 uint64_t id = ASMAtomicIncU64(&_uNextObjectID);
148 return id - 1;
149 }
150
151 void touch();
152
153 uint32_t getLastObjectLookup() const
154 {
155 return _tLastObjectLookup;
156 }
157
158 static WebServiceSession* findWebsessionFromRef(const WSDLT_ID &id);
159
160 size_t CountRefs();
161};
162
163/**
164 * ManagedObjectRef is used to map COM pointers to object IDs
165 * within a websession. Such object IDs are 64-bit integers.
166 *
167 * When a webservice method call is invoked on an object, it
168 * has an opaque string called a "managed object reference". Such
169 * a string consists of a websession ID combined with an object ID.
170 *
171 */
172class ManagedObjectRef
173{
174 protected:
175 // owning websession:
176 WebServiceSession &_websession;
177
178
179 IUnknown *_pobjUnknown; // pointer to IUnknown interface for this MOR
180
181 void *_pobjInterface; // pointer to COM interface represented by _guidInterface, for which this MOR
182 // was created; this may be an IUnknown or something more specific
183 com::Guid _guidInterface; // the interface which _pvObj represents
184
185 const char *_pcszInterface; // string representation of that interface (e.g. "IMachine")
186
187 // keys:
188 uint64_t _id;
189 uintptr_t _ulp;
190
191 // long ID as string
192 WSDLT_ID _strID;
193
194 public:
195 ManagedObjectRef(WebServiceSession &websession,
196 IUnknown *pobjUnknown,
197 void *pobjInterface,
198 const com::Guid &guidInterface,
199 const char *pcszInterface);
200 ~ManagedObjectRef();
201
202 uint64_t getID()
203 {
204 return _id;
205 }
206
207 /**
208 * Returns the contained COM pointer and the UUID of the COM interface
209 * which it supports.
210 * @param ppobjInterface
211 * @param ppobjUnknown
212 * @return
213 */
214 const com::Guid& getPtr(void **ppobjInterface,
215 IUnknown **ppobjUnknown)
216 {
217 *ppobjInterface = _pobjInterface;
218 *ppobjUnknown = _pobjUnknown;
219 return _guidInterface;
220 }
221
222 /**
223 * Returns the ID of this managed object reference to string
224 * form, for returning with SOAP data or similar.
225 *
226 * @return The ID in string form.
227 */
228 const WSDLT_ID& getWSDLID() const
229 {
230 return _strID;
231 }
232
233 const char* getInterfaceName() const
234 {
235 return _pcszInterface;
236 }
237
238 static int findRefFromId(const WSDLT_ID &id,
239 ManagedObjectRef **pRef,
240 bool fNullAllowed);
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_pWebsessionsLockHandle COMMA_LOCKVAL_SRC_POS);
276
277 ManagedObjectRef *pRef;
278 int vrc = ManagedObjectRef::findRefFromId(id, &pRef, fNullAllowed);
279 if (vrc != VINF_SUCCESS)
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 VINF_SUCCESS;
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 VINF_SUCCESS;
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 VINF_SUCCESS;
315 }
316
317 WEBDEBUG((" Interface not supported for object reference %s, which is of class %s\n", id.c_str(), pRef->getInterfaceName()));
318 vrc = VERR_WEB_UNSUPPORTED_INTERFACE;
319 RaiseSoapInvalidObjectFault(soap, id); // @todo better message
320 }
321
322 return vrc;
323}
324
325/**
326 * Creates a new managed object reference for the given COM pointer. If one
327 * already exists for the given pointer, then that reference's ID is returned.
328 *
329 * This gets called from tons of generated code in methodmaps.cpp to resolve
330 * objects *returned* from COM methods (i.e. create MOR strings from COM
331 * objects which might have been newly created).
332 *
333 * @param idParent managed object reference of calling object; used to extract
334 * websession ID
335 * @param pcszInterface
336 * @param pc COM object for which to create a reference
337 * @return existing or new managed object reference
338 */
339template <class T>
340const WSDLT_ID& createOrFindRefFromComPtr(const WSDLT_ID &idParent,
341 const char *pcszInterface,
342 const ComPtr<T> &pc)
343{
344 // NULL comptr should return NULL MOR
345 if (pc.isNull())
346 {
347 WEBDEBUG((" createOrFindRefFromComPtr(): returning empty MOR for NULL COM pointer\n"));
348 return g_EmptyWSDLID;
349 }
350
351 util::AutoWriteLock lock(g_pWebsessionsLockHandle COMMA_LOCKVAL_SRC_POS);
352 WebServiceSession *pWebsession;
353 if ((pWebsession = WebServiceSession::findWebsessionFromRef(idParent)))
354 {
355 ManagedObjectRef *pRef;
356
357 // we need an IUnknown pointer for the MOR
358 ComPtr<IUnknown> pobjUnknown = pc;
359
360 if ( ((pRef = pWebsession->findRefFromPtr(pobjUnknown)))
361 || ((pRef = new ManagedObjectRef(*pWebsession,
362 pobjUnknown, // IUnknown *pobjUnknown
363 pc, // void *pobjInterface
364 COM_IIDOF(T),
365 pcszInterface)))
366 )
367 return pRef->getWSDLID();
368 }
369
370 // websession has expired, return an empty MOR instead of allocating a
371 // new reference which couldn't be used anyway.
372 return g_EmptyWSDLID;
373}
374
375#endif /* !MAIN_INCLUDED_SRC_webservice_vboxweb_h */
376
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