File: | libsynthesis/src/Transport_interfaces/engine/enginesessiondispatch.cpp |
Warning: | line 395, column 10 Potential leak of memory pointed to by 'sessionHandleP' |
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 | ||||
17 | namespace sysync { | |||
18 | ||||
19 | ||||
20 | // write to platform's "console", whatever that is | |||
21 | void 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 | |||
33 | TEngineServerCommConfig::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 | |||
41 | TEngineServerCommConfig::~TEngineServerCommConfig() | |||
42 | { | |||
43 | // nop by now | |||
44 | } // TEngineServerCommConfig::~TEngineServerCommConfig | |||
45 | ||||
46 | ||||
47 | // init defaults | |||
48 | void 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 | |||
62 | bool 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 | |||
81 | void 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 | |||
98 | TEngineSessionDispatch::TEngineSessionDispatch() : | |||
99 | TSyncAppBase() | |||
100 | { | |||
101 | // this is a server engine | |||
102 | fIsServer = true; | |||
103 | } // TEngineSessionDispatch::TEngineSessionDispatch | |||
104 | ||||
105 | ||||
106 | // destructor | |||
107 | TEngineSessionDispatch::~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 | |||
117 | Ret_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 | |||
139 | bool 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 | |||
148 | void 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+="&"; | |||
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 | |||
189 | Ret_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 | |||
261 | void 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 | ||||
270 | bool 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 | ||||
287 | TEngineServerSessionHandle::TEngineServerSessionHandle(TServerEngineInterface *aServerEngineInterface) | |||
288 | { | |||
289 | fServerSessionP = NULL__null; | |||
290 | fSmlInstanceID = 0; | |||
291 | fServerSessionStatus = LOCERR_WRONGUSAGE; | |||
292 | fServerEngineInterface = aServerEngineInterface; | |||
293 | } | |||
294 | ||||
295 | TEngineServerSessionHandle::~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 | |||
314 | TSyError 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) { | |||
| ||||
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); | |||
344 | // - create session ID if none passed | |||
345 | string SessionIDString; | |||
346 | if (aSessionName && *aSessionName) { | |||
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) { | |||
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; | |||
| ||||
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 | |||
405 | TSyError 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 | |||
420 | TSyError 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 | |||
458 | TSyError 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) | |||
486 | InstanceID_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 |