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-2011 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\n"
00049             "  -s scope specifies the scope for the interests\n"
00050             "  -a allow stale data\n",
00051             progname);
00052     exit(1);
00053 }
00054 
00055 struct ccn_charbuf *
00056 make_template(int allow_stale, int scope)
00057 {
00058     struct ccn_charbuf *templ = ccn_charbuf_create();
00059     ccn_charbuf_append_tt(templ, CCN_DTAG_Interest, CCN_DTAG);
00060     ccn_charbuf_append_tt(templ, CCN_DTAG_Name, CCN_DTAG);
00061     ccn_charbuf_append_closer(templ); /* </Name> */
00062     // XXX - use pubid if possible
00063     ccn_charbuf_append_tt(templ, CCN_DTAG_MaxSuffixComponents, CCN_DTAG);
00064     ccnb_append_number(templ, 1);
00065     ccn_charbuf_append_closer(templ); /* </MaxSuffixComponents> */
00066     if (allow_stale) {
00067         ccn_charbuf_append_tt(templ, CCN_DTAG_AnswerOriginKind, CCN_DTAG);
00068         ccnb_append_number(templ, CCN_AOK_DEFAULT | CCN_AOK_STALE);
00069         ccn_charbuf_append_closer(templ); /* </AnswerOriginKind> */
00070     }
00071     if (scope >= 0) {
00072         ccnb_tagged_putf(templ, CCN_DTAG_Scope, "%d", scope);
00073     }
00074     ccn_charbuf_append_closer(templ); /* </Interest> */
00075     return(templ);
00076 }
00077 
00078 
00079 /**
00080  * Process options and then loop through command line CCNx URIs retrieving
00081  * the data and writing it to stdout.
00082  */
00083 int
00084 main(int argc, char **argv)
00085 {
00086     struct ccn *ccn = NULL;
00087     struct ccn_fetch *fetch = NULL;
00088     struct ccn_charbuf *name = NULL;
00089     struct ccn_charbuf *templ = NULL;
00090     const char *arg = NULL;
00091     int dflag = 0;
00092     int allow_stale = 0;
00093     int scope = -1;
00094     int pipeline = 4;
00095     unsigned char buf[8192];
00096     int i;
00097     int res;
00098     int opt;
00099     int assumeFixed = 0; // variable only for now
00100     
00101     while ((opt = getopt(argc, argv, "had:p:s:")) != -1) {
00102         switch (opt) {
00103             case 'a':
00104                 allow_stale = 1;
00105                 break;
00106             case 'd':
00107                 dflag = atoi(optarg);
00108                 break;
00109             case 'p':
00110                 pipeline = atoi(optarg);
00111                 break;
00112             case 's':
00113                 scope = atoi(optarg);
00114                 break;
00115             case 'h':
00116             default:
00117                 usage(argv[0]);
00118         }
00119     }
00120     arg = argv[optind];
00121     if (arg == NULL)
00122         usage(argv[0]);
00123     name = ccn_charbuf_create();
00124     /* Check the args first */
00125     for (i = optind; argv[i] != NULL; i++) {
00126         name->length = 0;
00127         res = ccn_name_from_uri(name, argv[i]);
00128         if (res < 0) {
00129             fprintf(stderr, "%s: bad ccn URI: %s\n", argv[0], argv[i]);
00130             exit(1);
00131         }
00132     }
00133     
00134     ccn = ccn_create();
00135     if (ccn_connect(ccn, NULL) == -1) {
00136         perror("Could not connect to ccnd");
00137         exit(1);
00138     }
00139     
00140     templ = make_template(allow_stale, scope);
00141     
00142     fetch = ccn_fetch_new(ccn);
00143     if (dflag) {
00144         ccn_fetch_set_debug(fetch, stderr, dflag);
00145     }
00146     
00147     for (i = optind; (arg = argv[i]) != NULL; i++) {
00148         name->length = 0;
00149         res = ccn_name_from_uri(name, argv[i]);
00150         struct ccn_fetch_stream *stream = ccn_fetch_open(fetch, name, arg, templ, pipeline, CCN_V_HIGHEST, assumeFixed);
00151         if (NULL == stream) {
00152             continue;
00153         }
00154         while ((res = ccn_fetch_read(stream, buf, sizeof(buf))) != 0) {
00155             if (res > 0) {
00156                 fwrite(buf, res, 1, stdout);
00157             } else if (res == CCN_FETCH_READ_NONE) {
00158                 if (ccn_run(ccn, 1000) < 0) {
00159                     fprintf(stderr, "%s: error during ccn_run\n", argv[0]);
00160                     exit(1);
00161                 }
00162             } else if (res == CCN_FETCH_READ_END) {
00163                 break;
00164             } else if (res == CCN_FETCH_READ_TIMEOUT) {
00165                 /* eventually have a way to handle long timeout? */
00166                 ccn_reset_timeout(stream);
00167                 if (ccn_run(ccn, 1000) < 0) {
00168                     fprintf(stderr, "%s: error during ccn_run\n", argv[0]);
00169                     exit(1);
00170                 }
00171             } else {
00172                 /* fatal stream error; shuld report this! */
00173                 fprintf(stderr, "%s: fetch error: %s\n", argv[0], arg);
00174                 exit(1);
00175             }
00176         }
00177         stream = ccn_fetch_close(stream);
00178     }
00179     fflush(stdout);
00180     fetch = ccn_fetch_destroy(fetch);
00181     ccn_destroy(&ccn);
00182     ccn_charbuf_destroy(&name);
00183     exit(0);
00184 }
Generated on Fri May 13 16:27:01 2011 for Content-Centric Networking in C by  doxygen 1.6.3