Esempio n. 1
0
/**
 * Write a file named index/stable that contains the size of
 * repoFile1 when the repository is shut down.
 */
static int
r_store_write_stable_point(struct ccnr_handle *h)
{
    struct ccn_charbuf *path = NULL;
    struct ccn_charbuf *cb = NULL;
    int fd;
    
    path = ccn_charbuf_create();
    cb = ccn_charbuf_create();
    ccn_charbuf_putf(path, "%s/index/stable", h->directory);
    unlink(ccn_charbuf_as_string(path)); /* Should not exist, but just in case. */
    fd = open(ccn_charbuf_as_string(path),
              O_CREAT | O_EXCL | O_WRONLY | O_TRUNC, 0666);
    if (fd == -1) {
        ccnr_msg(h, "cannot write stable mark %s: %s",
                 ccn_charbuf_as_string(path), strerror(errno));
        unlink(ccn_charbuf_as_string(path));
    }
    else {
        ccn_charbuf_putf(cb, "%ju", (uintmax_t)(h->stable));
        write(fd, cb->buf, cb->length);
        close(fd);
        if (CCNSHOULDLOG(h, dfsdf, CCNL_INFO))
            ccnr_msg(h, "Index marked stable - %s", ccn_charbuf_as_string(cb));
    }
    ccn_charbuf_destroy(&path);
    ccn_charbuf_destroy(&cb);
    return(0);
}
Esempio n. 2
0
/**
 * Get the specified numerical config value, subject to limits.
 */
intmax_t
r_init_confval(struct ccnr_handle *h, const char *key,
                     intmax_t lo, intmax_t hi, intmax_t deflt) {
    const char *s;
    intmax_t v;
    char *ep;
    
    if (!(lo <= deflt && deflt <= hi))
        abort();
    s = getenv(key);
    if (s != NULL && s[0] != 0) {
        ep = "x";
        v = strtoimax(s, &ep, 10);
        if (v != 0 || ep[0] == 0) {
            if (v > hi)
                v = hi;
            if (v < lo)
                v = lo;
            if (CCNSHOULDLOG(h, mmm, CCNL_FINEST))
                ccnr_msg(h, "Using %s=%jd", key, v);
            return(v);
        }
    }
    return (deflt);
}
Esempio n. 3
0
/**
 *  Get the base address of the content object
 *
 * This may involve reading the object in.  Caller should not assume that
 * the address will stay valid after it relinquishes control, either by
 * returning or by calling routines that might invalidate objects.
 *
 */
PUBLIC const unsigned char *
r_store_content_base(struct ccnr_handle *h, struct content_entry *content)
{
    const unsigned char *ans = NULL;
    
    if (content->cob != NULL && content->cob->length == content->size) {
        ans = content->cob->buf;
        goto Finish;
    }
    if (content->accession == CCNR_NULL_ACCESSION)
        goto Finish;
    ans = r_store_content_mapped(h, content);
    if (ans != NULL)
        goto Finish;
    ans = r_store_content_read(h, content);
Finish:
    if (ans != NULL) {
        /* Sanity check - make sure first 2 and last 2 bytes are good */
        if (content->size < 5 || ans[0] != 0x04 || ans[1] != 0x82 ||
            ans[content->size - 1] != 0 || ans[content->size - 2] != 0) {
            bogon = ans; /* for debugger */
            ans = NULL;
        }
    }
    if (ans == NULL || CCNSHOULDLOG(h, xxxx, CCNL_FINEST))
        ccnr_msg(h, "r_store_content_base.%d returning %p (acc=0x%jx, cookie=%u)",
                 __LINE__,
                 ans,
                 ccnr_accession_encode(h, content->accession),
                 (unsigned)content->cookie);
    return(ans);
}
Esempio n. 4
0
PUBLIC int
r_sendq_face_send_queue_insert(struct ccnr_handle *h,
                       struct fdholder *fdholder, struct content_entry *content)
{
    int ans = -1;
    int delay;
    enum cq_delay_class c;
    struct content_queue *q;
    if (fdholder == NULL || content == NULL || (fdholder->flags & CCNR_FACE_NOSEND) != 0)
        return(-1);
    c = choose_content_delay_class(h, fdholder->filedesc, r_store_content_flags(content));
    if (fdholder->q[c] == NULL)
        fdholder->q[c] = content_queue_create(h, fdholder, c);
    q = fdholder->q[c];
    if (q == NULL)
        return(-1);
    ans = ccn_indexbuf_set_insert(q->send_queue, r_store_content_cookie(h, content));
    if (q->sender == NULL) {
        delay = randomize_content_delay(h, q);
        q->ready = q->send_queue->n;
        q->sender = ccn_schedule_event(h->sched, delay,
                                       content_sender, q, fdholder->filedesc);
        if (CCNSHOULDLOG(h, LM_8, CCNL_FINER))
            ccnr_msg(h, "fdholder %u q %d delay %d usec", fdholder->filedesc, c, delay);
    }
    return (ans);
}
Esempio n. 5
0
/**
 *  Evict recoverable content from in-memory buffers
 */
PUBLIC void
r_store_trim(struct ccnr_handle *h, unsigned long limit)
{
    struct content_entry *content = NULL;
    int checklimit;
    unsigned before;
    unsigned rover;
    unsigned mask;
    
    r_store_index_needs_cleaning(h);
    before = h->cob_count;
    if (before <= limit)
        return;
    checklimit = h->cookie_limit;
    mask = h->cookie_limit - 1;
    for (rover = (h->trim_rover & mask);
         checklimit > 0 && h->cob_count > limit;
         checklimit--, rover = (rover + 1) & mask) {
        content = h->content_by_cookie[rover];
        if (content != NULL)
            r_store_content_trim(h, content);
    }
    h->trim_rover = rover;
    if (CCNSHOULDLOG(h, sdf, CCNL_FINER))
        ccnr_msg(h, "trimmed %u cobs", before - h->cob_count);
}
Esempio n. 6
0
PUBLIC struct content_entry *
process_incoming_content(struct ccnr_handle *h, struct fdholder *fdholder,
                         unsigned char *msg, size_t size)
{
    struct ccn_parsed_ContentObject obj = {0};
    int res;
    struct content_entry *content = NULL;
    ccnr_accession accession = CCNR_NULL_ACCESSION;
    
    content = calloc(1, sizeof(*content));
    if (content == NULL)
        goto Bail;    
    content->cob = ccn_charbuf_create();
    if (content->cob == NULL)
        goto Bail;    
    res = ccn_charbuf_append(content->cob, msg, size);
    if (res < 0) goto Bail;
    content->size = size;
    res = r_store_set_flatname(h, content, &obj);
    if (res < 0) goto Bail;
    ccnr_meter_bump(h, fdholder->meter[FM_DATI], 1);
    content->accession = CCNR_NULL_ACCESSION;
    r_store_enroll_content(h, content);
    if (CCNSHOULDLOG(h, LM_4, CCNL_FINE))
        ccnr_debug_content(h, __LINE__, "content_from", fdholder, content);
    res = r_store_content_btree_insert(h, content, &obj, &accession);
    if (res < 0) goto Bail;
    if (res == 0) {
        /* Content was there, with an accession */
        if (CCNSHOULDLOG(h, LM_4, CCNL_FINER))
            ccnr_debug_content(h, __LINE__, "content_duplicate",
                               fdholder, content);
        h->content_dups_recvd++;
        r_store_forget_content(h, &content);
        content = r_store_content_from_accession(h, accession);
        if (content == NULL)
            goto Bail;
    }
    r_store_set_content_timer(h, content, &obj);
    r_match_match_interests(h, content, &obj, NULL, fdholder);
    return(content);
Bail:
    r_store_forget_content(h, &content);
    return(content);
}
Esempio n. 7
0
PUBLIC void
r_store_send_content(struct ccnr_handle *h, struct fdholder *fdholder, struct content_entry *content)
{
    const unsigned char *content_msg = NULL;
    off_t offset;

    if (CCNSHOULDLOG(h, LM_4, CCNL_FINE))
        ccnr_debug_content(h, __LINE__, "content_to", fdholder, content);
    content_msg = r_store_content_base(h, content);
    r_link_stuff_and_send(h, fdholder, content_msg, content->size, NULL, 0, &offset);
    if (offset != (off_t)-1 && content->accession == CCNR_NULL_ACCESSION) {
        int res;
        res = r_store_set_accession_from_offset(h, content, fdholder, offset);
        if (res == 0)
            if (CCNSHOULDLOG(h, LM_4, CCNL_FINE))
                ccnr_debug_content(h, __LINE__, "content_stored",
                                   r_io_fdholder_from_fd(h, h->active_out_fd),
                                   content);
    }
}
Esempio n. 8
0
PUBLIC int
r_io_open_repo_data_file(struct ccnr_handle *h, const char *name, int output)
{
    struct ccn_charbuf *temp = NULL;
    int fd = -1;
    struct fdholder *fdholder = NULL;

    temp = ccn_charbuf_create();
    ccn_charbuf_putf(temp, "%s/%s", h->directory, name);
    fd = open(ccn_charbuf_as_string(temp), output ? (O_CREAT | O_WRONLY | O_APPEND) : O_RDONLY, 0666);
    if (fd == -1) {
        if (CCNSHOULDLOG(h, sdf, CCNL_FINE))
            ccnr_msg(h, "open(%s): %s", ccn_charbuf_as_string(temp), strerror(errno));
        ccn_charbuf_destroy(&temp);
        return(-1);
    }
    fdholder = r_io_record_fd(h, fd,
                            temp->buf, temp->length,
                            CCNR_FACE_REPODATA | (output ? CCNR_FACE_NORECV : CCNR_FACE_NOSEND));
    if (fdholder == NULL)
        close_fd(&fd);
    else {
        if (!output) {
            /* Use a larger buffer for indexing an existing repo file */
            if (fdholder->inbuf == NULL) {
                fdholder->inbuf = ccn_charbuf_create();
                fdholder->bufoffset = 0;
            }
            if (fdholder->inbuf != NULL)
                ccn_charbuf_reserve(fdholder->inbuf, 256 * 1024);
        }
        if (CCNSHOULDLOG(h, sdf, CCNL_INFO))
            ccnr_msg(h, "opened fd=%d file=%s", fd, ccn_charbuf_as_string(temp));
    }
    ccn_charbuf_destroy(&temp);
    return(fd);
}
Esempio n. 9
0
/**
 * Close an open file descriptor, and grumble about it.
 */
/* unused */ void
ccnr_close_fd(struct ccnr_handle *h, unsigned filedesc, int *pfd)
{
    int res;
    
    if (*pfd != -1) {
        int linger = 0;
        setsockopt(*pfd, SOL_SOCKET, SO_LINGER,
                   &linger, sizeof(linger));
        res = close(*pfd);
        if (res == -1)
            ccnr_msg(h, "close failed for fdholder %u fd=%d: %s (errno=%d)",
                     filedesc, *pfd, strerror(errno), errno);
        else if (CCNSHOULDLOG(h, io, CCNL_FINE))
            ccnr_msg(h, "closing fd %d while finalizing fdholder %u", *pfd, filedesc);
        *pfd = -1;
    }
}
Esempio n. 10
0
/**
 * Message helper for r_init_parse_config()
 */
static void
r_init_config_msg(struct ccnr_handle *h, int flags,
                  int line, int chindex, const char *msg)
{
    const char *problem = "Problem";
    int log_at = CCNL_WARNING;
    
    log_at = CCNL_WARNING;
    if ((flags & CCNR_CONFIG_ERR) != 0) {
        problem = "Error";
        log_at = CCNL_ERROR;
    }
    if ((flags & (CCNR_CONFIG_IGNORELINE|CCNR_CONFIG_PASSMASK)) == 1 &&
        CCNSHOULDLOG(h, mmm, log_at)) {
        ccnr_msg(h, "%s in config file %s/config - line %d column %d: %s",
                 problem, h->directory, line, chindex + 1, msg);
    }
}
Esempio n. 11
0
/**
 *  Remove internal representation of a content object
 */
PUBLIC void
r_store_forget_content(struct ccnr_handle *h, struct content_entry **pentry)
{
    unsigned i;
    struct content_entry *entry = *pentry;
    
    if (entry == NULL)
        return;
    *pentry = NULL;
    if ((entry->flags & CCN_CONTENT_ENTRY_STALE) != 0)
        h->n_stale--;
    if (CCNSHOULDLOG(h, LM_4, CCNL_FINER))
        ccnr_debug_content(h, __LINE__, "remove", NULL, entry);
    /* Remove the cookie reference */
    i = entry->cookie & (h->cookie_limit - 1);
    if (h->content_by_cookie[i] == entry)
        h->content_by_cookie[i] = NULL;
    entry->cookie = 0;
    /* Remove the accession reference */
    if (entry->accession != CCNR_NULL_ACCESSION) {
        struct hashtb_enumerator ee;
        struct hashtb_enumerator *e = &ee;
        hashtb_start(h->content_by_accession_tab, e);
        if (hashtb_seek(e, &entry->accession, sizeof(entry->accession), 0) ==
            HT_NEW_ENTRY) {
            ccnr_msg(h, "orphaned content %llu",
                     (unsigned long long)(entry->accession));
            hashtb_delete(e);
            hashtb_end(e);
            return;
        }
        hashtb_delete(e);
        hashtb_end(e);
        entry->accession = CCNR_NULL_ACCESSION;
    }
    /* Clean up allocated subfields */
    ccn_charbuf_destroy(&entry->flatname);
    if (entry->cob != NULL) {
        h->cob_count--;
        ccn_charbuf_destroy(&entry->cob);
    }
    free(entry);
}
Esempio n. 12
0
PUBLIC struct content_entry *
r_store_content_from_accession(struct ccnr_handle *h, ccnr_accession accession)
{
    struct ccn_parsed_ContentObject obj = {0};
    struct content_entry *content = NULL;
    struct content_by_accession_entry *entry;
    const unsigned char *content_base = NULL;
    int res;
    ccnr_accession acc;
    
    if (accession == CCNR_NULL_ACCESSION)
        return(NULL);
    entry = hashtb_lookup(h->content_by_accession_tab,
                          &accession, sizeof(accession));
    if (entry != NULL) {
        h->content_from_accession_hits++;
        return(entry->content);
    }
    h->content_from_accession_misses++;
    content = calloc(1, sizeof(*content));
    CHKPTR(content);
    content->cookie = 0;
    content->accession = accession;
    content->cob = NULL;
    content->size = 0;
    content_base = r_store_content_base(h, content);
    if (content_base == NULL || content->size == 0)
        goto Bail;
    res = r_store_set_flatname(h, content, &obj);
    if (res < 0) goto Bail;
    r_store_enroll_content(h, content);
    res = r_store_content_btree_insert(h, content, &obj, &acc);
    if (res < 0) goto Bail;
    if (res == 1 || CCNSHOULDLOG(h, sdf, CCNL_FINEST))
        ccnr_debug_content(h, __LINE__, "content/accession", NULL, content);
    return(content);
Bail:
    ccnr_msg(h, "r_store_content_from_accession.%d failed 0x%jx",
             __LINE__, ccnr_accession_encode(h, accession));
    r_store_forget_content(h, &content);
    return(content);
}
Esempio n. 13
0
static int
merge_files(struct ccnr_handle *h)
{
    int i, last_file;
    int res;
    struct ccn_charbuf *filename = ccn_charbuf_create();
    
    // first parse the file(s) making sure there are no errors
    for (i = 2;; i++) {
        filename->length = 0;
        ccn_charbuf_putf(filename, "repoFile%d", i);
        res = r_init_map_and_process_file(h, filename, 0);
        if (res == 1)
            break;
        if (res < 0) {
            ccnr_msg(h, "Error parsing repository file %s", ccn_charbuf_as_string(filename));
            return (-1);
        }
    }
    last_file = i - 1;
    
    for (i = 2; i <= last_file; i++) {
        filename->length = 0;
        ccn_charbuf_putf(filename, "repoFile%d", i);
        res = r_init_map_and_process_file(h, filename, 1);
        if (res < 0) {
            ccnr_msg(h, "Error in phase 2 incorporating repository file %s", ccn_charbuf_as_string(filename));
            return (-1);
        }
    }
    
    for (i = last_file; i > 1; --i) {
        filename->length = 0;
        ccn_charbuf_putf(filename, "%s/repoFile%d", h->directory, i);
        if (CCNSHOULDLOG(h, LM_128, CCNL_INFO))
            ccnr_msg(h, "unlinking %s", ccn_charbuf_as_string(filename));   
        unlink(ccn_charbuf_as_string(filename));
    }
    ccn_charbuf_destroy(&filename);
    return (0);
}
Esempio n. 14
0
/**
 * Read the former size of repoFile1 from index/stable, and remove
 * the latter.
 */
static void
r_store_read_stable_point(struct ccnr_handle *h)
{
    struct ccn_charbuf *path = NULL;
    struct ccn_charbuf *cb = NULL;
    int fd;
    int i;
    ssize_t rres;
    uintmax_t val;
    unsigned char c;
    
    path = ccn_charbuf_create();
    cb = ccn_charbuf_create();
    ccn_charbuf_putf(path, "%s/index/stable", h->directory);
    fd = open(ccn_charbuf_as_string(path), O_RDONLY, 0666);
    if (fd != -1) {
        rres = read(fd, ccn_charbuf_reserve(cb, 80), 80);
        if (rres > 0)
            cb->length = rres;
        close(fd);
        if (CCNSHOULDLOG(h, dfsdf, CCNL_INFO))
            ccnr_msg(h, "Last stable at %s", ccn_charbuf_as_string(cb));
    }
    for (val = 0, i = 0; i < cb->length; i++) {
        c = cb->buf[i];
        if ('0' <= c && c <= '9')
            val = val * 10 + (c - '0');
        else
            break;
    }
    if (i == 0 || i < cb->length) {
        ccnr_msg(h, "Bad stable mark - %s", ccn_charbuf_as_string(cb));
        h->stable = 0;
    }
    else {
        h->stable = val;
        unlink(ccn_charbuf_as_string(path));
    }
    ccn_charbuf_destroy(&path);
    ccn_charbuf_destroy(&cb);
}
Esempio n. 15
0
PUBLIC void
r_store_index_needs_cleaning(struct ccnr_handle *h)
{
    int k;
    if (h->btree != NULL && h->btree->io != NULL && h->btree->cleanreq > 0) {
        if (h->index_cleaner == NULL) {
            h->index_cleaner = ccn_schedule_event(h->sched,
                                                  CCN_BT_CLEAN_TICK_MICROS,
                                                  r_store_index_cleaner, NULL, 0);
            if (CCNSHOULDLOG(h, sdfsdffd, CCNL_FINER))
                ccnr_msg(h, "index cleaner started");
        }
        /* If necessary, clean in a hurry. */
        for (k = 30; /* Backstop to make sure we do not loop here */
             k > 0 && h->index_cleaner != NULL &&
             h->btree->io->openfds > CCN_BT_OPEN_NODES_LIMIT - 2; k--)
            r_store_index_cleaner(h->sched, h, h->index_cleaner, 0);
        if (k == 0)
            ccnr_msg(h, "index cleaner is in trouble");
    }
}
Esempio n. 16
0
static int
ccnr_direct_client_refresh(struct ccn_schedule *sched,
               void *clienth,
               struct ccn_scheduled_event *ev,
               int flags)
{
    struct ccnr_handle *ccnr = clienth;
    int microsec = 0;
    if ((flags & CCN_SCHEDULE_CANCEL) == 0 &&
          ccnr->direct_client != NULL &&
          ccnr->direct_client_refresh == ev) {
        microsec = ccn_process_scheduled_operations(ccnr->direct_client);
        // XXX - This is not really right, since an incoming request can cause us to need to reschedule this event.
        if CCNSHOULDLOG(ccnr, refresh, CCNL_FINEST)
            ccnr_msg(ccnr, "direct_client_refresh %d in %d usec",
                     ccn_get_connection_fd(ccnr->direct_client), microsec);
        if (microsec > ev->evint)
            microsec = ev->evint;
        if (microsec == 0)
            microsec = CCN_INTEREST_LIFETIME_MICROSEC;
    }
Esempio n. 17
0
PUBLIC struct content_entry *
r_store_next_child_at_level(struct ccnr_handle *h,
                    struct content_entry *content, int level)
{
    struct content_entry *next = NULL;
    struct ccn_charbuf *name;
    struct ccn_charbuf *flatname = NULL;
    int res;
    
    if (content == NULL)
        return(NULL);
    name = ccn_charbuf_create();
    ccn_name_init(name);
    res = ccn_name_append_flatname(name,
                                   content->flatname->buf,
                                   content->flatname->length, 0, level + 1);
    if (res < level)
        goto Bail;
    if (res == level)
        res = ccn_name_append(name, NULL, 0);
    else if (res == level + 1)
        res = ccn_name_next_sibling(name); // XXX - would be nice to have a flatname version of this
    if (res < 0)
        goto Bail;
    if (CCNSHOULDLOG(h, LM_8, CCNL_FINER))
        ccnr_debug_ccnb(h, __LINE__, "child_successor", NULL,
                        name->buf, name->length);
    flatname = ccn_charbuf_create();
    ccn_flatname_from_ccnb(flatname, name->buf, name->length);
    next = r_store_look(h, flatname->buf, flatname->length);
    if (next == content) {
        // XXX - I think this case should not occur, but just in case, avoid a loop.
        ccnr_debug_content(h, __LINE__, "urp", NULL, next);
        next = NULL;
    }
Bail:
    ccn_charbuf_destroy(&name);
    ccn_charbuf_destroy(&flatname);
    return(next);
}
Esempio n. 18
0
PUBLIC void
r_io_shutdown_client_fd(struct ccnr_handle *h, int fd)
{
    struct fdholder *fdholder = NULL;
    enum cq_delay_class c;
    int m;
    int res;
    
    fdholder = r_io_fdholder_from_fd(h, fd);
    if (fdholder == NULL) {
        ccnr_msg(h, "no fd holder for fd %d", fd);
        return;
    }
    if (fdholder == h->face0)
        (res = 0, h->face0 = NULL);
    else if ((fdholder->flags & CCNR_FACE_CCND))
        res = ccn_disconnect(h->direct_client);
    else
        res = close(fd);
    if (CCNSHOULDLOG(h, sdfdf, CCNL_INFO))
        ccnr_msg(h, "shutdown client fd=%d", fd);
    ccn_charbuf_destroy(&fdholder->inbuf);
    ccn_charbuf_destroy(&fdholder->outbuf);
    for (c = 0; c < CCN_CQ_N; c++)
        r_sendq_content_queue_destroy(h, &(fdholder->q[c]));
    for (m = 0; m < CCNR_FACE_METER_N; m++)
        ccnr_meter_destroy(&fdholder->meter[m]);
    if (h->fdholder_by_fd[fd] != fdholder) abort();
    h->fdholder_by_fd[fd] = NULL;
    ccn_charbuf_destroy(&fdholder->name);
    free(fdholder);
    if (h->active_in_fd == fd)
        h->active_in_fd = -1;
    if (h->active_out_fd == fd)
        h->active_out_fd = -1;
    if (h->repofile1_fd == fd)
        h->repofile1_fd = -1;
    // r_fwd_reap_needed(h, 250000);
}
Esempio n. 19
0
/**
 * Accept an incoming DGRAM_STREAM connection, creating a new fdholder.
 * @returns fd of new socket, or -1 for an error.
 */
PUBLIC int
r_io_accept_connection(struct ccnr_handle *h, int listener_fd)
{
    struct sockaddr_storage who;
    socklen_t wholen = sizeof(who);
    int fd;
    struct fdholder *fdholder;

    fd = accept(listener_fd, (struct sockaddr *)&who, &wholen);
    if (fd == -1) {
        ccnr_msg(h, "accept: %s", strerror(errno));
        return(-1);
    }
    fdholder = r_io_record_fd(h, fd,
                            (struct sockaddr *)&who, wholen,
                            CCNR_FACE_UNDECIDED);
    if (fdholder == NULL)
        close_fd(&fd);
    else if (CCNSHOULDLOG(h, io, CCNL_INFO))
        ccnr_msg(h, "accepted client fd=%d id=%u", fd, fdholder->filedesc);
    return(fd);
}
Esempio n. 20
0
/**
 * Consume matching interests
 * given a nameprefix_entry and a piece of content.
 *
 * If fdholder is not NULL, pay attention only to interests from that fdholder.
 * It is allowed to pass NULL for pc, but if you have a (valid) one it
 * will avoid a re-parse.
 * @returns number of matches found.
 */
PUBLIC int
r_match_consume_matching_interests(struct ccnr_handle *h,
                           struct nameprefix_entry *npe,
                           struct content_entry *content,
                           struct ccn_parsed_ContentObject *pc,
                           struct fdholder *fdholder)
{
    int matches = 0;
    struct propagating_entry *head;
    struct propagating_entry *next;
    struct propagating_entry *p;
    const unsigned char *content_msg;
    size_t content_size;
    struct fdholder *f;
    
    head = &npe->pe_head;
    // XXX - i do not think this is called in practice
    content_msg = r_store_content_base(h, content);
    content_size = r_store_content_size(h, content);
    f = fdholder;
    for (p = head->next; p != head; p = next) {
        next = p->next;
        if (p->interest_msg != NULL &&
            ((fdholder == NULL && (f = r_io_fdholder_from_fd(h, p->filedesc)) != NULL) ||
             (fdholder != NULL && p->filedesc == fdholder->filedesc))) {
            if (ccn_content_matches_interest(content_msg, content_size, 1, pc,
                                             p->interest_msg, p->size, NULL)) {
                r_sendq_face_send_queue_insert(h, f, content);
                if (CCNSHOULDLOG(h, (32 | 8), CCNL_FINE))
                    ccnr_debug_ccnb(h, __LINE__, "consume", f,
                                    p->interest_msg, p->size);
                matches += 1;
                r_match_consume_interest(h, p);
            }
        }
    }
    return(matches);
}
Esempio n. 21
0
static int
establish_min_send_bufsize(struct ccnr_handle *h, int fd, int minsize)
{
    int res;
    int bufsize;
    int obufsize;
    socklen_t bufsize_sz;

    bufsize_sz = sizeof(bufsize);
    res = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &bufsize, &bufsize_sz);
    if (res == -1)
        return (res);
    obufsize = bufsize;
    if (bufsize < minsize) {
        bufsize = minsize;
        res = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize));
        if (res == -1)
            return(res);
    }
    if (CCNSHOULDLOG(h, sdfdsf, CCNL_INFO))
        ccnr_msg(h, "SO_SNDBUF for fd %d is %d (was %d)", fd, bufsize, obufsize);
    return(bufsize);
}
Esempio n. 22
0
/**
 * Set up the array of fd descriptors for the poll(2) call.
 *
 */
PUBLIC void
r_io_prepare_poll_fds(struct ccnr_handle *h)
{
    int i, j, nfds;
    
    for (i = 1, nfds = 0; i < h->face_limit; i++)
        if (r_io_fdholder_from_fd(h, i) != NULL)
            nfds++;
    
    if (nfds != h->nfds) {
        h->nfds = nfds;
        h->fds = realloc(h->fds, h->nfds * sizeof(h->fds[0]));
        memset(h->fds, 0, h->nfds * sizeof(h->fds[0]));
    }
    for (i = 1, j = 0; i < h->face_limit; i++) {
        struct fdholder *fdholder = r_io_fdholder_from_fd(h, i);
        if (fdholder != NULL) {
            h->fds[j].fd = fdholder->filedesc;
            h->fds[j].events = 0;
            if ((fdholder->flags & (CCNR_FACE_NORECV|CCNR_FACE_REPODATA)) == 0)
                h->fds[j].events |= POLLIN;
            if (fdholder->filedesc == h->active_in_fd)
                h->fds[j].events |= POLLIN;
            if (((fdholder->flags & CCNR_FACE_REPODATA) == 0) &&
                ((fdholder->outbuf != NULL || (fdholder->flags & CCNR_FACE_CLOSING) != 0)))
                h->fds[j].events |= POLLOUT;
             if ((fdholder->flags & CCNR_FACE_CCND) != 0) {
                 if (ccn_output_is_pending(h->direct_client)) {
                     if (CCNSHOULDLOG(h, xxx, CCNL_FINEST))
                        ccnr_msg(h, "including direct client in poll set");
                     h->fds[j].events |= POLLOUT;
                }
             }
            j++;
        }
    }
}
Esempio n. 23
0
PUBLIC struct content_entry *
r_store_find_first_match_candidate(struct ccnr_handle *h,
                                   const unsigned char *interest_msg,
                                   const struct ccn_parsed_interest *pi)
{
    int res;
    size_t start = pi->offset[CCN_PI_B_Name];
    size_t end = pi->offset[CCN_PI_E_Name];
    struct ccn_charbuf *namebuf = NULL;
    struct ccn_charbuf *flatname = NULL;
    struct content_entry *content = NULL;
    
    flatname = ccn_charbuf_create();
    ccn_flatname_from_ccnb(flatname, interest_msg, pi->offset[CCN_PI_E]);
    if (pi->offset[CCN_PI_B_Exclude] < pi->offset[CCN_PI_E_Exclude]) {
        /* Check for <Exclude><Any/><Component>... fast case */
        struct ccn_buf_decoder decoder;
        struct ccn_buf_decoder *d;
        size_t ex1start;
        size_t ex1end;
        d = ccn_buf_decoder_start(&decoder,
                                  interest_msg + pi->offset[CCN_PI_B_Exclude],
                                  pi->offset[CCN_PI_E_Exclude] -
                                  pi->offset[CCN_PI_B_Exclude]);
        ccn_buf_advance(d);
        if (ccn_buf_match_dtag(d, CCN_DTAG_Any)) {
            ccn_buf_advance(d);
            ccn_buf_check_close(d);
            if (ccn_buf_match_dtag(d, CCN_DTAG_Component)) {
                ex1start = pi->offset[CCN_PI_B_Exclude] + d->decoder.token_index;
                ccn_buf_advance_past_element(d);
                ex1end = pi->offset[CCN_PI_B_Exclude] + d->decoder.token_index;
                if (d->decoder.state >= 0) {
                    namebuf = ccn_charbuf_create();
                    ccn_charbuf_append(namebuf,
                                       interest_msg + start,
                                       end - start);
                    namebuf->length--;
                    ccn_charbuf_append(namebuf,
                                       interest_msg + ex1start,
                                       ex1end - ex1start);
                    ccn_charbuf_append_closer(namebuf);
                    res = ccn_flatname_append_from_ccnb(flatname,
                                                        interest_msg + ex1start,
                                                        ex1end - ex1start,
                                                        0, 1);
                    if (res != 1)
                        ccnr_debug_ccnb(h, __LINE__, "fastex_bug", NULL,
                                        namebuf->buf, namebuf->length);
                    if (CCNSHOULDLOG(h, LM_8, CCNL_FINER))
                        ccnr_debug_ccnb(h, __LINE__, "fastex", NULL,
                                        namebuf->buf, namebuf->length);
                }
            }
        }
    }
    content = r_store_look(h, flatname->buf, flatname->length);
    ccn_charbuf_destroy(&namebuf);
    ccn_charbuf_destroy(&flatname);
    return(content);
}
Esempio n. 24
0
static int
r_store_index_cleaner(struct ccn_schedule *sched,
    void *clienth,
    struct ccn_scheduled_event *ev,
    int flags)
{
    struct ccnr_handle *h = clienth;
    struct hashtb_enumerator ee;
    struct hashtb_enumerator *e = &ee;
    struct ccn_btree_node *node = NULL;
    int k;
    int res;
    int overquota;
    
    (void)(sched);
    (void)(ev);
    if ((flags & CCN_SCHEDULE_CANCEL) != 0 ||
         h->btree == NULL || h->btree->io == NULL) {
        h->index_cleaner = NULL;
        ccn_indexbuf_destroy(&h->toclean);
        return(0);
    }
    /* First, work on cleaning the things we already know need cleaning */
    if (h->toclean != NULL) {
        for (k = 0; k < CCN_BT_CLEAN_BATCH && h->toclean->n > 0; k++) {
            node = ccn_btree_rnode(h->btree, h->toclean->buf[--h->toclean->n]);
            if (node != NULL && node->iodata != NULL) {
                res = ccn_btree_chknode(node); /* paranoia */
                if (res < 0 || CCNSHOULDLOG(h, sdfsdffd, CCNL_FINER))
                    ccnr_msg(h, "write index node %u (err %d)",
                             (unsigned)node->nodeid, node->corrupt);
                if (res >= 0) {
                    if (node->clean != node->buf->length)
                        res = h->btree->io->btwrite(h->btree->io, node);
                    if (res < 0)
                        ccnr_msg(h, "failed to write index node %u",
                                 (unsigned)node->nodeid);
                    else
                        node->clean = node->buf->length;
                }
                if (res >= 0 && node->iodata != NULL && node->activity == 0) {
                    if (CCNSHOULDLOG(h, sdfsdffd, CCNL_FINER))
                        ccnr_msg(h, "close index node %u",
                                 (unsigned)node->nodeid);
                    res = ccn_btree_close_node(h->btree, node);
                }
            }
        }
        if (h->toclean->n > 0)
            return(nrand48(h->seed) % (2U * CCN_BT_CLEAN_TICK_MICROS) + 500);
    }
    /* Sweep though and find the nodes that still need cleaning */
    overquota = 0;
    if (h->btree->nodepool >= 16)
        overquota = hashtb_n(h->btree->resident) - h->btree->nodepool;
    hashtb_start(h->btree->resident, e);
    for (node = e->data; node != NULL; node = e->data) {
        if (overquota > 0 &&
              node->activity == 0 &&
              node->iodata == NULL &&
              node->clean == node->buf->length) {
            overquota -= 1;
            if (CCNSHOULDLOG(h, sdfsdffd, CCNL_FINEST))
                ccnr_msg(h, "prune index node %u",
                         (unsigned)node->nodeid);
            hashtb_delete(e);
            continue;
        }
        node->activity /= 2; /* Age the node's activity */
        if (node->clean != node->buf->length ||
            (node->iodata != NULL && node->activity == 0)) {
            if (h->toclean == NULL) {
                h->toclean = ccn_indexbuf_create();
                if (h->toclean == NULL)
                    break;
            }
            ccn_indexbuf_append_element(h->toclean, node->nodeid);
        }
        hashtb_next(e);
    }
    hashtb_end(e);
    /* If nothing to do, shut down cleaner */
    if ((h->toclean == NULL || h->toclean->n == 0) && overquota <= 0 &&
        h->btree->io->openfds <= CCN_BT_OPEN_NODES_IDLE) {
        h->btree->cleanreq = 0;
        h->index_cleaner = NULL;
        ccn_indexbuf_destroy(&h->toclean);
        if (CCNSHOULDLOG(h, sdfsdffd, CCNL_FINE))
            ccnr_msg(h, "index btree nodes all clean");
        
        return(0);
    }
    return(nrand48(h->seed) % (2U * CCN_BT_CLEAN_TICK_MICROS) + 500);
}
Esempio n. 25
0
/**
 * Send data to the fdholder.
 *
 * No direct error result is provided; the fdholder state is updated as needed.
 */
PUBLIC void
r_io_send(struct ccnr_handle *h,
          struct fdholder *fdholder,
          const void *data, size_t size,
          off_t *offsetp)
{
    ssize_t res;
    off_t offset = -1;
    
    if (offsetp != NULL)
        *offsetp = (off_t)-1;
    if ((fdholder->flags & CCNR_FACE_NOSEND) != 0)
        return;
    if (fdholder->outbuf != NULL) {
        ccn_charbuf_append(fdholder->outbuf, data, size);
        return;
    }
    if (fdholder == h->face0) {
        ccnr_meter_bump(h, fdholder->meter[FM_BYTO], size);
        ccn_dispatch_message(h->internal_client, (void *)data, size);
        r_dispatch_process_internal_client_buffer(h);
        return;
    }
    if ((fdholder->flags & CCNR_FACE_CCND) != 0) {
        /* Writes here need to go via the direct client's handle. */
        ccnr_meter_bump(h, fdholder->meter[FM_BYTO], size);
        res = ccn_put(h->direct_client, data, size);
        if (res < 0 && CCNSHOULDLOG(h, r_io_send, CCNL_WARNING))
            ccnr_msg(h, "ccn_put failed");
        if (res == 1 && CCNSHOULDLOG(h, r_io_send, CCNL_FINEST))
            ccnr_msg(h, "ccn_put deferred output for later send");
        return;
    }
    if ((fdholder->flags & CCNR_FACE_REPODATA) != 0) {
        offset = lseek(fdholder->filedesc, 0, SEEK_END);
        if (offset == (off_t)-1) {
            ccnr_msg(h, "lseek(%d): %s", fdholder->filedesc, strerror(errno));
            return;
        }
        if (offsetp != NULL)
            *offsetp = offset;
        if (fdholder->filedesc == h->active_out_fd) {
            if (offset != h->stable && h->stable != 0)
                ccnr_msg(h, "expected file size %ju, found %ju",
                    (uintmax_t)h->stable,
                    (uintmax_t)offset);
            h->stable = offset + size;
        }
    }
    if ((fdholder->flags & CCNR_FACE_DGRAM) == 0)
        res = write(fdholder->filedesc, data, size);
    else
        res = sendto(sending_fd(h, fdholder), data, size, 0,
                     (struct sockaddr *)fdholder->name->buf,
                     fdholder->name->length);
    if (res > 0)
        ccnr_meter_bump(h, fdholder->meter[FM_BYTO], res);
    if (res == size)
        return;
    if (res == -1) {
        res = handle_send_error(h, errno, fdholder, data, size);
        if (res == -1)
            return;
    }
    if ((fdholder->flags & CCNR_FACE_DGRAM) != 0) {
        ccnr_msg(h, "sendto short");
        return;
    }
    if ((fdholder->flags & CCNR_FACE_REPODATA) != 0) {
        // need to truncate back to last known good object then exit.
        ccnr_msg(h, "Unrecoverable write error writing to repository. Content NOT stored.");
        ftruncate(fdholder->filedesc, offset);
        h->running = 0;
        return;
    }
    fdholder->outbufindex = 0;
    fdholder->outbuf = ccn_charbuf_create();
    if (fdholder->outbuf == NULL) {
        ccnr_msg(h, "do_write: %s", strerror(errno));
        return;
    }
    ccn_charbuf_append(fdholder->outbuf,
                       ((const unsigned char *)data) + res, size - res);
}
Esempio n. 26
0
PUBLIC void
r_store_init(struct ccnr_handle *h)
{
    struct ccn_btree *btree = NULL;
    struct ccn_btree_node *node = NULL;
    struct hashtb_param param = {0};
    int i;
    int j;
    int res;
    struct ccn_charbuf *path = NULL;
    struct ccn_charbuf *msgs = NULL;
    off_t offset;
    
    path = ccn_charbuf_create();
    param.finalize_data = h;
    param.finalize = 0;
    
    h->cob_limit = r_init_confval(h, "CCNR_CONTENT_CACHE", 16, 2000000, 4201);
    h->cookie_limit = choose_limit(h->cob_limit, (ccnr_cookie)(~0U));
    h->content_by_cookie = calloc(h->cookie_limit, sizeof(h->content_by_cookie[0]));
    CHKPTR(h->content_by_cookie);
    h->content_by_accession_tab = hashtb_create(sizeof(struct content_by_accession_entry), NULL);
    CHKPTR(h->content_by_accession_tab);
    h->btree = btree = ccn_btree_create();
    CHKPTR(btree);
    FAILIF(btree->nextnodeid != 1);
    ccn_charbuf_putf(path, "%s/index", h->directory);
    res = mkdir(ccn_charbuf_as_string(path), 0700);
    if (res != 0 && errno != EEXIST)
        r_init_fail(h, __LINE__, ccn_charbuf_as_string(path), errno);
    else {
        msgs = ccn_charbuf_create();
        btree->io = ccn_btree_io_from_directory(ccn_charbuf_as_string(path), msgs);
        if (btree->io == NULL)
            res = errno;
        if (msgs->length != 0 && CCNSHOULDLOG(h, sffdsdf, CCNL_WARNING)) {
            ccnr_msg(h, "while initializing %s - %s",
                     ccn_charbuf_as_string(path),
                     ccn_charbuf_as_string(msgs));
        }
        ccn_charbuf_destroy(&msgs);
        if (btree->io == NULL)
            r_init_fail(h, __LINE__, ccn_charbuf_as_string(path), res);
    }
    node = ccn_btree_getnode(btree, 1, 0);
    if (btree->io != NULL)
        btree->nextnodeid = btree->io->maxnodeid + 1;
    CHKPTR(node);
    if (node->buf->length == 0) {
        res = ccn_btree_init_node(node, 0, 'R', 0);
        CHKSYS(res);
    }
    ccn_charbuf_destroy(&path);
    if (h->running == -1)
        return;
    r_store_read_stable_point(h);
    h->active_in_fd = -1;
    h->active_out_fd = r_io_open_repo_data_file(h, "repoFile1", 1); /* output */
    offset = lseek(h->active_out_fd, 0, SEEK_END);
    h->startupbytes = offset;
    if (offset != h->stable || node->corrupt != 0) {
        ccnr_msg(h, "Index not current - resetting");
        ccn_btree_init_node(node, 0, 'R', 0);
        node = NULL;
        ccn_btree_destroy(&h->btree);
        path = ccn_charbuf_create();
        /* Remove old index files to avoid confusion */
        for (i = 1, j = 0; i > 0 && j < 3; i++) {
            path->length = 0;
            res = ccn_charbuf_putf(path, "%s/index/%d", h->directory, i);
            if (res >= 0)
                res = unlink(ccn_charbuf_as_string(path));
            if (res < 0)
                j++;
        }
        h->btree = btree = ccn_btree_create();
        path->length = 0;
        ccn_charbuf_putf(path, "%s/index", h->directory);
        btree->io = ccn_btree_io_from_directory(ccn_charbuf_as_string(path), msgs);
        CHKPTR(btree->io);
        btree->io->maxnodeid = 0;
        btree->nextnodeid = 1;
        node = ccn_btree_getnode(btree, 1, 0);
        btree->nextnodeid = btree->io->maxnodeid + 1;
        ccn_btree_init_node(node, 0, 'R', 0);
        h->stable = 0;
        h->active_in_fd = r_io_open_repo_data_file(h, "repoFile1", 0); /* input */
        ccn_charbuf_destroy(&path);
        if (CCNSHOULDLOG(h, dfds, CCNL_INFO))
            ccn_schedule_event(h->sched, 50000, r_store_reindexing, NULL, 0);
    }
    if (CCNSHOULDLOG(h, weuyg, CCNL_FINEST)) {
        FILE *dumpfile = NULL;
        
        path = ccn_charbuf_create();
        ccn_charbuf_putf(path, "%s/index/btree_check.out", h->directory);
        dumpfile = fopen(ccn_charbuf_as_string(path), "w");
        res = ccn_btree_check(btree, dumpfile);
        if (dumpfile != NULL) {
            fclose(dumpfile);
            dumpfile = NULL;
        }
        else
            path->length = 0;
        ccnr_msg(h, "ccn_btree_check returned %d (%s)",
                    res, ccn_charbuf_as_string(path));
        ccn_charbuf_destroy(&path);
        if (res < 0)
            r_init_fail(h, __LINE__, "index is corrupt", res);
    }
    btree->full = r_init_confval(h, "CCNR_BTREE_MAX_FANOUT", 4, 9999, 1999);
    btree->full0 = r_init_confval(h, "CCNR_BTREE_MAX_LEAF_ENTRIES", 4, 9999, 1999);
    btree->nodebytes = r_init_confval(h, "CCNR_BTREE_MAX_NODE_BYTES", 1024, 8388608, 2097152);
    btree->nodepool = r_init_confval(h, "CCNR_BTREE_NODE_POOL", 16, 2000000, 512);
    if (h->running != -1)
        r_store_index_needs_cleaning(h);
}
Esempio n. 27
0
PUBLIC struct content_entry *
r_store_lookup(struct ccnr_handle *h,
               const unsigned char *msg,
               const struct ccn_parsed_interest *pi,
               struct ccn_indexbuf *comps)
{
    struct content_entry *content = NULL;
    struct ccn_btree_node *leaf = NULL;
    ccnr_cookie last_match = 0;
    ccnr_accession last_match_acc = CCNR_NULL_ACCESSION;
    struct ccn_charbuf *scratch = NULL;
    size_t size = pi->offset[CCN_PI_E];
    int ndx;
    int res;
    int try;
    
    content = r_store_find_first_match_candidate(h, msg, pi);
    if (content != NULL && CCNSHOULDLOG(h, LM_8, CCNL_FINER))
        ccnr_debug_content(h, __LINE__, "first_candidate", NULL,
                           content);
    if (content != NULL &&
        !r_store_content_matches_interest_prefix(h, content, msg, size)) {
            if (CCNSHOULDLOG(h, LM_8, CCNL_FINER))
                ccnr_debug_ccnb(h, __LINE__, "prefix_mismatch", NULL,
                                msg, size);
            content = NULL;
        }
    scratch = ccn_charbuf_create();
    for (try = 0; content != NULL; try++) {
        res = ccn_btree_lookup(h->btree,
                               content->flatname->buf,
                               content->flatname->length,
                               &leaf);
        if (CCN_BT_SRCH_FOUND(res) == 0) {
            ccnr_debug_content(h, __LINE__, "impossible", NULL, content);
            content = NULL;
            break;
        }
        ndx = CCN_BT_SRCH_INDEX(res);
        res = ccn_btree_match_interest(leaf, ndx, msg, pi, scratch);
        if (res == -1) {
            ccnr_debug_ccnb(h, __LINE__, "match_error", NULL, msg, size);
            content = NULL;
            break;
        }
        if (res == 1) {
            if ((pi->orderpref & 1) == 0) // XXX - should be symbolic
                break;
            last_match = content->cookie;
            last_match_acc = content->accession;
            content = r_store_next_child_at_level(h, content, comps->n - 1);
        }
        else
            content = r_store_content_next(h, content);
        if (content != NULL &&
            !r_store_content_matches_interest_prefix(h, content, msg, size))
                content = NULL;
    }
    if (last_match != 0) {
        content = r_store_content_from_cookie(h, last_match);
        if (content == NULL)
            content = r_store_content_from_accession(h, last_match_acc);
    }
    ccn_charbuf_destroy(&scratch);
    return(content);
}

/**
 * Find the first content handle that matches the prefix given by the namish,
 * which may be a Name, Interest, ContentObject, ...
 *
 * Does not check the other parts of namish, in particular, does not generate
 * the digest component of a ContentObject.
 */
PUBLIC struct content_entry *
r_store_lookup_ccnb(struct ccnr_handle *h,
                    const unsigned char *namish, size_t size)
{
    struct content_entry *content = NULL;
    struct ccn_charbuf *flatname = NULL;
    int res;
    
    flatname = ccn_charbuf_create();
    if (flatname == NULL)
        goto Bail;
    res = ccn_flatname_from_ccnb(flatname, namish, size);
    if (res < 0)
        goto Bail;
    content = r_store_look(h, flatname->buf, flatname->length);
    if (content != NULL) {
        res = ccn_flatname_charbuf_compare(flatname, content->flatname);
        if (res == 0 || res == -9999) {
            /* prefix matches */
        }
        else
            content = NULL;
    }
Bail:
    ccn_charbuf_destroy(&flatname);
    return(content);
}

/**
 * Mark content as stale
 */
PUBLIC void
r_store_mark_stale(struct ccnr_handle *h, struct content_entry *content)
{
    ccnr_cookie cookie = content->cookie;
    if ((content->flags & CCN_CONTENT_ENTRY_STALE) != 0)
        return;
    if (CCNSHOULDLOG(h, LM_4, CCNL_FINE))
            ccnr_debug_content(h, __LINE__, "stale", NULL, content);
    content->flags |= CCN_CONTENT_ENTRY_STALE;
    h->n_stale++;
    if (cookie < h->min_stale)
        h->min_stale = cookie;
    if (cookie > h->max_stale)
        h->max_stale = cookie;
}

/**
 * Scheduled event that makes content stale when its FreshnessSeconds
 * has expired.
 */
static int
expire_content(struct ccn_schedule *sched,
               void *clienth,
               struct ccn_scheduled_event *ev,
               int flags)
{
    struct ccnr_handle *h = clienth;
    ccnr_cookie cookie = ev->evint;
    struct content_entry *content = NULL;
    if ((flags & CCN_SCHEDULE_CANCEL) != 0)
        return(0);
    content = r_store_content_from_cookie(h, cookie);
    if (content != NULL)
        r_store_mark_stale(h, content);
    return(0);
}

/**
 * Schedules content expiration based on its FreshnessSeconds.
 *
 */
PUBLIC void
r_store_set_content_timer(struct ccnr_handle *h, struct content_entry *content,
                  struct ccn_parsed_ContentObject *pco)
{
    int seconds = 0;
    int microseconds = 0;
    size_t start = pco->offset[CCN_PCO_B_FreshnessSeconds];
    size_t stop  = pco->offset[CCN_PCO_E_FreshnessSeconds];
    const unsigned char *content_msg = NULL;
    if (start == stop)
        return;
    content_msg = r_store_content_base(h, content);
    seconds = ccn_fetch_tagged_nonNegativeInteger(
                CCN_DTAG_FreshnessSeconds,
                content_msg,
                start, stop);
    if (seconds <= 0)
        return;
    if (seconds > ((1U<<31) / 1000000)) {
        ccnr_debug_content(h, __LINE__, "FreshnessSeconds_too_large", NULL,
                           content);
        return;
    }
    microseconds = seconds * 1000000;
    ccn_schedule_event(h->sched, microseconds,
                       &expire_content, NULL, content->cookie);
}
Esempio n. 28
0
int
ccnr_init_repo_keystore(struct ccnr_handle *ccnr, struct ccn *h)
{
    struct ccn_charbuf *temp = NULL;
    struct ccn_charbuf *culprit = NULL;
    struct stat statbuf;
    int res = -1;
    char *keystore_path = NULL;
    struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT;
    
    temp = ccn_charbuf_create();
    culprit = temp;
    ccn_charbuf_putf(temp, "%s/", ccnr->directory);
    res = stat(ccn_charbuf_as_string(temp), &statbuf);
    if (res == -1)
        goto Finish;
    if ((statbuf.st_mode & S_IFDIR) == 0) {
        res = -1;
        errno = ENOTDIR;
        goto Finish;
    }
    ccn_charbuf_putf(temp, "ccnx_repository_keystore");
    keystore_path = strdup(ccn_charbuf_as_string(temp));
    res = stat(keystore_path, &statbuf);
    
    if (res == 0 && h != NULL)
        res = ccn_load_default_key(h, keystore_path, CCNR_KEYSTORE_PASS);
    if (res >= 0) {
        culprit = NULL;
        goto Finish;
    }
    /* No stored keystore that we can access. Create one if we can.*/
    res = ccn_keystore_file_init(keystore_path, CCNR_KEYSTORE_PASS, "Repository", 0, 0);
    if (res != 0) {
        res = -1;
        goto Finish;
    }
    if (CCNSHOULDLOG(ccnr, keystore, CCNL_WARNING))
        ccnr_msg(ccnr, "New repository private key saved in %s", keystore_path);
    if (h != NULL)
        res = ccn_load_default_key(h, keystore_path, CCNR_KEYSTORE_PASS);
Finish:
    if (res >= 0 && h != NULL)
        res = ccn_chk_signing_params(h, NULL, &sp, NULL, NULL, NULL, NULL);
    if (res >= 0 && h != NULL) {
        memcpy(ccnr->ccnr_id, sp.pubid, sizeof(ccnr->ccnr_id));
        if (ccnr->ccnr_keyid == NULL)
            ccnr->ccnr_keyid = ccn_charbuf_create();
        else
            ccnr->ccnr_keyid->length = 0;
        ccn_charbuf_append_value(ccnr->ccnr_keyid, CCN_MARKER_CONTROL, 1);
        ccn_charbuf_append_string(ccnr->ccnr_keyid, ".M.K");
        ccn_charbuf_append_value(ccnr->ccnr_keyid, 0, 1);
        ccn_charbuf_append(ccnr->ccnr_keyid, ccnr->ccnr_id, sizeof(ccnr->ccnr_id));
    }
    if (res < 0) {
        ccnr->running = -1; /* Make note of init failure */
        if (culprit != NULL)
            ccnr_msg(ccnr, "Error accessing keystore - %s: %s\n",
                     strerror(errno), ccn_charbuf_as_string(temp));
    }
    ccn_charbuf_destroy(&temp);
    if (keystore_path != NULL)
        free(keystore_path);
    return(res);
}
Esempio n. 29
0
/**
 * Common interest handler
 */
PUBLIC enum ccn_upcall_res
ccnr_answer_req(struct ccn_closure *selfp,
                 enum ccn_upcall_kind kind,
                 struct ccn_upcall_info *info)
{
    struct ccn_charbuf *msg = NULL;
    struct ccn_charbuf *name = NULL;
    struct ccn_charbuf *keylocator = NULL;
    struct ccn_charbuf *signed_info = NULL;
    struct ccn_charbuf *reply_body = NULL;
    struct ccnr_handle *ccnr = NULL;
    int res = 0;
    int morecomps = 0;
    const unsigned char *final_comp = NULL;
    size_t final_size = 0;
    
    switch (kind) {
        case CCN_UPCALL_FINAL:
            free(selfp);
            return(CCN_UPCALL_RESULT_OK);
        case CCN_UPCALL_INTEREST:
            break;
        case CCN_UPCALL_CONSUMED_INTEREST:
            return(CCN_UPCALL_RESULT_OK);
        default:
            return(CCN_UPCALL_RESULT_ERR);
    }
    ccnr = (struct ccnr_handle *)selfp->data;
    if (CCNSHOULDLOG(ccnr, LM_128, CCNL_FINE))
        ccnr_debug_ccnb(ccnr, __LINE__, "ccnr_answer_req", NULL,
                        info->interest_ccnb, info->pi->offset[CCN_PI_E]);
    morecomps = selfp->intdata & MORECOMPS_MASK;
    if ((info->pi->answerfrom & CCN_AOK_NEW) == 0 &&
        selfp->intdata != OP_SERVICE)
        return(CCN_UPCALL_RESULT_OK);
    if (info->matched_comps >= info->interest_comps->n)
        goto Bail;
    if ((selfp->intdata & OPER_MASK) != OP_SERVICE &&
        info->pi->prefix_comps != info->matched_comps + morecomps)
        goto Bail;
    if (morecomps == 1) {
        res = ccn_name_comp_get(info->interest_ccnb, info->interest_comps,
                                info->matched_comps,
                                &final_comp, &final_size);
        if (res < 0)
            goto Bail;
    }
    if ((selfp->intdata & MUST_VERIFY) != 0) {
        struct ccn_parsed_ContentObject pco = {0};
        // XXX - probably should check for message origin BEFORE verify
        res = ccn_parse_ContentObject(final_comp, final_size, &pco, NULL);
        if (res < 0) {
            ccnr_debug_ccnb(ccnr, __LINE__, "co_parse_failed", NULL,
                            info->interest_ccnb, info->pi->offset[CCN_PI_E]);
            goto Bail;
        }
        res = ccn_verify_content(info->h, final_comp, &pco);
        if (res != 0) {
            ccnr_debug_ccnb(ccnr, __LINE__, "co_verify_failed", NULL,
                            info->interest_ccnb, info->pi->offset[CCN_PI_E]);
            goto Bail;
        }
    }
    switch (selfp->intdata & OPER_MASK) {
        case OP_SERVICE:
            if (ccnr->service_ccnb == NULL)
                ccnr->service_ccnb = ccnr_init_service_ccnb(ccnr, info->h, CCNRID_LOCAL_URI, 600);
            if (ccn_content_matches_interest(
                    ccnr->service_ccnb->buf,
                    ccnr->service_ccnb->length,
                    1,
                    NULL,
                    info->interest_ccnb,
                    info->pi->offset[CCN_PI_E],
                    info->pi
                )) {
                ccn_put(info->h, ccnr->service_ccnb->buf,
                                 ccnr->service_ccnb->length);
                res = CCN_UPCALL_RESULT_INTEREST_CONSUMED;
                goto Finish;
            }
            // XXX this needs refactoring.
            if (ccnr->neighbor_ccnb == NULL)
                ccnr->neighbor_ccnb = ccnr_init_service_ccnb(ccnr, info->h, CCNRID_NEIGHBOR_URI, 5);
            if (ccn_content_matches_interest(
                    ccnr->neighbor_ccnb->buf,
                    ccnr->neighbor_ccnb->length,
                    1,
                    NULL,
                    info->interest_ccnb,
                    info->pi->offset[CCN_PI_E],
                    info->pi
                )) {
                ccn_put(info->h, ccnr->neighbor_ccnb->buf,
                                 ccnr->neighbor_ccnb->length);
                res = CCN_UPCALL_RESULT_INTEREST_CONSUMED;
                goto Finish;
            }
            if (ccn_content_matches_interest(
                                             ccnr->policy_link_cob->buf,
                                             ccnr->policy_link_cob->length,
                                             1,
                                             NULL,
                                             info->interest_ccnb,
                                             info->pi->offset[CCN_PI_E],
                                             info->pi
                                             )) {
                ccn_put(info->h, ccnr->policy_link_cob->buf,
                        ccnr->policy_link_cob->length);
                res = CCN_UPCALL_RESULT_INTEREST_CONSUMED;
                goto Finish;
            }
            goto Bail;
            break;
        default:
            // No other OP_xxx are supported here
            goto Bail;
    }
Bail:
    res = CCN_UPCALL_RESULT_ERR;
Finish:
    ccn_charbuf_destroy(&msg);
    ccn_charbuf_destroy(&name);
    ccn_charbuf_destroy(&keylocator);
    ccn_charbuf_destroy(&reply_body);
    ccn_charbuf_destroy(&signed_info);
    return(res);
}
Esempio n. 30
0
static int
content_sender(struct ccn_schedule *sched,
    void *clienth,
    struct ccn_scheduled_event *ev,
    int flags)
{
    int i, j;
    int delay;
    int nsec;
    int burst_nsec;
    int burst_max;
    struct ccnr_handle *h = clienth;
    struct content_entry *content = NULL;
    unsigned filedesc = ev->evint;
    struct fdholder *fdholder = NULL;
    struct content_queue *q = ev->evdata;
    (void)sched;
    
    if ((flags & CCN_SCHEDULE_CANCEL) != 0)
        goto Bail;
    fdholder = r_io_fdholder_from_fd(h, filedesc);
    if (fdholder == NULL)
        goto Bail;
    if (q->send_queue == NULL)
        goto Bail;
    if ((fdholder->flags & CCNR_FACE_NOSEND) != 0)
        goto Bail;
    /* Send the content at the head of the queue */
    if (q->ready > q->send_queue->n ||
        (q->ready == 0 && q->nrun >= 12 && q->nrun < 120))
        q->ready = q->send_queue->n;
    nsec = 0;
    burst_nsec = q->burst_nsec;
    burst_max = 2;
    if (q->ready < burst_max)
        burst_max = q->ready;
    if (burst_max == 0)
        q->nrun = 0;
    for (i = 0; i < burst_max && nsec < 1000000; i++) {
        content = r_store_content_from_cookie(h, q->send_queue->buf[i]);
        if (content == NULL)
            q->nrun = 0;
        else {
            r_link_send_content(h, fdholder, content);
            /* fdholder may have vanished, bail out if it did */
            if (r_io_fdholder_from_fd(h, filedesc) == NULL)
                goto Bail;
            // nsec += burst_nsec * (unsigned)((content->size + 1023) / 1024);
            q->nrun++;
        }
    }
    if (q->ready < i) abort();
    q->ready -= i;
    /* Update queue */
    for (j = 0; i < q->send_queue->n; i++, j++)
        q->send_queue->buf[j] = q->send_queue->buf[i];
    q->send_queue->n = j;
    /* Do a poll before going on to allow others to preempt send. */
    delay = (nsec + 499) / 1000 + 1;
    if (q->ready > 0) {
        return(delay);
    }
    q->ready = j;
    if (q->nrun >= 12 && q->nrun < 120) {
        /* We seem to be a preferred provider, forgo the randomized delay */
        if (j == 0)
            delay += burst_nsec / 50;
        return(delay);
    }
    /* Determine when to run again */
    for (i = 0; i < q->send_queue->n; i++) {
        content = r_store_content_from_cookie(h, q->send_queue->buf[i]);
        if (content != NULL) {
            q->nrun = 0;
            delay = randomize_content_delay(h, q);
            if (CCNSHOULDLOG(h, LM_8, CCNL_FINER))
                ccnr_msg(h, "fdholder %u queued %u delay %i",
                         (unsigned)ev->evint, q->ready, delay);
            return(delay);
        }
    }
    q->send_queue->n = q->ready = 0;
Bail:
    q->sender = NULL;
    return(0);
}