dataresponsetest.c

Go to the documentation of this file.
00001 /**
00002  * @file dataresponsetest.c
00003  *
00004  * A CCNx command-line utility.
00005  *
00006  * Copyright (C) 2008, 2009, 2011 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 #include <fcntl.h>
00020 #include <stdio.h>
00021 #include <stdlib.h>
00022 #include <unistd.h>
00023 #include <string.h>
00024 #include <sys/types.h>
00025 
00026 #include <ccn/ccn.h>
00027 
00028 static struct options {
00029     int logging;
00030     int nointerest;
00031     int reconnect;
00032 } options = {0, 0, 0};
00033 
00034 struct handlerstate {
00035     int next;
00036     int count;
00037     struct handlerstateitem {
00038         char *filename;
00039         unsigned char *contents;
00040         size_t  size;
00041         struct ccn_parsed_ContentObject x;
00042         struct ccn_indexbuf *components;
00043     } *items;
00044 };
00045 
00046 enum ccn_upcall_res interest_handler(struct ccn_closure *selfp,
00047                                      enum ccn_upcall_kind,
00048                                      struct ccn_upcall_info *info);
00049 
00050 int
00051 main (int argc, char *argv[]) {
00052     struct ccn *ccn = NULL;
00053     struct ccn_closure *action;
00054     struct ccn_charbuf *namebuf = NULL;
00055     struct ccn_charbuf *interestnamebuf = NULL;
00056     struct ccn_charbuf *interesttemplatebuf = NULL;
00057     struct ccn_buf_decoder decoder;
00058     struct ccn_buf_decoder *d;
00059     struct handlerstate *state;
00060     char *filename;
00061     char rawbuf[1024 * 1024];
00062     ssize_t rawlen;
00063     int i, n, res;
00064     int fd = -1;
00065 
00066     ccn = ccn_create();
00067     if (ccn_connect(ccn, NULL) == -1) {
00068         perror("ccn_connect");
00069         exit(1);
00070     }
00071     
00072     state = calloc(1, sizeof(struct handlerstate));
00073     action = calloc(1, sizeof(struct ccn_closure));
00074     action->p = interest_handler;
00075 
00076     namebuf = ccn_charbuf_create();
00077     if (namebuf == NULL) {
00078         fprintf(stderr, "ccn_charbuf_create\n");
00079         exit(1);
00080     }
00081     res = ccn_name_init(namebuf);
00082     if (res < 0) {
00083         fprintf(stderr, "ccn_name_init\n");
00084         exit(1);
00085     }
00086 
00087     interestnamebuf = ccn_charbuf_create();
00088     interesttemplatebuf = ccn_charbuf_create();
00089     if (interestnamebuf == NULL || interesttemplatebuf == NULL) {
00090         fprintf(stderr, "ccn_charbuf_create\n");
00091         exit(1);
00092     }
00093     res = ccn_name_init(interestnamebuf);
00094     if (res < 0) {
00095         fprintf(stderr, "ccn_name_init\n");
00096         exit(1);
00097     }
00098 
00099     n = 0;
00100     for (i = 1; i < argc; i++) {
00101         if (fd != -1) close(fd);
00102         filename = argv[i];
00103         if (0 == strcmp(filename, "-d")) {
00104             options.logging++;
00105             continue;
00106         }
00107         if (0 == strcmp(filename, "-nointerest")) {
00108             options.nointerest = 1;
00109             continue;
00110         }
00111         if (0 == strcmp(filename, "-reconnect")) {
00112             options.reconnect = 1;
00113             continue;
00114         }
00115         
00116         if (options.logging > 0) fprintf(stderr, "Processing %s ", filename);
00117         fd = open(filename, O_RDONLY);
00118         if (fd == -1) {
00119             perror("- open");
00120             continue;
00121         }
00122 
00123         rawlen = read(fd, rawbuf, sizeof(rawbuf));
00124         if (rawlen <= 0) {
00125             perror("- read");
00126             continue;
00127         }
00128         
00129         d = ccn_buf_decoder_start(&decoder, (unsigned char *)rawbuf, rawlen);
00130 
00131         if (ccn_buf_match_dtag(d, CCN_DTAG_ContentObject)) {
00132             state->items = realloc(state->items, (n + 1) * sizeof(*(state->items)));
00133             if (state->items == NULL) {
00134                 perror(" - realloc failed");
00135                 exit(1);
00136             }
00137             memset(&(state->items[n]), 0, sizeof(*(state->items)));
00138             state->items[n].components = ccn_indexbuf_create();
00139             res = ccn_parse_ContentObject((unsigned char *)rawbuf, rawlen, &(state->items[n].x), state->items[n].components);
00140             if (res < 0) {
00141                 if (options.logging > 0) fprintf(stderr, "Processing %s ", filename);
00142                 fprintf(stderr, "- skipping: ContentObject error %d\n", res);
00143                 ccn_indexbuf_destroy(&state->items[n].components);
00144                 continue;
00145             }
00146             if (options.logging > 0) fprintf(stderr, "- ok\n");
00147             state->items[n].filename = filename;
00148             state->items[n].contents = malloc(rawlen);
00149             state->items[n].size = rawlen;
00150             memcpy(state->items[n].contents, rawbuf, rawlen);
00151             n++;
00152         } else if (ccn_buf_match_dtag(d, CCN_DTAG_Interest)) {
00153             struct ccn_parsed_interest interest = {0};
00154             if (options.nointerest == 0) {
00155                 size_t name_start;
00156                 size_t name_size;
00157                 interestnamebuf->length = 0;
00158                 interesttemplatebuf->length = 0;
00159                 res = ccn_parse_interest((unsigned char *)rawbuf, rawlen, &interest, NULL);
00160                 name_start = interest.offset[CCN_PI_B_Name];
00161                 name_size = interest.offset[CCN_PI_E_Name] - name_start;
00162                 ccn_charbuf_append(interestnamebuf, rawbuf + name_start, name_size);
00163                 ccn_charbuf_append(interesttemplatebuf, rawbuf, rawlen);
00164                 res = ccn_express_interest(ccn, interestnamebuf, action, interesttemplatebuf);
00165             }
00166         } else {
00167             if (options.logging == 0) fprintf(stderr, "Processing %s ", filename);
00168             fprintf(stderr, "- skipping: unknown type\n");
00169         }
00170     }
00171     state->count = n;
00172     action->data = state;
00173 
00174     if (ccn_name_init(namebuf) == -1) {
00175         fprintf(stderr, "ccn_name_init\n");
00176         exit(1);
00177     }
00178 
00179     res = ccn_set_interest_filter(ccn, namebuf, action);
00180     for (;;) {
00181         res = ccn_run(ccn, -1);
00182         ccn_disconnect(ccn);
00183         if (!options.reconnect)
00184             break;
00185         sleep(2);
00186         ccn_connect(ccn, NULL);
00187     }
00188     ccn_destroy(&ccn);
00189     exit(0);
00190 }
00191 
00192 int
00193 match_components(unsigned char *msg1, struct ccn_indexbuf *comp1,
00194                  unsigned char *msg2, struct ccn_indexbuf *comp2) {
00195     int matched;
00196     int lc1, lc2;
00197     unsigned char *c1p, *c2p;
00198 
00199     for (matched = 0; (matched < comp1->n - 1) && (matched < comp2->n - 1); matched++) {
00200         lc1 = comp1->buf[matched + 1] - comp1->buf[matched];
00201         lc2 = comp2->buf[matched + 1] - comp2->buf[matched];
00202         if (lc1 != lc2) return (matched);
00203 
00204         c1p = msg1 + comp1->buf[matched];
00205         c2p = msg2 + comp2->buf[matched];
00206         if (memcmp(c1p, c2p, lc1) != 0) return (matched);
00207     }
00208     return (matched);
00209 }
00210 
00211 enum ccn_upcall_res
00212 interest_handler(struct ccn_closure *selfp,
00213                  enum ccn_upcall_kind upcall_kind,
00214                  struct ccn_upcall_info *info)
00215 {
00216     int i, c, mc, match, res;
00217     struct handlerstateitem item;
00218     struct handlerstate *state;
00219     size_t ccnb_size = 0;
00220 
00221     state = selfp->data;
00222     switch(upcall_kind) {
00223     case CCN_UPCALL_FINAL:
00224         fprintf(stderr, "Upcall final\n");
00225         return (0);
00226 
00227     case CCN_UPCALL_INTEREST_TIMED_OUT:
00228         fprintf(stderr, "refresh\n");
00229         return (CCN_UPCALL_RESULT_REEXPRESS);
00230         
00231     case CCN_UPCALL_CONTENT:
00232     case CCN_UPCALL_CONTENT_UNVERIFIED:
00233         ccnb_size = info->pco->offset[CCN_PCO_E];
00234         c = state->count;
00235         for (i = 0; i < c; i++) {
00236             if (info->content_comps->n == state->items[i].components->n) {
00237                 mc = match_components((unsigned char *)info->content_ccnb, info->content_comps,
00238                                   state->items[i].contents, state->items[i].components);
00239                 if (mc == (info->content_comps->n - 1)) {
00240                     fprintf(stderr, "Duplicate content\n");
00241                     return (0);
00242                 }
00243             }
00244         }
00245         fprintf(stderr, "Storing content item %d ", c);
00246         state->items = realloc(state->items, (c + 1) * sizeof(*(state->items)));
00247         if (state->items == NULL) {
00248             perror("realloc failed");
00249             exit(1);
00250         }
00251         memset(&(state->items[c]), 0, sizeof(*(state->items)));
00252         state->items[c].components = ccn_indexbuf_create();
00253         /* XXX: probably should not have to do this re-parse of the content object */
00254         res = ccn_parse_ContentObject(info->content_ccnb, ccnb_size, &(state->items[c].x), state->items[c].components);
00255         if (res < 0) {
00256             fprintf(stderr, "- skipping: Not a ContentObject\n");
00257             ccn_indexbuf_destroy(&state->items[c].components);
00258             return (-1);
00259         }
00260         fprintf(stderr, "- ok\n");
00261         state->items[c].filename = "ephemeral";
00262         state->items[c].contents = malloc(ccnb_size);
00263         state->items[c].size = ccnb_size;
00264         memcpy(state->items[c].contents, info->content_ccnb, ccnb_size);
00265         state->count = c + 1;
00266         return (0);
00267 
00268     case CCN_UPCALL_CONTENT_BAD:
00269         fprintf(stderr, "Content signature verification failed! Discarding.\n");
00270         return (-1);
00271 
00272     case CCN_UPCALL_CONSUMED_INTEREST:
00273         fprintf(stderr, "Upcall consumed interest\n");
00274         return (-1); /* no data */
00275 
00276     case CCN_UPCALL_INTEREST:
00277         c = state->count;
00278         for (i = 0; i < c; i++) {
00279             match = ccn_content_matches_interest(state->items[i].contents,
00280                                                  state->items[i].size,
00281                                                  1,
00282                                                  NULL,
00283                                                  info->interest_ccnb,
00284                                                  info->pi->offset[CCN_PI_E],
00285                                                  info->pi);
00286             if (match) {
00287                 ccn_put(info->h, state->items[i].contents, state->items[i].size);
00288                 fprintf(stderr, "Sending %s\n", state->items[i].filename);
00289                 if (i < c - 1) {
00290                     item = state->items[i];
00291                     memmove(&(state->items[i]), &(state->items[i+1]), sizeof(item) * ((c - 1) - i));
00292                     state->items[c - 1] = item;
00293                 }
00294                 return (1);
00295             }
00296         }
00297         return(0);
00298     case CCN_UPCALL_CONTENT_KEYMISSING:
00299     case CCN_UPCALL_CONTENT_RAW:
00300         /* should not happen */
00301         return (-1);
00302     }
00303     return (-1);
00304 }

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