blob: cee63ba9b3bb234696b669e7d53cbca57b4c439f [file] [log] [blame]
Ilya Moiseenkoc115fba2011-08-01 10:53:18 -07001/*
2 * ccn_buf_decoder.cc
3 * Abstraction
4 *
5 * Created by Ilya on 7/29/11.
6 * Copyright 2011 __MyCompanyName__. All rights reserved.
7 *
8 */
9
10#include <string.h>
11#include <stdlib.h>
12#include "ccn_ccn.h"
13#include "ccn_charbuf.h"
14#include "ccn_coding.h"
15#include "ccn_indexbuf.h"
16
17/**
18 * @file ccn_buf_decoder.c
19 * @brief Support for Interest and ContentObject decoding.
20 *
21 * Part of the CCNx C Library.
22 *
23 * Copyright (C) 2008, 2009, 2010 Palo Alto Research Center, Inc.
24 *
25 * This library is free software; you can redistribute it and/or modify it
26 * under the terms of the GNU Lesser General Public License version 2.1
27 * as published by the Free Software Foundation.
28 * This library is distributed in the hope that it will be useful,
29 * but WITHOUT ANY WARRANTY; without even the implied warranty of
30 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
31 * Lesser General Public License for more details. You should have received
32 * a copy of the GNU Lesser General Public License along with this library;
33 * if not, write to the Free Software Foundation, Inc., 51 Franklin Street,
34 * Fifth Floor, Boston, MA 02110-1301 USA.
35 */
36
37
38struct ccn_buf_decoder *
39ccn_buf_decoder_start(struct ccn_buf_decoder *d,
40 const unsigned char *buf, size_t size)
41{
42 memset(&d->decoder, 0, sizeof(d->decoder));
43 d->decoder.state |= CCN_DSTATE_PAUSE;
44 d->buf = buf;
45 d->size = size;
46 ccn_skeleton_decode(&d->decoder, buf, size);
47 return(d);
48}
49
50void
51ccn_buf_advance(struct ccn_buf_decoder *d)
52{
53 ccn_skeleton_decode(&d->decoder,
54 d->buf + d->decoder.index,
55 d->size - d->decoder.index);
56}
57
58int
59ccn_buf_match_dtag(struct ccn_buf_decoder *d, enum ccn_dtag dtag)
60{
61 return (d->decoder.state >= 0 &&
62 CCN_GET_TT_FROM_DSTATE(d->decoder.state) == CCN_DTAG &&
63 (int)d->decoder.numval == dtag);
64}
65
66int
67ccn_buf_match_some_dtag(struct ccn_buf_decoder *d)
68{
69 return(d->decoder.state >= 0 &&
70 CCN_GET_TT_FROM_DSTATE(d->decoder.state) == CCN_DTAG);
71}
72
73int
74ccn_buf_match_some_blob(struct ccn_buf_decoder *d)
75{
76 return(d->decoder.state >= 0 &&
77 CCN_GET_TT_FROM_DSTATE(d->decoder.state) == CCN_BLOB);
78}
79
80int
81ccn_buf_match_blob(struct ccn_buf_decoder *d,
82 const unsigned char **bufp, size_t *sizep)
83{
84 if (ccn_buf_match_some_blob(d)) {
85 if (bufp != NULL)
86 *bufp = d->buf + d->decoder.index;
87 if (sizep != NULL)
88 *sizep = d->decoder.numval;
89 return (1);
90 }
91 if (bufp != NULL)
92 *bufp = d->buf + d->decoder.token_index;
93 if (sizep != NULL)
94 *sizep = 0;
95 return(0);
96}
97
98int
99ccn_buf_match_udata(struct ccn_buf_decoder *d, const char *s)
100{
101 size_t len = strlen(s);
102 return (d->decoder.state >= 0 &&
103 CCN_GET_TT_FROM_DSTATE(d->decoder.state) == CCN_UDATA &&
104 d->decoder.numval == len &&
105 0 == memcmp(d->buf + d->decoder.index, s, len));
106}
107
108int
109ccn_buf_match_attr(struct ccn_buf_decoder *d, const char *s)
110{
111 size_t len = strlen(s);
112 return (d->decoder.state >= 0 &&
113 CCN_GET_TT_FROM_DSTATE(d->decoder.state) == CCN_ATTR &&
114 d->decoder.numval == len &&
115 0 == memcmp(d->buf + d->decoder.index, s, len));
116}
117
118void
119ccn_buf_check_close(struct ccn_buf_decoder *d)
120{
121 if (d->decoder.state >= 0) {
122 if (CCN_GET_TT_FROM_DSTATE(d->decoder.state) != CCN_NO_TOKEN)
123 d->decoder.state = CCN_DSTATE_ERR_NEST;
124 else
125 ccn_buf_advance(d);
126 }
127}
128
129int
130ccn_buf_advance_past_element(struct ccn_buf_decoder *d)
131{
132 enum ccn_tt tt;
133 int nest;
134 if (d->decoder.state < 0)
135 return(d->decoder.state);
136 tt = (ccn_tt)CCN_GET_TT_FROM_DSTATE(d->decoder.state);
137 if (tt == CCN_DTAG || tt == CCN_TAG) {
138 nest = d->decoder.nest;
139 ccn_buf_advance(d);
140 while (d->decoder.state >= 0 && d->decoder.nest >= nest)
141 ccn_buf_advance(d);
142 /* The nest decrements before the closer is consumed */
143 ccn_buf_check_close(d);
144 }
145 else
146 return(-1);
147 if (d->decoder.state < 0)
148 return(d->decoder.state);
149 return (0);
150}
151
152int
153ccn_parse_required_tagged_BLOB(struct ccn_buf_decoder *d, enum ccn_dtag dtag,
154 int minlen, int maxlen)
155{
156 int res = -1;
157 size_t len = 0;
158 if (ccn_buf_match_dtag(d, dtag)) {
159 res = d->decoder.element_index;
160 ccn_buf_advance(d);
161 if (ccn_buf_match_some_blob(d)) {
162 len = d->decoder.numval;
163 ccn_buf_advance(d);
164 }
165 ccn_buf_check_close(d);
166 if ((int)len < minlen || (maxlen >= 0 && (int)len > maxlen)) {
167 d->decoder.state = -__LINE__;
168 }
169 }
170 else
171 d->decoder.state = -__LINE__;
172 if (d->decoder.state < 0)
173 return (d->decoder.state);
174 return(res);
175}
176
177int
178ccn_parse_optional_tagged_BLOB(struct ccn_buf_decoder *d, enum ccn_dtag dtag,
179 int minlen, int maxlen)
180{
181 if (ccn_buf_match_dtag(d, dtag))
182 return(ccn_parse_required_tagged_BLOB(d, dtag, minlen, maxlen));
183 return(-1);
184}
185
186uintmax_t
187ccn_parse_required_tagged_binary_number(struct ccn_buf_decoder *d,
188 enum ccn_dtag dtag,
189 int minlen, int maxlen)
190{
191 uintmax_t value = 0;
192 const unsigned char *p = NULL;
193 size_t len = 0;
194 int i;
195 if (0 <= minlen && minlen <= maxlen && maxlen <= (int)sizeof(value) &&
196 ccn_buf_match_dtag(d, dtag)) {
197 ccn_buf_advance(d);
198 if (ccn_buf_match_blob(d, &p, &len))
199 ccn_buf_advance(d);
200 ccn_buf_check_close(d);
201 if (d->decoder.state < 0)
202 return(value);
203 if (minlen <= (int)len && (int)len <= maxlen)
204 for (i = 0; i < (int)len; i++)
205 value = (value << 8) + p[i];
206 else
207 d->decoder.state = -__LINE__;
208 }
209 else
210 d->decoder.state = -__LINE__;
211 return(value);
212}
213
214uintmax_t
215ccn_parse_optional_tagged_binary_number(struct ccn_buf_decoder *d, enum ccn_dtag dtag,
216 int minlen, int maxlen, uintmax_t default_value)
217{
218 if (ccn_buf_match_dtag(d, dtag))
219 return(ccn_parse_required_tagged_binary_number(d, dtag, minlen, maxlen));
220 return(default_value);
221}
222
223int
224ccn_parse_required_tagged_UDATA(struct ccn_buf_decoder *d, enum ccn_dtag dtag)
225{
226 int res = -1;
227 if (ccn_buf_match_dtag(d, dtag)) {
228 res = d->decoder.element_index;
229 ccn_buf_advance(d);
230 if (d->decoder.state >= 0 &&
231 CCN_GET_TT_FROM_DSTATE(d->decoder.state) == CCN_UDATA)
232 ccn_buf_advance(d);
233 else
234 d->decoder.state = -__LINE__;
235 ccn_buf_check_close(d);
236 }
237 else
238 d->decoder.state = -__LINE__;
239 if (d->decoder.state < 0)
240 return (-1);
241 return(res);
242}
243
244int
245ccn_parse_optional_tagged_UDATA(struct ccn_buf_decoder *d, enum ccn_dtag dtag)
246{
247 if (ccn_buf_match_dtag(d, dtag))
248 return(ccn_parse_required_tagged_UDATA(d, dtag));
249 return(-1);
250}
251
252/**
253 * Parses a ccnb-encoded element expected to contain a UDATA string.
254 * @param d is the decoder
255 * @param dtag is the expected dtag value
256 * @param store - on success, the string value is appended to store,
257 * with null termination.
258 * @returns the offset into the store buffer of the copied value, or -1 for error.
259 * If a parse error occurs, d->decoder.state is set to a negative value.
260 * If the element is not present, -1 is returned but no parse error
261 * is indicated.
262 */
263int
264ccn_parse_tagged_string(struct ccn_buf_decoder *d, enum ccn_dtag dtag, struct ccn_charbuf *store)
265{
266 const unsigned char *p = NULL;
267 size_t size = 0;
268 int res;
269
270 if (ccn_buf_match_dtag(d, dtag)) {
271 ccn_buf_advance(d);
272 if (d->decoder.state >= 0 &&
273 CCN_GET_TT_FROM_DSTATE(d->decoder.state) == CCN_UDATA) {
274 res = store->length;
275 p = d->buf + d->decoder.index;
276 size = d->decoder.numval;
277 ccn_buf_advance(d);
278 }
279 ccn_buf_check_close(d);
280 if (d->decoder.state >= 0) {
281 // XXX - should check for valid utf-8 data.
282 res = store->length;
283 if (size > 0)
284 ccn_charbuf_append(store, p, size);
285 ccn_charbuf_append_value(store, 0, 1);
286 return(res);
287 }
288 }
289 return(-1);
290}
291
292/**
293 * Parses a ccnb-encoded name
294 * @param d is the decoder
295 * @param components may be NULL, otherwise is filled in with the
296 * Component boundary offsets
297 * @returns the number of Components in the Name, or -1 if there is an error.
298 */
299int
300ccn_parse_Name(struct ccn_buf_decoder *d, struct ccn_indexbuf *components)
301{
302 int ncomp = 0;
303 if (ccn_buf_match_dtag(d, CCN_DTAG_Name)) {
304 if (components != NULL) components->n = 0;
305 ccn_buf_advance(d);
306 while (ccn_buf_match_dtag(d, CCN_DTAG_Component)) {
307 if (components != NULL)
308 ccn_indexbuf_append_element(components, d->decoder.token_index);
309 ncomp += 1;
310 ccn_buf_advance(d);
311 if (ccn_buf_match_blob(d, NULL, NULL))
312 ccn_buf_advance(d);
313 ccn_buf_check_close(d);
314 }
315 if (components != NULL)
316 ccn_indexbuf_append_element(components, d->decoder.token_index);
317 ccn_buf_check_close(d);
318 }
319 else
320 d->decoder.state = -__LINE__;
321 if (d->decoder.state < 0)
322 return(-1);
323 else
324 return(ncomp);
325}
326
327int
328ccn_parse_PublisherID(struct ccn_buf_decoder *d, struct ccn_parsed_interest *pi)
329{
330 int res = -1;
331 int iskey = 0;
332 unsigned pubstart = d->decoder.token_index;
333 unsigned keystart = pubstart;
334 unsigned keyend = pubstart;
335 unsigned pubend = pubstart;
336 iskey = ccn_buf_match_dtag(d, CCN_DTAG_PublisherPublicKeyDigest);
337 if (iskey ||
338 ccn_buf_match_dtag(d, CCN_DTAG_PublisherCertificateDigest) ||
339 ccn_buf_match_dtag(d, CCN_DTAG_PublisherIssuerKeyDigest) ||
340 ccn_buf_match_dtag(d, CCN_DTAG_PublisherIssuerCertificateDigest)) {
341 res = d->decoder.element_index;
342 ccn_buf_advance(d);
343 keystart = d->decoder.token_index;
344 if (!ccn_buf_match_some_blob(d))
345 return (d->decoder.state = -__LINE__);
346 ccn_buf_advance(d);
347 keyend = d->decoder.token_index;
348 ccn_buf_check_close(d);
349 pubend = d->decoder.token_index;
350 }
351 if (d->decoder.state < 0)
352 return (d->decoder.state);
353 if (pi != NULL) {
354 pi->offset[CCN_PI_B_PublisherID] = pubstart;
355 pi->offset[CCN_PI_B_PublisherIDKeyDigest] = keystart;
356 pi->offset[CCN_PI_E_PublisherIDKeyDigest] = iskey ? keyend : keystart;
357 pi->offset[CCN_PI_E_PublisherID] = pubend;
358 }
359 return(res);
360}
361
362static int
363ccn_parse_optional_Any_or_Bloom(struct ccn_buf_decoder *d)
364{
365 int res;
366 res = ccn_parse_optional_tagged_BLOB(d, CCN_DTAG_Bloom, 1, 1024+8);
367 if (res >= 0)
368 return(res);
369 if (ccn_buf_match_dtag(d, CCN_DTAG_Any)) {
370 ccn_buf_advance(d);
371 ccn_buf_check_close(d);
372 res = 0;
373 }
374 if (d->decoder.state < 0)
375 return (d->decoder.state);
376 return(res);
377}
378
379int
380ccn_parse_Exclude(struct ccn_buf_decoder *d)
381{
382 int res = -1;
383 if (ccn_buf_match_dtag(d, CCN_DTAG_Exclude)) {
384 res = d->decoder.element_index;
385 ccn_buf_advance(d);
386 ccn_parse_optional_Any_or_Bloom(d);
387 while (ccn_buf_match_dtag(d, CCN_DTAG_Component)) {
388 ccn_parse_required_tagged_BLOB(d, CCN_DTAG_Component, 0, -1);
389 ccn_parse_optional_Any_or_Bloom(d);
390 }
391 ccn_buf_check_close(d);
392 }
393 if (d->decoder.state < 0)
394 return (d->decoder.state);
395 return(res);
396}
397
398
399
400int
401ccn_parse_nonNegativeInteger(struct ccn_buf_decoder *d)
402{
403 const unsigned char *p;
404 int i;
405 int n;
406 int val;
407 int newval;
408 unsigned char c;
409 if (d->decoder.state < 0)
410 return(d->decoder.state);
411 if (CCN_GET_TT_FROM_DSTATE(d->decoder.state) == CCN_UDATA) {
412 p = d->buf + d->decoder.index;
413 n = d->decoder.numval;
414 if (n < 1)
415 return(d->decoder.state = -__LINE__);
416 val = 0;
417 for (i = 0; i < n; i++) {
418 c = p[i];
419 if ('0' <= c && c <= '9') {
420 newval = val * 10 + (c - '0');
421 if (newval < val)
422 return(d->decoder.state = -__LINE__);
423 val = newval;
424 }
425 else
426 return(d->decoder.state = -__LINE__);
427 }
428 ccn_buf_advance(d);
429 return(val);
430 }
431 return(d->decoder.state = -__LINE__);
432}
433
434/**
435 * Parse a potentially large non-negative integer.
436 *
437 * @returns 0 for success, and the value is place in *result; for an error
438 * a negative value is returned and *result is unchanged.
439 */
440int
441ccn_parse_uintmax(struct ccn_buf_decoder *d, uintmax_t *result)
442{
443 const unsigned char *p;
444 int i;
445 int n;
446 uintmax_t val;
447 uintmax_t newval;
448 unsigned char c;
449 if (d->decoder.state < 0)
450 return(d->decoder.state);
451 if (CCN_GET_TT_FROM_DSTATE(d->decoder.state) == CCN_UDATA) {
452 p = d->buf + d->decoder.index;
453 n = d->decoder.numval;
454 if (n < 1)
455 return(d->decoder.state = -__LINE__);
456 val = 0;
457 for (i = 0; i < n; i++) {
458 c = p[i];
459 if ('0' <= c && c <= '9') {
460 newval = val * 10 + (c - '0');
461 if (newval < val)
462 return(d->decoder.state = -__LINE__);
463 val = newval;
464 }
465 else
466 return(d->decoder.state = -__LINE__);
467 }
468 ccn_buf_advance(d);
469 *result = val;
470 return(0);
471 }
472 return(d->decoder.state = -__LINE__);
473}
474
475int
476ccn_parse_timestamp(struct ccn_buf_decoder *d)
477{
478 const unsigned char dlm[] = "--T::.Z";
479 const unsigned char *p;
480 int i;
481 int k;
482 int n;
483 if (d->decoder.state < 0)
484 return(d->decoder.state);
485 if (CCN_GET_TT_FROM_DSTATE(d->decoder.state) == CCN_BLOB) {
486 /* New-style binary timestamp, 12-bit fraction */
487 n = d->decoder.numval;
488 if (n < 3 || n > 7)
489 return(d->decoder.state = -__LINE__);
490 ccn_buf_advance(d);
491 return(0);
492 }
493 if (CCN_GET_TT_FROM_DSTATE(d->decoder.state) == CCN_UDATA) {
494 /* This is for some temporary back-compatibility */
495 p = d->buf + d->decoder.index;
496 n = d->decoder.numval;
497 if (n < 8 || n > 40)
498 return(d->decoder.state = -__LINE__);
499 if (p[n - 1] != 'Z')
500 return(d->decoder.state = -__LINE__);
501 for (i = 0, k = 0; i < n && '0' <= p[i] && p[i] <= '9';) {
502 i++;
503 if (i < n && p[i] == dlm[k]) {
504 if (dlm[k++] == 0)
505 return(d->decoder.state = -__LINE__);
506 i++;
507 }
508 }
509 if (k < 5)
510 return(d->decoder.state = -__LINE__);
511 if (!(i == n || i == n - 1))
512 return(d->decoder.state = -__LINE__);
513 ccn_buf_advance(d);
514 return(0);
515 }
516 return(d->decoder.state = -__LINE__);
517}
518
519int
520ccn_parse_required_tagged_timestamp(struct ccn_buf_decoder *d, enum ccn_dtag dtag)
521{
522 int res = -1;
523 if (ccn_buf_match_dtag(d, dtag)) {
524 res = d->decoder.element_index;
525 ccn_buf_advance(d);
526 ccn_parse_timestamp(d);
527 ccn_buf_check_close(d);
528 }
529 else
530 d->decoder.state = -__LINE__;
531 if (d->decoder.state < 0)
532 return (-1);
533 return(res);
534}
535
536int
537ccn_parse_optional_tagged_nonNegativeInteger(struct ccn_buf_decoder *d, enum ccn_dtag dtag)
538{
539 int res = -1;
540 if (ccn_buf_match_dtag(d, dtag)) {
541 ccn_buf_advance(d);
542 res = ccn_parse_nonNegativeInteger(d);
543 ccn_buf_check_close(d);
544 }
545 if (d->decoder.state < 0)
546 return (d->decoder.state);
547 return(res);
548}
549
550int
551ccn_fetch_tagged_nonNegativeInteger(enum ccn_dtag tt,
552 const unsigned char *buf,
553 size_t start, size_t stop)
554{
555 struct ccn_buf_decoder decoder;
556 struct ccn_buf_decoder *d;
557 int result = -1;
558 if (stop < start) return(-1);
559 d = ccn_buf_decoder_start(&decoder, buf + start, stop - start);
560 if (ccn_buf_match_dtag(d, tt)) {
561 ccn_buf_advance(d);
562 result = ccn_parse_nonNegativeInteger(d);
563 ccn_buf_check_close(d);
564 }
565 if (result < 0)
566 return(-1);
567 return(result);
568}
569
570
571int
572ccn_parse_interest(const unsigned char *msg, size_t size,
573 struct ccn_parsed_interest *interest,
574 struct ccn_indexbuf *components)
575{
576 struct ccn_buf_decoder decoder;
577 struct ccn_buf_decoder *d = ccn_buf_decoder_start(&decoder, msg, size);
578 int magic = 0;
579 int ncomp = 0;
580 int res;
581 if (ccn_buf_match_dtag(d, CCN_DTAG_Interest)) {
582 if (components == NULL) {
583 /* We need to have the component offsets. */
584 components = ccn_indexbuf_create();
585 if (components == NULL) return(-1);
586 res = ccn_parse_interest(msg, size, interest, components);
587 ccn_indexbuf_destroy(&components);
588 return(res);
589 }
590 ccn_buf_advance(d);
591 interest->offset[CCN_PI_B_Name] = d->decoder.element_index;
592 interest->offset[CCN_PI_B_Component0] = d->decoder.index;
593 ncomp = ccn_parse_Name(d, components);
594 if (d->decoder.state < 0) {
595 memset(interest->offset, 0, sizeof(interest->offset));
596 return(d->decoder.state);
597 }
598 interest->offset[CCN_PI_E_ComponentLast] = d->decoder.token_index - 1;
599 interest->offset[CCN_PI_E_Name] = d->decoder.token_index;
600 interest->prefix_comps = ncomp;
601 interest->offset[CCN_PI_B_LastPrefixComponent] = components->buf[(ncomp > 0) ? (ncomp - 1) : 0];
602 interest->offset[CCN_PI_E_LastPrefixComponent] = components->buf[ncomp];
603 /* optional MinSuffixComponents, MaxSuffixComponents */
604 interest->min_suffix_comps = 0;
605 interest->max_suffix_comps = 32767;
606 interest->offset[CCN_PI_B_MinSuffixComponents] = d->decoder.token_index;
607 res = ccn_parse_optional_tagged_nonNegativeInteger(d,
608 CCN_DTAG_MinSuffixComponents);
609 interest->offset[CCN_PI_E_MinSuffixComponents] = d->decoder.token_index;
610 if (res >= 0)
611 interest->min_suffix_comps = res;
612 interest->offset[CCN_PI_B_MaxSuffixComponents] = d->decoder.token_index;
613 res = ccn_parse_optional_tagged_nonNegativeInteger(d,
614 CCN_DTAG_MaxSuffixComponents);
615 interest->offset[CCN_PI_E_MaxSuffixComponents] = d->decoder.token_index;
616 if (res >= 0)
617 interest->max_suffix_comps = res;
618 if (interest->max_suffix_comps < interest->min_suffix_comps)
619 return (d->decoder.state = -__LINE__);
620 /* optional PublisherID */
621 res = ccn_parse_PublisherID(d, interest);
622 /* optional Exclude element */
623 interest->offset[CCN_PI_B_Exclude] = d->decoder.token_index;
624 res = ccn_parse_Exclude(d);
625 interest->offset[CCN_PI_E_Exclude] = d->decoder.token_index;
626 /* optional ChildSelector */
627 interest->offset[CCN_PI_B_ChildSelector] = d->decoder.token_index;
628 res = ccn_parse_optional_tagged_nonNegativeInteger(d,
629 CCN_DTAG_ChildSelector);
630 if (res < 0)
631 res = 0;
632 interest->orderpref = res;
633 interest->offset[CCN_PI_E_ChildSelector] = d->decoder.token_index;
634 if (interest->orderpref > 5)
635 return (d->decoder.state = -__LINE__);
636 /* optional AnswerOriginKind */
637 interest->offset[CCN_PI_B_AnswerOriginKind] = d->decoder.token_index;
638 interest->answerfrom = ccn_parse_optional_tagged_nonNegativeInteger(d,
639 CCN_DTAG_AnswerOriginKind);
640 interest->offset[CCN_PI_E_AnswerOriginKind] = d->decoder.token_index;
641 if (interest->answerfrom == -1)
642 interest->answerfrom = CCN_AOK_DEFAULT;
643 else if ((interest->answerfrom & CCN_AOK_NEW) != 0 &&
644 (interest->answerfrom & CCN_AOK_CS) == 0)
645 return (d->decoder.state = -__LINE__);
646 /* optional Scope */
647 interest->offset[CCN_PI_B_Scope] = d->decoder.token_index;
648 interest->scope = ccn_parse_optional_tagged_nonNegativeInteger(d,
649 CCN_DTAG_Scope);
650 interest->offset[CCN_PI_E_Scope] = d->decoder.token_index;
651 if (interest->scope > 9)
652 return (d->decoder.state = -__LINE__);
653 if ((interest->answerfrom & CCN_AOK_EXPIRE) != 0 &&
654 interest->scope != 0)
655 return (d->decoder.state = -__LINE__);
656 /* optional InterestLifetime */
657 interest->offset[CCN_PI_B_InterestLifetime] = d->decoder.token_index;
658 res = ccn_parse_optional_tagged_BLOB(d, CCN_DTAG_InterestLifetime, 1, 8);
659 if (res >= 0)
660 magic |= 20100401;
661 interest->offset[CCN_PI_E_InterestLifetime] = d->decoder.token_index;
662 /* optional Nonce */
663 interest->offset[CCN_PI_B_Nonce] = d->decoder.token_index;
664 res = ccn_parse_optional_tagged_BLOB(d, CCN_DTAG_Nonce, 4, 64);
665 interest->offset[CCN_PI_E_Nonce] = d->decoder.token_index;
666 /* Allow for no experimental stuff */
667 interest->offset[CCN_PI_B_OTHER] = d->decoder.token_index;
668 interest->offset[CCN_PI_E_OTHER] = d->decoder.token_index;
669 ccn_buf_check_close(d);
670 interest->offset[CCN_PI_E] = d->decoder.index;
671 }
672 else
673 return (d->decoder.state = -__LINE__);
674 if (d->decoder.state < 0)
675 return (d->decoder.state);
676 if (d->decoder.index != (int)size || !CCN_FINAL_DSTATE(d->decoder.state))
677 return (CCN_DSTATE_ERR_CODING);
678 if (magic == 0)
679 magic = 20090701;
680 if (!(magic == 20090701 || magic == 20100401))
681 return (d->decoder.state = -__LINE__);
682 interest->magic = magic;
683 return (ncomp);
684}
685
686struct parsed_KeyName {
687 int Name;
688 int endName;
689 int PublisherID;
690 int endPublisherID;
691};
692
693static int
694ccn_parse_KeyName(struct ccn_buf_decoder *d, struct parsed_KeyName *x)
695{
696 int res = -1;
697 if (ccn_buf_match_dtag(d, CCN_DTAG_KeyName)) {
698 res = d->decoder.element_index;
699 ccn_buf_advance(d);
700 x->Name = d->decoder.token_index;
701 ccn_parse_Name(d, NULL);
702 x->endName = d->decoder.token_index;
703 x->PublisherID = ccn_parse_PublisherID(d, NULL);
704 x->endPublisherID = d->decoder.token_index;
705 ccn_buf_check_close(d);
706 }
707 else
708 d->decoder.state = -__LINE__;
709 if (d->decoder.state < 0)
710 return (d->decoder.state);
711 return(res);
712}
713
714static int
715ccn_parse_Signature(struct ccn_buf_decoder *d, struct ccn_parsed_ContentObject *x)
716{
717 int res = -1;
718 int i;
719 struct ccn_parsed_ContentObject dummy;
720 if (x == NULL)
721 x = &dummy;
722 for (i = CCN_PCO_B_Signature; i <= CCN_PCO_E_Signature; i++) {
723 x->offset[i] = d->decoder.token_index;
724 }
725 if (ccn_buf_match_dtag(d, CCN_DTAG_Signature)) {
726 res = d->decoder.element_index;
727 ccn_buf_advance(d);
728 x->offset[CCN_PCO_B_DigestAlgorithm] = d->decoder.token_index;
729 ccn_parse_optional_tagged_UDATA(d, CCN_DTAG_DigestAlgorithm);
730 x->offset[CCN_PCO_E_DigestAlgorithm] = d->decoder.token_index;
731 x->offset[CCN_PCO_B_Witness] = d->decoder.token_index;
732 ccn_parse_optional_tagged_BLOB(d, CCN_DTAG_Witness, 8, -1);
733 x->offset[CCN_PCO_E_Witness] = d->decoder.token_index;
734 x->offset[CCN_PCO_B_SignatureBits] = d->decoder.token_index;
735 ccn_parse_required_tagged_BLOB(d, CCN_DTAG_SignatureBits, 16, -1);
736 x->offset[CCN_PCO_E_SignatureBits] = d->decoder.token_index;
737 ccn_buf_check_close(d);
738 x->offset[CCN_PCO_E_Signature] = d->decoder.token_index;
739 }
740 if (d->decoder.state < 0)
741 return (d->decoder.state);
742 return(res);
743}
744
745static int
746ccn_parse_SignedInfo(struct ccn_buf_decoder *d, struct ccn_parsed_ContentObject *x)
747{
748 x->offset[CCN_PCO_B_SignedInfo] = d->decoder.token_index;
749 if (ccn_buf_match_dtag(d, CCN_DTAG_SignedInfo)) {
750 ccn_buf_advance(d);
751 x->offset[CCN_PCO_B_PublisherPublicKeyDigest] = d->decoder.token_index;
752 ccn_parse_required_tagged_BLOB(d, CCN_DTAG_PublisherPublicKeyDigest, 16, 64);
753 x->offset[CCN_PCO_E_PublisherPublicKeyDigest] = d->decoder.token_index;
754
755 x->offset[CCN_PCO_B_Timestamp] = d->decoder.token_index;
756 ccn_parse_required_tagged_timestamp(d, CCN_DTAG_Timestamp);
757 x->offset[CCN_PCO_E_Timestamp] = d->decoder.token_index;
758
759 x->offset[CCN_PCO_B_Type] = d->decoder.token_index;
760 x->type = CCN_CONTENT_DATA;
761 x->type = (ccn_content_type)ccn_parse_optional_tagged_binary_number(d, CCN_DTAG_Type, 3, 3, CCN_CONTENT_DATA);
762 x->offset[CCN_PCO_E_Type] = d->decoder.token_index;
763
764 x->offset[CCN_PCO_B_FreshnessSeconds] = d->decoder.token_index;
765 ccn_parse_optional_tagged_nonNegativeInteger(d, CCN_DTAG_FreshnessSeconds);
766 x->offset[CCN_PCO_E_FreshnessSeconds] = d->decoder.token_index;
767
768 x->offset[CCN_PCO_B_FinalBlockID] = d->decoder.token_index;
769 ccn_parse_optional_tagged_BLOB(d, CCN_DTAG_FinalBlockID, 1, -1);
770 x->offset[CCN_PCO_E_FinalBlockID] = d->decoder.token_index;
771
772 x->offset[CCN_PCO_B_KeyLocator] = d->decoder.token_index;
773 x->offset[CCN_PCO_B_Key_Certificate_KeyName] = d->decoder.token_index;
774 x->offset[CCN_PCO_E_Key_Certificate_KeyName] = d->decoder.token_index;
775 x->offset[CCN_PCO_B_KeyName_Name] = d->decoder.token_index;
776 x->offset[CCN_PCO_E_KeyName_Name] = d->decoder.token_index;
777 x->offset[CCN_PCO_B_KeyName_Pub] = d->decoder.token_index;
778 x->offset[CCN_PCO_E_KeyName_Pub] = d->decoder.token_index;
779 if (ccn_buf_match_dtag(d, CCN_DTAG_KeyLocator)) {
780 ccn_buf_advance(d);
781 x->offset[CCN_PCO_B_Key_Certificate_KeyName] = d->decoder.token_index;
782 if (ccn_buf_match_dtag(d, CCN_DTAG_Key)) {
783 (void)ccn_parse_required_tagged_BLOB(d, CCN_DTAG_Key, 0, -1);
784 }
785 else if (ccn_buf_match_dtag(d, CCN_DTAG_Certificate)) {
786 (void)ccn_parse_required_tagged_BLOB(d, CCN_DTAG_Certificate, 0, -1);
787 }
788 else {
789 struct parsed_KeyName keyname = {-1, -1, -1, -1};
790 if (ccn_parse_KeyName(d, &keyname) >= 0) {
791 if (keyname.Name >= 0) {
792 x->offset[CCN_PCO_B_KeyName_Name] = keyname.Name;
793 x->offset[CCN_PCO_E_KeyName_Name] = keyname.endName;
794 }
795 if (keyname.PublisherID >= 0) {
796 x->offset[CCN_PCO_B_KeyName_Pub] = keyname.PublisherID;
797 x->offset[CCN_PCO_E_KeyName_Pub] = keyname.endPublisherID;
798 }
799 }
800 }
801 x->offset[CCN_PCO_E_Key_Certificate_KeyName] = d->decoder.token_index;
802 ccn_buf_check_close(d);
803 }
804 x->offset[CCN_PCO_E_KeyLocator] = d->decoder.token_index;
805 ccn_buf_check_close(d);
806 }
807 else
808 d->decoder.state = -__LINE__;
809 x->offset[CCN_PCO_E_SignedInfo] = d->decoder.token_index;
810 if (d->decoder.state < 0)
811 return (d->decoder.state);
812 return(0);
813}
814
815int
816ccn_parse_ContentObject(const unsigned char *msg, size_t size,
817 struct ccn_parsed_ContentObject *x,
818 struct ccn_indexbuf *components)
819{
820 struct ccn_buf_decoder decoder;
821 struct ccn_buf_decoder *d = ccn_buf_decoder_start(&decoder, msg, size);
822 int res;
823 x->magic = 20090415;
824 x->digest_bytes = 0;
825 if (ccn_buf_match_dtag(d, CCN_DTAG_ContentObject)) {
826 ccn_buf_advance(d);
827 res = ccn_parse_Signature(d, x);
828 x->offset[CCN_PCO_B_Name] = d->decoder.token_index;
829 x->offset[CCN_PCO_B_Component0] = d->decoder.index;
830 res = ccn_parse_Name(d, components);
831 if (res < 0)
832 d->decoder.state = -__LINE__;
833 x->name_ncomps = res;
834 x->offset[CCN_PCO_E_ComponentLast] = d->decoder.token_index - 1;
835 x->offset[CCN_PCO_E_Name] = d->decoder.token_index;
836 ccn_parse_SignedInfo(d, x);
837 x->offset[CCN_PCO_B_Content] = d->decoder.token_index;
838 ccn_parse_required_tagged_BLOB(d, CCN_DTAG_Content, 0, -1);
839 x->offset[CCN_PCO_E_Content] = d->decoder.token_index;
840 ccn_buf_check_close(d);
841 x->offset[CCN_PCO_E] = d->decoder.index;
842 }
843 else
844 d->decoder.state = -__LINE__;
845 if (d->decoder.index != (int)size || !CCN_FINAL_DSTATE(d->decoder.state))
846 return (CCN_DSTATE_ERR_CODING);
847 return(0);
848}
849
850int
851ccn_ref_tagged_BLOB(enum ccn_dtag tt,
852 const unsigned char *buf, size_t start, size_t stop,
853 const unsigned char **presult, size_t *psize)
854{
855 struct ccn_buf_decoder decoder;
856 struct ccn_buf_decoder *d;
857 if (stop < start) return(-1);
858 d = ccn_buf_decoder_start(&decoder, buf + start, stop - start);
859 if (ccn_buf_match_dtag(d, tt)) {
860 ccn_buf_advance(d);
861 if (ccn_buf_match_blob(d, presult, psize))
862 ccn_buf_advance(d);
863 ccn_buf_check_close(d);
864 }
865 else
866 return(-1);
867 if (d->decoder.index != (int)d->size || !CCN_FINAL_DSTATE(d->decoder.state))
868 return (CCN_DSTATE_ERR_CODING);
869 return(0);
870}
871
872static struct ccn_buf_decoder *
873ccn_buf_decoder_start_at_components(struct ccn_buf_decoder *d,
874 const unsigned char *buf, size_t buflen)
875{
876 ccn_buf_decoder_start(d, buf, buflen);
877 while (ccn_buf_match_dtag(d, CCN_DTAG_Name) ||
878 ccn_buf_match_dtag(d, CCN_DTAG_Interest) ||
879 ccn_buf_match_dtag(d, CCN_DTAG_ContentObject)
880 ) {
881 ccn_buf_advance(d);
882 ccn_parse_Signature(d, NULL);
883 }
884 return(d);
885}
886
887int
888ccn_content_get_value(const unsigned char *data, size_t data_size,
889 const struct ccn_parsed_ContentObject *content,
890 const unsigned char **value, size_t *value_size)
891{
892 int res;
893 res = ccn_ref_tagged_BLOB(CCN_DTAG_Content, data,
894 content->offset[CCN_PCO_B_Content],
895 content->offset[CCN_PCO_E_Content],
896 value, value_size);
897 return(res);
898}
899
900int
901ccn_compare_names(const unsigned char *a, size_t asize,
902 const unsigned char *b, size_t bsize)
903{
904 struct ccn_buf_decoder a_decoder;
905 struct ccn_buf_decoder b_decoder;
906 struct ccn_buf_decoder *aa =
907 ccn_buf_decoder_start_at_components(&a_decoder, a, asize);
908 struct ccn_buf_decoder *bb =
909 ccn_buf_decoder_start_at_components(&b_decoder, b, bsize);
910 const unsigned char *acp = NULL;
911 const unsigned char *bcp = NULL;
912 size_t acsize;
913 size_t bcsize;
914 int cmp = 0;
915 int more_a;
916 for (;;) {
917 more_a = ccn_buf_match_dtag(aa, CCN_DTAG_Component);
918 cmp = more_a - ccn_buf_match_dtag(bb, CCN_DTAG_Component);
919 if (more_a == 0 || cmp != 0)
920 break;
921 ccn_buf_advance(aa);
922 ccn_buf_advance(bb);
923 acsize = bcsize = 0;
924 if (ccn_buf_match_blob(aa, &acp, &acsize))
925 ccn_buf_advance(aa);
926 if (ccn_buf_match_blob(bb, &bcp, &bcsize))
927 ccn_buf_advance(bb);
928 cmp = acsize - bcsize;
929 if (cmp != 0)
930 break;
931 cmp = memcmp(acp, bcp, acsize);
932 if (cmp != 0)
933 break;
934 ccn_buf_check_close(aa);
935 ccn_buf_check_close(bb);
936 }
937 return (cmp);
938}
939