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 smlDataSyncServerAlertCallback(
00030 SmlDsSession *dsession,
00031 SmlAlertType recvType,
00032 const char *last,
00033 const char *next,
00034 void *userdata)
00035 {
00036 smlTrace(TRACE_ENTRY, "%s(%p, %i, %s, %s, %p)", __func__, dsession, recvType, 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 SmlAlertType sentType = recvType;
00043
00044
00045
00046
00047
00048
00049
00050 if (recvType != SML_ALERT_TWO_WAY &&
00051 recvType != SML_ALERT_SLOW_SYNC &&
00052 recvType != SML_ALERT_TWO_WAY_BY_SERVER)
00053 {
00054 smlErrorSet(&error, SML_ERROR_NOT_IMPLEMENTED, "Unsupported alert type %d.", recvType);
00055 goto error;
00056 }
00057
00058 char *remote_key = g_strdup_printf("remoteanchor%s", smlDsSessionGetLocation(dsession));
00059 datastore->remoteNext = g_strdup(next);
00060
00061
00062
00063
00064
00065 if (recvType == SML_ALERT_TWO_WAY || recvType == SML_ALERT_TWO_WAY_BY_SERVER)
00066 {
00067 if (!last)
00068 {
00069 smlTrace(TRACE_INTERNAL, "%s: TWO-WAY-SYNC but last is missing", __func__);
00070 sentType = SML_ALERT_SLOW_SYNC;
00071 ret = FALSE;
00072 } else {
00073 char *cached = NULL;
00074 if (dsObject->getAnchorCallback)
00075 cached = dsObject->getAnchorCallback(
00076 dsObject,
00077 remote_key,
00078 dsObject->getAnchorUserdata,
00079 &error);
00080 if (!cached && error)
00081 goto error;
00082 if (!cached || strcmp(cached, last))
00083 {
00084 smlTrace(TRACE_INTERNAL,
00085 "%s: TWO-WAY-SYNC but received LAST(%s) and cached LAST (%s) mismatch",
00086 __func__, VA_STRING(last), VA_STRING(cached));
00087 if (cached)
00088 smlSafeCFree(&cached);
00089 sentType = SML_ALERT_SLOW_SYNC;
00090 ret = FALSE;
00091 }
00092 }
00093 }
00094
00095 if (dsObject->getAlertTypeCallback)
00096 {
00097 SmlAlertType alertType;
00098 alertType = dsObject->getAlertTypeCallback(
00099 dsObject,
00100 datastore->sourceUri,
00101 sentType,
00102 dsObject->getAlertTypeUserdata,
00103 &error);
00104 if (alertType == SML_ALERT_UNKNOWN || error)
00105 goto error;
00106 if (alertType == SML_ALERT_SLOW_SYNC &&
00107 alertType != recvType)
00108 ret = FALSE;
00109 sentType = alertType;
00110 }
00111
00112 smlSafeCFree(&remote_key);
00113
00114
00115
00116
00117
00118
00119 if (
00120 (
00121 recvType != SML_ALERT_SLOW_SYNC &&
00122 sentType != SML_ALERT_SLOW_SYNC &&
00123 ret == FALSE
00124 ) ||
00125 (
00126 recvType != SML_ALERT_SLOW_SYNC &&
00127 sentType == SML_ALERT_SLOW_SYNC &&
00128 ret != FALSE
00129 ) ||
00130 (
00131 recvType == SML_ALERT_SLOW_SYNC &&
00132 sentType != SML_ALERT_SLOW_SYNC
00133 ) ||
00134 (
00135 recvType == SML_ALERT_SLOW_SYNC &&
00136 sentType == SML_ALERT_SLOW_SYNC &&
00137 ret == FALSE
00138 )
00139 )
00140 {
00141 if (ret) {
00142 smlErrorSet(&error, SML_ERROR_GENERIC,
00143 "The library user tries to respond an alert %d " \
00144 "with an alert %d and status 200 which is illegal.",
00145 recvType, sentType);
00146 } else {
00147 smlErrorSet(&error, SML_ERROR_GENERIC,
00148 "The library user tries to respond an alert %d " \
00149 "with an alert %d and status 508 which is illegal.",
00150 recvType, sentType);
00151 }
00152 goto error;
00153 }
00154
00155
00156 char *local_key = g_strdup_printf("localanchor%s", smlDsSessionGetLocation(dsession));
00157 char *local_last = NULL;
00158 if (dsObject->getAnchorCallback)
00159 local_last = dsObject->getAnchorCallback(
00160 dsObject,
00161 local_key,
00162 dsObject->getAnchorUserdata,
00163 &error);
00164 if (!local_last && error)
00165 goto error;
00166 if (datastore->localNext)
00167 smlSafeCFree(&(datastore->localNext));
00168 if (local_last == NULL || strlen(local_last) == 0)
00169 {
00170
00171
00172
00173 if (smlDataSyncIsTimestamp(next, dsObject->useTimestampAnchor) != dsObject->useTimestampAnchor)
00174 {
00175
00176
00177
00178 smlTrace(TRACE_INTERNAL,
00179 "%s: libsyncml uses different timestamp anchor modes.",
00180 __func__);
00181 }
00182 }
00183 datastore->localNext = smlDataSyncGetNextAnchor(datastore, local_last, &error);
00184 if (!datastore->localNext)
00185 goto error;
00186
00187
00188 if (!smlDsSessionSendAlert(
00189 dsession, sentType,
00190 local_last, datastore->localNext,
00191 smlDataSyncAlertStatusCallback,
00192 datastore, &error))
00193 goto error;
00194
00195
00196 smlSafeCFree(&local_key);
00197 if (local_last)
00198 smlSafeCFree(&local_last);
00199
00200 smlTrace(TRACE_EXIT, "%s: %i", __func__, ret);
00201 return ret;
00202 error:
00203 smlErrorRef(&error);
00204 smlDataSyncSendEvent(
00205 dsObject, SML_DATA_SYNC_EVENT_ERROR,
00206 dsObject->eventUserdata, error);
00207 smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(&error));
00208 smlErrorDeref(&error);
00209 return FALSE;
00210 }
00211
00212 SmlBool smlDataSyncServerInit(SmlDataSyncObject *dsObject, SmlError **error)
00213 {
00214 CHECK_ERROR_REF
00215
00216 dsObject->manager = smlManagerNew(dsObject->tsp, error);
00217 if (!dsObject->manager)
00218 goto error;
00219 smlManagerSetEventCallback(dsObject->manager, smlDataSyncEventCallback, dsObject);
00220 smlManagerSetLocalMaxMsgSize(dsObject->manager, dsObject->maxMsgSize);
00221 smlManagerSetLocalMaxObjSize(dsObject->manager, dsObject->maxObjSize);
00222
00223
00224 dsObject->funcDatastoreAlert = smlDataSyncServerAlertCallback;
00225
00226
00227 dsObject->auth = smlAuthNew(error);
00228 if (!dsObject->auth)
00229 goto error;
00230 smlAuthSetVerifyCallback(dsObject->auth, smlDataSyncVerifyUserCallback, dsObject);
00231 if (!dsObject->username) {
00232 smlAuthSetEnable(dsObject->auth, FALSE);
00233 } else {
00234 smlAuthSetEnable(dsObject->auth, TRUE);
00235 smlAuthSetType(dsObject->auth, dsObject->authType);
00236 }
00237 if (!smlAuthRegister(dsObject->auth, dsObject->manager, error))
00238 goto error;
00239
00240
00241 if (!smlDataSyncDevInfInit(dsObject, SML_DEVINF_DEVTYPE_SERVER, error))
00242 goto error;
00243
00244
00245 GList *o = dsObject->datastores;
00246 for (; o; o = o->next) {
00247 SmlDataSyncDatastore *datastore = o->data;
00248
00249
00250 SmlLocation *loc = smlLocationNew(datastore->sourceUri, NULL, error);
00251 if (!loc)
00252 goto error;
00253
00254 datastore->server = smlDsServerNew(datastore->contentType, loc, error);
00255 if (!datastore->server) {
00256 smlLocationUnref(loc);
00257 goto error;
00258 }
00259 smlLocationUnref(loc);
00260
00261 if (!smlDsServerRegister(datastore->server, dsObject->manager, error))
00262 goto error;
00263
00264 smlDsServerSetConnectCallback(
00265 datastore->server,
00266 smlDataSyncDatastoreConnectCallback,
00267 datastore);
00268
00269
00270 if (!smlDataSyncDevInfAddDatastore(dsObject->localDevInf, datastore, error))
00271 goto error;
00272 }
00273
00274
00275 if (!smlManagerStart(dsObject->manager, error))
00276 goto error;
00277
00278
00279 if (!smlTransportInitialize(dsObject->tsp, error))
00280 goto error;
00281
00282 smlTrace(TRACE_EXIT, "%s - TRUE", __func__);
00283 return TRUE;
00284
00285 error:
00286 smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error));
00287 return FALSE;
00288 }
00289