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