1 /*************************************************************************/ 2 /* module: SyncML Command Dispatcher */ 3 /* */ 4 /* file: mgrcmddispatcher.c */ 5 /* target system: all */ 6 /* target OS: all */ 7 /* */ 8 /* Description: */ 9 /* Core module for dispatching parsed commands and invoking callback */ 10 /* functions of the application */ 11 /*************************************************************************/ 12 13 14 /* 15 * Copyright Notice 16 * Copyright (c) Ericsson, IBM, Lotus, Matsushita Communication 17 * Industrial Co., Ltd., Motorola, Nokia, Openwave Systems, Inc., 18 * Palm, Inc., Psion, Starfish Software, Symbian, Ltd. (2001). 19 * All Rights Reserved. 20 * Implementation of all or part of any Specification may require 21 * licenses under third party intellectual property rights, 22 * including without limitation, patent rights (such a third party 23 * may or may not be a Supporter). The Sponsors of the Specification 24 * are not responsible and shall not be held responsible in any 25 * manner for identifying or failing to identify any or all such 26 * third party intellectual property rights. 27 * 28 * THIS DOCUMENT AND THE INFORMATION CONTAINED HEREIN ARE PROVIDED 29 * ON AN "AS IS" BASIS WITHOUT WARRANTY OF ANY KIND AND ERICSSON, IBM, 30 * LOTUS, MATSUSHITA COMMUNICATION INDUSTRIAL CO. LTD, MOTOROLA, 31 * NOKIA, PALM INC., PSION, STARFISH SOFTWARE AND ALL OTHER SYNCML 32 * SPONSORS DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING 33 * BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION 34 * HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF 35 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT 36 * SHALL ERICSSON, IBM, LOTUS, MATSUSHITA COMMUNICATION INDUSTRIAL CO., 37 * LTD, MOTOROLA, NOKIA, PALM INC., PSION, STARFISH SOFTWARE OR ANY 38 * OTHER SYNCML SPONSOR BE LIABLE TO ANY PARTY FOR ANY LOSS OF 39 * PROFITS, LOSS OF BUSINESS, LOSS OF USE OF DATA, INTERRUPTION OF 40 * BUSINESS, OR FOR DIRECT, INDIRECT, SPECIAL OR EXEMPLARY, INCIDENTAL, 41 * PUNITIVE OR CONSEQUENTIAL DAMAGES OF ANY KIND IN CONNECTION WITH 42 * THIS DOCUMENT OR THE INFORMATION CONTAINED HEREIN, EVEN IF ADVISED 43 * OF THE POSSIBILITY OF SUCH LOSS OR DAMAGE. 44 * 45 * The above notice and this paragraph must be included on all copies 46 * of this document that are made. 47 * 48 */ 49 50 51 52 53 /************************************************************************* 54 * Definitions 55 *************************************************************************/ 56 57 58 #include <define.h> 59 /* Include Headers */ 60 #include <smldef.h> 61 #include <smldtd.h> 62 #include <smlerr.h> 63 64 #include "libmem.h" 65 #include "xltdec.h" 66 #include "mgr.h" 67 68 69 70 /* Used external functions */ 71 #ifndef __SML_LITE__ /* these API calls are NOT included in the Toolkit lite version */ 72 extern Ret_t addInfo(InstanceInfoPtr_t pInfo); 73 extern InstanceInfoPtr_t findInfo(InstanceID_t id); 74 extern Ret_t removeInfo(InstanceID_t id); 75 #endif 76 Ret_t smlLockReadBuffer(InstanceID_t id, MemPtr_t *pReadPosition, MemSize_t *usedSize); 77 Ret_t smlUnlockReadBuffer(InstanceID_t id, MemSize_t processedBytes); 78 79 /* Prototypes of exported SyncML API functions */ 80 extern Ret_t smlProcessData(InstanceID_t id, SmlProcessMode_t mode); 81 82 /* Private function prototypes */ 83 static Ret_t mgrProcessNextCommand(InstanceID_t id, InstanceInfoPtr_t pInstanceInfo); 84 static Ret_t mgrProcessStartMessage(InstanceID_t id, InstanceInfoPtr_t pInstanceInfo); 85 Ret_t mgrResetWorkspace (InstanceID_t id); 86 87 88 89 /************************************************************************* 90 * Exported SyncML API functions 91 *************************************************************************/ 92 93 94 95 96 /** 97 * FUNCTION: smlProcessData 98 * 99 * Start the parsing of the XML code in the workspace buffer, 100 * dispatches the interpreted command and calls the corresponding callback 101 * functions provided by the application. 102 * 103 * IN: InstanceID_t 104 * The SyncML instance id is used for referencing the 105 * workspace buffer from the XML content is parsed 106 * 107 * IN: ProcessMode_t 108 * Mode of processing, Defines, if only the first or next 109 * XML command is parsed or if all commands are processed 110 * subsequently until the end of the entire workspace buffer 111 * is reached. The NEXT_COMMAND flag defines the blocking mode, 112 * the ALL_COMMANDS tag defines the non-blocking mode. 113 * 114 * RETURN: Ret_t 115 */ 116 SML_API Ret_t smlProcessData(InstanceID_t id, SmlProcessMode_t mode) 117 { 118 /* --- Definitions --- */ 119 InstanceInfoPtr_t pInstanceInfo; // state info for the given instanceID 120 Ret_t rc; // Temporary return code saver 121 122 123 #ifdef NOWSM 124 pInstanceInfo = (InstanceInfoPtr_t)id; // ID is the instance info pointer 125 #else 126 /* --- Find that instance --- */ 127 #ifdef __SML_LITE__ /* Only ONE instance is supported in the Toolkit lite version */ 128 pInstanceInfo = mgrGetInstanceListAnchor(); 129 #else 130 pInstanceInfo = (InstanceInfoPtr_t) findInfo(id); 131 #endif 132 #endif 133 134 if (pInstanceInfo==NULL) return SML_ERR_MGR_INVALID_INSTANCE_INFO; 135 136 /* --- Are callback functions defined? --- */ 137 if (pInstanceInfo->callbacks==NULL) return SML_ERR_COMMAND_NOT_HANDLED; 138 139 /* --- Is parsing already in progress? --- */ 140 if (pInstanceInfo->decoderState==NULL) 141 { 142 /* No! Parse the Message header section first */ 143 rc = mgrProcessStartMessage(id, pInstanceInfo); 144 145 if (rc!=SML_ERR_OK) return rc; 146 } 147 148 149 /* --- Parse now the Message body section! --- */ 150 do { 151 rc=mgrProcessNextCommand(id, pInstanceInfo); 152 } while ( 153 // keep processing while no error occurs, 154 // AND the document end was not reached (decoderState has been invalidated), 155 // AND the ALL_COMMAND mode is used 156 (rc==SML_ERR_OK) 157 &&((pInstanceInfo->decoderState)!=NULL) 158 &&(mode==SML_ALL_COMMANDS) 159 ); 160 161 if (rc != SML_ERR_OK) { 162 // abort, unlock the buffer again without changing it's current position 163 smlUnlockReadBuffer(id, (MemSize_t)0); 164 // Reset the decoder module (free the decoding object) 165 xltDecReset(pInstanceInfo->decoderState); 166 // this decoding job is over! reset Instance Info pointer 167 pInstanceInfo->decoderState=NULL; 168 // Reset the Workspace (the remaining unparsed document fragment will be lost) 169 mgrResetWorkspace(id); 170 } 171 172 return rc; 173 } 174 175 176 /************************************************************************* 177 * Private Functions 178 *************************************************************************/ 179 180 181 182 183 /** 184 * FUNCTION: 185 * Parses the header information at the beginning of an SyncML document. 186 * 187 * IN: InstanceID 188 * current InstanceID to pass to callback functions 189 * 190 * IN/OUT: InstanceInfo 191 * state information of the given InstanceID (decoder state will be changed) 192 * 193 * RETURN: Return value of the Parser, 194 * SML_ERR_OK if next command was handled successfully 195 */ 196 static Ret_t mgrProcessStartMessage(InstanceID_t id, InstanceInfoPtr_t pInstanceInfo) 197 { 198 199 200 /* --- Definitions --- */ 201 Ret_t rc; // Temporary return code saver 202 SmlSyncHdrPtr_t pContent=NULL; // data of the command to process 203 MemPtr_t pCurrentReadPosition ; // current Position from which is read 204 MemPtr_t pBeginPosition; // saves the first position which has been reading 205 MemSize_t usedSize ; // size of used memory to be read 206 207 208 /* --- Get Read Access to the workspace --- */ 209 rc = smlLockReadBuffer(id, &pCurrentReadPosition, &usedSize); 210 211 if (rc!=SML_ERR_OK) { 212 // abort, unlock the buffer again without changing it's current position 213 smlUnlockReadBuffer(id, (MemSize_t)0); 214 return rc; 215 } 216 217 // Remember the position we have started reading 218 pBeginPosition=pCurrentReadPosition; 219 220 /* --- Start new decoding sequence and pass returned decoder status structure to instanceInfo --- */ 221 rc = xltDecInit(pInstanceInfo->instanceOptions->encoding, 222 pCurrentReadPosition+usedSize-1, &pCurrentReadPosition, 223 (XltDecoderPtr_t *)&(pInstanceInfo->decoderState), &pContent); 224 225 if (rc!=SML_ERR_OK) { 226 // abort, unlock the buffer again without changing it's current position 227 smlUnlockReadBuffer(id, (MemSize_t)0); 228 // Reset the decoder module (free the decoding object) 229 xltDecReset(pInstanceInfo->decoderState); 230 // this decoding job is over! reset Instance Info pointer 231 pInstanceInfo->decoderState=NULL; 232 // Reset the Workspace (the remaining unparsed document fragment will be lost) 233 mgrResetWorkspace(id); 234 return rc; 235 } 236 237 /* --- End Read Access to the workspace --- */ 238 rc = smlUnlockReadBuffer(id, (MemSize_t)pCurrentReadPosition-(MemSize_t)pBeginPosition); 239 if (rc!=SML_ERR_OK) return rc; 240 241 /* --- Perform callback to handle the beginning of a new message --- */ 242 if (pInstanceInfo->callbacks->startMessageFunc==NULL) return SML_ERR_COMMAND_NOT_HANDLED; 243 rc=pInstanceInfo->callbacks->startMessageFunc(id, pInstanceInfo->userData, pContent); 244 245 if (rc != SML_ERR_OK) 246 { 247 // abort, unlock the buffer again without changing it's current position 248 smlUnlockReadBuffer(id, (MemSize_t)0); 249 // Reset the decoder module (free the decoding object) 250 xltDecReset(pInstanceInfo->decoderState); 251 // this decoding job is over! reset Instance Info pointer 252 pInstanceInfo->decoderState=NULL; 253 // Reset the Workspace (the remaining unparsed document fragment will be lost) 254 mgrResetWorkspace(id); 255 } 256 257 return rc; 258 } 259 260 261 262 /** 263 * FUNCTION: 264 * Parses the next Sync Command in the sync document. 265 * 266 * IN: InstanceID 267 * current InstanceID to pass to callback functions 268 * 269 * IN: InstanceInfo 270 * state information of the given InstanceID 271 * 272 * RETURN: Return value of the Parser of the called application callback, 273 * SML_ERR_OK if next command was handled successfully 274 */ 275 static Ret_t mgrProcessNextCommand(InstanceID_t id, InstanceInfoPtr_t pInstanceInfo) 276 { 277 278 /* --- Definitions --- */ 279 Ret_t rc; // Temporary return code saver 280 SmlProtoElement_t cmdType; // ID of the command to process 281 VoidPtr_t pContent=NULL; // data of the command to process 282 MemPtr_t pCurrentReadPosition; // current Position from which is read 283 MemPtr_t pBeginPosition; // saves the first position which has been reading 284 MemSize_t usedSize; // size of used memory to be read 285 Boolean_t final; // flag indicates last message within a package 286 287 288 /* --- Get Read Access to the workspace --- */ 289 rc = smlLockReadBuffer(id, &pCurrentReadPosition, &usedSize); 290 291 if (rc!=SML_ERR_OK) { 292 // abort, unlock the buffer again without changing it's current position 293 smlUnlockReadBuffer(id, (MemSize_t)0); 294 return rc; 295 } 296 297 // Remember the position we have started reading 298 pBeginPosition=pCurrentReadPosition; 299 300 301 /* --- Parse next Command --- */ 302 rc = xltDecNext(pInstanceInfo->decoderState, pCurrentReadPosition+usedSize, &pCurrentReadPosition, &cmdType, &pContent); 303 304 if (rc!=SML_ERR_OK) { 305 // abort, unlock the buffer again without changing it's current position 306 smlUnlockReadBuffer(id, (MemSize_t)0); 307 // Reset the decoder module (free the decoding object) 308 xltDecReset(pInstanceInfo->decoderState); 309 // this decoding job is over! reset Instance Info pointer 310 pInstanceInfo->decoderState=NULL; 311 // Reset the Workspace (the remaining unparsed document fragment will be lost) 312 mgrResetWorkspace(id); 313 return rc; 314 } 315 316 /* --- End Read Access to the workspace --- */ 317 rc = smlUnlockReadBuffer(id, (MemSize_t)pCurrentReadPosition-(MemSize_t)pBeginPosition); 318 319 if (rc!=SML_ERR_OK) { 320 // abort, unlock the buffer again without changing it's current position 321 smlUnlockReadBuffer(id, (MemSize_t)0); 322 return rc; 323 } 324 325 /* --- Did we reach end of synchronization document? --- */ 326 if (((XltDecoderPtr_t)(pInstanceInfo->decoderState))->finished!=0) { 327 final = ((XltDecoderPtr_t)(pInstanceInfo->decoderState))->final; // flag is returned to appl. with callback 328 rc=xltDecTerminate(pInstanceInfo->decoderState); 329 330 if (rc!=SML_ERR_OK) 331 { 332 // abort, unlock the buffer again without changing it's current position 333 smlUnlockReadBuffer(id, (MemSize_t)0); 334 // Reset the decoder module (free the decoding object) 335 xltDecReset(pInstanceInfo->decoderState); 336 // this decoding job is over! reset Instance Info pointer 337 pInstanceInfo->decoderState=NULL; 338 // Reset the Workspace (the remaining unparsed document fragment will be lost) 339 mgrResetWorkspace(id); 340 return rc; 341 } 342 343 // this decoding job is over! reset Instance Info pointer 344 // (the decoding object itself has been freed by the decoder) 345 pInstanceInfo->decoderState=NULL; 346 347 // Call the callback for handling an message ending 348 if (pInstanceInfo->callbacks->endMessageFunc==NULL) return SML_ERR_COMMAND_NOT_HANDLED; 349 350 rc=pInstanceInfo->callbacks->endMessageFunc(id, pInstanceInfo->userData, final); 351 return rc; 352 } 353 354 /* --- Dispatch parsed command (and call the applications command handler function)--- */ 355 switch (cmdType) 356 { 357 /* Handle ADD Command */ 358 case SML_PE_ADD: 359 if (pInstanceInfo->callbacks->addCmdFunc==NULL) return SML_ERR_COMMAND_NOT_HANDLED; 360 return pInstanceInfo->callbacks->addCmdFunc (id, pInstanceInfo->userData, pContent); 361 break; 362 363 /* Handle ALERT Command */ 364 case SML_PE_ALERT: 365 if (pInstanceInfo->callbacks->alertCmdFunc==NULL) return SML_ERR_COMMAND_NOT_HANDLED; 366 return pInstanceInfo->callbacks->alertCmdFunc (id, pInstanceInfo->userData, pContent); 367 break; 368 369 /* Handle DELETE Command */ 370 case SML_PE_DELETE: 371 if (pInstanceInfo->callbacks->deleteCmdFunc==NULL) return SML_ERR_COMMAND_NOT_HANDLED; 372 return pInstanceInfo->callbacks->deleteCmdFunc (id, pInstanceInfo->userData, pContent); 373 break; 374 375 /* Handle PUT Command */ 376 case SML_PE_PUT: 377 if (pInstanceInfo->callbacks->putCmdFunc==NULL) return SML_ERR_COMMAND_NOT_HANDLED; 378 return pInstanceInfo->callbacks->putCmdFunc (id, pInstanceInfo->userData, pContent); 379 break; 380 381 /* Handle GET Command */ 382 case SML_PE_GET: 383 if (pInstanceInfo->callbacks->getCmdFunc==NULL) return SML_ERR_COMMAND_NOT_HANDLED; 384 return pInstanceInfo->callbacks->getCmdFunc (id, pInstanceInfo->userData, pContent); 385 break; 386 387 #ifdef MAP_RECEIVE 388 /* Handle MAP Command */ 389 case SML_PE_MAP: 390 if (pInstanceInfo->callbacks->mapCmdFunc==NULL) return SML_ERR_COMMAND_NOT_HANDLED; 391 return pInstanceInfo->callbacks->mapCmdFunc (id, pInstanceInfo->userData, pContent); 392 break; 393 #endif 394 395 #ifdef RESULT_RECEIVE 396 /* Handle RESULTS Command */ 397 case SML_PE_RESULTS: 398 if (pInstanceInfo->callbacks->resultsCmdFunc==NULL) return SML_ERR_COMMAND_NOT_HANDLED; 399 return pInstanceInfo->callbacks->resultsCmdFunc (id, pInstanceInfo->userData, pContent); 400 break; 401 #endif 402 403 /* Handle STATUS Command */ 404 case SML_PE_STATUS: 405 if (pInstanceInfo->callbacks->statusCmdFunc==NULL) return SML_ERR_COMMAND_NOT_HANDLED; 406 return pInstanceInfo->callbacks->statusCmdFunc (id, pInstanceInfo->userData, pContent); 407 break; 408 409 /* Handle START SYNC Command */ 410 case SML_PE_SYNC_START: 411 if (pInstanceInfo->callbacks->startSyncFunc==NULL) return SML_ERR_COMMAND_NOT_HANDLED; 412 return pInstanceInfo->callbacks->startSyncFunc (id, pInstanceInfo->userData, pContent); 413 break; 414 415 /* Handle END SYNC Command */ 416 case SML_PE_SYNC_END: 417 if (pInstanceInfo->callbacks->endSyncFunc==NULL) return SML_ERR_COMMAND_NOT_HANDLED; 418 return pInstanceInfo->callbacks->endSyncFunc (id, pInstanceInfo->userData); 419 break; 420 421 /* Handle REPLACE Command */ 422 case SML_PE_REPLACE: 423 if (pInstanceInfo->callbacks->replaceCmdFunc==NULL) return SML_ERR_COMMAND_NOT_HANDLED; 424 return pInstanceInfo->callbacks->replaceCmdFunc (id, pInstanceInfo->userData, pContent); 425 break; 426 427 /* Handle Final Flag */ 428 case SML_PE_FINAL: 429 // if a FINAL Flag appears do nothing 430 return SML_ERR_OK; 431 break; 432 433 434 #ifdef SEARCH_RECEIVE /* these API calls are NOT included in the Toolkit lite version */ 435 436 /* Handle SEARCH Command */ 437 case SML_PE_SEARCH: 438 if (pInstanceInfo->callbacks->searchCmdFunc==NULL) return SML_ERR_COMMAND_NOT_HANDLED; 439 return pInstanceInfo->callbacks->searchCmdFunc (id, pInstanceInfo->userData, pContent); 440 break; 441 #endif 442 443 #ifdef SEQUENCE_RECEIVE 444 /* Handle START SEQUENCE Command */ 445 case SML_PE_SEQUENCE_START: 446 if (pInstanceInfo->callbacks->startSequenceFunc==NULL) return SML_ERR_COMMAND_NOT_HANDLED; 447 return pInstanceInfo->callbacks->startSequenceFunc (id, pInstanceInfo->userData, pContent); 448 break; 449 450 /* Handle END SEQUENCE Command */ 451 case SML_PE_SEQUENCE_END: 452 if (pInstanceInfo->callbacks->endSequenceFunc==NULL) return SML_ERR_COMMAND_NOT_HANDLED; 453 return pInstanceInfo->callbacks->endSequenceFunc (id, pInstanceInfo->userData); 454 break; 455 #endif 456 457 #ifdef ATOMIC_RECEIVE 458 459 /* Handle START ATOMIC Command */ 460 case SML_PE_ATOMIC_START: 461 if (pInstanceInfo->callbacks->startAtomicFunc==NULL) return SML_ERR_COMMAND_NOT_HANDLED; 462 return pInstanceInfo->callbacks->startAtomicFunc (id, pInstanceInfo->userData, pContent); 463 break; 464 465 /* Handle END ATOMIC Command */ 466 case SML_PE_ATOMIC_END: 467 if (pInstanceInfo->callbacks->endAtomicFunc==NULL) return SML_ERR_COMMAND_NOT_HANDLED; 468 return pInstanceInfo->callbacks->endAtomicFunc (id, pInstanceInfo->userData); 469 break; 470 #endif 471 472 #ifdef COPY_RECEIVE 473 474 /* Handle COPY Command */ 475 case SML_PE_COPY: 476 if (pInstanceInfo->callbacks->copyCmdFunc==NULL) return SML_ERR_COMMAND_NOT_HANDLED; 477 return pInstanceInfo->callbacks->copyCmdFunc (id, pInstanceInfo->userData, pContent); 478 break; 479 #endif 480 481 #ifdef EXEC_RECEIVE 482 483 /* Handle EXEC Command */ 484 case SML_PE_EXEC: 485 if (pInstanceInfo->callbacks->execCmdFunc==NULL) return SML_ERR_COMMAND_NOT_HANDLED; 486 return pInstanceInfo->callbacks->execCmdFunc (id, pInstanceInfo->userData, pContent); 487 break; 488 489 #endif 490 491 /* Handle ERROR DETECTED */ 492 //case SML_PE_ERROR: 493 // if (pInstanceInfo->callbacks->handleErrorFunc==NULL) return SML_ERR_COMMAND_NOT_HANDLED; 494 // return pInstanceInfo->callbacks->handleErrorFunc (id, pInstanceInfo->userData); 495 // break; 496 497 /* --- Invalid Command Element --- */ 498 default: 499 return SML_ERR_XLT_INVAL_PROTO_ELEM; 500 break; 501 } // switch 502 } 503 504 /* eof */ 505