00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "data_sync_server.h"
00022 #include "data_sync_common.h"
00023 #include "libsyncml/sml_error_internals.h"
00024 #include "data_sync_callbacks.h"
00025 #include "libsyncml/objects/sml_ds_server.h"
00026 #include "data_sync_devinf.h"
00027 #include "libsyncml/sml_support.h"
00028
00029 static SmlBool smlDataSyncClientAlertCallback(
00030 SmlDsSession *dsession,
00031 SmlAlertType type,
00032 const char *last,
00033 const char *next,
00034 void *userdata)
00035 {
00036 smlTrace(TRACE_ENTRY, "%s(%p, %i, %s, %s, %p)", __func__, dsession, type, VA_STRING(last), VA_STRING(next), userdata);
00037
00038 SmlDataSyncDatastore *datastore = userdata;
00039 SmlDataSyncObject *dsObject = datastore->dsObject;
00040 SmlBool ret = TRUE;
00041 SmlError *error = NULL;
00042
00043
00044
00045
00046
00047
00048
00049 if (type != SML_ALERT_TWO_WAY &&
00050 type != SML_ALERT_SLOW_SYNC &&
00051 type != SML_ALERT_TWO_WAY_BY_SERVER)
00052 {
00053 smlErrorSet(&error, SML_ERROR_NOT_IMPLEMENTED, "Unsupported alert type %d.", type);
00054 goto error;
00055 }
00056
00057 char *remote_key = g_strdup_printf("remoteanchor%s", smlDsSessionGetLocation(dsession));
00058 datastore->remoteNext = g_strdup(next);
00059
00060
00061
00062
00063
00064 if (type == SML_ALERT_TWO_WAY || type == SML_ALERT_TWO_WAY_BY_SERVER)
00065 {
00066 if (!last)
00067 {
00068 smlTrace(TRACE_INTERNAL, "%s: TWO-WAY-SYNC is requested but there is no LAST anchor.", __func__);
00069 type = SML_ALERT_SLOW_SYNC;
00070 ret = FALSE;
00071 } else {
00072 char *cached = NULL;
00073 if (dsObject->getAnchorCallback)
00074 cached = dsObject->getAnchorCallback(
00075 dsObject,
00076 remote_key,
00077 dsObject->getAnchorUserdata,
00078 &error);
00079 if (!cached && error)
00080 goto error;
00081 if (!cached || strcmp(cached, last))
00082 {
00083 smlTrace(TRACE_INTERNAL,
00084 "%s: TWO-WAY-SYNC is requested but the cached LAST anchor (%s) does not match the presented LAST anchor from the remote peer (%s).",
00085 __func__, last, cached);
00086 if (cached)
00087 smlSafeCFree(&cached);
00088 type = SML_ALERT_SLOW_SYNC;
00089 ret = FALSE;
00090 }
00091 }
00092 }
00093
00094 if (dsObject->getAlertTypeCallback)
00095 {
00096 SmlAlertType h = dsObject->getAlertTypeCallback(
00097 dsObject,
00098 datastore->sourceUri,
00099 type,
00100 dsObject->getAlertTypeUserdata,
00101 &error);
00102 if (h == SML_ALERT_UNKNOWN || error)
00103 goto error;
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113 if (h != type) {
00114 if (h != SML_ALERT_SLOW_SYNC) {
00115 smlErrorSet(&error, SML_ERROR_GENERIC,
00116 "It is not possible to change the alert type after an OMA DS client received the alerts from the OMA DS server.");
00117 goto error;
00118 } else {
00119
00120 SmlLocation *source = NULL;
00121 source = smlLocationNew(datastore->sourceUri, NULL, &error);
00122 if (!source)
00123 goto error;
00124 SmlCommand *alert = NULL;
00125 alert = smlCommandNewAlert(
00126 SML_ALERT_SLOW_SYNC,
00127 smlDsSessionGetTarget(datastore->session),
00128 source,
00129 NULL, datastore->localNext,
00130 NULL, &error);
00131 if (!alert) {
00132 smlLocationUnref(source);
00133 goto error;
00134 }
00135 smlLocationUnref(source);
00136 if (!smlSessionSendCommand(dsObject->session, alert, NULL, NULL, NULL, &error)) {
00137 smlCommandUnref(alert);
00138 goto error;
00139 }
00140 smlCommandUnref(alert);
00141
00142
00143 ret = FALSE;
00144 }
00145 }
00146 }
00147
00148 smlSafeCFree(&remote_key);
00149
00150 smlTrace(TRACE_EXIT, "%s: %i", __func__, ret);
00151 return ret;
00152 error:
00153 smlErrorRef(&error);
00154 smlDataSyncSendEvent(
00155 dsObject, SML_DATA_SYNC_EVENT_ERROR,
00156 dsObject->eventUserdata, error);
00157 smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(&error));
00158 smlErrorDeref(&error);
00159 return FALSE;
00160 }
00161
00162 SmlBool smlDataSyncClientSendAlert(
00163 SmlDataSyncDatastore *datastore,
00164 SmlAlertType type,
00165 SmlError **error)
00166 {
00167 smlTrace(TRACE_ENTRY, "%s(%p, %d, %p)", __func__, datastore, type, error);
00168 CHECK_ERROR_REF
00169 SmlDataSyncObject *dsObject = datastore->dsObject;
00170
00171
00172 SmlAlertType alertType = type;
00173 char *local_last = NULL;
00174 if (dsObject->getAlertTypeCallback)
00175 {
00176 alertType = dsObject->getAlertTypeCallback(
00177 dsObject,
00178 datastore->sourceUri,
00179 type,
00180 dsObject->getAlertTypeUserdata,
00181 error);
00182 if (*error)
00183 goto error;
00184 }
00185 if (alertType == SML_ALERT_UNKNOWN)
00186 {
00187 smlTrace(TRACE_INTERNAL, "%s: no alert type => slow-sync", __func__);
00188 alertType = SML_ALERT_SLOW_SYNC;
00189 }
00190 if (alertType != SML_ALERT_SLOW_SYNC)
00191 {
00192
00193 alertType = SML_ALERT_TWO_WAY;
00194 char *local_key = g_strdup_printf("localanchor%s", smlDsServerGetLocation(datastore->server));
00195 if (dsObject->getAnchorCallback)
00196 local_last = dsObject->getAnchorCallback(
00197 dsObject,
00198 local_key,
00199 dsObject->getAnchorUserdata,
00200 error);
00201 smlSafeCFree(&local_key);
00202 }
00203
00204
00205 if (datastore->localNext)
00206 smlSafeCFree(&(datastore->localNext));
00207 datastore->localNext = smlDataSyncGetNextAnchor(datastore, local_last, error);
00208
00209
00210
00211
00212
00213
00214 while (!dsObject->session) {
00215 smlManagerDispatch(dsObject->manager);
00216 }
00217
00218
00219
00220
00221 datastore->session = smlDsServerSendAlert(
00222 datastore->server,
00223 dsObject->session,
00224 alertType,
00225 local_last, datastore->localNext,
00226 smlDataSyncAlertStatusCallback, datastore,
00227 error);
00228 if (local_last)
00229 smlSafeCFree(&local_last);
00230 if (!datastore->session)
00231 goto error;
00232
00233
00234
00235
00236 smlDsSessionGetAlert(datastore->session, smlDataSyncClientAlertCallback, datastore);
00237 if (dsObject->changeCallback) {
00238 smlDsSessionGetSync(datastore->session,
00239 smlDataSyncSyncCallback, datastore);
00240 smlDsSessionGetChanges(datastore->session,
00241 smlDataSyncChangeCallback, datastore);
00242 }
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252 SmlBool ret = TRUE;
00253 if (alertType == SML_ALERT_SLOW_SYNC &&
00254 alertType != type &&
00255 type != SML_ALERT_UNKNOWN) {
00256 ret = FALSE;
00257 }
00258
00259 smlTrace(TRACE_EXIT, "%s: %i", __func__, ret);
00260 return ret;
00261 error:
00262 smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error));
00263 return FALSE;
00264 }
00265
00266 static SmlErrorType smlDataSyncSanCallback(
00267 SmlDsServer *server,
00268 SmlSession *session,
00269 SmlAlertType type,
00270 void *userdata)
00271 {
00272 smlTrace(TRACE_ENTRY, "%s(%p, %p, %d, %p)", __func__, server, session, type, userdata);
00273 SmlDataSyncDatastore *datastore = userdata;
00274 SmlDataSyncObject *dsObject = datastore->dsObject;
00275 SmlError *error = NULL;
00276 SmlErrorType ret = SML_NO_ERROR;
00277
00278
00279 if (!dsObject->session) {
00280 dsObject->session = session;
00281 smlSessionRef(session);
00282 }
00283
00284 if (!smlDataSyncClientSendAlert(datastore, type, &error)) {
00285 if (!error)
00286 ret = SML_ERROR_REQUIRE_REFRESH;
00287 else
00288 goto error;
00289 }
00290
00291 smlTrace(TRACE_EXIT, "%s: %i", __func__, ret);
00292 return ret;
00293 error:
00294 smlErrorRef(&error);
00295 smlDataSyncSendEvent(
00296 dsObject, SML_DATA_SYNC_EVENT_ERROR,
00297 dsObject->eventUserdata, error);
00298 smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(&error));
00299 smlErrorDeref(&error);
00300 return SML_ERROR_GENERIC;
00301 }
00302
00303 SmlBool smlDataSyncClientInit(SmlDataSyncObject *dsObject, SmlError **error)
00304 {
00305 smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, dsObject, error);
00306 CHECK_ERROR_REF
00307
00308 dsObject->manager = smlManagerNew(dsObject->tsp, error);
00309 if (!dsObject->manager)
00310 goto error;
00311 smlManagerSetEventCallback(dsObject->manager, smlDataSyncEventCallback, dsObject);
00312 smlManagerSetLocalMaxMsgSize(dsObject->manager, dsObject->maxMsgSize);
00313 smlManagerSetLocalMaxObjSize(dsObject->manager, dsObject->maxObjSize);
00314
00315
00316 dsObject->funcDatastoreAlert = smlDataSyncClientAlertCallback;
00317
00318
00319 if (!smlDataSyncDevInfInit(dsObject, SML_DEVINF_DEVTYPE_WORKSTATION, error))
00320 goto error;
00321
00322
00323 GList *o = dsObject->datastores;
00324 for (; o; o = o->next) {
00325 SmlDataSyncDatastore *datastore = o->data;
00326 smlTrace(TRACE_INTERNAL, "preparing DsServer (datastore) %s", datastore->sourceUri);
00327
00328
00329 SmlLocation *loc = smlLocationNew(datastore->sourceUri, NULL, error);
00330 if (!loc)
00331 goto error;
00332
00333 datastore->server = smlDsClientNew(datastore->contentType, loc, loc, error);
00334 smlLocationUnref(loc);
00335 if (!datastore->server)
00336 goto error;
00337
00338 if (!smlDsServerRegister(datastore->server, dsObject->manager, error))
00339 goto error;
00340
00341
00342
00343
00344 smlDsServerSetConnectCallback(
00345 datastore->server,
00346 smlDataSyncDatastoreConnectCallback,
00347 datastore);
00348
00349 smlDsServerSetSanSessionCallback(
00350 datastore->server,
00351 smlDataSyncSanCallback,
00352 datastore);
00353
00354
00355 if (!smlDataSyncDevInfAddDatastore(dsObject->localDevInf, datastore, error))
00356 goto error;
00357 }
00358
00359
00360 if (!smlManagerStart(dsObject->manager, error))
00361 goto error;
00362
00363
00364 if (!smlTransportInitialize(dsObject->tsp, error))
00365 goto error;
00366
00367 smlTrace(TRACE_EXIT, "%s - TRUE", __func__);
00368 return TRUE;
00369
00370 error:
00371 smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error));
00372 return FALSE;
00373 }
00374