示例#1
0
void CcnbMsg_setupEncap(CcnbMsg self, size_t size) {
	ccn_charbuf_reset(self);
	ccn_charbuf_reserve(self, size);
	self->length = size;
	memcpy(self->buf, CCN_EMPTY_PDU, CCN_EMPTY_PDU_LENGTH - 1);
	self->buf[self->length - 1] = CCN_EMPTY_PDU[CCN_EMPTY_PDU_LENGTH - 1];
}
示例#2
0
/**
 * Append a binary timestamp
 * as a BLOB using the ccn binary Timestamp representation (12-bit fraction).
 * @param c is the buffer to append to.
 * @param marker
 *   If marker >= 0, the low-order byte is used as a marker byte, useful for
 *   some content naming conventions (versioning, in particular).
 * @param secs - seconds since epoch
 * @param nsecs - nanoseconds
 * @returns 0 for success or -1 for error.
 */
int
ccnb_append_timestamp_blob(struct ccn_charbuf *c,
                           enum ccn_marker marker,
                           intmax_t secs, int nsecs)
{
    int i;
    int n;
    intmax_t ts;
    unsigned char *p;
    if (secs <= 0 || nsecs < 0 || nsecs > 999999999)
        return(-1);
    n = 2;
    for (ts = secs >> 4; n < 7 && ts != 0; ts >>= 8)
        n++;
    ccn_charbuf_append_tt(c, n + (marker >= 0), CCN_BLOB);
    if (marker >= 0)
        ccn_charbuf_append_value(c, marker, 1);
    p = ccn_charbuf_reserve(c, n);
    if (p == NULL)
        return(-1);
    ts = secs >> 4;
    for (i = 0; i < n - 2; i++)
        p[i] = ts >> (8 * (n - 3 - i));
    /* arithmetic contortions are to avoid overflowing 31 bits */
    ts = ((secs & 15) << 12) + ((nsecs / 5 * 8 + 195312) / 390625);
    for (i = n - 2; i < n; i++)
        p[i] = ts >> (8 * (n - 1 - i));
    c->length += n;
    return(0);
}
示例#3
0
/**
 * Append a tagged UDATA string, with printf-style formatting
 *
 * This is a ccnb-encoded element with containing UDATA as content.
 * @param c is the buffer to append to.
 * @param dtag is the element's dtab.
 * @param fmt is a printf-style format string, followed by its values
 * @returns 0 for success or -1 for error.
 */
int
ccnb_tagged_putf(struct ccn_charbuf *c,
                 enum ccn_dtag dtag, const char *fmt, ...)
{
    int res;
    int size;
    va_list ap;
    char *ptr;
    
    res = ccn_charbuf_append_tt(c, dtag, CCN_DTAG);
    if (res < 0)
        return(-1);
    ptr = (char *)ccn_charbuf_reserve(c, strlen(fmt) + 20);
    if (ptr == NULL)
        return(-1);
    va_start(ap, fmt);
    size = vsnprintf(ptr + 2, (c->limit - c->length - 2), fmt, ap);
    va_end(ap);
    if (size < 0)
        return(-1);
    if (size > 0) {
        if (size >= (c->limit - c->length - 2))
            ptr = NULL;
        res |= ccn_charbuf_append_tt(c, size, CCN_UDATA);
        if (ptr == (char *)c->buf + c->length + 2)
            c->length += size;
        else if (ptr == (char *)c->buf + c->length + 1) {
            memmove(ptr - 1, ptr, size);
            c->length += size;
        }
        else {
            ptr = (char *)ccn_charbuf_reserve(c, size + 1);
            va_start(ap, fmt);
            size = vsnprintf(ptr, size + 1, fmt, ap);
            va_end(ap);
            if (size < 0)
                return(-1);
            c->length += size;
        }
    }
    res |= ccn_charbuf_append_closer(c);
    return(res == 0 ? 0 : -1);    
}
示例#4
0
文件: CcnClient.c 项目: ltr120/NDNFD
void CcnbMsg_setupEncap(CcnbMsg self, size_t size) {
#ifdef NDNFD
	assert(false);
#endif
	ccn_charbuf_reset(self);
	ccn_charbuf_reserve(self, size);
	self->length = size;
	memcpy(self->buf, CCN_EMPTY_PDU, CCN_EMPTY_PDU_LENGTH - 1);
	self->buf[self->length - 1] = CCN_EMPTY_PDU[CCN_EMPTY_PDU_LENGTH - 1];
}
示例#5
0
文件: CcnClient.c 项目: ltr120/NDNFD
CcnbMsg CcnbMsg_ctor(size_t size) {
	CcnbMsg self = (CcnbMsg)ccn_charbuf_create();
#ifdef NDNFD
	ccn_charbuf_reserve(self, size);
	self->length = size;
#else
	CcnbMsg_setupEncap(self, size + CCN_EMPTY_PDU_LENGTH);
#endif
	return self;
}
示例#6
0
文件: CcnClient.c 项目: ltr120/NDNFD
void CcnbMsg_resize(CcnbMsg self, size_t size) {
#ifdef NDNFD
	if (size > self->length) {
		ccn_charbuf_reserve(self, size - self->length);
	}
	self->length = size;
#else
	size_t oldsize = self->length + CCN_EMPTY_PDU_LENGTH;
	if (size == oldsize) return;
	CcnbMsg_setupEncap(self, size + CCN_EMPTY_PDU_LENGTH);
#endif
}
示例#7
0
static void
append_bloom_element(struct ccn_charbuf *templ,
                     enum ccn_dtag dtag, struct ccn_bloom *b)
{
        int i;
        ccn_charbuf_append_tt(templ, dtag, CCN_DTAG);
        i = ccn_bloom_wiresize(b);
        ccn_charbuf_append_tt(templ, i, CCN_BLOB);
        ccn_bloom_store_wire(b, ccn_charbuf_reserve(templ, i), i);
        templ->length += i;
        ccn_charbuf_append_closer(templ);
}
示例#8
0
/*
 * Encode the number in big-endian binary, using one more than the
 * minimum number of bytes (that is, the first byte is always zero).
 */
void
ccn_binary_seqfunc(uintmax_t x, void *param, struct ccn_charbuf *resultbuf)
{
    uintmax_t m;
    int n;
    unsigned char *b;
    (void)param; /* unused */
    for (n = 0, m = 0; x < m; n++)
        m = (m << 8) | 0xff;
    b = ccn_charbuf_reserve(resultbuf, n + 1);
    resultbuf->length = n + 1;
    for (; n >= 0; n--, x >>= 8)
        b[n] = x & 0xff;
}
示例#9
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 ccn_charbuf *
r_init_read_config(struct ccnr_handle *h)
{
    struct ccn_charbuf *path = NULL;
    struct ccn_charbuf *contents = NULL;
    size_t sz = 800;
    ssize_t sres = -1;
    int fd;
    
    h->directory = getenv("CCNR_DIRECTORY");
    if (h->directory == NULL || h->directory[0] == 0)
        h->directory = ".";
    path = ccn_charbuf_create();
    contents = ccn_charbuf_create();
    if (path == NULL || contents == NULL)
        return(NULL);
    ccn_charbuf_putf(path, "%s/config", h->directory);
    fd = open(ccn_charbuf_as_string(path), O_RDONLY);
    if (fd == -1) {
        if (errno == ENOENT)
            sres = 0;
        else
            r_init_fail(h, __LINE__, ccn_charbuf_as_string(path), errno);
    }
    else {
        for (;;) {
            sres = read(fd, ccn_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);
    }
    ccn_charbuf_destroy(&path);
    if (sres < 0)
        ccn_charbuf_destroy(&contents);
    return(contents);
}
示例#10
0
文件: ccnr_store.c 项目: Emat12/ccnx
/**
 * 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);
}
示例#11
0
int
ccn_append_pubkey_blob(struct ccn_charbuf *c, const struct ccn_pkey *i_pubkey)
{
    int res;
    size_t bytes;
    unsigned char *p = NULL;
    res = i2d_PUBKEY((EVP_PKEY *)i_pubkey, NULL);
    if (res < 0)
        return(-1);
    bytes = res;
    res = ccn_charbuf_append_tt(c, bytes, CCN_BLOB);
    if (res < 0)
        return(-1);
    p = ccn_charbuf_reserve(c, bytes);
    if (p == NULL)
        return(-1);
    res = i2d_PUBKEY((EVP_PKEY *)i_pubkey, &p);
    if (res != (int)bytes)
        return(-1);
    c->length += bytes;
    return(bytes);
}
示例#12
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);
}
示例#13
0
int
main(int argc, char **argv)
{
    const char *progname = argv[0];
    struct ccn *ccn = NULL;
    struct ccn_charbuf *name = NULL;
    struct ccn_charbuf *pname = NULL;
    struct ccn_charbuf *temp = NULL;
    struct ccn_charbuf *extopt = NULL;
    long expire = -1;
    int versioned = 0;
    size_t blocksize = 8*1024;
    int status = 0;
    int res;
    ssize_t read_res;
    unsigned char *buf = NULL;
    enum ccn_content_type content_type = CCN_CONTENT_DATA;
    struct ccn_closure in_interest = {.p=&incoming_interest};
    const char *postver = NULL;
    const char *key_uri = NULL;
    int force = 0;
    int verbose = 0;
    int timeout = -1;
    int setfinal = 0;
    int prefixcomps = -1;
    int fd;
    struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT;
    
    while ((res = getopt(argc, argv, "e:fhk:lvV:p:t:w:x:")) != -1) {
        switch (res) {
            case 'e':
                if (extopt == NULL)
                    extopt = ccn_charbuf_create();
                fd = open(optarg, O_RDONLY);
                if (fd < 0) {
                    perror(optarg);
                    exit(1);
                }
                for (;;) {
                    read_res = read(fd, ccn_charbuf_reserve(extopt, 64), 64);
                    if (read_res <= 0)
                        break;
                    extopt->length += read_res;
                }
                if (read_res < 0)
                    perror(optarg);
                close(fd);
                break;
            case 'f':
                force = 1;
                break;
            case 'l':
                setfinal = 1; // set FinalBlockID to last comp of name
                break;
            case 'k':
                key_uri = optarg;
                break;
            case 'p':
                prefixcomps = atoi(optarg);
                if (prefixcomps < 0)
                    usage(progname);
                break;
            case 'x':
                expire = atol(optarg);
                if (expire <= 0)
                    usage(progname);
                break;
            case 'v':
                verbose = 1;
                break;
            case 'V':
                versioned = 1;
                postver = optarg;
                if (0 == memcmp(postver, "%00", 3))
                    setfinal = 1;
                break;
            case 'w':
                timeout = atol(optarg);
                if (timeout <= 0)
                    usage(progname);
                timeout *= 1000;
                break;
            case 't':
                if (0 == strcasecmp(optarg, "DATA")) {
                    content_type = CCN_CONTENT_DATA;
                    break;
                }
                if (0 == strcasecmp(optarg, "ENCR")) {
                    content_type = CCN_CONTENT_ENCR;
                    break;
                }
                if (0 == strcasecmp(optarg, "GONE")) {
                    content_type = CCN_CONTENT_GONE;
                    break;
                }
                if (0 == strcasecmp(optarg, "KEY")) {
                    content_type = CCN_CONTENT_KEY;
                    break;
                }
                if (0 == strcasecmp(optarg, "LINK")) {
                    content_type = CCN_CONTENT_LINK;
                    break;
                }
                if (0 == strcasecmp(optarg, "NACK")) {
                    content_type = CCN_CONTENT_NACK;
                    break;
                }
                content_type = atoi(optarg);
                if (content_type > 0 && content_type <= 0xffffff)
                    break;
                fprintf(stderr, "Unknown content type %s\n", optarg);
                /* FALLTHRU */
            default:
            case 'h':
                usage(progname);
                break;
        }
    }
    argc -= optind;
    argv += optind;
    if (argv[0] == NULL)
        usage(progname);
    name = ccn_charbuf_create();
    res = ccn_name_from_uri(name, argv[0]);
    if (res < 0) {
        fprintf(stderr, "%s: bad ccn URI: %s\n", progname, argv[0]);
        exit(1);
    }
    if (argv[1] != NULL)
        fprintf(stderr, "%s warning: extra arguments ignored\n", progname);
    
    /* Preserve the original prefix, in case we add versioning,
     * but trim it down if requested for the interest filter registration
     */
    pname = ccn_charbuf_create();
    ccn_charbuf_append(pname, name->buf, name->length);
    if (prefixcomps >= 0) {
        res = ccn_name_chop(pname, NULL, prefixcomps);
        if (res < 0) {
            fprintf(stderr, "%s: unable to trim name to %d component%s.\n",
                    progname, prefixcomps, prefixcomps == 1 ? "" : "s");
            exit(1);
        }
    }
    /* Connect to ccnd */
    ccn = ccn_create();
    if (ccn_connect(ccn, NULL) == -1) {
        perror("Could not connect to ccnd");
        exit(1);
    }

    /* Read the actual user data from standard input */
    buf = calloc(1, blocksize);
    read_res = read_full(0, buf, blocksize);
    if (read_res < 0) {
        perror("read");
        read_res = 0;
        status = 1;
    }
        
    /* Tack on the version component if requested */
    if (versioned) {
        res = ccn_create_version(ccn, name, CCN_V_REPLACE | CCN_V_NOW | CCN_V_HIGH, 0, 0);
        if (res < 0) {
            fprintf(stderr, "%s: ccn_create_version() failed\n", progname);
            exit(1);
        }
        if (postver != NULL) {
            res = ccn_name_from_uri(name, postver);
            if (res < 0) {
                fprintf(stderr, "-V %s: invalid name suffix\n", postver);
                exit(0);
            }
        }
    }
    temp = ccn_charbuf_create();
    
    /* Ask for a FinalBlockID if appropriate. */
    if (setfinal)
        sp.sp_flags |= CCN_SP_FINAL_BLOCK;
    
    if (res < 0) {
        fprintf(stderr, "Failed to create signed_info (res == %d)\n", res);
        exit(1);
    }
    
    /* Set content type */
    sp.type = content_type;
    
    /* Set freshness */
    if (expire >= 0) {
        if (sp.template_ccnb == NULL) {
            sp.template_ccnb = ccn_charbuf_create();
            ccn_charbuf_append_tt(sp.template_ccnb, CCN_DTAG_SignedInfo, CCN_DTAG);
        }
        else if (sp.template_ccnb->length > 0) {
            sp.template_ccnb->length--;
        }
        ccnb_tagged_putf(sp.template_ccnb, CCN_DTAG_FreshnessSeconds, "%ld", expire);
        sp.sp_flags |= CCN_SP_TEMPL_FRESHNESS;
        ccn_charbuf_append_closer(sp.template_ccnb);
    }
    
    /* Set key locator, if supplied */
    if (key_uri != NULL) {
        struct ccn_charbuf *c = ccn_charbuf_create();
        res = ccn_name_from_uri(c, key_uri);
        if (res < 0) {
            fprintf(stderr, "%s is not a valid ccnx URI\n", key_uri);
            exit(1);
        }
        if (sp.template_ccnb == NULL) {
            sp.template_ccnb = ccn_charbuf_create();
            ccn_charbuf_append_tt(sp.template_ccnb, CCN_DTAG_SignedInfo, CCN_DTAG);
        }
        else if (sp.template_ccnb->length > 0) {
            sp.template_ccnb->length--;
        }
        ccn_charbuf_append_tt(sp.template_ccnb, CCN_DTAG_KeyLocator, CCN_DTAG);
        ccn_charbuf_append_tt(sp.template_ccnb, CCN_DTAG_KeyName, CCN_DTAG);
        ccn_charbuf_append(sp.template_ccnb, c->buf, c->length);
        ccn_charbuf_append_closer(sp.template_ccnb);
        ccn_charbuf_append_closer(sp.template_ccnb);
        sp.sp_flags |= CCN_SP_TEMPL_KEY_LOCATOR;
        ccn_charbuf_append_closer(sp.template_ccnb);
        ccn_charbuf_destroy(&c);
    }

    if (extopt != NULL && extopt->length > 0) {
        if (sp.template_ccnb == NULL) {
            sp.template_ccnb = ccn_charbuf_create();
            ccn_charbuf_append_tt(sp.template_ccnb, CCN_DTAG_SignedInfo, CCN_DTAG);
        }
        else if (sp.template_ccnb->length > 0) {
            sp.template_ccnb->length--;
        }
        ccnb_append_tagged_blob(sp.template_ccnb, CCN_DTAG_ExtOpt,
                                extopt->buf, extopt->length);
        sp.sp_flags |= CCN_SP_TEMPL_EXT_OPT;
        ccn_charbuf_append_closer(sp.template_ccnb);
    }
    
    /* Create the signed content object, ready to go */
    temp->length = 0;
    res = ccn_sign_content(ccn, temp, name, &sp, buf, read_res);
    if (res != 0) {
        fprintf(stderr, "Failed to encode ContentObject (res == %d)\n", res);
        exit(1);
    }
    if (read_res == blocksize) {
        read_res = read_full(0, buf, 1);
        if (read_res == 1) {
            fprintf(stderr, "%s: warning - truncated data\n", argv[0]);
            status = 1;
        }
    }
    free(buf);
    buf = NULL;
    if (force) {
        /* At user request, send without waiting to see an interest */
        res = ccn_put(ccn, temp->buf, temp->length);
        if (res < 0) {
            fprintf(stderr, "ccn_put failed (res == %d)\n", res);
            exit(1);
        }
    }
    else {
        in_interest.data = temp;
        /* Set up a handler for interests */
        res = ccn_set_interest_filter(ccn, pname, &in_interest);
        if (res < 0) {
            fprintf(stderr, "Failed to register interest (res == %d)\n", res);
            exit(1);
        }
        res = ccn_run(ccn, timeout);
        if (in_interest.intdata == 0) {
            if (verbose)
                fprintf(stderr, "Nobody's interested\n");
            exit(1);
        }
    }
    
    if (verbose) {
        struct ccn_charbuf *uri = ccn_charbuf_create();
        uri->length = 0;
        ccn_uri_append(uri, name->buf, name->length, 1);
        printf("wrote %s\n", ccn_charbuf_as_string(uri));
        ccn_charbuf_destroy(&uri);
    }
    ccn_destroy(&ccn);
    ccn_charbuf_destroy(&name);
    ccn_charbuf_destroy(&pname);
    ccn_charbuf_destroy(&temp);
    ccn_charbuf_destroy(&sp.template_ccnb);
    ccn_charbuf_destroy(&extopt);
    exit(status);
}
示例#14
0
文件: ccnr_store.c 项目: Emat12/ccnx
static const unsigned char *
r_store_content_read(struct ccnr_handle *h, struct content_entry *content)
{
    unsigned repofile;
    off_t offset;
    struct ccn_charbuf *cob = NULL;
    ssize_t rres = 0;
    int fd = -1;
    unsigned char buf[8800];
    struct ccn_skeleton_decoder decoder = {0};
    struct ccn_skeleton_decoder *d = &decoder;
    ssize_t dres;
    
    repofile = r_store_repofile_from_accession(h, content->accession);
    offset = r_store_offset_from_accession(h, content->accession);
    if (repofile != 1)
        goto Bail;
    if (content->cob != NULL)
        goto Bail;
    fd = r_io_repo_data_file_fd(h, repofile, 0);
    if (fd == -1)
        goto Bail;
    cob = ccn_charbuf_create();
    if (cob == NULL)
        goto Bail;
    if (content->size > 0) {
        if (ccn_charbuf_reserve(cob, content->size) == NULL)
            goto Bail;
        rres = pread(fd, cob->buf, content->size, offset);
        if (rres == content->size) {
            cob->length = content->size;
            content->cob = cob;
            h->cob_count++;
            return(cob->buf);
        }
        if (rres == -1)
            ccnr_msg(h, "r_store_content_read %u :%s (errno = %d)",
                     fd, strerror(errno), errno);
        else
            ccnr_msg(h, "r_store_content_read %u expected %d bytes, but got %d",
                     fd, (int)content->size, (int)rres);
    } else {
        rres = pread(fd, buf, 8800, offset); // XXX - should be symbolic
        if (rres == -1) {
            ccnr_msg(h, "r_store_content_read %u :%s (errno = %d)",
                     fd, strerror(errno), errno);
            goto Bail;
        }
        dres = ccn_skeleton_decode(d, buf, rres);
        if (d->state != 0) {
            ccnr_msg(h, "r_store_content_read %u : error parsing cob", fd);
            goto Bail;
        }
        content->size = dres;
        if (ccn_charbuf_append(cob, buf, dres) < 0)
            goto Bail;
        content->cob = cob;
        h->cob_count++;
        return(cob->buf);        
    }
Bail:
    ccn_charbuf_destroy(&cob);
    return(NULL);
}
示例#15
0
int
main(int argc, char *argv[])
{
    struct ccn_charbuf *buffer;
    struct ccn_charbuf *signed_info = ccn_charbuf_create();
    struct ccn_skeleton_decoder dd = {0};
    ssize_t res;
    char *outname = NULL;
    int result = 0;
    char * contents[] = {"INVITE sip:[email protected] SIP/2.0\nVia: SIP/2.0/UDP 127.0.0.1:5060;rport;branch=z9hG4bK519044721\nFrom: <sip:[email protected]>;tag=2105643453\nTo: Test User <sip:[email protected]>\nCall-ID: [email protected]\nCSeq: 20 INVITE\nContact: <sip:[email protected]:5060>\nMax-Forwards: 70\nUser-Agent: Linphone-1.7.1/eXosip\nSubject: Phone call\nExpires: 120\nAllow: INVITE, ACK, CANCEL, BYE, OPTIONS, REFER, SUBSCRIBE, NOTIFY, MESSAGE\nContent-Type: application/sdp\nContent-Length:   448\n\nv=0\no=jthornto 123456 654321 IN IP4 127.0.0.1\ns=A conversation\nc=IN IP4 127.0.0.1\nt=0 0\nm=audio 7078 RTP/AVP 111 110 0 3 8 101\na=rtpmap:111 speex/16000/1\na=rtpmap:110 speex/8000/1\na=rtpmap:0 PCMU/8000/1\na=rtpmap:3 GSM/8000/1\na=rtpmap:8 PCMA/8000/1\na=rtpmap:101 telephone-event/8000\na=fmtp:101 0-11\nm=video 9078 RTP/AVP 97 98 99\na=rtpmap:97 theora/90000\na=rtpmap:98 H263-1998/90000\na=fmtp:98 CIF=1;QCIF=1\na=rtpmap:99 MP4V-ES/90000\n",
 
			 "Quaer #%2d zjduer  badone",
                         "",
                         NULL};
    char * paths[] = { "/sip/protocol/parc.com/domain/foo/principal/invite/verb/[email protected]/id", 
		       "/d/e/f",
                       "/zero/length/content",
                       NULL};
    struct path * cur_path = NULL;
    struct ccn_keystore *keystore = ccn_keystore_create();
    struct ccn_keystore *aes_keystore = ccn_aes_keystore_create();
    char *keystore_name = NULL;
    char *keystore_password = NULL;
    char *aes_keystore_name = NULL;
    unsigned char keybuf[32];

    int i;

    while ((i = getopt(argc, argv, "a:k:p:o:")) != -1) {
        switch (i) {
	    case 'a':
                aes_keystore_name = optarg;
                break;
            case 'k':
                keystore_name = optarg;
                break;
            case 'p':
                keystore_password = optarg;
                break;
            case 'o':
                outname = optarg;
                break;
            default:
                printf("Usage: %s [-k <keystore>] [-o <outfilename>]\n", argv[0]);
                exit(1);
        }
    }

    if (keystore_name == NULL)
        keystore_name = "test.keystore";

    if (aes_keystore_name == NULL)
        aes_keystore_name = "test.aeskeystore";

    if (keystore_password == NULL)
        keystore_password = "******";

    res = ccn_keystore_init(keystore, keystore_name, keystore_password);
    if (res != 0) {
        printf ("Initializing keystore in %s\n", keystore_name);
        res = ccn_keystore_file_init(keystore_name, keystore_password,
                                     "ccnxuser", 0, 3650);
        if (res != 0) {
            fprintf (stderr, "Cannot create keystore [%s]", keystore_name);
            return res;
        }
        res = ccn_keystore_init(keystore, keystore_name, keystore_password);
        if (res != 0) {
            printf("Failed to initialize keystore\n");
            exit(1);
        }
    }

    res = ccn_aes_keystore_init(aes_keystore, aes_keystore_name, keystore_password);
    if (res != 0) {
        printf ("Initializing AES keystore in %s\n", aes_keystore_name);
        ccn_generate_symmetric_key(keybuf, 256);
        res = ccn_aes_keystore_file_init(aes_keystore_name, keystore_password, keybuf, 256);
        if (res != 0) {
            fprintf (stderr, "Cannot create keystore [%s]", keystore_name);
            return res;
        }
        res = ccn_aes_keystore_init(aes_keystore, aes_keystore_name, keystore_password);
        if (res != 0) {
            printf("Failed to initialize keystore\n");
            exit(1);
        }
    }

    printf("Creating signed_info\n");
    res = ccn_signed_info_create(signed_info,
                                 /*pubkeyid*/ccn_keystore_key_digest(keystore),
                                 /*publisher_key_id_size*/ccn_keystore_key_digest_length(keystore),
                                 /*timestamp*/NULL,
                                 /*type*/CCN_CONTENT_GONE,
                                 /*freshness*/ 42,
                                 /*finalblockid*/NULL,
                                 /*keylocator*/NULL);
    if (res < 0) {
        printf("Failed to create signed_info!\n");
    }

    res = ccn_skeleton_decode(&dd, signed_info->buf, signed_info->length);
    if (!(res == signed_info->length && dd.state == 0)) {
        printf("Failed to decode signed_info!  Result %d State %d\n", (int)res, dd.state);
        result = 1;
    }
    memset(&dd, 0, sizeof(dd));
    printf("Done with signed_info\n");

    result = encode_sample_test(ccn_keystore_key(keystore), ccn_keystore_public_key(keystore), 
		ccn_keystore_digest_algorithm(keystore), paths, contents, signed_info, outname);

    if (! result) {
    	result = encode_sample_test(ccn_keystore_key(aes_keystore), ccn_keystore_key(aes_keystore), 
                        ccn_keystore_digest_algorithm(aes_keystore),
			paths, contents, signed_info, outname);
    }

    /* Now exercise as unit tests */

    for (i = 0; paths[i] != NULL && contents[i] != NULL; i++) {
        printf("Unit test case %d\n", i);
        cur_path = path_create(paths[i]);
        buffer = ccn_charbuf_create();
        if (encode_message(buffer, cur_path, contents[i], strlen(contents[i]), signed_info,
                       ccn_keystore_key(keystore), ccn_keystore_digest_algorithm(keystore))) {
            printf("Failed encode\n");
            result = 1;
        } else if (decode_message(buffer, cur_path, contents[i], strlen(contents[i]), 
                       ccn_keystore_public_key(keystore))) {
            printf("Failed decode\n");
            result = 1;
        }
        ccn_charbuf_destroy(&buffer);
        buffer = ccn_charbuf_create();
        if (encode_message(buffer, cur_path, contents[i], strlen(contents[i]), signed_info,
                       ccn_keystore_key(aes_keystore), ccn_keystore_digest_algorithm(aes_keystore))) {
            printf("Failed encode\n");
            result = 1;
        } else if (decode_message(buffer, cur_path, contents[i], strlen(contents[i]), ccn_keystore_key(aes_keystore))) {
            printf("Failed decode\n");
            result = 1;
        }
        path_destroy(&cur_path);
        ccn_charbuf_destroy(&buffer);
    }

    /* Test the uri encode / decode routines */

    init_all_chars_percent_encoded();
    init_all_chars_mixed_encoded();
    const char *uri_tests[] = {
        "_+4", "ccnx:/this/is/a/test",       "",     "ccnx:/this/is/a/test",
        ".+4", "../test2?x=2",              "?x=2", "ccnx:/this/is/a/test2",
        "_-X", "../should/error",           "",     "",
        "_+2", "/missing/scheme",           "",     "ccnx:/missing/scheme",
        ".+0", "../../../../../././#/",     "#/",   "ccnx:/",
        ".+1", all_chars_percent_encoded,   "",     all_chars_percent_encoded_canon,
        "_+1", all_chars_percent_encoded_canon, "", all_chars_percent_encoded_canon,
        ".+4", "ccnx:/.../.%2e./...././.....///?...", "?...", "ccnx:/.../.../..../.....",
        "_-X", "/%3G?bad-pecent-encode",    "",     "",
        "_-X", "/%3?bad-percent-encode",    "",     "",
        "_-X", "/%#bad-percent-encode",    "",     "",
        "_+3", "ccnx://[email protected]:42/ignore/host/part of uri", "", "ccnx:/ignore/host/part%20of%20uri",
        NULL, NULL, NULL, NULL
    };
    const char **u;
    struct ccn_charbuf *uri_out = ccn_charbuf_create();
    buffer = ccn_charbuf_create();
    for (u = uri_tests; *u != NULL; u += 4, i++) {
        printf("Unit test case %d\n", i);
        if (u[0][0] != '.')
            buffer->length = 0;
        res = ccn_name_from_uri(buffer, u[1]);
        if (!expected_res(res, u[0][1])) {
            printf("Failed: ccn_name_from_uri wrong res %d\n", (int)res);
            result = 1;
        }
        if (res >= 0) {
            if (res > strlen(u[1])) {
                printf("Failed: ccn_name_from_uri long res %d\n", (int)res);
                result = 1;
            }
            else if (0 != strcmp(u[1] + res, u[2])) {
                printf("Failed: ccn_name_from_uri expecting leftover '%s', got '%s'\n", u[2], u[1] + res);
                result = 1;
            }
            uri_out->length = 0;
            res = ccn_uri_append(uri_out, buffer->buf, buffer->length,
                                 CCN_URI_PERCENTESCAPE | CCN_URI_INCLUDESCHEME);
            if (!expected_res(res, u[0][2])) {
                printf("Failed: ccn_uri_append wrong res %d\n", (int)res);
                result = 1;
            }
            if (res >= 0) {
                if (uri_out->length != strlen(u[3])) {
                    printf("Failed: ccn_uri_append produced wrong number of characters\n");
                    result = 1;
                }
                ccn_charbuf_reserve(uri_out, 1)[0] = 0;
                if (0 != strcmp((const char *)uri_out->buf, u[3])) {
                    printf("Failed: ccn_uri_append produced wrong output\n");
                    printf("Expected: %s\n", u[3]);
                    printf("  Actual: %s\n", (const char *)uri_out->buf);
                    result = 1;
                }
            }
        }
    }
    ccn_charbuf_destroy(&buffer);
    ccn_charbuf_destroy(&uri_out);
    printf("Name marker tests\n");
    do {
        const char *expected_uri = "ccnx:/example.com/.../%01/%FE/%01%02%03%04%05%06%07%08/%FD%10%10%10%10%1F%FF/%00%81";
        const char *expected_chopped_uri = "ccnx:/example.com/.../%01/%FE";
        const char *expected_bumped_uri = "ccnx:/example.com/.../%01/%FF";
        const char *expected_bumped2_uri = "ccnx:/example.com/.../%01/%00%00";

        printf("Unit test case %d\n", i++);
        buffer = ccn_charbuf_create();
        uri_out = ccn_charbuf_create();
        res = ccn_name_init(buffer);
        res |= ccn_name_append_str(buffer, "example.com");
        res |= ccn_name_append_numeric(buffer, CCN_MARKER_NONE, 0);
        res |= ccn_name_append_numeric(buffer, CCN_MARKER_NONE, 1);
        res |= ccn_name_append_numeric(buffer, 0xFE, 0);
        res |= ccn_name_append_numeric(buffer, CCN_MARKER_NONE, 0x0102030405060708ULL);
        res |= ccn_name_append_numeric(buffer, CCN_MARKER_VERSION, 0x101010101FFFULL);
        res |= ccn_name_append_numeric(buffer, CCN_MARKER_SEQNUM, 129);
        res |= ccn_uri_append(uri_out, buffer->buf, buffer->length,
                              CCN_URI_PERCENTESCAPE | CCN_URI_INCLUDESCHEME);
        if (res < 0) {
            printf("Failed: name marker tests had negative res\n");
            result = 1;
        }
        if (0 != strcmp(ccn_charbuf_as_string(uri_out), expected_uri)) {
            printf("Failed: name marker tests produced wrong output\n");
            printf("Expected: %s\n", expected_uri);
            printf("  Actual: %s\n", (const char *)uri_out->buf);
            result = 1;
        }
        res = ccn_name_chop(buffer, NULL, 100);
        if (res != -1) {
            printf("Failed: ccn_name_chop did not produce error \n");
            result = 1;
        }
        res = ccn_name_chop(buffer, NULL, 4);
        if (res != 4) {
            printf("Failed: ccn_name_chop got wrong length\n");
            result = 1;
        }
        uri_out->length = 0;
        ccn_uri_append(uri_out, buffer->buf, buffer->length, CCN_URI_INCLUDESCHEME);
        if (0 != strcmp(ccn_charbuf_as_string(uri_out), expected_chopped_uri)) {
            printf("Failed: ccn_name_chop botch\n");
            printf("Expected: %s\n", expected_chopped_uri);
            printf("  Actual: %s\n", (const char *)uri_out->buf);
            result = 1;
        }
        res = ccn_name_next_sibling(buffer);
        if (res != 4) {
            printf("Failed: ccn_name_next_sibling got wrong length\n");
            result = 1;
        }
        uri_out->length = 0;
        ccn_uri_append(uri_out, buffer->buf, buffer->length, CCN_URI_INCLUDESCHEME);
        if (0 != strcmp(ccn_charbuf_as_string(uri_out), expected_bumped_uri)) {
            printf("Failed: ccn_name_next_sibling botch\n");
            printf("Expected: %s\n", expected_bumped_uri);
            printf("  Actual: %s\n", (const char *)uri_out->buf);
            result = 1;
        }
        ccn_name_next_sibling(buffer);
        uri_out->length = 0;
        ccn_uri_append(uri_out, buffer->buf, buffer->length, 
                       CCN_URI_PERCENTESCAPE | CCN_URI_INCLUDESCHEME);
        if (0 != strcmp(ccn_charbuf_as_string(uri_out), expected_bumped2_uri)) {
            printf("Failed: ccn_name_next_sibling botch\n");
            printf("Expected: %s\n", expected_bumped2_uri);
            printf("  Actual: %s\n", (const char *)uri_out->buf);
            result = 1;
        }
        ccn_charbuf_destroy(&buffer);
        ccn_charbuf_destroy(&uri_out);
    } while (0);

    do {
        const char *expected_uri_mixed = "ccnx:/example.com/.../%01/%FE/=0102030405060708/=FD101010101FFF/=0081";
        
        printf("Unit test case %d\n", i++);
        buffer = ccn_charbuf_create();
        uri_out = ccn_charbuf_create();
        res = ccn_name_init(buffer);
        res |= ccn_name_append_str(buffer, "example.com");
        res |= ccn_name_append_numeric(buffer, CCN_MARKER_NONE, 0);
        res |= ccn_name_append_numeric(buffer, CCN_MARKER_NONE, 1);
        res |= ccn_name_append_numeric(buffer, 0xFE, 0);
        res |= ccn_name_append_numeric(buffer, CCN_MARKER_NONE, 0x0102030405060708ULL);
        res |= ccn_name_append_numeric(buffer, CCN_MARKER_VERSION, 0x101010101FFFULL);
        res |= ccn_name_append_numeric(buffer, CCN_MARKER_SEQNUM, 129);
        res |= ccn_uri_append(uri_out, buffer->buf, buffer->length,
                              CCN_URI_MIXEDESCAPE | CCN_URI_INCLUDESCHEME);
        if (res < 0) {
            printf("Failed: name marker tests had negative res\n");
            result = 1;
        }
        if (0 != strcmp(ccn_charbuf_as_string(uri_out), expected_uri_mixed)) {
            printf("Failed: name marker tests produced wrong output\n");
            printf("Expected: %s\n", expected_uri_mixed);
            printf("  Actual: %s\n", (const char *)uri_out->buf);
            result = 1;
        }
        ccn_charbuf_destroy(&buffer);
        ccn_charbuf_destroy(&uri_out);
    } while (0);
    printf("Empty component encoding test\n");
    do {
        struct ccn_charbuf *name = ccn_charbuf_create();
        struct ccn_charbuf *expected_encoding = ccn_charbuf_create();
        /* manually create an encoding of <Name><Component/></Name> to ensure
         * that the regular encoders do not create a 0-length blob as part of
         * the empty component.
         */
        ccnb_element_begin(expected_encoding, CCN_DTAG_Name);
        ccnb_element_begin(expected_encoding, CCN_DTAG_Component);
        ccnb_element_end(expected_encoding);
        ccnb_element_end(expected_encoding);
        ccn_name_from_uri(name, "ccnx:/...");
        if (expected_encoding->length != name->length) {
            printf("Failed: encoding length %u but expected %u\n", (unsigned) name->length,
                   (unsigned)expected_encoding->length);
            result = 1;
        }
        for (i = 0; i < expected_encoding->length; i++) {
            if (expected_encoding->buf[i] != name->buf[i]) {
                printf("Failed: encoding mismatch at %d, got %d but expected %d\n",
                       i, name->buf[i], expected_encoding->buf[i]);
                result = 1;
            }
        }
        
    } while (0);
    
    printf("Timestamp tests\n");
    do {
        intmax_t sec;
        int nsec;
        int r;
        int f;
        struct ccn_charbuf *a[2];
        int t0 = 1363899678;
        
        printf("Unit test case %d\n", i++);
        /* Run many increasing inputs and make sure the output is in order. */
        a[0] = ccn_charbuf_create();
        a[1] = ccn_charbuf_create();
        ccnb_append_timestamp_blob(a[1], CCN_MARKER_NONE, t0 - 1, 0);
        for (f = 0, nsec = 0, sec = t0; sec < t0 + 20; nsec += 122099) {
            while (nsec >= 1000000000) {
                sec++;
                nsec -= 1000000000;
            }
            ccn_charbuf_reset(a[f]);
            r = ccnb_append_timestamp_blob(a[f], CCN_MARKER_NONE, sec, nsec);
            if (r != 0 || a[f]->length != 7 || memcmp(a[1-f]->buf, a[f]->buf, 6) > 0) {
                printf("Failed ccnb_append_timestamp_blob(...,%jd,%d)\n", sec, nsec);
                result = 1;
            }
            f = 1 - f;
        }
        ccn_charbuf_destroy(&a[0]);
        ccn_charbuf_destroy(&a[1]);
    } while (0);
    printf("Message digest tests\n");
    do {
        printf("Unit test case %d\n", i++);
        struct ccn_digest *dg = ccn_digest_create(CCN_DIGEST_SHA256);
        if (dg == NULL) {
            printf("Failed: ccn_digest_create returned NULL\n");
            result = 1;
            break;
        }
        printf("Unit test case %d\n", i++);
        const unsigned char expected_digest[] = {
            0xb3, 0x82, 0xcd, 0xb0, 0xe9, 0x5d, 0xf7, 0x3b, 0xe7, 0xdc, 0x19, 0x81, 0x3a, 0xfd, 0xdf, 0x89, 0xfb, 0xd4, 0xd4, 0xa0, 0xdb, 0x11, 0xa6, 0xba, 0x24, 0x16, 0x5b, 0xad, 0x9d, 0x90, 0x72, 0xb0
        };
        unsigned char actual_digest[sizeof(expected_digest)] = {0};
        const char *data = "Content-centric";
        if (ccn_digest_size(dg) != sizeof(expected_digest)) {
            printf("Failed: wrong digest size\n");
            result = 1;
            break;
        }
        printf("Unit test case %d\n", i++);
        ccn_digest_init(dg);
        res = ccn_digest_update(dg, data, strlen(data));
        if (res != 0)
            printf("Warning: check res %d\n", (int)res);
        printf("Unit test case %d\n", i++);
        res = ccn_digest_final(dg, actual_digest, sizeof(expected_digest));
        if (res != 0)
            printf("Warning: check res %d\n", (int)res);
        if (0 != memcmp(actual_digest, expected_digest, sizeof(expected_digest))) {
            printf("Failed: wrong digest\n");
            result = 1;
            break;
        }
    } while (0);
    printf("Really basic PRNG test\n");
    do {
        unsigned char r1[42];
        unsigned char r2[42];
        printf("Unit test case %d\n", i++);
        ccn_add_entropy(&i, sizeof(i), 0); /* Not much entropy, really. */
        ccn_random_bytes(r1, sizeof(r1));
        memcpy(r2, r1, sizeof(r2));
        ccn_random_bytes(r2, sizeof(r2));
        if (0 == memcmp(r1, r2, sizeof(r2))) {
            printf("Failed: badly broken PRNG\n");
            result = 1;
            break;
        }
    } while (0);
    printf("Bloom filter tests\n");
    do {
        unsigned char seed1[4] = "1492";
        const char *a[13] = {
            "one", "two", "three", "four",
            "five", "six", "seven", "eight",
            "nine", "ten", "eleven", "twelve",
            "thirteen"
        };
        struct ccn_bloom *b1 = NULL;
        struct ccn_bloom *b2 = NULL;
        int j, k, t1, t2;
        unsigned short us;

        printf("Unit test case %d\n", i++);
        b1 = ccn_bloom_create(13, seed1);

        for (j = 0; j < 13; j++)
            if (ccn_bloom_match(b1, a[j], strlen(a[j]))) break;
        if (j < 13) {
            printf("Failed: \"%s\" matched empty Bloom filter\n", a[j]);
            result = 1;
            break;
        }
        printf("Unit test case %d\n", i++);
        for (j = 0; j < 13; j++)
            ccn_bloom_insert(b1, a[j], strlen(a[j]));
        for (j = 0; j < 13; j++)
            if (!ccn_bloom_match(b1, a[j], strlen(a[j]))) break;
        if (j < 13) {
            printf("Failed: \"%s\" not found when it should have been\n", a[j]);
            result = 1;
            break;
        }
        printf("Unit test case %d\n", i++);
        for (j = 0, k = 0; j < 13; j++)
            if (ccn_bloom_match(b1, a[j]+1, strlen(a[j]+1)))
                k++;
        if (k > 0) {
            printf("Mmm, found %d false positives\n", k);
            if (k > 2) {
                result = 1;
                break;
            }
        }
        unsigned char seed2[5] = "aqfb\0";
        for (; seed2[3] <= 'f'; seed2[3]++) {
            printf("Unit test case %d (%4s)    ", i++, seed2);
            b2 = ccn_bloom_create(13, seed2);
            for (j = 0; j < 13; j++)
                ccn_bloom_insert(b2, a[j], strlen(a[j]));
            for (j = 0, k = 0, us = ~0; us > 0; us--) {
                t1 = ccn_bloom_match(b1, &us, sizeof(us));
                t2 = ccn_bloom_match(b2, &us, sizeof(us));
                j += (t1 | t2);
                k += (t1 & t2);
            }
            printf("either=%d both=%d wiresize=%d\n", j, k, ccn_bloom_wiresize(b1));
            if (k > 12) {
                printf("Failed: Bloom seeding may not be effective\n");
                result = 1;
            }
            ccn_bloom_destroy(&b2);
        }
        ccn_bloom_destroy(&b1);
    } while (0);
    printf("ccn_sign_content() tests\n");
    do {
        struct ccn *h = ccn_create();
	int res;
	res = unit_tests_for_signing(h, &i, 0);
	if (res == 1)
            result = 1;
        printf("Unit test case %d\n", i++);
        ccn_destroy(&h);
    } while (0);
    do {
        struct ccn *h = ccn_create();
	int res;
	res = ccn_load_default_key(h, aes_keystore_name, keystore_password);
	if (res < 0) {
            result = 1;
            printf("Failed: res == %d\n", (int)res);
        } else 
            res = unit_tests_for_signing(h, &i, 1);
	if (res == 1)
            result = 1;
        printf("Unit test case %d\n", i++);
        ccn_destroy(&h);
    } while (0);
    printf("link tests\n");
    printf("link tests\n");
    do {
        struct ccn_charbuf *l = ccn_charbuf_create();
        struct ccn_charbuf *name = ccn_charbuf_create();
        struct ccn_parsed_Link pl = {0};
        struct ccn_buf_decoder decoder;
        struct ccn_buf_decoder *d;
        struct ccn_indexbuf *comps = ccn_indexbuf_create();
        printf("Unit test case %d\n", i++);
        ccn_name_from_uri(name, "ccnx:/test/link/name");
        ccnb_append_Link(l, name, "label", NULL);
        d = ccn_buf_decoder_start(&decoder, l->buf, l->length);
        res = ccn_parse_Link(d, &pl, comps);
        if (res != 3 /* components in name */) {
            printf("Failed: ccn_parse_Link res == %d\n", (int)res);
            result = 1;
        }
    } while (0);

    exit(result);
}
示例#16
0
int
main (int argc, char *argv[]) {
    struct ccn_charbuf *buffer = ccn_charbuf_create();
    struct ccn_charbuf *signed_info = ccn_charbuf_create();
    struct ccn_skeleton_decoder dd = {0};
    ssize_t res;
    char *outname = NULL;
    int fd;
    int result = 0;
    char * contents[] = {"INVITE sip:[email protected] SIP/2.0\nVia: SIP/2.0/UDP 127.0.0.1:5060;rport;branch=z9hG4bK519044721\nFrom: <sip:[email protected]>;tag=2105643453\nTo: Test User <sip:[email protected]>\nCall-ID: [email protected]\nCSeq: 20 INVITE\nContact: <sip:[email protected]:5060>\nMax-Forwards: 70\nUser-Agent: Linphone-1.7.1/eXosip\nSubject: Phone call\nExpires: 120\nAllow: INVITE, ACK, CANCEL, BYE, OPTIONS, REFER, SUBSCRIBE, NOTIFY, MESSAGE\nContent-Type: application/sdp\nContent-Length:   448\n\nv=0\no=jthornto 123456 654321 IN IP4 127.0.0.1\ns=A conversation\nc=IN IP4 127.0.0.1\nt=0 0\nm=audio 7078 RTP/AVP 111 110 0 3 8 101\na=rtpmap:111 speex/16000/1\na=rtpmap:110 speex/8000/1\na=rtpmap:0 PCMU/8000/1\na=rtpmap:3 GSM/8000/1\na=rtpmap:8 PCMA/8000/1\na=rtpmap:101 telephone-event/8000\na=fmtp:101 0-11\nm=video 9078 RTP/AVP 97 98 99\na=rtpmap:97 theora/90000\na=rtpmap:98 H263-1998/90000\na=fmtp:98 CIF=1;QCIF=1\na=rtpmap:99 MP4V-ES/90000\n", 
 
			 "Quaer #%2d zjduer  badone",
                         "",
                         NULL};
    char * paths[] = { "/sip/protocol/parc.com/domain/foo/principal/invite/verb/[email protected]/id", 
		       "/d/e/f",
                       "/zero/length/content",
                       NULL};
    struct path * cur_path = NULL;
    struct ccn_keystore *keystore = ccn_keystore_create();
    char *home = getenv("HOME");
    char *keystore_suffix = "/.ccnx/.ccnx_keystore";
    char *keystore_name = NULL;

    int i;

    if (argc == 3 && strcmp(argv[1], "-o") == 0) {
	outname = argv[2];
    } else {
	printf("Usage: %s -o <outfilename>\n", argv[0]);
	exit(1);
    }

    if (home == NULL) {
        printf("Unable to determine home directory for keystore\n");
        exit(1);
    }
    keystore_name = calloc(1, strlen(home) + strlen(keystore_suffix) + 1);
    
    strcat(keystore_name, home);
    strcat(keystore_name, keystore_suffix);

    if (0 != ccn_keystore_init(keystore, keystore_name, "Th1s1sn0t8g00dp8ssw0rd.")) {
        printf("Failed to initialize keystore\n");
        exit(1);
    }

    printf("Creating signed_info\n");
    res = ccn_signed_info_create(signed_info,
                                 /*pubkeyid*/ccn_keystore_public_key_digest(keystore),
                                 /*publisher_key_id_size*/ccn_keystore_public_key_digest_length(keystore),
                                 /*datetime*/NULL,
                                 /*type*/CCN_CONTENT_GONE,
                                 /*freshness*/ 42,
                                 /*finalblockid*/NULL,
                                 /*keylocator*/NULL);
    if (res < 0) {
        printf("Failed to create signed_info!\n");
    }
    
    res = ccn_skeleton_decode(&dd, signed_info->buf, signed_info->length);
    if (!(res == signed_info->length && dd.state == 0)) {
        printf("Failed to decode signed_info!  Result %d State %d\n", (int)res, dd.state);
        result = 1;
    }
    memset(&dd, 0, sizeof(dd));
    printf("Done with signed_info\n");

    printf("Encoding sample message data length %d\n", (int)strlen(contents[0]));
    cur_path = path_create(paths[0]);
    if (encode_message(buffer, cur_path, contents[0], strlen(contents[0]), signed_info, ccn_keystore_private_key(keystore))) {
	printf("Failed to encode message!\n");
    } else {
	printf("Encoded sample message length is %d\n", (int)buffer->length);

	res = ccn_skeleton_decode(&dd, buffer->buf, buffer->length);
	if (!(res == buffer->length && dd.state == 0)) {
	    printf("Failed to decode!  Result %d State %d\n", (int)res, dd.state);
	    result = 1;
	}
        if (outname != NULL) {
            fd = open(outname, O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU);
            if (fd == -1)
                perror(outname);
            res = write(fd, buffer->buf, buffer->length);
            close(fd);
	}
        if (decode_message(buffer, cur_path, contents[0], strlen(contents[0]), ccn_keystore_public_key(keystore)) != 0) {
	    result = 1;
	}
        printf("Expect signature verification failure: ");
        if (buffer->length >= 20)
            buffer->buf[buffer->length - 20] += 1;
	if (decode_message(buffer, cur_path, contents[0], strlen(contents[0]), ccn_keystore_public_key(keystore)) == 0) {
	    result = 1;
	}
    }
    path_destroy(&cur_path);
    ccn_charbuf_destroy(&buffer);
    printf("Done with sample message\n");
    
    /* Now exercise as unit tests */
    
    for (i = 0; paths[i] != NULL && contents[i] != NULL; i++) {
	printf("Unit test case %d\n", i);
	cur_path = path_create(paths[i]);
	buffer = ccn_charbuf_create();
	if (encode_message(buffer, cur_path, contents[i], strlen(contents[i]), signed_info, ccn_keystore_private_key(keystore))) {
	    printf("Failed encode\n");
            result = 1;
	} else if (decode_message(buffer, cur_path, contents[i], strlen(contents[i]), ccn_keystore_public_key(keystore))) {
	    printf("Failed decode\n");
            result = 1;
	}
	path_destroy(&cur_path);
	ccn_charbuf_destroy(&buffer);
    }
    
    /* Test the uri encode / decode routines */
        
    init_all_chars_percent_encoded();
    const char *uri_tests[] = {
        "_+4", "ccnx:/this/is/a/test",       "",     "ccnx:/this/is/a/test",
        ".+4", "../test2?x=2",              "?x=2", "ccnx:/this/is/a/test2",
        "_-X", "../should/error",           "",     "",
        "_+2", "/missing/scheme",           "",     "ccnx:/missing/scheme",
        ".+0", "../../../../../././#/",     "#/",   "ccnx:/",
        ".+1", all_chars_percent_encoded,   "",     all_chars_percent_encoded_canon,
        "_+1", all_chars_percent_encoded_canon, "", all_chars_percent_encoded_canon,
        ".+4", "ccnx:/.../.%2e./...././.....///?...", "?...", "ccnx:/.../.../..../.....",
        "_-X", "/%3G?bad-pecent-encode",    "",     "",
        "_-X", "/%3?bad-percent-encode",    "",     "",
        "_-X", "/%#bad-percent-encode",    "",     "",
        "_+3", "ccnx://[email protected]:42/ignore/host/part of uri", "", "ccnx:/ignore/host/part%20of%20uri",
        NULL, NULL, NULL, NULL
    };
    const char **u;
    struct ccn_charbuf *uri_out = ccn_charbuf_create();
    buffer = ccn_charbuf_create();
    for (u = uri_tests; *u != NULL; u += 4, i++) {
        printf("Unit test case %d\n", i);
        if (u[0][0] != '.')
            buffer->length = 0;
        res = ccn_name_from_uri(buffer, u[1]);
        if (!expected_res(res, u[0][1])) {
            printf("Failed: ccn_name_from_uri wrong res %d\n", (int)res);
            result = 1;
        }
        if (res >= 0) {
            if (res > strlen(u[1])) {
                printf("Failed: ccn_name_from_uri long res %d\n", (int)res);
                result = 1;
            }
            else if (0 != strcmp(u[1] + res, u[2])) {
                printf("Failed: ccn_name_from_uri expecting leftover '%s', got '%s'\n", u[2], u[1] + res);
                result = 1;
            }
            uri_out->length = 0;
            res = ccn_uri_append(uri_out, buffer->buf, buffer->length, 1);
            if (!expected_res(res, u[0][2])) {
                printf("Failed: ccn_uri_append wrong res %d\n", (int)res);
                result = 1;
            }
            if (res >= 0) {
                if (uri_out->length != strlen(u[3])) {
                    printf("Failed: ccn_uri_append produced wrong number of characters\n");
                    result = 1;
                }
                ccn_charbuf_reserve(uri_out, 1)[0] = 0;
                if (0 != strcmp((const char *)uri_out->buf, u[3])) {
                    printf("Failed: ccn_uri_append produced wrong output\n");
                    printf("Expected: %s\n", u[3]);
                    printf("  Actual: %s\n", (const char *)uri_out->buf);
                    result = 1;
                }
            }
        }
    }
    ccn_charbuf_destroy(&buffer);
    ccn_charbuf_destroy(&uri_out);
    printf("Name marker tests\n");
    do {
        const char *expected_uri = "ccnx:/example.com/.../%01/%FE/%01%02%03%04%05%06%07%08/%FD%10%10%10%10%1F%FF/%00%81";
        const char *expected_chopped_uri = "ccnx:/example.com/.../%01/%FE";
        const char *expected_bumped_uri = "ccnx:/example.com/.../%01/%FF";
        const char *expected_bumped2_uri = "ccnx:/example.com/.../%01/%00%00";

        printf("Unit test case %d\n", i++);
        buffer = ccn_charbuf_create();
        uri_out = ccn_charbuf_create();
        res = ccn_name_init(buffer);
        res |= ccn_name_append_str(buffer, "example.com");
        res |= ccn_name_append_numeric(buffer, CCN_MARKER_NONE, 0);
        res |= ccn_name_append_numeric(buffer, CCN_MARKER_NONE, 1);
        res |= ccn_name_append_numeric(buffer, 0xFE, 0);
        res |= ccn_name_append_numeric(buffer, CCN_MARKER_NONE, 0x0102030405060708ULL);
        res |= ccn_name_append_numeric(buffer, CCN_MARKER_VERSION, 0x101010101FFFULL);
        res |= ccn_name_append_numeric(buffer, CCN_MARKER_SEQNUM, 129);
        res |= ccn_uri_append(uri_out, buffer->buf, buffer->length, 1);
        if (res < 0) {
            printf("Failed: name marker tests had negative res\n");
            result = 1;
        }
        if (0 != strcmp(ccn_charbuf_as_string(uri_out), expected_uri)) {
            printf("Failed: name marker tests produced wrong output\n");
            printf("Expected: %s\n", expected_uri);
            printf("  Actual: %s\n", (const char *)uri_out->buf);
            result = 1;
        }
        res = ccn_name_chop(buffer, NULL, 100);
        if (res != -1) {
            printf("Failed: ccn_name_chop did not produce error \n");
            result = 1;
        }
        res = ccn_name_chop(buffer, NULL, 4);
        if (res != 4) {
            printf("Failed: ccn_name_chop got wrong length\n");
            result = 1;
        }
        uri_out->length = 0;
        ccn_uri_append(uri_out, buffer->buf, buffer->length, 1);
        if (0 != strcmp(ccn_charbuf_as_string(uri_out), expected_chopped_uri)) {
            printf("Failed: ccn_name_chop botch\n");
            printf("Expected: %s\n", expected_chopped_uri);
            printf("  Actual: %s\n", (const char *)uri_out->buf);
            result = 1;
        }
        res = ccn_name_next_sibling(buffer);
        if (res != 4) {
            printf("Failed: ccn_name_next_sibling got wrong length\n");
            result = 1;
        }
        uri_out->length = 0;
        ccn_uri_append(uri_out, buffer->buf, buffer->length, 1);
        if (0 != strcmp(ccn_charbuf_as_string(uri_out), expected_bumped_uri)) {
            printf("Failed: ccn_name_next_sibling botch\n");
            printf("Expected: %s\n", expected_bumped_uri);
            printf("  Actual: %s\n", (const char *)uri_out->buf);
            result = 1;
        }
        ccn_name_next_sibling(buffer);
        uri_out->length = 0;
        ccn_uri_append(uri_out, buffer->buf, buffer->length, 1);
        if (0 != strcmp(ccn_charbuf_as_string(uri_out), expected_bumped2_uri)) {
            printf("Failed: ccn_name_next_sibling botch\n");
            printf("Expected: %s\n", expected_bumped2_uri);
            printf("  Actual: %s\n", (const char *)uri_out->buf);
            result = 1;
        }
        ccn_charbuf_destroy(&buffer);
        ccn_charbuf_destroy(&uri_out);
    } while (0);
    printf("Message digest tests\n");
    do {
        printf("Unit test case %d\n", i++);
        struct ccn_digest *dg = ccn_digest_create(CCN_DIGEST_SHA256);
        if (dg == NULL) {
            printf("Failed: ccn_digest_create returned NULL\n");
            result = 1;
            break;
        }
        printf("Unit test case %d\n", i++);
        const unsigned char expected_digest[] = {
            0xb3, 0x82, 0xcd, 0xb0, 0xe9, 0x5d, 0xf7, 0x3b, 0xe7, 0xdc, 0x19, 0x81, 0x3a, 0xfd, 0xdf, 0x89, 0xfb, 0xd4, 0xd4, 0xa0, 0xdb, 0x11, 0xa6, 0xba, 0x24, 0x16, 0x5b, 0xad, 0x9d, 0x90, 0x72, 0xb0
        };
        unsigned char actual_digest[sizeof(expected_digest)] = {0};
        const char *data = "Content-centric";
        if (ccn_digest_size(dg) != sizeof(expected_digest)) {
            printf("Failed: wrong digest size\n");
            result = 1;
            break;
        }
        printf("Unit test case %d\n", i++);
        ccn_digest_init(dg);
        res = ccn_digest_update(dg, data, strlen(data));
        if (res != 0)
            printf("Warning: check res %d\n", (int)res);
        printf("Unit test case %d\n", i++);
        res = ccn_digest_final(dg, actual_digest, sizeof(expected_digest));
        if (res != 0)
            printf("Warning: check res %d\n", (int)res);
        if (0 != memcmp(actual_digest, expected_digest, sizeof(expected_digest))) {
            printf("Failed: wrong digest\n");
            result = 1;
            break;
        }
    } while (0);
    printf("Really basic PRNG test\n");
    do {
        unsigned char r1[42];
        unsigned char r2[42];
        printf("Unit test case %d\n", i++);
        ccn_add_entropy(&i, sizeof(i), 0); /* Not much entropy, really. */
        ccn_random_bytes(r1, sizeof(r1));
        memcpy(r2, r1, sizeof(r2));
        ccn_random_bytes(r2, sizeof(r2));
        if (0 == memcmp(r1, r2, sizeof(r2))) {
            printf("Failed: badly broken PRNG\n");
            result = 1;
            break;
        }
    } while (0);
    printf("Bloom filter tests\n");
    do {
        unsigned char seed1[4] = "1492";
        const char *a[13] = {
            "one", "two", "three", "four",
            "five", "six", "seven", "eight",
            "nine", "ten", "eleven", "twelve",
            "thirteen"
        };
        struct ccn_bloom *b1 = NULL;
        struct ccn_bloom *b2 = NULL;
        int j, k, t1, t2;
        unsigned short us;
        
        printf("Unit test case %d\n", i++);
        b1 = ccn_bloom_create(13, seed1);
        
        for (j = 0; j < 13; j++)
            if (ccn_bloom_match(b1, a[j], strlen(a[j]))) break;
        if (j < 13) {
            printf("Failed: \"%s\" matched empty Bloom filter\n", a[j]);
            result = 1;
            break;
        }
        printf("Unit test case %d\n", i++);
        for (j = 0; j < 13; j++)
            ccn_bloom_insert(b1, a[j], strlen(a[j]));
        for (j = 0; j < 13; j++)
            if (!ccn_bloom_match(b1, a[j], strlen(a[j]))) break;
        if (j < 13) {
            printf("Failed: \"%s\" not found when it should have been\n", a[j]);
            result = 1;
            break;
        }
        printf("Unit test case %d\n", i++);
        for (j = 0, k = 0; j < 13; j++)
            if (ccn_bloom_match(b1, a[j]+1, strlen(a[j]+1)))
                k++;
        if (k > 0) {
            printf("Mmm, found %d false positives\n", k);
            if (k > 2) {
                result = 1;
                break;
            }
        }
        unsigned char seed2[5] = "aqfb\0";
        for (; seed2[3] <= 'f'; seed2[3]++) {
            printf("Unit test case %d (%4s)    ", i++, seed2);
            b2 = ccn_bloom_create(13, seed2);
            for (j = 0; j < 13; j++)
                ccn_bloom_insert(b2, a[j], strlen(a[j]));
            for (j = 0, k = 0, us = ~0; us > 0; us--) {
                t1 = ccn_bloom_match(b1, &us, sizeof(us));
                t2 = ccn_bloom_match(b2, &us, sizeof(us));
                j += (t1 | t2);
                k += (t1 & t2);
            }
            printf("either=%d both=%d wiresize=%d\n", j, k, ccn_bloom_wiresize(b1));
            if (k > 12) {
                printf("Failed: Bloom seeding may not be effective\n");
                result = 1;
            }
            ccn_bloom_destroy(&b2);
        }
        ccn_bloom_destroy(&b1);
    } while (0);
    printf("ccn_sign_content() tests\n");
    do {
        struct ccn *h = ccn_create();
        struct ccn_charbuf *co = ccn_charbuf_create();
        struct ccn_signing_params sparm = CCN_SIGNING_PARAMS_INIT;
        struct ccn_parsed_ContentObject pco = {0};
        struct ccn_charbuf *name = ccn_charbuf_create();
        
        printf("Unit test case %d\n", i++);
        ccn_name_from_uri(name, "ccnx:/test/data/%00%42");
        res = ccn_sign_content(h, co, name, NULL, "DATA", 4);
        if (res != 0) {
            printf("Failed: res == %d\n", (int)res);
            result = 1;
        }
        sparm.template_ccnb = ccn_charbuf_create();
        res = ccn_parse_ContentObject(co->buf, co->length, &pco, NULL);
        if (res != 0) {
            printf("Failed: ccn_parse_ContentObject res == %d\n", (int)res);
            result = 1;
            break;
        }
        ccn_charbuf_append(sparm.template_ccnb,
            co->buf + pco.offset[CCN_PCO_B_SignedInfo],
            pco.offset[CCN_PCO_E_SignedInfo] - pco.offset[CCN_PCO_B_SignedInfo]);
        sparm.sp_flags = CCN_SP_TEMPL_TIMESTAMP;
        printf("Unit test case %d\n", i++);
        res = ccn_sign_content(h, co, name, &sparm, "DATA", 4);
        if (res != 0) {
            printf("Failed: res == %d\n", (int)res);
            result = 1;
        }
        printf("Unit test case %d\n", i++);
        sparm.sp_flags = -1;
        res = ccn_sign_content(h, co, name, &sparm, "DATA", 4);
        if (res != -1) {
            printf("Failed: res == %d\n", (int)res);
            result = 1;
        }
        ccn_charbuf_destroy(&name);
        ccn_charbuf_destroy(&sparm.template_ccnb);
        ccn_charbuf_destroy(&co);
        ccn_destroy(&h);
    } while (0);
    printf("link tests\n");
    do {
        struct ccn_charbuf *l = ccn_charbuf_create();
        struct ccn_charbuf *name = ccn_charbuf_create();
        struct ccn_parsed_Link pl = {0};
        struct ccn_buf_decoder decoder;
        struct ccn_buf_decoder *d;
        struct ccn_indexbuf *comps = ccn_indexbuf_create();
        printf("Unit test case %d\n", i++);
        ccn_name_from_uri(name, "ccnx:/test/link/name");
        ccnb_append_Link(l, name, "label", NULL);
        d = ccn_buf_decoder_start(&decoder, l->buf, l->length);
        res = ccn_parse_Link(d, &pl, comps);
        if (res != 3 /* components in name */) {
            printf("Failed: ccn_parse_Link res == %d\n", (int)res);
            result = 1;
        }        
    } while (0);
    
    exit(result);
}
示例#17
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 CCNR_GLOBAL_PREFIX or the system
 * default value of ccnx:/parc.com/csl/ccn/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 ccnr_handle *ccnr)
{
    int fd;
    ssize_t res;
    struct content_entry *content = NULL;
    const unsigned char *content_msg = NULL;
    struct ccn_parsed_ContentObject pco = {0};
    struct ccn_parsed_Link pl = {0};
    struct ccn_indexbuf *nc = NULL;
    struct ccn_charbuf *basename = NULL;
    struct ccn_charbuf *policy = NULL;
    struct ccn_charbuf *policy_cob = NULL;
    struct ccn_charbuf *policyFileName;
    const char *global_prefix;
    const unsigned char *buf = NULL;
    size_t length = 0;
    int segment = 0;
    int final = 0;
    struct ccn_buf_decoder decoder;
    struct ccn_buf_decoder *d;
    
    policyFileName = ccn_charbuf_create();
    ccn_charbuf_putf(policyFileName, "%s/repoPolicy", ccnr->directory);
    ccnr->parsed_policy = ccnr_parsed_policy_create();
    fd = open(ccn_charbuf_as_string(policyFileName), O_RDONLY);
    if (fd >= 0) {
        ccnr->policy_link_cob = ccn_charbuf_create();
        ccn_charbuf_reserve(ccnr->policy_link_cob, 4096);   // limits the size of the policy link
        ccnr->policy_link_cob->length = 0;    // clear the buffer
        res = read(fd, ccnr->policy_link_cob->buf, ccnr->policy_link_cob->limit - ccnr->policy_link_cob->length);
        close(fd);
        if (res == -1) {
            r_init_fail(ccnr, __LINE__, "Error reading repoPolicy file.", errno);
            ccn_charbuf_destroy(&ccnr->policy_link_cob);
            ccn_charbuf_destroy(&policyFileName);
            return(-1);
        }
        ccnr->policy_link_cob->length = res;
        nc = ccn_indexbuf_create();
        res = ccn_parse_ContentObject(ccnr->policy_link_cob->buf,
                                      ccnr->policy_link_cob->length, &pco, nc);
        res = ccn_ref_tagged_BLOB(CCN_DTAG_Content, ccnr->policy_link_cob->buf,
                                  pco.offset[CCN_PCO_B_Content],
                                  pco.offset[CCN_PCO_E_Content],
                                  &buf, &length);
        d = ccn_buf_decoder_start(&decoder, buf, length);
        res = ccn_parse_Link(d, &pl, NULL);
        if (res <= 0) {
            ccnr_msg(ccnr, "Policy link is malformed.");
            goto CreateNewPolicy;
        }
        basename = ccn_charbuf_create();
        ccn_charbuf_append(basename, buf + pl.offset[CCN_PL_B_Name],
                           pl.offset[CCN_PL_E_Name] - pl.offset[CCN_PL_B_Name]);
        ccnr->policy_name = ccn_charbuf_create(); // to detect writes to this name
        ccn_charbuf_append_charbuf(ccnr->policy_name, basename); // has version
        ccn_name_chop(ccnr->policy_name, NULL, -1); // get rid of version
        policy = ccn_charbuf_create();
        // if we fail to retrieve the link target, report and then create a new one
        do {
            ccn_name_append_numeric(basename, CCN_MARKER_SEQNUM, segment++);
            content = r_store_lookup_ccnb(ccnr, basename->buf, basename->length);
            if (content == NULL) {
                ccnr_debug_ccnb(ccnr, __LINE__, "policy lookup failed for", NULL,
                                basename->buf, basename->length);
                break;
            }
            ccn_name_chop(basename, NULL, -1);
            content_msg = r_store_content_base(ccnr, content);
            if (content_msg == NULL) {
                ccnr_debug_ccnb(ccnr, __LINE__, "Unable to read policy object", NULL,
                                basename->buf, basename->length);
                break;
            }
            res = ccn_parse_ContentObject(content_msg, r_store_content_size(ccnr, content), &pco, nc);
            res = ccn_ref_tagged_BLOB(CCN_DTAG_Content, content_msg,
                                      pco.offset[CCN_PCO_B_Content],
                                      pco.offset[CCN_PCO_E_Content],
                                      &buf, &length);
            ccn_charbuf_append(policy, buf, length);
            final = ccn_is_final_pco(content_msg, &pco, nc);
        } while (!final && segment < 100);
/**
 * Convert a ccnx-scheme URI to a ccnb-encoded Name.
 * The converted result is placed in c.
 * On input, c may contain a base name, in which case relative URIs are allowed.
 * Otherwise c should start out empty, and the URI must be absolute.
 * @returns -1 if an error is found, otherwise returns the number of characters
 *          that were processed.
 */
int
ccn_name_from_uri(struct ccn_charbuf *c, const char *uri)
{
    int res = 0;
    struct ccn_charbuf *compbuf = NULL;
    const char *stop = uri + strlen(uri);
    const char *s = uri;
    size_t cont = 0;
    
    compbuf = ccn_charbuf_create();
    if (compbuf == NULL) return(-1);
    if (s[0] != '/') {
        res = ccn_append_uri_component(compbuf, s, stop - s, &cont);
        if (res < -2)
            goto Done;
        ccn_charbuf_reserve(compbuf, 1)[0] = 0;
        if ((0 == strcasecmp((const char *)(compbuf->buf), "ccnx:") ||
             0 == strcasecmp((const char *)(compbuf->buf), "ccn:")) &&
            s[cont-1] == ':') {
            s += cont;
            cont = 0;
        }
        /// @bug XXX - need to error out on other uri schemes
    }
    if (s[0] == '/') {
        ccn_name_init(c);
        if (s[1] == '/') {
            /* Skip over hostname part - not used in ccnx scheme */
            s += 2;
            compbuf->length = 0;
            res = ccn_append_uri_component(compbuf, s, stop - s, &cont);
            if (res < 0 && res != -2)
                goto Done;
            s += cont; cont = 0;
        }
    }
    while (s[0] != 0 && s[0] != '?' && s[0] != '#') {
        if (s[0] == '/')
            s++;
        compbuf->length = 0;
        res = ccn_append_uri_component(compbuf, s, stop - s, &cont);
        s += cont; cont = 0;
        if (res < -2)
            goto Done;
        if (res == -2) {
            res = 0; /* process . or equiv in URI */
            continue;
        }
        if (res == -1) {
            /* process .. in URI - discard last name component */
            res = ccn_name_last_component_offset(c->buf, c->length);
            if (res < 0)
                goto Done;
            c->length = res;
            ccn_charbuf_append_closer(c);
            continue;
        }
        res = ccn_name_append(c, compbuf->buf, compbuf->length);
        if (res < 0)
            goto Done;
    }
Done:
    ccn_charbuf_destroy(&compbuf);
    if (res < 0)
        return(-1);
    if (c->length < 2 || c->buf[c->length-1] != CCN_CLOSE)
        return(-1);
    return(s - uri);
}