Bug Summary

File:libsynthesis/src/Transport_interfaces/engine/enginesessiondispatch.cpp
Warning:line 395, column 10
Potential leak of memory pointed to by 'sessionHandleP'

Annotated Source Code

1/*
2 * TEngineSessionDispatch
3 * Server library specific descendant of TSyncSessionDispatch
4 *
5 * Copyright (c) 2009-2011 by Synthesis AG + plan44.ch
6 *
7 * 2009-02-06 : luz : Created
8 *
9 */
10
11
12#include "prefix_file.h"
13#include "engine_server.h"
14#include "enginesessiondispatch.h"
15
16
17namespace sysync {
18
19
20// write to platform's "console", whatever that is
21void AppConsolePuts(const char *aText)
22{
23 // Just print to platform's console
24 PlatformConsolePuts(aText);
25} // AppConsolePuts
26
27
28// TEngineServerCommConfig
29// =======================
30
31
32// config constructor
33TEngineServerCommConfig::TEngineServerCommConfig(TConfigElement *aParentElementP) :
34 TCommConfig("engineserver",aParentElementP)
35{
36 // do not call clear(), because this is virtual!
37} // TEngineServerCommConfig::TEngineServerCommConfig
38
39
40// config destructor
41TEngineServerCommConfig::~TEngineServerCommConfig()
42{
43 // nop by now
44} // TEngineServerCommConfig::~TEngineServerCommConfig
45
46
47// init defaults
48void TEngineServerCommConfig::clear(void)
49{
50 // init defaults
51 fSessionIDCGIPrefix = "sessionid=";
52 fSessionIDCGI = true;
53 fBuffersRetryAnswer = false; // we don't know if the app driving the engine implements this, so default is off
54 // clear inherited
55 inherited::clear();
56} // TEngineServerCommConfig::clear
57
58
59#ifndef HARDCODED_CONFIG
60
61// XPT transport config element parsing
62bool TEngineServerCommConfig::localStartElement(const char *aElementName, const char **aAttributes, sInt32 aLine)
63{
64 // checking the elements
65 if (strucmp(aElementName,"buffersretryanswer")==0)
66 expectBool(fBuffersRetryAnswer);
67 if (strucmp(aElementName,"sessionidcgiprefix")==0)
68 expectString(fSessionIDCGIPrefix);
69 if (strucmp(aElementName,"sessionidcgi")==0)
70 expectBool(fSessionIDCGI);
71 else
72 return inherited::localStartElement(aElementName,aAttributes,aLine);
73 // ok
74 return true;
75} // TEngineServerCommConfig::localStartElement
76
77#endif
78
79
80// resolve
81void TEngineServerCommConfig::localResolve(bool aLastPass)
82{
83 if (aLastPass) {
84 // check for required settings
85 // NOP for now
86 }
87 // resolve inherited
88 inherited::localResolve(aLastPass);
89} // TEngineServerCommConfig::localResolve
90
91
92
93// TEngineSessionDispatch
94// ======================
95
96
97// constructor
98TEngineSessionDispatch::TEngineSessionDispatch() :
99 TSyncAppBase()
100{
101 // this is a server engine
102 fIsServer = true;
103} // TEngineSessionDispatch::TEngineSessionDispatch
104
105
106// destructor
107TEngineSessionDispatch::~TEngineSessionDispatch()
108{
109 fDeleting=true; // flag deletion to block calling critical (virtual) methods
110 // clean up
111 // %%%
112} // TEngineSessionDispatch::~TEngineSessionDispatch
113
114
115// Called from SyncML toolkit when a new SyncML message arrives
116// - dispatches to session's StartMessage
117Ret_t TEngineSessionDispatch::StartMessage(
118 InstanceID_t aSmlWorkspaceID, // SyncML toolkit workspace instance ID
119 VoidPtr_t aUserData, // pointer to a TSyncAgent descendant
120 SmlSyncHdrPtr_t aContentP // SyncML tookit's decoded form of the <SyncHdr> element
121) {
122 TSyncSession *sessionP = static_cast<TSyncAgent *>(aUserData); // the server session
123 SYSYNC_TRYtry {
124 // let session handle details of StartMessage callback
125 return sessionP->StartMessage(aContentP);
126 }
127 SYSYNC_CATCH (exception &e)catch(exception &e) {
128 return HandleDecodingException(sessionP,"StartMessage",&e);
129 SYSYNC_ENDCATCH}
130 SYSYNC_CATCH (...)catch(...) {
131 return HandleDecodingException(sessionP,"StartMessage",NULL__null);
132 SYSYNC_ENDCATCH}
133} // TEngineSessionDispatch::StartMessage
134
135
136
137
138// Test if message buffering is available
139bool TEngineSessionDispatch::canBufferRetryAnswer(void)
140{
141 // basically, we can buffer, we do it if configured
142 return dynamic_cast<TEngineServerCommConfig *>(getRootConfig()->fCommConfigP)->fBuffersRetryAnswer;
143} // TEngineSessionDispatch::canBufferRetryAnswer
144
145
146
147// Combine URI and session ID to make a RespURI according to transport
148void TEngineSessionDispatch::generateRespURI(
149 string &aRespURI,
150 cAppCharP aLocalURI,
151 cAppCharP aSessionID
152)
153{
154 TEngineServerCommConfig *commCfgP = static_cast<TEngineServerCommConfig *>(getRootConfig()->fCommConfigP);
155 if (aLocalURI && aSessionID && commCfgP && commCfgP->fSessionIDCGI) {
156 // include session ID as CGI into RespURI
157 aRespURI=aLocalURI;
158 // see if there is already a sessionid in this localURI
159 string::size_type n=aRespURI.find(commCfgP->fSessionIDCGIPrefix);
160 if (n!=string::npos) {
161 n+=commCfgP->fSessionIDCGIPrefix.size(); // char after prefix
162 // is already there, replace value with new value
163 string::size_type m=aRespURI.find_first_of("&?\n\r",n);
164 if (m==string::npos)
165 aRespURI.replace(n,999,aSessionID);
166 else
167 aRespURI.replace(n,m-n,aSessionID);
168 }
169 else {
170 // no sessionID yet
171 if (strchr(aLocalURI,'?')) {
172 // already has CGI param
173 aRespURI+="&amp;";
174 }
175 else {
176 // is first CGI param
177 aRespURI+='?';
178 }
179 // append session ID as CGI parameter
180 aRespURI+=commCfgP->fSessionIDCGIPrefix;
181 aRespURI+=aSessionID;
182 }
183 }
184} // TEngineSessionDispatch::generateRespURI
185
186
187
188// Handle exception happening while decoding commands for a session
189Ret_t TEngineSessionDispatch::HandleDecodingException(TSyncSession *aSessionP, const char *aRoutine, exception *aExceptionP)
190{
191 #ifdef SYDEBUG2
192 // determine session name
193 const char *sname = "<unknown>";
194 SYSYNC_TRYtry {
195 if (aSessionP) {
196 sname = aSessionP->getLocalSessionID();
197 }
198 }
199 SYSYNC_CATCH (...)catch(...) {
200 sname = "<BAD aSessionP, caused exception>";
201 aSessionP=NULL__null; // prevent attempt to write to session's log
202 SYSYNC_ENDCATCH}
203 // determine routine name
204 if (!aRoutine) aRoutine="<unspecified routine>";
205 // show details
206 if (aExceptionP) {
207 // known exception
208 // - show it in global log
209 PDEBUGPRINTFX(DBG_ERROR,({ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "******** Exception in %s, sessionID=%s: %s"
, aRoutine, sname, aExceptionP->what() ); }
210 "******** Exception in %s, sessionID=%s: %s",{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "******** Exception in %s, sessionID=%s: %s"
, aRoutine, sname, aExceptionP->what() ); }
211 aRoutine,{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "******** Exception in %s, sessionID=%s: %s"
, aRoutine, sname, aExceptionP->what() ); }
212 sname,{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "******** Exception in %s, sessionID=%s: %s"
, aRoutine, sname, aExceptionP->what() ); }
213 aExceptionP->what(){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "******** Exception in %s, sessionID=%s: %s"
, aRoutine, sname, aExceptionP->what() ); }
214 )){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "******** Exception in %s, sessionID=%s: %s"
, aRoutine, sname, aExceptionP->what() ); }
;
215 // - and also in session log
216 #ifdef SYDEBUG2
217 if (aSessionP) {
218 POBJDEBUGPRINTFX(aSessionP,DBG_ERROR,({ if ((aSessionP) && (((0x00000002) & (aSessionP)
->getDbgMask()) == (0x00000002))) (aSessionP)->getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "******** Warning: Exception in %s: %s"
, aRoutine, aExceptionP->what() ); }
219 "******** Warning: Exception in %s: %s",{ if ((aSessionP) && (((0x00000002) & (aSessionP)
->getDbgMask()) == (0x00000002))) (aSessionP)->getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "******** Warning: Exception in %s: %s"
, aRoutine, aExceptionP->what() ); }
220 aRoutine,{ if ((aSessionP) && (((0x00000002) & (aSessionP)
->getDbgMask()) == (0x00000002))) (aSessionP)->getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "******** Warning: Exception in %s: %s"
, aRoutine, aExceptionP->what() ); }
221 aExceptionP->what(){ if ((aSessionP) && (((0x00000002) & (aSessionP)
->getDbgMask()) == (0x00000002))) (aSessionP)->getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "******** Warning: Exception in %s: %s"
, aRoutine, aExceptionP->what() ); }
222 )){ if ((aSessionP) && (((0x00000002) & (aSessionP)
->getDbgMask()) == (0x00000002))) (aSessionP)->getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "******** Warning: Exception in %s: %s"
, aRoutine, aExceptionP->what() ); }
;
223 }
224 #endif
225 }
226 else {
227 // unknown exception
228 // - show it in global log
229 PDEBUGPRINTFX(DBG_ERROR,({ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "******** Unknown Exception in %s, sessionID=%s"
, aRoutine, sname ); }
230 "******** Unknown Exception in %s, sessionID=%s",{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "******** Unknown Exception in %s, sessionID=%s"
, aRoutine, sname ); }
231 aRoutine,{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "******** Unknown Exception in %s, sessionID=%s"
, aRoutine, sname ); }
232 sname{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "******** Unknown Exception in %s, sessionID=%s"
, aRoutine, sname ); }
233 )){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "******** Unknown Exception in %s, sessionID=%s"
, aRoutine, sname ); }
;
234 // - and also in session log
235 #ifdef SYDEBUG2
236 if (aSessionP) {
237 POBJDEBUGPRINTFX(aSessionP,DBG_ERROR,({ if ((aSessionP) && (((0x00000002) & (aSessionP)
->getDbgMask()) == (0x00000002))) (aSessionP)->getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "******** Warning: Unknown Exception in %s"
, aRoutine ); }
238 "******** Warning: Unknown Exception in %s",{ if ((aSessionP) && (((0x00000002) & (aSessionP)
->getDbgMask()) == (0x00000002))) (aSessionP)->getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "******** Warning: Unknown Exception in %s"
, aRoutine ); }
239 aRoutine{ if ((aSessionP) && (((0x00000002) & (aSessionP)
->getDbgMask()) == (0x00000002))) (aSessionP)->getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "******** Warning: Unknown Exception in %s"
, aRoutine ); }
240 )){ if ((aSessionP) && (((0x00000002) & (aSessionP)
->getDbgMask()) == (0x00000002))) (aSessionP)->getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "******** Warning: Unknown Exception in %s"
, aRoutine ); }
;
241 }
242 #endif
243 }
244 #endif
245 // try to kill session
246 DEBUGPRINTFX(DBG_SESSION,("******** Exception aborts session")){ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("******** Exception aborts session"
); }
;
247 if (aSessionP)
248 aSessionP->AbortSession(412,true); // incomplete command
249 // return error
250 DEBUGPRINTFX(DBG_SESSION,("******** Exception: returning SML_ERR_UNSPECIFIC to abort smlProcessData")){ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("******** Exception: returning SML_ERR_UNSPECIFIC to abort smlProcessData"
); }
;
251 return SML_ERR_UNSPECIFIC0x10;
252} // TEngineSessionDispatch::HandleDecodingException
253
254
255
256// factory methods of Rootconfig
257// =============================
258
259
260// create default transport config
261void TEngineServerRootConfig::installCommConfig(void)
262{
263 // engine API needs no config at this time, commconfig is a NOP dummy for now
264 fCommConfigP=new TEngineServerCommConfig(this);
265} // TEngineServerRootConfig::installCommConfig
266
267
268#ifndef HARDCODED_CONFIG
269
270bool TEngineServerRootConfig::parseCommConfig(const char **aAttributes, sInt32 aLine)
271{
272 // engine API needs no config at this time
273 return false;
274} // TEngineServerRootConfig::parseCommConfig
275
276#endif
277
278
279
280// TEngineServerSessionHandle
281// ==========================
282
283// Note: this is not a relative of TSyncSessionHandle, but only a container for TSyncAgent also
284// holding some engine-related status. TSyncAgent is run with a NULL TSyncSessionHandle
285// when called via engine, as all session dispatching is outside the engine.
286
287TEngineServerSessionHandle::TEngineServerSessionHandle(TServerEngineInterface *aServerEngineInterface)
288{
289 fServerSessionP = NULL__null;
290 fSmlInstanceID = 0;
291 fServerSessionStatus = LOCERR_WRONGUSAGE;
292 fServerEngineInterface = aServerEngineInterface;
293}
294
295TEngineServerSessionHandle::~TEngineServerSessionHandle()
296{
297 // remove the session if still existing
298 if (fServerSessionP) delete fServerSessionP;
299 fServerSessionP = NULL__null;
300 // also release the toolkit instance
301 fServerEngineInterface->getSyncAppBase()->freeSmlInstance(fSmlInstanceID);
302 fSmlInstanceID=NULL__null;
303}
304
305
306// TServerEngineInterface
307// ======================
308
309/// @brief Open a session
310/// @param aNewSessionH[out] receives session handle for all session execution calls
311/// @param aSelector[in] selector, depending on session type.
312/// @param aSessionName[in] a text name/id to identify the session. If NULL, session gets a standard ID based on time and memory location
313/// @return LOCERR_OK on success, SyncML or LOCERR_xxx error code on failure
314TSyError TServerEngineInterface::OpenSessionInternal(SessionH &aNewSessionH, uInt32 aSelector, cAppCharP aSessionName)
315{
316 TEngineSessionDispatch *sessionDispatchP = static_cast<TEngineSessionDispatch *>(getSyncAppBase());
317
318 // check type of session
319 if (aSelector == SESSIONSEL_DBAPI_TUNNEL) {
1
Assuming 'aSelector' is not equal to SESSIONSEL_DBAPI_TUNNEL
2
Taking false branch
320 // initiate a DBAPI tunnel session.
321 /*
322 #ifdef DBAPI_TUNNEL_SUPPORT
323 #error "%%% tbi"
324 // Create a new session, sessionName selects datastore
325 sessionHandleP->fServerSessionStatus = sessionDispatchP->CreateTunnelSession(aSessionName);
326 if (sessionHandleP->fServerSessionStatus==LOCERR_OK) {
327 // return the session pointer as handle
328 %%%aNewSessionH=clientBaseP->fClientSessionP;
329 }
330 #else
331 return LOCERR_NOTIMP; // tunnel not implemented
332 #endif
333 */
334 // %%% for now: not implemented
335 return LOCERR_NOTIMP; // tunnel not implemented
336 }
337 else {
338 // create a new server session
339 TEngineServerSessionHandle *sessionHandleP = NULL__null;
340 TSyncAgent *sessionP=NULL__null;
341 SYSYNC_TRYtry {
342 // - create a handle
343 sessionHandleP = new TEngineServerSessionHandle(this);
3
Memory is allocated
344 // - create session ID if none passed
345 string SessionIDString;
346 if (aSessionName && *aSessionName) {
4
Assuming 'aSessionName' is non-null
5
Assuming the condition is true
6
Taking true branch
347 SessionIDString = aSessionName;
348 }
349 else {
350 // - create unique server-side session ID
351 // format = aaaabbbbccccdddd
352 // - aaaa = low word of time(NULL) >> 1 (to make sure MSB is cleared)
353 // - dddd = high word of time(NULL)
354 // - bbbbcccc = memory address of session handle
355 uInt64 sid =
356 time(NULL__null);
357 sid =
358 ((sid >> 16) & 0xFFFF) + ((sid << 47) & 0x7FFF000000000000LL) + // aaaa00000000dddd
359 ((((uIntPtr)sessionHandleP)&0xFFFFFFFF) << 16); // 0000bbbbcccc0000
360 // - make a string of it
361 StringObjPrintf(SessionIDString,"%llu",(long long unsigned)sid);
362 }
363 // - create session object
364 sessionP =
365 static_cast<TAgentConfig *>(sessionDispatchP->getRootConfig()->fAgentConfigP)
366 ->CreateServerSession(NULL__null,SessionIDString.c_str());
367 if (sessionP) {
7
Assuming 'sessionP' is null
8
Taking false branch
368 // assign to handle
369 sessionHandleP->fServerSessionP = sessionP;
370 sessionHandleP->fServerSessionStatus = LOCERR_OK;
371 // also create a toolkit instance for the session (so we can start receiving data)
372 if (!getSyncAppBase()->newSmlInstance(
373 SML_XML,
374 sessionDispatchP->getRootConfig()->fLocalMaxMsgSize * 2, // twice the message size
375 sessionHandleP->fSmlInstanceID
376 )) {
377 // failed creating instance (must be memory problem)
378 delete sessionP;
379 return LOCERR_OUTOFMEM;
380 }
381 // link session with toolkit instance back and forth
382 getSyncAppBase()->setSmlInstanceUserData(sessionHandleP->fSmlInstanceID,sessionP); // toolkit must know session (as userData)
383 sessionP->setSmlWorkspaceID(sessionHandleP->fSmlInstanceID); // session must know toolkit workspace
384 // created session ok
385 aNewSessionH = (SessionH)sessionHandleP;
386 return LOCERR_OK;
387 }
388 }
389 SYSYNC_CATCH (...)catch(...) {
390 // error creating session
391 if (sessionHandleP) delete sessionHandleP;
392 return LOCERR_EXCEPTION;
393 SYSYNC_ENDCATCH}
394 }
395 return LOCERR_WRONGUSAGE;
9
Potential leak of memory pointed to by 'sessionHandleP'
396}
397
398
399/// @brief open session specific runtime parameter/settings key
400/// @note key handle obtained with this call must be closed BEFORE SESSION IS CLOSED!
401/// @param aNewKeyH[out] receives the opened key's handle on success
402/// @param aSessionH[in] session handle obtained with OpenSession
403/// @param aMode[in] the open mode
404/// @return LOCERR_OK on success, SyncML or LOCERR_xxx error code on failure
405TSyError TServerEngineInterface::OpenSessionKey(SessionH aSessionH, KeyH &aNewKeyH, uInt16 aMode)
406{
407 if (!aSessionH) return LOCERR_WRONGUSAGE;
408 TEngineServerSessionHandle *sessionHandleP = reinterpret_cast<TEngineServerSessionHandle *>(aSessionH);
409 // create settings key for the session
410 aNewKeyH = (KeyH)sessionHandleP->fServerSessionP->newSessionKey(this);
411 // done
412 return LOCERR_OK;
413}
414
415
416/// @brief Close a session
417/// @note terminates and destroys the session (if not already terminated)
418/// @param aSessionH[in] session handle obtained with OpenSession
419/// @return LOCERR_OK on success, SyncML or LOCERR_xxx error code on failure
420TSyError TServerEngineInterface::CloseSession(SessionH aSessionH)
421{
422 if (!aSessionH) return LOCERR_WRONGUSAGE;
423 TSyError sta = LOCERR_OK;
424 TEngineServerSessionHandle *sessionHandleP = reinterpret_cast<TEngineServerSessionHandle *>(aSessionH);
425 TSyncAgent *serverSessionP = sessionHandleP->fServerSessionP;
426 if (serverSessionP) {
427 // session still exists
428 if (!serverSessionP->isAborted()) {
429 // if not already aborted otherwise (e.g. by writing "abortstatus" in session key), let it be "timeout"
430 serverSessionP->AbortSession(408, true);
431 }
432 SYSYNC_TRYtry {
433 // - terminate (might hang a while until subthreads properly terminate)
434 serverSessionP->TerminateSession();
435 // - delete
436 sessionHandleP->fServerSessionP = NULL__null; // consider deleted, whatever happens
437 delete serverSessionP; // might hang until subthreads have terminated
438 }
439 SYSYNC_CATCH(...)catch(...) {
440 sessionHandleP->fServerSessionP = NULL__null; // consider deleted, even if failed
441 sta = LOCERR_EXCEPTION;
442 SYSYNC_ENDCATCH}
443 }
444 // forget session handle (and toolkit instance)
445 delete sessionHandleP;
446 // done
447 return LOCERR_OK;
448}
449
450
451/// @brief Executes sync session or other sync related activity step by step
452/// @param aSessionH[in] session handle obtained with OpenSession
453/// @param aStepCmd[in/out] step command (STEPCMD_xxx):
454/// - tells caller to send or receive data or end the session etc.
455/// - instructs engine to suspend or abort the session etc.
456/// @param aInfoP[in] pointer to a TEngineProgressInfo structure, NULL if no progress info needed
457/// @return LOCERR_OK on success, SyncML or LOCERR_xxx error code on failure
458TSyError TServerEngineInterface::SessionStep(SessionH aSessionH, uInt16 &aStepCmd, TEngineProgressInfo *aInfoP)
459{
460 if (!aSessionH) return LOCERR_WRONGUSAGE;
461 TEngineServerSessionHandle *sessionHandleP = reinterpret_cast<TEngineServerSessionHandle *>(aSessionH);
462 TSyncAgent *serverSessionP = sessionHandleP->fServerSessionP;
463
464 // preprocess general step codes
465 switch (aStepCmd) {
466 case STEPCMD_TRANSPFAIL :
467 // directly abort
468 serverSessionP->AbortSession(LOCERR_TRANSPFAIL,true);
469 goto abort;
470 case STEPCMD_TIMEOUT :
471 // directly abort
472 serverSessionP->AbortSession(408,true);
473 abort:
474 aStepCmd = STEPCMD_STEP; // convert to normal step
475 break;
476 }
477 // let server session handle it
478 sessionHandleP->fServerSessionStatus = serverSessionP->SessionStep(aStepCmd, aInfoP);
479 // return step status
480 return sessionHandleP->fServerSessionStatus;
481} // TServerEngineInterface::SessionStep
482
483
484/// @brief returns the SML instance for a given session handle
485/// (internal helper to allow TEngineInterface to provide the access to the SyncML buffer)
486InstanceID_t TServerEngineInterface::getSmlInstanceOfSession(SessionH aSessionH)
487{
488 if (!aSessionH) return 0; // something wrong with session handle -> no SML instance
489 TEngineServerSessionHandle *sessionHandleP = reinterpret_cast<TEngineServerSessionHandle *>(aSessionH);
490 TSyncAgent *serverSessionP = sessionHandleP->fServerSessionP;
491 if (!serverSessionP) return 0; // something wrong with session handle -> no SML instance
492 // return SML instance associated with that session
493 return serverSessionP->getSmlWorkspaceID();
494} // TServerEngineInterface::getSmlInstanceOfSession
495
496
497} // namespace sysync
498
499// eof