Beispiel #1
0
/**
 * Read the contents of the repository config file
 *
 * Calls r_init_fail and returns NULL in case of error.
 * @returns unparsed content of config file in a newly allocated charbuf
 */
struct ndn_charbuf *
r_init_read_config(struct ndnr_handle *h)
{
    struct ndn_charbuf *path = NULL;
    struct ndn_charbuf *contents = NULL;
    size_t sz = 800;
    ssize_t sres = -1;
    int fd;
    
    h->directory = getenv("NDNR_DIRECTORY");
    if (h->directory == NULL || h->directory[0] == 0)
        h->directory = ".";
    path = ndn_charbuf_create();
    contents = ndn_charbuf_create();
    if (path == NULL || contents == NULL)
        return(NULL);
    ndn_charbuf_putf(path, "%s/config", h->directory);
    fd = open(ndn_charbuf_as_string(path), O_RDONLY);
    if (fd == -1) {
        if (errno == ENOENT)
            sres = 0;
        else
            r_init_fail(h, __LINE__, ndn_charbuf_as_string(path), errno);
    }
    else {
        for (;;) {
            sres = read(fd, ndn_charbuf_reserve(contents, sz), sz);
            if (sres == 0)
                break;
            if (sres < 0) {
                r_init_fail(h, __LINE__, "Read failed reading config", errno);
                break;
            }
            contents->length += sres;
            if (contents->length > 999999) {
                r_init_fail(h, __LINE__, "config file too large", 0);
                sres = -1;
                break;
            }
        }
        close(fd);
    }
    ndn_charbuf_destroy(&path);
    if (sres < 0)
        ndn_charbuf_destroy(&contents);
    return(contents);
}
Beispiel #2
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);
}
Beispiel #3
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);
Beispiel #4
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);
}