data_sync_callbacks.c
/*
* libsyncml - A syncml protocol implementation
* Copyright (C) 2008-2009 Michael Bell <michael.bell@opensync.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "data_sync_callbacks.h"
#include "libsyncml/syncml_internals.h"
#include "libsyncml/sml_support.h"
#include "libsyncml/sml_error_internals.h"
#include <string.h>
#include <strings.h>
#include "defines.h"
#include "data_sync_devinf.h"
#include "libsyncml/objects/sml_ds_server_internals.h"
#include "libsyncml/sml_manager_internals.h"
//#include "syncml_common.h"
//#include "syncml_callbacks.h"
//#include "syncml_vformat.h"
//#include "syncml_devinf.h"
//#include "syncml_ds_client.h"
//#include "syncml_ds_server.h"
/* **************************************** */
/* ***** Management Callbacks ***** */
/* **************************************** */
void smlDataSyncEventCallback(
SmlManager *manager,
SmlManagerEventType type,
SmlSession *session,
SmlError *error,
void *userdata)
{
smlTrace(TRACE_ENTRY, "%s(%p, %i, %p, %p, %p)", __func__, manager, type, session, error, userdata);
SmlDataSyncObject *dsObject = userdata;
smlAssert(dsObject);
GList *o = NULL;
/* FIXME: Is this lock really needed? */
/* FIXME: Who is allowed to call smlManagerDispatch? */
/* FIXME: The SmlManager must be synchronized and not the callback. */
g_mutex_lock(dsObject->managerMutex);
switch (type) {
case SML_MANAGER_SESSION_FLUSH:
case SML_MANAGER_CONNECT_DONE:
smlTrace(TRACE_INTERNAL, "%s: ignored event %d ", __func__, type);
dsObject->internalState = SML_DATA_SYNC_STATE_CONNECTED;
break;
case SML_MANAGER_SESSION_ESTABLISHED:
smlTrace(TRACE_INTERNAL, "%s: session established", __func__);
dsObject->internalState = SML_DATA_SYNC_STATE_SESSION_READY;
smlDataSyncSendEvent(
dsObject, SML_DATA_SYNC_EVENT_CONNECT,
dsObject->eventUserdata, NULL);
break;
case SML_MANAGER_DISCONNECT_DONE:
smlTrace(TRACE_INTERNAL, "%s: connection with device has ended", __func__);
/* If the transport was never connected
* then it is useless to handle the disconnect
* event.
*/
if (dsObject->internalState < SML_DATA_SYNC_STATE_CONNECTED)
{
smlTrace(TRACE_INTERNAL,
"%s: ignored disconnect because never connected",
__func__);
break;
}
/* anchor caching is optional */
if (dsObject->setAnchorCallback)
{
o = dsObject->datastores;
for (; o; o = o->next) {
SmlDataSyncDatastore *datastore = o->data;
/* write new sync anchors */
char *anchor = g_strdup_printf(
"localanchor%s",
smlDsSessionGetLocation(datastore->session));
if (!dsObject->setAnchorCallback(
dsObject,
anchor, datastore->localNext,
dsObject->setAnchorUserdata,
&error))
goto error;
anchor = g_strdup_printf(
"remoteanchor%s",
smlDsSessionGetLocation(datastore->session));
if (!dsObject->setAnchorCallback(
dsObject,
anchor, datastore->remoteNext,
dsObject->setAnchorUserdata,
&error))
goto error;
}
}
dsObject->internalState = SML_DATA_SYNC_STATE_DISCONNECTED;
smlDataSyncSendEvent(
dsObject, SML_DATA_SYNC_EVENT_DISCONNECT,
dsObject->eventUserdata, NULL);
smlDataSyncSendEvent(
dsObject, SML_DATA_SYNC_EVENT_FINISHED,
dsObject->eventUserdata, NULL);
break;
case SML_MANAGER_TRANSPORT_ERROR:
smlTrace(TRACE_INTERNAL,
"There was an error in the transport: %s",
smlErrorPrint(&error));
if (SML_DATA_SYNC_STATE_CONNECTED <= dsObject->internalState &&
dsObject->internalState < SML_DATA_SYNC_STATE_DISCONNECTED) {
if (dsObject->internalState < SML_DATA_SYNC_STATE_DISCONNECT_IN_PROGRESS) {
dsObject->internalState = SML_DATA_SYNC_STATE_DISCONNECT_IN_PROGRESS;
SmlError *locerror = NULL;
SmlLink *link_ = smlManagerSessionGetLink(
dsObject->manager,
dsObject->session,
&locerror);
if (link_ || !locerror)
smlTransportDisconnect(
dsObject->tsp,
link_,
&locerror);
if (link_)
smlLinkDeref(link_);
/* error is already tracked.
* So locerror can be ignored.
*/
if (locerror)
smlErrorDeref(&locerror);
/* It is not a good idea to wait for the
* disconnect here. First this is an
* asynchronous software so it is always
* bad if the software blocks. Second it
* is dangerous to call smlManagerDispatch
* here because an error during these
* dispatch activities can lead to another
* error which overwrites the original
* error.
*
* Deadlock must be handled in another way.
* The SyncML protocol is usually already
* broken if this happens (TRANSPORT_ERROR).
*
* So yes, it is important to disconnect
* and no, it must not run dispatch.
*/
} else {
/* disconnect failed */
dsObject->internalState = SML_DATA_SYNC_STATE_DISCONNECTED;
}
}
goto error;
break;
case SML_MANAGER_SESSION_NEW:
smlTrace(TRACE_INTERNAL, "%s: Just received a new session with ID %s",
__func__, VA_STRING(smlSessionGetSessionID(session)));
if (dsObject->session) {
smlTrace(TRACE_INTERNAL,
"%s: WARNING: There was an old session %s in the environment.",
__func__, VA_STRING(smlSessionGetSessionID(dsObject->session)));
smlSessionUnref(dsObject->session);
dsObject->session = NULL;
}
smlSessionUseStringTable(session, dsObject->useStringTable);
smlSessionUseOnlyReplace(session, dsObject->onlyReplace);
smlSessionUseNumberOfChanges(session, dsObject->useNumberOfChanges);
smlTrace(TRACE_INTERNAL, "%s: maxObjSize %d",
__func__, dsObject->maxObjSize);
dsObject->session = session;
smlSessionRef(session);
/* authentication management for OMA DS clients*/
if (dsObject->dsType == SML_SESSION_TYPE_CLIENT &&
(dsObject->username || dsObject->password))
{
/* prepare credential */
SmlCred *cred = smlCredNewAuth(dsObject->authType,
dsObject->username, dsObject->password,
&error);
if (!cred)
goto error;
smlSessionRegisterCred(dsObject->session, cred);
smlTrace(TRACE_INTERNAL, "%s: credential initialized", __func__);
}
break;
case SML_MANAGER_SESSION_FINAL:
smlTrace(TRACE_INTERNAL, "%s: Session %s reported final",
__func__, VA_STRING(smlSessionGetSessionID(session)));
/* determine which package was received */
if (dsObject->dsType == SML_SESSION_TYPE_CLIENT)
{
/* only devinf receiving is not supported */
if (dsObject->actualPackage < SML_PACKAGE_1)
dsObject->actualPackage = SML_PACKAGE_1;
else
dsObject->actualPackage += 2;
} else { // SML_SESSION_TYPE_SERVER
/* only devinf receiving is not supported */
if (dsObject->actualPackage < SML_PACKAGE_2)
dsObject->actualPackage = SML_PACKAGE_2;
else
dsObject->actualPackage += 2;
}
smlTrace(TRACE_INTERNAL, "%s: package == %d", __func__, dsObject->actualPackage);
/* start callbacks etc. according to state */
switch(dsObject->actualPackage)
{
case SML_PACKAGE_1: /* SAN received by client */
/* This is the best position to check for
* the availability of the remote device
* information. If it is not present then
* the own device information is send and
* the remote ones is requested.
*/
if (!smlDataSyncManageDevInf(dsObject, TRUE, &error))
goto error;
if (!smlSessionFlush(dsObject->session, TRUE, &error))
goto error;
break;
case SML_PACKAGE_2: /* alerts received by server */
/* This is the best position to check for
* the availability of the remote device
* information. If it is not present then
* the own device information is send and
* the remote ones is requested.
*/
if (!smlDataSyncManageDevInf(dsObject, TRUE, &error))
goto error;
if (!smlSessionFlush(dsObject->session, TRUE, &error))
goto error;
smlDataSyncSendEvent(
dsObject, SML_DATA_SYNC_EVENT_GOT_ALL_ALERTS,
dsObject->eventUserdata, NULL);
break;
case SML_PACKAGE_3: /* alerts received by client */
smlDataSyncSendEvent(
dsObject, SML_DATA_SYNC_EVENT_GOT_ALL_ALERTS,
dsObject->eventUserdata, NULL);
break;
case SML_PACKAGE_4: /* syncs received by server */
smlDataSyncSendEvent(
dsObject, SML_DATA_SYNC_EVENT_GOT_ALL_CHANGES,
dsObject->eventUserdata, NULL);
break;
case SML_PACKAGE_5: /* syncs received by client */
if (!smlDataSyncSendMap(dsObject, &error))
goto error;
if (!smlSessionFlush(dsObject->session, TRUE, &error))
goto error;
smlDataSyncSendEvent(
dsObject, SML_DATA_SYNC_EVENT_GOT_ALL_CHANGES,
dsObject->eventUserdata, NULL);
break;
case SML_PACKAGE_6: /* map received by server */
if (!smlSessionFlush(dsObject->session, TRUE, &error))
goto error;
break;
case SML_PACKAGE_END: /* end received by client */
/* everything done */
/* auto disconnect by library */
break;
default:
smlErrorSet(&error, SML_ERROR_NOT_IMPLEMENTED,
"The package %d is actually not supported.",
dsObject->actualPackage);
goto error;
}
break;
case SML_MANAGER_SESSION_END:
smlTrace(TRACE_INTERNAL, "%s: Session %s has ended",
__func__, VA_STRING(smlSessionGetSessionID(session)));
SmlLink *link_ = smlManagerSessionGetLink(
dsObject->manager,
dsObject->session,
&error);
if (!link_ && error)
goto error;
/* OBEX is a stateful protocol and the client should
* init the disconnect. The problem is what happens
* when the client hangs?
*
* if (dsObject->tspType != SML_TRANSPORT_OBEX_SERVER &&
* !smlTransportDisconnect(dsObject->tsp, link, &error))
*/
if (!smlTransportDisconnect(dsObject->tsp, link_, &error))
{
if (link_)
smlLinkDeref(link_);
goto error;
}
if (link_)
smlLinkDeref(link_);
break;
case SML_MANAGER_SESSION_ERROR:
if (session)
smlTrace(TRACE_INTERNAL,
"There was an error in the session %s: %s",
VA_STRING(smlSessionGetSessionID(session)),
smlErrorPrint(&error));
else
smlTrace(TRACE_INTERNAL,
"There was a general error in the manager. %s",
smlErrorPrint(&error));
goto error;
break;
case SML_MANAGER_SESSION_WARNING:
g_warning("WARNING: %s\n", smlErrorPrint(&error));
break;
default:
g_warning("%s: Unknown event received: %d.", __func__, type);
break;
}
g_mutex_unlock(dsObject->managerMutex);
smlTrace(TRACE_EXIT, "%s", __func__);
return;
error:
g_mutex_unlock(dsObject->managerMutex);
smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(&error));
smlDataSyncSendEvent(
dsObject, SML_DATA_SYNC_EVENT_ERROR,
dsObject->eventUserdata, error);
}
/* *************************************** */
/* ***** DsSession Callbacks ***** */
/* *************************************** */
void smlDataSyncDatastoreConnectCallback(
SmlDsSession *dsession,
void *userdata)
{
smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, dsession, userdata);
smlAssert(dsession);
smlAssert(userdata);
SmlDataSyncDatastore *datastore = userdata;
SmlDataSyncObject *dsObject = datastore->dsObject;
/* The session is required here. So if the session is missing
* then the function has to block here. This is no real problem
* because the SESSION_EVENT_NEW must already be in the queue of
* the manager object.
*/
while (!dsObject->session) {
smlManagerDispatch(dsObject->manager);
}
/* set callbacks if the DsSession was not ready before */
if (!datastore->session || datastore->session != dsession)
{
smlTrace(TRACE_INTERNAL, "%s: should be an OMA DS server", __func__);
smlAssert(dsObject->funcDatastoreAlert);
datastore->session = dsession;
smlDsSessionGetAlert(datastore->session, dsObject->funcDatastoreAlert, datastore);
if (dsObject->changeCallback) {
smlDsSessionGetSync(datastore->session,
smlDataSyncSyncCallback, datastore);
smlDsSessionGetChanges(datastore->session,
smlDataSyncChangeCallback, datastore);
smlDsSessionGetMapping(datastore->session,
smlDataSyncMappingCallback, datastore);
}
smlDsSessionRef(dsession);
}
smlTrace(TRACE_EXIT, "%s", __func__);
return;
#if 0 /* UNUSED */
error:
smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(&error));
smlDataSyncSendEvent(
dsObject, SML_DATA_SYNC_EVENT_ERROR,
dsObject->eventUserdata, error);
#endif /* UNUSED */
}
/* *********************************** */
/* ***** Alert Callbacks ***** */
/* *********************************** */
void smlDataSyncAlertStatusCallback(
SmlSession *session,
SmlStatus *status,
void *userdata)
{
smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, status, userdata);
SmlDataSyncDatastore *datastore = userdata;
/* If we talk as an OMA DS client with server like an OCS
* then it can happen that this server denies the alert
* because of an internal problem.
* Example OCS: If there is an error inside of an SyncML session
* then you must wait a configured time before you
* can again sucessfully connect this server.
* Typically the server responds with error 503.
*/
unsigned int code = smlStatusGetCode(status);
if (code >= 300 && code != SML_ERROR_REQUIRE_REFRESH)
{
/* This is an error. */
SmlError *error = NULL;
smlErrorSet(&error, SML_ERROR_GENERIC,
"The alert response signals an error - %d.", code);
smlErrorRef(&error);
smlDataSyncSendEvent(
datastore->dsObject, SML_DATA_SYNC_EVENT_ERROR,
datastore->dsObject->eventUserdata, error);
smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(&error));
smlErrorDeref(&error);
} else {
smlTrace(TRACE_EXIT, "%s", __func__);
}
}
/* ********************************** */
/* ***** Sync Callbacks ***** */
/* ********************************** */
void smlDataSyncSyncCallback(
SmlDsSession *dsession,
unsigned int numchanges,
void *userdata)
{
smlTrace(TRACE_ENTRY, "%s(%p, %i, %p)", __func__, dsession, numchanges, userdata);
SmlDataSyncDatastore *datastore = userdata;
SmlError *error = NULL;
/* If the device information was not sent together with the
* alerts and it was not cached then the device information
* can be received together with the sync command(s).
* This can happen with OMA DS clients and servers.
*/
if (!smlDataSyncManageDevInf(datastore->dsObject, FALSE, &error))
goto error;
smlTrace(TRACE_EXIT, "%s", __func__);
return;
error:
smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(&error));
smlDataSyncSendEvent(
datastore->dsObject, SML_DATA_SYNC_EVENT_ERROR,
datastore->dsObject->eventUserdata, error);
}
void smlDataSyncSyncStatusCallback(
SmlSession *session,
SmlStatus *status,
void *userdata)
{
smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, session, status, userdata);
SmlDataSyncDatastore *datastore = userdata;
if (smlStatusGetClass(status) != SML_ERRORCLASS_SUCCESS)
{
// inform user
smlTrace(TRACE_INTERNAL, "%s: The synchronisation request failed.", __func__);
smlTrace(TRACE_INTERNAL, "%s: Location => %s", __func__, VA_STRING(datastore->dsObject->url));
smlTrace(TRACE_INTERNAL, "%s: Database => %s", __func__, VA_STRING(datastore->sourceUri));
smlTrace(TRACE_INTERNAL, "%s: Error => %d", __func__, smlStatusGetCode(status));
if (smlStatusGetCode(status) == SML_ERROR_SERVICE_UNAVAILABLE &&
(strstr(datastore->dsObject->url, "ocst") ||
strstr(datastore->dsObject->url, "ocas")))
{
/* this is a potential Oracle Collaboration Suite */
/* typical errorcode from OCS if there is something wrong */
smlTrace(TRACE_INTERNAL,
"%s: Oracle Collaboration Suite detected.",
__func__);
smlTrace(TRACE_INTERNAL,
"%s: Typical undefined error from OCS (503 - SyncML timeout error).",
__func__);
smlTrace(TRACE_INTERNAL,
"%s: Please wait 5 minutes before retry - default session timeout.",
__func__);
}
// stop session
// FIXME: this is not available in a clean way today
// FIXME: we need a session state
// FIXME: osync must be signalled
// FIXME: we need a mutex lock on database->env
// smlSessionEnd(database->env->session, NULL);
// printf(" Session finished.\n");
// smlManagerSessionRemove(database->env->manager, database->env->session);
// smlManagerStop(database->env->manager);
// smlManagerQuit(database->env->manager);
// printf(" Manager finished.\n");
SmlError *error = NULL;
smlErrorSet(&error, smlStatusGetCode(status),
"Sync failed with error %d.",
smlStatusGetCode(status));
smlErrorRef(&error);
smlDataSyncSendEvent(
datastore->dsObject, SML_DATA_SYNC_EVENT_ERROR,
datastore->dsObject->eventUserdata, error);
smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(&error));
smlErrorDeref(&error);
} else {
smlTrace(TRACE_EXIT, "%s", __func__);
}
}
/* ************************************ */
/* ***** Change Callbacks ***** */
/* ************************************ */
SmlBool smlDataSyncChangeCallback(
SmlDsSession *dsession,
SmlChangeType type,
const char *uid,
char *data,
unsigned int size,
const char *contenttype,
void *userdata,
SmlError **error)
{
smlTrace(TRACE_ENTRY, "%s(%p, %i, %s, %p, %i, %s, %p, %p)", __func__, dsession, type, VA_STRING(uid), data, size, VA_STRING(contenttype), userdata, error);
CHECK_ERROR_REF
SmlDataSyncDatastore *datastore = userdata;
smlAssert(type);
smlAssert(datastore);
smlAssert(datastore->dsObject);
smlAssert(datastore->dsObject->changeCallback);
/* some mobiles sends replace commands during slow-sync */
if (datastore->alertType == SML_ALERT_SLOW_SYNC &&
type == SML_CHANGE_REPLACE)
type = SML_CHANGE_ADD;
/* decode base64 data if necessary */
size_t appClassLength = ((size_t) index(datastore->contentType, '/')) -
((size_t) datastore->contentType);
if ( ( strstr(datastore->contentType, SML_CONTENT_TYPE_APPLICATION) == datastore->contentType &&
appClassLength == strlen(SML_CONTENT_TYPE_APPLICATION) ) ||
( strstr(datastore->contentType, SML_CONTENT_TYPE_AUDIO) == datastore->contentType &&
appClassLength == strlen(SML_CONTENT_TYPE_AUDIO) ) ||
( strstr(datastore->contentType, SML_CONTENT_TYPE_IMAGE) == datastore->contentType &&
appClassLength == strlen(SML_CONTENT_TYPE_IMAGE) ) ||
( strstr(datastore->contentType, SML_CONTENT_TYPE_MESSAGE) == datastore->contentType &&
appClassLength == strlen(SML_CONTENT_TYPE_MESSAGE) ) ||
( strstr(datastore->contentType, SML_CONTENT_TYPE_VIDEO) == datastore->contentType &&
appClassLength == strlen(SML_CONTENT_TYPE_AUDIO) ) )
{
/* binary data must be base64 encoded */
char *b64data = data;
size_t length = 0;
data = (char *) g_base64_decode(b64data, &length);
size = length;
smlSafeCFree(&b64data);
if (!data) {
smlErrorSet(error, SML_ERROR_GENERIC,
"The base 64 decoding of glib failed.");
goto error;
}
}
/* perform callback */
if (!datastore->dsObject->changeCallback(
datastore->dsObject, datastore->sourceUri,
type, uid, data, size,
datastore->dsObject->changeUserdata,
error))
goto error;
/* if this is a client then the callback should add a mapping */
smlTrace(TRACE_EXIT, "%s", __func__);
return TRUE;
error:
smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error));
return FALSE;
}
void smlDataSyncChangeStatusCallback(
SmlDsSession *dsession,
SmlStatus *status,
const char *newuid,
void *userdata)
{
smlTrace(TRACE_ENTRY, "%s(%p, %p, %s, %p)", __func__, dsession, status, VA_STRING(newuid), userdata);
SmlError *error = NULL;
smlAssert(userdata);
SmlDataSyncChange *change = userdata;
SmlDataSyncDatastore *datastore = change->datastore;
SmlDataSyncObject *dsObject = datastore->dsObject;
smlAssert(dsObject);
if (dsObject->changeStatusCallback &&
!dsObject->changeStatusCallback(
dsObject,
smlStatusGetCode(status),
newuid,
change->userdata, &error))
goto error;
smlTrace(TRACE_EXIT, "%s", __func__);
return;
error:
smlErrorRef(&error);
smlDataSyncSendEvent(
dsObject, SML_DATA_SYNC_EVENT_ERROR,
dsObject->eventUserdata, error);
smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(&error));
smlErrorDeref(&error);
}
void smlDataSyncMappingCallback(
SmlDsSession *dsession,
SmlLocation *orig,
SmlLocation *newuid,
void *userdata)
{
smlTrace(TRACE_ENTRY, "%s(%p, %s, %s, %p)", __func__, dsession, VA_STRING(smlLocationGetURI(orig)), VA_STRING(smlLocationGetURI(newuid)), userdata);
SmlError *error = NULL;
SmlDataSyncDatastore *datastore = userdata;
smlAssert(datastore);
smlAssert(datastore->dsObject);
smlAssert(datastore->dsObject->mappingCallback);
/* perform callback */
if (!datastore->dsObject->mappingCallback(
datastore->dsObject, datastore->sourceUri,
smlLocationGetURI(orig),
smlLocationGetURI(newuid),
datastore->dsObject->mappingUserdata,
&error))
goto error;
smlTrace(TRACE_EXIT, "%s", __func__);
return;
error:
smlErrorRef(&error);
smlDataSyncSendEvent(
datastore->dsObject, SML_DATA_SYNC_EVENT_ERROR,
datastore->dsObject->eventUserdata, error);
smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(&error));
smlErrorDeref(&error);
}
/* ********************************* */
/* ***** Map Callbacks ***** */
/* ********************************* */
void smlDataSyncMapStatusCallback(
SmlSession *session,
SmlStatus *status,
void *userdata)
{
smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, status, userdata);
if (smlStatusGetClass(status) != SML_ERRORCLASS_SUCCESS)
{
SmlDataSyncDatastore *datastore = userdata;
SmlError *error = NULL;
smlErrorSet(&error, smlStatusGetCode(status),
"Map of datastore %s was rejected with error code %d",
datastore->sourceUri, smlStatusGetCode(status));
smlDataSyncSendEvent(
datastore->dsObject, SML_DATA_SYNC_EVENT_ERROR,
datastore->dsObject->eventUserdata, error);
}
smlTrace(TRACE_EXIT, "%s", __func__);
}
/* ******************************************* */
/* ***** Authentication Callback ***** */
/* ******************************************* */
SmlBool smlDataSyncVerifyUserCallback(
SmlChal *chal,
SmlCred *cred,
const char *username,
void *userdata,
SmlError **error)
{
smlTrace(TRACE_ENTRY, "%s(%p, %p, %s, %p)", __func__, chal, cred, VA_STRING(username), userdata);
CHECK_ERROR_REF
SmlDataSyncObject *dsObject = userdata;
/* We have only one user and not a whole user database. */
smlTrace(TRACE_EXIT, "%s", __func__);
return smlAuthVerify(chal, cred, dsObject->username, dsObject->password, error);
}
smlDsSessionGetChanges
void smlDsSessionGetChanges(SmlDsSession *dsession, SmlDsSessionChangesCb chgCallback, void *userdata)
Gets a already received sync command.
Definition: sml_ds_server.c:1022
SmlDataSyncDatastore
This object represents an OMA DS datastore.
Definition: data_sync.h:93
SmlCred
Definition: sml_elements_internals.h:87
smlErrorPrint
const char * smlErrorPrint(SmlError **error)
Returns the message of the error.
Definition: sml_error.c:299
SmlDataSyncObject
This is the central synchronization object.
Definition: data_sync.h:110
smlSessionFlush
SmlBool smlSessionFlush(SmlSession *session, SmlBool final, SmlError **error)
Flushes a session.
Definition: sml_session.c:2010
SmlManager
Definition: sml_manager_internals.h:35
SmlStatus
Definition: sml_command_internals.h:94
SmlChal
Definition: sml_elements_internals.h:96
smlDsSessionGetAlert
void smlDsSessionGetAlert(SmlDsSession *dsession, SmlDsSessionAlertCb callback, void *userdata)
Gets a already received alert.
Definition: sml_ds_server.c:946
SmlSession
Definition: sml_session_internals.h:27
SmlDsSession
Definition: sml_ds_server_internals.h:45
SmlLink
Definition: sml_transport_internals.h:92
smlTrace
void smlTrace(SmlTraceType type, const char *message,...)
Used for tracing the application.
Definition: sml_support.c:120
SmlLocation
Definition: sml_elements_internals.h:40
smlErrorSet
void smlErrorSet(SmlError **error, SmlErrorType type, const char *format,...)
Sets the error.
Definition: sml_error.c:355
SmlDataSyncChange
This internal structure represents exactly one change.
Definition: data_sync.h:207
SmlError
Represent an error.
Definition: sml_error_internals.h:29