00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
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
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
00147
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
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 }