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 (argc != 1)
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     ccn = ccn_create();
00155     if (ccn_connect(ccn, NULL) == -1) {
00156         perror("Could not connect to ccnd");
00157         exit(1);
00158     }
00159     
00160     buf = calloc(1, blocksize);
00161     root = name;
00162     name = ccn_charbuf_create();
00163     temp = ccn_charbuf_create();
00164     templ = ccn_charbuf_create();
00165     signed_info = ccn_charbuf_create();
00166     keystore = ccn_keystore_create();
00167     temp->length = 0;
00168     ccn_charbuf_putf(temp, "%s/.ccnx/.ccnx_keystore", getenv("HOME"));
00169     res = ccn_keystore_init(keystore,
00170                             ccn_charbuf_as_string(temp),
00171                             "Th1s1sn0t8g00dp8ssw0rd.");
00172     if (res != 0) {
00173         printf("Failed to initialize keystore\n");
00174         exit(1);
00175     }
00176     
00177     name->length = 0;
00178     ccn_charbuf_append(name, root->buf, root->length);
00179     
00180     /* Set up a handler for interests */
00181     ccn_set_interest_filter(ccn, name, &in_interest);
00182     
00183     /* Initiate check to see whether there is already something there. */
00184     temp->length = 0;
00185     ccn_charbuf_putf(temp, "%d", 0);
00186     ccn_name_append(name, temp->buf, temp->length);
00187     templ->length = 0;
00188     ccn_charbuf_append_tt(templ, CCN_DTAG_Interest, CCN_DTAG);
00189     ccn_charbuf_append_tt(templ, CCN_DTAG_Name, CCN_DTAG);
00190     ccn_charbuf_append_closer(templ); /* </Name> */
00191     ccn_charbuf_append_tt(templ, CCN_DTAG_MaxSuffixComponents, CCN_DTAG);
00192     ccn_charbuf_append_tt(templ, 1, CCN_UDATA);
00193     ccn_charbuf_append(templ, "1", 1);
00194     ccn_charbuf_append_closer(templ); /* </MaxSuffixComponents> */
00195     // XXX - use pubid
00196     ccn_charbuf_append_closer(templ); /* </Interest> */
00197     res = ccn_express_interest(ccn, name, &in_content, templ);
00198     if (res < 0) abort();
00199     
00200     /* Construct a key locator contining the key itself */
00201     keylocator = ccn_charbuf_create();
00202     ccn_charbuf_append_tt(keylocator, CCN_DTAG_KeyLocator, CCN_DTAG);
00203     ccn_charbuf_append_tt(keylocator, CCN_DTAG_Key, CCN_DTAG);
00204     res = ccn_append_pubkey_blob(keylocator, ccn_keystore_public_key(keystore));
00205     if (res < 0)
00206         ccn_charbuf_destroy(&keylocator);
00207     else {
00208         ccn_charbuf_append_closer(keylocator); /* </Key> */
00209         ccn_charbuf_append_closer(keylocator); /* </KeyLocator> */
00210     }
00211     
00212     for (i = 0;; i++) {
00213         read_res = read_full(0, buf, blocksize);
00214         if (read_res < 0) {
00215             perror("read");
00216             read_res = 0;
00217             status = 1;
00218         }
00219         signed_info->length = 0;
00220         if (read_res < blocksize) {
00221             temp->length = 0;
00222             ccn_charbuf_putf(temp, "%d", i);
00223             ccn_name_append(name, temp->buf, temp->length);
00224             finalblockid = ccn_charbuf_create();
00225             ccn_charbuf_append_tt(finalblockid, temp->length, CCN_BLOB);
00226             ccn_charbuf_append(finalblockid, temp->buf, temp->length);
00227         }
00228         res = ccn_signed_info_create(signed_info,
00229                                      /*pubkeyid*/ccn_keystore_public_key_digest(keystore),
00230                                      /*publisher_key_id_size*/ccn_keystore_public_key_digest_length(keystore),
00231                                      /*datetime*/NULL,
00232                                      /*type*/CCN_CONTENT_DATA,
00233                                      /*freshness*/ expire,
00234                                      finalblockid,
00235                                      keylocator);
00236         /* Put the keylocator in the first block only. */
00237         ccn_charbuf_destroy(&keylocator);
00238         if (res < 0) {
00239             fprintf(stderr, "Failed to create signed_info (res == %d)\n", res);
00240             exit(1);
00241         }
00242         name->length = 0;
00243         ccn_charbuf_append(name, root->buf, root->length);
00244         temp->length = 0;
00245         ccn_charbuf_putf(temp, "%d", i);
00246         ccn_name_append(name, temp->buf, temp->length);
00247         temp->length = 0;
00248         ccn_charbuf_append(temp, buf, read_res);
00249         temp->length = 0;
00250         res = ccn_encode_ContentObject(temp,
00251                                        name,
00252                                        signed_info,
00253                                        buf,
00254                                        read_res,
00255                                        NULL,
00256                                        ccn_keystore_private_key(keystore));
00257         if (res != 0) {
00258             fprintf(stderr, "Failed to encode ContentObject (res == %d)\n", res);
00259             exit(1);
00260         }
00261         if (i == 0) {
00262             /* Finish check for old content */
00263             if (mydata.content_received == 0)
00264                 ccn_run(ccn, 100);
00265             if (mydata.content_received > 0) {
00266                 fprintf(stderr, "%s: name is in use: %s\n", progname, argv[0]);
00267                 exit(1);
00268             }
00269             mydata.outstanding++; /* the first one is free... */
00270         }
00271         res = ccn_put(ccn, temp->buf, temp->length);
00272         if (res < 0) {
00273             fprintf(stderr, "ccn_put failed (res == %d)\n", res);
00274             exit(1);
00275         }
00276         if (read_res < blocksize)
00277             break;
00278         if (mydata.outstanding > 0)
00279             mydata.outstanding--;
00280         else
00281             res = 10;
00282         res = ccn_run(ccn, res * 100);
00283         if (res < 0) {
00284             status = 1;
00285             break;
00286         }
00287     }
00288     
00289     free(buf);
00290     buf = NULL;
00291     ccn_charbuf_destroy(&root);
00292     ccn_charbuf_destroy(&name);
00293     ccn_charbuf_destroy(&temp);
00294     ccn_charbuf_destroy(&signed_info);
00295     ccn_charbuf_destroy(&finalblockid);
00296     ccn_keystore_destroy(&keystore);
00297     ccn_destroy(&ccn);
00298     exit(status);
00299 }

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