VirtualBox

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

Last change on this file since 37952 was 36883, checked in by vboxsync, 14 years ago

webservice: pass octet arrays as base64 strings

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