ccnls.c

Go to the documentation of this file.
00001 /**
00002  * @file ccnls.c
00003  * Attempts to list name components available at the next level of the hierarchy.
00004  *
00005  * A CCNx command-line utility.
00006  *
00007  * Copyright (C) 2008, 2009, 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 #include <errno.h>
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023 #include <string.h>
00024 #include <ccn/ccn.h>
00025 #include <ccn/charbuf.h>
00026 #include <ccn/uri.h>
00027 
00028 struct upcalldata {
00029     int magic; /* 856372 */
00030     long *counter;
00031     unsigned warn;
00032     unsigned option;
00033     int n_excl;
00034     int scope;
00035     struct ccn_charbuf **excl; /* Array of n_excl items */
00036 };
00037 
00038 #define MUST_VERIFY 0x01
00039 
00040 static int /* for qsort */
00041 namecompare(const void *a, const void *b)
00042 {
00043     const struct ccn_charbuf *aa = *(const struct ccn_charbuf **)a;
00044     const struct ccn_charbuf *bb = *(const struct ccn_charbuf **)b;
00045     int ans = ccn_compare_names(aa->buf, aa->length, bb->buf, bb->length);
00046     if (ans == 0)
00047         fprintf(stderr, "wassat? %d\n", __LINE__);
00048     return (ans);
00049 }
00050 
00051 enum ccn_upcall_res
00052 incoming_content(
00053     struct ccn_closure *selfp,
00054     enum ccn_upcall_kind kind,
00055     struct ccn_upcall_info *info)
00056 {
00057     struct ccn_charbuf *c = NULL;
00058     struct ccn_charbuf *comp = NULL;
00059     struct ccn_charbuf *uri = NULL;
00060     struct ccn_charbuf *templ = NULL;
00061     const unsigned char *ccnb = NULL;
00062     size_t ccnb_size = 0;
00063     struct ccn_indexbuf *comps = NULL;
00064     int matched_comps = 0;
00065     int res;
00066     int i;
00067     struct upcalldata *data = selfp->data;
00068     
00069     if (data->magic != 856372) abort();
00070     if (kind == CCN_UPCALL_FINAL)
00071         return(CCN_UPCALL_RESULT_OK);
00072     if (kind == CCN_UPCALL_INTEREST_TIMED_OUT)
00073         return(CCN_UPCALL_RESULT_REEXPRESS);
00074     if (kind == CCN_UPCALL_CONTENT_UNVERIFIED) {
00075         if ((data->option & MUST_VERIFY) != 0)
00076         return(CCN_UPCALL_RESULT_VERIFY);
00077         }
00078     else if (kind != CCN_UPCALL_CONTENT) abort();
00079     
00080     ccnb = info->content_ccnb;
00081     ccnb_size = info->pco->offset[CCN_PCO_E];
00082     comps = info->content_comps;
00083     matched_comps = info->pi->prefix_comps;
00084     c = ccn_charbuf_create();
00085     uri = ccn_charbuf_create();
00086     templ = ccn_charbuf_create();
00087     /* note that comps->n is 1 greater than the number of explicit components */
00088     if (matched_comps > comps->n) {
00089         ccn_uri_append(c, ccnb, ccnb_size, 1);
00090         fprintf(stderr, "How did this happen?  %s\n", ccn_charbuf_as_string(uri));
00091         exit(1);
00092     }
00093     data->counter[0]++;
00094     /* Recover the same prefix as before */
00095     ccn_name_init(c);
00096     res = ccn_name_append_components(c, info->interest_ccnb,
00097                                      info->interest_comps->buf[0],
00098                                      info->interest_comps->buf[matched_comps]);
00099     if (res < 0) abort();
00100     
00101     comp = ccn_charbuf_create();
00102     ccn_name_init(comp);
00103     if (matched_comps + 1 == comps->n) {
00104         /* Reconstruct the implicit ContentObject digest component */
00105         ccn_digest_ContentObject(ccnb, info->pco);
00106         ccn_name_append(comp, info->pco->digest, info->pco->digest_bytes);
00107     }
00108     else if (matched_comps < comps->n) {
00109         ccn_name_append_components(comp, ccnb,
00110                                    comps->buf[matched_comps],
00111                                    comps->buf[matched_comps + 1]);
00112     }
00113     res = ccn_uri_append(uri, comp->buf, comp->length, 0);
00114     if (res < 0 || uri->length < 1)
00115         fprintf(stderr, "*** Error: ccnls line %d res=%d\n", __LINE__, res);
00116     else {
00117         if (uri->length == 1)
00118             ccn_charbuf_append(uri, ".", 1);
00119         printf("%s%s\n", ccn_charbuf_as_string(uri) + 1,
00120                kind == CCN_UPCALL_CONTENT ? " [verified]" : " [unverified]");
00121     }
00122     ccn_charbuf_append_tt(templ, CCN_DTAG_Interest, CCN_DTAG);
00123     ccn_charbuf_append(templ, c->buf, c->length); /* Name */
00124     if (matched_comps == comps->n) {
00125         /* The interest supplied the digest component */
00126         ccn_charbuf_destroy(&comp);
00127         /*
00128          * We can't rely on the Exclude filter to keep from seeing this, so 
00129          * say that we need at least one more name component.
00130          */
00131         ccn_charbuf_append_tt(templ, CCN_DTAG_MinSuffixComponents, CCN_DTAG);
00132         ccn_charbuf_append_tt(templ, 1, CCN_UDATA);
00133         ccn_charbuf_append(templ, "1", 1);
00134         ccn_charbuf_append_closer(templ); /* </MinSuffixComponents> */
00135     }
00136     else {
00137         data->excl = realloc(data->excl, (data->n_excl + 1) * sizeof(data->excl[0]));
00138         data->excl[data->n_excl++] = comp;
00139         comp = NULL;
00140     }
00141     qsort(data->excl, data->n_excl, sizeof(data->excl[0]), &namecompare);
00142     ccn_charbuf_append_tt(templ, CCN_DTAG_Exclude, CCN_DTAG);
00143     for (i = 0; i < data->n_excl; i++) {
00144         comp = data->excl[i];
00145         if (comp->length < 4) abort();
00146         ccn_charbuf_append(templ, comp->buf + 1, comp->length - 2);
00147     }
00148     comp = NULL;
00149     ccn_charbuf_append_closer(templ); /* </Exclude> */
00150     ccnb_tagged_putf(templ, CCN_DTAG_AnswerOriginKind, "%d", CCN_AOK_CS);
00151     if (data->scope > -1)
00152        ccnb_tagged_putf(templ, CCN_DTAG_Scope, "%d", data->scope);
00153     ccn_charbuf_append_closer(templ); /* </Interest> */
00154     if (templ->length > data->warn) {
00155         fprintf(stderr, "*** Interest packet is %d bytes\n", (int)templ->length);
00156         data->warn = data->warn * 8 / 5;
00157     }
00158     ccn_express_interest(info->h, c, selfp, templ);
00159     ccn_charbuf_destroy(&templ);
00160     ccn_charbuf_destroy(&c);
00161     ccn_charbuf_destroy(&uri);
00162     return(CCN_UPCALL_RESULT_OK);
00163 }
00164 
00165 void
00166 usage(const char *prog)
00167 {
00168     fprintf(stderr, "Usage: %s uri\n"
00169             "   Prints names with uri as prefix\n"
00170             "     environment var CCN_SCOPE is scope for interests (0, 1 or 2, no default)\n"
00171             "     environment var CCN_LINGER is no-data timeout (seconds) default 0.5s\n"
00172             "     environment var CCN_VERIFY indicates signature verification is required (non-zero)\n", prog);
00173     exit(1);
00174 }
00175 
00176 int
00177 main(int argc, char **argv)
00178 {
00179     struct ccn *ccn = NULL;
00180     struct ccn_charbuf *c = NULL;
00181     struct ccn_charbuf *templ = NULL;
00182     struct upcalldata *data = NULL;
00183     int i;
00184     int n;
00185     int res;
00186     long counter = 0;
00187     struct ccn_closure *cl = NULL;
00188     int timeout_ms = 500;
00189     const char *env_timeout = getenv("CCN_LINGER");
00190     const char *env_verify = getenv("CCN_VERIFY");
00191     const char *env_scope = getenv("CCN_SCOPE");
00192 
00193     if (argv[1] == NULL || argv[2] != NULL)
00194         usage(argv[0]);
00195 
00196     if (env_timeout != NULL && (i = atoi(env_timeout)) > 0)
00197         timeout_ms = i * 1000;
00198 
00199     c = ccn_charbuf_create();
00200     res = ccn_name_from_uri(c, argv[1]);
00201     if (res < 0)
00202         usage(argv[0]);
00203         
00204     ccn = ccn_create();
00205     if (ccn_connect(ccn, NULL) == -1) {
00206         perror("Could not connect to ccnd");
00207         exit(1);
00208     }
00209     
00210     data = calloc(1, sizeof(*data));
00211     data->magic = 856372;
00212     data->warn = 1492;
00213     data->counter = &counter;
00214     data->option = 0;
00215     if (env_verify && *env_verify)
00216         data->option |= MUST_VERIFY;
00217     data->scope = -1;
00218     if (env_scope != NULL && (i = atoi(env_scope)) >= 0)
00219       data->scope = i;
00220     cl = calloc(1, sizeof(*cl));
00221     cl->p = &incoming_content;
00222     cl->data = data;
00223     if (data->scope > -1) {
00224         templ = ccn_charbuf_create();
00225         ccn_charbuf_append_tt(templ, CCN_DTAG_Interest, CCN_DTAG);
00226         ccn_charbuf_append_tt(templ, CCN_DTAG_Name, CCN_DTAG);
00227         ccn_charbuf_append_closer(templ); /* </Name> */
00228         ccnb_tagged_putf(templ, CCN_DTAG_Scope, "%d", data->scope);
00229         ccn_charbuf_append_closer(templ); /* </Interest> */
00230     }
00231     ccn_express_interest(ccn, c, cl, templ);
00232     ccn_charbuf_destroy(&templ);
00233     cl = NULL;
00234     data = NULL;
00235     for (i = 0;; i++) {
00236         n = counter;
00237         ccn_run(ccn, timeout_ms); /* stop if we run dry for 1/2 sec */
00238         fflush(stdout);
00239         if (counter == n)
00240             break;
00241     }
00242     ccn_destroy(&ccn);
00243     ccn_charbuf_destroy(&c);
00244     exit(0);
00245 }

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