enum ndn_upcall_res incoming_interest( struct ndn_closure *selfp, enum ndn_upcall_kind kind, struct ndn_upcall_info *info) { struct ndn_charbuf *cob = selfp->data; int res; switch (kind) { case NDN_UPCALL_FINAL: break; case NDN_UPCALL_INTEREST: if (ndn_content_matches_interest(cob->buf, cob->length, 1, NULL, info->interest_ndnb, info->pi->offset[NDN_PI_E], info->pi)) { res = ndn_put(info->h, cob->buf, cob->length); if (res >= 0) { selfp->intdata = 1; ndn_set_run_timeout(info->h, 0); return(NDN_UPCALL_RESULT_INTEREST_CONSUMED); } } break; default: break; } return(NDN_UPCALL_RESULT_OK); }
enum ndn_upcall_res outgoing_content(struct ndn_closure *selfp, enum ndn_upcall_kind kind, struct ndn_upcall_info *info) { struct mini_store *md; struct ndn_charbuf *cob = NULL; int i; int res = 0; int which; md = selfp->data; which = md->me.intdata; if (kind == NDN_UPCALL_FINAL) { fprintf(stderr, "NDN_UPCALL_FINAL for store %d\n", which); for (i = 0; i < MINI_STORE_LIMIT; i++) ndn_charbuf_destroy(&md->cob[i]); return(NDN_UPCALL_RESULT_OK); } printf("Store %d got interest matching %d components, kind = %d", which, info->matched_comps, kind); /* Look through our little pile of content and send one that matches */ if (kind == NDN_UPCALL_INTEREST) { for (i = 0; i < MINI_STORE_LIMIT; i++) { cob = md->cob[i]; if (cob != NULL && cob_matches(info, cob)) { res = ndn_put(info->h, cob->buf, cob->length); if (res == -1) { fprintf(stderr, "... error sending data\n"); return(NDN_UPCALL_RESULT_ERR); } else { printf("... sent my content:\n"); printraw(cob->buf, cob->length); ndn_charbuf_destroy(&md->cob[i]); return(NDN_UPCALL_RESULT_INTEREST_CONSUMED); } } } printf("... no match\n"); } else printf("\n"); return(NDN_UPCALL_RESULT_ERR); }
enum ndn_upcall_res hash_store_handle_proto_sha256(struct hash_store* self, struct ndn_upcall_info* info) { int res; // extract hash const uint8_t* hash; size_t hashsz; res = ndn_name_comp_get(info->interest_ndnb, info->interest_comps, 1, &hash, &hashsz); if (res != 0 || hashsz != SEGMENT_HASHSZ) return NDN_UPCALL_RESULT_ERR; LOG("hash_store_handle_proto_sha256("); LOG_hash(hash, hashsz); LOG(") "); // find content ndnr_accession accession = hash_store_find(self, hash); if (accession == NDNR_NULL_ACCESSION) { LOG("MISS\n"); return NDN_UPCALL_RESULT_OK; } struct content_entry* orig_content = r_store_content_from_accession(self->h, accession); if (orig_content == NULL) { LOG("LOST\n"); return NDN_UPCALL_RESULT_OK; } if (orig_content->cob == NULL && r_store_content_base(self->h, orig_content) == NULL) { LOG("LOST\n"); return NDN_UPCALL_RESULT_OK; } LOG("HIT %" PRIx64 ", ", (uint64_t)ndnr_accession_encode(self->h, accession)); // extract payload struct ndn_parsed_ContentObject orig_pco = {0}; res = ndn_parse_ContentObject(orig_content->cob->buf, orig_content->cob->length, &orig_pco, NULL); if (res != 0) { LOG("cannot parse\n"); return NDN_UPCALL_RESULT_OK; } const uint8_t* payload; size_t payloadsz; res = ndn_content_get_value(orig_content->cob->buf, orig_content->cob->length, &orig_pco, &payload, &payloadsz); if (res != 0) { LOG("cannot extract payload\n"); return NDN_UPCALL_RESULT_OK; } // verify hash if (!hash_store_verify_hash(self, payload, payloadsz, hash)) { LOG("hash mismatch\n"); return NDN_UPCALL_RESULT_OK; } // build reply struct ndn_charbuf* reply = ndn_charbuf_create(); hash_store_build_reply(self, reply, hash, payload, payloadsz); // send reply TODO use queues res = ndn_put(info->h, reply->buf, reply->length); if (res != 0) { LOG("cannot send\n"); ndn_charbuf_destroy(&reply); return NDN_UPCALL_RESULT_OK; } ndn_charbuf_destroy(&reply); LOG("OK\n"); return NDN_UPCALL_RESULT_INTEREST_CONSUMED; }
enum ndn_upcall_res interest_handler(struct ndn_closure *selfp, enum ndn_upcall_kind upcall_kind, struct ndn_upcall_info *info) { int i, c, mc, match, res; struct handlerstateitem item; struct handlerstate *state; size_t ndnb_size = 0; state = selfp->data; switch(upcall_kind) { case NDN_UPCALL_FINAL: fprintf(stderr, "Upcall final\n"); return (0); case NDN_UPCALL_INTEREST_TIMED_OUT: fprintf(stderr, "refresh\n"); return (NDN_UPCALL_RESULT_REEXPRESS); case NDN_UPCALL_CONTENT: case NDN_UPCALL_CONTENT_UNVERIFIED: ndnb_size = info->pco->offset[NDN_PCO_E]; c = state->count; for (i = 0; i < c; i++) { if (info->content_comps->n == state->items[i].components->n) { mc = match_components((unsigned char *)info->content_ndnb, info->content_comps, state->items[i].contents, state->items[i].components); if (mc == (info->content_comps->n - 1)) { fprintf(stderr, "Duplicate content\n"); return (0); } } } fprintf(stderr, "Storing content item %d ", c); state->items = realloc(state->items, (c + 1) * sizeof(*(state->items))); if (state->items == NULL) { perror("realloc failed"); exit(1); } memset(&(state->items[c]), 0, sizeof(*(state->items))); state->items[c].components = ndn_indexbuf_create(); /* XXX: probably should not have to do this re-parse of the content object */ res = ndn_parse_ContentObject(info->content_ndnb, ndnb_size, &(state->items[c].x), state->items[c].components); if (res < 0) { fprintf(stderr, "- skipping: Not a ContentObject\n"); ndn_indexbuf_destroy(&state->items[c].components); return (-1); } fprintf(stderr, "- ok\n"); state->items[c].filename = "ephemeral"; state->items[c].contents = malloc(ndnb_size); state->items[c].size = ndnb_size; memcpy(state->items[c].contents, info->content_ndnb, ndnb_size); state->count = c + 1; return (0); case NDN_UPCALL_CONTENT_BAD: fprintf(stderr, "Content signature verification failed! Discarding.\n"); return (-1); case NDN_UPCALL_CONSUMED_INTEREST: fprintf(stderr, "Upcall consumed interest\n"); return (-1); /* no data */ case NDN_UPCALL_INTEREST: c = state->count; for (i = 0; i < c; i++) { match = ndn_content_matches_interest(state->items[i].contents, state->items[i].size, 1, NULL, info->interest_ndnb, info->pi->offset[NDN_PI_E], info->pi); if (match) { ndn_put(info->h, state->items[i].contents, state->items[i].size); fprintf(stderr, "Sending %s\n", state->items[i].filename); if (i < c - 1) { item = state->items[i]; memmove(&(state->items[i]), &(state->items[i+1]), sizeof(item) * ((c - 1) - i)); state->items[c - 1] = item; } return (1); } } return(0); case NDN_UPCALL_CONTENT_KEYMISSING: case NDN_UPCALL_CONTENT_RAW: /* should not happen */ return (-1); } return (-1); }
int main(int argc, char **argv) { const char *progname = argv[0]; struct ndn *ndn = NULL; struct ndn_charbuf *root = NULL; struct ndn_charbuf *name = NULL; struct ndn_charbuf *temp = NULL; struct ndn_charbuf *templ = NULL; struct ndn_signing_params sp = NDN_SIGNING_PARAMS_INIT; long expire = -1; long blocksize = 1024; int i; int status = 0; int res; ssize_t read_res; unsigned char *buf = NULL; struct mydata mydata = { 0 }; struct ndn_closure in_content = {.p=&incoming_content, .data=&mydata}; struct ndn_closure in_interest = {.p=&incoming_interest, .data=&mydata}; while ((res = getopt(argc, argv, "hx:b:")) != -1) { switch (res) { case 'x': expire = atol(optarg); if (expire <= 0) usage(progname); break; case 'b': blocksize = atol(optarg); break; default: case 'h': usage(progname); break; } } argc -= optind; argv += optind; if (argc != 1) usage(progname); name = ndn_charbuf_create(); res = ndn_name_from_uri(name, argv[0]); if (res < 0) { fprintf(stderr, "%s: bad NDN URI: %s\n", progname, argv[0]); exit(1); } ndn = ndn_create(); if (ndn_connect(ndn, NULL) == -1) { perror("Could not connect to ndnd"); exit(1); } buf = calloc(1, blocksize); root = name; name = ndn_charbuf_create(); temp = ndn_charbuf_create(); templ = ndn_charbuf_create(); /* Set up a handler for interests */ ndn_charbuf_append(name, root->buf, root->length); ndn_set_interest_filter(ndn, name, &in_interest); /* Initiate check to see whether there is already something there. */ ndn_charbuf_reset(temp); ndn_charbuf_putf(temp, "%d", 0); ndn_name_append(name, temp->buf, temp->length); ndn_charbuf_reset(templ); ndnb_element_begin(templ, NDN_DTAG_Interest); ndnb_element_begin(templ, NDN_DTAG_Name); ndnb_element_end(templ); /* </Name> */ ndnb_tagged_putf(templ, NDN_DTAG_MaxSuffixComponents, "%d", 1); // XXX - use pubid ndnb_element_end(templ); /* </Interest> */ res = ndn_express_interest(ndn, name, &in_content, templ); if (res < 0) abort(); sp.freshness = expire; for (i = 0;; i++) { read_res = read_full(0, buf, blocksize); if (read_res < 0) { perror("read"); read_res = 0; status = 1; } if (read_res < blocksize) { sp.sp_flags |= NDN_SP_FINAL_BLOCK; } ndn_charbuf_reset(name); ndn_charbuf_append(name, root->buf, root->length); ndn_charbuf_reset(temp); ndn_charbuf_putf(temp, "%d", i); ndn_name_append(name, temp->buf, temp->length); ndn_charbuf_reset(temp); ndn_charbuf_append(temp, buf, read_res); ndn_charbuf_reset(temp); res = ndn_sign_content(ndn, temp, name, &sp, buf, read_res); if (res != 0) { fprintf(stderr, "Failed to sign ContentObject (res == %d)\n", res); exit(1); } /* Put the keylocator in the first block only. */ sp.sp_flags |= NDN_SP_OMIT_KEY_LOCATOR; if (i == 0) { /* Finish check for old content */ if (mydata.content_received == 0) ndn_run(ndn, 100); if (mydata.content_received > 0) { fprintf(stderr, "%s: name is in use: %s\n", progname, argv[0]); exit(1); } mydata.outstanding++; /* the first one is free... */ } res = ndn_put(ndn, temp->buf, temp->length); if (res < 0) { fprintf(stderr, "ndn_put failed (res == %d)\n", res); exit(1); } if (read_res < blocksize) break; if (mydata.outstanding > 0) mydata.outstanding--; else res = 10; res = ndn_run(ndn, res * 100); if (res < 0) { status = 1; break; } } free(buf); buf = NULL; ndn_charbuf_destroy(&root); ndn_charbuf_destroy(&name); ndn_charbuf_destroy(&temp); ndn_destroy(&ndn); exit(status); }
int main(int argc, char **argv) { const char *progname = argv[0]; struct ndn *ndn = NULL; struct ndn_charbuf *name = NULL; struct ndn_charbuf *pname = NULL; struct ndn_charbuf *temp = NULL; struct ndn_charbuf *extopt = NULL; long expire = -1; int versioned = 0; size_t blocksize = 8*1024; int status = 0; int res; ssize_t read_res; unsigned char *buf = NULL; enum ndn_content_type content_type = NDN_CONTENT_DATA; struct ndn_closure in_interest = {.p=&incoming_interest}; const char *postver = NULL; const char *key_uri = NULL; int force = 0; int verbose = 0; int timeout = -1; int setfinal = 0; int prefixcomps = -1; int fd; struct ndn_signing_params sp = NDN_SIGNING_PARAMS_INIT; while ((res = getopt(argc, argv, "e:fhk:lvV:p:t:w:x:")) != -1) { switch (res) { case 'e': if (extopt == NULL) extopt = ndn_charbuf_create(); fd = open(optarg, O_RDONLY); if (fd < 0) { perror(optarg); exit(1); } for (;;) { read_res = read(fd, ndn_charbuf_reserve(extopt, 64), 64); if (read_res <= 0) break; extopt->length += read_res; } if (read_res < 0) perror(optarg); close(fd); break; case 'f': force = 1; break; case 'l': setfinal = 1; // set FinalBlockID to last comp of name break; case 'k': key_uri = optarg; break; case 'p': prefixcomps = atoi(optarg); if (prefixcomps < 0) usage(progname); break; case 'x': expire = atol(optarg); if (expire <= 0) usage(progname); break; case 'v': verbose = 1; break; case 'V': versioned = 1; postver = optarg; if (0 == memcmp(postver, "%00", 3)) setfinal = 1; break; case 'w': timeout = atol(optarg); if (timeout <= 0) usage(progname); timeout *= 1000; break; case 't': if (0 == strcasecmp(optarg, "DATA")) { content_type = NDN_CONTENT_DATA; break; } if (0 == strcasecmp(optarg, "ENCR")) { content_type = NDN_CONTENT_ENCR; break; } if (0 == strcasecmp(optarg, "GONE")) { content_type = NDN_CONTENT_GONE; break; } if (0 == strcasecmp(optarg, "KEY")) { content_type = NDN_CONTENT_KEY; break; } if (0 == strcasecmp(optarg, "LINK")) { content_type = NDN_CONTENT_LINK; break; } if (0 == strcasecmp(optarg, "NACK")) { content_type = NDN_CONTENT_NACK; break; } content_type = atoi(optarg); if (content_type > 0 && content_type <= 0xffffff) break; fprintf(stderr, "Unknown content type %s\n", optarg); /* FALLTHRU */ default: case 'h': usage(progname); break; } } argc -= optind; argv += optind; if (argv[0] == NULL) usage(progname); name = ndn_charbuf_create(); res = ndn_name_from_uri(name, argv[0]); if (res < 0) { fprintf(stderr, "%s: bad ndn URI: %s\n", progname, argv[0]); exit(1); } if (argv[1] != NULL) fprintf(stderr, "%s warning: extra arguments ignored\n", progname); /* Preserve the original prefix, in case we add versioning, * but trim it down if requested for the interest filter registration */ pname = ndn_charbuf_create(); ndn_charbuf_append(pname, name->buf, name->length); if (prefixcomps >= 0) { res = ndn_name_chop(pname, NULL, prefixcomps); if (res < 0) { fprintf(stderr, "%s: unable to trim name to %d component%s.\n", progname, prefixcomps, prefixcomps == 1 ? "" : "s"); exit(1); } } /* Connect to ndnd */ ndn = ndn_create(); if (ndn_connect(ndn, NULL) == -1) { perror("Could not connect to ndnd"); exit(1); } /* Read the actual user data from standard input */ buf = calloc(1, blocksize); read_res = read_full(0, buf, blocksize); if (read_res < 0) { perror("read"); read_res = 0; status = 1; } /* Tack on the version component if requested */ if (versioned) { res = ndn_create_version(ndn, name, NDN_V_REPLACE | NDN_V_NOW | NDN_V_HIGH, 0, 0); if (res < 0) { fprintf(stderr, "%s: ndn_create_version() failed\n", progname); exit(1); } if (postver != NULL) { res = ndn_name_from_uri(name, postver); if (res < 0) { fprintf(stderr, "-V %s: invalid name suffix\n", postver); exit(0); } } } temp = ndn_charbuf_create(); /* Ask for a FinalBlockID if appropriate. */ if (setfinal) sp.sp_flags |= NDN_SP_FINAL_BLOCK; if (res < 0) { fprintf(stderr, "Failed to create signed_info (res == %d)\n", res); exit(1); } /* Set content type */ sp.type = content_type; /* Set freshness */ if (expire >= 0) { if (sp.template_ndnb == NULL) { sp.template_ndnb = ndn_charbuf_create(); ndn_charbuf_append_tt(sp.template_ndnb, NDN_DTAG_SignedInfo, NDN_DTAG); } else if (sp.template_ndnb->length > 0) { sp.template_ndnb->length--; } ndnb_tagged_putf(sp.template_ndnb, NDN_DTAG_FreshnessSeconds, "%ld", expire); sp.sp_flags |= NDN_SP_TEMPL_FRESHNESS; ndn_charbuf_append_closer(sp.template_ndnb); } /* Set key locator, if supplied */ if (key_uri != NULL) { struct ndn_charbuf *c = ndn_charbuf_create(); res = ndn_name_from_uri(c, key_uri); if (res < 0) { fprintf(stderr, "%s is not a valid ndnx URI\n", key_uri); exit(1); } if (sp.template_ndnb == NULL) { sp.template_ndnb = ndn_charbuf_create(); ndn_charbuf_append_tt(sp.template_ndnb, NDN_DTAG_SignedInfo, NDN_DTAG); } else if (sp.template_ndnb->length > 0) { sp.template_ndnb->length--; } ndn_charbuf_append_tt(sp.template_ndnb, NDN_DTAG_KeyLocator, NDN_DTAG); ndn_charbuf_append_tt(sp.template_ndnb, NDN_DTAG_KeyName, NDN_DTAG); ndn_charbuf_append(sp.template_ndnb, c->buf, c->length); ndn_charbuf_append_closer(sp.template_ndnb); ndn_charbuf_append_closer(sp.template_ndnb); sp.sp_flags |= NDN_SP_TEMPL_KEY_LOCATOR; ndn_charbuf_append_closer(sp.template_ndnb); ndn_charbuf_destroy(&c); } if (extopt != NULL && extopt->length > 0) { if (sp.template_ndnb == NULL) { sp.template_ndnb = ndn_charbuf_create(); ndn_charbuf_append_tt(sp.template_ndnb, NDN_DTAG_SignedInfo, NDN_DTAG); } else if (sp.template_ndnb->length > 0) { sp.template_ndnb->length--; } ndnb_append_tagged_blob(sp.template_ndnb, NDN_DTAG_ExtOpt, extopt->buf, extopt->length); sp.sp_flags |= NDN_SP_TEMPL_EXT_OPT; ndn_charbuf_append_closer(sp.template_ndnb); } /* Create the signed content object, ready to go */ temp->length = 0; res = ndn_sign_content(ndn, temp, name, &sp, buf, read_res); if (res != 0) { fprintf(stderr, "Failed to encode ContentObject (res == %d)\n", res); exit(1); } if (read_res == blocksize) { read_res = read_full(0, buf, 1); if (read_res == 1) { fprintf(stderr, "%s: warning - truncated data\n", argv[0]); status = 1; } } free(buf); buf = NULL; if (force) { /* At user request, send without waiting to see an interest */ res = ndn_put(ndn, temp->buf, temp->length); if (res < 0) { fprintf(stderr, "ndn_put failed (res == %d)\n", res); exit(1); } } else { in_interest.data = temp; /* Set up a handler for interests */ res = ndn_set_interest_filter(ndn, pname, &in_interest); if (res < 0) { fprintf(stderr, "Failed to register interest (res == %d)\n", res); exit(1); } res = ndn_run(ndn, timeout); if (in_interest.intdata == 0) { if (verbose) fprintf(stderr, "Nobody's interested\n"); exit(1); } } if (verbose) { struct ndn_charbuf *uri = ndn_charbuf_create(); uri->length = 0; ndn_uri_append(uri, name->buf, name->length, 1); printf("wrote %s\n", ndn_charbuf_as_string(uri)); ndn_charbuf_destroy(&uri); } ndn_destroy(&ndn); ndn_charbuf_destroy(&name); ndn_charbuf_destroy(&pname); ndn_charbuf_destroy(&temp); ndn_charbuf_destroy(&sp.template_ndnb); ndn_charbuf_destroy(&extopt); exit(status); }