VirtualBox

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

Last change on this file was 98297, checked in by vboxsync, 16 months 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
RevLine 
[69474]1/* $Id: vboxweb.h 98297 2023-01-25 01:59:25Z vboxsync $ */
[63979]2/** @file
3 * vboxweb.h - header file for "real" web server code.
4 */
5
[16120]6/*
[98103]7 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
[16120]8 *
[96407]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
[16120]26 */
27
[76562]28#ifndef MAIN_INCLUDED_SRC_webservice_vboxweb_h
29#define MAIN_INCLUDED_SRC_webservice_vboxweb_h
[76542]30#ifndef RT_WITHOUT_PRAGMA_ONCE
31# pragma once
32#endif
33
[22708]34#define LOG_GROUP LOG_GROUP_WEBSERVICE
35#include <VBox/log.h>
[59654]36#include <VBox/err.h>
[22708]37
38#include <VBox/com/VirtualBox.h>
39#include <VBox/com/Guid.h>
[26375]40#include <VBox/com/AutoLock.h>
[22708]41
[54266]42#include <iprt/asm.h>
[22708]43
[83794]44#include <iprt/sanitized/string>
[22708]45
[16120]46/****************************************************************************
47 *
[54266]48 * debug macro
49 *
50 ****************************************************************************/
51
[59654]52#define WEBDEBUG(a) do { if (g_fVerbose) { LogRel(a); } } while (0)
[54266]53
54/****************************************************************************
55 *
[30607]56 * typedefs
57 *
58 ****************************************************************************/
59
60// type used by gSOAP-generated code
[54266]61typedef std::string WSDLT_ID; // combined managed object ref (websession ID plus object ID)
[30607]62typedef std::string vbox__uuid;
63
64/****************************************************************************
65 *
[16120]66 * global variables
67 *
68 ****************************************************************************/
69
70extern bool g_fVerbose;
71
[54266]72extern util::WriteLockHandle *g_pWebsessionsLockHandle;
[16120]73
[30607]74extern const WSDLT_ID g_EmptyWSDLID;
[16120]75
76/****************************************************************************
77 *
78 * SOAP exceptions
79 *
80 ****************************************************************************/
81
[54266]82extern void RaiseSoapInvalidObjectFault(struct soap *soap, WSDLT_ID obj);
[16120]83
[54266]84extern void RaiseSoapRuntimeFault(struct soap *soap, const WSDLT_ID &idThis, const char *pcszMethodName, HRESULT apirc, IUnknown *pObj, const com::Guid &iid);
[16120]85
86/****************************************************************************
87 *
88 * conversion helpers
89 *
90 ****************************************************************************/
91
[54266]92extern std::string ConvertComString(const com::Bstr &bstr);
[16120]93
[54266]94extern std::string ConvertComString(const com::Guid &bstr);
[16120]95
[54266]96extern std::string Base64EncodeByteArray(ComSafeArrayIn(BYTE, aData));
[36883]97
[54266]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
[16120]100/****************************************************************************
101 *
102 * managed object reference classes
103 *
104 ****************************************************************************/
105
106class WebServiceSessionPrivate;
107class ManagedObjectRef;
108
109/**
[22666]110 * An instance of this gets created for every client that logs onto the
111 * webservice (via the special IWebsessionManager::logon() SOAP API) and
[54266]112 * maintains the managed object references for that websession.
[16120]113 */
114class WebServiceSession
115{
116 friend class ManagedObjectRef;
117
118 private:
[54266]119 uint64_t _uWebsessionID;
120 uint64_t _uNextObjectID;
[22666]121 WebServiceSessionPrivate *_pp; // opaque data struct (defined in vboxweb.cpp)
[16120]122 bool _fDestructing;
123
[61361]124 uint32_t _tLastObjectLookup;
[16120]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,
[35454]135 const char *pcszPassword,
136 IVirtualBox **ppVirtualBox);
[16120]137
[30607]138 ManagedObjectRef* findRefFromPtr(const IUnknown *pObject);
[16120]139
140 uint64_t getID() const
141 {
[54266]142 return _uWebsessionID;
[16120]143 }
144
[54266]145 uint64_t createObjectID()
146 {
147 uint64_t id = ASMAtomicIncU64(&_uNextObjectID);
148 return id - 1;
149 }
[16120]150
151 void touch();
152
[61361]153 uint32_t getLastObjectLookup() const
[16120]154 {
155 return _tLastObjectLookup;
156 }
157
[54266]158 static WebServiceSession* findWebsessionFromRef(const WSDLT_ID &id);
[16120]159
[61361]160 size_t CountRefs();
[16120]161};
162
163/**
164 * ManagedObjectRef is used to map COM pointers to object IDs
[54266]165 * within a websession. Such object IDs are 64-bit integers.
[16120]166 *
167 * When a webservice method call is invoked on an object, it
168 * has an opaque string called a "managed object reference". Such
[54266]169 * a string consists of a websession ID combined with an object ID.
[16120]170 *
171 */
172class ManagedObjectRef
173{
174 protected:
[54266]175 // owning websession:
176 WebServiceSession &_websession;
[16120]177
178
[30607]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
[16120]187 // keys:
188 uint64_t _id;
189 uintptr_t _ulp;
190
191 // long ID as string
192 WSDLT_ID _strID;
193
194 public:
[54266]195 ManagedObjectRef(WebServiceSession &websession,
[30607]196 IUnknown *pobjUnknown,
197 void *pobjInterface,
198 const com::Guid &guidInterface,
199 const char *pcszInterface);
[16120]200 ~ManagedObjectRef();
201
202 uint64_t getID()
203 {
204 return _id;
205 }
206
[30607]207 /**
208 * Returns the contained COM pointer and the UUID of the COM interface
209 * which it supports.
[65158]210 * @param ppobjInterface
211 * @param ppobjUnknown
[30607]212 * @return
213 */
214 const com::Guid& getPtr(void **ppobjInterface,
215 IUnknown **ppobjUnknown)
[16120]216 {
[30607]217 *ppobjInterface = _pobjInterface;
218 *ppobjUnknown = _pobjUnknown;
219 return _guidInterface;
[16120]220 }
221
[30607]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
[16120]233 const char* getInterfaceName() const
234 {
235 return _pcszInterface;
236 }
237
238 static int findRefFromId(const WSDLT_ID &id,
[20851]239 ManagedObjectRef **pRef,
240 bool fNullAllowed);
[16120]241};
242
243/**
244 * Template function that resolves a managed object reference to a COM pointer
[30607]245 * of the template class T.
[16120]246 *
[30607]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 *
[16120]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
[30607]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.
[16120]257 *
258 * @param soap
[20851]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,
[16120]261 * if SOAP_OK is returned
[20851]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.
[16120]266 * @return error code or SOAP_OK if no error
267 */
268template <class T>
269int findComPtrFromId(struct soap *soap,
270 const WSDLT_ID &id,
[20851]271 ComPtr<T> &pComPtr,
272 bool fNullAllowed)
[16120]273{
[30501]274 // findRefFromId requires thelock
[54266]275 util::AutoWriteLock lock(g_pWebsessionsLockHandle COMMA_LOCKVAL_SRC_POS);
[26375]276
[16120]277 ManagedObjectRef *pRef;
[98297]278 int vrc = ManagedObjectRef::findRefFromId(id, &pRef, fNullAllowed);
279 if (vrc != VINF_SUCCESS)
[30607]280 // error:
[16120]281 RaiseSoapInvalidObjectFault(soap, id);
282 else
283 {
[21763]284 if (fNullAllowed && pRef == NULL)
285 {
[30607]286 WEBDEBUG((" %s(): returning NULL object as permitted\n", __FUNCTION__));
[22666]287 pComPtr.setNull();
[98297]288 return VINF_SUCCESS;
[21763]289 }
290
[30607]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
[98297]303 return VINF_SUCCESS;
[30607]304 }
[16120]305
[30607]306 // QueryInterface tests whether p actually supports the templated T interface desired by caller
307 T *pT;
[32780]308 pobjUnknown->QueryInterface(guidCaller.ref(), (void**)&pT); // this adds a reference count
[30607]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;
[98297]314 return VINF_SUCCESS;
[30607]315 }
316
[16301]317 WEBDEBUG((" Interface not supported for object reference %s, which is of class %s\n", id.c_str(), pRef->getInterfaceName()));
[98297]318 vrc = VERR_WEB_UNSUPPORTED_INTERFACE;
[16120]319 RaiseSoapInvalidObjectFault(soap, id); // @todo better message
320 }
321
[98297]322 return vrc;
[16120]323}
324
325/**
[54266]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.
[16120]328 *
[54266]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).
[30607]332 *
[54266]333 * @param idParent managed object reference of calling object; used to extract
334 * websession ID
[65158]335 * @param pcszInterface
[16120]336 * @param pc COM object for which to create a reference
337 * @return existing or new managed object reference
338 */
339template <class T>
[30607]340const WSDLT_ID& createOrFindRefFromComPtr(const WSDLT_ID &idParent,
341 const char *pcszInterface,
[54266]342 const ComPtr<T> &pc)
[16120]343{
[20851]344 // NULL comptr should return NULL MOR
345 if (pc.isNull())
346 {
[30607]347 WEBDEBUG((" createOrFindRefFromComPtr(): returning empty MOR for NULL COM pointer\n"));
348 return g_EmptyWSDLID;
[20851]349 }
350
[54266]351 util::AutoWriteLock lock(g_pWebsessionsLockHandle COMMA_LOCKVAL_SRC_POS);
352 WebServiceSession *pWebsession;
353 if ((pWebsession = WebServiceSession::findWebsessionFromRef(idParent)))
[16120]354 {
355 ManagedObjectRef *pRef;
[30607]356
357 // we need an IUnknown pointer for the MOR
358 ComPtr<IUnknown> pobjUnknown = pc;
359
[54266]360 if ( ((pRef = pWebsession->findRefFromPtr(pobjUnknown)))
361 || ((pRef = new ManagedObjectRef(*pWebsession,
[30607]362 pobjUnknown, // IUnknown *pobjUnknown
363 pc, // void *pobjInterface
364 COM_IIDOF(T),
365 pcszInterface)))
[16120]366 )
[30607]367 return pRef->getWSDLID();
[16120]368 }
369
[54266]370 // websession has expired, return an empty MOR instead of allocating a
[26942]371 // new reference which couldn't be used anyway.
[30607]372 return g_EmptyWSDLID;
[16120]373}
[76542]374
[76562]375#endif /* !MAIN_INCLUDED_SRC_webservice_vboxweb_h */
[76542]376
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use