00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <errno.h>
00022 #include <fcntl.h>
00023 #include <stdio.h>
00024 #include <stdlib.h>
00025 #include <string.h>
00026 #include <sys/types.h>
00027 #include <unistd.h>
00028
00029 #include <ccn/ccn.h>
00030 #include <ccn/reg_mgmt.h>
00031 #include <ccn/uri.h>
00032
00033 int verbose;
00034
00035 void
00036 printraw(const void *r, int n)
00037 {
00038 int i, l;
00039 const unsigned char *p = r;
00040
00041 if (verbose == 0)
00042 return;
00043 while (n > 0) {
00044 l = (n > 40 ? 40 : n);
00045 for (i = 0; i < l; i++)
00046 printf(" %c", (' ' <= p[i] && p[i] <= '~') ? p[i] : '.');
00047 printf("\n");
00048 for (i = 0; i < l; i++)
00049 printf("%02X", p[i]);
00050 printf("\n");
00051 p += l;
00052 n -= l;
00053 }
00054 }
00055
00056 static unsigned char rawbuf[65536];
00057 static ssize_t rawlen;
00058
00059 #define N_POOLS 10
00060 #define MINI_STORE_LIMIT 10
00061 struct mini_store {
00062 struct ccn_closure me;
00063 struct ccn_charbuf *cob[MINI_STORE_LIMIT];
00064 };
00065 static struct ccn_closure incoming_content_action[N_POOLS];
00066 static struct mini_store store[N_POOLS];
00067
00068 int
00069 add_to_pool(int pool, const unsigned char *r, size_t n)
00070 {
00071 int i, j;
00072 struct ccn_charbuf **coba;
00073
00074 coba = store[pool].cob;
00075 for (i = 0, j = 0; i < MINI_STORE_LIMIT; i++) {
00076 if (coba[i] != NULL)
00077 coba[j++] = coba[i];
00078 }
00079 for (i = j; i < MINI_STORE_LIMIT; i++)
00080 coba[i] = NULL;
00081 if (j < MINI_STORE_LIMIT) {
00082 coba[j] = ccn_charbuf_create();
00083 ccn_charbuf_append(coba[j], r, n);
00084 return(j + 1);
00085 }
00086 return(-1);
00087 }
00088
00089 int
00090 n_pool(int pool)
00091 {
00092 int i, n;
00093 struct ccn_charbuf **coba;
00094
00095 coba = store[pool].cob;
00096 for (i = 0, n = 0; i < MINI_STORE_LIMIT; i++)
00097 if (coba[i] != NULL)
00098 n++;
00099 return(n);
00100 }
00101
00102 enum ccn_upcall_res
00103 incoming_content(struct ccn_closure *selfp,
00104 enum ccn_upcall_kind kind,
00105 struct ccn_upcall_info *info)
00106 {
00107 if (kind == CCN_UPCALL_FINAL)
00108 return(CCN_UPCALL_RESULT_OK);
00109 if (kind == CCN_UPCALL_INTEREST_TIMED_OUT)
00110 return(CCN_UPCALL_RESULT_REEXPRESS);
00111 if (kind != CCN_UPCALL_CONTENT && kind != CCN_UPCALL_CONTENT_UNVERIFIED)
00112 return(CCN_UPCALL_RESULT_ERR);
00113 printf("Got content matching %d components:\n", info->pi->prefix_comps);
00114 printraw(info->content_ccnb, info->pco->offset[CCN_PCO_E]);
00115 add_to_pool(selfp->intdata, info->content_ccnb, info->pco->offset[CCN_PCO_E]);
00116 return(CCN_UPCALL_RESULT_OK);
00117 }
00118
00119 int
00120 cob_matches(struct ccn_upcall_info *info, struct ccn_charbuf *cob)
00121 {
00122 int ans;
00123
00124 ans = ccn_content_matches_interest(cob->buf, cob->length, 1, NULL,
00125 info->interest_ccnb,
00126 info->pi->offset[CCN_PI_E],
00127 info->pi);
00128 return(ans);
00129 }
00130
00131 enum ccn_upcall_res
00132 outgoing_content(struct ccn_closure *selfp,
00133 enum ccn_upcall_kind kind,
00134 struct ccn_upcall_info *info)
00135 {
00136 struct mini_store *md;
00137 struct ccn_charbuf *cob = NULL;
00138 int i;
00139 int res = 0;
00140 int which;
00141
00142 md = selfp->data;
00143 which = md->me.intdata;
00144 if (kind == CCN_UPCALL_FINAL) {
00145 fprintf(stderr, "CCN_UPCALL_FINAL for store %d\n", which);
00146 for (i = 0; i < MINI_STORE_LIMIT; i++)
00147 ccn_charbuf_destroy(&md->cob[i]);
00148 return(CCN_UPCALL_RESULT_OK);
00149 }
00150 printf("Store %d got interest matching %d components, kind = %d",
00151 which, info->matched_comps, kind);
00152
00153 if (kind == CCN_UPCALL_INTEREST) {
00154 for (i = 0; i < MINI_STORE_LIMIT; i++) {
00155 cob = md->cob[i];
00156 if (cob != NULL && cob_matches(info, cob)) {
00157 res = ccn_put(info->h, cob->buf, cob->length);
00158 if (res == -1) {
00159 fprintf(stderr, "... error sending data\n");
00160 return(CCN_UPCALL_RESULT_ERR);
00161 }
00162 else {
00163 printf("... sent my content:\n");
00164 printraw(cob->buf, cob->length);
00165 ccn_charbuf_destroy(&md->cob[i]);
00166 return(CCN_UPCALL_RESULT_INTEREST_CONSUMED);
00167 }
00168 }
00169 }
00170 printf("... no match\n");
00171 }
00172 else
00173 printf("\n");
00174 return(CCN_UPCALL_RESULT_ERR);
00175 }
00176
00177 #define USAGE "ccnlibtest [-hv] (pool n | flags x | prefix uri | run millis | file.ccnb) ..."
00178
00179 void
00180 usage(void)
00181 {
00182 fprintf(stderr, USAGE "\n");
00183 exit(1);
00184 }
00185
00186 int
00187 main(int argc, char **argv)
00188 {
00189 char *arg = NULL;
00190 struct ccn *ccnH = NULL;
00191 struct ccn_parsed_interest interest = {0};
00192 struct ccn_charbuf *c = ccn_charbuf_create();
00193 struct ccn_charbuf *templ = ccn_charbuf_create();
00194 struct ccn_indexbuf *comps = ccn_indexbuf_create();
00195 int i;
00196 int millis = 0;
00197 int opt;
00198 int pool = 0;
00199 int regflgs = (CCN_FORW_CHILD_INHERIT | CCN_FORW_ACTIVE);
00200 int res;
00201 int status = 0;
00202 int val = 0;
00203
00204 while ((opt = getopt(argc, argv, "hv")) != -1) {
00205 switch (opt) {
00206 default:
00207 case 'h':
00208 usage();
00209 break;
00210 case 'v':
00211 verbose++;
00212 break;
00213 }
00214 }
00215 argc -= optind;
00216 argv += optind;
00217 ccnH = ccn_create();
00218 if (ccn_connect(ccnH, NULL) == -1) {
00219 ccn_perror(ccnH, "ccn_connect");
00220 exit(1);
00221 }
00222 for (i = 0; i < N_POOLS; i++) {
00223 store[i].me.p = &outgoing_content;
00224 store[i].me.data = &store[i];
00225 store[i].me.intdata = i;
00226 incoming_content_action[i].p = &incoming_content;
00227 incoming_content_action[i].intdata = i;
00228 }
00229 for (i = 0; i < argc; i++) {
00230 arg = argv[i];
00231 if (0 == strcmp(arg, "pool")) {
00232 if (argv[i+1] == NULL)
00233 usage();
00234 pool = argv[i+1][0] - '0';
00235 if (argv[i+1][1] || pool < 0 || pool >= N_POOLS)
00236 usage();
00237 fprintf(stderr, "Pool %d\n", pool);
00238 i++;
00239 continue;
00240 }
00241 if (0 == strcmp(arg, "prefix")) {
00242 if (argv[i+1] == NULL)
00243 usage();
00244 c->length = 0;
00245 res = ccn_name_from_uri(c, argv[i+1]);
00246 if (res < 0)
00247 usage();
00248 fprintf(stderr, "Prefix ff=%#x %s pool %d\n",
00249 regflgs, argv[i+1], pool);
00250 if (store[pool].me.intdata != pool) {
00251 abort();
00252 }
00253 res = ccn_set_interest_filter_with_flags(ccnH, c, &store[pool].me, regflgs);
00254 if (res < 0) {
00255 ccn_perror(ccnH, "ccn_set_interest_filter_with_flags");
00256 status = 1;
00257 }
00258 res = ccn_run(ccnH, 2);
00259 if (res < 0)
00260 break;
00261 i++;
00262 continue;
00263 }
00264 if (0 == strcmp(arg, "flags")) {
00265 if (argv[i+1] == NULL)
00266 usage();
00267 regflgs = atoi(argv[i+1]);
00268 if (regflgs <= 0 && strcmp(argv[i+1], "0") != 0)
00269 usage();
00270 i++;
00271 continue;
00272 }
00273 if (0 == strcmp(arg, "mincob")) {
00274 if (argv[i+1] == NULL)
00275 usage();
00276 val = atoi(argv[i+1]);
00277 if (val <= 0 && strcmp(argv[i+1], "0") != 0)
00278 usage();
00279 i++;
00280 if (n_pool(pool) < val) {
00281 fprintf(stderr, "Pool %d has %d cobs, expected at least %d\n",
00282 pool, n_pool(pool), val);
00283 exit(1);
00284 }
00285 continue;
00286 }
00287 if (0 == strcmp(arg, "maxcob")) {
00288 if (argv[i+1] == NULL)
00289 usage();
00290 val = atoi(argv[i+1]);
00291 if (val <= 0 && strcmp(argv[i+1], "0") != 0)
00292 usage();
00293 i++;
00294 if (n_pool(pool) > val) {
00295 fprintf(stderr, "Pool %d has %d cobs, expected at most %d\n",
00296 pool, n_pool(pool), val);
00297 exit(1);
00298 }
00299 continue;
00300 }
00301 if (0 == strcmp(arg, "run")) {
00302 if (argv[i+1] == NULL)
00303 usage();
00304 millis = atoi(argv[i+1]);
00305 if (millis <= 0 && strcmp(argv[i+1], "0") != 0)
00306 usage();
00307 i++;
00308 res = ccn_run(ccnH, millis);
00309 if (res < 0) {
00310 ccn_perror(ccnH, "ccn_run");
00311 exit(1);
00312 }
00313 continue;
00314 }
00315 close(0);
00316 res = open(arg, O_RDONLY);
00317 if (res != 0) {
00318 perror(arg);
00319 exit(1);
00320 }
00321 fprintf(stderr, "Reading %s ... ", arg);
00322 rawlen = read(0, rawbuf, sizeof(rawbuf));
00323 if (rawlen < 0) {
00324 perror("skipping");
00325
00326 continue;
00327 }
00328
00329 res = ccn_parse_interest(rawbuf, rawlen, &interest, NULL);
00330 if (res >= 0) {
00331 size_t name_start = interest.offset[CCN_PI_B_Name];
00332 size_t name_size = interest.offset[CCN_PI_E_Name] - name_start;
00333 templ->length = 0;
00334 ccn_charbuf_append(templ, rawbuf, rawlen);
00335 fprintf(stderr, "Expressing interest with %d name components\n", res);
00336 c->length = 0;
00337 ccn_charbuf_append(c, rawbuf + name_start, name_size);
00338
00339 ccn_express_interest(ccnH, c, &(incoming_content_action[pool]), templ);
00340 }
00341 else {
00342 struct ccn_parsed_ContentObject obj = {0};
00343 int try;
00344 res = ccn_parse_ContentObject(rawbuf, rawlen, &obj, comps);
00345 if (res >= 0) {
00346 for (try = 0; try < 5; try++) {
00347 res = add_to_pool(pool, rawbuf, rawlen);
00348 if (res >= 0) {
00349 fprintf(stderr, "Added to pool %d\n", pool);
00350 break;
00351 }
00352 if (try == 5) {
00353 fprintf(stderr, "No buffer for %s\n", arg);
00354 status = 1;
00355 break;
00356 }
00357 fprintf(stderr, "Pool %d full - wait for drain\n", pool);
00358 if (ccn_run(ccnH, 1000) < 0)
00359 break;
00360 }
00361 res = ccn_run(ccnH, 10);
00362 }
00363 else {
00364 fprintf(stderr, "What is that?\n");
00365 status = 1;
00366 }
00367 }
00368 res = ccn_run(ccnH, 10);
00369 if (res < 0) {
00370 ccn_perror(ccnH, "oops");
00371 status = 1;
00372 }
00373 }
00374 res = ccn_run(ccnH, 10);
00375 if (res < 0)
00376 status = 1;
00377 ccn_destroy(&ccnH);
00378 exit(status);
00379 }