00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "../syncml.h"
00022 #include "../syncml_internals.h"
00023 #include "../sml_error_internals.h"
00024
00025 #include <libsyncml/data_sync_api/defines.h>
00026 #include <libsyncml/data_sync_api/standard.h>
00027 #include <libsyncml/data_sync_api/callbacks.h>
00028
00029
00030 #include <strings.h>
00031
00032 #include "data_sync.h"
00033 #include "data_sync_client.h"
00034 #include "data_sync_server.h"
00035 #include "data_sync_callbacks.h"
00036 #include "data_sync_callbacks.h"
00037 #include "data_sync_devinf.h"
00038 #include "data_sync_loop.h"
00039 #include "transport.h"
00040 #include "libsyncml/objects/sml_ds_server_internals.h"
00041
00042
00043
00044
00045
00046 SmlDataSyncObject *smlDataSyncNew(
00047 SmlSessionType dsType,
00048 SmlTransportType tspType,
00049 SmlError **error)
00050 {
00051 smlTrace(TRACE_ENTRY, "%s(%d, %d, %p)", __func__, dsType, tspType, error);
00052 CHECK_ERROR_REF
00053
00054 smlTrace(TRACE_INTERNAL, "%s: libsyncml version: %s", __func__, VERSION);
00055
00056 SmlDataSyncObject *dsObject = smlTryMalloc0(sizeof(SmlDataSyncObject), error);
00057 if (!dsObject)
00058 goto error;
00059 smlDataSyncObjectRef(dsObject);
00060
00061 dsObject->dsType = dsType;
00062 dsObject->tspType = tspType;
00063 dsObject->version = SML_VERSION_11;
00064 dsObject->internalState = SML_DATA_SYNC_STATE_NEW;
00065
00066 dsObject->useNumberOfChanges = TRUE;
00067 dsObject->useTimestampAnchor = TRUE;
00068 dsObject->maxObjSize = SML_DEFAULT_MAX_OBJ_SIZE;
00069 dsObject->maxMsgSize = SML_DEFAULT_MAX_MSG_SIZE;
00070
00071 dsObject->tsp = smlTransportNew(tspType, error);
00072 if (!dsObject->tsp)
00073 goto error;
00074 switch(tspType)
00075 {
00076 case SML_TRANSPORT_OBEX_CLIENT:
00077 dsObject->funcTspInit = smlDataSyncTransportObexClientInit;
00078 dsObject->funcTspConnect = smlDataSyncTransportObexClientConnect;
00079 break;
00080 case SML_TRANSPORT_OBEX_SERVER:
00081 dsObject->funcTspInit = NULL;
00082 dsObject->funcTspConnect = NULL;
00083 break;
00084 case SML_TRANSPORT_HTTP_SERVER:
00085 dsObject->funcTspInit = smlDataSyncTransportHttpServerInit;
00086 dsObject->funcTspConnect = NULL;
00087 break;
00088 case SML_TRANSPORT_HTTP_CLIENT:
00089 dsObject->funcTspInit = smlDataSyncTransportHttpClientInit;
00090 dsObject->funcTspConnect = smlDataSyncTransportHttpClientConnect;
00091 break;
00092 default:
00093 smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION,
00094 "Unknown transport type %d used in __func__.",
00095 tspType, __func__);
00096 goto error;
00097 break;
00098 }
00099 switch(dsType)
00100 {
00101 case SML_SESSION_TYPE_SERVER:
00102 dsObject->funcDsInit = smlDataSyncServerInit;
00103 dsObject->funcDsConnect = NULL;
00104 break;
00105 case SML_SESSION_TYPE_CLIENT:
00106 dsObject->funcDsInit = smlDataSyncClientInit;
00107 dsObject->funcDsConnect = NULL;
00108 break;
00109 default:
00110 smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION,
00111 "Unknown data sync type %d used in %s.",
00112 dsType, __func__);
00113 goto error;
00114 break;
00115 }
00116
00117 smlTrace(TRACE_EXIT, "%s - %p", __func__, dsObject);
00118 return dsObject;
00119 error:
00120 if (dsObject) {
00121 if (dsObject->tsp)
00122 smlTransportFree(dsObject->tsp);
00123 smlDataSyncObjectUnref(&dsObject);
00124 }
00125 smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error));
00126 return NULL;
00127 }
00128
00129 void smlDataSyncObjectRef(SmlDataSyncObject *dsObject)
00130 {
00131 g_atomic_int_inc(&(dsObject->refCount));
00132 }
00133
00134 SmlBool smlDataSyncSetOption(
00135 SmlDataSyncObject *dsObject,
00136 const char *name,
00137 const char *value,
00138 SmlError **error)
00139 {
00140 smlTrace(TRACE_ENTRY, "%s(%p, %s, %s, %p)", __func__, dsObject, VA_STRING(name), VA_STRING(value), error);
00141 CHECK_ERROR_REF
00142
00143 if (!strcmp(SML_DATA_SYNC_CONFIG_CONNECTION_TYPE, name)) {
00144 if (!strcmp(SML_DATA_SYNC_CONFIG_CONNECTION_SERIAL, value))
00145 dsObject->conType = SML_TRANSPORT_CONNECTION_TYPE_SERIAL;
00146 if (!strcmp(SML_DATA_SYNC_CONFIG_CONNECTION_BLUETOOTH, value))
00147 dsObject->conType = SML_TRANSPORT_CONNECTION_TYPE_BLUETOOTH;
00148 if (!strcmp(SML_DATA_SYNC_CONFIG_CONNECTION_IRDA, value))
00149 dsObject->conType = SML_TRANSPORT_CONNECTION_TYPE_IRDA;
00150 if (!strcmp(SML_DATA_SYNC_CONFIG_CONNECTION_NET, value))
00151 dsObject->conType = SML_TRANSPORT_CONNECTION_TYPE_NET;
00152 if (!strcmp(SML_DATA_SYNC_CONFIG_CONNECTION_USB, value))
00153 dsObject->conType = SML_TRANSPORT_CONNECTION_TYPE_USB;
00154 if (!smlTransportSetConnectionType(dsObject->tsp, dsObject->conType, error))
00155 goto error;
00156 } else if (!strcmp(SML_DATA_SYNC_CONFIG_VERSION, name)) {
00157 dsObject->version = SML_VERSION_UNKNOWN;
00158 if (!strcmp("1.0", value))
00159 dsObject->version = SML_VERSION_10;
00160 if (!strcmp("1.1", value))
00161 dsObject->version = SML_VERSION_11;
00162 if (!strcmp("1.2", value))
00163 dsObject->version = SML_VERSION_12;
00164 if (dsObject->version == SML_VERSION_UNKNOWN) {
00165 smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION,
00166 "Unknown SyncML version %s.", value);
00167 goto error;
00168 }
00169 } else if (!strcmp(SML_DATA_SYNC_CONFIG_AUTH_TYPE, name)) {
00170 if (!strcmp(value, SML_DATA_SYNC_CONFIG_AUTH_BASIC)) {
00171 dsObject->authType = SML_AUTH_TYPE_BASIC;
00172 } else if (!strcmp(value, SML_DATA_SYNC_CONFIG_AUTH_MD5)) {
00173 dsObject->authType = SML_AUTH_TYPE_MD5;
00174 } else if (!strcmp(value, SML_DATA_SYNC_CONFIG_AUTH_NONE)) {
00175 dsObject->authType = SML_AUTH_TYPE_UNKNOWN;
00176 } else {
00177
00178 smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION,
00179 "Unknown authentication type %s.", value);
00180 goto error;
00181 }
00182 } else if (!strcmp(SML_TRANSPORT_CONFIG_URL, name)) {
00183 dsObject->url = g_strdup(value);
00184
00185
00186
00187
00188 if (!dsObject->target)
00189 dsObject->target = g_strdup(value);
00190 } else if (!strcmp(SML_DATA_SYNC_CONFIG_TARGET, name)) {
00191 if (dsObject->target)
00192 smlSafeCFree(&(dsObject->target));
00193 dsObject->target = g_strdup(value);
00194 } else if (!strcmp(SML_DATA_SYNC_CONFIG_IDENTIFIER, name)) {
00195 if (dsObject->identifier)
00196 smlSafeCFree(&(dsObject->identifier));
00197 if (value && strlen(value)) {
00198 dsObject->identifier = g_strdup(value);
00199 } else {
00200 smlTrace(TRACE_INTERNAL,
00201 "%s: set identifier to NULL", __func__);
00202 }
00203 } else if (!strcmp(SML_DATA_SYNC_CONFIG_AUTH_USERNAME, name)) {
00204 dsObject->username = g_strdup(value);
00205 } else if (!strcmp(SML_DATA_SYNC_CONFIG_AUTH_PASSWORD, name)) {
00206 dsObject->password = g_strdup(value);
00207 } else if (!strcmp(SML_DATA_SYNC_CONFIG_USE_WBXML, name)) {
00208 dsObject->useWbxml = atoi(value);
00209 } else if (!strcmp(SML_DATA_SYNC_CONFIG_USE_STRING_TABLE, name)) {
00210 dsObject->useStringTable = atoi(value);
00211 } else if (!strcmp(SML_DATA_SYNC_CONFIG_USE_TIMESTAMP_ANCHOR, name)) {
00212 dsObject->useTimestampAnchor = atoi(value);
00213 } else if (!strcmp(SML_DATA_SYNC_CONFIG_USE_NUMBER_OF_CHANGES, name)) {
00214 dsObject->useNumberOfChanges = atoi(value);
00215 } else if (!strcmp(SML_DATA_SYNC_CONFIG_USE_LOCALTIME, name)) {
00216 dsObject->onlyLocaltime = atoi(value);
00217 } else if (!strcmp(SML_DATA_SYNC_CONFIG_ONLY_REPLACE, name)) {
00218 dsObject->onlyReplace = atoi(value);
00219 } else if (!strcmp(SML_DATA_SYNC_CONFIG_MAX_OBJ_SIZE, name)) {
00220 dsObject->maxObjSize = atoi(value);
00221 } else if (!strcmp(SML_DATA_SYNC_CONFIG_MAX_MSG_SIZE, name)) {
00222 dsObject->maxMsgSize = atoi(value);
00223 } else if (!strcmp(SML_DATA_SYNC_CONFIG_FAKE_DEVICE, name)) {
00224 dsObject->fakeDevice = g_strdup(value);
00225 } else if (!strcmp(SML_DATA_SYNC_CONFIG_FAKE_MANUFACTURER, name)) {
00226 dsObject->fakeManufacturer = g_strdup(value);
00227 } else if (!strcmp(SML_DATA_SYNC_CONFIG_FAKE_MODEL, name)) {
00228 dsObject->fakeModel = g_strdup(value);
00229 } else if (!strcmp(SML_DATA_SYNC_CONFIG_FAKE_SOFTWARE_VERSION, name)) {
00230 dsObject->fakeSoftwareVersion = g_strdup(value);
00231 } else {
00232 if (!smlTransportSetConfigOption(dsObject->tsp, name, value, error))
00233 goto error;
00234 }
00235
00236
00237 if ((dsObject->username || dsObject->password) &&
00238 dsObject->authType == SML_AUTH_TYPE_UNKNOWN)
00239 {
00240 smlTrace(TRACE_INTERNAL,
00241 "%s: authType is set to default (syncml:auth-basic)", __func__);
00242 dsObject->authType = SML_AUTH_TYPE_BASIC;
00243 }
00244
00245 smlTrace(TRACE_EXIT, "%s - TRUE", __func__);
00246 return TRUE;
00247 error:
00248 smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error));
00249 return FALSE;
00250 }
00251
00252 SmlBool smlDataSyncAddDatastore(SmlDataSyncObject *dsObject,
00253 const char *contentType,
00254 const char *target,
00255 const char *source,
00256 SmlError **error)
00257 {
00258 smlTrace(TRACE_ENTRY, "%s(%p, %s, %s, %s, %p)", __func__, dsObject, VA_STRING(contentType), VA_STRING(target), VA_STRING(source), error);
00259 CHECK_ERROR_REF
00260
00261 char *lcCT = NULL;
00262 char *lcSource = NULL;
00263
00264 SmlDataSyncDatastore *datastore = smlTryMalloc0(sizeof(SmlDataSyncDatastore), error);
00265 if (!datastore)
00266 goto error;
00267
00268 datastore->dsObject = dsObject;
00269 datastore->syncChanges = NULL;
00270 datastore->syncContexts = NULL;
00271 datastore->sourceUri = g_strdup(source);
00272 datastore->targetUri = g_strdup(target);
00273 datastore->contentType = g_strdup(contentType);
00274
00275 dsObject->datastores = g_list_append(dsObject->datastores, datastore);
00276
00277
00278
00279 if (dsObject->tspType == SML_TRANSPORT_OBEX_CLIENT)
00280 {
00281 lcCT = g_ascii_strdown(contentType, strlen(contentType));
00282 lcSource = g_utf8_strdown(source, strlen(source));
00283 if (strstr(lcCT, "vcard") &&
00284 !smlTransportSetConfigOption(
00285 dsObject->tsp,
00286 SML_TRANSPORT_CONFIG_DATASTORE,
00287 SML_TRANSPORT_CONFIG_DATASTORE_CONTACT,
00288 error))
00289 {
00290 goto error;
00291 }
00292 if (strstr(lcCT, "calendar") &&
00293 ( strstr(lcSource, "cal") ||
00294 strstr(lcSource, "event")
00295 )&&
00296 !smlTransportSetConfigOption(
00297 dsObject->tsp,
00298 SML_TRANSPORT_CONFIG_DATASTORE,
00299 SML_TRANSPORT_CONFIG_DATASTORE_EVENT,
00300 error))
00301 {
00302 goto error;
00303 }
00304 if (strstr(lcCT, "calendar") &&
00305 strstr(lcSource, "todo") &&
00306 !smlTransportSetConfigOption(
00307 dsObject->tsp,
00308 SML_TRANSPORT_CONFIG_DATASTORE,
00309 SML_TRANSPORT_CONFIG_DATASTORE_TODO,
00310 error))
00311 {
00312 goto error;
00313 }
00314 if (strstr(lcCT, "text/plain") &&
00315 !smlTransportSetConfigOption(
00316 dsObject->tsp,
00317 SML_TRANSPORT_CONFIG_DATASTORE,
00318 SML_TRANSPORT_CONFIG_DATASTORE_NOTE,
00319 error))
00320 {
00321 goto error;
00322 }
00323 smlSafeCFree(&lcCT);
00324 smlSafeCFree(&lcSource);
00325 }
00326
00327 smlTrace(TRACE_EXIT, "%s - TRUE", __func__);
00328 return TRUE;
00329 error:
00330 if (datastore)
00331 smlSafeFree((gpointer *)&datastore);
00332 if (lcCT)
00333 smlSafeCFree(&lcCT);
00334 if (lcSource)
00335 smlSafeCFree(&lcSource);
00336 smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error));
00337 return FALSE;
00338 }
00339
00340 static SmlDataSyncDatastore *smlDataSyncGetDatastoreFromSource(
00341 SmlDataSyncObject *dsObject,
00342 const char *source,
00343 SmlError **error)
00344 {
00345 CHECK_ERROR_REF
00346 smlAssert(dsObject);
00347 smlAssert(source);
00348
00349 GList *o = dsObject->datastores;
00350 for (; o; o = o->next) {
00351 SmlDataSyncDatastore *datastore = o->data;
00352 if (!strcmp(datastore->sourceUri, source))
00353 return datastore;
00354 }
00355
00356 smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION,
00357 "Cannot find datastore for source name %s.", source);
00358 return NULL;
00359 }
00360
00361
00362
00363
00364
00365 void smlDataSyncRegisterEventCallback(
00366 SmlDataSyncObject *dsObject,
00367 SmlDataSyncEventCallback callback,
00368 void *userdata)
00369 {
00370 smlTrace(TRACE_ENTRY, "%s", __func__);
00371 smlAssert(dsObject);
00372 smlAssert(callback);
00373
00374 dsObject->eventCallback = callback;
00375 dsObject->eventUserdata = userdata;
00376
00377 smlTrace(TRACE_EXIT, "%s", __func__);
00378 }
00379
00380 void smlDataSyncRegisterGetAlertTypeCallback(
00381 SmlDataSyncObject *dsObject,
00382 SmlDataSyncGetAlertTypeCallback callback,
00383 void *userdata)
00384 {
00385 smlTrace(TRACE_ENTRY, "%s", __func__);
00386 smlAssert(dsObject);
00387 smlAssert(callback);
00388
00389 dsObject->getAlertTypeCallback = callback;
00390 dsObject->getAlertTypeUserdata = userdata;
00391
00392 smlTrace(TRACE_EXIT, "%s", __func__);
00393 }
00394
00395 void smlDataSyncRegisterChangeCallback(
00396 SmlDataSyncObject *dsObject,
00397 SmlDataSyncChangeCallback callback,
00398 void *userdata)
00399 {
00400 smlTrace(TRACE_ENTRY, "%s", __func__);
00401 smlAssert(dsObject);
00402 smlAssert(callback);
00403
00404 dsObject->changeCallback = callback;
00405 dsObject->changeUserdata = userdata;
00406
00407 GList *o = dsObject->datastores;
00408 for (;o;o = o->next) {
00409 SmlDataSyncDatastore *datastore = o->data;
00410 if (datastore->session) {
00411 smlDsSessionGetSync(datastore->session,
00412 smlDataSyncSyncCallback, datastore);
00413 smlDsSessionGetChanges(datastore->session,
00414 smlDataSyncChangeCallback, datastore);
00415 }
00416 }
00417
00418 smlTrace(TRACE_EXIT, "%s", __func__);
00419 }
00420
00421 void smlDataSyncRegisterChangeStatusCallback(
00422 SmlDataSyncObject *dsObject,
00423 SmlDataSyncChangeStatusCallback callback)
00424 {
00425 smlTrace(TRACE_ENTRY, "%s", __func__);
00426 smlAssert(dsObject);
00427 smlAssert(callback);
00428
00429 dsObject->changeStatusCallback = callback;
00430
00431
00432 smlTrace(TRACE_EXIT, "%s", __func__);
00433 }
00434
00435 void smlDataSyncRegisterMapCallback(
00436 SmlDataSyncObject *dsObject,
00437 SmlDataSyncMappingCallback callback,
00438 void *userdata)
00439 {
00440 smlTrace(TRACE_ENTRY, "%s", __func__);
00441 smlAssert(dsObject);
00442 smlAssert(callback);
00443
00444 dsObject->mappingCallback = callback;
00445 dsObject->mappingUserdata = userdata;
00446
00447 GList *o = dsObject->datastores;
00448 for (;o;o = o->next) {
00449 SmlDataSyncDatastore *datastore = o->data;
00450 if (datastore->session) {
00451 smlDsSessionGetMapping(datastore->session,
00452 smlDataSyncMappingCallback, datastore);
00453 }
00454 }
00455
00456 smlTrace(TRACE_EXIT, "%s", __func__);
00457 }
00458
00459
00460 void smlDataSyncRegisterGetAnchorCallback(
00461 SmlDataSyncObject *dsObject,
00462 SmlDataSyncGetAnchorCallback callback,
00463 void *userdata)
00464 {
00465 smlTrace(TRACE_ENTRY, "%s", __func__);
00466 smlAssert(dsObject);
00467 smlAssert(callback);
00468
00469 dsObject->getAnchorCallback = callback;
00470 dsObject->getAnchorUserdata = userdata;
00471
00472 smlTrace(TRACE_EXIT, "%s", __func__);
00473 }
00474
00475 void smlDataSyncRegisterSetAnchorCallback(
00476 SmlDataSyncObject *dsObject,
00477 SmlDataSyncSetAnchorCallback callback,
00478 void *userdata)
00479 {
00480 smlTrace(TRACE_ENTRY, "%s", __func__);
00481 smlAssert(dsObject);
00482 smlAssert(callback);
00483
00484 dsObject->setAnchorCallback = callback;
00485 dsObject->setAnchorUserdata = userdata;
00486
00487 smlTrace(TRACE_EXIT, "%s", __func__);
00488 }
00489
00490 void smlDataSyncRegisterWriteDevInfCallback(
00491 SmlDataSyncObject *dsObject,
00492 SmlDataSyncWriteDevInfCallback callback,
00493 void *userdata)
00494 {
00495 smlTrace(TRACE_ENTRY, "%s", __func__);
00496 smlAssert(dsObject);
00497 smlAssert(callback);
00498
00499 dsObject->writeDevInfCallback = callback;
00500 dsObject->writeDevInfUserdata = userdata;
00501
00502 smlTrace(TRACE_EXIT, "%s", __func__);
00503 }
00504
00505 void smlDataSyncRegisterReadDevInfCallback(
00506 SmlDataSyncObject *dsObject,
00507 SmlDataSyncReadDevInfCallback callback,
00508 void *userdata)
00509 {
00510 smlTrace(TRACE_ENTRY, "%s", __func__);
00511 smlAssert(dsObject);
00512 smlAssert(callback);
00513
00514 dsObject->readDevInfCallback = callback;
00515 dsObject->readDevInfUserdata = userdata;
00516
00517 smlTrace(TRACE_EXIT, "%s", __func__);
00518 }
00519
00520 void smlDataSyncRegisterHandleRemoteDevInfCallback(
00521 SmlDataSyncObject *dsObject,
00522 SmlDataSyncHandleRemoteDevInfCallback callback,
00523 void *userdata)
00524 {
00525 smlTrace(TRACE_ENTRY, "%s", __func__);
00526 smlAssert(dsObject);
00527 smlAssert(callback);
00528
00529 dsObject->handleRemoteDevInfCallback = callback;
00530 dsObject->handleRemoteDevInfUserdata = userdata;
00531
00532 smlTrace(TRACE_EXIT, "%s", __func__);
00533 }
00534
00535
00536
00537
00538
00539 SmlBool smlDataSyncInit(SmlDataSyncObject *dsObject, SmlError **error)
00540 {
00541 smlTrace(TRACE_ENTRY, "%s", __func__);
00542 CHECK_ERROR_REF
00543 smlAssert(dsObject);
00544
00545 if (!dsObject->identifier)
00546 dsObject->identifier = smlDataSyncDevInfGetIdentifier();
00547
00548 dsObject->managerMutex = g_mutex_new();
00549
00550 if (dsObject->funcTspInit &&
00551 !dsObject->funcTspInit(dsObject, error))
00552 goto error;
00553 if (!dsObject->funcDsInit(dsObject, error))
00554 goto error;
00555
00556 dsObject->internalState = SML_DATA_SYNC_STATE_INITIALIZED;
00557
00558 smlTrace(TRACE_EXIT, "%s - TRUE", __func__);
00559 return TRUE;
00560 error:
00561 smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error));
00562 return FALSE;
00563 }
00564
00565 SmlBool smlDataSyncRun(SmlDataSyncObject *dsObject, SmlError **error)
00566 {
00567 smlTrace(TRACE_ENTRY, "%s", __func__);
00568 CHECK_ERROR_REF
00569
00570
00571
00572
00573
00574 if (dsObject->funcTspConnect &&
00575 !dsObject->funcTspConnect(dsObject, error))
00576 goto error;
00577 if (dsObject->funcDsConnect &&
00578 !dsObject->funcDsConnect(dsObject, error))
00579 goto error;
00580
00581 if (!smlDataSyncLoopStart(dsObject, error))
00582 goto error;
00583
00584 smlTrace(TRACE_EXIT, "%s - TRUE", __func__);
00585 return TRUE;
00586 error:
00587 smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error));
00588 return FALSE;
00589 }
00590
00591
00592
00593 SmlBool smlDataSyncAddChange(
00594 SmlDataSyncObject *dsObject,
00595 const char *source,
00596 SmlChangeType type,
00597 const char *name,
00598 const char *data,
00599 unsigned int size,
00600 void *userdata,
00601 SmlError **error)
00602 {
00603 smlTrace(TRACE_ENTRY, "%s(%s)", __func__, VA_STRING(source));
00604
00605
00606 CHECK_ERROR_REF
00607 smlAssert(dsObject);
00608 smlAssert(source);
00609 smlAssert(type);
00610
00611
00612 SmlDataSyncChange *change = smlTryMalloc0(sizeof(SmlDataSyncChange), error);
00613 if (!change)
00614 goto error;
00615
00616
00617 change->type = type;
00618 change->name = g_strdup(name);
00619 change->userdata = userdata;
00620
00621
00622 change->datastore = smlDataSyncGetDatastoreFromSource(dsObject, source, error);
00623 if (!change->datastore)
00624 goto error;
00625 SmlDataSyncDatastore *datastore = change->datastore;
00626
00627
00628 if (data) {
00629 smlAssert(datastore->contentType);
00630 smlAssert(index(datastore->contentType, '/'));
00631 size_t appClassLength = ((size_t) index(datastore->contentType, '/')) -
00632 ((size_t) datastore->contentType);
00633 if ( ( strstr(datastore->contentType, SML_CONTENT_TYPE_APPLICATION) == datastore->contentType &&
00634 appClassLength == strlen(SML_CONTENT_TYPE_APPLICATION) ) ||
00635 ( strstr(datastore->contentType, SML_CONTENT_TYPE_AUDIO) == datastore->contentType &&
00636 appClassLength == strlen(SML_CONTENT_TYPE_AUDIO) ) ||
00637 ( strstr(datastore->contentType, SML_CONTENT_TYPE_IMAGE) == datastore->contentType &&
00638 appClassLength == strlen(SML_CONTENT_TYPE_IMAGE) ) ||
00639 ( strstr(datastore->contentType, SML_CONTENT_TYPE_MESSAGE) == datastore->contentType &&
00640 appClassLength == strlen(SML_CONTENT_TYPE_MESSAGE) ) ||
00641 ( strstr(datastore->contentType, SML_CONTENT_TYPE_VIDEO) == datastore->contentType &&
00642 appClassLength == strlen(SML_CONTENT_TYPE_AUDIO) ) )
00643 {
00644
00645 change->data = g_base64_encode((const unsigned char *) data, size);
00646 if (!change->data) {
00647 smlErrorSet(error, SML_ERROR_GENERIC,
00648 "The base 64 encoding of glib failed.");
00649 goto error;
00650 }
00651 change->size = strlen(change->data);
00652 } else {
00653 change->data = smlTryMalloc0(size+1, error);
00654 if (!change->data)
00655 goto error;
00656 memcpy(change->data, data, size);
00657 change->size = size;
00658 }
00659 } else {
00660 change->data = NULL;
00661 change->size = 0;
00662 }
00663
00664
00665 datastore->changes = g_list_append(datastore->changes, change);
00666
00667 smlTrace(TRACE_EXIT, "%s - TRUE", __func__);
00668 return TRUE;
00669 error:
00670 smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error));
00671 return FALSE;
00672 }
00673
00674 SmlBool smlDataSyncSendChanges(SmlDataSyncObject *dsObject, SmlError **error)
00675 {
00676
00677
00678
00679 smlTrace(TRACE_ENTRY, "%s", __func__);
00680 CHECK_ERROR_REF
00681
00682
00683
00684 if (dsObject->internalState >= SML_DATA_SYNC_STATE_SENT_CHANGES)
00685 {
00686 smlErrorSet(error, SML_ERROR_GENERIC,
00687 "The function %s is called to late or more than once.", __func__);
00688 goto error;
00689 } else {
00690 dsObject->internalState = SML_DATA_SYNC_STATE_SENT_CHANGES;
00691 }
00692 if (dsObject->dsType == SML_SESSION_TYPE_SERVER &&
00693 dsObject->actualPackage != SML_PACKAGE_4)
00694 {
00695 smlErrorSet(error, SML_ERROR_GENERIC,
00696 "This is not the server's sync package (%d).",
00697 dsObject->actualPackage);
00698 goto error;
00699 }
00700 if (dsObject->dsType == SML_SESSION_TYPE_CLIENT &&
00701 dsObject->actualPackage != SML_PACKAGE_3)
00702 {
00703 smlErrorSet(error, SML_ERROR_GENERIC,
00704 "This is not the client's sync package (%d).",
00705 dsObject->actualPackage);
00706 goto error;
00707 }
00708
00709
00710
00711 GList *o = dsObject->datastores;
00712 for (; o; o = o->next) {
00713 SmlDataSyncDatastore *datastore = o->data;
00714 smlAssert(datastore);
00715
00716 int num = g_list_length(datastore->changes);
00717 if (!smlDsSessionSendSync(
00718 datastore->session,
00719 num,
00720 smlDataSyncSyncStatusCallback,
00721 datastore,
00722 error))
00723 goto error;
00724
00725 int i = 0;
00726 for (i = 0; i < num; i++) {
00727 SmlDataSyncChange *change = g_list_nth_data(datastore->changes, i);
00728 if (!smlDsSessionQueueChange(
00729 datastore->session,
00730 change->type,
00731 change->name,
00732 change->data,
00733 change->size,
00734 datastore->contentType,
00735 smlDataSyncChangeStatusCallback,
00736 change,
00737 error))
00738 goto error;
00739 }
00740
00741 if (!smlDsSessionCloseSync(datastore->session, error))
00742 goto error;
00743 }
00744
00745
00746
00747 if (!smlSessionFlush(dsObject->session, TRUE, error))
00748 goto error;
00749
00750 smlTrace(TRACE_EXIT, "%s - TRUE", __func__);
00751 return TRUE;
00752 error:
00753 smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error));
00754 return FALSE;
00755 }
00756
00757 SmlBool smlDataSyncAddMapping(
00758 SmlDataSyncObject *dsObject,
00759 const char *source,
00760 const char *remoteID,
00761 const char *localID,
00762 SmlError **error)
00763 {
00764 smlTrace(TRACE_ENTRY, "%s(%s)", __func__, VA_STRING(source));
00765
00766
00767 CHECK_ERROR_REF
00768 smlAssert(dsObject);
00769 smlAssert(source);
00770 smlAssert(remoteID);
00771 smlAssert(localID);
00772
00773
00774
00775
00776
00777
00778 SmlDataSyncDatastore *datastore = NULL;
00779 datastore = smlDataSyncGetDatastoreFromSource(dsObject, source, error);
00780 if (!datastore)
00781 goto error;
00782 if (!smlDsSessionQueueMap(datastore->session, remoteID, localID, error))
00783 goto error;
00784
00785 smlTrace(TRACE_EXIT, "%s - TRUE", __func__);
00786 return TRUE;
00787 error:
00788 smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error));
00789 return FALSE;
00790 }
00791
00792 SmlBool smlDataSyncSendMap(SmlDataSyncObject *dsObject, SmlError **error)
00793 {
00794 smlTrace(TRACE_ENTRY, "%s", __func__);
00795 CHECK_ERROR_REF
00796 smlAssert(dsObject);
00797
00798
00799
00800 if (dsObject->dsType == SML_SESSION_TYPE_SERVER)
00801 {
00802 smlErrorSet(error, SML_ERROR_GENERIC, "An OMA DS server never sends a map.");
00803 goto error;
00804 }
00805 if (dsObject->dsType == SML_SESSION_TYPE_CLIENT &&
00806 dsObject->actualPackage != SML_PACKAGE_5)
00807 {
00808 smlErrorSet(error, SML_ERROR_GENERIC, "Missing server's sync package.");
00809 goto error;
00810 }
00811
00812
00813
00814 GList *o = dsObject->datastores;
00815 for (; o; o = o->next) {
00816 SmlDataSyncDatastore *datastore = o->data;
00817 smlAssert(datastore);
00818
00819
00820 if (!smlDsSessionCloseMap(datastore->session, smlDataSyncMapStatusCallback, datastore, error))
00821 goto error;
00822 }
00823
00824 smlTrace(TRACE_EXIT, "%s - TRUE", __func__);
00825 return TRUE;
00826 error:
00827 smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error));
00828 return FALSE;
00829 }
00830
00831
00832 const SmlLocation *smlDataSyncGetTarget(
00833 SmlDataSyncObject *dsObject,
00834 SmlError **error)
00835 {
00836 smlTrace(TRACE_INTERNAL, "%s(%p, %p)", __func__, dsObject, error);
00837 smlAssert(dsObject);
00838 return smlSessionGetTarget(dsObject->session);
00839 }
00840
00841
00842
00843
00844 void smlDataSyncObjectUnref(SmlDataSyncObject **dsObject)
00845 {
00846 if (g_atomic_int_dec_and_test(&((*dsObject)->refCount))) {
00847
00848
00849 if ((*dsObject)->thread)
00850 smlDataSyncLoopStop((*dsObject));
00851
00852
00853 if ((*dsObject)->manager) {
00854 smlManagerStop((*dsObject)->manager);
00855 smlManagerFree((*dsObject)->manager);
00856 }
00857 if ((*dsObject)->managerMutex)
00858 g_mutex_free((*dsObject)->managerMutex);
00859
00860
00861 if ((*dsObject)->tsp) {
00862 SmlError *error = NULL;
00863 if ((*dsObject)->dsType == SML_SESSION_TYPE_CLIENT &&
00864 SML_DATA_SYNC_STATE_CONNECTED >= (*dsObject)->internalState &&
00865 (*dsObject)->internalState <= SML_DATA_SYNC_STATE_DISCONNECTED &&
00866 !smlTransportDisconnect((*dsObject)->tsp, NULL, &error)) {
00867
00868 smlTrace(TRACE_ERROR, "%s: %s",
00869 __func__, smlErrorPrint(&error));
00870 smlErrorDeref(&error);
00871 }
00872
00873 if ((*dsObject)->internalState >= SML_DATA_SYNC_STATE_INITIALIZED &&
00874 !smlTransportFinalize((*dsObject)->tsp, &error)) {
00875 smlTrace(TRACE_ERROR, "%s: %s",
00876 __func__, smlErrorPrint(&error));
00877 smlErrorDeref(&error);
00878 }
00879 smlTransportFree((*dsObject)->tsp);
00880 }
00881
00882
00883 if ((*dsObject)->url)
00884 smlSafeCFree(&((*dsObject)->url));
00885 if ((*dsObject)->target)
00886 smlSafeCFree(&((*dsObject)->target));
00887 if ((*dsObject)->identifier)
00888 smlSafeCFree(&((*dsObject)->identifier));
00889 if ((*dsObject)->username)
00890 smlSafeCFree(&((*dsObject)->username));
00891 if ((*dsObject)->password)
00892 smlSafeCFree(&((*dsObject)->password));
00893 if ((*dsObject)->fakeDevice)
00894 smlSafeCFree(&((*dsObject)->fakeDevice));
00895 if ((*dsObject)->fakeManufacturer)
00896 smlSafeCFree(&((*dsObject)->fakeManufacturer));
00897 if ((*dsObject)->fakeModel)
00898 smlSafeCFree(&((*dsObject)->fakeModel));
00899 if ((*dsObject)->fakeSoftwareVersion)
00900 smlSafeCFree(&((*dsObject)->fakeSoftwareVersion));
00901
00902
00903 while((*dsObject)->datastores) {
00904 SmlDataSyncDatastore *datastore = (*dsObject)->datastores->data;
00905 (*dsObject)->datastores = g_list_remove(
00906 (*dsObject)->datastores,
00907 datastore);
00908 if (datastore->sourceUri)
00909 smlSafeCFree(&(datastore->sourceUri));
00910 if (datastore->targetUri)
00911 smlSafeCFree(&(datastore->targetUri));
00912 if (datastore->contentType)
00913 smlSafeCFree(&(datastore->contentType));
00914 if (datastore->remoteNext)
00915 smlSafeCFree(&(datastore->remoteNext));
00916 if (datastore->localNext)
00917 smlSafeCFree(&(datastore->localNext));
00918 if (datastore->session)
00919 smlDsSessionUnref(datastore->session);
00920 if (datastore->server)
00921 smlDsServerFree(datastore->server);
00922
00923 while(datastore->changes) {
00924 SmlDataSyncChange *change = datastore->changes->data;
00925 datastore->changes = g_list_remove(
00926 datastore->changes,
00927 change);
00928 if (change->name)
00929 smlSafeCFree(&(change->name));
00930 if (change->data)
00931 smlSafeCFree(&(change->data));
00932 smlSafeFree((gpointer *)&change);
00933 }
00934
00935 smlSafeFree((gpointer *)&datastore);
00936 }
00937
00938
00939 if ((*dsObject)->auth)
00940 smlAuthFree((*dsObject)->auth);
00941
00942
00943 if ((*dsObject)->session)
00944 smlSessionUnref((*dsObject)->session);
00945
00946
00947 if ((*dsObject)->localDevInf)
00948 smlDevInfUnref((*dsObject)->localDevInf);
00949 if ((*dsObject)->remoteDevInf)
00950 smlDevInfUnref((*dsObject)->remoteDevInf);
00951 if ((*dsObject)->agent)
00952 smlDevInfAgentFree((*dsObject)->agent);
00953
00954 smlSafeFree((gpointer *) dsObject);
00955 }
00956 }
00957
00958
00959
00960 void smlDataSyncSendEvent(
00961 SmlDataSyncObject *dsObject,
00962 SmlDataSyncEventType type,
00963 void *userdata,
00964 SmlError *error)
00965 {
00966
00967 smlAssert(dsObject);
00968 smlAssert(dsObject->eventCallback);
00969 dsObject->eventCallback(dsObject, type, userdata, error);
00970 }
00971