Bug Summary

File:libsynthesis/src/sysync/syncsession.cpp
Warning:line 2088, column 15
Value stored to 'sendable' is never read

Annotated Source Code

1/*
2 * TSyncSession
3 * Represents an entire Synchronisation Session, possibly consisting
4 * of multiple SyncML-Toolkit "Sessions" (Message composition/de-
5 * composition) as well as multiple database synchronisations.
6 *
7 * Copyright (c) 2001-2011 by Synthesis AG + plan44.ch
8 *
9 * 2001-05-07 : luz : Created
10 *
11 */
12
13
14#include "prefix_file.h"
15
16#include "sysync.h"
17#include "syncsession.h"
18#include "syncagent.h"
19#ifdef SUPERDATASTORES1
20 #include "superdatastore.h"
21#endif
22#ifdef SCRIPT_SUPPORT1
23 #include "scriptcontext.h"
24#endif
25#ifdef MULTI_THREAD_SUPPORT1
26 #include "platform_thread.h"
27#endif
28
29#include <xltdec.h>
30#include <xltdevinf.h>
31
32#ifndef SYNCSESSION_PART1_EXCLUDE
33
34namespace sysync {
35
36// enum names
37// ----------
38
39// SyncML version info
40const char * const SyncMLVerProtoNames[numSyncMLVersions] = {
41 "undefined",
42 "SyncML/1.0",
43 "SyncML/1.1",
44 "SyncML/1.2"
45};
46const SmlVersion_t SmlVersionCodes[numSyncMLVersions] = {
47 SML_VERS_UNDEF,
48 SML_VERS_1_0,
49 SML_VERS_1_1,
50 SML_VERS_1_2
51};
52const char * const SyncMLVerDTDNames[numSyncMLVersions] = {
53 "???",
54 "1.0",
55 "1.1",
56 "1.2"
57};
58const char * const SyncMLDevInfNames[numSyncMLVersions] = {
59 NULL__null,
60 "./devinf10",
61 "./devinf11",
62 "./devinf12"
63};
64#ifndef HARDCODED_CONFIG
65// version for use in config files
66const char * const SyncMLVersionNames[numSyncMLVersions] = {
67 "unknown",
68 "1.0",
69 "1.1",
70 "1.2"
71};
72#endif
73
74
75// auth type names for config
76const char * const authTypeNames[numAuthTypes] = {
77 "none", // no authorisation
78 "basic", // basic (B64 encoded user pw string)
79 "md5", // Md5 encoded user:pw:nonce
80};
81
82
83// sync mode names
84const char * const SyncModeNames[numSyncModes] = {
85 "twoway",
86 "fromserver",
87 "fromclient"
88};
89
90
91
92#ifdef SYDEBUG2
93// package state names
94const char * const PackageStateNames[numPackageStates] = {
95 "idle",
96 "init",
97 "sync",
98 "initsync",
99 "map",
100 "supplement"
101};
102
103// sync operations
104const char * const SyncOpNames[numSyncOperations] = {
105 "wants-add",
106 "add",
107 "wants-replace",
108 "replace",
109 "reference-only",
110 "archive+delete",
111 "soft-delete",
112 "delete",
113 "copy",
114 "move",
115 "[none]" // should be last
116};
117
118#endif
119
120// sync mode descriptions
121const char * const SyncModeDescriptions[numSyncModes] = {
122 "two-way",
123 "from server only",
124 "from client only"
125};
126
127
128#ifdef SCRIPT_SUPPORT1
129
130// builtin functions for status-handling scripts
131
132// integer STATUS()
133static void func_Status(TItemField *&aTermP, TScriptContext *aFuncContextP)
134{
135 TErrorFuncContext *errctxP = static_cast<TErrorFuncContext *>(aFuncContextP->getCallerContext());
136 aTermP->setAsInteger(
137 errctxP->statuscode
138 );
139} // func_Status
140
141
142// void SETSTATUS(integer statuscode)
143static void func_SetStatus(TItemField *&aTermP, TScriptContext *aFuncContextP)
144{
145 TErrorFuncContext *errctxP = static_cast<TErrorFuncContext *>(aFuncContextP->getCallerContext());
146 errctxP->newstatuscode=
147 aFuncContextP->getLocalVar(0)->getAsInteger();
148} // func_SetStatus
149
150
151// void SETRESEND(boolean doresend)
152static void func_SetResend(TItemField *&aTermP, TScriptContext *aFuncContextP)
153{
154 TErrorFuncContext *errctxP = static_cast<TErrorFuncContext *>(aFuncContextP->getCallerContext());
155 errctxP->resend=
156 aFuncContextP->getLocalVar(0)->getAsBoolean();
157} // func_SetResend
158
159
160// void ABORTDATASTORE(integer statuscode)
161static void func_AbortDatastore(TItemField *&aTermP, TScriptContext *aFuncContextP)
162{
163 TErrorFuncContext *errctxP = static_cast<TErrorFuncContext *>(aFuncContextP->getCallerContext());
164 if (errctxP->datastoreP) {
165 errctxP->datastoreP->engAbortDataStoreSync(aFuncContextP->getLocalVar(0)->getAsInteger(),true); // we cause the abort locally
166 }
167} // func_AbortDatastore
168
169
170// void STOPADDING()
171static void func_StopAdding(TItemField *&aTermP, TScriptContext *aFuncContextP)
172{
173 TErrorFuncContext *errctxP = static_cast<TErrorFuncContext *>(aFuncContextP->getCallerContext());
174 if (errctxP->datastoreP) {
175 errctxP->datastoreP->engStopAddingToRemote();
176 }
177} // func_StopAdding
178
179
180// string SYNCOP()
181// returns sync-operation as text
182static void func_SyncOp(TItemField *&aTermP, TScriptContext *aFuncContextP)
183{
184 TErrorFuncContext *errctxP = static_cast<TErrorFuncContext *>(aFuncContextP->getCallerContext());
185 aTermP->setAsString(
186 SyncOpNames[errctxP->syncop]
187 );
188} // func_SyncOp
189
190
191const uInt8 param_OneInteger[] = { VAL(fty_integer)( (uInt8)fty_integer) };
192const uInt8 param_TwoIntegers[] = { VAL(fty_integer)( (uInt8)fty_integer), VAL(fty_integer)( (uInt8)fty_integer) };
193const uInt8 param_OneString[] = { VAL(fty_string)( (uInt8)fty_string) };
194
195const TBuiltInFuncDef ErrorFuncDefs[] = {
196 { "STATUS", func_Status, fty_integer, 0, NULL__null },
197 { "SETSTATUS", func_SetStatus, fty_none, 1, param_OneInteger },
198 { "SETRESEND", func_SetResend, fty_none, 1, param_OneInteger },
199 { "ABORTDATASTORE", func_AbortDatastore, fty_none, 1, param_OneInteger },
200 { "STOPADDING", func_StopAdding, fty_none, 0, NULL__null },
201 { "SYNCOP", func_SyncOp, fty_string, 0, NULL__null },
202};
203
204const TFuncTable ErrorFuncTable = {
205 sizeof(ErrorFuncDefs) / sizeof(TBuiltInFuncDef), // size of table
206 ErrorFuncDefs, // table pointer
207 NULL__null // no chain func
208};
209
210
211// void SETSTATUS(integer statuscode)
212static void func_GetPutResSetStatus(TItemField *&aTermP, TScriptContext *aFuncContextP)
213{
214 TGetPutResultFuncContext *gprctxP = static_cast<TGetPutResultFuncContext *>(aFuncContextP->getCallerContext());
215 gprctxP->statuscode=
216 aFuncContextP->getLocalVar(0)->getAsInteger();
217} // func_GetPutResSetStatus
218
219
220// integer ISPUT()
221static void func_IsPut(TItemField *&aTermP, TScriptContext *aFuncContextP)
222{
223 TGetPutResultFuncContext *gprctxP = static_cast<TGetPutResultFuncContext *>(aFuncContextP->getCallerContext());
224 aTermP->setAsBoolean(gprctxP->isPut);
225} // func_IsPut
226
227
228// string ITEMURI()
229static void func_ItemURI(TItemField *&aTermP, TScriptContext *aFuncContextP)
230{
231 TGetPutResultFuncContext *gprctxP = static_cast<TGetPutResultFuncContext *>(aFuncContextP->getCallerContext());
232 aTermP->setAsString(gprctxP->itemURI);
233} // func_ItemURI
234
235
236// void SETITEMURI(string data)
237static void func_SetItemURI(TItemField *&aTermP, TScriptContext *aFuncContextP)
238{
239 TGetPutResultFuncContext *gprctxP = static_cast<TGetPutResultFuncContext *>(aFuncContextP->getCallerContext());
240 aFuncContextP->getLocalVar(0)->getAsString(gprctxP->itemURI);
241} // func_SetItemURI
242
243
244// string ITEMDATA()
245static void func_ItemData(TItemField *&aTermP, TScriptContext *aFuncContextP)
246{
247 TGetPutResultFuncContext *gprctxP = static_cast<TGetPutResultFuncContext *>(aFuncContextP->getCallerContext());
248 aTermP->setAsString(gprctxP->itemData);
249} // func_ItemData
250
251
252// void SETITEMDATA(string data)
253static void func_SetItemData(TItemField *&aTermP, TScriptContext *aFuncContextP)
254{
255 TGetPutResultFuncContext *gprctxP = static_cast<TGetPutResultFuncContext *>(aFuncContextP->getCallerContext());
256 aFuncContextP->getLocalVar(0)->getAsString(gprctxP->itemData);
257} // func_SetItemData
258
259
260// string METATYPE()
261static void func_MetaType(TItemField *&aTermP, TScriptContext *aFuncContextP)
262{
263 TGetPutResultFuncContext *gprctxP = static_cast<TGetPutResultFuncContext *>(aFuncContextP->getCallerContext());
264 aTermP->setAsString(gprctxP->metaType);
265} // func_MetaType
266
267
268// void SETMETATYPE(string data)
269static void func_SetMetaType(TItemField *&aTermP, TScriptContext *aFuncContextP)
270{
271 TGetPutResultFuncContext *gprctxP = static_cast<TGetPutResultFuncContext *>(aFuncContextP->getCallerContext());
272 aFuncContextP->getLocalVar(0)->getAsString(gprctxP->metaType);
273} // func_SetMetaType
274
275
276// void ISSUEPUT(boolean allowFailure, boolean noResp)
277// use ITEMURI, ITEMDATA and METATYPE to issue a PUT command
278static void func_IssuePut(TItemField *&aTermP, TScriptContext *aFuncContextP)
279{
280 TGetPutResultFuncContext *gprctxP = static_cast<TGetPutResultFuncContext *>(aFuncContextP->getCallerContext());
281 if (gprctxP->canIssue) {
282 TPutCommand *putcommandP = new TPutCommand(aFuncContextP->getSession());
283 putcommandP->setMeta(newMetaType(gprctxP->metaType.c_str()));
284 SmlItemPtr_t putItemP = putcommandP->addSourceLocItem(gprctxP->itemURI.c_str());
285 // - add data to item
286 putItemP->data = newPCDataString(gprctxP->itemData);
287 // issue it
288 if (aFuncContextP->getLocalVar(0)->getAsBoolean()) putcommandP->allowFailure(); // allow failure (4xx or 5xx status)
289 aFuncContextP->getSession()->issueRootPtr(putcommandP,aFuncContextP->getLocalVar(1)->getAsBoolean());
290 }
291} // func_IssuePut
292
293
294// void ISSUEGET(boolean allowFailure)
295// use ITEMURI and METATYPE to issue a GET command
296static void func_IssueGet(TItemField *&aTermP, TScriptContext *aFuncContextP)
297{
298 TGetPutResultFuncContext *gprctxP = static_cast<TGetPutResultFuncContext *>(aFuncContextP->getCallerContext());
299 if (gprctxP->canIssue) {
300 TGetCommand *getcommandP = new TGetCommand(aFuncContextP->getSession());
301 getcommandP->addTargetLocItem(gprctxP->itemURI.c_str());
302 getcommandP->setMeta(newMetaType(gprctxP->metaType.c_str()));
303 // issue it
304 if (aFuncContextP->getLocalVar(0)->getAsBoolean()) getcommandP->allowFailure(); // allow failure (4xx or 5xx status)
305 aFuncContextP->getSession()->issueRootPtr(getcommandP,false); // get with noResp does not make sense
306 }
307} // func_IssueGet
308
309
310// void ISSUEALERT(boolean allowFailure, integer alertcode)
311// use ITEMDATA to add an Alert item
312static void func_IssueAlert(TItemField *&aTermP, TScriptContext *aFuncContextP)
313{
314 TGetPutResultFuncContext *gprctxP = static_cast<TGetPutResultFuncContext *>(aFuncContextP->getCallerContext());
315 if (gprctxP->canIssue) {
316 uInt16 alertcode = aFuncContextP->getLocalVar(1)->getAsInteger();
317 TAlertCommand *alertCommandP = new TAlertCommand(aFuncContextP->getSession(),NULL__null,alertcode);
318 // - add string data item
319 alertCommandP->addItem(newStringDataItem(gprctxP->itemData.c_str()));
320 // issue it
321 if (aFuncContextP->getLocalVar(0)->getAsBoolean()) alertCommandP->allowFailure(); // allow failure (4xx or 5xx status)
322 aFuncContextP->getSession()->issueRootPtr(alertCommandP,false); // Alert with noResp not supported
323 }
324} // func_IssueAlert
325
326
327
328
329const TBuiltInFuncDef GetPutResultFuncDefs[] = {
330 { "SETSTATUS", func_GetPutResSetStatus, fty_none, 1, param_OneInteger },
331 { "ISPUT", func_IsPut, fty_integer, 0, NULL__null },
332 { "ITEMURI", func_ItemURI, fty_string, 0, NULL__null },
333 { "SETITEMURI", func_SetItemURI, fty_none, 1, param_OneString },
334 { "ITEMDATA", func_ItemData, fty_string, 0, NULL__null },
335 { "SETITEMDATA", func_SetItemData, fty_none, 1, param_OneString },
336 { "METATYPE", func_MetaType, fty_string, 0, NULL__null },
337 { "SETMETATYPE", func_SetMetaType, fty_none, 1, param_OneString },
338 { "ISSUEPUT", func_IssuePut, fty_none, 2, param_TwoIntegers },
339 { "ISSUEGET", func_IssueGet, fty_none, 1, param_OneInteger },
340 { "ISSUEALERT", func_IssueAlert, fty_none, 2, param_TwoIntegers }
341};
342
343const TFuncTable GetPutResultFuncTable = {
344 sizeof(GetPutResultFuncDefs) / sizeof(TBuiltInFuncDef), // size of table
345 GetPutResultFuncDefs, // table pointer
346 NULL__null // no chain func
347};
348
349
350
351#endif
352
353
354#ifndef NO_REMOTE_RULES
355
356// Remote Rule Config
357// ==================
358
359#define DONT_REJECT0xFFFF 0xFFFF
360
361// config constructor
362TRemoteRuleConfig::TRemoteRuleConfig(const char *aElementName, TConfigElement *aParentElementP) :
363 TConfigElement(aElementName,aParentElementP)
364{
365 clear();
366} // TRemoteRuleConfig::TRemoteRuleConfig
367
368
369// config destructor
370TRemoteRuleConfig::~TRemoteRuleConfig()
371{
372 if (fOverrideDevInfBufferP)
373 smlFreeProtoElement(fOverrideDevInfBufferP);
374
375 clear();
376} // TRemoteRuleConfig::~TRemoteRuleConfig
377
378
379// init defaults
380void TRemoteRuleConfig::clear(void)
381{
382 // init defaults
383 // - id
384 fManufacturer.erase();
385 fModel.erase();
386 fOem.erase();
387 fFirmwareVers.erase();
388 fSoftwareVers.erase();
389 fHardwareVers.erase();
390 fDevId.erase();
391 fDevTyp.erase();
392 // - options
393 fRejectStatusCode=DONT_REJECT0xFFFF; // not rejected
394 fLegacyMode=-1; // set if remote is known legacy, so don't use new types
395 fLenientMode=-1; // set if remote's SyncML should be handled leniently, i.e. not too strict checking where not absolutely needed
396 fLimitedFieldLengths=-1; // set if remote has limited field lengths
397 fDontSendEmptyProperties=-1; // set if remote does not want empty properties
398 fDoQuote8BitContent=-1; // normally, only use QP for contents with EOLNs in vCard 2.1
399 fDoNotFoldContent=-1; // normally, content must be folded in MIME-DIR
400 fNoReplaceInSlowsync=-1; // normally, we are allowed to use Replace (as server) in slow sync
401 fTreatRemoteTimeAsLocal=-1; // do not ignore time zone
402 fTreatRemoteTimeAsUTC=-1; // do not ignore time zone
403 fVCal10EnddatesSameDay=-1; // use default end date rendering
404 fIgnoreDevInfMaxSize=-1; // do not ignore max field size in remote's devInf
405 fIgnoreCTCap=-1; // do not ignore CTCap
406 fDSPathInDevInf=-1; // use actual DS path as used in Alert for creating datastore devInf (needed for newer Nokia clients)
407 fDSCgiInDevInf=-1; // also show CGI as used in Alert for creating datastore devInf (needed for newer Nokia clients)
408 fForceUTC=-1; // automatic decision based on DevInf (SyncML 1.1) or just UTC for SyncML 1.0
409 fForceLocaltime=-1;
410 fTreatCopyAsAdd=-1;
411 fCompleteFromClientOnly=-1;
412 fRequestMaxTime=-1; // not defined
413 fDefaultOutCharset=chs_unknown; // do not set the default output charset
414 fDefaultInCharset=chs_unknown; // do not set the default input interpretation charset
415 // - options that also have a configurable session default
416 fUpdateClientDuringSlowsync=-1;
417 fUpdateServerDuringSlowsync=-1;
418 fAllowMessageRetries=-1;
419 fStrictExecOrdering=-1;
420 #ifndef MINIMAL_CODE
421 fRemoteDescName.erase();
422 #endif
423 fSubRulesList.clear(); // no included subrules
424 fSubRule = false; // normal rule by default
425 // - rules are final by default
426 fFinalRule = true;
427 // no DevInf by default
428 fOverrideDevInfP = NULL__null;
429 fOverrideDevInfBufferP = NULL__null;
430 // clear inherited
431 inherited::clear();
432} // TRemoteRuleConfig::clear
433
434
435#ifndef HARDCODED_CONFIG
436
437// remote rule config element parsing
438bool TRemoteRuleConfig::localStartElement(const char *aElementName, const char **aAttributes, sInt32 aLine)
439{
440 // checking the elements
441 // - identification of remote (irrelevant for subrules)
442 if (!fSubRule && strucmp(aElementName,"manufacturer")==0)
443 expectString(fManufacturer);
444 else if (!fSubRule && strucmp(aElementName,"model")==0)
445 expectString(fModel);
446 else if (!fSubRule && strucmp(aElementName,"oem")==0)
447 expectString(fOem);
448 else if (!fSubRule && strucmp(aElementName,"firmware")==0)
449 expectString(fFirmwareVers);
450 else if (!fSubRule && strucmp(aElementName,"software")==0)
451 expectString(fSoftwareVers);
452 else if (!fSubRule && strucmp(aElementName,"hardware")==0)
453 expectString(fHardwareVers);
454 else if (!fSubRule && strucmp(aElementName,"deviceid")==0)
455 expectString(fDevId);
456 else if (!fSubRule && strucmp(aElementName,"devicetype")==0)
457 expectString(fDevTyp);
458 // - options
459 else if (strucmp(aElementName,"legacymode")==0)
460 expectTristate(fLegacyMode);
461 else if (strucmp(aElementName,"lenientmode")==0)
462 expectTristate(fLenientMode);
463 else if (strucmp(aElementName,"limitedfieldlengths")==0)
464 expectTristate(fLimitedFieldLengths);
465 else if (strucmp(aElementName,"noemptyproperties")==0)
466 expectTristate(fDontSendEmptyProperties);
467 else if (strucmp(aElementName,"quote8bitcontent")==0)
468 expectTristate(fDoQuote8BitContent);
469 else if (strucmp(aElementName,"nocontentfolding")==0)
470 expectTristate(fDoNotFoldContent);
471 else if (strucmp(aElementName,"noreplaceinslowsync")==0)
472 expectTristate(fNoReplaceInSlowsync);
473 else if (strucmp(aElementName,"treataslocaltime")==0)
474 expectTristate(fTreatRemoteTimeAsLocal);
475 else if (strucmp(aElementName,"treatasutc")==0)
476 expectTristate(fTreatRemoteTimeAsUTC);
477 else if (strucmp(aElementName,"autoenddateinclusive")==0)
478 expectTristate(fVCal10EnddatesSameDay);
479 else if (strucmp(aElementName,"ignoredevinfmaxsize")==0)
480 expectTristate(fIgnoreDevInfMaxSize);
481 else if (strucmp(aElementName,"ignorectcap")==0)
482 expectTristate(fIgnoreCTCap);
483 else if (strucmp(aElementName,"dspathindevinf")==0)
484 expectTristate(fDSPathInDevInf);
485 else if (strucmp(aElementName,"dscgiindevinf")==0)
486 expectTristate(fDSCgiInDevInf);
487 else if (strucmp(aElementName,"updateclientinslowsync")==0)
488 expectTristate(fUpdateClientDuringSlowsync);
489 else if (strucmp(aElementName,"updateserverinslowsync")==0)
490 expectTristate(fUpdateServerDuringSlowsync);
491 else if (strucmp(aElementName,"allowmessageretries")==0)
492 expectTristate(fAllowMessageRetries);
493 else if (strucmp(aElementName,"strictexecordering")==0)
494 expectTristate(fStrictExecOrdering);
495 else if (strucmp(aElementName,"treatcopyasadd")==0)
496 expectTristate(fTreatCopyAsAdd);
497 else if (strucmp(aElementName,"completefromclientonly")==0)
498 expectTristate(fCompleteFromClientOnly);
499 else if (strucmp(aElementName,"requestmaxtime")==0)
500 expectInt32(fRequestMaxTime);
501 else if (strucmp(aElementName,"outputcharset")==0)
502 expectEnum(sizeof(fDefaultOutCharset),&fDefaultOutCharset,MIMECharSetNames,numCharSets);
503 else if (strucmp(aElementName,"inputcharset")==0)
504 expectEnum(sizeof(fDefaultInCharset),&fDefaultInCharset,MIMECharSetNames,numCharSets);
505 else if (strucmp(aElementName,"rejectstatus")==0)
506 expectUInt16(fRejectStatusCode);
507 else if (strucmp(aElementName,"forceutc")==0)
508 expectTristate(fForceUTC);
509 else if (strucmp(aElementName,"forcelocaltime")==0)
510 expectTristate(fForceLocaltime);
511 else if (strucmp(aElementName,"overridedevinf")==0)
512 expectString(fOverrideDevInfXML);
513 // inclusion of subrules
514 else if (strucmp(aElementName,"include")==0) {
515 // <include rule=""/>
516 expectEmpty();
517 const char* nam = getAttr(aAttributes,"rule");
518 if (!nam)
519 return fail("<include> must specify \"rule\"");
520 else {
521 // find rule
522 TRemoteRulesList::iterator pos;
523 TSessionConfig *scfgP = static_cast<TSessionConfig *>(getParentElement());
524 for(pos=scfgP->fRemoteRulesList.begin();pos!=scfgP->fRemoteRulesList.end();pos++) {
525 if (strucmp(nam,(*pos)->getName())==0) {
526 fSubRulesList.push_back(*pos);
527 return true; // done
528 }
529 }
530 return fail("rule '%s' for <include> not found (must be defined before included)",nam);
531 }
532 }
533 // rule script. Note that this is special, as it is NOT resolved in the config, but
534 // copied to the session first, as it might differ between sessions.
535 #ifdef SCRIPT_SUPPORT1
536 else if (strucmp(aElementName,"rulescript")==0)
537 expectScript(fRuleScriptTemplate,aLine,NULL__null,true); // late binding, no declarations allowed
538 #endif
539 #ifndef MINIMAL_CODE
540 else if (strucmp(aElementName,"descriptivename")==0)
541 expectString(fRemoteDescName);
542 #endif
543 // - final rule?
544 else if (strucmp(aElementName,"finalrule")==0)
545 expectBool(fFinalRule);
546 // - not known here
547 else
548 return inherited::localStartElement(aElementName,aAttributes,aLine);
549 // ok
550 return true;
551} // TRemoteRuleConfig::localStartElement
552
553#endif // HARDCODED_CONFIG
554
555#endif // NO_REMOTE_RULES
556
557
558#endif // not SYNCSESSION_PART1_EXCLUDE
559#ifndef SYNCSESSION_PART2_EXCLUDE
560
561
562// Session Config
563// ==============
564
565
566// config constructor
567TSessionConfig::TSessionConfig(const char *aElementName, TConfigElement *aParentElementP) :
568 inherited(aElementName,aParentElementP)
569{
570 clear();
571} // TSessionConfig::TSessionConfig
572
573
574// config destructor
575TSessionConfig::~TSessionConfig()
576{
577 clear();
578} // TSessionConfig::~TSessionConfig
579
580
581// init defaults
582void TSessionConfig::clear(void)
583{
584 // init defaults
585 #ifndef NO_REMOTE_RULES
586 // - no remote rules
587 TRemoteRulesList::iterator pos;
588 for(pos=fRemoteRulesList.begin();pos!=fRemoteRulesList.end();pos++)
589 delete *pos;
590 fRemoteRulesList.clear();
591 #endif
592 // remove datastores
593 TLocalDSList::iterator pos2;
594 for(pos2=fDatastores.begin();pos2!=fDatastores.end();pos2++)
595 delete *pos2;
596 fDatastores.clear();
597 // - no simple auth
598 fSimpleAuthUser.erase();
599 fSimpleAuthPassword.erase();
600 // - medium timeout
601 fSessionTimeout = 60; // one minute, will be overridden by derived classes
602 // - set default maximum SyncML version enabled
603 fMaxSyncMLVersionSupported = MAX_SYNCML_VERSIONsyncml_vers_1_2;
604 // - minimum is 1.0
605 fMinSyncMLVersionSupported=syncml_vers_1_0;
606 // - accept server-alerted codes by default
607 fAcceptServerAlerted = true;
608 // - defaults for remote-rule configurable behaviour
609 fUpdateClientDuringSlowsync = false; // do not update client records during slowsync (but do it for first sync!)
610 fUpdateServerDuringSlowsync = false; // do not update server records during NON-FIRST-TIME slowsync (but do it for first sync!)
611 fAllowMessageRetries = true; // generally allow retries
612 fCompleteFromClientOnly = false; // default to standard-compliant behaviour.
613 fRequestMaxTime = 0; // no limit by default
614 fRequestMinTime = 0; // no minimal request processing delay
615 // - default value for flag to send property lists in CTCap
616 fShowCTCapProps = true;
617 // - default value for flag to send type/size in CTCap for SyncML 1.0 (disable as old clients like S55 crash on this)
618 fShowTypeSzInCTCap10 = false;
619 // - sync mode extensions may be needed for SyncEvolution, but are causing troubles with Nokia phones and some servers so these are off by default
620 fSyncModeExtensions = false;
621 if (IS_CLIENT(!getSyncAppBase()->isServer())) {
622 // - Synthesis clients always behaved like that (sending 23:59:59), so we'll keep it as a default
623 fVCal10EnddatesSameDay = true;
624 }
625 else {
626 // - Many modern clients need the exclusive format (start of next day) to detect all-day events properly.
627 // Synthesis clients detect these fine as well, so not using 23:59:59 style by default is more
628 // compatible in general for a server.
629 fVCal10EnddatesSameDay = false;
630 }
631 // traditionally Synthesis has folded content
632 fDoNotFoldContent = false;
633 // - default value for flag is "default" (depends on SyncML version)
634 fEnumDefaultPropParams=-1;
635 // - decide, whether multi-threading for the datastores will be used:
636 // As there are some problems with older Linux versions (e.g. Debian 3.0r2 stable) the
637 // default values are set for downwards compatibility Linux=false / all others=true
638 // Multithreading can be switched of either by #define or by <fMultiThread> flag
639 #if defined LINUX || !defined MULTI_THREAD_DATASTORE1
640 fMultiThread= false;
641 #else
642 fMultiThread= true;
643 #endif
644 // - do not wait for status of interrupted command by default (note: before 2.1.0.2, this was always true)
645 fWaitForStatusOfInterrupted=false;
646 // - accept delete commands for already deleted items with 200 (rather that 404 or 211)
647 #ifdef SCTS_COMPATIBILITY_HACKS
648 fDeletingGoneOK=false; // SCTS needs that
649 #else
650 fDeletingGoneOK=true; // makes more sense as it avoids unnecessary session aborts
651 #endif
652 // - abort if all items sent to remote fail
653 fAbortOnAllItemsFailed=true; // note: does only apply in slow syncs now!
654 // - default to system time
655 fUserTimeContext=TCTX_SYSTEM((timecontext_t) ((tctx_tz_system) | TCTX_SYMBOLIC_TZ));
656 #ifdef SCRIPT_SUPPORT1
657 // - session init script
658 fSessionInitScript.erase();
659 // - status handling scripts
660 fSentItemStatusScript.erase();
661 fReceivedItemStatusScript.erase();
662 // - session termination script
663 fSessionFinishScript.erase();
664 // - custom get handler
665 fCustomGetHandlerScript.erase();
666 // - custom get and put generators
667 fCustomGetPutScript.erase();
668 fCustomEndPutScript.erase();
669 // - custom PUT and RESULT handler
670 fCustomPutResultHandlerScript.erase();
671 #endif
672 #ifndef MINIMAL_CODE
673 // - logfile
674 fLogFileName.erase();
675 if (IS_SERVER(getSyncAppBase()->isServer())) {
676 fLogFileFormat.assign(DEFAULT_LOG_FORMAT_SERVER"%seT\t%U\t%syV\t%sS\t%tS\t%iS\t%iR\t%nR\t%vR\t%nD\t%laI\t%luI\t%ldI\t%leI\t%raI\t%ruI\t%rdI\t%reI\t%smI\t%scI\t%ccI\t%dcI\t%doB\t%diB\t%toB\t%tiB\n");
677 fLogFileLabels.assign(DEFAULT_LOG_LABELS_SERVER"SyncEndTime\tUser\tSyncMLVers\tStatus\tSynctype\tSessionID\tRemote ID\tRemote Name\tRemote VersInfo\tDatastore\tLocAdded\tLocUpdated\tLocDeleted\tLocErrors\tRemAdded\tRemUpdated\tRemDeleted\tRemErrors\tSlowSyncMatches\tServerWon\tClientWon\tDuplicated\tBytesOut\tBytesIn\tSessionBytesOut\tSessionBytesIn\n\n");
678 }
679 else {
680 fLogFileFormat.assign(DEFAULT_LOG_FORMAT_CLIENT"%seT\t%U\t%syV\t%sS\t%tS\t%iS\t%iR\t%nR\t%vR\t%nD\t%laI\t%luI\t%ldI\t%leI\t%raI\t%ruI\t%rdI\t%reI\t%doB\t%diB\n");
681 fLogFileLabels.assign(DEFAULT_LOG_LABELS_CLIENT"SyncEndTime\tUser\tSyncMLVers\tStatus\tSynctype\tSessionID\tRemote ID\tRemote Name\tRemote VersInfo\tDatastore\tLocAdded\tLocUpdated\tLocDeleted\tLocErrors\tRemAdded\tRemUpdated\tRemDeleted\tRemErrors\tBytesOut\tBytesIn\n\n");
682 }
683 fLogEnabled=true;
684 fDebugChunkMaxSize=0; // disabled
685 #endif
686 fRelyOnEarlyMaps=true; // we rely on early maps sent by clients for adds from the previous session
687 // clear inherited
688 inherited::clear();
689} // TSessionConfig::clear
690
691
692// get local DS config pointer by database name or dbTypeID
693TLocalDSConfig *TSessionConfig::getLocalDS(const char *aName, uInt32 aDBTypeID)
694{
695 TLocalDSList::iterator pos;
696 for(pos=fDatastores.begin();pos!=fDatastores.end();pos++) {
697 if (aName==NULL__null) {
698 if ((*pos)->fLocalDBTypeID==aDBTypeID) return *pos; // found by DBTypeID
699 }
700 else {
701 if (strucmp((*pos)->getName(),aName)==0) return *pos; // found by name
702 }
703 }
704 return NULL__null; // not found
705} // TSessionConfig::getLocalDS
706
707
708#ifndef HARDCODED_CONFIG
709
710// server config element parsing
711bool TSessionConfig::localStartElement(const char *aElementName, const char **aAttributes, sInt32 aLine)
712{
713 // checking the elements
714 #ifndef NO_REMOTE_RULES
715 bool isSubRule = strucmp(aElementName,"subrule")==0;
716 if (strucmp(aElementName,"remoterule")==0 || isSubRule) {
717 // check for optional name attribute
718 const char* nam = getAttr(aAttributes,"name");
719 if (!nam) nam="unnamed";
720 // create rule
721 TRemoteRuleConfig *ruleP = new TRemoteRuleConfig(nam,this);
722 ruleP->fSubRule = isSubRule;
723 fRemoteRulesList.push_back(ruleP);
724 expectChildParsing(*ruleP);
725 }
726 else
727 #endif
728 if (strucmp(aElementName,"sessiontimeout")==0)
729 expectInt32(fSessionTimeout);
730 else if (strucmp(aElementName,"requestmaxtime")==0)
731 expectUInt32(fRequestMaxTime);
732 else if (strucmp(aElementName,"requestmintime")==0)
733 expectInt32(fRequestMinTime);
734 else if (strucmp(aElementName,"simpleauthuser")==0)
735 expectString(fSimpleAuthUser);
736 else if (strucmp(aElementName,"simpleauthpw")==0)
737 expectString(fSimpleAuthPassword);
738 else if (strucmp(aElementName,"maxsyncmlversion")==0)
739 expectEnum(sizeof(fMaxSyncMLVersionSupported),&fMaxSyncMLVersionSupported,SyncMLVersionNames,numSyncMLVersions);
740 else if (strucmp(aElementName,"minsyncmlversion")==0)
741 expectEnum(sizeof(fMinSyncMLVersionSupported),&fMinSyncMLVersionSupported,SyncMLVersionNames,numSyncMLVersions);
742 else if (strucmp(aElementName,"acceptserveralerted")==0)
743 expectBool(fAcceptServerAlerted);
744 else if (strucmp(aElementName,"updateclientinslowsync")==0)
745 expectBool(fUpdateClientDuringSlowsync);
746 else if (strucmp(aElementName,"updateserverinslowsync")==0)
747 expectBool(fUpdateServerDuringSlowsync);
748 else if (strucmp(aElementName,"completefromclientonly")==0)
749 expectBool(fCompleteFromClientOnly);
750 else if (strucmp(aElementName,"allowmessageretries")==0)
751 expectBool(fAllowMessageRetries);
752 else if (strucmp(aElementName,"multithread")==0)
753 expectBool(fMultiThread);
754 else if (strucmp(aElementName,"waitforstatusofinterrupted")==0)
755 expectBool(fWaitForStatusOfInterrupted);
756 else if (strucmp(aElementName,"deletinggoneok")==0)
757 expectBool(fDeletingGoneOK);
758 else if (strucmp(aElementName,"abortonallitemsfailed")==0)
759 expectBool(fAbortOnAllItemsFailed);
760 else if (strucmp(aElementName,"showctcapproperties")==0)
761 expectBool(fShowCTCapProps);
762 else if (strucmp(aElementName,"showtypesizeinctcap10")==0)
763 expectBool(fShowTypeSzInCTCap10);
764 else if (strucmp(aElementName,"syncmodeextensions")==0)
765 expectBool(fSyncModeExtensions);
766 else if (strucmp(aElementName,"autoenddateinclusive")==0)
767 expectBool(fVCal10EnddatesSameDay);
768 else if (strucmp(aElementName,"donotfoldcontent")==0)
769 expectBool(fDoNotFoldContent);
770 else if (strucmp(aElementName,"enumdefaultpropparams")==0)
771 expectTristate(fEnumDefaultPropParams); // Tristate!!!
772 else if (strucmp(aElementName,"usertimezone")==0)
773 expectTimezone(fUserTimeContext);
774 #ifdef SCRIPT_SUPPORT1
775 else if (strucmp(aElementName,"sessioninitscript")==0)
776 expectScript(fSessionInitScript,aLine,NULL__null);
777 else if (strucmp(aElementName,"sentitemstatusscript")==0)
778 expectScript(fSentItemStatusScript,aLine,&ErrorFuncTable);
779 else if (strucmp(aElementName,"receiveditemstatusscript")==0)
780 expectScript(fReceivedItemStatusScript,aLine,&ErrorFuncTable);
781 else if (strucmp(aElementName,"sessionfinishscript")==0)
782 expectScript(fSessionFinishScript,aLine,NULL__null);
783 else if (strucmp(aElementName,"customgethandlerscript")==0)
784 expectScript(fCustomGetHandlerScript,aLine,&GetPutResultFuncTable);
785 else if (strucmp(aElementName,"customgetputscript")==0)
786 expectScript(fCustomGetPutScript,aLine,&GetPutResultFuncTable);
787 else if (strucmp(aElementName,"customendputscript")==0)
788 expectScript(fCustomEndPutScript,aLine,&GetPutResultFuncTable);
789 else if (strucmp(aElementName,"customputresulthandlerscript")==0)
790 expectScript(fCustomPutResultHandlerScript,aLine,&GetPutResultFuncTable);
791 #endif
792 #ifndef MINIMAL_CODE
793 // logfile
794 else if (strucmp(aElementName,"logfile")==0)
795 expectMacroString(fLogFileName);
796 else if (strucmp(aElementName,"logformat")==0)
797 expectCString(fLogFileFormat);
798 else if (strucmp(aElementName,"loglabels")==0)
799 expectCString(fLogFileLabels);
800 else if (strucmp(aElementName,"logenabled")==0)
801 expectBool(fLogEnabled);
802 else if (strucmp(aElementName,"debugchunkmaxsize")==0)
803 expectUInt32(fDebugChunkMaxSize);
804 #endif
805 else if (strucmp(aElementName,"relyonearlymaps")==0)
806 expectBool(fRelyOnEarlyMaps);
807 // - local datastores
808 else if (strucmp(aElementName,"datastore")==0) {
809 // definition of a new datastore
810 const char* nam = getAttr(aAttributes,"name");
811 if (!nam) {
812 ReportError(true,"datastore missing 'name' attribute");
813 }
814 else {
815 // get subtype attribute (some versions can have
816 // different datastore types in same agent)
817 const char* subtype = getAttr(aAttributes,"type");
818 // create new named datastore
819 TLocalDSConfig *datastorecfgP = newDatastoreConfig(nam,subtype,this);
820 if (!datastorecfgP)
821 ReportError(true,"datastore has unknown 'type' attribute");
822 else {
823 // - save in list
824 fDatastores.push_back(datastorecfgP);
825 // - let element handle parsing
826 expectChildParsing(*datastorecfgP);
827 }
828 }
829 }
830 #ifdef SUPERDATASTORES1
831 // - superdatastore
832 else if (strucmp(aElementName,"superdatastore")==0) {
833 // definition of a new datastore
834 const char* nam = getAttr(aAttributes,"name");
835 if (!nam) {
836 ReportError(true,"datastore missing 'name' attribute");
837 }
838 else {
839 // create new named datastore
840 TLocalDSConfig *datastorecfgP = new TSuperDSConfig(nam,this);
841 // - save in list
842 fDatastores.push_back(datastorecfgP);
843 // - let element handle parsing
844 expectChildParsing(*datastorecfgP);
845 }
846 }
847 #endif
848 // - none known here
849 else
850 return inherited::localStartElement(aElementName,aAttributes,aLine);
851 // ok
852 return true;
853} // TSessionConfig::localStartElement
854
855#endif
856
857
858// resolve
859void TSessionConfig::localResolve(bool aLastPass)
860{
861 // resolve
862 if (aLastPass) {
863 #ifndef NO_REMOTE_RULES
864 // - resolve rules and parse OverrideDevInf
865 TRemoteRulesList::iterator pos;
866 for(pos=fRemoteRulesList.begin();pos!=fRemoteRulesList.end();pos++) {
867 (*pos)->Resolve(aLastPass);
868
869 if (!(*pos)->fOverrideDevInfXML.empty()) {
870 // SMLTK expects full SyncML message
871 string buffer =
872 "<SyncML><SyncHdr>"
873 "<VerDTD>1.2</VerDTD>"
874 "<VerProto>SyncML/1.2</VerProto>"
875 "<SessionID>1</SessionID>"
876 "<MsgID>1</MsgID>"
877 "<Target><LocURI>foo</LocURI></Target>"
878 "<Source><LocURI>bar</LocURI></Source>"
879 "</SyncHdr>"
880 "<SyncBody>"
881 "<Results>"
882 "<CmdID>1</CmdID>"
883 "<MsgRef>1</MsgRef>"
884 "<CmdRef>1</CmdRef>"
885 "<Meta>"
886 "<Type>application/vnd.syncml-devinf+xml</Type>"
887 "</Meta>"
888 "<Item>"
889 "<Source>"
890 "<LocURI>./devinf12</LocURI>"
891 "</Source>"
892 "<Data>"
893 ;
894 buffer += (*pos)->fOverrideDevInfXML;
895 buffer +=
896 "</Data>"
897 "</Item>"
898 "</Results>"
899 "</SyncBody>"
900 "</SyncML>";
901 MemPtr_t xml = (unsigned char *)buffer.c_str();
902 XltDecoderPtr_t decoder = NULL__null;
903 SmlSyncHdrPtr_t hdr = NULL__null;
904 Ret_t ret = xltDecInit(SML_XML,
905 xml + buffer.size(),
906 &xml,
907 &decoder,
908 &hdr);
909 if (ret != SML_ERR_OK0x00) {
910 fRootElementP->setError(true, "initializing scanner for DevInf failed");
911 } else {
912 smlFreeProtoElement(hdr);
913 SmlProtoElement_t element;
914 VoidPtr_t content = NULL__null;
915 ret = xltDecNext(decoder,
916 xml + buffer.size(),
917 &xml,
918 &element,
919 &content);
920 if (ret != SML_ERR_OK0x00) {
921 fRootElementP->setError(true, "parsing of OverrideDevInf failed");
922 } else if (element != SML_PE_RESULTS ||
923 !((SmlResultsPtr_t)content)->itemList ||
924 !((SmlResultsPtr_t)content)->itemList->item ||
925 !((SmlResultsPtr_t)content)->itemList->item->data ||
926 ((SmlResultsPtr_t)content)->itemList->item->data->contentType != SML_PCDATA_EXTENSION ||
927 ((SmlResultsPtr_t)content)->itemList->item->data->extension != SML_EXT_DEVINF) {
928 fRootElementP->setError(true, "parsing of DevInf returned unexpected result");
929 if (content)
930 smlFreeProtoElement(content);
931 } else {
932 (*pos)->fOverrideDevInfP = (SmlDevInfDevInfPtr_t)((SmlResultsPtr_t)content)->itemList->item->data->content;
933 (*pos)->fOverrideDevInfBufferP = content;
934 }
935 }
936 if (decoder)
937 xltDecTerminate(decoder);
938 }
939 }
940 #endif
941 TLocalDSList::iterator pos2;
942 for(pos2=fDatastores.begin();pos2!=fDatastores.end();pos2++)
943 (*pos2)->Resolve(aLastPass);
944 #ifdef SCRIPT_SUPPORT1
945 TScriptContext *sccP = NULL__null;
946 SYSYNC_TRYtry {
947 // resolve all scripts in same context
948 // - init scripts
949 TScriptContext::resolveScript(getSyncAppBase(),fSessionInitScript,sccP,NULL__null);
950 TScriptContext::resolveScript(getSyncAppBase(),fSentItemStatusScript,sccP,NULL__null);
951 TScriptContext::resolveScript(getSyncAppBase(),fReceivedItemStatusScript,sccP,NULL__null);
952 TScriptContext::resolveScript(getSyncAppBase(),fSessionFinishScript,sccP,NULL__null);
953 TScriptContext::resolveScript(getSyncAppBase(),fCustomGetHandlerScript,sccP,NULL__null);
954 TScriptContext::resolveScript(getSyncAppBase(),fCustomGetPutScript,sccP,NULL__null);
955 TScriptContext::resolveScript(getSyncAppBase(),fCustomEndPutScript,sccP,NULL__null);
956 TScriptContext::resolveScript(getSyncAppBase(),fCustomPutResultHandlerScript,sccP,NULL__null);
957 // - forget this context
958 if (sccP) delete sccP;
959 }
960 SYSYNC_CATCH (...)catch(...) {
961 if (sccP) delete sccP;
962 SYSYNC_RETHROWthrow;
963 SYSYNC_ENDCATCH}
964 #endif
965 }
966 // resolve inherited
967 inherited::localResolve(aLastPass);
968} // TSessionConfig::localResolve
969
970
971
972
973// TSyncSession
974// ============
975
976// constructor
977TSyncSession::TSyncSession(
978 TSyncAppBase *aSyncAppBaseP, // the owning application base (dispatcher/client base)
979 const char *aSessionID // a session ID
980) :
981 #ifdef SYDEBUG2
982 fSessionDebugLogs(0),
983 #endif
984 fTerminated(false),
985 #ifdef SYDEBUG2
986 fSessionLogger(&fSessionZones),
987 #endif
988 fSyncAppBaseP(aSyncAppBaseP) // link to owning base (dispatcher/clienbase)
989{
990 // Inherit globally defined time zones
991 // Note: this must be done as very first step as all time output routines will use the
992 // session zones
993 fSessionZones = *(fSyncAppBaseP->getAppZones());
994 // now mark used to avoid early timeout (will be marked again at InternalResetSession())
995 SessionUsed();
996 fLastRequestStarted=getSessionLastUsed(); // set this in case we terminate before StartMessage()
997 fSessionStarted=fLastRequestStarted; // this is also the start of the session
998 // show creation
999 DEBUGPRINTFX(DBG_OBJINST,("++++++++ TSyncSession created")){ if (((0x00020000) & getDbgMask()) == (0x00020000)) getDbgLogger
()->setNextMask(0x00020000).DebugPrintfLastMask ("++++++++ TSyncSession created"
); }
;
1000 // assign session ID to have debug ID on correct channel
1001 fLocalSessionID.assign(aSessionID);
1002 DEBUGPRINTFX(DBG_EXOTIC,("TSyncSession::TSyncSession: Session ID assigned")){ if (((0x80000000) & getDbgMask()) == (0x80000000)) getDbgLogger
()->setNextMask(0x80000000).DebugPrintfLastMask ("TSyncSession::TSyncSession: Session ID assigned"
); }
;
1003 // init and start profiling
1004 MP_SHOWCURRENT(DBG_PROFILE,"TSyncSession::TSyncSession: TSyncSession created");
1005 TP_INIT(fTPInfo);
1006 TP_START(fTPInfo,TP_general);
1007 DEBUGPRINTFX(DBG_EXOTIC,("TSyncSession::TSyncSession: Profiling initialized")){ if (((0x80000000) & getDbgMask()) == (0x80000000)) getDbgLogger
()->setNextMask(0x80000000).DebugPrintfLastMask ("TSyncSession::TSyncSession: Profiling initialized"
); }
;
1008 // set fields
1009 fEncoding = SML_UNDEF;
1010 fLocalAbortReason = true; // unless set otherwise
1011 fAbortReasonStatus = 0;
1012 fSessionIsBusy = false; // not busy by default
1013 fSmlWorkspaceID = 0; // no SyncML toolkit workspace ID yet
1014 fMaxRoomForData = getRootConfig()->fLocalMaxMsgSize; // rough init
1015 // other pointers
1016 #ifdef SCRIPT_SUPPORT1
1017 fSessionScriptContextP = NULL__null;
1018 #endif
1019 fInterruptedCommandP = NULL__null;
1020 fIncompleteDataCommandP = NULL__null;
1021 #ifdef SYNCSTATUS_AT_SYNC_CLOSE
1022 fSyncCloseStatusCommandP=NULL__null;
1023 #endif
1024 fCmdIncoming=NULL__null;
1025 // we do not know anything about remote datastores yet
1026 fRemoteDevInfKnown=false;
1027 fRemoteDataStoresKnown=false;
1028 fRemoteDataTypesKnown=false;
1029 fRemoteDevInfLock=false;
1030 // we have not sent any devinf to the remote yet
1031 fRemoteGotDevinf=false;
1032 fRemoteMustSeeDevinf=false;
1033 fCustomGetPutSent=false;
1034 // assume normal, full-featured session. Profile config or session progress might set this flag later
1035 fLegacyMode = false;
1036 fLenientMode = false;
1037
1038 //initialize the conditonal variables to keep valgrind happy
1039 fNeedAuth = true;
1040 fRemoteRequestedAuth = auth_none;
1041
1042 #ifdef SYDEBUG2
1043 // initialize session debug logging
1044 fSessionDebugLogs=getRootConfig()->fDebugConfig.fSessionDebugLogs; /// init from config @todo: get rid of this special session level flag, handle it all via session logger's fDebugEnabled / getDbgMask()
1045 fSessionLogger.setEnabled(fSessionDebugLogs); // init from session-level flag @todo: get rid of this special session level flag, handle it all via session logger's fDebugEnabled / getDbgMask()
1046 fSessionLogger.setMask(getRootConfig()->fDebugConfig.fDebug); // init from config
1047 fSessionLogger.setOptions(&(getRootConfig()->fDebugConfig.fSessionDbgLoggerOptions));
1048 if (getRootConfig()->fDebugConfig.fLogSessionsToGlobal) {
1049 // pass session output to app global logger
1050 fSessionLogger.outputVia(getSyncAppBase()->getDbgLogger());
1051 // show start of log
1052 PDEBUGPRINTFX(DBG_HOT,("--------- START of embedded log for session ID '%s' ---------", fLocalSessionID.c_str())){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("--------- START of embedded log for session ID '%s' ---------"
, fLocalSessionID.c_str()); }
;
1053 }
1054 else {
1055 // use separate output for session logs
1056 fSessionLogger.installOutput(getSyncAppBase()->newDbgOutputter(false)); // install the output object (and pass ownership!)
1057 fSessionLogger.setDebugPath(getRootConfig()->fDebugConfig.fDebugInfoPath.c_str()); // base path
1058 const string &name = getRootConfig()->fDebugConfig.fSessionDbgLoggerOptions.fBasename;
1059 fSessionLogger.appendToDebugPath(name.empty() ?
1060 TARGETID"sysynclib_uni_linux" :
1061 name.c_str());
1062 if (getRootConfig()->fDebugConfig.fSingleSessionLog) {
1063 getRootConfig()->fDebugConfig.fSessionDbgLoggerOptions.fAppend=true; // One single log - in this case, we MUST append to current log
1064 fSessionLogger.appendToDebugPath("_session"); // only single session log, always with the same name
1065 }
1066 else {
1067 if (getRootConfig()->fDebugConfig.fTimedSessionLogNames) {
1068 fSessionLogger.appendToDebugPath("_");
1069 string t;
1070 TimestampToISO8601Str(t, getSystemNowAs(TCTX_UTC((timecontext_t) ((tctx_tz_UTC) | TCTX_SYMBOLIC_TZ))), TCTX_UTC((timecontext_t) ((tctx_tz_UTC) | TCTX_SYMBOLIC_TZ)), false, false);
1071 fSessionLogger.appendToDebugPath(t.c_str());
1072 }
1073 fSessionLogger.appendToDebugPath("_s");
1074 fSessionLogger.appendToDebugPath(fLocalSessionID.c_str());
1075 }
1076 }
1077 fSessionLogger.DebugDefineMainThread();
1078 // initialize session level dump flags
1079 fDumpCount=0;
1080 fIgnoreIncomingCommands=false;
1081 fOutgoingXMLInstance=NULL__null;
1082 fIncomingXMLInstance=NULL__null;
1083 fXMLtranslate=getRootConfig()->fDebugConfig.fXMLtranslate; // initialize from config
1084 fMsgDump=getRootConfig()->fDebugConfig.fMsgDump; // initialize from config
1085 #endif
1086
1087 // reset session at creation
1088 DEBUGPRINTFX(DBG_EXOTIC,("TSyncSession::TSyncSession: calling InternalResetSession")){ if (((0x80000000) & getDbgMask()) == (0x80000000)) getDbgLogger
()->setNextMask(0x80000000).DebugPrintfLastMask ("TSyncSession::TSyncSession: calling InternalResetSession"
); }
;
1089 InternalResetSessionEx(false);
1090 DEBUGPRINTFX(DBG_EXOTIC,("TSyncSession::TSyncSession: InternalResetSession called")){ if (((0x80000000) & getDbgMask()) == (0x80000000)) getDbgLogger
()->setNextMask(0x80000000).DebugPrintfLastMask ("TSyncSession::TSyncSession: InternalResetSession called"
); }
;
1091 // show starting
1092 #ifndef ENGINE_LIBRARY1
1093 // - don't show it here in library case as Agent must be ready as well to distribute event correctly
1094 SESSION_PROGRESS_EVENT(this,pev_sessionstart,NULL,0,0,0)this->NotifySessionProgressEvent(pev_sessionstart,__null,0
,0,0)
;
1095 #endif
1096 #ifdef SYDEBUG2
1097 #if defined(SYSYNC_SERVER1) && defined(SYSYNC_CLIENT1)
1098 #define CAN_BE_TEXT"Server+Client" "Server+Client"
1099 #elif defined(SYSYNC_SERVER1)
1100 #define CAN_BE_TEXT"Server+Client" "Server"
1101 #else
1102 #define CAN_BE_TEXT"Server+Client" "Client"
1103 #endif
1104 if (PDEBUGTEST(DBG_HOT)(((0x00000001) & getDbgMask()) == (0x00000001))) {
1105 // Show Session Start
1106 PDEBUGPRINTFX(DBG_HOT,({ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "==== %s Session started with SyncML (%s) Engine Version %d.%d.%d.%d"
, (getSyncAppBase()->isServer()) ? "Server" : "Client", "Server+Client"
, 3, 4, 0, 47 ); }
1107 "==== %s Session started with SyncML (%s) Engine Version %d.%d.%d.%d",{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "==== %s Session started with SyncML (%s) Engine Version %d.%d.%d.%d"
, (getSyncAppBase()->isServer()) ? "Server" : "Client", "Server+Client"
, 3, 4, 0, 47 ); }
1108 IS_SERVER ? "Server" : "Client",{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "==== %s Session started with SyncML (%s) Engine Version %d.%d.%d.%d"
, (getSyncAppBase()->isServer()) ? "Server" : "Client", "Server+Client"
, 3, 4, 0, 47 ); }
1109 CAN_BE_TEXT,{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "==== %s Session started with SyncML (%s) Engine Version %d.%d.%d.%d"
, (getSyncAppBase()->isServer()) ? "Server" : "Client", "Server+Client"
, 3, 4, 0, 47 ); }
1110 SYSYNC_VERSION_MAJOR,{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "==== %s Session started with SyncML (%s) Engine Version %d.%d.%d.%d"
, (getSyncAppBase()->isServer()) ? "Server" : "Client", "Server+Client"
, 3, 4, 0, 47 ); }
1111 SYSYNC_VERSION_MINOR,{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "==== %s Session started with SyncML (%s) Engine Version %d.%d.%d.%d"
, (getSyncAppBase()->isServer()) ? "Server" : "Client", "Server+Client"
, 3, 4, 0, 47 ); }
1112 SYSYNC_SUBVERSION,{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "==== %s Session started with SyncML (%s) Engine Version %d.%d.%d.%d"
, (getSyncAppBase()->isServer()) ? "Server" : "Client", "Server+Client"
, 3, 4, 0, 47 ); }
1113 SYSYNC_BUILDNUMBER{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "==== %s Session started with SyncML (%s) Engine Version %d.%d.%d.%d"
, (getSyncAppBase()->isServer()) ? "Server" : "Client", "Server+Client"
, 3, 4, 0, 47 ); }
1114 )){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "==== %s Session started with SyncML (%s) Engine Version %d.%d.%d.%d"
, (getSyncAppBase()->isServer()) ? "Server" : "Client", "Server+Client"
, 3, 4, 0, 47 ); }
;
1115 // show Product ID string
1116 PDEBUGPRINTFX(DBG_HOT,({ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "---- Hardcoded Product name: "
"SySync SyncML Library OpenSource Linux" ); }
1117 "---- Hardcoded Product name: " CUST_SYNC_MODEL{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "---- Hardcoded Product name: "
"SySync SyncML Library OpenSource Linux" ); }
1118 )){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "---- Hardcoded Product name: "
"SySync SyncML Library OpenSource Linux" ); }
;
1119 PDEBUGPRINTFX(DBG_HOT,({ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "---- Configured Model/Manufacturer: %s / %s"
, getSyncAppBase()->getModel().c_str(), getSyncAppBase()->
getManufacturer().c_str() ); }
1120 "---- Configured Model/Manufacturer: %s / %s",{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "---- Configured Model/Manufacturer: %s / %s"
, getSyncAppBase()->getModel().c_str(), getSyncAppBase()->
getManufacturer().c_str() ); }
1121 getSyncAppBase()->getModel().c_str(), getSyncAppBase()->getManufacturer().c_str(){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "---- Configured Model/Manufacturer: %s / %s"
, getSyncAppBase()->getModel().c_str(), getSyncAppBase()->
getManufacturer().c_str() ); }
1122 )){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "---- Configured Model/Manufacturer: %s / %s"
, getSyncAppBase()->getModel().c_str(), getSyncAppBase()->
getManufacturer().c_str() ); }
;
1123 // show platform we're on
1124 string devid;
1125 getSyncAppBase()->getMyDeviceID(devid);
1126 PDEBUGPRINTFX(DBG_HOT,({ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "---- Running on "
"Linux" ", URI/deviceID='%s'", devid.c_str() ); }
1127 "---- Running on " SYSYNC_PLATFORM_NAME ", URI/deviceID='%s'",{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "---- Running on "
"Linux" ", URI/deviceID='%s'", devid.c_str() ); }
1128 devid.c_str(){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "---- Running on "
"Linux" ", URI/deviceID='%s'", devid.c_str() ); }
1129 )){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "---- Running on "
"Linux" ", URI/deviceID='%s'", devid.c_str() ); }
;
1130 // show process and thread ID of the main session thread
1131 #ifdef MULTI_THREAD_SUPPORT1
1132 PDEBUGPRINTFX(DBG_HOT,({ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "---- Process ID = %lu, Thread ID = %lu"
, myProcessID(), myThreadID() ); }
1133 "---- Process ID = %lu, Thread ID = %lu",{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "---- Process ID = %lu, Thread ID = %lu"
, myProcessID(), myThreadID() ); }
1134 myProcessID(),{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "---- Process ID = %lu, Thread ID = %lu"
, myProcessID(), myThreadID() ); }
1135 myThreadID(){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "---- Process ID = %lu, Thread ID = %lu"
, myProcessID(), myThreadID() ); }
1136 )){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "---- Process ID = %lu, Thread ID = %lu"
, myProcessID(), myThreadID() ); }
;
1137 #endif
1138 // show platform details
1139 string dname,vers;
1140 // - as determined by engine itself
1141 getPlatformString(pfs_device_name,dname);
1142 getPlatformString(pfs_platformvers,vers);
1143 PDEBUGPRINTFX(DBG_HOT,({ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "---- Platform Hardware Name/Version = '%s', Firmware/OS Version = '%s'"
, dname.c_str(), vers.c_str() ); }
1144 "---- Platform Hardware Name/Version = '%s', Firmware/OS Version = '%s'",{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "---- Platform Hardware Name/Version = '%s', Firmware/OS Version = '%s'"
, dname.c_str(), vers.c_str() ); }
1145 dname.c_str(),{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "---- Platform Hardware Name/Version = '%s', Firmware/OS Version = '%s'"
, dname.c_str(), vers.c_str() ); }
1146 vers.c_str(){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "---- Platform Hardware Name/Version = '%s', Firmware/OS Version = '%s'"
, dname.c_str(), vers.c_str() ); }
1147 )){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "---- Platform Hardware Name/Version = '%s', Firmware/OS Version = '%s'"
, dname.c_str(), vers.c_str() ); }
;
1148 // - as configured
1149 PDEBUGPRINTFX(DBG_HOT,({ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "---- Configured Hardware Version = '%s', Firmware Version = '%s'"
, getSyncAppBase()->getHardwareVersion().c_str(), getSyncAppBase
()->getFirmwareVersion().c_str() ); }
1150 "---- Configured Hardware Version = '%s', Firmware Version = '%s'",{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "---- Configured Hardware Version = '%s', Firmware Version = '%s'"
, getSyncAppBase()->getHardwareVersion().c_str(), getSyncAppBase
()->getFirmwareVersion().c_str() ); }
1151 getSyncAppBase()->getHardwareVersion().c_str(),{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "---- Configured Hardware Version = '%s', Firmware Version = '%s'"
, getSyncAppBase()->getHardwareVersion().c_str(), getSyncAppBase
()->getFirmwareVersion().c_str() ); }
1152 getSyncAppBase()->getFirmwareVersion().c_str(){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "---- Configured Hardware Version = '%s', Firmware Version = '%s'"
, getSyncAppBase()->getHardwareVersion().c_str(), getSyncAppBase
()->getFirmwareVersion().c_str() ); }
1153 )){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "---- Configured Hardware Version = '%s', Firmware Version = '%s'"
, getSyncAppBase()->getHardwareVersion().c_str(), getSyncAppBase
()->getFirmwareVersion().c_str() ); }
;
1154 // show time zone infos
1155 lineartime_t tim;
1156 string z,ts;
1157 timecontext_t tctx;
1158 sInt16 offs;
1159 // - System local time and zone
1160 tctx = getRootConfig()->fSystemTimeContext;
1161 TzResolveMetaContext(tctx, getSessionZones()); // make non-meta
1162 TimeZoneContextToName(tctx, z, getSessionZones());
1163 tim = getSystemNowAs(tctx);
1164 StringObjTimestamp(ts,tim);
1165 TzResolveToOffset(tctx, offs, tim, false, getSessionZones());
1166 PDEBUGPRINTFX(DBG_HOT,({ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "---- System local time : %s (time zone '%s', offset %hd:%02hd hours east of UTC)"
, ts.c_str(),z.c_str(), (sInt16)(offs / MinsPerHour), (sInt16
)abs(offs % MinsPerHour) ); }
1167 "---- System local time : %s (time zone '%s', offset %hd:%02hd hours east of UTC)",{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "---- System local time : %s (time zone '%s', offset %hd:%02hd hours east of UTC)"
, ts.c_str(),z.c_str(), (sInt16)(offs / MinsPerHour), (sInt16
)abs(offs % MinsPerHour) ); }
1168 ts.c_str(),z.c_str(),{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "---- System local time : %s (time zone '%s', offset %hd:%02hd hours east of UTC)"
, ts.c_str(),z.c_str(), (sInt16)(offs / MinsPerHour), (sInt16
)abs(offs % MinsPerHour) ); }
1169 (sInt16)(offs / MinsPerHour),{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "---- System local time : %s (time zone '%s', offset %hd:%02hd hours east of UTC)"
, ts.c_str(),z.c_str(), (sInt16)(offs / MinsPerHour), (sInt16
)abs(offs % MinsPerHour) ); }
1170 (sInt16)abs(offs % MinsPerHour){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "---- System local time : %s (time zone '%s', offset %hd:%02hd hours east of UTC)"
, ts.c_str(),z.c_str(), (sInt16)(offs / MinsPerHour), (sInt16
)abs(offs % MinsPerHour) ); }
1171 )){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "---- System local time : %s (time zone '%s', offset %hd:%02hd hours east of UTC)"
, ts.c_str(),z.c_str(), (sInt16)(offs / MinsPerHour), (sInt16
)abs(offs % MinsPerHour) ); }
;
1172 PDEBUGPRINTFX(DBG_EXOTIC,(" Offset in Minutes east of UTC: %hd",offs)){ if (((0x80000000) & getDbgMask()) == (0x80000000)) getDbgLogger
()->setNextMask(0x80000000).DebugPrintfLastMask (" Offset in Minutes east of UTC: %hd"
,offs); }
;
1173 // - System time in UTC
1174 tim = getSystemNowAs(TCTX_UTC((timecontext_t) ((tctx_tz_UTC) | TCTX_SYMBOLIC_TZ)));
1175 StringObjTimestamp(ts,tim);
1176 PDEBUGPRINTFX(DBG_HOT,("---- System time in UTC : %s",ts.c_str())){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("---- System time in UTC : %s"
,ts.c_str()); }
;
1177 // - make a winter and a summer test
1178 if (PDEBUGTEST(DBG_EXOTIC)(((0x80000000) & getDbgMask()) == (0x80000000))) {
1179 sInt16 y,m,d;
1180 lineartime2date(tim,&y,&m,&d);
1181 d=1;m=2; // February 1st
1182 tim=date2lineartime(y,m,d);
1183 TzResolveToOffset(TCTX_SYSTEM((timecontext_t) ((tctx_tz_system) | TCTX_SYMBOLIC_TZ)), offs, tim, true, getSessionZones());
1184 PDEBUGPRINTFX(DBG_EXOTIC,({ if (((0x80000000) & getDbgMask()) == (0x80000000)) getDbgLogger
()->setNextMask(0x80000000).DebugPrintfLastMask ( "---- System time zone offset per %04hd-02-01 = %hd:%02hd (=%hd mins)"
, y, (sInt16)(offs / MinsPerHour), (sInt16)abs(offs % MinsPerHour
), offs ); }
1185 "---- System time zone offset per %04hd-02-01 = %hd:%02hd (=%hd mins)",{ if (((0x80000000) & getDbgMask()) == (0x80000000)) getDbgLogger
()->setNextMask(0x80000000).DebugPrintfLastMask ( "---- System time zone offset per %04hd-02-01 = %hd:%02hd (=%hd mins)"
, y, (sInt16)(offs / MinsPerHour), (sInt16)abs(offs % MinsPerHour
), offs ); }
1186 y, (sInt16)(offs / MinsPerHour), (sInt16)abs(offs % MinsPerHour), offs{ if (((0x80000000) & getDbgMask()) == (0x80000000)) getDbgLogger
()->setNextMask(0x80000000).DebugPrintfLastMask ( "---- System time zone offset per %04hd-02-01 = %hd:%02hd (=%hd mins)"
, y, (sInt16)(offs / MinsPerHour), (sInt16)abs(offs % MinsPerHour
), offs ); }
1187 )){ if (((0x80000000) & getDbgMask()) == (0x80000000)) getDbgLogger
()->setNextMask(0x80000000).DebugPrintfLastMask ( "---- System time zone offset per %04hd-02-01 = %hd:%02hd (=%hd mins)"
, y, (sInt16)(offs / MinsPerHour), (sInt16)abs(offs % MinsPerHour
), offs ); }
;
1188 d=1;m=8; // August 1st
1189 tim=date2lineartime(y,m,d);
1190 TzResolveToOffset(TCTX_SYSTEM((timecontext_t) ((tctx_tz_system) | TCTX_SYMBOLIC_TZ)), offs, tim, true, getSessionZones());
1191 PDEBUGPRINTFX(DBG_EXOTIC,({ if (((0x80000000) & getDbgMask()) == (0x80000000)) getDbgLogger
()->setNextMask(0x80000000).DebugPrintfLastMask ( "---- System time zone offset per %04hd-08-01 = %hd:%02hd (=%hd mins)"
, y, (sInt16)(offs / MinsPerHour), (sInt16)abs(offs % MinsPerHour
), offs ); }
1192 "---- System time zone offset per %04hd-08-01 = %hd:%02hd (=%hd mins)",{ if (((0x80000000) & getDbgMask()) == (0x80000000)) getDbgLogger
()->setNextMask(0x80000000).DebugPrintfLastMask ( "---- System time zone offset per %04hd-08-01 = %hd:%02hd (=%hd mins)"
, y, (sInt16)(offs / MinsPerHour), (sInt16)abs(offs % MinsPerHour
), offs ); }
1193 y, (sInt16)(offs / MinsPerHour), (sInt16)abs(offs % MinsPerHour), offs{ if (((0x80000000) & getDbgMask()) == (0x80000000)) getDbgLogger
()->setNextMask(0x80000000).DebugPrintfLastMask ( "---- System time zone offset per %04hd-08-01 = %hd:%02hd (=%hd mins)"
, y, (sInt16)(offs / MinsPerHour), (sInt16)abs(offs % MinsPerHour
), offs ); }
1194 )){ if (((0x80000000) & getDbgMask()) == (0x80000000)) getDbgLogger
()->setNextMask(0x80000000).DebugPrintfLastMask ( "---- System time zone offset per %04hd-08-01 = %hd:%02hd (=%hd mins)"
, y, (sInt16)(offs / MinsPerHour), (sInt16)abs(offs % MinsPerHour
), offs ); }
;
1195 }
1196 }
1197 #endif
1198 DebugShowCfgInfo();
1199} // TSyncSession::TSyncSession
1200
1201
1202// destructor
1203TSyncSession::~TSyncSession()
1204{
1205 // remove user data pointer because session does not exist any longer
1206 getSyncAppBase()->setSmlInstanceUserData(fSmlWorkspaceID,NULL__null);
1207 // make sure it is terminated (but normally it is already terminated here)
1208 TerminateSession();
1209 // debug
1210 DEBUGPRINTFX(DBG_OBJINST,("-------- TSyncSession almost destroyed (except implicit member destruction)")){ if (((0x00020000) & getDbgMask()) == (0x00020000)) getDbgLogger
()->setNextMask(0x00020000).DebugPrintfLastMask ("-------- TSyncSession almost destroyed (except implicit member destruction)"
); }
;
1211 #ifdef SYDEBUG2
1212 if (getRootConfig()->fDebugConfig.fLogSessionsToGlobal) {
1213 // show end of embedded log
1214 PDEBUGPRINTFX(DBG_HOT,("--------- END of embedded log for session ID '%s' ---------", fLocalSessionID.c_str())){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("--------- END of embedded log for session ID '%s' ---------"
, fLocalSessionID.c_str()); }
;
1215 }
1216 fSessionLogger.DebugThreadOutputDone();
1217 #endif
1218} // TSyncSession::~TSyncSession
1219
1220
1221/// @brief terminate a session.
1222/// @Note: Termination is final - session cannot be restarted by RestartSession() after
1223// calling this routine
1224void TSyncSession::TerminateSession(void)
1225{
1226 if (!fTerminated) {
1227 // save type of ending (before fAborted gets reset in InternalResetSession())
1228 bool normalend = !fAborted;
1229 bool allsuccess = isAllSuccess();
1230 // do this class' reset stuff
1231 DEBUGPRINTFX(DBG_EXOTIC,("TSyncSession::TerminateSession: calling InternalResetSession")){ if (((0x80000000) & getDbgMask()) == (0x80000000)) getDbgLogger
()->setNextMask(0x80000000).DebugPrintfLastMask ("TSyncSession::TerminateSession: calling InternalResetSession"
); }
;
1232 InternalResetSessionEx(true);
1233 DEBUGPRINTFX(DBG_EXOTIC,("TSyncSession::TerminateSession: InternalResetSession called")){ if (((0x80000000) & getDbgMask()) == (0x80000000)) getDbgLogger
()->setNextMask(0x80000000).DebugPrintfLastMask ("TSyncSession::TerminateSession: InternalResetSession called"
); }
;
1234 #ifdef SCRIPT_SUPPORT1
1235 // remove the session script context
1236 if (fSessionScriptContextP) {
1237 delete fSessionScriptContextP;
1238 fSessionScriptContextP = NULL__null;
1239 }
1240 #endif
1241 // remove all local datastores
1242 TLocalDataStorePContainer::iterator pos1;
1243 int n=fLocalDataStores.size();
1244 PDEBUGPRINTFX(DBG_EXOTIC,("Deleting %d datastores",n)){ if (((0x80000000) & getDbgMask()) == (0x80000000)) getDbgLogger
()->setNextMask(0x80000000).DebugPrintfLastMask ("Deleting %d datastores"
,n); }
;
1245 for (pos1=fLocalDataStores.begin(); pos1!=fLocalDataStores.end(); ++pos1) {
1246 delete *pos1;
1247 }
1248 fLocalDataStores.clear(); // clear list
1249 // remove all local itemtypes
1250 TSyncItemTypePContainer::iterator pos2;
1251 for (pos2=fLocalItemTypes.begin(); pos2!=fLocalItemTypes.end(); ++pos2) {
1252 delete *pos2;
1253 }
1254 fLocalItemTypes.clear(); // clear list
1255 #ifdef SYDEBUG2
1256 // save half-begun XML translations
1257 XMLTranslationOutgoingEnd();
1258 XMLTranslationIncomingEnd();
1259 #endif
1260 // stop and show profiling info
1261 TP_STOP(fTPInfo);
1262 #ifdef TIME_PROFILING
1263 if (getDbgMask() & DBG_PROFILE0x00040000) {
1264 sInt16 i;
1265 uInt32 sy,us;
1266 PDEBUGPRINTFX(DBG_PROFILE,("Session CPU usage statistics: (system/user/total)")){ if (((0x00040000) & getDbgMask()) == (0x00040000)) getDbgLogger
()->setNextMask(0x00040000).DebugPrintfLastMask ("Session CPU usage statistics: (system/user/total)"
); }
;
1267 // sections
1268 for (i=0; i<numTPTypes; i++) {
1269 sy = TP_GETSYSTEMMS(fTPInfo,(TTP_Types)i)0;
1270 us = TP_GETUSERMS(fTPInfo,(TTP_Types)i)0;
1271 PDEBUGPRINTFX(DBG_PROFILE,({ if (((0x00040000) & getDbgMask()) == (0x00040000)) getDbgLogger
()->setNextMask(0x00040000).DebugPrintfLastMask ( "- %-20s : %10ld /%10ld /%10ld ms"
, TP_TypeNames[i], sy, us, sy+us ); }
1272 "- %-20s : %10ld /%10ld /%10ld ms",{ if (((0x00040000) & getDbgMask()) == (0x00040000)) getDbgLogger
()->setNextMask(0x00040000).DebugPrintfLastMask ( "- %-20s : %10ld /%10ld /%10ld ms"
, TP_TypeNames[i], sy, us, sy+us ); }
1273 TP_TypeNames[i],{ if (((0x00040000) & getDbgMask()) == (0x00040000)) getDbgLogger
()->setNextMask(0x00040000).DebugPrintfLastMask ( "- %-20s : %10ld /%10ld /%10ld ms"
, TP_TypeNames[i], sy, us, sy+us ); }
1274 sy,{ if (((0x00040000) & getDbgMask()) == (0x00040000)) getDbgLogger
()->setNextMask(0x00040000).DebugPrintfLastMask ( "- %-20s : %10ld /%10ld /%10ld ms"
, TP_TypeNames[i], sy, us, sy+us ); }
1275 us,{ if (((0x00040000) & getDbgMask()) == (0x00040000)) getDbgLogger
()->setNextMask(0x00040000).DebugPrintfLastMask ( "- %-20s : %10ld /%10ld /%10ld ms"
, TP_TypeNames[i], sy, us, sy+us ); }
1276 sy+us{ if (((0x00040000) & getDbgMask()) == (0x00040000)) getDbgLogger
()->setNextMask(0x00040000).DebugPrintfLastMask ( "- %-20s : %10ld /%10ld /%10ld ms"
, TP_TypeNames[i], sy, us, sy+us ); }
1277 )){ if (((0x00040000) & getDbgMask()) == (0x00040000)) getDbgLogger
()->setNextMask(0x00040000).DebugPrintfLastMask ( "- %-20s : %10ld /%10ld /%10ld ms"
, TP_TypeNames[i], sy, us, sy+us ); }
;
1278 }
1279 // total
1280 sy = TP_GETTOTALSYSTEMMS(fTPInfo)0;
1281 us = TP_GETTOTALUSERMS(fTPInfo)0;
1282 PDEBUGPRINTFX(DBG_PROFILE,({ if (((0x00040000) & getDbgMask()) == (0x00040000)) getDbgLogger
()->setNextMask(0x00040000).DebugPrintfLastMask ( "- TOTAL : %10ld /%10ld /%10ld ms"
, sy, us, sy+us ); }
1283 "- TOTAL : %10ld /%10ld /%10ld ms",{ if (((0x00040000) & getDbgMask()) == (0x00040000)) getDbgLogger
()->setNextMask(0x00040000).DebugPrintfLastMask ( "- TOTAL : %10ld /%10ld /%10ld ms"
, sy, us, sy+us ); }
1284 sy,{ if (((0x00040000) & getDbgMask()) == (0x00040000)) getDbgLogger
()->setNextMask(0x00040000).DebugPrintfLastMask ( "- TOTAL : %10ld /%10ld /%10ld ms"
, sy, us, sy+us ); }
1285 us,{ if (((0x00040000) & getDbgMask()) == (0x00040000)) getDbgLogger
()->setNextMask(0x00040000).DebugPrintfLastMask ( "- TOTAL : %10ld /%10ld /%10ld ms"
, sy, us, sy+us ); }
1286 sy+us{ if (((0x00040000) & getDbgMask()) == (0x00040000)) getDbgLogger
()->setNextMask(0x00040000).DebugPrintfLastMask ( "- TOTAL : %10ld /%10ld /%10ld ms"
, sy, us, sy+us ); }
1287 )){ if (((0x00040000) & getDbgMask()) == (0x00040000)) getDbgLogger
()->setNextMask(0x00040000).DebugPrintfLastMask ( "- TOTAL : %10ld /%10ld /%10ld ms"
, sy, us, sy+us ); }
;
1288 // Real time
1289 uInt32 rt = TP_GETREALTIME(fTPInfo)0;
1290 PDEBUGPRINTFX(DBG_PROFILE,({ if (((0x00040000) & getDbgMask()) == (0x00040000)) getDbgLogger
()->setNextMask(0x00040000).DebugPrintfLastMask ( "- Real Time : %10ld ms"
, rt ); }
1291 "- Real Time : %10ld ms",{ if (((0x00040000) & getDbgMask()) == (0x00040000)) getDbgLogger
()->setNextMask(0x00040000).DebugPrintfLastMask ( "- Real Time : %10ld ms"
, rt ); }
1292 rt{ if (((0x00040000) & getDbgMask()) == (0x00040000)) getDbgLogger
()->setNextMask(0x00040000).DebugPrintfLastMask ( "- Real Time : %10ld ms"
, rt ); }
1293 )){ if (((0x00040000) & getDbgMask()) == (0x00040000)) getDbgLogger
()->setNextMask(0x00040000).DebugPrintfLastMask ( "- Real Time : %10ld ms"
, rt ); }
;
1294 // % CPU
1295 PDEBUGPRINTFX(DBG_PROFILE,({ if (((0x00040000) & getDbgMask()) == (0x00040000)) getDbgLogger
()->setNextMask(0x00040000).DebugPrintfLastMask ( "- CPU load : %10ld promille"
, rt ? (sy+us)*1000/rt : 0 ); }
1296 "- CPU load : %10ld promille",{ if (((0x00040000) & getDbgMask()) == (0x00040000)) getDbgLogger
()->setNextMask(0x00040000).DebugPrintfLastMask ( "- CPU load : %10ld promille"
, rt ? (sy+us)*1000/rt : 0 ); }
1297 rt ? (sy+us)*1000/rt : 0{ if (((0x00040000) & getDbgMask()) == (0x00040000)) getDbgLogger
()->setNextMask(0x00040000).DebugPrintfLastMask ( "- CPU load : %10ld promille"
, rt ? (sy+us)*1000/rt : 0 ); }
1298 )){ if (((0x00040000) & getDbgMask()) == (0x00040000)) getDbgLogger
()->setNextMask(0x00040000).DebugPrintfLastMask ( "- CPU load : %10ld promille"
, rt ? (sy+us)*1000/rt : 0 ); }
;
1299 }
1300 #endif
1301 MP_SHOWCURRENT(DBG_PROFILE,"TSyncSession deleting");
1302 // show ending (if not normal, then ending was already shown in AbortSession())
1303 if (normalend) {
1304 SESSION_PROGRESS_EVENT(this,pev_sessionend,NULL, allsuccess ? 0 : LOCERR_INCOMPLETE,0,0)this->NotifySessionProgressEvent(pev_sessionend,__null,allsuccess
? 0 : LOCERR_INCOMPLETE,0,0)
;
1305 }
1306 // is NOW terminated
1307 fTerminated = true;
1308 PDEBUGPRINTFX(DBG_EXOTIC,("Session is now terminated (but not yet deleted)")){ if (((0x80000000) & getDbgMask()) == (0x80000000)) getDbgLogger
()->setNextMask(0x80000000).DebugPrintfLastMask ("Session is now terminated (but not yet deleted)"
); }
;
1309 } // if not already terminated
1310} // TSyncSession::TerminateSession
1311
1312
1313// Virtual version
1314void TSyncSession::ResetSession(void)
1315{
1316 // terminate sync of datastores
1317 TerminateDatastores();
1318 // reset internals
1319 DEBUGPRINTFX(DBG_EXOTIC,("TSyncSession::ResetSession: calling InternalResetSession")){ if (((0x80000000) & getDbgMask()) == (0x80000000)) getDbgLogger
()->setNextMask(0x80000000).DebugPrintfLastMask ("TSyncSession::ResetSession: calling InternalResetSession"
); }
;
1320 InternalResetSessionEx(false);
1321 DEBUGPRINTFX(DBG_EXOTIC,("TSyncSession::ResetSession: InternalResetSession called")){ if (((0x80000000) & getDbgMask()) == (0x80000000)) getDbgLogger
()->setNextMask(0x80000000).DebugPrintfLastMask ("TSyncSession::ResetSession: InternalResetSession called"
); }
;
1322 // no ancestor to call
1323} // TSyncSession::ResetSession
1324
1325
1326/// @brief Announce destruction of descendant to all datastores which might have direct links to these descendants and must cancel those
1327/// @note must be called by derived class' destructors to allow datastores to detach from agent BEFORE descendant destructor has run
1328void TSyncSession::announceDestruction()
1329{
1330 // terminate sync with all datastores
1331 TLocalDataStorePContainer::iterator pos;
1332 for (pos=fLocalDataStores.begin(); pos!=fLocalDataStores.end(); ++pos) {
1333 // now let datastores cancel possible direct links to derived TSession
1334 (*pos)->announceAgentDestruction();
1335 }
1336} // TSyncSession::announceDestruction
1337
1338
1339// - terminate all datastores
1340void TSyncSession::TerminateDatastores(localstatus aAbortStatusCode)
1341{
1342 // terminate sync with all datastores
1343 TLocalDataStorePContainer::iterator pos;
1344 for (pos=fLocalDataStores.begin(); pos!=fLocalDataStores.end(); ++pos) {
1345 // terminate
1346 (*pos)->engTerminateDatastore(aAbortStatusCode);
1347 }
1348} // TSyncSession::TerminateDatastores
1349
1350
1351// - resets session and removes all datastores (local and remote)
1352void TSyncSession::ResetAndRemoveDatastores(void)
1353{
1354 // Must reset session before
1355 ResetSession();
1356 // remove all local datastores
1357 TLocalDataStorePContainer::iterator pos;
1358 for (pos=fLocalDataStores.begin(); pos!=fLocalDataStores.end(); ++pos) {
1359 // now actually delete them
1360 TLocalEngineDS *dsP = (*pos);
1361 if (dsP) {
1362 (*pos) = NULL__null; // to avoid double deletes
1363 delete dsP;
1364 }
1365 }
1366 fLocalDataStores.clear(); // remove pointers
1367} // TSyncSession::ResetAndRemoveDatastores
1368
1369
1370
1371// reset session to inital state (new)
1372// - this is called at creation and destruction but can be called
1373// also when an existing session needs to be restarted.
1374// - InternalResetSession() must be proof for being called more than
1375// once in a row.
1376// - InternalResetSession() must also be callable from destructor
1377// (care not to call other objects which will refer to the already
1378// half-destructed session!)
1379void TSyncSession::InternalResetSessionEx(bool terminationCall)
1380{
1381 #ifdef SCRIPT_SUPPORT1
1382 // call session termination script (ONCE!)
1383 if (terminationCall && !fTerminated) {
1384 TScriptContext::execute(
1385 fSessionScriptContextP,
1386 getSessionConfig()->fSessionFinishScript,
1387 NULL__null, // context's function table
1388 NULL__null // datastore pointer needed for context
1389 );
1390 }
1391 #endif
1392
1393 // reset sync and datastores
1394 // - version not known in advance
1395 fSyncMLVersion=syncml_vers_unknown;
1396 // - immediately abort SYNC command in progress
1397 fLocalSyncDatastoreP = NULL__null;
1398 #ifndef NO_REMOTE_RULES
1399 // - no remote rules applied
1400 fActiveRemoteRules.clear();
1401 #endif
1402 // - set defaults for >=SyncML 1.1 features
1403 fRemoteWantsNOC = false; // no, unless requested
1404 fRemoteCanHandleUTC = false; // assume remote can not handle UTC time (note that for SyncML 1.0 this will be set to true later)
1405 fRemoteSupportsLargeObjects = false; // no large object support by default
1406 // - default options
1407 fTreatRemoteTimeAsLocal = false; // do not ignore time zone information from remote
1408 fTreatRemoteTimeAsUTC = false; // do not ignore time zone information from remote
1409 fIgnoreDevInfMaxSize = false; // do not ignore <maxsize> specification in CTCap
1410 fIgnoreCTCap = false; // do not ignore CTCap
1411 fDSPathInDevInf = true; // newer Nokias need this, as they expect the same path in devInf as they sent in alert
1412 fDSCgiInDevInf = true; // newer Nokias need this, as they expect the same path AND CGI in devInf as they sent in alert
1413 fReadOnly = false; // always disabled unless set by SessionLogin()
1414 // - init user time zone from setting. May be modified later using SETUSERTIMEZONE()
1415 fUserTimeContext = getSessionConfig()->fUserTimeContext;
1416 #ifdef SYDEBUG2
1417 fSessionLogger.setEnabled(getRootConfig()->fDebugConfig.fSessionDebugLogs); // get default value
1418 #endif
1419 #ifndef MINIMAL_CODE
1420 fLogEnabled = getSessionConfig()->fLogEnabled;
1421 #endif
1422 #ifdef SCRIPT_SUPPORT1
1423 // retain session variables if InternalResetSessionEx() is called more than once in the same session
1424 // (which is normal procedure in clients, where SelectProfile calls ResetSession)
1425 // Note: fSessionScriptContextP will be deleted in the destructor
1426 if (!fSessionScriptContextP) {
1427 if (!terminationCall && !fTerminated) {
1428 // prepare session-level scripts
1429 TScriptContext::rebuildContext(getSyncAppBase(),getSessionConfig()->fSessionInitScript,fSessionScriptContextP,this);
1430 TScriptContext::rebuildContext(getSyncAppBase(),getSessionConfig()->fSentItemStatusScript,fSessionScriptContextP,this);
1431 TScriptContext::rebuildContext(getSyncAppBase(),getSessionConfig()->fReceivedItemStatusScript,fSessionScriptContextP,this);
1432 TScriptContext::rebuildContext(getSyncAppBase(),getSessionConfig()->fSessionFinishScript,fSessionScriptContextP,this);
1433 TScriptContext::rebuildContext(getSyncAppBase(),getSessionConfig()->fCustomGetHandlerScript,fSessionScriptContextP,this);
1434 TScriptContext::rebuildContext(getSyncAppBase(),getSessionConfig()->fCustomGetPutScript,fSessionScriptContextP,this);
1435 TScriptContext::rebuildContext(getSyncAppBase(),getSessionConfig()->fCustomEndPutScript,fSessionScriptContextP,this);
1436 TScriptContext::rebuildContext(getSyncAppBase(),getSessionConfig()->fCustomPutResultHandlerScript,fSessionScriptContextP,this,true); // now instantiate vars
1437 }
1438 }
1439 #endif
1440 // - remove all remote datastores
1441 TRemoteDataStorePContainer::iterator pos1;
1442 for (pos1=fRemoteDataStores.begin(); pos1!=fRemoteDataStores.end(); ++pos1) {
1443 delete *pos1;
1444 }
1445 fRemoteDataStores.clear(); // clear list
1446 // - remove all remote itemtypes
1447 TSyncItemTypePContainer::iterator pos2;
1448 for (pos2=fRemoteItemTypes.begin(); pos2!=fRemoteItemTypes.end(); ++pos2) {
1449 delete *pos2;
1450 }
1451 fRemoteItemTypes.clear(); // clear list
1452 // reset basics
1453 SYSYNC_TRYtry {
1454 // empty command queues
1455 TSmlCommandPContainer::iterator pos;
1456 // - commands waiting for status
1457 for (pos=fStatusWaitCommands.begin(); pos!=fStatusWaitCommands.end(); ++pos) {
1458 #ifdef SYDEBUG2
1459 TSmlCommand *cmdP = *pos;
1460 // show that command was not answered
1461 PDEBUGPRINTFX(DBG_PROTO,("Never received status for &html;<a name=\"SO_%ld_%ld\" href=\"#IO_%ld_%ld\">&html;command '%s'&html;</a>&html;, (outgoing MsgID=%ld, CmdID=%ld)",{ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ("Never received status for &html;<a name=\"SO_%ld_%ld\" href=\"#IO_%ld_%ld\">&html;command '%s'&html;</a>&html;, (outgoing MsgID=%ld, CmdID=%ld)"
, (long)cmdP->getMsgID(), (long)cmdP->getCmdID(), (long
)cmdP->getMsgID(), (long)cmdP->getCmdID(), cmdP->getName
(), (long)cmdP->getMsgID(), (long)cmdP->getCmdID() ); }
1462 (long)cmdP->getMsgID(),{ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ("Never received status for &html;<a name=\"SO_%ld_%ld\" href=\"#IO_%ld_%ld\">&html;command '%s'&html;</a>&html;, (outgoing MsgID=%ld, CmdID=%ld)"
, (long)cmdP->getMsgID(), (long)cmdP->getCmdID(), (long
)cmdP->getMsgID(), (long)cmdP->getCmdID(), cmdP->getName
(), (long)cmdP->getMsgID(), (long)cmdP->getCmdID() ); }
1463 (long)cmdP->getCmdID(),{ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ("Never received status for &html;<a name=\"SO_%ld_%ld\" href=\"#IO_%ld_%ld\">&html;command '%s'&html;</a>&html;, (outgoing MsgID=%ld, CmdID=%ld)"
, (long)cmdP->getMsgID(), (long)cmdP->getCmdID(), (long
)cmdP->getMsgID(), (long)cmdP->getCmdID(), cmdP->getName
(), (long)cmdP->getMsgID(), (long)cmdP->getCmdID() ); }
1464 (long)cmdP->getMsgID(),{ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ("Never received status for &html;<a name=\"SO_%ld_%ld\" href=\"#IO_%ld_%ld\">&html;command '%s'&html;</a>&html;, (outgoing MsgID=%ld, CmdID=%ld)"
, (long)cmdP->getMsgID(), (long)cmdP->getCmdID(), (long
)cmdP->getMsgID(), (long)cmdP->getCmdID(), cmdP->getName
(), (long)cmdP->getMsgID(), (long)cmdP->getCmdID() ); }
1465 (long)cmdP->getCmdID(),{ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ("Never received status for &html;<a name=\"SO_%ld_%ld\" href=\"#IO_%ld_%ld\">&html;command '%s'&html;</a>&html;, (outgoing MsgID=%ld, CmdID=%ld)"
, (long)cmdP->getMsgID(), (long)cmdP->getCmdID(), (long
)cmdP->getMsgID(), (long)cmdP->getCmdID(), cmdP->getName
(), (long)cmdP->getMsgID(), (long)cmdP->getCmdID() ); }
1466 cmdP->getName(),{ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ("Never received status for &html;<a name=\"SO_%ld_%ld\" href=\"#IO_%ld_%ld\">&html;command '%s'&html;</a>&html;, (outgoing MsgID=%ld, CmdID=%ld)"
, (long)cmdP->getMsgID(), (long)cmdP->getCmdID(), (long
)cmdP->getMsgID(), (long)cmdP->getCmdID(), cmdP->getName
(), (long)cmdP->getMsgID(), (long)cmdP->getCmdID() ); }
1467 (long)cmdP->getMsgID(),{ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ("Never received status for &html;<a name=\"SO_%ld_%ld\" href=\"#IO_%ld_%ld\">&html;command '%s'&html;</a>&html;, (outgoing MsgID=%ld, CmdID=%ld)"
, (long)cmdP->getMsgID(), (long)cmdP->getCmdID(), (long
)cmdP->getMsgID(), (long)cmdP->getCmdID(), cmdP->getName
(), (long)cmdP->getMsgID(), (long)cmdP->getCmdID() ); }
1468 (long)cmdP->getCmdID(){ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ("Never received status for &html;<a name=\"SO_%ld_%ld\" href=\"#IO_%ld_%ld\">&html;command '%s'&html;</a>&html;, (outgoing MsgID=%ld, CmdID=%ld)"
, (long)cmdP->getMsgID(), (long)cmdP->getCmdID(), (long
)cmdP->getMsgID(), (long)cmdP->getCmdID(), cmdP->getName
(), (long)cmdP->getMsgID(), (long)cmdP->getCmdID() ); }
1469 )){ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ("Never received status for &html;<a name=\"SO_%ld_%ld\" href=\"#IO_%ld_%ld\">&html;command '%s'&html;</a>&html;, (outgoing MsgID=%ld, CmdID=%ld)"
, (long)cmdP->getMsgID(), (long)cmdP->getCmdID(), (long
)cmdP->getMsgID(), (long)cmdP->getCmdID(), cmdP->getName
(), (long)cmdP->getMsgID(), (long)cmdP->getCmdID() ); }
;
1470 #endif
1471 // delete, if this is not the interrupted command.
1472 // Note: only the interrupted command can also be in the status queue.
1473 // Other queues are exclusive owners of their commands.
1474 if (*pos != fInterruptedCommandP)
1475 delete *pos;
1476 else
1477 DEBUGPRINTF(("- prevented deleting because command is interrupted")){ if (((0x00008000) & getDbgMask()) == (0x00008000)) getDbgLogger
()->setNextMask(0x00008000).DebugPrintfLastMask ("- prevented deleting because command is interrupted"
); }
;
1478 }
1479 fStatusWaitCommands.clear(); // clear list
1480 // - commands waiting for outgoing message to begin
1481 forgetHeaderWaitCommands();
1482 // - commands to be issued only after all commands in this message have
1483 // been processed and answered by a status
1484 for (pos=fEndOfMessageCommands.begin(); pos!=fEndOfMessageCommands.end(); ++pos) {
1485 // show that command was not sent
1486 DEBUGPRINTF(("Never sent end-of-message command '%s', (outgoing MsgID=%ld, CmdID=%ld)",{ if (((0x00008000) & getDbgMask()) == (0x00008000)) getDbgLogger
()->setNextMask(0x00008000).DebugPrintfLastMask ("Never sent end-of-message command '%s', (outgoing MsgID=%ld, CmdID=%ld)"
, (*pos)->getName(), (long)(*pos)->getMsgID(), (long)(*
pos)->getCmdID() ); }
1487 (*pos)->getName(),{ if (((0x00008000) & getDbgMask()) == (0x00008000)) getDbgLogger
()->setNextMask(0x00008000).DebugPrintfLastMask ("Never sent end-of-message command '%s', (outgoing MsgID=%ld, CmdID=%ld)"
, (*pos)->getName(), (long)(*pos)->getMsgID(), (long)(*
pos)->getCmdID() ); }
1488 (long)(*pos)->getMsgID(),{ if (((0x00008000) & getDbgMask()) == (0x00008000)) getDbgLogger
()->setNextMask(0x00008000).DebugPrintfLastMask ("Never sent end-of-message command '%s', (outgoing MsgID=%ld, CmdID=%ld)"
, (*pos)->getName(), (long)(*pos)->getMsgID(), (long)(*
pos)->getCmdID() ); }
1489 (long)(*pos)->getCmdID(){ if (((0x00008000) & getDbgMask()) == (0x00008000)) getDbgLogger
()->setNextMask(0x00008000).DebugPrintfLastMask ("Never sent end-of-message command '%s', (outgoing MsgID=%ld, CmdID=%ld)"
, (*pos)->getName(), (long)(*pos)->getMsgID(), (long)(*
pos)->getCmdID() ); }
1490 )){ if (((0x00008000) & getDbgMask()) == (0x00008000)) getDbgLogger
()->setNextMask(0x00008000).DebugPrintfLastMask ("Never sent end-of-message command '%s', (outgoing MsgID=%ld, CmdID=%ld)"
, (*pos)->getName(), (long)(*pos)->getMsgID(), (long)(*
pos)->getCmdID() ); }
;
1491 // delete
1492 delete *pos;
1493 }
1494 fEndOfMessageCommands.clear(); // clear list
1495 // - commands to be sent in next message
1496 for (pos=fNextMessageCommands.begin(); pos!=fNextMessageCommands.end(); ++pos) {
1497 // show that command was not sent
1498 DEBUGPRINTF(("Never sent next-message command '%s', (outgoing MsgID=%ld, CmdID=%ld)",{ if (((0x00008000) & getDbgMask()) == (0x00008000)) getDbgLogger
()->setNextMask(0x00008000).DebugPrintfLastMask ("Never sent next-message command '%s', (outgoing MsgID=%ld, CmdID=%ld)"
, (*pos)->getName(), (long)(*pos)->getMsgID(), (long)(*
pos)->getCmdID() ); }
1499 (*pos)->getName(),{ if (((0x00008000) & getDbgMask()) == (0x00008000)) getDbgLogger
()->setNextMask(0x00008000).DebugPrintfLastMask ("Never sent next-message command '%s', (outgoing MsgID=%ld, CmdID=%ld)"
, (*pos)->getName(), (long)(*pos)->getMsgID(), (long)(*
pos)->getCmdID() ); }
1500 (long)(*pos)->getMsgID(),{ if (((0x00008000) & getDbgMask()) == (0x00008000)) getDbgLogger
()->setNextMask(0x00008000).DebugPrintfLastMask ("Never sent next-message command '%s', (outgoing MsgID=%ld, CmdID=%ld)"
, (*pos)->getName(), (long)(*pos)->getMsgID(), (long)(*
pos)->getCmdID() ); }
1501 (long)(*pos)->getCmdID(){ if (((0x00008000) & getDbgMask()) == (0x00008000)) getDbgLogger
()->setNextMask(0x00008000).DebugPrintfLastMask ("Never sent next-message command '%s', (outgoing MsgID=%ld, CmdID=%ld)"
, (*pos)->getName(), (long)(*pos)->getMsgID(), (long)(*
pos)->getCmdID() ); }
1502 )){ if (((0x00008000) & getDbgMask()) == (0x00008000)) getDbgLogger
()->setNextMask(0x00008000).DebugPrintfLastMask ("Never sent next-message command '%s', (outgoing MsgID=%ld, CmdID=%ld)"
, (*pos)->getName(), (long)(*pos)->getMsgID(), (long)(*
pos)->getCmdID() ); }
;
1503 // delete
1504 delete *pos;
1505 }
1506 fNextMessageCommands.clear(); // clear list
1507 // - commands to be sent in next package
1508 for (pos=fNextPackageCommands.begin(); pos!=fNextPackageCommands.end(); ++pos) {
1509 // show that command was not sent
1510 DEBUGPRINTF(("Never sent next-package command '%s', (outgoing MsgID=%ld, CmdID=%ld)",{ if (((0x00008000) & getDbgMask()) == (0x00008000)) getDbgLogger
()->setNextMask(0x00008000).DebugPrintfLastMask ("Never sent next-package command '%s', (outgoing MsgID=%ld, CmdID=%ld)"
, (*pos)->getName(), (long)(*pos)->getMsgID(), (long)(*
pos)->getCmdID() ); }
1511 (*pos)->getName(),{ if (((0x00008000) & getDbgMask()) == (0x00008000)) getDbgLogger
()->setNextMask(0x00008000).DebugPrintfLastMask ("Never sent next-package command '%s', (outgoing MsgID=%ld, CmdID=%ld)"
, (*pos)->getName(), (long)(*pos)->getMsgID(), (long)(*
pos)->getCmdID() ); }
1512 (long)(*pos)->getMsgID(),{ if (((0x00008000) & getDbgMask()) == (0x00008000)) getDbgLogger
()->setNextMask(0x00008000).DebugPrintfLastMask ("Never sent next-package command '%s', (outgoing MsgID=%ld, CmdID=%ld)"
, (*pos)->getName(), (long)(*pos)->getMsgID(), (long)(*
pos)->getCmdID() ); }
1513 (long)(*pos)->getCmdID(){ if (((0x00008000) & getDbgMask()) == (0x00008000)) getDbgLogger
()->setNextMask(0x00008000).DebugPrintfLastMask ("Never sent next-package command '%s', (outgoing MsgID=%ld, CmdID=%ld)"
, (*pos)->getName(), (long)(*pos)->getMsgID(), (long)(*
pos)->getCmdID() ); }
1514 )){ if (((0x00008000) & getDbgMask()) == (0x00008000)) getDbgLogger
()->setNextMask(0x00008000).DebugPrintfLastMask ("Never sent next-package command '%s', (outgoing MsgID=%ld, CmdID=%ld)"
, (*pos)->getName(), (long)(*pos)->getMsgID(), (long)(*
pos)->getCmdID() ); }
;
1515 // delete
1516 delete *pos;
1517 }
1518 fNextPackageCommands.clear(); // clear list
1519 // - interrupted command
1520 if (fInterruptedCommandP) {
1521 // show that command was not sent
1522 DEBUGPRINTF(("Never finished interrupted command '%s', (outgoing MsgID=%ld, CmdID=%ld)",{ if (((0x00008000) & getDbgMask()) == (0x00008000)) getDbgLogger
()->setNextMask(0x00008000).DebugPrintfLastMask ("Never finished interrupted command '%s', (outgoing MsgID=%ld, CmdID=%ld)"
, fInterruptedCommandP->getName(), (long)fInterruptedCommandP
->getMsgID(), (long)fInterruptedCommandP->getCmdID() );
}
1523 fInterruptedCommandP->getName(),{ if (((0x00008000) & getDbgMask()) == (0x00008000)) getDbgLogger
()->setNextMask(0x00008000).DebugPrintfLastMask ("Never finished interrupted command '%s', (outgoing MsgID=%ld, CmdID=%ld)"
, fInterruptedCommandP->getName(), (long)fInterruptedCommandP
->getMsgID(), (long)fInterruptedCommandP->getCmdID() );
}
1524 (long)fInterruptedCommandP->getMsgID(),{ if (((0x00008000) & getDbgMask()) == (0x00008000)) getDbgLogger
()->setNextMask(0x00008000).DebugPrintfLastMask ("Never finished interrupted command '%s', (outgoing MsgID=%ld, CmdID=%ld)"
, fInterruptedCommandP->getName(), (long)fInterruptedCommandP
->getMsgID(), (long)fInterruptedCommandP->getCmdID() );
}
1525 (long)fInterruptedCommandP->getCmdID(){ if (((0x00008000) & getDbgMask()) == (0x00008000)) getDbgLogger
()->setNextMask(0x00008000).DebugPrintfLastMask ("Never finished interrupted command '%s', (outgoing MsgID=%ld, CmdID=%ld)"
, fInterruptedCommandP->getName(), (long)fInterruptedCommandP
->getMsgID(), (long)fInterruptedCommandP->getCmdID() );
}
1526 )){ if (((0x00008000) & getDbgMask()) == (0x00008000)) getDbgLogger
()->setNextMask(0x00008000).DebugPrintfLastMask ("Never finished interrupted command '%s', (outgoing MsgID=%ld, CmdID=%ld)"
, fInterruptedCommandP->getName(), (long)fInterruptedCommandP
->getMsgID(), (long)fInterruptedCommandP->getCmdID() );
}
;
1527 delete fInterruptedCommandP;
1528 fInterruptedCommandP=NULL__null;
1529 }
1530 // - commands to be executed again at beginning of next message
1531 fDelayedExecSyncEnds=0;
1532 for (pos=fDelayedExecutionCommands.begin(); pos!=fDelayedExecutionCommands.end(); ++pos) {
1533 // show that command was not sent
1534 DEBUGPRINTF(("Never finished executing command '%s', (incoming MsgID=%ld, CmdID=%ld)",{ if (((0x00008000) & getDbgMask()) == (0x00008000)) getDbgLogger
()->setNextMask(0x00008000).DebugPrintfLastMask ("Never finished executing command '%s', (incoming MsgID=%ld, CmdID=%ld)"
, (*pos)->getName(), (long)(*pos)->getMsgID(), (long)(*
pos)->getCmdID() ); }
1535 (*pos)->getName(),{ if (((0x00008000) & getDbgMask()) == (0x00008000)) getDbgLogger
()->setNextMask(0x00008000).DebugPrintfLastMask ("Never finished executing command '%s', (incoming MsgID=%ld, CmdID=%ld)"
, (*pos)->getName(), (long)(*pos)->getMsgID(), (long)(*
pos)->getCmdID() ); }
1536 (long)(*pos)->getMsgID(),{ if (((0x00008000) & getDbgMask()) == (0x00008000)) getDbgLogger
()->setNextMask(0x00008000).DebugPrintfLastMask ("Never finished executing command '%s', (incoming MsgID=%ld, CmdID=%ld)"
, (*pos)->getName(), (long)(*pos)->getMsgID(), (long)(*
pos)->getCmdID() ); }
1537 (long)(*pos)->getCmdID(){ if (((0x00008000) & getDbgMask()) == (0x00008000)) getDbgLogger
()->setNextMask(0x00008000).DebugPrintfLastMask ("Never finished executing command '%s', (incoming MsgID=%ld, CmdID=%ld)"
, (*pos)->getName(), (long)(*pos)->getMsgID(), (long)(*
pos)->getCmdID() ); }
1538 )){ if (((0x00008000) & getDbgMask()) == (0x00008000)) getDbgLogger
()->setNextMask(0x00008000).DebugPrintfLastMask ("Never finished executing command '%s', (incoming MsgID=%ld, CmdID=%ld)"
, (*pos)->getName(), (long)(*pos)->getMsgID(), (long)(*
pos)->getCmdID() ); }
;
1539 // delete
1540 delete *pos;
1541 }
1542 fDelayedExecutionCommands.clear(); // clear list
1543 #ifdef SYNCSTATUS_AT_SYNC_CLOSE
1544 // make sure sync status is disposed
1545 if (fSyncCloseStatusCommandP) delete fSyncCloseStatusCommandP;
1546 fSyncCloseStatusCommandP=NULL__null;
1547 #endif
1548 // remove incomplete data command
1549 if (fIncompleteDataCommandP) delete fIncompleteDataCommandP;
1550 fIncompleteDataCommandP=NULL__null;
1551 }
1552 SYSYNC_CATCH (exception &e)catch(exception &e) {
1553 #ifdef SYDEBUG2
1554 DEBUGPRINTFX(DBG_ERROR,({ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "WARNING: Exception during InternalResetSession(): %s"
, e.what() ); }
1555 "WARNING: Exception during InternalResetSession(): %s",{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "WARNING: Exception during InternalResetSession(): %s"
, e.what() ); }
1556 e.what(){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "WARNING: Exception during InternalResetSession(): %s"
, e.what() ); }
1557 )){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "WARNING: Exception during InternalResetSession(): %s"
, e.what() ); }
;
1558 #endif
1559 SYSYNC_ENDCATCH}
1560 SYSYNC_CATCH (...)catch(...) {
1561 #ifdef SYDEBUG2
1562 DEBUGPRINTFX(DBG_ERROR,({ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "WARNING: Unknown Exception during InternalResetSession()"
); }
1563 "WARNING: Unknown Exception during InternalResetSession()"{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "WARNING: Unknown Exception during InternalResetSession()"
); }
1564 )){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "WARNING: Unknown Exception during InternalResetSession()"
); }
;
1565 #endif
1566 SYSYNC_ENDCATCH}
1567 // remember time of creation or last reset
1568 SessionUsed();
1569 // reset session status
1570 fIncomingState=psta_idle; // no incoming package status yet
1571 fCmdIncomingState=psta_idle;
1572 fCmdIncoming=NULL__null;
1573 fOutgoingState=psta_idle; // no outgoing package status yet
1574 fRestarting=false;
1575 fNextMessageRequests=0; // no pending next message requests
1576 fFakeFinalFlag=false; // special flag to work around broken resume implementations
1577 fNewOutgoingPackage=true; // first message will be first in outgoing package
1578 fSessionAuthorized=false; // session not permanently authorized
1579 fMessageAuthorized=false; // message not authorized either
1580 fAuthFailures=0; // no failed attempts by remote so far
1581 fAuthRetries=0; // no failed attempts by myself so far
1582 fIncomingMsgID=0; // expected session to start with MsgID=1, so must be 0 now as it will be incremented at StartMessage()
1583 fOutgoingMsgID=0; // starting answers with MsgID=1, so must be 0 as it will be incremented before sending a new message
1584 fAborted=false; // not yet aborted
1585 fSuspended=false; // not being suspended yet
1586 fSuspendAlertSent=false; // no suspend alert sent so far
1587 fFailedDatastores=0; // none failed
1588 fErrorItemDatastores=0; // none generated or detected error items
1589 fInProgress=false; // not yet in progress
1590 fOutgoingStarted=false; // no outgoing message started yet
1591 fSequenceNesting=0; // no sequence command open
1592 fMaxOutgoingMsgSize=0; // no limit for outgoing messages so far
1593 fMaxOutgoingObjSize=0; // SyncML 1.1: no limit for outgoing objects so far
1594 fOutgoingMessageFull=false; // limit not yet reached
1595 // init special remote-dependent behaviour
1596 fLimitedRemoteFieldLengths=false; // assume remote has not generally limited field lenghts
1597 fDontSendEmptyProperties=false; // normally, empty properties will be sent
1598 fDoQuote8BitContent=false;
1599 fNoReplaceInSlowsync=false;
1600 fTreatRemoteTimeAsLocal=false;
1601 fTreatRemoteTimeAsUTC=false;
1602 fIgnoreDevInfMaxSize=false;
1603 fTreatCopyAsAdd=false;
1604 fStrictExecOrdering=true; // SyncML standard requires strict ordering (of statuses, but this implies execution of commands, too)
1605 fDefaultOutCharset=chs_utf8; // SyncML content is usually UTF-8
1606 fDefaultInCharset=chs_utf8; // SyncML content is usually UTF-8
1607 // defaults for possibly remote-dependent behaviour
1608 fCompleteFromClientOnly=getSessionConfig()->fCompleteFromClientOnly; // conform to standard by default
1609 fRequestMaxTime=getSessionConfig()->fRequestMaxTime;
1610 fRequestMinTime=getSessionConfig()->fRequestMinTime;
1611 fUpdateClientDuringSlowsync=getSessionConfig()->fUpdateClientDuringSlowsync;
1612 fUpdateServerDuringSlowsync=getSessionConfig()->fUpdateServerDuringSlowsync;
1613 fAllowMessageRetries=getSessionConfig()->fAllowMessageRetries;
1614 fShowCTCapProps=getSessionConfig()->fShowCTCapProps;
1615 fShowTypeSzInCTCap10=getSessionConfig()->fShowTypeSzInCTCap10;
1616 fVCal10EnddatesSameDay=getSessionConfig()->fVCal10EnddatesSameDay;
1617 fDoNotFoldContent=getSessionConfig()->fDoNotFoldContent;
1618 // tristates!!
1619 fEnumDefaultPropParams=getSessionConfig()->fEnumDefaultPropParams;
1620 #ifdef SCRIPT_SUPPORT1
1621 // call session init script
1622 if (!terminationCall && !fTerminated) {
1623 TScriptContext::execute(
1624 fSessionScriptContextP,
1625 getSessionConfig()->fSessionInitScript,
1626 NULL__null, // context's function table
1627 NULL__null // datastore pointer needed for context
1628 );
1629 }
1630 #endif
1631} // TSyncSession::InternalResetSessionEx
1632
1633
1634
1635#ifdef PROGRESS_EVENTS1
1636
1637// event generator
1638bool TSyncSession::NotifySessionProgressEvent(
1639 TProgressEventType aEventType,
1640 TLocalDSConfig *aDatastoreID,
1641 sInt32 aExtra1,
1642 sInt32 aExtra2,
1643 sInt32 aExtra3
1644)
1645{
1646 #ifdef ENGINE_LIBRARY1
1647 // library build, session level events get queued and dispatched via sessionstep
1648 // - handle some events specially
1649 if (aEventType == pev_nop)
1650 return true; // just continue
1651 else {
1652 // - prepare info record
1653 TEngineProgressInfo info;
1654 info.eventtype = (uInt16)(aEventType);
1655 // - datastore ID, if any
1656 if (aDatastoreID != NULL__null)
1657 info.targetID = (sInt32)(aDatastoreID->fLocalDBTypeID);
1658 else
1659 info.targetID = 0;
1660 // - extras
1661 info.extra1 = aExtra1;
1662 info.extra2 = aExtra2;
1663 info.extra3 = aExtra3;
1664 // - handle it
1665 return HandleSessionProgressEvent(info);
1666 }
1667 #else
1668 // old monolithic build, pass to appbase which dispatches them to the app via callback
1669 return getSyncAppBase()->NotifyAppProgressEvent(aEventType,aDatastoreID,aExtra1,aExtra2,aExtra3);
1670 #endif
1671} // TSyncAppBase::NotifySessionProgressEvent
1672
1673#endif // PROGRESS_EVENTS
1674
1675
1676
1677// get root config pointer
1678// NOTE: we have moved this here because Palm linker
1679// would have problems accessing it as syncsession.cpp is
1680// large enough to have EndMessage >32k away from the
1681// original position of this routine.
1682TRootConfig *TSyncSession::getRootConfig(void)
1683{
1684 return fSyncAppBaseP->getRootConfig();
1685} // TSyncSession::getRootConfig
1686
1687
1688// forget commands waiting to be sent when header is generated
1689void TSyncSession::forgetHeaderWaitCommands(void)
1690{
1691 // empty command queues
1692 TSmlCommandPContainer::iterator pos;
1693 // - commands waiting for outgoing message to begin
1694 for (pos=fHeaderWaitCommands.begin(); pos!=fHeaderWaitCommands.end(); ++pos) {
1695 #if SYDEBUG2>1
1696 TSmlCommand *cmdP = *pos;
1697 // show that command was not answered
1698 DEBUGPRINTF(("Never sent command '%s', (outgoing MsgID=%ld, CmdID=%ld) because outgoing message never started",{ if (((0x00008000) & getDbgMask()) == (0x00008000)) getDbgLogger
()->setNextMask(0x00008000).DebugPrintfLastMask ("Never sent command '%s', (outgoing MsgID=%ld, CmdID=%ld) because outgoing message never started"
, cmdP->getName(), (long)cmdP->getMsgID(), (long)cmdP->
getCmdID() ); }
1699 cmdP->getName(),{ if (((0x00008000) & getDbgMask()) == (0x00008000)) getDbgLogger
()->setNextMask(0x00008000).DebugPrintfLastMask ("Never sent command '%s', (outgoing MsgID=%ld, CmdID=%ld) because outgoing message never started"
, cmdP->getName(), (long)cmdP->getMsgID(), (long)cmdP->
getCmdID() ); }
1700 (long)cmdP->getMsgID(),{ if (((0x00008000) & getDbgMask()) == (0x00008000)) getDbgLogger
()->setNextMask(0x00008000).DebugPrintfLastMask ("Never sent command '%s', (outgoing MsgID=%ld, CmdID=%ld) because outgoing message never started"
, cmdP->getName(), (long)cmdP->getMsgID(), (long)cmdP->
getCmdID() ); }
1701 (long)cmdP->getCmdID(){ if (((0x00008000) & getDbgMask()) == (0x00008000)) getDbgLogger
()->setNextMask(0x00008000).DebugPrintfLastMask ("Never sent command '%s', (outgoing MsgID=%ld, CmdID=%ld) because outgoing message never started"
, cmdP->getName(), (long)cmdP->getMsgID(), (long)cmdP->
getCmdID() ); }
1702 )){ if (((0x00008000) & getDbgMask()) == (0x00008000)) getDbgLogger
()->setNextMask(0x00008000).DebugPrintfLastMask ("Never sent command '%s', (outgoing MsgID=%ld, CmdID=%ld) because outgoing message never started"
, cmdP->getName(), (long)cmdP->getMsgID(), (long)cmdP->
getCmdID() ); }
;
1703 #endif
1704 // delete
1705 delete *pos;
1706 }
1707 fHeaderWaitCommands.clear(); // clear list
1708} // TSyncSession::forgetHeaderWaitCommands
1709
1710
1711// abort processing commands in this message
1712void TSyncSession::AbortCommandProcessing(TSyError aStatusCode)
1713{
1714 if (!fIgnoreIncomingCommands) {
1715 fIgnoreIncomingCommands=true; // do not process further commands
1716 fStatusCodeForIgnored=aStatusCode; // save status code
1717 PDEBUGPRINTFX(DBG_HOT,({ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "--------------- Ignoring all commands in this message (after %ld sec. request processing, %ld sec. total) with Status %hd (0=none) from here on"
, (long)((getSystemNowAs(((timecontext_t) ((tctx_tz_UTC) | TCTX_SYMBOLIC_TZ
)))-getLastRequestStarted()) / (lineartime_t)secondToLinearTimeFactor
), (long)((getSystemNowAs(((timecontext_t) ((tctx_tz_UTC) | TCTX_SYMBOLIC_TZ
)))-getSessionStarted()) / (lineartime_t)secondToLinearTimeFactor
), fStatusCodeForIgnored ); }
1718 "--------------- Ignoring all commands in this message (after %ld sec. request processing, %ld sec. total) with Status %hd (0=none) from here on",{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "--------------- Ignoring all commands in this message (after %ld sec. request processing, %ld sec. total) with Status %hd (0=none) from here on"
, (long)((getSystemNowAs(((timecontext_t) ((tctx_tz_UTC) | TCTX_SYMBOLIC_TZ
)))-getLastRequestStarted()) / (lineartime_t)secondToLinearTimeFactor
), (long)((getSystemNowAs(((timecontext_t) ((tctx_tz_UTC) | TCTX_SYMBOLIC_TZ
)))-getSessionStarted()) / (lineartime_t)secondToLinearTimeFactor
), fStatusCodeForIgnored ); }
1719 (long)((getSystemNowAs(TCTX_UTC)-getLastRequestStarted()) / (lineartime_t)secondToLinearTimeFactor),{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "--------------- Ignoring all commands in this message (after %ld sec. request processing, %ld sec. total) with Status %hd (0=none) from here on"
, (long)((getSystemNowAs(((timecontext_t) ((tctx_tz_UTC) | TCTX_SYMBOLIC_TZ
)))-getLastRequestStarted()) / (lineartime_t)secondToLinearTimeFactor
), (long)((getSystemNowAs(((timecontext_t) ((tctx_tz_UTC) | TCTX_SYMBOLIC_TZ
)))-getSessionStarted()) / (lineartime_t)secondToLinearTimeFactor
), fStatusCodeForIgnored ); }
1720 (long)((getSystemNowAs(TCTX_UTC)-getSessionStarted()) / (lineartime_t)secondToLinearTimeFactor),{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "--------------- Ignoring all commands in this message (after %ld sec. request processing, %ld sec. total) with Status %hd (0=none) from here on"
, (long)((getSystemNowAs(((timecontext_t) ((tctx_tz_UTC) | TCTX_SYMBOLIC_TZ
)))-getLastRequestStarted()) / (lineartime_t)secondToLinearTimeFactor
), (long)((getSystemNowAs(((timecontext_t) ((tctx_tz_UTC) | TCTX_SYMBOLIC_TZ
)))-getSessionStarted()) / (lineartime_t)secondToLinearTimeFactor
), fStatusCodeForIgnored ); }
1721 fStatusCodeForIgnored{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "--------------- Ignoring all commands in this message (after %ld sec. request processing, %ld sec. total) with Status %hd (0=none) from here on"
, (long)((getSystemNowAs(((timecontext_t) ((tctx_tz_UTC) | TCTX_SYMBOLIC_TZ
)))-getLastRequestStarted()) / (lineartime_t)secondToLinearTimeFactor
), (long)((getSystemNowAs(((timecontext_t) ((tctx_tz_UTC) | TCTX_SYMBOLIC_TZ
)))-getSessionStarted()) / (lineartime_t)secondToLinearTimeFactor
), fStatusCodeForIgnored ); }
1722 )){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "--------------- Ignoring all commands in this message (after %ld sec. request processing, %ld sec. total) with Status %hd (0=none) from here on"
, (long)((getSystemNowAs(((timecontext_t) ((tctx_tz_UTC) | TCTX_SYMBOLIC_TZ
)))-getLastRequestStarted()) / (lineartime_t)secondToLinearTimeFactor
), (long)((getSystemNowAs(((timecontext_t) ((tctx_tz_UTC) | TCTX_SYMBOLIC_TZ
)))-getSessionStarted()) / (lineartime_t)secondToLinearTimeFactor
), fStatusCodeForIgnored ); }
;
1723 }
1724} // TSyncSession::AbortCommandProcessing
1725
1726
1727// suspend session (that is: flag abortion)
1728void TSyncSession::SuspendSession(TSyError aReason)
1729{
1730 // first check for suspend
1731 if (fSyncMLVersion>=syncml_vers_1_2) {
1732 // try suspend, only possible if not already suspended or aborted
1733 if (!fSuspended && !fAborted) {
1734 fSuspended=true; // trigger suspend
1735 fAbortReasonStatus = aReason;
1736 fLocalAbortReason = true;
1737 AbortCommandProcessing(514); // abort command processing, all subsequent commands will be ignored with "cancelled" status
1738 PDEBUGPRINTFX(DBG_ERROR,({ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "WARNING: Session locally flagged for suspend, reason=%hd"
, aReason ); }
1739 "WARNING: Session locally flagged for suspend, reason=%hd",{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "WARNING: Session locally flagged for suspend, reason=%hd"
, aReason ); }
1740 aReason{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "WARNING: Session locally flagged for suspend, reason=%hd"
, aReason ); }
1741 )){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "WARNING: Session locally flagged for suspend, reason=%hd"
, aReason ); }
;
1742 CONSOLEPRINTF((SySync_ConsolePrintf(stderr, "SYSYNC " "Session will be suspended due to local error code %hd\n"
"\n", aReason)
1743 "Session will be suspended due to local error code %hd\n",SySync_ConsolePrintf(stderr, "SYSYNC " "Session will be suspended due to local error code %hd\n"
"\n", aReason)
1744 aReasonSySync_ConsolePrintf(stderr, "SYSYNC " "Session will be suspended due to local error code %hd\n"
"\n", aReason)
1745 ))SySync_ConsolePrintf(stderr, "SYSYNC " "Session will be suspended due to local error code %hd\n"
"\n", aReason)
;
1746 }
1747 }
1748 else {
1749 // We can't suspend, we need to abort
1750 AbortSession(500,true,aReason);
1751 }
1752} // TSyncSession::SuspendSession
1753
1754
1755void TSyncSession::MarkSuspendAlertSent(bool aSent)
1756{
1757 fSuspendAlertSent = aSent;
1758}
1759
1760
1761// abort session (that is: flag abortion)
1762void TSyncSession::AbortSession(TSyError aStatusCode, bool aLocalProblem, TSyError aReason)
1763{
1764 // Catch the case that some inner routine, e.g. a plugin, detects a user suspend. It can
1765 // return LOCERR_USERSUSPEND then and will cause the engine instead of aborting.
1766 if (aStatusCode==LOCERR_USERSUSPEND) {
1767 SuspendSession(LOCERR_USERSUSPEND);
1768 return;
1769 }
1770 // make sure session gets aborted
1771 // BUT: do NOT reset yet. Reset would incorrectly abort message answering
1772 if (!fAborted && !fTerminated) {
1773 fAborted=true; // session aborted
1774 fAbortReasonStatus = aReason ? aReason : aStatusCode;
1775 fLocalAbortReason = aLocalProblem;
1776 fInProgress=false; // not in progress any more (will be deleted after end of request)
1777 PDEBUGBLOCKFMT(("SessionAbort","Aborting Session",getDbgLogger()->DebugOpenBlockExpanded ("SessionAbort","Aborting Session"
, "Status=%hd|ProblemSource=%s", fAbortReasonStatus, fLocalAbortReason
? "LOCAL" : "REMOTE" )
1778 "Status=%hd|ProblemSource=%s",getDbgLogger()->DebugOpenBlockExpanded ("SessionAbort","Aborting Session"
, "Status=%hd|ProblemSource=%s", fAbortReasonStatus, fLocalAbortReason
? "LOCAL" : "REMOTE" )
1779 fAbortReasonStatus,getDbgLogger()->DebugOpenBlockExpanded ("SessionAbort","Aborting Session"
, "Status=%hd|ProblemSource=%s", fAbortReasonStatus, fLocalAbortReason
? "LOCAL" : "REMOTE" )
1780 fLocalAbortReason ? "LOCAL" : "REMOTE"getDbgLogger()->DebugOpenBlockExpanded ("SessionAbort","Aborting Session"
, "Status=%hd|ProblemSource=%s", fAbortReasonStatus, fLocalAbortReason
? "LOCAL" : "REMOTE" )
1781 ))getDbgLogger()->DebugOpenBlockExpanded ("SessionAbort","Aborting Session"
, "Status=%hd|ProblemSource=%s", fAbortReasonStatus, fLocalAbortReason
? "LOCAL" : "REMOTE" )
;
1782 PDEBUGPRINTFX(DBG_ERROR,({ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "WARNING: Aborting Session with Reason Status %hd (%s problem) ***"
, fAbortReasonStatus, fLocalAbortReason ? "LOCAL" : "REMOTE" )
; }
1783 "WARNING: Aborting Session with Reason Status %hd (%s problem) ***",{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "WARNING: Aborting Session with Reason Status %hd (%s problem) ***"
, fAbortReasonStatus, fLocalAbortReason ? "LOCAL" : "REMOTE" )
; }
1784 fAbortReasonStatus,{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "WARNING: Aborting Session with Reason Status %hd (%s problem) ***"
, fAbortReasonStatus, fLocalAbortReason ? "LOCAL" : "REMOTE" )
; }
1785 fLocalAbortReason ? "LOCAL" : "REMOTE"{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "WARNING: Aborting Session with Reason Status %hd (%s problem) ***"
, fAbortReasonStatus, fLocalAbortReason ? "LOCAL" : "REMOTE" )
; }
1786 )){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "WARNING: Aborting Session with Reason Status %hd (%s problem) ***"
, fAbortReasonStatus, fLocalAbortReason ? "LOCAL" : "REMOTE" )
; }
;
1787 // In SyncML 1.1, we have a special status code to show that commands are not
1788 // executed any more due to cancellation of the session
1789 if (fSyncMLVersion>=syncml_vers_1_1)
1790 aStatusCode=514; // cancelled, command not completed
1791 AbortCommandProcessing(aStatusCode);
1792 // let all local datastores know
1793 TLocalDataStorePContainer::iterator pos;
1794 for (pos=fLocalDataStores.begin(); pos!=fLocalDataStores.end(); ++pos) {
1795 (*pos)->engAbortDataStoreSync(fAbortReasonStatus, fLocalAbortReason);
1796 }
1797 CONSOLEPRINTF((SySync_ConsolePrintf(stderr, "SYSYNC " "Session aborted because of %s SyncML error code %hd\n"
"\n", fLocalAbortReason ? "LOCAL" : "REMOTE", fAbortReasonStatus
)
1798 "Session aborted because of %s SyncML error code %hd\n",SySync_ConsolePrintf(stderr, "SYSYNC " "Session aborted because of %s SyncML error code %hd\n"
"\n", fLocalAbortReason ? "LOCAL" : "REMOTE", fAbortReasonStatus
)
1799 fLocalAbortReason ? "LOCAL" : "REMOTE",SySync_ConsolePrintf(stderr, "SYSYNC " "Session aborted because of %s SyncML error code %hd\n"
"\n", fLocalAbortReason ? "LOCAL" : "REMOTE", fAbortReasonStatus
)
1800 fAbortReasonStatusSySync_ConsolePrintf(stderr, "SYSYNC " "Session aborted because of %s SyncML error code %hd\n"
"\n", fLocalAbortReason ? "LOCAL" : "REMOTE", fAbortReasonStatus
)
1801 ))SySync_ConsolePrintf(stderr, "SYSYNC " "Session aborted because of %s SyncML error code %hd\n"
"\n", fLocalAbortReason ? "LOCAL" : "REMOTE", fAbortReasonStatus
)
;
1802 SESSION_PROGRESS_EVENT(this->NotifySessionProgressEvent(pev_sessionend,__null,getAbortReasonStatus
(),0,0)
1803 this,this->NotifySessionProgressEvent(pev_sessionend,__null,getAbortReasonStatus
(),0,0)
1804 pev_sessionend,this->NotifySessionProgressEvent(pev_sessionend,__null,getAbortReasonStatus
(),0,0)
1805 NULL,this->NotifySessionProgressEvent(pev_sessionend,__null,getAbortReasonStatus
(),0,0)
1806 getAbortReasonStatus(),this->NotifySessionProgressEvent(pev_sessionend,__null,getAbortReasonStatus
(),0,0)
1807 0,0this->NotifySessionProgressEvent(pev_sessionend,__null,getAbortReasonStatus
(),0,0)
1808 )this->NotifySessionProgressEvent(pev_sessionend,__null,getAbortReasonStatus
(),0,0)
;
1809 PDEBUGENDBLOCK("SessionAbort")getDbgLogger()->DebugCloseBlock( "SessionAbort");
1810 }
1811} // TSyncSession::AbortSession
1812
1813
1814// returns true if session was a complete success
1815bool TSyncSession::isAllSuccess(void)
1816{
1817 return fFailedDatastores==0 && fErrorItemDatastores==0;
1818} // TSyncSession::isAllSuccess
1819
1820
1821// let session know that datastore has failed
1822void TSyncSession::DatastoreFailed(TSyError aStatusCode, bool aLocalProblem)
1823{
1824 fFailedDatastores++;
1825 // %%% note that this is not perfect for server, as inactive datastores are possible
1826 if (fFailedDatastores>=fLocalDataStores.size()) {
1827 // all have failed by now, abort the session
1828 AbortSession(aStatusCode, aLocalProblem, aStatusCode);
1829 }
1830} // TSyncSession::DatastoreFailed
1831
1832
1833// set SyncML toolkit workspace ID
1834void TSyncSession::setSmlWorkspaceID(InstanceID_t aSmlWorkspaceID)
1835{
1836 fSmlWorkspaceID=aSmlWorkspaceID;
1837} // TSyncSession::setSmlWorkspaceID
1838
1839
1840// show some information about the config
1841void TSyncSession::DebugShowCfgInfo(void)
1842{
1843 #ifdef SYDEBUG2
1844 string t;
1845 StringObjTimestamp(t,getRootConfig()->fConfigDate);
1846 // now write settings to log
1847 PDEBUGPRINTFX(DBG_HOT,({ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "==== Config file='%s', Last Change=%s"
, getSyncAppBase()->fConfigFilePath.c_str(), t.c_str() ); }
1848 "==== Config file='%s', Last Change=%s",{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "==== Config file='%s', Last Change=%s"
, getSyncAppBase()->fConfigFilePath.c_str(), t.c_str() ); }
1849 getSyncAppBase()->fConfigFilePath.c_str(),{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "==== Config file='%s', Last Change=%s"
, getSyncAppBase()->fConfigFilePath.c_str(), t.c_str() ); }
1850 t.c_str(){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "==== Config file='%s', Last Change=%s"
, getSyncAppBase()->fConfigFilePath.c_str(), t.c_str() ); }
1851 )){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "==== Config file='%s', Last Change=%s"
, getSyncAppBase()->fConfigFilePath.c_str(), t.c_str() ); }
;
1852 #ifndef HARDCODED_CONFIG
1853 PDEBUGPRINTFX(DBG_HOT,({ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "==== Config ID string='%s'"
, getRootConfig()->fConfigIDString.c_str() ); }
1854 "==== Config ID string='%s'",{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "==== Config ID string='%s'"
, getRootConfig()->fConfigIDString.c_str() ); }
1855 getRootConfig()->fConfigIDString.c_str(){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "==== Config ID string='%s'"
, getRootConfig()->fConfigIDString.c_str() ); }
1856 )){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "==== Config ID string='%s'"
, getRootConfig()->fConfigIDString.c_str() ); }
;
1857 #endif
1858 #endif
1859} // TSyncSession::DebugShowCfgInfo
1860
1861
1862#ifndef MINIMAL_CODE
1863
1864#include <errno(*__errno_location ()).h>
1865
1866// write to sync log file
1867void TSyncSession::WriteLogLine(const char *aLogline)
1868{
1869 if (getSessionConfig()->fLogFileName.empty()) return; // do not write without a path
1870 // open for append
1871 FILE * logfile=fopen(getSessionConfig()->fLogFileName.c_str(),"a");
1872 if (!logfile) {
1873 PDEBUGPRINTFX(DBG_ERROR,("**** Cannot write to logfile '%s' (errno=%ld)",getSessionConfig()->fLogFileName.c_str(),(long)errno)){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("**** Cannot write to logfile '%s' (errno=%ld)"
,getSessionConfig()->fLogFileName.c_str(),(long)(*__errno_location
())); }
;
1874 return; // cannot write
1875 }
1876 // check if we need to write labels first
1877 if (!getSessionConfig()->fLogFileLabels.empty()) {
1878 // check file size
1879 if (ftell(logfile)==0) {
1880 // we are at the beginning, print labels first
1881 fputs(getSessionConfig()->fLogFileLabels.c_str(),logfile);
1882 }
1883 }
1884 // now write log line
1885 fputs(aLogline,logfile);
1886 // close file
1887 fclose(logfile);
1888} // TSyncSession::WriteLogLine
1889
1890#endif
1891
1892
1893
1894// queue a SyncBody context command for issuing after incoming message has ended
1895void TSyncSession::queueForIssueRoot(
1896 TSmlCommand * &aSyncCommandP // the command
1897)
1898{
1899 fEndOfMessageCommands.push_back(aSyncCommandP);
1900 aSyncCommandP=NULL__null;
1901} // TSyncSession::queueForIssueRoot
1902
1903
1904// queue a SyncBody context command for issuing after incoming message has ended
1905void TSyncSession::issueNotBeforePackage(
1906 TPackageStates aPackageState,
1907 TSmlCommand *aSyncCommandP // the command
1908)
1909{
1910 if (fOutgoingState>=aPackageState) {
1911 issueRootPtr(aSyncCommandP);
1912 }
1913 else {
1914 PDEBUGPRINTFX(DBG_SESSION,("%s queued for next package",aSyncCommandP->getName())){ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("%s queued for next package"
,aSyncCommandP->getName()); }
;
1915 fNextPackageCommands.push_back(aSyncCommandP);
1916 }
1917} // TSyncSession::issueNotBeforePackage
1918
1919
1920// issue a command in SyncBody context (uses session's interruptedCommand/NextMessageCommands)
1921bool TSyncSession::issueRootPtr(
1922 TSmlCommand *aSyncCommandP, // the command
1923 bool aNoResp, // set if no response is wanted
1924 bool aIsOKSyncHdrStatus // set if this is sync hdr status
1925)
1926{
1927 // now issue
1928 return issuePtr(aSyncCommandP,fNextMessageCommands,fInterruptedCommandP,aNoResp,aIsOKSyncHdrStatus);
1929} // TSyncSession::issueRootPtr
1930
1931
1932// issue object passed as pointer (rather than pointer reference)
1933// normally used internally only
1934bool TSyncSession::issuePtr(
1935 TSmlCommand *aSyncCommandP, // the command
1936 TSmlCommandPContainer &aNextMessageCommands, // the list to add the command if cannot be issued in this message
1937 TSmlCommand * &aInterruptedCommandP, // where to store command ptr if it was interrupted
1938 bool aNoResp, // set if no response is wanted
1939 bool aIsOKSyncHdrStatus // set if this is sync hdr status
1940)
1941{
1942 bool issued=true; // NULL issue is successful issue
1943
1944 if (aSyncCommandP) {
1945 PDEBUGBLOCKFMT(("issue","issuing command",getDbgLogger()->DebugOpenBlockExpanded ("issue","issuing command"
, "Cmd=%s", aSyncCommandP->getName() )
1946 "Cmd=%s",getDbgLogger()->DebugOpenBlockExpanded ("issue","issuing command"
, "Cmd=%s", aSyncCommandP->getName() )
1947 aSyncCommandP->getName()getDbgLogger()->DebugOpenBlockExpanded ("issue","issuing command"
, "Cmd=%s", aSyncCommandP->getName() )
1948 ))getDbgLogger()->DebugOpenBlockExpanded ("issue","issuing command"
, "Cmd=%s", aSyncCommandP->getName() )
;
1949 if (fCmdIncoming &&
1950 aSyncCommandP->getCmdType()==scmd_status) {
1951 // Queue instead of sending immediately, see TSyncSession::process().
1952 fCmdIncoming->queueStatusCmd(aSyncCommandP);
1953 if (fCmdIncoming->getCmdType()==scmd_sync) {
1954 TSyncCommand *syncCommandP=static_cast<TSyncCommand *>(fCmdIncoming);
1955 syncCommandP->setLocalDatastore(fLocalSyncDatastoreP);
1956 PDEBUGPRINTFX(DBG_SESSION,("issuePtr: store fLocalSyncDatastoreP in sync command")){ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("issuePtr: store fLocalSyncDatastoreP in sync command"
); }
;
1957 }
1958 DEBUGPRINTFX(DBG_PROTO,("%s: queue reply to %s because of pending commands",{ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ("%s: queue reply to %s because of pending commands"
, aSyncCommandP->getName(), fCmdIncoming->getName() ); }
1959 aSyncCommandP->getName(),{ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ("%s: queue reply to %s because of pending commands"
, aSyncCommandP->getName(), fCmdIncoming->getName() ); }
1960 fCmdIncoming->getName(){ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ("%s: queue reply to %s because of pending commands"
, aSyncCommandP->getName(), fCmdIncoming->getName() ); }
1961 )){ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ("%s: queue reply to %s because of pending commands"
, aSyncCommandP->getName(), fCmdIncoming->getName() ); }
;
1962 goto endissue;
1963 }
1964 SYSYNC_TRYtry {
1965 // check for not-to-be-sent commands
1966 if (aSyncCommandP->getDontSend()) {
1967 // command must not be sent, just silently discarded
1968 DEBUGPRINTFX(DBG_PROTO,("%s: not sent because fDontSend is set -> just delete",{ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ("%s: not sent because fDontSend is set -> just delete"
, aSyncCommandP->getName() ); }
1969 aSyncCommandP->getName(){ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ("%s: not sent because fDontSend is set -> just delete"
, aSyncCommandP->getName() ); }
1970 )){ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ("%s: not sent because fDontSend is set -> just delete"
, aSyncCommandP->getName() ); }
;
1971 delete aSyncCommandP;
1972 issued=true; // counts as issued
1973 goto endissue;
1974 }
1975 // check if this commmand now triggers need to answer
1976 if (!aIsOKSyncHdrStatus) {
1977 fNeedToAnswer=true;
1978 }
1979 // check if outgoing message has already started. If not, queue command
1980 // for sending when message has started (client case, when status for
1981 // header must be evaluated before next header can be generated)
1982 if (!fOutgoingStarted) {
1983 fHeaderWaitCommands.push_back(aSyncCommandP);
1984 PDEBUGPRINTFX(DBG_SESSION+DBG_EXOTIC,({ if (((0x00000020 +0x80000000) & getDbgMask()) == (0x00000020
+0x80000000)) getDbgLogger()->setNextMask(0x00000020 +0x80000000
).DebugPrintfLastMask ( "Outgoing message header not yet generated, command '%s' queued"
, aSyncCommandP->getName() ); }
1985 "Outgoing message header not yet generated, command '%s' queued",{ if (((0x00000020 +0x80000000) & getDbgMask()) == (0x00000020
+0x80000000)) getDbgLogger()->setNextMask(0x00000020 +0x80000000
).DebugPrintfLastMask ( "Outgoing message header not yet generated, command '%s' queued"
, aSyncCommandP->getName() ); }
1986 aSyncCommandP->getName(){ if (((0x00000020 +0x80000000) & getDbgMask()) == (0x00000020
+0x80000000)) getDbgLogger()->setNextMask(0x00000020 +0x80000000
).DebugPrintfLastMask ( "Outgoing message header not yet generated, command '%s' queued"
, aSyncCommandP->getName() ); }
1987 )){ if (((0x00000020 +0x80000000) & getDbgMask()) == (0x00000020
+0x80000000)) getDbgLogger()->setNextMask(0x00000020 +0x80000000
).DebugPrintfLastMask ( "Outgoing message header not yet generated, command '%s' queued"
, aSyncCommandP->getName() ); }
;
1988 issued=true; // act as if issued
1989 goto endissue;
1990 }
1991 // check if this is a continuation of a suspended chunked item transfer
1992 // if yes, substitute the full data we currently have in the item (from
1993 // the database) with the buffered left-overs from the previous
1994 // session.
1995 aSyncCommandP->checkChunkContinuation();
1996 // check if message size restrictions or local buffer size
1997 // will prevent command from being sent now
1998 TSmlCommand *splitCmdP = NULL__null;
1999 if (!fOutgoingMessageFull) {
2000 #ifndef USE_SML_EVALUATION1
2001 #error "This Implementation does not work any more without USE_SML_EVALUATION"
2002 #endif
2003 // check if enough room to send data
2004 sInt32 freeaftersend=aSyncCommandP->evalIssue(
2005 peekNextOutgoingCmdID(), // this will be the ID
2006 getOutgoingMsgID(),
2007 aNoResp
2008 );
2009 // - if room for new commands is smaller than expected message size
2010 sInt32 maxfree=getSmlWorkspaceFreeBytes();
2011 sInt32 sizetoend=maxfree-freeaftersend;
2012 #ifdef SYDEBUG2
2013 PDEBUGPRINTFX(DBG_SESSION+DBG_EXOTIC,({ if (((0x00000020 +0x80000000) & getDbgMask()) == (0x00000020
+0x80000000)) getDbgLogger()->setNextMask(0x00000020 +0x80000000
).DebugPrintfLastMask ( "Command '%s': is %hd-th counted cmd, cmdsize(+tags needed to end msg)=%ld, available=%ld (maxfree=%ld, freeaftersend=%ld, notUsableBufferBytes()=%ld)"
, aSyncCommandP->getName(), fOutgoingCmds, (long)sizetoend
, (long)(maxfree-getNotUsableBufferBytes()), (long)maxfree, (
long)freeaftersend, (long)getNotUsableBufferBytes() ); }
2014 "Command '%s': is %hd-th counted cmd, cmdsize(+tags needed to end msg)=%ld, available=%ld (maxfree=%ld, freeaftersend=%ld, notUsableBufferBytes()=%ld)",{ if (((0x00000020 +0x80000000) & getDbgMask()) == (0x00000020
+0x80000000)) getDbgLogger()->setNextMask(0x00000020 +0x80000000
).DebugPrintfLastMask ( "Command '%s': is %hd-th counted cmd, cmdsize(+tags needed to end msg)=%ld, available=%ld (maxfree=%ld, freeaftersend=%ld, notUsableBufferBytes()=%ld)"
, aSyncCommandP->getName(), fOutgoingCmds, (long)sizetoend
, (long)(maxfree-getNotUsableBufferBytes()), (long)maxfree, (
long)freeaftersend, (long)getNotUsableBufferBytes() ); }
2015 aSyncCommandP->getName(),{ if (((0x00000020 +0x80000000) & getDbgMask()) == (0x00000020
+0x80000000)) getDbgLogger()->setNextMask(0x00000020 +0x80000000
).DebugPrintfLastMask ( "Command '%s': is %hd-th counted cmd, cmdsize(+tags needed to end msg)=%ld, available=%ld (maxfree=%ld, freeaftersend=%ld, notUsableBufferBytes()=%ld)"
, aSyncCommandP->getName(), fOutgoingCmds, (long)sizetoend
, (long)(maxfree-getNotUsableBufferBytes()), (long)maxfree, (
long)freeaftersend, (long)getNotUsableBufferBytes() ); }
2016 fOutgoingCmds,{ if (((0x00000020 +0x80000000) & getDbgMask()) == (0x00000020
+0x80000000)) getDbgLogger()->setNextMask(0x00000020 +0x80000000
).DebugPrintfLastMask ( "Command '%s': is %hd-th counted cmd, cmdsize(+tags needed to end msg)=%ld, available=%ld (maxfree=%ld, freeaftersend=%ld, notUsableBufferBytes()=%ld)"
, aSyncCommandP->getName(), fOutgoingCmds, (long)sizetoend
, (long)(maxfree-getNotUsableBufferBytes()), (long)maxfree, (
long)freeaftersend, (long)getNotUsableBufferBytes() ); }
2017 (long)sizetoend, // size of command (+tags needed to end msg){ if (((0x00000020 +0x80000000) & getDbgMask()) == (0x00000020
+0x80000000)) getDbgLogger()->setNextMask(0x00000020 +0x80000000
).DebugPrintfLastMask ( "Command '%s': is %hd-th counted cmd, cmdsize(+tags needed to end msg)=%ld, available=%ld (maxfree=%ld, freeaftersend=%ld, notUsableBufferBytes()=%ld)"
, aSyncCommandP->getName(), fOutgoingCmds, (long)sizetoend
, (long)(maxfree-getNotUsableBufferBytes()), (long)maxfree, (
long)freeaftersend, (long)getNotUsableBufferBytes() ); }
2018 (long)(maxfree-getNotUsableBufferBytes()),{ if (((0x00000020 +0x80000000) & getDbgMask()) == (0x00000020
+0x80000000)) getDbgLogger()->setNextMask(0x00000020 +0x80000000
).DebugPrintfLastMask ( "Command '%s': is %hd-th counted cmd, cmdsize(+tags needed to end msg)=%ld, available=%ld (maxfree=%ld, freeaftersend=%ld, notUsableBufferBytes()=%ld)"
, aSyncCommandP->getName(), fOutgoingCmds, (long)sizetoend
, (long)(maxfree-getNotUsableBufferBytes()), (long)maxfree, (
long)freeaftersend, (long)getNotUsableBufferBytes() ); }
2019 (long)maxfree,{ if (((0x00000020 +0x80000000) & getDbgMask()) == (0x00000020
+0x80000000)) getDbgLogger()->setNextMask(0x00000020 +0x80000000
).DebugPrintfLastMask ( "Command '%s': is %hd-th counted cmd, cmdsize(+tags needed to end msg)=%ld, available=%ld (maxfree=%ld, freeaftersend=%ld, notUsableBufferBytes()=%ld)"
, aSyncCommandP->getName(), fOutgoingCmds, (long)sizetoend
, (long)(maxfree-getNotUsableBufferBytes()), (long)maxfree, (
long)freeaftersend, (long)getNotUsableBufferBytes() ); }
2020 (long)freeaftersend,{ if (((0x00000020 +0x80000000) & getDbgMask()) == (0x00000020
+0x80000000)) getDbgLogger()->setNextMask(0x00000020 +0x80000000
).DebugPrintfLastMask ( "Command '%s': is %hd-th counted cmd, cmdsize(+tags needed to end msg)=%ld, available=%ld (maxfree=%ld, freeaftersend=%ld, notUsableBufferBytes()=%ld)"
, aSyncCommandP->getName(), fOutgoingCmds, (long)sizetoend
, (long)(maxfree-getNotUsableBufferBytes()), (long)maxfree, (
long)freeaftersend, (long)getNotUsableBufferBytes() ); }
2021 (long)getNotUsableBufferBytes(){ if (((0x00000020 +0x80000000) & getDbgMask()) == (0x00000020
+0x80000000)) getDbgLogger()->setNextMask(0x00000020 +0x80000000
).DebugPrintfLastMask ( "Command '%s': is %hd-th counted cmd, cmdsize(+tags needed to end msg)=%ld, available=%ld (maxfree=%ld, freeaftersend=%ld, notUsableBufferBytes()=%ld)"
, aSyncCommandP->getName(), fOutgoingCmds, (long)sizetoend
, (long)(maxfree-getNotUsableBufferBytes()), (long)maxfree, (
long)freeaftersend, (long)getNotUsableBufferBytes() ); }
2022 )){ if (((0x00000020 +0x80000000) & getDbgMask()) == (0x00000020
+0x80000000)) getDbgLogger()->setNextMask(0x00000020 +0x80000000
).DebugPrintfLastMask ( "Command '%s': is %hd-th counted cmd, cmdsize(+tags needed to end msg)=%ld, available=%ld (maxfree=%ld, freeaftersend=%ld, notUsableBufferBytes()=%ld)"
, aSyncCommandP->getName(), fOutgoingCmds, (long)sizetoend
, (long)(maxfree-getNotUsableBufferBytes()), (long)maxfree, (
long)freeaftersend, (long)getNotUsableBufferBytes() ); }
;
2023 #endif
2024 #ifndef MINIMAL_CODE
2025 // - check for artifical debug chunking
2026 if (getSessionConfig()->fDebugChunkMaxSize && aSyncCommandP->isSyncOp()) {
2027 // always chunk commands over the configured size
2028 uInt32 cmdSize=getSmlWorkspaceFreeBytes()-freeaftersend;
2029 if (cmdSize>getSessionConfig()->fDebugChunkMaxSize) {
2030 // simulate a different free after send to force chunking
2031 sInt32 nfas=getNotUsableBufferBytes()-(cmdSize-getSessionConfig()->fDebugChunkMaxSize)+100;
2032 if (nfas<freeaftersend) {
2033 freeaftersend=nfas;
2034 PDEBUGPRINTFX(DBG_ERROR,("Attention: Debug Chunking enabled, freeaftersend adjusted to %ld",(long)freeaftersend)){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("Attention: Debug Chunking enabled, freeaftersend adjusted to %ld"
,(long)freeaftersend); }
;
2035 }
2036 }
2037 }
2038 #endif
2039 // - check if we can send this
2040 if (freeaftersend<=getNotUsableBufferBytes()) {
2041 // not enough space in this message
2042 PDEBUGPRINTFX(DBG_PROTO,({ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ( "command is %ld bytes too big to be sent as-is in this message"
, (long)(getNotUsableBufferBytes()-freeaftersend) ); }
2043 "command is %ld bytes too big to be sent as-is in this message",{ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ( "command is %ld bytes too big to be sent as-is in this message"
, (long)(getNotUsableBufferBytes()-freeaftersend) ); }
2044 (long)(getNotUsableBufferBytes()-freeaftersend){ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ( "command is %ld bytes too big to be sent as-is in this message"
, (long)(getNotUsableBufferBytes()-freeaftersend) ); }
2045 )){ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ( "command is %ld bytes too big to be sent as-is in this message"
, (long)(getNotUsableBufferBytes()-freeaftersend) ); }
;
2046 bool sendable=false;
2047 // - first choice: try to split (available in SyncML 1.1 and later)
2048 if (getSyncMLVersion()>=syncml_vers_1_1) {
2049 // we can use moredata mechanism, try if it works for this command
2050 if (fOutgoingCmds>0 && sizetoend < getMaxOutgoingSize()/4) {
2051 // this is a small command, and not in best position
2052 // - command will most likely fit into next message, so end this message now
2053 fOutgoingMessageFull=true;
2054 sendable=true; // kind of "sendable" - as are confident it will be sendable in next message
2055 PDEBUGPRINTFX(DBG_PROTO,("command is less than 1/4 of maxmsgsize -> will likely fit into next message, so queue it")){ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ("command is less than 1/4 of maxmsgsize -> will likely fit into next message, so queue it"
); }
;
2056 }
2057 else {
2058 // - try to split
2059 // reserve about 200 bytes for Meta Size
2060 splitCmdP = aSyncCommandP->splitCommand(getNotUsableBufferBytes()-freeaftersend+200);
2061 if (splitCmdP) {
2062 sendable=true;
2063 }
2064 else if (aSyncCommandP->canSplit()) {
2065 // command is basically splittable, but not right now - end message now and try in next
2066 fOutgoingMessageFull=true;
2067 sendable=true; // kind of "sendable" - just not now, but certainly later
2068 }
2069 }
2070 }
2071 // - second choice: try to shrink (mainly devInf)
2072 if (!sendable) {
2073 // gets sendable if we can shrink it to given size
2074 sendable = aSyncCommandP->shrinkCommand(getNotUsableBufferBytes()-freeaftersend);
2075 PDEBUGPRINTFX(DBG_PROTO+DBG_HOT,({ if (((0x00000010 +0x00000001) & getDbgMask()) == (0x00000010
+0x00000001)) getDbgLogger()->setNextMask(0x00000010 +0x00000001
).DebugPrintfLastMask ( "shrinkCommand could %sshrink command by %ld bytes or more (which is needed to send it now)"
, sendable ? "" : "NOT ", (long)(getNotUsableBufferBytes()-freeaftersend
) ); }
2076 "shrinkCommand could %sshrink command by %ld bytes or more (which is needed to send it now)",{ if (((0x00000010 +0x00000001) & getDbgMask()) == (0x00000010
+0x00000001)) getDbgLogger()->setNextMask(0x00000010 +0x00000001
).DebugPrintfLastMask ( "shrinkCommand could %sshrink command by %ld bytes or more (which is needed to send it now)"
, sendable ? "" : "NOT ", (long)(getNotUsableBufferBytes()-freeaftersend
) ); }
2077 sendable ? "" : "NOT ",{ if (((0x00000010 +0x00000001) & getDbgMask()) == (0x00000010
+0x00000001)) getDbgLogger()->setNextMask(0x00000010 +0x00000001
).DebugPrintfLastMask ( "shrinkCommand could %sshrink command by %ld bytes or more (which is needed to send it now)"
, sendable ? "" : "NOT ", (long)(getNotUsableBufferBytes()-freeaftersend
) ); }
2078 (long)(getNotUsableBufferBytes()-freeaftersend){ if (((0x00000010 +0x00000001) & getDbgMask()) == (0x00000010
+0x00000001)) getDbgLogger()->setNextMask(0x00000010 +0x00000001
).DebugPrintfLastMask ( "shrinkCommand could %sshrink command by %ld bytes or more (which is needed to send it now)"
, sendable ? "" : "NOT ", (long)(getNotUsableBufferBytes()-freeaftersend
) ); }
2079 )){ if (((0x00000010 +0x00000001) & getDbgMask()) == (0x00000010
+0x00000001)) getDbgLogger()->setNextMask(0x00000010 +0x00000001
).DebugPrintfLastMask ( "shrinkCommand could %sshrink command by %ld bytes or more (which is needed to send it now)"
, sendable ? "" : "NOT ", (long)(getNotUsableBufferBytes()-freeaftersend
) ); }
;
2080 }
2081 // - third choice: send it later as first command
2082 if (!sendable) {
2083 if (fOutgoingCmds>0 && sizetoend<getMaxOutgoingSize()+300) {
2084 // not best position now, and not plain impossible (i.e. cmd<maxmsgsize+300)
2085 PDEBUGPRINTFX(DBG_PROTO,("command can fit into one message -> queue and hope we'll be able to send it as only command in subsequent message")){ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ("command can fit into one message -> queue and hope we'll be able to send it as only command in subsequent message"
); }
;
2086 // - command will possibly fit into next message, so end this message now
2087 fOutgoingMessageFull=true;
2088 sendable=true; // kind of "sendable" - as we are hoping it will be sendable later
Value stored to 'sendable' is never read
2089 }
2090 else {
2091 // this WAS already the best possible position to send or really too big
2092 // - we are in trouble, this command is unsendable
2093 PDEBUGPRINTFX(DBG_ERROR,("%s: Warning: command is too big to be sent at all -> discarded/mark for resend",{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("%s: Warning: command is too big to be sent at all -> discarded/mark for resend"
, aSyncCommandP->getName() ); }
2094 aSyncCommandP->getName(){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("%s: Warning: command is too big to be sent at all -> discarded/mark for resend"
, aSyncCommandP->getName() ); }
2095 )){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("%s: Warning: command is too big to be sent at all -> discarded/mark for resend"
, aSyncCommandP->getName() ); }
;
2096 // - try again in next session (data size might be smaller then, or remote might allow larger data at some time)
2097 aSyncCommandP->markForResend();
2098 // - just discard it for now
2099 delete aSyncCommandP;
2100 issued=false; // not issued (but also not queued again).
2101 goto endissue;
2102 }
2103 }
2104 // check if command was made sendable by splitting off a part
2105 if (splitCmdP) {
2106 // - queue command containing remaining data for issuing in next message
2107 aNextMessageCommands.push_back(splitCmdP);
2108 PDEBUGPRINTFX(DBG_PROTO+DBG_HOT,("Split command, sending a chunk, queued rest of data for sending in next message")){ if (((0x00000010 +0x00000001) & getDbgMask()) == (0x00000010
+0x00000001)) getDbgLogger()->setNextMask(0x00000010 +0x00000001
).DebugPrintfLastMask ("Split command, sending a chunk, queued rest of data for sending in next message"
); }
;
2109 // - Note: fOutgoingMessageFull is not set here (as first part of cmd must be sent first)
2110 // but will be set below after issuing first part (due to splitCmdP!=NULL)
2111 }
2112 } // command too large to be sent now
2113 }
2114 // Queue if message is full, or if we have a interrupted command and
2115 // command to be sent is something other than status. This will make sure
2116 // incoming commands get their statuses before message is filled with other
2117 // explicitly generated commands
2118 if (fOutgoingMessageFull || (aInterruptedCommandP && aSyncCommandP->getCmdType()!=scmd_status)) {
2119 // - queue for issuing in next message
2120 aNextMessageCommands.push_back(aSyncCommandP);
2121 PDEBUGPRINTFX(DBG_HOT,({ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "No room for issueing in this message, command '%s' queued for next message"
, aSyncCommandP->getName() ); }
2122 "No room for issueing in this message, command '%s' queued for next message",{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "No room for issueing in this message, command '%s' queued for next message"
, aSyncCommandP->getName() ); }
2123 aSyncCommandP->getName(){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "No room for issueing in this message, command '%s' queued for next message"
, aSyncCommandP->getName() ); }
2124 )){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "No room for issueing in this message, command '%s' queued for next message"
, aSyncCommandP->getName() ); }
;
2125 // - could not be issued, was queued
2126 issued=false;
2127 }
2128 else {
2129 // issue the command
2130 if (splitCmdP) fOutgoingMessageFull=true; // if we are sending a split command, message IS full after that!
2131 bool dodelete=true;
2132 if (aSyncCommandP->issue(getNextOutgoingCmdID(),fOutgoingMsgID,aNoResp)) {
2133 // command expects status and must be kept in list
2134 PDEBUGPRINTFX(DBG_HOT,("%s: issued as (outgoing MsgID=%ld, CmdID=%ld), now queueing for &html;<a name=\"IO_%ld_%ld\" href=\"#SO_%ld_%ld\">&html;status&html;</a>&html;",{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("%s: issued as (outgoing MsgID=%ld, CmdID=%ld), now queueing for &html;<a name=\"IO_%ld_%ld\" href=\"#SO_%ld_%ld\">&html;status&html;</a>&html;"
, aSyncCommandP->getName(), (long)aSyncCommandP->getMsgID
(), (long)aSyncCommandP->getCmdID(), (long)aSyncCommandP->
getMsgID(), (long)aSyncCommandP->getCmdID(), (long)aSyncCommandP
->getMsgID(), (long)aSyncCommandP->getCmdID() ); }
2135 aSyncCommandP->getName(),{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("%s: issued as (outgoing MsgID=%ld, CmdID=%ld), now queueing for &html;<a name=\"IO_%ld_%ld\" href=\"#SO_%ld_%ld\">&html;status&html;</a>&html;"
, aSyncCommandP->getName(), (long)aSyncCommandP->getMsgID
(), (long)aSyncCommandP->getCmdID(), (long)aSyncCommandP->
getMsgID(), (long)aSyncCommandP->getCmdID(), (long)aSyncCommandP
->getMsgID(), (long)aSyncCommandP->getCmdID() ); }
2136 (long)aSyncCommandP->getMsgID(),{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("%s: issued as (outgoing MsgID=%ld, CmdID=%ld), now queueing for &html;<a name=\"IO_%ld_%ld\" href=\"#SO_%ld_%ld\">&html;status&html;</a>&html;"
, aSyncCommandP->getName(), (long)aSyncCommandP->getMsgID
(), (long)aSyncCommandP->getCmdID(), (long)aSyncCommandP->
getMsgID(), (long)aSyncCommandP->getCmdID(), (long)aSyncCommandP
->getMsgID(), (long)aSyncCommandP->getCmdID() ); }
2137 (long)aSyncCommandP->getCmdID(),{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("%s: issued as (outgoing MsgID=%ld, CmdID=%ld), now queueing for &html;<a name=\"IO_%ld_%ld\" href=\"#SO_%ld_%ld\">&html;status&html;</a>&html;"
, aSyncCommandP->getName(), (long)aSyncCommandP->getMsgID
(), (long)aSyncCommandP->getCmdID(), (long)aSyncCommandP->
getMsgID(), (long)aSyncCommandP->getCmdID(), (long)aSyncCommandP
->getMsgID(), (long)aSyncCommandP->getCmdID() ); }
2138 (long)aSyncCommandP->getMsgID(),{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("%s: issued as (outgoing MsgID=%ld, CmdID=%ld), now queueing for &html;<a name=\"IO_%ld_%ld\" href=\"#SO_%ld_%ld\">&html;status&html;</a>&html;"
, aSyncCommandP->getName(), (long)aSyncCommandP->getMsgID
(), (long)aSyncCommandP->getCmdID(), (long)aSyncCommandP->
getMsgID(), (long)aSyncCommandP->getCmdID(), (long)aSyncCommandP
->getMsgID(), (long)aSyncCommandP->getCmdID() ); }
2139 (long)aSyncCommandP->getCmdID(),{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("%s: issued as (outgoing MsgID=%ld, CmdID=%ld), now queueing for &html;<a name=\"IO_%ld_%ld\" href=\"#SO_%ld_%ld\">&html;status&html;</a>&html;"
, aSyncCommandP->getName(), (long)aSyncCommandP->getMsgID
(), (long)aSyncCommandP->getCmdID(), (long)aSyncCommandP->
getMsgID(), (long)aSyncCommandP->getCmdID(), (long)aSyncCommandP
->getMsgID(), (long)aSyncCommandP->getCmdID() ); }
2140 (long)aSyncCommandP->getMsgID(),{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("%s: issued as (outgoing MsgID=%ld, CmdID=%ld), now queueing for &html;<a name=\"IO_%ld_%ld\" href=\"#SO_%ld_%ld\">&html;status&html;</a>&html;"
, aSyncCommandP->getName(), (long)aSyncCommandP->getMsgID
(), (long)aSyncCommandP->getCmdID(), (long)aSyncCommandP->
getMsgID(), (long)aSyncCommandP->getCmdID(), (long)aSyncCommandP
->getMsgID(), (long)aSyncCommandP->getCmdID() ); }
2141 (long)aSyncCommandP->getCmdID(){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("%s: issued as (outgoing MsgID=%ld, CmdID=%ld), now queueing for &html;<a name=\"IO_%ld_%ld\" href=\"#SO_%ld_%ld\">&html;status&html;</a>&html;"
, aSyncCommandP->getName(), (long)aSyncCommandP->getMsgID
(), (long)aSyncCommandP->getCmdID(), (long)aSyncCommandP->
getMsgID(), (long)aSyncCommandP->getCmdID(), (long)aSyncCommandP
->getMsgID(), (long)aSyncCommandP->getCmdID() ); }
2142 )){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("%s: issued as (outgoing MsgID=%ld, CmdID=%ld), now queueing for &html;<a name=\"IO_%ld_%ld\" href=\"#SO_%ld_%ld\">&html;status&html;</a>&html;"
, aSyncCommandP->getName(), (long)aSyncCommandP->getMsgID
(), (long)aSyncCommandP->getCmdID(), (long)aSyncCommandP->
getMsgID(), (long)aSyncCommandP->getCmdID(), (long)aSyncCommandP
->getMsgID(), (long)aSyncCommandP->getCmdID() ); }
;
2143 // - queue for status
2144 aSyncCommandP->setWaitingForStatus(true); // increment waiting for status count of this command
2145 fStatusWaitCommands.push_back(aSyncCommandP);
2146 dodelete=false;
2147 }
2148 else {
2149 // command does not expect status and can be deleted if it is finished
2150 PDEBUGPRINTFX(DBG_HOT,("%s: issued as (outgoing MsgID=%ld, CmdID=%ld), not waiting for status",{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("%s: issued as (outgoing MsgID=%ld, CmdID=%ld), not waiting for status"
, aSyncCommandP->getName(), (long)aSyncCommandP->getMsgID
(), (long)aSyncCommandP->getCmdID() ); }
2151 aSyncCommandP->getName(),{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("%s: issued as (outgoing MsgID=%ld, CmdID=%ld), not waiting for status"
, aSyncCommandP->getName(), (long)aSyncCommandP->getMsgID
(), (long)aSyncCommandP->getCmdID() ); }
2152 (long)aSyncCommandP->getMsgID(),{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("%s: issued as (outgoing MsgID=%ld, CmdID=%ld), not waiting for status"
, aSyncCommandP->getName(), (long)aSyncCommandP->getMsgID
(), (long)aSyncCommandP->getCmdID() ); }
2153 (long)aSyncCommandP->getCmdID(){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("%s: issued as (outgoing MsgID=%ld, CmdID=%ld), not waiting for status"
, aSyncCommandP->getName(), (long)aSyncCommandP->getMsgID
(), (long)aSyncCommandP->getCmdID() ); }
2154 )){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("%s: issued as (outgoing MsgID=%ld, CmdID=%ld), not waiting for status"
, aSyncCommandP->getName(), (long)aSyncCommandP->getMsgID
(), (long)aSyncCommandP->getCmdID() ); }
;
2155 }
2156 // Now as it is issued, count all "real" commands
2157 if (!aIsOKSyncHdrStatus) {
2158 // count outgoing "real" command, that is NOT SyncHdr OK status nor Alert 222 OK statu
2159 // Note that issuing a container command such as <sync> will have pre-decremented fOutgoingCmds
2160 // to compensate (container should not be counted)
2161 fOutgoingCmds++;
2162 }
2163 // test if finished issuing
2164 if (!aSyncCommandP->finished()) {
2165 // issuing was interrupted, continue at start of next message
2166 aInterruptedCommandP=aSyncCommandP; // remember
2167 dodelete=false;
2168 issued=false;
2169 PDEBUGPRINTFX(DBG_SESSION,("%s: issue not finished -> queued interrupted command",{ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("%s: issue not finished -> queued interrupted command"
, aSyncCommandP->getName() ); }
2170 aSyncCommandP->getName(){ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("%s: issue not finished -> queued interrupted command"
, aSyncCommandP->getName() ); }
2171 )){ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("%s: issue not finished -> queued interrupted command"
, aSyncCommandP->getName() ); }
;
2172 }
2173 // - delete if not queued
2174 if (dodelete) {
2175 PDEBUGPRINTFX(DBG_SESSION,("%s: issue finished and not waiting for status -> deleting command",{ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("%s: issue finished and not waiting for status -> deleting command"
, aSyncCommandP->getName() ); }
2176 aSyncCommandP->getName(){ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("%s: issue finished and not waiting for status -> deleting command"
, aSyncCommandP->getName() ); }
2177 )){ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("%s: issue finished and not waiting for status -> deleting command"
, aSyncCommandP->getName() ); }
;
2178 delete aSyncCommandP;
2179 }
2180 // message size
2181 PDEBUGPRINTFX(DBG_PROTO,("Outgoing Message size is now %ld bytes",(long)getOutgoingMessageSize())){ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ("Outgoing Message size is now %ld bytes"
,(long)getOutgoingMessageSize()); }
;
2182 }
2183 }
2184 SYSYNC_CATCH (...)catch(...) {
2185 // exception during command issuing
2186 // - make sure command is deleted (as issue owns it now)
2187 delete aSyncCommandP;
2188 // make sure session gets aborted
2189 AbortSession(500,true); // local problem
2190 // close block
2191 PDEBUGENDBLOCK("issue")getDbgLogger()->DebugCloseBlock( "issue");
2192 // re-throw
2193 SYSYNC_RETHROWthrow;
2194 SYSYNC_ENDCATCH}
2195 endissue:
2196 PDEBUGENDBLOCK("issue")getDbgLogger()->DebugCloseBlock( "issue");
2197 } // if something to issue at all
2198 else {
2199 DEBUGPRINTFX(DBG_SESSION,("issuePtr called with NULL command")){ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("issuePtr called with NULL command"
); }
;
2200 }
2201 // return true if completely issued, false if interrupted or not issued at all
2202 return issued;
2203} // TSyncSession::issuePtr
2204
2205
2206// returns true if given number of bytes are transferable
2207// (not exceeding MaxMsgSize (in SyncML 1.0) or MaxObjSize (SyncML 1.1 and later)
2208bool TSyncSession::dataSizeTransferable(uInt32 aDataBytes)
2209{
2210 if (fSyncMLVersion<syncml_vers_1_1 || !fRemoteSupportsLargeObjects) {
2211 // SyncML 1.0: Data is transferable only if it is not more
2212 // than the room we had when the first syncop command in the message
2213 // was being sent
2214 return aDataBytes<=uInt32(fMaxRoomForData);
2215 }
2216 else {
2217 // SyncML 1.1 and later: Data is transferable if it is not more than
2218 // the MaxObjSize (if defined at all)
2219 return aDataBytes<=uInt32(fMaxOutgoingObjSize) || fMaxOutgoingObjSize==0;
2220 }
2221} // TSyncSession::dataSizeTransferable
2222
2223
2224
2225#ifndef USE_SML_EVALUATION1
2226 #error "This implementation requires USE_SML_EVALUATION"
2227#endif
2228
2229// get how many bytes may not be used in the outgoing message buffer
2230// because of maxMsgSize restrictions
2231sInt32 TSyncSession::getNotUsableBufferBytes(void)
2232{
2233 if (fMaxOutgoingMsgSize) {
2234 // there is a limit
2235 sInt32 leavefree =
2236 getSmlWorkspaceFreeBytes() // what is free now
2237 + fOutgoingMsgSize // + what is already used = totally available
2238 - fMaxOutgoingMsgSize; // - max number to send = what we must leave free
2239 // if available space is less than what we may send, there's no need
2240 // to leave anything free.
2241 return leavefree > 0 ? leavefree : 0;
2242 }
2243 else {
2244 // limited only by workspace itself: no bytes need to be left free
2245 return 0;
2246 }
2247} // TSyncSession::getNotUsableBufferBytes
2248
2249
2250// get max size outgoing message may have (either defined by remote's maxmsgsize or local buffer space)
2251sInt32 TSyncSession::getMaxOutgoingSize(void)
2252{
2253 return fMaxOutgoingMsgSize>0 ? fMaxOutgoingMsgSize : getSmlWorkspaceFreeBytes();
2254} // TSyncSession::getMaxOutgoingSize
2255
2256
2257/// @brief mark all pending items for a datastore for resume
2258/// (those items that are in a session queue for being issued or getting status)
2259void TSyncSession::markPendingForResume(TLocalEngineDS *aForDatastoreP)
2260{
2261 TSmlCommandPContainer::iterator pos;
2262 // - commands not issued yet because header not yet generated
2263 for (pos=fHeaderWaitCommands.begin(); pos!=fHeaderWaitCommands.end(); ++pos) {
2264 (*pos)->markPendingForResume(aForDatastoreP,true); // unsent
2265 }
2266 // - commands not issued yet because they belong at the end of the message
2267 for (pos=fEndOfMessageCommands.begin(); pos!=fEndOfMessageCommands.end(); ++pos) {
2268 (*pos)->markPendingForResume(aForDatastoreP,true); // unsent
2269 }
2270 // - interrupted and next-message commands
2271 markPendingForResume(fNextMessageCommands,fInterruptedCommandP,aForDatastoreP);
2272 // - next package commands
2273 for (pos=fNextPackageCommands.begin(); pos!=fNextPackageCommands.end(); ++pos) {
2274 (*pos)->markPendingForResume(aForDatastoreP,true); // unsent
2275 }
2276 // - commands waiting for status
2277 for (pos=fStatusWaitCommands.begin(); pos!=fStatusWaitCommands.end(); ++pos) {
2278 (*pos)->markPendingForResume(aForDatastoreP,false); // these are already sent (except if they are waiting for chunk ok 213 status)!
2279 }
2280} // TSyncSession::markPendingForResume
2281
2282
2283/// @brief mark all pending items for a datastore for resume
2284/// (those items that are in a session queue for being issued or getting status)
2285void TSyncSession::markPendingForResume(
2286 TSmlCommandPContainer &aNextMessageCommands,
2287 TSmlCommand *aInterruptedCommandP,
2288 TLocalEngineDS *aForDatastoreP
2289)
2290{
2291 // - all those that are in an interrupted command
2292 if (aInterruptedCommandP) {
2293 aInterruptedCommandP->markPendingForResume(aForDatastoreP,true); // these are unsent
2294 }
2295 // - all those pending for next message
2296 TSmlCommandPContainer::iterator pos;
2297 for (pos=aNextMessageCommands.begin(); pos!=aNextMessageCommands.end(); ++pos) {
2298 (*pos)->markPendingForResume(aForDatastoreP,true); // these are unsent
2299 }
2300} // TSyncSession::markPendingForResume
2301
2302
2303// continue interrupted or prevented issue of root level commands
2304void TSyncSession::ContinuePackageRoot(void)
2305{
2306 // check if we have anything to send, and if so, reset the count
2307 if (fNextMessageCommands.size()>0 || fInterruptedCommandP) {
2308 #ifdef SYDEBUG2
2309 if (fNextMessageRequests) {
2310 PDEBUGPRINTFX(DBG_PROTO,("Fulfilling %ld Next-Message-Request-Alerts 222 by sending commands now",(long)fNextMessageRequests)){ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ("Fulfilling %ld Next-Message-Request-Alerts 222 by sending commands now"
,(long)fNextMessageRequests); }
;
2311 }
2312 #endif
2313 fNextMessageRequests=0; // sent something, request fulfilled
2314 }
2315 ContinuePackage(fNextMessageCommands,fInterruptedCommandP);
2316} // TSyncSession::ContinuePackageRoot
2317
2318
2319// continue interrupted or prevented issue in next package
2320void TSyncSession::ContinuePackage(
2321 TSmlCommandPContainer &aNextMessageCommands,
2322 TSmlCommand * &aInterruptedCommandP
2323)
2324{
2325 TSmlCommand *cmdP = aInterruptedCommandP;
2326 // - first restart interrupted command
2327 if (cmdP && !isAborted() && !isSuspending()) {
2328 // first check if interrupted command has received status
2329 if (cmdP->isWaitingForStatus() && getSessionConfig()->fWaitForStatusOfInterrupted) {
2330 // Command to be continued has not yet received status, so wait with continuing it
2331 PDEBUGPRINTFX(DBG_SESSION,({ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ( "Interrupted command '%s' (outgoing MsgID=%ld, CmdID=%ld) is still waiting for status -> do not continue nor send queued commands"
, cmdP->getName(), (long)cmdP->getMsgID(), (long)cmdP->
getCmdID() ); }
2332 "Interrupted command '%s' (outgoing MsgID=%ld, CmdID=%ld) is still waiting for status -> do not continue nor send queued commands",{ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ( "Interrupted command '%s' (outgoing MsgID=%ld, CmdID=%ld) is still waiting for status -> do not continue nor send queued commands"
, cmdP->getName(), (long)cmdP->getMsgID(), (long)cmdP->
getCmdID() ); }
2333 cmdP->getName(),{ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ( "Interrupted command '%s' (outgoing MsgID=%ld, CmdID=%ld) is still waiting for status -> do not continue nor send queued commands"
, cmdP->getName(), (long)cmdP->getMsgID(), (long)cmdP->
getCmdID() ); }
2334 (long)cmdP->getMsgID(),{ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ( "Interrupted command '%s' (outgoing MsgID=%ld, CmdID=%ld) is still waiting for status -> do not continue nor send queued commands"
, cmdP->getName(), (long)cmdP->getMsgID(), (long)cmdP->
getCmdID() ); }
2335 (long)cmdP->getCmdID(){ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ( "Interrupted command '%s' (outgoing MsgID=%ld, CmdID=%ld) is still waiting for status -> do not continue nor send queued commands"
, cmdP->getName(), (long)cmdP->getMsgID(), (long)cmdP->
getCmdID() ); }
2336 )){ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ( "Interrupted command '%s' (outgoing MsgID=%ld, CmdID=%ld) is still waiting for status -> do not continue nor send queued commands"
, cmdP->getName(), (long)cmdP->getMsgID(), (long)cmdP->
getCmdID() ); }
;
2337 // aInterruptedCommandP is still set, prevents sending of queued commands
2338 }
2339 else {
2340 PDEBUGPRINTFX(DBG_SESSION,("Sending command that was interrupted at end of last message")){ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("Sending command that was interrupted at end of last message"
); }
;
2341 // there is an interrupted command, continue it
2342 bool dodelete=true;
2343 // if an interrupted command must be continued, this can't be an OK for SyncHdr
2344 fNeedToAnswer=true;
2345 bool newIssue=false;
2346 // now continue issuing
2347 bool queueForStatus=cmdP->continueIssue(newIssue);
2348 // check if complete re-issuing is needed
2349 if (newIssue) {
2350 // command must be re-issued as if it was a new command
2351 PDEBUGPRINTFX(DBG_SESSION,("%s: continuing command by issuing anew",cmdP->getName())){ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("%s: continuing command by issuing anew"
,cmdP->getName()); }
;
2352 // interruption is over for now, IssuePtr will set it again if interrupted again
2353 aInterruptedCommandP=NULL__null;
2354 // IssuePtr will take care of all needed status queueing and deleting command if finished etc.
2355 issuePtr(cmdP,aNextMessageCommands,aInterruptedCommandP);
2356 // never delete, as issuePtr will have done it if needed
2357 dodelete=false;
2358 }
2359 else {
2360 // no complete re-issuing needed, just check if we need to queue for status (again)
2361 if (queueForStatus) {
2362 // command expects status (again?) and must be kept in list
2363 PDEBUGPRINTFX(DBG_SESSION,("%s: continued, now queueing for status (again) as (outgoing MsgID=%ld, CmdID=%ld)",{ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("%s: continued, now queueing for status (again) as (outgoing MsgID=%ld, CmdID=%ld)"
, cmdP->getName(), (long)cmdP->getMsgID(), (long)cmdP->
getCmdID() ); }
2364 cmdP->getName(),{ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("%s: continued, now queueing for status (again) as (outgoing MsgID=%ld, CmdID=%ld)"
, cmdP->getName(), (long)cmdP->getMsgID(), (long)cmdP->
getCmdID() ); }
2365 (long)cmdP->getMsgID(),{ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("%s: continued, now queueing for status (again) as (outgoing MsgID=%ld, CmdID=%ld)"
, cmdP->getName(), (long)cmdP->getMsgID(), (long)cmdP->
getCmdID() ); }
2366 (long)cmdP->getCmdID(){ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("%s: continued, now queueing for status (again) as (outgoing MsgID=%ld, CmdID=%ld)"
, cmdP->getName(), (long)cmdP->getMsgID(), (long)cmdP->
getCmdID() ); }
2367 )){ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("%s: continued, now queueing for status (again) as (outgoing MsgID=%ld, CmdID=%ld)"
, cmdP->getName(), (long)cmdP->getMsgID(), (long)cmdP->
getCmdID() ); }
;
2368 // - queue for status (note that every SyncML 1.1 chunk wants to see a status 213 in any case!)
2369 if (!cmdP->isWaitingForStatus()) {
2370 // only put to the queue again if not already waiting there
2371 fStatusWaitCommands.push_back(cmdP);
2372 cmdP->setWaitingForStatus(true);
2373 }
2374 else {
2375 // already waiting, so it's already in the queue - do not push it again
2376 PDEBUGPRINTFX(DBG_SESSION,("%s: continued command was already waiting for status, do not push again", cmdP->getName())){ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("%s: continued command was already waiting for status, do not push again"
, cmdP->getName()); }
;
2377 }
2378 dodelete=false;
2379 }
2380 }
2381 // test if completely issued now
2382 if (!cmdP->finished()) {
2383 // issuing was again interrupted, continue at start of next message
2384 // - keep aInterruptedCommandP pointer unchanged
2385 dodelete=false;
2386 PDEBUGPRINTFX(DBG_SESSION,("%s: continueIssue not finished -> queued interrupted command again",{ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("%s: continueIssue not finished -> queued interrupted command again"
, cmdP->getName() ); }
2387 cmdP->getName(){ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("%s: continueIssue not finished -> queued interrupted command again"
, cmdP->getName() ); }
2388 )){ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("%s: continueIssue not finished -> queued interrupted command again"
, cmdP->getName() ); }
;
2389 }
2390 else {
2391 // no interrupted command any more
2392 aInterruptedCommandP=NULL__null;
2393 }
2394 // delete if not queued
2395 if (dodelete) {
2396 PDEBUGPRINTFX(DBG_SESSION,("%s: continueIssue finished and not waiting for status -> deleting command",{ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("%s: continueIssue finished and not waiting for status -> deleting command"
, cmdP->getName() ); }
2397 cmdP->getName(){ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("%s: continueIssue finished and not waiting for status -> deleting command"
, cmdP->getName() ); }
2398 )){ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("%s: continueIssue finished and not waiting for status -> deleting command"
, cmdP->getName() ); }
;
2399 delete cmdP;
2400 }
2401 } // if status was received for interrupted command
2402 } // if interrupted command
2403 // send commands from queue (until interrupted again)
2404 #ifdef SYDEBUG2
2405 if (!isAborted() && !isSuspending() && !aInterruptedCommandP && aNextMessageCommands.size()>0) {
2406 PDEBUGPRINTFX(DBG_SESSION,("Sending %ld commands that didn't make it into last message",(long)aNextMessageCommands.size())){ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("Sending %ld commands that didn't make it into last message"
,(long)aNextMessageCommands.size()); }
;
2407 }
2408 #endif
2409 TSmlCommandPContainer::iterator pos;
2410 while (!isAborted() && !isSuspending() && !aInterruptedCommandP && !outgoingMessageFull()) {
2411 // first in list
2412 pos=aNextMessageCommands.begin();
2413 if (pos==aNextMessageCommands.end()) break; // done
2414 // take command out of the list
2415 cmdP=(*pos);
2416 aNextMessageCommands.erase(pos);
2417 // issue it (without luck, might land in the queue again --> %%% endless retry??)
2418 if (!issuePtr(cmdP,aNextMessageCommands,aInterruptedCommandP)) break;
2419 }
2420} // TSyncSession::ContinuePackage
2421
2422
2423
2424// create, send and delete SyncHeader "command"
2425void TSyncSession::issueHeader(bool aNoResp)
2426{
2427 #ifdef SYDEBUG2
2428 // Start output translation before issuing outgoing header
2429 XMLTranslationOutgoingStart();
2430 #endif
2431 if (IS_CLIENT(!getSyncAppBase()->isServer())) {
2432 #ifdef SYDEBUG2
2433 // for client, document exchange starts with outgoing message
2434 // but for server, SyncML_Outgoing is started before SyncML_Incoming, as SyncML_Incoming ends first
2435 PDEBUGBLOCKDESC("SyncML_Outgoing","start of new outgoing message")getDbgLogger()->DebugOpenBlock( "SyncML_Outgoing","start of new outgoing message"
)
;
2436 PDEBUGPRINTFX(DBG_HOT,("=================> Started new outgoing message")){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("=================> Started new outgoing message"
); }
;
2437 #endif
2438 #ifdef EXPIRES_AFTER_DATE
2439 // set 1/4 of the date here
2440 fCopyOfScrambledNow=((getSyncAppBase()->fScrambledNow)<<2)+503; // scramble again a little
2441 #endif
2442 }
2443 // create and send response header
2444 TSyncHeader *syncheaderP;
2445 MP_NEW(syncheaderP,DBG_OBJINST,"TSyncHeader",TSyncHeader(this,aNoResp))syncheaderP = new TSyncHeader(this,aNoResp);
2446 PDEBUGBLOCKFMT(("SyncHdr","SyncHdr generation","SyncMLVers=%s|OutgoingMsgID=%ld",SyncMLVerDTDNames[fSyncMLVersion],(long)fOutgoingMsgID))getDbgLogger()->DebugOpenBlockExpanded ("SyncHdr","SyncHdr generation"
,"SyncMLVers=%s|OutgoingMsgID=%ld",SyncMLVerDTDNames[fSyncMLVersion
],(long)fOutgoingMsgID)
;
2447 SYSYNC_TRYtry {
2448 // Note: do not use session's issue(), as this is designed for real commands, not headers
2449 if (syncheaderP->issue(0,fOutgoingMsgID)) {
2450 // - queue for status
2451 PDEBUGPRINTFX(DBG_PROTO,("SyncHdr: issued in MsgID=%ld, now queueing for status",(long)syncheaderP->getMsgID())){ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ("SyncHdr: issued in MsgID=%ld, now queueing for status"
,(long)syncheaderP->getMsgID()); }
;
2452 syncheaderP->setWaitingForStatus(true);
2453 fStatusWaitCommands.push_back(syncheaderP);
2454 }
2455 else {
2456 PDEBUGPRINTFX(DBG_PROTO,("SyncHdr: issued in MsgID=%ld, now deleting",(long)syncheaderP->getMsgID())){ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ("SyncHdr: issued in MsgID=%ld, now deleting"
,(long)syncheaderP->getMsgID()); }
;
2457 delete syncheaderP; // not used any more
2458 }
2459 DEBUGPRINTFX(DBG_PROTO,("Outgoing Message size is now %ld bytes",(long)getOutgoingMessageSize())){ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ("Outgoing Message size is now %ld bytes"
,(long)getOutgoingMessageSize()); }
;
2460 // - init number of commands in message
2461 fOutgoingCmds=0;
2462 // - now issue all commands that could not yet be sent because outgoing
2463 // message was not started
2464 #ifdef SYDEBUG2
2465 if (fHeaderWaitCommands.size()>0) {
2466 PDEBUGPRINTFX(DBG_SESSION,("Sending %ld commands that were queued because header was not yet generated",(long)fHeaderWaitCommands.size())){ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("Sending %ld commands that were queued because header was not yet generated"
,(long)fHeaderWaitCommands.size()); }
;
2467 }
2468 #endif
2469 TSmlCommandPContainer::iterator pos;
2470 while (!fAborted) {
2471 // first in list
2472 pos=fHeaderWaitCommands.begin();
2473 if (pos==fHeaderWaitCommands.end()) break; // done
2474 // take command out of the list
2475 TSmlCommand *cmdP=(*pos);
2476 fHeaderWaitCommands.erase(pos);
2477 if (!cmdP) {
2478 DEBUGPRINTFX(DBG_ERROR,("There was a NULL command in the fHeaderWaitCommands queue?!?")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("There was a NULL command in the fHeaderWaitCommands queue?!?"
); }
;
2479 continue;
2480 }
2481 // issue now (as if all were OK for synchdr, because fNeedToAnswer may not be affected here!)
2482 if (!issuePtr(cmdP,fNextMessageCommands,fInterruptedCommandP,false,true)) {
2483 PDEBUGPRINTFX(DBG_SESSION,("Could not issue queued command")){ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("Could not issue queued command"
); }
;
2484 break;
2485 }
2486 }
2487 PDEBUGENDBLOCK("SyncHdr")getDbgLogger()->DebugCloseBlock( "SyncHdr");
2488 }
2489 SYSYNC_CATCH (...)catch(...) {
2490 PDEBUGENDBLOCK("SyncHdr")getDbgLogger()->DebugCloseBlock( "SyncHdr");
2491 delete syncheaderP; // not used any more
2492 SYSYNC_RETHROWthrow; // rethrow
2493 SYSYNC_ENDCATCH}
2494} // TSyncSession::IssueHeader
2495
2496
2497
2498
2499// process a command (analyze and execute it).
2500// Ownership of command is passed to process() in all cases.
2501// Note: This method does not throw exceptions (catches all) and
2502// is suitable for being called without further precautions from
2503// SyncML toolkit callbacks. Exceptions are translated to
2504// smlXXX error codes.
2505Ret_t TSyncSession::process(TSmlCommand *aSyncCommandP)
2506{
2507 if (aSyncCommandP) {
2508 SYSYNC_TRYtry {
2509 // first analyze it (before we can open the block, as we need to find cmdID fisrt)
2510 if (!aSyncCommandP->analyze(fIncomingState)) {
2511 // bad command
2512 PDEBUGPRINTFX(DBG_ERROR,("%s: command failed analyze() -> aborting session",aSyncCommandP->getName())){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("%s: command failed analyze() -> aborting session"
,aSyncCommandP->getName()); }
;
2513 AbortSession(400,true); // local problem
2514 delete aSyncCommandP;
2515 }
2516 else {
2517 // command ok so far (has cmdid, so we can refer to it)
2518 PDEBUGBLOCKFMT(("processCmd","Processing incoming command",getDbgLogger()->DebugOpenBlockExpanded ("processCmd","Processing incoming command"
, "Cmd=%s|IncomingMsgID=%ld|CmdID=%ld", aSyncCommandP->getName
(), (long)aSyncCommandP->getMsgID(), (long)aSyncCommandP->
getCmdID() )
2519 "Cmd=%s|IncomingMsgID=%ld|CmdID=%ld",getDbgLogger()->DebugOpenBlockExpanded ("processCmd","Processing incoming command"
, "Cmd=%s|IncomingMsgID=%ld|CmdID=%ld", aSyncCommandP->getName
(), (long)aSyncCommandP->getMsgID(), (long)aSyncCommandP->
getCmdID() )
2520 aSyncCommandP->getName(),getDbgLogger()->DebugOpenBlockExpanded ("processCmd","Processing incoming command"
, "Cmd=%s|IncomingMsgID=%ld|CmdID=%ld", aSyncCommandP->getName
(), (long)aSyncCommandP->getMsgID(), (long)aSyncCommandP->
getCmdID() )
2521 (long)aSyncCommandP->getMsgID(),getDbgLogger()->DebugOpenBlockExpanded ("processCmd","Processing incoming command"
, "Cmd=%s|IncomingMsgID=%ld|CmdID=%ld", aSyncCommandP->getName
(), (long)aSyncCommandP->getMsgID(), (long)aSyncCommandP->
getCmdID() )
2522 (long)aSyncCommandP->getCmdID()getDbgLogger()->DebugOpenBlockExpanded ("processCmd","Processing incoming command"
, "Cmd=%s|IncomingMsgID=%ld|CmdID=%ld", aSyncCommandP->getName
(), (long)aSyncCommandP->getMsgID(), (long)aSyncCommandP->
getCmdID() )
2523 ))getDbgLogger()->DebugOpenBlockExpanded ("processCmd","Processing incoming command"
, "Cmd=%s|IncomingMsgID=%ld|CmdID=%ld", aSyncCommandP->getName
(), (long)aSyncCommandP->getMsgID(), (long)aSyncCommandP->
getCmdID() )
;
2524 SYSYNC_TRYtry {
2525 // - test if processing is enabled
2526 if (fIgnoreIncomingCommands && !aSyncCommandP->neverIgnore()) {
2527 // commands must be ignored (fatal error in previous command/header)
2528 PDEBUGPRINTFX(DBG_ERROR,("%s: IGNORED ",aSyncCommandP->getName())){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("%s: IGNORED "
,aSyncCommandP->getName()); }
;
2529 // - still generate status (except if aborted status is 0, which means silent abort)
2530 // but DO NOT generate status for status!
2531 if (fStatusCodeForIgnored!=0 && aSyncCommandP->getCmdType()!=scmd_status) {
2532 PDEBUGPRINTFX(DBG_ERROR,(" Sending status %hd for ignored command",fStatusCodeForIgnored)){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask (" Sending status %hd for ignored command"
,fStatusCodeForIgnored); }
;
2533 TStatusCommand *aStatusCmdP = aSyncCommandP->newStatusCommand(fStatusCodeForIgnored);
2534 issueRootPtr(aStatusCmdP);
2535 }
2536 // - delete unexecuted
2537 delete aSyncCommandP;
2538 }
2539 else if (
2540 // Be extra careful: even if fStrictExecOrdering=false, still delay
2541 // further commands if they would overtake non-trivial commands in the
2542 // delay queue. This solves a particular problem where the Sync command
2543 // gets delayed due to slow TStdLogicDS::startDataAccessForServer().
2544 // The server then sees a second (fake?!) Sync command (incoming MsgID=2, CmdID=0)
2545 // which it must delay instead of executing it.
2546 (fStrictExecOrdering || !onlyItemChangesPending()) &&
2547 fDelayedExecutionCommands.size()>0 &&
2548 aSyncCommandP->getCmdType()!=scmd_status &&
2549 aSyncCommandP->getCmdType()!=scmd_alert
2550 ) {
2551 // some commands have been delayed already -> delay all non-statuses and alerts as well
2552 PDEBUGPRINTFX(DBG_SESSION,("%s: command received after other commands needed to be delayed -> must be delayed, too",aSyncCommandP->getName())){ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("%s: command received after other commands needed to be delayed -> must be delayed, too"
,aSyncCommandP->getName()); }
;
2553 // - put into delayed execution queue
2554 delayExecUntilNextRequest(aSyncCommandP);
2555 }
2556 else {
2557 if (fDelayedExecutionCommands.size()>0 &&
2558 !aSyncCommandP->canExecuteOutOfOrder()) {
2559 PDEBUGPRINTFX(DBG_SESSION,("%s: command cannot be executed with other commands already delayed -> flush queue",aSyncCommandP->getName())){ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("%s: command cannot be executed with other commands already delayed -> flush queue"
,aSyncCommandP->getName()); }
;
2560 fCmdIncoming = NULL__null;
2561 tryDelayedExecutionCommands();
2562 }
2563
2564 // command is ok, execute it
2565 fCmdIncomingState=aSyncCommandP->getPackageState();
2566 // Queue Status commands issued during execute()?
2567 if (fDelayedExecutionCommands.size()>0 &&
2568 aSyncCommandP->getCmdType()!=scmd_status &&
2569 aSyncCommandP->getCmdType()!=scmd_alert) {
2570 // Yes, let issueRootPtr() attach to queue in aSyncCommandP and issue later
2571 // in tryDelayedExecutionCommands() resp. executeDelayedCmd().
2572 fCmdIncoming=aSyncCommandP;
2573 } else {
2574 fCmdIncoming=NULL__null;
2575 }
2576 if (aSyncCommandP->execute()) {
2577 // execution finished, can be deleted
2578 if (aSyncCommandP->finished()) {
2579 if (aSyncCommandP->hasQueuedStatusCmds()) {
2580 PDEBUGPRINTFX(DBG_SESSION,("%s: command finished execution with pending Status replies -> queue command",aSyncCommandP->getName())){ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("%s: command finished execution with pending Status replies -> queue command"
,aSyncCommandP->getName()); }
;
2581 delayExecUntilNextRequest(aSyncCommandP);
2582 } else {
2583 PDEBUGPRINTFX(DBG_SESSION,("%s: command finished execution -> deleting",aSyncCommandP->getName())){ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("%s: command finished execution -> deleting"
,aSyncCommandP->getName()); }
;
2584 delete aSyncCommandP;
2585 }
2586 }
2587 else {
2588 PDEBUGPRINTFX(DBG_SESSION,("%s: command NOT finished execution, NOT deleting now",aSyncCommandP->getName())){ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("%s: command NOT finished execution, NOT deleting now"
,aSyncCommandP->getName()); }
;
2589 }
2590 }
2591 else {
2592 // command has not finished execution, must be retried after next incoming message
2593 PDEBUGPRINTFX(DBG_SESSION,("%s: command wants re-execution later -> queueing",aSyncCommandP->getName())){ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("%s: command wants re-execution later -> queueing"
,aSyncCommandP->getName()); }
;
2594 // - put into delayed execution queue
2595 delayExecUntilNextRequest(aSyncCommandP);
2596 }
2597 } // if not ignored
2598 // successfully processed
2599 fCmdIncoming=NULL__null;
2600 PDEBUGENDBLOCK("processCmd")getDbgLogger()->DebugCloseBlock( "processCmd");
2601 } // try
2602 SYSYNC_CATCH (...)catch(...) {
2603 fCmdIncoming=NULL__null;
2604 PDEBUGENDBLOCK("processCmd")getDbgLogger()->DebugCloseBlock( "processCmd");
2605 SYSYNC_RETHROWthrow;
2606 SYSYNC_ENDCATCH}
2607 } // if analyzed successfully
2608 }
2609 SYSYNC_CATCH (TSmlException &e)catch(TSmlException &e) {
2610 // Sml error exception somewhere in command processing
2611 // - make sure command is deleted (as issue owns it now)
2612 delete aSyncCommandP;
2613 PDEBUGPRINTFX(DBG_ERROR,("WARNING: process(cmd) SmlException: %s, smlerr=%hd",e.what(),e.getSmlError())){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("WARNING: process(cmd) SmlException: %s, smlerr=%hd"
,e.what(),e.getSmlError()); }
;
2614 // - return SML error that caused this exception
2615 return e.getSmlError();
2616 SYSYNC_ENDCATCH}
2617 SYSYNC_CATCH (TSyncException &e)catch(TSyncException &e) {
2618 // sync exception during command processing
2619 // - make sure command is deleted (as issue owns it now)
2620 delete aSyncCommandP;
2621 PDEBUGPRINTFX(DBG_ERROR,("WARNING: process(cmd) SyncException: %s, status=%hd",e.what(),e.status())){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("WARNING: process(cmd) SyncException: %s, status=%hd"
,e.what(),e.status()); }
;
2622 // - unspecific SyncML toolkit error, causes session to abort
2623 return SML_ERR_UNSPECIFIC0x10;
2624 SYSYNC_ENDCATCH}
2625 SYSYNC_CATCH (exception &e)catch(exception &e) {
2626 // C++ exception during command processing
2627 // - make sure command is deleted (as issue owns it now)
2628 delete aSyncCommandP;
2629 PDEBUGPRINTFX(DBG_ERROR,("WARNING: process(cmd) Exception: %s",e.what())){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("WARNING: process(cmd) Exception: %s"
,e.what()); }
;
2630 // - unspecific SyncML toolkit error, causes session to abort
2631 return SML_ERR_UNSPECIFIC0x10;
2632 SYSYNC_ENDCATCH}
2633 SYSYNC_CATCH (...)catch(...) {
2634 // other exception during command processing
2635 // - make sure command is deleted (as issue owns it now)
2636 delete aSyncCommandP;
2637 PDEBUGPRINTFX(DBG_ERROR,("WARNING: process(cmd) unknown exception: -> cmd deleted")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("WARNING: process(cmd) unknown exception: -> cmd deleted"
); }
;
2638 // - unspecific SyncML toolkit error, causes session to abort
2639 return SML_ERR_UNSPECIFIC0x10;
2640 SYSYNC_ENDCATCH}
2641 }
2642 // successful
2643 return SML_ERR_OK0x00;
2644} // TSyncSession::process
2645
2646
2647// process synchdr (analyze and execute it).
2648// Ownership of command is passed to process() in all cases.
2649// Note: May cause session reset if message sequence numbers are not ok.
2650Ret_t TSyncSession::processHeader(TSyncHeader *aSyncHdrP)
2651{
2652 if (aSyncHdrP) {
2653 PDEBUGBLOCKDESC("processHdr","Processing incoming SyncHdr")getDbgLogger()->DebugOpenBlock( "processHdr","Processing incoming SyncHdr"
)
;
2654 SYSYNC_TRYtry {
2655 // init some session vars
2656 // - do not ignore commands by default
2657 fIgnoreIncomingCommands=false;
2658 // - need to answer raises out of first non-synchdr-status command issue()d
2659 fNeedToAnswer=false; // no need yet
2660 // - initialize message status
2661 fMsgNoResp=false; // default to response for messages
2662 fIncomingMsgID++; // count this incoming message
2663 // init flag
2664 bool tryagain=false;
2665 do {
2666 // first analyze header
2667 if (!aSyncHdrP->analyze(fIncomingState)) {
2668 // bad command
2669 PDEBUGPRINTFX(DBG_ERROR,("%s: failed analyze() -> deleting",aSyncHdrP->getName())){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("%s: failed analyze() -> deleting"
,aSyncHdrP->getName()); }
;
2670 delete aSyncHdrP;
2671 aSyncHdrP = NULL__null;
2672 }
2673 else {
2674 // command is ok, execute it
2675 fCmdIncomingState=aSyncHdrP->getPackageState();
2676 PDEBUGBLOCKFMT(("SyncHdr","Processing incoming SyncHdr",getDbgLogger()->DebugOpenBlockExpanded ("SyncHdr","Processing incoming SyncHdr"
, "IncomingMsgID=%ld", (long)fIncomingMsgID )
2677 "IncomingMsgID=%ld",getDbgLogger()->DebugOpenBlockExpanded ("SyncHdr","Processing incoming SyncHdr"
, "IncomingMsgID=%ld", (long)fIncomingMsgID )
2678 (long)fIncomingMsgIDgetDbgLogger()->DebugOpenBlockExpanded ("SyncHdr","Processing incoming SyncHdr"
, "IncomingMsgID=%ld", (long)fIncomingMsgID )
2679 ))getDbgLogger()->DebugOpenBlockExpanded ("SyncHdr","Processing incoming SyncHdr"
, "IncomingMsgID=%ld", (long)fIncomingMsgID )
;
2680 SYSYNC_TRYtry {
2681 if (aSyncHdrP->execute()) {
2682 // show session info after processing header
2683 #ifdef SYDEBUG2
2684 PDEBUGPRINTFX(DBG_HOT,("Incoming SyncHdr processed, incomingMsgID=%ld, SyncMLVers=%s",(long)fIncomingMsgID,SyncMLVerDTDNames[fSyncMLVersion])){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("Incoming SyncHdr processed, incomingMsgID=%ld, SyncMLVers=%s"
,(long)fIncomingMsgID,SyncMLVerDTDNames[fSyncMLVersion]); }
;
2685 PDEBUGPRINTFX(DBG_HOT,("- Session ID='%s'",fSynchdrSessionID.c_str())){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("- Session ID='%s'"
,fSynchdrSessionID.c_str()); }
;
2686 PDEBUGPRINTFX(DBG_HOT,("- Source (Remote party): URI='%s' DisplayName='%s'",fRemoteURI.c_str(),fRemoteName.c_str())){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("- Source (Remote party): URI='%s' DisplayName='%s'"
,fRemoteURI.c_str(),fRemoteName.c_str()); }
;
2687 PDEBUGPRINTFX(DBG_HOT,("- Response to be sent to URI='%s'",fRespondURI.empty() ? "[none specified, back to source]" : fRespondURI.c_str())){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("- Response to be sent to URI='%s'"
,fRespondURI.empty() ? "[none specified, back to source]" : fRespondURI
.c_str()); }
;
2688 PDEBUGPRINTFX(DBG_HOT,("- Target (Local party) : URI='%s' DisplayName='%s'",fLocalURI.c_str(),fLocalName.c_str())){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("- Target (Local party) : URI='%s' DisplayName='%s'"
,fLocalURI.c_str(),fLocalName.c_str()); }
;
2689 #endif
2690 CONSOLEPRINTF(("> SyncML message #%ld received from '%s'",(long)fIncomingMsgID,fRemoteURI.c_str()))SySync_ConsolePrintf(stderr, "SYSYNC " "> SyncML message #%ld received from '%s'"
"\n",(long)fIncomingMsgID,fRemoteURI.c_str())
;
2691 // - UTC support is implied for SyncML 1.0 (as most devices support it, and
2692 // there is was no way to signal it in 1.0).
2693 if (!fRemoteDevInfKnown && fSyncMLVersion==syncml_vers_1_0) fRemoteCanHandleUTC=true;
2694 // execution finished, can be deleted
2695 PDEBUGPRINTFX(DBG_SESSION,("%s: finished execution -> deleting",aSyncHdrP->getName())){ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("%s: finished execution -> deleting"
,aSyncHdrP->getName()); }
;
2696 delete aSyncHdrP;
2697 aSyncHdrP = NULL__null;
2698 // now execute delayed commands (before executing new ones)
2699 PDEBUGPRINTFX(DBG_SESSION,("New message: Executing %ld delayed commands",(long)fDelayedExecutionCommands.size())){ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("New message: Executing %ld delayed commands"
,(long)fDelayedExecutionCommands.size()); }
;
2700 bool syncEndAfterSyncPackageEnd=tryDelayedExecutionCommands();
2701 // check if all delayed commands are executed now
2702 if (fDelayedExecSyncEnds<=0 && syncEndAfterSyncPackageEnd) {
2703 // there was at least one queued syncend executed AFTER end of incoming sync package
2704 // This means that we must finalize the sync-from-remote phase for the datastores here
2705 // (as it was suppressed when the incoming sync package had ended)
2706 TLocalDataStorePContainer::iterator dspos;
2707 for (dspos=fLocalDataStores.begin(); dspos!=fLocalDataStores.end(); ++dspos) {
2708 (*dspos)->engEndOfSyncFromRemote(true);
2709 }
2710 }
2711 else {
2712 PDEBUGPRINTFX(DBG_SESSION,("%ld delayed commands could not yet be executed and are left in the queue for next message",(long)fDelayedExecutionCommands.size())){ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("%ld delayed commands could not yet be executed and are left in the queue for next message"
,(long)fDelayedExecutionCommands.size()); }
;
2713 }
2714 // now issue next package commands if any
2715 if (fNewOutgoingPackage) {
2716 PDEBUGPRINTFX(DBG_SESSION,("New package: Sending %ld commands that were generated earlier for this package",(long)fNextPackageCommands.size())){ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("New package: Sending %ld commands that were generated earlier for this package"
,(long)fNextPackageCommands.size()); }
;
2717 TSmlCommandPContainer::iterator nppos;
2718 for (nppos=fNextPackageCommands.begin(); nppos!=fNextPackageCommands.end(); nppos++) {
2719 // issue it (might land in NextMessageCommands)
2720 issueRootPtr((*nppos));
2721 }
2722 // done sending next package commands
2723 fNextPackageCommands.clear(); // clear list
2724 }
2725 // done, don't try again
2726 break;
2727 }
2728 else {
2729 // unexecutable SyncHdr
2730 // - could be resent message
2731 if (fMessageRetried) {
2732 // simply abort processing, let transport handle this
2733 PDEBUGENDBLOCK("processHdr")getDbgLogger()->DebugCloseBlock( "processHdr");
2734 return LOCERR_RETRYMSG; // signal retry has happened
2735 }
2736 // - let agent decide what to do (and whether to try again executing the command)
2737 DEBUGPRINTFX(DBG_SESSION,("%s: Cannot be executed properly, trying to recover",aSyncHdrP->getName())){ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("%s: Cannot be executed properly, trying to recover"
,aSyncHdrP->getName()); }
;
2738 tryagain = syncHdrFailure(tryagain);
2739 } // synchdr not ok
2740 } // try
2741 SYSYNC_CATCH (...)catch(...) {
2742 PDEBUGENDBLOCK("SyncHdr")getDbgLogger()->DebugCloseBlock( "SyncHdr");
2743 SYSYNC_RETHROWthrow;
2744 SYSYNC_ENDCATCH}
2745 }
2746 } while(tryagain && aSyncHdrP);
2747 PDEBUGENDBLOCK("SyncHdr")getDbgLogger()->DebugCloseBlock( "SyncHdr");
2748 }
2749 SYSYNC_CATCH (TSmlException &e)catch(TSmlException &e) {
2750 // Sml error exception somewhere in command processing
2751 // - make sure command is deleted (as issue owns it now)
2752 delete aSyncHdrP;
2753 PDEBUGPRINTFX(DBG_ERROR,("WARNING: synchdr SmlException: %s, smlerr=%hd",e.what(),e.getSmlError())){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("WARNING: synchdr SmlException: %s, smlerr=%hd"
,e.what(),e.getSmlError()); }
;
2754 PDEBUGENDBLOCK("processHdr")getDbgLogger()->DebugCloseBlock( "processHdr");
2755 // - return SML error that caused this exception
2756 return e.getSmlError();
2757 SYSYNC_ENDCATCH}
2758 SYSYNC_CATCH (exception &e)catch(exception &e) {
2759 // C++ exception somewhere in command processing
2760 // - make sure command is deleted (as issue owns it now)
2761 delete aSyncHdrP;
2762 PDEBUGPRINTFX(DBG_ERROR,("WARNING: synchdr exception: %s",e.what())){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("WARNING: synchdr exception: %s"
,e.what()); }
;
2763 PDEBUGENDBLOCK("processHdr")getDbgLogger()->DebugCloseBlock( "processHdr");
2764 // - return SML error that caused this exception
2765 return SML_ERR_UNSPECIFIC0x10;
2766 SYSYNC_ENDCATCH}
2767 SYSYNC_CATCH (...)catch(...) {
2768 // other exception during command processing
2769 // - make sure command is deleted (as issue owns it now)
2770 delete aSyncHdrP;
2771 PDEBUGPRINTFX(DBG_ERROR,("WARNING: synchdr unknown-class exception: -> deleted")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("WARNING: synchdr unknown-class exception: -> deleted"
); }
;
2772 PDEBUGENDBLOCK("processHdr")getDbgLogger()->DebugCloseBlock( "processHdr");
2773 // - unspecific SyncML toolkit error, causes session to abort
2774 return SML_ERR_UNSPECIFIC0x10;
2775 SYSYNC_ENDCATCH}
2776 }
2777 // successful
2778 PDEBUGENDBLOCK("processHdr")getDbgLogger()->DebugCloseBlock( "processHdr");
2779 return SML_ERR_OK0x00;
2780} // TSyncSession::processHeader
2781
2782bool TSyncSession::onlyItemChangesPending()
2783{
2784 TSmlCommandPContainer::iterator pos=fDelayedExecutionCommands.begin();
2785 while (pos!=fDelayedExecutionCommands.end()) {
2786 TSmlCommand *cmdP = *pos;
2787 switch (cmdP->getCmdType()) {
2788 // A white-list of commands perform simple data changes.
2789 // These commands can be overtaken by the execution of
2790 // other commands, see TSyncSession::process().
2791 case scmd_add:
2792 case scmd_delete:
2793 case scmd_replace:
2794 case scmd_copy:
2795 break;
2796 default:
2797 return false;
2798 }
2799 ++pos;
2800 }
2801 return true;
2802}
2803
2804bool TSyncSession::onlySyncPending()
2805{
2806 TSmlCommandPContainer::iterator pos=fDelayedExecutionCommands.begin();
2807 while (pos!=fDelayedExecutionCommands.end()) {
2808 TSmlCommand *cmdP = *pos;
2809 if (cmdP->getCmdType() != scmd_sync) {
2810 return false;
2811 }
2812 ++pos;
2813 }
2814 return true;
2815}
2816
2817bool TSyncSession::tryDelayedExecutionCommands()
2818{
2819 bool syncEndAfterSyncPackageEnd=false;
2820 // Always try issuing the first command until queue is empty.
2821 while (!fDelayedExecutionCommands.empty()) {
2822 // execute again
2823 TSmlCommand *cmdP = fDelayedExecutionCommands.front();
2824 // command ok so far (has cmdid, so we can refer to it)
2825 PDEBUGBLOCKFMT(("executeDelayedCmd","Re-executing command from delayed queue",getDbgLogger()->DebugOpenBlockExpanded ("executeDelayedCmd"
,"Re-executing command from delayed queue", "Cmd=%s|IncomingMsgID=%ld|CmdID=%ld"
, cmdP->getName(), (long)cmdP->getMsgID(), (long)cmdP->
getCmdID() )
2826 "Cmd=%s|IncomingMsgID=%ld|CmdID=%ld",getDbgLogger()->DebugOpenBlockExpanded ("executeDelayedCmd"
,"Re-executing command from delayed queue", "Cmd=%s|IncomingMsgID=%ld|CmdID=%ld"
, cmdP->getName(), (long)cmdP->getMsgID(), (long)cmdP->
getCmdID() )
2827 cmdP->getName(),getDbgLogger()->DebugOpenBlockExpanded ("executeDelayedCmd"
,"Re-executing command from delayed queue", "Cmd=%s|IncomingMsgID=%ld|CmdID=%ld"
, cmdP->getName(), (long)cmdP->getMsgID(), (long)cmdP->
getCmdID() )
2828 (long)cmdP->getMsgID(),getDbgLogger()->DebugOpenBlockExpanded ("executeDelayedCmd"
,"Re-executing command from delayed queue", "Cmd=%s|IncomingMsgID=%ld|CmdID=%ld"
, cmdP->getName(), (long)cmdP->getMsgID(), (long)cmdP->
getCmdID() )
2829 (long)cmdP->getCmdID()getDbgLogger()->DebugOpenBlockExpanded ("executeDelayedCmd"
,"Re-executing command from delayed queue", "Cmd=%s|IncomingMsgID=%ld|CmdID=%ld"
, cmdP->getName(), (long)cmdP->getMsgID(), (long)cmdP->
getCmdID() )
2830 ))getDbgLogger()->DebugOpenBlockExpanded ("executeDelayedCmd"
,"Re-executing command from delayed queue", "Cmd=%s|IncomingMsgID=%ld|CmdID=%ld"
, cmdP->getName(), (long)cmdP->getMsgID(), (long)cmdP->
getCmdID() )
;
2831 SYSYNC_TRYtry {
2832 fCmdIncomingState=cmdP->getPackageState();
2833 if (executeDelayedCmd(cmdP)) {
2834 // check if this was a syncend which was now executed AFTER the end of the incoming sync package
2835 if (cmdP->getCmdType()==scmd_syncend) {
2836 fDelayedExecSyncEnds--; // count executed syncend
2837 if (cmdP->getPackageState()!=fIncomingState)
2838 syncEndAfterSyncPackageEnd=true; // remember that we had at least one
2839 }
2840 // execution finished, can be deleted
2841 if (fIncompleteDataCommandP == cmdP) {
2842 PDEBUGPRINTFX(DBG_SESSION,("%s: command incomplete -> keeping it for next message",cmdP->getName())){ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("%s: command incomplete -> keeping it for next message"
,cmdP->getName()); }
;
2843 } else {
2844 PDEBUGPRINTFX(DBG_SESSION,("%s: command finished execution -> deleting",cmdP->getName())){ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("%s: command finished execution -> deleting"
,cmdP->getName()); }
;
2845 delete cmdP;
2846 }
2847 // delete from queue
2848 fDelayedExecutionCommands.pop_front();
2849 }
2850 else {
2851 // command has not finished execution, must be retried after next incoming message
2852 PDEBUGPRINTFX(DBG_SESSION,("%s: command STILL NOT finished execution -> keep it (and all follwoing) in queue ",cmdP->getName())){ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("%s: command STILL NOT finished execution -> keep it (and all follwoing) in queue "
,cmdP->getName()); }
;
2853 // keep this and all subsequent commands in the queue
2854 PDEBUGENDBLOCK("executeDelayedCmd")getDbgLogger()->DebugCloseBlock( "executeDelayedCmd");
2855 break;
2856 }
2857 PDEBUGENDBLOCK("executeDelayedCmd")getDbgLogger()->DebugCloseBlock( "executeDelayedCmd");
2858 } // try
2859 SYSYNC_CATCH (...)catch(...) {
2860 PDEBUGENDBLOCK("executeDelayedCmd")getDbgLogger()->DebugCloseBlock( "executeDelayedCmd");
2861 SYSYNC_RETHROWthrow;
2862 SYSYNC_ENDCATCH}
2863 }
2864 return syncEndAfterSyncPackageEnd;
2865}
2866
2867bool TSyncSession::executeDelayedCmd(TSmlCommand *aCmdP)
2868{
2869 if (aCmdP->hasQueuedStatusCmds()) {
2870 // The only way how such a command can end up in the queue is
2871 // if it has finished earlier. Now we can try to issue the
2872 // queued status replies, because all previous commands have
2873 // been dealt with.
2874
2875 // If a Sync command was queued, all of its SyncOp commands
2876 // were also queued. We are going to execute them now for the
2877 // first time, which depends on having fLocalSyncDatastoreP
2878 // set correctly (see TSyncOpCommand::execute()). This was
2879 // set when executing the Sync command for the first time, and
2880 // must be restored here, otherwise we end up using the
2881 // fLocalSyncDatastoreP from, for example, a previously resumed
2882 // SyncOp from a different datastore.
2883 if (aCmdP->getCmdType()==scmd_sync) {
2884 TSyncCommand *syncCommandP=static_cast<TSyncCommand *>(aCmdP);
2885 fLocalSyncDatastoreP=syncCommandP->getLocalDatastore();
2886 PDEBUGPRINTFX(DBG_SESSION,("executeDelayedCmd: restore fLocalSyncDatastoreP from sync command")){ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("executeDelayedCmd: restore fLocalSyncDatastoreP from sync command"
); }
;
2887 }
2888
2889 // Take over ownership of all queued status commands.
2890 TSmlCommandPContainer statusCmds;
2891 aCmdP->transferQueuedStatusCmds(statusCmds);
2892 SYSYNC_TRYtry {
2893 while (!statusCmds.empty()) {
2894 TSmlCommand *statusCmdP=statusCmds.front();
2895 statusCmds.pop_front();
2896 // All commands for which we might queue statuses send
2897 // them with default parameters (see synccommand.cpp).
2898 // Therefore we can do the same here, without having to
2899 // store the parameters.
2900 issueRootPtr(statusCmdP);
2901 }
2902 }
2903 SYSYNC_CATCH (...)catch(...) {
2904 TSmlCommandPContainerClear(statusCmds);
2905 SYSYNC_RETHROWthrow;
2906 SYSYNC_ENDCATCH}
2907 TSmlCommandPContainerClear(statusCmds);
2908 return true;
2909 } else {
2910 return aCmdP->execute();
2911 }
2912}
2913
2914#ifdef __PALM_OS__
2915#pragma segment session2
2916#endif
2917
2918// %%% integrate Results command here, too (that, is, make a common
2919// ancestor for both TStatusCommand and TResultsCommand which
2920// is then handled here in common).
2921// handle a status "command"
2922// Ownership of status is passed to handleStatus() in all cases.
2923// Note: This method does not throw exceptions (catches all) and
2924// is suitable for being called without further precautions from
2925// SyncML toolkit callbacks. Exceptions are translated to
2926// smlXXX error codes.
2927Ret_t TSyncSession::handleStatus(TStatusCommand *aStatusCommandP)
2928{
2929 if (aStatusCommandP) {
2930 PDEBUGBLOCKDESC("processStatus","Processing incoming Status")getDbgLogger()->DebugOpenBlock( "processStatus","Processing incoming Status"
)
;
2931 SYSYNC_TRYtry {
2932 // analyze first
2933 if (!aStatusCommandP->analyze(fIncomingState)) {
2934 // bad command
2935 PDEBUGPRINTFX(DBG_SESSION,("%s: status failed analyze() -> deleting",aStatusCommandP->getName())){ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("%s: status failed analyze() -> deleting"
,aStatusCommandP->getName()); }
;
2936 delete aStatusCommandP;
2937 }
2938 else {
2939 bool found=false;
2940 // status is ok, find matching command
2941 TSmlCommandPContainer::iterator pos;
2942 for (pos=fStatusWaitCommands.begin(); pos!=fStatusWaitCommands.end(); ++pos) {
2943 if ((*pos)->matchStatus(aStatusCommandP)) {
2944 PDEBUGPRINTFX(DBG_PROTO,("Found matching command '%s' for Status",(*pos)->getName())){ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ("Found matching command '%s' for Status"
,(*pos)->getName()); }
;
2945 (*pos)->setWaitingForStatus(false); // has received status
2946 found=true;
2947 if (fIgnoreIncomingCommands) {
2948 // ignore statuses, but remove waiting command from queue
2949 if ((*pos)->finished()) delete (*pos); // unfinished are owned otherwise and must not be deleted
2950 fStatusWaitCommands.erase(pos);
2951 PDEBUGPRINTFX(DBG_SESSION,("Status ignored, command considered done -> deleted")){ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("Status ignored, command considered done -> deleted"
); }
;
2952 }
2953 else {
2954 // let descendants know when we process a required status
2955 if ((*pos)->statusEssential()) {
2956 essentialStatusReceived();
2957 }
2958 // normally process status
2959 if ((*pos)->handleStatus(aStatusCommandP)) {
2960 PDEBUGPRINTFX(DBG_SESSION,("Status: processed, removed command '%s' from status wait queue",(*pos)->getName())){ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("Status: processed, removed command '%s' from status wait queue"
,(*pos)->getName()); }
;
2961 // done with command, remove from queue
2962 if ((*pos)->finished()) {
2963 // - if this is an interrupted command, make sure to remove pointer
2964 if ((*pos)==fInterruptedCommandP) fInterruptedCommandP=NULL__null;
2965 // - delete command itself
2966 // NOTE; if not finished, command is owned otherwise and must
2967 // persist
2968 PDEBUGPRINTFX(DBG_SESSION,("Status: command '%s' has handled status and allows to be deleted",(*pos)->getName())){ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("Status: command '%s' has handled status and allows to be deleted"
,(*pos)->getName()); }
;
2969 delete (*pos);
2970 }
2971 else {
2972 PDEBUGPRINTFX(DBG_SESSION,("Status: command '%s' has handled status, but not finished() -> NOT deleted",(*pos)->getName())){ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("Status: command '%s' has handled status, but not finished() -> NOT deleted"
,(*pos)->getName()); }
;
2973 }
2974 // - anyway, remove from list
2975 fStatusWaitCommands.erase(pos);
2976 }
2977 else {
2978 // command not yet acknowledged, keep in queue
2979 (*pos)->setWaitingForStatus(true); // is again waiting for a status
2980 PDEBUGPRINTFX(DBG_SESSION,("(intermediate) Status processed, command kept in queue, not deleted")){ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("(intermediate) Status processed, command kept in queue, not deleted"
); }
;
2981 }
2982 } // else normal processing
2983 break; // exit for loop (iterator is not ok any more)
2984 }
2985 } // for
2986 if (!found) {
2987 // no matching command found
2988 PDEBUGPRINTFX(DBG_ERROR,("No command found for status -> ignoring")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("No command found for status -> ignoring"
); }
;
2989 }
2990 // now delete status
2991 delete aStatusCommandP;
2992 } // if analyzed successfully
2993 }
2994 SYSYNC_CATCH (TSmlException &e)catch(TSmlException &e) {
2995 // Sml error exception somewhere in command processing
2996 // - make sure command is deleted (as issue owns it now)
2997 delete aStatusCommandP;
2998 PDEBUGPRINTFX(DBG_ERROR,("WARNING: handleStatus SmlException: %s, smlerr=%hd",e.what(),e.getSmlError())){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("WARNING: handleStatus SmlException: %s, smlerr=%hd"
,e.what(),e.getSmlError()); }
;
2999 PDEBUGENDBLOCK("processStatus")getDbgLogger()->DebugCloseBlock( "processStatus");
3000 // - return SML error that caused this exception
3001 return e.getSmlError();
3002 SYSYNC_ENDCATCH}
3003 SYSYNC_CATCH (exception &e)catch(exception &e) {
3004 // Sml error exception somewhere in command processing
3005 // - make sure command is deleted (as issue owns it now)
3006 delete aStatusCommandP;
3007 PDEBUGPRINTFX(DBG_ERROR,("WARNING: handleStatus exception: %s",e.what())){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("WARNING: handleStatus exception: %s"
,e.what()); }
;
3008 PDEBUGENDBLOCK("processStatus")getDbgLogger()->DebugCloseBlock( "processStatus");
3009 // - unspecific SyncML toolkit error, causes session to abort
3010 return SML_ERR_UNSPECIFIC0x10;
3011 SYSYNC_ENDCATCH}
3012 SYSYNC_CATCH (...)catch(...) {
3013 // other exception during command processing
3014 // - make sure command is deleted (as issue owns it now)
3015 delete aStatusCommandP;
3016 PDEBUGPRINTFX(DBG_ERROR,("WARNING: handleStatus unknown-class exception: -> deleted")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("WARNING: handleStatus unknown-class exception: -> deleted"
); }
;
3017 PDEBUGENDBLOCK("processStatus")getDbgLogger()->DebugCloseBlock( "processStatus");
3018 // - unspecific SyncML toolkit error, causes session to abort
3019 return SML_ERR_UNSPECIFIC0x10;
3020 SYSYNC_ENDCATCH}
3021 }
3022 // successful
3023 PDEBUGENDBLOCK("processStatus")getDbgLogger()->DebugCloseBlock( "processStatus");
3024 return SML_ERR_OK0x00;
3025} // TSyncSession::handleStatus
3026
3027
3028// Session level meta
3029SmlPcdataPtr_t TSyncSession::newHeaderMeta(void)
3030{
3031 SmlPcdataPtr_t metaP = NULL__null;
3032
3033 // create meta for initialisation message only
3034 #ifdef SEND_MAXMSGSIZE_ON_INIT_ONLY
3035 if (fOutgoingState<=psta_init)
3036 #endif
3037 {
3038 metaP=newMeta();
3039 SmlMetInfMetInfPtr_t metinfP = smlPCDataToMetInfP(metaP);
3040 // - add max message size
3041 metinfP->maxmsgsize=newPCDataLong(getRootConfig()->fLocalMaxMsgSize);
3042 if (
3043 (getRootConfig()->fLocalMaxObjSize>0) &&
3044 (fSyncMLVersion>=syncml_vers_1_1)
3045 ) {
3046 // SyncML 1.1 has object size
3047 metinfP->maxobjsize=newPCDataLong(getRootConfig()->fLocalMaxObjSize);
3048 }
3049 }
3050 return metaP;
3051} // TSyncSession::newHeaderMeta
3052
3053
3054// create new SyncHdr structure for TSyncHeader command
3055// (here because all data for this is in session anyway)
3056// Called exclusively from TSyncHeader command
3057SmlSyncHdrPtr_t TSyncSession::NewOutgoingSyncHdr(bool aOutgoingNoResp)
3058{
3059 SmlSyncHdrPtr_t headerP;
3060
3061 MP_SHOWCURRENT(DBG_PROFILE,"Start of outgoing message");
3062 // set response status for entire message
3063 fOutgoingNoResp=aOutgoingNoResp;
3064 // get new number for this message
3065 fOutgoingMsgID++;
3066 // reset message size counting
3067 fOutgoingMsgSize=0;
3068 // reset command ID
3069 fOutgoingCmdID=0;
3070 // now compose Sync Header from session vars
3071 // - create empty header
3072 headerP = SML_NEW(SmlSyncHdr_t)((SmlSyncHdr_t*) _smlMalloc(sizeof(SmlSyncHdr_t)));
3073 #ifdef EXPIRES_AFTER_DATE
3074 // prepare for a check, convert back to normal value * 4
3075 sInt32 scramblednow4 = (fCopyOfScrambledNow-503);
3076 #endif
3077 SYSYNC_TRYtry {
3078 // set proto element type to make it auto-disposable
3079 headerP->elementType=SML_PE_HEADER;
3080 // set version information
3081 headerP->version=newPCDataString(SyncMLVerDTDNames[fSyncMLVersion]);
3082 headerP->proto=newPCDataString(SyncMLVerProtoNames[fSyncMLVersion]);
3083 // set session ID
3084 headerP->sessionID=newPCDataString(fSynchdrSessionID);
3085 // set new message ID for this message
3086 #ifdef APP_CAN_EXPIRE
3087 // check for expiry again
3088 #ifdef EXPIRES_AFTER_DATE
3089 // - has hard expiry date
3090 if (
3091 (scramblednow4>SCRAMBLED_EXPIRY_VALUE*4)
3092 #ifdef SYSER_REGISTRATION
3093 && (!getSyncAppBase()->fRegOK) // only abort if no registration (but accept timed registration)
3094 #endif
3095 )
3096 getSyncAppBase()->fAppExpiryStatus=LOCERR_EXPIRED;
3097 #else
3098 // - no hard expiry date, just check if license is still valid
3099 if (
3100 !getSyncAppBase()->fRegOK || // no registered at all
3101 getSyncAppBase()->fDaysLeft==0 // or expired
3102 )
3103 getSyncAppBase()->fAppExpiryStatus=LOCERR_EXPIRED;
3104 #endif
3105 #endif
3106 headerP->msgID=newPCDataLong(fOutgoingMsgID);
3107 // flags
3108 headerP->flags=fOutgoingNoResp ? SmlNoResp_f0x0100 : 0;
3109 // target (URI/Name of Remote party)
3110 // Note: Tsutomu Uenoyama (uenoyama@trl.mei.co.jp) sais in syncml feedback
3111 // list that server RespURI behaviour should
3112 // be reflecting received RespURI in target, so we do it:
3113 headerP->target=newLocation(
3114 fRespondURI.empty() ? fRemoteURI.c_str() : fRespondURI.c_str(),
3115 fRemoteName.c_str()
3116 );
3117 PDEBUGPRINTFX(DBG_PROTO,("Target (Remote URI) = '%s'",fRespondURI.empty() ? fRemoteURI.c_str() : fRespondURI.c_str())){ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ("Target (Remote URI) = '%s'"
,fRespondURI.empty() ? fRemoteURI.c_str() : fRespondURI.c_str
()); }
;
3118 // source (URI / User-Name of local party)
3119 // NOTE: The LocName must contain the name of the user and not
3120 // the name of the device (this is a SyncML 1.0.1 correction
3121 // to make MD5 auth implementable - we need a clear-text user name)
3122 headerP->source=newLocation(
3123 fLocalURI.c_str(),
3124 getUsernameForRemote() // user name for remote login, NULL if none available
3125 );
3126 // add respURI if local party cannot be responded to via normal URI
3127 // New added for T68i: do not send a RespURI for an aborted session
3128 if (!isAborted() && fMessageAuthorized)
3129 headerP->respURI=newResponseURIForRemote();
3130 else
3131 headerP->respURI=NULL__null;
3132 // add credentials if remote needs them
3133 headerP->cred=newCredentialsForRemote();
3134 // agent-specific meta
3135 headerP->meta=newHeaderMeta();
3136 }
3137 SYSYNC_CATCH (...)catch(...) {
3138 // make sure header is disposed
3139 smlFreeProtoElement(headerP);
3140 SYSYNC_RETHROWthrow; // re-throw
3141 SYSYNC_ENDCATCH}
3142 // return it
3143 return headerP;
3144} // TSyncSession::NewOutgoingSyncHdr
3145
3146
3147// delay command for execution at beginning of next received message
3148void TSyncSession::delayExecUntilNextRequest(TSmlCommand *aCommand)
3149{
3150 // push into delay queue
3151 fDelayedExecutionCommands.push_back(aCommand);
3152 // a delayed (=not processed) syncstart must clear the current fLocalSyncDatastoreP,
3153 // as it is not yet known for that <sync>. This causes syncops to receive a NULL datastore
3154 // at creation, so they must check for that and get it at execute().
3155 if (aCommand->getCmdType()==scmd_sync) {
3156 // delayed <sync> has no datastore (yet)
3157 fLocalSyncDatastoreP=NULL__null;
3158 PDEBUGPRINTFX(DBG_DATA,("delayExecUntilNextRequest: unsetting fLocalSyncDatastoreP for scmd_sync")){ if (((0x00000080) & getDbgMask()) == (0x00000080)) getDbgLogger
()->setNextMask(0x00000080).DebugPrintfLastMask ("delayExecUntilNextRequest: unsetting fLocalSyncDatastoreP for scmd_sync"
); }
;
3159 }
3160 else if (aCommand->getCmdType()==scmd_syncend) {
3161 // count delayed syncends as they need special care later
3162 fDelayedExecSyncEnds++;
3163 if (fLocalSyncDatastoreP) {
3164 // and forget current datastore - safety only, should be NULL here anyway
3165 fLocalSyncDatastoreP=NULL__null;
3166 PDEBUGPRINTFX(DBG_DATA,("processSyncEnd: unsetting fLocalSyncDatastoreP for scmd_syncend")){ if (((0x00000080) & getDbgMask()) == (0x00000080)) getDbgLogger
()->setNextMask(0x00000080).DebugPrintfLastMask ("processSyncEnd: unsetting fLocalSyncDatastoreP for scmd_syncend"
); }
;
3167 }
3168 }
3169} // TSyncSession::delayExecUntilNextRequest
3170
3171
3172// remote party requests next message by Alert 222
3173void TSyncSession::nextMessageRequest(void)
3174{
3175 // count the request
3176 fNextMessageRequests++;
3177 if (IS_SERVER(getSyncAppBase()->isServer())) {
3178 // check if we have seen many requests but could not fulfil them
3179 if (fNextMessageRequests>3) {
3180 // check for resume that does not send us an empty Sync (Symbian client at TestFest 16)
3181 PDEBUGPRINTFX(DBG_ERROR,("Warning: More than 3 consecutive Alert 222 - looks like endless loop, check if we need to work around client implementation issues")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("Warning: More than 3 consecutive Alert 222 - looks like endless loop, check if we need to work around client implementation issues"
); }
;
3182 // - check datastores
3183 TLocalDataStorePContainer::iterator pos;
3184 for (pos=fLocalDataStores.begin(); pos!=fLocalDataStores.end(); ++pos) {
3185 // see if it is currently resuming
3186 TLocalEngineDS *ldsP = (*pos);
3187 if (ldsP->isResuming() && ldsP->getDSState()<dssta_serverseenclientmods) {
3188 // fake empty <sync> from client to get things going again
3189 // - create it
3190 SmlSyncPtr_t fakeSyncCmdP = (SmlSyncPtr_t)smlLibMalloc(sizeof(SmlSync_t));
3191 fakeSyncCmdP->elementType = SML_PE_SYNC_START;
3192 fakeSyncCmdP->cmdID=NULL__null; // none needed here
3193 fakeSyncCmdP->flags=0; // none
3194 fakeSyncCmdP->cred=NULL__null;
3195 fakeSyncCmdP->target=newLocation(ldsP->getName()); // client would target myself
3196 fakeSyncCmdP->source=newLocation(ldsP->getRemoteDBPath()); // client would target myself
3197 fakeSyncCmdP->meta=NULL__null; // no meta
3198 fakeSyncCmdP->noc=NULL__null; // no NOC
3199 // - have it processed like it was a real command
3200 PDEBUGPRINTFX(DBG_HOT+DBG_PROTO,("Probably client expects resume to continue without sending an empty <Sync> -> simulate one")){ if (((0x00000001 +0x00000010) & getDbgMask()) == (0x00000001
+0x00000010)) getDbgLogger()->setNextMask(0x00000001 +0x00000010
).DebugPrintfLastMask ("Probably client expects resume to continue without sending an empty <Sync> -> simulate one"
); }
;
3201 PDEBUGBLOCKFMT((getDbgLogger()->DebugOpenBlockExpanded ( "Resume_Sim_Sync"
,"Simulated empty sync to get resume going", "datastore=%s", ldsP
->getName() )
3202 "Resume_Sim_Sync","Simulated empty sync to get resume going",getDbgLogger()->DebugOpenBlockExpanded ( "Resume_Sim_Sync"
,"Simulated empty sync to get resume going", "datastore=%s", ldsP
->getName() )
3203 "datastore=%s",getDbgLogger()->DebugOpenBlockExpanded ( "Resume_Sim_Sync"
,"Simulated empty sync to get resume going", "datastore=%s", ldsP
->getName() )
3204 ldsP->getName()getDbgLogger()->DebugOpenBlockExpanded ( "Resume_Sim_Sync"
,"Simulated empty sync to get resume going", "datastore=%s", ldsP
->getName() )
3205 ))getDbgLogger()->DebugOpenBlockExpanded ( "Resume_Sim_Sync"
,"Simulated empty sync to get resume going", "datastore=%s", ldsP
->getName() )
;
3206 TStatusCommand *fakeStatusCmdP = new TStatusCommand(this);
3207 bool queueforlater=false;
3208 /* bool ok= */
3209 processSyncStart(
3210 fakeSyncCmdP,
3211 *fakeStatusCmdP,
3212 queueforlater // will be set if command must be queued for later re-execution
3213 );
3214 if (!queueforlater) {
3215 fNextMessageRequests=0; // reset that counter
3216 // and make sure we advance the sync session state
3217 // - now the real ugly hacking starts - we have to fake receiving a <final/>
3218 fFakeFinalFlag=true;
3219 }
3220 else {
3221 PDEBUGPRINTFX(DBG_ERROR,("simulated <Sync> can't be processed now, we'll try again later")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("simulated <Sync> can't be processed now, we'll try again later"
); }
;
3222 }
3223 // now just simulate a </sync>
3224 processSyncEnd(queueforlater);
3225 // now let this particular datastore "know" that sync-from-client is over now
3226 (*pos)->engEndOfSyncFromRemote(true); // fake "final"
3227 PDEBUGENDBLOCK("Resume_Sim_Sync")getDbgLogger()->DebugCloseBlock( "Resume_Sim_Sync");
3228 }
3229 }
3230 }
3231 } // server
3232} // TSyncSession::nextMessageRequest
3233
3234
3235
3236
3237// check if session must continue (for session-level reasons, that
3238// is without regarding sync state of server or client)
3239bool TSyncSession::sessionMustContinue(void) {
3240 // if there are delayed commands not yet executed after this message: session must go on
3241 if (!fDelayedExecutionCommands.empty()) {
3242 PDEBUGPRINTFX(DBG_SESSION,({ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ( "%ld commands in delayed-execution-queue -> session must continue"
, (long)fDelayedExecutionCommands.size() ); }
3243 "%ld commands in delayed-execution-queue -> session must continue",{ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ( "%ld commands in delayed-execution-queue -> session must continue"
, (long)fDelayedExecutionCommands.size() ); }
3244 (long)fDelayedExecutionCommands.size(){ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ( "%ld commands in delayed-execution-queue -> session must continue"
, (long)fDelayedExecutionCommands.size() ); }
3245 )){ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ( "%ld commands in delayed-execution-queue -> session must continue"
, (long)fDelayedExecutionCommands.size() ); }
;
3246 return true; // must continue
3247 }
3248 // if no status to wait for: session may be deleted now
3249 if (fStatusWaitCommands.empty()) return false;
3250 TSmlCommandPContainer::iterator pos;
3251 // show them
3252 #ifdef SYDEBUG2
3253 for (pos=fStatusWaitCommands.begin(); pos!=fStatusWaitCommands.end(); ++pos) {
3254 TSmlCommand *cmdP = *pos;
3255 // show that command was not answered
3256 PDEBUGPRINTFX(DBG_PROTO,("- Not yet received %sstatus for command '%s', (outgoing MsgID=%ld, CmdID=%ld)",{ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ("- Not yet received %sstatus for command '%s', (outgoing MsgID=%ld, CmdID=%ld)"
, cmdP->statusEssential() ? "REQUIRED " : "", cmdP->getName
(), (long)cmdP->getMsgID(), (long)cmdP->getCmdID() ); }
3257 cmdP->statusEssential() ? "REQUIRED " : "",{ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ("- Not yet received %sstatus for command '%s', (outgoing MsgID=%ld, CmdID=%ld)"
, cmdP->statusEssential() ? "REQUIRED " : "", cmdP->getName
(), (long)cmdP->getMsgID(), (long)cmdP->getCmdID() ); }
3258 cmdP->getName(),{ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ("- Not yet received %sstatus for command '%s', (outgoing MsgID=%ld, CmdID=%ld)"
, cmdP->statusEssential() ? "REQUIRED " : "", cmdP->getName
(), (long)cmdP->getMsgID(), (long)cmdP->getCmdID() ); }
3259 (long)cmdP->getMsgID(),{ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ("- Not yet received %sstatus for command '%s', (outgoing MsgID=%ld, CmdID=%ld)"
, cmdP->statusEssential() ? "REQUIRED " : "", cmdP->getName
(), (long)cmdP->getMsgID(), (long)cmdP->getCmdID() ); }
3260 (long)cmdP->getCmdID(){ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ("- Not yet received %sstatus for command '%s', (outgoing MsgID=%ld, CmdID=%ld)"
, cmdP->statusEssential() ? "REQUIRED " : "", cmdP->getName
(), (long)cmdP->getMsgID(), (long)cmdP->getCmdID() ); }
3261 )){ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ("- Not yet received %sstatus for command '%s', (outgoing MsgID=%ld, CmdID=%ld)"
, cmdP->statusEssential() ? "REQUIRED " : "", cmdP->getName
(), (long)cmdP->getMsgID(), (long)cmdP->getCmdID() ); }
;
3262 }
3263 #endif
3264 // check type of commands we miss status for
3265 bool mustgoon=false;
3266 for (pos=fStatusWaitCommands.begin(); pos!=fStatusWaitCommands.end(); ++pos) {
3267 TSmlCommand *cmdP = *pos;
3268 if (cmdP->statusEssential()) {
3269 // we need a status for at least one of these
3270 mustgoon=true;
3271 break;
3272 }
3273 }
3274 // if only one single status to wait for, check if it is
3275 // SyncHdr status; if no, session MUST continue
3276 // (otherwise, remote will not send status for SyncHdr alone)
3277 if (mustgoon) {
3278 PDEBUGPRINTFX(DBG_HOT,("SESSION CANNOT END - Not yet received REQUIRED status for some of %ld commands",(long)fStatusWaitCommands.size())){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("SESSION CANNOT END - Not yet received REQUIRED status for some of %ld commands"
,(long)fStatusWaitCommands.size()); }
;
3279 }
3280 return mustgoon;
3281} // TSyncSession::sessionMustContinue
3282
3283
3284// returns true if session has pending commands
3285bool TSyncSession::hasPendingCommands(void)
3286{
3287 return (!(
3288 fNextMessageCommands.size()==0 && // ..no commands to send in next message AND
3289 fDelayedExecutionCommands.size()==0 && // ..no commands to process in next message AND
3290 fInterruptedCommandP==NULL__null // ..no interrupted outgoing commands
3291 ));
3292} // TSyncSession::hasPendingCommands
3293
3294
3295// finish outgoing Message, returns true if final message of package
3296bool TSyncSession::FinishMessage(bool aAllowFinal, bool aForceNonFinal)
3297{
3298 Ret_t err;
3299 bool final=true;
3300
3301 // finish message if any
3302 if (fOutgoingStarted) {
3303 // there is an unfinished message, finish it
3304 // - final only if no commands waiting for next message
3305 // and caller allows final
3306 final=
3307 !aForceNonFinal && (
3308 fAborted || // if aborted, this is a final message, OR..
3309 (aAllowFinal && !hasPendingCommands()) // ..(if allowed final AND no pending commands)
3310 ); // ...THEN this is a final package
3311 PDEBUGPRINTFX(DBG_PROTO,({ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ( "Ending message with %s%ld next-message/%ld next-package commands: %sFINAL (%sfinal %sallowed by caller)"
, fInterruptedCommandP ? "interrupted command and " : "", (long
)fNextMessageCommands.size(), (long)fNextPackageCommands.size
(), final ? "" : "NOT ", fAborted ? "ABORTED, " : "", aAllowFinal
? "" : "not " ); }
3312 "Ending message with %s%ld next-message/%ld next-package commands: %sFINAL (%sfinal %sallowed by caller)",{ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ( "Ending message with %s%ld next-message/%ld next-package commands: %sFINAL (%sfinal %sallowed by caller)"
, fInterruptedCommandP ? "interrupted command and " : "", (long
)fNextMessageCommands.size(), (long)fNextPackageCommands.size
(), final ? "" : "NOT ", fAborted ? "ABORTED, " : "", aAllowFinal
? "" : "not " ); }
3313 fInterruptedCommandP ? "interrupted command and " : "",{ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ( "Ending message with %s%ld next-message/%ld next-package commands: %sFINAL (%sfinal %sallowed by caller)"
, fInterruptedCommandP ? "interrupted command and " : "", (long
)fNextMessageCommands.size(), (long)fNextPackageCommands.size
(), final ? "" : "NOT ", fAborted ? "ABORTED, " : "", aAllowFinal
? "" : "not " ); }
3314 (long)fNextMessageCommands.size(),{ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ( "Ending message with %s%ld next-message/%ld next-package commands: %sFINAL (%sfinal %sallowed by caller)"
, fInterruptedCommandP ? "interrupted command and " : "", (long
)fNextMessageCommands.size(), (long)fNextPackageCommands.size
(), final ? "" : "NOT ", fAborted ? "ABORTED, " : "", aAllowFinal
? "" : "not " ); }
3315 (long)fNextPackageCommands.size(),{ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ( "Ending message with %s%ld next-message/%ld next-package commands: %sFINAL (%sfinal %sallowed by caller)"
, fInterruptedCommandP ? "interrupted command and " : "", (long
)fNextMessageCommands.size(), (long)fNextPackageCommands.size
(), final ? "" : "NOT ", fAborted ? "ABORTED, " : "", aAllowFinal
? "" : "not " ); }
3316 final ? "" : "NOT ",{ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ( "Ending message with %s%ld next-message/%ld next-package commands: %sFINAL (%sfinal %sallowed by caller)"
, fInterruptedCommandP ? "interrupted command and " : "", (long
)fNextMessageCommands.size(), (long)fNextPackageCommands.size
(), final ? "" : "NOT ", fAborted ? "ABORTED, " : "", aAllowFinal
? "" : "not " ); }
3317 fAborted ? "ABORTED, " : "",{ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ( "Ending message with %s%ld next-message/%ld next-package commands: %sFINAL (%sfinal %sallowed by caller)"
, fInterruptedCommandP ? "interrupted command and " : "", (long
)fNextMessageCommands.size(), (long)fNextPackageCommands.size
(), final ? "" : "NOT ", fAborted ? "ABORTED, " : "", aAllowFinal
? "" : "not " ); }
3318 aAllowFinal ? "" : "not "{ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ( "Ending message with %s%ld next-message/%ld next-package commands: %sFINAL (%sfinal %sallowed by caller)"
, fInterruptedCommandP ? "interrupted command and " : "", (long
)fNextMessageCommands.size(), (long)fNextPackageCommands.size
(), final ? "" : "NOT ", fAborted ? "ABORTED, " : "", aAllowFinal
? "" : "not " ); }
3319 )){ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ( "Ending message with %s%ld next-message/%ld next-package commands: %sFINAL (%sfinal %sallowed by caller)"
, fInterruptedCommandP ? "interrupted command and " : "", (long
)fNextMessageCommands.size(), (long)fNextPackageCommands.size
(), final ? "" : "NOT ", fAborted ? "ABORTED, " : "", aAllowFinal
? "" : "not " ); }
;
3320 // - close message now
3321 sInt32 bytesbeforeissue=getSmlWorkspaceFreeBytes();
3322 fOutgoingStarted=false; // done now
3323 fOutgoingMessageFull=false; // message finished, not full any more
3324 #ifdef SYDEBUG2
3325 if (fXMLtranslate && fOutgoingXMLInstance)
3326 smlEndMessage(fOutgoingXMLInstance,final);
3327 // Now dump XML translation of outgoing message
3328 XMLTranslationOutgoingEnd();
3329 #endif
3330 if ((err=smlEndMessage(fSmlWorkspaceID, final))!=SML_ERR_OK0x00) {
3331 SYSYNC_THROW(TSmlException("smlEndMessage",err))throw TSmlException("smlEndMessage",err);
3332 }
3333 incOutgoingMessageSize(bytesbeforeissue-getSmlWorkspaceFreeBytes());
3334 PDEBUGPRINTFX(DBG_PROTO,("Entire message size is now %ld Bytes",(long)getOutgoingMessageSize())){ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ("Entire message size is now %ld Bytes"
,(long)getOutgoingMessageSize()); }
;
3335 // if outgoing message was not final, prevent session end
3336 // except if session is aborted (and final flag is forced nonFinal e.g. when ending session because of serverBusy()
3337 if (!final && !fAborted) fInProgress=true;
3338 CONSOLEPRINTF(("< SyncML message #%ld sent to '%s'",(long)fOutgoingMsgID,fRespondURI.empty() ? fRemoteURI.c_str() : fRespondURI.c_str()))SySync_ConsolePrintf(stderr, "SYSYNC " "< SyncML message #%ld sent to '%s'"
"\n",(long)fOutgoingMsgID,fRespondURI.empty() ? fRemoteURI.c_str
() : fRespondURI.c_str())
;
3339 MP_SHOWCURRENT(DBG_PROFILE,"End of outgoing message");
3340 // dump it if configured
3341 #ifdef SYDEBUG2
3342 DumpSyncMLMessage(true); // outgoing
3343 #endif
3344 }
3345 // if this message ends with <Final/>, next message will be in new package
3346 fNewOutgoingPackage=final;
3347 return final;
3348} // TSyncSession::FinishMessage
3349
3350
3351// get name of current encoding
3352const char *TSyncSession::getEncodingName(void)
3353{
3354 return SyncMLEncodingMIMENames[fEncoding];
3355} // TSyncSession::getEncodingName
3356
3357
3358// add current encoding spec to given (type-)string
3359void TSyncSession::addEncoding(string &aString)
3360{
3361 aString+=SYNCML_ENCODING_SEPARATOR"+";
3362 aString+=getEncodingName();
3363} // TSyncSession::addEncoding
3364
3365
3366// set encoding for session
3367void TSyncSession::setEncoding(SmlEncoding_t aEncoding)
3368{
3369 Ret_t err=smlSetEncoding(fSmlWorkspaceID,aEncoding);
3370 if (err==SML_ERR_OK0x00) {
3371 fEncoding = aEncoding;
3372 }
3373} // TSyncSession::setEncoding
3374
3375
3376// find remote datastore by (remote party specified) URI
3377TRemoteDataStore *TSyncSession::findRemoteDataStore(const char *aDatastoreURI)
3378{
3379 TRemoteDataStorePContainer::iterator pos;
3380 TRemoteDataStore *bestMatchP=NULL__null;
3381 uInt16 bestNumMatched=0;
3382 // search for BEST match (most number of chars matched)
3383 for (pos=fRemoteDataStores.begin(); pos!=fRemoteDataStores.end(); ++pos) {
3384 // test for match
3385 if ((*pos)->isDatastore(aDatastoreURI) > bestNumMatched) {
3386 bestMatchP = *pos; // best so far, but check all
3387 }
3388 }
3389 return bestMatchP; // return NULL if no match found or best matching
3390} // TSyncSession::findRemoteDataStore
3391
3392
3393// - find local datastore by URI and separate identifying from optional part of URI
3394TLocalEngineDS *TSyncSession::findLocalDataStoreByURI(const char *aURI,string *aOptions, string *aIdentifyingURI)
3395{
3396 string dburi;
3397
3398 // - get relative URI of requested database
3399 const char *dblocuri = SessionRelativeURI(aURI);
3400 // In this base class implementation, identification is path, options are CGI
3401 // - separate target address and CGI (if any)
3402 const char *optionsCGI=(const char *)strchr(dblocuri,'?');
3403 if (optionsCGI) {
3404 dburi.assign(dblocuri,optionsCGI-dblocuri);
3405 optionsCGI++; // skip '?'
3406 dblocuri=dburi.c_str();
3407 PDEBUGPRINTFX(DBG_PROTO,("Target Address CGI Options: %s",optionsCGI)){ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ("Target Address CGI Options: %s"
,optionsCGI); }
;
3408 if (aOptions) aOptions->assign(optionsCGI);
3409 }
3410 else {
3411 // no CGI contained
3412 if (aOptions) aOptions->erase();
3413 }
3414 // assign identifying part of URL now
3415 if (aIdentifyingURI) {
3416 aIdentifyingURI->assign(dblocuri);
3417 }
3418 // find datastore now
3419 DEBUGPRINTF(("Determined relative, identifying URI (w/o CGI): %s",dblocuri)){ if (((0x00008000) & getDbgMask()) == (0x00008000)) getDbgLogger
()->setNextMask(0x00008000).DebugPrintfLastMask ("Determined relative, identifying URI (w/o CGI): %s"
,dblocuri); }
;
3420 return findLocalDataStore(dblocuri);
3421} // TSyncSession::findLocalDataStorebyURI
3422
3423
3424// find local datastore by (relative) URI
3425TLocalEngineDS *TSyncSession::findLocalDataStore(const char *aDatastoreURI)
3426{
3427 TLocalDataStorePContainer::iterator pos;
3428 for (pos=fLocalDataStores.begin(); pos!=fLocalDataStores.end(); ++pos) {
3429 // test for match (we do not do best-match search here because these are names
3430 // under our own control that do not contain slashes and hence no
3431 // mismatch possibilities like "/Calendar" and "/Calendar/Events" as
3432 // with Oracle server.
3433 if ((*pos)->isDatastore(aDatastoreURI))
3434 return (*pos); // found
3435 }
3436 return NULL__null; // none found
3437} // TSyncSession::findLocalDataStore
3438
3439
3440// - find local datastore by datastore handle (=config pointer)
3441TLocalEngineDS *TSyncSession::findLocalDataStore(void *aDSHandle)
3442{
3443 TLocalDataStorePContainer::iterator pos;
3444 for (pos=fLocalDataStores.begin(); pos!=fLocalDataStores.end(); ++pos) {
3445 // test for match
3446 TLocalEngineDS *ldsP = (*pos);
3447 if ((void *)(ldsP->getDSConfig())==aDSHandle)
3448 return (ldsP); // found
3449 }
3450 return NULL__null; // none found
3451} // TSyncSession::findLocalDataStore
3452
3453
3454TLocalEngineDS *TSyncSession::addLocalDataStore(TLocalDSConfig *aLocalDSConfigP)
3455{
3456 TLocalEngineDS *ldsP=aLocalDSConfigP->newLocalDataStore(this);
3457 fLocalDataStores.push_back(ldsP);
3458 return ldsP;
3459} // TSyncSession::addLocalDataStore
3460
3461
3462
3463// - find local datatype by config pointer (used to avoid duplicating types
3464// in session if used by more than a single datastore)
3465TSyncItemType *TSyncSession::findLocalType(TDataTypeConfig *aDataTypeConfigP)
3466{
3467 TSyncItemTypePContainer::iterator pos;
3468 for (pos=fLocalItemTypes.begin(); pos!=fLocalItemTypes.end(); ++pos) {
3469 // test for match
3470 if ((void *)((*pos)->getTypeConfig())==aDataTypeConfigP)
3471 return (*pos); // found
3472 }
3473 return NULL__null; // none found
3474} // TSyncSession::findLocalType
3475
3476
3477// - find implemented remote datatype by config pointer (and related datastore, if any)
3478TSyncItemType *TSyncSession::findRemoteType(TDataTypeConfig *aDataTypeConfigP, TSyncDataStore *aRelatedRemoteDS)
3479{
3480 TSyncItemTypePContainer::iterator pos;
3481 for (pos=fRemoteItemTypes.begin(); pos!=fRemoteItemTypes.end(); ++pos) {
3482 // test for match
3483 if ((void *)((*pos)->getTypeConfig())==aDataTypeConfigP) {
3484 // match only if related to same datastore or not related
3485 if (aRelatedRemoteDS == (*pos)->getRelatedDatastore())
3486 return (*pos); // found
3487 }
3488 }
3489 return NULL__null; // none found
3490} // TSyncSession::findRemoteType
3491
3492
3493
3494
3495
3496// get new list of all local datastores
3497SmlDevInfDatastoreListPtr_t TSyncSession::newDevInfDataStoreList(bool aAlertedOnly, bool aWithoutCTCapProps)
3498{
3499 SmlDevInfDatastoreListPtr_t rootP,*insertpos;
3500 SmlDevInfDatastorePtr_t datastoreP;
3501
3502 // no list at beginning
3503 rootP=NULL__null;
3504 insertpos = &rootP;
3505
3506 // go through local datastore list
3507 TLocalDataStorePContainer::iterator pos1;
3508 for (pos1=fLocalDataStores.begin(); pos1!=fLocalDataStores.end(); ++pos1) {
3509 // check if we only want alerted datastore's info (client case)
3510 if (aAlertedOnly) {
3511 if (!(*pos1)->testState(dssta_clientsentalert))
3512 continue; // not alerted, do not show this one
3513 }
3514 // see if we have info at all
3515 datastoreP = (*pos1)->getDatastoreDevinf(IS_SERVER(getSyncAppBase()->isServer()), aWithoutCTCapProps);
3516 if (datastoreP) {
3517 // create new list item
3518 (*insertpos) = SML_NEW(SmlDevInfDatastoreList_t)((SmlDevInfDatastoreList_t*) _smlMalloc(sizeof(SmlDevInfDatastoreList_t
)))
;
3519 (*insertpos)->next = NULL__null;
3520 (*insertpos)->data = datastoreP;
3521 // set new insert position
3522 insertpos = &((*insertpos)->next);
3523 }
3524 }
3525 return rootP;
3526} // TSyncSession::newDevInfDataStoreList
3527
3528
3529// get common sync capabilities mask of this session (datastores might modify it)
3530uInt32 TSyncSession::getSyncCapMask(void)
3531{
3532 return
3533 SCAP_MASK_NORMAL((0x0002 | 0x0004) | 0x0008 | 0x0010 | 0x0020 | 0x0040) |
3534 (getSessionConfig()->fAcceptServerAlerted ? SCAP_MASK_SERVER_ALERTED0x0080 : 0);
3535} // TSyncSession::getSyncCapMask
3536
3537
3538// get new list of all local item types
3539SmlDevInfCtcapListPtr_t TSyncSession::newLocalCTCapList(bool aAlertedOnly, TLocalEngineDS *aOnlyForDS, bool aWithoutCTCapProps)
3540{
3541 SmlDevInfCtcapListPtr_t rootP,*insertpos;
3542 SmlDevInfCTCapPtr_t ctcapP;
3543
3544 // no list at beginning
3545 rootP=NULL__null;
3546 insertpos = &rootP;
3547 bool showTy;
3548 TTypeVariantDescriptor variantDesc = NULL__null;
3549
3550 // go through local datastore list
3551 // Note: rulematch types should normally not be shown, but the way to do that
3552 // is not some testing here (which is almost impossible), but profiles
3553 // defined for rulematch types should be made invisible.
3554 TSyncItemTypePContainer::iterator pos2;
3555 TLocalDataStorePContainer::iterator pos1;
3556 for (pos2=fLocalItemTypes.begin(); pos2!=fLocalItemTypes.end(); ++pos2) {
3557 showTy=true;
3558 // check for restriction to certain datastore
3559 if (aOnlyForDS) {
3560 // only show if specified datastore is using the type
3561 showTy = aOnlyForDS->doesUseType(*pos2, &variantDesc);
3562 }
3563 // see if datatype is used by any of the alerted datastores
3564 if (showTy && aAlertedOnly) {
3565 showTy=false;
3566 for (pos1=fLocalDataStores.begin(); pos1!=fLocalDataStores.end(); ++pos1) {
3567 // check if we only want alerted datastore's info (client case)
3568 if (!(*pos1)->testState(dssta_clientsentalert)) continue; // test next
3569 // see if datatype is used by this datastore
3570 if ((*pos1)->doesUseType(*pos2)) {
3571 showTy=true;
3572 break;
3573 }
3574 }
3575 }
3576 // now show if selected
3577 if (showTy) {
3578 // see if we have info at all
3579 ctcapP = (*pos2)->getCTCapDevInf(aOnlyForDS, variantDesc, aWithoutCTCapProps);
3580 if (ctcapP) {
3581 // create new list item
3582 (*insertpos) = SML_NEW(SmlDevInfCtcapList_t)((SmlDevInfCtcapList_t*) _smlMalloc(sizeof(SmlDevInfCtcapList_t
)))
;
3583 (*insertpos)->next = NULL__null;
3584 (*insertpos)->data = ctcapP;
3585 // set new insert position
3586 insertpos = &((*insertpos)->next);
3587 }
3588 }
3589 }
3590 return rootP;
3591} // TSyncSession::newLocalCTCapList
3592
3593
3594// build DevInf of this session
3595SmlDevInfDevInfPtr_t TSyncSession::newDevInf(bool aAlertedOnly, bool aWithoutCTCapProps)
3596{
3597 SmlDevInfDevInfPtr_t devinfP;
3598
3599 // Create empty DevInf
3600 devinfP = SML_NEW(SmlDevInfDevInf_t)((SmlDevInfDevInf_t*) _smlMalloc(sizeof(SmlDevInfDevInf_t)));
3601 // Fill in information for current session
3602 devinfP->verdtd=newPCDataString(SyncMLVerDTDNames[fSyncMLVersion]);
3603 // - identification of this SyncML implementation
3604 devinfP->man=newPCDataOptString(getSyncAppBase()->getManufacturer().c_str());
3605 devinfP->mod=newPCDataOptString(getSyncAppBase()->getModel().c_str());
3606 devinfP->oem=newPCDataOptString(getSyncAppBase()->getOEM());
3607 devinfP->swv=newPCDataOptString(getSyncAppBase()->getSoftwareVersion());
3608 // - identification of the device ID and type (server/client etc.)
3609 devinfP->devid=newPCDataString(getDeviceID().c_str());
3610 devinfP->devtyp=newPCDataString(getDeviceType().c_str());
3611 // - identification of the platform the software runs on
3612 devinfP->hwv=newPCDataOptString(getSyncAppBase()->getHardwareVersion().c_str());
3613 devinfP->fwv=newPCDataOptString(getSyncAppBase()->getFirmwareVersion().c_str());
3614 // Now get info for content capabilities
3615 if (fSyncMLVersion<syncml_vers_1_2) {
3616 // CTCap is global, get it without limitation to a datastore
3617 devinfP->ctcap=newLocalCTCapList(aAlertedOnly, NULL__null, aWithoutCTCapProps);
3618 }
3619 else
3620 devinfP->ctcap=NULL__null; // no global CTCap any more at devInf level
3621 // Now get info for datastores
3622 devinfP->datastore=newDevInfDataStoreList(aAlertedOnly, aWithoutCTCapProps);
3623 // SyncML 1.1 related flags
3624 devinfP->flags=0; // no SyncML 1.1 flags by default
3625 if (fSyncMLVersion>=syncml_vers_1_1) {
3626 // - we can always parse number of changes (whether we can make use of it is irrelevant)
3627 devinfP->flags |= SmlDevInfNOfM_f0x0002;
3628 // - check if we support UTC based time (implementations with no means to obtain time zone might not)
3629 if (canHandleUTC())
3630 devinfP->flags |= SmlDevInfUTC_f0x0001; // we can handle UTC
3631 // - we support large object
3632 devinfP->flags |= SmlDevInfLargeObject_f0x0008;
3633 }
3634 // Now get extensions info
3635 devinfP->ext=NULL__null;
3636 // %%% tdb, optional
3637 // return
3638 return devinfP;
3639} // TSyncSession::newDevInf
3640
3641
3642// get devInf for this session (caller is passed ownership)
3643SmlItemPtr_t TSyncSession::getLocalDevInfItem(bool aAlertedOnly, bool aWithoutCTCapProps)
3644{
3645 // - create item with correct source and Meta information
3646 SmlItemPtr_t devinf = newItem();
3647 // %%% if strictly following example in SyncML protocol specs,
3648 // source should not have a Displayname
3649 //fLocalDevInfItemP->source=newLocation(SYNCML_DEVINF_LOCURI,SYNCML_DEVINF_LOCNAME);
3650 // %%% if strictly following example in SyncML protocol specs,
3651 // source should not have "./" prefix
3652 // %%% this is disputable, DCM expects ./, so we send it again now
3653 devinf->source=newLocation(SyncMLDevInfNames[fSyncMLVersion]);
3654 // - create meta type
3655 /* %%% if strictly following example in SyncML protocol specs, meta
3656 * must be defined in the result/put command, not the individual item
3657 string metatype=SYNCML_DEVINF_META_TYPE;
3658 addEncoding(metatype);
3659 fLocalDevInfItemP->meta=newMetaType(metatype.c_str());
3660 %%% */
3661 // - create DevInf PCData
3662 devinf->data = SML_NEW(SmlPcdata_t)((SmlPcdata_t*) _smlMalloc(sizeof(SmlPcdata_t)));
3663 devinf->data->contentType=SML_PCDATA_EXTENSION;
3664 devinf->data->extension=SML_EXT_DEVINF;
3665 // - %%% assume length is not relevant for structured content (looks like in mgrutil.c)
3666 devinf->data->length=0;
3667 // - create and insert DevInf
3668 devinf->data->content = newDevInf(aAlertedOnly, aWithoutCTCapProps);
3669 // - done
3670 return devinf;
3671} // TSyncSession::getLocalDevInfItem
3672
3673
3674// analyze remote devinf delivered by Put or Get/Result commands
3675// or loaded from cache by loadRemoteDevInf()
3676localstatus TSyncSession::analyzeRemoteDevInf(
3677 SmlDevInfDevInfPtr_t aDevInfP
3678)
3679{
3680 localstatus sta = LOCERR_OK;
3681 PDEBUGBLOCKDESC("DevInf_Analyze","Analyzing remote devInf")getDbgLogger()->DebugOpenBlock( "DevInf_Analyze","Analyzing remote devInf"
)
;
3682 if (!aDevInfP) {
3683 PDEBUGPRINTFX(DBG_ERROR,("Warning: No DevInf found (possible cause: improperly encoded devInf from remote)")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("Warning: No DevInf found (possible cause: improperly encoded devInf from remote)"
); }
;
3684 sta=400; // no devInf
3685 goto done;
3686 }
3687 else {
3688 // we have seen the devinf now
3689 fRemoteDevInfKnown=true;
3690 // analyze what device we have here
3691 PDEBUGPRINTFX(DBG_REMOTEINFO+DBG_HOT,({ if (((0x00000100 +0x00000001) & getDbgMask()) == (0x00000100
+0x00000001)) getDbgLogger()->setNextMask(0x00000100 +0x00000001
).DebugPrintfLastMask ( "Device ID='%" ".50" "s', Type='%" ".20"
"s', Model='%" ".50" "s'", smlPCDataToCharP(aDevInfP->devid
), smlPCDataToCharP(aDevInfP->devtyp), smlPCDataToCharP(aDevInfP
->mod) ); }
3692 "Device ID='%" FMT_LENGTH(".50") "s', Type='%" FMT_LENGTH(".20") "s', Model='%" FMT_LENGTH(".50") "s'",{ if (((0x00000100 +0x00000001) & getDbgMask()) == (0x00000100
+0x00000001)) getDbgLogger()->setNextMask(0x00000100 +0x00000001
).DebugPrintfLastMask ( "Device ID='%" ".50" "s', Type='%" ".20"
"s', Model='%" ".50" "s'", smlPCDataToCharP(aDevInfP->devid
), smlPCDataToCharP(aDevInfP->devtyp), smlPCDataToCharP(aDevInfP
->mod) ); }
3693 FMT_LENGTH_LIMITED(50,smlPCDataToCharP(aDevInfP->devid)),{ if (((0x00000100 +0x00000001) & getDbgMask()) == (0x00000100
+0x00000001)) getDbgLogger()->setNextMask(0x00000100 +0x00000001
).DebugPrintfLastMask ( "Device ID='%" ".50" "s', Type='%" ".20"
"s', Model='%" ".50" "s'", smlPCDataToCharP(aDevInfP->devid
), smlPCDataToCharP(aDevInfP->devtyp), smlPCDataToCharP(aDevInfP
->mod) ); }
3694 FMT_LENGTH_LIMITED(20,smlPCDataToCharP(aDevInfP->devtyp)),{ if (((0x00000100 +0x00000001) & getDbgMask()) == (0x00000100
+0x00000001)) getDbgLogger()->setNextMask(0x00000100 +0x00000001
).DebugPrintfLastMask ( "Device ID='%" ".50" "s', Type='%" ".20"
"s', Model='%" ".50" "s'", smlPCDataToCharP(aDevInfP->devid
), smlPCDataToCharP(aDevInfP->devtyp), smlPCDataToCharP(aDevInfP
->mod) ); }
3695 FMT_LENGTH_LIMITED(50,smlPCDataToCharP(aDevInfP->mod)){ if (((0x00000100 +0x00000001) & getDbgMask()) == (0x00000100
+0x00000001)) getDbgLogger()->setNextMask(0x00000100 +0x00000001
).DebugPrintfLastMask ( "Device ID='%" ".50" "s', Type='%" ".20"
"s', Model='%" ".50" "s'", smlPCDataToCharP(aDevInfP->devid
), smlPCDataToCharP(aDevInfP->devtyp), smlPCDataToCharP(aDevInfP
->mod) ); }
3696 )){ if (((0x00000100 +0x00000001) & getDbgMask()) == (0x00000100
+0x00000001)) getDbgLogger()->setNextMask(0x00000100 +0x00000001
).DebugPrintfLastMask ( "Device ID='%" ".50" "s', Type='%" ".20"
"s', Model='%" ".50" "s'", smlPCDataToCharP(aDevInfP->devid
), smlPCDataToCharP(aDevInfP->devtyp), smlPCDataToCharP(aDevInfP
->mod) ); }
;
3697 PDEBUGPRINTFX(DBG_REMOTEINFO+DBG_HOT,({ if (((0x00000100 +0x00000001) & getDbgMask()) == (0x00000100
+0x00000001)) getDbgLogger()->setNextMask(0x00000100 +0x00000001
).DebugPrintfLastMask ( "Manufacturer='%" ".30" "s', OEM='%" ".30"
"s'", smlPCDataToCharP(aDevInfP->man), smlPCDataToCharP(aDevInfP
->oem) ); }
3698 "Manufacturer='%" FMT_LENGTH(".30") "s', OEM='%" FMT_LENGTH(".30") "s'",{ if (((0x00000100 +0x00000001) & getDbgMask()) == (0x00000100
+0x00000001)) getDbgLogger()->setNextMask(0x00000100 +0x00000001
).DebugPrintfLastMask ( "Manufacturer='%" ".30" "s', OEM='%" ".30"
"s'", smlPCDataToCharP(aDevInfP->man), smlPCDataToCharP(aDevInfP
->oem) ); }
3699 FMT_LENGTH_LIMITED(30,smlPCDataToCharP(aDevInfP->man)),{ if (((0x00000100 +0x00000001) & getDbgMask()) == (0x00000100
+0x00000001)) getDbgLogger()->setNextMask(0x00000100 +0x00000001
).DebugPrintfLastMask ( "Manufacturer='%" ".30" "s', OEM='%" ".30"
"s'", smlPCDataToCharP(aDevInfP->man), smlPCDataToCharP(aDevInfP
->oem) ); }
3700 FMT_LENGTH_LIMITED(30,smlPCDataToCharP(aDevInfP->oem)){ if (((0x00000100 +0x00000001) & getDbgMask()) == (0x00000100
+0x00000001)) getDbgLogger()->setNextMask(0x00000100 +0x00000001
).DebugPrintfLastMask ( "Manufacturer='%" ".30" "s', OEM='%" ".30"
"s'", smlPCDataToCharP(aDevInfP->man), smlPCDataToCharP(aDevInfP
->oem) ); }
3701 )){ if (((0x00000100 +0x00000001) & getDbgMask()) == (0x00000100
+0x00000001)) getDbgLogger()->setNextMask(0x00000100 +0x00000001
).DebugPrintfLastMask ( "Manufacturer='%" ".30" "s', OEM='%" ".30"
"s'", smlPCDataToCharP(aDevInfP->man), smlPCDataToCharP(aDevInfP
->oem) ); }
;
3702 PDEBUGPRINTFX(DBG_REMOTEINFO+DBG_HOT,({ if (((0x00000100 +0x00000001) & getDbgMask()) == (0x00000100
+0x00000001)) getDbgLogger()->setNextMask(0x00000100 +0x00000001
).DebugPrintfLastMask ( "Softwarevers='%" ".30" "s', Firmwarevers='%"
".30" "s', Hardwarevers='%" ".30" "s'", smlPCDataToCharP(aDevInfP
->swv), smlPCDataToCharP(aDevInfP->fwv), smlPCDataToCharP
(aDevInfP->hwv) ); }
3703 "Softwarevers='%" FMT_LENGTH(".30") "s', Firmwarevers='%" FMT_LENGTH(".30") "s', Hardwarevers='%" FMT_LENGTH(".30") "s'",{ if (((0x00000100 +0x00000001) & getDbgMask()) == (0x00000100
+0x00000001)) getDbgLogger()->setNextMask(0x00000100 +0x00000001
).DebugPrintfLastMask ( "Softwarevers='%" ".30" "s', Firmwarevers='%"
".30" "s', Hardwarevers='%" ".30" "s'", smlPCDataToCharP(aDevInfP
->swv), smlPCDataToCharP(aDevInfP->fwv), smlPCDataToCharP
(aDevInfP->hwv) ); }
3704 FMT_LENGTH_LIMITED(30,smlPCDataToCharP(aDevInfP->swv)),{ if (((0x00000100 +0x00000001) & getDbgMask()) == (0x00000100
+0x00000001)) getDbgLogger()->setNextMask(0x00000100 +0x00000001
).DebugPrintfLastMask ( "Softwarevers='%" ".30" "s', Firmwarevers='%"
".30" "s', Hardwarevers='%" ".30" "s'", smlPCDataToCharP(aDevInfP
->swv), smlPCDataToCharP(aDevInfP->fwv), smlPCDataToCharP
(aDevInfP->hwv) ); }
3705 FMT_LENGTH_LIMITED(30,smlPCDataToCharP(aDevInfP->fwv)),{ if (((0x00000100 +0x00000001) & getDbgMask()) == (0x00000100
+0x00000001)) getDbgLogger()->setNextMask(0x00000100 +0x00000001
).DebugPrintfLastMask ( "Softwarevers='%" ".30" "s', Firmwarevers='%"
".30" "s', Hardwarevers='%" ".30" "s'", smlPCDataToCharP(aDevInfP
->swv), smlPCDataToCharP(aDevInfP->fwv), smlPCDataToCharP
(aDevInfP->hwv) ); }
3706 FMT_LENGTH_LIMITED(30,smlPCDataToCharP(aDevInfP->hwv)){ if (((0x00000100 +0x00000001) & getDbgMask()) == (0x00000100
+0x00000001)) getDbgLogger()->setNextMask(0x00000100 +0x00000001
).DebugPrintfLastMask ( "Softwarevers='%" ".30" "s', Firmwarevers='%"
".30" "s', Hardwarevers='%" ".30" "s'", smlPCDataToCharP(aDevInfP
->swv), smlPCDataToCharP(aDevInfP->fwv), smlPCDataToCharP
(aDevInfP->hwv) ); }
3707 )){ if (((0x00000100 +0x00000001) & getDbgMask()) == (0x00000100
+0x00000001)) getDbgLogger()->setNextMask(0x00000100 +0x00000001
).DebugPrintfLastMask ( "Softwarevers='%" ".30" "s', Firmwarevers='%"
".30" "s', Hardwarevers='%" ".30" "s'", smlPCDataToCharP(aDevInfP
->swv), smlPCDataToCharP(aDevInfP->fwv), smlPCDataToCharP
(aDevInfP->hwv) ); }
;
3708 #ifndef MINIMAL_CODE
3709 // get the devinf details 1:1
3710 fRemoteDevInf_devid=smlPCDataToCharP(aDevInfP->devid);
3711 fRemoteDevInf_devtyp=smlPCDataToCharP(aDevInfP->devtyp);
3712 fRemoteDevInf_mod=smlPCDataToCharP(aDevInfP->mod);
3713 fRemoteDevInf_man=smlPCDataToCharP(aDevInfP->man);
3714 fRemoteDevInf_oem=smlPCDataToCharP(aDevInfP->oem);
3715 fRemoteDevInf_swv=smlPCDataToCharP(aDevInfP->swv);
3716 fRemoteDevInf_fwv=smlPCDataToCharP(aDevInfP->fwv);
3717 fRemoteDevInf_hwv=smlPCDataToCharP(aDevInfP->hwv);
3718 // get the descriptive name of the device
3719 fRemoteDescName.assign(smlPCDataToCharP(aDevInfP->man));
3720 if (fRemoteDescName.size()>0) fRemoteDescName+=" ";
3721 fRemoteDescName.append(smlPCDataToCharP(aDevInfP->mod));
3722 // get extra info: "Type (HWV, FWV, SWV) Oem"
3723 fRemoteInfoString+=fRemoteDevInf_devtyp;
3724 fRemoteInfoString+=" (";
3725 fRemoteInfoString+=fRemoteDevInf_hwv;
3726 fRemoteInfoString+=", ";
3727 fRemoteInfoString+=fRemoteDevInf_fwv;
3728 fRemoteInfoString+=", ";
3729 fRemoteInfoString+=fRemoteDevInf_swv;
3730 fRemoteInfoString+=") ";
3731 fRemoteInfoString+=fRemoteDevInf_oem;
3732 #endif
3733 // Show SyncML version here (again)
3734 PDEBUGPRINTFX(DBG_REMOTEINFO+DBG_HOT,("SyncML Version: %s",SyncMLVerProtoNames[fSyncMLVersion])){ if (((0x00000100 +0x00000001) & getDbgMask()) == (0x00000100
+0x00000001)) getDbgLogger()->setNextMask(0x00000100 +0x00000001
).DebugPrintfLastMask ("SyncML Version: %s",SyncMLVerProtoNames
[fSyncMLVersion]); }
;
3735 // check SyncML 1.1 flags
3736 if (fSyncMLVersion>=syncml_vers_1_1) {
3737 // - check if remote can receive NOC (number of changes)
3738 fRemoteWantsNOC = (aDevInfP->flags & SmlDevInfNOfM_f0x0002);
3739 // - check if remote can handle UTC time
3740 fRemoteCanHandleUTC = (aDevInfP->flags & SmlDevInfUTC_f0x0001);
3741 // - check if remote supports large objects
3742 fRemoteSupportsLargeObjects = (aDevInfP->flags & SmlDevInfLargeObject_f0x0008);
3743 PDEBUGPRINTFX(DBG_REMOTEINFO+DBG_HOT,({ if (((0x00000100 +0x00000001) & getDbgMask()) == (0x00000100
+0x00000001)) getDbgLogger()->setNextMask(0x00000100 +0x00000001
).DebugPrintfLastMask ( "SyncML capability flags: wantsNOC=%s, canHandleUTC=%s, supportsLargeObjs=%s"
, aDevInfP->flags & 0x0002 ? "Yes" : "No", aDevInfP->
flags & 0x0001 ? "Yes" : "No", aDevInfP->flags & 0x0008
? "Yes" : "No" ); }
3744 "SyncML capability flags: wantsNOC=%s, canHandleUTC=%s, supportsLargeObjs=%s",{ if (((0x00000100 +0x00000001) & getDbgMask()) == (0x00000100
+0x00000001)) getDbgLogger()->setNextMask(0x00000100 +0x00000001
).DebugPrintfLastMask ( "SyncML capability flags: wantsNOC=%s, canHandleUTC=%s, supportsLargeObjs=%s"
, aDevInfP->flags & 0x0002 ? "Yes" : "No", aDevInfP->
flags & 0x0001 ? "Yes" : "No", aDevInfP->flags & 0x0008
? "Yes" : "No" ); }
3745 aDevInfP->flags & SmlDevInfNOfM_f ? "Yes" : "No",{ if (((0x00000100 +0x00000001) & getDbgMask()) == (0x00000100
+0x00000001)) getDbgLogger()->setNextMask(0x00000100 +0x00000001
).DebugPrintfLastMask ( "SyncML capability flags: wantsNOC=%s, canHandleUTC=%s, supportsLargeObjs=%s"
, aDevInfP->flags & 0x0002 ? "Yes" : "No", aDevInfP->
flags & 0x0001 ? "Yes" : "No", aDevInfP->flags & 0x0008
? "Yes" : "No" ); }
3746 aDevInfP->flags & SmlDevInfUTC_f ? "Yes" : "No",{ if (((0x00000100 +0x00000001) & getDbgMask()) == (0x00000100
+0x00000001)) getDbgLogger()->setNextMask(0x00000100 +0x00000001
).DebugPrintfLastMask ( "SyncML capability flags: wantsNOC=%s, canHandleUTC=%s, supportsLargeObjs=%s"
, aDevInfP->flags & 0x0002 ? "Yes" : "No", aDevInfP->
flags & 0x0001 ? "Yes" : "No", aDevInfP->flags & 0x0008
? "Yes" : "No" ); }
3747 aDevInfP->flags & SmlDevInfLargeObject_f ? "Yes" : "No"{ if (((0x00000100 +0x00000001) & getDbgMask()) == (0x00000100
+0x00000001)) getDbgLogger()->setNextMask(0x00000100 +0x00000001
).DebugPrintfLastMask ( "SyncML capability flags: wantsNOC=%s, canHandleUTC=%s, supportsLargeObjs=%s"
, aDevInfP->flags & 0x0002 ? "Yes" : "No", aDevInfP->
flags & 0x0001 ? "Yes" : "No", aDevInfP->flags & 0x0008
? "Yes" : "No" ); }
3748 )){ if (((0x00000100 +0x00000001) & getDbgMask()) == (0x00000100
+0x00000001)) getDbgLogger()->setNextMask(0x00000100 +0x00000001
).DebugPrintfLastMask ( "SyncML capability flags: wantsNOC=%s, canHandleUTC=%s, supportsLargeObjs=%s"
, aDevInfP->flags & 0x0002 ? "Yes" : "No", aDevInfP->
flags & 0x0001 ? "Yes" : "No", aDevInfP->flags & 0x0008
? "Yes" : "No" ); }
;
3749 }
3750 // detect remote specific server behaviour if needed
3751 SmlDevInfDevInfPtr_t CTCapDevInfP = aDevInfP;
3752 sta = checkRemoteSpecifics(aDevInfP, &CTCapDevInfP);
3753 if (sta!=LOCERR_OK) {
3754 remoteAnalyzed(); // analyzed to reject
3755 goto done;
3756 }
3757 // switch to DevInf provided by remote rules
3758 if (CTCapDevInfP != aDevInfP) {
3759 PDEBUGPRINTFX(DBG_REMOTEINFO,("using CTCaps provided in DevInf of remote rule")){ if (((0x00000100) & getDbgMask()) == (0x00000100)) getDbgLogger
()->setNextMask(0x00000100).DebugPrintfLastMask ("using CTCaps provided in DevInf of remote rule"
); }
;
3760 aDevInfP = CTCapDevInfP;
3761 }
3762 // Types and datastores may not be changed/added if sync has allready started
3763 if (fRemoteDevInfLock) {
3764 // Sync already started, in "blind" mode or previously received devInf,
3765 // do not confuse things with changing devInf in mid-sync
3766 PDEBUGPRINTFX(DBG_ERROR,({ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "WARNING: Type and Datastore info in DevInf ignored because it came to late"
); }
3767 "WARNING: Type and Datastore info in DevInf ignored because it came to late"{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "WARNING: Type and Datastore info in DevInf ignored because it came to late"
); }
3768 )){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "WARNING: Type and Datastore info in DevInf ignored because it came to late"
); }
;
3769 }
3770 else {
3771 if (getSyncMLVersion()<syncml_vers_1_2) {
3772 // analyze CTCaps (content type capabilities)
3773 SmlDevInfCtcapListPtr_t ctlP = aDevInfP->ctcap;
3774 // loop through list
3775 PDEBUGBLOCKDESC("RemoteTypes", "Analyzing remote types listed in devInf level CTCap")getDbgLogger()->DebugOpenBlock( "RemoteTypes","Analyzing remote types listed in devInf level CTCap"
)
;
3776 if (fIgnoreCTCap) {
3777 // ignore CTCap
3778 if (ctlP) {
3779 PDEBUGPRINTFX(DBG_REMOTEINFO+DBG_HOT,("Remote rule prevents looking at CTCap")){ if (((0x00000100 +0x00000001) & getDbgMask()) == (0x00000100
+0x00000001)) getDbgLogger()->setNextMask(0x00000100 +0x00000001
).DebugPrintfLastMask ("Remote rule prevents looking at CTCap"
); }
;
3780 }
3781 }
3782 else {
3783 while (ctlP) {
3784 if (ctlP->data) {
3785 // create appropriate remote data itemtypes
3786 if (TSyncItemType::analyzeCTCapAndCreateItemTypes(
3787 this,
3788 NULL__null, // this is the pre-DS1.2 style where CTCap is on devInf level
3789 ctlP->data, // CTCap
3790 fLocalItemTypes, // look up in local types for specialized classes
3791 fRemoteItemTypes // add new item types here
3792 )) {
3793 // we have CTCap info of at least one remote type
3794 fRemoteDataTypesKnown=true;
3795 }
3796 else {
3797 PDEBUGPRINTFX(DBG_ERROR,("CTCap could not be used (missing version)")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("CTCap could not be used (missing version)"
); }
;
3798 sta=500;
3799 }
3800 }
3801 // - go to next item
3802 ctlP=ctlP->next;
3803 } // while
3804 }
3805 PDEBUGENDBLOCK("RemoteTypes")getDbgLogger()->DebugCloseBlock( "RemoteTypes");
3806 } // if <DS1.2
3807 // now get datastores
3808 PDEBUGBLOCKDESC("RemoteDatastores", "Analyzing remote datastores")getDbgLogger()->DebugOpenBlock( "RemoteDatastores","Analyzing remote datastores"
)
;
3809 SmlDevInfDatastoreListPtr_t dslP = aDevInfP->datastore;
3810 while(dslP) {
3811 if (dslP->data) {
3812 // we have DataStore info of remote datastores
3813 fRemoteDataStoresKnown=true;
3814 // there is a DataStore entry, create RemoteDataStore for it
3815 TRemoteDataStore *datastoreP;
3816 MP_NEW(datastoreP,DBG_OBJINST,"TRemoteDataStore",TRemoteDataStore(this))datastoreP = new TRemoteDataStore(this);
3817 PDEBUGBLOCKDESC("RemoteDSDevInf", "Registering remote Datastore from devInf")getDbgLogger()->DebugOpenBlock( "RemoteDSDevInf","Registering remote Datastore from devInf"
)
;
3818 // let new datastore analyze the devinf data
3819 if (!datastoreP->setDatastoreDevInf(
3820 dslP->data,
3821 fLocalItemTypes, // look up for datatypes here first
3822 fRemoteItemTypes // but add types here
3823 )) {
3824 // invalid CTCap
3825 PDEBUGPRINTFX(DBG_ERROR,("Invalid DataStore devInf")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("Invalid DataStore devInf"
); }
;
3826 delete datastoreP; // forget invalid data store
3827 sta=500; // failed
3828 }
3829 else {
3830 // CTCap set successfully, new type created
3831 // - save it in the list of remote types
3832 fRemoteDataStores.push_back(datastoreP);
3833 }
3834 PDEBUGENDBLOCK("RemoteDSDevInf")getDbgLogger()->DebugCloseBlock( "RemoteDSDevInf");
3835 }
3836 // - go to next item
3837 dslP=dslP->next;
3838 } // while
3839 PDEBUGENDBLOCK("RemoteDatastores")getDbgLogger()->DebugCloseBlock( "RemoteDatastores");
3840 } // else sync not started yet
3841 }
3842 // give descendants possibility to do something with the analyzed data
3843 remoteAnalyzed();
3844 // ok
3845done:
3846 PDEBUGENDBLOCK("DevInf_Analyze")getDbgLogger()->DebugCloseBlock( "DevInf_Analyze");
3847 return sta;
3848} // TSyncSession::analyzeRemoteDevInf
3849
3850
3851#ifdef SYSYNC_SERVER1
3852
3853// Initialize Sync: set up datastores and types for server sync session
3854localstatus TSyncSession::initSync(
3855 const char *aLocalDatastoreURI,
3856 const char *aRemoteDatastoreURI
3857)
3858{
3859 localstatus sta = LOCERR_OK;
3860
3861 // search for local datastore first
3862 string cgiOptions;
3863 // - search for datastore and obtain possible CGI;
3864 // fallback to remote datastore URI is for Sony Ericsson C510,
3865 // which sends an empty target (= local) URI (also needs
3866 // to be done in Alert handling)
3867 fLocalSyncDatastoreP = findLocalDataStoreByURI(SessionRelativeURI((!aLocalDatastoreURI ||
3868 !aLocalDatastoreURI[0]) ?
3869 aRemoteDatastoreURI :
3870 aLocalDatastoreURI),&cgiOptions);
3871 PDEBUGPRINTFX(DBG_DATA,("initSync: setting fLocalSyncDatastoreP")){ if (((0x00000080) & getDbgMask()) == (0x00000080)) getDbgLogger
()->setNextMask(0x00000080).DebugPrintfLastMask ("initSync: setting fLocalSyncDatastoreP"
); }
;
3872 if (!fLocalSyncDatastoreP) {
3873 // no such local datastore
3874 return 404;
3875 }
3876 // Local datastore is known here (fLocalSyncDatastoreP)
3877 // - now init for reception of syncops
3878 sta = fLocalSyncDatastoreP->engInitForSyncOps(aRemoteDatastoreURI);
3879 #ifdef SYNCML_TAF_SUPPORT
3880 if (sta==LOCERR_OK) {
3881 // - make sure that options are reparsed (TAF *might* change from Sync request to Sync request)
3882 sta = fLocalSyncDatastoreP->engParseOptions(
3883 cgiOptions.c_str(),
3884 true // we are parsing options from <sync> target URI
3885 );
3886 }
3887 #endif
3888 #ifdef OBJECT_FILTERING1
3889 if (sta==LOCERR_OK) {
3890 // %%% check for DS 1.2 <filter> in <Sync> command as well (we do parse <filter> in <Alert> already)
3891 #if (!defined _MSC_VER || defined WINCE) && !defined(__GNUC__4)
3892 #warning "tbd %%%: check for DS 1.2 <filter> in <Sync> command as well (we do parse <filter> in <Alert> already)"
3893 #endif
3894 }
3895 #endif
3896 #ifdef OBJECT_FILTERING1
3897 // Show filter summary
3898 #ifdef SYDEBUG2
3899 #ifdef SYNCML_TAF_SUPPORT
3900 PDEBUGPRINTFX(DBG_FILTER,("TAF (temporary, INCLUSIVE) Filter : %s",fLocalSyncDatastoreP->fTargetAddressFilter.c_str())){ if (((0x08000000) & getDbgMask()) == (0x08000000)) getDbgLogger
()->setNextMask(0x08000000).DebugPrintfLastMask ("TAF (temporary, INCLUSIVE) Filter : %s"
,fLocalSyncDatastoreP->fTargetAddressFilter.c_str()); }
;
3901 #endif // SYNCML_TAF_SUPPORT
3902 PDEBUGPRINTFX(DBG_FILTER,("SyncSet (dynamic, EXCLUSIVE) Filter : %s",fLocalSyncDatastoreP->fSyncSetFilter.c_str())){ if (((0x08000000) & getDbgMask()) == (0x08000000)) getDbgLogger
()->setNextMask(0x08000000).DebugPrintfLastMask ("SyncSet (dynamic, EXCLUSIVE) Filter : %s"
,fLocalSyncDatastoreP->fSyncSetFilter.c_str()); }
;
3903 #ifdef SYSYNC_TARGET_OPTIONS1
3904 string ts;
3905 StringObjTimestamp(ts,fLocalSyncDatastoreP->fDateRangeStart);
3906 PDEBUGPRINTFX(DBG_FILTER,("Date Range Start : %s",fLocalSyncDatastoreP->fDateRangeStart ? ts.c_str() : "<none>")){ if (((0x08000000) & getDbgMask()) == (0x08000000)) getDbgLogger
()->setNextMask(0x08000000).DebugPrintfLastMask ("Date Range Start : %s"
,fLocalSyncDatastoreP->fDateRangeStart ? ts.c_str() : "<none>"
); }
;
3907 StringObjTimestamp(ts,fLocalSyncDatastoreP->fDateRangeEnd);
3908 PDEBUGPRINTFX(DBG_FILTER,("Date Range End : %s",fLocalSyncDatastoreP->fDateRangeEnd ? ts.c_str() : "<none>")){ if (((0x08000000) & getDbgMask()) == (0x08000000)) getDbgLogger
()->setNextMask(0x08000000).DebugPrintfLastMask ("Date Range End : %s"
,fLocalSyncDatastoreP->fDateRangeEnd ? ts.c_str() : "<none>"
); }
;
3909 #endif // SYSYNC_TARGET_OPTIONS
3910 #endif // SYDEBUG
3911 #endif // OBJECT_FILTERING
3912 // return status
3913 return sta;
3914} // TSyncSession::initSync
3915
3916#endif // SYSYNC_SERVER
3917
3918
3919
3920// end sync group (of client sync commands)
3921bool TSyncSession::processSyncEnd(bool &aQueueForLater)
3922{
3923 bool ok=true;
3924
3925 // inform local
3926 if (fLocalSyncDatastoreP) {
3927 // let datastore process it
3928 ok=fLocalSyncDatastoreP->engProcessSyncCmdEnd(aQueueForLater);
3929 }
3930 // end Sync bracket
3931 #ifdef SYNCSTATUS_AT_SYNC_CLOSE
3932 // %%% status for sync command sent AFTER statuses for contained commands
3933 if (fSyncCloseStatusCommandP)
3934 issueRoot(fSyncCloseStatusCommandP);
3935 #endif
3936 // no local datastore active
3937 fLocalSyncDatastoreP=NULL__null;
3938 PDEBUGPRINTFX(DBG_DATA,("processSyncEnd: unsetting fLocalSyncDatastoreP")){ if (((0x00000080) & getDbgMask()) == (0x00000080)) getDbgLogger
()->setNextMask(0x00000080).DebugPrintfLastMask ("processSyncEnd: unsetting fLocalSyncDatastoreP"
); }
;
3939 return ok;
3940} // TSyncSession::processSyncEnd
3941
3942
3943
3944// process generic sync command item within Sync group
3945// - returns true (and unmodified or non-200-successful status) if
3946// operation could be processed regularily
3947// - returns false (but probably still successful status) if
3948// operation was processed with internal irregularities, such as
3949// trying to delete non-existant item in datastore with
3950// incomplete Rollbacks (which returns status 200 in this case!).
3951bool TSyncSession::processSyncOpItem(
3952 TSyncOperation aSyncOp, // the operation
3953 SmlItemPtr_t aItemP, // the item to be processed
3954 SmlMetInfMetInfPtr_t aMetaP, // command-wide meta, if any
3955 TLocalEngineDS *aLocalSyncDatastore, // the local datastore for this syncop item
3956 TStatusCommand &aStatusCommand, // pre-set 200 status, can be modified in case of errors
3957 bool &aQueueForLater // must be set if item cannot be processed now, but must be processed later
3958)
3959{
3960 // assign datastore context (%%% note: some day we will get rid of this
3961 // "global" pointer to the active datastore by moving it into the <sync> command
3962 // object and installing a hierarchical command processor.)
3963 fLocalSyncDatastoreP=aLocalSyncDatastore;
3964 PDEBUGPRINTFX(DBG_DATA,("processSyncOpItem: setting fLocalSyncDatastoreP")){ if (((0x00000080) & getDbgMask()) == (0x00000080)) getDbgLogger
()->setNextMask(0x00000080).DebugPrintfLastMask ("processSyncOpItem: setting fLocalSyncDatastoreP"
); }
;
3965 // Server mode: commands affect datastores currently in sync
3966 if (!fLocalSyncDatastoreP) {
3967 // sync generic command outside sync bracket -> error
3968 aStatusCommand.setStatusCode(403); // forbidden
3969 ADDDEBUGITEM(aStatusCommand,"Add/Copy/Replace/Delete unrelated to datastores"){ if ((((0x00000001) & getDbgMask()) == (0x00000001))) aStatusCommand
.addItemString("Add/Copy/Replace/Delete unrelated to datastores"
); }
;
3970 PDEBUGPRINTFX(DBG_ERROR,("Add/Copy/Replace/Delete unrelated to datastores")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("Add/Copy/Replace/Delete unrelated to datastores"
); }
;
3971 // no success
3972 return false;
3973 }
3974 // check for aborted datastore
3975 if (fLocalSyncDatastoreP->CheckAborted(aStatusCommand)) return false;
3976 // check if we can process it now
3977 // Note: request time limit is active in server only.
3978 if (!fLocalSyncDatastoreP->engIsStarted(false) || RemainingRequestTime()<0) {
3979 aQueueForLater=true; // re-execute later...
3980 return true; // ...but otherwise ok
3981 }
3982 // process Sync operation sent by remote
3983 // - show
3984 PDEBUGPRINTFX(DBG_DATA,({ if (((0x00000080) & getDbgMask()) == (0x00000080)) getDbgLogger
()->setNextMask(0x00000080).DebugPrintfLastMask ( "Remote sent %s-operation:"
, SyncOpNames[aSyncOp] ); }
3985 "Remote sent %s-operation:",{ if (((0x00000080) & getDbgMask()) == (0x00000080)) getDbgLogger
()->setNextMask(0x00000080).DebugPrintfLastMask ( "Remote sent %s-operation:"
, SyncOpNames[aSyncOp] ); }
3986 SyncOpNames[aSyncOp]{ if (((0x00000080) & getDbgMask()) == (0x00000080)) getDbgLogger
()->setNextMask(0x00000080).DebugPrintfLastMask ( "Remote sent %s-operation:"
, SyncOpNames[aSyncOp] ); }
3987 )){ if (((0x00000080) & getDbgMask()) == (0x00000080)) getDbgLogger
()->setNextMask(0x00000080).DebugPrintfLastMask ( "Remote sent %s-operation:"
, SyncOpNames[aSyncOp] ); }
;
3988 PDEBUGPRINTFX(DBG_DATA,({ if (((0x00000080) & getDbgMask()) == (0x00000080)) getDbgLogger
()->setNextMask(0x00000080).DebugPrintfLastMask ( "- Source: remoteID ='%s', remoteName='%s'"
, smlSrcTargLocURIToCharP(aItemP->source), smlSrcTargLocNameToCharP
(aItemP->source) ); }
3989 "- Source: remoteID ='%s', remoteName='%s'",{ if (((0x00000080) & getDbgMask()) == (0x00000080)) getDbgLogger
()->setNextMask(0x00000080).DebugPrintfLastMask ( "- Source: remoteID ='%s', remoteName='%s'"
, smlSrcTargLocURIToCharP(aItemP->source), smlSrcTargLocNameToCharP
(aItemP->source) ); }
3990 smlSrcTargLocURIToCharP(aItemP->source),{ if (((0x00000080) & getDbgMask()) == (0x00000080)) getDbgLogger
()->setNextMask(0x00000080).DebugPrintfLastMask ( "- Source: remoteID ='%s', remoteName='%s'"
, smlSrcTargLocURIToCharP(aItemP->source), smlSrcTargLocNameToCharP
(aItemP->source) ); }
3991 smlSrcTargLocNameToCharP(aItemP->source){ if (((0x00000080) & getDbgMask()) == (0x00000080)) getDbgLogger
()->setNextMask(0x00000080).DebugPrintfLastMask ( "- Source: remoteID ='%s', remoteName='%s'"
, smlSrcTargLocURIToCharP(aItemP->source), smlSrcTargLocNameToCharP
(aItemP->source) ); }
3992 )){ if (((0x00000080) & getDbgMask()) == (0x00000080)) getDbgLogger
()->setNextMask(0x00000080).DebugPrintfLastMask ( "- Source: remoteID ='%s', remoteName='%s'"
, smlSrcTargLocURIToCharP(aItemP->source), smlSrcTargLocNameToCharP
(aItemP->source) ); }
;
3993 PDEBUGPRINTFX(DBG_DATA,({ if (((0x00000080) & getDbgMask()) == (0x00000080)) getDbgLogger
()->setNextMask(0x00000080).DebugPrintfLastMask ( "- Target: localID ='%s', remoteName='%s'"
, smlSrcTargLocURIToCharP(aItemP->target), smlSrcTargLocNameToCharP
(aItemP->target) ); }
3994 "- Target: localID ='%s', remoteName='%s'",{ if (((0x00000080) & getDbgMask()) == (0x00000080)) getDbgLogger
()->setNextMask(0x00000080).DebugPrintfLastMask ( "- Target: localID ='%s', remoteName='%s'"
, smlSrcTargLocURIToCharP(aItemP->target), smlSrcTargLocNameToCharP
(aItemP->target) ); }
3995 smlSrcTargLocURIToCharP(aItemP->target),{ if (((0x00000080) & getDbgMask()) == (0x00000080)) getDbgLogger
()->setNextMask(0x00000080).DebugPrintfLastMask ( "- Target: localID ='%s', remoteName='%s'"
, smlSrcTargLocURIToCharP(aItemP->target), smlSrcTargLocNameToCharP
(aItemP->target) ); }
3996 smlSrcTargLocNameToCharP(aItemP->target){ if (((0x00000080) & getDbgMask()) == (0x00000080)) getDbgLogger
()->setNextMask(0x00000080).DebugPrintfLastMask ( "- Target: localID ='%s', remoteName='%s'"
, smlSrcTargLocURIToCharP(aItemP->target), smlSrcTargLocNameToCharP
(aItemP->target) ); }
3997 )){ if (((0x00000080) & getDbgMask()) == (0x00000080)) getDbgLogger
()->setNextMask(0x00000080).DebugPrintfLastMask ( "- Target: localID ='%s', remoteName='%s'"
, smlSrcTargLocURIToCharP(aItemP->target), smlSrcTargLocNameToCharP
(aItemP->target) ); }
;
3998 // now let datastore handle it
3999 bool regular = fLocalSyncDatastoreP->engProcessSyncOpItem(aSyncOp, aItemP, aMetaP, aStatusCommand);
4000 TSyError statuscode = aStatusCommand.getStatusCode();
4001 if (statuscode == LOCERR_AGAIN) {
4002 if (fStrictExecOrdering) {
4003 // Cannot reorder commands, so force execution now. If we had a way of
4004 // telling the store that it should not use LOCERR_AGAIN, we could
4005 // avoid this unnecessary "delay + flush" for each item.
4006 PDEBUGPRINTFX(DBG_DATA,("Re-executing %s-operation because <strictexecordering> is on.", SyncOpNames[aSyncOp])){ if (((0x00000080) & getDbgMask()) == (0x00000080)) getDbgLogger
()->setNextMask(0x00000080).DebugPrintfLastMask ("Re-executing %s-operation because <strictexecordering> is on."
, SyncOpNames[aSyncOp]); }
;
4007 regular = fLocalSyncDatastoreP->engProcessSyncOpItem(aSyncOp, aItemP, aMetaP, aStatusCommand);
4008 statuscode = aStatusCommand.getStatusCode();
4009 } else {
4010 PDEBUGPRINTFX(DBG_DATA,("Queueing %s-operation for later.", SyncOpNames[aSyncOp])){ if (((0x00000080) & getDbgMask()) == (0x00000080)) getDbgLogger
()->setNextMask(0x00000080).DebugPrintfLastMask ("Queueing %s-operation for later."
, SyncOpNames[aSyncOp]); }
;
4011 aQueueForLater=true; // re-execute later...
4012 return true; // ...but otherwise ok
4013 }
4014 }
4015 #ifdef SCRIPT_SUPPORT1
4016 // let script check status code if the operation completed
4017 TErrorFuncContext errctx;
4018 errctx.statuscode = statuscode;
4019 errctx.newstatuscode = errctx.statuscode;
4020 errctx.syncop = aSyncOp;
4021 errctx.datastoreP = fLocalSyncDatastoreP;
4022 // call script
4023 regular =
4024 TScriptContext::executeTest(
4025 regular, // pass through regular status
4026 fSessionScriptContextP,
4027 getSessionConfig()->fReceivedItemStatusScript,
4028 &ErrorFuncTable,
4029 &errctx // caller context
4030 );
4031 // not completely handled, use possibly modified status code
4032 #ifdef SYDEBUG2
4033 if (aStatusCommand.getStatusCode() != errctx.newstatuscode) {
4034 PDEBUGPRINTFX(DBG_ERROR,("Status: Session Script changed original status=%hd to %hd (original op was %s)",aStatusCommand.getStatusCode(),errctx.newstatuscode,SyncOpNames[errctx.syncop])){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("Status: Session Script changed original status=%hd to %hd (original op was %s)"
,aStatusCommand.getStatusCode(),errctx.newstatuscode,SyncOpNames
[errctx.syncop]); }
;
4035 }
4036 #endif
4037 aStatusCommand.setStatusCode(errctx.newstatuscode);
4038 #endif
4039 // check status
4040 if (!regular) {
4041 localstatus sta=aStatusCommand.getStatusCode();
4042 if (sta>=300 && sta!=419) { // conflict resolved with server data is not an error
4043 PDEBUGPRINTFX(DBG_ERROR,({ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "processSyncOpItem: Error while processing item, status=%hd"
, aStatusCommand.getStatusCode() ); }
4044 "processSyncOpItem: Error while processing item, status=%hd",{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "processSyncOpItem: Error while processing item, status=%hd"
, aStatusCommand.getStatusCode() ); }
4045 aStatusCommand.getStatusCode(){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "processSyncOpItem: Error while processing item, status=%hd"
, aStatusCommand.getStatusCode() ); }
4046 )){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "processSyncOpItem: Error while processing item, status=%hd"
, aStatusCommand.getStatusCode() ); }
;
4047 fLocalSyncDatastoreP->fLocalItemsError++; // count this as an error, as remote will see it as such
4048 }
4049 else {
4050 PDEBUGPRINTFX(DBG_DATA+DBG_HOT,({ if (((0x00000080 +0x00000001) & getDbgMask()) == (0x00000080
+0x00000001)) getDbgLogger()->setNextMask(0x00000080 +0x00000001
).DebugPrintfLastMask ( "processSyncOpItem: Irregularity while processing item, status=%hd"
, aStatusCommand.getStatusCode() ); }
4051 "processSyncOpItem: Irregularity while processing item, status=%hd",{ if (((0x00000080 +0x00000001) & getDbgMask()) == (0x00000080
+0x00000001)) getDbgLogger()->setNextMask(0x00000080 +0x00000001
).DebugPrintfLastMask ( "processSyncOpItem: Irregularity while processing item, status=%hd"
, aStatusCommand.getStatusCode() ); }
4052 aStatusCommand.getStatusCode(){ if (((0x00000080 +0x00000001) & getDbgMask()) == (0x00000080
+0x00000001)) getDbgLogger()->setNextMask(0x00000080 +0x00000001
).DebugPrintfLastMask ( "processSyncOpItem: Irregularity while processing item, status=%hd"
, aStatusCommand.getStatusCode() ); }
4053 )){ if (((0x00000080 +0x00000001) & getDbgMask()) == (0x00000080
+0x00000001)) getDbgLogger()->setNextMask(0x00000080 +0x00000001
).DebugPrintfLastMask ( "processSyncOpItem: Irregularity while processing item, status=%hd"
, aStatusCommand.getStatusCode() ); }
;
4054 }
4055 }
4056 // done
4057 return regular;
4058} // TSyncSession::processSyncOpItem
4059
4060
4061#endif // not SYNCSESSION_PART2_EXCLUDE
4062#ifndef SYNCSESSION_PART1_EXCLUDE
4063
4064
4065// generate challenge for session
4066SmlChalPtr_t TSyncSession::newSessionChallenge(void)
4067{
4068 sysync::TAuthTypes auth = requestedAuthType();
4069
4070 // Avoid misleading debug output (there is no challenge)
4071 // and more importantly, creating a new nonce that is not
4072 // going to be used. That causes unnecessary disk writes.
4073 if (auth == sysync::auth_none) return NULL__null;
4074
4075 string nonce;
4076 getNextNonce(fRemoteURI.c_str(),nonce);
4077 PDEBUGPRINTFX(DBG_PROTO,({ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ( "Challenge for next auth: AuthType=%s, Nonce='%s', binary %sallowed"
, authTypeSyncMLNames[auth], nonce.c_str(), getEncoding()==SML_WBXML
? "" : "NOT " ); }
4078 "Challenge for next auth: AuthType=%s, Nonce='%s', binary %sallowed",{ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ( "Challenge for next auth: AuthType=%s, Nonce='%s', binary %sallowed"
, authTypeSyncMLNames[auth], nonce.c_str(), getEncoding()==SML_WBXML
? "" : "NOT " ); }
4079 authTypeSyncMLNames[auth],{ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ( "Challenge for next auth: AuthType=%s, Nonce='%s', binary %sallowed"
, authTypeSyncMLNames[auth], nonce.c_str(), getEncoding()==SML_WBXML
? "" : "NOT " ); }
4080 nonce.c_str(),{ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ( "Challenge for next auth: AuthType=%s, Nonce='%s', binary %sallowed"
, authTypeSyncMLNames[auth], nonce.c_str(), getEncoding()==SML_WBXML
? "" : "NOT " ); }
4081 getEncoding()==SML_WBXML ? "" : "NOT "{ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ( "Challenge for next auth: AuthType=%s, Nonce='%s', binary %sallowed"
, authTypeSyncMLNames[auth], nonce.c_str(), getEncoding()==SML_WBXML
? "" : "NOT " ); }
4082 )){ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ( "Challenge for next auth: AuthType=%s, Nonce='%s', binary %sallowed"
, authTypeSyncMLNames[auth], nonce.c_str(), getEncoding()==SML_WBXML
? "" : "NOT " ); }
;
4083 return newChallenge(auth,nonce,getEncoding()==SML_WBXML);
4084} // TSyncSession::newSessionChallenge
4085
4086
4087// generate credentials (based on fRemoteNonce, fRemoteRequestedAuth, fRemoteRequestedAuthEnc)
4088SmlCredPtr_t TSyncSession::newCredentials(const char *aUser, const char *aPassword)
4089{
4090 SmlCredPtr_t credP = NULL__null;
4091 SmlMetInfMetInfPtr_t metinfP = NULL__null;
4092 uInt8 *authdata = NULL__null;
4093 void *tobefreed = NULL__null;
4094 uInt32 authdatalen=0;
4095 bool isbinary=false;
4096 uInt8 digest[16]; // for MD5 digest
4097
4098 // create auth data
4099 // - build basic user/pw string
4100 string userpw;
4101 userpw.assign(aUser);
4102 userpw+=':';
4103 userpw.append(aPassword);
4104 // - code auth data
4105 switch (fRemoteRequestedAuth) {
4106 case auth_basic:
4107 // Note: this has been clarified in SyncML 1.1: even if B64 is inherent for
4108 // Basic auth, specifying B64 as format does NOT mean that user:pw is B64-ed twice,
4109 // but it is just an optional declaration of the inherent B64 format.
4110 #ifdef BASIC_AUTH_HAS_INHERENT_B64
4111 // %%% seems to be wrong according to SCTS...
4112 // Note that the b64 here is PART OF THE BASIC AUTH SCHEME
4113 // so format MUST NOT specify b64 again!
4114 fRemoteRequestedAuthEnc=fmt_chr;
4115 // make b64 of string
4116 authdata=(uInt8 *)b64::encode((const uInt8 *)userpw.c_str(), userpw.size(), &authdatalen);
4117 tobefreed=(void *)authdata; // remember to free at end of routine
4118 #else
4119 // basic auth is always b64 encoded
4120 fRemoteRequestedAuthEnc=fmt_b64;
4121 authdata=(uInt8 *)userpw.c_str();
4122 #endif
4123 break;
4124 case auth_md5:
4125 // Note that b64 encoding IS NOT part of the MD5 auth scheme.
4126 // Only if remote specifies b64 format in challenge, b64 encoding is applied
4127 if (fSyncMLVersion<syncml_vers_1_1) {
4128 // before 1.1, nonce was MD5-ed together with user/pw
4129 userpw+=':';
4130 userpw+=fRemoteNonce; // append nonce string, might contain NULs
4131 }
4132 // apply MD5
4133 md5::SYSYNC_MD5_CTX context;
4134 md5::Init (&context);
4135 md5::Update (&context, (unsigned const char *)userpw.c_str(), userpw.size());
4136 // get result
4137 md5::Final (digest, &context);
4138 // more if SyncML 1.1 or later
4139 if (fSyncMLVersion>=syncml_vers_1_1) {
4140 // starting with 1.1, nonce is added to b64ed-MD5 and the MD5ed again
4141 // - B64 it
4142 authdata=(uInt8*)b64::encode(digest, 16, &authdatalen);
4143 // - MD5 it while adding nonce
4144 md5::Init (&context);
4145 md5::Update (&context, authdata, authdatalen);
4146 b64::free((void *)authdata); // return buffer allocated by b64::encode
4147 // - important: add colon as nonce separator
4148 md5::Update (&context, (uInt8 *) ":", 1);
4149 // - also add nonce that will be used for checking later
4150 md5::Update (&context, (uInt8 *) fRemoteNonce.c_str(), fRemoteNonce.size());
4151 // - this is the MD5 auth value
4152 // according to SyncML 1.1,
4153 // "changes_for_syncml_represent_v11_20020215.pdf", Section 2.19
4154 md5::Final (digest, &context);
4155 // - according to the above mentioned section 2.19, MD5 auth is
4156 // always b64 encoded, even in binary transports. This is a
4157 // contradiction to discussion in syncml@yahoogroups, particularily
4158 // a statement by Peter Thompson who stated that MD5 auth MUST NOT
4159 // be b64 encoded in WBXML. Who knows???
4160 fRemoteRequestedAuthEnc=fmt_b64;
4161 } // syncml 1.1
4162 // auth data is 16 byte digest value in binary
4163 authdata=(uInt8 *)digest;
4164 authdatalen=16;
4165 isbinary=true;
4166 break;
4167 default : break;
4168 } // switch
4169 if (authdata) {
4170 // create cred
4171 credP = SML_NEW(SmlCred_t)((SmlCred_t*) _smlMalloc(sizeof(SmlCred_t)));
4172 // now add auth data (format if necessary)
4173 // - force b64 anyway if content is binary but transport isn't
4174 if (isbinary && getEncoding()==SML_XML) {
4175 fRemoteRequestedAuthEnc=fmt_b64;
4176 isbinary=false;
4177 }
4178 // - create formatted version of content. Use Opaque for binary content
4179 credP->data=newPCDataFormatted(authdata,authdatalen,fRemoteRequestedAuthEnc,isbinary);
4180 // create meta and get pointer
4181 credP->meta=newMeta();
4182 metinfP = smlPCDataToMetInfP(credP->meta);
4183 // add auth type meta
4184 metinfP->type=newPCDataString(authTypeSyncMLNames[fRemoteRequestedAuth]);
4185 // Note: aEncType==fmt_chr will not add format tag, as fmt_chr is the default
4186 metinfP->format=newPCDataFormat(fRemoteRequestedAuthEnc,false); // no format if default of fmt_chr
4187 }
4188 // free buffer
4189 if (tobefreed) b64::free(tobefreed);
4190 // return cred or NULL if none
4191 return credP;
4192} // TSyncSession::newCredentials
4193
4194
4195// check credentials
4196// Note: should be called even if there are no credentials, as we
4197// need a Session login BEFORE generating status with next Nonce
4198bool TSyncSession::checkCredentials(const char *aUserName, const SmlCredPtr_t aCredP, TStatusCommand &aStatusCommand)
4199{
4200 TAuthTypes authtype=auth_basic; // default to basic
4201 char *tobefreed = NULL__null;
4202 const char *authdata = NULL__null;
4203 TFmtTypes authfmt = fmt_chr;
4204 bool authok = false;
4205
4206 #ifdef EXPIRES_AFTER_DATE
4207 // check for hard expiry again
4208 if (
4209 (fCopyOfScrambledNow>(SCRAMBLED_EXPIRY_VALUE*4+503))
4210 #ifdef SYSER_REGISTRATION
4211 && (!getSyncAppBase()->fRegOK) // only abort if no registration (but accept timed registration)
4212 #endif
4213 ) {
4214 aStatusCommand.setStatusCode(401); // seems to be hacked
4215 return false;
4216 }
4217 #endif
4218 // Check type of credentials
4219 if (!aCredP) {
4220 // Anonymous login attempt
4221 authtype=auth_none;
4222 }
4223 else {
4224 SmlMetInfMetInfPtr_t metaP;
4225 if ((metaP=smlPCDataToMetInfP(aCredP->meta))!=NULL__null) {
4226 // look for type
4227 if (metaP->type) {
4228 // get type (otherwise default to auth-basic)
4229 const char *ty = smlPCDataToCharP(metaP->type);
4230 sInt16 t;
4231 if (StrToEnum(authTypeSyncMLNames,numAuthTypes,t,ty)) {
4232 authtype=(TAuthTypes)t;
4233 }
4234 else {
4235 // bad auth schema
4236 authtype=auth_none; // disable checking below
4237 aStatusCommand.setStatusCode(406); // unsupported optional feature (auth method)
4238 aStatusCommand.addItemString(ty); // identify bad auth method
4239 }
4240 }
4241 // look for format
4242 // - get format
4243 if (!smlPCDataToFormat(metaP->format,authfmt)) {
4244 authtype=auth_none; // disable checking below
4245 aStatusCommand.setStatusCode(415); // unsupported format
4246 aStatusCommand.addItemString(smlPCDataToCharP(metaP->format)); // identify bad format
4247 }
4248 // - handle format and get auth data according to auth type
4249 authdata = smlPCDataToCharP(aCredP->data); // get it as is
4250 // Now check auth
4251 switch (authtype) {
4252 case auth_none:
4253 // anonymous login attempt
4254 // - no special measure needed
4255 break;
4256 case auth_basic:
4257 // basic is always b64 encoded
4258 #ifdef SYDEBUG2
4259 if (authfmt!=fmt_b64)
4260 PDEBUGPRINTFX(DBG_ERROR,("Auth-basic has no <format>b64 spec --> assumed b64 anyway")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("Auth-basic has no <format>b64 spec --> assumed b64 anyway"
); }
;
4261 #endif
4262 authfmt=fmt_b64; // basic is ALWAYS b64
4263 break;
4264 case auth_md5:
4265 // verify that we have the username in clear text for MD5 auth
4266 if (!aUserName || *aUserName==0)
4267 {
4268 // username missing, probably strict (bad) SyncML 1.0 conformance,
4269 // we need SyncML 1.0.1 corrected auth (MD5 w/o username is almost
4270 // impossible to process)
4271 authtype=auth_none; // disable checking below
4272 aStatusCommand.setStatusCode(415); // unsupported format
4273 ADDDEBUGITEM(aStatusCommand,"Missing clear-text username in Source LocName (SyncML 1.0.1)"){ if ((((0x00000001) & getDbgMask()) == (0x00000001))) aStatusCommand
.addItemString("Missing clear-text username in Source LocName (SyncML 1.0.1)"
); }
;
4274 PDEBUGPRINTFX(DBG_ERROR,("Missing clear-text username in Source LocName (SyncML 1.0.1)")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("Missing clear-text username in Source LocName (SyncML 1.0.1)"
); }
;
4275 break;
4276 }
4277 // MD5 can come as binary (for WBXML)
4278 if (getEncoding()==SML_WBXML) {
4279 if (authfmt==fmt_chr || authfmt==fmt_bin) {
4280 // assume unencoded MD5 digest (16 bytes binary), make b64
4281 uInt32 l;
4282 tobefreed=b64::encode((uInt8 *)authdata,16,&l);
4283 authdata=tobefreed;
4284 // now authdata is b64 as well
4285 authfmt=fmt_b64;
4286 }
4287 }
4288 break;
4289 case numAuthTypes:
4290 // invalid type?!
4291 break;
4292 }
4293 } // if meta
4294 }
4295 #ifndef MINIMAL_CODE
4296 // save user name for later reference
4297 if (aUserName) fSyncUserName.assign(aUserName);
4298 else fSyncUserName.erase();
4299 #endif
4300 // check credentials
4301 if (authtype==auth_none) {
4302 // check if we can login anonymously
4303 // NOTE: do it anyway, even if !isAuthTypeAllowed() to make sure
4304 // SessionLogin is called
4305 authok=checkCredentials(aUserName,NULL__null,auth_none);
4306 if (!authok || !isAuthTypeAllowed(auth_none)) {
4307 // anonymous login not possible, request credentials
4308 aStatusCommand.setStatusCode(407); // unauthorized, missing credentials
4309 PDEBUGPRINTFX(DBG_PROTO,("Authorization required but none found in SyncHdr, sending status 407 + chal")){ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ("Authorization required but none found in SyncHdr, sending status 407 + chal"
); }
;
4310 // - add challenge
4311 aStatusCommand.setChallenge(newSessionChallenge());
4312 authok=false;
4313 }
4314 }
4315 else {
4316 // verify format (must be MD5 by now)
4317 if (authfmt!=fmt_b64) {
4318 aStatusCommand.setStatusCode(415); // unsupported format
4319 }
4320 else if (!authdata || !*authdata) {
4321 aStatusCommand.setStatusCode(400); // missing data, malformed request
4322 }
4323 else {
4324 // first check credentials
4325 // NOTE: This must be done first, to force calling SessionLogin
4326 // in all cases
4327 authok=checkCredentials(aUserName,authdata,authtype);
4328 // now check result
4329 if (!isAuthTypeAllowed(authtype)) {
4330 aStatusCommand.setStatusCode(401); // we need another auth type, tell client which one
4331 authok=false; // anyway, reject
4332 PDEBUGPRINTFX(DBG_ERROR,("Authorization failed (wrong type of creds), sending 401 + chal")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("Authorization failed (wrong type of creds), sending 401 + chal"
); }
;
4333 }
4334 else if (!authok) {
4335 // auth type allowed, but auth itself not ok
4336 aStatusCommand.setStatusCode(401); // unauthorized, bad credentials
4337 PDEBUGPRINTFX(DBG_ERROR,("Authorization failed (invalid credentials) sending 401 + chal")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("Authorization failed (invalid credentials) sending 401 + chal"
); }
;
4338 }
4339 if (!authok) {
4340 // - add challenge
4341 aStatusCommand.setChallenge(newSessionChallenge());
4342 }
4343 }
4344 }
4345 // free buffer if any
4346 if (tobefreed) b64::free(tobefreed);
4347 // make sure we see what config was used in the log
4348 DebugShowCfgInfo();
4349 PDEBUGPRINTFX(DBG_HOT,({ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "==== Authorisation %s with SyncML Engine Version %d.%d.%d.%d"
, authok ? "successful" : "failed", 3, 4, 0, 47 ); }
4350 "==== Authorisation %s with SyncML Engine Version %d.%d.%d.%d",{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "==== Authorisation %s with SyncML Engine Version %d.%d.%d.%d"
, authok ? "successful" : "failed", 3, 4, 0, 47 ); }
4351 authok ? "successful" : "failed",{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "==== Authorisation %s with SyncML Engine Version %d.%d.%d.%d"
, authok ? "successful" : "failed", 3, 4, 0, 47 ); }
4352 SYSYNC_VERSION_MAJOR,{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "==== Authorisation %s with SyncML Engine Version %d.%d.%d.%d"
, authok ? "successful" : "failed", 3, 4, 0, 47 ); }
4353 SYSYNC_VERSION_MINOR,{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "==== Authorisation %s with SyncML Engine Version %d.%d.%d.%d"
, authok ? "successful" : "failed", 3, 4, 0, 47 ); }
4354 SYSYNC_SUBVERSION,{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "==== Authorisation %s with SyncML Engine Version %d.%d.%d.%d"
, authok ? "successful" : "failed", 3, 4, 0, 47 ); }
4355 SYSYNC_BUILDNUMBER{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "==== Authorisation %s with SyncML Engine Version %d.%d.%d.%d"
, authok ? "successful" : "failed", 3, 4, 0, 47 ); }
4356 )){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "==== Authorisation %s with SyncML Engine Version %d.%d.%d.%d"
, authok ? "successful" : "failed", 3, 4, 0, 47 ); }
;
4357 if (IS_SERVER(getSyncAppBase()->isServer())) {
4358 #ifdef SYSYNC_SERVER1
4359 PDEBUGPRINTFX(DBG_HOT,({ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "==== SyncML URL used = '%s', username as sent by remote = '%s'"
, fInitialLocalURI.c_str(), fSyncUserName.c_str() ); }
4360 "==== SyncML URL used = '%s', username as sent by remote = '%s'",{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "==== SyncML URL used = '%s', username as sent by remote = '%s'"
, fInitialLocalURI.c_str(), fSyncUserName.c_str() ); }
4361 fInitialLocalURI.c_str(),{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "==== SyncML URL used = '%s', username as sent by remote = '%s'"
, fInitialLocalURI.c_str(), fSyncUserName.c_str() ); }
4362 fSyncUserName.c_str(){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "==== SyncML URL used = '%s', username as sent by remote = '%s'"
, fInitialLocalURI.c_str(), fSyncUserName.c_str() ); }
4363 )){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "==== SyncML URL used = '%s', username as sent by remote = '%s'"
, fInitialLocalURI.c_str(), fSyncUserName.c_str() ); }
;
4364 #endif
4365 } // server
4366 // return result
4367 return authok;
4368} // TSyncSession::checkCredentials(SmlCredPtr_t...)
4369
4370
4371// check credential string
4372bool TSyncSession::checkCredentials(const char *aUserName, const char *aCred, TAuthTypes aAuthType)
4373{
4374 // now check auth
4375 if (aAuthType==auth_basic) {
4376 // basic auth allows extracting clear-text password
4377 string user,password;
4378 getAuthBasicUserPass(aCred,user,password);
4379 #ifndef MINIMAL_CODE
4380 fSyncUserName = user;
4381 #endif
4382 if (aUserName && !(user==aUserName)) {
4383 // username does not match LocName (should, in SyncML 1.0.1 and later)
4384 PDEBUGPRINTFX(DBG_PROTO,({ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ( "basic_auth encoded username (%s) does not match LocName username (%s)"
, user.c_str(), aUserName ? aUserName : "[NULL Username]" ); }
4385 "basic_auth encoded username (%s) does not match LocName username (%s)",{ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ( "basic_auth encoded username (%s) does not match LocName username (%s)"
, user.c_str(), aUserName ? aUserName : "[NULL Username]" ); }
4386 user.c_str(),{ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ( "basic_auth encoded username (%s) does not match LocName username (%s)"
, user.c_str(), aUserName ? aUserName : "[NULL Username]" ); }
4387 aUserName ? aUserName : "[NULL Username]"{ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ( "basic_auth encoded username (%s) does not match LocName username (%s)"
, user.c_str(), aUserName ? aUserName : "[NULL Username]" ); }
4388 )){ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ( "basic_auth encoded username (%s) does not match LocName username (%s)"
, user.c_str(), aUserName ? aUserName : "[NULL Username]" ); }
;
4389 }
4390 // we have the password in clear text
4391 return SessionLogin(user.c_str(), password.c_str(), sectyp_clearpass, fRemoteURI.c_str());
4392 }
4393 else if (aAuthType==auth_md5) {
4394 // login user and device to the service
4395 // - this is normally implemented in derived classes
4396 return SessionLogin(aUserName, aCred, fSyncMLVersion>=syncml_vers_1_1 ? sectyp_md5_V11 : sectyp_md5_V10, fRemoteURI.c_str());
4397 }
4398 else if (aAuthType==auth_none) {
4399 // even if we have no login, do a "login" with empty credentials
4400 return SessionLogin("anonymous", NULL__null, sectyp_anonymous, fRemoteURI.c_str());
4401 }
4402 else {
4403 return false; // unknown auth, is not ok
4404 }
4405} // TSyncSession::checkCredentials(const char *...)
4406
4407
4408
4409// Helper function:
4410// check plain user / password / nonce combination
4411// against given auth string.
4412bool TSyncSession::checkAuthPlain(
4413 const char *aUserName, const char *aPassWord, const char *aNonce, // given values
4414 const char *aAuthString, TAuthSecretTypes aAuthStringType // check against this
4415)
4416{
4417 string upw;
4418
4419 #ifdef SYDEBUG2
4420 PDEBUGPRINTFX(DBG_ADMIN,("Username = %s",aUserName)){ if (((0x00000040) & getDbgMask()) == (0x00000040)) getDbgLogger
()->setNextMask(0x00000040).DebugPrintfLastMask ("Username = %s"
,aUserName); }
;
4421 DEBUGPRINTFX(DBG_USERDATA+DBG_EXOTIC,("Password = %s",aPassWord)){ if (((0x01000000 +0x80000000) & getDbgMask()) == (0x01000000
+0x80000000)) getDbgLogger()->setNextMask(0x01000000 +0x80000000
).DebugPrintfLastMask ("Password = %s",aPassWord
); }
;
4422 #endif
4423 if (aAuthStringType==sectyp_anonymous) {
4424 return (aPassWord==NULL__null || *aPassWord==0); // anonymous login ok if no password expected
4425 }
4426 else if (aAuthStringType==sectyp_clearpass) {
4427 return (strcmp(aAuthString,aPassWord)==0); // login ok if password matches
4428 }
4429 else {
4430 // must be MD5
4431 // - concatenate user:password
4432 upw = aUserName;
4433 upw+=':';
4434 upw.append(aPassWord);
4435 // depends on method
4436 if (aAuthStringType==sectyp_md5_V11) {
4437 // V1.1 requires MD5b64-ing user/pw before adding nonce
4438 MD5B64(upw.c_str(),upw.size(),upw);
4439 }
4440 // now check result
4441 return checkMD5WithNonce(upw.c_str(),aNonce,aAuthString);
4442 }
4443 // unknown auth secret type
4444 return false;
4445} // TSyncSession::checkAuthPlain
4446
4447
4448// Helper function:
4449// check MD5B64(user:pw) / nonce combination
4450// against given auth string.
4451bool TSyncSession::checkAuthMD5(
4452 const char *aUserName, const char *aMD5B64, const char *aNonce, // given values
4453 const char *aAuthString, TAuthSecretTypes aAuthStringType // check against this
4454)
4455{
4456
4457 if (aAuthStringType==sectyp_md5_V11) {
4458 // we have a V11 authstring, check it against our MD5B64(user:pw)
4459 return checkMD5WithNonce(aMD5B64,aNonce,aAuthString);
4460 }
4461 else if (aAuthStringType==sectyp_clearpass) {
4462 // we must generate the MD5B64(user:pw) from clear text
4463 string myAuthString = aUserName;
4464 myAuthString+=':';
4465 myAuthString+=aAuthString;
4466 MD5B64(myAuthString.c_str(),myAuthString.size(),myAuthString);
4467 #ifdef SYDEBUG2
4468 PDEBUGPRINTFX(DBG_ADMIN,("MD5B64(user:pw) stored in local DB = %s",aMD5B64)){ if (((0x00000040) & getDbgMask()) == (0x00000040)) getDbgLogger
()->setNextMask(0x00000040).DebugPrintfLastMask ("MD5B64(user:pw) stored in local DB = %s"
,aMD5B64); }
;
4469 PDEBUGPRINTFX(DBG_ADMIN,("calculated MD5B64(remoteuser:remotepw) = %s",myAuthString.c_str())){ if (((0x00000040) & getDbgMask()) == (0x00000040)) getDbgLogger
()->setNextMask(0x00000040).DebugPrintfLastMask ("calculated MD5B64(remoteuser:remotepw) = %s"
,myAuthString.c_str()); }
;
4470 #endif
4471 // then we can directly compare them
4472 return myAuthString==aMD5B64;
4473 }
4474 else
4475 return false; // we cannot auth V1.0 MD5 against MD5B64(user:password)
4476} // checkAuthMD5
4477
4478
4479// Helper function:
4480// check V1.1 MD5 type auth against known md5userpass
4481// (B64 encoded MD5 digest of user:password) and nonce
4482// Note: This works only with V1.1-type credentials!!!!
4483bool TSyncSession::checkMD5WithNonce(
4484 const char *aStringBeforeNonce,
4485 const char *aNonce,
4486 const char *aMD5B64Creds
4487)
4488{
4489 string pattern; // pattern to match with
4490
4491 // see if user/pw/nonce matches given MD5
4492 // - add nonce to prepared string
4493 // For V1.0 this is "user:password"
4494 // For >=V1.1 this is MD5B64("user:password")
4495 pattern = aStringBeforeNonce;
4496 pattern+=':';
4497 pattern.append(aNonce);
4498 // - MD5 and B64 entire thing (again)
4499 MD5B64(pattern.c_str(),pattern.size(),pattern);
4500 #ifdef SYDEBUG2
4501 DEBUGPRINTFX(DBG_ADMIN ,("String before Nonce = %s",aStringBeforeNonce)){ if (((0x00000040) & getDbgMask()) == (0x00000040)) getDbgLogger
()->setNextMask(0x00000040).DebugPrintfLastMask ("String before Nonce = %s"
,aStringBeforeNonce); }
;
4502 DEBUGPRINTFX(DBG_ADMIN ,("Nonce used = %s",aNonce)){ if (((0x00000040) & getDbgMask()) == (0x00000040)) getDbgLogger
()->setNextMask(0x00000040).DebugPrintfLastMask ("Nonce used = %s"
,aNonce); }
;
4503 PDEBUGPRINTFX(DBG_ADMIN,("Locally calculated MD5B64 = %s",pattern.c_str())){ if (((0x00000040) & getDbgMask()) == (0x00000040)) getDbgLogger
()->setNextMask(0x00000040).DebugPrintfLastMask ("Locally calculated MD5B64 = %s"
,pattern.c_str()); }
;
4504 PDEBUGPRINTFX(DBG_ADMIN,("Received MD5B64 from remote = %s",aMD5B64Creds)){ if (((0x00000040) & getDbgMask()) == (0x00000040)) getDbgLogger
()->setNextMask(0x00000040).DebugPrintfLastMask ("Received MD5B64 from remote = %s"
,aMD5B64Creds); }
;
4505 #endif
4506 // - now compare with given credentials
4507 return strnncmp(aMD5B64Creds,pattern.c_str(),pattern.size())==0;
4508} // TSyncSession::checkMD5WithNonce
4509
4510
4511// helper: get user/password out of basic credential string, returns false if bad cred
4512bool TSyncSession::getAuthBasicUserPass(const char *aBasicCreds, string &aUsername, string &aPassword)
4513{
4514 // - convert to user/pw string
4515 uInt32 userpwlen;
4516 uInt8 *userpw=b64::decode(aBasicCreds, 0, &userpwlen);
4517 bool ok=false;
4518 if (userpw) {
4519 // adjust length if already null terminated
4520 if (userpw[userpwlen-1]==0) userpwlen=strlen((char *)userpw);
4521 // extract plain-text username first
4522 const char *p=strchr((const char *)userpw,':');
4523 if (p) {
4524 // save user name
4525 aUsername.assign((const char *)userpw,p-(const char *)userpw);
4526 // save password
4527 aPassword.assign(p+1);
4528 ok=true;
4529 }
4530 }
4531 b64::free(userpw);
4532 return ok;
4533} // TSyncSession::getAuthBasicUserPass
4534
4535
4536// check credential string (clear text pw, MD5, etc.)
4537// This function is normally derived to provide checking of auth string
4538// Notes:
4539// - all auth requests are resolved using this function.
4540// - For pre-SyncML 1.1 MD5 auth, credentials are checkable only
4541// against plain text passwords. It's up to the derived class to decide if
4542// this is possible or not.
4543bool TSyncSession::SessionLogin(
4544 const char *aUserName,
4545 const char *aAuthString,
4546 TAuthSecretTypes aAuthStringType,
4547 const char *aDeviceID
4548)
4549{
4550 string nonce;
4551 // get config for session
4552 TSessionConfig *scP = getSessionConfig();
4553 // anonymous is always ok (because checking if anonymous allowed is done already)
4554 if (aAuthStringType==sectyp_anonymous) return true; // ok
4555 // check simple auth
4556 if (scP->fSimpleAuthUser.empty()) return false; // no simple auth
4557 // check user name
4558 if (strucmp(scP->fSimpleAuthUser.c_str(),aUserName)!=0) return false; // wrong user name
4559 // now check auth string
4560 if (aAuthStringType==sectyp_md5_V10 || aAuthStringType==sectyp_md5_V11) {
4561 // we need a nonce
4562 getAuthNonce(aDeviceID,nonce);
4563 }
4564 // now check
4565 return checkAuthPlain(
4566 scP->fSimpleAuthUser.c_str(),
4567 scP->fSimpleAuthPassword.c_str(),
4568 nonce.c_str(),
4569 aAuthString,
4570 aAuthStringType
4571 );
4572} // TSyncSession::SessionLogin
4573
4574
4575
4576// check remote devinf to detect special behaviour needed for some clients (or servers). Base class
4577// does not do anything on server level (configured rules are handled at session level)
4578// - NOTE: aDevInfP can be NULL to specify that remote device has not sent any devInf at all
4579// and this is a blind sync attempt (so best-guess workaround settings might apply)
4580localstatus TSyncSession::checkRemoteSpecifics(SmlDevInfDevInfPtr_t aDevInfP, SmlDevInfDevInfPtr_t *aOverrideDevInfP)
4581{
4582 #if defined(SYSER_REGISTRATION) || !defined(NO_REMOTE_RULES)
4583 localstatus sta = LOCERR_OK;
4584 #endif
4585
4586 // check hard-coded restrictions
4587 if (aDevInfP && (
4588 false
4589 #ifdef REMOTE_RESTR_DEVID
4590 || strwildcmp(smlPCDataToCharP(aDevInfP->devid),REMOTE_RESTR_DEVID)!=0
4591 #endif
4592 #ifdef REMOTE_RESTR_MAN
4593 || strwildcmp(smlPCDataToCharP(aDevInfP->man),REMOTE_RESTR_MAN)!=0
4594 #endif
4595 #ifdef REMOTE_RESTR_MOD
4596 || strwildcmp(smlPCDataToCharP(aDevInfP->mod),REMOTE_RESTR_MOD)!=0
4597 #endif
4598 #ifdef REMOTE_RESTR_OEM
4599 || strwildcmp(smlPCDataToCharP(aDevInfP->oem),REMOTE_RESTR_OEM)!=0
4600 #endif
4601 #ifdef REMOTE_RESTR_URI
4602 || strwildcmp(fRemoteURI.c_str(),REMOTE_RESTR_URI)!=0
4603 #endif
4604 )) {
4605 PDEBUGPRINTFX(DBG_ERROR,("Software not allowed syncing with this remote party")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("Software not allowed syncing with this remote party"
); }
;
4606 AbortSession(403,true);
4607 return 403;
4608 }
4609
4610 // check license restrictions
4611 #ifdef SYSER_REGISTRATION
4612 sInt16 daysleft;
4613 string s;
4614
4615 // - get restriction string from licensed info
4616 sta = getSyncAppBase()->getAppEnableInfo(daysleft, NULL__null, &s);
4617 string restrid,restrval;
4618 const char *p = s.c_str(); // start of license info string
4619 while (sta==LOCERR_OK && (p=getSyncAppBase()->getLicenseRestriction(p,restrid,restrval))!=NULL__null) {
4620 const char *restr=NULL__null;
4621 if (restrid=="u") { // URL
4622 // we can check the remote URL without having devinf
4623 restr=fRemoteURI.c_str();
4624 }
4625 else {
4626 if (restrid.size()==1) {
4627 // there is a restriction
4628 if (!aDevInfP) {
4629 // we cannot check these restrictions without having a devInf
4630 sta = LOCERR_BADREG;
4631 PDEBUGPRINTFX(DBG_ERROR,("License restriction needs devInf from remote but none found -> block sync")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("License restriction needs devInf from remote but none found -> block sync"
); }
;
4632 break;
4633 }
4634 // we have devinf, we can check it
4635 switch (restrid[0]) {
4636 case 'i' : restr=smlPCDataToCharP(aDevInfP->devid); break;
4637 case 'm' : restr=smlPCDataToCharP(aDevInfP->man); break;
4638 case 't' : restr=smlPCDataToCharP(aDevInfP->mod); break;
4639 case 'o' : restr=smlPCDataToCharP(aDevInfP->oem); break;
4640 }
4641 }
4642 }
4643 // - now compare with wildcards allowed if we have anything to compare
4644 if (restr) sta = strwildcmp(restr,restrval.c_str())==0 ? LOCERR_OK : LOCERR_BADREG; // service unavailable
4645 }
4646 // - abort if not ok
4647 if (sta!=LOCERR_OK) {
4648 PDEBUGPRINTFX(DBG_ERROR,("License does not allow syncing with this remote party, status=%hd",sta)){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("License does not allow syncing with this remote party, status=%hd"
,sta); }
;
4649 AbortSession(403,true,sta);
4650 return sta;
4651 }
4652 #endif // SYSER_REGISTRATION
4653 // check remote rules
4654 #ifndef NO_REMOTE_RULES
4655 PDEBUGBLOCKDESC("RemoteRules","Checking for remote rules")getDbgLogger()->DebugOpenBlock( "RemoteRules","Checking for remote rules"
)
;
4656 // get config for session
4657 TSessionConfig *scP = getSessionConfig();
4658 // look if we have matching rule(s) for this device
4659 TRemoteRulesList::iterator pos;
4660 for(pos=scP->fRemoteRulesList.begin();pos!=scP->fRemoteRulesList.end();pos++) {
4661 TRemoteRuleConfig *ruleP = *pos;
4662 // compare with devinf (or test for default-rule if aDevInfP is NULL
4663 if (
4664 !ruleP->fSubRule && // subrules never apply directly
4665 (ruleP->fManufacturer.empty() || (aDevInfP && strwildcmp(smlPCDataToCharP(aDevInfP->man),ruleP->fManufacturer.c_str())==0)) &&
4666 (ruleP->fModel.empty() || (aDevInfP && strwildcmp(smlPCDataToCharP(aDevInfP->mod),ruleP->fModel.c_str())==0)) &&
4667 (ruleP->fOem.empty() || (aDevInfP && strwildcmp(smlPCDataToCharP(aDevInfP->oem),ruleP->fOem.c_str())==0)) &&
4668 (ruleP->fFirmwareVers.empty() || (aDevInfP && ruleP->fFirmwareVers==smlPCDataToCharP(aDevInfP->fwv))) &&
4669 (ruleP->fSoftwareVers.empty() || (aDevInfP && ruleP->fSoftwareVers==smlPCDataToCharP(aDevInfP->swv))) &&
4670 (ruleP->fHardwareVers.empty() || (aDevInfP && ruleP->fHardwareVers==smlPCDataToCharP(aDevInfP->hwv))) &&
4671 (ruleP->fDevId.empty() || (aDevInfP && ruleP->fDevId==smlPCDataToCharP(aDevInfP->devid))) &&
4672 (ruleP->fDevTyp.empty() || (aDevInfP && ruleP->fDevTyp==smlPCDataToCharP(aDevInfP->devtyp)))
4673 ) {
4674 // found matching rule
4675 PDEBUGPRINTFX(DBG_HOT,("Found <remoterule> '%s' matching for this peer",ruleP->getName())){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("Found <remoterule> '%s' matching for this peer"
,ruleP->getName()); }
;
4676 // remember it
4677 fActiveRemoteRules.push_back(ruleP);
4678 // add included subrules
4679 TRemoteRulesList::iterator spos;
4680 for(spos=ruleP->fSubRulesList.begin();spos!=ruleP->fSubRulesList.end();spos++) {
4681 fActiveRemoteRules.push_back(*spos);
4682 PDEBUGPRINTFX(DBG_HOT,("- rule also activates sub-rule '%s'",(*spos)->getName())){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("- rule also activates sub-rule '%s'"
,(*spos)->getName()); }
;
4683 }
4684 // if this rule is final, don't check for further matches
4685 if (ruleP->fFinalRule) break;
4686 }
4687 }
4688 // process activated rules and subrules
4689 for(pos=fActiveRemoteRules.begin();pos!=fActiveRemoteRules.end();pos++) {
4690 // activate this rule
4691 TRemoteRuleConfig *ruleP = *pos;
4692 if (ruleP->fOverrideDevInfP && aOverrideDevInfP) {
4693 // processing in caller will continue with updated DevInf
4694 *aOverrideDevInfP = ruleP->fOverrideDevInfP;
4695 }
4696 // - apply options that have a value
4697 if (ruleP->fLegacyMode>=0) fLegacyMode = ruleP->fLegacyMode;
4698 if (ruleP->fLenientMode>=0) fLenientMode = ruleP->fLenientMode;
4699 if (ruleP->fLimitedFieldLengths>=0) fLimitedRemoteFieldLengths = ruleP->fLimitedFieldLengths;
4700 if (ruleP->fDontSendEmptyProperties>=0) fDontSendEmptyProperties = ruleP->fDontSendEmptyProperties;
4701 if (ruleP->fDoQuote8BitContent>=0) fDoQuote8BitContent = ruleP->fDoQuote8BitContent;
4702 if (ruleP->fDoNotFoldContent>=0) fDoNotFoldContent = ruleP->fDoNotFoldContent;
4703 if (ruleP->fNoReplaceInSlowsync>=0) fNoReplaceInSlowsync = ruleP->fNoReplaceInSlowsync;
4704 if (ruleP->fTreatRemoteTimeAsLocal>=0) fTreatRemoteTimeAsLocal = ruleP->fTreatRemoteTimeAsLocal;
4705 if (ruleP->fTreatRemoteTimeAsUTC>=0) fTreatRemoteTimeAsUTC = ruleP->fTreatRemoteTimeAsUTC;
4706 if (ruleP->fVCal10EnddatesSameDay>=0) fVCal10EnddatesSameDay = ruleP->fVCal10EnddatesSameDay;
4707 if (ruleP->fIgnoreDevInfMaxSize>=0) fIgnoreDevInfMaxSize = ruleP->fIgnoreDevInfMaxSize;
4708 if (ruleP->fIgnoreCTCap>=0) fIgnoreCTCap = ruleP->fIgnoreCTCap;
4709 if (ruleP->fDSPathInDevInf>=0) fDSPathInDevInf = ruleP->fDSPathInDevInf;
4710 if (ruleP->fDSCgiInDevInf>=0) fDSCgiInDevInf = ruleP->fDSCgiInDevInf;
4711 if (ruleP->fUpdateClientDuringSlowsync>=0) fUpdateClientDuringSlowsync = ruleP->fUpdateClientDuringSlowsync;
4712 if (ruleP->fUpdateServerDuringSlowsync>=0) fUpdateServerDuringSlowsync = ruleP->fUpdateServerDuringSlowsync;
4713 if (ruleP->fAllowMessageRetries>=0) fAllowMessageRetries = ruleP->fAllowMessageRetries;
4714 if (ruleP->fStrictExecOrdering>=0) fStrictExecOrdering = ruleP->fStrictExecOrdering;
4715 if (ruleP->fTreatCopyAsAdd>=0) fTreatCopyAsAdd = ruleP->fTreatCopyAsAdd;
4716 if (ruleP->fCompleteFromClientOnly>=0) fCompleteFromClientOnly = ruleP->fCompleteFromClientOnly;
4717 if (ruleP->fRequestMaxTime>=0) fRequestMaxTime = ruleP->fRequestMaxTime;
4718 if (ruleP->fDefaultOutCharset!=chs_unknown) fDefaultOutCharset = ruleP->fDefaultOutCharset;
4719 if (ruleP->fDefaultInCharset!=chs_unknown) fDefaultInCharset = ruleP->fDefaultInCharset;
4720 // - possibly override decisions that are otherwise made by session
4721 // Note: this is not a single option because we had this before rule options were tristates.
4722 if (ruleP->fForceUTC>0) fRemoteCanHandleUTC=true;
4723 if (ruleP->fForceLocaltime>0) fRemoteCanHandleUTC=false;
4724 // - descriptive name for the device (for log)
4725 #ifndef MINIMAL_CODE
4726 if (!ruleP->fRemoteDescName.empty()) fRemoteDescName = ruleP->fRemoteDescName;
4727 #endif
4728 // - test for rejection
4729 if (ruleP->fRejectStatusCode!=DONT_REJECT0xFFFF) {
4730 // reject operation with this device
4731 sta = ruleP->fRejectStatusCode;
4732 PDEBUGPRINTFX(DBG_ERROR,("remote party rejected by <remoterule> '%s', status=%hd",ruleP->getName(),sta)){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("remote party rejected by <remoterule> '%s', status=%hd"
,ruleP->getName(),sta); }
;
4733 AbortSession(sta,true);
4734 return sta;
4735 }
4736 // - execute rule script
4737 #ifdef SCRIPT_SUPPORT1
4738 if (!ruleP->fRuleScriptTemplate.empty()) {
4739 // copy from template
4740 string ruleScript = ruleP->fRuleScriptTemplate;
4741 // resolve variable references
4742 TScriptContext::linkIntoContext(ruleScript,fSessionScriptContextP,this);
4743 // execute now
4744 PDEBUGPRINTFX(DBG_HOT,("Executing rulescript for rule '%s'",ruleP->getName())){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("Executing rulescript for rule '%s'"
,ruleP->getName()); }
;
4745 TScriptContext::execute(
4746 fSessionScriptContextP,
4747 ruleScript,
4748 NULL__null, // context's function table
4749 NULL__null // datastore pointer needed for context
4750 );
4751 }
4752 #endif
4753 } // for all activated rules
4754 PDEBUGENDBLOCK("RemoteRules")getDbgLogger()->DebugCloseBlock( "RemoteRules");
4755 // something failed in applying remote rules?
4756 if (sta!=LOCERR_OK)
4757 return sta;
4758 #endif // NO_REMOTE_RULES
4759 // Final adjustments
4760 #ifndef NO_REMOTE_RULES
4761 if (fActiveRemoteRules.empty())
4762 #endif
4763 {
4764 // no remote rule (none found or mechanism excluded by NO_REMOTE_RULES)
4765 if (!aDevInfP) {
4766 // no devinf -> blind sync attempt: apply best-guess workaround settings
4767 // Note that a blind sync attempt means that the remote party is at least partly non-compliant, as we always request a devInf!
4768 PDEBUGPRINTFX(DBG_ERROR,("No remote information available -> applying best-guess workaround behaviour options")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("No remote information available -> applying best-guess workaround behaviour options"
); }
;
4769 #ifndef MINIMAL_CODE
4770 // set device description
4771 fRemoteDescName = fRemoteName.empty() ? "[unknown remote]" : fRemoteName.c_str();
4772 fRemoteDescName += " (no devInf)";
4773 #endif // MINIMAL_CODE
4774 // switch on legacy behaviour (conservative preferred types)
4775 fLegacyMode = true;
4776 if (IS_CLIENT(!getSyncAppBase()->isServer())) {
4777 // Client case
4778 fRemoteCanHandleUTC = true; // Assume server can handle UTC (it is very improbable a server can't)
4779 }
4780 else {
4781 // Server case
4782 fRemoteCanHandleUTC = fSyncMLVersion==syncml_vers_1_0 ? true : false; // Assume client cannot handle UTC (it is likely a client can't, or at least can't properly, so localtime is safer)
4783 fLimitedRemoteFieldLengths = true; // assume limited client field length (almost all clients have limited length)
4784 }
4785 }
4786 }
4787 // show summary
4788 PDEBUGPRINTFX(DBG_HOT+DBG_REMOTEINFO,("Summary of all behaviour options (possibly modified by remote rule(s))")){ if (((0x00000001 +0x00000100) & getDbgMask()) == (0x00000001
+0x00000100)) getDbgLogger()->setNextMask(0x00000001 +0x00000100
).DebugPrintfLastMask ("Summary of all behaviour options (possibly modified by remote rule(s))"
); }
;
4789 #ifndef MINIMAL_CODE
4790 PDEBUGPRINTFX(DBG_HOT+DBG_REMOTEINFO,("- Remote Description : %s",fRemoteDescName.c_str())){ if (((0x00000001 +0x00000100) & getDbgMask()) == (0x00000001
+0x00000100)) getDbgLogger()->setNextMask(0x00000001 +0x00000100
).DebugPrintfLastMask ("- Remote Description : %s",fRemoteDescName
.c_str()); }
;
4791 #endif
4792 PDEBUGPRINTFX(DBG_HOT+DBG_REMOTEINFO,("- Legacy mode : %s",boolString(fLegacyMode))){ if (((0x00000001 +0x00000100) & getDbgMask()) == (0x00000001
+0x00000100)) getDbgLogger()->setNextMask(0x00000001 +0x00000100
).DebugPrintfLastMask ("- Legacy mode : %s",boolString
(fLegacyMode)); }
;
4793 PDEBUGPRINTFX(DBG_HOT+DBG_REMOTEINFO,("- Lenient mode : %s",boolString(fLenientMode))){ if (((0x00000001 +0x00000100) & getDbgMask()) == (0x00000001
+0x00000100)) getDbgLogger()->setNextMask(0x00000001 +0x00000100
).DebugPrintfLastMask ("- Lenient mode : %s",boolString
(fLenientMode)); }
;
4794 PDEBUGPRINTFX(DBG_HOT+DBG_REMOTEINFO,("- Limited Field Lengths : %s",boolString(fLimitedRemoteFieldLengths))){ if (((0x00000001 +0x00000100) & getDbgMask()) == (0x00000001
+0x00000100)) getDbgLogger()->setNextMask(0x00000001 +0x00000100
).DebugPrintfLastMask ("- Limited Field Lengths : %s",boolString
(fLimitedRemoteFieldLengths)); }
;
4795 PDEBUGPRINTFX(DBG_HOT+DBG_REMOTEINFO,("- Do not send empty props : %s",boolString(fDontSendEmptyProperties))){ if (((0x00000001 +0x00000100) & getDbgMask()) == (0x00000001
+0x00000100)) getDbgLogger()->setNextMask(0x00000001 +0x00000100
).DebugPrintfLastMask ("- Do not send empty props : %s",boolString
(fDontSendEmptyProperties)); }
;
4796 PDEBUGPRINTFX(DBG_HOT+DBG_REMOTEINFO,("- Quote 8bit content : %s",boolString(fDoQuote8BitContent))){ if (((0x00000001 +0x00000100) & getDbgMask()) == (0x00000001
+0x00000100)) getDbgLogger()->setNextMask(0x00000001 +0x00000100
).DebugPrintfLastMask ("- Quote 8bit content : %s",boolString
(fDoQuote8BitContent)); }
;
4797 PDEBUGPRINTFX(DBG_HOT+DBG_REMOTEINFO,("- Prevent Content Folding : %s",boolString(fDoNotFoldContent))){ if (((0x00000001 +0x00000100) & getDbgMask()) == (0x00000001
+0x00000100)) getDbgLogger()->setNextMask(0x00000001 +0x00000100
).DebugPrintfLastMask ("- Prevent Content Folding : %s",boolString
(fDoNotFoldContent)); }
;
4798 PDEBUGPRINTFX(DBG_HOT+DBG_REMOTEINFO,("- No replace in slowsync : %s",boolString(fNoReplaceInSlowsync))){ if (((0x00000001 +0x00000100) & getDbgMask()) == (0x00000001
+0x00000100)) getDbgLogger()->setNextMask(0x00000001 +0x00000100
).DebugPrintfLastMask ("- No replace in slowsync : %s",boolString
(fNoReplaceInSlowsync)); }
;
4799 PDEBUGPRINTFX(DBG_HOT+DBG_REMOTEINFO,("- Treat remote TZ as local : %s",boolString(fTreatRemoteTimeAsLocal))){ if (((0x00000001 +0x00000100) & getDbgMask()) == (0x00000001
+0x00000100)) getDbgLogger()->setNextMask(0x00000001 +0x00000100
).DebugPrintfLastMask ("- Treat remote TZ as local : %s",boolString
(fTreatRemoteTimeAsLocal)); }
;
4800 PDEBUGPRINTFX(DBG_HOT+DBG_REMOTEINFO,("- Treat remote TZ as UTC : %s",boolString(fTreatRemoteTimeAsUTC))){ if (((0x00000001 +0x00000100) & getDbgMask()) == (0x00000001
+0x00000100)) getDbgLogger()->setNextMask(0x00000001 +0x00000100
).DebugPrintfLastMask ("- Treat remote TZ as UTC : %s",boolString
(fTreatRemoteTimeAsUTC)); }
;
4801 PDEBUGPRINTFX(DBG_HOT+DBG_REMOTEINFO,("- Use 23:59:59 end dates : %s",boolString(fVCal10EnddatesSameDay))){ if (((0x00000001 +0x00000100) & getDbgMask()) == (0x00000001
+0x00000100)) getDbgLogger()->setNextMask(0x00000001 +0x00000100
).DebugPrintfLastMask ("- Use 23:59:59 end dates : %s",boolString
(fVCal10EnddatesSameDay)); }
;
4802 PDEBUGPRINTFX(DBG_HOT+DBG_REMOTEINFO,("- Ignore field maxSize : %s",boolString(fIgnoreDevInfMaxSize))){ if (((0x00000001 +0x00000100) & getDbgMask()) == (0x00000001
+0x00000100)) getDbgLogger()->setNextMask(0x00000001 +0x00000100
).DebugPrintfLastMask ("- Ignore field maxSize : %s",boolString
(fIgnoreDevInfMaxSize)); }
;
4803 PDEBUGPRINTFX(DBG_HOT+DBG_REMOTEINFO,("- Ignore CTCap : %s",boolString(fIgnoreCTCap))){ if (((0x00000001 +0x00000100) & getDbgMask()) == (0x00000001
+0x00000100)) getDbgLogger()->setNextMask(0x00000001 +0x00000100
).DebugPrintfLastMask ("- Ignore CTCap : %s",boolString
(fIgnoreCTCap)); }
;
4804 PDEBUGPRINTFX(DBG_HOT+DBG_REMOTEINFO,("- send DS path in devInf : %s",boolString(fDSPathInDevInf))){ if (((0x00000001 +0x00000100) & getDbgMask()) == (0x00000001
+0x00000100)) getDbgLogger()->setNextMask(0x00000001 +0x00000100
).DebugPrintfLastMask ("- send DS path in devInf : %s",boolString
(fDSPathInDevInf)); }
;
4805 PDEBUGPRINTFX(DBG_HOT+DBG_REMOTEINFO,("- send DS CGI in devInf : %s",boolString(fDSCgiInDevInf))){ if (((0x00000001 +0x00000100) & getDbgMask()) == (0x00000001
+0x00000100)) getDbgLogger()->setNextMask(0x00000001 +0x00000100
).DebugPrintfLastMask ("- send DS CGI in devInf : %s",boolString
(fDSCgiInDevInf)); }
;
4806 PDEBUGPRINTFX(DBG_HOT+DBG_REMOTEINFO,("- Update Client in slowsync : %s",boolString(fUpdateClientDuringSlowsync))){ if (((0x00000001 +0x00000100) & getDbgMask()) == (0x00000001
+0x00000100)) getDbgLogger()->setNextMask(0x00000001 +0x00000100
).DebugPrintfLastMask ("- Update Client in slowsync : %s",boolString
(fUpdateClientDuringSlowsync)); }
;
4807 PDEBUGPRINTFX(DBG_HOT+DBG_REMOTEINFO,("- Update Server in slowsync : %s",boolString(fUpdateServerDuringSlowsync))){ if (((0x00000001 +0x00000100) & getDbgMask()) == (0x00000001
+0x00000100)) getDbgLogger()->setNextMask(0x00000001 +0x00000100
).DebugPrintfLastMask ("- Update Server in slowsync : %s",boolString
(fUpdateServerDuringSlowsync)); }
;
4808 PDEBUGPRINTFX(DBG_HOT+DBG_REMOTEINFO,("- Allow message retries : %s",boolString(fAllowMessageRetries))){ if (((0x00000001 +0x00000100) & getDbgMask()) == (0x00000001
+0x00000100)) getDbgLogger()->setNextMask(0x00000001 +0x00000100
).DebugPrintfLastMask ("- Allow message retries : %s",boolString
(fAllowMessageRetries)); }
;
4809 PDEBUGPRINTFX(DBG_HOT+DBG_REMOTEINFO,("- Strict SyncML exec order : %s",boolString(fStrictExecOrdering))){ if (((0x00000001 +0x00000100) & getDbgMask()) == (0x00000001
+0x00000100)) getDbgLogger()->setNextMask(0x00000001 +0x00000100
).DebugPrintfLastMask ("- Strict SyncML exec order : %s",boolString
(fStrictExecOrdering)); }
;
4810 PDEBUGPRINTFX(DBG_HOT+DBG_REMOTEINFO,("- Treat copy like add : %s",boolString(fTreatCopyAsAdd))){ if (((0x00000001 +0x00000100) & getDbgMask()) == (0x00000001
+0x00000100)) getDbgLogger()->setNextMask(0x00000001 +0x00000100
).DebugPrintfLastMask ("- Treat copy like add : %s",boolString
(fTreatCopyAsAdd)); }
;
4811 PDEBUGPRINTFX(DBG_HOT+DBG_REMOTEINFO,("- Complete From-Client-Only : %s",boolString(fCompleteFromClientOnly))){ if (((0x00000001 +0x00000100) & getDbgMask()) == (0x00000001
+0x00000100)) getDbgLogger()->setNextMask(0x00000001 +0x00000100
).DebugPrintfLastMask ("- Complete From-Client-Only : %s",boolString
(fCompleteFromClientOnly)); }
;
4812 PDEBUGPRINTFX(DBG_HOT+DBG_REMOTEINFO,("- Remote can handle UTC : %s",boolString(fRemoteCanHandleUTC))){ if (((0x00000001 +0x00000100) & getDbgMask()) == (0x00000001
+0x00000100)) getDbgLogger()->setNextMask(0x00000001 +0x00000100
).DebugPrintfLastMask ("- Remote can handle UTC : %s",boolString
(fRemoteCanHandleUTC)); }
;
4813 PDEBUGPRINTFX(DBG_HOT+DBG_REMOTEINFO,("- Max Request time [sec] : %ld",static_cast<long>(fRequestMaxTime))){ if (((0x00000001 +0x00000100) & getDbgMask()) == (0x00000001
+0x00000100)) getDbgLogger()->setNextMask(0x00000001 +0x00000100
).DebugPrintfLastMask ("- Max Request time [sec] : %ld",static_cast
<long>(fRequestMaxTime)); }
;
4814 PDEBUGPRINTFX(DBG_HOT+DBG_REMOTEINFO,("- Content output charset : %s",MIMECharSetNames[fDefaultOutCharset])){ if (((0x00000001 +0x00000100) & getDbgMask()) == (0x00000001
+0x00000100)) getDbgLogger()->setNextMask(0x00000001 +0x00000100
).DebugPrintfLastMask ("- Content output charset : %s",MIMECharSetNames
[fDefaultOutCharset]); }
;
4815 PDEBUGPRINTFX(DBG_HOT+DBG_REMOTEINFO,("- Content input charset : %s",MIMECharSetNames[fDefaultInCharset])){ if (((0x00000001 +0x00000100) & getDbgMask()) == (0x00000001
+0x00000100)) getDbgLogger()->setNextMask(0x00000001 +0x00000100
).DebugPrintfLastMask ("- Content input charset : %s",MIMECharSetNames
[fDefaultInCharset]); }
;
4816 // done
4817 return LOCERR_OK;
4818} // TSyncSession::checkRemoteSpecifics
4819
4820
4821#ifndef NO_REMOTE_RULES
4822
4823// check if given rule (by name, or if aRuleName=NULL by rule pointer) is active
4824bool TSyncSession::isActiveRule(cAppCharP aRuleName, TRemoteRuleConfig *aRuleP)
4825{
4826 TRemoteRulesList::iterator pos;
4827 for(pos=fActiveRemoteRules.begin();pos!=fActiveRemoteRules.end();pos++) {
4828 if (
4829 (aRuleName==NULL__null && (*pos)==aRuleP) || // match by pointer...
4830 (strucmp(aRuleName,(*pos)->getName())==0) // ...or name
4831 )
4832 return true;
4833 }
4834 // no match
4835 return false;
4836} // TSyncSession::isActiveRule
4837
4838#endif // NO_REMOTE_RULES
4839
4840
4841// access to config
4842TSessionConfig *TSyncSession::getSessionConfig(void)
4843{
4844 TSessionConfig *scP;
4845 GET_CASTED_PTR(scP,TSessionConfig,getSyncAppBase()->getRootConfig()->fAgentConfigP,DEBUGTEXT("no TSessionConfig","sss1")){ scP = dynamic_cast<TSessionConfig *>(getSyncAppBase()
->getRootConfig()->fAgentConfigP); if (!scP) { throw TSyncException
("no TSessionConfig"); } }
;
4846 return scP;
4847} // TSyncSession::getSessionConfig
4848
4849
4850
4851// process a Map command in context of session
4852bool TSyncSession::processMapCommand(
4853 SmlMapPtr_t aMapCommandP, // the map command contents
4854 TStatusCommand &aStatusCommand, // pre-set 200 status, can be modified in case of errors
4855 bool &aQueueForLater
4856)
4857{
4858 // if not overridden, we cannot process Map
4859 aStatusCommand.setStatusCode(403);
4860 ADDDEBUGITEM(aStatusCommand,"Map command not allowed in this context"){ if ((((0x00000001) & getDbgMask()) == (0x00000001))) aStatusCommand
.addItemString("Map command not allowed in this context"); }
;
4861 return false; // failed
4862} // TSyncSession::processMapCommand
4863
4864
4865// called to issue custom get and put commands
4866// may issue custom get and put commands
4867void TSyncSession::issueCustomGetPut(bool aGotDevInf, bool aSentDevInf)
4868{
4869 #ifdef SCRIPT_SUPPORT1
4870 // call script that might issue GETs and PUTs
4871 // - set up context
4872 TGetPutResultFuncContext ctx;
4873 ctx.isPut=false;
4874 ctx.canIssue=true;
4875 ctx.statuscode=0;
4876 ctx.itemURI.erase();
4877 ctx.itemData.erase();
4878 ctx.metaType.erase();
4879 // - execute
4880 TScriptContext::execute(
4881 fSessionScriptContextP,
4882 getSessionConfig()->fCustomGetPutScript,
4883 &GetPutResultFuncTable,
4884 &ctx // caller context
4885 );
4886 #endif
4887} // TSyncSession::issueCustomGetPut
4888
4889
4890// called to issue custom put commands at end of session
4891// may issue custom put commands (gets don't make sense at end of a session)
4892void TSyncSession::issueCustomEndPut(void)
4893{
4894 #ifdef SCRIPT_SUPPORT1
4895 // call script that might issue GETs and PUTs
4896 // - set up context
4897 TGetPutResultFuncContext ctx;
4898 ctx.isPut=false;
4899 ctx.canIssue=true;
4900 ctx.statuscode=0;
4901 ctx.itemURI.erase();
4902 ctx.itemData.erase();
4903 ctx.metaType.erase();
4904 // - execute
4905 TScriptContext::execute(
4906 fSessionScriptContextP,
4907 getSessionConfig()->fCustomEndPutScript,
4908 &GetPutResultFuncTable,
4909 &ctx // caller context
4910 );
4911 #endif
4912} // TSyncSession::issueCustomEndPut
4913
4914
4915
4916
4917
4918// called to process unknown get item, may return a Results command. Must set status to non-404 if get could be served
4919// (may be overridden by descendants, only called if no descendant can handle an item)
4920TResultsCommand *TSyncSession::processGetItem(const char *aLocUri, TGetCommand *aGetCommandP, SmlItemPtr_t aGetItemP, TStatusCommand &aStatusCommand)
4921{
4922 TResultsCommand *resultsCmdP = NULL__null;
4923 #ifdef SCRIPT_SUPPORT1
4924 // first check if script handles it
4925 // - set up context
4926 TGetPutResultFuncContext ctx;
4927 ctx.isPut=false;
4928 ctx.canIssue=false;
4929 ctx.statuscode=aStatusCommand.getStatusCode();
4930 ctx.itemURI=aLocUri;
4931 ctx.itemData.erase();
4932 // - get meta type of item, if any
4933 AssignString(ctx.metaType,smlMetaTypeToCharP(smlPCDataToMetInfP(aGetItemP->meta)));
4934 if (ctx.metaType.empty()) {
4935 // none in item, get from command
4936 AssignString(ctx.metaType,smlMetaTypeToCharP(smlPCDataToMetInfP(aGetCommandP->getMeta())));
4937 }
4938 // - execute
4939 bool hasResult =
4940 TScriptContext::executeTest(
4941 false, // do not assume script handles the GET
4942 fSessionScriptContextP,
4943 getSessionConfig()->fCustomGetHandlerScript,
4944 &GetPutResultFuncTable,
4945 &ctx // caller context
4946 );
4947 // - update status, anyway
4948 aStatusCommand.setStatusCode(ctx.statuscode);
4949 // - create result, if script decides so
4950 if (hasResult) {
4951 // script returns true, so it has handled the GET command
4952 // - create a result command (%%% currently GET command itself does not carry src/targ URIs, only item does)
4953 resultsCmdP = new TResultsCommand(this,aGetCommandP,NULL__null,NULL__null);
4954 // - create data item
4955 SmlItemPtr_t resItemP = newItem();
4956 // - source is get item's URI reflected (if not changed by script)
4957 resItemP->source=newLocation(ctx.itemURI.c_str());
4958 // - data is just string
4959 resItemP->data = newPCDataString(ctx.itemData);
4960 // - add item to command
4961 resultsCmdP->addItem(resItemP);
4962 // - set result command meta if not empty string
4963 resultsCmdP->setMeta(newMetaType(ctx.metaType.c_str()));
4964 // get item handled, return
4965 return resultsCmdP;
4966 }
4967 #endif
4968 // look for ./devinf10 special case
4969 if (strucmp(aLocUri,SyncMLDevInfNames[getSyncMLVersion()])==0) {
4970 // status is ok
4971 aStatusCommand.setStatusCode(200);
4972 // prepare a devinf10 <Result>
4973 resultsCmdP = new TDevInfResultsCommand(this,aGetCommandP);
4974 }
4975 return resultsCmdP;
4976} // TSyncSession::processGetItem
4977
4978
4979// - put and results command processing
4980// (may be overridden by descendants, only called if no descendant can handle an item)
4981void TSyncSession::processPutResultItem(bool aIsPut, const char *aLocUri, TSmlCommand *aPutResultsCommandP, SmlItemPtr_t aPutResultsItemP, TStatusCommand &aStatusCommand)
4982{
4983 localstatus sta = aStatusCommand.getStatusCode();
4984 #ifdef SCRIPT_SUPPORT1
4985 // first check if script handles it
4986 // - set up context
4987 TGetPutResultFuncContext ctx;
4988 ctx.isPut=aIsPut;
4989 ctx.canIssue=false;
4990 ctx.statuscode=sta;
4991 ctx.itemURI=aLocUri;
4992 // - get data of item, if any
4993 smlPCDataToStringObj(aPutResultsItemP->data,ctx.itemData);
4994 // - get meta type of item, if any
4995 AssignString(ctx.metaType,smlMetaTypeToCharP(smlPCDataToMetInfP(aPutResultsItemP->meta)));
4996 if (ctx.metaType.empty()) {
4997 // none in item, get from command
4998 AssignString(ctx.metaType,smlMetaTypeToCharP(smlPCDataToMetInfP(aPutResultsCommandP->getMeta())));
4999 }
5000 // - execute
5001 bool hasProcessed =
5002 TScriptContext::executeTest(
5003 false, // do not assume script handles the PUT or RESULT
5004 fSessionScriptContextP,
5005 getSessionConfig()->fCustomPutResultHandlerScript,
5006 &GetPutResultFuncTable,
5007 &ctx // caller context
5008 );
5009 // update status code
5010 sta=ctx.statuscode;
5011 if (sta!=LOCERR_OK)
5012 aStatusCommand.setStatusCode(syncmlError(sta));
5013 // if processed, return now
5014 if (hasProcessed)
5015 return;
5016 #endif
5017 // check for ./devinfXX
5018 if (strucmp(aLocUri,SyncMLDevInfNames[getSyncMLVersion()])==0) {
5019 // remote is sending DevInf, receive it
5020 SmlDevInfDevInfPtr_t devinfP = smlPCDataToDevInfP(aPutResultsItemP->data);
5021 // save received devinf (if database supports it)
5022 saveRemoteDevInf(getRemoteURI(),devinfP);
5023 // analyze
5024 aStatusCommand.setStatusCode(200); // assume ok
5025 sta=analyzeRemoteDevInf(devinfP);
5026 if (sta!=LOCERR_OK)
5027 aStatusCommand.setStatusCode(syncmlError(sta));
5028 }
5029 else {
5030 // unknown
5031 PDEBUGPRINTFX(DBG_ERROR,({ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "Unknown %s-command with URI=%s received, returning default status=%hd"
, aIsPut ? "PUT" : "RESULTS", aLocUri, sta ); }
5032 "Unknown %s-command with URI=%s received, returning default status=%hd",{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "Unknown %s-command with URI=%s received, returning default status=%hd"
, aIsPut ? "PUT" : "RESULTS", aLocUri, sta ); }
5033 aIsPut ? "PUT" : "RESULTS",{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "Unknown %s-command with URI=%s received, returning default status=%hd"
, aIsPut ? "PUT" : "RESULTS", aLocUri, sta ); }
5034 aLocUri,{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "Unknown %s-command with URI=%s received, returning default status=%hd"
, aIsPut ? "PUT" : "RESULTS", aLocUri, sta ); }
5035 sta{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "Unknown %s-command with URI=%s received, returning default status=%hd"
, aIsPut ? "PUT" : "RESULTS", aLocUri, sta ); }
5036 )){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "Unknown %s-command with URI=%s received, returning default status=%hd"
, aIsPut ? "PUT" : "RESULTS", aLocUri, sta ); }
;
5037 }
5038} // TSyncSession::processPutResultItem
5039
5040
5041
5042// process an alert item in context of session
5043// Most handling takes place in derived classes,
5044// this base class only implements basic stuff
5045// - returns command to be issued after issuing status, NULL if none
5046TSmlCommand *TSyncSession::processAlertItem(
5047 uInt16 aAlertCode, // alert code
5048 SmlItemPtr_t aItemP, // alert item to be processed (as one alert can have multiple items)
5049 SmlCredPtr_t aCredP, // alert cred element, if any
5050 TStatusCommand &aStatusCommand, // pre-set 200 status, can be modified in case of errors
5051 TLocalEngineDS *&aLocalDataStoreP // receives datastore pointer, if alert affects a datastore
5052)
5053{
5054 // no alert response command by default
5055 TSmlCommand *alertresponsecmdP=NULL__null;
5056 TLocalEngineDS *datastoreP;
5057 string optionsCGI,identifyingTargetURI;
5058
5059 // dispatch numeric alerts
5060 switch (aAlertCode) {
5061 // sync alerts
5062 case 200:
5063 case 201:
5064 case 202:
5065 case 203:
5066 case 204:
5067 case 205:
5068 // Sync resume alert
5069 case 225: {
5070 // Synchronisation initialisation alerts
5071 if (allowAlertAfterMap() && fIncomingState==psta_map) {
5072 // reset to state that allows a sync to start
5073 PDEBUGPRINTFX(DBG_HOT,("process alert: restart sync")){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("process alert: restart sync"
); }
;
5074 fIncomingState = psta_init;
5075 fOutgoingState = psta_init;
5076 fRestarting = true;
5077 }
5078
5079 // - test if context is ok
5080 if (fIncomingState!=psta_init && fIncomingState!=psta_initsync) {
5081 // Sync alert only allowed in init package or combined init/sync
5082 PDEBUGPRINTFX(DBG_ERROR,({ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "Sync Alert not allowed with incoming package state='%s'"
, PackageStateNames[fIncomingState] ); }
5083 "Sync Alert not allowed with incoming package state='%s'",{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "Sync Alert not allowed with incoming package state='%s'"
, PackageStateNames[fIncomingState] ); }
5084 PackageStateNames[fIncomingState]{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "Sync Alert not allowed with incoming package state='%s'"
, PackageStateNames[fIncomingState] ); }
5085 )){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "Sync Alert not allowed with incoming package state='%s'"
, PackageStateNames[fIncomingState] ); }
;
5086 aStatusCommand.setStatusCode(403); // forbidden
5087 ADDDEBUGITEM(aStatusCommand,"Sync Alert only allowed in init package"){ if ((((0x00000001) & getDbgMask()) == (0x00000001))) aStatusCommand
.addItemString("Sync Alert only allowed in init package"); }
;
5088 return NULL__null; // no alert sent back
5089 }
5090 // find requested database by URI
5091 const char *target = smlSrcTargLocURIToCharP(aItemP->target);
5092 if (!target || !target[0]) {
5093 // same fallback for Sony Ericsson C510 as in
5094 // TSyncSession::initSync()
5095 target = smlSrcTargLocURIToCharP(aItemP->source);
5096 }
5097 datastoreP = findLocalDataStoreByURI(
5098 target, // target as sent from remote
5099 &optionsCGI, // options, if any
5100 &identifyingTargetURI // identifying part of URI (CGI removed)
5101 );
5102 if (!datastoreP) {
5103 // no such local datastore
5104 aStatusCommand.setStatusCode(404); // not found
5105 }
5106 else {
5107 // save alerted datastore pointer (will be returned to caller, which is TAlertCommand)
5108 aLocalDataStoreP=datastoreP;
5109 // get anchors
5110 const char *nextRemoteAnchor = smlMetaNextAnchorToCharP(smlPCDataToMetInfP(aItemP->meta));
5111 if (nextRemoteAnchor==NULL__null) nextRemoteAnchor=""; // some remotes may send NO anchor
5112 const char *lastRemoteAnchor = smlMetaLastAnchorToCharP(smlPCDataToMetInfP(aItemP->meta));
5113 if (lastRemoteAnchor==NULL__null) lastRemoteAnchor=""; // some remotes may send NO anchor
5114 // get URIs
5115 const char *targetURI = smlSrcTargLocURIToCharP(aItemP->target);
5116 const char *sourceURI = smlSrcTargLocURIToCharP(aItemP->source);
5117 // get Filter
5118 SmlFilterPtr_t targetFilter = aItemP->target ? aItemP->target->filter : NULL__null;
5119 if (fRestarting) {
5120 // reset datastore first
5121 datastoreP->engFinishDataStoreSync(LOCERR_OK);
5122 }
5123 // alert datastore of requested sync
5124 // - let datastore process alert and generate additional alert if needed
5125 // NOTE: this might generate a PUT command if remote needs to see our
5126 // devInf (config changed since last sync)
5127 alertresponsecmdP=datastoreP->engProcessSyncAlert(
5128 NULL__null, // not as subdatastore
5129 aAlertCode, // the alert code
5130 lastRemoteAnchor, // last anchor of client
5131 nextRemoteAnchor, // next anchor of client
5132 targetURI, // target as sent from remote
5133 identifyingTargetURI.c_str(), // identifying part of URI (relative, options removed)
5134 optionsCGI.c_str(), // extracted options (e.g. filtering) CGI
5135 targetFilter, // DS 1.2 filter, if any (can be NULL if none)
5136 sourceURI, // source URI
5137 aStatusCommand // status that might be modified
5138 );
5139 // echo next anchor sent with item back in status
5140 // %%% specs say that only next anchor must be echoed, SCTS echoes both
5141 SmlItemPtr_t itemP = newItem(); // empty item
5142 // NOTE: anchor is MetInf, but is echoed in DATA part of item, not META!
5143 itemP->data = newMetaAnchor(nextRemoteAnchor,NULL__null); // only next (like specs)
5144 aStatusCommand.addItem(itemP); // add it to status
5145 }
5146 break;
5147 }
5148 case 224 :
5149 // Suspend alert
5150 SuspendSession(514);
5151 break;
5152 case 100 :
5153 // DISPLAY
5154 PDEBUGPRINTFX(DBG_HOT,({ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "---------------- DISPLAY ALERT (100): %s"
, smlPCDataToCharP(aItemP->data) ); }
5155 "---------------- DISPLAY ALERT (100): %s",{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "---------------- DISPLAY ALERT (100): %s"
, smlPCDataToCharP(aItemP->data) ); }
5156 smlPCDataToCharP(aItemP->data){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "---------------- DISPLAY ALERT (100): %s"
, smlPCDataToCharP(aItemP->data) ); }
5157 )){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "---------------- DISPLAY ALERT (100): %s"
, smlPCDataToCharP(aItemP->data) ); }
;
5158 // show it on the console
5159 CONSOLEPRINTF((SySync_ConsolePrintf(stderr, "SYSYNC " "***** Message from Remote: %s"
"\n", smlPCDataToCharP(aItemP->data))
5160 "***** Message from Remote: %s",SySync_ConsolePrintf(stderr, "SYSYNC " "***** Message from Remote: %s"
"\n", smlPCDataToCharP(aItemP->data))
5161 smlPCDataToCharP(aItemP->data)SySync_ConsolePrintf(stderr, "SYSYNC " "***** Message from Remote: %s"
"\n", smlPCDataToCharP(aItemP->data))
5162 ))SySync_ConsolePrintf(stderr, "SYSYNC " "***** Message from Remote: %s"
"\n", smlPCDataToCharP(aItemP->data))
;
5163 // callback to allow GUI clients to display the message
5164 if (!SESSION_PROGRESS_EVENT(this,pev_display100,NULL,uIntPtr(smlPCDataToCharP(aItemP->data)),0,0)this->NotifySessionProgressEvent(pev_display100,__null,uIntPtr
(smlPCDataToCharP(aItemP->data)),0,0)
) {
5165 // user answered no to our question "continue?"
5166 aStatusCommand.setStatusCode(514); // cancelled
5167 // Do NOT abort the session, so give the server a chance to do someting more sensible based on the 514 status.
5168 aStatusCommand.addItemString("User abort in response to Alert 100 message");
5169 PDEBUGPRINTFX(DBG_ERROR,("User abort after seeing Alert 100 message: %s",smlPCDataToCharP(aItemP->data))){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("User abort after seeing Alert 100 message: %s"
,smlPCDataToCharP(aItemP->data)); }
;
5170 }
5171 break;
5172 case 223:
5173 // Chunking error: missing end of chunk
5174 aStatusCommand.setStatusCode(223);
5175 aStatusCommand.addItemString("Missing end of chunk");
5176 PDEBUGPRINTFX(DBG_ERROR,({ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "Warning: Alert Code 223 -> Missing end of chunk for item localid='%s', remoteid='%s'"
, smlSrcTargLocURIToCharP(aItemP->target), smlSrcTargLocURIToCharP
(aItemP->source) ); }
5177 "Warning: Alert Code 223 -> Missing end of chunk for item localid='%s', remoteid='%s'",{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "Warning: Alert Code 223 -> Missing end of chunk for item localid='%s', remoteid='%s'"
, smlSrcTargLocURIToCharP(aItemP->target), smlSrcTargLocURIToCharP
(aItemP->source) ); }
5178 smlSrcTargLocURIToCharP(aItemP->target),{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "Warning: Alert Code 223 -> Missing end of chunk for item localid='%s', remoteid='%s'"
, smlSrcTargLocURIToCharP(aItemP->target), smlSrcTargLocURIToCharP
(aItemP->source) ); }
5179 smlSrcTargLocURIToCharP(aItemP->source){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "Warning: Alert Code 223 -> Missing end of chunk for item localid='%s', remoteid='%s'"
, smlSrcTargLocURIToCharP(aItemP->target), smlSrcTargLocURIToCharP
(aItemP->source) ); }
5180 )){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "Warning: Alert Code 223 -> Missing end of chunk for item localid='%s', remoteid='%s'"
, smlSrcTargLocURIToCharP(aItemP->target), smlSrcTargLocURIToCharP
(aItemP->source) ); }
;
5181 break;
5182 default :
5183 // unknown alert code
5184 aStatusCommand.setStatusCode(406);
5185 aStatusCommand.addItemString("Unimplemented Alert Code");
5186 PDEBUGPRINTFX(DBG_ERROR,("Unimplemented Alert Code %hd -> Status 406",aAlertCode)){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("Unimplemented Alert Code %hd -> Status 406"
,aAlertCode); }
;
5187 break;
5188 } // switch fAlertCode
5189 // return command generated (or NULL if none)
5190 return alertresponsecmdP;
5191} // TSyncSession::processAlertItem
5192
5193
5194
5195#ifdef SYDEBUG2
5196 #define XML_TRANSLATION_ENABLED
5197#else
5198 #undef XML_TRANSLATION_ENABLED
5199#endif
5200
5201#ifdef SYDEBUG2
5202
5203void TSyncSession::XMLTranslationIncomingStart(void)
5204{
5205 // start translation instances
5206 #ifdef XML_TRANSLATION_ENABLED
5207 if (fXMLtranslate && !getRootConfig()->fDebugConfig.fDebugInfoPath.empty()) {
5208 DEBUGPRINTFX(DBG_EXOTIC,("Initializing incoming XML translation instance")){ if (((0x80000000) & getDbgMask()) == (0x80000000)) getDbgLogger
()->setNextMask(0x80000000).DebugPrintfLastMask ("Initializing incoming XML translation instance"
); }
5209 if (!getSyncAppBase()->newSmlInstance(
5210 SML_XML,
5211 getRootConfig()->fLocalMaxMsgSize * 3, // XML should not be more than 3 times larger than WBXML
5212 fIncomingXMLInstance
5213 )) {
5214 // if instance cannot be created, turn off XML translation to avoid crashes
5215 fXMLtranslate=false;
5216 PDEBUGPRINTFX(DBG_ERROR,("XML translation disabled because of lacking memory")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("XML translation disabled because of lacking memory"
); }
5217 }
5218 }
5219 else
5220 fXMLtranslate=false;
5221 #endif
5222} // TSyncSession::XMLTranslationIncomingStart
5223
5224
5225void TSyncSession::XMLTranslationOutgoingStart(void)
5226{
5227 #ifdef XML_TRANSLATION_ENABLED
5228 // start translation instances
5229 if (fXMLtranslate && !getRootConfig()->fDebugConfig.fDebugInfoPath.empty()) {
5230 DEBUGPRINTFX(DBG_EXOTIC,("Initializing outgoing XML translation instance")){ if (((0x80000000) & getDbgMask()) == (0x80000000)) getDbgLogger
()->setNextMask(0x80000000).DebugPrintfLastMask ("Initializing outgoing XML translation instance"
); }
5231 if (!getSyncAppBase()->newSmlInstance(
5232 SML_XML,
5233 getRootConfig()->fLocalMaxMsgSize * 3, // XML should not be more than 3 times larger than WBXML
5234 fOutgoingXMLInstance
5235 )) {
5236 // if instance cannot be created, turn off XML translation to avoid crashes
5237 fXMLtranslate=false;
5238 PDEBUGPRINTFX(DBG_ERROR,("XML translation disabled because of lacking memory")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("XML translation disabled because of lacking memory"
); }
5239 }
5240 }
5241 else
5242 fXMLtranslate=false;
5243 #endif
5244} // TSyncSession::XMLTranslationOutgoingStart
5245
5246
5247/// @todo
5248/// rewrite this to use a TDbgOut object to write stuff
5249// finish and output XML translation of incoming traffic
5250void TSyncSession::XMLTranslationIncomingEnd(void)
5251{
5252 #ifdef XML_TRANSLATION_ENABLED
5253 if (fIncomingXMLInstance && fXMLtranslate) {
5254 // write XML translation of input and output to files
5255 DEBUGPRINTFX(DBG_EXOTIC,("XML translation enabled...")){ if (((0x80000000) & getDbgMask()) == (0x80000000)) getDbgLogger
()->setNextMask(0x80000000).DebugPrintfLastMask ("XML translation enabled..."
); }
5256 MemPtr_t XMLtext;
5257 MemSize_t XMLsize;
5258 string fname;
5259 // - incoming
5260 // - get XML
5261 DEBUGPRINTFX(DBG_EXOTIC,("- Writing incoming XML translation")){ if (((0x80000000) & getDbgMask()) == (0x80000000)) getDbgLogger
()->setNextMask(0x80000000).DebugPrintfLastMask ("- Writing incoming XML translation"
); }
5262 XMLtext=NULL__null; XMLsize=0;
5263 if (smlLockReadBuffer(fIncomingXMLInstance,&XMLtext,&XMLsize)==SML_ERR_OK0x00) {
5264 // save to file
5265 TDbgOut *dbgOutP = getSyncAppBase()->newDbgOutputter(false);
5266 if (dbgOutP) {
5267 // create base file name (trm = translated message)
5268 string dumpfilename;
5269 StringObjPrintf(dumpfilename,
5270 "%s_trm%03ld_%03ld_incoming",
5271 getDbgLogger()->getDebugPath(), // path + session log base name
5272 (long)getLastIncomingMsgID(),
5273 (long)++fDumpCount // to make sure it is unique even in case of retries
5274 );
5275 // open file in raw mode
5276 if (dbgOutP->openDbg(
5277 dumpfilename.c_str(),
5278 ".xml",
5279 dbgflush_none,
5280 false, // append to existing if any
5281 true // raw mode
5282 )) {
5283 // write out the entire message
5284 dbgOutP->putRawData(XMLtext, XMLsize);
5285 // close the file
5286 dbgOutP->closeDbg();
5287 // add a link into the session file to immediately get the file
5288 PDEBUGPRINTFX(DBG_HOT+DBG_PROTO,({ if (((0x00000001 +0x00000010) & getDbgMask()) == (0x00000001
+0x00000010)) getDbgLogger()->setNextMask(0x00000001 +0x00000010
).DebugPrintfLastMask ( "Incoming %sXML message msgID=%ld &html;<a href=\"%s_trm%03ld_%03ld_incoming.xml\" target=\"_blank\">&html;saved as XML translation&html;</a>&html;"
, getEncoding()==SML_XML ? "" : "WB", (long)getLastIncomingMsgID
(), getDbgLogger()->getDebugFilename(), (long)getLastIncomingMsgID
(), (long)fDumpCount ); }
5289 "Incoming %sXML message msgID=%ld &html;<a href=\"%s_trm%03ld_%03ld_incoming.xml\" target=\"_blank\">&html;saved as XML translation&html;</a>&html;",{ if (((0x00000001 +0x00000010) & getDbgMask()) == (0x00000001
+0x00000010)) getDbgLogger()->setNextMask(0x00000001 +0x00000010
).DebugPrintfLastMask ( "Incoming %sXML message msgID=%ld &html;<a href=\"%s_trm%03ld_%03ld_incoming.xml\" target=\"_blank\">&html;saved as XML translation&html;</a>&html;"
, getEncoding()==SML_XML ? "" : "WB", (long)getLastIncomingMsgID
(), getDbgLogger()->getDebugFilename(), (long)getLastIncomingMsgID
(), (long)fDumpCount ); }
5290 getEncoding()==SML_XML ? "" : "WB",{ if (((0x00000001 +0x00000010) & getDbgMask()) == (0x00000001
+0x00000010)) getDbgLogger()->setNextMask(0x00000001 +0x00000010
).DebugPrintfLastMask ( "Incoming %sXML message msgID=%ld &html;<a href=\"%s_trm%03ld_%03ld_incoming.xml\" target=\"_blank\">&html;saved as XML translation&html;</a>&html;"
, getEncoding()==SML_XML ? "" : "WB", (long)getLastIncomingMsgID
(), getDbgLogger()->getDebugFilename(), (long)getLastIncomingMsgID
(), (long)fDumpCount ); }
5291 (long)getLastIncomingMsgID(),{ if (((0x00000001 +0x00000010) & getDbgMask()) == (0x00000001
+0x00000010)) getDbgLogger()->setNextMask(0x00000001 +0x00000010
).DebugPrintfLastMask ( "Incoming %sXML message msgID=%ld &html;<a href=\"%s_trm%03ld_%03ld_incoming.xml\" target=\"_blank\">&html;saved as XML translation&html;</a>&html;"
, getEncoding()==SML_XML ? "" : "WB", (long)getLastIncomingMsgID
(), getDbgLogger()->getDebugFilename(), (long)getLastIncomingMsgID
(), (long)fDumpCount ); }
5292 getDbgLogger()->getDebugFilename(), // session log base name{ if (((0x00000001 +0x00000010) & getDbgMask()) == (0x00000001
+0x00000010)) getDbgLogger()->setNextMask(0x00000001 +0x00000010
).DebugPrintfLastMask ( "Incoming %sXML message msgID=%ld &html;<a href=\"%s_trm%03ld_%03ld_incoming.xml\" target=\"_blank\">&html;saved as XML translation&html;</a>&html;"
, getEncoding()==SML_XML ? "" : "WB", (long)getLastIncomingMsgID
(), getDbgLogger()->getDebugFilename(), (long)getLastIncomingMsgID
(), (long)fDumpCount ); }
5293 (long)getLastIncomingMsgID(),{ if (((0x00000001 +0x00000010) & getDbgMask()) == (0x00000001
+0x00000010)) getDbgLogger()->setNextMask(0x00000001 +0x00000010
).DebugPrintfLastMask ( "Incoming %sXML message msgID=%ld &html;<a href=\"%s_trm%03ld_%03ld_incoming.xml\" target=\"_blank\">&html;saved as XML translation&html;</a>&html;"
, getEncoding()==SML_XML ? "" : "WB", (long)getLastIncomingMsgID
(), getDbgLogger()->getDebugFilename(), (long)getLastIncomingMsgID
(), (long)fDumpCount ); }
5294 (long)fDumpCount{ if (((0x00000001 +0x00000010) & getDbgMask()) == (0x00000001
+0x00000010)) getDbgLogger()->setNextMask(0x00000001 +0x00000010
).DebugPrintfLastMask ( "Incoming %sXML message msgID=%ld &html;<a href=\"%s_trm%03ld_%03ld_incoming.xml\" target=\"_blank\">&html;saved as XML translation&html;</a>&html;"
, getEncoding()==SML_XML ? "" : "WB", (long)getLastIncomingMsgID
(), getDbgLogger()->getDebugFilename(), (long)getLastIncomingMsgID
(), (long)fDumpCount ); }
5295 )){ if (((0x00000001 +0x00000010) & getDbgMask()) == (0x00000001
+0x00000010)) getDbgLogger()->setNextMask(0x00000001 +0x00000010
).DebugPrintfLastMask ( "Incoming %sXML message msgID=%ld &html;<a href=\"%s_trm%03ld_%03ld_incoming.xml\" target=\"_blank\">&html;saved as XML translation&html;</a>&html;"
, getEncoding()==SML_XML ? "" : "WB", (long)getLastIncomingMsgID
(), getDbgLogger()->getDebugFilename(), (long)getLastIncomingMsgID
(), (long)fDumpCount ); }
;
5296 }
5297 else {
5298 PDEBUGPRINTFX(DBG_ERROR,("Cannot write <xmltranslate> file")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("Cannot write <xmltranslate> file"
); }
;
5299 }
5300 delete dbgOutP;
5301 }
5302 }
5303 }
5304 if (fIncomingXMLInstance) {
5305 // finally free instance
5306 getSyncAppBase()->freeSmlInstance(fIncomingXMLInstance);
5307 fIncomingXMLInstance=NULL__null;
5308 }
5309 #endif
5310} // TSyncSession::XMLTranslationIncomingEnd
5311
5312
5313// finish and output XML translation of outgoing traffic
5314/// @todo
5315/// rewrite this to use a TDbgOut object to write stuff
5316void TSyncSession::XMLTranslationOutgoingEnd(void)
5317{
5318 #ifdef XML_TRANSLATION_ENABLED
5319 if (fOutgoingXMLInstance && fXMLtranslate) {
5320 // write XML translation of input and output to files
5321 DEBUGPRINTFX(DBG_EXOTIC,("XML translation enabled...")){ if (((0x80000000) & getDbgMask()) == (0x80000000)) getDbgLogger
()->setNextMask(0x80000000).DebugPrintfLastMask ("XML translation enabled..."
); }
5322 MemPtr_t XMLtext;
5323 MemSize_t XMLsize;
5324 string fname;
5325 // - outgoing
5326 // write only if session is debug-enabled
5327 // - get XML
5328 DEBUGPRINTFX(DBG_EXOTIC,("- Writing outgoing XML translation")){ if (((0x80000000) & getDbgMask()) == (0x80000000)) getDbgLogger
()->setNextMask(0x80000000).DebugPrintfLastMask ("- Writing outgoing XML translation"
); }
5329 XMLtext=NULL__null; XMLsize=0;
5330 if (smlLockReadBuffer(fOutgoingXMLInstance,&XMLtext,&XMLsize)==SML_ERR_OK0x00) {
5331 // save to file
5332 TDbgOut *dbgOutP = getSyncAppBase()->newDbgOutputter(false);
5333 if (dbgOutP) {
5334 // create base file name (trm = translated message)
5335 string dumpfilename;
5336 StringObjPrintf(dumpfilename,
5337 "%s_trm%03ld_%03ld_outgoing",
5338 getDbgLogger()->getDebugPath(), // path + session log base name
5339 (long)getOutgoingMsgID(),
5340 (long)++fDumpCount // to make sure it is unique even in case of retries
5341 );
5342 // open file in raw mode
5343 if (dbgOutP->openDbg(
5344 dumpfilename.c_str(),
5345 ".xml",
5346 dbgflush_none,
5347 false, // append to existing if any
5348 true // raw mode
5349 )) {
5350 // write out the entire message
5351 dbgOutP->putRawData(XMLtext, XMLsize);
5352 // close the file
5353 dbgOutP->closeDbg();
5354 // add a link into the session file to immediately get the file
5355 PDEBUGPRINTFX(DBG_HOT+DBG_PROTO,({ if (((0x00000001 +0x00000010) & getDbgMask()) == (0x00000001
+0x00000010)) getDbgLogger()->setNextMask(0x00000001 +0x00000010
).DebugPrintfLastMask ( "Outgoing %sXML message msgID=%ld &html;<a href=\"%s_trm%03ld_%03ld_outgoing.xml\" target=\"_blank\">&html;saved as XML translation&html;</a>&html;"
, getEncoding()==SML_XML ? "" : "WB", (long)getOutgoingMsgID(
), getDbgLogger()->getDebugFilename(), (long)getOutgoingMsgID
(), (long)fDumpCount ); }
5356 "Outgoing %sXML message msgID=%ld &html;<a href=\"%s_trm%03ld_%03ld_outgoing.xml\" target=\"_blank\">&html;saved as XML translation&html;</a>&html;",{ if (((0x00000001 +0x00000010) & getDbgMask()) == (0x00000001
+0x00000010)) getDbgLogger()->setNextMask(0x00000001 +0x00000010
).DebugPrintfLastMask ( "Outgoing %sXML message msgID=%ld &html;<a href=\"%s_trm%03ld_%03ld_outgoing.xml\" target=\"_blank\">&html;saved as XML translation&html;</a>&html;"
, getEncoding()==SML_XML ? "" : "WB", (long)getOutgoingMsgID(
), getDbgLogger()->getDebugFilename(), (long)getOutgoingMsgID
(), (long)fDumpCount ); }
5357 getEncoding()==SML_XML ? "" : "WB",{ if (((0x00000001 +0x00000010) & getDbgMask()) == (0x00000001
+0x00000010)) getDbgLogger()->setNextMask(0x00000001 +0x00000010
).DebugPrintfLastMask ( "Outgoing %sXML message msgID=%ld &html;<a href=\"%s_trm%03ld_%03ld_outgoing.xml\" target=\"_blank\">&html;saved as XML translation&html;</a>&html;"
, getEncoding()==SML_XML ? "" : "WB", (long)getOutgoingMsgID(
), getDbgLogger()->getDebugFilename(), (long)getOutgoingMsgID
(), (long)fDumpCount ); }
5358 (long)getOutgoingMsgID(),{ if (((0x00000001 +0x00000010) & getDbgMask()) == (0x00000001
+0x00000010)) getDbgLogger()->setNextMask(0x00000001 +0x00000010
).DebugPrintfLastMask ( "Outgoing %sXML message msgID=%ld &html;<a href=\"%s_trm%03ld_%03ld_outgoing.xml\" target=\"_blank\">&html;saved as XML translation&html;</a>&html;"
, getEncoding()==SML_XML ? "" : "WB", (long)getOutgoingMsgID(
), getDbgLogger()->getDebugFilename(), (long)getOutgoingMsgID
(), (long)fDumpCount ); }
5359 getDbgLogger()->getDebugFilename(), // session log base name{ if (((0x00000001 +0x00000010) & getDbgMask()) == (0x00000001
+0x00000010)) getDbgLogger()->setNextMask(0x00000001 +0x00000010
).DebugPrintfLastMask ( "Outgoing %sXML message msgID=%ld &html;<a href=\"%s_trm%03ld_%03ld_outgoing.xml\" target=\"_blank\">&html;saved as XML translation&html;</a>&html;"
, getEncoding()==SML_XML ? "" : "WB", (long)getOutgoingMsgID(
), getDbgLogger()->getDebugFilename(), (long)getOutgoingMsgID
(), (long)fDumpCount ); }
5360 (long)getOutgoingMsgID(),{ if (((0x00000001 +0x00000010) & getDbgMask()) == (0x00000001
+0x00000010)) getDbgLogger()->setNextMask(0x00000001 +0x00000010
).DebugPrintfLastMask ( "Outgoing %sXML message msgID=%ld &html;<a href=\"%s_trm%03ld_%03ld_outgoing.xml\" target=\"_blank\">&html;saved as XML translation&html;</a>&html;"
, getEncoding()==SML_XML ? "" : "WB", (long)getOutgoingMsgID(
), getDbgLogger()->getDebugFilename(), (long)getOutgoingMsgID
(), (long)fDumpCount ); }
5361 (long)fDumpCount{ if (((0x00000001 +0x00000010) & getDbgMask()) == (0x00000001
+0x00000010)) getDbgLogger()->setNextMask(0x00000001 +0x00000010
).DebugPrintfLastMask ( "Outgoing %sXML message msgID=%ld &html;<a href=\"%s_trm%03ld_%03ld_outgoing.xml\" target=\"_blank\">&html;saved as XML translation&html;</a>&html;"
, getEncoding()==SML_XML ? "" : "WB", (long)getOutgoingMsgID(
), getDbgLogger()->getDebugFilename(), (long)getOutgoingMsgID
(), (long)fDumpCount ); }
5362 )){ if (((0x00000001 +0x00000010) & getDbgMask()) == (0x00000001
+0x00000010)) getDbgLogger()->setNextMask(0x00000001 +0x00000010
).DebugPrintfLastMask ( "Outgoing %sXML message msgID=%ld &html;<a href=\"%s_trm%03ld_%03ld_outgoing.xml\" target=\"_blank\">&html;saved as XML translation&html;</a>&html;"
, getEncoding()==SML_XML ? "" : "WB", (long)getOutgoingMsgID(
), getDbgLogger()->getDebugFilename(), (long)getOutgoingMsgID
(), (long)fDumpCount ); }
;
5363 }
5364 else {
5365 PDEBUGPRINTFX(DBG_ERROR,("Cannot write <xmltranslate> file")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("Cannot write <xmltranslate> file"
); }
;
5366 }
5367 delete dbgOutP;
5368 }
5369 }
5370 }
5371 if (fOutgoingXMLInstance) {
5372 // finally free instance
5373 getSyncAppBase()->freeSmlInstance(fOutgoingXMLInstance);
5374 fOutgoingXMLInstance=NULL__null;
5375 }
5376 #endif
5377} // TSyncSession::XMLTranslationOutgoingEnd
5378
5379
5380// dump message from specified buffer
5381void TSyncSession::DumpSyncMLBuffer(MemPtr_t aBuffer, MemSize_t aBufSize, bool aOutgoing, Ret_t aDecoderError)
5382{
5383 #ifdef MSGDUMP1
5384 // log message currently in SML buffer
5385 if (fMsgDump && !getRootConfig()->fDebugConfig.fDebugInfoPath.empty()) {
5386 TDbgOut *dbgOutP = getSyncAppBase()->newDbgOutputter(false);
5387 if (dbgOutP) {
5388 // create base file name
5389 string dumpfilename;
5390 // regular message,
5391 StringObjPrintf(dumpfilename,
5392 "%s_msg%03ld_%03ld_%sing",
5393 getDbgLogger()->getDebugPath(), // path + session log base name
5394 (long)(aOutgoing ? getOutgoingMsgID() : getLastIncomingMsgID()+1), // just generated msgID / expected next incoming ID
5395 (long)++fDumpCount, // to make sure it is unique even in case of retries
5396 aOutgoing ? "outgo" : "incom"
5397 );
5398 if (aDecoderError) {
5399 // append error code
5400 StringObjAppendPrintf(dumpfilename,"_ERR_0x%04X",aDecoderError);
5401 }
5402 // open file in raw mode
5403 if (dbgOutP->openDbg(
5404 dumpfilename.c_str(),
5405 getEncoding()==SML_XML ? ".xml" : ".wbxml",
5406 dbgflush_none,
5407 false, // append to existing if any
5408 true // raw mode
5409 )) {
5410 // write out the entire message
5411 dbgOutP->putRawData(aBuffer, aBufSize);
5412 // close the file
5413 dbgOutP->closeDbg();
5414 // add a link into the session file to immediately get the file if it is XML
5415 if (getEncoding()==SML_XML) {
5416 PDEBUGPRINTFX(DBG_HOT+DBG_PROTO,({ if (((0x00000001 +0x00000010) & getDbgMask()) == (0x00000001
+0x00000010)) getDbgLogger()->setNextMask(0x00000001 +0x00000010
).DebugPrintfLastMask ( "%sing XML message msgID=%ld &html;<a href=\"%s_msg%03ld_%03ld_%sing.xml\" target=\"_blank\">&html;dumped to file&html;</a>&html;"
, aOutgoing ? "Outgo" : "Incom", (long)getOutgoingMsgID(), getDbgLogger
()->getDebugFilename(), (long)(aOutgoing ? getOutgoingMsgID
() : getLastIncomingMsgID()+1), (long)fDumpCount, aOutgoing ?
"outgo" : "incom" ); }
5417 "%sing XML message msgID=%ld &html;<a href=\"%s_msg%03ld_%03ld_%sing.xml\" target=\"_blank\">&html;dumped to file&html;</a>&html;",{ if (((0x00000001 +0x00000010) & getDbgMask()) == (0x00000001
+0x00000010)) getDbgLogger()->setNextMask(0x00000001 +0x00000010
).DebugPrintfLastMask ( "%sing XML message msgID=%ld &html;<a href=\"%s_msg%03ld_%03ld_%sing.xml\" target=\"_blank\">&html;dumped to file&html;</a>&html;"
, aOutgoing ? "Outgo" : "Incom", (long)getOutgoingMsgID(), getDbgLogger
()->getDebugFilename(), (long)(aOutgoing ? getOutgoingMsgID
() : getLastIncomingMsgID()+1), (long)fDumpCount, aOutgoing ?
"outgo" : "incom" ); }
5418 aOutgoing ? "Outgo" : "Incom",{ if (((0x00000001 +0x00000010) & getDbgMask()) == (0x00000001
+0x00000010)) getDbgLogger()->setNextMask(0x00000001 +0x00000010
).DebugPrintfLastMask ( "%sing XML message msgID=%ld &html;<a href=\"%s_msg%03ld_%03ld_%sing.xml\" target=\"_blank\">&html;dumped to file&html;</a>&html;"
, aOutgoing ? "Outgo" : "Incom", (long)getOutgoingMsgID(), getDbgLogger
()->getDebugFilename(), (long)(aOutgoing ? getOutgoingMsgID
() : getLastIncomingMsgID()+1), (long)fDumpCount, aOutgoing ?
"outgo" : "incom" ); }
5419 (long)getOutgoingMsgID(),{ if (((0x00000001 +0x00000010) & getDbgMask()) == (0x00000001
+0x00000010)) getDbgLogger()->setNextMask(0x00000001 +0x00000010
).DebugPrintfLastMask ( "%sing XML message msgID=%ld &html;<a href=\"%s_msg%03ld_%03ld_%sing.xml\" target=\"_blank\">&html;dumped to file&html;</a>&html;"
, aOutgoing ? "Outgo" : "Incom", (long)getOutgoingMsgID(), getDbgLogger
()->getDebugFilename(), (long)(aOutgoing ? getOutgoingMsgID
() : getLastIncomingMsgID()+1), (long)fDumpCount, aOutgoing ?
"outgo" : "incom" ); }
5420 getDbgLogger()->getDebugFilename(), // session log base name{ if (((0x00000001 +0x00000010) & getDbgMask()) == (0x00000001
+0x00000010)) getDbgLogger()->setNextMask(0x00000001 +0x00000010
).DebugPrintfLastMask ( "%sing XML message msgID=%ld &html;<a href=\"%s_msg%03ld_%03ld_%sing.xml\" target=\"_blank\">&html;dumped to file&html;</a>&html;"
, aOutgoing ? "Outgo" : "Incom", (long)getOutgoingMsgID(), getDbgLogger
()->getDebugFilename(), (long)(aOutgoing ? getOutgoingMsgID
() : getLastIncomingMsgID()+1), (long)fDumpCount, aOutgoing ?
"outgo" : "incom" ); }
5421 (long)(aOutgoing ? getOutgoingMsgID() : getLastIncomingMsgID()+1), // just generated msgID / expected next incoming ID{ if (((0x00000001 +0x00000010) & getDbgMask()) == (0x00000001
+0x00000010)) getDbgLogger()->setNextMask(0x00000001 +0x00000010
).DebugPrintfLastMask ( "%sing XML message msgID=%ld &html;<a href=\"%s_msg%03ld_%03ld_%sing.xml\" target=\"_blank\">&html;dumped to file&html;</a>&html;"
, aOutgoing ? "Outgo" : "Incom", (long)getOutgoingMsgID(), getDbgLogger
()->getDebugFilename(), (long)(aOutgoing ? getOutgoingMsgID
() : getLastIncomingMsgID()+1), (long)fDumpCount, aOutgoing ?
"outgo" : "incom" ); }
5422 (long)fDumpCount,{ if (((0x00000001 +0x00000010) & getDbgMask()) == (0x00000001
+0x00000010)) getDbgLogger()->setNextMask(0x00000001 +0x00000010
).DebugPrintfLastMask ( "%sing XML message msgID=%ld &html;<a href=\"%s_msg%03ld_%03ld_%sing.xml\" target=\"_blank\">&html;dumped to file&html;</a>&html;"
, aOutgoing ? "Outgo" : "Incom", (long)getOutgoingMsgID(), getDbgLogger
()->getDebugFilename(), (long)(aOutgoing ? getOutgoingMsgID
() : getLastIncomingMsgID()+1), (long)fDumpCount, aOutgoing ?
"outgo" : "incom" ); }
5423 aOutgoing ? "outgo" : "incom"{ if (((0x00000001 +0x00000010) & getDbgMask()) == (0x00000001
+0x00000010)) getDbgLogger()->setNextMask(0x00000001 +0x00000010
).DebugPrintfLastMask ( "%sing XML message msgID=%ld &html;<a href=\"%s_msg%03ld_%03ld_%sing.xml\" target=\"_blank\">&html;dumped to file&html;</a>&html;"
, aOutgoing ? "Outgo" : "Incom", (long)getOutgoingMsgID(), getDbgLogger
()->getDebugFilename(), (long)(aOutgoing ? getOutgoingMsgID
() : getLastIncomingMsgID()+1), (long)fDumpCount, aOutgoing ?
"outgo" : "incom" ); }
5424 )){ if (((0x00000001 +0x00000010) & getDbgMask()) == (0x00000001
+0x00000010)) getDbgLogger()->setNextMask(0x00000001 +0x00000010
).DebugPrintfLastMask ( "%sing XML message msgID=%ld &html;<a href=\"%s_msg%03ld_%03ld_%sing.xml\" target=\"_blank\">&html;dumped to file&html;</a>&html;"
, aOutgoing ? "Outgo" : "Incom", (long)getOutgoingMsgID(), getDbgLogger
()->getDebugFilename(), (long)(aOutgoing ? getOutgoingMsgID
() : getLastIncomingMsgID()+1), (long)fDumpCount, aOutgoing ?
"outgo" : "incom" ); }
;
5425 }
5426 }
5427 else {
5428 PDEBUGPRINTFX(DBG_ERROR,("Cannot write <msgdump> file")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("Cannot write <msgdump> file"
); }
;
5429 }
5430 delete dbgOutP;
5431 }
5432 }
5433 #endif // MSGDUMP
5434} // TSyncSession::DumpSyncMLBuffer
5435
5436
5437// Dump message in SML buffer to file
5438void TSyncSession::DumpSyncMLMessage(bool aOutgoing)
5439{
5440 // dump message if needed
5441 #ifdef MSGDUMP1
5442 // log message currently in SML buffer
5443 if (fMsgDump && !getRootConfig()->fDebugConfig.fDebugInfoPath.empty()) {
5444 // peek into buffer
5445 MemPtr_t data;
5446 MemSize_t datasize;
5447 if (smlPeekMessageBuffer(getSmlWorkspaceID(), aOutgoing, &data, &datasize)==SML_ERR_OK0x00) {
5448 DumpSyncMLBuffer(data,datasize,aOutgoing,SML_ERR_OK0x00);
5449 }
5450 }
5451 #endif // MSGDUMP
5452} // TSyncSession::DumpSyncMLMessage
5453
5454
5455#endif // SYDEBUG
5456
5457
5458// SyncML Toolkit callback handlers
5459// ================================
5460
5461
5462// start of SyncML message
5463Ret_t TSyncSession::StartMessage(SmlSyncHdrPtr_t aContentP)
5464{
5465 #ifdef SYDEBUG2
5466 fSessionLogger.DebugDefineMainThread();
5467 #endif
5468 SessionUsed(); // session used
5469 fLastRequestStarted = getSystemNowAs(TCTX_UTC((timecontext_t) ((tctx_tz_UTC) | TCTX_SYMBOLIC_TZ))); // request started
5470 fMessageRetried = false; // we assume no message retry
5471 MP_SHOWCURRENT(DBG_PROFILE,"Start of incoming Message");
5472 TP_START(fTPInfo,TP_general); // could be new thread
5473 #ifdef EXPIRES_AFTER_DATE
5474 if (IS_SERVER(getSyncAppBase()->isServer())) {
5475 // set 1/4 of the date here
5476 fCopyOfScrambledNow=((getSyncAppBase()->fScrambledNow)<<2)+503; // scramble again a little
5477 }
5478 #endif // EXPIRES_AFTER_DATE
5479 // dump it if configured
5480 // Note: this must happen here before answer writing to the instance buffer starts, as otherwise
5481 // the already consumed part of the buffer might get overwritten (the SyncML message header in this case).
5482 #ifdef SYDEBUG2
5483 DumpSyncMLMessage(false); // incoming
5484 #endif
5485 if (IS_SERVER(getSyncAppBase()->isServer())) {
5486 // for server, SyncML_Outgoing is started here, as SyncML_Incoming ends before SyncML_Outgoing
5487 // but for client, document exchange starts with outgoing message
5488 PDEBUGBLOCKDESC("SyncML_Outgoing","preparing for response before starting to analyze new incoming message")getDbgLogger()->DebugOpenBlock( "SyncML_Outgoing","preparing for response before starting to analyze new incoming message"
)
;
5489 }
5490 PDEBUGBLOCKFMT(("SyncML_Incoming","Starting to analyze incoming message",getDbgLogger()->DebugOpenBlockExpanded ("SyncML_Incoming",
"Starting to analyze incoming message", "RequestNo=%ld|SySyncVers=%d.%d.%d.%d"
,(long)fSyncAppBaseP->requestCount(), 3, 4, 0, 47 )
5491 "RequestNo=%ld|SySyncVers=%d.%d.%d.%d",(long)fSyncAppBaseP->requestCount(),getDbgLogger()->DebugOpenBlockExpanded ("SyncML_Incoming",
"Starting to analyze incoming message", "RequestNo=%ld|SySyncVers=%d.%d.%d.%d"
,(long)fSyncAppBaseP->requestCount(), 3, 4, 0, 47 )
5492 SYSYNC_VERSION_MAJOR,getDbgLogger()->DebugOpenBlockExpanded ("SyncML_Incoming",
"Starting to analyze incoming message", "RequestNo=%ld|SySyncVers=%d.%d.%d.%d"
,(long)fSyncAppBaseP->requestCount(), 3, 4, 0, 47 )
5493 SYSYNC_VERSION_MINOR,getDbgLogger()->DebugOpenBlockExpanded ("SyncML_Incoming",
"Starting to analyze incoming message", "RequestNo=%ld|SySyncVers=%d.%d.%d.%d"
,(long)fSyncAppBaseP->requestCount(), 3, 4, 0, 47 )
5494 SYSYNC_SUBVERSION,getDbgLogger()->DebugOpenBlockExpanded ("SyncML_Incoming",
"Starting to analyze incoming message", "RequestNo=%ld|SySyncVers=%d.%d.%d.%d"
,(long)fSyncAppBaseP->requestCount(), 3, 4, 0, 47 )
5495 SYSYNC_BUILDNUMBERgetDbgLogger()->DebugOpenBlockExpanded ("SyncML_Incoming",
"Starting to analyze incoming message", "RequestNo=%ld|SySyncVers=%d.%d.%d.%d"
,(long)fSyncAppBaseP->requestCount(), 3, 4, 0, 47 )
5496 ))getDbgLogger()->DebugOpenBlockExpanded ("SyncML_Incoming",
"Starting to analyze incoming message", "RequestNo=%ld|SySyncVers=%d.%d.%d.%d"
,(long)fSyncAppBaseP->requestCount(), 3, 4, 0, 47 )
;
5497 PDEBUGPRINTFX(DBG_HOT,({ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "=================> Starting to analyze incoming message, SySync V%d.%d.%d.%d, RequestNo=%ld"
, 3, 4, 0, 47, (long)fSyncAppBaseP->requestCount() ); }
5498 "=================> Starting to analyze incoming message, SySync V%d.%d.%d.%d, RequestNo=%ld",{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "=================> Starting to analyze incoming message, SySync V%d.%d.%d.%d, RequestNo=%ld"
, 3, 4, 0, 47, (long)fSyncAppBaseP->requestCount() ); }
5499 SYSYNC_VERSION_MAJOR,{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "=================> Starting to analyze incoming message, SySync V%d.%d.%d.%d, RequestNo=%ld"
, 3, 4, 0, 47, (long)fSyncAppBaseP->requestCount() ); }
5500 SYSYNC_VERSION_MINOR,{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "=================> Starting to analyze incoming message, SySync V%d.%d.%d.%d, RequestNo=%ld"
, 3, 4, 0, 47, (long)fSyncAppBaseP->requestCount() ); }
5501 SYSYNC_SUBVERSION,{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "=================> Starting to analyze incoming message, SySync V%d.%d.%d.%d, RequestNo=%ld"
, 3, 4, 0, 47, (long)fSyncAppBaseP->requestCount() ); }
5502 SYSYNC_BUILDNUMBER,{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "=================> Starting to analyze incoming message, SySync V%d.%d.%d.%d, RequestNo=%ld"
, 3, 4, 0, 47, (long)fSyncAppBaseP->requestCount() ); }
5503 (long)fSyncAppBaseP->requestCount(){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "=================> Starting to analyze incoming message, SySync V%d.%d.%d.%d, RequestNo=%ld"
, 3, 4, 0, 47, (long)fSyncAppBaseP->requestCount() ); }
5504 )){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "=================> Starting to analyze incoming message, SySync V%d.%d.%d.%d, RequestNo=%ld"
, 3, 4, 0, 47, (long)fSyncAppBaseP->requestCount() ); }
;
5505 #ifdef SYDEBUG2
5506 // Start incoming translation before decoding header
5507 XMLTranslationIncomingStart();
5508 if (fXMLtranslate && fIncomingXMLInstance) {
5509 // Note: we must find the SyncML version in advance, as fSyncMLVersion is not yet valid here
5510 sInt16 hdrVers;
5511 StrToEnum(SyncMLVerDTDNames,numSyncMLVersions,hdrVers,smlPCDataToCharP(aContentP->version));
5512 smlStartMessageExt(fIncomingXMLInstance,aContentP,SmlVersionCodes[hdrVers]);
5513 }
5514 #endif
5515 // update encoding
5516 smlGetEncoding(fSmlWorkspaceID,&fEncoding);
5517 // create command
5518 TSyncHeader *syncheaderP;
5519 MP_NEW(syncheaderP,DBG_OBJINST,"TSyncHeader",TSyncHeader(this,aContentP))syncheaderP = new TSyncHeader(this,aContentP);
5520 // execute it (special case for header)
5521 return processHeader(syncheaderP);
5522} // TSyncSession::StartMessage
5523
5524
5525// special entry point to prematurely abort processing of a incoming message
5526// and cause the necessary cleanup
5527void TSyncSession::CancelMessageProcessing(void)
5528{
5529 #ifdef SYDEBUG2
5530 // Now dump XML translation of incoming message (as far as it was processed at all)
5531 XMLTranslationIncomingEnd();
5532 #endif
5533 // Show premature end of input processing
5534 PDEBUGPRINTFX(DBG_HOT,({ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "=================> Aborted processing message #%ld, request=%ld"
, (long)fIncomingMsgID, (long)fSyncAppBaseP->requestCount(
) ); }
5535 "=================> Aborted processing message #%ld, request=%ld",{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "=================> Aborted processing message #%ld, request=%ld"
, (long)fIncomingMsgID, (long)fSyncAppBaseP->requestCount(
) ); }
5536 (long)fIncomingMsgID,{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "=================> Aborted processing message #%ld, request=%ld"
, (long)fIncomingMsgID, (long)fSyncAppBaseP->requestCount(
) ); }
5537 (long)fSyncAppBaseP->requestCount(){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "=================> Aborted processing message #%ld, request=%ld"
, (long)fIncomingMsgID, (long)fSyncAppBaseP->requestCount(
) ); }
5538 )){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "=================> Aborted processing message #%ld, request=%ld"
, (long)fIncomingMsgID, (long)fSyncAppBaseP->requestCount(
) ); }
;
5539} // TSyncSession::CancelMessageProcessing
5540
5541
5542Ret_t TSyncSession::EndMessage(Boolean_t final)
5543{
5544 #ifdef SYDEBUG2
5545 // generate XML translation
5546 if (fXMLtranslate && fIncomingXMLInstance)
5547 smlEndMessage(fIncomingXMLInstance,final);
5548 // Now dump XML translation of incoming message
5549 XMLTranslationIncomingEnd();
5550 #endif
5551 // Flush pending item change commands?
5552 //
5553 // Don't retry other commands here (like a pending Sync), because
5554 // the whole purpose of delaying Sync is to give a preliminary
5555 // answer to the peer before finishing the command.
5556 //
5557 // Delaying them although we are expected to finish (final set!)
5558 // would have two drawbacks:
5559 // - Requires another message roundtrip.
5560 // - More complex state transitions which is known to not work:
5561 // Synthesis<->Synthesis sync did not complete correctly when the
5562 // server forced the client to send another message, because client
5563 // and server did not agree on the end of the session. (see
5564 // "[os-libsynthesis] temporary local ID + FinalizeLocalID").
5565 if (final && !onlySyncPending() && !fDelayedExecutionCommands.empty()) {
5566 // TODO: tell stores explicitly that we really need the results now
5567 // instead of relying on the indirect semantic of "second call must
5568 // succeed".
5569 tryDelayedExecutionCommands();
5570 }
5571
5572 // End of incoming message
5573 PDEBUGPRINTFX(DBG_HOT,({ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "=================> Finished processing incoming message #%ld (%sfinal), request=%ld"
, (long)fIncomingMsgID, final ? "" : "not ", (long)fSyncAppBaseP
->requestCount() ); }
5574 "=================> Finished processing incoming message #%ld (%sfinal), request=%ld",{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "=================> Finished processing incoming message #%ld (%sfinal), request=%ld"
, (long)fIncomingMsgID, final ? "" : "not ", (long)fSyncAppBaseP
->requestCount() ); }
5575 (long)fIncomingMsgID,{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "=================> Finished processing incoming message #%ld (%sfinal), request=%ld"
, (long)fIncomingMsgID, final ? "" : "not ", (long)fSyncAppBaseP
->requestCount() ); }
5576 final ? "" : "not ",{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "=================> Finished processing incoming message #%ld (%sfinal), request=%ld"
, (long)fIncomingMsgID, final ? "" : "not ", (long)fSyncAppBaseP
->requestCount() ); }
5577 (long)fSyncAppBaseP->requestCount(){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "=================> Finished processing incoming message #%ld (%sfinal), request=%ld"
, (long)fIncomingMsgID, final ? "" : "not ", (long)fSyncAppBaseP
->requestCount() ); }
5578 )){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "=================> Finished processing incoming message #%ld (%sfinal), request=%ld"
, (long)fIncomingMsgID, final ? "" : "not ", (long)fSyncAppBaseP
->requestCount() ); }
;
5579 // start outgoing message if not already done so
5580 // Note: this should NOT happen, as EVERY message from the remote should contain a SyncHdr status which
5581 // should have started the message already
5582 if (!fOutgoingStarted) {
5583 PDEBUGPRINTFX(DBG_ERROR,("Warning: incoming message #%ld did not contain a SyncHdr status (protocol violation)",(long)fIncomingMsgID)){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("Warning: incoming message #%ld did not contain a SyncHdr status (protocol violation)"
,(long)fIncomingMsgID); }
;
5584 // try to continue by simply ignoring - might not always work out (e.g. when authorisation is not yet complete, this will fail)
5585 issueHeader(false);
5586 }
5587 // forget pending continue requests
5588 if (final)
5589 fNextMessageRequests=0; // no pending next message requests when a message is final
5590 // make sure peer gets devInf Put if needed (only if it didn't issue a GET)
5591 // Note: do it here because we have processed all commands (alerts) now but
5592 // server response alerts are still in the fEndOfMessageCommands queue.
5593 // This ensures that clients gets PUT before it gets ALERTs.
5594 if (!fRemoteGotDevinf && mustSendDevInf()) {
5595 // remote has not got devinf and should see it
5596 if (!getRootConfig()->fNeverPutDevinf) {
5597 // PUT devinf now
5598 PDEBUGPRINTFX(DBG_PROTO,("Remote must see our changed devInf -> creating PUT command")){ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ("Remote must see our changed devInf -> creating PUT command"
); }
;
5599 TDevInfPutCommand *putcmdP = new TDevInfPutCommand(this);
5600 issueRootPtr(putcmdP);
5601 }
5602 else {
5603 PDEBUGPRINTFX(DBG_PROTO,("Remote should see devinf, but PUT is suppressed: <neverputdevinf>")){ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ("Remote should see devinf, but PUT is suppressed: <neverputdevinf>"
); }
;
5604 }
5605 }
5606 // hook for placing custom GET and PUT
5607 if (!fCustomGetPutSent) {
5608 fCustomGetPutSent=true;
5609 issueCustomGetPut(fRemoteDevInfKnown,fRemoteGotDevinf);
5610 }
5611 // now issue all commands that may only be issued AFTER sending statuses for incoming commands
5612 TSmlCommandPContainer::iterator pos;
5613 while (true) {
5614 // first in list
5615 pos=fEndOfMessageCommands.begin();
5616 if (pos==fEndOfMessageCommands.end()) break; // done
5617 // take command out of the list
5618 TSmlCommand *cmdP=(*pos);
5619 fEndOfMessageCommands.erase(pos);
5620 PDEBUGPRINTFX(DBG_SESSION,("<--- Issuing command '%s' from EndOfMessage Queue",cmdP->getName())){ if (((0x00000020) & getDbgMask()) == (0x00000020)) getDbgLogger
()->setNextMask(0x00000020).DebugPrintfLastMask ("<--- Issuing command '%s' from EndOfMessage Queue"
,cmdP->getName()); }
;
5621 // issue it (doesn't matter if cannot be sent with this message,
5622 // it will then be moved into the fNextMessageCommands queue)
5623 issuePtr(cmdP,fNextMessageCommands,fInterruptedCommandP);
5624 }
5625 // now continue with package if it was discontinued in last message
5626 // %%% if (fNextMessageRequests>0) {
5627 // We have received a 222 Alert, so continue package now
5628 // %%% always continue, even if we didn't see a 222 alert
5629 ContinuePackageRoot();
5630 // %%% }
5631 // let client or server do what is needed
5632 if (fFakeFinalFlag) {
5633 PDEBUGPRINTFX(DBG_ERROR,("Warning: heavy workaround active - <final/> simulated to get resume without sync-from-client going")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("Warning: heavy workaround active - <final/> simulated to get resume without sync-from-client going"
); }
;
5634 }
5635 MessageEnded(final || fFakeFinalFlag);
5636 fFakeFinalFlag=false;
5637 #ifdef SYNCSTATUS_AT_SYNC_CLOSE
5638 // make sure sync status is disposed
5639 if (fSyncCloseStatusCommandP) delete fSyncCloseStatusCommandP;
5640 fSyncCloseStatusCommandP=NULL__null;
5641 #endif
5642 MP_SHOWCURRENT(DBG_PROFILE,"End of incoming message");
5643 // ok if no exception thrown
5644 return SML_ERR_OK0x00;
5645} // TSyncSession::EndMessage
5646
5647
5648
5649Ret_t TSyncSession::StartSync(SmlSyncPtr_t aContentP)
5650{
5651 #ifdef SYDEBUG2
5652 // generate XML translation
5653 if (fXMLtranslate && fIncomingXMLInstance)
5654 smlStartSync(fIncomingXMLInstance,aContentP);
5655 #endif
5656 // create command object
5657 TSyncCommand *commandP = new TSyncCommand(this,fIncomingMsgID,aContentP);
5658 // process it
5659 return process(commandP);
5660} // TSyncSession::StartSync
5661
5662
5663Ret_t TSyncSession::EndSync(void)
5664{
5665 #ifdef SYDEBUG2
5666 // generate XML translation
5667 if (fXMLtranslate && fIncomingXMLInstance)
5668 smlEndSync(fIncomingXMLInstance);
5669 #endif
5670
5671 /* %%% old version: sync end is no command itself,
5672 makes queuing <sync> sequences for later processing
5673 impossible, so we made it be a separate command
5674 // process Sync End
5675 // %%% evtl. catch...
5676 PDEBUGPRINTFX(DBG_HOT,("End of <Sync> command"));
5677 // Note: do not call if previous Sync start might not have been processed
5678 if (!fIgnoreIncomingCommands) processSyncEnd();
5679 return SML_ERR_OK;
5680 */
5681 // create command object
5682 TSyncEndCommand *commandP = new TSyncEndCommand(this,fIncomingMsgID);
5683 // process it
5684 return process(commandP);
5685} // TSyncSession::EndSync
5686
5687
5688#ifdef ATOMIC_RECEIVE
5689Ret_t TSyncSession::StartAtomic(SmlAtomicPtr_t aContentP)
5690{
5691 #ifdef SYDEBUG2
5692 // generate XML translation
5693 if (fXMLtranslate && fIncomingXMLInstance)
5694 smlStartAtomic(fIncomingXMLInstance,aContentP);
5695 #endif
5696 // NOTE from Specs: Nested Atomic commands are not legal. A nested Atomic
5697 // command will generate an error 500 - command failed.
5698 // create command object
5699 // %%% create DUMMY command for now
5700 PDEBUGPRINTFX(DBG_HOT,("Start of Atomic bracket: return Status 406 unimplemented")){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("Start of Atomic bracket: return Status 406 unimplemented"
); }
;
5701 TUnimplementedCommand *commandP =
5702 new TUnimplementedCommand(
5703 this,
5704 fIncomingMsgID,
5705 aContentP->cmdID,
5706 0,
5707 scmd_copy,
5708 aContentP,
5709 406); // optional feature not supported
5710 // process it
5711 return process(commandP);
5712} // TSyncSession::StartAtomic
5713
5714Ret_t TSyncSession::EndAtomic(void)
5715{
5716 #ifdef SYDEBUG2
5717 // generate XML translation
5718 if (fXMLtranslate && fIncomingXMLInstance)
5719 smlEndAtomic(fIncomingXMLInstance);
5720 #endif
5721 // process Atomic end
5722 // %%% not implemented, just accept
5723 PDEBUGPRINTFX(DBG_HOT,("End of Atomic bracket")){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("End of Atomic bracket"
); }
;
5724 return SML_ERR_OK0x00;
5725} // TSyncSession::EndAtomic
5726#endif
5727
5728
5729#ifdef SEQUENCE_RECEIVE
5730Ret_t TSyncSession::StartSequence(SmlSequencePtr_t aContentP)
5731{
5732 #ifdef SYDEBUG2
5733 // generate XML translation
5734 if (fXMLtranslate && fIncomingXMLInstance)
5735 smlStartSequence(fIncomingXMLInstance,aContentP);
5736 #endif
5737 // %%% later, implement a nestable command object and derive Sequence,Atomic and Sync
5738 // from it. Similar to nested command creation, maintain a chain of nested commands;
5739 // session will have a pointer to most recent nest and ALL commands will have a pointer
5740 // to owning command (or NULL if they are on root level).
5741 // Sequence is trivial as SySync executes command in sequence anyway
5742 // - simply keep track of nesting
5743 fSequenceNesting++;
5744 PDEBUGPRINTFX(DBG_HOT,("Start of Sequence bracket, nesting level is now %hd",fSequenceNesting)){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("Start of Sequence bracket, nesting level is now %hd"
,fSequenceNesting); }
;
5745 // get cmdid
5746 sInt32 cmdid;
5747 StrToLong(smlPCDataToCharP(aContentP->cmdID),cmdid);
5748 // make status
5749 TStatusCommand *statusCmdP = new TStatusCommand(
5750 this, // associated session (for callbacks)
5751 cmdid, // referred-to command ID
5752 scmd_sequence, // referred-to command type (scmd_xxx)
5753 (aContentP->flags & SmlNoResp_f0x0100)!=0, // set if no-Resp
5754 200 // status code
5755 ); // issue ok status
5756 // - return status
5757 issueRootPtr(statusCmdP);
5758 // - ok
5759 return SML_ERR_OK0x00;
5760} // TSyncSession::StartSequence
5761
5762
5763Ret_t TSyncSession::EndSequence(void)
5764{
5765 #ifdef SYDEBUG2
5766 // generate XML translation
5767 if (fXMLtranslate && fIncomingXMLInstance)
5768 smlEndSequence(fIncomingXMLInstance);
5769 #endif
5770 // - keep track of nesting
5771 if (fSequenceNesting<1) {
5772 // error in nesting
5773 PDEBUGPRINTFX(DBG_HOT,("End of Sequence bracket, MISSING PRECEEDING SEQUENCE START -> aborting session")){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("End of Sequence bracket, MISSING PRECEEDING SEQUENCE START -> aborting session"
); }
;
5774 AbortSession(400,true); // bad nesting is severe, abort session
5775 }
5776 else {
5777 // nesting ok
5778 fSequenceNesting--;
5779 PDEBUGPRINTFX(DBG_HOT,("End of Sequence bracket, nesting level is now %hd",fSequenceNesting)){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("End of Sequence bracket, nesting level is now %hd"
,fSequenceNesting); }
;
5780 }
5781 return SML_ERR_OK0x00;
5782} // TSyncSession::EndSequence
5783#endif
5784
5785
5786Ret_t TSyncSession::AddCmd(SmlAddPtr_t aContentP)
5787{
5788 #ifdef SYDEBUG2
5789 // generate XML translation
5790 if (fXMLtranslate && fIncomingXMLInstance)
5791 smlAddCmd(fIncomingXMLInstance,aContentP);
5792 #endif
5793 // create SyncOp command object
5794 TSyncOpCommand *commandP = new TSyncOpCommand(
5795 this,
5796 fLocalSyncDatastoreP,
5797 fIncomingMsgID,
5798 sop_add,
5799 scmd_add,
5800 aContentP
5801 );
5802 // process it
5803 return process(commandP);
5804} // TSyncSession::AddCmd
5805
5806
5807Ret_t TSyncSession::AlertCmd(SmlAlertPtr_t aContentP)
5808{
5809 #ifdef SYDEBUG2
5810 // generate XML translation
5811 if (fXMLtranslate && fIncomingXMLInstance)
5812 smlAlertCmd(fIncomingXMLInstance,aContentP);
5813 #endif
5814 // create command object
5815 TAlertCommand *commandP = new TAlertCommand(this,fIncomingMsgID,aContentP);
5816 // process it
5817 return process(commandP);
5818} // TSyncSession::AlertCmd
5819
5820
5821Ret_t TSyncSession::DeleteCmd(SmlDeletePtr_t aContentP)
5822{
5823 #ifdef SYDEBUG2
5824 // generate XML translation
5825 if (fXMLtranslate && fIncomingXMLInstance)
5826 smlDeleteCmd(fIncomingXMLInstance,aContentP);
5827 #endif
5828 // determine type of delete
5829 TSyncOperation syncop;
5830 if (aContentP->flags & SmlArchive_f0x8000) syncop = sop_archive_delete;
5831 else if (aContentP->flags & SmlSftDel_f0x4000) syncop = sop_soft_delete;
5832 else syncop=sop_delete;
5833 // create SyncOp command object
5834 TSyncOpCommand *commandP = new TSyncOpCommand(
5835 this,
5836 fLocalSyncDatastoreP, // note that this one might be NULL in case previous sync command was delayed
5837 fIncomingMsgID,
5838 syncop,
5839 scmd_delete,
5840 aContentP
5841 );
5842 // process it
5843 return process(commandP);
5844} // TSyncSession::DeleteCmd
5845
5846
5847// process GET commands
5848Ret_t TSyncSession::GetCmd(SmlGetPtr_t aContentP)
5849{
5850 #ifdef SYDEBUG2
5851 // generate XML translation
5852 if (fXMLtranslate && fIncomingXMLInstance)
5853 smlGetCmd(fIncomingXMLInstance,aContentP);
5854 #endif
5855 // create command object
5856 TGetCommand *commandP = new TGetCommand(this,fIncomingMsgID,aContentP);
5857 // process it
5858 return process(commandP);
5859} // TSyncSession::GetCmd
5860
5861
5862Ret_t TSyncSession::PutCmd(SmlPutPtr_t aContentP)
5863{
5864 #ifdef SYDEBUG2
5865 // generate XML translation
5866 if (fXMLtranslate && fIncomingXMLInstance)
5867 smlPutCmd(fIncomingXMLInstance,aContentP);
5868 #endif
5869 // create command object
5870 TPutCommand *commandP = new TPutCommand(this,fIncomingMsgID,aContentP);
5871 // process it
5872 return process(commandP);
5873} // TSyncSession::PutCmd
5874
5875
5876#ifdef MAP_RECEIVE
5877Ret_t TSyncSession::MapCmd(SmlMapPtr_t aContentP)
5878{
5879 #ifdef SYDEBUG2
5880 // generate XML translation
5881 if (fXMLtranslate && fIncomingXMLInstance)
5882 smlMapCmd(fIncomingXMLInstance,aContentP);
5883 #endif
5884 // create command object
5885 TMapCommand *commandP = new TMapCommand(this,fIncomingMsgID,aContentP);
5886 // process it
5887 return process(commandP);
5888} // TSyncSession::MapCmd
5889#endif
5890
5891
5892#ifdef RESULT_RECEIVE
5893Ret_t TSyncSession::ResultsCmd(SmlResultsPtr_t aContentP)
5894{
5895 #ifdef SYDEBUG2
5896 // generate XML translation
5897 if (fXMLtranslate && fIncomingXMLInstance)
5898 smlResultsCmd(fIncomingXMLInstance,aContentP);
5899 #endif
5900 // create command object
5901 TResultsCommand *commandP = new TResultsCommand(this,fIncomingMsgID,aContentP);
5902 // process it
5903 return process(commandP);
5904} // TSyncSession::ResultsCmd
5905#endif
5906
5907
5908Ret_t TSyncSession::StatusCmd(SmlStatusPtr_t aContentP)
5909{
5910 #ifdef SYDEBUG2
5911 // generate XML translation
5912 if (fXMLtranslate && fIncomingXMLInstance)
5913 smlStatusCmd(fIncomingXMLInstance,aContentP);
5914 #endif
5915 // create command object
5916 TStatusCommand *statuscommandP = new TStatusCommand(this,fIncomingMsgID,aContentP);
5917 // handle status (search for command that waits for this status)
5918 return handleStatus(statuscommandP);
5919} // TSyncSession::StatusCmd
5920
5921
5922Ret_t TSyncSession::ReplaceCmd(SmlReplacePtr_t aContentP)
5923{
5924 #ifdef SYDEBUG2
5925 // generate XML translation
5926 if (fXMLtranslate && fIncomingXMLInstance)
5927 smlReplaceCmd(fIncomingXMLInstance,aContentP);
5928 #endif
5929 // create SyncOp command object
5930 TSyncOpCommand *commandP = new TSyncOpCommand(
5931 this,
5932 fLocalSyncDatastoreP,
5933 fIncomingMsgID,
5934 sop_replace,
5935 scmd_replace,
5936 aContentP
5937 );
5938 // process it
5939 return process(commandP);
5940} // TSyncSession::ReplaceCmd
5941
5942
5943#ifdef COPY_RECEIVE
5944Ret_t TSyncSession::CopyCmd(SmlReplacePtr_t aContentP)
5945{
5946 #ifdef SYDEBUG2
5947 #ifdef COPY_SEND
5948 // generate XML translation
5949 if (fXMLtranslate && fIncomingXMLInstance)
5950 smlCopyCmd(fIncomingXMLInstance,aContentP);
5951 #else
5952 #error "We will have incomplete XML translation when only COPY_RECEIVE is defined"
5953 #endif
5954 #endif
5955 // create SyncOp command object
5956 TSyncOpCommand *commandP = new TSyncOpCommand(
5957 this,
5958 fLocalSyncDatastoreP,
5959 fIncomingMsgID,
5960 fTreatCopyAsAdd ? sop_add : sop_copy,
5961 scmd_copy,
5962 aContentP
5963 );
5964 // process it
5965 return process(commandP);
5966} // TSyncSession::CopyCmd
5967#endif
5968
5969
5970Ret_t TSyncSession::MoveCmd(SmlReplacePtr_t aContentP)
5971{
5972 #ifdef SYDEBUG2
5973 // generate XML translation
5974 if (fXMLtranslate && fIncomingXMLInstance)
5975 smlMoveCmd(fIncomingXMLInstance,aContentP);
5976 #endif
5977 // create SyncOp command object
5978 TSyncOpCommand *commandP = new TSyncOpCommand(
5979 this,
5980 fLocalSyncDatastoreP,
5981 fIncomingMsgID,
5982 sop_move,
5983 scmd_move,
5984 aContentP
5985 );
5986 // process it
5987 return process(commandP);
5988} // TSyncSession::MoveCmd
5989
5990// - error handling
5991Ret_t TSyncSession::HandleError(void)
5992{
5993 // %%% tbd
5994 DEBUGPRINTFX(DBG_ERROR,("HandleError reached")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("HandleError reached"
); }
;
5995 return SML_ERR_OK0x00; // %%%
5996} // TSyncSession::HandleError
5997
5998
5999
6000Ret_t TSyncSession::DummyHandler(const char* msg)
6001{
6002 //DEBUGPRINTFX(DBG_ERROR,("DummyHandler: msg=%s",msg));
6003 return SML_ERR_OK0x00;
6004} // TSyncSession::DummyHandler
6005
6006
6007
6008#ifdef ENGINEINTERFACE_SUPPORT1
6009
6010// Support for EngineModule common interface
6011// =========================================
6012
6013// open subkey by name (not by path!)
6014// - this is the actual implementation
6015TSyError TSessionKey::OpenSubKeyByName(
6016 TSettingsKeyImpl *&aSettingsKeyP,
6017 cAppCharP aName, stringSize aNameSize,
6018 uInt16 aMode
6019) {
6020 #ifdef SCRIPT_SUPPORT1
6021 if (strucmp(aName,"sessionvars",aNameSize)==0) {
6022 // note: if no session scripts are used, context does not exist and is NULL.
6023 // TScriptVarKey does not crash with a NULL, so we can give ok here (but no session vars
6024 // will be accessible).
6025 aSettingsKeyP = new TScriptVarKey(fEngineInterfaceP,fSessionP->getSessionScriptContext());
6026 }
6027 else
6028 #endif
6029 return inherited::OpenSubKeyByName(aSettingsKeyP,aName,aNameSize,aMode);
6030 // opened a key
6031 return LOCERR_OK;
6032} // TSessionKey::OpenSubKeyByName
6033
6034#endif // ENGINEINTERFACE_SUPPORT
6035
6036
6037} // namespace sysync
6038
6039
6040// factory methods of Session Config
6041// =================================
6042
6043// only one of XML2GO or SDK/Plugin can be on top of customagent
6044#ifdef XML2GO_SUPPORT
6045 #include "xml2goapids.h"
6046#elif defined(SDK_SUPPORT1)
6047 #include "pluginapids.h"
6048#endif
6049// ODBC can be in-between if selected
6050#ifdef SQL_SUPPORT1
6051 #include "odbcapids.h"
6052#endif
6053
6054
6055namespace sysync {
6056
6057#ifndef HARDCODED_CONFIG
6058
6059// create new datastore config by name
6060// returns NULL if none found
6061TLocalDSConfig *TSessionConfig::newDatastoreConfig(const char *aName, const char *aType, TConfigElement *aParentP)
6062{
6063 #ifdef XML2GO_SUPPORT
6064 if (aType && strucmp(aType,"xml2go")==0) {
6065 // xml2go enhanced datastore
6066 return new TXml2goDSConfig(aName,aParentP);
6067 }
6068 else
6069 #elif defined(SDK_SUPPORT1)
6070 if (aType && strucmp(aType,"plugin")==0) {
6071 // APIDB enhanced datastore (on top of ODBC if SQL_SUPPORT is on)
6072 return new TPluginDSConfig(aName,aParentP);
6073 }
6074 else
6075 #endif
6076 #ifdef SQL_SUPPORT1
6077 if (aType==0 || strucmp(aType,"odbc")==0 || strucmp(aType,"sql")==0) {
6078 // ODBC enabled datastore
6079 return new TOdbcDSConfig(aName,aParentP);
6080 }
6081 else
6082 #endif
6083 return NULL__null; // unknown datastore
6084} // TSessionConfig::newDatastoreConfig
6085
6086#endif // HARDCODED_CONFIG
6087
6088bool TSyncSession::receivedSyncModeExtensions()
6089{
6090 TRemoteDataStorePContainer::iterator pos;
6091 for (pos=fRemoteDataStores.begin(); pos!=fRemoteDataStores.end(); ++pos) {
6092 set<string> modes;
6093 (*pos)->getSyncModes(modes);
6094 set<string>::const_iterator it;
6095 for (it=modes.begin(); it!=modes.end(); ++it) {
6096 const char *nptr = it->c_str();
6097 char *endptr;
6098 if (!*nptr) {
6099 // ignore empty mode
6100 continue;
6101 }
6102 long mode = strtol(nptr, &endptr, 10);
6103 // ignore trailing spaces
6104 while (isspace(*endptr)) {
6105 endptr++;
6106 }
6107 if (*endptr) {
6108 // non-standard character => found extensions
6109 return true;
6110 }
6111
6112 if (mode > 32) {
6113 // Non-standed integer code!
6114 // Choosing 32 is somewhat random, not all of those
6115 // are really defined in the standard.
6116 return true;
6117 }
6118 }
6119 }
6120 return false;
6121}
6122
6123} // namespace sysync
6124
6125#endif // not SYNCSESSION_PART1_EXCLUDE
6126
6127// eof