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_manager_internals.h"
00027 #include "sml_transport_internals.h"
00028 #include "sml_command_internals.h"
00029 #include "sml_elements_internals.h"
00030 #include "sml_session_internals.h"
00031
00032 typedef struct managerSession {
00033 SmlLink *link;
00034 SmlSession *session;
00035 unsigned int finalLock;
00036 SmlTransport *transport;
00037 GList *objects;
00038 } managerSession;
00039
00040 managerSession *_smlManagerGetManagerSession(SmlManager *manager, SmlSession *session);
00041
00042 SmlObject *smlManagerObjectFindInternal(
00043 SmlManager *manager,
00044 SmlSession *session,
00045 SmlCommandType type,
00046 SmlLocation *target,
00047 SmlLocation *source,
00048 const char* contentType);
00049
00050 static managerSession *_manager_session_find(SmlManager *manager, SmlSession *session)
00051 {
00052 smlAssert(session);
00053 smlAssert(manager);
00054
00055 GList *s = NULL;
00056 for (s = manager->sessions; s; s = s->next) {
00057 managerSession *sess = s->data;
00058 if (sess->session == session)
00059 return sess;
00060 }
00061 return NULL;
00062 }
00063
00064 static void _manager_session_free(managerSession *sess)
00065 {
00066 smlAssert(sess);
00067
00068 smlSessionUnref(sess->session);
00069
00070 if (sess->link)
00071 smlLinkDeref(sess->link);
00072
00073 while (sess->objects) {
00074 SmlObject *object = sess->objects->data;
00075 smlManagerObjectFree(object);
00076 sess->objects = g_list_delete_link(sess->objects, sess->objects);
00077 }
00078
00079 smlSafeFree((gpointer *)&sess);
00080 }
00081
00082 static gboolean _manager_prepare_internal(GSource *source, gint *timeout_)
00083 {
00084 smlTrace(TRACE_INTERNAL, "%s(%p, %p)", __func__, source, timeout_);
00085 *timeout_ = 1;
00086 return FALSE;
00087 }
00088
00089 static gboolean _manager_check_internal(GSource *source)
00090 {
00091 SmlManager *manager = *((SmlManager **)(source + 1));
00092 GList *s = NULL;
00093 for (s = manager->sessions; s; s = s->next) {
00094 managerSession *session = s->data;
00095 if (smlSessionCheck(session->session))
00096 return TRUE;
00097 }
00098 return FALSE;
00099 }
00100
00101 static gboolean _manager_dispatch_internal(GSource *source, GSourceFunc callback, gpointer user_data)
00102 {
00103 smlTrace(TRACE_INTERNAL, "%s(%p, %p, %p)", __func__, source, callback, user_data);
00104 int max = 100;
00105
00106 SmlManager *manager = user_data;
00107 GList *s = NULL;
00108 for (s = manager->sessions; s; s = s->next) {
00109 managerSession *session = s->data;
00110 while (smlSessionCheck(session->session) && max) {
00111
00112
00113
00114
00115
00116
00117 if (smlSessionTryLock(session->session))
00118 {
00119 smlSessionDispatch(session->session);
00120 smlSessionUnlock(session->session);
00121 }
00122 max--;
00123 }
00124 }
00125
00126 return TRUE;
00127 }
00128
00129 static void _smlManagerSendEvent(SmlManager *manager, SmlManagerEventType type, SmlSession *session, SmlCommand *command, SmlCommand *parent, SmlError *error)
00130 {
00131 smlTrace(TRACE_ENTRY, "%s(%p, %i, %p, %p, %p, %p)", __func__, manager, type, session, command, parent, error);
00132
00133 SmlError *lerr = NULL;
00134 SmlManagerEvent *event = smlTryMalloc0(sizeof(SmlManagerEvent), &lerr);
00135 if (event) {
00136 event->type = type;
00137
00138 if (session) {
00139 event->session = session;
00140 smlSessionRef(session);
00141 } else {
00142 event->session = NULL;
00143 }
00144
00145 if (command) {
00146 event->command = command;
00147 smlCommandRef(command);
00148 } else {
00149 event->command = NULL;
00150 }
00151
00152 if (parent) {
00153 event->parent = parent;
00154 smlCommandRef(parent);
00155 } else {
00156 event->parent = NULL;
00157 }
00158
00159 if (error) {
00160 event->error = error;
00161 smlErrorRef(&error);
00162 }
00163
00164 smlQueueSend(manager->userEventQueue, event);
00165 } else {
00166
00167 g_error("%s", smlErrorPrint(&lerr));
00168 smlErrorDeref(&lerr);
00169 }
00170
00171 smlTrace(TRACE_EXIT, "%s", __func__);
00172 }
00173
00174 void _smlManagerEventFree(SmlManagerEvent *event)
00175 {
00176 smlTrace(TRACE_ENTRY, "%s(%p)", __func__, event);
00177 smlAssert(event);
00178
00179 if (event->session)
00180 smlSessionUnref(event->session);
00181
00182 if (event->command)
00183 smlCommandUnref(event->command);
00184
00185 if (event->parent)
00186 smlCommandUnref(event->parent);
00187
00188 if (event->error)
00189 smlErrorDeref(&(event->error));
00190
00191 smlSafeFree((gpointer *)&event);
00192
00193 smlTrace(TRACE_EXIT, "%s", __func__);
00194 }
00195
00196
00197
00198 static SmlBool _smlManagerDataHandler(SmlTransport *tsp, SmlLink *link_, SmlTransportEventType type, SmlTransportData *data, SmlError *error, void *userdata)
00199 {
00200 smlTrace(TRACE_ENTRY, "%s(%p, %p, %i, %p, %p, %p)", __func__, tsp, link_, type, data, error, userdata);
00201 smlAssert(userdata);
00202 SmlManager *manager = userdata;
00203 SmlParser *parser = NULL;
00204 SmlHeader *header = NULL;
00205 SmlCred *cred = NULL;
00206 SmlSession *session = NULL;
00207 SmlError *locerror = NULL;
00208
00209 switch (type) {
00210 case SML_TRANSPORT_EVENT_CONNECT_DONE:
00211
00212 _smlManagerSendEvent(manager, SML_MANAGER_CONNECT_DONE, NULL, NULL, NULL, NULL);
00213 break;
00214 case SML_TRANSPORT_EVENT_DISCONNECT_DONE:
00215
00216 _smlManagerSendEvent(manager, SML_MANAGER_DISCONNECT_DONE, NULL, NULL, NULL, NULL);
00217 break;
00218 case SML_TRANSPORT_EVENT_DATA:
00219
00220 parser = smlParserNew(data->type, 0, &locerror);
00221 if (!parser)
00222 goto session_error;
00223
00224 smlParserSetManager(parser, manager);
00225
00226
00227 if (!smlParserStart(parser, data->data, data->size, &locerror))
00228 goto error_free_parser;
00229
00230
00231 header = NULL;
00232 cred = NULL;
00233 if (!smlParserGetHeader(parser, &header, &cred, &locerror))
00234 goto error_free_parser;
00235
00236
00237 session = smlManagerSessionFind(manager, header->sessionID);
00238 if (!session) {
00239
00240
00241 SmlSessionType sessionType;
00242 switch(smlTransportGetType(tsp))
00243 {
00244 case SML_TRANSPORT_OBEX_CLIENT:
00245
00246
00247
00248 sessionType = SML_SESSION_TYPE_SERVER;
00249 break;
00250 case SML_TRANSPORT_OBEX_SERVER:
00251 sessionType = SML_SESSION_TYPE_CLIENT;
00252 break;
00253 case SML_TRANSPORT_HTTP_SERVER:
00254 sessionType = SML_SESSION_TYPE_SERVER;
00255 break;
00256 default:
00257 smlErrorSet(&locerror,
00258 SML_ERROR_NOT_IMPLEMENTED,
00259 "New session was unexpectedly received for transport %d.",
00260 smlTransportGetType(tsp));
00261 goto error_free_header;
00262 break;
00263 }
00264 if (!(session = smlSessionNew(
00265 sessionType, data->type,
00266 header->version, header->protocol,
00267 header->source, header->target,
00268 header->sessionID, 1, &locerror)))
00269 goto error_free_header;
00270 if (link_)
00271 {
00272 char *responseURI = smlTransportGetResponseURI(link_, session, &locerror);
00273 if (!responseURI && locerror)
00274 goto error_free_header;
00275 if (responseURI)
00276 {
00277 if (!smlSessionSetResponseURI(session, responseURI, &locerror))
00278 {
00279 smlSafeCFree(&responseURI);
00280 goto error_free_header;
00281 }
00282 smlSafeCFree(&responseURI);
00283 }
00284 }
00285 if (!smlManagerSessionAdd(manager, session, link_, &locerror))
00286 goto error_free_header;
00287 smlSessionUnref(session);
00288 } else {
00289
00290
00291
00292 if (link_) {
00293 char *responseUri = smlTransportGetResponseURI(link_, session, &locerror);
00294 if (!responseUri && locerror) {
00295 goto error_free_header;
00296 }
00297 if (responseUri)
00298 smlSafeCFree(&responseUri);
00299 }
00300 }
00301
00302
00303
00304
00305
00306
00307
00308 smlSessionLock(session);
00309
00310
00311
00312
00313
00314
00315 GList *s;
00316 for (s = manager->sessions; s; s = s->next) {
00317 managerSession *sess = s->data;
00318 if (sess->session == session) {
00319 if (sess->link)
00320 smlLinkDeref(sess->link);
00321 sess->link = link_;
00322 if (link_)
00323 smlLinkRef(sess->link);
00324 break;
00325 }
00326 }
00327
00328
00329 if (!smlSessionReceiveHeader(session, header, &locerror))
00330 goto error_free_header;
00331
00332
00333 if (!smlManagerDispatchHeader(manager, session, header, cred, &locerror))
00334 goto error_free_header;
00335
00336 smlHeaderFree(header);
00337 if (cred)
00338 smlCredUnref(cred);
00339
00340
00341 if (!smlSessionReceiveBody(session, parser, &locerror))
00342 goto error_free_parser;
00343
00344
00345 smlParserFree(parser);
00346
00347
00348 smlSessionUnlock(session);
00349
00350 break;
00351 case SML_TRANSPORT_EVENT_ERROR:
00352
00353 smlErrorDuplicate(&locerror, &error);
00354 goto transport_error;
00355 break;
00356 }
00357
00358 smlTrace(TRACE_EXIT, "%s", __func__);
00359 return TRUE;
00360
00361 error_free_header:
00362 if (header)
00363 smlHeaderFree(header);
00364 if (cred)
00365 smlCredUnref(cred);
00366 error_free_parser:
00367 smlParserFree(parser);
00368 if (session)
00369 smlSessionUnlock(session);
00370 session_error:
00371 if (session == NULL && link_ && type == SML_TRANSPORT_EVENT_DATA) {
00372
00373
00374
00375
00376
00377
00378 SmlError *herror = NULL;
00379 if (!smlTransportDisconnect(manager->transport, link_, &herror)) {
00380 smlTrace(TRACE_ERROR, "%s: Disconnect on error failed. %s",
00381 smlErrorPrint(&herror));
00382 smlErrorDeref(&herror);
00383 }
00384 }
00385 _smlManagerSendEvent(manager, SML_MANAGER_SESSION_ERROR, session, NULL, NULL, locerror);
00386 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(&locerror));
00387 smlErrorDeref(&locerror);
00388 return FALSE;
00389
00390 transport_error:
00391 _smlManagerSendEvent(manager, SML_MANAGER_TRANSPORT_ERROR, NULL, NULL, NULL, locerror);
00392 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(&locerror));
00393 smlErrorDeref(&locerror);
00394 return FALSE;
00395 }
00396
00397 SmlManager *smlManagerNew(SmlTransport *tsp, SmlError **error)
00398 {
00399 smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, tsp, error);
00400 smlAssert(tsp);
00401 CHECK_ERROR_REF
00402
00403 SmlManager *manager = smlTryMalloc0(sizeof(SmlManager), error);
00404 if (!manager)
00405 goto error;
00406
00407 smlTransportSetEventCallback(tsp, _smlManagerDataHandler, manager);
00408 manager->transport = tsp;
00409
00410 manager->running_mutex = g_mutex_new();
00411 manager->running = g_cond_new();
00412
00413 manager->userEventQueue = smlQueueNew(error);
00414 if (!manager->userEventQueue)
00415 goto error_free_manager;
00416
00417 smlTrace(TRACE_EXIT, "%s", __func__);
00418 return manager;
00419
00420 error_free_manager:
00421 smlSafeFree((gpointer *)&manager);
00422 error:
00423 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
00424 return NULL;
00425 }
00426
00427 void smlManagerFree(SmlManager *manager)
00428 {
00429 smlTrace(TRACE_ENTRY, "%s(%p)", __func__, manager);
00430 smlAssert(manager);
00431
00432
00433 if (manager->context)
00434 smlManagerStop(manager);
00435
00436
00437
00438
00439
00440 if (manager->transport)
00441 smlTransportSetEventCallback(manager->transport, NULL, NULL);
00442
00443 while (manager->sessions) {
00444 managerSession *sess = manager->sessions->data;
00445
00446 _manager_session_free(sess);
00447
00448 manager->sessions = g_list_delete_link(manager->sessions, manager->sessions);
00449 }
00450
00451 while (manager->objects) {
00452 SmlObject *object = manager->objects->data;
00453
00454 smlManagerObjectFree(object);
00455 manager->objects = g_list_remove(manager->objects, object);
00456 }
00457
00458 if (manager->userEventQueue) {
00459 SmlManagerEvent *event = NULL;
00460 while ((event = smlQueueTryPop(manager->userEventQueue)))
00461 _smlManagerEventFree(event);
00462
00463 smlQueueFree(manager->userEventQueue);
00464 manager->userEventQueue = NULL;
00465 }
00466
00467 g_cond_free(manager->running);
00468 g_mutex_free(manager->running_mutex);
00469
00470 smlSafeFree((gpointer *)&manager);
00471
00472 smlTrace(TRACE_EXIT, "%s", __func__);
00473 }
00474
00475 void smlManagerSetEventCallback(SmlManager *manager, SmlManagerEventCb callback, void *userdata)
00476 {
00477 smlAssert(manager);
00478 smlAssert(callback);
00479
00480 manager->eventCallback = callback;
00481 manager->eventCallbackUserdata = userdata;
00482 }
00483
00484 SmlBool smlManagerStart(SmlManager *manager, SmlError **error)
00485 {
00486 smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, manager, error);
00487 smlAssert(manager);
00488 CHECK_ERROR_REF
00489
00490 manager->context = g_main_context_new();
00491 if (!manager->context) {
00492 smlErrorSet(error, SML_ERROR_GENERIC,
00493 "Cannot create new main context.");
00494 goto error;
00495 }
00496
00497 manager->functions = smlTryMalloc0(sizeof(GSourceFuncs), error);
00498 if (!manager->functions)
00499 goto error;
00500
00501 manager->functions->prepare = _manager_prepare_internal;
00502 manager->functions->check = _manager_check_internal;
00503 manager->functions->dispatch = _manager_dispatch_internal;
00504 manager->functions->finalize = NULL;
00505
00506 manager->thread = smlThreadNew(manager->context, error);
00507 if (!manager->thread)
00508 goto error;
00509 smlThreadStart(manager->thread);
00510
00511 manager->source = g_source_new(manager->functions, sizeof(GSource) + sizeof(SmlManager *));
00512 SmlManager **managerptr = (SmlManager **)(manager->source + 1);
00513 *managerptr = manager;
00514 g_source_set_callback(manager->source, NULL, manager, NULL);
00515 g_source_attach(manager->source, manager->context);
00516
00517 smlTrace(TRACE_EXIT, "%s", __func__);
00518 return TRUE;
00519
00520 error:
00521 if (manager->context) {
00522 g_main_context_unref(manager->context);
00523 manager->context = NULL;
00524 }
00525 if (manager->functions)
00526 smlSafeFree((gpointer *)&(manager->functions));
00527 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
00528 return FALSE;
00529 }
00530
00565 void smlManagerStop(SmlManager *manager)
00566 {
00567 smlTrace(TRACE_ENTRY, "%s(%p)", __func__, manager);
00568 smlAssert(manager);
00569 smlAssert(manager->thread);
00570
00571
00572
00573
00574
00575
00576 smlThreadStop(manager->thread);
00577 smlThreadFree(manager->thread);
00578 manager->thread = NULL;
00579
00580 g_source_unref(manager->source);
00581 manager->source = NULL;
00582
00583 g_main_context_unref(manager->context);
00584 manager->context = NULL;
00585
00586 smlSafeFree((gpointer *)&(manager->functions));
00587 manager->functions = NULL;
00588
00589
00590
00591 GList *sessionItem = manager->sessions;
00592 while (sessionItem) {
00593 managerSession *sess = sessionItem->data;
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604 SmlError *error = NULL;
00605 if (manager->transport->connected &&
00606 (!sess->link || sess->link->link_data) &&
00607 !smlTransportDisconnect(manager->transport, sess->link, &error)) {
00608 g_warning("Errors from the transport layer " \
00609 "cannot be handled while freeing the manager. %s",
00610 smlErrorPrint(&error));
00611 smlErrorDeref(&error);
00612 }
00613
00614 sessionItem = g_list_next(sessionItem);
00615 }
00616
00617 smlTrace(TRACE_EXIT, "%s", __func__);
00618 }
00619
00620
00621 void smlManagerRun(SmlManager *manager)
00622 {
00623 smlTrace(TRACE_ENTRY, "%s(%p)", __func__, manager);
00624 smlAssert(manager);
00625
00626 g_mutex_lock(manager->running_mutex);
00627 g_cond_wait(manager->running, manager->running_mutex);
00628 g_mutex_unlock(manager->running_mutex);
00629
00630 smlTrace(TRACE_EXIT, "%s", __func__);
00631 }
00632
00633 void smlManagerQuit(SmlManager *manager)
00634 {
00635 smlTrace(TRACE_ENTRY, "%s(%p)", __func__, manager);
00636 smlAssert(manager);
00637
00638 g_mutex_lock(manager->running_mutex);
00639 g_cond_signal(manager->running);
00640 g_mutex_unlock(manager->running_mutex);
00641
00642 smlTrace(TRACE_EXIT, "%s", __func__);
00643 }
00644
00645 SmlSession *smlManagerSessionFind(SmlManager *manager, const char *sessionID)
00646 {
00647 smlTrace(TRACE_ENTRY, "%s(%p, %s)", __func__, manager, VA_STRING(sessionID));
00648 GList *s = NULL;
00649 for (s = manager->sessions; s; s = s->next) {
00650 managerSession *session = s->data;
00651 if (!strcmp(smlSessionGetSessionID(session->session), sessionID)) {
00652 smlTrace(TRACE_EXIT, "%s: FOUND %p", __func__, session);
00653 return session->session;
00654 }
00655 }
00656
00657 smlTrace(TRACE_EXIT, "%s: NOT FOUND", __func__);
00658 return NULL;
00659 }
00660
00661 void smlManagerDispatch(SmlManager *manager)
00662 {
00663 smlTrace(TRACE_ENTRY, "%s(%p)", __func__, manager);
00664 smlAssert(manager);
00665 SmlManagerEvent *event = NULL;
00666 while ((event = smlQueueTryPop(manager->userEventQueue))) {
00667 smlTrace(TRACE_INTERNAL, "%s: type ::= %d", __func__, event->type);
00668
00669 if (event->session != NULL &&
00670 event->type == SML_MANAGER_SESSION_FINAL)
00671 {
00672 managerSession *sess = _smlManagerGetManagerSession(manager, event->session);
00673 if (sess && sess->finalLock)
00674 {
00675 smlTrace(TRACE_INTERNAL, "%s - locked final (%i)",
00676 __func__, sess->finalLock);
00677 smlQueuePushHead(manager->userEventQueue, event);
00678
00679
00680
00681
00682
00683
00684 break;
00685 }
00686 }
00687
00688 smlAssert(manager->eventCallback);
00689 manager->eventCallback(manager, event->type, event->session, event->error, manager->eventCallbackUserdata);
00690 _smlManagerEventFree(event);
00691 }
00692 smlTrace(TRACE_EXIT, "%s", __func__);
00693 }
00694
00695 SmlBool smlManagerCheck(SmlManager *manager)
00696 {
00697 return smlQueueCheck(manager->userEventQueue);
00698 }
00699
00700 static void _event_callback(SmlSession *session, SmlSessionEventType type, SmlCommand *command, SmlCommand *parent, SmlStatus *reply, SmlError *error, void *userdata)
00701 {
00702 smlTrace(TRACE_ENTRY, "%s(%p, %i, %p, %p, %p, %p, %p)", __func__, session, type, command, parent, reply, error, userdata);
00703 SmlManager *manager = userdata;
00704 SmlError *locerror = NULL;
00705
00706 switch (type) {
00707 case SML_SESSION_EVENT_ESTABLISHED:
00708
00709 _smlManagerSendEvent(manager, SML_MANAGER_SESSION_ESTABLISHED, session, NULL, NULL, NULL);
00710 break;
00711 case SML_SESSION_EVENT_HEADER_REPLY:
00712 break;
00713 case SML_SESSION_EVENT_RESPONSE_URI:
00714 if (!smlTransportSetResponseURI(
00715 manager->transport,
00716 smlLocationGetURI(smlSessionGetTarget(session)),
00717 &locerror))
00718 {
00719 _smlManagerSendEvent(manager, SML_MANAGER_SESSION_ERROR, session, NULL, NULL, locerror);
00720 goto error;
00721 }
00722 break;
00723 case SML_SESSION_EVENT_COMMAND_START:
00724 case SML_SESSION_EVENT_COMMAND_END:
00725 if (!smlManagerDispatchCommand(manager, session, command, &locerror)) {
00726 _smlManagerSendEvent(manager, SML_MANAGER_SESSION_WARNING, session, NULL, NULL, locerror);
00727 goto error;
00728 }
00729 break;
00730 case SML_SESSION_EVENT_CHILD_COMMAND:
00731 if (!smlManagerDispatchChildCommand(manager, session, parent, command, &locerror)) {
00732 _smlManagerSendEvent(manager, SML_MANAGER_SESSION_WARNING, session, NULL, NULL, locerror);
00733 goto error;
00734 }
00735 break;
00736 case SML_SESSION_EVENT_FINAL:
00737
00738 _smlManagerSendEvent(manager, SML_MANAGER_SESSION_FINAL, session, NULL, NULL, NULL);
00739 break;
00740 case SML_SESSION_EVENT_END:
00741
00742 _smlManagerSendEvent(manager, SML_MANAGER_SESSION_END, session, NULL, NULL, NULL);
00743 break;
00744 case SML_SESSION_EVENT_FLUSH:
00745
00746 _smlManagerSendEvent(manager, SML_MANAGER_SESSION_FLUSH, session, NULL, NULL, NULL);
00747 break;
00748 case SML_SESSION_EVENT_ERROR:
00749
00750 smlErrorDuplicate(&locerror, &error);
00751 _smlManagerSendEvent(manager, SML_MANAGER_SESSION_ERROR, session, NULL, NULL, locerror);
00752 goto error;
00753 break;
00754 }
00755
00756 smlTrace(TRACE_EXIT, "%s", __func__);
00757 return;
00758
00759 error:
00760 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(&locerror));
00761 smlErrorDeref(&locerror);
00762 }
00763
00764 static void _data_send_callback(SmlSession *session, SmlTransportData *data, void *userdata)
00765 {
00766 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, data, userdata);
00767 managerSession *sess = userdata;
00768
00769
00770 SmlError *error = NULL;
00771 if (!smlTransportSend(sess->transport, sess->link, data, &error))
00772 {
00773 smlTrace(TRACE_ERROR, "%s - %s", __func__, smlErrorPrint(&error));
00774 smlErrorDeref(&error);
00775 }
00776
00777 smlTrace(TRACE_EXIT, "%s", __func__);
00778 }
00779
00780 SmlBool smlManagerSessionAdd(SmlManager *manager, SmlSession *session, SmlLink *link_, SmlError **error)
00781 {
00782 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, manager, session, link_, error);
00783 CHECK_ERROR_REF
00784
00785 smlSessionRef(session);
00786
00787 if (smlSessionGetSessionID(session)) {
00788
00789 smlTrace(TRACE_INTERNAL, "Checking if session ID %s already exists", smlSessionGetSessionID(session));
00790
00791 if (smlManagerSessionFind(manager, smlSessionGetSessionID(session))) {
00792 smlErrorSet(error, SML_ERROR_GENERIC, "Session ID already exists");
00793 goto error;
00794 }
00795 } else {
00796 char *lastid = smlManagerGetNewSessionID(manager);
00797 smlSessionSetSessionID(session, lastid);
00798 smlSafeCFree(&lastid);
00799 }
00800
00801 managerSession *sess = smlTryMalloc0(sizeof(managerSession), error);
00802 if (!sess)
00803 goto error;
00804
00805 sess->session = session;
00806 sess->finalLock = 0;
00807
00808 if (link_) {
00809 sess->link = link_;
00810 smlLinkRef(link_);
00811 }
00812
00813 sess->transport = manager->transport;
00814
00815 manager->sessions = g_list_append(manager->sessions, sess);
00816
00817
00818 if (0 < manager->localMaxMsgSize &&
00819 (
00820 manager->localMaxMsgSize < smlSessionGetLocalMaxMsgSize(session) ||
00821 smlSessionGetLocalMaxMsgSize(session) <= 0
00822 ))
00823 smlSessionSetLocalMaxMsgSize(session, manager->localMaxMsgSize);
00824 if (0 < manager->localMaxObjSize &&
00825 (
00826 manager->localMaxObjSize < smlSessionGetLocalMaxObjSize(session) ||
00827 smlSessionGetLocalMaxObjSize(session) <= 0
00828 ))
00829 smlSessionSetLocalMaxObjSize(session, manager->localMaxObjSize);
00830 if (smlSessionGetLocalMaxObjSize(session) &&
00831 smlSessionGetLocalMaxMsgSize(session))
00832 smlSessionUseLargeObjects(session, TRUE);
00833 else
00834 smlSessionUseLargeObjects(session, FALSE);
00835
00836 smlSessionSetEventCallback(session, _event_callback, manager);
00837 smlSessionSetDataCallback(session, _data_send_callback, sess);
00838
00839 _smlManagerSendEvent(manager, SML_MANAGER_SESSION_NEW, session, NULL, NULL, NULL);
00840
00841 smlTrace(TRACE_EXIT, "%s", __func__);
00842 return TRUE;
00843
00844 error:
00845 smlSessionUnref(session);
00846 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
00847 return FALSE;
00848 }
00849
00850 managerSession *_smlManagerGetManagerSession(SmlManager *manager, SmlSession *session)
00851 {
00852 smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, manager, session);
00853
00854 GList *s;
00855 for (s = manager->sessions; s; s = s->next) {
00856 managerSession *sess = s->data;
00857 if (sess->session == session) {
00858 smlTrace(TRACE_EXIT, "%s - %p", __func__, sess);
00859 return sess;
00860 }
00861 }
00862
00863 smlTrace(TRACE_EXIT, "%s: Not Found", __func__);
00864 return NULL;
00865 }
00866
00867 void smlManagerSessionRemove(SmlManager *manager, SmlSession *session)
00868 {
00869 smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, manager, session);
00870
00871 managerSession *sess = _smlManagerGetManagerSession(manager, session);
00872 if (sess) {
00873 manager->sessions = g_list_remove(manager->sessions, sess);
00874 _manager_session_free(sess);
00875 smlTrace(TRACE_EXIT, "%s", __func__);
00876 } else {
00877 smlTrace(TRACE_EXIT, "%s: Not Found", __func__);
00878 }
00879 }
00880
00881 void smlManagerSessionFinalLockRef(SmlManager *manager, SmlSession *session)
00882 {
00883 smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, manager, session);
00884
00885 managerSession *sess = _smlManagerGetManagerSession(manager, session);
00886 if (sess) {
00887 sess->finalLock++;
00888 smlTrace(TRACE_EXIT, "%s", __func__);
00889 } else {
00890 smlTrace(TRACE_EXIT, "%s: Not Found", __func__);
00891 }
00892 }
00893
00894 void smlManagerSessionFinalLockUnref(SmlManager *manager, SmlSession *session)
00895 {
00896 smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, manager, session);
00897
00898 managerSession *sess = _smlManagerGetManagerSession(manager, session);
00899 if (sess) {
00900 sess->finalLock--;
00901 smlTrace(TRACE_EXIT, "%s - %i", __func__, sess->finalLock);
00902 } else {
00903 smlTrace(TRACE_EXIT, "%s: Not Found", __func__);
00904 }
00905 }
00906
00926 SmlBool smlManagerObjectRegister(SmlManager *manager, SmlCommandType type, SmlSession *session, SmlLocation *location, SmlLocation *source, const char *contentType, SmlCommandCb callback, SmlCommandCb childCallback, void *userdata, SmlError **error)
00927 {
00928 smlTrace(TRACE_ENTRY, "%s(%p, %i, %p, %p, %p, %s, %p, %p, %p, %p)", __func__, manager, type, session, location, source, VA_STRING(contentType), callback, childCallback, userdata, error);
00929 smlAssert(manager);
00930 smlAssert(callback);
00931 CHECK_ERROR_REF
00932
00933
00934
00935
00936 SmlObject *object = smlManagerObjectFindInternal(
00937 manager, session, type,
00938 location, source, contentType);
00939 if (object != NULL && session != NULL)
00940 {
00941
00942 SmlObject *hObject = smlManagerObjectFindInternal(
00943 manager, NULL, type,
00944 location, source, contentType);
00945 if (hObject != NULL && hObject == object)
00946 {
00947
00948
00949 object = NULL;
00950 }
00951 }
00952 if (object)
00953 {
00954
00955 smlTrace(TRACE_INTERNAL, "%s: prepare a reusable object", __func__);
00956
00957 if (object->location)
00958 smlLocationUnref(object->location);
00959 if (object->source)
00960 smlLocationUnref(object->source);
00961 if (object->contentType)
00962 smlSafeCFree(&(object->contentType));
00963 }
00964 else
00965 {
00966
00967 smlTrace(TRACE_INTERNAL, "%s: create and register a new object", __func__);
00968
00969 object = smlTryMalloc0(sizeof(SmlObject), error);
00970 if (!object)
00971 goto error;
00972
00973 if (session) {
00974 managerSession *sess = _manager_session_find(manager, session);
00975 if (!sess) {
00976 smlErrorSet(error, SML_ERROR_GENERIC, "Session not found");
00977 goto error_free_object;
00978 }
00979
00980 sess->objects = g_list_append(sess->objects, object);
00981 } else {
00982 manager->objects = g_list_append(manager->objects, object);
00983 }
00984 }
00985
00986 smlTrace(TRACE_INTERNAL, "%s: configure registered object", __func__);
00987
00988 object->type = type;
00989
00990 if (location) {
00991 object->location = location;
00992 smlLocationRef(location);
00993 }
00994
00995 if (source) {
00996 object->source = source;
00997 smlLocationRef(source);
00998 }
00999
01000 if (contentType) {
01001 object->contentType = g_strdup(contentType);
01002 }
01003
01004 object->commandCallback = callback;
01005 object->childCallback = childCallback;
01006 object->commandCallbackUserdata = userdata;
01007
01008 smlTrace(TRACE_EXIT, "%s", __func__);
01009 return TRUE;
01010
01011 error_free_object:
01012 smlManagerObjectFree(object);
01013 error:
01014 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
01015 return FALSE;
01016 }
01017
01018 void smlManagerObjectDeregister(SmlManager *manager, SmlCommandType type, SmlLocation *location, SmlLocation *source)
01019 {
01020 smlTrace(TRACE_ENTRY, "%s(%p, %i, %p, %p)", __func__, manager, type, location, source);
01021 smlAssert(manager);
01022
01023 GList *o2 = g_list_copy(manager->objects);
01024 GList *o = NULL;
01025 for (o = o2; o; o = o->next) {
01026 SmlObject *object = o->data;
01027
01028
01029 if (object->type != type)
01030 continue;
01031
01032 if (!smlLocationCompare(NULL, object->location, NULL, location))
01033 continue;
01034
01035 if (!smlLocationCompare(NULL, object->source, NULL, source))
01036 continue;
01037
01038 smlManagerObjectFree(object);
01039 manager->objects = g_list_remove(manager->objects, object);
01040 }
01041 g_list_free(o2);
01042
01043 smlTrace(TRACE_EXIT, "%s", __func__);
01044 }
01045
01046 void smlManagerObjectFree(SmlObject *object)
01047 {
01048 smlTrace(TRACE_ENTRY, "%s(%p)", __func__, object);
01049 smlAssert(object);
01050
01051 if (object->location)
01052 smlLocationUnref(object->location);
01053
01054 if (object->source)
01055 smlLocationUnref(object->source);
01056
01057 if (object->contentType)
01058 smlSafeCFree(&(object->contentType));
01059
01060 smlSafeFree((gpointer *)&object);
01061
01062 smlTrace(TRACE_EXIT, "%s", __func__);
01063 }
01064
01065 SmlObject *smlManagerObjectFind(SmlManager *manager, SmlSession *session, SmlCommand *cmd)
01066 {
01067 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, manager, session, cmd);
01068 smlAssert(manager);
01069 smlAssert(cmd);
01070
01071 SmlObject *object = smlManagerObjectFindInternal(
01072 manager,
01073 session,
01074 cmd->type,
01075 cmd->target, cmd->source,
01076 cmd->private.alert.contentType);
01077 smlTrace(TRACE_EXIT, "%s(%p)", __func__, object);
01078 return object;
01079 }
01080
01081 SmlObject *smlManagerObjectFindInternal(
01082 SmlManager *manager,
01083 SmlSession *session,
01084 SmlCommandType type,
01085 SmlLocation *target,
01086 SmlLocation *source,
01087 const char* contentType)
01088 {
01089 smlTrace(TRACE_ENTRY, "%s(%p, %p, %d, %p, %p)", __func__, manager, session, type, target, source);
01090 smlAssert(manager);
01091 SmlObject *object = NULL;
01092 GList *o = NULL;
01093
01094
01095 if (session) {
01096 managerSession *sess = _manager_session_find(manager, session);
01097 if (sess) {
01098 for (o = sess->objects; o; o = o->next) {
01099 object = o->data;
01100
01101 if (object->type != SML_COMMAND_TYPE_UNKNOWN && type != object->type)
01102 continue;
01103
01104 if (!smlLocationCompare(NULL, object->location, NULL, target))
01105 continue;
01106
01107 if (!smlLocationCompare(NULL, object->source, NULL, source))
01108 continue;
01109
01110 smlTrace(TRACE_EXIT, "%s: FOUND (session): %p", __func__, object);
01111 return object;
01112 }
01113 }
01114 }
01115
01116 for (o = manager->objects; o; o = o->next) {
01117 object = o->data;
01118
01119 if (object->type != SML_COMMAND_TYPE_UNKNOWN && type != object->type)
01120 continue;
01121
01122 if (type == SML_COMMAND_TYPE_ALERT && contentType) {
01123 if (object->contentType) {
01124
01125 if (!strcmp(contentType, object->contentType)) {
01126 smlTrace(TRACE_EXIT, "%s: FOUND SAN TARGET: %p", __func__, object);
01127 return object;
01128 }
01129 }
01130
01131 continue;
01132 }
01133
01134 if (!smlLocationCompare(NULL, object->location, NULL, target))
01135 continue;
01136
01137 if (!smlLocationCompare(NULL, object->source, NULL, source))
01138 continue;
01139
01140
01141 if (object->contentType)
01142 continue;
01143
01144 smlTrace(TRACE_EXIT, "%s: FOUND: %p", __func__, object);
01145 return object;
01146 }
01147
01148 smlTrace(TRACE_EXIT, "%s: NOT FOUND", __func__);
01149 return NULL;
01150 }
01151
01152 SmlTransport *smlManagerGetTransport(SmlManager *manager)
01153 {
01154 smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, manager);
01155 smlAssert(manager);
01156
01157 SmlTransport *tsp = manager->transport;
01158
01159 smlTrace(TRACE_EXIT, "%s: %p", __func__, tsp);
01160 return tsp;
01161 }
01162
01163 SmlBool smlManagerDispatchHeader(SmlManager *manager, SmlSession *session, SmlHeader *header, SmlCred *cred, SmlError **error)
01164 {
01165 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p, %p)", __func__, manager, session, header, cred, error);
01166 smlAssert(manager);
01167 smlAssert(session);
01168 smlAssert(header);
01169 CHECK_ERROR_REF
01170
01171 if (manager->headerCallback &&
01172 session->sessionType == SML_SESSION_TYPE_SERVER) {
01173
01174 manager->headerCallback(session, header, cred, manager->headerCallbackUserdata);
01175 } else {
01176 smlTrace(TRACE_INTERNAL, "%s: Header not handled!", __func__);
01177 if (session->sessionType == SML_SESSION_TYPE_SERVER &&
01178 !session->established) {
01179
01180
01181
01182
01183
01184 g_warning("%s: This is an OMA DS server. " \
01185 "The header callback is missing. " \
01186 "All requests will be accepted without authentication.",
01187 __func__);
01188 session->established = TRUE;
01189 smlSessionDispatchEvent(
01190 session, SML_SESSION_EVENT_ESTABLISHED,
01191 NULL, NULL, NULL, NULL);
01192 }
01193 SmlStatus *status = smlStatusNew(
01194 SML_NO_ERROR, 0,
01195 header->messageID,
01196 header->source, header->target,
01197 SML_COMMAND_TYPE_HEADER, error);
01198 if (!status)
01199 goto error;
01200
01201 if (!smlSessionSendReply(session, status, error)) {
01202 smlStatusUnref(status);
01203 goto error;
01204 }
01205
01206 smlStatusUnref(status);
01207 }
01208
01209 smlTrace(TRACE_EXIT, "%s", __func__);
01210 return TRUE;
01211
01212 error:
01213 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
01214 return FALSE;
01215 }
01216
01217 SmlBool smlManagerDispatchChildCommand(SmlManager *manager, SmlSession *session, SmlCommand *parent, SmlCommand *cmd, SmlError **error)
01218 {
01219 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p, %p)", __func__, manager, session, parent, cmd, error);
01220 smlAssert(manager);
01221 smlAssert(session);
01222 smlAssert(parent);
01223 CHECK_ERROR_REF
01224
01225
01226 SmlObject *object = smlManagerObjectFind(manager, session, parent);
01227 if (object) {
01228
01229 if (!object->childCallback) {
01230 smlErrorSet(error, SML_ERROR_GENERIC, "No handler for the child was installed");
01231 goto error;
01232 }
01233
01234 object->childCallback(session, cmd, object->commandCallbackUserdata);
01235 } else {
01236 SmlStatus *reply = smlCommandNewReply(cmd, SML_ERROR_NOT_FOUND, error);
01237 if (!reply)
01238 goto error;
01239
01240 if (!smlSessionSendReply(session, reply, error)) {
01241 smlStatusUnref(reply);
01242 goto error;
01243 }
01244
01245 smlStatusUnref(reply);
01246
01247 smlErrorSet(error, SML_ERROR_GENERIC, "Unable to find child command handler");
01248
01249 goto error;
01250 }
01251
01252 smlTrace(TRACE_EXIT, "%s", __func__);
01253 return TRUE;
01254
01255 error:
01256 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
01257 return FALSE;
01258 }
01259
01260 SmlBool smlManagerDispatchCommand(SmlManager *manager, SmlSession *session, SmlCommand *cmd, SmlError **error)
01261 {
01262 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, manager, session, cmd, error);
01263 smlAssert(manager);
01264 smlAssert(session);
01265 smlAssert(cmd);
01266 CHECK_ERROR_REF
01267
01268
01269 SmlObject *object = smlManagerObjectFind(manager, session, cmd);
01270 if (object) {
01271
01272 if (!object->commandCallback) {
01273 smlErrorSet(error, SML_ERROR_GENERIC, "No handler for the child was installed");
01274 goto error;
01275 }
01276
01277 object->commandCallback(session, cmd, object->commandCallbackUserdata);
01278 } else {
01279 const char *type = smlCommandTypeToString(cmd->type, error);
01280
01281 smlErrorDeref(error);
01282 const char *srcuri = (cmd->source && cmd->source->locURI) ? cmd->source->locURI : "NULL";
01283 const char *dsturi = (cmd->target && cmd->target->locURI) ? cmd->target->locURI : "NULL";
01284 smlErrorSet(error, SML_ERROR_NOT_FOUND, "Unable to find command handler (%s: %s -> %s)", (type) ? type : "UNKNOWN", srcuri, dsturi);
01285
01286 SmlError *locerror = NULL;
01287 SmlStatus *reply = smlCommandNewReply(cmd, SML_ERROR_NOT_FOUND, &locerror);
01288 if (!reply) {
01289 smlErrorSet(error, SML_ERROR_NOT_FOUND, "%s %s",
01290 smlErrorPrint(error),
01291 smlErrorPrint(&locerror));
01292 goto error;
01293 }
01294
01295 if (!smlSessionSendReply(session, reply, &locerror)) {
01296 smlStatusUnref(reply);
01297 smlErrorSet(error, SML_ERROR_NOT_FOUND, "%s %s",
01298 smlErrorPrint(error),
01299 smlErrorPrint(&locerror));
01300 goto error;
01301 }
01302
01303 smlStatusUnref(reply);
01304
01305 goto error;
01306 }
01307
01308 smlTrace(TRACE_EXIT, "%s", __func__);
01309 return TRUE;
01310
01311 error:
01312 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
01313 return FALSE;
01314 }
01315
01316 void smlManagerRegisterHeaderHandler(SmlManager *manager, SmlHeaderCb callback, SmlStatusReplyCb statuscb, void *userdata)
01317 {
01318 smlAssert(manager);
01319
01320 manager->headerCallback = callback;
01321 manager->headerStatusCallback = statuscb;
01322 manager->headerCallbackUserdata = userdata;
01323 }
01324
01325 void smlManagerSetLocalMaxMsgSize(SmlManager *manager, unsigned int size)
01326 {
01327 smlAssert(manager);
01328 manager->localMaxMsgSize = size;
01329 }
01330
01331 void smlManagerSetLocalMaxObjSize(SmlManager *manager, unsigned int size)
01332 {
01333 smlAssert(manager);
01334 manager->localMaxObjSize = size;
01335 }
01336
01337 char *smlManagerGetNewSessionID(SmlManager *manager)
01338 {
01339 smlTrace(TRACE_ENTRY, "%s(%p)", __func__, manager);
01340 smlAssertMsg(manager, "The manager is required to avoid duplicated session IDs.");
01341
01342 char *sessionString = NULL;
01343 while (sessionString == NULL)
01344 {
01345
01346
01347 unsigned int sessionID = (unsigned int) g_random_int_range (0, 0xFFFF);
01348 sessionString = g_strdup_printf("%u", sessionID);
01349 smlTrace(TRACE_INTERNAL, "%s: new potential session ID is %lu.", __func__, sessionID);
01350 if (smlManagerSessionFind(manager, sessionString))
01351 smlSafeCFree(&sessionString);
01352 }
01353 smlTrace(TRACE_EXIT, "%s - %s", __func__, VA_STRING(sessionString));
01354 return sessionString;
01355 }
01356
01357 SmlLink *smlManagerSessionGetLink(
01358 SmlManager *manager,
01359 SmlSession *session,
01360 SmlError **error)
01361 {
01362 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, manager, session, error);
01363 CHECK_ERROR_REF
01364
01365 managerSession *_msession = _manager_session_find(manager, session);
01366 if (!_msession)
01367 {
01368 smlErrorSet(error, SML_ERROR_GENERIC,
01369 "The session %d is not registered at the manager.",
01370 smlSessionGetSessionID(session));
01371 goto error;
01372 }
01373
01374 if (_msession->link)
01375 smlLinkRef(_msession->link);
01376
01377 smlTrace(TRACE_EXIT, "%s - %p", __func__, _msession->link);
01378 return _msession->link;
01379 error:
01380 smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error));
01381 return NULL;
01382 }
01383