ccn_buf_decoder.c

Go to the documentation of this file.
00001 /**
00002  * @file ccn_buf_decoder.c
00003  * @brief Support for Interest and ContentObject decoding.
00004  * 
00005  * Part of the CCNx C Library.
00006  *
00007  * Copyright (C) 2008, 2009, 2010, 2011 Palo Alto Research Center, Inc.
00008  *
00009  * This library is free software; you can redistribute it and/or modify it
00010  * under the terms of the GNU Lesser General Public License version 2.1
00011  * as published by the Free Software Foundation.
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00015  * Lesser General Public License for more details. You should have received
00016  * a copy of the GNU Lesser General Public License along with this library;
00017  * if not, write to the Free Software Foundation, Inc., 51 Franklin Street,
00018  * Fifth Floor, Boston, MA 02110-1301 USA.
00019  */
00020 #include <string.h>
00021 #include <stdlib.h>
00022 #include <ccn/ccn.h>
00023 #include <ccn/charbuf.h>
00024 #include <ccn/coding.h>
00025 #include <ccn/indexbuf.h>
00026 
00027 struct ccn_buf_decoder *
00028 ccn_buf_decoder_start(struct ccn_buf_decoder *d,
00029                       const unsigned char *buf, size_t size)
00030 {
00031     memset(&d->decoder, 0, sizeof(d->decoder));
00032     d->decoder.state |= CCN_DSTATE_PAUSE;
00033     d->buf = buf;
00034     d->size = size;
00035     ccn_skeleton_decode(&d->decoder, buf, size);
00036     return(d);
00037 }
00038 
00039 void
00040 ccn_buf_advance(struct ccn_buf_decoder *d)
00041 {
00042     ccn_skeleton_decode(&d->decoder,
00043                         d->buf + d->decoder.index,
00044                         d->size - d->decoder.index);
00045 }
00046 
00047 int
00048 ccn_buf_match_dtag(struct ccn_buf_decoder *d, enum ccn_dtag dtag)
00049 {
00050     return (d->decoder.state >= 0 &&
00051             CCN_GET_TT_FROM_DSTATE(d->decoder.state) == CCN_DTAG &&
00052             d->decoder.numval == dtag);
00053 }
00054 
00055 int
00056 ccn_buf_match_some_dtag(struct ccn_buf_decoder *d)
00057 {
00058     return(d->decoder.state >= 0 &&
00059            CCN_GET_TT_FROM_DSTATE(d->decoder.state) == CCN_DTAG);
00060 }
00061 
00062 int
00063 ccn_buf_match_some_blob(struct ccn_buf_decoder *d)
00064 {
00065     return(d->decoder.state >= 0 &&
00066            CCN_GET_TT_FROM_DSTATE(d->decoder.state) == CCN_BLOB);
00067 }
00068 
00069 int
00070 ccn_buf_match_blob(struct ccn_buf_decoder *d,
00071                    const unsigned char **bufp, size_t *sizep)
00072 {
00073     if (ccn_buf_match_some_blob(d)) {
00074         if (bufp != NULL)
00075             *bufp = d->buf + d->decoder.index;
00076         if (sizep != NULL)
00077             *sizep = d->decoder.numval;
00078         return (1);
00079     }
00080     if (bufp != NULL)
00081         *bufp = d->buf + d->decoder.token_index;
00082     if (sizep != NULL)
00083         *sizep = 0;
00084     return(0);
00085 }
00086 
00087 int
00088 ccn_buf_match_udata(struct ccn_buf_decoder *d, const char *s)
00089 {
00090     size_t len = strlen(s);
00091     return (d->decoder.state >= 0 &&
00092             CCN_GET_TT_FROM_DSTATE(d->decoder.state) == CCN_UDATA &&
00093             d->decoder.numval == len &&
00094             0 == memcmp(d->buf + d->decoder.index, s, len));
00095 }
00096 
00097 int
00098 ccn_buf_match_attr(struct ccn_buf_decoder *d, const char *s)
00099 {
00100     size_t len = strlen(s);
00101     return (d->decoder.state >= 0 &&
00102             CCN_GET_TT_FROM_DSTATE(d->decoder.state) == CCN_ATTR &&
00103             d->decoder.numval == len &&
00104             0 == memcmp(d->buf + d->decoder.index, s, len));
00105 }
00106 
00107 void
00108 ccn_buf_check_close(struct ccn_buf_decoder *d)
00109 {
00110     if (d->decoder.state >= 0) {
00111         if (CCN_GET_TT_FROM_DSTATE(d->decoder.state) != CCN_NO_TOKEN)
00112             d->decoder.state = CCN_DSTATE_ERR_NEST;
00113         else
00114             ccn_buf_advance(d);
00115     }
00116 }
00117 
00118 int
00119 ccn_buf_advance_past_element(struct ccn_buf_decoder *d)
00120 {
00121     enum ccn_tt tt;
00122     int nest;
00123     if (d->decoder.state < 0)
00124         return(d->decoder.state);
00125     tt = CCN_GET_TT_FROM_DSTATE(d->decoder.state);
00126     if (tt == CCN_DTAG || tt == CCN_TAG) {
00127         nest = d->decoder.nest;
00128         ccn_buf_advance(d);
00129         while (d->decoder.state >= 0 && d->decoder.nest >= nest)
00130             ccn_buf_advance(d);
00131         /* The nest decrements before the closer is consumed */
00132         ccn_buf_check_close(d);
00133     }
00134     else
00135         return(-1);
00136     if (d->decoder.state < 0)
00137         return(d->decoder.state);
00138     return (0);
00139 }
00140 
00141 int
00142 ccn_parse_required_tagged_BLOB(struct ccn_buf_decoder *d, enum ccn_dtag dtag,
00143                                int minlen, int maxlen)
00144 {
00145     int res = -1;
00146     size_t len = 0;
00147     if (ccn_buf_match_dtag(d, dtag)) {
00148         res = d->decoder.element_index;
00149         ccn_buf_advance(d);
00150         if (ccn_buf_match_some_blob(d)) {
00151             len = d->decoder.numval;
00152             ccn_buf_advance(d);
00153         }
00154         ccn_buf_check_close(d);
00155         if (len < minlen || (maxlen >= 0 && len > maxlen)) {
00156             d->decoder.state = -__LINE__;
00157         }
00158     }
00159     else
00160         d->decoder.state = -__LINE__;
00161     if (d->decoder.state < 0)
00162         return (d->decoder.state);
00163     return(res);
00164 }
00165 
00166 int
00167 ccn_parse_optional_tagged_BLOB(struct ccn_buf_decoder *d, enum ccn_dtag dtag,
00168                                int minlen, int maxlen)
00169 {
00170     if (ccn_buf_match_dtag(d, dtag))
00171         return(ccn_parse_required_tagged_BLOB(d, dtag, minlen, maxlen));
00172     return(-1);
00173 }
00174 
00175 uintmax_t
00176 ccn_parse_required_tagged_binary_number(struct ccn_buf_decoder *d,
00177                                         enum ccn_dtag dtag,
00178                                         int minlen, int maxlen)
00179 {
00180     uintmax_t value = 0;
00181     const unsigned char *p = NULL;
00182     size_t len = 0;
00183     int i;
00184     if (0 <= minlen && minlen <= maxlen && maxlen <= sizeof(value) &&
00185           ccn_buf_match_dtag(d, dtag)) {
00186         ccn_buf_advance(d);
00187         if (ccn_buf_match_blob(d, &p, &len))
00188             ccn_buf_advance(d);
00189         ccn_buf_check_close(d);
00190         if (d->decoder.state < 0)
00191             return(value);
00192         if (minlen <= len && len <= maxlen)
00193             for (i = 0; i < len; i++)
00194                 value = (value << 8) + p[i];
00195         else
00196             d->decoder.state = -__LINE__;
00197     }
00198     else
00199         d->decoder.state = -__LINE__;
00200     return(value);
00201 }
00202 
00203 uintmax_t
00204 ccn_parse_optional_tagged_binary_number(struct ccn_buf_decoder *d, enum ccn_dtag dtag,
00205 int minlen, int maxlen, uintmax_t default_value)
00206 {
00207     if (ccn_buf_match_dtag(d, dtag))
00208         return(ccn_parse_required_tagged_binary_number(d, dtag, minlen, maxlen));
00209     return(default_value);
00210 }
00211 
00212 int
00213 ccn_parse_required_tagged_UDATA(struct ccn_buf_decoder *d, enum ccn_dtag dtag)
00214 {
00215     int res = -1;
00216     if (ccn_buf_match_dtag(d, dtag)) {
00217         res = d->decoder.element_index;
00218         ccn_buf_advance(d);
00219         if (d->decoder.state >= 0 &&
00220             CCN_GET_TT_FROM_DSTATE(d->decoder.state) == CCN_UDATA)
00221             ccn_buf_advance(d);
00222         else
00223             d->decoder.state = -__LINE__;
00224         ccn_buf_check_close(d);
00225     }
00226     else
00227         d->decoder.state = -__LINE__;
00228     if (d->decoder.state < 0)
00229         return (-1);
00230     return(res);
00231 }
00232 
00233 int
00234 ccn_parse_optional_tagged_UDATA(struct ccn_buf_decoder *d, enum ccn_dtag dtag)
00235 {
00236     if (ccn_buf_match_dtag(d, dtag))
00237         return(ccn_parse_required_tagged_UDATA(d, dtag));
00238     return(-1);
00239 }
00240 
00241 /**
00242  * Parses a ccnb-encoded element expected to contain a UDATA string.
00243  * @param d is the decoder
00244  * @param dtag is the expected dtag value
00245  * @param store - on success, the string value is appended to store,
00246  *        with null termination.
00247  * @returns the offset into the store buffer of the copied value, or -1 for error.
00248  *        If a parse error occurs, d->decoder.state is set to a negative value.
00249  *        If the element is not present, -1 is returned but no parse error
00250  *        is indicated.
00251  */
00252 int
00253 ccn_parse_tagged_string(struct ccn_buf_decoder *d, enum ccn_dtag dtag, struct ccn_charbuf *store)
00254 {
00255     const unsigned char *p = NULL;
00256     size_t size = 0;
00257     int res;
00258     
00259     if (ccn_buf_match_dtag(d, dtag)) {
00260         ccn_buf_advance(d);
00261         if (d->decoder.state >= 0 &&
00262             CCN_GET_TT_FROM_DSTATE(d->decoder.state) == CCN_UDATA) {
00263             p = d->buf + d->decoder.index;
00264             size = d->decoder.numval;
00265             ccn_buf_advance(d);
00266         }
00267         ccn_buf_check_close(d);
00268         if (d->decoder.state >= 0) {
00269             // XXX - should check for valid utf-8 data.
00270             res = store->length;
00271             if (size > 0)
00272                 ccn_charbuf_append(store, p, size);
00273             ccn_charbuf_append_value(store, 0, 1);
00274             return(res);
00275         }
00276     }
00277     return(-1);
00278 }
00279 
00280 /**
00281  * Parses a ccnb-encoded name
00282  * @param d is the decoder
00283  * @param components may be NULL, otherwise is filled in with the 
00284  *        Component boundary offsets
00285  * @returns the number of Components in the Name, or -1 if there is an error.
00286  */
00287 int
00288 ccn_parse_Name(struct ccn_buf_decoder *d, struct ccn_indexbuf *components)
00289 {
00290     int ncomp = 0;
00291     if (ccn_buf_match_dtag(d, CCN_DTAG_Name)) {
00292         if (components != NULL) components->n = 0;
00293         ccn_buf_advance(d);
00294         while (ccn_buf_match_dtag(d, CCN_DTAG_Component)) {
00295             if (components != NULL)
00296                 ccn_indexbuf_append_element(components, d->decoder.token_index);
00297             ncomp += 1;
00298             ccn_buf_advance(d);
00299             if (ccn_buf_match_blob(d, NULL, NULL))
00300                 ccn_buf_advance(d);
00301             ccn_buf_check_close(d);
00302         }
00303         if (components != NULL)
00304             ccn_indexbuf_append_element(components, d->decoder.token_index);
00305         ccn_buf_check_close(d);
00306     }
00307     else
00308         d->decoder.state = -__LINE__;
00309     if (d->decoder.state < 0)
00310         return(-1);
00311     else
00312         return(ncomp);
00313 }
00314 
00315 int
00316 ccn_parse_PublisherID(struct ccn_buf_decoder *d, struct ccn_parsed_interest *pi)
00317 {
00318     int res = -1;
00319     int iskey = 0;
00320     unsigned pubstart = d->decoder.token_index;
00321     unsigned keystart = pubstart;
00322     unsigned keyend = pubstart;
00323     unsigned pubend = pubstart;
00324     iskey = ccn_buf_match_dtag(d, CCN_DTAG_PublisherPublicKeyDigest);
00325     if (iskey                                                          ||
00326         ccn_buf_match_dtag(d, CCN_DTAG_PublisherCertificateDigest)     ||
00327         ccn_buf_match_dtag(d, CCN_DTAG_PublisherIssuerKeyDigest)       ||
00328         ccn_buf_match_dtag(d, CCN_DTAG_PublisherIssuerCertificateDigest)) {
00329         res = d->decoder.element_index;
00330         ccn_buf_advance(d);
00331         keystart = d->decoder.token_index;
00332         if (!ccn_buf_match_some_blob(d))
00333             return (d->decoder.state = -__LINE__);
00334         ccn_buf_advance(d);
00335         keyend = d->decoder.token_index;
00336         ccn_buf_check_close(d);
00337         pubend = d->decoder.token_index;
00338     }
00339     if (d->decoder.state < 0)
00340         return (d->decoder.state);
00341     if (pi != NULL) {
00342         pi->offset[CCN_PI_B_PublisherID] = pubstart;
00343         pi->offset[CCN_PI_B_PublisherIDKeyDigest] = keystart;
00344         pi->offset[CCN_PI_E_PublisherIDKeyDigest] = iskey ? keyend : keystart;
00345         pi->offset[CCN_PI_E_PublisherID] = pubend;
00346     }
00347     return(res);
00348 }
00349 
00350 static int
00351 ccn_parse_optional_Any_or_Bloom(struct ccn_buf_decoder *d)
00352 {
00353     int res;
00354     res = ccn_parse_optional_tagged_BLOB(d, CCN_DTAG_Bloom, 1, 1024+8);
00355     if (res >= 0)
00356         return(res);
00357     if (ccn_buf_match_dtag(d, CCN_DTAG_Any)) {
00358         ccn_buf_advance(d);
00359         ccn_buf_check_close(d);
00360         res = 0;
00361     }
00362     if (d->decoder.state < 0)
00363         return (d->decoder.state);
00364     return(res);
00365 }
00366 
00367 int
00368 ccn_parse_Exclude(struct ccn_buf_decoder *d)
00369 {
00370     int res = -1;
00371     if (ccn_buf_match_dtag(d, CCN_DTAG_Exclude)) {
00372         res = d->decoder.element_index;
00373         ccn_buf_advance(d);
00374         ccn_parse_optional_Any_or_Bloom(d);
00375         while (ccn_buf_match_dtag(d, CCN_DTAG_Component)) {
00376             ccn_parse_required_tagged_BLOB(d, CCN_DTAG_Component, 0, -1);
00377             ccn_parse_optional_Any_or_Bloom(d);
00378         }
00379         ccn_buf_check_close(d);
00380     }
00381     if (d->decoder.state < 0)
00382         return (d->decoder.state);
00383     return(res);
00384 }
00385 
00386 
00387 
00388 int
00389 ccn_parse_nonNegativeInteger(struct ccn_buf_decoder *d)
00390 {
00391     const unsigned char *p;
00392     int i;
00393     int n;
00394     int val;
00395     int newval;
00396     unsigned char c;
00397     if (d->decoder.state < 0)
00398         return(d->decoder.state);
00399     if (CCN_GET_TT_FROM_DSTATE(d->decoder.state) == CCN_UDATA) {
00400         p = d->buf + d->decoder.index;
00401         n = d->decoder.numval;
00402         if (n < 1)
00403             return(d->decoder.state = -__LINE__);
00404         val = 0;
00405         for (i = 0; i < n; i++) {
00406             c = p[i];
00407             if ('0' <= c && c <= '9') {
00408                 newval = val * 10 + (c - '0');
00409                 if (newval < val)
00410                     return(d->decoder.state = -__LINE__);
00411                 val = newval;
00412             }
00413             else
00414                 return(d->decoder.state = -__LINE__);
00415         }
00416         ccn_buf_advance(d);
00417         return(val);
00418     }
00419     return(d->decoder.state = -__LINE__);
00420 }
00421 
00422 /**
00423  * Parse a potentially large non-negative integer.
00424  *
00425  * @returns 0 for success, and the value is place in *result; for an error
00426  * a negative value is returned and *result is unchanged.
00427  */
00428 int
00429 ccn_parse_uintmax(struct ccn_buf_decoder *d, uintmax_t *result)
00430 {
00431     const unsigned char *p;
00432     int i;
00433     int n;
00434     uintmax_t val;
00435     uintmax_t newval;
00436     unsigned char c;
00437     if (d->decoder.state < 0)
00438         return(d->decoder.state);
00439     if (CCN_GET_TT_FROM_DSTATE(d->decoder.state) == CCN_UDATA) {
00440         p = d->buf + d->decoder.index;
00441         n = d->decoder.numval;
00442         if (n < 1)
00443             return(d->decoder.state = -__LINE__);
00444         val = 0;
00445         for (i = 0; i < n; i++) {
00446             c = p[i];
00447             if ('0' <= c && c <= '9') {
00448                 newval = val * 10 + (c - '0');
00449                 if (newval < val)
00450                     return(d->decoder.state = -__LINE__);
00451                 val = newval;
00452             }
00453             else
00454                 return(d->decoder.state = -__LINE__);
00455         }
00456         ccn_buf_advance(d);
00457         *result = val;
00458         return(0);
00459     }
00460     return(d->decoder.state = -__LINE__);
00461 }
00462 
00463 int
00464 ccn_parse_timestamp(struct ccn_buf_decoder *d)
00465 {
00466     const unsigned char dlm[] = "--T::.Z";
00467     const unsigned char *p;
00468     int i;
00469     int k;
00470     int n;
00471     if (d->decoder.state < 0)
00472         return(d->decoder.state);
00473     if (CCN_GET_TT_FROM_DSTATE(d->decoder.state) == CCN_BLOB) {
00474         /* New-style binary timestamp, 12-bit fraction */
00475         n = d->decoder.numval;
00476         if (n < 3 || n > 7)
00477             return(d->decoder.state = -__LINE__);
00478         ccn_buf_advance(d);
00479         return(0);
00480     }
00481     if (CCN_GET_TT_FROM_DSTATE(d->decoder.state) == CCN_UDATA) {
00482         /* This is for some temporary back-compatibility */
00483         p = d->buf + d->decoder.index;
00484         n = d->decoder.numval;
00485         if (n < 8 || n > 40)
00486             return(d->decoder.state = -__LINE__);
00487         if (p[n - 1] != 'Z')
00488             return(d->decoder.state = -__LINE__);
00489         for (i = 0, k = 0; i < n && '0' <= p[i] && p[i] <= '9';) {
00490             i++;
00491             if (i < n && p[i] == dlm[k]) {
00492                 if (dlm[k++] == 0)
00493                     return(d->decoder.state = -__LINE__);
00494                 i++;
00495             }
00496         }
00497         if (k < 5)
00498             return(d->decoder.state = -__LINE__);
00499         if (!(i == n || i == n - 1))
00500             return(d->decoder.state = -__LINE__);
00501         ccn_buf_advance(d);
00502         return(0);
00503     }
00504     return(d->decoder.state = -__LINE__);
00505 }
00506 
00507 int
00508 ccn_parse_required_tagged_timestamp(struct ccn_buf_decoder *d, enum ccn_dtag dtag)
00509 {
00510     int res = -1;
00511     if (ccn_buf_match_dtag(d, dtag)) {
00512         res = d->decoder.element_index;
00513         ccn_buf_advance(d);
00514         ccn_parse_timestamp(d);
00515         ccn_buf_check_close(d);
00516     }
00517     else
00518         d->decoder.state = -__LINE__;
00519     if (d->decoder.state < 0)
00520         return (-1);
00521     return(res);
00522 }
00523 
00524 int
00525 ccn_parse_optional_tagged_nonNegativeInteger(struct ccn_buf_decoder *d, enum ccn_dtag dtag)
00526 {
00527     int res = -1;
00528     if (ccn_buf_match_dtag(d, dtag)) {
00529         ccn_buf_advance(d);
00530         res = ccn_parse_nonNegativeInteger(d);
00531         ccn_buf_check_close(d);
00532     }
00533     if (d->decoder.state < 0)
00534         return (d->decoder.state);
00535     return(res);
00536 }
00537 
00538 int
00539 ccn_fetch_tagged_nonNegativeInteger(enum ccn_dtag tt,
00540                                     const unsigned char *buf,
00541                                     size_t start, size_t stop)
00542 {
00543     struct ccn_buf_decoder decoder;
00544     struct ccn_buf_decoder *d;
00545     int result = -1;
00546     if (stop < start) return(-1);
00547     d = ccn_buf_decoder_start(&decoder, buf + start, stop - start);
00548     if (ccn_buf_match_dtag(d, tt)) {
00549         ccn_buf_advance(d);
00550         result = ccn_parse_nonNegativeInteger(d);
00551         ccn_buf_check_close(d);
00552     }
00553     if (result < 0)
00554         return(-1);
00555     return(result);
00556 }
00557 
00558 
00559 int
00560 ccn_parse_interest(const unsigned char *msg, size_t size,
00561                    struct ccn_parsed_interest *interest,
00562                    struct ccn_indexbuf *components)
00563 {
00564     struct ccn_buf_decoder decoder;
00565     struct ccn_buf_decoder *d = ccn_buf_decoder_start(&decoder, msg, size);
00566     int magic = 0;
00567     int ncomp = 0;
00568     int res;
00569     if (ccn_buf_match_dtag(d, CCN_DTAG_Interest)) {
00570         if (components == NULL) {
00571             /* We need to have the component offsets. */
00572             components = ccn_indexbuf_create();
00573             if (components == NULL) return(-1);
00574             res = ccn_parse_interest(msg, size, interest, components);
00575             ccn_indexbuf_destroy(&components);
00576             return(res);
00577         }
00578         ccn_buf_advance(d);
00579         interest->offset[CCN_PI_B_Name] = d->decoder.element_index;
00580         interest->offset[CCN_PI_B_Component0] = d->decoder.index;
00581         ncomp = ccn_parse_Name(d, components);
00582         if (d->decoder.state < 0) {
00583             memset(interest->offset, 0, sizeof(interest->offset));
00584             return(d->decoder.state);
00585         }
00586         interest->offset[CCN_PI_E_ComponentLast] = d->decoder.token_index - 1;
00587         interest->offset[CCN_PI_E_Name] = d->decoder.token_index;
00588         interest->prefix_comps = ncomp;
00589         interest->offset[CCN_PI_B_LastPrefixComponent] = components->buf[(ncomp > 0) ? (ncomp - 1) : 0];
00590         interest->offset[CCN_PI_E_LastPrefixComponent] = components->buf[ncomp];
00591         /* optional MinSuffixComponents, MaxSuffixComponents */
00592         interest->min_suffix_comps = 0;
00593         interest->max_suffix_comps = 32767;
00594         interest->offset[CCN_PI_B_MinSuffixComponents] = d->decoder.token_index;
00595         res = ccn_parse_optional_tagged_nonNegativeInteger(d,
00596                                                            CCN_DTAG_MinSuffixComponents);
00597         interest->offset[CCN_PI_E_MinSuffixComponents] = d->decoder.token_index;
00598         if (res >= 0)
00599             interest->min_suffix_comps = res;
00600         interest->offset[CCN_PI_B_MaxSuffixComponents] = d->decoder.token_index;
00601         res = ccn_parse_optional_tagged_nonNegativeInteger(d,
00602                                                            CCN_DTAG_MaxSuffixComponents);
00603         interest->offset[CCN_PI_E_MaxSuffixComponents] = d->decoder.token_index;
00604         if (res >= 0)
00605             interest->max_suffix_comps = res;
00606         if (interest->max_suffix_comps < interest->min_suffix_comps)
00607             return (d->decoder.state = -__LINE__);
00608         /* optional PublisherID */
00609         res = ccn_parse_PublisherID(d, interest);
00610         /* optional Exclude element */
00611         interest->offset[CCN_PI_B_Exclude] = d->decoder.token_index;
00612         res = ccn_parse_Exclude(d);
00613         interest->offset[CCN_PI_E_Exclude] = d->decoder.token_index;
00614         /* optional ChildSelector */
00615         interest->offset[CCN_PI_B_ChildSelector] = d->decoder.token_index;
00616         res = ccn_parse_optional_tagged_nonNegativeInteger(d,
00617                          CCN_DTAG_ChildSelector);
00618         if (res < 0)
00619             res = 0;
00620         interest->orderpref = res;
00621         interest->offset[CCN_PI_E_ChildSelector] = d->decoder.token_index;
00622         if (interest->orderpref > 5)
00623             return (d->decoder.state = -__LINE__);        
00624         /* optional AnswerOriginKind */
00625         interest->offset[CCN_PI_B_AnswerOriginKind] = d->decoder.token_index;
00626         interest->answerfrom = ccn_parse_optional_tagged_nonNegativeInteger(d,
00627                          CCN_DTAG_AnswerOriginKind);
00628         interest->offset[CCN_PI_E_AnswerOriginKind] = d->decoder.token_index;
00629         if (interest->answerfrom == -1)
00630             interest->answerfrom = CCN_AOK_DEFAULT;
00631         else if ((interest->answerfrom & CCN_AOK_NEW) != 0 &&
00632                  (interest->answerfrom & CCN_AOK_CS) == 0)
00633             return (d->decoder.state = -__LINE__);
00634         /* optional Scope */
00635         interest->offset[CCN_PI_B_Scope] = d->decoder.token_index;
00636         interest->scope = ccn_parse_optional_tagged_nonNegativeInteger(d,
00637                          CCN_DTAG_Scope);
00638         interest->offset[CCN_PI_E_Scope] = d->decoder.token_index;
00639         if (interest->scope > 9)
00640                 return (d->decoder.state = -__LINE__);
00641         if ((interest->answerfrom & CCN_AOK_EXPIRE) != 0 &&
00642             interest->scope != 0)
00643                 return (d->decoder.state = -__LINE__);
00644         /* optional InterestLifetime */
00645         interest->offset[CCN_PI_B_InterestLifetime] = d->decoder.token_index;
00646         res = ccn_parse_optional_tagged_BLOB(d, CCN_DTAG_InterestLifetime, 1, 8);
00647         if (res >= 0)
00648             magic |= 20100401;
00649         interest->offset[CCN_PI_E_InterestLifetime] = d->decoder.token_index;
00650         /* optional Nonce */
00651         interest->offset[CCN_PI_B_Nonce] = d->decoder.token_index;
00652         res = ccn_parse_optional_tagged_BLOB(d, CCN_DTAG_Nonce, 4, 64);
00653         interest->offset[CCN_PI_E_Nonce] = d->decoder.token_index;
00654         /* Allow for no experimental stuff */
00655         interest->offset[CCN_PI_B_OTHER] = d->decoder.token_index;
00656         interest->offset[CCN_PI_E_OTHER] = d->decoder.token_index;
00657         ccn_buf_check_close(d);
00658         interest->offset[CCN_PI_E] = d->decoder.index;
00659     }
00660     else
00661         return (d->decoder.state = -__LINE__);
00662     if (d->decoder.state < 0)
00663         return (d->decoder.state);
00664     if (d->decoder.index != size || !CCN_FINAL_DSTATE(d->decoder.state))
00665         return (CCN_DSTATE_ERR_CODING);
00666     if (magic == 0)
00667         magic = 20090701;
00668     if (!(magic == 20090701 || magic == 20100401))
00669         return (d->decoder.state = -__LINE__);
00670     interest->magic = magic;
00671     return (ncomp);
00672 }
00673 
00674 struct parsed_KeyName {
00675     int Name;
00676     int endName;
00677     int PublisherID;
00678     int endPublisherID;
00679 };
00680 
00681 static int
00682 ccn_parse_KeyName(struct ccn_buf_decoder *d, struct parsed_KeyName *x)
00683 {
00684     int res = -1;
00685     if (ccn_buf_match_dtag(d, CCN_DTAG_KeyName)) {
00686         res = d->decoder.element_index;
00687         ccn_buf_advance(d);
00688         x->Name = d->decoder.token_index;
00689         ccn_parse_Name(d, NULL);
00690         x->endName = d->decoder.token_index;
00691         x->PublisherID = ccn_parse_PublisherID(d, NULL);
00692         x->endPublisherID = d->decoder.token_index;
00693         ccn_buf_check_close(d);
00694     }
00695     else
00696         d->decoder.state = -__LINE__;
00697     if (d->decoder.state < 0)
00698         return (d->decoder.state);
00699     return(res);
00700 }
00701 
00702 static int
00703 ccn_parse_Signature(struct ccn_buf_decoder *d, struct ccn_parsed_ContentObject *x)
00704 {
00705     int res = -1;
00706     int i;
00707     struct ccn_parsed_ContentObject dummy;
00708     if (x == NULL)
00709         x = &dummy;
00710     for (i = CCN_PCO_B_Signature; i <= CCN_PCO_E_Signature; i++) {
00711         x->offset[i] = d->decoder.token_index;
00712     }
00713     if (ccn_buf_match_dtag(d, CCN_DTAG_Signature)) {
00714         res = d->decoder.element_index;
00715         ccn_buf_advance(d);
00716         x->offset[CCN_PCO_B_DigestAlgorithm] = d->decoder.token_index;
00717         ccn_parse_optional_tagged_UDATA(d, CCN_DTAG_DigestAlgorithm);
00718         x->offset[CCN_PCO_E_DigestAlgorithm] = d->decoder.token_index;
00719         x->offset[CCN_PCO_B_Witness] = d->decoder.token_index;
00720         ccn_parse_optional_tagged_BLOB(d, CCN_DTAG_Witness, 8, -1);
00721         x->offset[CCN_PCO_E_Witness] = d->decoder.token_index;
00722         x->offset[CCN_PCO_B_SignatureBits] = d->decoder.token_index;
00723         ccn_parse_required_tagged_BLOB(d, CCN_DTAG_SignatureBits, 16, -1);
00724         x->offset[CCN_PCO_E_SignatureBits] = d->decoder.token_index;
00725         ccn_buf_check_close(d);
00726         x->offset[CCN_PCO_E_Signature] = d->decoder.token_index;
00727     }
00728     if (d->decoder.state < 0)
00729         return (d->decoder.state);
00730     return(res);
00731 }
00732 
00733 static int
00734 ccn_parse_SignedInfo(struct ccn_buf_decoder *d, struct ccn_parsed_ContentObject *x)
00735 {
00736     x->offset[CCN_PCO_B_SignedInfo] = d->decoder.token_index;
00737     if (ccn_buf_match_dtag(d, CCN_DTAG_SignedInfo)) {
00738         ccn_buf_advance(d);
00739         x->offset[CCN_PCO_B_PublisherPublicKeyDigest] = d->decoder.token_index;
00740         ccn_parse_required_tagged_BLOB(d, CCN_DTAG_PublisherPublicKeyDigest, 16, 64);
00741         x->offset[CCN_PCO_E_PublisherPublicKeyDigest] = d->decoder.token_index;
00742         
00743         x->offset[CCN_PCO_B_Timestamp] = d->decoder.token_index;
00744         ccn_parse_required_tagged_timestamp(d, CCN_DTAG_Timestamp);
00745         x->offset[CCN_PCO_E_Timestamp] = d->decoder.token_index;
00746         
00747         x->offset[CCN_PCO_B_Type] = d->decoder.token_index;
00748         x->type = CCN_CONTENT_DATA;
00749         x->type = ccn_parse_optional_tagged_binary_number(d, CCN_DTAG_Type, 3, 3, CCN_CONTENT_DATA);
00750         x->offset[CCN_PCO_E_Type] = d->decoder.token_index;
00751         
00752         x->offset[CCN_PCO_B_FreshnessSeconds] = d->decoder.token_index;
00753         ccn_parse_optional_tagged_nonNegativeInteger(d, CCN_DTAG_FreshnessSeconds);
00754         x->offset[CCN_PCO_E_FreshnessSeconds] = d->decoder.token_index;
00755         
00756         x->offset[CCN_PCO_B_FinalBlockID] = d->decoder.token_index;
00757         ccn_parse_optional_tagged_BLOB(d, CCN_DTAG_FinalBlockID, 1, -1);
00758         x->offset[CCN_PCO_E_FinalBlockID] = d->decoder.token_index;
00759         
00760         x->offset[CCN_PCO_B_KeyLocator] = d->decoder.token_index;
00761         x->offset[CCN_PCO_B_Key_Certificate_KeyName] = d->decoder.token_index;
00762         x->offset[CCN_PCO_E_Key_Certificate_KeyName] = d->decoder.token_index;
00763         x->offset[CCN_PCO_B_KeyName_Name] = d->decoder.token_index;
00764         x->offset[CCN_PCO_E_KeyName_Name] = d->decoder.token_index;
00765         x->offset[CCN_PCO_B_KeyName_Pub] = d->decoder.token_index;
00766         x->offset[CCN_PCO_E_KeyName_Pub] = d->decoder.token_index;
00767         if (ccn_buf_match_dtag(d, CCN_DTAG_KeyLocator)) {
00768             ccn_buf_advance(d);
00769             x->offset[CCN_PCO_B_Key_Certificate_KeyName] = d->decoder.token_index;
00770             if (ccn_buf_match_dtag(d, CCN_DTAG_Key)) {
00771                 (void)ccn_parse_required_tagged_BLOB(d, CCN_DTAG_Key, 0, -1);
00772             }
00773             else if (ccn_buf_match_dtag(d, CCN_DTAG_Certificate)) {
00774                 (void)ccn_parse_required_tagged_BLOB(d, CCN_DTAG_Certificate, 0, -1);
00775             }
00776             else {
00777                 struct parsed_KeyName keyname = {-1, -1, -1, -1};
00778                 if (ccn_parse_KeyName(d, &keyname) >= 0) {
00779                     if (keyname.Name >= 0) {
00780                         x->offset[CCN_PCO_B_KeyName_Name] = keyname.Name;
00781                         x->offset[CCN_PCO_E_KeyName_Name] = keyname.endName;
00782                     }
00783                     if (keyname.PublisherID >= 0) {
00784                         x->offset[CCN_PCO_B_KeyName_Pub] = keyname.PublisherID;
00785                         x->offset[CCN_PCO_E_KeyName_Pub] = keyname.endPublisherID;
00786                     }
00787                 }
00788             }
00789             x->offset[CCN_PCO_E_Key_Certificate_KeyName] = d->decoder.token_index;
00790             ccn_buf_check_close(d);
00791         }
00792         x->offset[CCN_PCO_E_KeyLocator] = d->decoder.token_index;
00793         ccn_buf_check_close(d);
00794     }
00795     else
00796         d->decoder.state = -__LINE__;
00797     x->offset[CCN_PCO_E_SignedInfo] = d->decoder.token_index;
00798     if (d->decoder.state < 0)
00799         return (d->decoder.state);
00800     return(0);
00801 }
00802 
00803 int
00804 ccn_parse_ContentObject(const unsigned char *msg, size_t size,
00805                         struct ccn_parsed_ContentObject *x,
00806                         struct ccn_indexbuf *components)
00807 {
00808     struct ccn_buf_decoder decoder;
00809     struct ccn_buf_decoder *d = ccn_buf_decoder_start(&decoder, msg, size);
00810     int res;
00811     x->magic = 20090415;
00812     x->digest_bytes = 0;
00813     if (ccn_buf_match_dtag(d, CCN_DTAG_ContentObject)) {
00814         ccn_buf_advance(d);
00815         res = ccn_parse_Signature(d, x);
00816         x->offset[CCN_PCO_B_Name] = d->decoder.token_index;
00817         x->offset[CCN_PCO_B_Component0] = d->decoder.index;
00818         res = ccn_parse_Name(d, components);
00819         if (res < 0)
00820             d->decoder.state = -__LINE__;
00821         x->name_ncomps = res;
00822         x->offset[CCN_PCO_E_ComponentLast] = d->decoder.token_index - 1;
00823         x->offset[CCN_PCO_E_Name] = d->decoder.token_index;
00824         ccn_parse_SignedInfo(d, x);
00825         x->offset[CCN_PCO_B_Content] = d->decoder.token_index;
00826         ccn_parse_required_tagged_BLOB(d, CCN_DTAG_Content, 0, -1);
00827         x->offset[CCN_PCO_E_Content] = d->decoder.token_index;
00828         ccn_buf_check_close(d);
00829         x->offset[CCN_PCO_E] = d->decoder.index;
00830     }
00831     else
00832         d->decoder.state = -__LINE__;
00833     if (d->decoder.index != size || !CCN_FINAL_DSTATE(d->decoder.state))
00834         return (CCN_DSTATE_ERR_CODING);
00835     return(0);
00836 }
00837 
00838 int
00839 ccn_ref_tagged_BLOB(enum ccn_dtag tt,
00840                     const unsigned char *buf, size_t start, size_t stop,
00841                     const unsigned char **presult, size_t *psize)
00842 {
00843     struct ccn_buf_decoder decoder;
00844     struct ccn_buf_decoder *d;
00845     if (stop < start) return(-1);
00846     d = ccn_buf_decoder_start(&decoder, buf + start, stop - start);
00847     if (ccn_buf_match_dtag(d, tt)) {
00848         ccn_buf_advance(d);
00849         if (ccn_buf_match_blob(d, presult, psize))
00850             ccn_buf_advance(d);
00851         ccn_buf_check_close(d);
00852     }
00853     else
00854         return(-1);
00855     if (d->decoder.index != d->size || !CCN_FINAL_DSTATE(d->decoder.state))
00856         return (CCN_DSTATE_ERR_CODING);
00857     return(0);
00858 }
00859 
00860 static struct ccn_buf_decoder *
00861 ccn_buf_decoder_start_at_components(struct ccn_buf_decoder *d,
00862     const unsigned char *buf, size_t buflen)
00863 {
00864     ccn_buf_decoder_start(d, buf, buflen);
00865     while (ccn_buf_match_dtag(d, CCN_DTAG_Name) ||
00866            ccn_buf_match_dtag(d, CCN_DTAG_Interest) ||
00867            ccn_buf_match_dtag(d, CCN_DTAG_ContentObject)
00868            ) {
00869         ccn_buf_advance(d);
00870         ccn_parse_Signature(d, NULL);
00871     }
00872     return(d);
00873 }
00874 
00875 int
00876 ccn_content_get_value(const unsigned char *data, size_t data_size,
00877                       const struct ccn_parsed_ContentObject *content,
00878                       const unsigned char **value, size_t *value_size)
00879 {
00880     int res;
00881     res = ccn_ref_tagged_BLOB(CCN_DTAG_Content, data,
00882           content->offset[CCN_PCO_B_Content],
00883           content->offset[CCN_PCO_E_Content],
00884           value, value_size);
00885     return(res);
00886 }
00887 
00888 int
00889 ccn_compare_names(const unsigned char *a, size_t asize,
00890                   const unsigned char *b, size_t bsize)
00891 {
00892     struct ccn_buf_decoder a_decoder;
00893     struct ccn_buf_decoder b_decoder;
00894     struct ccn_buf_decoder *aa =
00895         ccn_buf_decoder_start_at_components(&a_decoder, a, asize);
00896     struct ccn_buf_decoder *bb =
00897         ccn_buf_decoder_start_at_components(&b_decoder, b, bsize);
00898     const unsigned char *acp = NULL;
00899     const unsigned char *bcp = NULL;
00900     size_t acsize;
00901     size_t bcsize;
00902     int cmp = 0;
00903     int more_a;
00904     for (;;) {
00905         more_a = ccn_buf_match_dtag(aa, CCN_DTAG_Component);
00906         cmp = more_a - ccn_buf_match_dtag(bb, CCN_DTAG_Component);
00907         if (more_a == 0 || cmp != 0)
00908             break;
00909         ccn_buf_advance(aa);
00910         ccn_buf_advance(bb);
00911         acsize = bcsize = 0;
00912         if (ccn_buf_match_blob(aa, &acp, &acsize))
00913             ccn_buf_advance(aa);
00914         if (ccn_buf_match_blob(bb, &bcp, &bcsize))
00915             ccn_buf_advance(bb);
00916         cmp = acsize - bcsize;
00917         if (cmp != 0)
00918             break;
00919         cmp = memcmp(acp, bcp, acsize);
00920         if (cmp != 0)
00921             break;
00922         ccn_buf_check_close(aa);
00923         ccn_buf_check_close(bb);
00924     }
00925     return (cmp);
00926 }
00927 
00928 int
00929 ccn_parse_LinkAuthenticator(struct ccn_buf_decoder *d, struct ccn_parsed_Link *pl)
00930 {    
00931     /* Implement with a single offset for the blob, CCN_PL_[BE]_PublisherDigest
00932      * and remember the DTAG value to indicate which type of digest it is
00933      */
00934     if (ccn_buf_match_dtag(d, CCN_DTAG_LinkAuthenticator)) {
00935         ccn_buf_advance(d);                         // advance over DTAG token
00936         pl->offset[CCN_PL_B_LinkAuthenticator] = d->decoder.token_index;
00937         pl->offset[CCN_PL_B_PublisherID] = d->decoder.token_index;
00938         pl->offset[CCN_PL_B_PublisherDigest] = d->decoder.token_index;
00939         pl->offset[CCN_PL_E_PublisherDigest] = d->decoder.token_index;
00940         
00941         if (ccn_buf_match_dtag(d, CCN_DTAG_PublisherPublicKeyDigest)      ||
00942             ccn_buf_match_dtag(d, CCN_DTAG_PublisherCertificateDigest)    ||
00943             ccn_buf_match_dtag(d, CCN_DTAG_PublisherIssuerKeyDigest)      ||
00944             ccn_buf_match_dtag(d, CCN_DTAG_PublisherIssuerCertificateDigest)) {
00945             pl->publisher_digest_type = d->decoder.numval;  // remember the DTAG 
00946             ccn_buf_advance(d);                         // over the DTAG token
00947             if (!ccn_buf_match_some_blob(d))
00948                 return (d->decoder.state = -__LINE__);
00949             pl->offset[CCN_PL_B_PublisherDigest] = d->decoder.token_index;
00950             ccn_buf_advance(d);                         // over the digest
00951             pl->offset[CCN_PL_E_PublisherDigest] = d->decoder.token_index;
00952             ccn_buf_check_close(d);                     // over the DTAG closer
00953         }
00954         if (d->decoder.state < 0)
00955             return (d->decoder.state);
00956         pl->offset[CCN_PL_E_PublisherID] = d->decoder.token_index;
00957         
00958         /* parse optional NameComponentCount nonNegativeInteger */
00959         pl->offset[CCN_PL_B_NameComponentCount] = d->decoder.token_index;
00960         pl->name_component_count = ccn_parse_optional_tagged_nonNegativeInteger(d, CCN_DTAG_NameComponentCount);
00961         pl->offset[CCN_PL_E_NameComponentCount] = d->decoder.token_index;
00962         
00963         /* parse optional Timestamp TimestampType */
00964         pl->offset[CCN_PL_B_Timestamp] = d->decoder.token_index;
00965         if (ccn_buf_match_dtag(d, CCN_DTAG_Timestamp))
00966             ccn_parse_required_tagged_timestamp(d, CCN_DTAG_Timestamp);
00967         pl->offset[CCN_PL_E_Timestamp] = d->decoder.token_index;
00968         
00969         /* parse optional Type ContentType */
00970         pl->offset[CCN_PL_B_Type] = d->decoder.token_index;
00971         pl->type = ccn_parse_optional_tagged_binary_number(d, CCN_DTAG_Type, 3, 3, CCN_CONTENT_DATA);
00972         pl->offset[CCN_PL_E_Type] = d->decoder.token_index;
00973         
00974         /* parse optional ContentDigest Base64BinaryType */
00975         pl->offset[CCN_PL_B_ContentDigest] = d->decoder.token_index;
00976         ccn_parse_optional_tagged_BLOB(d, CCN_DTAG_ContentDigest, 32, 32);
00977         pl->offset[CCN_PL_E_ContentDigest] = d->decoder.token_index;
00978         ccn_buf_check_close(d);
00979         pl->offset[CCN_PL_E_LinkAuthenticator] = d->decoder.token_index;
00980         } else
00981         d->decoder.state = -__LINE__;
00982     if (!CCN_FINAL_DSTATE(d->decoder.state))
00983         return (CCN_DSTATE_ERR_CODING);
00984     return(0);
00985 }
00986 
00987 int
00988 ccn_parse_Link(struct ccn_buf_decoder *d,
00989                struct ccn_parsed_Link *link,
00990                struct ccn_indexbuf *components)
00991 {
00992     int ncomp = 0;
00993     int res;
00994     if (ccn_buf_match_dtag(d, CCN_DTAG_Link)) {
00995         if (components == NULL) {
00996             /* We need to have the component offsets. */
00997             components = ccn_indexbuf_create();
00998             if (components == NULL) return(-1);
00999             res = ccn_parse_Link(d, link, components);
01000             ccn_indexbuf_destroy(&components);
01001             return(res);
01002         }
01003         ccn_buf_advance(d);
01004         link->offset[CCN_PL_B_Name] = d->decoder.element_index;
01005         link->offset[CCN_PL_B_Component0] = d->decoder.index;
01006         ncomp = ccn_parse_Name(d, components);
01007         if (d->decoder.state < 0) {
01008             memset(link->offset, 0, sizeof(link->offset));
01009             return(d->decoder.state);
01010         }
01011         link->offset[CCN_PL_E_ComponentLast] = d->decoder.token_index - 1;
01012         link->offset[CCN_PL_E_Name] = d->decoder.token_index;
01013         link->name_ncomps = ncomp;
01014         /* parse optional Label string */
01015         link->offset[CCN_PL_B_Label] = d->decoder.token_index;
01016         res = ccn_parse_optional_tagged_UDATA(d, CCN_DTAG_Label);
01017         link->offset[CCN_PL_E_Label] = d->decoder.token_index;
01018         /* parse optional LinkAuthenticator LinkAuthenticatorType */
01019         if (ccn_buf_match_dtag(d, CCN_DTAG_LinkAuthenticator))
01020             res = ccn_parse_LinkAuthenticator(d, link);
01021         ccn_buf_check_close(d);
01022     }
01023     else
01024         return (d->decoder.state = -__LINE__);
01025     if (d->decoder.state < 0)
01026         return (d->decoder.state);
01027     return(ncomp);
01028 }
01029 
01030 int
01031 ccn_parse_Collection_start(struct ccn_buf_decoder *d)
01032 {
01033     if (ccn_buf_match_dtag(d, CCN_DTAG_Collection)) {
01034         ccn_buf_advance(d);
01035     }
01036     else
01037         return (d->decoder.state = -__LINE__);
01038     if (d->decoder.state < 0)
01039         return (d->decoder.state);
01040     return(0);    
01041 
01042 }
01043 
01044 int
01045 ccn_parse_Collection_next(struct ccn_buf_decoder *d,
01046                           struct ccn_parsed_Link *link,
01047                           struct ccn_indexbuf *components)
01048 {
01049     if (ccn_buf_match_dtag(d, CCN_DTAG_Link)) {
01050         return(ccn_parse_Link(d, link, components));
01051     } else
01052         ccn_buf_check_close(d);
01053     
01054     if (d->decoder.state < 0)
01055         return(d->decoder.state);
01056     else
01057         return(0);
01058 }

Generated on Thu Feb 16 00:44:00 2012 for Content-Centric Networking in C by  doxygen 1.5.6