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 <ccn/ccn.h>
00025 #include <ccn/charbuf.h>
00026 #include <ccn/uri.h>
00027
00028 struct upcalldata {
00029 int magic;
00030 long *counter;
00031 unsigned warn;
00032 unsigned option;
00033 int n_excl;
00034 struct ccn_charbuf **excl;
00035 };
00036
00037 #define MUST_VERIFY 0x01
00038
00039 static int
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
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
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
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);
00123 if (matched_comps == comps->n) {
00124
00125 ccn_charbuf_destroy(&comp);
00126
00127
00128
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);
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);
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);
00155 ccn_charbuf_append_closer(templ);
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);
00225 fflush(stdout);
00226 if (counter == n)
00227 break;
00228 }
00229 ccn_destroy(&ccn);
00230 ccn_charbuf_destroy(&c);
00231 exit(0);
00232 }