21 #include "../syncml.h"
22 #include "../syncml_internals.h"
23 #include "../sml_error_internals.h"
25 #include <libsyncml/data_sync_api/defines.h>
26 #include <libsyncml/data_sync_api/standard.h>
27 #include <libsyncml/data_sync_api/callbacks.h>
32 #include "data_sync.h"
33 #include "data_sync_client.h"
34 #include "data_sync_server.h"
35 #include "data_sync_callbacks.h"
36 #include "data_sync_callbacks.h"
37 #include "data_sync_devinf.h"
38 #include "data_sync_loop.h"
39 #include "transport.h"
40 #include "libsyncml/objects/sml_ds_server_internals.h"
47 SmlSessionType dsType,
48 SmlTransportType tspType,
51 smlTrace(TRACE_ENTRY,
"%s(%d, %d, %p)", __func__, dsType, tspType, error);
54 smlTrace(TRACE_INTERNAL,
"%s: libsyncml version: %s", __func__, VERSION);
59 smlDataSyncObjectRef(dsObject);
61 dsObject->dsType = dsType;
62 dsObject->tspType = tspType;
63 dsObject->version = SML_VERSION_11;
64 dsObject->internalState = SML_DATA_SYNC_STATE_NEW;
66 dsObject->useNumberOfChanges = TRUE;
67 dsObject->useTimestampAnchor = TRUE;
68 dsObject->maxObjSize = SML_DEFAULT_MAX_OBJ_SIZE;
69 dsObject->maxMsgSize = SML_DEFAULT_MAX_MSG_SIZE;
76 case SML_TRANSPORT_OBEX_CLIENT:
77 dsObject->funcTspInit = smlDataSyncTransportObexClientInit;
78 dsObject->funcTspConnect = smlDataSyncTransportObexClientConnect;
80 case SML_TRANSPORT_OBEX_SERVER:
81 dsObject->funcTspInit = NULL;
82 dsObject->funcTspConnect = NULL;
84 case SML_TRANSPORT_HTTP_SERVER:
85 dsObject->funcTspInit = smlDataSyncTransportHttpServerInit;
86 dsObject->funcTspConnect = NULL;
88 case SML_TRANSPORT_HTTP_CLIENT:
89 dsObject->funcTspInit = smlDataSyncTransportHttpClientInit;
90 dsObject->funcTspConnect = smlDataSyncTransportHttpClientConnect;
93 smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION,
94 "Unknown transport type %d used in __func__.",
101 case SML_SESSION_TYPE_SERVER:
102 dsObject->funcDsInit = smlDataSyncServerInit;
103 dsObject->funcDsConnect = NULL;
105 case SML_SESSION_TYPE_CLIENT:
106 dsObject->funcDsInit = smlDataSyncClientInit;
107 dsObject->funcDsConnect = NULL;
110 smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION,
111 "Unknown data sync type %d used in %s.",
117 smlTrace(TRACE_EXIT,
"%s - %p", __func__, dsObject);
123 smlDataSyncObjectUnref(&dsObject);
131 g_atomic_int_inc(&(dsObject->refCount));
134 SmlBool smlDataSyncSetOption(
140 smlTrace(TRACE_ENTRY,
"%s(%p, %s, %s, %p)", __func__, dsObject, VA_STRING(name), VA_STRING(value), error);
143 if (!strcmp(SML_DATA_SYNC_CONFIG_CONNECTION_TYPE, name)) {
144 if (!strcmp(SML_DATA_SYNC_CONFIG_CONNECTION_SERIAL, value))
145 dsObject->conType = SML_TRANSPORT_CONNECTION_TYPE_SERIAL;
146 if (!strcmp(SML_DATA_SYNC_CONFIG_CONNECTION_BLUETOOTH, value))
147 dsObject->conType = SML_TRANSPORT_CONNECTION_TYPE_BLUETOOTH;
148 if (!strcmp(SML_DATA_SYNC_CONFIG_CONNECTION_IRDA, value))
149 dsObject->conType = SML_TRANSPORT_CONNECTION_TYPE_IRDA;
150 if (!strcmp(SML_DATA_SYNC_CONFIG_CONNECTION_NET, value))
151 dsObject->conType = SML_TRANSPORT_CONNECTION_TYPE_NET;
152 if (!strcmp(SML_DATA_SYNC_CONFIG_CONNECTION_USB, value))
153 dsObject->conType = SML_TRANSPORT_CONNECTION_TYPE_USB;
156 }
else if (!strcmp(SML_DATA_SYNC_CONFIG_VERSION, name)) {
157 dsObject->version = SML_VERSION_UNKNOWN;
158 if (!strcmp(
"1.0", value))
159 dsObject->version = SML_VERSION_10;
160 if (!strcmp(
"1.1", value))
161 dsObject->version = SML_VERSION_11;
162 if (!strcmp(
"1.2", value))
163 dsObject->version = SML_VERSION_12;
164 if (dsObject->version == SML_VERSION_UNKNOWN) {
165 smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION,
166 "Unknown SyncML version %s.", value);
169 }
else if (!strcmp(SML_DATA_SYNC_CONFIG_AUTH_TYPE, name)) {
170 if (!strcmp(value, SML_DATA_SYNC_CONFIG_AUTH_BASIC)) {
171 dsObject->authType = SML_AUTH_TYPE_BASIC;
172 }
else if (!strcmp(value, SML_DATA_SYNC_CONFIG_AUTH_MD5)) {
173 dsObject->authType = SML_AUTH_TYPE_MD5;
174 }
else if (!strcmp(value, SML_DATA_SYNC_CONFIG_AUTH_NONE)) {
175 dsObject->authType = SML_AUTH_TYPE_UNKNOWN;
178 smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION,
179 "Unknown authentication type %s.", value);
182 }
else if (!strcmp(SML_TRANSPORT_CONFIG_URL, name)) {
183 dsObject->url = g_strdup(value);
188 if (!dsObject->target)
189 dsObject->target = g_strdup(value);
190 }
else if (!strcmp(SML_DATA_SYNC_CONFIG_TARGET, name)) {
191 if (dsObject->target)
192 smlSafeCFree(&(dsObject->target));
193 dsObject->target = g_strdup(value);
194 }
else if (!strcmp(SML_DATA_SYNC_CONFIG_IDENTIFIER, name)) {
195 if (dsObject->identifier)
196 smlSafeCFree(&(dsObject->identifier));
197 if (value && strlen(value)) {
198 dsObject->identifier = g_strdup(value);
201 "%s: set identifier to NULL", __func__);
203 }
else if (!strcmp(SML_DATA_SYNC_CONFIG_AUTH_USERNAME, name)) {
204 dsObject->username = g_strdup(value);
205 }
else if (!strcmp(SML_DATA_SYNC_CONFIG_AUTH_PASSWORD, name)) {
206 dsObject->password = g_strdup(value);
207 }
else if (!strcmp(SML_DATA_SYNC_CONFIG_USE_WBXML, name)) {
208 dsObject->useWbxml = atoi(value);
209 }
else if (!strcmp(SML_DATA_SYNC_CONFIG_USE_STRING_TABLE, name)) {
210 dsObject->useStringTable = atoi(value);
211 }
else if (!strcmp(SML_DATA_SYNC_CONFIG_USE_TIMESTAMP_ANCHOR, name)) {
212 dsObject->useTimestampAnchor = atoi(value);
213 }
else if (!strcmp(SML_DATA_SYNC_CONFIG_USE_NUMBER_OF_CHANGES, name)) {
214 dsObject->useNumberOfChanges = atoi(value);
215 }
else if (!strcmp(SML_DATA_SYNC_CONFIG_USE_LOCALTIME, name)) {
216 dsObject->onlyLocaltime = atoi(value);
217 }
else if (!strcmp(SML_DATA_SYNC_CONFIG_ONLY_REPLACE, name)) {
218 dsObject->onlyReplace = atoi(value);
219 }
else if (!strcmp(SML_DATA_SYNC_CONFIG_MAX_OBJ_SIZE, name)) {
220 dsObject->maxObjSize = atoi(value);
221 }
else if (!strcmp(SML_DATA_SYNC_CONFIG_MAX_MSG_SIZE, name)) {
222 dsObject->maxMsgSize = atoi(value);
223 }
else if (!strcmp(SML_DATA_SYNC_CONFIG_FAKE_DEVICE, name)) {
224 dsObject->fakeDevice = g_strdup(value);
225 }
else if (!strcmp(SML_DATA_SYNC_CONFIG_FAKE_MANUFACTURER, name)) {
226 dsObject->fakeManufacturer = g_strdup(value);
227 }
else if (!strcmp(SML_DATA_SYNC_CONFIG_FAKE_MODEL, name)) {
228 dsObject->fakeModel = g_strdup(value);
229 }
else if (!strcmp(SML_DATA_SYNC_CONFIG_FAKE_SOFTWARE_VERSION, name)) {
230 dsObject->fakeSoftwareVersion = g_strdup(value);
237 if ((dsObject->username || dsObject->password) &&
238 dsObject->authType == SML_AUTH_TYPE_UNKNOWN)
241 "%s: authType is set to default (syncml:auth-basic)", __func__);
242 dsObject->authType = SML_AUTH_TYPE_BASIC;
245 smlTrace(TRACE_EXIT,
"%s - TRUE", __func__);
253 const char *contentType,
258 smlTrace(TRACE_ENTRY,
"%s(%p, %s, %s, %s, %p)", __func__, dsObject, VA_STRING(contentType), VA_STRING(target), VA_STRING(source), error);
262 char *lcSource = NULL;
268 datastore->dsObject = dsObject;
269 datastore->syncChanges = NULL;
270 datastore->syncContexts = NULL;
271 datastore->sourceUri = g_strdup(source);
272 datastore->targetUri = g_strdup(target);
273 datastore->contentType = g_strdup(contentType);
275 dsObject->datastores = g_list_append(dsObject->datastores, datastore);
279 if (dsObject->tspType == SML_TRANSPORT_OBEX_CLIENT)
281 lcCT = g_ascii_strdown(contentType, strlen(contentType));
282 lcSource = g_utf8_strdown(source, strlen(source));
283 if (strstr(lcCT,
"vcard") &&
286 SML_TRANSPORT_CONFIG_DATASTORE,
287 SML_TRANSPORT_CONFIG_DATASTORE_CONTACT,
292 if (strstr(lcCT,
"calendar") &&
293 ( strstr(lcSource,
"cal") ||
294 strstr(lcSource,
"event")
298 SML_TRANSPORT_CONFIG_DATASTORE,
299 SML_TRANSPORT_CONFIG_DATASTORE_EVENT,
304 if (strstr(lcCT,
"calendar") &&
305 strstr(lcSource,
"todo") &&
308 SML_TRANSPORT_CONFIG_DATASTORE,
309 SML_TRANSPORT_CONFIG_DATASTORE_TODO,
314 if (strstr(lcCT,
"text/plain") &&
317 SML_TRANSPORT_CONFIG_DATASTORE,
318 SML_TRANSPORT_CONFIG_DATASTORE_NOTE,
324 smlSafeCFree(&lcSource);
327 smlTrace(TRACE_EXIT,
"%s - TRUE", __func__);
331 smlSafeFree((gpointer *)&datastore);
335 smlSafeCFree(&lcSource);
349 GList *o = dsObject->datastores;
350 for (; o; o = o->next) {
352 if (!strcmp(datastore->sourceUri, source))
356 smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION,
357 "Cannot find datastore for source name %s.", source);
365 void smlDataSyncRegisterEventCallback(
367 SmlDataSyncEventCallback callback,
370 smlTrace(TRACE_ENTRY,
"%s", __func__);
374 dsObject->eventCallback = callback;
375 dsObject->eventUserdata = userdata;
377 smlTrace(TRACE_EXIT,
"%s", __func__);
380 void smlDataSyncRegisterGetAlertTypeCallback(
382 SmlDataSyncGetAlertTypeCallback callback,
385 smlTrace(TRACE_ENTRY,
"%s", __func__);
389 dsObject->getAlertTypeCallback = callback;
390 dsObject->getAlertTypeUserdata = userdata;
392 smlTrace(TRACE_EXIT,
"%s", __func__);
395 void smlDataSyncRegisterChangeCallback(
397 SmlDataSyncChangeCallback callback,
400 smlTrace(TRACE_ENTRY,
"%s", __func__);
404 dsObject->changeCallback = callback;
405 dsObject->changeUserdata = userdata;
407 GList *o = dsObject->datastores;
408 for (;o;o = o->next) {
410 if (datastore->session) {
411 smlDsSessionGetSync(datastore->session,
412 smlDataSyncSyncCallback, datastore);
414 smlDataSyncChangeCallback, datastore);
418 smlTrace(TRACE_EXIT,
"%s", __func__);
421 void smlDataSyncRegisterChangeStatusCallback(
423 SmlDataSyncChangeStatusCallback callback)
425 smlTrace(TRACE_ENTRY,
"%s", __func__);
429 dsObject->changeStatusCallback = callback;
432 smlTrace(TRACE_EXIT,
"%s", __func__);
435 void smlDataSyncRegisterMapCallback(
437 SmlDataSyncMappingCallback callback,
440 smlTrace(TRACE_ENTRY,
"%s", __func__);
444 dsObject->mappingCallback = callback;
445 dsObject->mappingUserdata = userdata;
447 GList *o = dsObject->datastores;
448 for (;o;o = o->next) {
450 if (datastore->session) {
451 smlDsSessionGetMapping(datastore->session,
452 smlDataSyncMappingCallback, datastore);
456 smlTrace(TRACE_EXIT,
"%s", __func__);
460 void smlDataSyncRegisterGetAnchorCallback(
462 SmlDataSyncGetAnchorCallback callback,
465 smlTrace(TRACE_ENTRY,
"%s", __func__);
469 dsObject->getAnchorCallback = callback;
470 dsObject->getAnchorUserdata = userdata;
472 smlTrace(TRACE_EXIT,
"%s", __func__);
475 void smlDataSyncRegisterSetAnchorCallback(
477 SmlDataSyncSetAnchorCallback callback,
480 smlTrace(TRACE_ENTRY,
"%s", __func__);
484 dsObject->setAnchorCallback = callback;
485 dsObject->setAnchorUserdata = userdata;
487 smlTrace(TRACE_EXIT,
"%s", __func__);
490 void smlDataSyncRegisterWriteDevInfCallback(
492 SmlDataSyncWriteDevInfCallback callback,
495 smlTrace(TRACE_ENTRY,
"%s", __func__);
499 dsObject->writeDevInfCallback = callback;
500 dsObject->writeDevInfUserdata = userdata;
502 smlTrace(TRACE_EXIT,
"%s", __func__);
505 void smlDataSyncRegisterReadDevInfCallback(
507 SmlDataSyncReadDevInfCallback callback,
510 smlTrace(TRACE_ENTRY,
"%s", __func__);
514 dsObject->readDevInfCallback = callback;
515 dsObject->readDevInfUserdata = userdata;
517 smlTrace(TRACE_EXIT,
"%s", __func__);
520 void smlDataSyncRegisterHandleRemoteDevInfCallback(
522 SmlDataSyncHandleRemoteDevInfCallback callback,
525 smlTrace(TRACE_ENTRY,
"%s", __func__);
529 dsObject->handleRemoteDevInfCallback = callback;
530 dsObject->handleRemoteDevInfUserdata = userdata;
532 smlTrace(TRACE_EXIT,
"%s", __func__);
541 smlTrace(TRACE_ENTRY,
"%s", __func__);
545 if (!dsObject->identifier)
546 dsObject->identifier = smlDataSyncDevInfGetIdentifier();
548 dsObject->managerMutex = g_mutex_new();
550 if (dsObject->funcTspInit &&
551 !dsObject->funcTspInit(dsObject, error))
553 if (!dsObject->funcDsInit(dsObject, error))
556 dsObject->internalState = SML_DATA_SYNC_STATE_INITIALIZED;
558 smlTrace(TRACE_EXIT,
"%s - TRUE", __func__);
567 smlTrace(TRACE_ENTRY,
"%s", __func__);
574 if (dsObject->funcTspConnect &&
575 !dsObject->funcTspConnect(dsObject, error))
577 if (dsObject->funcDsConnect &&
578 !dsObject->funcDsConnect(dsObject, error))
581 if (!smlDataSyncLoopStart(dsObject, error))
584 smlTrace(TRACE_EXIT,
"%s - TRUE", __func__);
593 SmlBool smlDataSyncAddChange(
603 smlTrace(TRACE_ENTRY,
"%s(%s)", __func__, VA_STRING(source));
618 change->name = g_strdup(name);
619 change->userdata = userdata;
622 change->datastore = smlDataSyncGetDatastoreFromSource(dsObject, source, error);
623 if (!change->datastore)
629 smlAssert(datastore->contentType);
630 smlAssert(index(datastore->contentType,
'/'));
631 size_t appClassLength = ((size_t) index(datastore->contentType,
'/')) -
632 ((
size_t) datastore->contentType);
633 if ( ( strstr(datastore->contentType, SML_CONTENT_TYPE_APPLICATION) == datastore->contentType &&
634 appClassLength == strlen(SML_CONTENT_TYPE_APPLICATION) ) ||
635 ( strstr(datastore->contentType, SML_CONTENT_TYPE_AUDIO) == datastore->contentType &&
636 appClassLength == strlen(SML_CONTENT_TYPE_AUDIO) ) ||
637 ( strstr(datastore->contentType, SML_CONTENT_TYPE_IMAGE) == datastore->contentType &&
638 appClassLength == strlen(SML_CONTENT_TYPE_IMAGE) ) ||
639 ( strstr(datastore->contentType, SML_CONTENT_TYPE_MESSAGE) == datastore->contentType &&
640 appClassLength == strlen(SML_CONTENT_TYPE_MESSAGE) ) ||
641 ( strstr(datastore->contentType, SML_CONTENT_TYPE_VIDEO) == datastore->contentType &&
642 appClassLength == strlen(SML_CONTENT_TYPE_AUDIO) ) )
645 change->data = g_base64_encode((
const unsigned char *) data, size);
648 "The base 64 encoding of glib failed.");
651 change->size = strlen(change->data);
656 memcpy(change->data, data, size);
665 datastore->changes = g_list_append(datastore->changes, change);
667 smlTrace(TRACE_EXIT,
"%s - TRUE", __func__);
679 smlTrace(TRACE_ENTRY,
"%s", __func__);
684 if (dsObject->internalState >= SML_DATA_SYNC_STATE_SENT_CHANGES)
687 "The function %s is called to late or more than once.", __func__);
690 dsObject->internalState = SML_DATA_SYNC_STATE_SENT_CHANGES;
692 if (dsObject->dsType == SML_SESSION_TYPE_SERVER &&
693 dsObject->actualPackage != SML_PACKAGE_4)
696 "This is not the server's sync package (%d).",
697 dsObject->actualPackage);
700 if (dsObject->dsType == SML_SESSION_TYPE_CLIENT &&
701 dsObject->actualPackage != SML_PACKAGE_3)
704 "This is not the client's sync package (%d).",
705 dsObject->actualPackage);
711 GList *o = dsObject->datastores;
712 for (; o; o = o->next) {
714 smlAssert(datastore);
716 int num = g_list_length(datastore->changes);
720 smlDataSyncSyncStatusCallback,
726 for (i = 0; i < num; i++) {
728 if (!smlDsSessionQueueChange(
734 datastore->contentType,
735 smlDataSyncChangeStatusCallback,
750 smlTrace(TRACE_EXIT,
"%s - TRUE", __func__);
757 SmlBool smlDataSyncAddMapping(
760 const char *remoteID,
764 smlTrace(TRACE_ENTRY,
"%s(%s)", __func__, VA_STRING(source));
779 datastore = smlDataSyncGetDatastoreFromSource(dsObject, source, error);
782 if (!smlDsSessionQueueMap(datastore->session, remoteID, localID, error))
785 smlTrace(TRACE_EXIT,
"%s - TRUE", __func__);
794 smlTrace(TRACE_ENTRY,
"%s", __func__);
800 if (dsObject->dsType == SML_SESSION_TYPE_SERVER)
802 smlErrorSet(error, SML_ERROR_GENERIC,
"An OMA DS server never sends a map.");
805 if (dsObject->dsType == SML_SESSION_TYPE_CLIENT &&
806 dsObject->actualPackage != SML_PACKAGE_5)
808 smlErrorSet(error, SML_ERROR_GENERIC,
"Missing server's sync package.");
814 GList *o = dsObject->datastores;
815 for (; o; o = o->next) {
817 smlAssert(datastore);
824 smlTrace(TRACE_EXIT,
"%s - TRUE", __func__);
836 smlTrace(TRACE_INTERNAL,
"%s(%p, %p)", __func__, dsObject, error);
838 return smlSessionGetTarget(dsObject->session);
846 if (g_atomic_int_dec_and_test(&((*dsObject)->refCount))) {
849 if ((*dsObject)->thread)
850 smlDataSyncLoopStop((*dsObject));
853 if ((*dsObject)->manager) {
855 smlManagerFree((*dsObject)->manager);
857 if ((*dsObject)->managerMutex)
858 g_mutex_free((*dsObject)->managerMutex);
861 if ((*dsObject)->tsp) {
863 if ((*dsObject)->dsType == SML_SESSION_TYPE_CLIENT &&
864 SML_DATA_SYNC_STATE_CONNECTED >= (*dsObject)->internalState &&
865 (*dsObject)->internalState <= SML_DATA_SYNC_STATE_DISCONNECTED &&
866 !smlTransportDisconnect((*dsObject)->tsp, NULL, &error)) {
870 smlErrorDeref(&error);
873 if ((*dsObject)->internalState >= SML_DATA_SYNC_STATE_INITIALIZED &&
877 smlErrorDeref(&error);
883 if ((*dsObject)->url)
884 smlSafeCFree(&((*dsObject)->url));
885 if ((*dsObject)->target)
886 smlSafeCFree(&((*dsObject)->target));
887 if ((*dsObject)->identifier)
888 smlSafeCFree(&((*dsObject)->identifier));
889 if ((*dsObject)->username)
890 smlSafeCFree(&((*dsObject)->username));
891 if ((*dsObject)->password)
892 smlSafeCFree(&((*dsObject)->password));
893 if ((*dsObject)->fakeDevice)
894 smlSafeCFree(&((*dsObject)->fakeDevice));
895 if ((*dsObject)->fakeManufacturer)
896 smlSafeCFree(&((*dsObject)->fakeManufacturer));
897 if ((*dsObject)->fakeModel)
898 smlSafeCFree(&((*dsObject)->fakeModel));
899 if ((*dsObject)->fakeSoftwareVersion)
900 smlSafeCFree(&((*dsObject)->fakeSoftwareVersion));
903 while((*dsObject)->datastores) {
905 (*dsObject)->datastores = g_list_remove(
906 (*dsObject)->datastores,
908 if (datastore->sourceUri)
909 smlSafeCFree(&(datastore->sourceUri));
910 if (datastore->targetUri)
911 smlSafeCFree(&(datastore->targetUri));
912 if (datastore->contentType)
913 smlSafeCFree(&(datastore->contentType));
914 if (datastore->remoteNext)
915 smlSafeCFree(&(datastore->remoteNext));
916 if (datastore->localNext)
917 smlSafeCFree(&(datastore->localNext));
918 if (datastore->session)
919 smlDsSessionUnref(datastore->session);
920 if (datastore->server)
921 smlDsServerFree(datastore->server);
923 while(datastore->changes) {
925 datastore->changes = g_list_remove(
929 smlSafeCFree(&(change->name));
931 smlSafeCFree(&(change->data));
932 smlSafeFree((gpointer *)&change);
935 smlSafeFree((gpointer *)&datastore);
939 if ((*dsObject)->auth)
940 smlAuthFree((*dsObject)->auth);
943 if ((*dsObject)->session)
944 smlSessionUnref((*dsObject)->session);
947 if ((*dsObject)->localDevInf)
948 smlDevInfUnref((*dsObject)->localDevInf);
949 if ((*dsObject)->remoteDevInf)
950 smlDevInfUnref((*dsObject)->remoteDevInf);
951 if ((*dsObject)->agent)
952 smlDevInfAgentFree((*dsObject)->agent);
954 smlSafeFree((gpointer *) dsObject);
960 void smlDataSyncSendEvent(
968 smlAssert(dsObject->eventCallback);
969 dsObject->eventCallback(dsObject, type, userdata, error);