00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "syncml.h"
00023
00024 #include "syncml_internals.h"
00025 #include "sml_error_internals.h"
00026 #include "sml_queue_internals.h"
00027 #include "sml_session_internals.h"
00028 #include "sml_command_internals.h"
00029 #include "sml_elements_internals.h"
00030 #include "sml_parse_internals.h"
00031 #include "sml_transport_internals.h"
00032 #include "objects/sml_auth_internals.h"
00033
00041
00042 typedef enum SmlSessionCommandType {
00043 SML_SESSION_COMMAND_START,
00044 SML_SESSION_COMMAND_END,
00045 SML_SESSION_STATUS,
00046 SML_SESSION_FLUSH
00047 } SmlSessionCommandType;
00048
00049 typedef struct SmlSessionCommand {
00050 SmlSessionCommandType type;
00051 SmlCommand *cmd;
00052 SmlCommand *parent;
00053 SmlStatus *status;
00054 SmlStatusReplyCb callback;
00055 void *callbackUserdata;
00056 SmlBool final;
00057 SmlBool end;
00058 } SmlSessionCommand;
00059
00060 void smlSessionDispatchEvent(SmlSession *session, SmlSessionEventType type, SmlCommand *cmd, SmlCommand *parent, SmlStatus *headerreply, SmlError *error)
00061 {
00062 smlTrace(TRACE_ENTRY, "%s(%p, %i, %p, %p, %p, %p)", __func__, session, type, cmd, parent, headerreply, error);
00063 smlAssert(session);
00064 smlAssert(session->eventCallback);
00065
00066 session->eventCallback(session, type, cmd, parent, headerreply, error, session->eventCallbackUserdata);
00067
00068 smlTrace(TRACE_EXIT, "%s", __func__);
00069 }
00070
00071 static void _smlSessionFreePendingReplies(SmlSession *session)
00072 {
00073 while (session->pendingReplies) {
00074 smlSafeFree((gpointer *)&(session->pendingReplies->data));
00075 session->pendingReplies = g_list_delete_link(session->pendingReplies, session->pendingReplies);
00076 }
00077 }
00078
00093 static SmlBool _smlSessionFlushInternal(SmlSession *session, SmlBool final, SmlError **error)
00094 {
00095 smlTrace(TRACE_ENTRY, "%s(%p, %i, %p)", __func__, session, final, error);
00096 CHECK_ERROR_REF
00097 smlAssert(session);
00098 smlAssert(session->dataCallback);
00099
00100 char *data = NULL;
00101 unsigned int size = 0;
00102 SmlBool end = FALSE;
00103
00104
00105 if (!smlAssemblerAddHeader(session->assembler, session, error))
00106 goto error;
00107
00108
00109 if (!smlAssemblerRun(session->assembler, &data, &size, &end, final, error))
00110 goto error;
00111 if (session->authenticate)
00112 end = FALSE;
00113
00114
00115 if (session->lastCommandID > 1)
00116 {
00117 smlAssemblerFlush(session->assembler);
00118 } else {
00119 session->lastCommandID = smlAssemblerFlush(session->assembler) - 1;
00120 }
00121 smlTrace(TRACE_INTERNAL, "%s: flushed assembler - last command id is %i now",
00122 __func__, session->lastCommandID);
00123
00124 SmlTransportData *tspdata = smlTransportDataNew(data, size, session->type, TRUE, error);
00125 if (!tspdata)
00126 goto error_free_data;
00127 data = NULL;
00128
00129 if (end && session->sessionType == SML_SESSION_TYPE_SERVER)
00130 tspdata->needsAnswer = FALSE;
00131
00132
00133 if (!session->authenticate)
00134 smlSessionDispatchEvent(session, SML_SESSION_EVENT_FLUSH, NULL, NULL, NULL, NULL);
00135
00136
00137 session->dataCallback(session, tspdata, session->dataCallbackUserdata);
00138
00139 smlTransportDataDeref(tspdata);
00140
00141 session->waiting = TRUE;
00142
00143 if (final)
00144 session->sending = FALSE;
00145
00146 if (end && session->sessionType == SML_SESSION_TYPE_SERVER) {
00147 smlTrace(TRACE_INTERNAL, "%s: Ending session now", __func__);
00148 session->end = TRUE;
00149 smlSessionRestoreTargetURI(session);
00150 g_mutex_lock(session->reportEnd);
00151 if (!session->reportedEnd) {
00152
00153 session->reportedEnd = TRUE;
00154 smlSessionDispatchEvent(session, SML_SESSION_EVENT_END,
00155 NULL, NULL, NULL, NULL);
00156 }
00157 g_mutex_unlock(session->reportEnd);
00158 }
00159
00160 smlTrace(TRACE_INTERNAL, "%s: incrementing lastMessageID %d (old)",
00161 __func__, session->lastMessageID);
00162 session->lastMessageID++;
00163
00164 session->hasCommand = FALSE;
00165
00166 smlTrace(TRACE_EXIT, "%s", __func__);
00167 return TRUE;
00168
00169 error_free_data:
00170 smlSafeCFree(&data);
00171 error:
00172 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
00173 return FALSE;
00174 }
00175
00176 static void _check_reply(SmlSession *session, SmlStatus *status, void *userdata)
00177 {
00178 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, status, userdata);
00179
00180 smlTrace(TRACE_EXIT, "%s", __func__);
00181 }
00182
00183 static void _smlSessionFragmentStatus(SmlSession *session, SmlStatus *status, void *userdata)
00184 {
00185 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, status, userdata);
00186
00187
00188 smlTrace(TRACE_INTERNAL, "%s: Got a status reply %i", __func__, status->type);
00189
00190 if (smlStatusGetCode(status) != SML_CHUNK_ACCEPTED) {
00191
00192
00193 smlCommandUnref(session->frag_command);
00194 session->frag_command = NULL;
00195 }
00196
00197 smlTrace(TRACE_EXIT, "%s", __func__);
00198 return;
00199
00200
00201
00202
00203
00204
00205 }
00206
00207 static SmlCommand *_smlSessionFragmentSend(SmlSession *session, SmlCommand *orig_cmd, SmlCommand *parent, unsigned int space, unsigned int start, unsigned int complete_size, SmlError **error)
00208 {
00209 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %i, %i, %i, %p)", __func__, session, orig_cmd, parent, space, start, complete_size, error);
00210 CHECK_ERROR_REF
00211
00212
00213
00214
00215 smlAssert(g_list_length(orig_cmd->private.change.items) == 1);
00216 SmlCommand *frag_cmd = NULL;
00217
00218 char *data = NULL;
00219 unsigned int size = 0;
00220 SmlItem *orig_item = g_list_nth_data(orig_cmd->private.change.items, 0);
00221 if (!smlItemGetData(orig_item, &data, &size, error))
00222 goto error;
00223
00224
00225
00226
00227 if (space < size - start) {
00228
00229
00230 frag_cmd = smlCommandNew(orig_cmd->type, error);
00231 if (!frag_cmd)
00232 goto error;
00233
00234 SmlItem *frag_item = smlItemNewForData(data + start, space, error);
00235 if (!frag_item)
00236 goto error_free_cmd;
00237 frag_cmd->private.change.items = g_list_append (NULL, frag_item);
00238 if (!frag_cmd->private.change.items)
00239 {
00240 smlItemUnref(frag_item);
00241 goto error_free_cmd;
00242 }
00243
00244 frag_item->moreData = TRUE;
00245
00246 frag_item->target = orig_item->target;
00247 if (frag_item->target)
00248 smlLocationRef(frag_item->target);
00249
00250 frag_item->source = orig_item->source;
00251 if (frag_item->source)
00252 smlLocationRef(frag_item->source);
00253
00254 frag_item->contenttype = g_strdup(orig_item->contenttype);
00255
00256
00257
00258
00259
00260 if (start == 0)
00261 frag_cmd->size = complete_size;
00262
00263 session->frag_size += space;
00264 } else {
00265
00266
00267
00268
00269
00270
00271
00272 smlAssert(g_list_length(orig_cmd->private.change.items) == 1);
00273 smlAssert(g_list_remove(orig_cmd->private.change.items, orig_item) == NULL);
00274 orig_cmd->private.change.items = NULL;
00275
00276
00277 SmlItem *frag_item = smlItemNewForData(data + start, size - start, error);
00278 if (!frag_item) {
00279 smlItemUnref(orig_item);
00280 goto error;
00281 }
00282 orig_cmd->private.change.items = g_list_append(NULL, frag_item);
00283 if (!orig_cmd->private.change.items)
00284 {
00285 smlItemUnref(orig_item);
00286 smlItemUnref(frag_item);
00287 goto error;
00288 }
00289
00290
00291 frag_item->contenttype = g_strdup(orig_item->contenttype);
00292 frag_item->target = orig_item->target;
00293 if (frag_item->target)
00294 smlLocationRef(frag_item->target);
00295 frag_item->source = orig_item->source;
00296 if (frag_item->source)
00297 smlLocationRef(frag_item->source);
00298
00299
00300 smlItemUnref(orig_item);
00301
00302
00303 frag_cmd = orig_cmd;
00304 session->frag_size += size - start;
00305 }
00306
00307
00308 smlTrace(TRACE_EXIT, "%s: %p", __func__, frag_cmd);
00309 return frag_cmd;
00310
00311 error_free_cmd:
00312 smlCommandUnref(frag_cmd);
00313 error:
00314 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
00315 return NULL;
00316 }
00317
00318 static SmlAssemblerResult _smlSessionStartCommandInternal(SmlSession *session, SmlCommand *cmd, SmlCommand *parent, SmlStatusReplyCb callback, void *userdata, SmlBool addToCommandStack, SmlError **error)
00319 {
00320 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p, %p, %i, %p)", __func__, session, cmd, parent, callback, userdata, addToCommandStack, error);
00321 smlAssert(session);
00322 smlAssert(cmd);
00323 CHECK_ERROR_REF
00324 SmlPendingStatus *pending = NULL;
00325 SmlBool fragmented = FALSE;
00326
00327 if (parent && !session->hasCommand) {
00328 GList *c = NULL;
00329 SmlCommand *oldcmd = NULL;
00330 SmlCommand *oldparent = NULL;
00331 GList * cmds = g_list_copy(session->commandStack);
00332 for (c = cmds; c; c = c->next) {
00333 oldcmd = c->data;
00334
00335 if (_smlSessionStartCommandInternal(session, oldcmd, oldparent, _check_reply, NULL, FALSE, error) != SML_ASSEMBLER_RESULT_OK)
00336 goto error;
00337 oldparent = oldcmd;
00338 }
00339 g_list_free(cmds);
00340 }
00341
00342
00343
00344 if ((cmd->type == SML_COMMAND_TYPE_ADD || cmd->type == SML_COMMAND_TYPE_REPLACE) &&
00345 smlAssemblerGetRemoteMaxMsgSize(session->assembler) > 0 && session->version != SML_VERSION_10) {
00346
00347 smlTrace(TRACE_INTERNAL, "%s: Checking if command needs to be fragmented", __func__);
00348
00349
00350
00351
00352 smlAssert(g_list_length(cmd->private.change.items) == 1);
00353
00354 char *data = NULL;
00355 unsigned int size = 0;
00356 SmlItem *item = g_list_nth_data(cmd->private.change.items, 0);
00357 if (!smlItemGetData(item, &data, &size, error))
00358 goto error;
00359
00360
00361
00362 int sendingmaxobjsize = smlSessionGetRemoteMaxObjSize(session);
00363 if ((sendingmaxobjsize > 0) &&
00364 (size > (unsigned int)sendingmaxobjsize))
00365 {
00366 smlErrorSet(error, SML_ERROR_SIZE_MISMATCH, "Item (%ub) is larger than the limit (%db)", size, smlSessionGetRemoteMaxObjSize(session));
00367 goto error;
00368 }
00369
00370 if (!session->frag_command)
00371 cmd->size = size;
00372 item->moreData = TRUE;
00373 int space = 0;
00374 if (!smlAssemblerGetSpace(session->assembler, &space, parent, cmd, error))
00375 goto error;
00376 cmd->size = 0;
00377 item->moreData = FALSE;
00378
00379
00380 if (session->frag_command ||
00381 (space > 0 &&
00382 (unsigned int) space < size - session->frag_size))
00383 {
00384 smlTrace(TRACE_INTERNAL, "%s: Space %i, size %i. Fragmenting. Already added: %i", __func__, space, size - session->frag_size, session->frag_size);
00385
00386
00387
00388 if (!session->frag_command) {
00389 session->frag_size = 0;
00390
00391 session->frag_command = cmd;
00392 smlCommandRef(cmd);
00393
00394 session->frag_callback = callback;
00395 session->frag_userdata = userdata;
00396 }
00397
00398 if (!(cmd = _smlSessionFragmentSend(session, session->frag_command, parent, space, session->frag_size, size, error)))
00399 goto error;
00400
00401 callback = _smlSessionFragmentStatus;
00402 userdata = NULL;
00403 fragmented = TRUE;
00404
00405
00406
00407
00408
00409 item = g_list_nth_data(cmd->private.change.items, 0);
00410 if (item->moreData == FALSE) {
00411 smlTrace(TRACE_INTERNAL, "%s: This is the last chunk", __func__);
00412
00413 callback = session->frag_callback;
00414 userdata = session->frag_userdata;
00415 fragmented = FALSE;
00416
00417 session->frag_size = 0;
00418
00419 smlCommandUnref(session->frag_command);
00420 session->frag_command = NULL;
00421 }
00422
00423 smlTrace(TRACE_INTERNAL, "%s: Fragmented. Added %i already", __func__, session->frag_size);
00424 }
00425 }
00426
00427
00428 session->lastCommandID++;
00429 cmd->cmdID = session->lastCommandID;
00430 smlTrace(TRACE_INTERNAL, "%s: last command id is %i", __func__, session->lastCommandID);
00431
00432
00433 switch (smlAssemblerStartCommand(session->assembler, parent, cmd, error)) {
00434 case SML_ASSEMBLER_RESULT_OK:
00435
00436 cmd->pushedBack = FALSE;
00437 break;
00438 case SML_ASSEMBLER_RESULT_MISMATCH:
00439 if (cmd->pushedBack) {
00440 smlErrorSet(error, SML_ERROR_GENERIC, "Command is too large");
00441 goto error;
00442 }
00443 cmd->pushedBack = TRUE;
00444
00445
00446
00447 if (!_smlSessionFlushInternal(session, FALSE, error)) {
00448 session->lastCommandID--;
00449 goto error;
00450 }
00451
00452 smlTrace(TRACE_EXIT, "%s: Mismatch", __func__);
00453 return SML_ASSEMBLER_RESULT_MISMATCH;
00454 case SML_ASSEMBLER_RESULT_ERROR:
00455 session->lastCommandID--;
00456 goto error;
00457 }
00458
00459
00460
00461
00462 if (callback) {
00463 pending = smlTryMalloc0(sizeof(SmlPendingStatus), error);
00464 if (!pending) {
00465 session->lastCommandID--;
00466 goto error;
00467 }
00468
00469 pending->callback = callback;
00470 pending->userdata = userdata;
00471 pending->cmdID = cmd->cmdID;
00472 pending->msgID = session->lastMessageID;
00473
00474 smlTrace(TRACE_INTERNAL, "%s: Appending pending status with cmdID %i and msgID %i", __func__, pending->cmdID, pending->msgID);
00475 session->pendingReplies = g_list_append(session->pendingReplies, pending);
00476 } else
00477 cmd->noResp = TRUE;
00478
00479
00480
00481 if (cmd->type == SML_COMMAND_TYPE_GET) {
00482 pending = smlTryMalloc0(sizeof(SmlPendingStatus), error);
00483 if (!pending) {
00484 session->lastCommandID--;
00485 goto error;
00486 }
00487
00488 pending->callback = callback;
00489 pending->userdata = userdata;
00490 pending->cmdID = cmd->cmdID;
00491 pending->msgID = session->lastMessageID;
00492
00493 smlTrace(TRACE_INTERNAL, "%s: Appending pending status for a result with cmdID %i and msgID %i", __func__, pending->cmdID, pending->msgID);
00494 session->pendingReplies = g_list_append(session->pendingReplies, pending);
00495 }
00496
00497 if (fragmented) {
00498
00499
00500 if (!_smlSessionFlushInternal(session, FALSE, error)) {
00501 session->lastCommandID--;
00502 goto error;
00503 }
00504
00505 smlCommandUnref(cmd);
00506
00507 smlTrace(TRACE_EXIT, "%s: Mismatch but fragmented", __func__);
00508 return SML_ASSEMBLER_RESULT_MISMATCH;
00509 }
00510
00511 if (addToCommandStack)
00512 session->commandStack = g_list_append(session->commandStack, cmd);
00513 session->hasCommand = TRUE;
00514
00515 smlTrace(TRACE_EXIT, "%s", __func__);
00516 return SML_ASSEMBLER_RESULT_OK;
00517
00518 error:
00519 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
00520 return SML_ASSEMBLER_RESULT_ERROR;
00521 }
00522
00523 static SmlBool _smlSessionEndCommandInternal(SmlSession *session, SmlCommand *parent, SmlError **error)
00524 {
00525 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, parent, error);
00526 smlAssert(session);
00527 CHECK_ERROR_REF
00528
00529 if (!smlAssemblerEndCommand(session->assembler, parent, error))
00530 goto error;
00531
00532 session->commandStack = g_list_delete_link(session->commandStack, g_list_last(session->commandStack));
00533
00534 smlTrace(TRACE_EXIT, "%s", __func__);
00535 return TRUE;
00536
00537 error:
00538 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
00539 return FALSE;
00540 }
00541
00542 static void _smlSessionCommandFree(SmlSessionCommand *sesscmd)
00543 {
00544 if (sesscmd->cmd)
00545 smlCommandUnref(sesscmd->cmd);
00546
00547 if (sesscmd->parent)
00548 smlCommandUnref(sesscmd->parent);
00549
00550 if (sesscmd->status)
00551 smlStatusUnref(sesscmd->status);
00552
00553 smlSafeFree((gpointer *)&sesscmd);
00554 }
00555
00556 static void _smlSessionCommandHandler(void *message, void *userdata)
00557 {
00558 smlTrace(TRACE_ENTRY, "%s", __func__);
00559 smlAssert(message);
00560 smlAssert(userdata);
00561 SmlSessionCommand *sesscmd = message;
00562 SmlSession *session = userdata;
00563 SmlError *error = NULL;
00564
00565 smlTrace(TRACE_INTERNAL, "%s: session cmd type %i", __func__, sesscmd->type);
00566
00567
00568 if (!session->assmHasHeader)
00569 {
00570 if (!smlAssemblerAddHeader(session->assembler, session, &error))
00571 goto error;
00572 session->assmHasHeader = TRUE;
00573 }
00574
00575 SmlCommand *parent = sesscmd->parent;
00576 SmlCommand *cmd = sesscmd->cmd;
00577 SmlStatus *status = sesscmd->status;
00578
00579 switch (sesscmd->type) {
00580 case SML_SESSION_FLUSH:
00581 if (sesscmd->end) {
00582 session->end = TRUE;
00583 smlTrace(TRACE_INTERNAL, "%s: End on flush was set", __func__);
00584 }
00585 if (!_smlSessionFlushInternal(session, sesscmd->final, &error))
00586 goto error;
00587 break;
00588 case SML_SESSION_COMMAND_END:
00589 if (!_smlSessionEndCommandInternal(session, parent, &error))
00590 goto error;
00591 break;
00592 case SML_SESSION_COMMAND_START:
00593 switch (_smlSessionStartCommandInternal(session, cmd, parent, sesscmd->callback, sesscmd->callbackUserdata, TRUE, &error)) {
00594 case SML_ASSEMBLER_RESULT_OK:
00595
00596 break;
00597 case SML_ASSEMBLER_RESULT_MISMATCH:
00598 smlQueuePushHead(session->command_queue, message);
00599 return;
00600 case SML_ASSEMBLER_RESULT_ERROR:
00601 goto error;
00602 }
00603 break;
00604 case SML_SESSION_STATUS:;
00605 unsigned int cmdRef, msgRef = 0;
00606 if (!smlAssemblerGetNextCmdRef(session->assembler, &cmdRef, &msgRef)) {
00607 smlErrorSet(&error, SML_ERROR_GENERIC, "No more statuses were needed");
00608 goto error;
00609 }
00610
00611 if (status->cmdRef != cmdRef || status->msgRef != msgRef) {
00612
00613 smlQueueSendPrio(session->command_queue, message);
00614 smlTrace(TRACE_EXIT,
00615 "%s - next needed command status %d for message %d is not this one (cmd %d, msg %d)",
00616 __func__, cmdRef, msgRef, status->cmdRef, status->msgRef);
00617 return;
00618 }
00619
00620
00621
00622
00623
00624
00625
00626
00627 smlTrace(TRACE_INTERNAL, "%s - try to add status", __func__);
00628 switch (smlAssemblerAddStatusFull(session->assembler, status, session->incomingBuffer ? TRUE : FALSE, &error)) {
00629 case SML_ASSEMBLER_RESULT_OK:
00630
00631 session->active = TRUE;
00632 break;
00633 case SML_ASSEMBLER_RESULT_MISMATCH:
00634
00635
00636 if (!_smlSessionFlushInternal(session, FALSE, &error)) {
00637 session->lastCommandID--;
00638 goto error;
00639 }
00640
00641
00642 smlQueuePushHeadPrio(session->command_queue, message);
00643 smlTrace(TRACE_EXIT, "%s - status cannot be added, so push back", __func__);
00644 return;
00645 break;
00646 case SML_ASSEMBLER_RESULT_ERROR:
00647 goto error;
00648 }
00649 break;
00650 }
00651
00652 _smlSessionCommandFree(sesscmd);
00653 smlTrace(TRACE_EXIT, "%s", __func__);
00654
00655 return;
00656
00657 error:
00658 smlSessionDispatchEvent(session, SML_SESSION_EVENT_ERROR, NULL, NULL, NULL, error);
00659 _smlSessionCommandFree(sesscmd);
00660 return;
00661 }
00662
00663 SmlBool smlSessionReceiveHeader(SmlSession *session, SmlHeader *header, SmlError **error)
00664 {
00665 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, header, error);
00666 smlAssert(session);
00667 smlAssert(header);
00668 CHECK_ERROR_REF
00669
00670
00671 if (header->messageID <= session->lastReceivedMessageID) {
00672 smlErrorSet(error, SML_ERROR_GENERIC, "Message ID not incremented");
00673 goto error;
00674 }
00675 session->lastReceivedMessageID = header->messageID;
00676 session->lastCommandID++;
00677
00678
00679 if (0 < header->maxmsgsize) {
00680
00681
00682
00683
00684
00685 smlAssemblerSetRemoteMaxMsgSize(session->assembler, header->maxmsgsize);
00686 }
00687 if (0 < header->maxmsgsize && header->maxmsgsize < session->localMaxMsgSize)
00688 {
00689
00690
00691
00692
00693
00694 smlSessionSetLocalMaxMsgSize(session, header->maxmsgsize);
00695 }
00696
00697
00698
00699 if (!smlAssemblerReserveStatus(session->assembler, 0, header->messageID, 1, error))
00700 goto error;
00701
00702
00703
00704 if (header->responseURI) {
00705 if (!session->orgTarget) {
00706
00707
00708
00709
00710
00711
00712 session->orgTarget = session->target;
00713 session->target = NULL;
00714 }
00715
00716 if (session->target) {
00717
00718
00719
00720
00721
00722 smlLocationUnref(session->target);
00723 }
00724
00725
00726 session->target = smlLocationNew(
00727 header->responseURI,
00728 smlLocationGetName(session->orgTarget),
00729 error);
00730 if (!session->target)
00731 goto error;
00732 smlSessionDispatchEvent(session, SML_SESSION_EVENT_RESPONSE_URI, NULL, NULL, NULL, NULL);
00733 smlTrace(TRACE_INTERNAL, "%s: RespURI: %s, Target: %s", __func__,
00734 VA_STRING(smlLocationGetURI(session->target)),
00735 VA_STRING(smlLocationGetURI(session->orgTarget)));
00736 } else {
00737
00738
00739
00740
00741
00742
00743
00744
00745 const char *header_source = smlLocationGetURI(header->source);
00746 const char *session_target = smlLocationGetURI(session->target);
00747 if (header_source &&
00748 session_target &&
00749 strcmp(header_source, session_target))
00750 {
00751
00752 smlTrace(TRACE_INTERNAL,
00753 "%s: update session target to header source %s",
00754 __func__, header_source);
00755 smlLocationSetURI(session->target, header_source);
00756 }
00757 }
00758 smlTrace(TRACE_EXIT, "%s", __func__);
00759 return TRUE;
00760
00761 error:
00762 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
00763 return FALSE;
00764 }
00765
00766 SmlBool smlSessionDispatchStatus(SmlSession *session, SmlStatus *status, SmlError **error)
00767 {
00768 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, status, error);
00769 smlAssert(status);
00770 CHECK_ERROR_REF
00771
00772 if (status->cmdRef == 0) {
00773 smlAssert(status->type == SML_COMMAND_TYPE_HEADER);
00774 smlAssert(status->data);
00775 SmlErrorType errorCode = atoi(status->data);
00776 if (session->sessionType == SML_SESSION_TYPE_SERVER)
00777 {
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788 SmlCommand *cmd = smlCommandNew(SML_COMMAND_TYPE_HEADER, error);
00789 smlSessionDispatchEvent(session, SML_SESSION_EVENT_HEADER_REPLY, cmd, NULL, status, NULL);
00790 smlCommandUnref(cmd);
00791 }
00792 else if (errorCode == SML_AUTH_ACCEPTED)
00793 {
00794
00795
00796
00797
00798 smlTrace(TRACE_INTERNAL, "%s - authentication succeeded", __func__);
00799 if (session->cred != NULL)
00800 {
00801 smlCredUnref(session->cred);
00802 session->cred = NULL;
00803 }
00804 if (!session->established)
00805 {
00806 session->established = TRUE;
00807 smlSessionDispatchEvent(
00808 session, SML_SESSION_EVENT_ESTABLISHED,
00809 NULL, NULL, NULL, NULL);
00810 }
00811 }
00812 else if (errorCode == SML_ERROR_AUTH_REQUIRED)
00813 {
00814
00815
00816
00817
00818
00819 smlTrace(TRACE_INTERNAL, "%s - authentication required", __func__);
00820 session->authenticate = TRUE;
00821 session->established = FALSE;
00822 smlAssemblerRestoreCommands(session->assembler);
00823 smlTrace(TRACE_INTERNAL, "%s - restored commands from previous message", __func__);
00824 smlAssert(status->chal);
00825 smlAssert(session->cred);
00826 if (session->cred->type == SML_AUTH_TYPE_MD5 &&
00827 status->chal->type != SML_AUTH_TYPE_MD5)
00828 {
00829 smlErrorSet(error, SML_ERROR_AUTH_REJECTED, "The remote peer tries to enforce an authentication method which violates the local security policy (syncml:auth-md5 is required).");
00830 goto error;
00831 }
00832 smlTrace(TRACE_INTERNAL, "%s - authentication type conforms to security policy", __func__);
00833
00834
00835 session->cred->data = smlAuthGetCredString(
00836 status->chal->type,
00837 session->cred->username,
00838 session->cred->password,
00839 status->chal->nonce_b64,
00840 error);
00841 if (!session->cred->data)
00842 goto error;
00843 smlTrace(TRACE_INTERNAL, "%s - credential string set", __func__);
00844 } else {
00845 if (!session->established)
00846 {
00847 session->established = TRUE;
00848 smlSessionDispatchEvent(
00849 session, SML_SESSION_EVENT_ESTABLISHED,
00850 NULL, NULL, NULL, NULL);
00851 }
00852 SmlCommand *cmd = smlCommandNew(SML_COMMAND_TYPE_HEADER, error);
00853 smlSessionDispatchEvent(session, SML_SESSION_EVENT_HEADER_REPLY, cmd, NULL, status, NULL);
00854 smlCommandUnref(cmd);
00855 }
00856 goto out;
00857 }
00858 smlTrace(TRACE_INTERNAL, "%s - no header status", __func__);
00859
00860
00861
00862
00863
00864
00865 GList *o = NULL;
00866 SmlBool foundPending = FALSE;
00867 for (o = session->pendingReplies; o; o = o ? o->next : NULL ) {
00868 SmlPendingStatus *pending = o->data;
00869 smlTrace(TRACE_INTERNAL, "%s: check cmd %i of msg %i", __func__, pending->cmdID, pending->msgID);
00870 if (pending->cmdID == status->cmdRef && pending->msgID == status->msgRef) {
00871 smlTrace(TRACE_INTERNAL, "%s - Found pending status %s of command %d in message %d",
00872 __func__, VA_STRING(status->data), status->cmdRef, status->msgRef);
00873 if (session->authenticate)
00874 {
00875
00876
00877
00878
00879
00880
00881
00882 smlTrace(TRACE_INTERNAL, "%s - update message ID to %d",
00883 __func__, session->lastMessageID);
00884 pending->msgID++;
00885 } else {
00886
00887 smlTrace(TRACE_INTERNAL, "%s - normal status", __func__);
00888 session->pendingReplies = g_list_remove(session->pendingReplies, pending);
00889
00890 smlAssert(pending->callback);
00891 pending->callback(session, status, pending->userdata);
00892
00893 smlSafeFree((gpointer *)&pending);
00894
00895
00896
00897
00898
00899
00900
00901 o = NULL;
00902 }
00903
00904 foundPending = TRUE;
00905 }
00906 }
00907 if (foundPending)
00908 goto out;
00909 smlTrace(TRACE_INTERNAL, "%s - no pending reply found", __func__);
00910
00911
00912
00913
00914 if (status->type == SML_COMMAND_TYPE_ALERT && !status->anchor) {
00915 smlTrace(TRACE_INTERNAL, "%s: Handling status for server alerted sync", __func__);
00916 SmlErrorType errorCode = atoi(status->data);
00917 if ((199 < errorCode && errorCode < 300) ||
00918 errorCode == 508)
00919 {
00920
00921 goto out;
00922 } else {
00923
00924
00925
00926
00927 smlErrorSet(error, errorCode, "The SAN alert was rejected.");
00928 goto error;
00929 }
00930 }
00931
00932 smlErrorSet(error, SML_ERROR_GENERIC,
00933 "Received unwanted status %s of command %d in message %d",
00934 status->data, status->cmdRef, status->msgRef);
00935 goto error;
00936 out:
00937 smlTrace(TRACE_EXIT, "%s", __func__);
00938 return TRUE;
00939 error:
00940 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
00941 return FALSE;
00942 }
00943
00944 SmlBool smlSessionCheck(SmlSession *session)
00945 {
00946 smlAssert(session);
00947
00948 if (session->waiting)
00949 {
00950 smlTrace(TRACE_INTERNAL, "%s: waiting", __func__);
00951 return FALSE;
00952 }
00953
00954 SmlBool result;
00955 if (!smlAssemblerIsStatusMissing(session->assembler))
00956 {
00957 result = smlQueueCheck(session->command_queue);
00958 smlTrace(TRACE_INTERNAL, "%s: no status is missing - %i", __func__, result);
00959 }
00960 else
00961 {
00962 result = smlQueueCheckPrio(session->command_queue);
00963 smlTrace(TRACE_INTERNAL, "%s: status is missing - %i", __func__, result);
00964 }
00965 return result;
00966 }
00967
00968 SmlBool smlSessionTryLock(SmlSession *session)
00969 {
00970 smlTrace(TRACE_ENTRY, "%s(%p)", __func__, session);
00971 smlAssert(session);
00972 smlAssert(session->dispatch_mutex);
00973 SmlBool ret = g_mutex_trylock(session->dispatch_mutex);
00974 smlTrace(TRACE_EXIT, "%s - %d", __func__, ret);
00975 return ret;
00976 }
00977
00978 void smlSessionLock(SmlSession *session)
00979 {
00980 smlTrace(TRACE_ENTRY, "%s(%p)", __func__, session);
00981 smlAssert(session);
00982 smlAssert(session->dispatch_mutex);
00983 g_mutex_lock(session->dispatch_mutex);
00984 smlTrace(TRACE_EXIT, "%s", __func__);
00985 }
00986
00987 void smlSessionUnlock(SmlSession *session)
00988 {
00989 smlTrace(TRACE_ENTRY, "%s", __func__);
00990 smlAssert(session);
00991 smlAssert(session->dispatch_mutex);
00992 g_mutex_unlock(session->dispatch_mutex);
00993 smlTrace(TRACE_EXIT, "%s", __func__);
00994 }
00995
00996 void smlSessionDispatch(SmlSession *session)
00997 {
00998 smlTrace(TRACE_ENTRY, "%s", __func__);
00999 smlAssert(session);
01000
01001 if (session->waiting)
01002 {
01003 smlTrace(TRACE_EXIT, "%s - session is waiting", __func__);
01004 return;
01005 }
01006
01007
01008
01009
01010 if (!smlAssemblerIsStatusMissing(session->assembler))
01011 {
01012 smlTrace(TRACE_INTERNAL, "%s: dispatch commands", __func__);
01013 smlQueueDispatch(session->command_queue);
01014 }
01015 else
01016 {
01017 smlTrace(TRACE_INTERNAL, "%s: dispatch status", __func__);
01018 smlQueueDispatchPrio(session->command_queue);
01019 }
01020 smlTrace(TRACE_EXIT, "%s - done", __func__);
01021 }
01022
01023 SmlBool smlSessionReceiveBody(SmlSession *session, SmlParser *parser, SmlError **error)
01024 {
01025 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, parser, error);
01026 smlAssert(session);
01027 smlAssert(parser);
01028 CHECK_ERROR_REF
01029 SmlStatus *status = NULL;
01030 SmlCommand *cmd = NULL;
01031 SmlParserResult result = SML_PARSER_RESULT_ERROR;
01032 SmlBool isSan = TRUE;
01033
01034 if (session->sessionType == SML_SESSION_TYPE_SERVER)
01035 isSan = FALSE;
01036
01037
01038
01039
01040
01041
01042
01043
01044 session->waiting = FALSE;
01045 session->sending = FALSE;
01046
01047 parse_status:
01048
01049 while (1) {
01050 if (!smlParserGetStatus(parser, &status, error))
01051 goto error_free_status;
01052
01053 if (!status)
01054 break;
01055
01056
01057
01058
01059
01060 isSan = FALSE;
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074 if (session->lastMessageID == 1)
01075 {
01076
01077 smlTrace(TRACE_INTERNAL, "%s - reply to SAN detected", __func__);
01078 session->lastMessageID = 2;
01079 }
01080
01081
01082 if (!smlSessionDispatchStatus(session, status, error))
01083 goto error_free_status;
01084
01085 smlStatusUnref(status);
01086 }
01087
01088
01089 while (1) {
01090 result = smlParserGetCommand(parser, &cmd, error);
01091 if (result == SML_PARSER_RESULT_ERROR)
01092 goto error_free_cmd;
01093 if (result == SML_PARSER_RESULT_OTHER)
01094 break;
01095
01096 if (cmd)
01097 cmd->msgID = session->lastReceivedMessageID;
01098
01099
01100
01101
01102
01103
01104 if (!session->established && !isSan) {
01105 session->lastCommandID++;
01106
01107
01108 if (!smlAssemblerReserveStatus(session->assembler, cmd->cmdID, session->lastReceivedMessageID, session->lastCommandID, error))
01109 goto error_free_cmd;
01110
01111
01112 SmlStatus *reply = smlCommandNewReply(
01113 cmd, SML_ERROR_AUTH_REQUIRED, error);
01114 if (!reply)
01115 goto error_free_cmd;
01116 if (!smlSessionSendReply(session, reply, error))
01117 goto error_free_cmd;
01118 smlStatusUnref(reply);
01119 smlCommandUnref(cmd);
01120 continue;
01121 }
01122
01123 switch (result) {
01124 case SML_PARSER_RESULT_OPEN:
01125 session->lastCommandID++;
01126
01127 if (!smlAssemblerReserveStatus(session->assembler, cmd->cmdID, session->lastReceivedMessageID, session->lastCommandID, error))
01128 goto error_free_cmd;
01129
01130
01131 if (session->parentCommand) {
01132 smlErrorSet(error, SML_ERROR_GENERIC, "Already had a parent");
01133 goto error_free_cmd;
01134 }
01135
01136
01137
01138
01139 if (cmd->type == SML_COMMAND_TYPE_SYNC) {
01140 smlTrace(TRACE_INTERNAL, "%s: maxObjSize: %i, numbOfChanges: %i, %i",
01141 __func__,
01142 cmd->private.sync.maxObjSize,
01143 cmd->private.sync.hasNumChanged,
01144 cmd->private.sync.numChanged);
01145
01146
01147 if (cmd->private.sync.maxObjSize >= 0)
01148 smlSessionSetRemoteMaxObjSize(session, cmd->private.sync.maxObjSize);
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162 }
01163
01164 session->parentCommand = cmd;
01165 cmd->msgID = session->lastReceivedMessageID;
01166
01167 if (!session->end) {
01168 smlSessionDispatchEvent(session, SML_SESSION_EVENT_COMMAND_START, cmd, NULL, NULL, NULL);
01169 } else {
01170 smlTrace(TRACE_INTERNAL, "%s: Replying with 407 since the session has ended",
01171 __func__);
01172 SmlStatus *reply = smlCommandNewReply(cmd, SML_ERROR_AUTH_REQUIRED, error);
01173 if (!reply)
01174 goto error_free_cmd;
01175
01176 if (!smlSessionSendReply(session, reply, error))
01177 goto error_free_cmd;
01178
01179 smlStatusUnref(reply);
01180 }
01181 break;
01182 case SML_PARSER_RESULT_NORMAL:
01183 session->lastCommandID++;
01184
01185 if (!smlAssemblerReserveStatus(session->assembler, cmd->cmdID, session->lastReceivedMessageID, session->lastCommandID, error))
01186 goto error_free_cmd;
01187
01188
01189 if (cmd->type == SML_COMMAND_TYPE_ALERT) {
01190 if (cmd->private.alert.type == SML_ALERT_NEXT_MESSAGE) {
01191 SmlStatus *reply = smlCommandNewReply(cmd, SML_NO_ERROR, error);
01192 if (!reply)
01193 goto error_free_cmd;
01194
01195 if (!smlSessionSendReply(session, reply, error))
01196 goto error_free_cmd;
01197
01198 smlStatusUnref(reply);
01199
01200 smlCommandUnref(cmd);
01201 break;
01202 } else {
01203 smlTrace(TRACE_INTERNAL, "%s: Alert maxObjSize: %i",
01204 __func__, cmd->private.alert.maxObjSize);
01205 if (cmd->private.alert.maxObjSize >= 0)
01206 smlAssemblerSetRemoteMaxObjSize(session->assembler, cmd->private.alert.maxObjSize);
01207 }
01208 }
01209
01210
01211 if (cmd->type == SML_COMMAND_TYPE_ADD || cmd->type == SML_COMMAND_TYPE_REPLACE) {
01212
01213 SmlItem *lastItem = g_list_nth_data(cmd->private.change.items,
01214 g_list_length(cmd->private.change.items) - 1);
01215
01216 if (session->incomingBuffer) {
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226 smlTrace(TRACE_INTERNAL, "%s: Appending to incoming buffer", __func__);
01227
01228
01229
01230
01231 if (cmd->size) {
01232 smlErrorSet(error, SML_ERROR_GENERIC,
01233 "Only the first chunk can have the size set");
01234 goto error_free_cmd;
01235 }
01236
01237
01238
01239
01240
01241 char *data = NULL;
01242 unsigned int size = 0;
01243 SmlItem *item = g_list_nth_data(cmd->private.change.items, 0);
01244 if (!item)
01245 goto error_free_cmd;
01246 if (!smlItemGetData(item, &data, &size, error))
01247 goto error_free_cmd;
01248 lastItem = g_list_nth_data(session->incomingBuffer->private.change.items, g_list_length(session->incomingBuffer->private.change.items) - 1);
01249 if (!smlItemAddData(lastItem, data, size, error))
01250 goto error_free_cmd;
01251 lastItem->moreData = item->moreData;
01252 smlTrace(TRACE_INTERNAL,
01253 "%s: Appended %i to buffer. Buffer size: %i. Required: %i",
01254 __func__, size,
01255 xmlBufferLength(lastItem->buffer),
01256 lastItem->size);
01257
01258
01259 guint i;
01260 for (i=1; i < g_list_length(cmd->private.change.items); i++)
01261 {
01262 item = g_list_nth_data(cmd->private.change.items, i);
01263 session->incomingBuffer->private.change.items =
01264 g_list_append(
01265 session->incomingBuffer->private.change.items,
01266 item);
01267 }
01268 smlItemUnref(g_list_nth_data(cmd->private.change.items, 0));
01269 g_list_free(cmd->private.change.items);
01270 cmd->private.change.items = NULL;
01271
01272
01273
01274
01275 lastItem = g_list_nth_data(session->incomingBuffer->private.change.items, g_list_length(session->incomingBuffer->private.change.items) - 1);
01276 if (!lastItem->moreData) {
01277 smlTrace(TRACE_INTERNAL,
01278 "%s: Command buffer complete. Dispatching.",
01279 __func__);
01280
01281
01282 if (!smlItemCheck(lastItem)) {
01283
01284 SmlStatus *reply = smlCommandNewReply(cmd, SML_ERROR_SIZE_MISMATCH, error);
01285 if (!reply)
01286 goto error_free_cmd;
01287 if (!smlSessionSendReply(session, reply, error))
01288 goto error_free_cmd;
01289 smlStatusUnref(reply);
01290 smlErrorSet(error, SML_ERROR_GENERIC,
01291 "Chunked item size mismatch");
01292 goto error_free_cmd;
01293 }
01294
01295
01296
01297
01298
01299
01300
01301 cmd->private.change.items =
01302 session->incomingBuffer->private.change.items;
01303 session->incomingBuffer->private.change.items = NULL;
01304 smlCommandUnref(session->incomingBuffer);
01305 session->incomingBuffer = NULL;
01306 }
01307 } else if (lastItem->moreData) {
01308
01309
01310
01311
01312
01313
01314 if (!cmd->size) {
01315 smlErrorSet(error, SML_ERROR_GENERIC, "First MoreData item didn't have size set");
01316 goto error_free_cmd;
01317 }
01318
01319 session->incomingBuffer = cmd;
01320 smlCommandRef(cmd);
01321 smlTrace(TRACE_INTERNAL, "%s: New Buffer started. Buffered item size: %i. Required: %i",
01322 __func__,
01323 xmlBufferLength(lastItem->buffer),
01324 lastItem->size);
01325
01326 char *bin = smlPrintBinary((char *) xmlBufferContent(lastItem->buffer), xmlBufferLength(lastItem->buffer));
01327 smlTrace(TRACE_INTERNAL, "%s: Content so far: %s\n",
01328 __func__, VA_STRING(bin));
01329 smlSafeCFree(&bin);
01330 }
01331
01332 if (lastItem->moreData == TRUE) {
01333 smlTrace(TRACE_INTERNAL, "%s: Got item with moreData %i",
01334 __func__, cmd->msgID);
01335
01336 SmlStatus *reply = smlCommandNewReply(cmd, SML_CHUNK_ACCEPTED, error);
01337 if (!reply)
01338 goto error_free_cmd;
01339
01340 if (!smlSessionSendReply(session, reply, error))
01341 goto error_free_cmd;
01342
01343 smlStatusUnref(reply);
01344
01345 smlCommandUnref(cmd);
01346 break;
01347 }
01348 }
01349
01350
01351 if (cmd->type == SML_COMMAND_TYPE_RESULTS) {
01352
01353 if (!smlSessionDispatchStatus(session, cmd->private.results.status, error))
01354 goto error_free_status;
01355 } else {
01356
01357 cmd->msgID = session->lastReceivedMessageID;
01358 if (!session->end) {
01359 if (!session->parentCommand) {
01360 smlSessionDispatchEvent(session, SML_SESSION_EVENT_COMMAND_START, cmd, NULL, NULL, NULL);
01361 } else {
01362 smlSessionDispatchEvent(session, SML_SESSION_EVENT_CHILD_COMMAND, cmd, session->parentCommand, NULL, NULL);
01363 }
01364 } else {
01365 smlTrace(TRACE_INTERNAL, "%s: Replying with 407 since the session has ended2",
01366 __func__);
01367 SmlStatus *reply = smlCommandNewReply(cmd, SML_ERROR_AUTH_REQUIRED, error);
01368 if (!reply)
01369 goto error_free_cmd;
01370
01371 if (!smlSessionSendReply(session, reply, error))
01372 goto error_free_cmd;
01373
01374 smlStatusUnref(reply);
01375 }
01376 }
01377
01378 smlCommandUnref(cmd);
01379 break;
01380 case SML_PARSER_RESULT_CLOSE:
01381
01382
01383
01384
01385
01386
01387 if (session->parentCommand->type == SML_COMMAND_TYPE_SYNC) {
01388 smlSessionDispatchEvent(
01389 session,
01390 SML_SESSION_EVENT_COMMAND_END,
01391 session->parentCommand,
01392 NULL, NULL, NULL);
01393 }
01394
01395 smlCommandUnref(session->parentCommand);
01396 session->parentCommand = NULL;
01397 break;
01398 case SML_PARSER_RESULT_STATUS:
01399 goto parse_status;
01400 default:
01401 goto error_free_cmd;
01402 }
01403 }
01404
01405
01406
01407
01408
01409
01410 SmlBool final = FALSE;
01411 SmlBool end = FALSE;
01412 if (!smlParserEnd(parser, &final, &end, error))
01413 goto error_free_cmd;
01414
01415
01416
01417 if (final && !session->authenticate) {
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428 session->sending = TRUE;
01429 smlSessionDispatchEvent(session, SML_SESSION_EVENT_FINAL, NULL, NULL, NULL, NULL);
01430 }
01431
01432
01433
01434
01435
01436
01437 while (1) {
01438 unsigned int cmdRef, msgRef;
01439 if (!smlAssemblerGetNextCmdRef(session->assembler, &cmdRef, &msgRef))
01440 break;
01441 smlTrace(TRACE_INTERNAL, "%s: command %d of message %d found",
01442 __func__, cmdRef, msgRef);
01443
01444
01445 usleep(10000);
01446
01447
01448
01449
01450
01451
01452
01453
01454 unsigned int num = smlQueueLengthPrio(session->command_queue);
01455 smlTrace(TRACE_INTERNAL, "%s: Now dispatching %i statuses. Session waiting: %i, prio: %i",
01456 __func__, num, session->waiting, smlQueueCheckPrio(session->command_queue));
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467 unsigned int i = 0;
01468 while (!session->waiting && smlQueueCheckPrio(session->command_queue) && i < num) {
01469 smlSessionDispatch(session);
01470 i++;
01471 }
01472
01473 }
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491 unsigned int receivedMsg = session->lastReceivedMessageID;
01492 unsigned int lastMsg = session->lastMessageID;
01493 while (!session->waiting && !session->sending &&
01494 smlQueueCheck(session->command_queue) &&
01495 smlQueueLength(session->command_queue) != smlQueueLengthPrio(session->command_queue) &&
01496 receivedMsg == session->lastReceivedMessageID &&
01497 lastMsg == session->lastMessageID)
01498 {
01499
01500
01501
01502
01503
01504
01505
01506
01507 smlQueueDispatch(session->command_queue);
01508 }
01509
01510 smlTrace(TRACE_INTERNAL, "%s: Final %i, waiting %i, sending %i",
01511 __func__, final, session->waiting, session->sending);
01512 if (session->authenticate) {
01513
01514
01515
01516 smlTrace(TRACE_INTERNAL, "%s: ongoing authentication", __func__);
01517 }
01518 else if (final) {
01519
01520
01521
01522
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535 if (session->pendingReplies) {
01536
01537
01538
01539
01540
01541
01542
01543
01544 GList *o = NULL;
01545 for (o = session->pendingReplies; o; o = o->next) {
01546 SmlPendingStatus *pending = o->data;
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562 if ((!session->waiting && pending->msgID < session->lastMessageID) ||
01563 (session->waiting && pending->msgID < session->lastMessageID - 1))
01564 {
01565 smlErrorSet(error, SML_ERROR_GENERIC, "Didn't receive a reply for pending status (actual message %i, received message %i, cmdID %i, msgID %i)", session->lastMessageID, session->lastReceivedMessageID, pending->cmdID, pending->msgID);
01566 goto error;
01567 }
01568 }
01569 }
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583 if (session->incomingBuffer) {
01584 smlErrorSet(error, SML_ERROR_GENERIC, "Incoming buffer was open when final arrived");
01585 smlCommandUnref(session->incomingBuffer);
01586 session->incomingBuffer = NULL;
01587 goto error;
01588 }
01589 } else if (!session->waiting && !session->sending) {
01590
01591
01592
01593
01594
01595
01596
01597 smlTrace(TRACE_INTERNAL, "%s: This is not the final message. Empty? %i",
01598 __func__, smlAssemblerIsEmpty(session->assembler));
01599
01600
01601
01602
01603
01604 if (smlAssemblerIsEmpty(session->assembler)) {
01605
01606
01607
01608
01609
01610
01611
01612 SmlCommand *alert = smlCommandNewAlert(SML_ALERT_NEXT_MESSAGE, NULL, NULL, NULL, NULL, NULL, error);
01613 if (!alert)
01614 goto error;
01615
01616 if (_smlSessionStartCommandInternal(session, alert, NULL, NULL, NULL, TRUE, error) != SML_ASSEMBLER_RESULT_OK)
01617 goto error;
01618 if (!_smlSessionEndCommandInternal(session, NULL, error))
01619 goto error;
01620
01621 smlCommandUnref(alert);
01622 }
01623
01624
01625
01626 if (!_smlSessionFlushInternal(session, FALSE, error))
01627 goto error;
01628 }
01629
01630 if (session->authenticate) {
01631
01632 smlTrace(TRACE_INTERNAL, "%s: ongoing authentication", __func__);
01633
01634
01635
01636 session->end = FALSE;
01637 smlTrace(TRACE_INTERNAL, "%s: flushing server finally",
01638 __func__);
01639 if (!_smlSessionFlushInternal(session, TRUE, error))
01640 goto error;
01641
01642
01643
01644 session->authenticate = FALSE;
01645 } else if (end) {
01646
01647
01648
01649
01650
01651
01652
01653 smlTrace(TRACE_INTERNAL, "%s: Ending session now", __func__);
01654 session->end = TRUE;
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665 if (final)
01666 {
01667 smlTrace(TRACE_INTERNAL, "%s: session end on final",
01668 __func__);
01669 if (session->sessionType == SML_SESSION_TYPE_SERVER)
01670 {
01671 smlTrace(TRACE_INTERNAL, "%s: flushing server finally",
01672 __func__);
01673 if (!_smlSessionFlushInternal(session, TRUE, error))
01674 goto error;
01675 }
01676 } else {
01677 if (!session->waiting)
01678 {
01679
01680
01681
01682
01683
01684
01685
01686
01687 smlErrorSet(error, SML_ERROR_BAD_REQUEST,
01688 "The message from the remote peer does not contain a command.");
01689 goto error;
01690 }
01691 }
01692
01693
01694
01695
01696
01697
01698 if (!final || session->sessionType != SML_SESSION_TYPE_SERVER)
01699 {
01700 g_mutex_lock(session->reportEnd);
01701 if (!session->reportedEnd) {
01702
01703 session->reportedEnd = TRUE;
01704 smlSessionRestoreTargetURI(session);
01705 smlSessionDispatchEvent(session, SML_SESSION_EVENT_END,
01706 NULL, NULL, NULL, NULL);
01707 }
01708 g_mutex_unlock(session->reportEnd);
01709 }
01710 }
01711
01712 smlTrace(TRACE_EXIT, "%s", __func__);
01713 return TRUE;
01714
01715 error_free_cmd:
01716 if (cmd)
01717 smlCommandUnref(cmd);
01718 error_free_status:
01719 if (status)
01720 smlStatusUnref(status);
01721 error:
01722 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
01723 return FALSE;
01724 }
01725
01726 void smlSessionSetEventCallback(SmlSession *session, SmlSessionEventCallback callback, void *userdata)
01727 {
01728 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, callback, userdata);
01729 smlAssert(session);
01730
01731 session->eventCallback = callback;
01732 session->eventCallbackUserdata = userdata;
01733
01734 smlTrace(TRACE_EXIT, "%s", __func__);
01735 }
01736
01737 void smlSessionSetDataCallback(SmlSession *session, SmlSessionDataCallback callback, void *userdata)
01738 {
01739 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, callback, userdata);
01740 smlAssert(session);
01741
01742 session->dataCallback = callback;
01743 session->dataCallbackUserdata = userdata;
01744
01745 smlTrace(TRACE_EXIT, "%s", __func__);
01746 }
01747
01748 const char *smlSessionGetSessionID(SmlSession *session)
01749 {
01750 smlAssert(session);
01751
01752 return session->sessionID;
01753 }
01754
01755 void smlSessionSetSessionID(SmlSession *session, const char *sessionID)
01756 {
01757 smlAssert(session);
01758
01759 if (session->sessionID)
01760 smlSafeCFree(&(session->sessionID));
01761 session->sessionID = g_strdup(sessionID);
01762 }
01763
01764 SmlProtocolVersion smlSessionGetVersion(SmlSession *session)
01765 {
01766 smlAssert(session);
01767
01768 return session->version;
01769 }
01770
01771 SmlLocation *smlSessionGetSource(SmlSession *session)
01772 {
01773 smlAssert(session);
01774 return session->source;
01775 }
01776
01777 SmlLocation *smlSessionGetTarget(SmlSession *session)
01778 {
01779 smlAssert(session);
01780 return session->target;
01781 }
01782
01783 void smlSessionRegisterCred(SmlSession *session, SmlCred *cred)
01784 {
01785 smlAssert(session);
01786 smlAssert(session->sessionType == SML_SESSION_TYPE_CLIENT);
01787 smlAssert(cred);
01788 if (session->cred)
01789 smlCredUnref(session->cred);
01790 session->cred = cred;
01791 if (cred->username)
01792 smlLocationSetName(session->source, cred->username);
01793 smlCredRef(session->cred);
01794 }
01795
01807
01813
01832 SmlSession *smlSessionNew(SmlSessionType sessionType, SmlMimeType mimetype, SmlProtocolVersion version, SmlProtocolType protocol, SmlLocation *target, SmlLocation *source, const char *sessionID, unsigned int messageID, SmlError **error)
01833 {
01834 smlTrace(TRACE_ENTRY, "%s(%i, %i, %i, %i, %p, %p, %s, %i, %p)", __func__, sessionType, mimetype, version, protocol, target, source, VA_STRING(sessionID), messageID, error);
01835 CHECK_ERROR_REF
01836
01837
01838 if (!g_thread_supported ()) g_thread_init (NULL);
01839
01840
01841 SmlSession *session = smlTryMalloc0(sizeof(SmlSession), error);
01842 if (!session)
01843 goto error;
01844
01845 session->dispatch_mutex = g_mutex_new();
01846 session->refCount = 1;
01847 session->eventCallback = NULL;
01848 session->version = version;
01849 session->protocol = protocol;
01850 session->type = mimetype;
01851 session->sessionID = g_strdup(sessionID);
01852 if (messageID)
01853 session->lastMessageID = messageID;
01854 else
01855 session->lastMessageID = 1;
01856
01857 session->end = FALSE;
01858 session->reportEnd = g_mutex_new();
01859 session->reportedEnd = FALSE;
01860 session->sessionType = sessionType;
01861 session->lastCommandID = 0;
01862
01863 if (sessionType == SML_SESSION_TYPE_CLIENT)
01864 session->sending = TRUE;
01865 else
01866 session->sending = FALSE;
01867
01868 session->source = source;
01869 smlLocationRef(source);
01870
01871 session->target = target;
01872 smlLocationRef(target);
01873
01874 session->cred = NULL;
01875 session->chal = NULL;
01876
01877
01878
01879 session->assembler = smlAssemblerNew(mimetype, 0, error);
01880 if (!session->assembler)
01881 goto error_free_session;
01882 smlAssemblerSetOption(session->assembler, "USE_STRTABLE", "1");
01883
01884 if (!smlAssemblerStart(session->assembler, session, error))
01885 goto error_free_session;
01886
01887
01888
01889
01890
01891
01892
01893 session->assmHasHeader = FALSE;
01894
01895 session->command_queue = smlQueueNew(error);
01896 if (!session->command_queue)
01897 goto error_free_session;
01898 smlQueueSetHandler(session->command_queue, (SmlQueueHandler)_smlSessionCommandHandler, session);
01899
01900 smlTrace(TRACE_EXIT, "%s: %p", __func__, session);
01901 return session;
01902
01903 error_free_session:
01904 smlSessionUnref(session);
01905 error:
01906 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
01907 return NULL;
01908 }
01909
01910 SmlSession *smlSessionRef(SmlSession *session)
01911 {
01912 smlTrace(TRACE_ENTRY, "%s(%p)", __func__, session);
01913 smlAssert(session);
01914
01915 g_atomic_int_inc(&(session->refCount));
01916
01917 smlTrace(TRACE_EXIT, "%s: New refcount: %i", __func__, session->refCount);
01918 return session;
01919 }
01920
01921 void smlSessionUnref(SmlSession *session)
01922 {
01923 smlTrace(TRACE_ENTRY, "%s(%p)", __func__, session);
01924 smlAssert(session);
01925
01926 if (g_atomic_int_dec_and_test(&(session->refCount))) {
01927 smlTrace(TRACE_INTERNAL, "%s: Refcount == 0!", __func__);
01928
01929 if (session->target)
01930 smlLocationUnref(session->target);
01931
01932 if (session->responseURI)
01933 smlSafeCFree(&(session->responseURI));
01934
01935 if (session->source)
01936 smlLocationUnref(session->source);
01937
01938 if (session->cred)
01939 smlCredUnref(session->cred);
01940
01941 if (session->chal)
01942 smlChalUnref(session->chal);
01943
01944 if (session->sessionID)
01945 smlSafeCFree(&(session->sessionID));
01946
01947 if (session->command_queue) {
01948 SmlSessionCommand *sesscmd = NULL;
01949 while ((sesscmd = smlQueueTryPop(session->command_queue)))
01950 _smlSessionCommandFree(sesscmd);
01951
01952 smlQueueFree(session->command_queue);
01953 }
01954
01955 _smlSessionFreePendingReplies(session);
01956
01957 if (session->assembler)
01958 smlAssemblerFree(session->assembler);
01959
01960 if (session->incomingBuffer) {
01961 smlTrace(TRACE_INTERNAL, "%s: There is an unhandled incoming buffer.", __func__);
01962 smlCommandUnref(session->incomingBuffer);
01963 }
01964
01965 if (session->parentCommand)
01966 smlCommandUnref(session->parentCommand);
01967
01968 smlTrace(TRACE_INTERNAL, "%s: cleanup dispatch mutex", __func__);
01969 if (!g_mutex_trylock(session->dispatch_mutex))
01970 g_warning("%s: The session is still locked for dispatching - forcing unlock/free.",
01971 __func__);
01972 g_mutex_unlock(session->dispatch_mutex);
01973 g_mutex_free(session->dispatch_mutex);
01974 smlTrace(TRACE_INTERNAL, "%s: cleanup reportEnd mutex", __func__);
01975
01976 if (!g_mutex_trylock(session->reportEnd))
01977 g_warning("%s: The reportEnd is still locked to set reportEnd - forcing unlock/free.",
01978 __func__);
01979 g_mutex_unlock(session->reportEnd);
01980 g_mutex_free(session->reportEnd);
01981
01982 smlSafeFree((gpointer *)&session);
01983 }
01984
01985 smlTrace(TRACE_EXIT, "%s", __func__);
01986 }
01987
01995
02010 SmlBool smlSessionFlush(SmlSession *session, SmlBool final, SmlError **error)
02011 {
02012 smlTrace(TRACE_ENTRY, "%s(%p, %i, %p)", __func__, session, final, error);
02013 smlAssert(session);
02014 CHECK_ERROR_REF
02015
02016 SmlSessionCommand *sesscmd = smlTryMalloc0(sizeof(SmlSessionCommand), error);
02017 if (!sesscmd)
02018 goto error;
02019
02020 sesscmd->type = SML_SESSION_FLUSH;
02021 sesscmd->final = final;
02022
02023 smlTrace(TRACE_INTERNAL, "%s: sending flush (%i) command %p via queue %p",
02024 __func__, SML_SESSION_FLUSH, sesscmd, session->command_queue);
02025
02026 smlQueueSend(session->command_queue, sesscmd);
02027
02028
02029 session->end = FALSE;
02030
02031 smlTrace(TRACE_EXIT, "%s", __func__);
02032 return TRUE;
02033
02034 error:
02035 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
02036 return FALSE;
02037 }
02038
02057 SmlBool smlSessionEnd(SmlSession *session, SmlError **error)
02058 {
02059 smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, session, error);
02060 smlAssert(session);
02061 CHECK_ERROR_REF
02062
02063 g_mutex_lock(session->reportEnd);
02064 if (session->reportedEnd)
02065 {
02066
02067
02068
02069
02070
02071
02072 g_mutex_unlock(session->reportEnd);
02073 smlTrace(TRACE_EXIT, "%s - session end already signalled.", __func__);
02074 return TRUE;
02075 }
02076 session->reportedEnd = TRUE;
02077
02078
02079
02080
02081
02082
02083
02084
02085
02086
02087
02088
02089 if (smlSessionCheck(session) ||
02090 (!session->end && session->lastCommandID))
02091 {
02092
02093
02094
02095 session->reportedEnd = FALSE;
02096
02097 SmlSessionCommand *sesscmd = smlTryMalloc0(sizeof(SmlSessionCommand), error);
02098 if (!sesscmd)
02099 goto error;
02100
02101 sesscmd->type = SML_SESSION_FLUSH;
02102 sesscmd->final = TRUE;
02103 sesscmd->end = TRUE;
02104 smlTrace(TRACE_INTERNAL, "%s: sending command %p", sesscmd);
02105
02106 smlQueueSend(session->command_queue, sesscmd);
02107 } else {
02108
02109
02110
02111 smlTrace(TRACE_INTERNAL, "%s: no status/command ... only sending event", __func__);
02112 smlSessionRestoreTargetURI(session);
02113 smlSessionDispatchEvent(session, SML_SESSION_EVENT_END, NULL, NULL, NULL, NULL);
02114 }
02115
02116 g_mutex_unlock(session->reportEnd);
02117 smlTrace(TRACE_EXIT, "%s", __func__);
02118 return TRUE;
02119
02120 error:
02121 g_mutex_unlock(session->reportEnd);
02122 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
02123 return FALSE;
02124 }
02125
02126
02127 void smlSessionRestoreTargetURI(SmlSession *session)
02128 {
02129 smlTrace(TRACE_ENTRY, "%s(%p)", __func__, session);
02130 smlAssert(session);
02131
02132 if (session->orgTarget) {
02133
02134
02135
02136
02137 smlLocationUnref(session->target);
02138 session->target = session->orgTarget;
02139 session->orgTarget = NULL;
02140
02141
02142
02143
02144 }
02145
02146 smlTrace(TRACE_EXIT, "%s", __func__);
02147 }
02148
02149
02150 SmlBool smlSessionSetResponseURI(
02151 SmlSession *session,
02152 const char *responseURI,
02153 SmlError **error)
02154 {
02155 smlTrace(TRACE_ENTRY, "%s(%p, %s, %p)", __func__, session, VA_STRING(responseURI), error);
02156 CHECK_ERROR_REF
02157
02158 if (session->responseURI) {
02159 g_warning("The response URI (%s) of a session (%s) should never be overwritten (%s).",
02160 session->responseURI, session->sessionID, responseURI);
02161 smlSafeCFree(&(session->responseURI));
02162 }
02163
02164 session->responseURI = g_strdup(responseURI);
02165
02166 smlTrace(TRACE_EXIT, "%s", __func__);
02167 return TRUE;
02168 }
02169
02170 void smlSessionUseStringTable(SmlSession *session, SmlBool useStringtable)
02171 {
02172 smlTrace(TRACE_ENTRY, "%s(%p, %i)", __func__, session, useStringtable);
02173 smlAssert(session);
02174
02175 smlAssemblerSetOption(session->assembler, "USE_STRTABLE", useStringtable ? "1" : "0");
02176
02177 smlTrace(TRACE_EXIT, "%s", __func__);
02178 }
02179
02180 void smlSessionUseNumberOfChanges(SmlSession *session, SmlBool support)
02181 {
02182 smlTrace(TRACE_ENTRY, "%s(%p, %i)", __func__, session, support);
02183 smlAssert(session);
02184
02185 smlAssemblerSetOption(session->assembler, "USE_NUMBEROFCHANGES", support ? "1" : "0");
02186
02187 smlTrace(TRACE_EXIT, "%s", __func__);
02188 }
02189
02190 void smlSessionUseLargeObjects(SmlSession *session, SmlBool support)
02191 {
02192 smlTrace(TRACE_ENTRY, "%s(%p, %i)", __func__, session, support);
02193 smlAssert(session);
02194
02195 smlAssemblerSetOption(session->assembler, "USE_LARGEOBJECTS", support ? "1" : "0");
02196
02197 smlTrace(TRACE_EXIT, "%s", __func__);
02198 }
02199
02200 void smlSessionUseOnlyReplace(SmlSession *session, SmlBool onlyReplace)
02201 {
02202 smlTrace(TRACE_ENTRY, "%s(%p, %i)", __func__, session, onlyReplace);
02203 smlAssert(session);
02204
02205 smlAssemblerSetOption(session->assembler, "ONLY_REPLACE", onlyReplace ? "1" : "0");
02206 session->onlyReplace = onlyReplace;
02207
02208 smlTrace(TRACE_EXIT, "%s", __func__);
02209 }
02210
02211
02212 void smlSessionSetSendingLimit(SmlSession *session, unsigned int limit)
02213 {
02214 smlSessionSetRemoteMaxMsgSize(session, limit);
02215 }
02216
02217
02218 unsigned int smlSessionGetSendingLimit(SmlSession *session)
02219 {
02220 return smlSessionGetRemoteMaxMsgSize(session);
02221 }
02222
02223
02224 void smlSessionSetReceivingLimit(SmlSession *session, unsigned int limit)
02225 {
02226 smlSessionSetLocalMaxMsgSize(session, limit);
02227 }
02228
02229
02230 void smlSessionSetSendingMaxMsgSize(SmlSession *session, unsigned int size)
02231 {
02232 smlSessionSetRemoteMaxMsgSize(session, size);
02233 }
02234
02235
02236 unsigned int smlSessionGetSendingMaxMsgSize(SmlSession *session)
02237 {
02238 return smlSessionGetRemoteMaxMsgSize(session);
02239 }
02240
02241
02242 void smlSessionSetReceivingMaxMsgSize(SmlSession *session, unsigned int size)
02243 {
02244 smlSessionSetLocalMaxMsgSize(session, size);
02245 }
02246
02247 void smlSessionSetRemoteMaxMsgSize(SmlSession *session, unsigned int size)
02248 {
02249 smlTrace(TRACE_ENTRY, "%s(%p, %u)", __func__, session, size);
02250 smlAssert(session);
02251
02252 smlAssemblerSetRemoteMaxMsgSize(session->assembler, size);
02253
02254 smlTrace(TRACE_EXIT, "%s", __func__);
02255 }
02256
02257 unsigned int smlSessionGetRemoteMaxMsgSize(SmlSession *session)
02258 {
02259 smlAssert(session);
02260 return smlAssemblerGetRemoteMaxMsgSize(session->assembler);
02261 }
02262
02263 void smlSessionSetLocalMaxMsgSize(SmlSession *session, unsigned int size)
02264 {
02265 smlTrace(TRACE_ENTRY, "%s(%p, %u)", __func__, session, size);
02266 smlAssert(session);
02267
02268 if (! smlSessionGetRemoteMaxMsgSize(session) > 0 ||
02269 smlSessionGetRemoteMaxMsgSize(session) > size)
02270 {
02271 session->localMaxMsgSize = size;
02272 } else {
02273 session->localMaxMsgSize = smlSessionGetRemoteMaxMsgSize(session);
02274 }
02275
02276 smlTrace(TRACE_EXIT, "%s", __func__);
02277 }
02278
02279 unsigned int smlSessionGetLocalMaxMsgSize(SmlSession *session)
02280 {
02281 smlAssert(session);
02282 return session->localMaxMsgSize;
02283 }
02284
02285
02286 void smlSessionSetSendingMaxObjSize(SmlSession *session, int limit)
02287 {
02288 smlSessionSetRemoteMaxObjSize(session, limit);
02289 }
02290
02291
02292 void smlSessionSetRequestedMaxObjSize(SmlSession *session, int limit)
02293 {
02294 smlSessionSetRemoteMaxObjSize(session, limit);
02295 }
02296
02297
02298 int smlSessionGetSendingMaxObjSize(SmlSession *session)
02299 {
02300 return smlSessionGetRemoteMaxObjSize(session);
02301 }
02302
02303
02304 void smlSessionSetReceivingMaxObjSize(SmlSession *session, unsigned int limit)
02305 {
02306 smlSessionSetLocalMaxObjSize(session, limit);
02307 }
02308
02309
02310 unsigned int smlSessionGetReceivingMaxObjSize(SmlSession *session)
02311 {
02312 return smlSessionGetLocalMaxObjSize(session);
02313 }
02314
02325 void smlSessionSetRemoteMaxObjSize(SmlSession *session, unsigned int limit)
02326 {
02327 smlTrace(TRACE_ENTRY, "%s(%p, %i)", __func__, session, limit);
02328 smlAssert(session);
02329
02330 smlAssemblerSetRemoteMaxObjSize(session->assembler, limit);
02331
02332 smlTrace(TRACE_EXIT, "%s", __func__);
02333 }
02334
02339 unsigned int smlSessionGetRemoteMaxObjSize(SmlSession *session)
02340 {
02341 smlTrace(TRACE_ENTRY, "%s(%p)", __func__, session);
02342 smlAssert(session);
02343
02344 int result = smlAssemblerGetRemoteMaxObjSize(session->assembler);
02345
02346 smlTrace(TRACE_EXIT, "%s => %i", __func__, result);
02347 return result;
02348 }
02349
02363 void smlSessionSetLocalMaxObjSize(SmlSession *session, unsigned int limit)
02364 {
02365 smlTrace(TRACE_ENTRY, "%s(%p, %u)", __func__, session, limit);
02366 smlAssert(session);
02367
02368 int remoteLimit = smlSessionGetRemoteMaxObjSize(session);
02369
02370 if (remoteLimit > 0)
02371 {
02372
02373 if ((unsigned int)remoteLimit > limit && limit > 0)
02374 {
02375
02376
02377
02378
02379 session->localMaxObjSize = limit;
02380 } else {
02381
02382
02383
02384
02385
02386 session->localMaxObjSize = remoteLimit;
02387 }
02388 } else {
02389
02390 session->localMaxObjSize = limit;
02391 }
02392
02393 smlTrace(TRACE_EXIT, "%s => %d", __func__, session->localMaxObjSize);
02394 }
02395
02396 unsigned int smlSessionGetLocalMaxObjSize(SmlSession *session)
02397 {
02398 smlAssert(session);
02399 return session->localMaxObjSize;
02400 }
02401
02422 SmlBool smlSessionSendCommand(SmlSession *session, SmlCommand *cmd, SmlCommand *parent, SmlStatusReplyCb callback, void *userdata, SmlError **error)
02423 {
02424 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p, %p, %p)", __func__, session, cmd, parent, callback, userdata, error);
02425 smlAssert(session);
02426 smlAssert(cmd);
02427 CHECK_ERROR_REF
02428
02429 if (!smlSessionStartCommand(session, cmd, parent, callback, userdata, error))
02430 goto error;
02431
02432 if (!smlSessionEndCommand(session, parent, error))
02433 goto error;
02434
02435 smlTrace(TRACE_EXIT, "%s", __func__);
02436 return TRUE;
02437
02438 error:
02439 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
02440 return FALSE;
02441 }
02442
02454 SmlBool smlSessionStartCommand(SmlSession *session, SmlCommand *cmd, SmlCommand *parent, SmlStatusReplyCb callback, void *userdata, SmlError **error)
02455 {
02456 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p, %p, %p)", __func__, session, cmd, parent, callback, userdata, error);
02457 smlAssert(session);
02458 smlAssert(cmd);
02459 CHECK_ERROR_REF
02460
02461 SmlSessionCommand *sesscmd = smlTryMalloc0(sizeof(SmlSessionCommand), error);
02462 if (!sesscmd)
02463 goto error;
02464
02465 sesscmd->type = SML_SESSION_COMMAND_START;
02466 sesscmd->cmd = cmd;
02467 smlCommandRef(cmd);
02468
02469 if (parent) {
02470 sesscmd->parent = parent;
02471 smlCommandRef(parent);
02472 }
02473
02474 sesscmd->callback = callback;
02475 sesscmd->callbackUserdata = userdata;
02476
02477 smlQueueSend(session->command_queue, sesscmd);
02478
02479 smlTrace(TRACE_EXIT, "%s", __func__);
02480 return TRUE;
02481
02482 error:
02483 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
02484 return FALSE;
02485 }
02486
02495 SmlBool smlSessionEndCommand(SmlSession *session, SmlCommand *parent, SmlError **error)
02496 {
02497 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, parent, error);
02498 smlAssert(session);
02499 CHECK_ERROR_REF
02500
02501 SmlSessionCommand *sesscmd = smlTryMalloc0(sizeof(SmlSessionCommand), error);
02502 if (!sesscmd)
02503 goto error;
02504
02505 sesscmd->type = SML_SESSION_COMMAND_END;
02506
02507 if (parent) {
02508 sesscmd->parent = parent;
02509 smlCommandRef(parent);
02510 }
02511
02512 smlQueueSend(session->command_queue, sesscmd);
02513
02514 smlTrace(TRACE_EXIT, "%s", __func__);
02515 return TRUE;
02516
02517 error:
02518 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
02519 return FALSE;
02520 }
02521
02522
02536 SmlBool smlSessionSendReply(SmlSession *session, SmlStatus *status, SmlError **error)
02537 {
02538 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, status, error);
02539 smlAssert(session);
02540 smlAssert(status);
02541 CHECK_ERROR_REF
02542
02543 SmlSessionCommand *sesscmd = smlTryMalloc0(sizeof(SmlSessionCommand), error);
02544 if (!sesscmd)
02545 goto error;
02546
02547 sesscmd->type = SML_SESSION_STATUS;
02548 sesscmd->status = status;
02549 smlStatusRef(status);
02550
02551 smlQueueSendPrio(session->command_queue, sesscmd);
02552
02553 smlTrace(TRACE_EXIT, "%s", __func__);
02554 return TRUE;
02555
02556 error:
02557 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
02558 return FALSE;
02559 }
02560