Ejemplo n.º 1
0
/**
 * Destroy the ndnr instance, releasing all associated resources.
 */
PUBLIC void
r_init_destroy(struct ndnr_handle **pndnr)
{
    struct ndnr_handle *h = *pndnr;
    int stable;
    if (h == NULL)
        return;
    stable = h->active_in_fd == -1 ? 1 : 0;
    r_io_shutdown_all(h);
    ndnr_direct_client_stop(h);
    ndn_schedule_destroy(&h->sched);
    hashtb_destroy(&h->propagating_tab);
    hashtb_destroy(&h->nameprefix_tab);
    hashtb_destroy(&h->enum_state_tab);
    hashtb_destroy(&h->content_by_accession_tab);

    // SyncActions sync_stop method should be shutting down heartbeat
    if (h->sync_plumbing) {
        h->sync_plumbing->sync_methods->sync_stop(h->sync_plumbing, NULL);
        free(h->sync_plumbing);
        h->sync_plumbing = NULL;
        h->sync_base = NULL; // freed by sync_stop ?
    }
    
    r_store_final(h, stable);
    
    if (h->fds != NULL) {
        free(h->fds);
        h->fds = NULL;
        h->nfds = 0;
    }
    if (h->fdholder_by_fd != NULL) {
        free(h->fdholder_by_fd);
        h->fdholder_by_fd = NULL;
        h->face_limit = h->face_gen = 0;
    }
    if (h->content_by_cookie != NULL) {
        free(h->content_by_cookie);
        h->content_by_cookie = NULL;
        h->cookie_limit = 1;
    }
    ndn_charbuf_destroy(&h->scratch_charbuf);
    ndn_indexbuf_destroy(&h->skiplinks);
    ndn_indexbuf_destroy(&h->scratch_indexbuf);
    ndn_indexbuf_destroy(&h->unsol);
    if (h->parsed_policy != NULL) {
        ndn_indexbuf_destroy(&h->parsed_policy->namespaces);
        ndn_charbuf_destroy(&h->parsed_policy->store);
        free(h->parsed_policy);
        h->parsed_policy = NULL;
    }
    ndn_charbuf_destroy(&h->policy_name);
    ndn_charbuf_destroy(&h->policy_link_cob);
    ndn_charbuf_destroy(&h->ndnr_keyid);
    free(h);
    *pndnr = NULL;
}
Ejemplo n.º 2
0
/*
 * Destroy the result of a ndn_header_parse or ndn_get_header
 */
void
ndn_header_destroy(struct ndn_header **ph)
{
    if (*ph == NULL)
        return;
    ndn_charbuf_destroy(&(*ph)->root_digest);
    ndn_charbuf_destroy(&(*ph)->content_digest);
    free(*ph);
    *ph = NULL;
}
Ejemplo n.º 3
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);
}
Ejemplo n.º 4
0
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);
}
Ejemplo n.º 5
0
/**
 * Destroy the result of ndn_face_instance_parse().
 */
void
ndn_face_instance_destroy(struct ndn_face_instance **pfi)
{
    if (*pfi == NULL)
        return;
    ndn_charbuf_destroy(&(*pfi)->store);
    free(*pfi);
    *pfi = NULL;
}
Ejemplo n.º 6
0
/**
 * Destroy the result of ndn_forwarding_entry_parse().
 */
void
ndn_forwarding_entry_destroy(struct ndn_forwarding_entry **pfe)
{
    if (*pfe == NULL)
        return;
    ndn_charbuf_destroy(&(*pfe)->name_prefix);
    free(*pfe);
    *pfe = NULL;
}
Ejemplo n.º 7
0
struct ndn_header *
ndn_get_header(struct ndn *h, struct ndn_charbuf *name, int timeout)
{
    struct ndn_charbuf *hn;
    struct ndn_header *result = NULL;
    int res;

    hn = ndn_charbuf_create();
    ndn_charbuf_append_charbuf(hn, name);
    /*
     * Requires consistency with metadata profile in
     * javasrc/src/main/org/ndnx/ndn-tlv/profiles/metadata/MetadataProfile.java
     */
    ndn_name_append(hn, meta, sizeof(meta));
    ndn_name_append_str(hn, ".header");
    res = ndn_resolve_version(h, hn, NDN_V_HIGHEST, timeout);
    if (res <= 0) {
        /* Version not found: try old header name from prior to 04/2010 */
        ndn_charbuf_reset(hn);
        ndn_charbuf_append_charbuf(hn, name);
        ndn_name_append_str(hn, "_meta_");
        ndn_name_append_str(hn, ".header");
        res = ndn_resolve_version(h, hn, NDN_V_HIGHEST, timeout);
    }
    /* headers must be versioned */
    if (res > 0) {
        struct ndn_charbuf *ho = ndn_charbuf_create();
        struct ndn_parsed_ContentObject pcobuf = { 0 };
        const unsigned char *hc;
        size_t hcs;

        res = ndn_get(h, hn, NULL, timeout, ho, &pcobuf, NULL, 0);
        if (res == 0) {
            hc = ho->buf;
            hcs = ho->length;
            ndn_content_get_value(hc, hcs, &pcobuf, &hc, &hcs);
            result = ndn_header_parse(hc, hcs);
        }
        ndn_charbuf_destroy(&ho);
    }
    ndn_charbuf_destroy(&hn);
    return (result);
}
Ejemplo n.º 8
0
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;
}
Ejemplo n.º 9
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);
}
Ejemplo n.º 10
0
PUBLIC void
ndnr_parsed_policy_destroy(struct ndnr_parsed_policy **ppp)
{
    struct ndnr_parsed_policy *pp;
    
    if (*ppp == NULL)
        return;
    pp = *ppp;
    ndn_charbuf_destroy(&pp->store);
    ndn_indexbuf_destroy(&pp->namespaces);
    free(pp);
    *ppp = NULL;
}
Ejemplo n.º 11
0
static int do_ping(struct ndn_schedule *sched, void *clienth,
        struct ndn_scheduled_event *ev, int flags)
{
    struct ndn_ping_client *client = clienth;
    if (client->total >= 0 && client->sent >= client->total)
        return 0;

    struct ndn_charbuf *name = ndn_charbuf_create();
    struct ndn_charbuf *templ = NULL;
    long int rnum;
    char rnumstr[20];
    int res;

    ndn_charbuf_append(name, client->prefix->buf, client->prefix->length);
    if (client->number < 0)
        rnum = random();
    else {
        rnum = client->number;
        client->number ++;
    }
    memset(&rnumstr, 0, 20);
    sprintf(rnumstr, "%ld", rnum);
    ndn_name_append_str(name, rnumstr);

    templ = make_template(client->allow_caching);
    res = ndn_express_interest(client->h, name, client->closure, templ);
    add_ndn_ping_entry(client, name, rnum);
    client->sent ++;
    sta.sent ++;

    ndn_charbuf_destroy(&templ);
    ndn_charbuf_destroy(&name);

    if (res < 0)
        print_log(client->print_timestamp, "failed to express Interest to %s: number = %ld\n",
                client->original_prefix, rnum);

    return client->interval * 1000000;
}
Ejemplo n.º 12
0
static struct ndn_charbuf *
ndnr_init_policy_cob(struct ndnr_handle *ndnr, struct ndn *h,
                     struct ndn_charbuf *basename,
                     int freshness, struct ndn_charbuf *content)
{
    struct ndn_signing_params sp = NDN_SIGNING_PARAMS_INIT;
    struct ndn_charbuf *name = ndn_charbuf_create();
    struct ndn_charbuf *pubid = ndn_charbuf_create();
    struct ndn_charbuf *pubkey = ndn_charbuf_create();
    struct ndn_charbuf *keyid = ndn_charbuf_create();
    struct ndn_charbuf *tcob = ndn_charbuf_create();
    struct ndn_charbuf *cob = NULL;          // result
    int res;
    
    res = ndn_get_public_key(h, NULL, pubid, pubkey);
    if (res < 0) 
        goto Leave;
    res = ndn_charbuf_append_charbuf(name, basename);
    if (ndn_name_from_uri(name, "%00") < 0)
        goto Leave;
    sp.sp_flags |= NDN_SP_FINAL_BLOCK;
    sp.type = NDN_CONTENT_DATA;
    sp.freshness = freshness;
    res |= ndn_sign_content(h, tcob, name, &sp, content->buf, content->length);
    if (res == 0) {
        cob = tcob;
        tcob = NULL;
    }
    
Leave:
    ndn_charbuf_destroy(&name);
    ndn_charbuf_destroy(&pubid);
    ndn_charbuf_destroy(&pubkey);
    ndn_charbuf_destroy(&keyid);
    ndn_charbuf_destroy(&tcob);
    return (cob);
}
Ejemplo n.º 13
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;
}
Ejemplo n.º 14
0
static void
express_bulkdata_interest(struct ndn *h, struct pending *p)
{
    int res;
    struct bulkdata *b = NULL;
    struct ndn_charbuf *name = NULL;
    struct ndn_charbuf *templ = NULL;
    struct ndn_charbuf *seq = NULL;
    
    b = p->parent;
    if (b == NULL)
        return;
    name = ndn_charbuf_create();
    templ = ndn_charbuf_create();
    seq = ndn_charbuf_create();

    ndn_charbuf_append(name, b->name_prefix->buf, b->name_prefix->length);
    
    seq->length = 0;
    (*b->seqfunc)(p->x, b->seqfunc_param, seq);
    ndn_name_append(name, seq->buf, seq->length);
    
    ndn_charbuf_append_tt(templ, NDN_DTAG_Interest, NDN_DTAG);

    ndn_charbuf_append_tt(templ, NDN_DTAG_Name, NDN_DTAG);
    ndn_charbuf_append_closer(templ); /* </Name> */

    // XXX - may want to set Min/MaxSuffixComponents
    
    ndn_charbuf_append_closer(templ); /* </Interest> */
    res = ndn_express_interest(h, name, &p->closure, templ);
    assert(res >= 0); // XXX - handle this better
    ndn_charbuf_destroy(&name);
    ndn_charbuf_destroy(&templ);
    ndn_charbuf_destroy(&seq);
}
Ejemplo n.º 15
0
PyObject *
_pyndn_cmd_KeyLocator_to_ndn(PyObject *UNUSED(self), PyObject *args,
                             PyObject *kwds)
{
    static char *kwlist[] = {"name", "digest", "key", "cert", NULL};
    PyObject *py_name = Py_None, *py_digest = Py_None, *py_key = Py_None,
              *py_cert = Py_None;
    struct ndn_charbuf *keylocator;
    int r;

    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO", kwlist, &py_name,
                                     &py_digest, &py_key, &py_cert))
        return NULL;

    keylocator = ndn_charbuf_create();
    JUMP_IF_NULL_MEM(keylocator, error);

    r = ndn_charbuf_append_tt(keylocator, NDN_DTAG_KeyLocator, NDN_DTAG);
    JUMP_IF_NEG_MEM(r, error);

    if (py_name != Py_None) {
        //TODO: add digest as well
        r = KeyLocator_name_to_ndn(keylocator, py_name);
        JUMP_IF_NEG(r, error);
    } else if (py_key != Py_None) {
        r = KeyLocator_key_to_ndn(keylocator, py_key);
        JUMP_IF_NEG(r, error);
    } else if (py_cert != Py_None) {
#if 0
        ndn_charbuf_append_tt(keylocator, NDN_DTAG_Certificate, NDN_DTAG);
        // TODO: How to handle certificate?  ** Not supported here
        ndn_charbuf_append_closer(keylocator); /* </Certificate> */
#endif

        PyErr_SetString(PyExc_NotImplementedError, "Certificate key locator is"
                        " not implemented");
        goto error;
    }

    r = ndn_charbuf_append_closer(keylocator); /* </KeyLocator> */
    JUMP_IF_NEG_MEM(r, error);

    return NDNObject_New(KEY_LOCATOR, keylocator);
error:
    ndn_charbuf_destroy(&keylocator);

    return NULL;
}
Ejemplo n.º 16
0
/*
 * Construct and send a new interest that uses the exclusion list.
 * Return -1 if not sent because of packet size, 0 for success.
 */
static int
express_my_interest(struct ndn *h,
                    struct ndn_closure *selfp,
                    struct ndn_charbuf *name)
{
    int ans;
    struct ndn_charbuf *templ = NULL;
    int i;
    struct ndn_traversal *data = get_my_data(selfp);

    templ = ndn_charbuf_create();
    ndn_charbuf_append_tt(templ, NDN_DTAG_Interest, NDN_DTAG);
    ndn_charbuf_append_tt(templ, NDN_DTAG_Name, NDN_DTAG);
    ndn_charbuf_append_closer(templ); /* </Name> */
    if (data->n_excl != 0) {
        ndn_charbuf_append_tt(templ, NDN_DTAG_Exclude, NDN_DTAG);
        if ((data->flags & EXCLUDE_LOW) != 0)
            append_Any_filter(templ);
        for (i = 0; i < data->n_excl; i++) {
            struct ndn_charbuf *comp = data->excl[i];
            if (comp->length < 4) abort();
            ndn_charbuf_append(templ, comp->buf + 1, comp->length - 2);
        }
        if ((data->flags & EXCLUDE_HIGH) != 0)
            append_Any_filter(templ);
        ndn_charbuf_append_closer(templ); /* </Exclude> */
    }
    answer_passive(templ, (data->flags & ALLOW_STALE) != 0);
    if ((data->flags & LOCAL_SCOPE) != 0)
        local_scope(templ);
    ndn_charbuf_append_closer(templ); /* </Interest> */
    if (templ->length + name->length > data->warn + 2) {
        fprintf(stderr, "*** Interest packet is %d bytes\n", (int)templ->length);
        data->warn = data->warn * 8 / 5;
    }
    if (templ->length + name->length > 1450 && data->n_excl > 3)
        ans = -1;
    else {
        ndn_express_interest(h, name, selfp, templ);
        ans = 0;
    }
    ndn_charbuf_destroy(&templ);
    return(ans);
}
Ejemplo n.º 17
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);
}
Ejemplo n.º 18
0
/**
 * Advance the last Component of a Name to the next possible value.
 * @param c contains a ndnb-encoded Name to be updated.
 * @returns -1 for error, otherwise the number of Components
 */
int
ndn_name_next_sibling(struct ndn_charbuf *c)
{
    int res = -1;
    struct ndn_indexbuf *ndx;
    unsigned char *lastcomp = NULL;
    size_t lastcompsize = 0;
    size_t i;
    int carry;
    struct ndn_charbuf *newcomp;

    ndx = ndn_indexbuf_create();
    if (ndx == NULL) goto Finish;
    res = ndn_name_split(c, ndx);
    if (res <= 0) {
        res = -1;
        goto Finish;
    }
    res = ndn_ref_tagged_BLOB(NDN_DTAG_Component, c->buf,
        ndx->buf[res-1], ndx->buf[res],
        (const unsigned char **)&lastcomp,
        &lastcompsize);
    if (res < 0) goto Finish;
    for (carry = 1, i = lastcompsize; carry && i > 0; i--) {
        carry = (((++lastcomp[i-1]) & 0xFF) == 0x00);
    }
    if (carry) {
        newcomp = ndn_charbuf_create();
        res |= ndn_charbuf_append_value(newcomp, 0, 1);
        res |= ndn_charbuf_append(newcomp, lastcomp, lastcompsize);
        res |= ndn_name_chop(c, ndx, ndx->n - 2);
        res |= ndn_name_append(c, newcomp->buf, newcomp->length);
        ndn_charbuf_destroy(&newcomp);
        if (res < 0) goto Finish;
    }
    res = ndx->n - 1;
Finish:
    ndn_indexbuf_destroy(&ndx);
    return(res);
}
Ejemplo n.º 19
0
/**
 * should probably return a new cob, rather than reusing one.
 * should publish link as:
 *    NDNRID_POLICY_URI("ndn:/%C1.M.S.localhost/%C1.M.SRV/repository/POLICY)/%C1.M.K--pubid--/--version--/%00
 * should have key locator which is the key name of the repository
 */
PUBLIC struct ndn_charbuf *
ndnr_init_policy_link_cob(struct ndnr_handle *ndnr, struct ndn *h,
                          struct ndn_charbuf *targetname)
{
    struct ndn_signing_params sp = NDN_SIGNING_PARAMS_INIT;
    struct ndn_charbuf *name = ndn_charbuf_create();
    struct ndn_charbuf *pubid = ndn_charbuf_create();
    struct ndn_charbuf *pubkey = ndn_charbuf_create();
    struct ndn_charbuf *keyid = ndn_charbuf_create();
    struct ndn_charbuf *content = ndn_charbuf_create();
    struct ndn_charbuf *cob = ndn_charbuf_create();
    struct ndn_charbuf *answer = NULL;
    int res;
    
    res = ndn_get_public_key(h, NULL, pubid, pubkey);
    if (res < 0)
        goto Bail;
    if (ndn_name_from_uri(name, NDNRID_POLICY_URI) < 0)
        goto Bail;
    res |= ndn_charbuf_append_value(keyid, NDN_MARKER_CONTROL, 1);
    res |= ndn_charbuf_append_string(keyid, ".M.K");
    res |= ndn_charbuf_append_value(keyid, 0, 1);
    res |= ndn_charbuf_append_charbuf(keyid, pubid);
    res |= ndn_name_append(name, keyid->buf, keyid->length);
    res |= ndn_create_version(h, name, NDN_V_NOW, 0, 0);
    if (ndn_name_from_uri(name, "%00") < 0)
        goto Bail;
    sp.sp_flags |= NDN_SP_FINAL_BLOCK;
    sp.type = NDN_CONTENT_LINK;
    res |= ndnb_append_Link(content, targetname, "Repository Policy", NULL);
    if (res != 0)
        goto Bail;
    res |= ndn_sign_content(h, cob, name, &sp, content->buf, content->length);
    if (res != 0)
        goto Bail;
    answer = cob;
    cob = NULL;
    
Bail:
    ndn_charbuf_destroy(&name);
    ndn_charbuf_destroy(&pubid);
    ndn_charbuf_destroy(&pubkey);
    ndn_charbuf_destroy(&keyid);
    ndn_charbuf_destroy(&content);
    ndn_charbuf_destroy(&cob);
    return (answer);
}
Ejemplo n.º 20
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);
}
Ejemplo n.º 21
0
static struct ndn_charbuf *
resolve_templ(struct ndn_charbuf *templ, unsigned const char *vcomp,
              int size, int lifetime, int versioning_flags)
{
    if (templ == NULL)
        templ = ndn_charbuf_create();
    if (size < 3 || size > 16) {
        ndn_charbuf_destroy(&templ);
        return(NULL);
    }
    templ->length = 0;
    ndn_charbuf_append_tt(templ, NDN_DTAG_Interest, NDN_DTAG);
    ndn_charbuf_append_tt(templ, NDN_DTAG_Name, NDN_DTAG);
    ndn_charbuf_append_closer(templ); /* </Name> */
    ndn_charbuf_append_tt(templ, NDN_DTAG_Exclude, NDN_DTAG);
    append_filter_all(templ);
    ndn_charbuf_append_tt(templ, NDN_DTAG_Component, NDN_DTAG);
    ndn_charbuf_append_tt(templ, size, NDN_BLOB);
    ndn_charbuf_append(templ, vcomp, size);
    ndn_charbuf_append_closer(templ); /* </Component> */
    append_future_vcomp(templ);
    append_filter_all(templ);
    ndn_charbuf_append_closer(templ); /* </Exclude> */
    answer_highest(templ);
    answer_passive(templ);
    if ((versioning_flags & NDN_V_SCOPE2) != 0)
        ndnb_tagged_putf(templ, NDN_DTAG_Scope, "%d", 2);
    else if ((versioning_flags & NDN_V_SCOPE1) != 0)
        ndnb_tagged_putf(templ, NDN_DTAG_Scope, "%d", 1);
    else if ((versioning_flags & NDN_V_SCOPE0) != 0)
        ndnb_tagged_putf(templ, NDN_DTAG_Scope, "%d", 0);
    if (lifetime > 0)
        ndnb_append_tagged_binary_number(templ, NDN_DTAG_InterestLifetime, lifetime);
    ndn_charbuf_append_closer(templ); /* </Interest> */
    return(templ);
}
Ejemplo n.º 22
0
struct ndn_forwarding_entry *
ndn_forwarding_entry_parse(const unsigned char *p, size_t size)
{
    struct ndn_buf_decoder decoder;
    struct ndn_buf_decoder *d = ndn_buf_decoder_start(&decoder, p, size);
    struct ndn_charbuf *store = ndn_charbuf_create();
    struct ndn_forwarding_entry *result;
    const unsigned char *val;
    size_t sz;
    size_t start;
    size_t end;
    int action_off = -1;
    int ndnd_id_off = -1;
    
    if (store == NULL)
        return(NULL);
    result = calloc(1, sizeof(*result));
    if (result == NULL) {
        ndn_charbuf_destroy(&store);
        return(NULL);
    }
    if (ndn_buf_match_dtag(d, NDN_DTAG_ForwardingEntry)) {
        ndn_buf_advance(d);
        action_off = ndn_parse_tagged_string(d, NDN_DTAG_Action, store);
        if (ndn_buf_match_dtag(d, NDN_DTAG_Name)) {
            result->name_prefix = ndn_charbuf_create();
            start = d->decoder.token_index;
            ndn_parse_Name(d, NULL);
            end = d->decoder.token_index;
            ndn_charbuf_append(result->name_prefix, p + start, end - start);
        }
        else
            result->name_prefix = NULL;
        if (ndn_buf_match_dtag(d, NDN_DTAG_PublisherPublicKeyDigest)) {
            ndn_buf_advance(d);
            if (ndn_buf_match_blob(d, &val, &sz)) {
                ndn_buf_advance(d);
                if (sz != 32)
                    d->decoder.state = -__LINE__;
            }
            ndn_buf_check_close(d);
            if (d->decoder.state >= 0) {
                ndnd_id_off = store->length;
                ndn_charbuf_append(store, val, sz);
                result->ndnd_id_size = sz;
            }
        }
        result->faceid = ndn_parse_optional_tagged_nonNegativeInteger(d, NDN_DTAG_FaceID);
        result->flags = ndn_parse_optional_tagged_nonNegativeInteger(d, NDN_DTAG_ForwardingFlags);
        result->lifetime = ndn_parse_optional_tagged_nonNegativeInteger(d, NDN_DTAG_FreshnessSeconds);
        ndn_buf_check_close(d);
    }
    else
        d->decoder.state = -__LINE__;
    
    if (d->decoder.index != size || !NDN_FINAL_DSTATE(d->decoder.state) ||
        store->length > sizeof(result->store))
        ndn_forwarding_entry_destroy(&result);
    else {
        char *b = (char *)result->store;
        memcpy(b, store->buf, store->length);
        result->action = (action_off == -1) ? NULL : b + action_off;
        result->ndnd_id = (ndnd_id_off == -1) ? NULL : result->store + ndnd_id_off;
    }
    ndn_charbuf_destroy(&store);
    return(result);
}
Ejemplo n.º 23
0
/**
 * Convert a ndnx-scheme URI to a ndnb-encoded Name.
 * The converted result is placed in c.
 * On input, c may contain a base name, in which case relative URIs are allowed.
 * Otherwise c should start out empty, and the URI must be absolute.
 * @returns -1 if an error is found, otherwise returns the number of characters
 *          that were processed.
 */
int
ndn_name_from_uri(struct ndn_charbuf *c, const char *uri)
{
    int res = 0;
    struct ndn_charbuf *compbuf = NULL;
    const char *stop = uri + strlen(uri);
    const char *s = uri;
    size_t cont = 0;
    
    compbuf = ndn_charbuf_create();
    if (compbuf == NULL) return(-1);
    if (s[0] != '/') {
        res = ndn_append_uri_component(compbuf, s, stop - s, &cont);
        if (res < -2)
            goto Done;
        ndn_charbuf_reserve(compbuf, 1)[0] = 0;
        if (s[cont-1] == ':') {
            if ((0 == strcasecmp((const char *)(compbuf->buf), "ndn:") ||
                 0 == strcasecmp((const char *)(compbuf->buf), "ndn:"))) {
                s += cont;
                cont = 0;
            } else
                return (-1);
        }
    }
    if (s[0] == '/') {
        ndn_name_init(c);
        if (s[1] == '/') {
            /* Skip over hostname part - not used in ndnx scheme */
            s += 2;
            compbuf->length = 0;
            res = ndn_append_uri_component(compbuf, s, stop - s, &cont);
            if (res < 0 && res != -2)
                goto Done;
            s += cont; cont = 0;
        }
    }
    while (s[0] != 0 && s[0] != '?' && s[0] != '#') {
        if (s[0] == '/')
            s++;
        compbuf->length = 0;
        res = ndn_append_uri_component(compbuf, s, stop - s, &cont);
        s += cont; cont = 0;
        if (res < -2)
            goto Done;
        if (res == -2) {
            res = 0; /* process . or equiv in URI */
            continue;
        }
        if (res == -1) {
            /* process .. in URI - discard last name component */
            res = ndn_name_last_component_offset(c->buf, c->length);
            if (res < 0)
                goto Done;
            c->length = res;
            ndn_charbuf_append_closer(c);
            continue;
        }
        res = ndn_name_append(c, compbuf->buf, compbuf->length);
        if (res < 0)
            goto Done;
    }
Done:
    ndn_charbuf_destroy(&compbuf);
    if (res < 0)
        return(-1);
    if (c->length < 2 || c->buf[c->length-1] != NDN_CLOSE)
        return(-1);
    return(s - uri);
}
Ejemplo n.º 24
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);
}
Ejemplo n.º 25
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);
}
Ejemplo n.º 26
0
/**
 * Resolve the version, based on existing ndn content.
 * @param h is the the ndn handle; it may be NULL, but it is preferable to
 *        use the handle that the client probably already has.
 * @param name is a ndnb-encoded Name prefix. It gets extended in-place with
 *        one additional Component such that it names highest extant
 *        version that can be found, subject to the supplied timeout.
 * @param versioning_flags presently must be NDN_V_HIGH or NDN_V_HIGHEST,
 *        possibly combined with NDN_V_NESTOK.  If NDN_V_NESTOK is not present
 *        and the ending component appears to be a version, the routine
 *        returns 0 immediately, on the assumption that an explicit
 *        version has already been provided.
 * @param timeout_ms is a time value in milliseconds. This is the total time
 *        that the caller can wait.
 * @returns -1 for error, 0 if name was not extended, 1 if was.
 */
int
ndn_resolve_version(struct ndn *h, struct ndn_charbuf *name,
                    int versioning_flags, int timeout_ms)
{
    int res;
    int myres = -1;
    struct ndn_parsed_ContentObject pco_space = { 0 };
    struct ndn_charbuf *templ = NULL;
    struct ndn_charbuf *prefix = ndn_charbuf_create();
    struct ndn_charbuf *cobj = ndn_charbuf_create();
    struct ndn_parsed_ContentObject *pco = &pco_space;
    struct ndn_indexbuf *ndx = ndn_indexbuf_create();
    const unsigned char *vers = NULL;
    size_t vers_size = 0;
    struct timeval start, prev, now;
    int n;
    int rtt_max = 0;
    int rtt;
    int ttimeout;
    struct ndn_indexbuf *nix = ndn_indexbuf_create();
    unsigned char lowtime[7] = {NDN_MARKER_VERSION, 0, FF, FF, FF, FF, FF};
    
    if ((versioning_flags & ~NDN_V_NESTOK & ~NDN_V_EST) != NDN_V_HIGH) {
        ndn_seterror(h, EINVAL);
        ndn_perror(h, "ndn_resolve_version is only implemented for versioning_flags = NDN_V_HIGH(EST)");
        goto Finish;
    }
    n = ndn_name_split(name, nix);
    if (n < 0)
        goto Finish;
    if ((versioning_flags & NDN_V_NESTOK) == 0) {
        res = ndn_name_comp_get(name->buf, nix, n - 1, &vers, &vers_size);
        if (res >= 0 && vers_size == 7 && vers[0] == NDN_MARKER_VERSION) {
            myres = 0;
            goto Finish;
        }    
    }
    templ = resolve_templ(templ, lowtime, sizeof(lowtime),
                          ms_to_tu(timeout_ms) * 7 / 8, versioning_flags);
    ndn_charbuf_append(prefix, name->buf, name->length); /* our copy */
    cobj->length = 0;
    gettimeofday(&start, NULL);
    prev = start;
    /*
     * the algorithm for NDN_V_HIGHEST is to send the initial Interest with
     * a lifetime that will ensure 1 resend before the timeout, and to keep
     * keep sending an Interest, excluding earlier versions, tracking the
     * maximum round trip time and using a timeout of 4*RTT, and an interest
     * lifetime that should get a retransmit.   If there is no response,
     * return the highest version found so far.
     */
    myres = 0;
    res = ndn_get(h, prefix, templ, timeout_ms, cobj, pco, ndx, 0);
    while (cobj->length != 0) {
        if (pco->type == NDN_CONTENT_NACK) // XXX - also check for number of components
            break;
        res = ndn_name_comp_get(cobj->buf, ndx, n, &vers, &vers_size);
        if (res < 0)
            break;
        if (vers_size == 7 && vers[0] == NDN_MARKER_VERSION) {
            /* Looks like we have versions. */
            name->length = 0;
            ndn_charbuf_append(name, prefix->buf, prefix->length);
            ndn_name_append(name, vers, vers_size);
            myres = 1;
            if ((versioning_flags & NDN_V_EST) == 0)
                break;
            gettimeofday(&now, NULL);
            rtt = (now.tv_sec - prev.tv_sec) * 1000000 + (now.tv_usec - prev.tv_usec);
            if (rtt > rtt_max) rtt_max = rtt;
            prev = now;
            timeout_ms -= (now.tv_sec - start.tv_sec) * 1000 + (now.tv_usec - start.tv_usec) / 1000;
            if (timeout_ms <= 0)
                break;
            ttimeout = timeout_ms < (rtt_max/250) ? timeout_ms : (rtt_max/250);
            templ = resolve_templ(templ, vers, vers_size, ms_to_tu(ttimeout) * 7 / 8, versioning_flags);
            if (templ == NULL) break;
            cobj->length = 0;
            res = ndn_get(h, prefix, templ, ttimeout, cobj, pco, ndx,
                          NDN_GET_NOKEYWAIT);
        }
        else break;
    }
Finish:
    ndn_charbuf_destroy(&prefix);
    ndn_charbuf_destroy(&cobj);
    ndn_indexbuf_destroy(&ndx);
    ndn_indexbuf_destroy(&nix);
    ndn_charbuf_destroy(&templ);
    return(myres);
}
Ejemplo n.º 27
0
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);
}
Ejemplo n.º 28
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);
Ejemplo n.º 29
0
/**
 * Parse a ndnb-ecoded FaceInstance into an internal representation
 *
 * The space used for the various strings is held by the charbuf.
 * A client may replace the strings with other pointers, but then
 * assumes responsibilty for managing those pointers.
 * @returns pointer to newly allocated structure describing the face, or
 *          NULL if there is an error.
 */
struct ndn_face_instance *
ndn_face_instance_parse(const unsigned char *p, size_t size)
{
    struct ndn_buf_decoder decoder;
    struct ndn_buf_decoder *d = ndn_buf_decoder_start(&decoder, p, size);
    struct ndn_charbuf *store = ndn_charbuf_create();
    struct ndn_face_instance *result;
    const unsigned char *val;
    size_t sz;
    int action_off = -1;
    int ndnd_id_off = -1;
    int host_off = -1;
    int port_off = -1;
    int mcast_off = -1;
    
    if (store == NULL)
        return(NULL);
    result = calloc(1, sizeof(*result));
    if (result == NULL) {
        ndn_charbuf_destroy(&store);
        return(NULL);
    }
    result->store = store;
    if (ndn_buf_match_dtag(d, NDN_DTAG_FaceInstance)) {
        ndn_buf_advance(d);
        action_off = ndn_parse_tagged_string(d, NDN_DTAG_Action, store);
        if (ndn_buf_match_dtag(d, NDN_DTAG_PublisherPublicKeyDigest)) {
            ndn_buf_advance(d);
            if (ndn_buf_match_blob(d, &val, &sz)) {
                ndn_buf_advance(d);
                if (sz != 32)
                    d->decoder.state = -__LINE__;
            }
            ndn_buf_check_close(d);
            if (d->decoder.state >= 0) {
                ndnd_id_off = store->length;
                ndn_charbuf_append(store, val, sz);
                result->ndnd_id_size = sz;
            }
        }
        result->faceid = ndn_parse_optional_tagged_nonNegativeInteger(d, NDN_DTAG_FaceID);
        result->descr.ipproto = ndn_parse_optional_tagged_nonNegativeInteger(d, NDN_DTAG_IPProto);
        host_off = ndn_parse_tagged_string(d, NDN_DTAG_Host, store);
        port_off = ndn_parse_tagged_string(d, NDN_DTAG_Port, store);
        mcast_off = ndn_parse_tagged_string(d, NDN_DTAG_MulticastInterface, store);
        result->descr.mcast_ttl = ndn_parse_optional_tagged_nonNegativeInteger(d, NDN_DTAG_MulticastTTL);
        result->lifetime = ndn_parse_optional_tagged_nonNegativeInteger(d, NDN_DTAG_FreshnessSeconds);
        ndn_buf_check_close(d);
    }
    else
        d->decoder.state = -__LINE__;
    
    if (d->decoder.index != size || !NDN_FINAL_DSTATE(d->decoder.state))
        ndn_face_instance_destroy(&result);
    else {
        char *b = (char *)store->buf;
        result->action = (action_off == -1) ? NULL : b + action_off;
        result->ndnd_id = (ndnd_id_off == -1) ? NULL : store->buf + ndnd_id_off;
        result->descr.address = (host_off == -1) ? NULL : b + host_off;
        result->descr.port = (port_off == -1) ? NULL : b + port_off;
        result->descr.source_address = (mcast_off == -1) ? NULL : b + mcast_off;
    }
    return(result);
}
Ejemplo n.º 30
0
/**
 * Create a new ndnr instance
 * @param progname - name of program binary, used for locating helpers
 * @param logger - logger function
 * @param loggerdata - data to pass to logger function
 */
PUBLIC struct ndnr_handle *
r_init_create(const char *progname, ndnr_logger logger, void *loggerdata)
{
    char *sockname = NULL;
    const char *portstr = NULL;
    const char *listen_on = NULL;
    const char *d = NULL;
    struct ndnr_handle *h = NULL;
    struct hashtb_param param = {0};
    struct ndn_charbuf *config = NULL;
    int res;
    
    h = calloc(1, sizeof(*h));
    if (h == NULL)
        return(h);
    h->notify_after = 0; //NDNR_MAX_ACCESSION;
    h->logger = logger;
    h->loggerdata = loggerdata;
    h->logpid = (int)getpid();
    h->progname = progname;
    h->debug = -1;
    config = r_init_read_config(h);
    if (config == NULL)
        goto Bail;
    r_init_parse_config(h, config, 0); /* silent pass to pick up NDNR_DEBUG */
    h->debug = 1; /* so that we see any complaints */
    h->debug = r_init_debug_getenv(h, "NDNR_DEBUG");
    res = r_init_parse_config(h, config, 1);
    if (res < 0) {
        h->running = -1;
        goto Bail;
    }
    r_init_parse_config(h, config, 2);
    sockname = r_net_get_local_sockname();
    h->skiplinks = ndn_indexbuf_create();
    h->face_limit = 10; /* soft limit */
    h->fdholder_by_fd = calloc(h->face_limit, sizeof(h->fdholder_by_fd[0]));
    param.finalize_data = h;
    param.finalize = &r_fwd_finalize_nameprefix;
    h->nameprefix_tab = hashtb_create(sizeof(struct nameprefix_entry), &param);
    param.finalize = 0; // PRUNED &r_fwd_finalize_propagating;
    h->propagating_tab = hashtb_create(sizeof(struct propagating_entry), &param);
    param.finalize = &r_proto_finalize_enum_state;
    h->enum_state_tab = hashtb_create(sizeof(struct enum_state), &param);
    h->min_stale = ~0;
    h->max_stale = 0;
    h->unsol = ndn_indexbuf_create();
    h->ticktock.descr[0] = 'C';
    h->ticktock.micros_per_base = 1000000;
    h->ticktock.gettime = &r_util_gettime;
    h->ticktock.data = h;
    h->sched = ndn_schedule_create(h, &h->ticktock);
    h->starttime = h->sec;
    h->starttime_usec = h->usec;
    h->oldformatcontentgrumble = 1;
    h->oldformatinterestgrumble = 1;
    h->cob_limit = 4201;
    h->start_write_scope_limit = r_init_confval(h, "NDNR_START_WRITE_SCOPE_LIMIT", 0, 3, 3);
    h->debug = 1; /* so that we see any complaints */
    h->debug = r_init_debug_getenv(h, "NDNR_DEBUG");
    h->syncdebug = r_init_debug_getenv(h, "NDNS_DEBUG");
    portstr = getenv("NDNR_STATUS_PORT");
    if (portstr == NULL || portstr[0] == 0 || strlen(portstr) > 10)
        portstr = "";
    h->portstr = portstr;
    ndnr_msg(h, "NDNR_DEBUG=%d NDNR_DIRECTORY=%s NDNR_STATUS_PORT=%s", h->debug, h->directory, h->portstr);
    listen_on = getenv("NDNR_LISTEN_ON");
    if (listen_on != NULL && listen_on[0] != 0)
        ndnr_msg(h, "NDNR_LISTEN_ON=%s", listen_on);
    
    if (ndnr_init_repo_keystore(h, NULL) < 0) {
        h->running = -1;
        goto Bail;
    }
    r_util_reseed(h);
    r_store_init(h);
    if (h->running == -1) goto Bail;
    while (h->active_in_fd >= 0) {
        r_dispatch_process_input(h, h->active_in_fd);
        r_store_trim(h, h->cob_limit);
        ndn_schedule_run(h->sched);
    }
    ndnr_msg(h, "Repository file is indexed");
    if (h->face0 == NULL) {
        struct fdholder *fdholder;
        fdholder = calloc(1, sizeof(*fdholder));
        if (dup2(open("/dev/null", O_RDONLY), 0) == -1)
            ndnr_msg(h, "stdin: %s", strerror(errno));
        fdholder->filedesc = 0;
        fdholder->flags = (NDNR_FACE_GG | NDNR_FACE_NORECV);
        r_io_enroll_face(h, fdholder);
    }
    ndnr_direct_client_start(h);
    d = getenv("NDNR_SKIP_VERIFY");
#if (NDN_API_VERSION >= 4004)
    if (d != NULL && strcmp(d, "1") == 0) {
        ndnr_msg(h, "NDNR_SKIP_VERIFY=%s", d);
        ndn_defer_verification(h->direct_client, 1);
    }
#endif
    if (ndn_connect(h->direct_client, NULL) != -1) {
        int af = 0;
        int bufsize;
        int flags;
        int fd;
        struct fdholder *fdholder;

        fd = ndn_get_connection_fd(h->direct_client);
        // Play a dirty trick here - if this wins, we can fix it right in the c lib later on...
        af = try_tcp_instead(fd);  
        flags = NDNR_FACE_NDND;
        if (af == AF_INET)
            flags |= NDNR_FACE_INET;
        else if (af == AF_INET6)
            flags |= NDNR_FACE_INET6;
        else
            flags |= NDNR_FACE_LOCAL;
        fdholder = r_io_record_fd(h, fd, "NDND", 5, flags);
        if (fdholder == NULL) abort();
        ndnr_uri_listen(h, h->direct_client, "ndn:/%C1.M.S.localhost/%C1.M.SRV/repository",
                        &ndnr_answer_req, OP_SERVICE);
        ndnr_uri_listen(h, h->direct_client, "ndn:/%C1.M.S.neighborhood/%C1.M.SRV/repository",
                        &ndnr_answer_req, OP_SERVICE);
        bufsize = r_init_confval(h, "NDNR_MIN_SEND_BUFSIZE", 1, 2097152, 16384);
        establish_min_send_bufsize(h, fd, bufsize);
    }
    else
        ndn_disconnect(h->direct_client); // Apparently ndn_connect error case needs work.
    if (1 == r_init_confval(h, "NDNS_ENABLE", 0, 1, 1)) {
        h->sync_plumbing = calloc(1, sizeof(struct sync_plumbing));
        h->sync_plumbing->ndn = h->direct_client;
        h->sync_plumbing->sched = h->sched;
        h->sync_plumbing->client_methods = &sync_client_methods;
        h->sync_plumbing->client_data = h;
        h->sync_base = SyncNewBaseForActions(h->sync_plumbing);
    }
    if (-1 == load_policy(h))
        goto Bail;
    r_net_listen_on(h, listen_on);
    ndnr_internal_client_start(h);
    r_proto_init(h);
    r_proto_activate_policy(h, h->parsed_policy);
    if (merge_files(h) == -1)
        r_init_fail(h, __LINE__, "Unable to merge additional repository data files.", errno);
    if (h->running == -1) goto Bail;
    if (h->sync_plumbing) {
        // Start sync running
        // returns < 0 if a failure occurred
        // returns 0 if the name updates should fully restart
        // returns > 0 if the name updates should restart at last fence
        res = h->sync_plumbing->sync_methods->sync_start(h->sync_plumbing, NULL);
        if (res < 0) {
            r_init_fail(h, __LINE__, "starting sync", res);
            abort();
        }
        else if (res > 0) {
            // XXX: need to work out details of starting from last fence.
            // By examination of code, SyncActions won't take this path
        }
    }
Bail:
    if (sockname)
        free(sockname);
    sockname = NULL;
    ndn_charbuf_destroy(&config);
    if (h->running == -1)
        r_init_destroy(&h);
    return(h);
}