libsyncml  0.5.4
sml_devinf_obj.c
1 /*
2  * libsyncml - A syncml protocol implementation
3  * Copyright (C) 2005 Armin Bauer <armin.bauer@opensync.org>
4  * Copyright (C) 2007-2009 Michael Bell <michael.bell@opensync.org>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  */
21 
22 #include <libsyncml/syncml.h>
23 #include "sml_devinf_obj.h"
24 
25 #include <libsyncml/syncml_internals.h>
26 #include "sml_devinf_obj_internals.h"
27 #include <libsyncml/sml_session_internals.h>
28 #include <libsyncml/sml_elements_internals.h>
29 #include <libsyncml/sml_command_internals.h>
30 #include "libsyncml/sml_error_internals.h"
31 
32 #ifdef WIN32
33 #include <windef.h>
34 #else
35 #include<sys/utsname.h>
36 #endif
37 
38 /* Design notice
39  *
40  * There is only one SmlDevInfAgent per SmlManager
41  * because there is only one local device information.
42  * Therefore the agent must be able to manage one
43  * device information per session because every remote
44  * device can have different capabilities.
45  */
46 
47 /* functions to manage SmlDevInfAgentSession */
48 
49 static SmlDevInfAgentSession* _new_session(
50  SmlDevInfAgent *agent,
51  SmlSession *session,
52  SmlError **error)
53 {
54  smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, agent, session, error);
55 
56  CHECK_ERROR_REF
57  smlAssert(agent);
58  smlAssert(agent->sessions);
59  smlAssert(session);
60 
62  if (!as)
63  goto error;
64 
65  g_hash_table_insert(agent->sessions, session, as);
66 
67  smlTrace(TRACE_EXIT, "%s - %p", __func__, as);
68  return as;
69 error:
70  smlSafeFree((gpointer *) &as);
71  smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error));
72  return NULL;
73 }
74 
75 static SmlDevInfAgentSession* _get_session(
76  SmlDevInfAgent *agent,
77  SmlSession *session)
78 {
79  smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, agent, session);
80 
81  smlAssert(agent);
82  smlAssert(agent->sessions);
83  smlAssert(session);
84 
85  SmlDevInfAgentSession *as = g_hash_table_lookup(agent->sessions, session);
86  smlTrace(TRACE_EXIT, "%s - %p", __func__, as);
87  return as;
88 }
89 
90 static void _free_session (gpointer data)
91 {
92  smlTrace(TRACE_ENTRY, "%s(%p)", __func__, data);
93 
94  SmlDevInfAgentSession *as = data;
95  if (as->recvDevInf)
96  smlDevInfUnref(as->recvDevInf);
97  smlSafeFree((gpointer *) &as);
98 
99  smlTrace(TRACE_EXIT, "%s", __func__);
100 }
101 
102 /* functions to manage SmlDevInfAgent */
103 
104 static void _get_devinf_reply(SmlSession *session, SmlStatus *status, void *userdata)
105 {
106  smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, status, userdata);
107  SmlError *error = NULL;
108  SmlDevInfAgent *agent = userdata;
109 
110  if (smlStatusIsResult(status)) {
111  SmlCommand *result = smlStatusGetResult(status);
112 
113  /* get cached session or add session to agent cache */
114 
115  SmlDevInfAgentSession *as = _get_session(agent, session);
116  if (!as) {
117  as = _new_session(agent, session, &error);
118  if (!as)
119  goto error;
120  }
121 
122  /* cache device information */
123 
124  as->recvDevInf = smlDevInfFromResult(result, &error);
125  if (!as->recvDevInf)
126  goto error;
127 
128  /* send answer */
129 
130  SmlStatus *reply = smlCommandNewReply(result, SML_NO_ERROR, &error);
131  if (!reply)
132  goto error;
133 
134  if (!smlSessionSendReply(session, reply, &error)) {
135  smlStatusUnref(reply);
136  goto error;
137  }
138 
139  smlStatusUnref(reply);
140  }
141 
142  smlTrace(TRACE_EXIT, "%s", __func__);
143  return;
144 
145 error:
146  smlSessionDispatchEvent(session, SML_SESSION_EVENT_ERROR, NULL, NULL, NULL, error);
147  smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(&error));
148  smlErrorDeref(&error);
149 }
150 
151 static void _devinf_reply(SmlSession *session, SmlStatus *status, void *userdata)
152 {
153  smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, status, userdata);
154 
155  smlTrace(TRACE_EXIT, "%s", __func__);
156 }
157 
158 static SmlBool _send_devinf(SmlDevInfAgent *agent, SmlSession *session, SmlCommand *get, SmlError **error)
159 {
160  smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, agent, session, get, error);
161  CHECK_ERROR_REF
162  SmlCommand *result = NULL;
163  SmlCommand *cmd = NULL;
164 
165  /* It is a good idea to perform some sanity checks on the
166  * configuration before the device information is sent.
167  */
168 
169  /* If this is SyncML 1.1 or higher then large object support is
170  * required for OMA DS servers.
171  */
172  if (smlSessionGetVersion(session) >= SML_VERSION_11 &&
173  session->sessionType == SML_SESSION_TYPE_SERVER &&
174  !smlDevInfSupportsLargeObjs(agent->devinf))
175  {
176  smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION,
177  "OMA DS Server must support large object handling if SyncML 1.1 or higher is used.");
178  goto error;
179  }
180 
181  /* If large object support is enabled then MaxMsgSize and
182  * MaxObjSize must be set.
183  */
184  if (smlDevInfSupportsLargeObjs(agent->devinf))
185  {
186  if (smlSessionGetLocalMaxMsgSize(session) < 1)
187  {
188  smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION,
189  "If large object support is enabled then MaxMsgSize must be set.");
190  goto error;
191  }
192  if (smlSessionGetLocalMaxObjSize(session) < 1)
193  {
194  smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION,
195  "If large object support is enabled then MaxObjSize must be set.");
196  goto error;
197  }
198  }
199 
200  /* get cached session or add session to agent cache */
201 
202  SmlDevInfAgentSession *as = _get_session(agent, session);
203  if (!as) {
204  as = _new_session(agent, session, error);
205  if (!as)
206  goto error;
207  }
208 
209  /* Sanity checks complete. Sending device information ... */
210 
211  if (!as->devinfSent) {
212  if (get) {
213  if (smlSessionGetVersion(session) == SML_VERSION_10)
214  result = smlDevInfNewResult(get, agent->devinf, SML_DEVINF_VERSION_10, error);
215  else if (smlSessionGetVersion(session) == SML_VERSION_12)
216  result = smlDevInfNewResult(get, agent->devinf, SML_DEVINF_VERSION_12, error);
217  else
218  result = smlDevInfNewResult(get, agent->devinf, SML_DEVINF_VERSION_11, error);
219 
220  if (!result)
221  goto error;
222 
223  if (!smlSessionSendCommand(session, result, NULL, _devinf_reply, agent, error)) {
224  smlCommandUnref(result);
225  goto error;
226  }
227 
228  smlCommandUnref(result);
229 
230  SmlStatus *reply = smlCommandNewReply(get, SML_NO_ERROR, error);
231  if (!reply)
232  goto error;
233 
234  if (!smlSessionSendReply(session, reply, error)) {
235  smlStatusUnref(reply);
236  goto error;
237  }
238 
239  smlStatusUnref(reply);
240  } else {
241  if (smlSessionGetVersion(session) == SML_VERSION_10)
242  cmd = smlDevInfNewPut(agent->devinf, SML_DEVINF_VERSION_10, error);
243  else if (smlSessionGetVersion(session) == SML_VERSION_12)
244  cmd = smlDevInfNewPut(agent->devinf, SML_DEVINF_VERSION_12, error);
245  else
246  cmd = smlDevInfNewPut(agent->devinf, SML_DEVINF_VERSION_11, error);
247 
248  if (!cmd)
249  goto error;
250 
251  if (!smlSessionSendCommand(session, cmd, NULL, _devinf_reply, agent, error)) {
252  smlCommandUnref(cmd);
253  goto error;
254  }
255 
256  smlCommandUnref(cmd);
257  }
258  as->devinfSent = TRUE;
259  } else {
260  smlTrace(TRACE_INTERNAL, "%s: Already sent the devinf!", __func__);
261 
262  if (get) {
263  /* We return a generic error if we dont want to send the devinf to a get
264  * request. Hope that all devices like this */
265  SmlStatus *reply = smlCommandNewReply(get, SML_ERROR_GENERIC, error);
266  if (!reply)
267  goto error;
268 
269  if (!smlSessionSendReply(session, reply, error)) {
270  smlStatusUnref(reply);
271  goto error;
272  }
273 
274  smlStatusUnref(reply);
275  } else {
276  /* This means that a software component tries to
277  * send the device information but it was already
278  * sent. This can happen if the local library
279  * user is missing the remote device information
280  * and wants to send the get request together
281  * with its own device information. Nevertheless
282  * this is an error - but it can be ignored.
283  */
284  smlTrace(TRACE_INTERNAL,
285  "%s: libsyncml does not send local device information twice.",
286  __func__);
287  }
288  }
289 
290  smlTrace(TRACE_EXIT, "%s", __func__);
291  return TRUE;
292 
293 error:
294  smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
295  return FALSE;
296 }
297 
298 static void _recv_devinf(SmlSession *session, SmlCommand *cmd, void *userdata)
299 {
300  smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, cmd, userdata);
301  SmlDevInfAgent *agent = userdata;
302  SmlError *error = NULL;
303  char *data = NULL;
304  unsigned int size = 0;
305 
306  if (!smlItemGetData(cmd->private.access.item, &data, &size, &error))
307  goto error;
308 
309  SmlDevInfAgentSession *as = _get_session(agent, session);
310  if (!as) {
311  as = _new_session(agent, session, &error);
312  if (!as)
313  goto error;
314  }
315 
316  as->recvDevInf = smlDevInfParse(data, size, &error);
317  if (!as->recvDevInf)
318  goto error;
319 
320  SmlStatus *reply = smlCommandNewReply(cmd, SML_NO_ERROR, &error);
321  if (!reply)
322  goto error;
323 
324  if (!smlSessionSendReply(session, reply, &error)) {
325  smlStatusUnref(reply);
326  goto error;
327  }
328 
329  smlStatusUnref(reply);
330 
331  smlTrace(TRACE_EXIT, "%s", __func__);
332  return;
333 
334 error:
335  smlSessionDispatchEvent(session, SML_SESSION_EVENT_ERROR, NULL, NULL, NULL, error);
336  smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(&error));
337  smlErrorDeref(&error);
338 }
339 
340 static void _request_devinf(SmlSession *session, SmlCommand *cmd, void *userdata)
341 {
342  smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, session, cmd, userdata);
343  SmlDevInfAgent *agent = userdata;
344  SmlError *error = NULL;
345 
346  if (!_send_devinf(agent, session, cmd, &error))
347  goto error;
348 
349  smlTrace(TRACE_EXIT, "%s", __func__);
350  return;
351 
352 error:
353  smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(&error));
354 }
355 
356 SmlDevInfAgent *smlDevInfAgentNew(SmlDevInf *devinf, SmlError **error)
357 {
358  smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, devinf, error);
359  CHECK_ERROR_REF
360  smlAssert(devinf);
361 
362  SmlDevInfAgent *agent = smlTryMalloc0(sizeof(SmlDevInfAgent), error);
363  if (!agent)
364  goto error;
365 
366  agent->devinf = devinf;
367  agent->sessions = g_hash_table_new_full(NULL, NULL, NULL, _free_session);
368  if (!agent->sessions) {
369  smlErrorSet(error, SML_ERROR_INTERNAL_NO_MEMORY, "Cannot create new hash table.");
370  goto error;
371  }
372 
373  if (!smlDevInfGetManufacturer(devinf))
374  smlDevInfSetManufacturer(devinf, "OpenSync");
375  if (!smlDevInfGetModel(devinf))
376  smlDevInfSetModel(devinf, "libsyncml");
377  if (!smlDevInfGetOEM(devinf))
378  {
379 #ifdef WIN32
380  smlDevInfSetOEM(devinf, "Windows");
381  DWORD dwVersion = GetVersion();
382  DWORD dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
383  DWORD dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion)));
384  DWORD dwBuild = 0;
385  if (dwVersion < 0x80000000) dwBuild = (DWORD)(HIWORD(dwVersion));
386 
387  char szVersion[1024];
388  sprintf(szVersion, "%d.%d (%d)", dwMajorVersion, dwMinorVersion, dwBuild);
389  smlDevInfSetFirmwareVersion(devinf, szVersion);
390 #else
391  struct utsname *buf = malloc(sizeof(struct utsname));
392  if (uname(buf) == 0)
393  {
394  smlDevInfSetOEM(devinf, buf->sysname);
395  smlDevInfSetFirmwareVersion(devinf, buf->release);
396  }
397  smlSafeFree((gpointer *)&buf);
398 #endif
399  }
400  if (!smlDevInfGetSoftwareVersion(devinf))
401  smlDevInfSetSoftwareVersion(devinf, VERSION);
402 
403  smlTrace(TRACE_EXIT, "%s: %p", __func__, agent);
404  return agent;
405 
406 error:
407  if (agent)
408  smlSafeFree((gpointer *) &agent);
409  smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
410  return NULL;
411 }
412 
413 
414 void smlDevInfAgentFree(SmlDevInfAgent *agent)
415 {
416  smlTrace(TRACE_ENTRY, "%s(%p)", __func__, agent);
417  smlAssert(agent);
418 
419  if (agent->devinf)
420  smlDevInfUnref(agent->devinf);
421  g_hash_table_destroy(agent->sessions);
422  smlSafeFree((gpointer *)&agent);
423 
424  smlTrace(TRACE_EXIT, "%s", __func__);
425 }
426 
427 /* FIXME: DEPRECATED */
428 void smlDevInfAgentSetDevInf(SmlDevInfAgent *agent, SmlDevInf *devinf)
429 {
430  smlTrace(TRACE_ERROR, "%s(%p, %p)", __func__, agent, devinf);
431  smlAssertMsg(NULL, "This function is a design bug.");
432 }
433 
434 /* FIXME: DEPRECATED */
435 SmlDevInf *smlDevInfAgentGetDevInf(SmlDevInfAgent *agent)
436 {
437  smlTrace(TRACE_ERROR, "%s(%p, %p)", __func__, agent);
438  smlAssertMsg(NULL, "This function is a design bug.");
439  return NULL;
440 }
441 
442 /* Set the devinf of the remote peer. */
443 SmlBool smlDevInfAgentSetSessionDevInf(
444  SmlDevInfAgent *agent,
445  SmlSession *session,
446  SmlDevInf *devinf,
447  SmlError **error)
448 {
449  smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, agent, session, devinf, error);
450 
451  CHECK_ERROR_REF
452  smlAssert(agent);
453  smlAssert(agent->sessions);
454  smlAssert(session);
455  smlAssert(devinf);
456 
457  SmlDevInfAgentSession *as = _get_session(agent, session);
458  if (!as) {
459  as = _new_session(agent, session, error);
460  if (!as)
461  goto error;
462  }
463 
464  as->recvDevInf = devinf;
465 
466  smlTrace(TRACE_EXIT, "%s", __func__);
467  return TRUE;
468 error:
469  smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error));
470  return FALSE;
471 }
472 
473 /* Get the devinf that was sent in the session. Returns FALSE if no devinf was received yet. */
474 SmlDevInf *smlDevInfAgentGetSessionDevInf(SmlDevInfAgent *agent, SmlSession *session)
475 {
476  smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, agent, session);
477 
478  smlAssert(agent);
479  smlAssert(agent->sessions);
480  smlAssert(session);
481 
482  SmlDevInfAgentSession *as = _get_session(agent, session);
483  if (!as)
484  {
485  smlTrace(TRACE_EXIT, "%s - the session is not cached until now", __func__);
486  return NULL;
487  }
488 
489  smlTrace(TRACE_EXIT, "%s - %p", __func__, as->recvDevInf);
490  return as->recvDevInf;
491 }
492 
494 SmlBool smlDevInfAgentSendDevInf(SmlDevInfAgent *agent, SmlSession *session, SmlError **error)
495 {
496  smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, agent, session, error);
497  CHECK_ERROR_REF
498  smlAssert(agent);
499 
500  if (!_send_devinf(agent, session, NULL, error))
501  goto error;
502 
503  smlTrace(TRACE_EXIT, "%s", __func__);
504  return TRUE;
505 
506 error:
507  smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
508  return FALSE;
509 }
510 
513 {
514  smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, agent, session, error);
515  CHECK_ERROR_REF
516  smlAssert(agent);
517  SmlCommand *get = NULL;
518 
519  SmlDevInfAgentSession *as = _get_session(agent, session);
520  if (!as) {
521  as = _new_session(agent, session, error);
522  if (!as)
523  goto error;
524  }
525 
526  if (as->recvDevInf) {
527  smlTrace(TRACE_EXIT, "%s: Already have the devinf", __func__);
528  return TRUE;
529  }
530 
531  if (!as->devinfRequested)
532  {
533  if (smlSessionGetVersion(session) == SML_VERSION_10)
534  get = smlDevInfNewGet(SML_DEVINF_VERSION_10, error);
535  else if (smlSessionGetVersion(session) == SML_VERSION_12)
536  get = smlDevInfNewGet(SML_DEVINF_VERSION_12, error);
537  else
538  get = smlDevInfNewGet(SML_DEVINF_VERSION_11, error);
539 
540  if (!get)
541  goto error;
542 
543  if (!smlSessionSendCommand(session, get, NULL, _get_devinf_reply, agent, error)) {
544  smlCommandUnref(get);
545  goto error;
546  }
547 
548  smlCommandUnref(get);
549 
550  as->devinfRequested = TRUE;
551  } else {
552  smlTrace(TRACE_INTERNAL, "%s: Already requested the devinf!", __func__);
553  }
554 
555  smlTrace(TRACE_EXIT, "%s", __func__);
556  return TRUE;
557 
558 error:
559  smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
560  return FALSE;
561 }
562 
563 SmlBool smlDevInfAgentRegisterSession(SmlDevInfAgent *agent, SmlManager *manager, SmlSession *session, SmlError **error)
564 {
565  smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, agent, manager, session, error);
566  CHECK_ERROR_REF
567  smlAssert(agent);
568  smlAssert(manager);
569 
570  SmlLocation *devinf12 = smlLocationNew("./devinf12", NULL, error);
571  SmlLocation *devinf11 = smlLocationNew("./devinf11", NULL, error);
572  SmlLocation *devinf10 = smlLocationNew("./devinf10", NULL, error);
573 
574  if (!devinf12 || !devinf11 || !devinf10)
575  goto error;
576 
577  /* PUT callbacks
578  *
579  * This command is used to actively send device information without
580  * being asked for. Usually a client do this if it is the first
581  * connection with the server or the client has no problems with
582  * its bandwith.
583  *
584  * Sometimes a server is missing the client's device information.
585  * In this situation the server can send a PUT and a GET to force
586  * the client to send the device information. This can happen if
587  * the client know that server should have its device information
588  * because of an earlier synchronization but the server does not
589  * have the device information. Sometimes server databases (incl.
590  * the device information database) are lost or it is simply a
591  * new server but with the old server address (IP) or name (DNS).
592  *
593  * Please note that a client can ignore a PUT from a server.
594  * Nevertheless it is recommended that a client does not ignore
595  * the device information of a server.
596  */
597 
598  smlTrace(TRACE_INTERNAL, "%s: register callbacks for PUT command", __func__);
600  manager, SML_COMMAND_TYPE_PUT, session,
601  NULL, devinf10, NULL, _recv_devinf, NULL, agent,
602  error))
603  goto error_free_loc;
605  manager, SML_COMMAND_TYPE_PUT, session,
606  NULL, devinf11, NULL, _recv_devinf, NULL, agent,
607  error))
608  goto error_free_loc;
610  manager, SML_COMMAND_TYPE_PUT, session,
611  NULL, devinf12, NULL, _recv_devinf, NULL, agent,
612  error))
613  goto error_free_loc;
614 
615  /* GET callbacks
616  *
617  * This command is used to request the device information of a
618  * remote peer. Usually the client do this if it is the first
619  * connection with this server or the client does not remember
620  * the server's device information. The most mobiles only do
621  * this for the first successful connection. Data costs usually
622  * high amounts of money in the mobile world and the bandwith is
623  * small in the mobile world.
624  *
625  * Nevertheless if a mobile does not perform the PUT command and
626  * the server does not know the device information of the client
627  * then the server can send a GET command and the client has to
628  * react on it. Please see above why this can happen.
629  *
630  * Please note that client and server must be able to handle the
631  * GET command. A RESULTS command must be send with the local
632  * device information.
633  */
634 
635  smlTrace(TRACE_INTERNAL, "%s: register callbacks for GET command", __func__);
637  manager, SML_COMMAND_TYPE_GET, session,
638  devinf10, NULL, NULL, _request_devinf, NULL, agent,
639  error))
640  goto error_free_loc;
642  manager, SML_COMMAND_TYPE_GET, session,
643  devinf11, NULL, NULL, _request_devinf, NULL, agent,
644  error))
645  goto error_free_loc;
647  manager, SML_COMMAND_TYPE_GET, session,
648  devinf12, NULL, NULL, _request_devinf, NULL, agent,
649  error))
650  goto error_free_loc;
651 
652  /* RESULTS callbacks
653  *
654  * This command is used to send the device information which
655  * was requested with a GET command. This command can be send by
656  * server and clients. Please see above when this happens.
657  *
658  * A server must be able to handle and interpret a RESULTS
659  * command from a client. Especially this is required because a
660  * server must explicitly request such a command with a previous
661  * GET command.
662  *
663  * Please note that a client can ignore a RESULTS from a server.
664  * Nevertheless it is recommended that a client does not ignore
665  * the device information of a server.
666  */
667 
668  smlTrace(TRACE_INTERNAL, "%s: register callbacks for RESULTS command", __func__);
670  manager, SML_COMMAND_TYPE_RESULTS, session,
671  devinf10, NULL, NULL, _recv_devinf, NULL, agent,
672  error))
673  goto error_free_loc;
675  manager, SML_COMMAND_TYPE_RESULTS, session,
676  devinf11, NULL, NULL, _recv_devinf, NULL, agent,
677  error))
678  goto error_free_loc;
680  manager, SML_COMMAND_TYPE_RESULTS, session,
681  devinf12, NULL, NULL, _recv_devinf, NULL, agent,
682  error))
683  goto error_free_loc;
684 
685  smlLocationUnref(devinf10);
686  smlLocationUnref(devinf11);
687  smlLocationUnref(devinf12);
688 
689  smlTrace(TRACE_EXIT, "%s", __func__);
690  return TRUE;
691 
692 error_free_loc:
693  if (devinf10)
694  smlLocationUnref(devinf10);
695  if (devinf11)
696  smlLocationUnref(devinf11);
697  if (devinf12)
698  smlLocationUnref(devinf12);
699 error:
700  smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
701  return FALSE;
702 }
703 
704 SmlBool smlDevInfAgentRegister(SmlDevInfAgent *agent, SmlManager *manager, SmlError **error)
705 {
706  smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, agent, manager, error);
707  CHECK_ERROR_REF
708 
709  SmlBool retval = smlDevInfAgentRegisterSession(agent, manager, NULL, error);
710 
711  if (!retval)
712  goto error;
713 
714  smlTrace(TRACE_EXIT, "%s", __func__);
715  return TRUE;
716 
717 error:
718  smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
719  return FALSE;
720 }
721 
SmlBool smlDevInfAgentSendDevInf(SmlDevInfAgent *agent, SmlSession *session, SmlError **error)
SmlBool smlSessionSendReply(SmlSession *session, SmlStatus *status, SmlError **error)
Sends a reply to a command.
Definition: sml_session.c:2536
const char * smlErrorPrint(SmlError **error)
Returns the message of the error.
Definition: sml_error.c:299
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
SmlBool smlItemGetData(SmlItem *item, char **data, unsigned int *size, SmlError **error)
Definition: sml_elements.c:495
void smlTrace(SmlTraceType type, const char *message,...)
Used for tracing the application.
Definition: sml_support.c:120
SmlBool smlDevInfAgentRequestDevInf(SmlDevInfAgent *agent, SmlSession *session, SmlError **error)
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
void * smlTryMalloc0(long n_bytes, SmlError **error)
Safely mallocs.
Definition: sml_support.c:335
void smlErrorSet(SmlError **error, SmlErrorType type, const char *format,...)
Sets the error.
Definition: sml_error.c:355
Represent an error.