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