ccnsnew.c

Go to the documentation of this file.
00001 /**
00002  * @file cmd/ccnsnew.c
00003  * 
00004  * A CCNx program to collect content objects as they arrive.
00005  */
00006 /* Copyright (C) 2012 Palo Alto Research Center, Inc.
00007  *
00008  * This work is free software; you can redistribute it and/or modify it under
00009  * the terms of the GNU General Public License version 2 as published by the
00010  * Free Software Foundation.
00011  * This work is distributed in the hope that it will be useful, but WITHOUT ANY
00012  * WARRANTY; without even the implied warranty of MERCHANTABILITY or
00013  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
00014  * for more details. You should have received a copy of the GNU General Public
00015  * License along with this program; if not, write to the
00016  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017  * Boston, MA 02110-1301, USA.
00018  */
00019 
00020 #include <stdlib.h>
00021 #include <stdio.h>
00022 #include <unistd.h>
00023 
00024 #include <ccn/ccn.h>
00025 #include <ccn/charbuf.h>
00026 #include <ccn/reg_mgmt.h>
00027 #include <ccn/uri.h>
00028 
00029 #define USAGE "[-p port] [ -0123s ] ccnx:/uri ...\n collect arriving content"
00030 
00031 static enum ccn_upcall_res incoming_interest(struct ccn_closure *,
00032                                              enum ccn_upcall_kind,
00033                                              struct ccn_upcall_info *);
00034 static enum ccn_upcall_res  incoming_content(struct ccn_closure *,
00035                                              enum ccn_upcall_kind,
00036                                              struct ccn_upcall_info *);
00037 static void usage(void);
00038 static const char *progname;
00039 static int setscope = 0;
00040 
00041 int
00042 main(int argc, char **argv)
00043 {
00044     struct ccn *h;
00045     int fflags;
00046     int i;
00047     int opt;
00048     int res;
00049     const char *arg = NULL;
00050     const char *portstr = NULL;
00051     struct ccn_charbuf *regprefix = NULL;
00052     struct ccn_closure in_interest = {0};
00053     
00054     setscope = 0;
00055     progname = argv[0];
00056     while ((opt = getopt(argc, argv, "0123shp:")) != -1) {
00057         switch (opt) {
00058             case 'p':
00059                 fprintf(stderr, "-p port: not yet implemented\n");
00060                 portstr = optarg;
00061                 break;
00062             case '0':
00063             case '1':
00064             case '2':
00065             case '3':
00066                 setscope = opt - '0';
00067                 break;
00068             case 's':
00069                 setscope = -1;
00070                 break;
00071             case 'h':
00072             default:
00073                 usage();
00074         }
00075     }
00076     if (argv[optind] == NULL)
00077         usage();
00078     
00079     h = ccn_create();
00080     res = ccn_connect(h, NULL);
00081     if (res < 0) {
00082         ccn_perror(h, "ccn_connect");
00083         return(1);
00084     }
00085     regprefix = ccn_charbuf_create();
00086     in_interest.p = &incoming_interest;
00087     for (i = optind; (arg = argv[i]) != NULL; i++) {
00088         ccn_charbuf_reset(regprefix);
00089         res = ccn_name_from_uri(regprefix, arg);
00090         if (res < 0) {
00091             fprintf(stderr, "%s: not a valid ccnx URI\n", arg);
00092             usage();
00093         }
00094         fflags = CCN_FORW_TAP | CCN_FORW_CHILD_INHERIT | CCN_FORW_ACTIVE;
00095         res = ccn_set_interest_filter_with_flags(h, regprefix, &in_interest, fflags);
00096         if (res < 0) {
00097             ccn_perror(h, "ccn_set_interest_filter_with_flags");
00098             exit(1);
00099         }
00100     }
00101     ccn_run(h, -1);
00102     ccn_charbuf_destroy(&regprefix);
00103     ccn_destroy(&h);
00104     return(0);
00105 }
00106 
00107 struct mydata {
00108     struct ccn_closure self;
00109     int timeouts;
00110     const char *debug;
00111     char debugspace[1];
00112 };
00113 
00114 /** Content handler */
00115 static enum ccn_upcall_res
00116 incoming_content(struct ccn_closure *selfp,
00117                  enum ccn_upcall_kind kind,
00118                  struct ccn_upcall_info *info)
00119 {
00120     struct mydata *md;
00121     size_t size;
00122     ssize_t resl;
00123     
00124     md = selfp->data;
00125     if (selfp != &md->self)
00126         return(CCN_UPCALL_RESULT_ERR);
00127     switch (kind) {
00128         case CCN_UPCALL_FINAL:
00129             selfp->data = NULL;
00130             free(md);
00131             break;
00132         case CCN_UPCALL_INTEREST_TIMED_OUT:
00133             md->timeouts++;
00134             break;
00135         case CCN_UPCALL_CONTENT_UNVERIFIED:
00136         case CCN_UPCALL_CONTENT:
00137             size = info->pco->offset[CCN_PCO_E];
00138             resl = write(1, info->content_ccnb, size);
00139             if (resl != size)
00140                 exit(1);
00141             break;
00142         default:
00143             return(CCN_UPCALL_RESULT_ERR);
00144     }
00145     return(CCN_UPCALL_RESULT_OK);
00146 }
00147 
00148 /**
00149  * Me too - express the interest that we just saw, with small modifications
00150  *
00151  * The idea is to be able to get a copy of whatever content comes along to
00152  * satisfy the interest.
00153  *
00154  * Before sending the interest back out, we need to strip the Nonce, because
00155  * otherwise it will just be discarded as a duplicate.
00156  *
00157  * The scope may also be modified; normally it is set to 0 to minimize the
00158  * impact on traffic.
00159  */
00160 static int
00161 me_too(struct ccn *h,
00162        struct ccn_parsed_interest *pi,
00163        const unsigned char *imsg,
00164        int scope)
00165 {
00166     struct ccn_charbuf *templ;
00167     struct ccn_charbuf *name;
00168     struct mydata *md;
00169     const unsigned char *p;
00170     size_t s;
00171     size_t t;
00172     int res;
00173     
00174     templ = ccn_charbuf_create();
00175     name = ccn_charbuf_create();
00176     p = &(imsg[pi->offset[CCN_PI_B_Name]]);
00177     s = pi->offset[CCN_PI_E_Name] - pi->offset[CCN_PI_B_Name];
00178     ccn_charbuf_append(name, p, s);
00179     p = imsg;
00180     s = pi->offset[CCN_PI_B_Scope];
00181     ccn_charbuf_append(templ, p, s);
00182     if (scope >= 0) {
00183         if (scope < 3)
00184             ccnb_tagged_putf(templ, CCN_DTAG_Scope, "%d", scope);
00185         s = pi->offset[CCN_PI_E_Scope];
00186     }
00187     t = pi->offset[CCN_PI_B_Nonce];
00188     ccn_charbuf_append(templ, p + s, t - s);
00189     ccn_charbuf_append_closer(templ);
00190     md = calloc(1, sizeof(*md));
00191     if (md == NULL)
00192         res = -1;
00193     else {
00194         md->self.p = &incoming_content;
00195         md->self.data = md;
00196         res = ccn_express_interest(h, name, &md->self, templ);
00197     }
00198     ccn_charbuf_destroy(&name);
00199     ccn_charbuf_destroy(&templ);
00200     return(res);
00201 }
00202 
00203 /** Interest handler */
00204 static enum ccn_upcall_res
00205 incoming_interest(struct ccn_closure *selfp,
00206                   enum ccn_upcall_kind kind,
00207                   struct ccn_upcall_info *info)
00208 {
00209     switch (kind) {
00210         case CCN_UPCALL_FINAL:
00211             /* no cleanup needed */
00212             break;
00213         case CCN_UPCALL_INTEREST:
00214         case CCN_UPCALL_CONSUMED_INTEREST:
00215             me_too(info->h, info->pi, info->interest_ccnb, setscope);
00216             break;
00217         default:
00218             return(CCN_UPCALL_RESULT_ERR);
00219     }
00220     return(CCN_UPCALL_RESULT_OK);
00221 }
00222 
00223 /** Usage */
00224 static void
00225 usage(void)
00226 {
00227     fprintf(stderr, "%s: " USAGE "\n", progname);
00228     exit(1);
00229 }
Generated on Tue Aug 21 14:54:17 2012 for Content-Centric Networking in C by  doxygen 1.6.3