VirtualBox

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

Last change on this file since 64226 was 63979, checked in by vboxsync, 8 years ago

file header standards

  • Property filesplitter.c set to Makefile.kmk
  • Property svn:eol-style set to native
File size: 12.4 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
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 pc COM object for which to create a reference
320 * @return existing or new managed object reference
321 */
322template <class T>
323const WSDLT_ID& createOrFindRefFromComPtr(const WSDLT_ID &idParent,
324 const char *pcszInterface,
325 const ComPtr<T> &pc)
326{
327 // NULL comptr should return NULL MOR
328 if (pc.isNull())
329 {
330 WEBDEBUG((" createOrFindRefFromComPtr(): returning empty MOR for NULL COM pointer\n"));
331 return g_EmptyWSDLID;
332 }
333
334 util::AutoWriteLock lock(g_pWebsessionsLockHandle COMMA_LOCKVAL_SRC_POS);
335 WebServiceSession *pWebsession;
336 if ((pWebsession = WebServiceSession::findWebsessionFromRef(idParent)))
337 {
338 ManagedObjectRef *pRef;
339
340 // we need an IUnknown pointer for the MOR
341 ComPtr<IUnknown> pobjUnknown = pc;
342
343 if ( ((pRef = pWebsession->findRefFromPtr(pobjUnknown)))
344 || ((pRef = new ManagedObjectRef(*pWebsession,
345 pobjUnknown, // IUnknown *pobjUnknown
346 pc, // void *pobjInterface
347 COM_IIDOF(T),
348 pcszInterface)))
349 )
350 return pRef->getWSDLID();
351 }
352
353 // websession has expired, return an empty MOR instead of allocating a
354 // new reference which couldn't be used anyway.
355 return g_EmptyWSDLID;
356}
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