ccn_header.c

Go to the documentation of this file.
00001 /**
00002  * @file ccn_file_header.c
00003  * @brief Support for parsing and creating file headers
00004  * 
00005  * Part of the CCNx C Library.
00006  *
00007  * Copyright (C) 2009 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 <stddef.h>
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023 #include <string.h>
00024 
00025 #include <ccn/ccn.h>
00026 #include <ccn/charbuf.h>
00027 #include <ccn/coding.h>
00028 
00029 #include <ccn/header.h>
00030 
00031 const unsigned char meta[8] = {CCN_MARKER_CONTROL, '.', 'M', 'E', 'T', 'A', '.', 'M'};
00032 
00033 int
00034 ccn_parse_tagged_required_uintmax(struct ccn_buf_decoder *d, enum ccn_dtag dtag, uintmax_t *result)
00035 {
00036     int res = -1;
00037     if (ccn_buf_match_dtag(d, dtag)) {
00038         ccn_buf_advance(d);
00039         res = ccn_parse_uintmax(d, result);
00040         ccn_buf_check_close(d);
00041     } else {
00042         return (d->decoder.state = -__LINE__);
00043     }
00044     return (res);
00045 }
00046 /**
00047  * Parse a ccnb-encoded Header 
00048  */
00049 struct ccn_header *
00050 ccn_header_parse(const unsigned char *p, size_t size)
00051 {
00052     struct ccn_buf_decoder decoder;
00053     struct ccn_buf_decoder *d = ccn_buf_decoder_start(&decoder, p, size);
00054     struct ccn_header *result;
00055     const unsigned char *blob;
00056     size_t blobsize;
00057     int res = 0;
00058 
00059     result = calloc(1, sizeof(*result));
00060     if (result == NULL)
00061         return (NULL);
00062     if (ccn_buf_match_dtag(d, CCN_DTAG_Header)) {
00063         ccn_buf_advance(d);
00064         res |= ccn_parse_tagged_required_uintmax(d, CCN_DTAG_Start, &result->start);
00065         res |= ccn_parse_tagged_required_uintmax(d, CCN_DTAG_Count, &result->count);
00066         res |= ccn_parse_tagged_required_uintmax(d, CCN_DTAG_BlockSize, &result->block_size);
00067         res |= ccn_parse_tagged_required_uintmax(d, CCN_DTAG_Length, &result->length);
00068         if (res != 0) {
00069             free(result);
00070             return (NULL);
00071         }
00072         if (ccn_buf_match_dtag(d, CCN_DTAG_ContentDigest)) {
00073             ccn_buf_advance(d);
00074             if (ccn_buf_match_blob(d, &blob, &blobsize)) {
00075                 result->content_digest = ccn_charbuf_create();
00076                 ccn_charbuf_append(result->content_digest, blob, blobsize);
00077                 ccn_buf_advance(d);
00078             }
00079             ccn_buf_check_close(d);
00080         }
00081         if (ccn_buf_match_dtag(d, CCN_DTAG_RootDigest)) {
00082             ccn_buf_advance(d);
00083             if (ccn_buf_match_blob(d, &blob, &blobsize)) {
00084                 result->root_digest = ccn_charbuf_create();
00085                 ccn_charbuf_append(result->root_digest, blob, blobsize);
00086                 ccn_buf_advance(d);
00087             }
00088             ccn_buf_check_close(d);
00089         }
00090         ccn_buf_check_close(d);
00091     } 
00092     else
00093         d->decoder.state = -__LINE__;
00094     
00095     if (d->decoder.index != size || !CCN_FINAL_DSTATE(d->decoder.state)) {
00096         ccn_header_destroy(&result);
00097     }
00098     return (result);
00099 }
00100 /*
00101  * Destroy the result of a ccn_header_parse or ccn_get_header
00102  */
00103 void
00104 ccn_header_destroy(struct ccn_header **ph)
00105 {
00106     if (*ph == NULL)
00107         return;
00108     ccn_charbuf_destroy(&(*ph)->root_digest);
00109     ccn_charbuf_destroy(&(*ph)->content_digest);
00110     free(*ph);
00111     *ph = NULL;
00112 }
00113 
00114 int
00115 ccnb_append_header(struct ccn_charbuf *c,
00116                    const struct ccn_header *h)
00117 {
00118     int res;
00119     res = ccnb_element_begin(c, CCN_DTAG_Header);
00120     res |= ccnb_tagged_putf(c, CCN_DTAG_Start, "%u", h->start);
00121     res |= ccnb_tagged_putf(c, CCN_DTAG_Count, "%u", h->count);
00122     res |= ccnb_tagged_putf(c, CCN_DTAG_BlockSize, "%u", h->block_size);
00123     res |= ccnb_tagged_putf(c, CCN_DTAG_Length, "%u", h->length);
00124     if (h->content_digest != NULL) {
00125         res |= ccnb_append_tagged_blob(c, CCN_DTAG_ContentDigest,
00126                                        h->content_digest->buf, h->content_digest->length);
00127     }
00128     if (h->root_digest != NULL) {
00129         res |= ccnb_append_tagged_blob(c, CCN_DTAG_RootDigest,
00130                                        h->root_digest->buf, h->root_digest->length);
00131     }
00132     res |= ccnb_element_end(c);
00133     return (res);
00134 }
00135 
00136 struct ccn_header *
00137 ccn_get_header(struct ccn *h, struct ccn_charbuf *name, int timeout)
00138 {
00139     struct ccn_charbuf *hn;
00140     struct ccn_header *result = NULL;
00141     int res;
00142 
00143     hn = ccn_charbuf_create();
00144     ccn_charbuf_append_charbuf(hn, name);
00145     /*
00146      * Requires consistency with metadata profile in
00147      * javasrc/src/org/ccnx/ccn/profiles/metadata/MetadataProfile.java
00148      */
00149     ccn_name_append(hn, meta, sizeof(meta));
00150     ccn_name_append_str(hn, ".header");
00151     res = ccn_resolve_version(h, hn, CCN_V_HIGHEST, timeout);
00152     if (res != 0) {
00153         /* Failed: try old header name from prior to 04/2010 */
00154         ccn_charbuf_reset(hn);
00155         ccn_charbuf_append_charbuf(hn, name);
00156         ccn_name_append_str(hn, "_meta_");
00157         ccn_name_append_str(hn, ".header");
00158         res = ccn_resolve_version(h, hn, CCN_V_HIGHEST, timeout);
00159     }
00160     
00161     if (res == 0) {
00162         struct ccn_charbuf *ho = ccn_charbuf_create();
00163         struct ccn_parsed_ContentObject pcobuf = { 0 };
00164         const unsigned char *hc;
00165         size_t hcs;
00166 
00167         res = ccn_get(h, hn, NULL, timeout, ho, &pcobuf, NULL, 0);
00168         if (res == 0) {
00169             hc = ho->buf;
00170             hcs = ho->length;
00171             ccn_content_get_value(hc, hcs, &pcobuf, &hc, &hcs);
00172             result = ccn_header_parse(hc, hcs);
00173         }
00174         ccn_charbuf_destroy(&ho);
00175     }
00176     ccn_charbuf_destroy(&hn);
00177     return (result);
00178 }
Generated on Fri May 13 16:27:02 2011 for Content-Centric Networking in C by  doxygen 1.6.3