VirtualBox

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

Last change on this file since 78093 was 76562, checked in by vboxsync, 6 years ago

Main: Use MAIN_INCLUDED_ and MAIN_INCLUDED_SRC_ as header guard prefixes with scm.

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