Bug Summary

File:libsynthesis/src/sysync/synccommand.cpp
Warning:line 2532, column 9
Value stored to 'processitem' is never read

Annotated Source Code

1/*
2 * File: SyncCommand.cpp
3 *
4 * Author: Lukas Zeller (luz@plan44.ch)
5 *
6 * TSmlCommand, TXXXCmd....
7 * Wrapper classes for SyncML Commands and the associated SyncML
8 * Toolkit mechanics.
9 *
10 * Copyright (c) 2001-2011 by Synthesis AG + plan44.ch
11 *
12 * 2001-05-30 : luz : created
13 *
14 */
15
16// includes
17#include "prefix_file.h"
18
19#include "synccommand.h"
20#include "syncsession.h"
21
22// %%%% debug hack switch
23//#define DEBUG_XMLRESPONSE_FOR_WBXML 1
24//#undef DEBUG_XMLRESPONSE_FOR_WBXML
25
26// Status for Results is not needed according to SyncML 1.0.1
27// specs but 9210 seems to need it.
28// Note: future versions of the standard will require
29// status for all commands, so this is going to be the default
30#define RESULTS_SENDS_STATUS1 1
31
32// Map statuses are sent immediately, even if they will be part
33// of sync-updates-to-client package (instead of map-acknowledge)
34// This seems to be the normal case
35#define MAP_STATUS_IMMEDIATE1 1
36
37
38#ifndef SYNCCOMMAND_PART1_EXCLUDE
39
40using namespace sysync;
41
42namespace sysync {
43void TSmlCommandPContainerClear(TSmlCommandPContainer &aContainer)
44{
45 while (!aContainer.empty()) {
46 delete aContainer.front();
47 aContainer.pop_front();
48 }
49}
50}
51
52/* command name list, used for cmdRef */
53
54const char * const SyncCommandNames[numSmlCommandTypes] = {
55 "SyncHdr",
56 "Sync",
57 "Sync", // note this is actually SyncEnd, but as we send this as cmdRef, it MUST be named "Sync" as well
58 "Add",
59 "Alert",
60 "Delete",
61 "Get",
62 "Put",
63 "Map",
64 "Results",
65 "Status",
66 "Replace",
67 "Copy",
68 "Move",
69 "Sequence",
70 "Atomic",
71 "[unknown]"
72};
73
74
75/*
76 * Implementation of TSmlCommand
77 */
78
79/* public TSmlCommand members */
80
81
82// base constructor (to be called by all derived constructors)
83TSmlCommand::TSmlCommand(
84 TSmlCommandTypes aCmdType, // the command type
85 bool aOutgoing, // set if this is a outgoing command (to avoid confusion)
86 TSyncSession *aSessionP, // associated session (for callbacks)
87 uInt32 aMsgID // (optional, for receiving only) the Message ID of the command
88)
89{
90 // save info
91 fCmdType=aCmdType;
92 fMsgID=aMsgID;
93 fSessionP=aSessionP;
94 fOutgoing=aOutgoing;
95 // init
96 fWaitingForStatus=0; // not yet waiting for any statuses
97 fCmdID=0; // no ID yet, will be either set at issue() or read at StartProcessing()
98 fNoResp=false; // respond by default
99 fDontSend=false; // send by default
100 fEvalMode=false; // no eval
101 fPrepared=false;
102 fAllowFailure=false;
103 // debug
104 DEBUGPRINTFX(DBG_PROTO,("Created command '%s' (%s)", getName(), fOutgoing ? "outgoing" : "incoming")){ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ("Created command '%s' (%s)"
, getName(), fOutgoing ? "outgoing" : "incoming"); }
;
105} // TSmlCommand::TSmlCommand
106
107
108// get name of command
109const char *TSmlCommand::getName(void)
110{
111 return SyncCommandNames[fCmdType];
112} // TSmlCommand::getName
113
114
115#ifdef SYDEBUG2
116TDebugLogger *TSmlCommand::getDbgLogger(void)
117{
118 // commands log to session's logger
119 return fSessionP ? fSessionP->getDbgLogger() : NULL__null;
120} // TSmlCommand::getDbgLogger
121
122uInt32 TSmlCommand::getDbgMask(void)
123{
124 if (!fSessionP) return 0; // no session, no debug
125 return fSessionP->getDbgMask();
126} // TSmlCommand::getDbgMask
127#endif
128
129
130TSyncAppBase *TSmlCommand::getSyncAppBase(void)
131{
132 return fSessionP ? fSessionP->getSyncAppBase() : NULL__null;
133} // TSmlCommand::getSyncAppBase
134
135
136// get name of certain command
137const char *TSmlCommand::getNameOf(TSmlCommandTypes aCmdType)
138{
139 return SyncCommandNames[aCmdType];
140} // TSmlCommand::getNameOf
141
142
143// start processing a command
144void TSmlCommand::StartProcessing(
145 SmlPcdataPtr_t aCmdID, // ID of command
146 Flag_t aFlags // flags of command
147)
148{
149 // get command ID
150 StrToULong(smlPCDataToCharP(aCmdID),fCmdID);
151 // get noResp state
152 fNoResp=(aFlags & SmlNoResp_f0x0100)!=0;
153 PDEBUGPRINTFX(DBG_HOT,("Started processing Command '%s' (incoming MsgID=%ld, CmdID=%ld)%s",getName(),(long)fMsgID,(long)fCmdID,fNoResp ? ", noResp" : "")){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("Started processing Command '%s' (incoming MsgID=%ld, CmdID=%ld)%s"
,getName(),(long)fMsgID,(long)fCmdID,fNoResp ? ", noResp" : ""
); }
;
154} // TSmlCommand::StartProcessing
155
156
157
158// - Prepare for issuing, evaluate size of command
159sInt32 TSmlCommand::evalIssue(
160 uInt32 aAsCmdID, // command ID to be used
161 uInt32 aInMsgID, // message ID in which command is being issued
162 bool aNoResp // issue without wanting response
163)
164{
165 MemSize_t res;
166 bool ok;
167
168 fPrepared=false; // force re-prepare
169
170 // start evaluation run
171 smlStartEvaluation(fSessionP->getSmlWorkspaceID());
172
173 fEvalMode=true;
174 SYSYNC_TRYtry {
175 // - call issue to get size
176 ok=issue(aAsCmdID,aInMsgID,aNoResp);
177 // - back to normal mode
178 fEvalMode=false;
179 smlEndEvaluation(fSessionP->getSmlWorkspaceID(),&res);
180 if (!ok) res=-1; // no room, error
181 /* %%% hack to force unsendable-sized syncop commands:
182 #ifdef RELEASE_VERSION
183 #error "%%%%remove this debuh hack!!!"
184 #endif
185 if (dynamic_cast<TSyncOpCommand *>(this)!=NULL) {
186 // always oversized
187 res=0;
188 }
189 */
190 }
191 SYSYNC_CATCH (...)catch(...) {
192 fEvalMode=false;
193 smlEndEvaluation(fSessionP->getSmlWorkspaceID(),&res);
194 SYSYNC_RETHROWthrow;
195 SYSYNC_ENDCATCH}
196
197 // return available space after sending this command
198 return res;
199} // TSmlCommand::evalIssue
200
201
202
203void TSmlCommand::PrepareIssue(
204 SmlPcdataPtr_t *aCmdID, // ID of command
205 Flag_t *aFlags // flags of command
206)
207{
208 if (!fPrepared) {
209 fPrepared=true;
210 // set Command ID
211 if (aCmdID) {
212 // remove old
213 if (*aCmdID) smlFreePcdata(*aCmdID);
214 // create new
215 *aCmdID=newPCDataLong(fCmdID);
216 }
217 // add NoResp flag if requested
218 if (aFlags)
219 *aFlags |= fNoResp ? SmlNoResp_f0x0100 : 0;
220 }
221 if (!fEvalMode) {
222 #ifdef SYDEBUG2
223 if (aCmdID) {
224 if (*aCmdID==NULL__null)
225 SYSYNC_THROW(TSyncException("No Command ID set at evalIssue() but requested one at issue()"))throw TSyncException("No Command ID set at evalIssue() but requested one at issue()"
)
;
226 }
227 #endif
228 // save workspace size immediately before sending to calc message size
229 fBytesbefore=fSessionP->getSmlWorkspaceFreeBytes();
230 #ifdef DEBUG_XMLRESPONSE_FOR_WBXML
231 // %%% debug hack %%% force output to be XML
232 smlSetEncoding(fSessionP->getSmlWorkspaceID(),SML_XML);
233 #endif
234 }
235} // TSmlCommand::PrepareIssue
236
237
238#ifndef USE_SML_EVALUATION1
239
240// get (approximated) message size required for sending it
241uInt32 TSmlCommand::messageSize(void)
242{
243 // default, should be enough for most commands
244 return DEFAULTCOMMANDSIZE200;;
245}
246
247#endif
248
249// finalizes issuing a command (updates message size)
250void TSmlCommand::FinalizeIssue(void)
251{
252 fSessionP->incOutgoingMessageSize(fBytesbefore-fSessionP->getSmlWorkspaceFreeBytes()); // update msg size
253 #ifdef DEBUG_XMLRESPONSE_FOR_WBXML
254 // %%% debug hack %%% force input to be WBXML again
255 smlSetEncoding(fSessionP->getSmlWorkspaceID(),SML_WBXML);
256 #endif
257} // TSmlCommand::FinalizeIssue
258
259
260// finalizes issuing a command (updates message size)
261bool TSmlCommand::queueForResponse(void)
262{
263 return (!fNoResp && !fSessionP->fOutgoingNoResp);
264} // TSmlCommand::queueForStatus
265
266
267// returns true if command must be put to the waiting-for-status queue.
268// If false, command can be deleted
269bool TSmlCommand::issue(
270 uInt32 aAsCmdID, // command ID to be used
271 uInt32 aInMsgID, // message ID in which command is being issued
272 bool aNoResp
273)
274{
275 // set command ID and Message ID (for further compare with incoming statuses)
276 fCmdID=aAsCmdID;
277 fMsgID=aInMsgID;
278 fNoResp=aNoResp;
279 return fEvalMode; // evaluation ok, but base class commands cannot be issued
280} // TSmlCommand::issue
281
282
283// execute command (perform real actions, generate status)
284// returns true if command has executed and can be deleted
285bool TSmlCommand::execute(void)
286{
287 // non-derived execute (such as map received by client): protocol error
288 TStatusCommand *statusCmdP=newStatusCommand(400);
289 ISSUE_COMMAND_ROOT(fSessionP,statusCmdP){ TSmlCommand* p=statusCmdP; statusCmdP=__null; fSessionP->
issueRootPtr(p); }
;
290 // done
291 return false;
292} // TSmlCommand::execute
293
294
295// - test if command matches status
296bool TSmlCommand::matchStatus(TStatusCommand *aStatusCmdP)
297{
298 // match if cmdID and msgID are the same
299 return (
300 (fMsgID==aStatusCmdP->fRefMsgID) &&
301 (fCmdID==aStatusCmdP->fRefCmdID)
302 );
303} // TSmlCommand::matchStatus
304
305
306// handle status received for previously issued command
307// returns true if done, false if command must be kept in the status queue
308bool TSmlCommand::handleStatus(TStatusCommand *aStatusCmdP)
309{
310 // base class just handles common cases
311 TSyError statuscode = aStatusCmdP->getStatusCode();
312 if (statuscode<200) {
313 // informational
314 switch (statuscode) {
315 case 101:
316 // in progress, wait for final status
317 POBJDEBUGPRINTFX(fSessionP,DBG_HOT,("Status: 101: In progress, keep waiting for final status")){ if ((fSessionP) && (((0x00000001) & (fSessionP)
->getDbgMask()) == (0x00000001))) (fSessionP)->getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("Status: 101: In progress, keep waiting for final status"
); }
;
318 return false; // keep in queue
319 //break;
320 default:
321 // unknown
322 POBJDEBUGPRINTFX(fSessionP,DBG_ERROR,("Status: %hd: unknown informational status -> accepted",statuscode)){ if ((fSessionP) && (((0x00000002) & (fSessionP)
->getDbgMask()) == (0x00000002))) (fSessionP)->getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("Status: %hd: unknown informational status -> accepted"
,statuscode); }
;
323 return true;
324 }
325 }
326 else if (statuscode<300) {
327 if (statuscode==202) {
328 // accepted for processing
329 POBJDEBUGPRINTFX(fSessionP,DBG_PROTO,("Status: 202: accepted for processing, keep waiting for final status")){ if ((fSessionP) && (((0x00000010) & (fSessionP)
->getDbgMask()) == (0x00000010))) (fSessionP)->getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ("Status: 202: accepted for processing, keep waiting for final status"
); }
;
330 return false; // keep in queue
331 }
332 // successful
333 POBJDEBUGPRINTFX(fSessionP,DBG_PROTO,("Status: %hd: successful --> accept as ok",statuscode)){ if ((fSessionP) && (((0x00000010) & (fSessionP)
->getDbgMask()) == (0x00000010))) (fSessionP)->getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ("Status: %hd: successful --> accept as ok"
,statuscode); }
;
334 return true; // done with command
335 }
336 else if (statuscode<400) {
337 // redirection
338 // %%% - we cannot handle them, abort for now
339 POBJDEBUGPRINTFX(fSessionP,DBG_ERROR,("Status: %hd: redirected --> we cannot handle this, abort session",statuscode)){ if ((fSessionP) && (((0x00000002) & (fSessionP)
->getDbgMask()) == (0x00000002))) (fSessionP)->getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("Status: %hd: redirected --> we cannot handle this, abort session"
,statuscode); }
;
340 fSessionP->AbortSession(412,false,statuscode); // other party's fault: incomplete command
341 return true; // done with command
342 }
343 else if (statuscode==418) {
344 POBJDEBUGPRINTFX(fSessionP,DBG_PROTO,("Status: 418: already existed on peer --> accept as ok")){ if ((fSessionP) && (((0x00000010) & (fSessionP)
->getDbgMask()) == (0x00000010))) (fSessionP)->getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ("Status: 418: already existed on peer --> accept as ok"
); }
;
345 return true; // done with command
346 }
347 else if (statuscode<500) {
348 // originator exception (we sent some bad stuff)
349 POBJDEBUGPRINTFX(fSessionP,DBG_ERROR,("Status: %hd: originator exception",statuscode)){ if ((fSessionP) && (((0x00000002) & (fSessionP)
->getDbgMask()) == (0x00000002))) (fSessionP)->getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("Status: %hd: originator exception"
,statuscode); }
;
350 if (!fAllowFailure) fSessionP->AbortSession(500,false,statuscode); // our fault
351 return true; // done with command
352 }
353 else {
354 // must be recipient exception
355 POBJDEBUGPRINTFX(fSessionP,DBG_ERROR,("Status: %hd: recipient exception",statuscode)){ if ((fSessionP) && (((0x00000002) & (fSessionP)
->getDbgMask()) == (0x00000002))) (fSessionP)->getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("Status: %hd: recipient exception"
,statuscode); }
;
356 if (!fAllowFailure) fSessionP->AbortSession(statuscode,false,statuscode); // show other party's reason for error
357 return true; // done with command
358 }
359 // just to make sure
360 return true; // done with command
361} // TSmlCommand::handleStatus
362
363
364
365// generate status depending on fNoResp and session's fMsgNoResp
366TStatusCommand *TSmlCommand::newStatusCommand(TSyError aStatusCode, const char *aStringItem)
367{
368 TStatusCommand *statusCmdP = new TStatusCommand(fSessionP,this,aStatusCode);
369 if (aStringItem)
370 statusCmdP->addItemString(aStringItem);
371 return statusCmdP;
372} // TSmlCommand::newStatusCommand
373
374
375// generate and send status depending on fNoResp and session's fMsgNoResp
376void TSmlCommand::issueStatusCommand(TSyError aStatusCode)
377{
378 // issuePtr can handle NULL in case no status was generated...
379 fSessionP->issueRootPtr(newStatusCommand(aStatusCode));
380} // TSmlCommand::issueStatusCommand
381
382
383
384TSmlCommand::~TSmlCommand()
385{
386 TSmlCommandPContainerClear(fPendingStatusReplies);
387 PDEBUGPRINTFX(DBG_PROTO,("Deleted command '%s' (%s MsgID=%ld, CmdID=%ld)",getName(),fOutgoing ? "outgoing" : "incoming", (long)fMsgID,(long)fCmdID)){ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ("Deleted command '%s' (%s MsgID=%ld, CmdID=%ld)"
,getName(),fOutgoing ? "outgoing" : "incoming", (long)fMsgID,
(long)fCmdID); }
;
388} // TSmlCommand::~TSmlCommand
389
390void TSmlCommand::queueStatusCmd(TSmlCommand *aSyncCommandP)
391{
392 fPendingStatusReplies.push_back(aSyncCommandP);
393}
394
395bool TSmlCommand::hasQueuedStatusCmds() const
396{
397 return !fPendingStatusReplies.empty();
398}
399
400void TSmlCommand::transferQueuedStatusCmds(TSmlCommandPContainer &commands)
401{
402 while (!fPendingStatusReplies.empty()) {
403 commands.push_back(fPendingStatusReplies.front());
404 fPendingStatusReplies.pop_front();
405 }
406}
407
408/* end of TSmlCommand implementation */
409
410
411
412/*
413 * Implementation of TSyncHeader
414 */
415
416/* public TSyncHeader members */
417
418
419// constructor for receiving Sync header
420TSyncHeader::TSyncHeader(
421 TSyncSession *aSessionP, // associated session (for callbacks)
422 SmlSyncHdrPtr_t aSyncHdrElementP // associated SyncHdr content element
423) :
424 TSmlCommand(scmd_synchdr,false,aSessionP)
425{
426 // save element
427 fSyncHdrElementP = aSyncHdrElementP;
428} // TSyncHeader::TSyncHeader
429
430
431// constructor for sending SyncHdr
432TSyncHeader::TSyncHeader(
433 TSyncSession *aSessionP, // associated session (for callbacks)
434 bool aOutgoingNoResp // if true, entire message will request no responses
435) :
436 TSmlCommand(scmd_synchdr,true,aSessionP)
437{
438 // prevent two simultaneous messages
439 if (fSessionP->fOutgoingStarted)
440 SYSYNC_THROW(TSyncException("Tried to start new message before finishing previous"))throw TSyncException("Tried to start new message before finishing previous"
)
;
441 // let session create the structure (using session vars for info)
442 fSyncHdrElementP=fSessionP->NewOutgoingSyncHdr(aOutgoingNoResp);
443 // now outgoing message IS started
444 fSessionP->fOutgoingStarted=true;
445} // TSyncHeader::TSyncHeader
446
447
448// returns true if command must be put to the waiting-for-status queue.
449// If false, command can be deleted
450bool TSyncHeader::issue(
451 uInt32 aAsCmdID, // command ID to be used
452 uInt32 aInMsgID, // message ID in which command is being issued
453 bool aNoResp
454)
455{
456 // prepare basic stuff
457 TSmlCommand::issue(0,aInMsgID,false);
458 // now issue
459 if (fSyncHdrElementP) {
460 // issue command with SyncML toolkit, no CmdID or flags to set here
461 PrepareIssue(NULL__null,NULL__null);
462 if (!fEvalMode) {
463 Ret_t err;
464 #ifdef SYDEBUG2
465 if (fSessionP->fXMLtranslate && fSessionP->fOutgoingXMLInstance) {
466 err=smlStartMessageExt(fSessionP->fOutgoingXMLInstance,fSyncHdrElementP,SmlVersionCodes[fSessionP->fSyncMLVersion]);
467 if (err!=SML_ERR_OK0x00) {
468 // problem with XML translation
469 PDEBUGPRINTFX(DBG_ERROR,("XML translation disabled due to sml error=%04hX",err)){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("XML translation disabled due to sml error=%04hX"
,err); }
;
470 fSessionP->fXMLtranslate=false;
471 }
472 }
473 #endif
474 if ((err=smlStartMessageExt(fSessionP->getSmlWorkspaceID(),fSyncHdrElementP,SmlVersionCodes[fSessionP->fSyncMLVersion]))!=SML_ERR_OK0x00) {
475 SYSYNC_THROW(TSmlException("smlStartMessage",err))throw TSmlException("smlStartMessage",err);
476 }
477 FinalizeIssue();
478 // we don't need the status structure any more, free (and NULL ptr) now
479 FreeSmlElement();
480 }
481 else
482 // just evaluate size
483 return smlStartMessageExt(fSessionP->getSmlWorkspaceID(),fSyncHdrElementP,SmlVersionCodes[fSessionP->fSyncMLVersion])==SML_ERR_OK0x00;
484 }
485 else {
486 DEBUGPRINTFX(DBG_ERROR,("*** Tried to issue NULL synchdr")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("*** Tried to issue NULL synchdr"
); }
;
487 }
488 // header will normally receive status
489 return queueForResponse();
490} // TSyncHeader::issue
491
492
493// handle status received for previously issued command
494// returns true if done, false if command must be kept in the status queue
495bool TSyncHeader::handleStatus(TStatusCommand *aStatusCmdP)
496{
497 // status for SyncHdr
498 if (!fSessionP->handleHeaderStatus(aStatusCmdP)) {
499 // session could not handle item
500 return TSmlCommand::handleStatus(aStatusCmdP);
501 }
502 // status handled
503 return true; // done with command
504} // TSyncHeader::handleStatus
505
506
507// execute command (perform real actions, generate status)
508// returns true if command has executed and can be deleted
509// NOTE: synchdr is a special case: if it returns FALSE,
510// session must be reset and synchdr must be re-excecuted
511bool TSyncHeader::execute(void)
512{
513 const char *verDTD;
514 const char *verProto;
515 TStatusCommand *statusCmdP=NULL__null;
516 sInt16 statuscode=400;
517 bool hdrok=true;
518
519 if (!fSyncHdrElementP) SYSYNC_THROW(TSyncException("empty header"))throw TSyncException("empty header");
520 if (!fSessionP) SYSYNC_THROW(TSyncException("missing fSessionP"))throw TSyncException("missing fSessionP");
521 // first get message ID to be able to generate statuses
522 fMsgID=0; // none by default
523 if (StrToULong(smlPCDataToCharP(fSyncHdrElementP->msgID),fMsgID)) {
524 // got msgID, check if ok
525 if (
526 fMsgID==uInt32(fSessionP->fIncomingMsgID-1) &&
527 fSessionP->fAllowMessageRetries // check if we want to allow this (7250 for example seems to retry messages)
528 ) {
529 // this seems to be a transport-level retry of the previous message
530 PDEBUGPRINTFX(DBG_ERROR,("*********** WARNING: Remote resent MsgID %ld",(long)fMsgID)){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("*********** WARNING: Remote resent MsgID %ld"
,(long)fMsgID); }
;
531 // set back incoming ID
532 fSessionP->fIncomingMsgID = fMsgID;
533 // -> we should resend the previous answer again.
534 if (
535 fSessionP->getSyncAppBase()->canBufferRetryAnswer()
536 ) {
537 // we can resend answers
538 PDEBUGPRINTFX(DBG_ERROR,("last answer buffered -> sending it again")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("last answer buffered -> sending it again"
); }
;
539 fSessionP->fMessageRetried=true;
540 return false;
541 }
542 else {
543 // use not foolproof poor man's method
544 // %%% This will fail if the previous message received has
545 // changed datastore/session/package states, but will work if
546 // the retry is within a phase (probable case for long sessions)
547 PDEBUGPRINTFX(DBG_ERROR,("No buffered answer to resend -> just process msg again (WARNING: possibly messes up session state)")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("No buffered answer to resend -> just process msg again (WARNING: possibly messes up session state)"
); }
;
548 }
549 }
550 if (fMsgID<uInt32(fSessionP->fIncomingMsgID)) {
551 // bad Message ID (lower than previous): forget previous session, start new one
552 PDEBUGPRINTFX(DBG_ERROR,("Bad incoming MsgID %ld, expected >=%ld -> Aborting previous Session, starting new",(long)fMsgID,(long)fSessionP->fIncomingMsgID)){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("Bad incoming MsgID %ld, expected >=%ld -> Aborting previous Session, starting new"
,(long)fMsgID,(long)fSessionP->fIncomingMsgID); }
;
553 return false; // session must be restarted, this command re-executed
554 }
555 }
556 else {
557 // header without session ID is bad
558 statuscode=500;
559 statusCmdP=newStatusCommand(statuscode);
560 // log file entry
561 PDEBUGPRINTFX(DBG_ERROR,("Missing incoming MsgID -> Aborting Session")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("Missing incoming MsgID -> Aborting Session"
); }
;
562 hdrok=false; // cannot start
563 }
564 // Assign session-var anyway
565 fSessionP->fIncomingMsgID=fMsgID;
566 // now check header for conformance
567 SYSYNC_TRYtry {
568 // get info out of SyncHdr
569 if (hdrok) {
570 // get noResp flag (which is valid for the entire message)
571 fNoResp=(fSyncHdrElementP->flags & SmlNoResp_f0x0100)!=0;
572 fSessionP->fMsgNoResp=fNoResp; // copy to session flag
573 // test SyncML version compatibility
574 verProto=smlPCDataToCharP(fSyncHdrElementP->proto);
575 verDTD=smlPCDataToCharP(fSyncHdrElementP->version);
576 sInt16 ver;
577 // find version
578 for (ver=1; ver<numSyncMLVersions; ver++) {
579 if (strcmp(verProto,SyncMLVerProtoNames[ver])==0) {
580 // known version found
581 // - set it only for server, client keeps preset version (will change it when
582 // a 513 is detected)
583 if (IS_SERVER(getSyncAppBase()->isServer())) fSessionP->fSyncMLVersion=(TSyncMLVersions)ver;
584 break;
585 }
586 }
587 // - Protocol Version
588 TSyncMLVersions maxver = fSessionP->getSessionConfig()->fMaxSyncMLVersionSupported;
589 TSyncMLVersions minver = fSessionP->getSessionConfig()->fMinSyncMLVersionSupported;
590 if (
591 ver<minver ||
592 ver>=numSyncMLVersions ||
593 ver>maxver ||
594 (IS_SERVER(getSyncAppBase()->isServer()) && fSessionP->fSyncMLVersion!=syncml_vers_unknown && fSessionP->fSyncMLVersion!=ver)
595 ) {
596 // unsupported protocol version (or different than in first message): Status 513
597 // - Make sure we have a valid SyncML version
598 if (
599 fSessionP->fSyncMLVersion==syncml_vers_unknown ||
600 fSessionP->fSyncMLVersion>maxver
601 ) {
602 // use highest version we know for the answering message
603 fSessionP->fSyncMLVersion = maxver;
604 }
605 else if (fSessionP->fSyncMLVersion<minver) {
606 // use lowest enabled version for answering message
607 fSessionP->fSyncMLVersion = minver;
608 }
609 // - Set status
610 statuscode=513;
611 statusCmdP=newStatusCommand(statuscode);
612 // - add version(s) we support in data item
613 string vs;
614 for (sInt16 v=minver; v<=maxver; v++) {
615 if (!vs.empty()) vs+=", ";
616 vs+=SyncMLVerProtoNames[v];
617 }
618 statusCmdP->addItemString(vs.c_str());
619 // - log file entry
620 PDEBUGPRINTFX(DBG_ERROR,("Unsupported or changing verProto %s -> Aborting Session",verProto)){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("Unsupported or changing verProto %s -> Aborting Session"
,verProto); }
;
621 hdrok=false; // bad header
622 }
623 // protocol version known, check if DTD matches
624 else if (strcmp(verDTD,SyncMLVerDTDNames[ver])!=0) {
625 // wrong DTD version for this protocol version: Status 505
626 statuscode=505;
627 statusCmdP=newStatusCommand(statuscode);
628 statusCmdP->addItemString(SyncMLVerDTDNames[ver]);
629 // log file entry
630 PDEBUGPRINTFX(DBG_ERROR,({ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "Wrong verDTD %s, expected %s -> Aborting Session"
, verDTD, SyncMLVerDTDNames[ver] ); }
631 "Wrong verDTD %s, expected %s -> Aborting Session",{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "Wrong verDTD %s, expected %s -> Aborting Session"
, verDTD, SyncMLVerDTDNames[ver] ); }
632 verDTD,{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "Wrong verDTD %s, expected %s -> Aborting Session"
, verDTD, SyncMLVerDTDNames[ver] ); }
633 SyncMLVerDTDNames[ver]{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "Wrong verDTD %s, expected %s -> Aborting Session"
, verDTD, SyncMLVerDTDNames[ver] ); }
634 )){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "Wrong verDTD %s, expected %s -> Aborting Session"
, verDTD, SyncMLVerDTDNames[ver] ); }
;
635 hdrok=false; // bad header
636 }
637 // if ok so far, continue header processing
638 if (hdrok) {
639 PDEBUGPRINTFX(DBG_HOT,("Started Processing of message #%ld (%s)",(long)fSessionP->fIncomingMsgID,SyncMLVerProtoNames[ver])){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("Started Processing of message #%ld (%s)"
,(long)fSessionP->fIncomingMsgID,SyncMLVerProtoNames[ver])
; }
;
640 // take a look at SyncHdr Meta
641 SmlMetInfMetInfPtr_t metaP=smlPCDataToMetInfP(fSyncHdrElementP->meta);
642 if (metaP) {
643 // max (outgoing) message size
644 if (metaP->maxmsgsize) {
645 smlPCDataToLong(metaP->maxmsgsize,fSessionP->fMaxOutgoingMsgSize);
646 PDEBUGPRINTFX(DBG_REMOTEINFO,("MaxMsgSize found in SyncHdr: %ld -> set for outgoing msgs",(long)fSessionP->fMaxOutgoingMsgSize)){ if (((0x00000100) & getDbgMask()) == (0x00000100)) getDbgLogger
()->setNextMask(0x00000100).DebugPrintfLastMask ("MaxMsgSize found in SyncHdr: %ld -> set for outgoing msgs"
,(long)fSessionP->fMaxOutgoingMsgSize); }
;
647 }
648 // max (outgoing) object size (SyncML 1.1 only)
649 if (metaP->maxobjsize) {
650 smlPCDataToLong(metaP->maxobjsize,fSessionP->fMaxOutgoingObjSize);
651 PDEBUGPRINTFX(DBG_REMOTEINFO,("MaxObjSize found in SyncHdr: %ld",(long)fSessionP->fMaxOutgoingObjSize)){ if (((0x00000100) & getDbgMask()) == (0x00000100)) getDbgLogger
()->setNextMask(0x00000100).DebugPrintfLastMask ("MaxObjSize found in SyncHdr: %ld"
,(long)fSessionP->fMaxOutgoingObjSize); }
;
652 }
653 }
654 // call server/client specific message start in derived classes
655 statusCmdP=newStatusCommand(200); // prepare OK default status (will possibly be modified by MessageStarted())
656 hdrok=fSessionP->MessageStarted(fSyncHdrElementP,*statusCmdP);
657 }
658 else {
659 //#warning "comment the next line to have server respond like pre-1.0.8.29"
660 // call client/server specific message start routine, but with error flag
661 // Note: we already have a status command (containing an error)
662 fSessionP->MessageStarted(fSyncHdrElementP,*statusCmdP,true);
663 }
664 }
665 // complete and send status, if any
666 if (statusCmdP) {
667 statusCmdP->addTargetRef(fSessionP->fLocalURI.c_str());
668 statusCmdP->addSourceRef(fSessionP->fRemoteURI.c_str());
669 // issue as SyncHdr status (if successful status)
670 TStatusCommand *cmdP = statusCmdP; statusCmdP=NULL__null;
671 statuscode=cmdP->getStatusCode(); // get actual status code
672 fSessionP->issueRootPtr(cmdP,false,statuscode==200);
673 }
674 // set session vars according to header success or failure
675 // - ignore all further incoming commands when header is not ok
676 // NOTE: bad cred will NOT (any longer, SyncFest #5) be flagged as bad header
677 // but instead MessageStarted may have aborted command processing
678 if (!hdrok) fSessionP->AbortSession(400,true); // bad request
679 // free this one now, is not needed any more
680 FreeSmlElement();
681 }
682 SYSYNC_CATCH (...)catch(...) {
683 // make sure owned objects in local scope are deleted
684 if (statusCmdP) delete statusCmdP;
685 // re-throw
686 SYSYNC_RETHROWthrow;
687 SYSYNC_ENDCATCH}
688 // done with command, delete it now: return true
689 return true;
690} // TSyncHeader::execute
691
692
693
694void TSyncHeader::FreeSmlElement(void)
695{
696 // remove SyncML toolkit element(s)
697 FREEPROTOELEMENT(fSyncHdrElementP);
698} // TSyncHeader::FreeSmlElement
699
700
701TSyncHeader::~TSyncHeader()
702{
703 // free command elements, if any (use explicit invocation as this is a destructor)
704 TSyncHeader::FreeSmlElement();
705} // TSyncHeader::~TSyncHeader
706
707
708/* end of TSyncHeader implementation */
709
710
711
712/*
713 * Implementation of TSyncCommand
714 */
715
716
717// constructor for sending Sync Command
718TSyncCommand::TSyncCommand(
719 TSyncSession *aSessionP, // associated session (for callbacks)
720 TLocalEngineDS *aLocalDataStoreP, // local datastore
721 TRemoteDataStore *aRemoteDataStoreP // remote datastore
722) :
723 TSmlCommand(scmd_sync,true,aSessionP),
724 fInterruptedCommandP(NULL__null)
725{
726 // save params
727 fLocalDataStoreP=aLocalDataStoreP;
728 fRemoteDataStoreP=aRemoteDataStoreP;
729 // create internal sync element
730 fSyncElementP = SML_NEW(SmlSync_t)((SmlSync_t*) _smlMalloc(sizeof(SmlSync_t)));
731 // set proto element type to make it auto-disposable
732 fSyncElementP->elementType=SML_PE_SYNC_START;
733 // Cmd ID is now empty (will be set when issued)
734 fSyncElementP->cmdID=NULL__null;
735 // default to no flags (noResp is set at issue, if at all)
736 fSyncElementP->flags=0;
737 // set source and target
738 fSyncElementP->target=newLocation(fRemoteDataStoreP->getFullName()); // remote is target for Sync command
739 fSyncElementP->source=newLocation(fLocalDataStoreP->getRemoteViewOfLocalURI()); // local is source of Sync command
740 // no optional elements for now
741 fSyncElementP->cred=NULL__null; // %%% no database level auth yet at all
742 fSyncElementP->meta=NULL__null; // %%% no search grammar for now
743 // add number of changes for SyncML 1.1 if remote supports it
744 fSyncElementP->noc=NULL__null; // default to none
745 fRemoteWantsNOC=aSessionP->fRemoteWantsNOC;
746 if (fRemoteWantsNOC) {
747 sInt32 noc = fLocalDataStoreP->getNumberOfChanges();
748 if (noc>=0) {
749 // we have a valid NOC value, add it
750 fSyncElementP->noc=newPCDataLong(noc);
751 }
752 }
753 // not yet in progress (as not yet issued)
754 fInProgress=false;
755} // TSyncCommand::TSyncCommand
756
757
758// constructor for receiving Sync Command
759TSyncCommand::TSyncCommand(
760 TSyncSession *aSessionP, // associated session (for callbacks)
761 uInt32 aMsgID, // the Message ID of the command
762 SmlSyncPtr_t aSyncElementP // associated Sync content element
763) :
764 TSmlCommand(scmd_sync,false,aSessionP,aMsgID),
765 fInterruptedCommandP(NULL__null)
766{
767 // save sync element
768 fSyncElementP = aSyncElementP;
769 fInProgress=false; // just in case...
770 // no params
771 fLocalDataStoreP=NULL__null;
772 fRemoteDataStoreP=NULL__null;
773} // TSyncCommand::TSyncCommand
774
775
776// handle status received for previously issued command
777// returns true if done, false if command must be kept in the status queue
778bool TSyncCommand::handleStatus(TStatusCommand *aStatusCmdP)
779{
780 // catch those codes that do not abort entire session
781 TSyError statuscode = aStatusCmdP->getStatusCode();
782 bool handled=false;
783 switch (statuscode) {
784 case 404: // datastore not found
785 case 403: // forbidden
786 case 406: // bad mode
787 case 415: // type(s) not supported
788 case 422: // bad CGI
789 case 510: // datastore error
790 case 512: // sync failed
791 case 514: // cancelled
792 if (fLocalDataStoreP) {
793 // there is a local datastore to abort
794 fLocalDataStoreP->engAbortDataStoreSync(statuscode,false); // remote problem
795 }
796 if (fInProgress) {
797 // make sure sync command is finished now
798 fInProgress=false;
799 // Note that setting fInProgress to false
800 // is only completely safe in issue().
801 // Here it is allowed as we KNOW that syncCommand
802 // is root level, so session's handleStatus()
803 // will properly clear the fInterruptedCommandP
804 // (this would not work if this command was nested)
805 }
806 handled = true;
807 break;
808 default:
809 handled=TSmlCommand::handleStatus(aStatusCmdP);
810 break;
811 }
812 return handled;
813} // TSyncCommand::handleStatus
814
815
816// mark any syncitems (or other data) for resume. Called for pending commands
817// when a Suspend alert is received or whenever a resumable state must be saved
818void TSyncCommand::markPendingForResume(TLocalEngineDS *aForDatastoreP, bool aUnsent)
819{
820 // only act if this is for our local datastore and unsent
821 // (sent ones will be in the status wait queue, and will be found there)
822 if (aUnsent && fLocalDataStoreP==aForDatastoreP) {
823 fSessionP->markPendingForResume(
824 fNextMessageCommands,
825 fInterruptedCommandP,
826 fLocalDataStoreP
827 );
828 }
829} // TSyncCommand::markPendingForResume
830
831
832// analyze command (but do not yet execute)
833bool TSyncCommand::analyze(TPackageStates aPackageState)
834{
835 TSmlCommand::analyze(aPackageState);
836 // get Command ID and flags
837 if (fSyncElementP) {
838 StartProcessing(fSyncElementP->cmdID,fSyncElementP->flags);
839 return true;
840 }
841 else return false; // no proto element, bad command
842} // TSyncCommand::analyze
843
844
845// execute command (perform real actions, generate status)
846// returns true if command has executed and can be deleted
847bool TSyncCommand::execute(void)
848{
849 TStatusCommand *statusCmdP=NULL__null;
850 bool queueforlater = false;
851
852 if (fSyncElementP)
853 SYSYNC_TRYtry {
854 // determine database to be synced (target LocURI)
855 // - generate default OK status
856 statusCmdP = newStatusCommand(200);
857 // - add source and target refs from item
858 statusCmdP->addSourceRef(smlSrcTargLocURIToCharP(fSyncElementP->source));
859 statusCmdP->addTargetRef(smlSrcTargLocURIToCharP(fSyncElementP->target));
860 PDEBUGPRINTFX(DBG_HOT,({ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "Processing Sync, Source='%s', Target='%s'"
, smlSrcTargLocURIToCharP(fSyncElementP->source), smlSrcTargLocURIToCharP
(fSyncElementP->target) ); }
861 "Processing Sync, Source='%s', Target='%s'",{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "Processing Sync, Source='%s', Target='%s'"
, smlSrcTargLocURIToCharP(fSyncElementP->source), smlSrcTargLocURIToCharP
(fSyncElementP->target) ); }
862 smlSrcTargLocURIToCharP(fSyncElementP->source),{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "Processing Sync, Source='%s', Target='%s'"
, smlSrcTargLocURIToCharP(fSyncElementP->source), smlSrcTargLocURIToCharP
(fSyncElementP->target) ); }
863 smlSrcTargLocURIToCharP(fSyncElementP->target){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "Processing Sync, Source='%s', Target='%s'"
, smlSrcTargLocURIToCharP(fSyncElementP->source), smlSrcTargLocURIToCharP
(fSyncElementP->target) ); }
864 )){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "Processing Sync, Source='%s', Target='%s'"
, smlSrcTargLocURIToCharP(fSyncElementP->source), smlSrcTargLocURIToCharP
(fSyncElementP->target) ); }
;
865 // - check for MaxObjSize here
866 SmlMetInfMetInfPtr_t metaP=smlPCDataToMetInfP(fSyncElementP->meta);
867 if (metaP && metaP->maxobjsize) {
868 smlPCDataToLong(metaP->maxobjsize,fSessionP->fMaxOutgoingObjSize);
869 PDEBUGPRINTFX(DBG_REMOTEINFO,("MaxObjSize found in Sync command: %ld",(long)fSessionP->fMaxOutgoingObjSize)){ if (((0x00000100) & getDbgMask()) == (0x00000100)) getDbgLogger
()->setNextMask(0x00000100).DebugPrintfLastMask ("MaxObjSize found in Sync command: %ld"
,(long)fSessionP->fMaxOutgoingObjSize); }
;
870 }
871 // - let session do the processing
872 queueforlater=false;
873 fSessionP->processSyncStart(
874 fSyncElementP,
875 *statusCmdP,
876 queueforlater // will be set if command must be queued for later re-execution
877 );
878 if (queueforlater) {
879 // we don't need the status now
880 delete statusCmdP;
881 }
882 else {
883 // Sync command execution completed, send (or save) status now
884 #ifdef SYNCSTATUS_AT_SYNC_CLOSE
885 // %%% don't send, just save for being sent at </Sync>
886 fSessionP->fSyncCloseStatusCommandP=statusCmdP;
887 #else
888 // - issue status for item
889 ISSUE_COMMAND_ROOT(fSessionP,statusCmdP){ TSmlCommand* p=statusCmdP; statusCmdP=__null; fSessionP->
issueRootPtr(p); }
;
890 #endif
891 /* %%% no need to abort session, failing sync command stops sync with this
892 datastore anyway
893 // make sure session gets aborted when Sync is not successful
894 if (!ok) {
895 fSessionP->AbortSession(500,true);
896 }
897 */
898 // free element
899 FreeSmlElement();
900 }
901 }
902 SYSYNC_CATCH (...)catch(...) {
903 // make sure owned objects in local scope are deleted
904 if (statusCmdP) delete statusCmdP;
905 // re-throw
906 SYSYNC_RETHROWthrow;
907 SYSYNC_ENDCATCH}
908 // return true if command has fully executed
909 return !queueforlater;
910} // TSyncCommand::execute
911
912
913// returns true if command must be put to the waiting-for-status queue.
914// If false, command can be deleted
915bool TSyncCommand::issue(
916 uInt32 aAsCmdID, // command ID to be used
917 uInt32 aInMsgID, // message ID in which command is being issued
918 bool aNoResp
919)
920{
921 // prepare basic stuff
922 TSmlCommand::issue(aAsCmdID,aInMsgID,aNoResp);
923 // now issue
924 if (fSyncElementP) {
925 // generate (first) opening (or evaluate)
926 if (fEvalMode) return generateOpen();
927 generateOpen();
928 // generate commands, update fInProgress
929 generateCommandsAndClose();
930 // Make sure this is not counted as command (will be counted in issuePtr(), so
931 // decrement here). Note that this must be done AFTER calling generateCommandsAndClose(),
932 // because generating needs the correct count (and this <sync> is not yet included by now!)
933 fSessionP->fOutgoingCmds--; // we're now one below the real count, but that will be compensated when returning to issuePtr
934 }
935 else {
936 DEBUGPRINTFX(DBG_ERROR,("*** Tried to issue NULL sync")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("*** Tried to issue NULL sync"
); }
;
937 }
938 // return true if command must be queued for status/result response reception
939 return queueForResponse();
940} // TSyncCommand::issue
941
942
943// - test if completely issued (must be called after issue() and continueIssue())
944bool TSyncCommand::finished(void)
945{
946 // not finished as long there are more syncOps to send;
947 // incoming are always finished after executing
948 return (!fInProgress || !fOutgoing);
949} // TSyncCommand::finished
950
951
952// generate opening <Sync> bracket
953bool TSyncCommand::generateOpen(void)
954{
955 // issue command Start <Sync> with SyncML toolkit
956 fPrepared=false; // force re-preparing in all cases (as this might be continuing a command)
957 PrepareIssue(&fSyncElementP->cmdID,&fSyncElementP->flags);
958
959 // (re-)check NumberOfChanges, because in a SyncML client that number might not
960 // have been available right away when constructing the TSyncCommand.
961 if (!fSyncElementP->noc &&
962 fRemoteWantsNOC) {
963 sInt32 noc = fLocalDataStoreP->getNumberOfChanges();
964 if (noc>=0) {
965 fSyncElementP->noc=newPCDataLong(noc);
966 }
967 }
968
969 if (!fEvalMode) {
970 #ifdef SYDEBUG2
971 if (fSessionP->fXMLtranslate && fSessionP->fOutgoingXMLInstance)
972 smlStartSync(fSessionP->fOutgoingXMLInstance,fSyncElementP);
973 #endif
974 Ret_t err;
975 if ((err=smlStartSync(fSessionP->getSmlWorkspaceID(),fSyncElementP))!=SML_ERR_OK0x00) {
976 SYSYNC_THROW(TSmlException("smlStartSync",err))throw TSmlException("smlStartSync",err);
977 }
978 FinalizeIssue();
979 // show debug
980 PDEBUGBLOCKFMT(("sync","Opened Sync command bracket",getDbgLogger()->DebugOpenBlockExpanded ("sync","Opened Sync command bracket"
, "Reopen=%s|SourceURI=%s|TargetURI=%s|IncomingMsgID=%ld|CmdID=%ld"
, fInProgress ? "yes" : "no", smlSrcTargLocURIToCharP(fSyncElementP
->source), smlSrcTargLocURIToCharP(fSyncElementP->target
), (long)fMsgID, (long)fCmdID )
981 "Reopen=%s|SourceURI=%s|TargetURI=%s|IncomingMsgID=%ld|CmdID=%ld",getDbgLogger()->DebugOpenBlockExpanded ("sync","Opened Sync command bracket"
, "Reopen=%s|SourceURI=%s|TargetURI=%s|IncomingMsgID=%ld|CmdID=%ld"
, fInProgress ? "yes" : "no", smlSrcTargLocURIToCharP(fSyncElementP
->source), smlSrcTargLocURIToCharP(fSyncElementP->target
), (long)fMsgID, (long)fCmdID )
982 fInProgress ? "yes" : "no",getDbgLogger()->DebugOpenBlockExpanded ("sync","Opened Sync command bracket"
, "Reopen=%s|SourceURI=%s|TargetURI=%s|IncomingMsgID=%ld|CmdID=%ld"
, fInProgress ? "yes" : "no", smlSrcTargLocURIToCharP(fSyncElementP
->source), smlSrcTargLocURIToCharP(fSyncElementP->target
), (long)fMsgID, (long)fCmdID )
983 smlSrcTargLocURIToCharP(fSyncElementP->source),getDbgLogger()->DebugOpenBlockExpanded ("sync","Opened Sync command bracket"
, "Reopen=%s|SourceURI=%s|TargetURI=%s|IncomingMsgID=%ld|CmdID=%ld"
, fInProgress ? "yes" : "no", smlSrcTargLocURIToCharP(fSyncElementP
->source), smlSrcTargLocURIToCharP(fSyncElementP->target
), (long)fMsgID, (long)fCmdID )
984 smlSrcTargLocURIToCharP(fSyncElementP->target),getDbgLogger()->DebugOpenBlockExpanded ("sync","Opened Sync command bracket"
, "Reopen=%s|SourceURI=%s|TargetURI=%s|IncomingMsgID=%ld|CmdID=%ld"
, fInProgress ? "yes" : "no", smlSrcTargLocURIToCharP(fSyncElementP
->source), smlSrcTargLocURIToCharP(fSyncElementP->target
), (long)fMsgID, (long)fCmdID )
985 (long)fMsgID,getDbgLogger()->DebugOpenBlockExpanded ("sync","Opened Sync command bracket"
, "Reopen=%s|SourceURI=%s|TargetURI=%s|IncomingMsgID=%ld|CmdID=%ld"
, fInProgress ? "yes" : "no", smlSrcTargLocURIToCharP(fSyncElementP
->source), smlSrcTargLocURIToCharP(fSyncElementP->target
), (long)fMsgID, (long)fCmdID )
986 (long)fCmdIDgetDbgLogger()->DebugOpenBlockExpanded ("sync","Opened Sync command bracket"
, "Reopen=%s|SourceURI=%s|TargetURI=%s|IncomingMsgID=%ld|CmdID=%ld"
, fInProgress ? "yes" : "no", smlSrcTargLocURIToCharP(fSyncElementP
->source), smlSrcTargLocURIToCharP(fSyncElementP->target
), (long)fMsgID, (long)fCmdID )
987 ))getDbgLogger()->DebugOpenBlockExpanded ("sync","Opened Sync command bracket"
, "Reopen=%s|SourceURI=%s|TargetURI=%s|IncomingMsgID=%ld|CmdID=%ld"
, fInProgress ? "yes" : "no", smlSrcTargLocURIToCharP(fSyncElementP
->source), smlSrcTargLocURIToCharP(fSyncElementP->target
), (long)fMsgID, (long)fCmdID )
;
988 PDEBUGPRINTFX(DBG_HOT,({ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "%sOpened <Sync> bracket, Source='%s', Target='%s' as (outgoing MsgID=%ld, CmdID=%ld)"
, fInProgress ? "Re-" : "", smlSrcTargLocURIToCharP(fSyncElementP
->source), smlSrcTargLocURIToCharP(fSyncElementP->target
), (long)fMsgID, (long)fCmdID ); }
989 "%sOpened <Sync> bracket, Source='%s', Target='%s' as (outgoing MsgID=%ld, CmdID=%ld)",{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "%sOpened <Sync> bracket, Source='%s', Target='%s' as (outgoing MsgID=%ld, CmdID=%ld)"
, fInProgress ? "Re-" : "", smlSrcTargLocURIToCharP(fSyncElementP
->source), smlSrcTargLocURIToCharP(fSyncElementP->target
), (long)fMsgID, (long)fCmdID ); }
990 fInProgress ? "Re-" : "",{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "%sOpened <Sync> bracket, Source='%s', Target='%s' as (outgoing MsgID=%ld, CmdID=%ld)"
, fInProgress ? "Re-" : "", smlSrcTargLocURIToCharP(fSyncElementP
->source), smlSrcTargLocURIToCharP(fSyncElementP->target
), (long)fMsgID, (long)fCmdID ); }
991 smlSrcTargLocURIToCharP(fSyncElementP->source),{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "%sOpened <Sync> bracket, Source='%s', Target='%s' as (outgoing MsgID=%ld, CmdID=%ld)"
, fInProgress ? "Re-" : "", smlSrcTargLocURIToCharP(fSyncElementP
->source), smlSrcTargLocURIToCharP(fSyncElementP->target
), (long)fMsgID, (long)fCmdID ); }
992 smlSrcTargLocURIToCharP(fSyncElementP->target),{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "%sOpened <Sync> bracket, Source='%s', Target='%s' as (outgoing MsgID=%ld, CmdID=%ld)"
, fInProgress ? "Re-" : "", smlSrcTargLocURIToCharP(fSyncElementP
->source), smlSrcTargLocURIToCharP(fSyncElementP->target
), (long)fMsgID, (long)fCmdID ); }
993 (long)fMsgID,{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "%sOpened <Sync> bracket, Source='%s', Target='%s' as (outgoing MsgID=%ld, CmdID=%ld)"
, fInProgress ? "Re-" : "", smlSrcTargLocURIToCharP(fSyncElementP
->source), smlSrcTargLocURIToCharP(fSyncElementP->target
), (long)fMsgID, (long)fCmdID ); }
994 (long)fCmdID{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "%sOpened <Sync> bracket, Source='%s', Target='%s' as (outgoing MsgID=%ld, CmdID=%ld)"
, fInProgress ? "Re-" : "", smlSrcTargLocURIToCharP(fSyncElementP
->source), smlSrcTargLocURIToCharP(fSyncElementP->target
), (long)fMsgID, (long)fCmdID ); }
995 )){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "%sOpened <Sync> bracket, Source='%s', Target='%s' as (outgoing MsgID=%ld, CmdID=%ld)"
, fInProgress ? "Re-" : "", smlSrcTargLocURIToCharP(fSyncElementP
->source), smlSrcTargLocURIToCharP(fSyncElementP->target
), (long)fMsgID, (long)fCmdID ); }
;
996 // calculate (approx) max free space for data
997 fSessionP->fMaxRoomForData =
998 fSessionP->getSmlWorkspaceFreeBytes()-fSessionP->getNotUsableBufferBytes()- // what is free
999 DEFAULTCOMMANDSIZE200;; // minus a standard command size
1000 // now we are in progress
1001 fInProgress=true;
1002 return true;
1003 }
1004 else
1005 return smlStartSync(fSessionP->getSmlWorkspaceID(),fSyncElementP)==SML_ERR_OK0x00;
1006} // TSyncCommand::generateOpen
1007
1008
1009// generate commands for inside of the <Sync> bracket
1010void TSyncCommand::generateCommandsAndClose(void)
1011{
1012 // generate new commands only if message is not full already
1013 if (!fSessionP->outgoingMessageFull()) {
1014 // check for unassigned fLocalDataStoreP as this seems to happen sometimes in the cmdline client
1015 PPOINTERTEST(fLocalDataStoreP,("Warning: fLocalDataStoreP==NULL, cannot generate commands -> empty <sync> command"))if (!fLocalDataStoreP) getDbgLogger()->setNextMask(0x00000002
).DebugPrintfLastMask ("Warning: fLocalDataStoreP==NULL, cannot generate commands -> empty <sync> command"
)
;
1016 if (fLocalDataStoreP) {
1017 fInProgress = !(
1018 fLocalDataStoreP->engGenerateSyncCommands
1019 (
1020 fNextMessageCommands,
1021 fInterruptedCommandP
1022 )
1023 );
1024 }
1025 }
1026 // issue command End </Sync> with SyncML toolkit
1027 // - save workspace size immediately before sending to calc message size
1028 fBytesbefore=fSessionP->getSmlWorkspaceFreeBytes();
1029 #ifdef SYDEBUG2
1030 if (fSessionP->fXMLtranslate && fSessionP->fOutgoingXMLInstance)
1031 smlEndSync(fSessionP->fOutgoingXMLInstance);
1032 #endif
1033 Ret_t err;
1034 if ((err=smlEndSync(fSessionP->getSmlWorkspaceID()))!=SML_ERR_OK0x00) {
1035 SYSYNC_THROW(TSmlException("smlEndSync",err))throw TSmlException("smlEndSync",err);
1036 }
1037 FinalizeIssue();
1038 PDEBUGPRINTFX(DBG_HOT,({ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "Closed </Sync> bracket, %sfinal"
, fInProgress ? "NOT " : "" ); }
1039 "Closed </Sync> bracket, %sfinal",{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "Closed </Sync> bracket, %sfinal"
, fInProgress ? "NOT " : "" ); }
1040 fInProgress ? "NOT " : ""{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "Closed </Sync> bracket, %sfinal"
, fInProgress ? "NOT " : "" ); }
1041 )){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "Closed </Sync> bracket, %sfinal"
, fInProgress ? "NOT " : "" ); }
;
1042 PDEBUGENDBLOCK("sync")getDbgLogger()->DebugCloseBlock( "sync");
1043} // TSyncCommand::generateCommandsAndClose
1044
1045
1046// - continue issuing command. This is called by session at start of new message
1047// when finished() returned false after issue()/continueIssue()
1048// (which causes caller of finished() to put command into fInteruptedCommands queue)
1049// returns true if command should be queued for status (again?)
1050// NOTE: continueIssue must make sure that it gets a new CmdID/MsgID because
1051// the command itself is issued multiple times
1052bool TSyncCommand::continueIssue(bool &aNewIssue)
1053{
1054 aNewIssue=false; // never issue anew!
1055 if (!fInProgress) return false; // done, don't queue for status again
1056 // command is in progress, re-open a <sync> bracket in this message
1057 // - get new CmdID/MsgID
1058 fCmdID = fSessionP->getNextOutgoingCmdID();
1059 fMsgID = fSessionP->getOutgoingMsgID();
1060 // - now issue open
1061 generateOpen();
1062 // first try to execute queued sub-commands that could not be sent in last message
1063 fSessionP->ContinuePackage(
1064 fNextMessageCommands,
1065 fInterruptedCommandP
1066 );
1067 // then generate more commands if needed (updates fInProgress)
1068 generateCommandsAndClose();
1069 // new sync command must be queued for status again
1070 return true;
1071} // TSyncCommand::continueIssue
1072
1073
1074void TSyncCommand::FreeSmlElement(void)
1075{
1076 // remove SyncML toolkit element(s)
1077 FREEPROTOELEMENT(fSyncElementP);
1078} // TResultsCommand::FreeSmlElement
1079
1080
1081TSyncCommand::~TSyncCommand()
1082{
1083 // free command elements, if any (use explicit invocation as this is a destructor)
1084 TSyncCommand::FreeSmlElement();
1085 // forget any queued sub commands
1086 TSmlCommandPContainer::iterator pos;
1087 for (pos=fNextMessageCommands.begin(); pos!=fNextMessageCommands.end(); ++pos) {
1088 // show that command was not sent
1089 DEBUGPRINTFX(DBG_ERROR,("Never sent prepared Sub-Command '%s', (outgoing MsgID=%ld, CmdID=%ld)",{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("Never sent prepared Sub-Command '%s', (outgoing MsgID=%ld, CmdID=%ld)"
, (*pos)->getName(), (long)(*pos)->getMsgID(), (long)(*
pos)->getCmdID() ); }
1090 (*pos)->getName(),{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("Never sent prepared Sub-Command '%s', (outgoing MsgID=%ld, CmdID=%ld)"
, (*pos)->getName(), (long)(*pos)->getMsgID(), (long)(*
pos)->getCmdID() ); }
1091 (long)(*pos)->getMsgID(),{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("Never sent prepared Sub-Command '%s', (outgoing MsgID=%ld, CmdID=%ld)"
, (*pos)->getName(), (long)(*pos)->getMsgID(), (long)(*
pos)->getCmdID() ); }
1092 (long)(*pos)->getCmdID(){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("Never sent prepared Sub-Command '%s', (outgoing MsgID=%ld, CmdID=%ld)"
, (*pos)->getName(), (long)(*pos)->getMsgID(), (long)(*
pos)->getCmdID() ); }
1093 )){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("Never sent prepared Sub-Command '%s', (outgoing MsgID=%ld, CmdID=%ld)"
, (*pos)->getName(), (long)(*pos)->getMsgID(), (long)(*
pos)->getCmdID() ); }
;
1094 // delete
1095 delete *pos;
1096 }
1097 fNextMessageCommands.clear(); // clear list
1098 // - interrupted command
1099 // NOTE: interrupted subcommands may NOT exist in any of the main command
1100 // queues, because these OWN the commands and will delete them
1101 // at ResetSession().
1102 if (fInterruptedCommandP) {
1103 // show that command was not sent
1104 DEBUGPRINTFX(DBG_ERROR,("Never finished interrupted sub-command '%s', (outgoing MsgID=%ld, CmdID=%ld)",{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("Never finished interrupted sub-command '%s', (outgoing MsgID=%ld, CmdID=%ld)"
, fInterruptedCommandP->getName(), (long)fInterruptedCommandP
->getMsgID(), (long)fInterruptedCommandP->getCmdID() );
}
1105 fInterruptedCommandP->getName(),{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("Never finished interrupted sub-command '%s', (outgoing MsgID=%ld, CmdID=%ld)"
, fInterruptedCommandP->getName(), (long)fInterruptedCommandP
->getMsgID(), (long)fInterruptedCommandP->getCmdID() );
}
1106 (long)fInterruptedCommandP->getMsgID(),{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("Never finished interrupted sub-command '%s', (outgoing MsgID=%ld, CmdID=%ld)"
, fInterruptedCommandP->getName(), (long)fInterruptedCommandP
->getMsgID(), (long)fInterruptedCommandP->getCmdID() );
}
1107 (long)fInterruptedCommandP->getCmdID(){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("Never finished interrupted sub-command '%s', (outgoing MsgID=%ld, CmdID=%ld)"
, fInterruptedCommandP->getName(), (long)fInterruptedCommandP
->getMsgID(), (long)fInterruptedCommandP->getCmdID() );
}
1108 )){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("Never finished interrupted sub-command '%s', (outgoing MsgID=%ld, CmdID=%ld)"
, fInterruptedCommandP->getName(), (long)fInterruptedCommandP
->getMsgID(), (long)fInterruptedCommandP->getCmdID() );
}
;
1109 delete fInterruptedCommandP;
1110 fInterruptedCommandP=NULL__null;
1111 }
1112} // TSyncCommand::~TSyncCommand
1113
1114
1115/* end of TSyncCommand implementation */
1116
1117
1118/*
1119 * Implementation of TSyncEndCommand
1120 */
1121
1122
1123// constructor for receiving Sync Command
1124TSyncEndCommand::TSyncEndCommand(
1125 TSyncSession *aSessionP, // associated session (for callbacks)
1126 uInt32 aMsgID // the Message ID of the command
1127) :
1128 TSmlCommand(scmd_syncend,false,aSessionP,aMsgID)
1129{
1130 // nop so far
1131} // TSyncEndCommand::TSyncEndCommand
1132
1133
1134// execute command (perform real actions, generate status)
1135// returns true if command has executed and can be deleted
1136bool TSyncEndCommand::execute(void)
1137{
1138 bool queueforlater=false;
1139
1140 // let session do the appropriate processing
1141 fSessionP->processSyncEnd(queueforlater);
1142 // return true if command has fully executed
1143 return !queueforlater;
1144} // TSyncEndCommand::execute
1145
1146
1147TSyncEndCommand::~TSyncEndCommand()
1148{
1149} // TSyncEndCommand::~TSyncEndCommand
1150
1151
1152/* end of TSyncEndCommand implementation */
1153
1154
1155
1156/*
1157 * Implementation of TAlertCommand
1158 */
1159
1160
1161// constructor for sending Alert
1162TAlertCommand::TAlertCommand(
1163 TSyncSession *aSessionP, // associated session (for callbacks)
1164 TLocalEngineDS *aLocalDataStoreP, // local datastore
1165 uInt16 aAlertCode // Alert code to send
1166) :
1167 TSmlCommand(scmd_alert,true,aSessionP)
1168{
1169 // save datastore
1170 fLocalDataStoreP = aLocalDataStoreP;
1171 // save Alert Code
1172 fAlertCode = aAlertCode;
1173 // create internal alert element
1174 fAlertElementP = SML_NEW(SmlAlert_t)((SmlAlert_t*) _smlMalloc(sizeof(SmlAlert_t)));
1175 // set proto element type to make it auto-disposable
1176 fAlertElementP->elementType=SML_PE_ALERT;
1177 // Cmd ID is now empty (will be set when issued)
1178 fAlertElementP->cmdID=NULL__null;
1179 // default to no flags (noResp is set at issue, if at all)
1180 fAlertElementP->flags=0;
1181 // data is alert code
1182 fAlertElementP->data=newPCDataLong(fAlertCode);
1183 // no optional elements for now
1184 fAlertElementP->cred=NULL__null;
1185 fAlertElementP->itemList=NULL__null;
1186} // TAlertCommand::TAlertCommand
1187
1188
1189// constructor for receiving Alert
1190TAlertCommand::TAlertCommand(
1191 TSyncSession *aSessionP, // associated session (for callbacks)
1192 uInt32 aMsgID, // the Message ID of the command
1193 SmlAlertPtr_t aAlertElementP // associated Alert content element
1194) :
1195 TSmlCommand(scmd_alert,false,aSessionP,aMsgID)
1196{
1197 // save alert element
1198 fAlertElementP = aAlertElementP;
1199 // no params
1200 fLocalDataStoreP=NULL__null;
1201} // TAlertCommand::TAlertCommand
1202
1203
1204// analyze command (but do not yet execute)
1205bool TAlertCommand::analyze(TPackageStates aPackageState)
1206{
1207 TSmlCommand::analyze(aPackageState);
1208 // get Command ID and flags
1209 if (fAlertElementP) {
1210 StartProcessing(fAlertElementP->cmdID,fAlertElementP->flags);
1211 return true;
1212 }
1213 else return false; // no proto element, bad command
1214} // TAlertCommand::analyze
1215
1216
1217// execute command (perform real actions, generate status)
1218// returns true if command has executed and can be deleted
1219bool TAlertCommand::execute(void)
1220{
1221 TStatusCommand *statusCmdP=NULL__null;
1222 TSmlCommand *alertresponsecmdP=NULL__null;
1223
1224 SYSYNC_TRYtry {
1225 // get alert code
1226 sInt32 temp;
1227 if (!smlPCDataToLong(fAlertElementP->data,temp)) {
1228 // non-numeric alert
1229 PDEBUGPRINTFX(DBG_ERROR,({ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "Non-Integer Alert Data: '%s', cannot handle"
, smlPCDataToCharP(fAlertElementP->data) ); }
1230 "Non-Integer Alert Data: '%s', cannot handle",{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "Non-Integer Alert Data: '%s', cannot handle"
, smlPCDataToCharP(fAlertElementP->data) ); }
1231 smlPCDataToCharP(fAlertElementP->data){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "Non-Integer Alert Data: '%s', cannot handle"
, smlPCDataToCharP(fAlertElementP->data) ); }
1232 )){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "Non-Integer Alert Data: '%s', cannot handle"
, smlPCDataToCharP(fAlertElementP->data) ); }
;
1233 statusCmdP = newStatusCommand(400,"Alert Data not understood");
1234 }
1235 else {
1236 fAlertCode=temp;
1237 PDEBUGPRINTFX(DBG_HOT,({ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "Code=%hd. %s Cred. Analyzing Items"
, fAlertCode, fAlertElementP->cred ? "has" : "No" ); }
1238 "Code=%hd. %s Cred. Analyzing Items",{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "Code=%hd. %s Cred. Analyzing Items"
, fAlertCode, fAlertElementP->cred ? "has" : "No" ); }
1239 fAlertCode,{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "Code=%hd. %s Cred. Analyzing Items"
, fAlertCode, fAlertElementP->cred ? "has" : "No" ); }
1240 fAlertElementP->cred ? "has" : "No"{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "Code=%hd. %s Cred. Analyzing Items"
, fAlertCode, fAlertElementP->cred ? "has" : "No" ); }
1241 )){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "Code=%hd. %s Cred. Analyzing Items"
, fAlertCode, fAlertElementP->cred ? "has" : "No" ); }
;
1242 // intercept special codes
1243 if (fAlertCode==221) {
1244 // %%% tdb
1245 PDEBUGPRINTFX(DBG_ERROR,("*********** RESULT ALERT 221 received in bad context")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("*********** RESULT ALERT 221 received in bad context"
); }
;
1246 statusCmdP = newStatusCommand(400,"221 Alert in bad context received");
1247 } else if (fAlertCode==222) {
1248 // request next message in packet
1249 PDEBUGPRINTFX(DBG_HOT,("Next Message in Packet Alert (222): flag sending waiting commands")){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("Next Message in Packet Alert (222): flag sending waiting commands"
); }
;
1250 // - acknowledge 222 alert
1251 statusCmdP = newStatusCommand(200);
1252 // - add source and target refs
1253 statusCmdP->addTargetRef(fSessionP->getLocalURI());
1254 statusCmdP->addSourceRef(fSessionP->getRemoteURI());
1255 // - issue status for item (but not being sent alone with SyncHdr status)
1256 // (treat it like ok-synchdr-status = NOT to be sent if there's no real command following)
1257 { TSmlCommand* p=statusCmdP; statusCmdP=NULL__null; fSessionP->issueRootPtr(p,false,true); }
1258 // - signal occurrence of 222 alert to session
1259 fSessionP->nextMessageRequest();
1260 } else {
1261 // normal alert, walk through items
1262 SmlItemListPtr_t nextitemP = fAlertElementP->itemList;
1263 while (nextitemP) {
1264 if (nextitemP->item) {
1265 // - check for MaxObjSize here
1266 SmlMetInfMetInfPtr_t metaP=smlPCDataToMetInfP(nextitemP->item->meta);
1267 if (metaP && metaP->maxobjsize) {
1268 smlPCDataToLong(metaP->maxobjsize,fSessionP->fMaxOutgoingObjSize);
1269 PDEBUGPRINTFX(DBG_REMOTEINFO,("MaxObjSize found in Alert command: %ld",(long)fSessionP->fMaxOutgoingObjSize)){ if (((0x00000100) & getDbgMask()) == (0x00000100)) getDbgLogger
()->setNextMask(0x00000100).DebugPrintfLastMask ("MaxObjSize found in Alert command: %ld"
,(long)fSessionP->fMaxOutgoingObjSize); }
;
1270 }
1271 // process alert item with common code
1272 // - generate default OK status
1273 statusCmdP = newStatusCommand(200);
1274 // - add source and target refs from item
1275 statusCmdP->addSourceRef(smlSrcTargLocURIToCharP(nextitemP->item->source));
1276 statusCmdP->addTargetRef(smlSrcTargLocURIToCharP(nextitemP->item->target));
1277 PDEBUGPRINTFX(DBG_HOT,({ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "- Processing Alert Item (code=%hd), Source='%s', Target='%s'"
, fAlertCode, smlSrcTargLocURIToCharP(nextitemP->item->
source), smlSrcTargLocURIToCharP(nextitemP->item->target
) ); }
1278 "- Processing Alert Item (code=%hd), Source='%s', Target='%s'",{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "- Processing Alert Item (code=%hd), Source='%s', Target='%s'"
, fAlertCode, smlSrcTargLocURIToCharP(nextitemP->item->
source), smlSrcTargLocURIToCharP(nextitemP->item->target
) ); }
1279 fAlertCode,{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "- Processing Alert Item (code=%hd), Source='%s', Target='%s'"
, fAlertCode, smlSrcTargLocURIToCharP(nextitemP->item->
source), smlSrcTargLocURIToCharP(nextitemP->item->target
) ); }
1280 smlSrcTargLocURIToCharP(nextitemP->item->source),{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "- Processing Alert Item (code=%hd), Source='%s', Target='%s'"
, fAlertCode, smlSrcTargLocURIToCharP(nextitemP->item->
source), smlSrcTargLocURIToCharP(nextitemP->item->target
) ); }
1281 smlSrcTargLocURIToCharP(nextitemP->item->target){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "- Processing Alert Item (code=%hd), Source='%s', Target='%s'"
, fAlertCode, smlSrcTargLocURIToCharP(nextitemP->item->
source), smlSrcTargLocURIToCharP(nextitemP->item->target
) ); }
1282 )){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "- Processing Alert Item (code=%hd), Source='%s', Target='%s'"
, fAlertCode, smlSrcTargLocURIToCharP(nextitemP->item->
source), smlSrcTargLocURIToCharP(nextitemP->item->target
) ); }
;
1283 // - let session process the alert item
1284 alertresponsecmdP =
1285 fSessionP->processAlertItem(
1286 fAlertCode,
1287 nextitemP->item,
1288 fAlertElementP->cred,
1289 *statusCmdP,
1290 fLocalDataStoreP // receives involved datastore (Note: if Alert cmd has multiple items, this will finally contain only the datastore of the last item, others might differ)
1291 );
1292 // - issue status for item
1293 ISSUE_COMMAND_ROOT(fSessionP,statusCmdP){ TSmlCommand* p=statusCmdP; statusCmdP=__null; fSessionP->
issueRootPtr(p); }
;
1294 // - issue result (e.g. acknowledge alert) for item, if any
1295 if (alertresponsecmdP) {
1296 fSessionP->queueForIssueRoot(alertresponsecmdP);
1297 }
1298 }
1299 // next
1300 nextitemP=nextitemP->next;
1301 } // while
1302 } // normal alert code with item
1303 } // numeric alert code
1304 // free element
1305 FreeSmlElement();
1306 }
1307 SYSYNC_CATCH (...)catch(...) {
1308 // make sure owned objects in local scope are deleted
1309 if (statusCmdP) delete statusCmdP;
1310 if (alertresponsecmdP) delete alertresponsecmdP;
1311 // re-throw
1312 SYSYNC_RETHROWthrow;
1313 SYSYNC_ENDCATCH}
1314 // done with command, delete it now: return true
1315 return true;
1316} // TAlertCommand::execute
1317
1318
1319// returns true if command must be put to the waiting-for-status queue.
1320// If false, command can be deleted
1321bool TAlertCommand::issue(
1322 uInt32 aAsCmdID, // command ID to be used
1323 uInt32 aInMsgID, // message ID in which command is being issued
1324 bool aNoResp
1325)
1326{
1327 // prepare basic stuff
1328 TSmlCommand::issue(aAsCmdID,aInMsgID,aNoResp);
1329 // now issue
1330 if (fAlertElementP) {
1331 // issue command with SyncML toolkit
1332 PrepareIssue(&fAlertElementP->cmdID,&fAlertElementP->flags);
1333 if (!fEvalMode) {
1334 #ifdef SYDEBUG2
1335 if (fSessionP->fXMLtranslate && fSessionP->fOutgoingXMLInstance)
1336 smlAlertCmd(fSessionP->fOutgoingXMLInstance,fAlertElementP);
1337 #endif
1338 Ret_t err;
1339 if ((err=smlAlertCmd(fSessionP->getSmlWorkspaceID(),fAlertElementP))!=SML_ERR_OK0x00) {
1340 SYSYNC_THROW(TSmlException("smlAlertCmd",err))throw TSmlException("smlAlertCmd",err);
1341 }
1342 FinalizeIssue();
1343 // show debug
1344 #ifdef SYDEBUG2
1345 PDEBUGPRINTFX(DBG_HOT,("Alert Code %s sent",{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("Alert Code %s sent"
, smlPCDataToCharP(fAlertElementP->data) ); }
1346 smlPCDataToCharP(fAlertElementP->data){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("Alert Code %s sent"
, smlPCDataToCharP(fAlertElementP->data) ); }
1347 )){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("Alert Code %s sent"
, smlPCDataToCharP(fAlertElementP->data) ); }
;
1348 // normal alert, walk through items
1349 SmlItemListPtr_t nextitemP = fAlertElementP->itemList;
1350 while (nextitemP) {
1351 if (nextitemP->item) {
1352 // show alert item
1353 PDEBUGPRINTFX(DBG_HOT,({ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "- Alert Item: Source='%s', Target='%s'"
, smlSrcTargLocURIToCharP(nextitemP->item->source), smlSrcTargLocURIToCharP
(nextitemP->item->target) ); }
1354 "- Alert Item: Source='%s', Target='%s'",{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "- Alert Item: Source='%s', Target='%s'"
, smlSrcTargLocURIToCharP(nextitemP->item->source), smlSrcTargLocURIToCharP
(nextitemP->item->target) ); }
1355 smlSrcTargLocURIToCharP(nextitemP->item->source),{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "- Alert Item: Source='%s', Target='%s'"
, smlSrcTargLocURIToCharP(nextitemP->item->source), smlSrcTargLocURIToCharP
(nextitemP->item->target) ); }
1356 smlSrcTargLocURIToCharP(nextitemP->item->target){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "- Alert Item: Source='%s', Target='%s'"
, smlSrcTargLocURIToCharP(nextitemP->item->source), smlSrcTargLocURIToCharP
(nextitemP->item->target) ); }
1357 )){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "- Alert Item: Source='%s', Target='%s'"
, smlSrcTargLocURIToCharP(nextitemP->item->source), smlSrcTargLocURIToCharP
(nextitemP->item->target) ); }
;
1358 }
1359 // next
1360 nextitemP=nextitemP->next;
1361 /// @note %%% we should not send more than one item for now!
1362 if (nextitemP)
1363 DEBUGPRINTFX(DBG_ERROR,("More than one item - handleStatus is not prepared for that!")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("More than one item - handleStatus is not prepared for that!"
); }
;
1364 } // while
1365 #endif
1366 // we don't need the status structure any more, free (and NULL ptr) now
1367 FreeSmlElement();
1368 }
1369 else
1370 return smlAlertCmd(fSessionP->getSmlWorkspaceID(),fAlertElementP)==SML_ERR_OK0x00;
1371 }
1372 else {
1373 DEBUGPRINTFX(DBG_ERROR,("*** Tried to issue NULL alert")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("*** Tried to issue NULL alert"
); }
;
1374 }
1375 // return true if command must be queued for status/result response reception
1376 return queueForResponse();
1377} // TAlertCommand::issue
1378
1379
1380bool TAlertCommand::statusEssential(void)
1381{
1382 // Alert 222 status is not essential
1383 return !(fAlertCode==222);
1384} // TAlertCommand::statusEssential
1385
1386
1387// handle status received for previously issued command
1388// returns true if done, false if command must be kept in the status queue
1389bool TAlertCommand::handleStatus(TStatusCommand *aStatusCmdP)
1390{
1391 /// @note: This is a simplified implementation which KNOWS that
1392 /// we do not send Alerts with more than one item. If we did one
1393 /// day, we'd have to extend this implementation.
1394 // if this alert command was created by a datastore, let it handle it
1395 if (fLocalDataStoreP) {
1396 // pass to local datastore
1397 if (fLocalDataStoreP->engHandleAlertStatus(aStatusCmdP->getStatusCode()))
1398 return true; // datastore handled it
1399 }
1400 // let SmlCommand handle it
1401 return TSmlCommand::handleStatus(aStatusCmdP);
1402} // TAlertCommand::handleStatus
1403
1404
1405// add a String Item to the alert
1406void TAlertCommand::addItemString(
1407 const char *aItemString // item string to be added
1408)
1409{
1410 if (fAlertElementP && aItemString) {
1411 addItem(newStringDataItem(aItemString));
1412 }
1413} // TAlertCommand::addItemString
1414
1415
1416// add an Item to the alert
1417void TAlertCommand::addItem(
1418 SmlItemPtr_t aItemP // existing item data structure, ownership is passed to Alert
1419)
1420{
1421 if (fAlertElementP)
1422 addItemToList(aItemP,&(fAlertElementP->itemList));
1423} // TAlertCommand::addItem
1424
1425
1426void TAlertCommand::FreeSmlElement(void)
1427{
1428 // remove SyncML toolkit element(s)
1429 FREEPROTOELEMENT(fAlertElementP);
1430} // TResultsCommand::FreeSmlElement
1431
1432
1433TAlertCommand::~TAlertCommand()
1434{
1435 // free command elements, if any (use explicit invocation as this is a destructor)
1436 TAlertCommand::FreeSmlElement();
1437} // TAlertCommand::~TAlertCommand
1438
1439
1440/* end of TAlertCommand implementation */
1441
1442
1443
1444
1445
1446/*
1447 * Implementation of TUnimplementedCommand
1448 */
1449
1450
1451// constructor for receiving command
1452TUnimplementedCommand::TUnimplementedCommand(
1453 TSyncSession *aSessionP, // associated session (for callbacks)
1454 uInt32 aMsgID, // the Message ID of the command
1455 SmlPcdataPtr_t aCmdID, // command ID (as contents are unknown an cannot be analyzed)
1456 Flag_t aFlags, // flags to get fNoResp
1457 TSmlCommandTypes aCmdType, // command type (for name)
1458 void *aContentP, // associated command content element
1459 TSyError aStatusCode // status code to be returned on execution
1460) :
1461 TSmlCommand(aCmdType,false,aSessionP,aMsgID)
1462{
1463 // get command ID
1464 StrToULong(smlPCDataToCharP(aCmdID),fCmdID);
1465 // save noResp
1466 fNoResp=(aFlags & SmlNoResp_f0x0100)!=0;
1467 // forget element
1468 smlFreeProtoElement(aContentP);
1469 // save status type
1470 fStatusCode=aStatusCode;
1471} // TUnimplementedCommand::TUnimplementedCommand
1472
1473
1474// execute command (perform real actions, generate status)
1475// returns true if command has executed and can be deleted
1476bool TUnimplementedCommand::execute(void)
1477{
1478 TStatusCommand *statusCmdP=NULL__null;
1479
1480 DEBUGPRINTFX(DBG_HOT,("UNIMPLEMENTED, started dummy processing, (incoming MsgID=%ld, CmdID=%ld)",(long)fMsgID,(long)fCmdID)){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("UNIMPLEMENTED, started dummy processing, (incoming MsgID=%ld, CmdID=%ld)"
,(long)fMsgID,(long)fCmdID); }
;
1481 SYSYNC_TRYtry {
1482 statusCmdP = newStatusCommand(fStatusCode);
1483 statusCmdP->addItemString("Unimplemented Command");
1484 ISSUE_COMMAND_ROOT(fSessionP,statusCmdP){ TSmlCommand* p=statusCmdP; statusCmdP=__null; fSessionP->
issueRootPtr(p); }
;
1485 }
1486 SYSYNC_CATCH (...)catch(...) {
1487 // make sure owned objects in local scope are deleted
1488 if (statusCmdP) delete statusCmdP;
1489 // re-throw
1490 SYSYNC_RETHROWthrow;
1491 SYSYNC_ENDCATCH}
1492 // done with command, delete it now: return true
1493 return true;
1494} // TUnimplementedCommand::execute
1495
1496
1497/* end of TUnimplementedCommand implementation */
1498
1499
1500
1501/*
1502 * Implementation of TSyncOpCommand
1503 */
1504
1505// constructor for receiving command
1506TSyncOpCommand::TSyncOpCommand(
1507 TSyncSession *aSessionP, // associated session (for callbacks)
1508 TLocalEngineDS *aDataStoreP, // the local datastore this syncop belongs to
1509 uInt32 aMsgID, // the Message ID of the command
1510 TSyncOperation aSyncOp, // the Sync operation (sop_xxx)
1511 TSmlCommandTypes aCmdType, // the command type (scmd_xxx)
1512 SmlGenericCmdPtr_t aSyncOpElementP // associated syncml protocol element
1513) :
1514 TSmlCommand(aCmdType,false,aSessionP,aMsgID)
1515{
1516 // save datastore
1517 fDataStoreP=aDataStoreP;
1518 // save operation type
1519 fSyncOp=aSyncOp;
1520 // save element
1521 fSyncOpElementP = aSyncOpElementP;
1522 // no remainder to be sent as next chunk
1523 fChunkedItemSize = 0;
1524 fIncompleteData = false;
1525 // no suspended part of item
1526 fStoredSize=0;
1527 fUnconfirmedSize=0;
1528 fLastChunkSize=0;
1529} // TSyncOpCommand::TSyncOpCommand
1530
1531
1532// constructor for sending command
1533TSyncOpCommand::TSyncOpCommand(
1534 TSyncSession *aSessionP, // associated session (for callbacks)
1535 TLocalEngineDS *aDataStoreP, // datastore from which command originates
1536 TSyncOperation aSyncOp, // sync operation (=command type)
1537 SmlPcdataPtr_t aMetaP // meta for entire command (passing owner)
1538) :
1539 TSmlCommand(scmd_unknown,true,aSessionP)
1540{
1541 // save datastore
1542 fDataStoreP=aDataStoreP;
1543 #ifndef USE_SML_EVALUATION1
1544 // no items yet
1545 fItemSizes=0;
1546 #endif
1547 // no remainder to be sent as next chunk
1548 fChunkedItemSize = 0;
1549 fIncompleteData = false;
1550 // no suspended part of item
1551 fStoredSize=0;
1552 fUnconfirmedSize=0;
1553 fLastChunkSize=0;
1554 // command type not yet determined
1555 fSyncOp=aSyncOp;
1556 // create internal alert element
1557 fSyncOpElementP = SML_NEW(SmlGenericCmd_t)((SmlGenericCmd_t*) _smlMalloc(sizeof(SmlGenericCmd_t)));
1558 // set default to make sure it is disposable (will be adjusted when items are added)
1559 fSyncOpElementP->elementType=SML_PE_GENERIC;
1560 // Cmd ID is now empty (will be set when issued)
1561 fSyncOpElementP->cmdID=NULL__null;
1562 // default to no flags (noResp is set at issue, if at all)
1563 fSyncOpElementP->flags=0;
1564 // insert meta, if any
1565 fSyncOpElementP->meta=aMetaP;
1566 // no optional elements for now
1567 fSyncOpElementP->cred=NULL__null;
1568 fSyncOpElementP->itemList=NULL__null;
1569 // determine command type
1570 switch (fSyncOp) {
1571 case sop_wants_add:
1572 case sop_add:
1573 fSyncOpElementP->elementType=SML_PE_ADD;
1574 fCmdType=scmd_add;
1575 break;
1576 case sop_copy:
1577 fSyncOpElementP->elementType=SML_PE_COPY;
1578 fCmdType=scmd_copy;
1579 break;
1580 case sop_move:
1581 fSyncOpElementP->elementType=SML_PE_MOVE;
1582 fCmdType=scmd_move;
1583 break;
1584 case sop_wants_replace:
1585 case sop_replace:
1586 fSyncOpElementP->elementType=SML_PE_REPLACE;
1587 fCmdType=scmd_replace;
1588 break;
1589 case sop_archive_delete:
1590 fSyncOpElementP->flags |= SmlArchive_f0x8000;
1591 goto dodelete;
1592 case sop_soft_delete:
1593 fSyncOpElementP->flags |= SmlSftDel_f0x4000;
1594 case sop_delete:
1595 dodelete:
1596 fSyncOpElementP->elementType=SML_PE_DELETE;
1597 fCmdType=scmd_delete;
1598 break;
1599 default:
1600 SYSYNC_THROW(TSyncException("Invalid SyncOp in TSyncOpCommand"))throw TSyncException("Invalid SyncOp in TSyncOpCommand");
1601 //break;
1602 } // switch
1603} // TSyncOpCommand::TSyncOpCommand
1604
1605
1606#ifndef USE_SML_EVALUATION1
1607
1608// get (approximated) message size required for sending it
1609uInt32 TSyncOpCommand::messageSize(void)
1610{
1611 // default, should be enough for most commands
1612 return TSmlCommand::messageSize()+fItemSizes;
1613}
1614
1615#endif
1616
1617
1618// handle status received for previously issued command
1619// returns true if done, false if command must be kept in the status queue
1620bool TSyncOpCommand::handleStatus(TStatusCommand *aStatusCmdP)
1621{
1622 // check if this is a split command
1623 if (fIncompleteData) {
1624 // must be 213
1625 if (aStatusCmdP->getStatusCode()==213) return true;
1626 // something wrong, we did not get a 213
1627 PDEBUGPRINTFX(DBG_ERROR,("chunked object received status %hd instead of 213 --> aborting session",aStatusCmdP->getStatusCode())){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("chunked object received status %hd instead of 213 --> aborting session"
,aStatusCmdP->getStatusCode()); }
;
1628 // reason for aborting is incomplete command (reception)
1629 fSessionP->AbortSession(412,true); // local problem
1630 }
1631 else {
1632 // end of non-split SyncOp means that possibly saved
1633 // parts of partial outgoing item are now obsolete
1634 if (fDataStoreP->fPartialItemState==pi_state_save_outgoing) {
1635 fDataStoreP->fPartialItemState=pi_state_none; // not any more
1636 PDEBUGPRINTFX(DBG_PROTO+DBG_EXOTIC,("chunked object received final status %hd --> forget partial item data now",aStatusCmdP->getStatusCode())){ if (((0x00000010 +0x80000000) & getDbgMask()) == (0x00000010
+0x80000000)) getDbgLogger()->setNextMask(0x00000010 +0x80000000
).DebugPrintfLastMask ("chunked object received final status %hd --> forget partial item data now"
,aStatusCmdP->getStatusCode()); }
;
1637 // - forget stored data in case we have any
1638 if (fDataStoreP->fPIStoredDataP) {
1639 if (fDataStoreP->fPIStoredDataAllocated)
1640 smlLibFree(fDataStoreP->fPIStoredDataP);
1641 fDataStoreP->fPIStoredDataP=NULL__null;
1642 fDataStoreP->fPIStoredDataAllocated=false; // not any more
1643 }
1644 // - clear URIs
1645 fDataStoreP->fLastSourceURI.erase();
1646 fDataStoreP->fLastTargetURI.erase();
1647 // - clear other flags
1648 fDataStoreP->fLastItemStatus=0; // none left to send
1649 fDataStoreP->fPITotalSize=0;
1650 fDataStoreP->fPIUnconfirmedSize=0;
1651 fDataStoreP->fPIStoredSize=0;
1652 }
1653 }
1654 // let datastore handle this
1655 // Note: as fDataStoreP is linked to the generating datastore, this will never be
1656 // a superdatastore. engHandleSyncOpStatus() is prepared to convert
1657 // superID prefixed localIDs back to subDS's localID
1658 bool handled=false;
1659 if (fDataStoreP) {
1660 handled=fDataStoreP->engHandleSyncOpStatus(aStatusCmdP,this);
1661 }
1662 if (!handled) {
1663 // let base class handle it
1664 handled=TSmlCommand::handleStatus(aStatusCmdP);
1665 }
1666 return handled;
1667} // TSyncOpCommand::handleStatus
1668
1669
1670// mark any syncitems (or other data) for resume. Called for pending commands
1671// when a Suspend alert is received or whenever a resumable state must be saved
1672void TSyncOpCommand::markPendingForResume(TLocalEngineDS *aForDatastoreP, bool aUnsent)
1673{
1674 // only act if this is for our local datastore, and only outgoing ones!
1675 if (fOutgoing && fDataStoreP==aForDatastoreP && fSyncOpElementP) {
1676 // go through all of my items
1677 SmlItemListPtr_t itemListP = fSyncOpElementP->itemList;
1678 SmlItemPtr_t itemP;
1679 while (itemListP) {
1680 itemP=itemListP->item;
1681 if (itemP) {
1682 // call datastore to mark this one for resume
1683 fDataStoreP->engMarkItemForResume(
1684 smlSrcTargLocURIToCharP(itemP->source), // source for outgoing items is localID
1685 smlSrcTargLocURIToCharP(itemP->target), // target for outgoing items is remoteID
1686 fIncompleteData ? true : aUnsent // if not completely sent yet, always treat it as unsent!
1687 );
1688 }
1689 itemListP=itemListP->next;
1690 }
1691 }
1692} // TSyncOpCommand::markPendingForResume
1693
1694
1695
1696// mark item for resend in next sync session (if possible)
1697void TSyncOpCommand::markForResend(void)
1698{
1699 if (fOutgoing && fDataStoreP) {
1700 // go through all of my items
1701 SmlItemListPtr_t itemListP = fSyncOpElementP->itemList;
1702 SmlItemPtr_t itemP;
1703 while (itemListP) {
1704 itemP=itemListP->item;
1705 if (itemP) {
1706 // call datastore to mark this one for resume
1707 fDataStoreP->engMarkItemForResend(
1708 smlSrcTargLocURIToCharP(itemP->source), // source for outgoing items is localID
1709 smlSrcTargLocURIToCharP(itemP->target) // target for outgoing items is remoteID
1710 );
1711 }
1712 itemListP=itemListP->next;
1713 }
1714 }
1715} // TSyncOpCommand::markForResend
1716
1717
1718
1719// let item update the partial item state for suspend
1720// Note: this may only be called for an item that is actually the partial item
1721void TSyncOpCommand::updatePartialItemState(TLocalEngineDS *aForDatastoreP)
1722{
1723 if (!fOutgoing && fDataStoreP==aForDatastoreP && fDataStoreP->dsResumeChunkedSupportedInDB()) {
1724 // save info for only partially received item
1725 fDataStoreP->fLastItemStatus = 0; // no status sent yet
1726 // pass current item data
1727 // - get last item data
1728 SmlItemListPtr_t itemnodeP=fSyncOpElementP->itemList;
1729 while (itemnodeP) {
1730 if (!itemnodeP->next) {
1731 // this is the last item
1732 fDataStoreP->fPartialItemState=pi_state_save_incoming;
1733 // - get total expected size
1734 fDataStoreP->fPITotalSize=0;
1735 SmlMetInfMetInfPtr_t metaP = smlPCDataToMetInfP(itemnodeP->item->meta);
1736 if (!metaP || !metaP->size) {
1737 // item has no meta or no meta-size, so size must be in meta of command
1738 metaP = smlPCDataToMetInfP(fSyncOpElementP->meta);
1739 }
1740 if (metaP) smlPCDataToULong(metaP->size, fDataStoreP->fPITotalSize);
1741 // - get data
1742 if (itemnodeP->item && itemnodeP->item->data) {
1743 // dispose current contents if these were separately allocated
1744 // (otherwise, we can just overwrite the pointer)
1745 if (fDataStoreP->fPIStoredDataP && fDataStoreP->fPIStoredDataAllocated)
1746 smlLibFree(fDataStoreP->fPIStoredDataP);
1747 // datastore does NOT get owner of the data!
1748 fDataStoreP->fPIStoredDataAllocated=false; // we still own that data, session must NOT try to dispose!
1749 fDataStoreP->fPIStoredSize=itemnodeP->item->data->length;
1750 fDataStoreP->fPIStoredDataP=itemnodeP->item->data->content;
1751 }
1752 // - get amount of stored data that is unconfirmed
1753 // (=the size of the most recently received chunk. This is unconfirmed
1754 // until the next chunk arrives, because we don't know before that if the
1755 // status 213 has reached the sender)
1756 fDataStoreP->fPIUnconfirmedSize=fLastChunkSize;
1757 // summarize
1758 PDEBUGPRINTFX(DBG_ADMIN,({ if (((0x00000040) & getDbgMask()) == (0x00000040)) getDbgLogger
()->setNextMask(0x00000040).DebugPrintfLastMask ( "State of partially received item: total size=%ld, received=%ld, unconfirmed=%ld"
, (long)fDataStoreP->fPITotalSize, (long)fDataStoreP->fPIStoredSize
, (long)fDataStoreP->fPIUnconfirmedSize ); }
1759 "State of partially received item: total size=%ld, received=%ld, unconfirmed=%ld",{ if (((0x00000040) & getDbgMask()) == (0x00000040)) getDbgLogger
()->setNextMask(0x00000040).DebugPrintfLastMask ( "State of partially received item: total size=%ld, received=%ld, unconfirmed=%ld"
, (long)fDataStoreP->fPITotalSize, (long)fDataStoreP->fPIStoredSize
, (long)fDataStoreP->fPIUnconfirmedSize ); }
1760 (long)fDataStoreP->fPITotalSize,{ if (((0x00000040) & getDbgMask()) == (0x00000040)) getDbgLogger
()->setNextMask(0x00000040).DebugPrintfLastMask ( "State of partially received item: total size=%ld, received=%ld, unconfirmed=%ld"
, (long)fDataStoreP->fPITotalSize, (long)fDataStoreP->fPIStoredSize
, (long)fDataStoreP->fPIUnconfirmedSize ); }
1761 (long)fDataStoreP->fPIStoredSize,{ if (((0x00000040) & getDbgMask()) == (0x00000040)) getDbgLogger
()->setNextMask(0x00000040).DebugPrintfLastMask ( "State of partially received item: total size=%ld, received=%ld, unconfirmed=%ld"
, (long)fDataStoreP->fPITotalSize, (long)fDataStoreP->fPIStoredSize
, (long)fDataStoreP->fPIUnconfirmedSize ); }
1762 (long)fDataStoreP->fPIUnconfirmedSize{ if (((0x00000040) & getDbgMask()) == (0x00000040)) getDbgLogger
()->setNextMask(0x00000040).DebugPrintfLastMask ( "State of partially received item: total size=%ld, received=%ld, unconfirmed=%ld"
, (long)fDataStoreP->fPITotalSize, (long)fDataStoreP->fPIStoredSize
, (long)fDataStoreP->fPIUnconfirmedSize ); }
1763 )){ if (((0x00000040) & getDbgMask()) == (0x00000040)) getDbgLogger
()->setNextMask(0x00000040).DebugPrintfLastMask ( "State of partially received item: total size=%ld, received=%ld, unconfirmed=%ld"
, (long)fDataStoreP->fPITotalSize, (long)fDataStoreP->fPIStoredSize
, (long)fDataStoreP->fPIUnconfirmedSize ); }
;
1764 // done
1765 break;
1766 }
1767 itemnodeP=itemnodeP->next;
1768 } // while
1769 }
1770} // TSyncOpCommand::updatePartialItemState
1771
1772
1773// get source (localID) of sent command
1774cAppCharP TSyncOpCommand::getSourceLocalID(void)
1775{
1776 if (!fSyncOpElementP) return NULL__null;
1777 if (!fSyncOpElementP->itemList) return NULL__null;
1778 if (!fSyncOpElementP->itemList->item) return NULL__null;
1779 return smlSrcTargLocURIToCharP(fSyncOpElementP->itemList->item->source);
1780} // TSyncOpCommand::getSourceLocalID
1781
1782
1783// get target (remoteID) of sent command
1784cAppCharP TSyncOpCommand::getTargetRemoteID(void)
1785{
1786 if (!fSyncOpElementP) return NULL__null;
1787 if (!fSyncOpElementP->itemList) return NULL__null;
1788 if (!fSyncOpElementP->itemList->item) return NULL__null;
1789 return smlSrcTargLocURIToCharP(fSyncOpElementP->itemList->item->target);
1790} // TSyncOpCommand::getTargetRemoteID
1791
1792
1793// add an Item to the sync op command
1794void TSyncOpCommand::addItem(
1795 SmlItemPtr_t aItemP // existing item data structure, ownership is passed to SyncOp command
1796)
1797{
1798 // add item
1799 if (fSyncOpElementP) {
1800 addItemToList(aItemP,&(fSyncOpElementP->itemList));
1801 #ifndef USE_SML_EVALUATION1
1802 fItemSizes +=
1803 ITEMOVERHEADSIZE90 +
1804 strlen(smlSrcTargLocURIToCharP(aItemP->target)) +
1805 strlen(smlSrcTargLocNameToCharP(aItemP->target)) +
1806 strlen(smlSrcTargLocURIToCharP(aItemP->source)) +
1807 strlen(smlSrcTargLocNameToCharP(aItemP->source));
1808 SmlMetInfMetInfPtr_t metaP = smlPCDataToMetInfP(aItemP->meta);
1809 if (metaP) fItemSizes+=strlen(smlPCDataToCharP(metaP->type));
1810 if (aItemP->data) fItemSizes+=aItemP->data->length;
1811 #endif
1812 }
1813} // TSyncOpCommand::addItem
1814
1815
1816
1817// helper: add dataPos EMI to meta
1818static void addDataPos(SmlMetInfMetInfPtr_t aMetaP, uInt32 aDataPos)
1819{
1820 // - find end of emi list or existing datapos
1821 SmlPcdataListPtr_t *emiPP = &(aMetaP->emi);
1822 /* version that searches for existing datapos and will replace it
1823 while (*emiPP!=NULL) {
1824 if (strucmp(smlPCDataToCharP((*emiPP)->data),"datapos=",8)==0) {
1825 // found existing datapos
1826 break;
1827 }
1828 emiPP = &((*emiPP)->next);
1829 }
1830 if (*emiPP==NULL) {
1831 // - add new EMI
1832 *emiPP=(SmlPcdataListPtr_t)smlLibMalloc(sizeof(SmlPcdataList_t));
1833 (*emiPP)->next=NULL;
1834 }
1835 else {
1836 // - replace existing
1837 smlFreePcdata((*emiPP)->data);
1838 }
1839 */
1840 while (*emiPP!=NULL__null) emiPP = &((*emiPP)->next);
1841 // - add new EMI list element
1842 *emiPP=(SmlPcdataListPtr_t)smlLibMalloc(sizeof(SmlPcdataList_t));
1843 (*emiPP)->next=NULL__null;
1844 // - set new data
1845 string s;
1846 StringObjPrintf(s,"datapos=%ld",(long)aDataPos);
1847 (*emiPP)->data = newPCDataString(s.c_str(),s.size());
1848} // addDataPos
1849
1850
1851
1852void TSyncOpCommand::saveAsPartialItem(SmlItemPtr_t aItemP)
1853{
1854 // - forget stored data in case we have any
1855 if (fDataStoreP->fPIStoredDataP) {
1856 if (fDataStoreP->fPIStoredDataAllocated)
1857 smlLibFree(fDataStoreP->fPIStoredDataP);
1858 fDataStoreP->fPIStoredDataP=NULL__null;
1859 fDataStoreP->fPIStoredDataAllocated=false; // not any more
1860 }
1861 // save only when we can actually store chunk resume data
1862 if (fDataStoreP->dsResumeChunkedSupportedInDB()) {
1863 // - save URIs
1864 fDataStoreP->fLastSourceURI=smlSrcTargLocURIToCharP(aItemP->source);
1865 fDataStoreP->fLastTargetURI=smlSrcTargLocURIToCharP(aItemP->target);
1866 // - copy current item's data now (before the split!)
1867 fDataStoreP->fPIStoredDataAllocated=true; // separately allocated buffer, not connected with item any more
1868 fDataStoreP->fPIStoredSize=aItemP->data->length; // length of unsplitted item's buffer
1869 fDataStoreP->fPIStoredDataP=smlLibMalloc(aItemP->data->length);
1870 smlLibMemcpy((uInt8 *)fDataStoreP->fPIStoredDataP,aItemP->data->content,aItemP->data->length);
1871 // - set other flags
1872 fDataStoreP->fLastItemStatus=0; // none left to send
1873 fDataStoreP->fPartialItemState=pi_state_save_outgoing;
1874 fDataStoreP->fPITotalSize=fChunkedItemSize;
1875 fDataStoreP->fPIUnconfirmedSize=fDataStoreP->fPIStoredSize; // just a copy
1876 }
1877} // TSyncOpCommand::saveAsPartialItem
1878
1879
1880// - possibly substitute data with previous session's buffered left-overs from a chunked transfer
1881// for resuming a chunked item transfer.
1882bool TSyncOpCommand::checkChunkContinuation(void)
1883{
1884 if (fChunkedItemSize==0 && fDataStoreP && fDataStoreP->fPartialItemState==pi_state_loaded_outgoing) {
1885 // this is a so far unchunked item, and there is
1886 // to-be-resent data from the previously suspended session
1887 // - check if the command contains the partially sent item
1888 SmlItemListPtr_t itemListP = fSyncOpElementP->itemList;
1889 while (itemListP) {
1890 if (
1891 itemListP->item &&
1892 strcmp(smlSrcTargLocURIToCharP(itemListP->item->source),fDataStoreP->fLastSourceURI.c_str())==0 &&
1893 strcmp(smlSrcTargLocURIToCharP(itemListP->item->target),fDataStoreP->fLastTargetURI.c_str())==0
1894 ) {
1895 // detected to-be-continued chunked item
1896 PDEBUGPRINTFX(DBG_PROTO+DBG_HOT,({ if (((0x00000010 +0x00000001) & getDbgMask()) == (0x00000010
+0x00000001)) getDbgLogger()->setNextMask(0x00000010 +0x00000001
).DebugPrintfLastMask ( "Resuming sending chunked item Source='%s', Target='%s' -> replacing data with rest from suspended session"
, fDataStoreP->fLastSourceURI.c_str(), fDataStoreP->fLastTargetURI
.c_str() ); }
1897 "Resuming sending chunked item Source='%s', Target='%s' -> replacing data with rest from suspended session",{ if (((0x00000010 +0x00000001) & getDbgMask()) == (0x00000010
+0x00000001)) getDbgLogger()->setNextMask(0x00000010 +0x00000001
).DebugPrintfLastMask ( "Resuming sending chunked item Source='%s', Target='%s' -> replacing data with rest from suspended session"
, fDataStoreP->fLastSourceURI.c_str(), fDataStoreP->fLastTargetURI
.c_str() ); }
1898 fDataStoreP->fLastSourceURI.c_str(),{ if (((0x00000010 +0x00000001) & getDbgMask()) == (0x00000010
+0x00000001)) getDbgLogger()->setNextMask(0x00000010 +0x00000001
).DebugPrintfLastMask ( "Resuming sending chunked item Source='%s', Target='%s' -> replacing data with rest from suspended session"
, fDataStoreP->fLastSourceURI.c_str(), fDataStoreP->fLastTargetURI
.c_str() ); }
1899 fDataStoreP->fLastTargetURI.c_str(){ if (((0x00000010 +0x00000001) & getDbgMask()) == (0x00000010
+0x00000001)) getDbgLogger()->setNextMask(0x00000010 +0x00000001
).DebugPrintfLastMask ( "Resuming sending chunked item Source='%s', Target='%s' -> replacing data with rest from suspended session"
, fDataStoreP->fLastSourceURI.c_str(), fDataStoreP->fLastTargetURI
.c_str() ); }
1900 )){ if (((0x00000010 +0x00000001) & getDbgMask()) == (0x00000010
+0x00000001)) getDbgLogger()->setNextMask(0x00000010 +0x00000001
).DebugPrintfLastMask ( "Resuming sending chunked item Source='%s', Target='%s' -> replacing data with rest from suspended session"
, fDataStoreP->fLastSourceURI.c_str(), fDataStoreP->fLastTargetURI
.c_str() ); }
;
1901 // Do not send meta size on all but first chunk
1902 SmlMetInfMetInfPtr_t metinfP = itemListP->item->meta ? (SmlMetInfMetInfPtr_t)(itemListP->item->meta->content) : NULL__null;
1903 if (metinfP && metinfP->size) {
1904 smlFreePcdata(metinfP->size);
1905 metinfP->size=NULL__null;
1906 }
1907 // But make sure item knows the original total size (prevents splitCommand to add meta size again)
1908 fChunkedItemSize = fDataStoreP->fPITotalSize;
1909 // now add dataPos as <meta><EMI>: fPITotalSize-fPIStoredSize
1910 // - make sure we have meta
1911 if (!metinfP) {
1912 itemListP->item->meta=newMeta();
1913 metinfP=(SmlMetInfMetInfPtr_t)(itemListP->item->meta->content);
1914 }
1915 // - add it (total - what remains to be sent)
1916 addDataPos(metinfP,fDataStoreP->fPITotalSize-fDataStoreP->fPIStoredSize);
1917 // update buffered data info
1918 if (itemListP->item->data) {
1919 // substitute original data with buffered rest of data from last session
1920 // (so in case the item has changed in the local DB, we'll still send the original data of
1921 // which the receiver already has seen a part)
1922 PDEBUGPRINTFX(DBG_PROTO+DBG_DETAILS,({ if (((0x00000010 +0x40000000) & getDbgMask()) == (0x00000010
+0x40000000)) getDbgLogger()->setNextMask(0x00000010 +0x40000000
).DebugPrintfLastMask ( "original data size of item=%ld, total size at time of suspend=%ld, rest being sent now=%ld"
, (long)itemListP->item->data->length, (long)fDataStoreP
->fPITotalSize, (long)fDataStoreP->fPIStoredSize ); }
1923 "original data size of item=%ld, total size at time of suspend=%ld, rest being sent now=%ld",{ if (((0x00000010 +0x40000000) & getDbgMask()) == (0x00000010
+0x40000000)) getDbgLogger()->setNextMask(0x00000010 +0x40000000
).DebugPrintfLastMask ( "original data size of item=%ld, total size at time of suspend=%ld, rest being sent now=%ld"
, (long)itemListP->item->data->length, (long)fDataStoreP
->fPITotalSize, (long)fDataStoreP->fPIStoredSize ); }
1924 (long)itemListP->item->data->length, // current total size{ if (((0x00000010 +0x40000000) & getDbgMask()) == (0x00000010
+0x40000000)) getDbgLogger()->setNextMask(0x00000010 +0x40000000
).DebugPrintfLastMask ( "original data size of item=%ld, total size at time of suspend=%ld, rest being sent now=%ld"
, (long)itemListP->item->data->length, (long)fDataStoreP
->fPITotalSize, (long)fDataStoreP->fPIStoredSize ); }
1925 (long)fDataStoreP->fPITotalSize, // total size at time of suspend{ if (((0x00000010 +0x40000000) & getDbgMask()) == (0x00000010
+0x40000000)) getDbgLogger()->setNextMask(0x00000010 +0x40000000
).DebugPrintfLastMask ( "original data size of item=%ld, total size at time of suspend=%ld, rest being sent now=%ld"
, (long)itemListP->item->data->length, (long)fDataStoreP
->fPITotalSize, (long)fDataStoreP->fPIStoredSize ); }
1926 (long)fDataStoreP->fPIStoredSize // what we will send now{ if (((0x00000010 +0x40000000) & getDbgMask()) == (0x00000010
+0x40000000)) getDbgLogger()->setNextMask(0x00000010 +0x40000000
).DebugPrintfLastMask ( "original data size of item=%ld, total size at time of suspend=%ld, rest being sent now=%ld"
, (long)itemListP->item->data->length, (long)fDataStoreP
->fPITotalSize, (long)fDataStoreP->fPIStoredSize ); }
1927 )){ if (((0x00000010 +0x40000000) & getDbgMask()) == (0x00000010
+0x40000000)) getDbgLogger()->setNextMask(0x00000010 +0x40000000
).DebugPrintfLastMask ( "original data size of item=%ld, total size at time of suspend=%ld, rest being sent now=%ld"
, (long)itemListP->item->data->length, (long)fDataStoreP
->fPITotalSize, (long)fDataStoreP->fPIStoredSize ); }
;
1928 // dispose current data
1929 smlLibFree(itemListP->item->data->content);
1930 // set new data from last session
1931 itemListP->item->data->length=fDataStoreP->fPIStoredSize;
1932 itemListP->item->data->content=fDataStoreP->fPIStoredDataP;
1933 // data is now owned by item
1934 fDataStoreP->fPIStoredDataP=NULL__null;
1935 fDataStoreP->fPIStoredSize=0;
1936 fDataStoreP->fPIStoredDataAllocated=false;
1937 }
1938 else {
1939 PDEBUGPRINTFX(DBG_ERROR,("WARNING: internal error: to-be-resumed item contains no data?")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("WARNING: internal error: to-be-resumed item contains no data?"
); }
;
1940 }
1941 fDataStoreP->fPartialItemState=pi_state_none; // consumed now
1942 fDataStoreP->fPITotalSize=0;
1943 fDataStoreP->fPIUnconfirmedSize=0;
1944 // substitution of item data done
1945 // (don't check other items - we have ONE item only, anyway in the current implementation)
1946 return true;
1947 }
1948 // next item
1949 itemListP=itemListP->next;
1950 }
1951 }
1952 // no chunk continuation
1953 return false;
1954} // TSyncOpCommand::checkChunkContinuation
1955
1956
1957// check if split is possible at all
1958bool TSyncOpCommand::canSplit(void)
1959{
1960 // Sync Op commands can be split when remote supports <moredata/> mechanism
1961 return fSessionP->fRemoteSupportsLargeObjects;
1962}
1963
1964
1965// - try to split (e.g. by SyncML 1.1 moredata mechanism) command by reducing
1966// original command by at least aReduceByBytes and generating a second
1967// command containing the rest of the data
1968// Returns NULL if split is not possible or not worth trying in the current situation
1969// (e.g.: only ridiculously small part would remain)
1970TSmlCommand *TSyncOpCommand::splitCommand(sInt32 aReduceByBytes)
1971{
1972 SmlItemListPtr_t *itemListPP;
1973 TSyncOpCommand *remainingDataCmdP=NULL__null;
1974
1975 // nothing remaining so far
1976 SmlItemListPtr_t remainingItems=NULL__null;
1977 // check other conditions
1978 if (!fSyncOpElementP) return NULL__null;
1979 // now find where we should split
1980 do {
1981 // start of list
1982 itemListPP = &(fSyncOpElementP->itemList);
1983 // check if any items
1984 if (*itemListPP==NULL__null) break; // no more items
1985 // find last item
1986 while ((*itemListPP)->next) itemListPP = &((*itemListPP)->next);
1987 // get it's data
1988 SmlItemPtr_t itemP = (*itemListPP)->item;
1989 SmlPcdataPtr_t dataP = itemP->data;
1990 // check if we should split this item
1991 if (
1992 canSplit() && // remote can handle large objects (that is: chunked transfers)
1993 dataP && // there is data
1994 dataP->contentType!=SML_PCDATA_EXTENSION && // it's not an extension
1995 dataP->length > (MemSize_t)aReduceByBytes+MIN_SPLIT_DATA200 // remaining length of first part is large enough to make splitting worth doing now
1996 ) {
1997 // split within this item
1998 // Prepare original item
1999 // - make sure we have meta
2000 if (!itemP->meta)
2001 itemP->meta = newMeta(); // create meta as we haven't got one yet
2002 SmlMetInfMetInfPtr_t metinfP = (SmlMetInfMetInfPtr_t)(itemP->meta->content);
2003 // - set size if this is the first chunk
2004 if (metinfP->size) smlFreePcdata(metinfP->size);
2005 if (fChunkedItemSize==0) {
2006 // first chunk
2007 // - set dataPos to 0
2008 addDataPos(metinfP,0);
2009 // Note: we don't need to buffer when sending the first chunk.
2010 // If we get suspended before the second chunk is being generated, the item will
2011 // start over from beginning anyway (and we can use data from the DB).
2012 fChunkedItemSize=dataP->length;
2013 metinfP->size=newPCDataLong(fChunkedItemSize);
2014 PDEBUGPRINTFX(DBG_PROTO+DBG_HOT,({ if (((0x00000010 +0x00000001) & getDbgMask()) == (0x00000010
+0x00000001)) getDbgLogger()->setNextMask(0x00000010 +0x00000001
).DebugPrintfLastMask ( "Item data too big (%ld) - must be chunked using <MoreData/>, %ld bytes to be sent later"
, (long)fChunkedItemSize, (long)aReduceByBytes ); }
2015 "Item data too big (%ld) - must be chunked using <MoreData/>, %ld bytes to be sent later",{ if (((0x00000010 +0x00000001) & getDbgMask()) == (0x00000010
+0x00000001)) getDbgLogger()->setNextMask(0x00000010 +0x00000001
).DebugPrintfLastMask ( "Item data too big (%ld) - must be chunked using <MoreData/>, %ld bytes to be sent later"
, (long)fChunkedItemSize, (long)aReduceByBytes ); }
2016 (long)fChunkedItemSize,{ if (((0x00000010 +0x00000001) & getDbgMask()) == (0x00000010
+0x00000001)) getDbgLogger()->setNextMask(0x00000010 +0x00000001
).DebugPrintfLastMask ( "Item data too big (%ld) - must be chunked using <MoreData/>, %ld bytes to be sent later"
, (long)fChunkedItemSize, (long)aReduceByBytes ); }
2017 (long)aReduceByBytes{ if (((0x00000010 +0x00000001) & getDbgMask()) == (0x00000010
+0x00000001)) getDbgLogger()->setNextMask(0x00000010 +0x00000001
).DebugPrintfLastMask ( "Item data too big (%ld) - must be chunked using <MoreData/>, %ld bytes to be sent later"
, (long)fChunkedItemSize, (long)aReduceByBytes ); }
2018 )){ if (((0x00000010 +0x00000001) & getDbgMask()) == (0x00000010
+0x00000001)) getDbgLogger()->setNextMask(0x00000010 +0x00000001
).DebugPrintfLastMask ( "Item data too big (%ld) - must be chunked using <MoreData/>, %ld bytes to be sent later"
, (long)fChunkedItemSize, (long)aReduceByBytes ); }
;
2019 #ifdef SYDEBUG2
2020 // %%% should not happen, but I'm not sure it really won't
2021 if (fDataStoreP->fPartialItemState==pi_state_loaded_outgoing) {
2022 PDEBUGPRINTFX(DBG_ERROR,("WARNING - internal error: Splitting new item apparently before previous session's item has been resent")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("WARNING - internal error: Splitting new item apparently before previous session's item has been resent"
); }
;
2023 }
2024 #endif
2025 }
2026 else {
2027 // this item is NOT the first chunk -> save stuff we need to
2028 PDEBUGPRINTFX(DBG_PROTO+DBG_HOT,({ if (((0x00000010 +0x00000001) & getDbgMask()) == (0x00000010
+0x00000001)) getDbgLogger()->setNextMask(0x00000010 +0x00000001
).DebugPrintfLastMask ( "Remaining data still too big (%ld/%ld) - must be chunked again, %ld bytes to be sent later"
, (long)dataP->length, (long)fChunkedItemSize, (long)aReduceByBytes
); }
2029 "Remaining data still too big (%ld/%ld) - must be chunked again, %ld bytes to be sent later",{ if (((0x00000010 +0x00000001) & getDbgMask()) == (0x00000010
+0x00000001)) getDbgLogger()->setNextMask(0x00000010 +0x00000001
).DebugPrintfLastMask ( "Remaining data still too big (%ld/%ld) - must be chunked again, %ld bytes to be sent later"
, (long)dataP->length, (long)fChunkedItemSize, (long)aReduceByBytes
); }
2030 (long)dataP->length,{ if (((0x00000010 +0x00000001) & getDbgMask()) == (0x00000010
+0x00000001)) getDbgLogger()->setNextMask(0x00000010 +0x00000001
).DebugPrintfLastMask ( "Remaining data still too big (%ld/%ld) - must be chunked again, %ld bytes to be sent later"
, (long)dataP->length, (long)fChunkedItemSize, (long)aReduceByBytes
); }
2031 (long)fChunkedItemSize,{ if (((0x00000010 +0x00000001) & getDbgMask()) == (0x00000010
+0x00000001)) getDbgLogger()->setNextMask(0x00000010 +0x00000001
).DebugPrintfLastMask ( "Remaining data still too big (%ld/%ld) - must be chunked again, %ld bytes to be sent later"
, (long)dataP->length, (long)fChunkedItemSize, (long)aReduceByBytes
); }
2032 (long)aReduceByBytes{ if (((0x00000010 +0x00000001) & getDbgMask()) == (0x00000010
+0x00000001)) getDbgLogger()->setNextMask(0x00000010 +0x00000001
).DebugPrintfLastMask ( "Remaining data still too big (%ld/%ld) - must be chunked again, %ld bytes to be sent later"
, (long)dataP->length, (long)fChunkedItemSize, (long)aReduceByBytes
); }
2033 )){ if (((0x00000010 +0x00000001) & getDbgMask()) == (0x00000010
+0x00000001)) getDbgLogger()->setNextMask(0x00000010 +0x00000001
).DebugPrintfLastMask ( "Remaining data still too big (%ld/%ld) - must be chunked again, %ld bytes to be sent later"
, (long)dataP->length, (long)fChunkedItemSize, (long)aReduceByBytes
); }
;
2034 // Note: in this case, the item already has a dataPos - no need to add one here!
2035 // Resume the item in the middle rather than resending it in full.
2036 // IMPORTANT: It is essential not to store the fLastSourceURI/fLastTargetURI
2037 // on the first chunk, as it then probably still contains info from
2038 // the previous session.
2039 saveAsPartialItem(itemP);
2040 }
2041 // - set <moredata>
2042 itemP->flags |= SmlMoreData_f0x0400;
2043 // - create new data for original item (original data is in dataP)
2044 itemP->data = newPCDataStringX(
2045 (uInt8 *)dataP->content, // original data
2046 dataP->contentType==SML_PCDATA_OPAQUE, // opaque if original was opaque
2047 dataP->length-aReduceByBytes // reduced length
2048 );
2049 // Create additional item for next message
2050 // - new item
2051 SmlItemPtr_t nextItemP = newItem();
2052 // - with meta
2053 nextItemP->meta = newMeta();
2054 SmlMetInfMetInfPtr_t nextMetinfP = (SmlMetInfMetInfPtr_t)(nextItemP->meta->content);
2055 // - SyncML 1.1.1: The <Size> element MUST only be specified in the first chunk of the item.
2056 nextMetinfP->size=NULL__null; // no size in remaining items
2057 // - copy other meta
2058 if (metinfP->maxobjsize) nextMetinfP->format=newPCDataString(smlPCDataToCharP(metinfP->maxobjsize)); // We NEED this one of ZIPPED_BINDATA_SUPPORT!
2059 if (metinfP->format) nextMetinfP->format=newPCDataString(smlPCDataToCharP(metinfP->format));
2060 if (metinfP->type) nextMetinfP->type=newPCDataString(smlPCDataToCharP(metinfP->type));
2061 if (metinfP->mark) nextMetinfP->mark=newPCDataString(smlPCDataToCharP(metinfP->mark));
2062 //%%% if we ever decide to carry over EMI here, make sure we don't copy <EMI>dataPos=x</EMI>, as
2063 // addDataPos() code relies on no dataPos being present when called.
2064 //if (metinfP->emi) nextMetinfP->emi=newPCDataString(smlPCDataToCharP(metinfP->emi)); // %%% not needed yet
2065 if (metinfP->version) nextMetinfP->version=newPCDataString(smlPCDataToCharP(metinfP->version));
2066 // - copy source and target
2067 nextItemP->target=newOptLocation(smlSrcTargLocURIToCharP(itemP->target),smlSrcTargLocNameToCharP(itemP->target));
2068 nextItemP->source=newOptLocation(smlSrcTargLocURIToCharP(itemP->source),smlSrcTargLocNameToCharP(itemP->source));
2069 // - copy flags except <moredata>
2070 nextItemP->flags = itemP->flags & ~SmlMoreData_f0x0400;
2071 // - now copy rest of data
2072 nextItemP->data = newPCDataStringX(
2073 (uInt8 *)dataP->content + dataP->length-aReduceByBytes, // original data minus what we have in original item
2074 dataP->contentType==SML_PCDATA_OPAQUE, // opaque if original was opaque
2075 aReduceByBytes // reduced length = remaining bytes
2076 );
2077 // - original data can now be disposed
2078 smlFreePcdata(dataP);
2079 // Add correct data position to the next item now.
2080 addDataPos(nextMetinfP,fChunkedItemSize-aReduceByBytes);
2081 // Now insert new item containing remaining data to beginning of list for next chunk
2082 SmlItemListPtr_t ilP = SML_NEW(SmlItemList_t)((SmlItemList_t*) _smlMalloc(sizeof(SmlItemList_t)));
2083 ilP->next=remainingItems;
2084 ilP->item=nextItemP;
2085 remainingItems=ilP;
2086 // count reduction
2087 aReduceByBytes=0;
2088 // done
2089 break;
2090 }
2091 else {
2092 // Split between items
2093 fChunkedItemSize=0; // no chunking in progress now
2094 // - get last itemlist element
2095 SmlItemListPtr_t ilP = *itemListPP;
2096 // - cut it out of original list
2097 *itemListPP=NULL__null;
2098 // - put it at the BEGINNING of the remaining items list
2099 ilP->next=remainingItems;
2100 remainingItems=ilP;
2101 // - count reduction
2102 aReduceByBytes -= dataP ? dataP->length : 0;
2103 // loop to check second-last item
2104 }
2105 // repeat as long as reduction goal is not met
2106 } while (aReduceByBytes>0);
2107 // check if any items left in original command
2108 if (fSyncOpElementP->itemList == NULL__null) {
2109 // none left in original list, can't split
2110 // - put back remaining list to original item
2111 fSyncOpElementP->itemList = remainingItems;
2112 // - cannot split
2113 return NULL__null;
2114 }
2115 // now create new command containing the remaining items
2116 if (remainingItems) {
2117 if (aReduceByBytes<=0) {
2118 // duplicate meta
2119 SmlPcdataPtr_t splitMetaP = copyMeta(fSyncOpElementP->meta);
2120 // make new command
2121 remainingDataCmdP = new TSyncOpCommand(
2122 fSessionP, // associated session (for callbacks)
2123 fDataStoreP, // datastore from which command originates
2124 fSyncOp, // sync operation (=command type)
2125 splitMetaP // meta for entire command (passing owner)
2126 );
2127 // now pass remaining items to new command
2128 remainingDataCmdP->fSyncOpElementP->itemList = remainingItems;
2129 // next command must know that it part of a chunked transfer
2130 remainingDataCmdP->fChunkedItemSize = fChunkedItemSize;
2131 // original command must know that it must expect a 213 status
2132 fIncompleteData = true;
2133 }
2134 else {
2135 // remaining items not used, delete them
2136 smlFreeItemList(remainingItems);
2137 }
2138 }
2139 // return split-off command
2140 return remainingDataCmdP;
2141} // TSyncOpCommand::splitCommand
2142
2143
2144// - test if completely issued (must be called after issue() and continueIssue())
2145bool TSyncOpCommand::finished(void)
2146{
2147 return
2148 (fOutgoing) || // outgoing commands are always finished (new split mechanism actually splits the command in two separate commands)
2149 (!fOutgoing && fSessionP->fIncompleteDataCommandP!=this); // not part of an incoming chunked data transfer
2150} // TSyncOpCommand::finished
2151
2152
2153// analyze command (but do not yet execute)
2154bool TSyncOpCommand::analyze(TPackageStates aPackageState)
2155{
2156 TSmlCommand::analyze(aPackageState);
2157 // get Command ID and flags
2158 if (fSyncOpElementP) {
2159 StartProcessing(fSyncOpElementP->cmdID,fSyncOpElementP->flags);
2160 return true;
2161 }
2162 else return false; // no proto element, bad command
2163} // TSyncOpCommand::analyze
2164
2165
2166// Adds data chunk from specified command to this (incomplete) command
2167// includes checking if sync op and item source/target match and
2168// checks for size match
2169#define MISSING_END_OF_CHUNK_ERROR223 223 // End of Data for chunked object not received
2170
2171localstatus TSyncOpCommand::AddNextChunk(SmlItemPtr_t aNextChunkItem, TSyncOpCommand *aCmdP)
2172{
2173
2174 SmlItemListPtr_t incompletenode;
2175 SmlItemPtr_t incompleteitem;
2176 SmlPcdataPtr_t newdata;
2177 localstatus sta;
2178
2179 // find last item in this command
2180 incompletenode = fSyncOpElementP->itemList;
2181 if (!incompletenode) return 412; // incomplete command
2182 while (incompletenode && incompletenode->next) incompletenode=incompletenode->next;
2183 incompleteitem = incompletenode->item;
2184 // check for data integrity
2185 if (!incompleteitem) return 412;
2186 if (!incompleteitem->data) return 412;
2187 if (!aNextChunkItem) return 412;
2188 if (!aNextChunkItem->data) return 412;
2189 // check for item compatibility
2190 // - commands must have same sync op
2191 if (getSyncOp() != aCmdP->getSyncOp())
2192 goto missingeoc; // not a status - will be converted to alert
2193 // - must have same source and target URI
2194 if (
2195 strcmp(smlSrcTargLocURIToCharP(incompleteitem->source),smlSrcTargLocURIToCharP(aNextChunkItem->source))!=0 ||
2196 strcmp(smlSrcTargLocURIToCharP(incompleteitem->target),smlSrcTargLocURIToCharP(aNextChunkItem->target))!=0
2197 )
2198 goto missingeoc; // not a status - will be converted to alert
2199 // - must have same PCData type and not extension
2200 if (
2201 incompleteitem->data->contentType != aNextChunkItem->data->contentType ||
2202 aNextChunkItem->data->contentType == SML_PCDATA_EXTENSION
2203 )
2204 return 400; // originator error, bad request
2205 // append data from next chunk to incomplete item
2206 newdata = SML_NEW(SmlPcdata_t)((SmlPcdata_t*) _smlMalloc(sizeof(SmlPcdata_t)));
2207 // - same content type as previous data had
2208 newdata->contentType = incompleteitem->data->contentType;
2209 newdata->contentType = incompleteitem->data->contentType;
2210 // - set new size
2211 newdata->length = incompleteitem->data->length + aNextChunkItem->data->length;
2212 // - remember size of chunk we're adding now in the incomplete command
2213 aCmdP->fLastChunkSize = aNextChunkItem->data->length;
2214 // - allocate new data for updated item (including an extra NUL terminator)
2215 newdata->content=smlLibMalloc(newdata->length+1);
2216 if (newdata->content==NULL__null)
2217 return 413; // request entity too large
2218 // - copy existing content
2219 smlLibMemcpy(newdata->content,incompleteitem->data->content,incompleteitem->data->length);
2220 // - add new chunk
2221 smlLibMemcpy((uInt8 *)newdata->content+incompleteitem->data->length,aNextChunkItem->data->content,aNextChunkItem->data->length);
2222 // - set the NUL terminator in case item is parsed as C string
2223 *(((uInt8 *)newdata->content)+newdata->length)=0;
2224 // - free old data in item
2225 smlFreePcdata(incompleteitem->data);
2226 // - insert updated data
2227 incompleteitem->data = newdata;
2228 // Now check if we are complete
2229 if ((aNextChunkItem->flags & SmlMoreData_f0x0400) == 0) {
2230 // end of chunk, verify size
2231 // - get total size from meta (of original item)
2232 SmlMetInfMetInfPtr_t metaP = smlPCDataToMetInfP(incompleteitem->meta);
2233 if (!metaP || !metaP->size) {
2234 // item has no meta or no meta-size, so size must be in meta of command
2235 metaP = smlPCDataToMetInfP(fSyncOpElementP->meta);
2236 if (!metaP) {
2237 PDEBUGPRINTFX(DBG_ERROR,("Chunked item has no meta -> no size found")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("Chunked item has no meta -> no size found"
); }
;
2238 return 424; // no meta: Size mismatch
2239 }
2240 }
2241 sInt32 expectedSize;
2242 if (!smlPCDataToLong(metaP->size, expectedSize)) {
2243 PDEBUGPRINTFX(DBG_ERROR,("Chunked item had no or invalid meta <size> in first chunk")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("Chunked item had no or invalid meta <size> in first chunk"
); }
;
2244 return 424; // bad size string: size mismatch
2245 }
2246 // - check for size match
2247 if (incompleteitem->data->length != (MemSize_t)expectedSize) {
2248 // check if size mismatch could be due to duplicate transmit of unconfirmed data
2249 if (fUnconfirmedSize == uInt32(incompleteitem->data->length - expectedSize)) {
2250 // size mismatch is exactly what could be caused by duplicate transmit
2251 PDEBUGPRINTFX(DBG_PROTO+DBG_HOT,({ if (((0x00000010 +0x00000001) & getDbgMask()) == (0x00000010
+0x00000001)) getDbgLogger()->setNextMask(0x00000010 +0x00000001
).DebugPrintfLastMask ( "Detected duplicate chunk in reassembled item due to resume without dataPos (%ld bytes at %ld) -> adjusting"
, (long)fUnconfirmedSize, (long)fStoredSize-fUnconfirmedSize )
; }
2252 "Detected duplicate chunk in reassembled item due to resume without dataPos (%ld bytes at %ld) -> adjusting",{ if (((0x00000010 +0x00000001) & getDbgMask()) == (0x00000010
+0x00000001)) getDbgLogger()->setNextMask(0x00000010 +0x00000001
).DebugPrintfLastMask ( "Detected duplicate chunk in reassembled item due to resume without dataPos (%ld bytes at %ld) -> adjusting"
, (long)fUnconfirmedSize, (long)fStoredSize-fUnconfirmedSize )
; }
2253 (long)fUnconfirmedSize,{ if (((0x00000010 +0x00000001) & getDbgMask()) == (0x00000010
+0x00000001)) getDbgLogger()->setNextMask(0x00000010 +0x00000001
).DebugPrintfLastMask ( "Detected duplicate chunk in reassembled item due to resume without dataPos (%ld bytes at %ld) -> adjusting"
, (long)fUnconfirmedSize, (long)fStoredSize-fUnconfirmedSize )
; }
2254 (long)fStoredSize-fUnconfirmedSize{ if (((0x00000010 +0x00000001) & getDbgMask()) == (0x00000010
+0x00000001)) getDbgLogger()->setNextMask(0x00000010 +0x00000001
).DebugPrintfLastMask ( "Detected duplicate chunk in reassembled item due to resume without dataPos (%ld bytes at %ld) -> adjusting"
, (long)fUnconfirmedSize, (long)fStoredSize-fUnconfirmedSize )
; }
2255 )){ if (((0x00000010 +0x00000001) & getDbgMask()) == (0x00000010
+0x00000001)) getDbgLogger()->setNextMask(0x00000010 +0x00000001
).DebugPrintfLastMask ( "Detected duplicate chunk in reassembled item due to resume without dataPos (%ld bytes at %ld) -> adjusting"
, (long)fUnconfirmedSize, (long)fStoredSize-fUnconfirmedSize )
; }
;
2256 // - cut out duplicate
2257 smlLibMemmove(
2258 ((uInt8 *)incompleteitem->data->content+fStoredSize-fUnconfirmedSize), // to end of confirmed data
2259 ((uInt8 *)incompleteitem->data->content+fStoredSize), // from end of stored data
2260 incompleteitem->data->length-fStoredSize // everything between end of stored data and end of item
2261 );
2262 incompleteitem->data->length = expectedSize; // adjust length
2263 *((uInt8 *)incompleteitem->data->content+expectedSize)=0; // add new safety terminator
2264 fUnconfirmedSize=0; // no data unconfirmed any more
2265 }
2266 else {
2267 PDEBUGPRINTFX(DBG_ERROR,({ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "Chunked item has wrong size (%ld, expected=%ld) after reassembly"
, (long)incompleteitem->data->length, (long)expectedSize
); }
2268 "Chunked item has wrong size (%ld, expected=%ld) after reassembly",{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "Chunked item has wrong size (%ld, expected=%ld) after reassembly"
, (long)incompleteitem->data->length, (long)expectedSize
); }
2269 (long)incompleteitem->data->length,{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "Chunked item has wrong size (%ld, expected=%ld) after reassembly"
, (long)incompleteitem->data->length, (long)expectedSize
); }
2270 (long)expectedSize{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "Chunked item has wrong size (%ld, expected=%ld) after reassembly"
, (long)incompleteitem->data->length, (long)expectedSize
); }
2271 )){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "Chunked item has wrong size (%ld, expected=%ld) after reassembly"
, (long)incompleteitem->data->length, (long)expectedSize
); }
;
2272 return 424; // size mismatch
2273 }
2274 }
2275 // successfully reassembled
2276 sta=0;
2277 }
2278 else {
2279 // not yet completely reassembled
2280 sta=213;
2281 }
2282 // get MsgID and CmdID from added chunk's commnd
2283 fCmdID = aCmdP->getCmdID();
2284 fMsgID = aCmdP->getMsgID();
2285 // copy actual cmdID tag (to make sure we don't get the wrong CmdID when re-processing the command later)
2286 smlFreePcdata(fSyncOpElementP->cmdID); // ged rid of current ID
2287 fSyncOpElementP->cmdID = smlPcdataDup(aCmdP->fSyncOpElementP->cmdID); // copy ID from last added chunk
2288 // return status code
2289 return sta;
2290missingeoc:
2291 // missing end of chunk
2292 TAlertCommand *alertCmdP = new TAlertCommand(fSessionP, NULL__null, (uInt16)223);
2293 SmlItemPtr_t alertItemP = newItem();
2294 alertItemP->target=newOptLocation(smlSrcTargLocURIToCharP(incompleteitem->source));
2295 alertItemP->source=newOptLocation(smlSrcTargLocURIToCharP(incompleteitem->target));
2296 alertCmdP->addItem(alertItemP);
2297 // issue the alert
2298 fSessionP->issueRootPtr(alertCmdP);
2299 // signal failure of reassembling chunked item
2300 return MISSING_END_OF_CHUNK_ERROR223;
2301} // TSyncOpCommand::AddNextChunk
2302
2303
2304// SyncOp commands can execute out of order except when they
2305// contain chunked items, because then we would have to issue
2306// a 213 Status immediately, which would violate the ordering
2307// of Status replies.
2308bool TSyncOpCommand::canExecuteOutOfOrder()
2309{
2310 SmlItemListPtr_t *itemnodePP=&(fSyncOpElementP->itemList);
2311 while (*itemnodePP) {
2312 SmlItemListPtr_t thisitemnode = *itemnodePP;
2313 if (thisitemnode->item &&
2314 thisitemnode->item->flags & SmlMoreData_f0x0400) {
2315 return false;
2316 }
2317 itemnodePP = &(thisitemnode->next);
2318 }
2319 return true;
2320}
2321
2322// execute command (perform real actions, generate status)
2323// returns true if command has executed and can be deleted
2324bool TSyncOpCommand::execute(void)
2325{
2326 TStatusCommand *statusCmdP=NULL__null;
2327 SmlItemListPtr_t *itemnodePP, thisitemnode;
2328 localstatus sta;
2329 TSyncOpCommand *incompleteCmdP;
2330 bool queueforlater,processitem;
2331 bool nostatus;
2332 SmlItemListPtr_t tobequeueditems=NULL__null;
2333
2334 SYSYNC_TRYtry {
2335 // get datastore pointer if we do not have one yet
2336 if (fDataStoreP==NULL__null) {
2337 // in case we did not get the pointer at creation - that is, when the enclosing
2338 // <sync> was delayed - we must now get datastore as set by the current <sync> command
2339 fDataStoreP = fSessionP->fLocalSyncDatastoreP;
2340 if (fDataStoreP==NULL__null) {
2341 statusCmdP=newStatusCommand(404); // no datastore, we can't process items for it
2342 ISSUE_COMMAND_ROOT(fSessionP,statusCmdP){ TSmlCommand* p=statusCmdP; statusCmdP=__null; fSessionP->
issueRootPtr(p); }
;
2343 return true; // command executed
2344 }
2345 }
2346 // get command meta if any
2347 SmlMetInfMetInfPtr_t cmdmetaP=smlPCDataToMetInfP(fSyncOpElementP->meta);
2348 // process items
2349 DEBUGPRINTFX(DBG_HOT,("command started processing")){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("command started processing"
); }
;
2350 itemnodePP=&(fSyncOpElementP->itemList);
2351 while (*itemnodePP) {
2352 queueforlater=false; // do no queue by default
2353 processitem=true; // process by default
2354 nostatus=false; // set to true if someone else is responsible for updating fLastItemStatus
2355 thisitemnode = *itemnodePP;
2356 // no result nor status so far
2357 statusCmdP=NULL__null;
2358 // check for NULL item
2359 if (!thisitemnode->item) {
2360 PDEBUGPRINTFX(DBG_ERROR,("command with NULL item")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("command with NULL item"
); }
;
2361 statusCmdP=newStatusCommand(400); // protocol error
2362 ISSUE_COMMAND_ROOT(fSessionP,statusCmdP){ TSmlCommand* p=statusCmdP; statusCmdP=__null; fSessionP->
issueRootPtr(p); }
;
2363 return true; // command executed
2364 }
2365 // check if we are resuming a partially transmitted item (but MUST have data)
2366 if (
2367 fSessionP->fIncompleteDataCommandP==NULL__null &&
2368 thisitemnode->item->data && // item must have data
2369 fDataStoreP->fPartialItemState==pi_state_loaded_incoming &&
2370 strcmp(smlSrcTargLocURIToCharP(thisitemnode->item->source),fDataStoreP->fLastSourceURI.c_str())==0 &&
2371 strcmp(smlSrcTargLocURIToCharP(thisitemnode->item->target),fDataStoreP->fLastTargetURI.c_str())==0
2372 ) {
2373 // this is the last item sent in the previously suspended session
2374 if (fDataStoreP->fPIStoredSize==0) {
2375 // No item was left only partially received from the suspended session.
2376 // But we must handle the special case where the final status of the last item sent
2377 // in the suspended session did not reach the recipient, so we now see the last chunk again.
2378 // In this case, simply re-issue the status and ignore the contents
2379 if (fDataStoreP->fLastItemStatus) {
2380 // item already processed, just repeat sending the status
2381 PDEBUGPRINTFX(DBG_PROTO,("Received last chunk for already processed item -> just resending status %hd",fDataStoreP->fLastItemStatus)){ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ("Received last chunk for already processed item -> just resending status %hd"
,fDataStoreP->fLastItemStatus); }
;
2382 statusCmdP = newStatusCommand(fDataStoreP->fLastItemStatus);
2383 processitem=false; // do not further process the item, just status
2384 fDataStoreP->fPartialItemState=pi_state_none; // chunked transfer from last session finally done
2385 }
2386 }
2387 else {
2388 // we have a partially received item left from the suspended session
2389 // continue it
2390 PDEBUGPRINTFX(DBG_PROTO+DBG_HOT,({ if (((0x00000010 +0x00000001) & getDbgMask()) == (0x00000010
+0x00000001)) getDbgLogger()->setNextMask(0x00000010 +0x00000001
).DebugPrintfLastMask ( "Resuming receiving chunked item Source='%s', Target='%s'"
, fDataStoreP->fLastSourceURI.c_str(), fDataStoreP->fLastTargetURI
.c_str() ); }
2391 "Resuming receiving chunked item Source='%s', Target='%s'",{ if (((0x00000010 +0x00000001) & getDbgMask()) == (0x00000010
+0x00000001)) getDbgLogger()->setNextMask(0x00000010 +0x00000001
).DebugPrintfLastMask ( "Resuming receiving chunked item Source='%s', Target='%s'"
, fDataStoreP->fLastSourceURI.c_str(), fDataStoreP->fLastTargetURI
.c_str() ); }
2392 fDataStoreP->fLastSourceURI.c_str(),{ if (((0x00000010 +0x00000001) & getDbgMask()) == (0x00000010
+0x00000001)) getDbgLogger()->setNextMask(0x00000010 +0x00000001
).DebugPrintfLastMask ( "Resuming receiving chunked item Source='%s', Target='%s'"
, fDataStoreP->fLastSourceURI.c_str(), fDataStoreP->fLastTargetURI
.c_str() ); }
2393 fDataStoreP->fLastTargetURI.c_str(){ if (((0x00000010 +0x00000001) & getDbgMask()) == (0x00000010
+0x00000001)) getDbgLogger()->setNextMask(0x00000010 +0x00000001
).DebugPrintfLastMask ( "Resuming receiving chunked item Source='%s', Target='%s'"
, fDataStoreP->fLastSourceURI.c_str(), fDataStoreP->fLastTargetURI
.c_str() ); }
2394 )){ if (((0x00000010 +0x00000001) & getDbgMask()) == (0x00000010
+0x00000001)) getDbgLogger()->setNextMask(0x00000010 +0x00000001
).DebugPrintfLastMask ( "Resuming receiving chunked item Source='%s', Target='%s'"
, fDataStoreP->fLastSourceURI.c_str(), fDataStoreP->fLastTargetURI
.c_str() ); }
;
2395 // simulate a meta size from suspended session's saved item size
2396 // - create meta if none there
2397 if (!thisitemnode->item->meta)
2398 thisitemnode->item->meta = newMeta();
2399 // - now check/generate meta size
2400 SmlMetInfMetInfPtr_t metinfP = (SmlMetInfMetInfPtr_t)(thisitemnode->item->meta->content);
2401 if (metinfP->size) {
2402 #ifdef __MWERKS__
2403 #warning "%%% maybe use presence of meta size to know that this is NOT resuming, that is as an implicit dataPos=0"
2404 #endif
2405 /* if I understand correctly, size MUST NOT be present on any but the first chunk.
2406 If that's correct, we could discard the saved partial item from a previous session
2407 in case we see a size (because this would mean the item is retransmitted as a whole
2408 and sender does not support resuming a partial item */
2409 // item has meta size, check if correct
2410 uInt32 thissize;
2411 if (
2412 !smlPCDataToULong(metinfP->size, thissize) ||
2413 thissize!=fDataStoreP->fPITotalSize
2414 )
2415 {
2416 PDEBUGPRINTFX(DBG_ERROR,({ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "Resumed item size does not match (expected=%ld, found=%ld)"
, (long)fDataStoreP->fPITotalSize, (long)thissize ); }
2417 "Resumed item size does not match (expected=%ld, found=%ld)",{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "Resumed item size does not match (expected=%ld, found=%ld)"
, (long)fDataStoreP->fPITotalSize, (long)thissize ); }
2418 (long)fDataStoreP->fPITotalSize,{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "Resumed item size does not match (expected=%ld, found=%ld)"
, (long)fDataStoreP->fPITotalSize, (long)thissize ); }
2419 (long)thissize{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "Resumed item size does not match (expected=%ld, found=%ld)"
, (long)fDataStoreP->fPITotalSize, (long)thissize ); }
2420 )){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "Resumed item size does not match (expected=%ld, found=%ld)"
, (long)fDataStoreP->fPITotalSize, (long)thissize ); }
;
2421 statusCmdP = newStatusCommand(424);
2422 processitem=false; // do not further process the item
2423 }
2424 }
2425 else {
2426 // item has no meta size, create it now
2427 metinfP->size=newPCDataLong(fDataStoreP->fPITotalSize);
2428 }
2429 SmlPcdataPtr_t newdata=NULL__null;
2430 uInt32 dataPos=0;
2431 if (processitem) {
2432 // save sizes confirmed/unconfirmed data in this command object
2433 // (for possible reassembly adjustment when command is complete)
2434 fUnconfirmedSize=fDataStoreP->fPIUnconfirmedSize;
2435 fStoredSize=fDataStoreP->fPIStoredSize;
2436 // Determine Data position
2437 // - check if we have it in EMI (Synthesis-Oracle enhancement)
2438 // <EMI xmlns='syncml:metinf'>datapos=NUM</EMI>
2439 SmlPcdataListPtr_t emiP = metinfP->emi; // start with item meta EMI
2440 bool foundDataPos=false;
2441 for (uInt16 i=0; i<2; i++) {
2442 while (emiP) {
2443 if (emiP->data) {
2444 const char *p = smlPCDataToCharP(emiP->data);
2445 if (strucmp(p,"datapos=",8)==0) {
2446 // correct lead-in, get number now
2447 if (StrToULong(p+8,dataPos)>0) {
2448 PDEBUGPRINTFX(DBG_PROTO+DBG_DETAILS,("found <meta><EMI>datapos=%ld",(long)dataPos)){ if (((0x00000010 +0x40000000) & getDbgMask()) == (0x00000010
+0x40000000)) getDbgLogger()->setNextMask(0x00000010 +0x40000000
).DebugPrintfLastMask ("found <meta><EMI>datapos=%ld"
,(long)dataPos); }
;
2449 foundDataPos=true; // found dataPos
2450 break;
2451 }
2452 else {
2453 PDEBUGPRINTFX(DBG_ERROR,("invalid number in <meta><EMI>datapos, ignoring it")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("invalid number in <meta><EMI>datapos, ignoring it"
); }
;
2454 }
2455 }
2456 }
2457 // check next
2458 emiP=emiP->next;
2459 }
2460 // done if found
2461 if (foundDataPos) break;
2462 // try with cmd meta
2463 if (!cmdmetaP) break; // we don't have a command meta, no point to search
2464 emiP = cmdmetaP->emi; // cmd meta EMI
2465 }
2466 if (foundDataPos) {
2467 // we have a dataPos value
2468 // - no unconfirmed size any more for this item (but we still need the datastore-level vars
2469 // below to do the copying
2470 fUnconfirmedSize=0;
2471 // - confirmed size is the data position now
2472 fStoredSize=dataPos;
2473 }
2474 else {
2475 // without known dataPos, we assume all received data confirmed for now
2476 // and will adjust at end of item if needed
2477 dataPos = fDataStoreP->fPIStoredSize;
2478 }
2479 // - check integrity
2480 if (dataPos>fDataStoreP->fPIStoredSize) {
2481 PDEBUGPRINTFX(DBG_ERROR,({ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "Data position invalid (max allowed=%ld, found=%ld)"
, (long)fDataStoreP->fPIStoredSize, (long)dataPos ); }
2482 "Data position invalid (max allowed=%ld, found=%ld)",{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "Data position invalid (max allowed=%ld, found=%ld)"
, (long)fDataStoreP->fPIStoredSize, (long)dataPos ); }
2483 (long)fDataStoreP->fPIStoredSize,{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "Data position invalid (max allowed=%ld, found=%ld)"
, (long)fDataStoreP->fPIStoredSize, (long)dataPos ); }
2484 (long)dataPos{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "Data position invalid (max allowed=%ld, found=%ld)"
, (long)fDataStoreP->fPIStoredSize, (long)dataPos ); }
2485 )){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "Data position invalid (max allowed=%ld, found=%ld)"
, (long)fDataStoreP->fPIStoredSize, (long)dataPos ); }
;
2486 statusCmdP = newStatusCommand(412);
2487 processitem=false; // do not further process the item
2488 }
2489 if (processitem) {
2490 // - combine new and old data
2491 newdata = SML_NEW(SmlPcdata_t)((SmlPcdata_t*) _smlMalloc(sizeof(SmlPcdata_t)));
2492 // - same content type
2493 newdata->contentType = thisitemnode->item->data->contentType;
2494 // - set new size
2495 newdata->length = dataPos + thisitemnode->item->data->length;
2496 // - allocate new data for updated item (including an extra NUL terminator)
2497 newdata->content=smlLibMalloc(newdata->length+1);
2498 if (newdata->content==NULL__null) {
2499 statusCmdP = newStatusCommand(413);
2500 processitem=false; // do not further process the item
2501 }
2502 }
2503 }
2504 if (processitem) {
2505 // copy already received content up to dataPos
2506 smlLibMemcpy(newdata->content,fDataStoreP->fPIStoredDataP,dataPos);
2507 // forget data stored at DS level
2508 fDataStoreP->fPIStoredSize=0;
2509 if (fDataStoreP->fPIStoredDataP) {
2510 // only free if not owned by an item
2511 if (fDataStoreP->fPIStoredDataAllocated)
2512 smlLibFree(fDataStoreP->fPIStoredDataP);
2513 }
2514 fDataStoreP->fPIStoredDataP=NULL__null;
2515 // append content just received in this item
2516 smlLibMemcpy((uInt8 *)newdata->content+dataPos,thisitemnode->item->data->content,thisitemnode->item->data->length);
2517 // - set the NUL terminator in case item is parsed as C string
2518 *(((uInt8 *)newdata->content)+newdata->length)=0;
2519 // - free old data in item
2520 smlFreePcdata(thisitemnode->item->data);
2521 // - insert new data
2522 thisitemnode->item->data = newdata;
2523 }
2524 /* No, we need to keep pi_state_loaded_incoming until we get
2525 // Finished processing left-overs from last session
2526 fDataStoreP->fPartialItemState=pi_state_none;
2527 */
2528 // Now we can treat this as if it was the first (or only) chunk of a non-resumed item
2529 } // if we have partial data received in last session
2530 } // if item is the same as last item in suspended session
2531 if (processitem) {
2532 processitem=false; // only process further if we detect complete data
Value stored to 'processitem' is never read
2533 // check if this item is complete (not chunked by <moredata>)
2534 if (thisitemnode->item->flags & SmlMoreData_f0x0400) {
2535 // no, it's only a chunk
2536 if (thisitemnode->item->data==NULL__null) {
2537 PDEBUGPRINTFX(DBG_ERROR,("Chunked item has no <data>")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("Chunked item has no <data>"
); }
;
2538 statusCmdP->setStatusCode(412);
2539 // do not further process the command, issue status and exit
2540 ISSUE_COMMAND_ROOT(fSessionP,statusCmdP){ TSmlCommand* p=statusCmdP; statusCmdP=__null; fSessionP->
issueRootPtr(p); }
;
2541 return true; // processed (with error)
2542 }
2543 // - return appropriate status
2544 statusCmdP = newStatusCommand(213); // chunked item accepted and buffered
2545 // - no items may follow the chunked one
2546 if (thisitemnode->next) {
2547 PDEBUGPRINTFX(DBG_ERROR,("Chunked item had additional items after the chunked one")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("Chunked item had additional items after the chunked one"
); }
;
2548 statusCmdP->setStatusCode(400);
2549 // do not further process the command, issue status and exit
2550 ISSUE_COMMAND_ROOT(fSessionP,statusCmdP){ TSmlCommand* p=statusCmdP; statusCmdP=__null; fSessionP->
issueRootPtr(p); }
;
2551 return true; // processed (with error)
2552 }
2553 if (fSessionP->fIncompleteDataCommandP==NULL__null) {
2554 // This is the first chunk, save this as the original command (as it contains all meta)
2555 fSessionP->fIncompleteDataCommandP = this;
2556 // make sure that already executed items will not get saved
2557 *itemnodePP=NULL__null; // disconnect not-yet-executed items from executed ones
2558 smlFreeItemList(fSyncOpElementP->itemList); // free executed items
2559 fSyncOpElementP->itemList = thisitemnode; // put not-yet-executed, partial item into command
2560 // make sure moredata flag is not set on reassembled item
2561 thisitemnode->item->flags &= ~SmlMoreData_f0x0400;
2562 // save size of the chunk
2563 fLastChunkSize=thisitemnode->item->data->length;
2564 }
2565 else {
2566 // this is a chunk in the middle, combine its data
2567 // with the already buffered incomplete command
2568 // and update MsgID/CmdID. If source and target do not match,
2569 // statusCmdP will set to appropriate error code
2570 sta=fSessionP->fIncompleteDataCommandP->AddNextChunk(thisitemnode->item,this);
2571 if (sta) statusCmdP->setStatusCode(sta); // set error if any
2572 }
2573 PDEBUGPRINTFX(DBG_PROTO+DBG_HOT,("<Moredata/> set: Chunk (%ld bytes) received (plus possible carry over from suspend) and buffered",(long)fLastChunkSize)){ if (((0x00000010 +0x00000001) & getDbgMask()) == (0x00000010
+0x00000001)) getDbgLogger()->setNextMask(0x00000010 +0x00000001
).DebugPrintfLastMask ("<Moredata/> set: Chunk (%ld bytes) received (plus possible carry over from suspend) and buffered"
,(long)fLastChunkSize); }
;
2574 }
2575 else {
2576 // Complete item or end of chunked item
2577 processitem=true;
2578 incompleteCmdP = fSessionP->fIncompleteDataCommandP;
2579 if (incompleteCmdP) {
2580 // end of chunked item, add final chunk and check for errors
2581 sta=incompleteCmdP->AddNextChunk(thisitemnode->item,this);
2582 if (sta==MISSING_END_OF_CHUNK_ERROR223) {
2583 // command should have been end of chunked data, but wasn't.
2584 // Alert 223 is already issued.
2585 // - dispose of failed incomplete command
2586 delete incompleteCmdP;
2587 fSessionP->fIncompleteDataCommandP=NULL__null;
2588 // - process item as new command
2589 }
2590 else if (sta==0) {
2591 // successfully reassembled command, execute it now
2592 PDEBUGPRINTFX(DBG_PROTO+DBG_HOT,("Last Chunk received (%ld bytes), item is reassembled",(long)fLastChunkSize)){ if (((0x00000010 +0x00000001) & getDbgMask()) == (0x00000010
+0x00000001)) getDbgLogger()->setNextMask(0x00000010 +0x00000001
).DebugPrintfLastMask ("Last Chunk received (%ld bytes), item is reassembled"
,(long)fLastChunkSize); }
;
2593 // - first remove global link to it to avoid recursion
2594 fSessionP->fIncompleteDataCommandP=NULL__null;
2595 // - execute now (and pass ownership)
2596 // issues appropriate statuses, so we don't need to deal with it;
2597 // in fact, we must not touch fLastItemStatus because we don't
2598 // know the status
2599 nostatus=true;
2600 fSessionP->process(incompleteCmdP);
2601 // - this item is processed now, continue in loop if there are more items
2602 processitem=false; // do not process the item normally
2603 // Note: statusCmdP is NULL here, so no extra status will be issued for the
2604 // item (process() should have already caused appropriate statuses to
2605 // be generated.
2606 }
2607 else {
2608 // some error with this item, generate status
2609 statusCmdP = newStatusCommand(sta);
2610 PDEBUGPRINTFX(DBG_ERROR,("Adding next chunk to item failed with status=%hd",sta)){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("Adding next chunk to item failed with status=%hd"
,sta); }
;
2611 // - dispose of failed incomplete command
2612 delete incompleteCmdP;
2613 fSessionP->fIncompleteDataCommandP=NULL__null;
2614 // do not process anything any further
2615 processitem=false; // do not process the item normally
2616 fDataStoreP->fLocalItemsError++; // count this as an error
2617 }
2618 }
2619 else {
2620 // save size of the chunk (if item has ANY data at all)
2621 fLastChunkSize=thisitemnode->item->data ? thisitemnode->item->data->length : 0;
2622 }
2623 if (processitem) {
2624 // - get remote and local IDs of item
2625 const char *remoteID=smlSrcTargLocURIToCharP(thisitemnode->item->source);
2626 const char *localID=smlSrcTargLocURIToCharP(thisitemnode->item->target);
2627 // prepare OK status for item
2628 statusCmdP = newStatusCommand(200);
2629 // let session process the item
2630 PDEBUGPRINTFX(DBG_PROTO+DBG_HOT,({ if (((0x00000010 +0x00000001) & getDbgMask()) == (0x00000010
+0x00000001)) getDbgLogger()->setNextMask(0x00000010 +0x00000001
).DebugPrintfLastMask ( "Item (syncop: %s) started processing, remoteID='%s', localID='%s'"
, SyncOpNames[(sInt16)fSyncOp], remoteID, localID ); }
2631 "Item (syncop: %s) started processing, remoteID='%s', localID='%s'",{ if (((0x00000010 +0x00000001) & getDbgMask()) == (0x00000010
+0x00000001)) getDbgLogger()->setNextMask(0x00000010 +0x00000001
).DebugPrintfLastMask ( "Item (syncop: %s) started processing, remoteID='%s', localID='%s'"
, SyncOpNames[(sInt16)fSyncOp], remoteID, localID ); }
2632 SyncOpNames[(sInt16)fSyncOp],{ if (((0x00000010 +0x00000001) & getDbgMask()) == (0x00000010
+0x00000001)) getDbgLogger()->setNextMask(0x00000010 +0x00000001
).DebugPrintfLastMask ( "Item (syncop: %s) started processing, remoteID='%s', localID='%s'"
, SyncOpNames[(sInt16)fSyncOp], remoteID, localID ); }
2633 remoteID,{ if (((0x00000010 +0x00000001) & getDbgMask()) == (0x00000010
+0x00000001)) getDbgLogger()->setNextMask(0x00000010 +0x00000001
).DebugPrintfLastMask ( "Item (syncop: %s) started processing, remoteID='%s', localID='%s'"
, SyncOpNames[(sInt16)fSyncOp], remoteID, localID ); }
2634 localID{ if (((0x00000010 +0x00000001) & getDbgMask()) == (0x00000010
+0x00000001)) getDbgLogger()->setNextMask(0x00000010 +0x00000001
).DebugPrintfLastMask ( "Item (syncop: %s) started processing, remoteID='%s', localID='%s'"
, SyncOpNames[(sInt16)fSyncOp], remoteID, localID ); }
2635 )){ if (((0x00000010 +0x00000001) & getDbgMask()) == (0x00000010
+0x00000001)) getDbgLogger()->setNextMask(0x00000010 +0x00000001
).DebugPrintfLastMask ( "Item (syncop: %s) started processing, remoteID='%s', localID='%s'"
, SyncOpNames[(sInt16)fSyncOp], remoteID, localID ); }
;
2636 queueforlater=false;
2637 if (fSessionP->processSyncOpItem(
2638 fSyncOp, // the operation
2639 thisitemnode->item, // the item to be processed
2640 cmdmetaP, // command-wide meta, if any
2641 fDataStoreP, // related datastore pointer
2642 *statusCmdP, // pre-set 200 status, can be modified in case of errors
2643 queueforlater // set if processing of item must be done later
2644 )) {
2645 // fully ok (no internal change of requested operations or
2646 // silent acceptance of deleting non-existant item)
2647 }
2648 else {
2649 // Internal processing of items showed some irregularity, but
2650 // status to remote peer can still be ok (for example when trying
2651 // to delete non-existant item in datastore with incomplete rollbacks,
2652 // processSyncOpItem() will return false, but Status=200.
2653 PDEBUGPRINTFX(DBG_PROTO,({ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ( "Irregularity in execution of item, status=%hd"
, statusCmdP->getStatusCode() ); }
2654 "Irregularity in execution of item, status=%hd",{ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ( "Irregularity in execution of item, status=%hd"
, statusCmdP->getStatusCode() ); }
2655 statusCmdP->getStatusCode(){ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ( "Irregularity in execution of item, status=%hd"
, statusCmdP->getStatusCode() ); }
2656 )){ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ( "Irregularity in execution of item, status=%hd"
, statusCmdP->getStatusCode() ); }
;
2657 }
2658 } // if processitem
2659 } // if complete item
2660 } // if processitem
2661 // now generate status or queue for later
2662 // - remember as last item for possible suspend and resume
2663 fDataStoreP->fLastSourceURI = smlSrcTargLocURIToCharP(thisitemnode->item->source);
2664 fDataStoreP->fLastTargetURI = smlSrcTargLocURIToCharP(thisitemnode->item->target);
2665 if (queueforlater) {
2666 PDEBUGPRINTFX(DBG_PROTO,({ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ( "Item could not be processed completely now -> will be queued for later processing"
); }
2667 "Item could not be processed completely now -> will be queued for later processing"{ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ( "Item could not be processed completely now -> will be queued for later processing"
); }
2668 )){ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ( "Item could not be processed completely now -> will be queued for later processing"
); }
;
2669 // item processing could not complete, we must queue this and all other items
2670 // in this command for later processing. However, re-assembling chunked
2671 // items must proceed as normal.
2672 fDataStoreP->fLastItemStatus = 0; // no status sent yet
2673 // Therefore, we move this item from the original list to a list of to-be-queued items
2674 addItemToList(
2675 thisitemnode->item, // the item
2676 &tobequeueditems // place pointer to next node here
2677 );
2678 // cut item out of original list to make sure it does not get disposed with it
2679 // - itemnodePP points to pointer to list start or a "next" pointer in a node
2680 // (which in turn points to thisitemnode). Now let it point to the next item node.
2681 // - this also advance processing to the next item
2682 *itemnodePP = thisitemnode->next;
2683 // - dispose of the item node itself
2684 thisitemnode->next=NULL__null; // disconnect subsequent nodes
2685 thisitemnode->item=NULL__null; // disconnect item (which is now in tobequeueditems list)
2686 smlFreeItemList(thisitemnode); // dispose of node
2687 // - and the status command
2688 delete statusCmdP;
2689 statusCmdP = NULL__null;
2690 }
2691 else {
2692 // count incoming net data
2693 if (thisitemnode->item->data) {
2694 fDataStoreP->fIncomingDataBytes+=thisitemnode->item->data->length;
2695 }
2696 // item processed
2697 // - remember status (final only) for possible suspend and resume
2698 sta= statusCmdP ? statusCmdP->getStatusCode() : 0;
2699 if (!nostatus && sta!=213) {
2700 // final status received, save it for possible resend
2701 fDataStoreP->fLastItemStatus = sta;
2702 // but forget data stored at DS level
2703 fDataStoreP->fPIStoredSize=0;
2704 if (fDataStoreP->fPIStoredDataP) {
2705 // only free if not owned by an item
2706 if (fDataStoreP->fPIStoredDataAllocated)
2707 smlLibFree(fDataStoreP->fPIStoredDataP);
2708 }
2709 fDataStoreP->fPIStoredDataP=NULL__null;
2710 // make sure it gets saved
2711 fDataStoreP->fPartialItemState = pi_state_save_incoming;
2712 }
2713 // - issue status for it
2714 if (statusCmdP) {
2715 // add source and target refs of item
2716 statusCmdP->addTargetRef(smlSrcTargLocURIToCharP(thisitemnode->item->target)); // add target ref
2717 statusCmdP->addSourceRef(smlSrcTargLocURIToCharP(thisitemnode->item->source)); // add source ref
2718 // issue
2719 ISSUE_COMMAND_ROOT(fSessionP,statusCmdP){ TSmlCommand* p=statusCmdP; statusCmdP=__null; fSessionP->
issueRootPtr(p); }
;
2720 }
2721 // advance to next item in list
2722 itemnodePP = &(thisitemnode->next);
2723 }
2724 } // item loop
2725 // free this one in advance (only if command is finished)
2726 if (finished() && !tobequeueditems) FreeSmlElement();
2727 // update item list in command for queuing if needed
2728 if (tobequeueditems) {
2729 // there are to-be-queued items, insert them instead of the original item list
2730 // - delete current item list (only contains already processed and statused items)
2731 smlFreeItemList(fSyncOpElementP->itemList);
2732 // - insert to be queued items instead
2733 fSyncOpElementP->itemList=tobequeueditems;
2734 }
2735 }
2736 SYSYNC_CATCH (...)catch(...) {
2737 // make sure owned objects in local scope are deleted
2738 if (statusCmdP) delete statusCmdP;
2739 // re-throw
2740 SYSYNC_RETHROWthrow;
2741 SYSYNC_ENDCATCH}
2742 // if not all items could be executed, command must be queued for later re-execution.
2743 // (all successfully executed items are already deleted from the item list)
2744 return !tobequeueditems;
2745} // TSyncOpCommand::execute
2746
2747
2748// returns true if command must be put to the waiting-for-status queue.
2749// If false, command does not need to be put into waiting-for-status queue
2750// and can be deleted if finished() returns true
2751bool TSyncOpCommand::issue(
2752 uInt32 aAsCmdID, // command ID to be used
2753 uInt32 aInMsgID, // message ID in which command is being issued
2754 bool aNoResp // dummy here, because Status has always no response
2755)
2756{
2757 // prepare basic stuff
2758 TSmlCommand::issue(aAsCmdID,aInMsgID,aNoResp);
2759 // now issue
2760 if (fSyncOpElementP) {
2761 // issue command with SyncML toolkit (no flags)
2762 PrepareIssue(&fSyncOpElementP->cmdID,&fSyncOpElementP->flags); // CmdID and flags
2763 Ret_t err;
2764 InstanceID_t wspid = fSessionP->getSmlWorkspaceID();
2765 switch (fCmdType) {
2766 case scmd_add:
2767 #ifdef SYDEBUG2
2768 if (fSessionP->fXMLtranslate && fSessionP->fOutgoingXMLInstance && !fEvalMode)
2769 smlAddCmd(fSessionP->fOutgoingXMLInstance,fSyncOpElementP);
2770 #endif
2771 err=smlAddCmd(wspid,fSyncOpElementP);
2772 break;
2773 #ifdef COPY_SEND
2774 case scmd_copy:
2775 #ifdef SYDEBUG2
2776 if (fSessionP->fXMLtranslate && fSessionP->fOutgoingXMLInstance && !fEvalMode)
2777 smlCopyCmd(fSessionP->fOutgoingXMLInstance,fSyncOpElementP);
2778 #endif
2779 err=smlCopyCmd(wspid,fSyncOpElementP);
2780 break;
2781 #endif
2782 case scmd_move:
2783 #ifdef SYDEBUG2
2784 if (fSessionP->fXMLtranslate && fSessionP->fOutgoingXMLInstance && !fEvalMode)
2785 smlMoveCmd(fSessionP->fOutgoingXMLInstance,fSyncOpElementP);
2786 #endif
2787 err=smlMoveCmd(wspid,fSyncOpElementP);
2788 break;
2789 case scmd_replace:
2790 #ifdef SYDEBUG2
2791 if (fSessionP->fXMLtranslate && fSessionP->fOutgoingXMLInstance && !fEvalMode)
2792 smlReplaceCmd(fSessionP->fOutgoingXMLInstance,fSyncOpElementP);
2793 #endif
2794 err=smlReplaceCmd(wspid,fSyncOpElementP);
2795 break;
2796 case scmd_delete:
2797 #ifdef SYDEBUG2
2798 if (fSessionP->fXMLtranslate && fSessionP->fOutgoingXMLInstance && !fEvalMode)
2799 smlDeleteCmd(fSessionP->fOutgoingXMLInstance,fSyncOpElementP);
2800 #endif
2801 err=smlDeleteCmd(wspid,fSyncOpElementP);
2802 break;
2803 default:
2804 SYSYNC_THROW(TSyncException("TSyncOpCommand:issue, bad command type"))throw TSyncException("TSyncOpCommand:issue, bad command type"
)
;
2805 }
2806 if (!fEvalMode) {
2807 if (err!=SML_ERR_OK0x00) {
2808 SYSYNC_THROW(TSmlException("smlAdd/Copy/Replace/DeleteCmd",err))throw TSmlException("smlAdd/Copy/Replace/DeleteCmd",err);
2809 }
2810 FinalizeIssue();
2811 // show items
2812 SmlItemListPtr_t itemP = fSyncOpElementP->itemList;
2813 while (itemP) {
2814 // count net data sent
2815 sInt32 itemlen=0;
2816 if (itemP->item && itemP->item->data) {
2817 itemlen=itemP->item->data->length;
2818 fDataStoreP->fOutgoingDataBytes+=itemlen;
2819 }
2820 // show item source and target
2821 PDEBUGPRINTFX(DBG_PROTO,({ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ( "Item remoteID='%s', localID='%s', datasize=%ld"
, smlSrcTargLocURIToCharP(itemP->item->target), smlSrcTargLocURIToCharP
(itemP->item->source), (long)itemlen ); }
2822 "Item remoteID='%s', localID='%s', datasize=%ld",{ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ( "Item remoteID='%s', localID='%s', datasize=%ld"
, smlSrcTargLocURIToCharP(itemP->item->target), smlSrcTargLocURIToCharP
(itemP->item->source), (long)itemlen ); }
2823 smlSrcTargLocURIToCharP(itemP->item->target),{ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ( "Item remoteID='%s', localID='%s', datasize=%ld"
, smlSrcTargLocURIToCharP(itemP->item->target), smlSrcTargLocURIToCharP
(itemP->item->source), (long)itemlen ); }
2824 smlSrcTargLocURIToCharP(itemP->item->source),{ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ( "Item remoteID='%s', localID='%s', datasize=%ld"
, smlSrcTargLocURIToCharP(itemP->item->target), smlSrcTargLocURIToCharP
(itemP->item->source), (long)itemlen ); }
2825 (long)itemlen{ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ( "Item remoteID='%s', localID='%s', datasize=%ld"
, smlSrcTargLocURIToCharP(itemP->item->target), smlSrcTargLocURIToCharP
(itemP->item->source), (long)itemlen ); }
2826 )){ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ( "Item remoteID='%s', localID='%s', datasize=%ld"
, smlSrcTargLocURIToCharP(itemP->item->target), smlSrcTargLocURIToCharP
(itemP->item->source), (long)itemlen ); }
;
2827 if (fChunkedItemSize>0 && !fIncompleteData) {
2828 #ifdef SYDEBUG2
2829 PDEBUGPRINTFX(DBG_PROTO+DBG_HOT,({ if (((0x00000010 +0x00000001) & getDbgMask()) == (0x00000010
+0x00000001)) getDbgLogger()->setNextMask(0x00000010 +0x00000001
).DebugPrintfLastMask ( "Last Chunk (%ld bytes) of large object (%ld total) sent now - retaining it in case of implicit suspend"
, (long)itemlen, (long)fChunkedItemSize ); }
2830 "Last Chunk (%ld bytes) of large object (%ld total) sent now - retaining it in case of implicit suspend",{ if (((0x00000010 +0x00000001) & getDbgMask()) == (0x00000010
+0x00000001)) getDbgLogger()->setNextMask(0x00000010 +0x00000001
).DebugPrintfLastMask ( "Last Chunk (%ld bytes) of large object (%ld total) sent now - retaining it in case of implicit suspend"
, (long)itemlen, (long)fChunkedItemSize ); }
2831 (long)itemlen,{ if (((0x00000010 +0x00000001) & getDbgMask()) == (0x00000010
+0x00000001)) getDbgLogger()->setNextMask(0x00000010 +0x00000001
).DebugPrintfLastMask ( "Last Chunk (%ld bytes) of large object (%ld total) sent now - retaining it in case of implicit suspend"
, (long)itemlen, (long)fChunkedItemSize ); }
2832 (long)fChunkedItemSize{ if (((0x00000010 +0x00000001) & getDbgMask()) == (0x00000010
+0x00000001)) getDbgLogger()->setNextMask(0x00000010 +0x00000001
).DebugPrintfLastMask ( "Last Chunk (%ld bytes) of large object (%ld total) sent now - retaining it in case of implicit suspend"
, (long)itemlen, (long)fChunkedItemSize ); }
2833 )){ if (((0x00000010 +0x00000001) & getDbgMask()) == (0x00000010
+0x00000001)) getDbgLogger()->setNextMask(0x00000010 +0x00000001
).DebugPrintfLastMask ( "Last Chunk (%ld bytes) of large object (%ld total) sent now - retaining it in case of implicit suspend"
, (long)itemlen, (long)fChunkedItemSize ); }
;
2834 #endif
2835 if (itemlen>0)
2836 saveAsPartialItem(itemP->item);
2837 }
2838 // next
2839 itemP=itemP->next;
2840 }
2841 // we don't need the data any more, but we should keep the source and target IDs until we have the status
2842 // - get rid of data
2843 if (fSyncOpElementP->itemList) {
2844 // - free possible extra items (shouldn't be any - we always send single item per command)
2845 smlFreeItemList(fSyncOpElementP->itemList->next);
2846 fSyncOpElementP->itemList->next=NULL__null;
2847 // - free data and meta part of this item, but not target and source info
2848 if (fSyncOpElementP->itemList->item) {
2849 smlFreePcdata(fSyncOpElementP->itemList->item->meta);
2850 fSyncOpElementP->itemList->item->meta=NULL__null;
2851 smlFreePcdata(fSyncOpElementP->itemList->item->data);
2852 fSyncOpElementP->itemList->item->data=NULL__null;
2853 }
2854 }
2855 }
2856 else
2857 return err==SML_ERR_OK0x00; // ok if evaluation had no error
2858 }
2859 else {
2860 DEBUGPRINTFX(DBG_ERROR,("*** Tried to issue NULL status")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("*** Tried to issue NULL status"
); }
;
2861 }
2862 // sync op commands do need status
2863 return true; // queue for status
2864} // TSyncOpCommand::issue
2865
2866
2867void TSyncOpCommand::FreeSmlElement(void)
2868{
2869 // remove SyncML toolkit element(s)
2870 FREEPROTOELEMENT(fSyncOpElementP);
2871} // TSyncOpCommand::FreeSmlElement
2872
2873
2874TSyncOpCommand::~TSyncOpCommand()
2875{
2876 // free command elements, if any (use explicit invocation as this is a destructor)
2877 TSyncOpCommand::FreeSmlElement();
2878} // TSyncOpCommand::~TSyncOpCommand
2879
2880
2881/* end of TSyncOpCommand implementation */
2882
2883
2884#endif // SYNCCOMMAND_PART1_EXCLUDE
2885#ifndef SYNCCOMMAND_PART2_EXCLUDE
2886
2887/*
2888 * Implementation of TMapCommand
2889 */
2890
2891
2892// constructor for receiving Map command
2893TMapCommand::TMapCommand(
2894 TSyncSession *aSessionP, // associated session (for callbacks)
2895 uInt32 aMsgID, // the Message ID of the command
2896 SmlMapPtr_t aMapElementP // associated syncml protocol element
2897) :
2898 TSmlCommand(scmd_map,false,aSessionP,aMsgID)
2899{
2900 // save element
2901 fMapElementP = aMapElementP;
2902 fInProgress=false; // just in case...
2903 // no params
2904 fLocalDataStoreP=NULL__null;
2905 fRemoteDataStoreP=NULL__null;
2906} // TMapCommand::TMapCommand
2907
2908
2909#ifdef SYSYNC_SERVER1
2910// Server only receives Maps
2911
2912// analyze command (but do not yet execute)
2913bool TMapCommand::analyze(TPackageStates aPackageState)
2914{
2915 TSmlCommand::analyze(aPackageState);
2916 // get Command ID and flags
2917 if (fMapElementP) {
2918 StartProcessing(fMapElementP->cmdID,0);
2919 return true;
2920 }
2921 else return false; // no proto element, bad command
2922} // TMapCommand::analyze
2923
2924
2925// execute command (perform real actions, generate status)
2926// returns true if command has executed and can be deleted
2927bool TMapCommand::execute(void)
2928{
2929 TStatusCommand *statusCmdP=NULL__null;
2930 bool queueforlater;
2931
2932 SYSYNC_TRYtry {
2933 // prepare a status
2934 statusCmdP = newStatusCommand(200);
2935 // let session actually process the command
2936 queueforlater=false;
2937 fSessionP->processMapCommand(fMapElementP,*statusCmdP,queueforlater);
2938 // check if done or queued for later
2939 if (queueforlater) {
2940 delete statusCmdP;
2941 }
2942 else {
2943 // now issue status, if any
2944 if (statusCmdP) {
2945 statusCmdP->addTargetRef(smlSrcTargLocURIToCharP(fMapElementP->target)); // add target ref
2946 statusCmdP->addSourceRef(smlSrcTargLocURIToCharP(fMapElementP->source)); // add source ref
2947 #ifdef MAP_STATUS_IMMEDIATE1
2948 // issue status right now (might cause map statuses
2949 // returned in sync-updates-to-client package #4 instead of map-confirm #6
2950 ISSUE_COMMAND_ROOT(fSessionP,statusCmdP){ TSmlCommand* p=statusCmdP; statusCmdP=__null; fSessionP->
issueRootPtr(p); }
;
2951 #else
2952 // issue status only if outgoing package is map-response
2953 fSessionP->issueNotBeforePackage(psta_map,statusCmdP);
2954 #endif
2955 }
2956 // free this one in advance
2957 FreeSmlElement();
2958 }
2959 }
2960 SYSYNC_CATCH (...)catch(...) {
2961 // make sure owned objects in local scope are deleted
2962 if (statusCmdP) delete statusCmdP;
2963 // re-throw
2964 SYSYNC_RETHROWthrow;
2965 SYSYNC_ENDCATCH}
2966 // return true if command has fully executed
2967 return !queueforlater;
2968} // TMapCommand::execute
2969
2970#endif
2971
2972#ifdef SYSYNC_CLIENT1
2973
2974// Client only sends maps
2975
2976// constructor for sending MAP Command
2977TMapCommand::TMapCommand(
2978 TSyncSession *aSessionP, // associated session (for callbacks)
2979 TLocalEngineDS *aLocalDataStoreP, // local datastore
2980 TRemoteDataStore *aRemoteDataStoreP // remote datastore
2981) :
2982 TSmlCommand(scmd_map,true,aSessionP)
2983{
2984 // save params
2985 fLocalDataStoreP=aLocalDataStoreP;
2986 fRemoteDataStoreP=aRemoteDataStoreP;
2987 // create new internal map element
2988 fMapElementP=NULL__null; // none yet
2989 generateEmptyMapElement();
2990 // not yet in progress (as not yet issued)
2991 fInProgress=false;
2992} // TMapCommand::TMapCommand
2993
2994
2995// generate empty map element
2996void TMapCommand::generateEmptyMapElement(void)
2997{
2998 // free possibly still existing map element
2999 if (fMapElementP) FreeSmlElement();
3000 // create internal map element
3001 fMapElementP = SML_NEW(SmlMap_t)((SmlMap_t*) _smlMalloc(sizeof(SmlMap_t)));
3002 // set proto element type to make it auto-disposable
3003 fMapElementP->elementType=SML_PE_MAP;
3004 // Cmd ID is now empty (will be set when issued)
3005 fMapElementP->cmdID=NULL__null;
3006 // set source and target
3007 fMapElementP->target=newLocation(fRemoteDataStoreP->getFullName()); // remote is target for Map command
3008 fMapElementP->source=newLocation(fLocalDataStoreP->getRemoteViewOfLocalURI()); // local is source of Map command
3009 // no optional elements for now
3010 fMapElementP->cred=NULL__null; // %%% no database level auth yet at all
3011 fMapElementP->meta=NULL__null; // %%% no meta for now
3012 // map itemlist is empty
3013 fMapElementP->mapItemList=NULL__null;
3014 #ifndef USE_SML_EVALUATION1
3015 // no item sizes
3016 fItemSizes=0;
3017 #endif
3018} // TMapCommand::generateEmptyMapElement
3019
3020
3021// returns true if command must be put to the waiting-for-status queue.
3022// If false, command can be deleted (except if it is not finished() )
3023bool TMapCommand::issue(
3024 uInt32 aAsCmdID, // command ID to be used
3025 uInt32 aInMsgID, // message ID in which command is being issued
3026 bool aNoResp
3027)
3028{
3029 // prepare basic stuff
3030 TSmlCommand::issue(aAsCmdID,aInMsgID,aNoResp);
3031 // now issue
3032 if (fMapElementP) {
3033 // add as many Map items as possible, update fInProgress
3034 // BUT DONT DO THAT IN EVAL MODE (would be recursive, as generateMapItems()
3035 // will call evalIssue() which will call this routine....)
3036 if (!fEvalMode) generateMapItems();
3037 // issue command, but only if there are any items at all
3038 if (fMapElementP->mapItemList) {
3039 // now issue map command
3040 PrepareIssue(&fMapElementP->cmdID);
3041 if (!fEvalMode) {
3042 #ifdef SYDEBUG2
3043 if (fSessionP->fXMLtranslate && fSessionP->fOutgoingXMLInstance)
3044 smlMapCmd(fSessionP->fOutgoingXMLInstance,fMapElementP);
3045 #endif
3046 Ret_t err;
3047 if ((err=smlMapCmd(fSessionP->getSmlWorkspaceID(),fMapElementP))!=SML_ERR_OK0x00) {
3048 SYSYNC_THROW(TSmlException("smlMapCmd",err))throw TSmlException("smlMapCmd",err);
3049 }
3050 FinalizeIssue();
3051 // show debug
3052 DEBUGPRINTFX(DBG_HOT,({ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "Generated Map command, Source='%s', Target='%s'"
, smlSrcTargLocURIToCharP(fMapElementP->source), smlSrcTargLocURIToCharP
(fMapElementP->target) ); }
3053 "Generated Map command, Source='%s', Target='%s'",{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "Generated Map command, Source='%s', Target='%s'"
, smlSrcTargLocURIToCharP(fMapElementP->source), smlSrcTargLocURIToCharP
(fMapElementP->target) ); }
3054 smlSrcTargLocURIToCharP(fMapElementP->source),{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "Generated Map command, Source='%s', Target='%s'"
, smlSrcTargLocURIToCharP(fMapElementP->source), smlSrcTargLocURIToCharP
(fMapElementP->target) ); }
3055 smlSrcTargLocURIToCharP(fMapElementP->target){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "Generated Map command, Source='%s', Target='%s'"
, smlSrcTargLocURIToCharP(fMapElementP->source), smlSrcTargLocURIToCharP
(fMapElementP->target) ); }
3056 )){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "Generated Map command, Source='%s', Target='%s'"
, smlSrcTargLocURIToCharP(fMapElementP->source), smlSrcTargLocURIToCharP
(fMapElementP->target) ); }
;
3057 }
3058 else
3059 return smlMapCmd(fSessionP->getSmlWorkspaceID(),fMapElementP)==SML_ERR_OK0x00;
3060 }
3061 else {
3062 if (fEvalMode) return true; // evaluated nothing, is ok!
3063 DEBUGPRINTFX(DBG_PROTO,("Suppressed generating empty map command")){ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ("Suppressed generating empty map command"
); }
;
3064 return false; // do not queue, delete command now
3065 }
3066 // keep smlElement, as we need it to mark confirmed map items
3067 // at handleStatus().
3068 }
3069 else {
3070 DEBUGPRINTFX(DBG_ERROR,("*** Tried to issue NULL sync")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("*** Tried to issue NULL sync"
); }
;
3071 }
3072 // return true if command must be queued for status/result response reception
3073 return queueForResponse();
3074} // TMapCommand::issue
3075
3076
3077
3078// - test if completely issued (must be called after issue() and continueIssue())
3079bool TMapCommand::finished(void)
3080{
3081 // not finished as long there are more syncOps to send
3082 return (!fInProgress || !fOutgoing);
3083} // TMapCommand::finished
3084
3085
3086// - continue issuing command. This is called by session at start of new message
3087// when finished() returned false after issue()/continueIssue()
3088// (which causes caller of finished() to put command into fInteruptedCommands queue)
3089// returns true if command should be queued for status (again?)
3090// NOTE: continueIssue must make sure that it gets a new CmdID/MsgID because
3091// the command itself is issued multiple times
3092bool TMapCommand::continueIssue(bool &aNewIssue)
3093{
3094 aNewIssue=false; // never issue anew!
3095 if (!fInProgress) return false; // done, don't queue for status again
3096 // we can generate next map command only after we have received status for this one
3097 if (isWaitingForStatus()) return true; // still in progress, still waiting for status
3098 // command is in progress, continue with another <Map> command in this message
3099 // - create new Map command
3100 generateEmptyMapElement();
3101 // - issue again with new command ID
3102 fCmdID = fSessionP->getNextOutgoingCmdID();
3103 fMsgID = fSessionP->getOutgoingMsgID();
3104 // new map command must be queued for status again
3105 // but only if something was actually issued (map command issue can
3106 // be nop if there are no map items present)
3107 return issue(fCmdID,fMsgID,fNoResp);
3108} // TMapCommand::continueIssue
3109
3110
3111// add as many Map items as possible, update fInProgress
3112void TMapCommand::generateMapItems(void)
3113{
3114 // let datastore add Map items (possibly none)
3115 fInProgress = !(
3116 fLocalDataStoreP->engGenerateMapItems(this,NULL__null)
3117 );
3118} // TMapCommand::generateMapItems
3119
3120
3121// add a Map Item to the map command
3122void TMapCommand::addMapItem(const char *aLocalID, const char *aRemoteID)
3123{
3124 // make item
3125 SmlMapItemPtr_t mapitemP = SML_NEW(SmlMapItem_t)((SmlMapItem_t*) _smlMalloc(sizeof(SmlMapItem_t)));
3126 mapitemP->target=newLocation(aRemoteID);
3127 mapitemP->source=newLocation(aLocalID);
3128 #ifndef USE_SML_EVALUATION1
3129 // update size
3130 fItemSizes +=
3131 ITEMOVERHEADSIZE90 +
3132 strlen(aLocalID) +
3133 strlen(aRemoteID);
3134 #endif
3135 // add item to item list
3136 SmlMapItemListPtr_t *mapItemListPP = &(fMapElementP->mapItemList);
3137 // find last itemlist pointer
3138 while (*mapItemListPP) {
3139 mapItemListPP=&((*mapItemListPP)->next);
3140 }
3141 // aItemListPP now points to a NULL pointer which must be replaced by addr of new ItemList entry
3142 *mapItemListPP = SML_NEW(SmlMapItemList_t)((SmlMapItemList_t*) _smlMalloc(sizeof(SmlMapItemList_t)));
3143 (*mapItemListPP)->next=NULL__null;
3144 (*mapItemListPP)->mapItem=mapitemP; // insert new item
3145} // TMapCommand::addItem
3146
3147
3148// remove last added map item from the command
3149void TMapCommand::deleteLastMapItem(void)
3150{
3151 // make item
3152 #ifndef USE_SML_EVALUATION1
3153 #error "Not implemented for old non-eval method any more"
3154 #endif
3155 // kill last item in item list
3156 SmlMapItemListPtr_t *mapItemListPP = &(fMapElementP->mapItemList);
3157 // find last itemlist pointer pointing to an item
3158 while (*mapItemListPP && (*mapItemListPP)->next) {
3159 mapItemListPP=&((*mapItemListPP)->next);
3160 }
3161 // aItemListPP now points to the pointer which points to the last item list element (or is NULL if no items there)
3162 if (*mapItemListPP) {
3163 // delete rest of list, which consists of one item only
3164 smlFreeMapItemList(*mapItemListPP);
3165 // NULL link in previous item or beginning of list
3166 *mapItemListPP=NULL__null;
3167 }
3168} // TMapCommand::deleteLastMapItem
3169
3170
3171
3172// handle status received for previously issued command
3173// returns true if done, false if command must be kept in the status queue
3174bool TMapCommand::handleStatus(TStatusCommand *aStatusCmdP)
3175{
3176 bool handled=false;
3177 if (aStatusCmdP->getStatusCode()==200) {
3178 handled=true; // is ok
3179 // mark maps confirmed
3180 if (fLocalDataStoreP) {
3181 // go through all of my items
3182 SmlMapItemListPtr_t mapItemListP = fMapElementP->mapItemList;
3183 SmlMapItemPtr_t mapItemP;
3184 while (mapItemListP) {
3185 mapItemP=mapItemListP->mapItem;
3186 if (mapItemP) {
3187 // call datastore to mark this map confirmed (no need to be sent again in next session / resume)
3188 fLocalDataStoreP->engMarkMapConfirmed(
3189 smlSrcTargLocURIToCharP(mapItemP->source), // source for outgoing mapitem is localID
3190 smlSrcTargLocURIToCharP(mapItemP->target) // target for outgoing mapitem is remoteID
3191 );
3192 }
3193 mapItemListP=mapItemListP->next;
3194 }
3195 }
3196 }
3197 // anyway, we can now get rid of the map items in the command
3198 if (fMapElementP) FreeSmlElement();
3199 // check if base class must handle it
3200 if(!handled) {
3201 // let base class handle it
3202 handled=TSmlCommand::handleStatus(aStatusCmdP);
3203 }
3204 return handled;
3205} // TMapCommand::handleStatus
3206
3207#endif // client-only map implementation
3208
3209
3210// Common for Client and Server
3211
3212#ifndef USE_SML_EVALUATION1
3213
3214// get (approximated) message size required for sending it
3215uInt32 TMapCommand::messageSize(void)
3216{
3217 // return size of command so far
3218 return TSmlCommand::messageSize()+fItemSizes;
3219} // TMapCommand::messageSize
3220
3221#endif
3222
3223
3224void TMapCommand::FreeSmlElement(void)
3225{
3226 // remove SyncML toolkit element(s)
3227 FREEPROTOELEMENT(fMapElementP);
3228} // TMapCommand::FreeSmlElement
3229
3230
3231TMapCommand::~TMapCommand()
3232{
3233 // free command elements, if any (use explicit invocation as this is a destructor)
3234 TMapCommand::FreeSmlElement();
3235} // TMapCommand::TMapCommand
3236
3237
3238/* end of TMapCommand implementation */
3239
3240/*
3241 * Implementation of TGetCommand
3242 */
3243
3244// constructor for receiving command
3245TGetCommand::TGetCommand(
3246 TSyncSession *aSessionP, // associated session (for callbacks)
3247 uInt32 aMsgID, // the Message ID of the command
3248 SmlGetPtr_t aGetElementP // associated syncml protocol element
3249) :
3250 TSmlCommand(scmd_get,false,aSessionP,aMsgID)
3251{
3252 // save element
3253 fGetElementP = aGetElementP;
3254} // TGetCommand::TGetCommand
3255
3256
3257// constructor for sending command
3258TGetCommand::TGetCommand(
3259 TSyncSession *aSessionP // associated session (for callbacks)
3260) :
3261 TSmlCommand(scmd_get,true,aSessionP)
3262{
3263 // create internal get element
3264 fGetElementP = SML_NEW(SmlGet_t)((SmlGet_t*) _smlMalloc(sizeof(SmlGet_t)));
3265 // set proto element type to make it auto-disposable
3266 fGetElementP->elementType=SML_PE_GET;
3267 // Cmd ID is now empty (will be set when issued)
3268 fGetElementP->cmdID=NULL__null;
3269 // default to no flags (noResp is set at issue, if at all)
3270 fGetElementP->flags=0;
3271 // no optional elements for now
3272 fGetElementP->cred=NULL__null;
3273 fGetElementP->lang=NULL__null;
3274 fGetElementP->meta=NULL__null;
3275 fGetElementP->itemList=NULL__null;
3276} // TGetCommand::TGetCommand
3277
3278
3279// set Meta of the get command
3280void TGetCommand::setMeta(
3281 SmlPcdataPtr_t aMetaP // existing meta data structure, ownership is passed to Get
3282)
3283{
3284 if (fGetElementP)
3285 fGetElementP->meta=aMetaP;
3286} // TGetCommand::setMeta
3287
3288
3289// add an Item to the get command
3290void TGetCommand::addItem(
3291 SmlItemPtr_t aItemP // existing item data structure, ownership is passed to Get
3292)
3293{
3294 if (fGetElementP)
3295 addItemToList(aItemP,&(fGetElementP->itemList));
3296} // TGetCommand::addItem
3297
3298
3299// add a target specification Item to the get command
3300void TGetCommand::addTargetLocItem(
3301 const char *aTargetURI,
3302 const char *aTargetName
3303)
3304{
3305 SmlItemPtr_t itemP = newItem();
3306
3307 itemP->target = newLocation(aTargetURI,aTargetName);
3308 addItem(itemP);
3309} // TGetCommand::addTargetLocItem
3310
3311
3312
3313// analyze command (but do not yet execute)
3314bool TGetCommand::analyze(TPackageStates aPackageState)
3315{
3316 TSmlCommand::analyze(aPackageState);
3317 // get Command ID and flags
3318 if (fGetElementP) {
3319 StartProcessing(fGetElementP->cmdID,fGetElementP->flags);
3320 return true;
3321 }
3322 else return false; // no proto element, bad command
3323} // TGetCommand::analyze
3324
3325
3326// execute command (perform real actions, generate status)
3327// returns true if command has executed and can be deleted
3328bool TGetCommand::execute(void)
3329{
3330 TStatusCommand *statusCmdP=NULL__null;
3331 TResultsCommand *resultsCmdP=NULL__null;
3332 SmlItemListPtr_t thisitemnode,nextitemnode;
3333
3334 SYSYNC_TRYtry {
3335 // process items
3336 thisitemnode=fGetElementP->itemList;
3337 while (thisitemnode) {
3338 nextitemnode = thisitemnode->next;
3339 // no result nor status so far
3340 statusCmdP=NULL__null;
3341 resultsCmdP=NULL__null;
3342 // get Target LocURI
3343 if (!thisitemnode->item) SYSYNC_THROW(TSyncException("Get with NULL item"))throw TSyncException("Get with NULL item");
3344 string locURI=smlSrcTargLocURIToCharP(thisitemnode->item->target);
3345 DEBUGPRINTFX(DBG_HOT,("processing item with locURI=%s",locURI.c_str())){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("processing item with locURI=%s"
,locURI.c_str()); }
;
3346 // let session (and descendants) process it
3347 // - default to "not found" status
3348 statusCmdP = newStatusCommand(404);
3349 resultsCmdP=fSessionP->processGetItem(locURI.c_str(),this,thisitemnode->item,*statusCmdP);
3350 // now complete and issue status
3351 statusCmdP->addTargetRef(locURI.c_str()); // add target ref
3352 ISSUE_COMMAND_ROOT(fSessionP,statusCmdP){ TSmlCommand* p=statusCmdP; statusCmdP=__null; fSessionP->
issueRootPtr(p); }
;
3353 // issue results, if any
3354 if (resultsCmdP) {
3355 ISSUE_COMMAND_ROOT(fSessionP,resultsCmdP){ TSmlCommand* p=resultsCmdP; resultsCmdP=__null; fSessionP->
issueRootPtr(p); }
;
3356 }
3357 // next item
3358 thisitemnode=nextitemnode;
3359 }
3360 // free this one in advance
3361 FreeSmlElement();
3362 }
3363 SYSYNC_CATCH (...)catch(...) {
3364 // make sure owned objects in local scope are deleted
3365 if (statusCmdP) delete statusCmdP;
3366 if (resultsCmdP) delete resultsCmdP;
3367 // re-throw
3368 SYSYNC_RETHROWthrow;
3369 SYSYNC_ENDCATCH}
3370 // done with command, delete it now: return true
3371 return true;
3372} // TGetCommand::execute
3373
3374
3375// returns true if command must be put to the waiting-for-status queue.
3376// If false, command can be deleted
3377bool TGetCommand::issue(
3378 uInt32 aAsCmdID, // command ID to be used
3379 uInt32 aInMsgID, // message ID in which command is being issued
3380 bool aNoResp
3381)
3382{
3383 // prepare basic stuff
3384 TSmlCommand::issue(aAsCmdID,aInMsgID,aNoResp);
3385 // now issue
3386 if (fGetElementP) {
3387 // issue command with SyncML toolkit
3388 PrepareIssue(&fGetElementP->cmdID,&fGetElementP->flags);
3389 if (!fEvalMode) {
3390 #ifdef SYDEBUG2
3391 if (fSessionP->fXMLtranslate && fSessionP->fOutgoingXMLInstance)
3392 smlGetCmd(fSessionP->fOutgoingXMLInstance,fGetElementP);
3393 #endif
3394 Ret_t err;
3395 if ((err=smlGetCmd(fSessionP->getSmlWorkspaceID(),fGetElementP))!=SML_ERR_OK0x00) {
3396 SYSYNC_THROW(TSmlException("smlGetCmd",err))throw TSmlException("smlGetCmd",err);
3397 }
3398 FinalizeIssue();
3399 // we don't need the status structure any more, free (and NULL ptr) now
3400 FreeSmlElement();
3401 }
3402 else
3403 return smlGetCmd(fSessionP->getSmlWorkspaceID(),fGetElementP)==SML_ERR_OK0x00;
3404 }
3405 else {
3406 DEBUGPRINTFX(DBG_ERROR,("*** Tried to issue NULL get")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("*** Tried to issue NULL get"
); }
;
3407 }
3408 // return true if command must be queued for status/result response reception
3409 return queueForResponse();
3410} // TGetCommand::issue
3411
3412
3413bool TGetCommand::statusEssential(void)
3414{
3415 // get status is not essential in lenient mode
3416 return !(fSessionP->fLenientMode);
3417} // TGetCommand::statusEssential
3418
3419
3420// handle status received for previously issued command
3421// returns true if done, false if command must be kept in the status queue
3422bool TGetCommand::handleStatus(TStatusCommand *aStatusCmdP)
3423{
3424 // base class just handles common cases
3425 TSyError statuscode = aStatusCmdP->getStatusCode();
3426 if (statuscode>=500) {
3427 // %%% for SCTS, which rejects GET with status 500 in some cases
3428 POBJDEBUGPRINTFX(fSessionP,DBG_ERROR,("Status: %hd: 5xx for get is passed w/o error",statuscode)){ if ((fSessionP) && (((0x00000002) & (fSessionP)
->getDbgMask()) == (0x00000002))) (fSessionP)->getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("Status: %hd: 5xx for get is passed w/o error"
,statuscode); }
;
3429 return true;
3430 }
3431 // let ancestor analyze
3432 return TSmlCommand::handleStatus(aStatusCmdP);
3433} // TGetCommand::handleStatus
3434
3435
3436
3437
3438void TGetCommand::FreeSmlElement(void)
3439{
3440 // remove SyncML toolkit element(s)
3441 FREEPROTOELEMENT(fGetElementP);
3442} // TGetCommand::FreeSmlElement
3443
3444
3445TGetCommand::~TGetCommand()
3446{
3447 // free command elements, if any (use explicit invocation as this is a destructor)
3448 TGetCommand::FreeSmlElement();
3449} // TGetCommand::~TGetCommand
3450
3451
3452/* end of TGetCommand implementation */
3453
3454/*
3455 * Implementation of TPutCommand
3456 */
3457
3458
3459// constructor for receiving command
3460TPutCommand::TPutCommand(
3461 TSyncSession *aSessionP, // associated session (for callbacks)
3462 uInt32 aMsgID, // the Message ID of the command
3463 SmlGetPtr_t aPutElementP // associated syncml protocol element
3464) :
3465 TSmlCommand(scmd_put,false,aSessionP,aMsgID)
3466{
3467 // save element
3468 fPutElementP = aPutElementP;
3469} // TPutCommand::TPutCommand
3470
3471
3472// constructor for sending command
3473TPutCommand::TPutCommand(
3474 TSyncSession *aSessionP // associated session (for callbacks)
3475) :
3476 TSmlCommand(scmd_put,true,aSessionP)
3477{
3478 // create internal get element
3479 fPutElementP = SML_NEW(SmlPut_t)((SmlPut_t*) _smlMalloc(sizeof(SmlPut_t)));
3480 // set proto element type to make it auto-disposable
3481 fPutElementP->elementType=SML_PE_PUT;
3482 // Cmd ID is now empty (will be set when issued)
3483 fPutElementP->cmdID=NULL__null;
3484 // default to no flags (noResp is set at issue, if at all)
3485 fPutElementP->flags=0;
3486 // no optional elements for now
3487 fPutElementP->cred=NULL__null;
3488 fPutElementP->lang=NULL__null;
3489 fPutElementP->meta=NULL__null;
3490 fPutElementP->itemList=NULL__null;
3491} // TPutCommand::TPutCommand
3492
3493
3494// add Meta to the get command
3495void TPutCommand::setMeta(
3496 SmlPcdataPtr_t aMetaP // existing meta data structure, ownership is passed to Get
3497)
3498{
3499 if (fPutElementP)
3500 fPutElementP->meta=aMetaP;
3501} // TPutCommand::setMeta
3502
3503
3504// add an Item to the get command
3505void TPutCommand::addItem(
3506 SmlItemPtr_t aItemP // existing item data structure, ownership is passed to Get
3507)
3508{
3509 if (fPutElementP)
3510 addItemToList(aItemP,&(fPutElementP->itemList));
3511} // TPutCommand::addItem
3512
3513
3514// add a source specification Item to the put command and return a pointer
3515// to add data to it
3516SmlItemPtr_t TPutCommand::addSourceLocItem(
3517 const char *aTargetURI,
3518 const char *aTargetName
3519)
3520{
3521 SmlItemPtr_t itemP = newItem();
3522
3523 itemP->source = newLocation(aTargetURI,aTargetName);
3524 addItem(itemP);
3525 return itemP;
3526} // TPutCommand::addSourceLocItem
3527
3528
3529// analyze command (but do not yet execute)
3530bool TPutCommand::analyze(TPackageStates aPackageState)
3531{
3532 TSmlCommand::analyze(aPackageState);
3533 // get Command ID and flags
3534 if (fPutElementP) {
3535 StartProcessing(fPutElementP->cmdID,fPutElementP->flags);
3536 return true;
3537 }
3538 else return false; // no proto element, bad command
3539} // TPutCommand::analyze
3540
3541
3542// execute command (perform real actions, generate status)
3543// returns true if command has executed and can be deleted
3544bool TPutCommand::execute(void)
3545{
3546 TStatusCommand *statusCmdP=NULL__null;
3547 SmlItemListPtr_t thisitemnode,nextitemnode;
3548
3549 SYSYNC_TRYtry {
3550 // process items
3551 thisitemnode=fPutElementP->itemList;
3552 while (thisitemnode) {
3553 nextitemnode = thisitemnode->next;
3554 // no result nor status so far
3555 statusCmdP=NULL__null;
3556 if (!thisitemnode->item) SYSYNC_THROW(TSyncException("Put with NULL item"))throw TSyncException("Put with NULL item");
3557 // get Source LocURI
3558 string locURI=smlSrcTargLocURIToCharP(thisitemnode->item->source);
3559 DEBUGPRINTFX(DBG_HOT,("processing item with locURI=%s",locURI.c_str())){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("processing item with locURI=%s"
,locURI.c_str()); }
;
3560 // let session (and descendants) process it
3561 // - default to not allowed to put status
3562 statusCmdP = newStatusCommand(403);
3563 fSessionP->processPutResultItem(true,locURI.c_str(),this,thisitemnode->item,*statusCmdP);
3564 // now complete and issue status
3565 statusCmdP->addSourceRef(locURI.c_str()); // add source ref
3566 ISSUE_COMMAND_ROOT(fSessionP,statusCmdP){ TSmlCommand* p=statusCmdP; statusCmdP=__null; fSessionP->
issueRootPtr(p); }
;
3567 // next item
3568 thisitemnode=nextitemnode;
3569 }
3570 // free element
3571 FreeSmlElement();
3572 }
3573 SYSYNC_CATCH (...)catch(...) {
3574 // make sure owned objects in local scope are deleted
3575 if (statusCmdP) delete statusCmdP;
3576 // re-throw
3577 SYSYNC_RETHROWthrow;
3578 SYSYNC_ENDCATCH}
3579 // done with command, delete it now: return true
3580 return true;
3581} // TPutCommand::execute
3582
3583
3584// returns true if command must be put to the waiting-for-status queue.
3585// If false, command can be deleted
3586bool TPutCommand::issue(
3587 uInt32 aAsCmdID, // command ID to be used
3588 uInt32 aInMsgID, // message ID in which command is being issued
3589 bool aNoResp
3590)
3591{
3592 // prepare basic stuff
3593 TSmlCommand::issue(aAsCmdID,aInMsgID,aNoResp);
3594 // now issue
3595 if (fPutElementP) {
3596 // issue command with SyncML toolkit
3597 PrepareIssue(&fPutElementP->cmdID,&fPutElementP->flags);
3598 if (!fEvalMode) {
3599 #ifdef SYDEBUG2
3600 if (fSessionP->fXMLtranslate && fSessionP->fOutgoingXMLInstance)
3601 smlPutCmd(fSessionP->fOutgoingXMLInstance,fPutElementP);
3602 #endif
3603 Ret_t err;
3604 if ((err=smlPutCmd(fSessionP->getSmlWorkspaceID(),fPutElementP))!=SML_ERR_OK0x00) {
3605 SYSYNC_THROW(TSmlException("smlPutCmd",err))throw TSmlException("smlPutCmd",err);
3606 }
3607 FinalizeIssue();
3608 // we don't need the status structure any more, free (and NULL ptr) now
3609 FreeSmlElement();
3610 }
3611 else
3612 return smlPutCmd(fSessionP->getSmlWorkspaceID(),fPutElementP)==SML_ERR_OK0x00;
3613 }
3614 else {
3615 DEBUGPRINTFX(DBG_ERROR,("*** Tried to issue NULL put")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("*** Tried to issue NULL put"
); }
;
3616 }
3617 // return true if command must be queued for status/result response reception
3618 return queueForResponse();
3619} // TPutCommand::issue
3620
3621
3622void TPutCommand::FreeSmlElement(void)
3623{
3624 // remove SyncML toolkit element(s)
3625 FREEPROTOELEMENT(fPutElementP);
3626} // TPutCommand::FreeSmlElement
3627
3628
3629TPutCommand::~TPutCommand()
3630{
3631 // free command elements, if any (use explicit invocation as this is a destructor)
3632 TPutCommand::FreeSmlElement();
3633} // TPutCommand::~TPutCommand
3634
3635
3636/* end of TPutCommand implementation */
3637
3638
3639/*
3640 * Implementation of TStatusCommand
3641 */
3642
3643
3644// constructor for generating status
3645TStatusCommand::TStatusCommand(
3646 TSyncSession *aSessionP, // associated session (for callbacks)
3647 TSmlCommand *aCommandP, // command this status refers to
3648 TSyError aStatusCode // status code
3649) :
3650 TSmlCommand(scmd_status,true,aSessionP)
3651{
3652 // save status code
3653 fStatusCode=aStatusCode;
3654 // get reference info
3655 if (aCommandP) {
3656 // referring to a command
3657 fRefMsgID=aCommandP->getMsgID();
3658 fRefCmdID=aCommandP->getCmdID();
3659 fRefCmdType=aCommandP->getCmdType();
3660 // - set flag to suppress sending this status when NoResp is set
3661 fDontSend= aCommandP->getNoResp() || fSessionP->getMsgNoResp();
3662 }
3663 else {
3664 // referring to SyncHdr of current message
3665 fRefMsgID=fSessionP->fIncomingMsgID;
3666 fRefCmdID=0; // "command" ID of SyncHdr is 0
3667 fRefCmdType=scmd_synchdr; // is SyncHdr
3668 // - set flag to suppress sending this status when NoResp is set
3669 fDontSend=fSessionP->getMsgNoResp();
3670 }
3671 // create internal status element
3672 fStatusElementP = SML_NEW(SmlStatus_t)((SmlStatus_t*) _smlMalloc(sizeof(SmlStatus_t)));
3673 // set proto element type to make it auto-disposable
3674 fStatusElementP->elementType=SML_PE_STATUS;
3675 // Cmd ID is now empty (will be set at Issue to ensure correct sequential ordering in case this status is not immediately sent)
3676 fStatusElementP->cmdID=NULL__null;
3677 // status refers to message of specified command
3678 fStatusElementP->msgRef=newPCDataLong(fRefMsgID);
3679 // status refers to ID of specified command
3680 fStatusElementP->cmdRef=newPCDataLong(fRefCmdID);
3681 // add name
3682 fStatusElementP->cmd=newPCDataString(getNameOf(fRefCmdType));
3683 // no status code yet (will be added at issue())
3684 fStatusElementP->data=NULL__null;
3685 // no optional elements for now
3686 fStatusElementP->targetRefList=NULL__null;
3687 fStatusElementP->sourceRefList=NULL__null;
3688 fStatusElementP->cred=NULL__null;
3689 fStatusElementP->chal=NULL__null;
3690 fStatusElementP->itemList=NULL__null;
3691} // TStatusCommand::TStatusCommand
3692
3693
3694// %%%% (later obsolete) constructor for generating status w/o having a command object
3695TStatusCommand::TStatusCommand(
3696 TSyncSession *aSessionP, // associated session (for callbacks)
3697 uInt32 aRefCmdID, // referred-to command ID
3698 TSmlCommandTypes aRefCmdType, // referred-to command type (scmd_xxx)
3699 bool aNoResp, // set if no-Resp
3700 TSyError aStatusCode // status code
3701) :
3702 TSmlCommand(scmd_status,true,aSessionP)
3703{
3704 // save status code
3705 fStatusCode=aStatusCode;
3706 // get reference info
3707 fRefMsgID=fSessionP->fIncomingMsgID;
3708 fRefCmdID=aRefCmdID;
3709 fRefCmdType=aRefCmdType;
3710 // - set flag to suppress sending this status when NoResp is set
3711 fDontSend=aNoResp;
3712 // create internal status element
3713 fStatusElementP = SML_NEW(SmlStatus_t)((SmlStatus_t*) _smlMalloc(sizeof(SmlStatus_t)));
3714 // set proto element type to make it auto-disposable
3715 fStatusElementP->elementType=SML_PE_STATUS;
3716 // Cmd ID is now empty (will be set at Issue to ensure correct sequential ordering in case this status is not immediately sent)
3717 fStatusElementP->cmdID=NULL__null;
3718 // status refers to message of specified command
3719 fStatusElementP->msgRef=newPCDataLong(fRefMsgID);
3720 // status refers to ID of specified command
3721 fStatusElementP->cmdRef=newPCDataLong(fRefCmdID);
3722 // add name
3723 fStatusElementP->cmd=newPCDataString(getNameOf(fRefCmdType));
3724 // no status code yet (will be added at issue())
3725 fStatusElementP->data=NULL__null;
3726 // no optional elements for now
3727 fStatusElementP->targetRefList=NULL__null;
3728 fStatusElementP->sourceRefList=NULL__null;
3729 fStatusElementP->cred=NULL__null;
3730 fStatusElementP->chal=NULL__null;
3731 fStatusElementP->itemList=NULL__null;
3732} // TStatusCommand::TStatusCommand
3733
3734
3735// constructor for receiving status
3736TStatusCommand::TStatusCommand(
3737 TSyncSession *aSessionP, // associated session (for callbacks)
3738 uInt32 aMsgID, // the Message ID of the command
3739 SmlStatusPtr_t aStatusElementP // associated STATUS command content element
3740) :
3741 TSmlCommand(scmd_status,false,aSessionP,aMsgID)
3742{
3743 // save element
3744 fStatusElementP = aStatusElementP;
3745} // TStatusCommand::TStatusCommand
3746
3747
3748// analyze status
3749bool TStatusCommand::analyze(TPackageStates aPackageState)
3750{
3751 TSmlCommand::analyze(aPackageState);
3752 // get Command ID and flags
3753 if (fStatusElementP) {
3754 StartProcessing(fStatusElementP->cmdID,0);
3755 // get status code
3756 sInt32 temp;
3757 if (smlPCDataToLong(fStatusElementP->data,temp)) fStatusCode=temp;
3758 else {
3759 PDEBUGPRINTFX(DBG_ERROR,("Malformed status code: '%s'",smlPCDataToCharP(fStatusElementP->data))){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("Malformed status code: '%s'"
,smlPCDataToCharP(fStatusElementP->data)); }
;
3760 return false; // bad status
3761 }
3762 // get message reference
3763 if (!fStatusElementP->msgRef) {
3764 // no MsgRef -> must assume 1 (according to SyncML specs)
3765 fRefMsgID=1;
3766 DEBUGPRINTFX(DBG_PROTO,("No MsgRef in Status, assumed 1")){ if (((0x00000010) & getDbgMask()) == (0x00000010)) getDbgLogger
()->setNextMask(0x00000010).DebugPrintfLastMask ("No MsgRef in Status, assumed 1"
); }
;
3767 }
3768 else if (!smlPCDataToULong(fStatusElementP->msgRef,fRefMsgID)) {
3769 PDEBUGPRINTFX(DBG_ERROR,("Malformed message reference: '%s'",smlPCDataToCharP(fStatusElementP->msgRef))){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("Malformed message reference: '%s'"
,smlPCDataToCharP(fStatusElementP->msgRef)); }
;
3770 return false; // bad status
3771 }
3772 // get command reference
3773 if (!smlPCDataToULong(fStatusElementP->cmdRef,fRefCmdID)) {
3774 PDEBUGPRINTFX(DBG_ERROR,("Malformed command reference: '%s'",smlPCDataToCharP(fStatusElementP->msgRef))){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("Malformed command reference: '%s'"
,smlPCDataToCharP(fStatusElementP->msgRef)); }
;
3775 return false; // bad status
3776 }
3777 #ifdef SYDEBUG2
3778 // warn if error (don't treat slow sync status or conflict indication as errors)
3779 // - 418 = item already exits: sent by Funambol server when both client and
3780 // and server have a new item which is considered identical by the server
3781 // (must be really identical, minor difference will lead to a merged item
3782 // which is sent back to the client without the 418). See Moblin Bugzilla #4599.
3783 if (fStatusCode>=300 && fStatusCode!=508 && fStatusCode!=419 && fStatusCode!=418) {
3784 PDEBUGPRINTFX(DBG_ERROR,({ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "WARNING: RECEIVED NON-OK STATUS %hd for &html;<a name=\"SO_%ld_%ld\" href=\"#IO_%ld_%ld\">&html;command '%s'&html;</a>&html; (outgoing MsgID=%ld, CmdID=%ld)"
, fStatusCode, (long)fRefMsgID, (long)fRefCmdID, (long)fRefMsgID
, (long)fRefCmdID, smlPCDataToCharP(fStatusElementP->cmd),
(long)fRefMsgID, (long)fRefCmdID ); }
3785 "WARNING: RECEIVED NON-OK STATUS %hd for &html;<a name=\"SO_%ld_%ld\" href=\"#IO_%ld_%ld\">&html;command '%s'&html;</a>&html; (outgoing MsgID=%ld, CmdID=%ld)",{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "WARNING: RECEIVED NON-OK STATUS %hd for &html;<a name=\"SO_%ld_%ld\" href=\"#IO_%ld_%ld\">&html;command '%s'&html;</a>&html; (outgoing MsgID=%ld, CmdID=%ld)"
, fStatusCode, (long)fRefMsgID, (long)fRefCmdID, (long)fRefMsgID
, (long)fRefCmdID, smlPCDataToCharP(fStatusElementP->cmd),
(long)fRefMsgID, (long)fRefCmdID ); }
3786 fStatusCode,{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "WARNING: RECEIVED NON-OK STATUS %hd for &html;<a name=\"SO_%ld_%ld\" href=\"#IO_%ld_%ld\">&html;command '%s'&html;</a>&html; (outgoing MsgID=%ld, CmdID=%ld)"
, fStatusCode, (long)fRefMsgID, (long)fRefCmdID, (long)fRefMsgID
, (long)fRefCmdID, smlPCDataToCharP(fStatusElementP->cmd),
(long)fRefMsgID, (long)fRefCmdID ); }
3787 (long)fRefMsgID,{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "WARNING: RECEIVED NON-OK STATUS %hd for &html;<a name=\"SO_%ld_%ld\" href=\"#IO_%ld_%ld\">&html;command '%s'&html;</a>&html; (outgoing MsgID=%ld, CmdID=%ld)"
, fStatusCode, (long)fRefMsgID, (long)fRefCmdID, (long)fRefMsgID
, (long)fRefCmdID, smlPCDataToCharP(fStatusElementP->cmd),
(long)fRefMsgID, (long)fRefCmdID ); }
3788 (long)fRefCmdID,{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "WARNING: RECEIVED NON-OK STATUS %hd for &html;<a name=\"SO_%ld_%ld\" href=\"#IO_%ld_%ld\">&html;command '%s'&html;</a>&html; (outgoing MsgID=%ld, CmdID=%ld)"
, fStatusCode, (long)fRefMsgID, (long)fRefCmdID, (long)fRefMsgID
, (long)fRefCmdID, smlPCDataToCharP(fStatusElementP->cmd),
(long)fRefMsgID, (long)fRefCmdID ); }
3789 (long)fRefMsgID,{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "WARNING: RECEIVED NON-OK STATUS %hd for &html;<a name=\"SO_%ld_%ld\" href=\"#IO_%ld_%ld\">&html;command '%s'&html;</a>&html; (outgoing MsgID=%ld, CmdID=%ld)"
, fStatusCode, (long)fRefMsgID, (long)fRefCmdID, (long)fRefMsgID
, (long)fRefCmdID, smlPCDataToCharP(fStatusElementP->cmd),
(long)fRefMsgID, (long)fRefCmdID ); }
3790 (long)fRefCmdID,{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "WARNING: RECEIVED NON-OK STATUS %hd for &html;<a name=\"SO_%ld_%ld\" href=\"#IO_%ld_%ld\">&html;command '%s'&html;</a>&html; (outgoing MsgID=%ld, CmdID=%ld)"
, fStatusCode, (long)fRefMsgID, (long)fRefCmdID, (long)fRefMsgID
, (long)fRefCmdID, smlPCDataToCharP(fStatusElementP->cmd),
(long)fRefMsgID, (long)fRefCmdID ); }
3791 smlPCDataToCharP(fStatusElementP->cmd),{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "WARNING: RECEIVED NON-OK STATUS %hd for &html;<a name=\"SO_%ld_%ld\" href=\"#IO_%ld_%ld\">&html;command '%s'&html;</a>&html; (outgoing MsgID=%ld, CmdID=%ld)"
, fStatusCode, (long)fRefMsgID, (long)fRefCmdID, (long)fRefMsgID
, (long)fRefCmdID, smlPCDataToCharP(fStatusElementP->cmd),
(long)fRefMsgID, (long)fRefCmdID ); }
3792 (long)fRefMsgID,{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "WARNING: RECEIVED NON-OK STATUS %hd for &html;<a name=\"SO_%ld_%ld\" href=\"#IO_%ld_%ld\">&html;command '%s'&html;</a>&html; (outgoing MsgID=%ld, CmdID=%ld)"
, fStatusCode, (long)fRefMsgID, (long)fRefCmdID, (long)fRefMsgID
, (long)fRefCmdID, smlPCDataToCharP(fStatusElementP->cmd),
(long)fRefMsgID, (long)fRefCmdID ); }
3793 (long)fRefCmdID{ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "WARNING: RECEIVED NON-OK STATUS %hd for &html;<a name=\"SO_%ld_%ld\" href=\"#IO_%ld_%ld\">&html;command '%s'&html;</a>&html; (outgoing MsgID=%ld, CmdID=%ld)"
, fStatusCode, (long)fRefMsgID, (long)fRefCmdID, (long)fRefMsgID
, (long)fRefCmdID, smlPCDataToCharP(fStatusElementP->cmd),
(long)fRefMsgID, (long)fRefCmdID ); }
3794 )){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ( "WARNING: RECEIVED NON-OK STATUS %hd for &html;<a name=\"SO_%ld_%ld\" href=\"#IO_%ld_%ld\">&html;command '%s'&html;</a>&html; (outgoing MsgID=%ld, CmdID=%ld)"
, fStatusCode, (long)fRefMsgID, (long)fRefCmdID, (long)fRefMsgID
, (long)fRefCmdID, smlPCDataToCharP(fStatusElementP->cmd),
(long)fRefMsgID, (long)fRefCmdID ); }
;
3795 }
3796 else {
3797 // show what we have received
3798 PDEBUGPRINTFX(DBG_HOT,({ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "RECEIVED STATUS %hd for for &html;<a name=\"SO_%ld_%ld\" href=\"#IO_%ld_%ld\">&html;command '%s'&html;</a>&html; (outgoing MsgID=%ld, CmdID=%ld)"
, fStatusCode, (long)fRefMsgID, (long)fRefCmdID, (long)fRefMsgID
, (long)fRefCmdID, smlPCDataToCharP(fStatusElementP->cmd),
(long)fRefMsgID, (long)fRefCmdID ); }
3799 "RECEIVED STATUS %hd for for &html;<a name=\"SO_%ld_%ld\" href=\"#IO_%ld_%ld\">&html;command '%s'&html;</a>&html; (outgoing MsgID=%ld, CmdID=%ld)",{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "RECEIVED STATUS %hd for for &html;<a name=\"SO_%ld_%ld\" href=\"#IO_%ld_%ld\">&html;command '%s'&html;</a>&html; (outgoing MsgID=%ld, CmdID=%ld)"
, fStatusCode, (long)fRefMsgID, (long)fRefCmdID, (long)fRefMsgID
, (long)fRefCmdID, smlPCDataToCharP(fStatusElementP->cmd),
(long)fRefMsgID, (long)fRefCmdID ); }
3800 fStatusCode,{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "RECEIVED STATUS %hd for for &html;<a name=\"SO_%ld_%ld\" href=\"#IO_%ld_%ld\">&html;command '%s'&html;</a>&html; (outgoing MsgID=%ld, CmdID=%ld)"
, fStatusCode, (long)fRefMsgID, (long)fRefCmdID, (long)fRefMsgID
, (long)fRefCmdID, smlPCDataToCharP(fStatusElementP->cmd),
(long)fRefMsgID, (long)fRefCmdID ); }
3801 (long)fRefMsgID,{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "RECEIVED STATUS %hd for for &html;<a name=\"SO_%ld_%ld\" href=\"#IO_%ld_%ld\">&html;command '%s'&html;</a>&html; (outgoing MsgID=%ld, CmdID=%ld)"
, fStatusCode, (long)fRefMsgID, (long)fRefCmdID, (long)fRefMsgID
, (long)fRefCmdID, smlPCDataToCharP(fStatusElementP->cmd),
(long)fRefMsgID, (long)fRefCmdID ); }
3802 (long)fRefCmdID,{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "RECEIVED STATUS %hd for for &html;<a name=\"SO_%ld_%ld\" href=\"#IO_%ld_%ld\">&html;command '%s'&html;</a>&html; (outgoing MsgID=%ld, CmdID=%ld)"
, fStatusCode, (long)fRefMsgID, (long)fRefCmdID, (long)fRefMsgID
, (long)fRefCmdID, smlPCDataToCharP(fStatusElementP->cmd),
(long)fRefMsgID, (long)fRefCmdID ); }
3803 (long)fRefMsgID,{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "RECEIVED STATUS %hd for for &html;<a name=\"SO_%ld_%ld\" href=\"#IO_%ld_%ld\">&html;command '%s'&html;</a>&html; (outgoing MsgID=%ld, CmdID=%ld)"
, fStatusCode, (long)fRefMsgID, (long)fRefCmdID, (long)fRefMsgID
, (long)fRefCmdID, smlPCDataToCharP(fStatusElementP->cmd),
(long)fRefMsgID, (long)fRefCmdID ); }
3804 (long)fRefCmdID,{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "RECEIVED STATUS %hd for for &html;<a name=\"SO_%ld_%ld\" href=\"#IO_%ld_%ld\">&html;command '%s'&html;</a>&html; (outgoing MsgID=%ld, CmdID=%ld)"
, fStatusCode, (long)fRefMsgID, (long)fRefCmdID, (long)fRefMsgID
, (long)fRefCmdID, smlPCDataToCharP(fStatusElementP->cmd),
(long)fRefMsgID, (long)fRefCmdID ); }
3805 smlPCDataToCharP(fStatusElementP->cmd),{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "RECEIVED STATUS %hd for for &html;<a name=\"SO_%ld_%ld\" href=\"#IO_%ld_%ld\">&html;command '%s'&html;</a>&html; (outgoing MsgID=%ld, CmdID=%ld)"
, fStatusCode, (long)fRefMsgID, (long)fRefCmdID, (long)fRefMsgID
, (long)fRefCmdID, smlPCDataToCharP(fStatusElementP->cmd),
(long)fRefMsgID, (long)fRefCmdID ); }
3806 (long)fRefMsgID,{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "RECEIVED STATUS %hd for for &html;<a name=\"SO_%ld_%ld\" href=\"#IO_%ld_%ld\">&html;command '%s'&html;</a>&html; (outgoing MsgID=%ld, CmdID=%ld)"
, fStatusCode, (long)fRefMsgID, (long)fRefCmdID, (long)fRefMsgID
, (long)fRefCmdID, smlPCDataToCharP(fStatusElementP->cmd),
(long)fRefMsgID, (long)fRefCmdID ); }
3807 (long)fRefCmdID{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "RECEIVED STATUS %hd for for &html;<a name=\"SO_%ld_%ld\" href=\"#IO_%ld_%ld\">&html;command '%s'&html;</a>&html; (outgoing MsgID=%ld, CmdID=%ld)"
, fStatusCode, (long)fRefMsgID, (long)fRefCmdID, (long)fRefMsgID
, (long)fRefCmdID, smlPCDataToCharP(fStatusElementP->cmd),
(long)fRefMsgID, (long)fRefCmdID ); }
3808 )){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ( "RECEIVED STATUS %hd for for &html;<a name=\"SO_%ld_%ld\" href=\"#IO_%ld_%ld\">&html;command '%s'&html;</a>&html; (outgoing MsgID=%ld, CmdID=%ld)"
, fStatusCode, (long)fRefMsgID, (long)fRefCmdID, (long)fRefMsgID
, (long)fRefCmdID, smlPCDataToCharP(fStatusElementP->cmd),
(long)fRefMsgID, (long)fRefCmdID ); }
;
3809 }
3810 // - source and target refs
3811 if (PDEBUGMASKgetDbgMask() & DBG_HOT0x00000001) {
3812 SmlTargetRefListPtr_t targetrefP = fStatusElementP->targetRefList;
3813 while (targetrefP) {
3814 // target ref available
3815 PDEBUGPRINTFX(DBG_HOT,("- TargetRef (remoteID) = '%s'",smlPCDataToCharP(targetrefP->targetRef))){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("- TargetRef (remoteID) = '%s'"
,smlPCDataToCharP(targetrefP->targetRef)); }
;
3816 // next
3817 targetrefP=targetrefP->next;
3818 }
3819 SmlSourceRefListPtr_t sourcerefP = fStatusElementP->sourceRefList;
3820 while (sourcerefP) {
3821 // target ref available
3822 PDEBUGPRINTFX(DBG_HOT,("- SourceRef (localID) = '%s'",smlPCDataToCharP(sourcerefP->sourceRef))){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("- SourceRef (localID) = '%s'"
,smlPCDataToCharP(sourcerefP->sourceRef)); }
;
3823 // next
3824 sourcerefP=sourcerefP->next;
3825 }
3826 }
3827 // - optional items
3828 if (PDEBUGMASKgetDbgMask() & DBG_ERROR0x00000002) {
3829 SmlItemListPtr_t itemlistP = fStatusElementP->itemList;
3830 while (itemlistP) {
3831 // item available
3832 PDEBUGPRINTFX(DBG_HOT,("- Item data = %s",smlItemDataToCharP(itemlistP->item))){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("- Item data = %s"
,smlItemDataToCharP(itemlistP->item)); }
;
3833 // next
3834 itemlistP=itemlistP->next;
3835 }
3836 }
3837 #endif
3838 return true; // good status
3839 }
3840 else return false; // no proto element, bad command
3841} // TStatusCommand::analyze
3842
3843
3844
3845// returns true if command must be put to the waiting-for-status queue.
3846// If false, command can be deleted
3847bool TStatusCommand::issue(
3848 uInt32 aAsCmdID, // command ID to be used
3849 uInt32 aInMsgID, // message ID in which command is being issued
3850 bool aNoResp // dummy here, because Status has always no response
3851)
3852{
3853 // now issue
3854 if (fStatusElementP) {
3855 // prepare basic stuff
3856 TSmlCommand::issue(aAsCmdID,aInMsgID,true);
3857 // set status code in structure (but only once, in case we are evaluating before issuing)
3858 if (fStatusElementP->data==NULL__null) fStatusElementP->data=newPCDataLong(fStatusCode);
3859 // Status is meant to have a CmdID. SyncML 1.0 docs say no, but this was corrected in 1.0.1
3860 // issue command with SyncML toolkit (no flags)
3861 PrepareIssue(&fStatusElementP->cmdID,NULL__null); // CmdID (SyncML 1.0.1 conformant)
3862 if (!fEvalMode) {
3863 // PrepareIssue(NULL,NULL); // no CmdID, no flags
3864 #ifdef SYDEBUG2
3865 if (fSessionP->fXMLtranslate && fSessionP->fOutgoingXMLInstance)
3866 smlStatusCmd(fSessionP->fOutgoingXMLInstance,fStatusElementP);
3867 #endif
3868 Ret_t err;
3869 if ((err=smlStatusCmd(fSessionP->getSmlWorkspaceID(),fStatusElementP))!=SML_ERR_OK0x00) {
3870 SYSYNC_THROW(TSmlException("smlStatusCmd",err))throw TSmlException("smlStatusCmd",err);
3871 }
3872 FinalizeIssue();
3873 // show debug
3874 #ifdef SYDEBUG2
3875 // - warning for non-ok (don't treat slow sync status as error)
3876 if (fStatusCode>=300 && fStatusCode!=508) {
3877 PDEBUGPRINTFX(DBG_ERROR,("WARNING: Non-OK Status %hd returned to remote!",fStatusCode)){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("WARNING: Non-OK Status %hd returned to remote!"
,fStatusCode); }
;
3878 }
3879 // - what was issued
3880 PDEBUGPRINTFX(DBG_HOT,("Status Code %s issued for Cmd=%s, (incoming MsgID=%s, CmdID=%s)",{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("Status Code %s issued for Cmd=%s, (incoming MsgID=%s, CmdID=%s)"
, smlPCDataToCharP(fStatusElementP->data), smlPCDataToCharP
(fStatusElementP->cmd), smlPCDataToCharP(fStatusElementP->
msgRef), smlPCDataToCharP(fStatusElementP->cmdRef) ); }
3881 smlPCDataToCharP(fStatusElementP->data),{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("Status Code %s issued for Cmd=%s, (incoming MsgID=%s, CmdID=%s)"
, smlPCDataToCharP(fStatusElementP->data), smlPCDataToCharP
(fStatusElementP->cmd), smlPCDataToCharP(fStatusElementP->
msgRef), smlPCDataToCharP(fStatusElementP->cmdRef) ); }
3882 smlPCDataToCharP(fStatusElementP->cmd),{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("Status Code %s issued for Cmd=%s, (incoming MsgID=%s, CmdID=%s)"
, smlPCDataToCharP(fStatusElementP->data), smlPCDataToCharP
(fStatusElementP->cmd), smlPCDataToCharP(fStatusElementP->
msgRef), smlPCDataToCharP(fStatusElementP->cmdRef) ); }
3883 smlPCDataToCharP(fStatusElementP->msgRef),{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("Status Code %s issued for Cmd=%s, (incoming MsgID=%s, CmdID=%s)"
, smlPCDataToCharP(fStatusElementP->data), smlPCDataToCharP
(fStatusElementP->cmd), smlPCDataToCharP(fStatusElementP->
msgRef), smlPCDataToCharP(fStatusElementP->cmdRef) ); }
3884 smlPCDataToCharP(fStatusElementP->cmdRef){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("Status Code %s issued for Cmd=%s, (incoming MsgID=%s, CmdID=%s)"
, smlPCDataToCharP(fStatusElementP->data), smlPCDataToCharP
(fStatusElementP->cmd), smlPCDataToCharP(fStatusElementP->
msgRef), smlPCDataToCharP(fStatusElementP->cmdRef) ); }
3885 )){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("Status Code %s issued for Cmd=%s, (incoming MsgID=%s, CmdID=%s)"
, smlPCDataToCharP(fStatusElementP->data), smlPCDataToCharP
(fStatusElementP->cmd), smlPCDataToCharP(fStatusElementP->
msgRef), smlPCDataToCharP(fStatusElementP->cmdRef) ); }
;
3886 // - source and target refs
3887 if (PDEBUGTEST(DBG_HOT)(((0x00000001) & getDbgMask()) == (0x00000001))) {
3888 SmlTargetRefListPtr_t targetrefP = fStatusElementP->targetRefList;
3889 while (targetrefP) {
3890 // target ref available
3891 PDEBUGPRINTFX(DBG_HOT,("- TargetRef (localID) = '%s'",smlPCDataToCharP(targetrefP->targetRef))){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("- TargetRef (localID) = '%s'"
,smlPCDataToCharP(targetrefP->targetRef)); }
3892 // next
3893 targetrefP=targetrefP->next;
3894 }
3895 SmlSourceRefListPtr_t sourcerefP = fStatusElementP->sourceRefList;
3896 while (sourcerefP) {
3897 // target ref available
3898 PDEBUGPRINTFX(DBG_HOT,("- SourceRef (remoteID) = '%s'",smlPCDataToCharP(sourcerefP->sourceRef))){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("- SourceRef (remoteID) = '%s'"
,smlPCDataToCharP(sourcerefP->sourceRef)); }
3899 // next
3900 sourcerefP=sourcerefP->next;
3901 }
3902 }
3903 #endif
3904 // we don't need the status structure any more, free (and NULL ptr) now
3905 FreeSmlElement();
3906 }
3907 else
3908 return smlStatusCmd(fSessionP->getSmlWorkspaceID(),fStatusElementP)==SML_ERR_OK0x00;
3909 }
3910 else {
3911 DEBUGPRINTFX(DBG_ERROR,("*** Tried to issue NULL status")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("*** Tried to issue NULL status"
); }
;
3912 }
3913 // status does NOT await any answer, and can be deleted after issuing
3914 return false; // don't queue for status
3915} // TStatusCommand::issue
3916
3917
3918// add a target Ref to the status (no op if ref is NULL)
3919void TStatusCommand::addTargetRef(
3920 const char *aTargetRef // Target LocURI of an item this status applies to
3921)
3922{
3923 SmlTargetRefListPtr_t *targetreflistPP;
3924 if (fStatusElementP && aTargetRef && *aTargetRef) {
3925 // Note: empty refs will not be added
3926 targetreflistPP=&(fStatusElementP->targetRefList);
3927 // find last targetreflist pointer
3928 while (*targetreflistPP) {
3929 targetreflistPP=&((*targetreflistPP)->next);
3930 }
3931 // targetreflistPP now points to a NULL pointer which must be replaced by addr of new targetreflist entry
3932 *targetreflistPP = SML_NEW(SmlTargetRefList_t)((SmlTargetRefList_t*) _smlMalloc(sizeof(SmlTargetRefList_t))
)
;
3933 (*targetreflistPP)->next=NULL__null;
3934 (*targetreflistPP)->targetRef=
3935 newPCDataString(aTargetRef);
3936 }
3937} // TStatusCommand::addTargetRef
3938
3939
3940// add a source Ref to the status (no op if ref is NULL)
3941void TStatusCommand::addSourceRef(
3942 const char *aSourceRef // Target LocURI of an item this status applies to
3943)
3944{
3945 SmlSourceRefListPtr_t *sourcereflistPP;
3946 if (fStatusElementP && aSourceRef && *aSourceRef) {
3947 // Note: empty refs will not be added
3948 sourcereflistPP=&(fStatusElementP->sourceRefList);
3949 // find last sourcereflist pointer
3950 while (*sourcereflistPP) {
3951 sourcereflistPP=&((*sourcereflistPP)->next);
3952 }
3953 // sourcereflistPP now points to a NULL pointer which must be replaced by addr of new sourcereflist entry
3954 *sourcereflistPP = SML_NEW(SmlSourceRefList_t)((SmlSourceRefList_t*) _smlMalloc(sizeof(SmlSourceRefList_t))
)
;
3955 (*sourcereflistPP)->next=NULL__null;
3956 (*sourcereflistPP)->sourceRef=
3957 newPCDataString(aSourceRef);
3958 }
3959} // TStatusCommand::addSourceRef
3960
3961
3962// add a String Item to the status (only if not empty)
3963void TStatusCommand::addItemString(
3964 const char *aItemString // item string to be added
3965)
3966{
3967 if (fStatusElementP && aItemString && *aItemString) {
3968 addItem(newStringDataItem(aItemString));
3969 }
3970} // TStatusCommand::addItemString
3971
3972
3973// add an Item to the status
3974void TStatusCommand::addItem(
3975 SmlItemPtr_t aItemP // existing item data structure, ownership is passed to Status
3976)
3977{
3978 if (fStatusElementP)
3979 addItemToList(aItemP,&(fStatusElementP->itemList));
3980} // TStatusCommand::addItem
3981
3982
3983// move items from another status to this one (passes ownership of items and deletes them from original)
3984void TStatusCommand::moveItemsFrom(TStatusCommand *aStatusCommandP)
3985{
3986 if (fStatusElementP && aStatusCommandP) {
3987 // pass item list to new owner
3988 fStatusElementP->itemList = aStatusCommandP->fStatusElementP->itemList;
3989 // remove items from original
3990 aStatusCommandP->fStatusElementP->itemList = NULL__null;
3991 }
3992} // TStatusCommand::moveItemsFrom
3993
3994
3995
3996// add Challenge to status
3997// challenge data structure ownership is passed to Status
3998void TStatusCommand::setChallenge(SmlChalPtr_t aChallengeP)
3999{
4000 if (fStatusElementP) {
4001 if (fStatusElementP->chal) {
4002 // get rid of old challenge
4003 smlFreeChalPtr(fStatusElementP->chal);
4004 fStatusElementP->chal=NULL__null;
4005 }
4006 // set new
4007 fStatusElementP->chal=aChallengeP;
4008 }
4009} // TStatusCommand::setChallenge
4010
4011
4012// set Status code
4013void TStatusCommand::setStatusCode(TSyError aStatusCode)
4014{
4015 fStatusCode = aStatusCode;
4016} // TStatusCommand::setStatusCode
4017
4018
4019void TStatusCommand::FreeSmlElement(void)
4020{
4021 // remove SyncML toolkit element(s)
4022 FREEPROTOELEMENT(fStatusElementP);
4023} // TResultsCommand::FreeSmlElement
4024
4025
4026TStatusCommand::~TStatusCommand()
4027{
4028 // free command elements, if any (use explicit invocation as this is a destructor)
4029 TStatusCommand::FreeSmlElement();
4030} // TStatusCommand::TStatusCommand
4031
4032
4033/* end of TStatusCommand implementation */
4034
4035
4036/*
4037 * Implementation of TResultsCommand
4038 */
4039
4040// constructor for receiving command
4041TResultsCommand::TResultsCommand(
4042 TSyncSession *aSessionP, // associated session (for callbacks)
4043 uInt32 aMsgID, // the Message ID of the command
4044 SmlResultsPtr_t aResultsElementP // associated syncml protocol element
4045) :
4046 TSmlCommand(scmd_results,false,aSessionP,aMsgID)
4047{
4048 // save element
4049 fResultsElementP = aResultsElementP;
4050} // TResultsCommand::TResultsCommand
4051
4052
4053// constructor for generating results
4054TResultsCommand::TResultsCommand(
4055 TSyncSession *aSessionP, // associated session (for callbacks)
4056 TSmlCommand *aCommandP, // command these results refer to
4057 const char *aTargetRef, // target reference
4058 const char *aSourceRef // source reference
4059) :
4060 TSmlCommand(scmd_results,true,aSessionP)
4061{
4062 // create internal results element
4063 fResultsElementP = SML_NEW(SmlResults_t)((SmlResults_t*) _smlMalloc(sizeof(SmlResults_t)));
4064 // set proto element type to make it auto-disposable
4065 fResultsElementP->elementType=SML_PE_RESULTS;
4066 // Cmd ID is now empty (will be set when issued)
4067 fResultsElementP->cmdID=NULL__null;
4068 // results refer to message of specified command
4069 fResultsElementP->msgRef=newPCDataLong(aCommandP->getMsgID());
4070 // results refer to ID of specified command
4071 fResultsElementP->cmdRef=newPCDataLong(aCommandP->getCmdID());
4072 // no meta for now
4073 fResultsElementP->meta=NULL__null;
4074 // target reference if specified
4075 if (aTargetRef) fResultsElementP->targetRef=newPCDataString(aTargetRef);
4076 else fResultsElementP->targetRef=NULL__null;
4077 // source reference if specified
4078 if (aSourceRef) fResultsElementP->sourceRef=newPCDataString(aSourceRef);
4079 else fResultsElementP->sourceRef=NULL__null;
4080 // no items for now
4081 fResultsElementP->itemList=NULL__null;
4082} // TResultsCommand::TResultsCommand
4083
4084
4085
4086// returns true if command must be put to the waiting-for-status queue.
4087// If false, command can be deleted
4088bool TResultsCommand::issue(
4089 uInt32 aAsCmdID, // command ID to be used
4090 uInt32 aInMsgID, // message ID in which command is being issued
4091 bool aNoResp // issue without wanting response
4092)
4093{
4094 // prepare
4095 TSmlCommand::issue(aAsCmdID,aInMsgID,aNoResp);
4096 // now issue
4097 if (fResultsElementP) {
4098 // issue command with SyncML toolkit (no flags)
4099 PrepareIssue(&fResultsElementP->cmdID,NULL__null);
4100 if (!fEvalMode) {
4101 #ifdef SYDEBUG2
4102 if (fSessionP->fXMLtranslate && fSessionP->fOutgoingXMLInstance)
4103 smlResultsCmd(fSessionP->fOutgoingXMLInstance,fResultsElementP);
4104 #endif
4105 Ret_t err;
4106 if ((err=smlResultsCmd(fSessionP->getSmlWorkspaceID(),fResultsElementP))!=SML_ERR_OK0x00) {
4107 SYSYNC_THROW(TSmlException("smlResultsCmd",err))throw TSmlException("smlResultsCmd",err);
4108 }
4109 FinalizeIssue();
4110 // show debug
4111 DEBUGPRINTFX(DBG_HOT,("results issued for (incoming MsgID=%s, CmdID=%s)",{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("results issued for (incoming MsgID=%s, CmdID=%s)"
, smlPCDataToCharP(fResultsElementP->msgRef), smlPCDataToCharP
(fResultsElementP->cmdRef) ); }
4112 smlPCDataToCharP(fResultsElementP->msgRef),{ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("results issued for (incoming MsgID=%s, CmdID=%s)"
, smlPCDataToCharP(fResultsElementP->msgRef), smlPCDataToCharP
(fResultsElementP->cmdRef) ); }
4113 smlPCDataToCharP(fResultsElementP->cmdRef){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("results issued for (incoming MsgID=%s, CmdID=%s)"
, smlPCDataToCharP(fResultsElementP->msgRef), smlPCDataToCharP
(fResultsElementP->cmdRef) ); }
4114 )){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("results issued for (incoming MsgID=%s, CmdID=%s)"
, smlPCDataToCharP(fResultsElementP->msgRef), smlPCDataToCharP
(fResultsElementP->cmdRef) ); }
;
4115 // we don't need the results structure any more, free (and NULL ptr) now
4116 FreeSmlElement();
4117 }
4118 else
4119 return smlResultsCmd(fSessionP->getSmlWorkspaceID(),fResultsElementP)==SML_ERR_OK0x00;
4120 }
4121 else {
4122 DEBUGPRINTFX(DBG_ERROR,("*** Tried to issue NULL result")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("*** Tried to issue NULL result"
); }
;
4123 }
4124 // SyncML 1.0: result does NOT await any answer, and can be deleted after issuing
4125 // SyncML 1.0.1: all commands will receive a status (except Status)
4126 return true; // queue for status/result
4127} // TResultsCommand::issue
4128
4129
4130// add a String Item to the results
4131void TResultsCommand::addItemString(
4132 const char *aItemString // item string to be added
4133)
4134{
4135 if (fResultsElementP && aItemString) {
4136 addItem(newStringDataItem(aItemString));
4137 }
4138} // TResultsCommand::addItemString
4139
4140
4141// add an Item to the results
4142void TResultsCommand::addItem(
4143 SmlItemPtr_t aItemP // existing item data structure, ownership is passed to Results
4144)
4145{
4146 if (fResultsElementP)
4147 addItemToList(aItemP,&(fResultsElementP->itemList));
4148} // TResultsCommand::addItem
4149
4150
4151// set Meta of the results command
4152void TResultsCommand::setMeta(
4153 SmlPcdataPtr_t aMetaP // existing meta data structure, ownership is passed to Get
4154)
4155{
4156 if (fResultsElementP)
4157 fResultsElementP->meta=aMetaP;
4158} // TResultsCommand::setMeta
4159
4160
4161
4162
4163// analyze command (but do not yet execute)
4164bool TResultsCommand::analyze(TPackageStates aPackageState)
4165{
4166 TSmlCommand::analyze(aPackageState);
4167 // get Command ID and flags
4168 if (fResultsElementP) {
4169 StartProcessing(fResultsElementP->cmdID,0);
4170 return true;
4171 }
4172 else return false; // no proto element, bad command
4173} // TResultsCommand::analyze
4174
4175
4176// execute command (perform real actions, generate status)
4177// returns true if command has executed and can be deleted
4178bool TResultsCommand::execute(void)
4179{
4180 TStatusCommand *statusCmdP=NULL__null;
4181 SmlItemListPtr_t thisitemnode,nextitemnode;
4182
4183 // process items
4184 thisitemnode=fResultsElementP->itemList;
4185 while (thisitemnode) {
4186 nextitemnode = thisitemnode->next;
4187 if (!thisitemnode->item) SYSYNC_THROW(TSyncException("Results with NULL item"))throw TSyncException("Results with NULL item");
4188 // get Source LocURI
4189 string locURI=smlSrcTargLocURIToCharP(thisitemnode->item->source);
4190 DEBUGPRINTFX(DBG_HOT,("processing item with locURI=%s",locURI.c_str())){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("processing item with locURI=%s"
,locURI.c_str()); }
;
4191 // let session (and descendants) process it
4192 // - default to ok status
4193 statusCmdP = newStatusCommand(200);
4194 fSessionP->processPutResultItem(false,locURI.c_str(),this,thisitemnode->item,*statusCmdP);
4195 #ifdef RESULTS_SENDS_STATUS1
4196 // now complete and issue status
4197 statusCmdP->addSourceRef(locURI.c_str()); // add source ref
4198 ISSUE_COMMAND_ROOT(fSessionP,statusCmdP){ TSmlCommand* p=statusCmdP; statusCmdP=__null; fSessionP->
issueRootPtr(p); }
;
4199 #else
4200 // suppress (forget) status
4201 delete statusCmdP;
4202 #endif
4203 // next item
4204 thisitemnode=nextitemnode;
4205 }
4206 // free element
4207 FreeSmlElement();
4208 // done with command, delete it now: return true
4209 return true;
4210} // TResultsCommand::execute
4211
4212
4213void TResultsCommand::FreeSmlElement(void)
4214{
4215 // remove SyncML toolkit element(s)
4216 FREEPROTOELEMENT(fResultsElementP);
4217} // TResultsCommand::FreeSmlElement
4218
4219
4220TResultsCommand::~TResultsCommand()
4221{
4222 // free command elements, if any (use explicit invocation as this is a destructor)
4223 TResultsCommand::FreeSmlElement();
4224} // TResultsCommand::TResultsCommand
4225
4226
4227/* end of TResultsCommand implementation */
4228
4229
4230/*
4231 * Implementation of TDevInfResultsCommand
4232 */
4233
4234
4235// constructor for generating devInf results
4236TDevInfResultsCommand::TDevInfResultsCommand(
4237 TSyncSession *aSessionP, // associated session (for callbacks)
4238 TSmlCommand *aCommandP // command these results refer to
4239) :
4240 /* %%% if strictly following example in SyncML protocol specs
4241 * DevInf results don't have a source or target ref, only the item has
4242 TResultsCommand(aSessionP,aCommandP,SYNCML_DEVINF_LOCURI,NULL)
4243 */
4244 TResultsCommand(aSessionP,aCommandP,NULL__null,NULL__null)
4245{
4246 // standard result is now created
4247 // - create meta type
4248 /* %%% if strictly following example in SyncML protocol specs, meta
4249 * must be defined in the result/put command, not the individual item
4250 */
4251 string metatype=SYNCML_DEVINF_META_TYPE"application/vnd.syncml-devinf";
4252 fSessionP->addEncoding(metatype);
4253 fResultsElementP->meta=newMetaType(metatype.c_str());
4254 // - add local DevInf item to result
4255 // Note: explicit GET always returns entire devInf (all datastores)
4256 addItem(fSessionP->getLocalDevInfItem(false,false));
4257} // TDevInfResultsCommand::TDevInfResultsCommand
4258
4259
4260// - try to shrink command by at least aReduceByBytes
4261// Returns false if shrink is not possible
4262bool TDevInfResultsCommand::shrinkCommand(sInt32 aReduceByBytes)
4263{
4264 // measure current size (with current CmdID/MsgID)
4265 sInt32 origfree = evalIssue(fCmdID,fMsgID,fNoResp);
4266 // extract original devInf
4267 SmlItemPtr_t origDevInf = fResultsElementP->itemList->item;
4268 // remove it from the item list
4269 fResultsElementP->itemList->item = NULL__null;
4270 smlFreeItemList(fResultsElementP->itemList);
4271 fResultsElementP->itemList = NULL__null;
4272 // create reduced version of the devInf
4273 // - only alerted datastores if initialisation is complete (i.e. we KNOW which datastores the sync is about)
4274 // - no CTCap property lists
4275 SmlItemPtr_t reducedDevInf =
4276 fSessionP->getLocalDevInfItem(
4277 fSessionP->getIncomingState()>psta_init, // alerted only if init complete
4278 true // no CTCap property lists
4279 );
4280 // insert it into command
4281 addItem(reducedDevInf);
4282 // measure again
4283 sInt32 nowfree = evalIssue(fCmdID,fMsgID,fNoResp);
4284 // decide if we are successful
4285 if (nowfree-origfree>=aReduceByBytes) {
4286 // new devinf matches size requirement
4287 smlFreeItemPtr(origDevInf); // discard original devInf
4288 return true; // shrink successful
4289 }
4290 else {
4291 // new reduced devInf is still too big
4292 fResultsElementP->itemList->item = origDevInf; // restore oiginal devInf
4293 smlFreeItemPtr(reducedDevInf); // discard reduced one
4294 return false; // cannot shrink enough
4295 }
4296} // TDevInfResultsCommand::shrinkCommand
4297
4298
4299
4300// mark devinf as sent when issuing command
4301bool TDevInfResultsCommand::issue(
4302 uInt32 aAsCmdID, // command ID to be used
4303 uInt32 aInMsgID, // message ID in which command is being issued
4304 bool aNoResp
4305)
4306{
4307 fSessionP->remoteGotDevinf();
4308 return TResultsCommand::issue(aAsCmdID,aInMsgID,aNoResp);
4309} // TDevInfResultsCommand::issue
4310
4311
4312void TDevInfResultsCommand::FreeSmlElement(void)
4313{
4314 // remove SyncML toolkit element(s)
4315 // - result might already be freed!
4316 if (fResultsElementP) {
4317 FREEPROTOELEMENT(fResultsElementP);
4318 }
4319} // TDevInfResultsCommand::FreeSmlElement
4320
4321
4322TDevInfResultsCommand::~TDevInfResultsCommand()
4323{
4324 // free command elements, if any (use explicit invocation as this is a destructor)
4325 TDevInfResultsCommand::FreeSmlElement();
4326 // NOTE: fResultsElementP is NULLed so invocation of base class destuctor does no harm
4327} // TDevInfResultsCommand::TDevInfResultsCommand
4328
4329
4330/* end of TDevInfResultsCommand implementation */
4331
4332
4333/*
4334 * Implementation of TDevInfResultsCommand
4335 */
4336
4337
4338// constructor for generating devinf Put command
4339TDevInfPutCommand::TDevInfPutCommand(
4340 TSyncSession *aSessionP // associated session (for callbacks)
4341) :
4342 TPutCommand(aSessionP)
4343{
4344 // standard put is now created
4345 // - create meta type
4346 /* %%% if strictly following example in SyncML protocol specs, meta
4347 * must be defined in the result/put command, not the individual item
4348 */
4349 string metatype=SYNCML_DEVINF_META_TYPE"application/vnd.syncml-devinf";
4350 fSessionP->addEncoding(metatype);
4351 fPutElementP->meta=newMetaType(metatype.c_str());
4352 // - add local DevInf item to result
4353 // Note: PUT of server only returns alerted datastore's devInf
4354 addItem(fSessionP->getLocalDevInfItem(IS_SERVER(getSyncAppBase()->isServer()),false));
4355} // TDevInfPutCommand::TDevInfPutCommand
4356
4357
4358// mark devinf as sent when issuing command
4359bool TDevInfPutCommand::issue(
4360 uInt32 aAsCmdID, // command ID to be used
4361 uInt32 aInMsgID, // message ID in which command is being issued
4362 bool aNoResp
4363)
4364{
4365 fSessionP->remoteGotDevinf();
4366 return TPutCommand::issue(aAsCmdID,aInMsgID,aNoResp);
4367} // TDevInfPutCommand::issue
4368
4369
4370void TDevInfPutCommand::FreeSmlElement(void)
4371{
4372 // remove SyncML toolkit element(s)
4373 // - result might already be freed!
4374 if (fPutElementP) {
4375 FREEPROTOELEMENT(fPutElementP);
4376 }
4377} // TDevInfPutCommand::FreeSmlElement
4378
4379
4380TDevInfPutCommand::~TDevInfPutCommand()
4381{
4382 // free command elements, if any (use explicit invocation as this is a destructor)
4383 TDevInfPutCommand::FreeSmlElement();
4384 // NOTE: fResultsElementP is NULLed so invocation of base class destuctor does not harm
4385} // TDevInfPutCommand::~TDevInfPutCommand
4386
4387/* end of TDevInfPutCommand implementation */
4388
4389#endif // SYNCCOMMAND_PART2_EXCLUDE
4390
4391// eof