00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <errno.h>
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023 #include <string.h>
00024 #include <unistd.h>
00025 #include <ccn/bloom.h>
00026 #include <ccn/ccn.h>
00027 #include <ccn/charbuf.h>
00028 #include <ccn/uri.h>
00029
00030 struct upcalldata {
00031 int magic;
00032 long *counter;
00033 unsigned warn;
00034 int flags;
00035 int n_excl;
00036 struct ccn_charbuf **excl;
00037 };
00038 #define EXCLUDE_LOW 1
00039 #define EXCLUDE_HIGH 2
00040
00041
00042 static int namecompare(const void *a, const void *b);
00043 static struct upcalldata *get_my_data(struct ccn_closure *selfp);
00044 static void append_bf_all(struct ccn_charbuf *c);
00045 static int express_my_interest(struct ccn *h,
00046 struct ccn_closure *selfp,
00047 struct ccn_charbuf *name);
00048 static struct ccn_closure *split_my_excludes(struct ccn_closure *selfp);
00049 static enum ccn_upcall_res incoming_content(struct ccn_closure *selfp,
00050 enum ccn_upcall_kind kind,
00051 struct ccn_upcall_info *);
00052 static struct ccn_charbuf *ccn_charbuf_duplicate(struct ccn_charbuf *);
00053 static void answer_passive(struct ccn_charbuf *templ);
00054
00055
00056 static struct ccn_charbuf *passive_templ;
00057 static struct ccn_charbuf *
00058 create_passive_templ(void)
00059 {
00060 struct ccn_charbuf *templ = ccn_charbuf_create();
00061 ccn_charbuf_append_tt(templ, CCN_DTAG_Interest, CCN_DTAG);
00062 ccn_charbuf_append_tt(templ, CCN_DTAG_Name, CCN_DTAG);
00063 ccn_charbuf_append_closer(templ);
00064 answer_passive(templ);
00065 ccn_charbuf_append_closer(templ);
00066 return(templ);
00067 }
00068
00069
00070
00071
00072
00073
00074
00075 static int
00076 namecompare(const void *a, const void *b)
00077 {
00078 const struct ccn_charbuf *aa = *(const struct ccn_charbuf **)a;
00079 const struct ccn_charbuf *bb = *(const struct ccn_charbuf **)b;
00080 int ans = ccn_compare_names(aa->buf, aa->length, bb->buf, bb->length);
00081 if (ans == 0)
00082 fprintf(stderr, "wassat? %d\n", __LINE__);
00083 return (ans);
00084 }
00085
00086 static struct upcalldata *get_my_data(struct ccn_closure *selfp)
00087 {
00088 struct upcalldata *data = selfp->data;
00089 if (data->magic != 856372) abort();
00090 return(data);
00091 }
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125 static enum ccn_upcall_res
00126 incoming_content(
00127 struct ccn_closure *selfp,
00128 enum ccn_upcall_kind kind,
00129 struct ccn_upcall_info *info)
00130 {
00131 struct ccn_charbuf *c = NULL;
00132 struct ccn_charbuf *comp = NULL;
00133 struct ccn_charbuf *uri = NULL;
00134 const unsigned char *ccnb = NULL;
00135 size_t ccnb_size = 0;
00136 struct ccn_indexbuf *comps = NULL;
00137 int matched_comps = 0;
00138 int res;
00139 int i;
00140 struct upcalldata *data = get_my_data(selfp);
00141
00142 if (kind == CCN_UPCALL_FINAL) {
00143 for (i = 0; i < data->n_excl; i++)
00144 ccn_charbuf_destroy(&(data->excl[i]));
00145 if (data->excl != NULL)
00146 free(data->excl);
00147 free(data);
00148 free(selfp);
00149 return(0);
00150 }
00151 if (kind == CCN_UPCALL_INTEREST_TIMED_OUT)
00152 return(0);
00153 if (kind != CCN_UPCALL_CONTENT && kind != CCN_UPCALL_CONTENT_UNVERIFIED && kind != CCN_UPCALL_CONTENT_BAD)
00154 abort();
00155
00156 ccnb = info->content_ccnb;
00157 ccnb_size = info->pco->offset[CCN_PCO_E];
00158 comps = info->content_comps;
00159 matched_comps = info->pi->prefix_comps;
00160 c = ccn_charbuf_create();
00161 uri = ccn_charbuf_create();
00162
00163 if (matched_comps + 1 > comps->n) {
00164 ccn_uri_append(c, ccnb, ccnb_size, 1);
00165 fprintf(stderr, "How did this happen? %s\n", ccn_charbuf_as_string(uri));
00166 exit(1);
00167 }
00168
00169 if (kind == CCN_UPCALL_CONTENT_BAD) {
00170 ccn_uri_append(uri, ccnb, ccnb_size, 1);
00171 fprintf(stderr, "*** VERIFICATION FAILURE *** %s\n", ccn_charbuf_as_string(uri));
00172 uri->length = 0;
00173 }
00174
00175 data->counter[0]++;
00176
00177
00178 ccn_name_init(c);
00179 ccn_name_append_components(c, ccnb, comps->buf[0], comps->buf[matched_comps]);
00180
00181 comp = ccn_charbuf_create();
00182 ccn_name_init(comp);
00183 if (matched_comps + 1 == comps->n) {
00184
00185 ccn_digest_ContentObject(ccnb, info->pco);
00186 ccn_name_append(comp, info->pco->digest, info->pco->digest_bytes);
00187 }
00188 else {
00189 ccn_name_append_components(comp, ccnb,
00190 comps->buf[matched_comps],
00191 comps->buf[matched_comps + 1]);
00192 }
00193 data->excl = realloc(data->excl, (data->n_excl + 1) * sizeof(data->excl[0]));
00194 data->excl[data->n_excl++] = comp;
00195 comp = NULL;
00196 qsort(data->excl, data->n_excl, sizeof(data->excl[0]), &namecompare);
00197 res = express_my_interest(info->h, selfp, c);
00198 if (res == -1) {
00199 struct ccn_closure *high = split_my_excludes(selfp);
00200 if (high == NULL) abort();
00201 express_my_interest(info->h, selfp, c);
00202 express_my_interest(info->h, high, c);
00203 }
00204
00205 if (matched_comps + 2 < comps->n) {
00206 struct upcalldata *newdat = NULL;
00207 struct ccn_closure *cl;
00208 newdat = calloc(1, sizeof(*newdat));
00209 newdat->magic = 856372;
00210 newdat->warn = 1492;
00211 newdat->counter = data->counter;
00212 newdat->flags = 0;
00213 newdat->n_excl = 0;
00214 newdat->excl = NULL;
00215 cl = calloc(1, sizeof(*cl));
00216 cl->p = &incoming_content;
00217 cl->data = newdat;
00218 ccn_name_init(c);
00219 ccn_name_append_components(c, ccnb,
00220 comps->buf[0],
00221 comps->buf[matched_comps + 1]);
00222 ccn_express_interest(info->h, c, cl, passive_templ);
00223 }
00224 else {
00225 res = ccn_uri_append(uri, info->content_ccnb, info->pco->offset[CCN_PCO_E], 1);
00226 if (res < 0)
00227 fprintf(stderr, "*** Error: ccnslurp line %d res=%d\n", __LINE__, res);
00228 else
00229 printf("%s\n", ccn_charbuf_as_string(uri));
00230 }
00231 ccn_charbuf_destroy(&c);
00232 ccn_charbuf_destroy(&uri);
00233 return(0);
00234 }
00235
00236
00237
00238
00239
00240 static void
00241 answer_passive(struct ccn_charbuf *templ)
00242 {
00243 ccn_charbuf_append_tt(templ, CCN_DTAG_AnswerOriginKind, CCN_DTAG);
00244 ccn_charbuf_append_tt(templ, 1, CCN_UDATA);
00245 ccn_charbuf_append(templ, "1", 1);
00246 ccn_charbuf_append_closer(templ);
00247 }
00248
00249
00250
00251
00252
00253 static int
00254 express_my_interest(struct ccn *h,
00255 struct ccn_closure *selfp,
00256 struct ccn_charbuf *name)
00257 {
00258 int ans;
00259 struct ccn_charbuf *templ = NULL;
00260 int i;
00261 struct upcalldata *data = get_my_data(selfp);
00262
00263 templ = ccn_charbuf_create();
00264 ccn_charbuf_append_tt(templ, CCN_DTAG_Interest, CCN_DTAG);
00265 ccn_charbuf_append_tt(templ, CCN_DTAG_Name, CCN_DTAG);
00266 ccn_charbuf_append_closer(templ);
00267 ccn_charbuf_append_tt(templ, CCN_DTAG_Exclude, CCN_DTAG);
00268 if ((data->flags & EXCLUDE_LOW) != 0)
00269 append_bf_all(templ);
00270 for (i = 0; i < data->n_excl; i++) {
00271 struct ccn_charbuf *comp = data->excl[i];
00272 if (comp->length < 4) abort();
00273 ccn_charbuf_append(templ, comp->buf + 1, comp->length - 2);
00274 }
00275 if ((data->flags & EXCLUDE_HIGH) != 0)
00276 append_bf_all(templ);
00277 ccn_charbuf_append_closer(templ);
00278 answer_passive(templ);
00279 ccn_charbuf_append_closer(templ);
00280 if (templ->length + name->length > data->warn + 2) {
00281 fprintf(stderr, "*** Interest packet is %d bytes\n", (int)templ->length);
00282 data->warn = data->warn * 8 / 5;
00283 }
00284 if (templ->length + name->length > 1450 && data->n_excl > 3)
00285 ans = -1;
00286 else {
00287 ccn_express_interest(h, name, selfp, templ);
00288 ans = 0;
00289 }
00290 ccn_charbuf_destroy(&templ);
00291 return(ans);
00292 }
00293
00294
00295
00296
00297
00298 static struct ccn_closure *
00299 split_my_excludes(struct ccn_closure *selfp)
00300 {
00301 int i;
00302 int m;
00303 struct upcalldata *newdat = NULL;
00304 struct ccn_closure *cl;
00305 struct upcalldata *data = get_my_data(selfp);
00306
00307 if (data->n_excl < 3)
00308 return NULL;
00309 m = data->n_excl / 2;
00310 newdat = calloc(1, sizeof(*newdat));
00311 newdat->magic = 856372;
00312 newdat->warn = 1492;
00313 newdat->counter = data->counter;
00314 newdat->n_excl = data->n_excl - m;
00315 newdat->excl = calloc(newdat->n_excl, sizeof(newdat->excl[0]));
00316 if (newdat->excl == NULL) {
00317 free(newdat);
00318 return(NULL);
00319 }
00320 newdat->excl[0] = ccn_charbuf_duplicate(data->excl[m]);
00321 newdat->flags = data->flags | EXCLUDE_LOW;
00322 for (i = 1; i < newdat->n_excl; i++) {
00323 newdat->excl[i] = data->excl[m + i];
00324 data->excl[m + i] = NULL;
00325 }
00326 data->n_excl = m + 1;
00327 data->flags |= EXCLUDE_HIGH;
00328 cl = calloc(1, sizeof(*cl));
00329 cl->p = &incoming_content;
00330 cl->data = newdat;
00331 return(cl);
00332 }
00333
00334
00335
00336
00337
00338 static void
00339 append_bf_all(struct ccn_charbuf *c)
00340 {
00341 unsigned char bf_all[9] = { 3, 1, 'A', 0, 0, 0, 0, 0, 0xFF };
00342 const struct ccn_bloom_wire *b = ccn_bloom_validate_wire(bf_all, sizeof(bf_all));
00343 if (b == NULL) abort();
00344 ccn_charbuf_append_tt(c, CCN_DTAG_Bloom, CCN_DTAG);
00345 ccn_charbuf_append_tt(c, sizeof(bf_all), CCN_BLOB);
00346 ccn_charbuf_append(c, bf_all, sizeof(bf_all));
00347 ccn_charbuf_append_closer(c);
00348 }
00349
00350 static struct ccn_charbuf *
00351 ccn_charbuf_duplicate(struct ccn_charbuf *c)
00352 {
00353 struct ccn_charbuf *ans = ccn_charbuf_create();
00354 ccn_charbuf_append(ans, c->buf, c->length);
00355 return(ans);
00356 }
00357
00358 void
00359 usage(const char *prog)
00360 {
00361 fprintf(stderr,
00362 "%s [-h] URI\n"
00363 " Attempt to pull everything under given URI\n"
00364 " and print out names of found content to stdout\n"
00365 " -h Print this usage message.\n", prog);
00366 exit(1);
00367 }
00368
00369 int
00370 main(int argc, char **argv)
00371 {
00372 const char *progname = argv[0];
00373 struct ccn *ccn = NULL;
00374 struct ccn_charbuf *c = NULL;
00375 struct upcalldata *data = NULL;
00376 int opt;
00377 int i;
00378 long n;
00379 int res;
00380 long counter = 0;
00381 struct ccn_closure *cl = NULL;
00382
00383 while ((opt = getopt(argc, argv, "h")) != -1) {
00384 switch (opt) {
00385 case 'h':
00386 default:
00387 usage(argv[0]);
00388 }
00389 }
00390
00391 if (argv[optind] == NULL || argv[optind + 1] != NULL)
00392 usage(argv[0]);
00393
00394 passive_templ = create_passive_templ();
00395 c = ccn_charbuf_create();
00396 res = ccn_name_from_uri(c, argv[optind]);
00397 if (res < 0) {
00398 fprintf(stderr, "%s: bad ccn URI: %s\n", progname, argv[optind]);
00399 exit(1);
00400 }
00401
00402 ccn = ccn_create();
00403 if (ccn_connect(ccn, NULL) == -1) {
00404 perror("Could not connect to ccnd");
00405 exit(1);
00406 }
00407
00408 data = calloc(1, sizeof(*data));
00409 data->magic = 856372;
00410 data->warn = 1492;
00411 data->counter = &counter;
00412 cl = calloc(1, sizeof(*cl));
00413 cl->p = &incoming_content;
00414 cl->data = data;
00415 ccn_express_interest(ccn, c, cl, passive_templ);
00416 cl = NULL;
00417 data = NULL;
00418 ccn_charbuf_destroy(&c);
00419 for (i = 0;; i++) {
00420 n = counter;
00421 ccn_run(ccn, 1000);
00422 fflush(stdout);
00423 if (counter == n)
00424 break;
00425 }
00426 ccn_destroy(&ccn);
00427 ccn_charbuf_destroy(&passive_templ);
00428 exit(0);
00429 }