VirtualBox

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

Last change on this file since 53517 was 46478, checked in by vboxsync, 12 years ago

libs/xpcom: touch up Java XPCOM wrapper generation, new common exception handlin
g model
Main/glue: Java glue code with better exception handling, indentation/coding style fixes both in the XSLT and the generated code, touched up Java sample code showing exception handling and getting all error information, Python indentation/whitespace cleanup
Main/idl: make more interfaces available over the webservice, some minor docs changes, whitespace cleanup
Main/webservice: redo error reporting through exceptions, no longer loses error
information, allow more fine-grained suppression of methods/attributed, touched up C++ webservice sample code to support showing the full error information, build system changes to prepare for incremental Java compilation, indentation fixesFrontends/VBoxShell: minor cleanups, coding style fixes, indentation fixes, elim
inate warnings

  • Property filesplitter.c set to Makefile.kmk
  • Property svn:eol-style set to native
File size: 12.5 KB
Line 
1/*
2 * vboxweb.h:
3 * header file for "real" web server code.
4 *
5 * Copyright (C) 2006-2013 Oracle Corporation
6 *
7 * This file is part of VirtualBox Open Source Edition (OSE), as
8 * available from http://www.virtualbox.org. This file is free software;
9 * you can redistribute it and/or modify it under the terms of the GNU
10 * General Public License (GPL) as published by the Free Software
11 * Foundation, in version 2 as it comes in the "COPYING" file of the
12 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
13 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
14 */
15
16/****************************************************************************
17 *
18 * debug macro
19 *
20 ****************************************************************************/
21
22void WebLog(const char *pszFormat, ...);
23
24#define WEBDEBUG(a) do { if (g_fVerbose) { WebLog a; } } while (0)
25
26#ifdef DEBUG
27#define LOG_GROUP LOG_GROUP_WEBSERVICE
28#include <VBox/log.h>
29#endif
30
31#include <VBox/com/VirtualBox.h>
32#include <VBox/com/Guid.h>
33#include <VBox/com/AutoLock.h>
34
35#include <VBox/err.h>
36
37#include <iprt/stream.h>
38
39#include <string>
40
41/****************************************************************************
42 *
43 * typedefs
44 *
45 ****************************************************************************/
46
47// type used by gSOAP-generated code
48typedef std::string WSDLT_ID; // combined managed object ref (session ID plus object ID)
49typedef std::string vbox__uuid;
50
51/****************************************************************************
52 *
53 * global variables
54 *
55 ****************************************************************************/
56
57extern bool g_fVerbose;
58
59extern PRTSTREAM g_pstrLog;
60
61extern util::WriteLockHandle *g_pAuthLibLockHandle;
62extern util::WriteLockHandle *g_pSessionsLockHandle;
63
64extern const WSDLT_ID g_EmptyWSDLID;
65
66/****************************************************************************
67 *
68 * SOAP exceptions
69 *
70 ****************************************************************************/
71
72void RaiseSoapInvalidObjectFault(struct soap *soap, WSDLT_ID obj);
73
74void 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
82std::string ConvertComString(const com::Bstr &bstr);
83
84std::string ConvertComString(const com::Guid &bstr);
85
86std::string Base64EncodeByteArray(ComSafeArrayIn(BYTE, aData));
87
88void 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 * managed object reference classes
92 *
93 ****************************************************************************/
94
95class WebServiceSessionPrivate;
96class ManagedObjectRef;
97
98/**
99 * An instance of this gets created for every client that logs onto the
100 * webservice (via the special IWebsessionManager::logon() SOAP API) and
101 * maintains the managed object references for that session.
102 */
103class WebServiceSession
104{
105 friend class ManagedObjectRef;
106
107 private:
108 uint64_t _uSessionID;
109 WebServiceSessionPrivate *_pp; // opaque data struct (defined in vboxweb.cpp)
110 bool _fDestructing;
111
112 ManagedObjectRef *_pISession;
113
114 time_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 _uSessionID;
133 }
134
135 const WSDLT_ID& getSessionWSDLID() const;
136
137 void touch();
138
139 time_t getLastObjectLookup() const
140 {
141 return _tLastObjectLookup;
142 }
143
144 static WebServiceSession* findSessionFromRef(const WSDLT_ID &id);
145
146 void DumpRefs();
147};
148
149/**
150 * ManagedObjectRef is used to map COM pointers to object IDs
151 * within a session. Such object IDs are 64-bit integers.
152 *
153 * When a webservice method call is invoked on an object, it
154 * has an opaque string called a "managed object reference". Such
155 * a string consists of a session ID combined with an object ID.
156 *
157 */
158class ManagedObjectRef
159{
160 protected:
161 // owning session:
162 WebServiceSession &_session;
163
164
165 IUnknown *_pobjUnknown; // pointer to IUnknown interface for this MOR
166
167 void *_pobjInterface; // pointer to COM interface represented by _guidInterface, for which this MOR
168 // was created; this may be an IUnknown or something more specific
169 com::Guid _guidInterface; // the interface which _pvObj represents
170
171 const char *_pcszInterface; // string representation of that interface (e.g. "IMachine")
172
173 // keys:
174 uint64_t _id;
175 uintptr_t _ulp;
176
177 // long ID as string
178 WSDLT_ID _strID;
179
180 public:
181 ManagedObjectRef(WebServiceSession &session,
182 IUnknown *pobjUnknown,
183 void *pobjInterface,
184 const com::Guid &guidInterface,
185 const char *pcszInterface);
186 ~ManagedObjectRef();
187
188 uint64_t getID()
189 {
190 return _id;
191 }
192
193 /**
194 * Returns the contained COM pointer and the UUID of the COM interface
195 * which it supports.
196 * @param
197 * @return
198 */
199 const com::Guid& getPtr(void **ppobjInterface,
200 IUnknown **ppobjUnknown)
201 {
202 *ppobjInterface = _pobjInterface;
203 *ppobjUnknown = _pobjUnknown;
204 return _guidInterface;
205 }
206
207 /**
208 * Returns the ID of this managed object reference to string
209 * form, for returning with SOAP data or similar.
210 *
211 * @return The ID in string form.
212 */
213 const WSDLT_ID& getWSDLID() const
214 {
215 return _strID;
216 }
217
218 const char* getInterfaceName() const
219 {
220 return _pcszInterface;
221 }
222
223 static int findRefFromId(const WSDLT_ID &id,
224 ManagedObjectRef **pRef,
225 bool fNullAllowed);
226
227 static ManagedObjectRef* findFromPtr(ComPtr<IUnknown> pcu);
228 static ManagedObjectRef* create(const WSDLT_ID &idParent,
229 ComPtr<IUnknown> pcu);
230
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_pSessionsLockHandle 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 for the given COM pointer. If a reference already exists
317 * for the given pointer, then that reference's ID is returned instead.
318 *
319 * This gets called from tons of generated code in methodmaps.cpp to
320 * resolve objects *returned* from COM methods (i.e. create MOR strings from COM objects
321 * which might have been newly created).
322 *
323 * @param idParent managed object reference of calling object; used to extract session ID
324 * @param pc COM object for which to create a reference
325 * @return existing or new managed object reference
326 */
327template <class T>
328const WSDLT_ID& createOrFindRefFromComPtr(const WSDLT_ID &idParent,
329 const char *pcszInterface,
330 ComPtr<T> &pc)
331{
332 // NULL comptr should return NULL MOR
333 if (pc.isNull())
334 {
335 WEBDEBUG((" createOrFindRefFromComPtr(): returning empty MOR for NULL COM pointer\n"));
336 return g_EmptyWSDLID;
337 }
338
339 util::AutoWriteLock lock(g_pSessionsLockHandle COMMA_LOCKVAL_SRC_POS);
340 WebServiceSession *pSession;
341 if ((pSession = WebServiceSession::findSessionFromRef(idParent)))
342 {
343 ManagedObjectRef *pRef;
344
345 // we need an IUnknown pointer for the MOR
346 ComPtr<IUnknown> pobjUnknown = pc;
347
348 if ( ((pRef = pSession->findRefFromPtr(pobjUnknown)))
349 || ((pRef = new ManagedObjectRef(*pSession,
350 pobjUnknown, // IUnknown *pobjUnknown
351 pc, // void *pobjInterface
352 COM_IIDOF(T),
353 pcszInterface)))
354 )
355 return pRef->getWSDLID();
356 }
357
358 // session has expired, return an empty MOR instead of allocating a
359 // new reference which couldn't be used anyway.
360 return g_EmptyWSDLID;
361}
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