Exemple #1
0
/**
 * Basic tests of ndn_btree_io_from_directory() and its methods.
 *
 * Assumes TEST_DIRECTORY has been set.
 */
static int
test_btree_io(void)
{
    int res;
    struct ndn_btree_node nodespace = {0};
    struct ndn_btree_node *node = &nodespace;
    struct ndn_btree_io *io = NULL;

    /* Open it up. */
    io = ndn_btree_io_from_directory(getenv("TEST_DIRECTORY"), NULL);
    CHKPTR(io);
    node->buf = ndn_charbuf_create();
    CHKPTR(node->buf);
    node->nodeid = 12345;
    res = io->btopen(io, node);
    CHKSYS(res);
    FAILIF(node->iodata == NULL);
    ndn_charbuf_putf(node->buf, "smoke");
    res = io->btwrite(io, node);
    CHKSYS(res);
    node->buf->length = 0;
    ndn_charbuf_putf(node->buf, "garbage");
    res = io->btread(io, node, 500000);
    CHKSYS(res);
    FAILIF(node->buf->length != 5);
    FAILIF(node->buf->limit > 10000);
    node->clean = 5;
    ndn_charbuf_putf(node->buf, "r");
    res = io->btwrite(io, node);
    CHKSYS(res);
    node->buf->length--;
    ndn_charbuf_putf(node->buf, "d");
    res = io->btread(io, node, 1000);
    CHKSYS(res);
    FAILIF(0 != strcmp("smoker", ndn_charbuf_as_string(node->buf)));
    node->buf->length--;
    res = io->btwrite(io, node);
    CHKSYS(res);
    node->buf->length = 0;
    ndn_charbuf_putf(node->buf, "garbage");
    node->clean = 0;
    res = io->btread(io, node, 1000);
    CHKSYS(res);
    res = io->btclose(io, node);
    CHKSYS(res);
    FAILIF(node->iodata != NULL);
    FAILIF(0 != strcmp("smoke", ndn_charbuf_as_string(node->buf)));
    res = io->btdestroy(&io);
    CHKSYS(res);
    ndn_charbuf_destroy(&node->buf);
    return(res);
}
Exemple #2
0
/**
 * Read the contents of the repository config file
 *
 * Calls r_init_fail and returns NULL in case of error.
 * @returns unparsed content of config file in a newly allocated charbuf
 */
struct ndn_charbuf *
r_init_read_config(struct ndnr_handle *h)
{
    struct ndn_charbuf *path = NULL;
    struct ndn_charbuf *contents = NULL;
    size_t sz = 800;
    ssize_t sres = -1;
    int fd;
    
    h->directory = getenv("NDNR_DIRECTORY");
    if (h->directory == NULL || h->directory[0] == 0)
        h->directory = ".";
    path = ndn_charbuf_create();
    contents = ndn_charbuf_create();
    if (path == NULL || contents == NULL)
        return(NULL);
    ndn_charbuf_putf(path, "%s/config", h->directory);
    fd = open(ndn_charbuf_as_string(path), O_RDONLY);
    if (fd == -1) {
        if (errno == ENOENT)
            sres = 0;
        else
            r_init_fail(h, __LINE__, ndn_charbuf_as_string(path), errno);
    }
    else {
        for (;;) {
            sres = read(fd, ndn_charbuf_reserve(contents, sz), sz);
            if (sres == 0)
                break;
            if (sres < 0) {
                r_init_fail(h, __LINE__, "Read failed reading config", errno);
                break;
            }
            contents->length += sres;
            if (contents->length > 999999) {
                r_init_fail(h, __LINE__, "config file too large", 0);
                sres = -1;
                break;
            }
        }
        close(fd);
    }
    ndn_charbuf_destroy(&path);
    if (sres < 0)
        ndn_charbuf_destroy(&contents);
    return(contents);
}
Exemple #3
0
static int
merge_files(struct ndnr_handle *h)
{
    int i, last_file;
    int res;
    struct ndn_charbuf *filename = ndn_charbuf_create();
    
    // first parse the file(s) making sure there are no errors
    for (i = 2;; i++) {
        filename->length = 0;
        ndn_charbuf_putf(filename, "repoFile%d", i);
        res = r_init_map_and_process_file(h, filename, 0);
        if (res == 1)
            break;
        if (res < 0) {
            ndnr_msg(h, "Error parsing repository file %s", ndn_charbuf_as_string(filename));
            return (-1);
        }
    }
    last_file = i - 1;
    
    for (i = 2; i <= last_file; i++) {
        filename->length = 0;
        ndn_charbuf_putf(filename, "repoFile%d", i);
        res = r_init_map_and_process_file(h, filename, 1);
        if (res < 0) {
            ndnr_msg(h, "Error in phase 2 incorporating repository file %s", ndn_charbuf_as_string(filename));
            return (-1);
        }
    }
    
    for (i = last_file; i > 1; --i) {
        filename->length = 0;
        ndn_charbuf_putf(filename, "%s/repoFile%d", h->directory, i);
        if (NDNSHOULDLOG(h, LM_128, NDNL_INFO))
            ndnr_msg(h, "unlinking %s", ndn_charbuf_as_string(filename));   
        unlink(ndn_charbuf_as_string(filename));
    }
    ndn_charbuf_destroy(&filename);
    return (0);
}
Exemple #4
0
/**
 * Use standard mkdtemp() to create a subdirectory of the
 * current working directory, and set the TEST_DIRECTORY environment
 * variable with its name.
 */
static int
test_directory_creation(void)
{
    int res;
    struct ndn_charbuf *dirbuf;
    char *temp;
    
    dirbuf = ndn_charbuf_create();
    CHKPTR(dirbuf);
    res = ndn_charbuf_putf(dirbuf, "./%s", "_bt_XXXXXX");
    CHKSYS(res);
    temp = mkdtemp(ndn_charbuf_as_string(dirbuf));
    CHKPTR(temp);
    res = ndn_charbuf_putf(dirbuf, "/%s", "_test");
    CHKSYS(res);
    res = mkdir(ndn_charbuf_as_string(dirbuf), 0777);
    CHKSYS(res);
    printf("Created directory %s\n", ndn_charbuf_as_string(dirbuf));
    setenv("TEST_DIRECTORY", ndn_charbuf_as_string(dirbuf), 1);
    ndn_charbuf_destroy(&dirbuf);
    return(res);
}
Exemple #5
0
struct hash_store* hash_store_ctor(struct ndnr_handle* h) {
  struct hash_store* self = calloc(1, sizeof(*self));
  self->h = h;
  h->hashstore = self;
  
  // open btree with disk IO
  struct ndn_charbuf* path = ndn_charbuf_create();
  ndn_charbuf_putf(path, "%s/hashstore", h->directory);
  int res = mkdir(ndn_charbuf_as_string(path), 0700);
  if (res != 0 && errno != EEXIST) { free(self); ndn_charbuf_destroy(&path); return NULL; }
  self->btree = ndn_btree_create();
  self->btree->io = ndn_btree_io_from_directory(ndn_charbuf_as_string(path), NULL);
  if (self->btree->io == NULL) { free(self); ndn_charbuf_destroy(&path); ndn_btree_destroy(&self->btree); return NULL; }
  ndn_charbuf_destroy(&path);

  struct ndn_btree_node* node = ndn_btree_getnode(self->btree, 1, 0);
  self->btree->nextnodeid = self->btree->io->maxnodeid + 1;
  if (node->buf->length == 0) {
    res = ndn_btree_init_node(node, 0, 'R', 0);
  }
  
  LOG("hash_store_ctor\n");
  return self;
}
Exemple #6
0
/* returns
 *  res >= 0    res characters remaining to be processed from data
 *  decoder state will be set appropriately   
 */
static size_t
process_data(struct ndn_skeleton_decoder *d, unsigned char *data, size_t n, struct ndn_charbuf *c)
{
    size_t s;
    
retry:
    s = ndn_skeleton_decode(d, data, n);
    if (d->state < 0)
        return (0);
    if (NDN_FINAL_DSTATE(d->state)) {
        c->length = 0;
        ndn_uri_append(c, data, s, 1);
        printf("%s\n", ndn_charbuf_as_string(c));
        data += s;
        n -= s;
        if (n > 0) goto retry;
    }
    return(n);
}
Exemple #7
0
/**
 * Load a link to the repo policy from the repoPolicy file and load the link
 * target to extract the actual policy.
 * If a policy file does not exist a new one is created, with a link to a policy
 * based either on the environment variable NDNR_GLOBAL_PREFIX or the system
 * default value of ndn:/named-data.net/ndn/Repos, plus the system defaults for
 * other fields.
 * This routine must be called after the btree code is initialized and capable
 * of returning content objects.
 * Sets the parsed_policy field of the handle to be the new policy.
 */
static int
load_policy(struct ndnr_handle *ndnr)
{
    int fd;
    ssize_t res;
    struct content_entry *content = NULL;
    const unsigned char *content_msg = NULL;
    struct ndn_parsed_ContentObject pco = {0};
    struct ndn_parsed_Link pl = {0};
    struct ndn_indexbuf *nc = NULL;
    struct ndn_charbuf *basename = NULL;
    struct ndn_charbuf *policy = NULL;
    struct ndn_charbuf *policy_cob = NULL;
    struct ndn_charbuf *policyFileName;
    const char *global_prefix;
    const unsigned char *buf = NULL;
    size_t length = 0;
    int segment = 0;
    int final = 0;
    struct ndn_buf_decoder decoder;
    struct ndn_buf_decoder *d;
    
    policyFileName = ndn_charbuf_create();
    ndn_charbuf_putf(policyFileName, "%s/repoPolicy", ndnr->directory);
    ndnr->parsed_policy = ndnr_parsed_policy_create();
    fd = open(ndn_charbuf_as_string(policyFileName), O_RDONLY);
    if (fd >= 0) {
        ndnr->policy_link_cob = ndn_charbuf_create();
        ndn_charbuf_reserve(ndnr->policy_link_cob, 4096);   // limits the size of the policy link
        ndnr->policy_link_cob->length = 0;    // clear the buffer
        res = read(fd, ndnr->policy_link_cob->buf, ndnr->policy_link_cob->limit - ndnr->policy_link_cob->length);
        close(fd);
        if (res == -1) {
            r_init_fail(ndnr, __LINE__, "Error reading repoPolicy file.", errno);
            ndn_charbuf_destroy(&ndnr->policy_link_cob);
            ndn_charbuf_destroy(&policyFileName);
            return(-1);
        }
        ndnr->policy_link_cob->length = res;
        nc = ndn_indexbuf_create();
        res = ndn_parse_ContentObject(ndnr->policy_link_cob->buf,
                                      ndnr->policy_link_cob->length, &pco, nc);
        res = ndn_ref_tagged_BLOB(NDN_DTAG_Content, ndnr->policy_link_cob->buf,
                                  pco.offset[NDN_PCO_B_Content],
                                  pco.offset[NDN_PCO_E_Content],
                                  &buf, &length);
        d = ndn_buf_decoder_start(&decoder, buf, length);
        res = ndn_parse_Link(d, &pl, NULL);
        if (res <= 0) {
            ndnr_msg(ndnr, "Policy link is malformed.");
            goto CreateNewPolicy;
        }
        basename = ndn_charbuf_create();
        ndn_charbuf_append(basename, buf + pl.offset[NDN_PL_B_Name],
                           pl.offset[NDN_PL_E_Name] - pl.offset[NDN_PL_B_Name]);
        ndnr->policy_name = ndn_charbuf_create(); // to detect writes to this name
        ndn_charbuf_append_charbuf(ndnr->policy_name, basename); // has version
        ndn_name_chop(ndnr->policy_name, NULL, -1); // get rid of version
        policy = ndn_charbuf_create();
        // if we fail to retrieve the link target, report and then create a new one
        do {
            ndn_name_append_numeric(basename, NDN_MARKER_SEQNUM, segment++);
            content = r_store_lookup_ndnb(ndnr, basename->buf, basename->length);
            if (content == NULL) {
                ndnr_debug_ndnb(ndnr, __LINE__, "policy lookup failed for", NULL,
                                basename->buf, basename->length);
                break;
            }
            ndn_name_chop(basename, NULL, -1);
            content_msg = r_store_content_base(ndnr, content);
            if (content_msg == NULL) {
                ndnr_debug_ndnb(ndnr, __LINE__, "Unable to read policy object", NULL,
                                basename->buf, basename->length);
                break;
            }
            res = ndn_parse_ContentObject(content_msg, r_store_content_size(ndnr, content), &pco, nc);
            res = ndn_ref_tagged_BLOB(NDN_DTAG_Content, content_msg,
                                      pco.offset[NDN_PCO_B_Content],
                                      pco.offset[NDN_PCO_E_Content],
                                      &buf, &length);
            ndn_charbuf_append(policy, buf, length);
            final = ndn_is_final_pco(content_msg, &pco, nc);
        } while (!final && segment < 100);
Exemple #8
0
int
r_init_map_and_process_file(struct ndnr_handle *h, struct ndn_charbuf *filename, int add_content)
{
    int res = 0;
    int dres;
    struct stat statbuf;
    unsigned char *mapped_file = MAP_FAILED;
    unsigned char *msg;
    size_t size;
    int fd = -1;
    struct content_entry *content;
    struct ndn_skeleton_decoder *d;
    struct fdholder *fdholder;
    
    fd = r_io_open_repo_data_file(h, ndn_charbuf_as_string(filename), 0);
    if (fd == -1)   // Normal exit
        return(1);
    
    res = fstat(fd, &statbuf);
    if (res != 0) {
        ndnr_msg(h, "stat failed for %s (fd=%d), %s (errno=%d)",
                 ndn_charbuf_as_string(filename), fd, strerror(errno), errno);
        res = -errno;
        goto Bail;
    }
    if (statbuf.st_size == 0)
        goto Bail;
    
    mapped_file = mmap(NULL, statbuf.st_size, PROT_READ, MAP_SHARED, fd, 0);
    if (mapped_file == MAP_FAILED) {
        ndnr_msg(h, "mmap failed for %s (fd=%d), %s (errno=%d)",
                 ndn_charbuf_as_string(filename), fd, strerror(errno), errno);
        res = -errno;
        goto Bail;
    }
    fdholder = r_io_fdholder_from_fd(h, fd);
    d = &fdholder->decoder;
    msg = mapped_file;
    size = statbuf.st_size;
    while (d->index < size) {
        dres = ndn_skeleton_decode(d, msg + d->index, size - d->index);
        if (!NDN_FINAL_DSTATE(d->state))
            break;
        if (add_content) {
            content = process_incoming_content(h, fdholder, msg + d->index - dres, dres, NULL);
            if (content != NULL)
                r_store_commit_content(h, content);
        }
    }
    
    if (d->index != size || !NDN_FINAL_DSTATE(d->state)) {
        ndnr_msg(h, "protocol error on fdholder %u (state %d), discarding %d bytes",
                 fdholder->filedesc, d->state, (int)(size - d->index));
        res = -1;
        goto Bail;
    }
    
Bail:
    if (mapped_file != MAP_FAILED)
        munmap(mapped_file, statbuf.st_size);
    r_io_shutdown_client_fd(h, fd);
    return (res);
}
Exemple #9
0
/**
 * Parse the buffered configuration found in config
 *
 * The pass argument controls what is done with the result:
 *   0 - silent check for syntax errors;
 *   1 - check for syntax errors and warnings, logging the results,
 *   2 - incorporate settings into environ.
 *
 * @returns -1 if an error is found, otherwise the count of warnings.
 */
int
r_init_parse_config(struct ndnr_handle *h, struct ndn_charbuf *config, int pass)
{
    struct ndn_charbuf *key = NULL;
    struct ndn_charbuf *value = NULL;
    const unsigned char *b;
    int line;
    size_t i;
    size_t sol; /* start of line */
    size_t len; /* config->len */
    size_t ndx; /* temp for column report*/
    int ch;
    int warns = 0;
    int errors = 0;
    int use_it = 0;
    static const char pclegal[] = 
        "~@%-+=:,./[]"
        "abcdefghijklmnopqrstuvwxyz"
        "0123456789"
        "_"
        "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    const char *klegal = strchr(pclegal, 'a');
    int flags; /* for reporting */
    
    b = config->buf;
    len = config->length;
    if (len == 0)
        return(0);
    ndn_charbuf_as_string(config);
    key = ndn_charbuf_create();
    value = ndn_charbuf_create();
    if (key == NULL || value == NULL)
        return(-1);
    /* Ensure there is null termination in the buffered config */
    if (ndn_charbuf_as_string(config) == NULL)
        return(-1);
    for (line = 1, i = 0, ch = b[0], sol = 0; i < len;) {
        flags = pass;
        use_it = 0;
        if (ch > ' ' && ch != '#') {
            key->length = value->length = 0;
            /* parse key */
            while (i < len && ch != '\n' && ch != '=') {
                ndn_charbuf_append_value(key, ch, 1);
                ch = b[++i];
            }
            if (ch == '=')
                ch = b[++i];
            else {
                r_init_config_msg(h, flags, line, key->length, "missing '='");
                flags |= NDNR_CONFIG_IGNORELINE;
                warns++;
                ch = '\n';
            }
            /* parse value */
            while (i < len && ch > ' ') {
                ndn_charbuf_append_value(value, ch, 1);
                ch = b[++i];
            }
            /* See if it might be one of ours */
            if (key->length < 5 || (memcmp(key->buf, "NDNR_", 5) != 0 &&
                                    memcmp(key->buf, "NDNS_", 5) != 0)) {
                r_init_config_msg(h, flags, line, 0,
                                  "ignoring unrecognized key");
                flags |= NDNR_CONFIG_IGNORELINE;
                warns++;
                use_it = 0;
            }
            else
                use_it = 1;

            /* Check charset of key */
            ndx = strspn(ndn_charbuf_as_string(key), klegal);
            if (ndx != key->length) {
                errors += use_it;
                r_init_config_msg(h, (flags | NDNR_CONFIG_ERR), line, ndx,
                                  "unexpected character in key");
                flags |= NDNR_CONFIG_IGNORELINE;
                warns++;
            }
            /* Check charset of value */
            ndx = strspn(ndn_charbuf_as_string(value), pclegal);
            if (ndx != value->length) {
                errors += use_it;
                r_init_config_msg(h, (flags | NDNR_CONFIG_ERR),
                                  line, key->length + 1 + ndx,
                                  "unexpected character in value");
                flags |= NDNR_CONFIG_IGNORELINE;
                warns++;
            }
        }
        if (ch == '#') {
            /* a comment line or error recovery. */
            while (i < len && ch != '\n')
                ch = b[++i];
        }
        while (i < len && ch <= ' ') {
            if (ch == '\n') {
                line++;
                sol = i;
                break;
            }
            if (memchr("\r\t ", ch, 3) == NULL) {
                r_init_config_msg(h, pass, line, i - sol,
                                  "non-whitespace control char at end of line");
                warns++;
            } 
            ch = b[++i];
        }
        if (i == len) {
            r_init_config_msg(h, flags, line, i - sol,
                              "missing newline at end of file");
            warns++;
            ch = '\n';
        }
        else if (ch == '\n')
            ch = b[++i];
        else {
            r_init_config_msg(h, flags, line, i - sol, "junk at end of line");
            flags |= NDNR_CONFIG_IGNORELINE;
            warns++;
            ch = '#';
        }
        if (flags == 0 && strcmp(ndn_charbuf_as_string(key), "NDNR_DEBUG") == 0) {
            /* Set this on pass 0 so that it takes effect sooner. */
            h->debug = 1;
            setenv("NDNR_DEBUG", ndn_charbuf_as_string(value), 1);
            h->debug = r_init_debug_getenv(h, "NDNR_DEBUG");
        }
        if (pass == 2 && use_it) {
            if (NDNSHOULDLOG(h, mmm, NDNL_FINEST))
                ndnr_msg(h, "config: %s=%s",
                        ndn_charbuf_as_string(key),
                        ndn_charbuf_as_string(value));
            setenv(ndn_charbuf_as_string(key), ndn_charbuf_as_string(value), 1);
        }
    }
    ndn_charbuf_destroy(&key);
    ndn_charbuf_destroy(&value);
    return(errors ? -1 : warns);
}
Exemple #10
0
/*
 * This upcall gets called for each piece of incoming content that
 * matches one of our interests.  We need to issue a new interest that
 * excludes another component at the current level, and perhaps also
 * and interest to start exploring the next level.  Thus if the matched
 * interest is
 *   /a/b/c exclude {d,e,f,i,j,k}
 * and we get
 *   /a/b/c/g/h
 * we would issue a new interest
 *   /a/b/c exclude {d,e,f,g,i,j,k}
 * to continue exploring the current level, plus a simple interest
 *   /a/b/c/g
 * to start exploring the next level as well.
 *
 * This does end up fetching each piece of content multiple times, once for
 * each level in the name. The repeated requests will be answered from the local
 * content store, though, and so should not generate extra network traffic.
 * There is a lot of unanswerable interest generated, though.  
 *
 * To prevent the interests from becoming too huge, we may need to split them.
 * Thus if the first new interest above were deemed too large, we could instead
 * issue the two interests
 *   /a/b/c exclude {d,e,f,g,*}
 *   /a/b/c exclude {*,g,i,j,k}
 * where * stands for a Bloom filter that excludes anything.  Note the
 * repetition of g to ensure that these two interests cover disjoint portions
 * of the hierarchy. We need to keep track of the endpoint conditions
 * as well as the excluded set in our upcall data.
 * When a split happens, we need a new closure to track it, as we do when
 * we start exploring a new level.
 */
static enum ndn_upcall_res
incoming_content(
    struct ndn_closure *selfp,
    enum ndn_upcall_kind kind,
    struct ndn_upcall_info *info)
{
    struct ndn_charbuf *c = NULL;
    struct ndn_charbuf *comp = NULL;
    struct ndn_charbuf *uri = NULL;
    const unsigned char *ndnb = NULL;
    size_t ndnb_size = 0;
    struct ndn_indexbuf *comps = NULL;
    int matched_comps = 0;
    int res;
    int i;
    struct ndn_traversal *data = get_my_data(selfp);
    
    if (kind == NDN_UPCALL_FINAL) {
        for (i = 0; i < data->n_excl; i++)
            ndn_charbuf_destroy(&(data->excl[i]));
        if (data->excl != NULL)
            free(data->excl);
        free(data);
        free(selfp);
        return(0);
    }
    if (kind == NDN_UPCALL_INTEREST_TIMED_OUT)
        return(0);
    if (kind == NDN_UPCALL_CONTENT_BAD)
        return(0);
    if (kind == NDN_UPCALL_CONTENT_UNVERIFIED) {
        if ((data->flags & MUST_VERIFY) != 0)
            return(NDN_UPCALL_RESULT_VERIFY);
    }
    if (kind != NDN_UPCALL_CONTENT && kind != NDN_UPCALL_CONTENT_UNVERIFIED) abort();

    ndnb = info->content_ndnb;
    ndnb_size = info->pco->offset[NDN_PCO_E];
    comps = info->content_comps;
    matched_comps = info->pi->prefix_comps;
    c = ndn_charbuf_create();
    uri = ndn_charbuf_create();
        
    if (matched_comps + 1 > comps->n) {
        ndn_uri_append(c, ndnb, ndnb_size, 1);
        fprintf(stderr, "How did this happen?  %s\n", ndn_charbuf_as_string(uri));
        exit(1);
    }
    
    data->counter[0]++; /* Tell main that something new came in */

    /* Recover the same prefix as before */
    ndn_name_init(c);
    ndn_name_append_components(c, ndnb, comps->buf[0], comps->buf[matched_comps]);
    
    comp = ndn_charbuf_create();
    ndn_name_init(comp);
    if (matched_comps + 1 == comps->n) {
        /* Reconstruct the implicit content digest component */
        ndn_digest_ContentObject(ndnb, info->pco);
        ndn_name_append(comp, info->pco->digest, info->pco->digest_bytes);
    }
    else {
        ndn_name_append_components(comp, ndnb,
                                   comps->buf[matched_comps],
                                   comps->buf[matched_comps + 1]);
    }
    data->excl = realloc(data->excl, (data->n_excl + 1) * sizeof(data->excl[0]));
    data->excl[data->n_excl++] = comp;
    comp = NULL;
    qsort(data->excl, data->n_excl, sizeof(data->excl[0]), &namecompare);
    res = express_my_interest(info->h, selfp, c);
    if (res == -1) {
        struct ndn_closure *high = split_my_excludes(selfp);
        if (high == NULL) abort();
        express_my_interest(info->h, selfp, c);
        express_my_interest(info->h, high, c);
    }
    /* Explore the next level, if there is one. */
    if (matched_comps + 2 < comps->n) {
        struct ndn_traversal *newdat = NULL;
        struct ndn_closure *cl;
        newdat = calloc(1, sizeof(*newdat));
        newdat->magic = 68955871;
        newdat->warn = 1492;
        newdat->counter = data->counter;
        newdat->flags = data->flags & ~(EXCLUDE_LOW | EXCLUDE_HIGH);
        newdat->n_excl = 0;
        newdat->excl = NULL;
        cl = calloc(1, sizeof(*cl));
        cl->p = &incoming_content;
        cl->data = newdat;
        ndn_name_init(c);
        ndn_name_append_components(c, ndnb,
                                   comps->buf[0],
                                   comps->buf[matched_comps + 1]);
        express_my_interest(info->h, cl, c);
    }
    else {
        res = ndn_uri_append(uri, info->content_ndnb, info->pco->offset[NDN_PCO_E], 1);
        if (res < 0)
            fprintf(stderr, "*** Error: ndn_traverse line %d res=%d\n", __LINE__, res);
        else
            printf("%s\n", ndn_charbuf_as_string(uri));
    }
    ndn_charbuf_destroy(&c);
    ndn_charbuf_destroy(&uri);
    return(0);
}
Exemple #11
0
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);
}