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 int scope;
00035 struct ccn_charbuf **excl;
00036 };
00037
00038 #define MUST_VERIFY 0x01
00039
00040 static int
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
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
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
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);
00124 if (matched_comps == comps->n) {
00125
00126 ccn_charbuf_destroy(&comp);
00127
00128
00129
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);
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);
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);
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);
00228 ccnb_tagged_putf(templ, CCN_DTAG_Scope, "%d", data->scope);
00229 ccn_charbuf_append_closer(templ);
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);
00238 fflush(stdout);
00239 if (counter == n)
00240 break;
00241 }
00242 ccn_destroy(&ccn);
00243 ccn_charbuf_destroy(&c);
00244 exit(0);
00245 }