sml_devinf_obj.c
/*
* libsyncml - A syncml protocol implementation
* Copyright (C) 2005 Armin Bauer <armin.bauer@opensync.org>
* Copyright (C) 2007-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 <libsyncml/syncml.h>
#include "sml_devinf_obj.h"
#include <libsyncml/syncml_internals.h>
#include "sml_devinf_obj_internals.h"
#include <libsyncml/sml_session_internals.h>
#include <libsyncml/sml_elements_internals.h>
#include <libsyncml/sml_command_internals.h>
#include "libsyncml/sml_error_internals.h"
#ifdef WIN32
#include <windef.h>
#else
#include<sys/utsname.h>
#endif
/* Design notice
*
* There is only one SmlDevInfAgent per SmlManager
* because there is only one local device information.
* Therefore the agent must be able to manage one
* device information per session because every remote
* device can have different capabilities.
*/
/* functions to manage SmlDevInfAgentSession */
static SmlDevInfAgentSession* _new_session(
SmlDevInfAgent *agent,
SmlSession *session,
SmlError **error)
{
smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, agent, session, error);
CHECK_ERROR_REF
smlAssert(agent);
smlAssert(agent->sessions);
smlAssert(session);
SmlDevInfAgentSession *as = smlTryMalloc0(sizeof(SmlDevInfAgentSession), error);
if (!as)
goto error;
g_hash_table_insert(agent->sessions, session, as);
smlTrace(TRACE_EXIT, "%s - %p", __func__, as);
return as;
error:
smlSafeFree((gpointer *) &as);
smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error));
return NULL;
}
static SmlDevInfAgentSession* _get_session(
SmlDevInfAgent *agent,
SmlSession *session)
{
smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, agent, session);
smlAssert(agent);
smlAssert(agent->sessions);
smlAssert(session);
SmlDevInfAgentSession *as = g_hash_table_lookup(agent->sessions, session);
smlTrace(TRACE_EXIT, "%s - %p", __func__, as);
return as;
}
static void _free_session (gpointer data)
{
smlTrace(TRACE_ENTRY, "%s(%p)", __func__, data);
SmlDevInfAgentSession *as = data;
if (as->recvDevInf)
smlDevInfUnref(as->recvDevInf);
smlSafeFree((gpointer *) &as);
smlTrace(TRACE_EXIT, "%s", __func__);
}
/* functions to manage SmlDevInfAgent */
static void _get_devinf_reply(SmlSession *session, SmlStatus *status, void *userdata)
{
smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, status, userdata);
SmlError *error = NULL;
SmlDevInfAgent *agent = userdata;
if (smlStatusIsResult(status)) {
SmlCommand *result = smlStatusGetResult(status);
/* get cached session or add session to agent cache */
SmlDevInfAgentSession *as = _get_session(agent, session);
if (!as) {
as = _new_session(agent, session, &error);
if (!as)
goto error;
}
/* cache device information */
as->recvDevInf = smlDevInfFromResult(result, &error);
if (!as->recvDevInf)
goto error;
/* send answer */
SmlStatus *reply = smlCommandNewReply(result, SML_NO_ERROR, &error);
if (!reply)
goto error;
if (!smlSessionSendReply(session, reply, &error)) {
smlStatusUnref(reply);
goto error;
}
smlStatusUnref(reply);
}
smlTrace(TRACE_EXIT, "%s", __func__);
return;
error:
smlSessionDispatchEvent(session, SML_SESSION_EVENT_ERROR, NULL, NULL, NULL, error);
smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(&error));
smlErrorDeref(&error);
}
static void _devinf_reply(SmlSession *session, SmlStatus *status, void *userdata)
{
smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, status, userdata);
smlTrace(TRACE_EXIT, "%s", __func__);
}
static SmlBool _send_devinf(SmlDevInfAgent *agent, SmlSession *session, SmlCommand *get, SmlError **error)
{
smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, agent, session, get, error);
CHECK_ERROR_REF
SmlCommand *result = NULL;
SmlCommand *cmd = NULL;
/* It is a good idea to perform some sanity checks on the
* configuration before the device information is sent.
*/
/* If this is SyncML 1.1 or higher then large object support is
* required for OMA DS servers.
*/
if (smlSessionGetVersion(session) >= SML_VERSION_11 &&
session->sessionType == SML_SESSION_TYPE_SERVER &&
!smlDevInfSupportsLargeObjs(agent->devinf))
{
smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION,
"OMA DS Server must support large object handling if SyncML 1.1 or higher is used.");
goto error;
}
/* If large object support is enabled then MaxMsgSize and
* MaxObjSize must be set.
*/
if (smlDevInfSupportsLargeObjs(agent->devinf))
{
if (smlSessionGetLocalMaxMsgSize(session) < 1)
{
smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION,
"If large object support is enabled then MaxMsgSize must be set.");
goto error;
}
if (smlSessionGetLocalMaxObjSize(session) < 1)
{
smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION,
"If large object support is enabled then MaxObjSize must be set.");
goto error;
}
}
/* get cached session or add session to agent cache */
SmlDevInfAgentSession *as = _get_session(agent, session);
if (!as) {
as = _new_session(agent, session, error);
if (!as)
goto error;
}
/* Sanity checks complete. Sending device information ... */
if (!as->devinfSent) {
if (get) {
if (smlSessionGetVersion(session) == SML_VERSION_10)
result = smlDevInfNewResult(get, agent->devinf, SML_DEVINF_VERSION_10, error);
else if (smlSessionGetVersion(session) == SML_VERSION_12)
result = smlDevInfNewResult(get, agent->devinf, SML_DEVINF_VERSION_12, error);
else
result = smlDevInfNewResult(get, agent->devinf, SML_DEVINF_VERSION_11, error);
if (!result)
goto error;
if (!smlSessionSendCommand(session, result, NULL, _devinf_reply, agent, error)) {
smlCommandUnref(result);
goto error;
}
smlCommandUnref(result);
SmlStatus *reply = smlCommandNewReply(get, SML_NO_ERROR, error);
if (!reply)
goto error;
if (!smlSessionSendReply(session, reply, error)) {
smlStatusUnref(reply);
goto error;
}
smlStatusUnref(reply);
} else {
if (smlSessionGetVersion(session) == SML_VERSION_10)
cmd = smlDevInfNewPut(agent->devinf, SML_DEVINF_VERSION_10, error);
else if (smlSessionGetVersion(session) == SML_VERSION_12)
cmd = smlDevInfNewPut(agent->devinf, SML_DEVINF_VERSION_12, error);
else
cmd = smlDevInfNewPut(agent->devinf, SML_DEVINF_VERSION_11, error);
if (!cmd)
goto error;
if (!smlSessionSendCommand(session, cmd, NULL, _devinf_reply, agent, error)) {
smlCommandUnref(cmd);
goto error;
}
smlCommandUnref(cmd);
}
as->devinfSent = TRUE;
} else {
smlTrace(TRACE_INTERNAL, "%s: Already sent the devinf!", __func__);
if (get) {
/* We return a generic error if we dont want to send the devinf to a get
* request. Hope that all devices like this */
SmlStatus *reply = smlCommandNewReply(get, SML_ERROR_GENERIC, error);
if (!reply)
goto error;
if (!smlSessionSendReply(session, reply, error)) {
smlStatusUnref(reply);
goto error;
}
smlStatusUnref(reply);
} else {
/* This means that a software component tries to
* send the device information but it was already
* sent. This can happen if the local library
* user is missing the remote device information
* and wants to send the get request together
* with its own device information. Nevertheless
* this is an error - but it can be ignored.
*/
smlTrace(TRACE_INTERNAL,
"%s: libsyncml does not send local device information twice.",
__func__);
}
}
smlTrace(TRACE_EXIT, "%s", __func__);
return TRUE;
error:
smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
return FALSE;
}
static void _recv_devinf(SmlSession *session, SmlCommand *cmd, void *userdata)
{
smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, cmd, userdata);
SmlDevInfAgent *agent = userdata;
SmlError *error = NULL;
char *data = NULL;
unsigned int size = 0;
if (!smlItemGetData(cmd->private.access.item, &data, &size, &error))
goto error;
SmlDevInfAgentSession *as = _get_session(agent, session);
if (!as) {
as = _new_session(agent, session, &error);
if (!as)
goto error;
}
as->recvDevInf = smlDevInfParse(data, size, &error);
if (!as->recvDevInf)
goto error;
SmlStatus *reply = smlCommandNewReply(cmd, SML_NO_ERROR, &error);
if (!reply)
goto error;
if (!smlSessionSendReply(session, reply, &error)) {
smlStatusUnref(reply);
goto error;
}
smlStatusUnref(reply);
smlTrace(TRACE_EXIT, "%s", __func__);
return;
error:
smlSessionDispatchEvent(session, SML_SESSION_EVENT_ERROR, NULL, NULL, NULL, error);
smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(&error));
smlErrorDeref(&error);
}
static void _request_devinf(SmlSession *session, SmlCommand *cmd, void *userdata)
{
smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, cmd, userdata);
SmlDevInfAgent *agent = userdata;
SmlError *error = NULL;
if (!_send_devinf(agent, session, cmd, &error))
goto error;
smlTrace(TRACE_EXIT, "%s", __func__);
return;
error:
smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(&error));
}
SmlDevInfAgent *smlDevInfAgentNew(SmlDevInf *devinf, SmlError **error)
{
smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, devinf, error);
CHECK_ERROR_REF
smlAssert(devinf);
SmlDevInfAgent *agent = smlTryMalloc0(sizeof(SmlDevInfAgent), error);
if (!agent)
goto error;
agent->devinf = devinf;
agent->sessions = g_hash_table_new_full(NULL, NULL, NULL, _free_session);
if (!agent->sessions) {
smlErrorSet(error, SML_ERROR_INTERNAL_NO_MEMORY, "Cannot create new hash table.");
goto error;
}
if (!smlDevInfGetManufacturer(devinf))
smlDevInfSetManufacturer(devinf, "OpenSync");
if (!smlDevInfGetModel(devinf))
smlDevInfSetModel(devinf, "libsyncml");
if (!smlDevInfGetOEM(devinf))
{
#ifdef WIN32
smlDevInfSetOEM(devinf, "Windows");
DWORD dwVersion = GetVersion();
DWORD dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
DWORD dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion)));
DWORD dwBuild = 0;
if (dwVersion < 0x80000000) dwBuild = (DWORD)(HIWORD(dwVersion));
char szVersion[1024];
sprintf(szVersion, "%d.%d (%d)", dwMajorVersion, dwMinorVersion, dwBuild);
smlDevInfSetFirmwareVersion(devinf, szVersion);
#else
struct utsname *buf = malloc(sizeof(struct utsname));
if (uname(buf) == 0)
{
smlDevInfSetOEM(devinf, buf->sysname);
smlDevInfSetFirmwareVersion(devinf, buf->release);
}
smlSafeFree((gpointer *)&buf);
#endif
}
if (!smlDevInfGetSoftwareVersion(devinf))
smlDevInfSetSoftwareVersion(devinf, VERSION);
smlTrace(TRACE_EXIT, "%s: %p", __func__, agent);
return agent;
error:
if (agent)
smlSafeFree((gpointer *) &agent);
smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
return NULL;
}
void smlDevInfAgentFree(SmlDevInfAgent *agent)
{
smlTrace(TRACE_ENTRY, "%s(%p)", __func__, agent);
smlAssert(agent);
if (agent->devinf)
smlDevInfUnref(agent->devinf);
g_hash_table_destroy(agent->sessions);
smlSafeFree((gpointer *)&agent);
smlTrace(TRACE_EXIT, "%s", __func__);
}
/* FIXME: DEPRECATED */
void smlDevInfAgentSetDevInf(SmlDevInfAgent *agent, SmlDevInf *devinf)
{
smlTrace(TRACE_ERROR, "%s(%p, %p)", __func__, agent, devinf);
smlAssertMsg(NULL, "This function is a design bug.");
}
/* FIXME: DEPRECATED */
SmlDevInf *smlDevInfAgentGetDevInf(SmlDevInfAgent *agent)
{
smlTrace(TRACE_ERROR, "%s(%p, %p)", __func__, agent);
smlAssertMsg(NULL, "This function is a design bug.");
return NULL;
}
/* Set the devinf of the remote peer. */
SmlBool smlDevInfAgentSetSessionDevInf(
SmlDevInfAgent *agent,
SmlSession *session,
SmlDevInf *devinf,
SmlError **error)
{
smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, agent, session, devinf, error);
CHECK_ERROR_REF
smlAssert(agent);
smlAssert(agent->sessions);
smlAssert(session);
smlAssert(devinf);
SmlDevInfAgentSession *as = _get_session(agent, session);
if (!as) {
as = _new_session(agent, session, error);
if (!as)
goto error;
}
as->recvDevInf = devinf;
smlTrace(TRACE_EXIT, "%s", __func__);
return TRUE;
error:
smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error));
return FALSE;
}
/* Get the devinf that was sent in the session. Returns FALSE if no devinf was received yet. */
SmlDevInf *smlDevInfAgentGetSessionDevInf(SmlDevInfAgent *agent, SmlSession *session)
{
smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, agent, session);
smlAssert(agent);
smlAssert(agent->sessions);
smlAssert(session);
SmlDevInfAgentSession *as = _get_session(agent, session);
if (!as)
{
smlTrace(TRACE_EXIT, "%s - the session is not cached until now", __func__);
return NULL;
}
smlTrace(TRACE_EXIT, "%s - %p", __func__, as->recvDevInf);
return as->recvDevInf;
}
SmlBool smlDevInfAgentSendDevInf(SmlDevInfAgent *agent, SmlSession *session, SmlError **error)
{
smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, agent, session, error);
CHECK_ERROR_REF
smlAssert(agent);
if (!_send_devinf(agent, session, NULL, error))
goto error;
smlTrace(TRACE_EXIT, "%s", __func__);
return TRUE;
error:
smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
return FALSE;
}
SmlBool smlDevInfAgentRequestDevInf(SmlDevInfAgent *agent, SmlSession *session, SmlError **error)
{
smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, agent, session, error);
CHECK_ERROR_REF
smlAssert(agent);
SmlCommand *get = NULL;
SmlDevInfAgentSession *as = _get_session(agent, session);
if (!as) {
as = _new_session(agent, session, error);
if (!as)
goto error;
}
if (as->recvDevInf) {
smlTrace(TRACE_EXIT, "%s: Already have the devinf", __func__);
return TRUE;
}
if (!as->devinfRequested)
{
if (smlSessionGetVersion(session) == SML_VERSION_10)
get = smlDevInfNewGet(SML_DEVINF_VERSION_10, error);
else if (smlSessionGetVersion(session) == SML_VERSION_12)
get = smlDevInfNewGet(SML_DEVINF_VERSION_12, error);
else
get = smlDevInfNewGet(SML_DEVINF_VERSION_11, error);
if (!get)
goto error;
if (!smlSessionSendCommand(session, get, NULL, _get_devinf_reply, agent, error)) {
smlCommandUnref(get);
goto error;
}
smlCommandUnref(get);
as->devinfRequested = TRUE;
} else {
smlTrace(TRACE_INTERNAL, "%s: Already requested the devinf!", __func__);
}
smlTrace(TRACE_EXIT, "%s", __func__);
return TRUE;
error:
smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
return FALSE;
}
SmlBool smlDevInfAgentRegisterSession(SmlDevInfAgent *agent, SmlManager *manager, SmlSession *session, SmlError **error)
{
smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, agent, manager, session, error);
CHECK_ERROR_REF
smlAssert(agent);
smlAssert(manager);
SmlLocation *devinf12 = smlLocationNew("./devinf12", NULL, error);
SmlLocation *devinf11 = smlLocationNew("./devinf11", NULL, error);
SmlLocation *devinf10 = smlLocationNew("./devinf10", NULL, error);
if (!devinf12 || !devinf11 || !devinf10)
goto error;
/* PUT callbacks
*
* This command is used to actively send device information without
* being asked for. Usually a client do this if it is the first
* connection with the server or the client has no problems with
* its bandwith.
*
* Sometimes a server is missing the client's device information.
* In this situation the server can send a PUT and a GET to force
* the client to send the device information. This can happen if
* the client know that server should have its device information
* because of an earlier synchronization but the server does not
* have the device information. Sometimes server databases (incl.
* the device information database) are lost or it is simply a
* new server but with the old server address (IP) or name (DNS).
*
* Please note that a client can ignore a PUT from a server.
* Nevertheless it is recommended that a client does not ignore
* the device information of a server.
*/
smlTrace(TRACE_INTERNAL, "%s: register callbacks for PUT command", __func__);
if (!smlManagerObjectRegister(
manager, SML_COMMAND_TYPE_PUT, session,
NULL, devinf10, NULL, _recv_devinf, NULL, agent,
error))
goto error_free_loc;
if (!smlManagerObjectRegister(
manager, SML_COMMAND_TYPE_PUT, session,
NULL, devinf11, NULL, _recv_devinf, NULL, agent,
error))
goto error_free_loc;
if (!smlManagerObjectRegister(
manager, SML_COMMAND_TYPE_PUT, session,
NULL, devinf12, NULL, _recv_devinf, NULL, agent,
error))
goto error_free_loc;
/* GET callbacks
*
* This command is used to request the device information of a
* remote peer. Usually the client do this if it is the first
* connection with this server or the client does not remember
* the server's device information. The most mobiles only do
* this for the first successful connection. Data costs usually
* high amounts of money in the mobile world and the bandwith is
* small in the mobile world.
*
* Nevertheless if a mobile does not perform the PUT command and
* the server does not know the device information of the client
* then the server can send a GET command and the client has to
* react on it. Please see above why this can happen.
*
* Please note that client and server must be able to handle the
* GET command. A RESULTS command must be send with the local
* device information.
*/
smlTrace(TRACE_INTERNAL, "%s: register callbacks for GET command", __func__);
if (!smlManagerObjectRegister(
manager, SML_COMMAND_TYPE_GET, session,
devinf10, NULL, NULL, _request_devinf, NULL, agent,
error))
goto error_free_loc;
if (!smlManagerObjectRegister(
manager, SML_COMMAND_TYPE_GET, session,
devinf11, NULL, NULL, _request_devinf, NULL, agent,
error))
goto error_free_loc;
if (!smlManagerObjectRegister(
manager, SML_COMMAND_TYPE_GET, session,
devinf12, NULL, NULL, _request_devinf, NULL, agent,
error))
goto error_free_loc;
/* RESULTS callbacks
*
* This command is used to send the device information which
* was requested with a GET command. This command can be send by
* server and clients. Please see above when this happens.
*
* A server must be able to handle and interpret a RESULTS
* command from a client. Especially this is required because a
* server must explicitly request such a command with a previous
* GET command.
*
* Please note that a client can ignore a RESULTS from a server.
* Nevertheless it is recommended that a client does not ignore
* the device information of a server.
*/
smlTrace(TRACE_INTERNAL, "%s: register callbacks for RESULTS command", __func__);
if (!smlManagerObjectRegister(
manager, SML_COMMAND_TYPE_RESULTS, session,
devinf10, NULL, NULL, _recv_devinf, NULL, agent,
error))
goto error_free_loc;
if (!smlManagerObjectRegister(
manager, SML_COMMAND_TYPE_RESULTS, session,
devinf11, NULL, NULL, _recv_devinf, NULL, agent,
error))
goto error_free_loc;
if (!smlManagerObjectRegister(
manager, SML_COMMAND_TYPE_RESULTS, session,
devinf12, NULL, NULL, _recv_devinf, NULL, agent,
error))
goto error_free_loc;
smlLocationUnref(devinf10);
smlLocationUnref(devinf11);
smlLocationUnref(devinf12);
smlTrace(TRACE_EXIT, "%s", __func__);
return TRUE;
error_free_loc:
if (devinf10)
smlLocationUnref(devinf10);
if (devinf11)
smlLocationUnref(devinf11);
if (devinf12)
smlLocationUnref(devinf12);
error:
smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
return FALSE;
}
SmlBool smlDevInfAgentRegister(SmlDevInfAgent *agent, SmlManager *manager, SmlError **error)
{
smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, agent, manager, error);
CHECK_ERROR_REF
SmlBool retval = smlDevInfAgentRegisterSession(agent, manager, NULL, error);
if (!retval)
goto error;
smlTrace(TRACE_EXIT, "%s", __func__);
return TRUE;
error:
smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
return FALSE;
}
SmlDevInfAgent
Definition: sml_devinf_obj_internals.h:41
smlDevInfAgentSendDevInf
SmlBool smlDevInfAgentSendDevInf(SmlDevInfAgent *agent, SmlSession *session, SmlError **error)
Definition: sml_devinf_obj.c:494
smlSessionSendReply
SmlBool smlSessionSendReply(SmlSession *session, SmlStatus *status, SmlError **error)
Sends a reply to a command.
Definition: sml_session.c:2536
smlErrorPrint
const char * smlErrorPrint(SmlError **error)
Returns the message of the error.
Definition: sml_error.c:299
SmlManager
Definition: sml_manager_internals.h:35
SmlStatus
Definition: sml_command_internals.h:94
SmlSession
Definition: sml_session_internals.h:27
SmlCommand
Definition: sml_command_internals.h:73
smlSessionSendCommand
SmlBool smlSessionSendCommand(SmlSession *session, SmlCommand *cmd, SmlCommand *parent, SmlStatusReplyCb callback, void *userdata, SmlError **error)
Sends a command with a parent.
Definition: sml_session.c:2422
smlItemGetData
SmlBool smlItemGetData(SmlItem *item, char **data, unsigned int *size, SmlError **error)
Definition: sml_elements.c:495
smlTrace
void smlTrace(SmlTraceType type, const char *message,...)
Used for tracing the application.
Definition: sml_support.c:120
smlDevInfAgentRequestDevInf
SmlBool smlDevInfAgentRequestDevInf(SmlDevInfAgent *agent, SmlSession *session, SmlError **error)
Definition: sml_devinf_obj.c:512
SmlDevInf
Definition: sml_devinf_internals.h:33
SmlLocation
Definition: sml_elements_internals.h:40
smlManagerObjectRegister
SmlBool smlManagerObjectRegister(SmlManager *manager, SmlCommandType type, SmlSession *session, SmlLocation *location, SmlLocation *source, const char *contentType, SmlCommandCb callback, SmlCommandCb childCallback, void *userdata, SmlError **error)
Register an object with a session.
Definition: sml_manager.c:926
smlTryMalloc0
void * smlTryMalloc0(long n_bytes, SmlError **error)
Safely mallocs.
Definition: sml_support.c:335
smlErrorSet
void smlErrorSet(SmlError **error, SmlErrorType type, const char *format,...)
Sets the error.
Definition: sml_error.c:355
SmlDevInfAgentSession
Definition: sml_devinf_obj_internals.h:32
SmlError
Represent an error.
Definition: sml_error_internals.h:29