blob: f9f42c6038a5cd22dfbf647d68886a11530be5d8 [file] [log] [blame]
Michal Vasko7bcb48e2016-01-15 10:28:54 +01001/**
2 * \file messages.c
3 * \author Radek Krejci <rkrejci@cesnet.cz>
4 * \brief libnetconf2 - NETCONF messages functions
5 *
6 * Copyright (c) 2015 CESNET, z.s.p.o.
7 *
Radek Krejci9b81f5b2016-02-24 13:14:49 +01008 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
Michal Vaskoafd416b2016-02-25 14:51:46 +010011 *
Radek Krejci9b81f5b2016-02-24 13:14:49 +010012 * https://opensource.org/licenses/BSD-3-Clause
Michal Vasko7bcb48e2016-01-15 10:28:54 +010013 */
14
15#include <ctype.h>
16#include <stdlib.h>
17#include <string.h>
18#include <stdarg.h>
19
20#include <libyang/libyang.h>
21
22#include "libnetconf.h"
Michal Vasko7bcb48e2016-01-15 10:28:54 +010023
24const char *rpcedit_dfltop2str[] = {NULL, "merge", "replace", "none"};
25const char *rpcedit_testopt2str[] = {NULL, "test-then-set", "set", "test-only"};
26const char *rpcedit_erropt2str[] = {NULL, "stop-on-error", "continue-on-error", "rollback-on-error"};
27
28API NC_RPC_TYPE
29nc_rpc_get_type(const struct nc_rpc *rpc)
30{
Michal Vasko7f1c78b2016-01-19 09:52:14 +010031 if (!rpc) {
Michal Vasko45e53ae2016-04-07 11:46:03 +020032 ERRARG("rpc");
Michal Vasko7f1c78b2016-01-19 09:52:14 +010033 return 0;
34 }
35
Michal Vasko7bcb48e2016-01-15 10:28:54 +010036 return rpc->type;
37}
38
39API struct nc_rpc *
40nc_rpc_generic(const struct lyd_node *data, NC_PARAMTYPE paramtype)
41{
42 struct nc_rpc_generic *rpc;
43
Michal Vasko7f1c78b2016-01-19 09:52:14 +010044 if (!data) {
Michal Vasko45e53ae2016-04-07 11:46:03 +020045 ERRARG("data");
Michal Vasko7f1c78b2016-01-19 09:52:14 +010046 return NULL;
47 }
48
Michal Vasko7bcb48e2016-01-15 10:28:54 +010049 if (data->next || (data->prev != data)) {
50 ERR("Generic RPC must have a single root node.");
51 return NULL;
52 }
53
54 rpc = malloc(sizeof *rpc);
55 if (!rpc) {
56 ERRMEM;
57 return NULL;
58 }
59
60 rpc->type = NC_RPC_GENERIC;
61 rpc->has_data = 1;
62 if (paramtype == NC_PARAMTYPE_DUP_AND_FREE) {
63 rpc->content.data = lyd_dup(data, 1);
64 } else {
65 rpc->content.data = (struct lyd_node *)data;
66 }
67 rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
68
69 return (struct nc_rpc *)rpc;
70}
71
72API struct nc_rpc *
73nc_rpc_generic_xml(const char *xml_str, NC_PARAMTYPE paramtype)
74{
75 struct nc_rpc_generic *rpc;
76
Michal Vasko7f1c78b2016-01-19 09:52:14 +010077 if (!xml_str) {
Michal Vasko45e53ae2016-04-07 11:46:03 +020078 ERRARG("xml_str");
Michal Vasko7f1c78b2016-01-19 09:52:14 +010079 return NULL;
80 }
81
Michal Vasko7bcb48e2016-01-15 10:28:54 +010082 rpc = malloc(sizeof *rpc);
83 if (!rpc) {
84 ERRMEM;
85 return NULL;
86 }
87
88 rpc->type = NC_RPC_GENERIC;
89 rpc->has_data = 0;
90 if (paramtype == NC_PARAMTYPE_DUP_AND_FREE) {
91 rpc->content.xml_str = strdup(xml_str);
92 } else {
93 rpc->content.xml_str = (char *)xml_str;
94 }
95 rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
96
97 return (struct nc_rpc *)rpc;
98}
99
100API struct nc_rpc *
101nc_rpc_getconfig(NC_DATASTORE source, const char *filter, NC_WD_MODE wd_mode, NC_PARAMTYPE paramtype)
102{
103 struct nc_rpc_getconfig *rpc;
104
Michal Vasko7f1c78b2016-01-19 09:52:14 +0100105 if (!source) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200106 ERRARG("source");
Michal Vasko7f1c78b2016-01-19 09:52:14 +0100107 return NULL;
108 }
109
Michal Vaskof3c647b2016-03-08 12:17:33 +0100110 if (filter && filter[0] && (filter[0] != '<') && (filter[0] != '/') && !isalpha(filter[0])) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200111 ERR("Filter must either be an XML subtree or an XPath expression (invalid first char '%c').", filter[0]);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100112 return NULL;
113 }
114
115 rpc = malloc(sizeof *rpc);
116 if (!rpc) {
117 ERRMEM;
118 return NULL;
119 }
120
121 rpc->type = NC_RPC_GETCONFIG;
122 rpc->source = source;
123 if (filter && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
124 rpc->filter = strdup(filter);
125 } else {
126 rpc->filter = (char *)filter;
127 }
128 rpc->wd_mode = wd_mode;
129 rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
130
131 return (struct nc_rpc *)rpc;
132}
133
134API struct nc_rpc *
135nc_rpc_edit(NC_DATASTORE target, NC_RPC_EDIT_DFLTOP default_op, NC_RPC_EDIT_TESTOPT test_opt,
136 NC_RPC_EDIT_ERROPT error_opt, const char *edit_content, NC_PARAMTYPE paramtype)
137{
138 struct nc_rpc_edit *rpc;
139
Michal Vasko45e53ae2016-04-07 11:46:03 +0200140 if (!target) {
141 ERRARG("target");
142 return NULL;
143 } else if (!edit_content) {
144 ERRARG("edit_content");
Michal Vasko7f1c78b2016-01-19 09:52:14 +0100145 return NULL;
146 }
147
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100148 if ((edit_content[0] != '<') && !isalpha(edit_content[0])) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200149 ERR("<edit-config> content must either be a URL or an XML config (invalid first char '%c').", edit_content[0]);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100150 return NULL;
151 }
152
153 rpc = malloc(sizeof *rpc);
154 if (!rpc) {
155 ERRMEM;
156 return NULL;
157 }
158
159 rpc->type = NC_RPC_EDIT;
160 rpc->target = target;
161 rpc->default_op = default_op;
162 rpc->test_opt = test_opt;
163 rpc->error_opt = error_opt;
164 if (paramtype == NC_PARAMTYPE_DUP_AND_FREE) {
165 rpc->edit_cont = strdup(edit_content);
166 } else {
167 rpc->edit_cont = (char *)edit_content;
168 }
169 rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
170
171 return (struct nc_rpc *)rpc;
172}
173
174API struct nc_rpc *
175nc_rpc_copy(NC_DATASTORE target, const char *url_trg, NC_DATASTORE source, const char *url_or_config_src,
176 NC_WD_MODE wd_mode, NC_PARAMTYPE paramtype)
177{
178 struct nc_rpc_copy *rpc;
179
Michal Vasko45e53ae2016-04-07 11:46:03 +0200180 if (!target) {
181 ERRARG("target");
182 return NULL;
183 } else if (!source) {
184 ERRARG("source");
Michal Vasko7f1c78b2016-01-19 09:52:14 +0100185 return NULL;
186 }
187
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100188 if (url_or_config_src && (url_or_config_src[0] != '<') && !isalpha(url_or_config_src[0])) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200189 ERR("<copy-config> source is neither a URL nor an XML config (invalid first char '%c').", url_or_config_src[0]);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100190 return NULL;
191 }
192
193 rpc = malloc(sizeof *rpc);
194 if (!rpc) {
195 ERRMEM;
196 return NULL;
197 }
198
199 rpc->type = NC_RPC_COPY;
200 rpc->target = target;
201 if (url_trg && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
202 rpc->url_trg = strdup(url_trg);
203 } else {
204 rpc->url_trg = (char *)url_trg;
205 }
206 rpc->source = source;
207 if (url_or_config_src && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
208 rpc->url_config_src = strdup(url_or_config_src);
209 } else {
210 rpc->url_config_src = (char *)url_or_config_src;
211 }
212 rpc->wd_mode = wd_mode;
213 rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
214
215 return (struct nc_rpc *)rpc;
216}
217
218API struct nc_rpc *
219nc_rpc_delete(NC_DATASTORE target, const char *url, NC_PARAMTYPE paramtype)
220{
221 struct nc_rpc_delete *rpc;
222
Michal Vasko7f1c78b2016-01-19 09:52:14 +0100223 if (!target) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200224 ERRARG("target");
Michal Vasko7f1c78b2016-01-19 09:52:14 +0100225 return NULL;
226 }
227
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100228 rpc = malloc(sizeof *rpc);
229 if (!rpc) {
230 ERRMEM;
231 return NULL;
232 }
233
234 rpc->type = NC_RPC_DELETE;
235 rpc->target = target;
236 if (url && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
237 rpc->url = strdup(url);
238 } else {
239 rpc->url = (char *)url;
240 }
241 rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
242
243 return (struct nc_rpc *)rpc;
244}
245
246API struct nc_rpc *
247nc_rpc_lock(NC_DATASTORE target)
248{
249 struct nc_rpc_lock *rpc;
250
Michal Vasko7f1c78b2016-01-19 09:52:14 +0100251 if (!target) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200252 ERRARG("target");
Michal Vasko7f1c78b2016-01-19 09:52:14 +0100253 return NULL;
254 }
255
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100256 rpc = malloc(sizeof *rpc);
257 if (!rpc) {
258 ERRMEM;
259 return NULL;
260 }
261
262 rpc->type = NC_RPC_LOCK;
263 rpc->target = target;
264
265 return (struct nc_rpc *)rpc;
266}
267
268API struct nc_rpc *
269nc_rpc_unlock(NC_DATASTORE target)
270{
271 struct nc_rpc_lock *rpc;
272
Michal Vasko7f1c78b2016-01-19 09:52:14 +0100273 if (!target) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200274 ERRARG("target");
Michal Vasko7f1c78b2016-01-19 09:52:14 +0100275 return NULL;
276 }
277
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100278 rpc = malloc(sizeof *rpc);
279 if (!rpc) {
280 ERRMEM;
281 return NULL;
282 }
283
284 rpc->type = NC_RPC_UNLOCK;
285 rpc->target = target;
286
287 return (struct nc_rpc *)rpc;
288}
289
290API struct nc_rpc *
291nc_rpc_get(const char *filter, NC_WD_MODE wd_mode, NC_PARAMTYPE paramtype)
292{
293 struct nc_rpc_get *rpc;
294
Michal Vaskof3c647b2016-03-08 12:17:33 +0100295 if (filter && filter[0] && (filter[0] != '<') && (filter[0] != '/') && !isalpha(filter[0])) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200296 ERR("Filter must either be an XML subtree or an XPath expression (invalid first char '%c').", filter[0]);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100297 return NULL;
298 }
299
300 rpc = malloc(sizeof *rpc);
301 if (!rpc) {
302 ERRMEM;
303 return NULL;
304 }
305
306 rpc->type = NC_RPC_GET;
307 if (filter && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
308 rpc->filter = strdup(filter);
309 } else {
310 rpc->filter = (char *)filter;
311 }
312 rpc->wd_mode = wd_mode;
313 rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
314
315 return (struct nc_rpc *)rpc;
316}
317
318API struct nc_rpc *
319nc_rpc_kill(uint32_t session_id)
320{
321 struct nc_rpc_kill *rpc;
322
Michal Vasko7f1c78b2016-01-19 09:52:14 +0100323 if (!session_id) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200324 ERRARG("session_id");
Michal Vasko7f1c78b2016-01-19 09:52:14 +0100325 return NULL;
326 }
327
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100328 rpc = malloc(sizeof *rpc);
329 if (!rpc) {
330 ERRMEM;
331 return NULL;
332 }
333
334 rpc->type = NC_RPC_KILL;
335 rpc->sid = session_id;
336
337 return (struct nc_rpc *)rpc;
338}
339
340API struct nc_rpc *
341nc_rpc_commit(int confirmed, uint32_t confirm_timeout, const char *persist, const char *persist_id,
342 NC_PARAMTYPE paramtype)
343{
344 struct nc_rpc_commit *rpc;
345
346 rpc = malloc(sizeof *rpc);
347 if (!rpc) {
348 ERRMEM;
349 return NULL;
350 }
351
352 rpc->type = NC_RPC_COMMIT;
353 rpc->confirmed = confirmed;
354 rpc->confirm_timeout = confirm_timeout;
355 if (persist && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
356 rpc->persist = strdup(persist);
357 } else {
358 rpc->persist = (char *)persist;
359 }
360 if (persist_id && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
361 rpc->persist_id = strdup(persist_id);
362 } else {
363 rpc->persist_id = (char *)persist_id;
364 }
365 rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
366
367 return (struct nc_rpc *)rpc;
368}
369
370API struct nc_rpc *
371nc_rpc_discard(void)
372{
373 struct nc_rpc *rpc;
374
375 rpc = malloc(sizeof *rpc);
376 if (!rpc) {
377 ERRMEM;
378 return NULL;
379 }
380
381 rpc->type = NC_RPC_DISCARD;
382
383 return rpc;
384}
385
386API struct nc_rpc *
387nc_rpc_cancel(const char *persist_id, NC_PARAMTYPE paramtype)
388{
389 struct nc_rpc_cancel *rpc;
390
391 rpc = malloc(sizeof *rpc);
392 if (!rpc) {
393 ERRMEM;
394 return NULL;
395 }
396
397 rpc->type = NC_RPC_CANCEL;
398 if (persist_id && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
399 rpc->persist_id = strdup(persist_id);
400 } else {
401 rpc->persist_id = (char *)persist_id;
402 }
403 rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
404
405 return (struct nc_rpc *)rpc;
406}
407
408API struct nc_rpc *
409nc_rpc_validate(NC_DATASTORE source, const char *url_or_config, NC_PARAMTYPE paramtype)
410{
411 struct nc_rpc_validate *rpc;
412
Michal Vasko7f1c78b2016-01-19 09:52:14 +0100413 if (!source) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200414 ERRARG("source");
Michal Vasko7f1c78b2016-01-19 09:52:14 +0100415 return NULL;
416 }
417
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100418 if (url_or_config && (url_or_config[0] != '<') && !isalpha(url_or_config[0])) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200419 ERR("<validate> source is neither a URL nor an XML config (invalid first char '%c').", url_or_config[0]);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100420 return NULL;
421 }
422
423 rpc = malloc(sizeof *rpc);
424 if (!rpc) {
425 ERRMEM;
426 return NULL;
427 }
428
429 rpc->type = NC_RPC_VALIDATE;
430 rpc->source = source;
431 if (url_or_config && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
432 rpc->url_config_src = strdup(url_or_config);
433 } else {
434 rpc->url_config_src = (char *)url_or_config;
435 }
436 rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
437
438 return (struct nc_rpc *)rpc;
439}
440
441API struct nc_rpc *
442nc_rpc_getschema(const char *identifier, const char *version, const char *format, NC_PARAMTYPE paramtype)
443{
444 struct nc_rpc_getschema *rpc;
445
Michal Vasko7f1c78b2016-01-19 09:52:14 +0100446 if (!identifier) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200447 ERRARG("identifier");
Michal Vasko7f1c78b2016-01-19 09:52:14 +0100448 return NULL;
449 }
450
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100451 rpc = malloc(sizeof *rpc);
452 if (!rpc) {
453 ERRMEM;
454 return NULL;
455 }
456
457 rpc->type = NC_RPC_GETSCHEMA;
458 if (paramtype == NC_PARAMTYPE_DUP_AND_FREE) {
459 rpc->identifier = strdup(identifier);
460 } else {
461 rpc->identifier = (char *)identifier;
462 }
463 if (version && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
464 rpc->version = strdup(version);
465 } else {
466 rpc->version = (char *)version;
467 }
468 if (format && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
469 rpc->format = strdup(format);
470 } else {
471 rpc->format = (char *)format;
472 }
473 rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
474
475 return (struct nc_rpc *)rpc;
476}
477
478API struct nc_rpc *
479nc_rpc_subscribe(const char *stream_name, const char *filter, const char *start_time, const char *stop_time,
480 NC_PARAMTYPE paramtype)
481{
482 struct nc_rpc_subscribe *rpc;
483
Michal Vaskof3c647b2016-03-08 12:17:33 +0100484 if (filter && filter[0] && (filter[0] != '<') && (filter[0] != '/') && !isalpha(filter[0])) {
Michal Vasko45e53ae2016-04-07 11:46:03 +0200485 ERR("Filter must either be an XML subtree or an XPath expression (invalid first char '%c').", filter[0]);
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100486 return NULL;
487 }
488
489 rpc = malloc(sizeof *rpc);
490 if (!rpc) {
491 ERRMEM;
492 return NULL;
493 }
494
495 rpc->type = NC_RPC_SUBSCRIBE;
496 if (stream_name && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
497 rpc->stream = strdup(stream_name);
498 } else {
499 rpc->stream = (char *)stream_name;
500 }
501 if (filter && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
502 rpc->filter = strdup(filter);
503 } else {
504 rpc->filter = (char *)filter;
505 }
506 if (start_time && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
507 rpc->start = strdup(start_time);
508 } else {
509 rpc->start = (char *)start_time;
510 }
511 if (stop_time && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
512 rpc->stop = strdup(stop_time);
513 } else {
514 rpc->stop = (char *)stop_time;
515 }
516 rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
517
518 return (struct nc_rpc *)rpc;
519}
520
521API void
522nc_rpc_free(struct nc_rpc *rpc)
523{
524 struct nc_rpc_generic *rpc_generic;
525 struct nc_rpc_getconfig *rpc_getconfig;
526 struct nc_rpc_edit *rpc_edit;
527 struct nc_rpc_copy *rpc_copy;
528 struct nc_rpc_delete *rpc_delete;
529 struct nc_rpc_get *rpc_get;
530 struct nc_rpc_commit *rpc_commit;
531 struct nc_rpc_cancel *rpc_cancel;
532 struct nc_rpc_validate *rpc_validate;
533 struct nc_rpc_getschema *rpc_getschema;
534 struct nc_rpc_subscribe *rpc_subscribe;
535
536 if (!rpc) {
537 return;
538 }
539
540 switch (rpc->type) {
541 case NC_RPC_GENERIC:
542 rpc_generic = (struct nc_rpc_generic *)rpc;
543 if (rpc_generic->free) {
544 if (rpc_generic->has_data) {
545 lyd_free(rpc_generic->content.data);
546 } else {
547 free(rpc_generic->content.xml_str);
548 }
549 }
550 break;
551 case NC_RPC_GETCONFIG:
552 rpc_getconfig = (struct nc_rpc_getconfig *)rpc;
553 if (rpc_getconfig->free) {
554 free(rpc_getconfig->filter);
555 }
556 break;
557 case NC_RPC_EDIT:
558 rpc_edit = (struct nc_rpc_edit *)rpc;
559 if (rpc_edit->free) {
560 free(rpc_edit->edit_cont);
561 }
562 break;
563 case NC_RPC_COPY:
564 rpc_copy = (struct nc_rpc_copy *)rpc;
565 if (rpc_copy->free) {
566 free(rpc_copy->url_config_src);
567 }
568 break;
569 case NC_RPC_DELETE:
570 rpc_delete = (struct nc_rpc_delete *)rpc;
571 if (rpc_delete->free) {
572 free(rpc_delete->url);
573 }
574 break;
575 case NC_RPC_GET:
576 rpc_get = (struct nc_rpc_get *)rpc;
577 if (rpc_get->free) {
578 free(rpc_get->filter);
579 }
580 break;
581 case NC_RPC_COMMIT:
582 rpc_commit = (struct nc_rpc_commit *)rpc;
583 if (rpc_commit->free) {
584 free(rpc_commit->persist);
585 free(rpc_commit->persist_id);
586 }
587 break;
588 case NC_RPC_CANCEL:
589 rpc_cancel = (struct nc_rpc_cancel *)rpc;
590 if (rpc_cancel->free) {
591 free(rpc_cancel->persist_id);
592 }
593 break;
594 case NC_RPC_VALIDATE:
595 rpc_validate = (struct nc_rpc_validate *)rpc;
596 if (rpc_validate->free) {
597 free(rpc_validate->url_config_src);
598 }
599 break;
600 case NC_RPC_GETSCHEMA:
601 rpc_getschema = (struct nc_rpc_getschema *)rpc;
602 if (rpc_getschema->free) {
603 free(rpc_getschema->identifier);
604 free(rpc_getschema->version);
605 free(rpc_getschema->format);
606 }
607 break;
608 case NC_RPC_SUBSCRIBE:
609 rpc_subscribe = (struct nc_rpc_subscribe *)rpc;
610 if (rpc_subscribe->free) {
611 free(rpc_subscribe->stream);
612 free(rpc_subscribe->filter);
613 free(rpc_subscribe->start);
614 free(rpc_subscribe->stop);
615 }
616 break;
Michal Vasko7f1c78b2016-01-19 09:52:14 +0100617 default:
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100618 /* nothing special needed */
619 break;
620 }
621
622 free(rpc);
623}
624
625API void
626nc_reply_free(struct nc_reply *reply)
627{
Michal Vasko1a38c862016-01-15 15:50:07 +0100628 struct nc_client_reply_error *error;
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100629 struct nc_reply_data *data;
630 uint32_t i, j;
631
632 if (!reply) {
633 return;
634 }
635
636 switch (reply->type) {
637 case NC_RPL_DATA:
638 data = (struct nc_reply_data *)reply;
639 lyd_free_withsiblings(data->data);
640 break;
641
642 case NC_RPL_OK:
643 /* nothing to free */
644 break;
645
646 case NC_RPL_ERROR:
Michal Vasko1a38c862016-01-15 15:50:07 +0100647 error = (struct nc_client_reply_error *)reply;
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100648 for (i = 0; i < error->count; ++i) {
649 lydict_remove(error->ctx, error->err[i].type);
650 lydict_remove(error->ctx, error->err[i].tag);
651 lydict_remove(error->ctx, error->err[i].severity);
652 lydict_remove(error->ctx, error->err[i].apptag);
653 lydict_remove(error->ctx, error->err[i].path);
654 lydict_remove(error->ctx, error->err[i].message);
655 lydict_remove(error->ctx, error->err[i].message_lang);
656 lydict_remove(error->ctx, error->err[i].sid);
657 for (j = 0; j < error->err[i].attr_count; ++j) {
658 lydict_remove(error->ctx, error->err[i].attr[j]);
659 }
660 free(error->err[i].attr);
661 for (j = 0; j < error->err[i].elem_count; ++j) {
662 lydict_remove(error->ctx, error->err[i].elem[j]);
663 }
664 free(error->err[i].elem);
665 for (j = 0; j < error->err[i].ns_count; ++j) {
666 lydict_remove(error->ctx, error->err[i].ns[j]);
667 }
668 free(error->err[i].ns);
669 for (j = 0; j < error->err[i].other_count; ++j) {
670 lyxml_free(error->ctx, error->err[i].other[j]);
671 }
672 free(error->err[i].other);
673 }
674 free(error->err);
675 break;
676
677 case NC_RPL_NOTIF:
678 nc_notif_free((struct nc_notif *)reply);
Michal Vasko11d142a2016-01-19 15:58:24 +0100679 return;
Michal Vasko7bcb48e2016-01-15 10:28:54 +0100680 }
681
682 free(reply);
683}
Michal Vasko495c9462016-01-15 11:27:43 +0100684
685API void
686nc_notif_free(struct nc_notif *notif)
687{
688 if (!notif) {
689 return;
690 }
691
692 lydict_remove(notif->tree->schema->module->ctx, notif->datetime);
693 lyd_free(notif->tree);
694 free(notif);
695}