ccncat.c

Go to the documentation of this file.
00001 /**
00002  * @file ccncat.c
00003  * Reads streams at the given CCNx URIs and writes to stdout
00004  *
00005  * A CCNx command-line utility.
00006  *
00007  * Copyright (C) 2009-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 <stdio.h>
00022 #include <stdlib.h>
00023 #include <string.h>
00024 #include <unistd.h>
00025 #include <ccn/ccn.h>
00026 #include <ccn/charbuf.h>
00027 #include <ccn/uri.h>
00028 #include <ccn/fetch.h>
00029 
00030 /**
00031  * Provide usage hints for the program and then exit with a non-zero status.
00032  */
00033 static void
00034 usage(const char *progname)
00035 {
00036     fprintf(stderr,
00037             "%s [-h] [-d flags] [-p pipeline] [-s scope] [-a] ccnx:/a/b ...\n"
00038             "  Reads streams at the given ccn URIs and writes to stdout\n"
00039             "  -h produces this message\n"
00040             "  -d flags specifies the fetch debug flags which are the sum of\n"
00041             "    NoteGlitch = 1,\n"
00042             "    NoteAddRem = 2,\n"
00043             "    NoteNeed = 4,\n"
00044             "    NoteFill = 8,\n"
00045             "    NoteFinal = 16,\n"
00046             "    NoteTimeout = 32,\n"
00047             "    NoteOpenClose = 64\n"
00048             "  -p pipeline specifies the size of the pipeline.  Default 4.\n"
00049             "     pipeline >= 0.\n"
00050             "  -s scope specifies the scope for the interests.  Default unlimited.\n"
00051             "     scope = 0 (cache), 1 (local), 2 (neighborhood), 3 (unlimited).\n"
00052             "  -a allow stale data\n",
00053             progname);
00054     exit(1);
00055 }
00056 
00057 struct ccn_charbuf *
00058 make_template(int allow_stale, int scope)
00059 {
00060     struct ccn_charbuf *templ = ccn_charbuf_create();
00061     ccn_charbuf_append_tt(templ, CCN_DTAG_Interest, CCN_DTAG);
00062     ccn_charbuf_append_tt(templ, CCN_DTAG_Name, CCN_DTAG);
00063     ccn_charbuf_append_closer(templ); /* </Name> */
00064     // XXX - use pubid if possible
00065     ccn_charbuf_append_tt(templ, CCN_DTAG_MaxSuffixComponents, CCN_DTAG);
00066     ccnb_append_number(templ, 1);
00067     ccn_charbuf_append_closer(templ); /* </MaxSuffixComponents> */
00068     if (allow_stale) {
00069         ccn_charbuf_append_tt(templ, CCN_DTAG_AnswerOriginKind, CCN_DTAG);
00070         ccnb_append_number(templ, CCN_AOK_DEFAULT | CCN_AOK_STALE);
00071         ccn_charbuf_append_closer(templ); /* </AnswerOriginKind> */
00072     }
00073     if (scope >= 0 && scope <= 2) {
00074         ccnb_tagged_putf(templ, CCN_DTAG_Scope, "%d", scope);
00075     }
00076     ccn_charbuf_append_closer(templ); /* </Interest> */
00077     return(templ);
00078 }
00079 
00080 
00081 /**
00082  * Process options and then loop through command line CCNx URIs retrieving
00083  * the data and writing it to stdout.
00084  */
00085 int
00086 main(int argc, char **argv)
00087 {
00088     struct ccn *ccn = NULL;
00089     struct ccn_fetch *fetch = NULL;
00090     struct ccn_charbuf *name = NULL;
00091     struct ccn_charbuf *templ = NULL;
00092     const char *arg = NULL;
00093     int dflag = 0;
00094     int allow_stale = 0;
00095     int scope = -1;
00096     int pipeline = 4;
00097     unsigned char buf[8192];
00098     int i;
00099     int res;
00100     int opt;
00101     int assumeFixed = 0; // variable only for now
00102     
00103     while ((opt = getopt(argc, argv, "had:p:s:")) != -1) {
00104         switch (opt) {
00105             case 'a':
00106                 allow_stale = 1;
00107                 break;
00108             case 'd':
00109                 dflag = atoi(optarg);
00110                 break;
00111             case 'p':
00112                 pipeline = atoi(optarg);
00113                 if (pipeline < 0)
00114                     usage(argv[0]);
00115                 break;
00116             case 's':
00117                 scope = atoi(optarg);
00118                 if (scope < 0 || scope > 3)
00119                     usage(argv[0]);
00120                 break;
00121             case 'h':
00122             default:
00123                 usage(argv[0]);
00124         }
00125     }
00126     arg = argv[optind];
00127     if (arg == NULL)
00128         usage(argv[0]);
00129     name = ccn_charbuf_create();
00130     /* Check the args first */
00131     for (i = optind; argv[i] != NULL; i++) {
00132         name->length = 0;
00133         res = ccn_name_from_uri(name, argv[i]);
00134         if (res < 0) {
00135             fprintf(stderr, "%s: bad ccn URI: %s\n", argv[0], argv[i]);
00136             exit(1);
00137         }
00138     }
00139     
00140     ccn = ccn_create();
00141     if (ccn_connect(ccn, NULL) == -1) {
00142         perror("Could not connect to ccnd");
00143         exit(1);
00144     }
00145     
00146     templ = make_template(allow_stale, scope);
00147     
00148     fetch = ccn_fetch_new(ccn);
00149     if (dflag) {
00150         ccn_fetch_set_debug(fetch, stderr, dflag);
00151     }
00152     
00153     for (i = optind; (arg = argv[i]) != NULL; i++) {
00154         name->length = 0;
00155         res = ccn_name_from_uri(name, argv[i]);
00156         struct ccn_fetch_stream *stream = ccn_fetch_open(fetch, name, arg, templ, pipeline, CCN_V_HIGHEST, assumeFixed);
00157         if (NULL == stream) {
00158             continue;
00159         }
00160         while ((res = ccn_fetch_read(stream, buf, sizeof(buf))) != 0) {
00161             if (res > 0) {
00162                 fwrite(buf, res, 1, stdout);
00163             } else if (res == CCN_FETCH_READ_NONE) {
00164                 fflush(stdout);
00165                 if (ccn_run(ccn, 1000) < 0) {
00166                     fprintf(stderr, "%s: error during ccn_run\n", argv[0]);
00167                     exit(1);
00168                 }
00169             } else if (res == CCN_FETCH_READ_END) {
00170                 break;
00171             } else if (res == CCN_FETCH_READ_TIMEOUT) {
00172                 /* eventually have a way to handle long timeout? */
00173                 ccn_reset_timeout(stream);
00174                 fflush(stdout);
00175                 if (ccn_run(ccn, 1000) < 0) {
00176                     fprintf(stderr, "%s: error during ccn_run\n", argv[0]);
00177                     exit(1);
00178                 }
00179             } else {
00180                 /* fatal stream error; shuld report this! */
00181                 fprintf(stderr, "%s: fetch error: %s\n", argv[0], arg);
00182                 exit(1);
00183             }
00184         }
00185         stream = ccn_fetch_close(stream);
00186     }
00187     fflush(stdout);
00188     fetch = ccn_fetch_destroy(fetch);
00189     ccn_destroy(&ccn);
00190     ccn_charbuf_destroy(&name);
00191     exit(0);
00192 }

Generated on Thu Feb 16 00:43:59 2012 for Content-Centric Networking in C by  doxygen 1.5.6