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