ccn_name_util.c

Go to the documentation of this file.
00001 /**
00002  * @file ccn_name_util.c
00003  * @brief Support for manipulating ccnb-encoded Names.
00004  * 
00005  * Part of the CCNx C Library.
00006  *
00007  * Copyright (C) 2008-2010 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 #include <ccn/random.h>
00027 
00028 /**
00029  * Reset charbuf to represent an empty Name in binary format.
00030  * @returns 0, or -1 for error.
00031  */
00032 int
00033 ccn_name_init(struct ccn_charbuf *c)
00034 {
00035     int res;
00036     c->length = 0;
00037     res = ccn_charbuf_append_tt(c, CCN_DTAG_Name, CCN_DTAG);
00038     if (res == -1) return(res);
00039     res = ccn_charbuf_append_closer(c);
00040     return(res);
00041 }
00042 
00043 /**
00044  * Add a Component to a Name.
00045  *
00046  * The component is an arbitrary string of n octets, no escaping required.
00047  * @returns 0, or -1 for error.
00048  */
00049 int
00050 ccn_name_append(struct ccn_charbuf *c, const void *component, size_t n)
00051 {
00052     int res;
00053     const unsigned char closer[2] = {CCN_CLOSE, CCN_CLOSE};
00054     if (c->length < 2 || c->buf[c->length-1] != closer[1])
00055         return(-1);
00056     c->length -= 1;
00057     ccn_charbuf_reserve(c, n + 8);
00058     res = ccn_charbuf_append_tt(c, CCN_DTAG_Component, CCN_DTAG);
00059     if (res == -1) return(res);
00060     res = ccn_charbuf_append_tt(c, n, CCN_BLOB);
00061     if (res == -1) return(res);
00062     res = ccn_charbuf_append(c, component, n);
00063     if (res == -1) return(res);
00064     res = ccn_charbuf_append(c, closer, sizeof(closer));
00065     return(res);
00066 }
00067 
00068 /**
00069  * Add a Component that is a NUL-terminated string.
00070  *
00071  * The component added consists of the bytes of the string without the NUL.
00072  * This function is convenient for those applications that construct 
00073  * component names from simple strings.
00074  * @returns 0, or -1 for error.
00075  */
00076 int 
00077 ccn_name_append_str(struct ccn_charbuf *c, const char *s)
00078 {
00079     return(ccn_name_append(c, s, strlen(s)));
00080 }
00081 
00082 /**
00083  * Add a binary Component to a ccnb-encoded Name
00084  *
00085  * These are special components used for marking versions, fragments, etc.
00086  * @returns 0, or -1 for error
00087  * see doc/technical/NameConventions.html
00088  */
00089 int
00090 ccn_name_append_numeric(struct ccn_charbuf *c,
00091                         enum ccn_marker marker, uintmax_t value)
00092 {
00093     uintmax_t v;
00094     int i;
00095     char b[32];
00096     
00097     for (v = value, i = sizeof(b); v != 0 && i > 0; i--, v >>= 8)
00098         b[i-1] = v & 0xff;
00099     if (i < 1)
00100         return(-1);
00101     if (marker >= 0)
00102         b[--i] = marker;
00103     return(ccn_name_append(c, b + i, sizeof(b) - i));
00104 }
00105 
00106 /**
00107  * Add nonce Component to ccnb-encoded Name
00108  *
00109  * Uses %C1.N namespace.
00110  * @returns 0, or -1 for error
00111  * see doc/technical/NameConventions.html
00112  */
00113 int
00114 ccn_name_append_nonce(struct ccn_charbuf *c)
00115 {
00116     const unsigned char pre[4] = { CCN_MARKER_CONTROL, '.', 'N', 0 };
00117     unsigned char b[15];
00118     
00119     memcpy(b, pre, sizeof(pre));
00120     ccn_random_bytes(b + sizeof(pre), sizeof(b) - sizeof(pre));
00121     return(ccn_name_append(c, b, sizeof(b)));
00122 }
00123 
00124 /**
00125  * Add sequence of ccnb-encoded Components to a ccnb-encoded Name.
00126  *
00127  * start and stop are offsets from ccnb
00128  * @returns 0, or -1 for obvious error
00129  */
00130 int
00131 ccn_name_append_components(struct ccn_charbuf *c,
00132                            const unsigned char *ccnb,
00133                            size_t start, size_t stop)
00134 {
00135     int res;
00136     if (c->length < 2 || start > stop)
00137         return(-1);
00138     c->length -= 1;
00139     ccn_charbuf_reserve(c, stop - start + 1);
00140     res = ccn_charbuf_append(c, ccnb + start, stop - start);
00141     if (res == -1) return(res);
00142     res = ccn_charbuf_append_closer(c);
00143     return(res);
00144 }
00145 
00146 /**
00147  * Extract a pointer to and size of component at
00148  * given index i.  The first component is index 0.
00149  * @returns 0, or -1 for error.
00150  */
00151 int
00152 ccn_name_comp_get(const unsigned char *data,
00153                   const struct ccn_indexbuf *indexbuf,
00154                   unsigned int i,
00155                   const unsigned char **comp, size_t *size)
00156 {
00157     int len;
00158     struct ccn_buf_decoder decoder;
00159     struct ccn_buf_decoder *d;
00160     /* indexbuf should have an extra value marking end of last component,
00161        so we need to use last 2 values */
00162     if (indexbuf->n < 2 || i > indexbuf->n - 2) {
00163         /* There isn't a component at this index */
00164         return(-1);
00165     }
00166     len = indexbuf->buf[i + 1]-indexbuf->buf[i];
00167     d = ccn_buf_decoder_start(&decoder, data + indexbuf->buf[i], len);
00168     if (ccn_buf_match_dtag(d, CCN_DTAG_Component)) {
00169         ccn_buf_advance(d);
00170         if (ccn_buf_match_blob(d, comp, size))
00171             return(0);
00172         *comp = d->buf + d->decoder.index;
00173         *size = 0;
00174         ccn_buf_check_close(d);
00175         if (d->decoder.state >= 0)
00176             return(0);
00177     }
00178     return(-1);
00179 }
00180 
00181 int
00182 ccn_name_comp_strcmp(const unsigned char *data,
00183                      const struct ccn_indexbuf *indexbuf,
00184                      unsigned int i, const char *val)
00185 {
00186     const unsigned char *comp_ptr;
00187     size_t comp_size;
00188 
00189     // XXX - We probably want somewhat different semantics in the API -
00190     // comparing a string against a longer string with a 0 byte should
00191     // not claim equality.
00192     if (ccn_name_comp_get(data, indexbuf, i, &comp_ptr, &comp_size) == 0)
00193         return(strncmp(val, (const char *)comp_ptr, comp_size));
00194     /* Probably no such component, say query is greater-than */
00195     return(1);
00196 }
00197 
00198 /**
00199  * Find Component boundaries in a ccnb-encoded Name.
00200  *
00201  * Thin veneer over ccn_parse_Name().
00202  * components arg may be NULL to just do a validity check
00203  *
00204  * @returns -1 for error, otherwise the number of Components.
00205  */
00206 int
00207 ccn_name_split(const struct ccn_charbuf *c, struct ccn_indexbuf *components)
00208 {
00209     struct ccn_buf_decoder decoder;
00210     struct ccn_buf_decoder *d;
00211     d = ccn_buf_decoder_start(&decoder, c->buf, c->length);
00212     return(ccn_parse_Name(d, components));
00213 }
00214 
00215 /**
00216  * Chop the name down to n components.
00217  * @param c contains a ccnb-encoded Name
00218  * @param components may be NULL; if provided it must be consistent with
00219  *        some prefix of the name, and is updated accordingly.
00220  * @param n is the number or components to leave, or, if negative, specifies
00221  *        how many components to remove,
00222           e.g. -1 will remove just the last component.
00223  * @returns -1 for error, otherwise the new number of Components
00224  */
00225 int
00226 ccn_name_chop(struct ccn_charbuf *c, struct ccn_indexbuf *components, int n)
00227 {
00228     if (components == NULL) {
00229         int res;
00230         components = ccn_indexbuf_create();
00231         if (components == NULL)
00232             return(-1);
00233         res = ccn_name_split(c, components);
00234         if (res >= 0)
00235             res = ccn_name_chop(c, components, n);
00236         ccn_indexbuf_destroy(&components);
00237         return(res);
00238     }
00239     /* Fix up components if needed. We could be a little smarter about this. */
00240     if (components->n == 0 || components->buf[components->n-1] + 1 != c->length)
00241         if (ccn_name_split(c, components) < 0)
00242             return(-1);
00243     if (n < 0)
00244         n += (components->n - 1); /* APL-style indexing */
00245     if (n < 0)
00246         return(-1);
00247     if (n < components->n) {
00248         c->length = components->buf[n];
00249         ccn_charbuf_append_value(c, CCN_CLOSE, 1);
00250         components->n = n + 1;
00251         return(n);
00252     }
00253     return(-1);
00254 }
00255 
00256 /**
00257  * Advance the last Component of a Name to the next possible value.
00258  * @param c contains a ccnb-encoded Name to be updated.
00259  * @returns -1 for error, otherwise the number of Components
00260  */
00261 int
00262 ccn_name_next_sibling(struct ccn_charbuf *c)
00263 {
00264     int res = -1;
00265     struct ccn_indexbuf *ndx;
00266     unsigned char *lastcomp = NULL;
00267     size_t lastcompsize = 0;
00268     size_t i;
00269     int carry;
00270     struct ccn_charbuf *newcomp;
00271 
00272     ndx = ccn_indexbuf_create();
00273     if (ndx == NULL) goto Finish;
00274     res = ccn_name_split(c, ndx);
00275     if (res <= 0) {
00276         res = -1;
00277         goto Finish;
00278     }
00279     res = ccn_ref_tagged_BLOB(CCN_DTAG_Component, c->buf,
00280         ndx->buf[res-1], ndx->buf[res],
00281         (const unsigned char **)&lastcomp,
00282         &lastcompsize);
00283     if (res < 0) goto Finish;
00284     for (carry = 1, i = lastcompsize; carry && i > 0; i--) {
00285         carry = (((++lastcomp[i-1]) & 0xFF) == 0x00);
00286     }
00287     if (carry) {
00288         newcomp = ccn_charbuf_create();
00289         res |= ccn_charbuf_append_value(newcomp, 0, 1);
00290         res |= ccn_charbuf_append(newcomp, lastcomp, lastcompsize);
00291         res |= ccn_name_chop(c, ndx, ndx->n - 2);
00292         res |= ccn_name_append(c, newcomp->buf, newcomp->length);
00293         ccn_charbuf_destroy(&newcomp);
00294         if (res < 0) goto Finish;
00295     }
00296     res = ndx->n - 1;
00297 Finish:
00298     ccn_indexbuf_destroy(&ndx);
00299     return(res);
00300 }
Generated on Fri May 13 16:27:03 2011 for Content-Centric Networking in C by  doxygen 1.6.3