00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
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
00088
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
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;
00129 const unsigned char *cb = NULL;
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);
00140
00141 ccn_charbuf_append_tt(templ, CCN_DTAG_MaxSuffixComponents, CCN_DTAG);
00142 ccnb_append_number(templ, 2);
00143 ccn_charbuf_append_closer(templ);
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
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
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
00194 append_bloom_element(templ, CCN_DTAG_Bloom, b);
00195 }
00196 ccn_charbuf_append_closer(templ);
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);
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);
00208 }
00209 ccn_charbuf_append_closer(templ);
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;
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
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
00262 res = ccn_express_interest(info->h, name, 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 }