File: | libsynthesis/src/sysync/syncsession.cpp |
Warning: | line 2088, column 15 Value stored to 'sendable' is never read |
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 | |
34 | namespace sysync { |
35 | |
36 | // enum names |
37 | // ---------- |
38 | |
39 | // SyncML version info |
40 | const char * const SyncMLVerProtoNames[numSyncMLVersions] = { |
41 | "undefined", |
42 | "SyncML/1.0", |
43 | "SyncML/1.1", |
44 | "SyncML/1.2" |
45 | }; |
46 | const SmlVersion_t SmlVersionCodes[numSyncMLVersions] = { |
47 | SML_VERS_UNDEF, |
48 | SML_VERS_1_0, |
49 | SML_VERS_1_1, |
50 | SML_VERS_1_2 |
51 | }; |
52 | const char * const SyncMLVerDTDNames[numSyncMLVersions] = { |
53 | "???", |
54 | "1.0", |
55 | "1.1", |
56 | "1.2" |
57 | }; |
58 | const 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 |
66 | const 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 |
76 | const 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 |
84 | const char * const SyncModeNames[numSyncModes] = { |
85 | "twoway", |
86 | "fromserver", |
87 | "fromclient" |
88 | }; |
89 | |
90 | |
91 | |
92 | #ifdef SYDEBUG2 |
93 | // package state names |
94 | const char * const PackageStateNames[numPackageStates] = { |
95 | "idle", |
96 | "init", |
97 | "sync", |
98 | "initsync", |
99 | "map", |
100 | "supplement" |
101 | }; |
102 | |
103 | // sync operations |
104 | const 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 |
121 | const 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() |
133 | static 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) |
143 | static 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) |
152 | static 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) |
161 | static 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() |
171 | static 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 |
182 | static 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 | |
191 | const uInt8 param_OneInteger[] = { VAL(fty_integer)( (uInt8)fty_integer) }; |
192 | const uInt8 param_TwoIntegers[] = { VAL(fty_integer)( (uInt8)fty_integer), VAL(fty_integer)( (uInt8)fty_integer) }; |
193 | const uInt8 param_OneString[] = { VAL(fty_string)( (uInt8)fty_string) }; |
194 | |
195 | const 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 | |
204 | const 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) |
212 | static 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() |
221 | static 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() |
229 | static 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) |
237 | static 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() |
245 | static 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) |
253 | static 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() |
261 | static 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) |
269 | static 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 |
278 | static 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 |
296 | static 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 |
312 | static 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 | |
329 | const 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 | |
343 | const 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 |
362 | TRemoteRuleConfig::TRemoteRuleConfig(const char *aElementName, TConfigElement *aParentElementP) : |
363 | TConfigElement(aElementName,aParentElementP) |
364 | { |
365 | clear(); |
366 | } // TRemoteRuleConfig::TRemoteRuleConfig |
367 | |
368 | |
369 | // config destructor |
370 | TRemoteRuleConfig::~TRemoteRuleConfig() |
371 | { |
372 | if (fOverrideDevInfBufferP) |
373 | smlFreeProtoElement(fOverrideDevInfBufferP); |
374 | |
375 | clear(); |
376 | } // TRemoteRuleConfig::~TRemoteRuleConfig |
377 | |
378 | |
379 | // init defaults |
380 | void 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 |
438 | bool 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 |
567 | TSessionConfig::TSessionConfig(const char *aElementName, TConfigElement *aParentElementP) : |
568 | inherited(aElementName,aParentElementP) |
569 | { |
570 | clear(); |
571 | } // TSessionConfig::TSessionConfig |
572 | |
573 | |
574 | // config destructor |
575 | TSessionConfig::~TSessionConfig() |
576 | { |
577 | clear(); |
578 | } // TSessionConfig::~TSessionConfig |
579 | |
580 | |
581 | // init defaults |
582 | void 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 |
693 | TLocalDSConfig *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 |
711 | bool 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 |
859 | void 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 |
977 | TSyncSession::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 |
1203 | TSyncSession::~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 |
1224 | void 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 |
1314 | void 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 |
1328 | void 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 |
1340 | void 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) |
1352 | void 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!) |
1379 | void 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 |
1638 | bool 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. |
1682 | TRootConfig *TSyncSession::getRootConfig(void) |
1683 | { |
1684 | return fSyncAppBaseP->getRootConfig(); |
1685 | } // TSyncSession::getRootConfig |
1686 | |
1687 | |
1688 | // forget commands waiting to be sent when header is generated |
1689 | void 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 |
1712 | void 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) |
1728 | void 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 | |
1755 | void TSyncSession::MarkSuspendAlertSent(bool aSent) |
1756 | { |
1757 | fSuspendAlertSent = aSent; |
1758 | } |
1759 | |
1760 | |
1761 | // abort session (that is: flag abortion) |
1762 | void 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 |
1815 | bool TSyncSession::isAllSuccess(void) |
1816 | { |
1817 | return fFailedDatastores==0 && fErrorItemDatastores==0; |
1818 | } // TSyncSession::isAllSuccess |
1819 | |
1820 | |
1821 | // let session know that datastore has failed |
1822 | void 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 |
1834 | void TSyncSession::setSmlWorkspaceID(InstanceID_t aSmlWorkspaceID) |
1835 | { |
1836 | fSmlWorkspaceID=aSmlWorkspaceID; |
1837 | } // TSyncSession::setSmlWorkspaceID |
1838 | |
1839 | |
1840 | // show some information about the config |
1841 | void 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 |
1867 | void 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 |
1895 | void 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 |
1905 | void 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) |
1921 | bool 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 |
1934 | bool 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) |
2208 | bool 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 |
2231 | sInt32 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) |
2251 | sInt32 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) |
2259 | void 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) |
2285 | void 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 |
2304 | void 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 |
2320 | void 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" |
2425 | void 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. |
2505 | Ret_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. |
2650 | Ret_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 | |
2782 | bool 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 | |
2804 | bool 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 | |
2817 | bool 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 | |
2867 | bool 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. |
2927 | Ret_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 |
3029 | SmlPcdataPtr_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 |
3057 | SmlSyncHdrPtr_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 |
3148 | void 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 |
3173 | void 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) |
3239 | bool 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 |
3285 | bool 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 |
3296 | bool 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 |
3352 | const char *TSyncSession::getEncodingName(void) |
3353 | { |
3354 | return SyncMLEncodingMIMENames[fEncoding]; |
3355 | } // TSyncSession::getEncodingName |
3356 | |
3357 | |
3358 | // add current encoding spec to given (type-)string |
3359 | void TSyncSession::addEncoding(string &aString) |
3360 | { |
3361 | aString+=SYNCML_ENCODING_SEPARATOR"+"; |
3362 | aString+=getEncodingName(); |
3363 | } // TSyncSession::addEncoding |
3364 | |
3365 | |
3366 | // set encoding for session |
3367 | void 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 |
3377 | TRemoteDataStore *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 |
3394 | TLocalEngineDS *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 |
3425 | TLocalEngineDS *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) |
3441 | TLocalEngineDS *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 | |
3454 | TLocalEngineDS *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) |
3465 | TSyncItemType *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) |
3478 | TSyncItemType *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 |
3497 | SmlDevInfDatastoreListPtr_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) |
3530 | uInt32 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 |
3539 | SmlDevInfCtcapListPtr_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 |
3595 | SmlDevInfDevInfPtr_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) |
3643 | SmlItemPtr_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() |
3676 | localstatus 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 |
3845 | done: |
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 |
3854 | localstatus 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) |
3921 | bool 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!). |
3951 | bool 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 |
4066 | SmlChalPtr_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) |
4088 | SmlCredPtr_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 |
4198 | bool 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 |
4372 | bool 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. |
4412 | bool 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. |
4451 | bool 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!!!! |
4483 | bool 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 |
4512 | bool 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. |
4543 | bool 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) |
4580 | localstatus 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 |
4824 | bool 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 |
4842 | TSessionConfig *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 |
4852 | bool 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 |
4867 | void 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) |
4892 | void 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) |
4920 | TResultsCommand *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) |
4981 | void 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 |
5046 | TSmlCommand *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 | |
5203 | void 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 | |
5225 | void 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 |
5250 | void 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 |
5316 | void 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 |
5381 | void 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 |
5438 | void 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 |
5463 | Ret_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 |
5527 | void 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 | |
5542 | Ret_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 | |
5649 | Ret_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 | |
5663 | Ret_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 |
5689 | Ret_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 | |
5714 | Ret_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 |
5730 | Ret_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 | |
5763 | Ret_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 | |
5786 | Ret_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 | |
5807 | Ret_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 | |
5821 | Ret_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 |
5848 | Ret_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 | |
5862 | Ret_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 |
5877 | Ret_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 |
5893 | Ret_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 | |
5908 | Ret_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 | |
5922 | Ret_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 |
5944 | Ret_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 | |
5970 | Ret_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 |
5991 | Ret_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 | |
6000 | Ret_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 |
6015 | TSyError 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 | |
6055 | namespace sysync { |
6056 | |
6057 | #ifndef HARDCODED_CONFIG |
6058 | |
6059 | // create new datastore config by name |
6060 | // returns NULL if none found |
6061 | TLocalDSConfig *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 | |
6088 | bool 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 |