Ejemplo n.º 1
0
/*
 * deliver_content is used to deliver a previously-buffered
 * ContentObject to the client.
 */
static enum ndn_upcall_res
deliver_content(struct ndn *h, struct bulkdata *b)
{
    struct ndn_upcall_info info = {0};
    struct ndn_parsed_ContentObject obj = {0};
    struct pending *p = b->first;
    int res;
    enum ndn_upcall_res ans;
    assert(p != NULL && p->x == b->next_expected && p->content_ndnb != NULL);
    info.pco = &obj;
    info.content_comps = ndn_indexbuf_create();
    res = ndn_parse_ContentObject(p->content_ndnb, p->content_size,
                                  &obj, info.content_comps);
    assert(res >= 0);
    info.content_ndnb = p->content_ndnb;
    info.matched_comps = info.content_comps->n - 2;
    /* XXX - we have no matched interest to present */
    ans = (*b->client->p)(b->client, NDN_UPCALL_CONTENT, &info);
    // XXX - check for refusal
    info.content_ndnb = NULL;
    free(p->content_ndnb);
    p->content_ndnb = NULL;
    p->content_size = 0;
    ndn_indexbuf_destroy(&info.content_comps);
    if (ans == NDN_UPCALL_RESULT_OK) {
        struct ndn_closure *old = &p->closure;
        if ((--(old->refcount)) == 0) {
            info.pco = NULL;
            (old->p)(old, NDN_UPCALL_FINAL, &info);
        }
    }
    return(ans);
}
Ejemplo n.º 2
0
/**
 * 劈开ndnb名字,并把各个部分(n个)放到 components 中.
 * 貌似c会被修改. components 可以直接传null,即无所谓.
 * 参数:
 * c => 输入的 ndnb 名字
 * components => 输出
 * n => 需要留下的组件的数量. 负数代表需要remove的数量
 *
 * Chop the name down to n components.
 * @param c contains a ndnb-encoded Name
 * @param components may be NULL; if provided it must be consistent with
 *        some prefix of the name, and is updated accordingly.
 * @param n is the number or components to leave, or, if negative, specifies
 *        how many components to remove,
          e.g. -1 will remove just the last component.
 * @returns -1 for error, otherwise the new number of Components
 */
int
ndn_name_chop(struct ndn_charbuf *c, struct ndn_indexbuf *components, int n)
{
    if (components == NULL) {
        int res;
        components = ndn_indexbuf_create();
        if (components == NULL)
            return(-1);
        res = ndn_name_split(c, components);
        if (res >= 0)
            res = ndn_name_chop(c, components, n);
        ndn_indexbuf_destroy(&components);
        return(res);
    }
    /* Fix up components if needed. We could be a little smarter about this. */
    if (components->n == 0 || components->buf[components->n-1] + 1 != c->length)
        if (ndn_name_split(c, components) < 0)
            return(-1);
    if (n < 0)
        n += (components->n - 1); /* APL-style indexing */
    if (n < 0)
        return(-1);
    if (n < components->n) {
        c->length = components->buf[n];
        ndn_charbuf_append_value(c, NDN_CLOSE, 1);
        components->n = n + 1;
        return(n);
    }
    return(-1);
}
Ejemplo n.º 3
0
PUBLIC struct ndnr_parsed_policy *
ndnr_parsed_policy_create(void)
{
    struct ndnr_parsed_policy *pp;
    pp = calloc(1, sizeof(struct ndnr_parsed_policy));
    pp->store = ndn_charbuf_create();
    pp->namespaces = ndn_indexbuf_create();
    return(pp);
}
Ejemplo n.º 4
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.º 5
0
/**
 * Extend a Name with a new version stamp
 * @param h is the the ndn handle.
 *        May be NULL.  This procedure does not use the connection.
 * @param name is a ndnb-encoded Name prefix. By default it gets extended
 *        in-place with one additional Component that conforms to the
 *        versioning profile and is based on the supplied time, unless a
 *        version component is already present.
 * @param versioning_flags modifies the default behavior:
 *        NDN_V_REPLACE causes the last component to be replaced if it
 *        appears to be a version stamp.  If NDN_V_HIGH is set as well, an
 *        attempt will be made to generate a new version stamp that is
 *        later than the existing one, or to return an error.
 *        NDN_V_NOW bases the version on the current time rather than the
 *        supplied time.
 *        NDN_V_NESTOK will allow the new version component to be appended
 *        even if there is one there (this makes no difference if NDN_V_REPLACE
 *        is also set).
 * @param secs is the desired time, in seconds since epoch
 *        (ignored if NDN_V_NOW is set).
 * @param nsecs is the number of nanoseconds.
 * @returns -1 for error, 0 for success.
 */
int
ndn_create_version(struct ndn *h, struct ndn_charbuf *name,
                   int versioning_flags, intmax_t secs, int nsecs)
{
    size_t i;
    size_t j;
    size_t lc = 0;
    size_t oc = 0;
    int n;
    struct ndn_indexbuf *nix = NULL;
    int myres = -1;
    int already_versioned = 0;
    int ok_flags = (NDN_V_REPLACE | NDN_V_HIGH | NDN_V_NOW | NDN_V_NESTOK);
    // XXX - right now we ignore h, but in the future we may use it to try to avoid non-monotonicies in the versions.
    
    nix = ndn_indexbuf_create();
    n = ndn_name_split(name, nix);
    if (n < 0)
        goto Finish;
    if ((versioning_flags & ~ok_flags) != 0)
        goto Finish;        
    /* Check for existing version component */
    if (n >= 1) {
        oc = nix->buf[n-1];
        lc = nix->buf[n] - oc;
        if (lc <= 11 && lc >= 6 && name->buf[oc + 2] == NDN_MARKER_VERSION)
            already_versioned = 1;
    }
    myres = 0;
    if (already_versioned &&
        (versioning_flags & (NDN_V_REPLACE | NDN_V_NESTOK)) == 0)
        goto Finish;
    name->length -= 1; /* Strip name closer */
    i = name->length;
    myres |= ndn_charbuf_append_tt(name, NDN_DTAG_Component, NDN_DTAG);
    if ((versioning_flags & NDN_V_NOW) != 0)
        myres |= ndnb_append_now_blob(name, NDN_MARKER_VERSION);
    else {
        myres |= ndnb_append_timestamp_blob(name, NDN_MARKER_VERSION, secs, nsecs);
    }
    myres |= ndn_charbuf_append_closer(name); /* </Component> */
    if (myres < 0) {
        name->length = i;
        goto CloseName;
    }
    j = name->length;
    if (already_versioned && (versioning_flags & NDN_V_REPLACE) != 0) {
        oc = nix->buf[n-1];
        lc = nix->buf[n] - oc;
        if ((versioning_flags & NDN_V_HIGH) != 0 &&
            memcmp(name->buf + oc, name->buf + i, j - i) > 0) {
            /* Supplied version is in the future. */
            name->length = i;
            // XXX - we could try harder to make this work, for now just error out
            myres = -1;
            goto CloseName;
        }
        memmove(name->buf + oc, name->buf + i, j - i);
        name->length -= lc;
    }
CloseName:
    myres |= ndn_charbuf_append_closer(name); /* </Name> */
Finish:
    myres = (myres < 0) ? -1 : 0;
    ndn_indexbuf_destroy(&nix);
    return(myres);
}
Ejemplo n.º 6
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.º 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);
Ejemplo n.º 8
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);
}
Ejemplo n.º 9
0
int
main (int argc, char *argv[]) {
    struct ndn *ndn = NULL;
    struct ndn_closure *action;
    struct ndn_charbuf *namebuf = NULL;
    struct ndn_charbuf *interestnamebuf = NULL;
    struct ndn_charbuf *interesttemplatebuf = NULL;
    struct ndn_buf_decoder decoder;
    struct ndn_buf_decoder *d;
    struct handlerstate *state;
    char *filename;
    char rawbuf[1024 * 1024];
    ssize_t rawlen;
    int i, n, res;
    int fd = -1;

    ndn = ndn_create();
    if (ndn_connect(ndn, NULL) == -1) {
        perror("ndn_connect");
        exit(1);
    }
    
    state = calloc(1, sizeof(struct handlerstate));
    action = calloc(1, sizeof(struct ndn_closure));
    action->p = interest_handler;

    namebuf = ndn_charbuf_create();
    if (namebuf == NULL) {
        fprintf(stderr, "ndn_charbuf_create\n");
        exit(1);
    }
    res = ndn_name_init(namebuf);
    if (res < 0) {
        fprintf(stderr, "ndn_name_init\n");
        exit(1);
    }

    interestnamebuf = ndn_charbuf_create();
    interesttemplatebuf = ndn_charbuf_create();
    if (interestnamebuf == NULL || interesttemplatebuf == NULL) {
        fprintf(stderr, "ndn_charbuf_create\n");
        exit(1);
    }
    res = ndn_name_init(interestnamebuf);
    if (res < 0) {
        fprintf(stderr, "ndn_name_init\n");
        exit(1);
    }

    n = 0;
    for (i = 1; i < argc; i++) {
        if (fd != -1) close(fd);
        filename = argv[i];
        if (0 == strcmp(filename, "-d")) {
            options.logging++;
            continue;
        }
        if (0 == strcmp(filename, "-nointerest")) {
            options.nointerest = 1;
            continue;
        }
        if (0 == strcmp(filename, "-reconnect")) {
            options.reconnect = 1;
            continue;
        }
        
        if (options.logging > 0) fprintf(stderr, "Processing %s ", filename);
        fd = open(filename, O_RDONLY);
        if (fd == -1) {
            perror("- open");
            continue;
        }

        rawlen = read(fd, rawbuf, sizeof(rawbuf));
        if (rawlen <= 0) {
            perror("- read");
            continue;
        }
        
        d = ndn_buf_decoder_start(&decoder, (unsigned char *)rawbuf, rawlen);

        if (ndn_buf_match_dtag(d, NDN_DTAG_ContentObject)) {
            state->items = realloc(state->items, (n + 1) * sizeof(*(state->items)));
            if (state->items == NULL) {
                perror(" - realloc failed");
                exit(1);
            }
            memset(&(state->items[n]), 0, sizeof(*(state->items)));
            state->items[n].components = ndn_indexbuf_create();
            res = ndn_parse_ContentObject((unsigned char *)rawbuf, rawlen, &(state->items[n].x), state->items[n].components);
            if (res < 0) {
                if (options.logging > 0) fprintf(stderr, "Processing %s ", filename);
                fprintf(stderr, "- skipping: ContentObject error %d\n", res);
                ndn_indexbuf_destroy(&state->items[n].components);
                continue;
            }
            if (options.logging > 0) fprintf(stderr, "- ok\n");
            state->items[n].filename = filename;
            state->items[n].contents = malloc(rawlen);
            state->items[n].size = rawlen;
            memcpy(state->items[n].contents, rawbuf, rawlen);
            n++;
        } else if (ndn_buf_match_dtag(d, NDN_DTAG_Interest)) {
            struct ndn_parsed_interest interest = {0};
            if (options.nointerest == 0) {
                size_t name_start;
                size_t name_size;
                interestnamebuf->length = 0;
                interesttemplatebuf->length = 0;
                res = ndn_parse_interest((unsigned char *)rawbuf, rawlen, &interest, NULL);
                name_start = interest.offset[NDN_PI_B_Name];
                name_size = interest.offset[NDN_PI_E_Name] - name_start;
                ndn_charbuf_append(interestnamebuf, rawbuf + name_start, name_size);
                ndn_charbuf_append(interesttemplatebuf, rawbuf, rawlen);
                res = ndn_express_interest(ndn, interestnamebuf, action, interesttemplatebuf);
            }
        } else {
            if (options.logging == 0) fprintf(stderr, "Processing %s ", filename);
            fprintf(stderr, "- skipping: unknown type\n");
        }
    }
    state->count = n;
    action->data = state;

    if (ndn_name_init(namebuf) == -1) {
        fprintf(stderr, "ndn_name_init\n");
        exit(1);
    }

    res = ndn_set_interest_filter(ndn, namebuf, action);
    for (;;) {
        res = ndn_run(ndn, -1);
        ndn_disconnect(ndn);
        if (!options.reconnect)
            break;
        sleep(2);
        ndn_connect(ndn, NULL);
    }
    ndn_destroy(&ndn);
    exit(0);
}
Ejemplo n.º 10
0
enum ndn_upcall_res
interest_handler(struct ndn_closure *selfp,
                 enum ndn_upcall_kind upcall_kind,
                 struct ndn_upcall_info *info)
{
    int i, c, mc, match, res;
    struct handlerstateitem item;
    struct handlerstate *state;
    size_t ndnb_size = 0;

    state = selfp->data;
    switch(upcall_kind) {
    case NDN_UPCALL_FINAL:
        fprintf(stderr, "Upcall final\n");
        return (0);

    case NDN_UPCALL_INTEREST_TIMED_OUT:
        fprintf(stderr, "refresh\n");
        return (NDN_UPCALL_RESULT_REEXPRESS);
        
    case NDN_UPCALL_CONTENT:
    case NDN_UPCALL_CONTENT_UNVERIFIED:
        ndnb_size = info->pco->offset[NDN_PCO_E];
        c = state->count;
        for (i = 0; i < c; i++) {
            if (info->content_comps->n == state->items[i].components->n) {
                mc = match_components((unsigned char *)info->content_ndnb, info->content_comps,
                                  state->items[i].contents, state->items[i].components);
                if (mc == (info->content_comps->n - 1)) {
                    fprintf(stderr, "Duplicate content\n");
                    return (0);
                }
            }
        }
        fprintf(stderr, "Storing content item %d ", c);
        state->items = realloc(state->items, (c + 1) * sizeof(*(state->items)));
        if (state->items == NULL) {
            perror("realloc failed");
            exit(1);
        }
        memset(&(state->items[c]), 0, sizeof(*(state->items)));
        state->items[c].components = ndn_indexbuf_create();
        /* XXX: probably should not have to do this re-parse of the content object */
        res = ndn_parse_ContentObject(info->content_ndnb, ndnb_size, &(state->items[c].x), state->items[c].components);
        if (res < 0) {
            fprintf(stderr, "- skipping: Not a ContentObject\n");
            ndn_indexbuf_destroy(&state->items[c].components);
            return (-1);
        }
        fprintf(stderr, "- ok\n");
        state->items[c].filename = "ephemeral";
        state->items[c].contents = malloc(ndnb_size);
        state->items[c].size = ndnb_size;
        memcpy(state->items[c].contents, info->content_ndnb, ndnb_size);
        state->count = c + 1;
        return (0);

    case NDN_UPCALL_CONTENT_BAD:
	fprintf(stderr, "Content signature verification failed! Discarding.\n");
	return (-1);

    case NDN_UPCALL_CONSUMED_INTEREST:
        fprintf(stderr, "Upcall consumed interest\n");
        return (-1); /* no data */

    case NDN_UPCALL_INTEREST:
        c = state->count;
        for (i = 0; i < c; i++) {
            match = ndn_content_matches_interest(state->items[i].contents,
                                                 state->items[i].size,
                                                 1,
                                                 NULL,
                                                 info->interest_ndnb,
                                                 info->pi->offset[NDN_PI_E],
                                                 info->pi);
            if (match) {
                ndn_put(info->h, state->items[i].contents, state->items[i].size);
                fprintf(stderr, "Sending %s\n", state->items[i].filename);
                if (i < c - 1) {
                    item = state->items[i];
                    memmove(&(state->items[i]), &(state->items[i+1]), sizeof(item) * ((c - 1) - i));
                    state->items[c - 1] = item;
                }
                return (1);
            }
        }
        return(0);
    case NDN_UPCALL_CONTENT_KEYMISSING:
    case NDN_UPCALL_CONTENT_RAW:
        /* should not happen */
        return (-1);
    }
    return (-1);
}
Ejemplo n.º 11
0
int
main(int argc, char **argv)
{
    char *arg = NULL;
    struct ndn *ndnH = NULL;
    struct ndn_parsed_interest interest = {0};
    struct ndn_charbuf *c = ndn_charbuf_create();
    struct ndn_charbuf *templ = ndn_charbuf_create();
    struct ndn_indexbuf *comps = ndn_indexbuf_create();
    int i;
    int millis = 0;
    int secs = 0;
    int opt;
    int pool = 0;
    int regflgs = (NDN_FORW_CHILD_INHERIT | NDN_FORW_ACTIVE);
    int res;
    int status = 0;
    int val = 0;
    
    while ((opt = getopt(argc, argv, "hv")) != -1) {
        switch (opt) {
            default:
            case 'h':
                usage();
                break;
            case 'v':
                verbose++;
                break;
        }
    }
    argc -= optind;
    argv += optind;
    ndnH = ndn_create();
    if (ndn_connect(ndnH, NULL) == -1) {
        ndn_perror(ndnH, "ndn_connect");
        exit(1);
    }
    for (i = 0; i < N_POOLS; i++) {
        store[i].me.p = &outgoing_content;
        store[i].me.data = &store[i];
        store[i].me.intdata = i;
        incoming_content_action[i].p = &incoming_content;
        incoming_content_action[i].intdata = i;
    }
    for (i = 0; i < argc; i++) {
        arg = argv[i];
        if (0 == strcmp(arg, "reconnect")) {
            if (argv[i+1] == NULL)
                usage();
            secs = atoi(argv[i+1]);
            if (secs <= 0 && strcmp(argv[i+1], "0") != 0)
                usage();
            i++;
            ndn_disconnect(ndnH);
            sleep(secs);
            if (ndn_connect(ndnH, NULL) == -1) {
                ndn_perror(ndnH, "ndn_connect");
                exit(1);
            }
            continue;
        }
        if (0 == strcmp(arg, "pool")) {
            if (argv[i+1] == NULL)
                usage();
            pool = argv[i+1][0] - '0';
            if (argv[i+1][1] || pool < 0 || pool >= N_POOLS)
                usage();
            fprintf(stderr, "Pool %d\n", pool);
            i++;
            continue;
        }
        if (0 == strcmp(arg, "prefix")) {
            if (argv[i+1] == NULL)
                usage();
            c->length = 0;
            res = ndn_name_from_uri(c, argv[i+1]);
            if (res < 0)
                usage();
            fprintf(stderr, "Prefix ff=%#x %s pool %d\n",
                    regflgs, argv[i+1], pool);
            if (store[pool].me.intdata != pool) {
                abort();
            }
            res = ndn_set_interest_filter_with_flags(ndnH, c, &store[pool].me, regflgs);
            if (res < 0) {
                ndn_perror(ndnH, "ndn_set_interest_filter_with_flags");
                status = 1;
            }
            res = ndn_run(ndnH, 2);
            if (res < 0)
                break;
            i++;
            continue;
        }
        if (0 == strcmp(arg, "flags")) {
            if (argv[i+1] == NULL)
                usage();
            regflgs = atoi(argv[i+1]);
            if (regflgs <= 0 && strcmp(argv[i+1], "0") != 0)
                usage();
            i++;
            continue;
        }
        if (0 == strcmp(arg, "mincob")) {
            if (argv[i+1] == NULL)
                usage();
            val = atoi(argv[i+1]);
            if (val <= 0 && strcmp(argv[i+1], "0") != 0)
                usage();
            i++;
            if (n_pool(pool) < val) {
                fprintf(stderr, "Pool %d has %d cobs, expected at least %d\n",
                        pool, n_pool(pool), val);
                exit(1);
            }
            continue;
        }
        if (0 == strcmp(arg, "maxcob")) {
            if (argv[i+1] == NULL)
                usage();
            val = atoi(argv[i+1]);
            if (val <= 0 && strcmp(argv[i+1], "0") != 0)
                usage();
            i++;
            if (n_pool(pool) > val) {
                fprintf(stderr, "Pool %d has %d cobs, expected at most %d\n",
                        pool, n_pool(pool), val);
                exit(1);
            }
            continue;
        }
        if (0 == strcmp(arg, "run")) {
            if (argv[i+1] == NULL)
                usage();
            millis = atoi(argv[i+1]);
            if (millis <= 0 && strcmp(argv[i+1], "0") != 0)
                usage();
            i++;
            res = ndn_run(ndnH, millis);
            if (res < 0) {
                ndn_perror(ndnH, "ndn_run");
                exit(1);
            }
            continue;
        }
        close(0);
        res = open(arg, O_RDONLY);
        if (res != 0) {
            perror(arg);
            exit(1);
        }
        fprintf(stderr, "Reading %s ... ", arg);
        rawlen = read(0, rawbuf, sizeof(rawbuf));
        if (rawlen < 0) {
            perror("skipping");
            // XXX - status
            continue;
        }
        // XXX - Should do a skeleton check before parse
        res = ndn_parse_interest(rawbuf, rawlen, &interest, NULL);
        if (res >= 0) {
            size_t name_start = interest.offset[NDN_PI_B_Name];
            size_t name_size = interest.offset[NDN_PI_E_Name] - name_start;
            templ->length = 0;
            ndn_charbuf_append(templ, rawbuf, rawlen);
            fprintf(stderr, "Expressing interest with %d name components\n", res);
            c->length = 0;
            ndn_charbuf_append(c, rawbuf + name_start, name_size);
            // XXX - res is currently ignored
            ndn_express_interest(ndnH, c, &(incoming_content_action[pool]), templ);
        }
        else {
            struct ndn_parsed_ContentObject obj = {0};
            int try;
            res = ndn_parse_ContentObject(rawbuf, rawlen, &obj, comps);
            if (res >= 0) {
                for (try = 0; try < 5; try++) {
                    res = add_to_pool(pool, rawbuf, rawlen);
                    if (res >= 0) {
                        fprintf(stderr, "Added to pool %d\n", pool);
                        break;
                    }
                    if (try == 5) {
                        fprintf(stderr, "No buffer for %s\n", arg);
                        status = 1;
                        break;
                    }
                    fprintf(stderr, "Pool %d full - wait for drain\n", pool);
                    if (ndn_run(ndnH, 1000) < 0)
                        break;
                }
                res = ndn_run(ndnH, 10);
            }
            else {
                fprintf(stderr, "What is that?\n");
                status = 1;
            }
        }
        res = ndn_run(ndnH, 10);
        if (res < 0) {
            ndn_perror(ndnH, "oops");
            status = 1;
        }
    }
    res = ndn_run(ndnH, 10);
    if (res < 0)
        status = 1;
    ndn_destroy(&ndnH);
    exit(status);
}