ccnbuzz.c

Go to the documentation of this file.
00001 /**
00002  * @file ccnbuzz.c
00003  * Pre-reads stuff written by ccnsendchunks, produces no output.
00004  *
00005  * A CCNx command-line utility.
00006  *
00007  * Copyright (C) 2008-2011 Palo Alto Research Center, Inc.
00008  *
00009  * This work is free software; you can redistribute it and/or modify it under
00010  * the terms of the GNU General Public License version 2 as published by the
00011  * Free Software Foundation.
00012  * This work is distributed in the hope that it will be useful, but WITHOUT ANY
00013  * WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
00015  * for more details. You should have received a copy of the GNU General Public
00016  * License along with this program; if not, write to the
00017  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018  * Boston, MA 02110-1301, USA.
00019  */
00020 
00021 /**
00022  * Pre-reads stuff written by ccnsendchunks, produces no output
00023  * This is meant to be run in parallel with ccncatchunks to experiment
00024  * with the benefits of one kind of pipelining.
00025  *
00026  * The idea is to use the Exclude Bloom filters to artificially divide the 
00027  * possible interests into several different classes.  For example, you
00028  * might use 8 bits per Bloom filter, and just one hash function, so the
00029  * 8 different filters
00030  *    B0 = 01111111
00031  *    B1 = 10111111
00032  *      ...
00033  *    B8 = 11111110
00034  * will serve to partition the interests into 8 different classes and so at any
00035  * given time and node there can be 8 different pending interests for the prefix.
00036  * When a piece of content arrives at the endpoint, a new interest is issued
00037  * that uses the same Bloom filter, but is restricted to content with a larger
00038  * sequence number than the content that just arrived.
00039  * The "real" consumer gets its content by explicitly using the sequence
00040  * numbers in its requests; almost all of these will get fulfilled out of a
00041  * nearby cache and so few of the actual interests will need to propagate
00042  * out to the network.
00043  * Note that this scheme does not need to be aware of the sequence numbering
00044  * algorithm; it only relies on them to be increasing according to the
00045  * canonical ordering.
00046  */
00047 
00048 #include <stdio.h>
00049 #include <stdlib.h>
00050 #include <string.h>
00051 #include <unistd.h>
00052 #include <ccn/bloom.h>
00053 #include <ccn/ccn.h>
00054 #include <ccn/charbuf.h>
00055 #include <ccn/uri.h>
00056 
00057 static void
00058 usage(const char *progname)
00059 {
00060     fprintf(stderr,
00061             "%s [-a] [-n count] ccnx:/a/b\n"
00062             "   Pre-reads stuff written by ccnsendchunks, produces no output\n"
00063             "   -a - allow stale data\n"
00064             "   -n count - specify number of pipeline slots\n",
00065             progname);
00066     exit(1);
00067 }
00068 
00069 struct mydata {
00070     int allow_stale;
00071 };
00072 
00073 static void
00074 append_bloom_element(struct ccn_charbuf *templ,
00075                      enum ccn_dtag dtag, struct ccn_bloom *b)
00076 {
00077         int i;
00078         ccn_charbuf_append_tt(templ, dtag, CCN_DTAG);
00079         i = ccn_bloom_wiresize(b);
00080         ccn_charbuf_append_tt(templ, i, CCN_BLOB);
00081         ccn_bloom_store_wire(b, ccn_charbuf_reserve(templ, i), i);
00082         templ->length += i;
00083         ccn_charbuf_append_closer(templ);
00084 }
00085 
00086 /*
00087  * This appends a tagged, valid, fully-saturated Bloom filter, useful for
00088  * excluding everything between two 'fenceposts' in an Exclude construct.
00089  */
00090 static void
00091 append_bf_all(struct ccn_charbuf *c)
00092 {
00093     unsigned char bf_all[9] = { 3, 1, 'A', 0, 0, 0, 0, 0, 0xFF };
00094     const struct ccn_bloom_wire *b = ccn_bloom_validate_wire(bf_all, sizeof(bf_all));
00095     if (b == NULL) abort();
00096     ccn_charbuf_append_tt(c, CCN_DTAG_Bloom, CCN_DTAG);
00097     ccn_charbuf_append_tt(c, sizeof(bf_all), CCN_BLOB);
00098     ccn_charbuf_append(c, bf_all, sizeof(bf_all));
00099     ccn_charbuf_append_closer(c);
00100 }
00101 
00102 static struct ccn_bloom *
00103 make_partition(unsigned i, int lg_n)
00104 {
00105     struct ccn_bloom_wire template = {0};
00106     struct ccn_bloom *ans = NULL;
00107     unsigned j;
00108     
00109     if (lg_n > 13 || i >= (1U << lg_n)) abort();
00110     if (lg_n >= 3)
00111         template.lg_bits = lg_n;
00112     else
00113         template.lg_bits = 3;
00114     template.n_hash = 1;
00115     template.method = 'A';
00116     memset(template.bloom, ~0, sizeof(template.bloom));
00117     /* This loop is here to replicate out to a byte if lg_n < 3 */
00118     for (j = i; j < (1U << template.lg_bits); j += (1U << lg_n))
00119         template.bloom[j / 8] -= (1U << (j % 8));
00120     ans = ccn_bloom_from_wire(&template, 8 + (1 << (template.lg_bits - 3)));
00121     return(ans);
00122 }
00123 
00124 struct ccn_charbuf *
00125 make_template(struct mydata *md, struct ccn_upcall_info *info, struct ccn_bloom *b)
00126 {
00127     struct ccn_charbuf *templ = ccn_charbuf_create();
00128     const unsigned char *ib = NULL; /* info->interest_ccnb */
00129     const unsigned char *cb = NULL; /* info->content_ccnb */
00130     struct ccn_indexbuf *cc = NULL;
00131     struct ccn_parsed_interest *pi = NULL;
00132     struct ccn_buf_decoder decoder;
00133     struct ccn_buf_decoder *d;
00134     size_t start;
00135     size_t stop;
00136     
00137     ccn_charbuf_append_tt(templ, CCN_DTAG_Interest, CCN_DTAG);
00138     ccn_charbuf_append_tt(templ, CCN_DTAG_Name, CCN_DTAG);
00139     ccn_charbuf_append_closer(templ); /* </Name> */
00140     // XXX - use pubid if possible
00141     ccn_charbuf_append_tt(templ, CCN_DTAG_MaxSuffixComponents, CCN_DTAG);
00142     ccnb_append_number(templ, 2);
00143     ccn_charbuf_append_closer(templ); /* </MaxSuffixComponents> */
00144     if (info != NULL) {
00145         ccn_charbuf_append_tt(templ, CCN_DTAG_Exclude, CCN_DTAG);
00146         ib = info->interest_ccnb;
00147         cb = info->content_ccnb;
00148         cc = info->content_comps;
00149         append_bf_all(templ);
00150         /* Insert the last Component in the filter */
00151         ccn_charbuf_append(templ,
00152                            cb + cc->buf[cc->n - 2],
00153                            cc->buf[cc->n - 1] - cc->buf[cc->n - 2]);
00154         if (b == NULL) {
00155             /* Look for Bloom in the matched interest */
00156             pi = info->pi;
00157             if (pi->offset[CCN_PI_E_Exclude] > pi->offset[CCN_PI_B_Exclude]) {
00158                 start = stop = 0;
00159                 d = ccn_buf_decoder_start(&decoder,
00160                                           ib + pi->offset[CCN_PI_B_Exclude],
00161                                           pi->offset[CCN_PI_E_Exclude] -
00162                                           pi->offset[CCN_PI_B_Exclude]);
00163                 if (!ccn_buf_match_dtag(d, CCN_DTAG_Exclude))
00164                     d->decoder.state = -1;
00165                 ccn_buf_advance(d);
00166                 if (ccn_buf_match_dtag(d, CCN_DTAG_Bloom)) {
00167                     start = pi->offset[CCN_PI_B_Exclude] + d->decoder.token_index;
00168                     ccn_buf_advance(d);
00169                     if (ccn_buf_match_blob(d, NULL, NULL))
00170                         ccn_buf_advance(d);
00171                     ccn_buf_check_close(d);
00172                     stop = pi->offset[CCN_PI_B_Exclude] + d->decoder.token_index;
00173                 }
00174                 if (ccn_buf_match_dtag(d, CCN_DTAG_Component)) {
00175                     ccn_buf_advance(d);
00176                     if (ccn_buf_match_blob(d, NULL, NULL))
00177                         ccn_buf_advance(d);
00178                     ccn_buf_check_close(d);
00179                     start = pi->offset[CCN_PI_B_Exclude] + d->decoder.token_index;
00180                     if (ccn_buf_match_dtag(d, CCN_DTAG_Bloom)) {
00181                         ccn_buf_advance(d);
00182                         if (ccn_buf_match_blob(d, NULL, NULL))
00183                             ccn_buf_advance(d);
00184                         ccn_buf_check_close(d);
00185                     }
00186                     stop = pi->offset[CCN_PI_B_Exclude] + d->decoder.token_index;
00187                 }
00188                 if (d->decoder.state >= 0)
00189                     ccn_charbuf_append(templ, ib + start, stop - start);                
00190             }
00191         }
00192         else {
00193             /* Use the supplied Bloom */
00194             append_bloom_element(templ, CCN_DTAG_Bloom, b);
00195         }
00196         ccn_charbuf_append_closer(templ); /* </Exclude> */
00197     }
00198     else if (b != NULL) {
00199         ccn_charbuf_append_tt(templ, CCN_DTAG_Exclude, CCN_DTAG);
00200         append_bloom_element(templ, CCN_DTAG_Bloom, b);
00201         ccn_charbuf_append_closer(templ); /* </Exclude> */
00202     }
00203     if (md->allow_stale) {
00204         ccn_charbuf_append_tt(templ, CCN_DTAG_AnswerOriginKind, CCN_DTAG);
00205         ccnb_append_number(templ,
00206                                                 CCN_AOK_DEFAULT | CCN_AOK_STALE);
00207         ccn_charbuf_append_closer(templ); /* </AnswerOriginKind> */
00208     }
00209     ccn_charbuf_append_closer(templ); /* </Interest> */
00210     return(templ);
00211 }
00212 
00213 static enum ccn_upcall_res
00214 incoming_content(
00215     struct ccn_closure *selfp,
00216     enum ccn_upcall_kind kind,
00217     struct ccn_upcall_info *info)
00218 {
00219     struct ccn_charbuf *name = NULL;
00220     struct ccn_charbuf *templ = NULL;
00221     struct ccn_charbuf *temp = NULL;
00222     const unsigned char *ccnb = NULL;
00223     size_t ccnb_size = 0;
00224     const unsigned char *data = NULL;
00225     size_t data_size = 0;
00226     const unsigned char *cb = NULL; /* info->content_ccnb */
00227     struct ccn_indexbuf *cc = NULL;
00228     int res;
00229     struct mydata *md = selfp->data;
00230     
00231     if (kind == CCN_UPCALL_FINAL) {
00232         if (md != NULL) {
00233             selfp->data = NULL;
00234             free(md);
00235             md = NULL;
00236         }
00237         return(CCN_UPCALL_RESULT_OK);
00238     }
00239     if (kind == CCN_UPCALL_INTEREST_TIMED_OUT)
00240         return(CCN_UPCALL_RESULT_REEXPRESS);
00241     if (kind != CCN_UPCALL_CONTENT && kind != CCN_UPCALL_CONTENT_UNVERIFIED)
00242         return(CCN_UPCALL_RESULT_ERR);
00243     if (md == NULL)
00244         selfp->data = md = calloc(1, sizeof(*md));
00245     ccnb = info->content_ccnb;
00246     ccnb_size = info->pco->offset[CCN_PCO_E];
00247     cb = info->content_ccnb;
00248     cc = info->content_comps;
00249     res = ccn_content_get_value(ccnb, ccnb_size, info->pco, &data, &data_size);
00250     if (res < 0) abort();
00251     
00252     /* Ask for the next one */
00253     name = ccn_charbuf_create();
00254     ccn_name_init(name);
00255     if (cc->n < 2) abort();
00256     res = ccn_name_append_components(name, cb, cc->buf[0], cc->buf[cc->n - 1]);
00257     if (res < 0) abort();
00258     temp = ccn_charbuf_create();
00259 
00260     templ = make_template(md, info, NULL);
00261     // XXX - this program might not work correctly anymore
00262     res = ccn_express_interest(info->h, name, /* info->pi->prefix_comps,*/ selfp, templ);
00263     if (res < 0) abort();
00264     
00265     ccn_charbuf_destroy(&templ);
00266     ccn_charbuf_destroy(&name);
00267     
00268     return(CCN_UPCALL_RESULT_OK);
00269 }
00270 
00271 int
00272 main(int argc, char **argv)
00273 {
00274     struct ccn *ccn = NULL;
00275     struct ccn_charbuf *name = NULL;
00276     struct ccn_charbuf *templ = NULL;
00277     struct ccn_closure *incoming = NULL;
00278     const char *arg = NULL;
00279     int res;
00280     int opt;
00281     struct mydata *mydata;
00282     int allow_stale = 0;
00283     int lg_n = 3;
00284     unsigned n = 8;
00285     int i;
00286     
00287     while ((opt = getopt(argc, argv, "han:")) != -1) {
00288         switch (opt) {
00289             case 'a':
00290                 allow_stale = 1;
00291                 break;
00292             case 'n':
00293                 n = atoi(optarg);
00294                 if (n < 2 || n > 8*1024) {
00295                     fprintf(stderr, "invalid -n value\n");
00296                     usage(argv[0]);
00297                 }
00298                 break;
00299             case 'h':
00300             default:
00301                 usage(argv[0]);
00302         }
00303     }
00304     for (lg_n = 0; (1U << lg_n) < n; lg_n++)
00305         continue;
00306     n = 1U << lg_n;
00307     arg = argv[optind];
00308     if (arg == NULL)
00309         usage(argv[0]);
00310     name = ccn_charbuf_create();
00311     res = ccn_name_from_uri(name, arg);
00312     if (res < 0) {
00313         fprintf(stderr, "%s: bad ccn URI: %s\n", argv[0], arg);
00314         exit(1);
00315     }
00316     if (argv[optind + 1] != NULL)
00317         fprintf(stderr, "%s warning: extra arguments ignored\n", argv[0]);
00318     ccn = ccn_create();
00319     if (ccn_connect(ccn, NULL) == -1) {
00320         perror("Could not connect to ccnd");
00321         exit(1);
00322     }
00323     incoming = calloc(1, sizeof(*incoming));
00324     incoming->p = &incoming_content;
00325     mydata = calloc(1, sizeof(*mydata));
00326     mydata->allow_stale = allow_stale;
00327     incoming->data = mydata;
00328     
00329     for (i = 0; i < n; i++) {
00330         struct ccn_bloom *b = make_partition(i, lg_n);
00331         templ = make_template(mydata, NULL, b);
00332         ccn_express_interest(ccn, name, incoming, templ);
00333         ccn_charbuf_destroy(&templ);
00334         ccn_bloom_destroy(&b);
00335     }
00336     
00337     ccn_charbuf_destroy(&name);
00338     while (res >= 0) {
00339         res = ccn_run(ccn, 1000);
00340     }
00341     ccn_destroy(&ccn);
00342     exit(res < 0);
00343 }

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