blob: 0a85f569bf8b8eac6ca2fd5ad3cc42e9dd84b7ff [file] [log] [blame]
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001/**
2 * @file parser_lyb.c
3 * @author Michal Vasko <mvasko@cesnet.cz>
4 * @brief LYB data parser for libyang
5 *
6 * Copyright (c) 2018 CESNET, z.s.p.o.
7 *
8 * 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
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14
15#include <assert.h>
16#include <errno.h>
17#include <stdlib.h>
18#include <string.h>
19
20#include "libyang.h"
21#include "common.h"
22#include "context.h"
23#include "parser.h"
24#include "tree_internal.h"
25
26#define LYB_HAVE_READ_GOTO(r, d, go) if (r < 0) goto go; d += r;
27#define LYB_HAVE_READ_RETURN(r, d, ret) if (r < 0) return ret; d += r;
28
29static int
30lyb_read(const char *data, uint8_t *buf, size_t count, struct lyb_state *lybs)
31{
32 int ret = 0, i, empty_chunk_i;
33 size_t to_read;
34
35 assert(data && lybs);
36
37 while (1) {
38 /* check for fully-read (empty) data chunks */
39 to_read = count;
40 empty_chunk_i = -1;
41 for (i = 0; i < lybs->used; ++i) {
42 /* we want the innermost chunks resolved first, so replace previous empty chunks,
43 * also ignore chunks that are completely finished, there is nothing for us to do */
44 if ((lybs->written[i] <= count) && lybs->position[i]) {
45 /* empty chunk, do not read more */
46 to_read = lybs->written[i];
47 empty_chunk_i = i;
48 }
49 }
50
51 if ((empty_chunk_i == -1) && !count) {
52 break;
53 }
54
55 /* we are actually reading some data, not just finishing another chunk */
56 if (to_read) {
57 memcpy(buf, data + ret, to_read);
58
59 for (i = 0; i < lybs->used; ++i) {
60 /* decrease all written counters */
61 lybs->written[i] -= to_read;
62 }
63 /* decrease count/buf */
64 count -= to_read;
65 buf += to_read;
66
67 ret += to_read;
68 }
69
70 if (empty_chunk_i > -1) {
71 /* read the next chunk size */
72 memcpy(&lybs->written[empty_chunk_i], data + ret, LYB_SIZE_BYTES);
73 /* remember whether there is a following chunk or not */
74 lybs->position[empty_chunk_i] = (lybs->written[empty_chunk_i] == LYB_SIZE_MAX ? 1 : 0);
75
76 ret += LYB_SIZE_BYTES;
77 }
78 }
79
80 return ret;
81}
82
83static int
84lyb_read_number(uint64_t *num, uint64_t max_num, const char *data, struct lyb_state *lybs)
85{
86 int max_bits, max_bytes, i, r, ret = 0;
87
88 for (max_bits = 0; max_num; max_num >>= 1, ++max_bits);
89 max_bytes = max_bits / 8 + (max_bits % 8 ? 1 : 0);
90
91 *num = 0;
92 for (i = 0; i < max_bytes; ++i) {
93 *num <<= 8;
94 ret += (r = lyb_read(data, (uint8_t *)num, 1, lybs));
95 LYB_HAVE_READ_RETURN(r, data, -1);
96 }
97
98 return ret;
99}
100
101static int
102lyb_read_string(struct ly_ctx *ctx, const char **str, const char *data, struct lyb_state *lybs)
103{
104 int ret;
105 size_t len;
106
107 /* read until the end of this subtree */
108 len = lybs->written[lybs->used - 1];
109
110 *str = malloc((len + 1) * sizeof **str);
111 LY_CHECK_ERR_RETURN(!*str, LOGMEM(ctx), -1);
112
113 ret = lyb_read(data, (uint8_t *)*str, len, lybs);
114 LYB_HAVE_READ_GOTO(ret, data, error);
115 ((char *)*str)[len] = '\0';
116
117 /* store in the dictionary */
118 *str = lydict_insert_zc(ctx, (char *)*str);
119
120 return ret;
121
122error:
123 free((char *)*str);
124 *str = NULL;
125 return -1;
126}
127
128static void
129lyb_read_stop_subtree(struct lyb_state *lybs)
130{
131 if (lybs->written[lybs->used - 1]) {
132 LOGINT(NULL);
133 }
134
135 --lybs->used;
136}
137
138static int
139lyb_read_start_subtree(const char *data, struct lyb_state *lybs)
140{
141 uint64_t num = 0;
142
143 if (lybs->used == lybs->size) {
144 lybs->size += LYB_STATE_STEP;
145 lybs->written = ly_realloc(lybs->written, lybs->size * sizeof *lybs->written);
146 lybs->position = ly_realloc(lybs->position, lybs->size * sizeof *lybs->position);
147 LY_CHECK_ERR_RETURN(!lybs->written || !lybs->position, LOGMEM(NULL), -1);
148 }
149
150 memcpy(&num, data, LYB_SIZE_BYTES);
151
152 ++lybs->used;
153 lybs->written[lybs->used - 1] = num;
154 lybs->position[lybs->used - 1] = (num == LYB_SIZE_MAX ? 1 : 0);
155
156 return LYB_SIZE_BYTES;
157}
158
159static int
160lyb_parse_model(struct ly_ctx *ctx, const char *data, const struct lys_module **mod, struct lyb_state *lybs)
161{
162 int r, ret = 0;
163 uint16_t num = 0;
164 char *mod_name = NULL, mod_rev[11];
165
166 /* model name length */
167 ret += (r = lyb_read(data, (uint8_t *)&num, sizeof(uint16_t), lybs));
168 LYB_HAVE_READ_GOTO(r, data, error);
169
170 mod_name = malloc(num + 1);
171 LY_CHECK_ERR_GOTO(!mod_name, LOGMEM(ctx), error);
172
173 /* model name */
174 ret += (r = lyb_read(data, (uint8_t *)mod_name, num, lybs));
175 LYB_HAVE_READ_GOTO(r, data, error);
176 mod_name[num] = '\0';
177
178 /* revision */
179 ret += (r = lyb_read(data, (uint8_t *)&num, sizeof(uint16_t), lybs));
180 LYB_HAVE_READ_GOTO(r, data, error);
181
182 if (num) {
183 sprintf(mod_rev, "%04u-%02u-%02u", ((num & 0xFE00) >> 9) + 2000, (num & 0x01E0) >> 5, (num & 0x001F));
184 *mod = ly_ctx_get_module(ctx, mod_name, mod_rev, 0);
185 } else {
186 *mod = ly_ctx_get_module(ctx, mod_name, NULL, 0);
187 }
188 if (!*mod) {
189 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Module \"%s@%s\" not found in the context.", mod_name, (num ? mod_rev : "<none>"));
190 goto error;
191 }
192
193 free(mod_name);
194 return ret;
195
196error:
197 free(mod_name);
198 return -1;
199}
200
201static struct lyd_node *
202lyb_new_node(const struct lys_node *schema)
203{
204 struct lyd_node *node;
205
206 switch (schema->nodetype) {
207 case LYS_CONTAINER:
208 case LYS_LIST:
209 case LYS_NOTIF:
210 case LYS_RPC:
211 case LYS_ACTION:
212 node = calloc(sizeof(struct lyd_node), 1);
213 break;
214 case LYS_LEAF:
215 case LYS_LEAFLIST:
216 node = calloc(sizeof(struct lyd_node_leaf_list), 1);
217 break;
218 case LYS_ANYDATA:
219 case LYS_ANYXML:
220 node = calloc(sizeof(struct lyd_node_anydata), 1);
221 break;
222 default:
223 return NULL;
224 }
225 LY_CHECK_ERR_RETURN(!node, LOGMEM(schema->module->ctx), NULL);
226
227 /* fill basic info */
228 node->schema = (struct lys_node *)schema;
229 node->validity = ly_new_node_validity(schema);
230 if (resolve_applies_when(schema, 0, NULL)) {
231 node->when_status = LYD_WHEN;
232 }
233 node->prev = node;
234
235 return node;
236}
237
238static int
239lyb_parse_anydata(struct lyd_node *node, const char *data, struct lyb_state *lybs)
240{
241 int r, ret = 0;
242 struct lyd_node_anydata *any = (struct lyd_node_anydata *)node;
243
244 /* read value type */
245 ret += (r = lyb_read(data, (uint8_t *)&any->value_type, sizeof any->value_type, lybs));
246 LYB_HAVE_READ_RETURN(r, data, -1);
247
248 /* read anydata content */
249 if (any->value_type == LYD_ANYDATA_DATATREE) {
250 any->value.tree = lyd_parse_lyb(node->schema->module->ctx, data, 0, NULL, NULL, NULL, &r);
251 ret += r;
252 LYB_HAVE_READ_RETURN(r, data, -1);
253 } else {
254 ret += (r = lyb_read_string(node->schema->module->ctx, &any->value.str, data, lybs));
255 LYB_HAVE_READ_RETURN(r, data, -1);
256 }
257
258 return ret;
259}
260
261static int
262lyb_parse_val(struct lyd_node_leaf_list *node, const char *data, struct lyb_state *lybs)
263{
264 int ret;
265 uint8_t byte;
266 struct ly_ctx *ctx = node->schema->module->ctx;
267 struct lys_type *type = &((struct lys_node_leaf *)node->schema)->type;
268
269 if (node->value_flags & (LY_VALUE_USER || LY_VALUE_UNRES)) {
270 /* just read value_str */
271 return lyb_read_string(ctx, &node->value_str, data, lybs);
272 }
273
274 switch (node->value_type) {
275 case LY_TYPE_INST:
276 case LY_TYPE_IDENT:
277 case LY_TYPE_UNION:
278 /* we do not actually fill value now, but value_str */
279 ret = lyb_read_string(ctx, &node->value_str, data, lybs);
280 break;
281 case LY_TYPE_BINARY:
282 case LY_TYPE_STRING:
283 case LY_TYPE_UNKNOWN:
284 /* read string */
285 ret = lyb_read_string(ctx, &node->value.string, data, lybs);
286 break;
287 case LY_TYPE_BITS:
288 /* find the correct structure */
289 for (; !type->info.bits.count; type = &type->der->type);
290
291 node->value.bit = calloc(type->info.bits.count, sizeof *node->value.bit);
292 LY_CHECK_ERR_RETURN(!node->value.bit, LOGMEM(ctx), -1);
293
294 /* read values */
295 /* TODO */
296 break;
297 case LY_TYPE_BOOL:
298 /* read byte */
299 ret = lyb_read(data, &byte, sizeof byte, lybs);
300 if ((ret > 0) && byte) {
301 node->value.bln = 1;
302 }
303 break;
304 case LY_TYPE_EMPTY:
305 /* nothing to read */
306 ret = 0;
307 break;
308 case LY_TYPE_ENUM:
309 /* find the correct structure */
310 for (; !type->info.bits.count; type = &type->der->type);
311
312 /* TODO */
313 break;
314 case LY_TYPE_INT8:
315 case LY_TYPE_UINT8:
316 ret = lyb_read_number((uint64_t *)&node->value.uint8, UINT8_MAX, data, lybs);
317 break;
318 case LY_TYPE_INT16:
319 case LY_TYPE_UINT16:
320 ret = lyb_read_number((uint64_t *)&node->value.uint16, UINT16_MAX, data, lybs);
321 break;
322 case LY_TYPE_INT32:
323 case LY_TYPE_UINT32:
324 ret = lyb_read_number((uint64_t *)&node->value.uint32, UINT32_MAX, data, lybs);
325 break;
326 case LY_TYPE_DEC64:
327 case LY_TYPE_INT64:
328 case LY_TYPE_UINT64:
329 ret = lyb_read_number((uint64_t *)&node->value.uint64, UINT64_MAX, data, lybs);
330 break;
331 default:
332 return -1;
333 }
334
335 return ret;
336}
337
338static int
339lyb_parse_val_str(struct lyd_node_leaf_list *node)
340{
341 struct ly_ctx *ctx = node->schema->module->ctx;
342 struct lys_type *type = &((struct lys_node_leaf *)node->schema)->type;
343 char num_str[21];
344
345 if (node->value_flags & LY_VALUE_UNRES) {
346 /* nothing to do */
347 return 0;
348 }
349
350 if (node->value_flags & LY_VALUE_USER) {
351 /* unfortunately, we need to also fill the value properly, so just parse it again */
352 node->value_flags &= ~LY_VALUE_USER;
353 if (!lyp_parse_value(type, &node->value_str, NULL, node, NULL,
354 lyd_node_module((struct lyd_node *)node), 1, node->dflt, 1)) {
355 return -1;
356 }
357
358 if (!(node->value_flags & LY_VALUE_USER)) {
359 LOGWRN(ctx, "Node \"%s\" value was stored as a user type, but it is not in the current context.", node->schema->name);
360 }
361 return 0;
362 }
363
364 switch (node->value_type) {
365 case LY_TYPE_INST:
366 /* fill the instance-identifier target now */
367 /* TODO */
368 break;
369 case LY_TYPE_IDENT:
370 /* fill the identity pointer now */
371 node->value.ident = resolve_identref(type, node->value_str, (struct lyd_node *)node, node->schema->module, node->dflt);
372 if (!node->value.ident) {
373 return -1;
374 }
375 break;
376 case LY_TYPE_BINARY:
377 case LY_TYPE_STRING:
378 case LY_TYPE_UNKNOWN:
379 /* just re-assign it */
380 node->value_str = node->value.string;
381 break;
382 case LY_TYPE_BITS:
383 /* TODO */
384 break;
385 case LY_TYPE_BOOL:
386 node->value_str = lydict_insert(ctx, (node->value.bln ? "true" : "false"), 0);
387 break;
388 case LY_TYPE_EMPTY:
389 case LY_TYPE_UNION:
390 /* leave value empty */
391 break;
392 case LY_TYPE_ENUM:
393 /* TODO */
394 break;
395 case LY_TYPE_INT8:
396 sprintf(num_str, "%d", node->value.int8);
397 node->value_str = lydict_insert(ctx, num_str, 0);
398 break;
399 case LY_TYPE_UINT8:
400 sprintf(num_str, "%u", node->value.uint8);
401 node->value_str = lydict_insert(ctx, num_str, 0);
402 break;
403 case LY_TYPE_INT16:
404 sprintf(num_str, "%d", node->value.int16);
405 node->value_str = lydict_insert(ctx, num_str, 0);
406 break;
407 case LY_TYPE_UINT16:
408 sprintf(num_str, "%u", node->value.uint16);
409 node->value_str = lydict_insert(ctx, num_str, 0);
410 break;
411 case LY_TYPE_INT32:
412 sprintf(num_str, "%d", node->value.int32);
413 node->value_str = lydict_insert(ctx, num_str, 0);
414 break;
415 case LY_TYPE_UINT32:
416 sprintf(num_str, "%u", node->value.uint32);
417 node->value_str = lydict_insert(ctx, num_str, 0);
418 break;
419 case LY_TYPE_INT64:
420 sprintf(num_str, "%ld", node->value.int64);
421 node->value_str = lydict_insert(ctx, num_str, 0);
422 break;
423 case LY_TYPE_UINT64:
424 sprintf(num_str, "%lu", node->value.uint64);
425 node->value_str = lydict_insert(ctx, num_str, 0);
426 break;
427 case LY_TYPE_DEC64:
428 /* TODO */
429 break;
430 default:
431 return -1;
432 }
433
434 return 0;
435}
436
437static int
438lyb_parse_leaf(struct lyd_node *node, const char *data, struct lyb_state *lybs)
439{
440 int r, ret = 0;
441 uint8_t start_byte;
442 struct lyd_node_leaf_list *leaf = (struct lyd_node_leaf_list *)node;
443
444 /* read value type and flags on the first byte */
445 ret += (r = lyb_read(data, &start_byte, sizeof start_byte, lybs));
446 LYB_HAVE_READ_RETURN(r, data, -1);
447
448 /* fill value type, flags */
449 leaf->value_type = start_byte & 0x1F;
450 if (start_byte & 0x80) {
451 leaf->dflt = 1;
452 }
453 if (start_byte & 0x40) {
454 leaf->value_flags |= LY_VALUE_USER;
455 }
456 if (start_byte & 0x20) {
457 leaf->value_flags |= LY_VALUE_UNRES;
458 }
459
460 ret += (r = lyb_parse_val(leaf, data, lybs));
461 LYB_HAVE_READ_RETURN(r, data, -1);
462
463 ret += (r = lyb_parse_val_str(leaf));
464 LYB_HAVE_READ_RETURN(r, data, -1);
465
466 return ret;
467}
468
469static int
470lyb_parse_schema_hash(const struct lys_node *sparent, const struct lys_module *mod, const char *data,
471 struct hash_table **sibling_ht, struct lys_node **snode, struct lyb_state *lybs)
472{
473 int r, ret = 0;
474 const struct lys_node *sibling = NULL;
475 LYB_HASH hash, cur_hash;
476 struct ly_ctx *ctx;
477
478 assert((sparent || mod) && (!sparent || !mod));
479 ctx = (sparent ? sparent->module->ctx : mod->ctx);
480
481 /* read the hash */
482 ret += (r = lyb_read(data, &hash, sizeof hash, lybs));
483 LYB_HAVE_READ_RETURN(r, data, -1);
484
485 while ((sibling = lys_getnext(sibling, sparent, mod, 0))) {
486
487 /* make sure hashes are ready and get the current one */
488 cur_hash = 0;
489#ifdef LY_ENABLED_CACHE
490 if (sibling->hash) {
491 cur_hash = sibling->hash;
492 } else
493#endif
494 if (!*sibling_ht) {
495 *sibling_ht = lyb_hash_siblings((struct lys_node *)sibling);
496 if (!*sibling_ht) {
497 return -1;
498 }
499 }
500 if (!cur_hash) {
501 cur_hash = lyb_hash_find(*sibling_ht, sibling);
502 if (!cur_hash) {
503 return -1;
504 }
505 }
506
507 if (hash == cur_hash) {
508 /* match found */
509 *snode = (struct lys_node *)sibling;
510 break;
511 }
512 }
513
514 if (!sibling) {
515 if (mod) {
516 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Failed to find matching hash for a top-level node from \"%s\".", mod->name);
517 } else {
518 LOGVAL(ctx, LYE_SPEC, LY_VLOG_LYS, sparent, "Failed to find matching hash for a child of \"%s\".", sparent->name);
519 }
520 return -1;
521 }
522
523 return ret;
524}
525
526static int
527lyb_parse_subtree(struct ly_ctx *ctx, const char *data, struct lyd_node *parent, struct lyd_node **first_sibling,
528 struct hash_table **sibling_ht, struct lyb_state *lybs)
529{
530 int r, ret = 0;
531 struct hash_table *children_ht = NULL;
532 struct lyd_node *node = NULL, *iter;
533 const struct lys_module *mod;
534 struct lys_node *sparent, *snode;
535
536 assert((parent && !first_sibling) || (!parent && first_sibling));
537
538 /* register a new subtree */
539 ret += (r = lyb_read_start_subtree(data, lybs));
540 LYB_HAVE_READ_GOTO(r, data, error);
541
542 if (!parent) {
543 /* top-level, read module name */
544 ret += (r = lyb_parse_model(ctx, data, &mod, lybs));
545 LYB_HAVE_READ_GOTO(r, data, error);
546
547 sparent = NULL;
548 } else {
549 mod = NULL;
550 sparent = parent->schema;
551 }
552
553 /* read hash, find the schema node */
554 ret += (r = lyb_parse_schema_hash(sparent, mod, data, sibling_ht, &snode, lybs));
555 LYB_HAVE_READ_GOTO(r, data, error);
556
557 /*
558 * read the node
559 */
560 node = lyb_new_node(snode);
561 if (!node) {
562 goto error;
563 }
564
565 /* TODO read attributes */
566
567 /* TODO read hash if flag */
568
569 /* read node content */
570 switch (snode->nodetype) {
571 case LYS_CONTAINER:
572 case LYS_LIST:
573 /* nothing to read */
574 break;
575 case LYS_LEAF:
576 case LYS_LEAFLIST:
577 ret += (r = lyb_parse_leaf(node, data, lybs));
578 LYB_HAVE_READ_GOTO(r, data, error);
579 break;
580 case LYS_ANYXML:
581 case LYS_ANYDATA:
582 ret += (r = lyb_parse_anydata(node, data, lybs));
583 LYB_HAVE_READ_GOTO(r, data, error);
584 break;
585 default:
586 goto error;
587 }
588
589 /* insert into data tree, manually */
590 if (parent) {
591 if (!parent->child) {
592 /* only child */
593 parent->child = node;
594 } else {
595 /* last child */
596 parent->child->prev->next = node;
597 node->prev = parent->child->prev;
598 parent->child->prev = node;
599 }
600 node->parent = parent;
601 } else if (*first_sibling) {
602 /* last sibling */
603 (*first_sibling)->prev->next = node;
604 node->prev = (*first_sibling)->prev;
605 (*first_sibling)->prev = node;
606 } else {
607 /* only sibling */
608 *first_sibling = node;
609 }
610
611 /* read all descendants */
612 while (lybs->written[lybs->used - 1]) {
613 ret += (r = lyb_parse_subtree(ctx, data, node, NULL, &children_ht, lybs));
614 LYB_HAVE_READ_GOTO(r, data, error);
615 }
616 if (children_ht) {
617 lyht_free(children_ht);
618 }
619
620 /* end the subtree */
621 lyb_read_stop_subtree(lybs);
622
623 /* make containers default if should be */
624 if (node->schema->nodetype == LYS_CONTAINER) {
625 LY_TREE_FOR(node->child, iter) {
626 if (!iter->dflt) {
627 break;
628 }
629 }
630
631 if (!iter) {
632 node->dflt = 1;
633 }
634 }
635
636 return ret;
637
638error:
639 if (children_ht) {
640 lyht_free(children_ht);
641 }
642 lyd_free(node);
643 if (*first_sibling == node) {
644 *first_sibling = NULL;
645 }
646 return -1;
647}
648
649static int
650lyb_parse_header(const char *data, struct lyb_state *lybs)
651{
652 int ret = 0;
653 uint8_t byte = 0;
654
655 /* TODO version, option for hash storing */
656 ret += lyb_read(data, (uint8_t *)&byte, sizeof byte, lybs);
657
658 /* TODO all used models */
659
660 return ret;
661}
662
663struct lyd_node *
664lyd_parse_lyb(struct ly_ctx *ctx, const char *data, int options, const struct lyd_node *rpc_act,
665 const struct lyd_node *data_tree, const char *yang_data_name, int *parsed)
666{
667 int r, ret = 0;
668 struct hash_table *top_sibling_ht = NULL;
669 struct lyd_node *node = NULL;
670 struct lyb_state lybs;
671
672 if (!ctx || !data) {
673 LOGARG;
674 return NULL;
675 }
676
677 lybs.written = malloc(LYB_STATE_STEP * sizeof *lybs.written);
678 lybs.position = malloc(LYB_STATE_STEP * sizeof *lybs.position);
679 LY_CHECK_ERR_GOTO(!lybs.written || !lybs.position, LOGMEM(ctx), finish);
680 lybs.used = 0;
681 lybs.size = LYB_STATE_STEP;
682
683 /* read header */
684 ret += (r = lyb_parse_header(data, &lybs));
685 LYB_HAVE_READ_GOTO(r, data, finish);
686
687 /* TODO read used models */
688
689 /* read subtree(s) */
690 while (data[0]) {
691 ret += (r = lyb_parse_subtree(ctx, data, NULL, &node, &top_sibling_ht, &lybs));
692 LYB_HAVE_READ_GOTO(r, data, finish);
693 }
694
695 /* read the last zero, parsing finished */
696 ++ret;
697 r = ret;
698
699finish:
700 if (top_sibling_ht) {
701 lyht_free(top_sibling_ht);
702 }
703 free(lybs.written);
704 free(lybs.position);
705
706 if (parsed) {
707 *parsed = r;
708 }
709 return node;
710}