libsyncml  0.5.4
sml_command.c
1 /*
2  * libsyncml - A syncml protocol implementation
3  * Copyright (C) 2005 Armin Bauer <armin.bauer@opensync.org>
4  * Copyright (C) 2008 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 "syncml.h"
23 
24 #include "syncml_internals.h"
25 #include "sml_parse_internals.h"
26 #include "sml_command_internals.h"
27 #include "sml_session_internals.h"
28 #include "sml_elements_internals.h"
29 #include "sml_error_internals.h"
30 
31 SmlCommandType smlCommandTypeFromString(const char *name, SmlError **error)
32 {
33  CHECK_ERROR_REF
34  if (!name)
35  return SML_COMMAND_TYPE_UNKNOWN;
36 
37  if (!strcmp(name, SML_ELEMENT_ALERT)) {
38  return SML_COMMAND_TYPE_ALERT;
39  } else if (!strcmp(name, SML_ELEMENT_SYNC)) {
40  return SML_COMMAND_TYPE_SYNC;
41  } else if (!strcmp(name, SML_ELEMENT_PUT)) {
42  return SML_COMMAND_TYPE_PUT;
43  } else if (!strcmp(name, SML_ELEMENT_SYNCHDR)) {
44  return SML_COMMAND_TYPE_HEADER;
45  } else if (!strcmp(name, SML_ELEMENT_ADD)) {
46  return SML_COMMAND_TYPE_ADD;
47  } else if (!strcmp(name, SML_ELEMENT_REPLACE)) {
48  return SML_COMMAND_TYPE_REPLACE;
49  } else if (!strcmp(name, SML_ELEMENT_MAP)) {
50  return SML_COMMAND_TYPE_MAP;
51  } else if (!strcmp(name, SML_ELEMENT_DELETE)) {
52  return SML_COMMAND_TYPE_DELETE;
53  } else if (!strcmp(name, SML_ELEMENT_RESULTS)) {
54  return SML_COMMAND_TYPE_RESULTS;
55  } else if (!strcmp(name, SML_ELEMENT_GET)) {
56  return SML_COMMAND_TYPE_GET;
57  }
58 
59  smlErrorSet(error, SML_ERROR_GENERIC, "Unknown command name \"%s\"", name);
60  return SML_COMMAND_TYPE_UNKNOWN;
61 }
62 
63 const char *smlCommandTypeToString(SmlCommandType type, SmlError **error)
64 {
65  CHECK_ERROR_REF
66  switch (type) {
67  case SML_COMMAND_TYPE_ALERT:
68  return SML_ELEMENT_ALERT;
69  case SML_COMMAND_TYPE_SYNC:
70  return SML_ELEMENT_SYNC;
71  case SML_COMMAND_TYPE_PUT:
72  return SML_ELEMENT_PUT;
73  case SML_COMMAND_TYPE_HEADER:
74  return SML_ELEMENT_SYNCHDR;
75  case SML_COMMAND_TYPE_ADD:
76  return SML_ELEMENT_ADD;
77  case SML_COMMAND_TYPE_REPLACE:
78  return SML_ELEMENT_REPLACE;
79  case SML_COMMAND_TYPE_DELETE:
80  return SML_ELEMENT_DELETE;
81  case SML_COMMAND_TYPE_MAP:
82  return SML_ELEMENT_MAP;
83  case SML_COMMAND_TYPE_GET:
84  return SML_ELEMENT_GET;
85  case SML_COMMAND_TYPE_RESULTS:
86  return SML_ELEMENT_RESULTS;
87  default:
88  ;
89  }
90 
91  smlErrorSet(error, SML_ERROR_GENERIC, "Unknown command type \"%i\"", type);
92  return NULL;
93 }
94 
95 SmlStatus *smlStatusNew(SmlErrorType data, unsigned int cmdref, unsigned int msgref, SmlLocation *sourceref, SmlLocation *targetref, SmlCommandType type, SmlError **error)
96 {
97  smlTrace(TRACE_ENTRY, "%s(%i, %i, %i, %p, %p, %i, %p)", __func__, data, cmdref, msgref, sourceref, targetref, type, error);
98  CHECK_ERROR_REF
99  SmlStatus *status = smlTryMalloc0(sizeof(SmlStatus), error);
100  if (!status)
101  goto error;
102 
103  status->refCount = 1;
104  status->cmdRef = cmdref;
105  status->msgRef = msgref;
106  status->type = type;
107  if (data != SML_ERROR_UNKNOWN)
108  status->data = g_strdup_printf("%i", data);
109 
110  if (sourceref) {
111  status->sourceRef = sourceref;
112  smlLocationRef(sourceref);
113  }
114 
115  if (targetref) {
116  status->targetRef = targetref;
117  smlLocationRef(targetref);
118  }
119 
120  smlTrace(TRACE_EXIT, "%s: %p", __func__, status);
121  return status;
122 
123 error:
124  smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
125  return NULL;
126 }
127 
128 SmlStatus *smlStatusRef(SmlStatus *status)
129 {
130  smlTrace(TRACE_ENTRY, "%s(%p)", __func__, status);
131  smlAssert(status);
132 
133  g_atomic_int_inc(&(status->refCount));
134 
135  smlTrace(TRACE_EXIT, "%s: New refcount: %i", __func__, status->refCount);
136  return status;
137 }
138 
139 void smlStatusUnref(SmlStatus *status)
140 {
141  smlTrace(TRACE_ENTRY, "%s(%p)", __func__, status);
142  smlAssert(status);
143 
144  if (g_atomic_int_dec_and_test(&(status->refCount))) {
145  smlTrace(TRACE_INTERNAL, "%s: Refcount == 0!", __func__);
146 
147  if (status->sourceRef)
148  smlLocationUnref(status->sourceRef);
149 
150  if (status->targetRef)
151  smlLocationUnref(status->targetRef);
152 
153  if (status->data)
154  smlSafeCFree(&(status->data));
155 
156  if (status->anchor)
157  smlAnchorFree(status->anchor);
158 
159  if (status->item)
160  smlItemUnref(status->item);
161 
162  smlSafeFree((gpointer *)&status);
163  }
164 
165  smlTrace(TRACE_EXIT, "%s", __func__);
166 }
167 
168 SmlErrorType smlStatusGetCode(SmlStatus *status)
169 {
170  smlAssert(status);
171  smlAssert(status->data);
172  return atoi(status->data);
173 }
174 
175 SmlErrorClass smlStatusGetClass(SmlStatus *status)
176 {
177  smlAssert(status);
178  smlAssert(status->data);
179  return (atoi(status->data) / 100);
180 }
181 
182 SmlCommand *smlStatusGetResult(SmlStatus *status)
183 {
184  if (status->type == SML_COMMAND_TYPE_RESULTS)
185  return status->result;
186  return NULL;
187 }
188 
189 SmlBool smlStatusIsResult(SmlStatus *status)
190 {
191  return status->type == SML_COMMAND_TYPE_RESULTS ? TRUE : FALSE;
192 }
193 
194 SmlCommand *smlCommandNew(SmlCommandType type, SmlError **error)
195 {
196  smlTrace(TRACE_ENTRY, "%s(%i, %p)", __func__, type, error);
197  CHECK_ERROR_REF
198 
199  SmlCommand *cmd = smlTryMalloc0(sizeof(SmlCommand), error);
200  if (!cmd)
201  goto error;
202 
203  cmd->refCount = 1;
204  cmd->type = type;
205 
206  smlTrace(TRACE_EXIT, "%s: %p", __func__, cmd);
207  return cmd;
208 
209 error:
210  smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
211  return NULL;
212 }
213 
214 SmlStatus *smlCommandNewReply(const SmlCommand *cmd, SmlErrorType code, SmlError **error)
215 {
216  smlTrace(TRACE_ENTRY, "%s(%p, %i, %p)", __func__, cmd, code, error);
217  CHECK_ERROR_REF
218  smlAssert(cmd);
219 
220  SmlStatus *reply = smlStatusNew(code, cmd->cmdID, cmd->msgID, cmd->source, cmd->target, cmd->type, error);
221  if (!reply)
222  goto error;
223 
224  switch (cmd->type) {
225  case SML_COMMAND_TYPE_ALERT:
226  if (cmd->private.alert.anchor) {
227  reply->anchor = smlAnchorNew(NULL, cmd->private.alert.anchor->next, error);
228  if (!reply->anchor)
229  goto error;
230  }
231  break;
232  default:
233  ;
234  }
235 
236  smlTrace(TRACE_EXIT, "%s: %p", __func__, reply);
237  return reply;
238 
239 error:
240  smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
241  return NULL;
242 }
243 
244 SmlCommand *smlCommandNewResult(SmlCommand *cmd, SmlLocation *source, char *data, unsigned int size, const char *contenttype, SmlError **error)
245 {
246  smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %i, %s, %p)", __func__, cmd, source, data, size, VA_STRING(contenttype), error);
247  CHECK_ERROR_REF
248  smlAssert(cmd);
249 
250  SmlCommand *result = smlCommandNew(SML_COMMAND_TYPE_RESULTS, error);
251  if (!result)
252  goto error;
253 
254  result->private.results.status = smlStatusNew(SML_NO_ERROR, cmd->cmdID, cmd->msgID, cmd->source, cmd->target, SML_COMMAND_TYPE_RESULTS, error);
255  if (!result->private.results.status)
256  goto error_free_cmd;
257 
258  result->private.results.status->item = smlItemNewForData(data, size, error);
259  smlSafeCFree(&data);
260  if (!result->private.results.status->item)
261  goto error_free_cmd;
262 
263  result->private.results.status->item->contenttype = g_strdup(contenttype);
264  result->private.results.status->item->source = smlLocationClone(source, error);
265 
266  if (!result->private.results.status->item->source)
267  goto error_free_cmd;
268 
269  smlTrace(TRACE_EXIT, "%s: %p", __func__, result);
270  return result;
271 
272 error_free_cmd:
273  smlCommandUnref(result);
274 error:
275  if (data)
276  smlSafeCFree(&data);
277  smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
278  return NULL;
279 }
280 
281 SmlCommand *smlCommandRef(SmlCommand *cmd)
282 {
283  smlTrace(TRACE_ENTRY, "%s(%p)", __func__, cmd);
284  smlAssert(cmd);
285 
286  g_atomic_int_inc(&(cmd->refCount));
287 
288  smlTrace(TRACE_EXIT, "%s: New refcount: %i", __func__, cmd->refCount);
289  return cmd;
290 }
291 
292 void smlCommandUnref(SmlCommand *cmd)
293 {
294  smlTrace(TRACE_ENTRY, "%s(%p)", __func__, cmd);
295  smlAssert(cmd);
296 
297  if (g_atomic_int_dec_and_test(&(cmd->refCount))) {
298  smlTrace(TRACE_INTERNAL, "%s: Refcount == 0!", __func__);
299 
300  if (cmd->parent) {
301  cmd->parent->children = g_list_remove(cmd->parent->children, cmd);
302 
303  smlCommandUnref(cmd->parent);
304  cmd->parent = NULL;
305  }
306 
307  switch (cmd->type) {
308  case SML_COMMAND_TYPE_UNKNOWN:
309  case SML_COMMAND_TYPE_HEADER:
310  case SML_COMMAND_TYPE_SYNC:
311  break;
312  case SML_COMMAND_TYPE_ALERT:
313  if (cmd->private.alert.anchor)
314  smlAnchorFree(cmd->private.alert.anchor);
315  if (cmd->private.alert.contentType)
316  smlSafeCFree(&(cmd->private.alert.contentType));
317  break;
318  case SML_COMMAND_TYPE_PUT:
319  case SML_COMMAND_TYPE_GET:
320  if (cmd->private.access.type)
321  smlSafeCFree(&(cmd->private.access.type));
322 
323  if (cmd->private.access.item)
324  smlItemUnref(cmd->private.access.item);
325  break;
326  case SML_COMMAND_TYPE_ADD:
327  case SML_COMMAND_TYPE_REPLACE:
328  case SML_COMMAND_TYPE_DELETE:
329  if (cmd->private.change.items)
330  {
331  guint i;
332  for (i = 0; i < g_list_length(cmd->private.change.items); i++)
333  {
334  SmlItem *item = g_list_nth_data(cmd->private.change.items, i);
335  smlItemUnref(item);
336  }
337  g_list_free(cmd->private.change.items);
338  }
339  break;
340  case SML_COMMAND_TYPE_MAP:
341  while (cmd->private.map.items) {
342  SmlMapItem *item = cmd->private.map.items->data;
343  smlMapItemUnref(item);
344  cmd->private.map.items = g_list_delete_link(cmd->private.map.items, cmd->private.map.items);
345  }
346  break;
347  case SML_COMMAND_TYPE_RESULTS:
348  if (cmd->private.results.status)
349  smlStatusUnref(cmd->private.results.status);
350  break;
351  }
352 
353  if (cmd->target)
354  smlLocationUnref(cmd->target);
355 
356  if (cmd->source)
357  smlLocationUnref(cmd->source);
358 
359  smlSafeFree((gpointer *)&cmd);
360  }
361 
362  smlTrace(TRACE_EXIT, "%s", __func__);
363 }
364 
365 SmlCommand *smlCommandNewChange(SmlChangeType type, const char *uid, const char *data, unsigned int size, const char *contenttype, SmlError **error)
366 {
367  smlTrace(TRACE_ENTRY, "%s(%i, %s, %p, %i, %s, %p)", __func__, type, VA_STRING(uid), data, size, VA_STRING(contenttype), error);
368  CHECK_ERROR_REF
369  SmlCommand *cmd = NULL;
370 
371  switch (type) {
372  case SML_CHANGE_ADD:
373  cmd = smlCommandNew(SML_COMMAND_TYPE_ADD, error);
374  break;
375  case SML_CHANGE_REPLACE:
376  cmd = smlCommandNew(SML_COMMAND_TYPE_REPLACE, error);
377  break;
378  case SML_CHANGE_DELETE:
379  cmd = smlCommandNew(SML_COMMAND_TYPE_DELETE, error);
380  break;
381  default:
382  smlErrorSet(error, SML_ERROR_GENERIC, "Unknown changetype");
383  }
384  if (!cmd)
385  goto error;
386 
387  SmlItem *item = smlItemNewForData(data, size, error);
388  if (!item)
389  goto error_free_cmd;
390  cmd->private.change.items = g_list_append(NULL, item);
391  if (!cmd->private.change.items)
392  {
393  smlItemUnref(item);
394  goto error_free_cmd;
395  }
396 
397  SmlLocation *loc = smlLocationNew(uid, NULL, error);
398  if (!loc)
399  goto error_free_cmd;
400 
401  /* The usage of target and source depends on the role of the
402  * local peer. We cannot determine if the local peer is an
403  * OMA DS client or server. This function is only used by
404  * smlDsSessionQueueChange. So the correct usage of target
405  * and source must be ensured by the XML assembler.
406  */
407  item->source = loc;
408  if (type != SML_CHANGE_ADD) {
409  /* If this is an Add command then nobody knows
410  * which ID the remote peer will be use for this item.
411  */
412  smlLocationRef(loc);
413  item->target = loc;
414  }
415 
416  item->contenttype = g_strdup(contenttype);
417 
418  smlTrace(TRACE_EXIT, "%s: %p", __func__, cmd);
419  return cmd;
420 
421 error_free_cmd:
422  smlCommandUnref(cmd);
423 error:
424  smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
425  return NULL;
426 }
427 
433 SmlCommand *smlCommandNewPartialChange(SmlChangeType type, const char *uid, const char *data, unsigned int complete_size, unsigned int partial_size, const char *contenttype, SmlError **error)
434 {
435  smlTrace(TRACE_ENTRY, "%s(%i, %s, %p, %i, %i, %s, %p)", __func__, type, VA_STRING(uid), data, complete_size, partial_size, VA_STRING(contenttype), error);
436  CHECK_ERROR_REF
437  SmlCommand *cmd = NULL;
438 
439  switch (type) {
440  case SML_CHANGE_ADD:
441  cmd = smlCommandNew(SML_COMMAND_TYPE_ADD, error);
442  break;
443  case SML_CHANGE_REPLACE:
444  cmd = smlCommandNew(SML_COMMAND_TYPE_REPLACE, error);
445  break;
446  case SML_CHANGE_DELETE:
447  cmd = smlCommandNew(SML_COMMAND_TYPE_DELETE, error);
448  break;
449  default:
450  smlErrorSet(error, SML_ERROR_GENERIC, "Unknown changetype");
451  }
452  if (!cmd)
453  goto error;
454  cmd->size = complete_size;
455 
456  SmlItem *item = smlItemNewForData(data, partial_size, error);
457  if (!item)
458  goto error_free_cmd;
459  cmd->private.change.items = g_list_append(NULL, item);
460  if (!cmd->private.change.items)
461  {
462  smlItemUnref(item);
463  goto error_free_cmd;
464  }
465 
466  SmlLocation *loc = smlLocationNew(uid, NULL, error);
467  if (!loc)
468  goto error_free_cmd;
469 
470  if (type != SML_CHANGE_ADD)
471  item->target = loc;
472  else
473  item->source = loc;
474 
475  item->moreData = TRUE;
476  item->contenttype = g_strdup(contenttype);
477 
478  smlTrace(TRACE_EXIT, "%s: %p", __func__, cmd);
479  return cmd;
480 
481 error_free_cmd:
482  smlCommandUnref(cmd);
483 error:
484  smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
485  return NULL;
486 }
487 
488 SmlCommand *smlCommandNewAlert(SmlAlertType type, SmlLocation *target, SmlLocation *source, const char *next, const char *last, const char *contenttype, SmlError **error)
489 {
490  smlTrace(TRACE_ENTRY, "%s(%i, %p, %p, %s, %s, %s, %p)", __func__, type, target, source, VA_STRING(next), VA_STRING(last), VA_STRING(contenttype), error);
491  CHECK_ERROR_REF
492 
493  SmlCommand *cmd = smlCommandNew(SML_COMMAND_TYPE_ALERT, error);
494  if (!cmd)
495  goto error;
496 
497  if (target) {
498  cmd->target = target;
499  smlLocationRef(target);
500  }
501 
502  if (source) {
503  cmd->source = source;
504  smlLocationRef(source);
505  }
506 
507  /* A synchronization anchor makes only sense if it is not an
508  * alert for the next part of an incomplete package (next
509  * message alert) or SAN.
510  */
511  if (type != SML_ALERT_NEXT_MESSAGE && type != SML_ALERT_TWO_WAY_BY_SERVER) {
512  /* If this is a slow sync alert then it makes no sense
513  * to send the last sync anchor because a slow sync is
514  * only necessary if there was no earlier sync or
515  * something goes wrong since then which means there is
516  * no safe last anchor.
517  */
518  if (type == SML_ALERT_SLOW_SYNC) {
519  if (last)
520  smlTrace(TRACE_INTERNAL,
521  "%s: removing last anchor (%s) from slow sync alert",
522  __func__, VA_STRING(last));
523  cmd->private.alert.anchor = smlAnchorNew(NULL, next, error);
524  } else
525  cmd->private.alert.anchor = smlAnchorNew(last, next, error);
526  if (!cmd->private.alert.anchor)
527  goto error;
528  }
529  cmd->private.alert.type = type;
530  cmd->private.alert.contentType = g_strdup(contenttype);
531 
532  smlTrace(TRACE_EXIT, "%s: %p", __func__, cmd);
533  return cmd;
534 
535 error:
536  smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
537  return NULL;
538 }
539 
540 SmlCommand *smlCommandNewSync(SmlLocation *target, SmlLocation *source, unsigned int num_changes, SmlError **error)
541 {
542  smlTrace(TRACE_ENTRY, "%s(%p, %p, %i, %p)", __func__, target, source, num_changes, error);
543  CHECK_ERROR_REF
544  SmlCommand *cmd = smlCommandNew(SML_COMMAND_TYPE_SYNC, error);
545  if (!cmd)
546  goto error;
547 
548  cmd->target = target;
549  smlLocationRef(target);
550 
551  cmd->source = source;
552  smlLocationRef(source);
553 
554  cmd->private.sync.numChanged = num_changes;
555 
556  smlTrace(TRACE_EXIT, "%s: %p", __func__, cmd);
557  return cmd;
558 
559 error:
560  smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
561  return NULL;
562 }
563 
564 SmlCommand *smlCommandNewPut(SmlLocation *target, SmlLocation *source, const char *data, unsigned int size, const char *contenttype, SmlError **error)
565 {
566  smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %i, %s, %p)", __func__, target, source, data, size, VA_STRING(contenttype), error);
567  CHECK_ERROR_REF
568 
569  SmlCommand *cmd = smlCommandNew(SML_COMMAND_TYPE_PUT, error);
570  if (!cmd)
571  goto error;
572 
573  cmd->private.access.item = smlItemNewForData(data, size, error);
574  if (!cmd->private.access.item)
575  goto error_free_cmd;
576 
577  if (target) {
578  cmd->target = target;
579  smlLocationRef(target);
580  smlItemSetTarget(cmd->private.access.item, cmd->target);
581  }
582 
583  if (source) {
584  cmd->source = source;
585  smlLocationRef(source);
586  smlItemSetSource(cmd->private.access.item, cmd->source);
587  }
588 
589  cmd->private.access.item->contenttype = g_strdup(contenttype);
590 
591  smlTrace(TRACE_EXIT, "%s: %p", __func__, cmd);
592  return cmd;
593 
594 error_free_cmd:
595  smlCommandUnref(cmd);
596 error:
597  smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
598  return NULL;
599 }
600 
601 SmlCommand *smlCommandNewGet(SmlLocation *target, const char *contenttype, SmlError **error)
602 {
603  smlTrace(TRACE_ENTRY, "%s(%p, %s, %p)", __func__, target, VA_STRING(contenttype), error);
604  CHECK_ERROR_REF
605  smlAssert(target);
606 
607  SmlCommand *cmd = smlCommandNew(SML_COMMAND_TYPE_GET, error);
608  if (!cmd)
609  goto error;
610 
611  cmd->private.access.item = smlItemNew(0, error);
612  if (!cmd->private.access.item)
613  goto error_free_cmd;
614 
615  cmd->target = target;
616  smlLocationRef(target);
617  smlItemSetTarget(cmd->private.access.item, cmd->target);
618 
619  cmd->private.access.item->contenttype = g_strdup(contenttype);
620 
621  smlTrace(TRACE_EXIT, "%s: %p", __func__, cmd);
622  return cmd;
623 
624 error_free_cmd:
625  smlCommandUnref(cmd);
626 error:
627  smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
628  return NULL;
629 }
630 
631 SmlCommand *smlCommandNewMap(SmlLocation *target, SmlLocation *source, SmlError **error)
632 {
633  smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, target, source, error);
634  CHECK_ERROR_REF
635 
636  SmlCommand *cmd = smlCommandNew(SML_COMMAND_TYPE_MAP, error);
637  if (!cmd)
638  goto error;
639 
640  cmd->target = target;
641  smlLocationRef(target);
642 
643  cmd->source = source;
644  smlLocationRef(source);
645 
646  smlTrace(TRACE_EXIT, "%s: %p", __func__, cmd);
647  return cmd;
648 
649 error:
650  smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
651  return NULL;
652 }
653 
654 SmlBool smlCommandAddMapItem(SmlCommand *map, SmlMapItem *item, SmlError **error)
655 {
656  smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, map, item, error);
657  CHECK_ERROR_REF
658  smlAssert(map);
659  smlAssert(map->type == SML_COMMAND_TYPE_MAP);
660  smlAssert(item);
661 
662  smlMapItemRef(item);
663  map->private.map.items = g_list_append(map->private.map.items, item);
664 
665  smlTrace(TRACE_EXIT, "%s", __func__);
666  return TRUE;
667 }
668 
669 SmlAlertType smlAlertTypeConvert(unsigned int id, SmlError **error)
670 {
671  smlTrace(TRACE_ENTRY, "%s(%u, %p)", __func__, id, error);
672  CHECK_ERROR_REF
673 
674  if (id == 0 ||
675  id == 100 ||
676  (200 <= id && id <= 210) ||
677  (221 <= id && id <= 223))
678  {
679  SmlAlertType result = (SmlAlertType) id;
680  smlTrace(TRACE_EXIT, "%s - %u", __func__, result);
681  return result;
682  } else {
683  smlErrorSet(error, SML_ERROR_GENERIC,
684  "The unknown alert code %u was detected.", id);
685  smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error));
686  return SML_ALERT_UNKNOWN;
687  }
688 }
689 
const char * smlErrorPrint(SmlError **error)
Returns the message of the error.
Definition: sml_error.c:299
SmlErrorType type
void smlTrace(SmlTraceType type, const char *message,...)
Used for tracing the application.
Definition: sml_support.c:120
SmlCommand * smlCommandNewPartialChange(SmlChangeType type, const char *uid, const char *data, unsigned int complete_size, unsigned int partial_size, const char *contenttype, SmlError **error)
Definition: sml_command.c:433
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.