00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
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);
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
00301 return (-1);
00302 }
00303 return (-1);
00304 }