ccnlibtest.c

Go to the documentation of this file.
00001 /**
00002  * @file cmd/ccnlibtest.c
00003  */
00004 /*
00005  * A CCNx program.
00006  *
00007  * Copyright (C) 2009, 2010, 2012 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  
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 /* Use some static data for this simple program */
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     /* Look through our little pile of content and send one that matches */
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             // XXX - status
00326             continue;
00327         }
00328         // XXX - Should do a skeleton check before parse
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             // XXX - res is currently ignored
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 }
Generated on Tue Aug 21 14:54:16 2012 for Content-Centric Networking in C by  doxygen 1.6.3