ccnsendchunks.c

Go to the documentation of this file.
00001 /**
00002  * @file ccnsendchunks.c
00003  * Injects chunks of data from stdin into ccn
00004  *
00005  * A CCNx command-line utility.
00006  *
00007  * Copyright (C) 2008-2010 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 #include <errno.h>
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023 #include <string.h>
00024 #include <unistd.h>
00025 #include <ccn/ccn.h>
00026 #include <ccn/uri.h>
00027 #include <ccn/keystore.h>
00028 #include <ccn/signing.h>
00029 
00030 struct mydata {
00031     int content_received;
00032     int content_sent;
00033     int outstanding;
00034 };
00035 
00036 enum ccn_upcall_res
00037 incoming_content(
00038     struct ccn_closure *selfp,
00039     enum ccn_upcall_kind kind,
00040     struct ccn_upcall_info *info)
00041 {
00042     struct mydata *md = selfp->data;
00043 
00044     if (kind == CCN_UPCALL_FINAL)
00045         return(CCN_UPCALL_RESULT_OK);
00046     if (kind == CCN_UPCALL_INTEREST_TIMED_OUT)
00047         return(CCN_UPCALL_RESULT_OK);
00048     if ((kind != CCN_UPCALL_CONTENT && kind != CCN_UPCALL_CONTENT_UNVERIFIED) || md == NULL)
00049         return(CCN_UPCALL_RESULT_ERR);
00050     md->content_received++;
00051     ccn_set_run_timeout(info->h, 0);
00052     return(CCN_UPCALL_RESULT_OK);
00053 }
00054 
00055 enum ccn_upcall_res
00056 incoming_interest(
00057     struct ccn_closure *selfp,
00058     enum ccn_upcall_kind kind,
00059     struct ccn_upcall_info *info)
00060 {
00061     struct mydata *md = selfp->data;
00062 
00063     if (kind == CCN_UPCALL_FINAL)
00064         return(CCN_UPCALL_RESULT_OK);
00065     if (kind != CCN_UPCALL_INTEREST || md == NULL)
00066         return(CCN_UPCALL_RESULT_ERR);
00067     if ((info->pi->answerfrom & CCN_AOK_NEW) != 0) {
00068         if (md->outstanding < 10)
00069             md->outstanding = 10;
00070         ccn_set_run_timeout(info->h, 0);
00071     }
00072     return(CCN_UPCALL_RESULT_OK);
00073 }
00074 
00075 ssize_t
00076 read_full(int fd, unsigned char *buf, size_t size)
00077 {
00078     size_t i;
00079     ssize_t res = 0;
00080     for (i = 0; i < size; i += res) {
00081         res = read(fd, buf + i, size - i);
00082         if (res == -1) {
00083             if (errno == EAGAIN || errno == EINTR)
00084                 res = 0;
00085             else
00086                 return(res);
00087         }
00088         else if (res == 0)
00089             break;
00090     }
00091     return(i);
00092 }
00093 
00094 static void
00095 usage(const char *progname)
00096 {
00097         fprintf(stderr,
00098                 "%s [-h] [-x freshness_seconds] [-b blocksize] URI\n"
00099                 " Chops stdin into blocks (1K by default) and sends them "
00100                 "as consecutively numbered ContentObjects "
00101                 "under the given uri\n", progname);
00102         exit(1);
00103 }
00104 
00105 int
00106 main(int argc, char **argv)
00107 {
00108     const char *progname = argv[0];
00109     struct ccn *ccn = NULL;
00110     struct ccn_charbuf *root = NULL;
00111     struct ccn_charbuf *name = NULL;
00112     struct ccn_charbuf *temp = NULL;
00113     struct ccn_charbuf *templ = NULL;
00114     struct ccn_charbuf *signed_info = NULL;
00115     struct ccn_charbuf *keylocator = NULL;
00116     struct ccn_charbuf *finalblockid = NULL;
00117     struct ccn_keystore *keystore = NULL;
00118     long expire = -1;
00119     long blocksize = 1024;
00120     int i;
00121     int status = 0;
00122     int res;
00123     ssize_t read_res;
00124     unsigned char *buf = NULL;
00125     struct mydata mydata = { 0 };
00126     struct ccn_closure in_content = {.p=&incoming_content, .data=&mydata};
00127     struct ccn_closure in_interest = {.p=&incoming_interest, .data=&mydata};
00128     while ((res = getopt(argc, argv, "hx:b:")) != -1) {
00129         switch (res) {
00130             case 'x':
00131                 expire = atol(optarg);
00132                 if (expire <= 0)
00133                     usage(progname);
00134                 break;
00135             case 'b':
00136                 blocksize = atol(optarg);
00137                 break;
00138             default:
00139             case 'h':
00140                 usage(progname);
00141                 break;
00142         }
00143     }
00144     argc -= optind;
00145     argv += optind;
00146     if (argv[0] == NULL)
00147         usage(progname);
00148     name = ccn_charbuf_create();
00149     res = ccn_name_from_uri(name, argv[0]);
00150     if (res < 0) {
00151         fprintf(stderr, "%s: bad ccn URI: %s\n", progname, argv[0]);
00152         exit(1);
00153     }
00154     if (argv[1] != NULL)
00155         fprintf(stderr, "%s warning: extra arguments ignored\n", progname);
00156 
00157     ccn = ccn_create();
00158     if (ccn_connect(ccn, NULL) == -1) {
00159         perror("Could not connect to ccnd");
00160         exit(1);
00161     }
00162     
00163     buf = calloc(1, blocksize);
00164     root = name;
00165     name = ccn_charbuf_create();
00166     temp = ccn_charbuf_create();
00167     templ = ccn_charbuf_create();
00168     signed_info = ccn_charbuf_create();
00169     keystore = ccn_keystore_create();
00170     temp->length = 0;
00171     ccn_charbuf_putf(temp, "%s/.ccnx/.ccnx_keystore", getenv("HOME"));
00172     res = ccn_keystore_init(keystore,
00173                             ccn_charbuf_as_string(temp),
00174                             "Th1s1sn0t8g00dp8ssw0rd.");
00175     if (res != 0) {
00176         printf("Failed to initialize keystore\n");
00177         exit(1);
00178     }
00179     
00180     name->length = 0;
00181     ccn_charbuf_append(name, root->buf, root->length);
00182     
00183     /* Set up a handler for interests */
00184     ccn_set_interest_filter(ccn, name, &in_interest);
00185     
00186     /* Initiate check to see whether there is already something there. */
00187     temp->length = 0;
00188     ccn_charbuf_putf(temp, "%d", 0);
00189     ccn_name_append(name, temp->buf, temp->length);
00190     templ->length = 0;
00191     ccn_charbuf_append_tt(templ, CCN_DTAG_Interest, CCN_DTAG);
00192     ccn_charbuf_append_tt(templ, CCN_DTAG_Name, CCN_DTAG);
00193     ccn_charbuf_append_closer(templ); /* </Name> */
00194     ccn_charbuf_append_tt(templ, CCN_DTAG_MaxSuffixComponents, CCN_DTAG);
00195     ccn_charbuf_append_tt(templ, 1, CCN_UDATA);
00196     ccn_charbuf_append(templ, "1", 1);
00197     ccn_charbuf_append_closer(templ); /* </MaxSuffixComponents> */
00198     // XXX - use pubid
00199     ccn_charbuf_append_closer(templ); /* </Interest> */
00200     res = ccn_express_interest(ccn, name, &in_content, templ);
00201     if (res < 0) abort();
00202     
00203     /* Construct a key locator contining the key itself */
00204     keylocator = ccn_charbuf_create();
00205     ccn_charbuf_append_tt(keylocator, CCN_DTAG_KeyLocator, CCN_DTAG);
00206     ccn_charbuf_append_tt(keylocator, CCN_DTAG_Key, CCN_DTAG);
00207     res = ccn_append_pubkey_blob(keylocator, ccn_keystore_public_key(keystore));
00208     if (res < 0)
00209         ccn_charbuf_destroy(&keylocator);
00210     else {
00211         ccn_charbuf_append_closer(keylocator); /* </Key> */
00212         ccn_charbuf_append_closer(keylocator); /* </KeyLocator> */
00213     }
00214     
00215     for (i = 0;; i++) {
00216         read_res = read_full(0, buf, blocksize);
00217         if (read_res < 0) {
00218             perror("read");
00219             read_res = 0;
00220             status = 1;
00221         }
00222         signed_info->length = 0;
00223         if (read_res < blocksize) {
00224             temp->length = 0;
00225             ccn_charbuf_putf(temp, "%d", i);
00226             ccn_name_append(name, temp->buf, temp->length);
00227             finalblockid = ccn_charbuf_create();
00228             ccn_charbuf_append_tt(finalblockid, temp->length, CCN_BLOB);
00229             ccn_charbuf_append(finalblockid, temp->buf, temp->length);
00230         }
00231         res = ccn_signed_info_create(signed_info,
00232                                      /*pubkeyid*/ccn_keystore_public_key_digest(keystore),
00233                                      /*publisher_key_id_size*/ccn_keystore_public_key_digest_length(keystore),
00234                                      /*datetime*/NULL,
00235                                      /*type*/CCN_CONTENT_DATA,
00236                                      /*freshness*/ expire,
00237                                      finalblockid,
00238                                      keylocator);
00239         /* Put the keylocator in the first block only. */
00240         ccn_charbuf_destroy(&keylocator);
00241         if (res < 0) {
00242             fprintf(stderr, "Failed to create signed_info (res == %d)\n", res);
00243             exit(1);
00244         }
00245         name->length = 0;
00246         ccn_charbuf_append(name, root->buf, root->length);
00247         temp->length = 0;
00248         ccn_charbuf_putf(temp, "%d", i);
00249         ccn_name_append(name, temp->buf, temp->length);
00250         temp->length = 0;
00251         ccn_charbuf_append(temp, buf, read_res);
00252         temp->length = 0;
00253         res = ccn_encode_ContentObject(temp,
00254                                        name,
00255                                        signed_info,
00256                                        buf,
00257                                        read_res,
00258                                        NULL,
00259                                        ccn_keystore_private_key(keystore));
00260         if (res != 0) {
00261             fprintf(stderr, "Failed to encode ContentObject (res == %d)\n", res);
00262             exit(1);
00263         }
00264         if (i == 0) {
00265             /* Finish check for old content */
00266             if (mydata.content_received == 0)
00267                 ccn_run(ccn, 100);
00268             if (mydata.content_received > 0) {
00269                 fprintf(stderr, "%s: name is in use: %s\n", progname, argv[0]);
00270                 exit(1);
00271             }
00272             mydata.outstanding++; /* the first one is free... */
00273         }
00274         res = ccn_put(ccn, temp->buf, temp->length);
00275         if (res < 0) {
00276             fprintf(stderr, "ccn_put failed (res == %d)\n", res);
00277             exit(1);
00278         }
00279         if (read_res < blocksize)
00280             break;
00281         if (mydata.outstanding > 0)
00282             mydata.outstanding--;
00283         else
00284             res = 10;
00285         res = ccn_run(ccn, res * 100);
00286         if (res < 0) {
00287             status = 1;
00288             break;
00289         }
00290     }
00291     
00292     free(buf);
00293     buf = NULL;
00294     ccn_charbuf_destroy(&root);
00295     ccn_charbuf_destroy(&name);
00296     ccn_charbuf_destroy(&temp);
00297     ccn_charbuf_destroy(&signed_info);
00298     ccn_charbuf_destroy(&finalblockid);
00299     ccn_keystore_destroy(&keystore);
00300     ccn_destroy(&ccn);
00301     exit(status);
00302 }
Generated on Fri May 13 16:27:01 2011 for Content-Centric Networking in C by  doxygen 1.6.3