void
ccn_uri_append_percentescaped(struct ccn_charbuf *c,
                              const unsigned char *data, size_t size)
{
    size_t i;
    unsigned char ch;
    for (i = 0; i < size && data[i] == '.'; i++)
        continue;
    /* For a component that consists solely of zero or more dots, add 3 more */
    if (i == size)
        ccn_charbuf_append(c, "...", 3);
    for (i = 0; i < size; i++) {
        ch = data[i];
        /*
         * Leave unescaped only the generic URI unreserved characters.
         * See RFC 3986. Here we assume the compiler uses ASCII.
         */
        if (('a' <= ch && ch <= 'z') ||
            ('A' <= ch && ch <= 'Z') ||
            ('0' <= ch && ch <= '9') ||
            ch == '-' || ch == '.' || ch == '_' || ch == '~')
            ccn_charbuf_append(c, &(data[i]), 1);
        else
            ccn_charbuf_putf(c, "%%%02X", (unsigned)ch);
    }
}
Beispiel #2
0
/*
 * utility, may need to be exported, to parse the buffer into a given slice
 * structure.
 */
static int
slice_parse(struct ccns_slice *s, const unsigned char *p, size_t size) {
    int res = 0;
    struct ccn_buf_decoder decoder;
    struct ccn_buf_decoder *d = ccn_buf_decoder_start(&decoder, p, size);
    uintmax_t version;
    int op;
    int start;
    struct ccn_charbuf *clause = NULL;

    if (!ccn_buf_match_dtag(d, CCN_DTAG_SyncConfigSlice))
        return (-1);
    ccn_buf_advance(d);
    if (!ccn_buf_match_dtag(d, CCN_DTAG_SyncVersion))
        return (-1);
    ccn_buf_advance(d);
    ccn_parse_uintmax(d, &version);
    ccn_buf_check_close(d);
    if (version != SLICE_VERSION)
        return (-1);
    start = d->decoder.token_index;
    if (ccn_parse_Name(d, NULL) < 0)
        return(-1);
    ccn_charbuf_reset(s->topo);
    res = ccn_charbuf_append(s->topo, p + start, d->decoder.token_index - start);
    if (res < 0)
        return(-1);
    start = d->decoder.token_index;
    if (ccn_parse_Name(d, NULL) < 0)
        return(-1);
    ccn_charbuf_reset(s->prefix);
    res = ccn_charbuf_append(s->prefix, p + start, d->decoder.token_index - start);
    if (res < 0)
        return(-1);
    if (!ccn_buf_match_dtag(d, CCN_DTAG_SyncConfigSliceList))
        return(-1);
    ccn_buf_advance(d);
    clause = ccn_charbuf_create();
    if (clause == NULL)
        return(-1);
    while (ccn_buf_match_dtag(d, CCN_DTAG_SyncConfigSliceOp)) {
        ccn_buf_advance(d);
        op = ccn_parse_nonNegativeInteger(d); // op is a small integer
        ccn_buf_check_close(d);
        if (op != 0)
            break;
        ccn_charbuf_reset(clause);
        start = d->decoder.token_index;
        if (ccn_parse_Name(d, NULL) < 0)
            break;
        res = ccn_charbuf_append(clause, p + start, d->decoder.token_index - start);
        ccns_slice_add_clause(s, clause);
    }
    ccn_charbuf_destroy(&clause);
    ccn_buf_check_close(d); /* </SyncConfigSliceList> */
    ccn_buf_check_close(d); /* </SyncConfigSlice> */
    if (d->decoder.index != size || !CCN_FINAL_DSTATE(d->decoder.state))
        return(-1);
    return(0);
}
/*
 * ccn_append_uri_component:
 * This takes as input the escaped URI component at s and appends it
 * to c.  This does not do any ccnb-related stuff.
 * Processing stops at an error or if an unescaped nul, '/', '?', or '#' is found.
 * A component that consists solely of dots gets special treatment to reverse
 * the addition of ... by ccn_uri_append_percentescaped.  Since '.' is an unreserved
 * character, percent-encoding is not supposed to change meaning and hence
 * the dot processing happens after percent-encoding is removed.
 * A positive return value indicates there were unescaped reserved or
 * non-printable characters found.  This might warrant some extra checking
 * by the caller.
 * A return value of -1 indicates the component was "..", so the caller
 * will need to do something extra to handle this as appropriate.
 * A return value of -2 indicates the component was empty or ".", so the caller
 * should do nothing with it.
 * A return value of -3 indicates a bad %-escaped sequence.
 * If cont is not NULL, *cont is set to the number of input characters processed.
 */
int
ccn_append_uri_component(struct ccn_charbuf *c, const char *s, size_t limit, size_t *cont)
{
    size_t start = c->length;
    size_t i;
    int err = 0;
    int d1, d2;
    unsigned char ch;
    for (i = 0; i < limit; i++) {
        ch = s[i];
        switch (ch) {
            case 0:
            case '/':
            case '?':
            case '#':
                limit = i;
                break;
            case '%':
                if (i + 3 > limit || (d1 = hexit(s[i+1])) < 0 ||
                                     (d2 = hexit(s[i+2])) < 0   ) {
                    return(-3);
                }
                ch = d1 * 16 + d2;
                i += 2;
                ccn_charbuf_append(c, &ch, 1);
                break;
            case ':': case '[': case ']': case '@':
            case '!': case '$': case '&': case '\'': case '(': case ')':
            case '*': case '+': case ',': case ';': case '=':
                err++;
                /* FALLTHROUGH */
            default:
                if (ch <= ' ' || ch > '~')
                    err++;
                ccn_charbuf_append(c, &ch, 1);
                break;
        }
    }
    for (i = start; i < c->length && c->buf[i] == '.'; i++)
        continue;
    if (i == c->length) {
        /* all dots */
        i -= start;
        if (i <= 1) {
            c->length = start;
            err = -2;
        }
        else if (i == 2) {
            c->length = start;
            err = -1;
        }
        else
            c->length -= 3;
    }
    if (cont != NULL)
        *cont = limit;
    return(err);
}
Beispiel #4
0
/**
 * Construct a new face instance based on the given address and port
 * This face instance is only used to send new face request
 */
static struct 
ccn_face_instance *construct_face(const unsigned char *ccndid, size_t ccndid_size,
        const char *address, const char *port)
{
	struct ccn_face_instance *fi = calloc(1, sizeof(*fi));
	char rhostnamebuf[NI_MAXHOST];
	char rhostportbuf[NI_MAXSERV];
	struct addrinfo hints = {.ai_family = AF_UNSPEC, .ai_flags = (AI_ADDRCONFIG),
        .ai_socktype = SOCK_DGRAM};
	struct addrinfo *raddrinfo = NULL;
	struct ccn_charbuf *store = ccn_charbuf_create();
	int host_off = -1;
	int port_off = -1;
	int res;

	res = getaddrinfo(address, port, &hints, &raddrinfo);
	if (res != 0 || raddrinfo == NULL) 
	{
		fprintf(stderr, "Error: getaddrinfo\n");
		return NULL;
	}

	res = getnameinfo(raddrinfo->ai_addr, raddrinfo->ai_addrlen,
            rhostnamebuf, sizeof(rhostnamebuf),
            rhostportbuf, sizeof(rhostportbuf),
            NI_NUMERICHOST | NI_NUMERICSERV);
	freeaddrinfo(raddrinfo);	
	if (res != 0) 
	{
		fprintf(stderr, "Error: getnameinfo\n");
		return NULL;
	}

	fi->store = store;
	fi->descr.ipproto = IPPROTO_UDP;
	fi->descr.mcast_ttl = CCN_FIB_MCASTTTL;
	fi->lifetime = CCN_FIB_LIFETIME;

	ccn_charbuf_append(store, "newface", strlen("newface") + 1);
	host_off = store->length;
	ccn_charbuf_append(store, rhostnamebuf, strlen(rhostnamebuf) + 1);
	port_off = store->length;
	ccn_charbuf_append(store, rhostportbuf, strlen(rhostportbuf) + 1);

	char *b = (char *)store->buf;
	fi->action = b;
	fi->descr.address = b + host_off;
	fi->descr.port = b + port_off;
	fi->descr.source_address = NULL;
	fi->ccnd_id = ccndid;
	fi->ccnd_id_size = ccndid_size;

	return fi;
}
Beispiel #5
0
static int do_ping(struct ccn_schedule *sched, void *clienth,
        struct ccn_scheduled_event *ev, int flags)
{
    struct ccn_ping_client *client = clienth;
    if (client->total >= 0 && client->sent >= client->total)
        return 0;

    struct ccn_charbuf *name = ccn_charbuf_create();
    long int rnum;
    char rnumstr[20];
    int res;

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

    res = ccn_express_interest(client->h, name, client->closure, NULL);
    add_ccn_ping_entry(client, name, rnum);
    client->sent ++;
    sta.sent ++;

    ccn_charbuf_destroy(&name);

    if (res >= 0)
        return client->interval * 1000000;
    else
        return 0;
}
Beispiel #6
0
/**
 * Make a new fdholder corresponding to the fd
 */
PUBLIC struct fdholder *
r_io_record_fd(struct ccnr_handle *h, int fd,
                  void *who, socklen_t wholen,
                  int setflags)
{
    int res;
    struct fdholder *fdholder = NULL;
    
    res = fcntl(fd, F_SETFL, O_NONBLOCK);
    if (res == -1)
        ccnr_msg(h, "fcntl: %s", strerror(errno));
    fdholder = calloc(1, sizeof(*fdholder));
    
    
    if (fdholder == NULL)
        return(fdholder);
    fdholder->name = ccn_charbuf_create();
    if (fdholder->name == NULL)
        abort();
    if (who != NULL)
        ccn_charbuf_append(fdholder->name, who, wholen);
    fdholder->filedesc = fd;
    init_face_flags(h, fdholder, setflags);
    res = r_io_enroll_face(h, fdholder);
    if (res == -1) {
        ccn_charbuf_destroy(&fdholder->name);
        free(fdholder);
        fdholder = NULL;
    }
    return(fdholder);
}
Beispiel #7
0
static struct ccn_charbuf *
ccn_charbuf_duplicate(struct ccn_charbuf *c)
{
    struct ccn_charbuf *ans = ccn_charbuf_create();
    ccn_charbuf_append(ans, c->buf, c->length);
    return(ans);
}
Beispiel #8
0
static struct ccn_charbuf *
resolve_templ(struct ccn_charbuf *templ, unsigned const char *vcomp, int size)
{
    if (templ == NULL)
        templ = ccn_charbuf_create();
    if (size < 3 || size > 16) {
        ccn_charbuf_destroy(&templ);
        return(NULL);
    }
    templ->length = 0;
    ccn_charbuf_append_tt(templ, CCN_DTAG_Interest, CCN_DTAG);
    ccn_charbuf_append_tt(templ, CCN_DTAG_Name, CCN_DTAG);
    ccn_charbuf_append_closer(templ); /* </Name> */
    ccn_charbuf_append_tt(templ, CCN_DTAG_Exclude, CCN_DTAG);
    append_filter_all(templ);
    ccn_charbuf_append_tt(templ, CCN_DTAG_Component, CCN_DTAG);
    ccn_charbuf_append_tt(templ, size, CCN_BLOB);
    ccn_charbuf_append(templ, vcomp, size);
    ccn_charbuf_append_closer(templ); /* </Component> */
    append_future_vcomp(templ);
    append_filter_all(templ);
    ccn_charbuf_append_closer(templ); /* </Exclude> */
    answer_highest(templ);
    answer_passive(templ);
    ccn_charbuf_append_closer(templ); /* </Interest> */
    return(templ);
}
Beispiel #9
0
int
ccnb_append_forwarding_entry(struct ccn_charbuf *c,
                             const struct ccn_forwarding_entry *fe)
{
    int res;
    res = ccnb_element_begin(c, CCN_DTAG_ForwardingEntry);
    if (fe->action != NULL)
        res |= ccnb_tagged_putf(c, CCN_DTAG_Action, "%s",
                                   fe->action);
    if (fe->name_prefix != NULL && fe->name_prefix->length > 0)
        res |= ccn_charbuf_append(c, fe->name_prefix->buf,
                                     fe->name_prefix->length);
    if (fe->ccnd_id_size != 0)
        res |= ccnb_append_tagged_blob(c, CCN_DTAG_PublisherPublicKeyDigest,
                                          fe->ccnd_id, fe->ccnd_id_size);
    if (fe->faceid != ~0)
        res |= ccnb_tagged_putf(c, CCN_DTAG_FaceID, "%u",
                                   fe->faceid);
    if (fe->flags >= 0)
        res |= ccnb_tagged_putf(c, CCN_DTAG_ForwardingFlags, "%d",
                                   fe->flags);
    if (fe->lifetime >= 0)
        res |= ccnb_tagged_putf(c, CCN_DTAG_FreshnessSeconds, "%d",
                                   fe->lifetime);
    res |= ccnb_element_end(c);
    return(res);
}
Beispiel #10
0
/**
 * Write some data to a seqwriter.
 *
 * This is roughly analogous to a write(2) call in non-blocking mode.
 *
 * The current implementation returns an error and refuses the new data if
 * it does not fit in the current buffer.
 * That is, there are no partial writes.
 * In this case, the caller should ccn_run() for a little while and retry.
 * 
 * It is also an error to attempt to write more than 4096 bytes.
 *
 * @returns the size written, or -1 for an error.  In case of an error,
 *          the caller may test ccn_geterror() for values of EAGAIN or
 *          EINVAL from errno.h.
 */
int
ccn_seqw_write(struct ccn_seqwriter *w, const void *buf, size_t size)
{
    struct ccn_charbuf *cob = NULL;
    int res;
    int ans;
    
    if (w == NULL || w->cl.data != w)
        return(-1);
    if (w->buffer == NULL || size > MAX_DATA_SIZE)
        return(ccn_seterror(w->h, EINVAL));
    ans = size;
    if (size + w->buffer->length > MAX_DATA_SIZE)
        ans = ccn_seterror(w->h, EAGAIN);
    else if (size != 0)
        ccn_charbuf_append(w->buffer, buf, size);
    if (w->interests_possibly_pending &&
        (w->batching == 0 || ans == -1)) {
        cob = seqw_next_cob(w);
        if (cob != NULL) {
            res = ccn_put(w->h, cob->buf, cob->length);
            if (res >= 0) {
                if (w->seqnum == 0) {
                    w->cob0 = cob;
                    cob = NULL;
                }
                w->buffer->length = 0;
                w->seqnum++;
                w->interests_possibly_pending = 0;
            }
            ccn_charbuf_destroy(&cob);
        }
    }
    return(ans);
}
Beispiel #11
0
struct ccn_charbuf* CcnbOR_read(CcnbOR self) {
	if (NBS_error(self->nbs)) {
		self->error = true;
		return NULL;
	}
	uint8_t* buf = (uint8_t*)malloc(2048);
	size_t readSize = NBS_read(self->nbs, buf, 2048, NULL);
	if (readSize == 0) {
		free(buf);
		return NULL;
	}
	ssize_t consumeSize = ccn_skeleton_decode(self->rd, buf, readSize);
	if (self->rd->state < 0) self->error = true;
	else ccn_charbuf_append(self->cbuf, buf, consumeSize);

	if (consumeSize < readSize) NBS_pushback(self->nbs, buf, consumeSize, readSize - consumeSize, NULL);
	else free(buf);

	if (CCN_FINAL_DSTATE(self->rd->state)) {
		struct ccn_charbuf* cbuf = self->cbuf;
		self->cbuf = ccn_charbuf_create();
		CcnbOR_clear(self);
		return cbuf;
	}
	return NULL;
}
Beispiel #12
0
/**
 * Parses a ccnb-encoded element expected to contain a UDATA string.
 * @param d is the decoder
 * @param dtag is the expected dtag value
 * @param store - on success, the string value is appended to store,
 *        with null termination.
 * @returns the offset into the store buffer of the copied value, or -1 for error.
 *        If a parse error occurs, d->decoder.state is set to a negative value.
 *        If the element is not present, -1 is returned but no parse error
 *        is indicated.
 */
int
ccn_parse_tagged_string(struct ccn_buf_decoder *d, enum ccn_dtag dtag, struct ccn_charbuf *store)
{
    const unsigned char *p = NULL;
    size_t size = 0;
    int res;
    
    if (ccn_buf_match_dtag(d, dtag)) {
        ccn_buf_advance(d);
        if (d->decoder.state >= 0 &&
            CCN_GET_TT_FROM_DSTATE(d->decoder.state) == CCN_UDATA) {
            res = store->length;
            p = d->buf + d->decoder.index;
            size = d->decoder.numval;
            ccn_buf_advance(d);
        }
        ccn_buf_check_close(d);
        if (d->decoder.state >= 0) {
            // XXX - should check for valid utf-8 data.
            res = store->length;
            if (size > 0)
                ccn_charbuf_append(store, p, size);
            ccn_charbuf_append_value(store, 0, 1);
            return(res);
        }
    }
    return(-1);
}
Beispiel #13
0
int ccnb_append_dhcp_content(struct ccn_charbuf *c, int count, const struct ccn_dhcp_entry *head)
{
    int res;
    int i;
    const struct ccn_dhcp_entry *de = head;

    res = ccnb_element_begin(c, CCN_DTAG_Entry);
    res |= ccnb_tagged_putf(c, CCN_DTAG_Count, "%d", count);

    for (i = 0; i < count; i ++) {
        if (de == NULL)
        {
            fprintf(stderr, "Error: number of ccn_dhcp_entry does not match\n");
            break;
        }

        if (de->name_prefix != NULL && de->name_prefix->length > 0)
            res |= ccn_charbuf_append(c, de->name_prefix->buf, de->name_prefix->length);

        if (de->address != NULL)
            res |= ccnb_tagged_putf(c, CCN_DTAG_Host, "%s", de->address);
        if (de->port != NULL)
            res |= ccnb_tagged_putf(c, CCN_DTAG_Port, "%s", de->port);

        de = de->next;
    }

    res |= ccnb_element_end(c);
    return res;
}
Beispiel #14
0
/**
 * Append AnswerOriginKind=1 to partially constructed Interest, meaning
 * do not generate new content.
 */
static void
answer_passive(struct ccn_charbuf *templ)
{
    ccn_charbuf_append_tt(templ, CCN_DTAG_AnswerOriginKind, CCN_DTAG);
    ccn_charbuf_append_tt(templ, 1, CCN_UDATA);
    ccn_charbuf_append(templ, "1", 1);
    ccn_charbuf_append_closer(templ); /* </AnswerOriginKind> */
}
Beispiel #15
0
int
ccn_charbuf_append_closer(struct ccn_charbuf *c)
{
    int res;
    const unsigned char closer = CCN_CLOSE;
    res = ccn_charbuf_append(c, &closer, 1);
    return(res);
}
// replace_name()
// Helper function to replace names in content objects
// Could build another version that works on already parsed content objects
// But as seen below it would be better to use a modified encoding call that
// didn't include the name at all.
//
int replace_name(struct ccn_charbuf* dest, unsigned char* src,  size_t src_size, struct ccn_charbuf* name) {
	struct ccn_parsed_ContentObject* pco = (struct ccn_parsed_ContentObject*) calloc(sizeof(struct ccn_parsed_ContentObject), 1);
	int res = 0;
	res = ccn_parse_ContentObject(src,src_size, pco, NULL);
    if (res < 0) {
    	free(pco);
    	return (res);
    }
	ccn_charbuf_append_tt(dest, CCN_DTAG_ContentObject, CCN_DTAG);
	ccn_charbuf_append(dest, &src[pco->offset[CCN_PCO_B_Signature]], pco->offset[CCN_PCO_E_Signature] - pco->offset[CCN_PCO_B_Signature]);
	ccn_charbuf_append_charbuf(dest, name); // Already tagged
	ccn_charbuf_append(dest, &src[pco->offset[CCN_PCO_B_SignedInfo]], pco->offset[CCN_PCO_E_SignedInfo] - pco->offset[CCN_PCO_B_SignedInfo]);
	ccnb_append_tagged_blob(dest, CCN_DTAG_Content, NULL, 0);
	ccn_charbuf_append_closer(dest);
	free(pco);
	return (0);
}
Beispiel #17
0
int ccn_dhcp_content_parse(const unsigned char *p, size_t size, struct ccn_dhcp_entry *tail)
{
    struct ccn_buf_decoder decoder;
    struct ccn_buf_decoder *d = ccn_buf_decoder_start(&decoder, p, size);
    int i;
    int count;
    struct ccn_dhcp_entry *de = tail;

    if (ccn_buf_match_dtag(d, CCN_DTAG_Entry)) {
        ccn_buf_advance(d);

        count = ccn_parse_optional_tagged_nonNegativeInteger(d, CCN_DTAG_Count);

        for (i = 0; i < count; i ++) {
            struct ccn_charbuf *store = ccn_charbuf_create();
            size_t start;
            size_t end;
            int host_off = -1;
            int port_off = -1;

            de->next = calloc(1, sizeof(*de));
            de = de->next;
            memset(de, 0, sizeof(*de));
            de->store = store;
            de->next = NULL;

            if (ccn_buf_match_dtag(d, CCN_DTAG_Name)) {
                de->name_prefix = ccn_charbuf_create();
                start = d->decoder.token_index;
                ccn_parse_Name(d, NULL);
                end = d->decoder.token_index;
                ccn_charbuf_append(de->name_prefix, p + start, end - start);
            }
            else
                de->name_prefix = NULL;

            host_off = ccn_parse_tagged_string(d, CCN_DTAG_Host, store);
            port_off = ccn_parse_tagged_string(d, CCN_DTAG_Port, store);

            char *b = (char *)store->buf;
            char *h = b + host_off;
            char *p = b + port_off;
            if (host_off >= 0)
                memcpy((void *)de->address, h, strlen(h));
            if (port_off >= 0)
                memcpy((void *)de->port, p, strlen(p));
        }
    }
    else
        d->decoder.state = -__LINE__;

    if (d->decoder.index != size || !CCN_FINAL_DSTATE(d->decoder.state))
        ccn_dhcp_content_destroy(tail->next);

    return count;
}
Beispiel #18
0
struct ccn_charbuf* SockAddr_hashkey(SockAddr self) {
    if (self->hashkey == NULL) self->hashkey = ccn_charbuf_create();
    else ccn_charbuf_reset(self->hashkey);
    switch (self->addr->sa_family) {
        case AF_INET6: {
            struct sockaddr_in6* sin6 = (struct sockaddr_in6*)self->addr;
            ccn_charbuf_append(self->hashkey, &(sin6->sin6_addr), sizeof(struct in6_addr));
            ccn_charbuf_append(self->hashkey, &(sin6->sin6_port), sizeof(in_port_t));
        } break;
        case AF_PACKET: {
            struct sockaddr_ll* sll = (struct sockaddr_ll*)self->addr;
            ccn_charbuf_append(self->hashkey, &(sll->sll_addr), sll->sll_halen);
        } break;
        default:
        ccn_charbuf_append(self->hashkey, self->addr, self->addrlen);
        break;
    }
    return self->hashkey;
}
Beispiel #19
0
static void
append_future_vcomp(struct ccn_charbuf *templ)
{
    /* One beyond a distant future version stamp */
    unsigned char b[7] = {CCN_MARKER_VERSION + 1, 0, 0, 0, 0, 0, 0};
    ccn_charbuf_append_tt(templ, CCN_DTAG_Component, CCN_DTAG);
    ccn_charbuf_append_tt(templ, sizeof(b), CCN_BLOB);
    ccn_charbuf_append(templ, b, sizeof(b));
    ccn_charbuf_append_closer(templ); /* </Component> */
}
Beispiel #20
0
/*
 * This appends a tagged, valid, fully-saturated Bloom filter, useful for
 * excluding everything between two 'fenceposts' in an Exclude construct.
 */
static void
append_bf_all(struct ccn_charbuf *c)
{
    unsigned char bf_all[9] = { 3, 1, 'A', 0, 0, 0, 0, 0, 0xFF };
    const struct ccn_bloom_wire *b = ccn_bloom_validate_wire(bf_all, sizeof(bf_all));
    if (b == NULL) abort();
    ccn_charbuf_append_tt(c, CCN_DTAG_Bloom, CCN_DTAG);
    ccn_charbuf_append_tt(c, sizeof(bf_all), CCN_BLOB);
    ccn_charbuf_append(c, bf_all, sizeof(bf_all));
    ccn_charbuf_append_closer(c);
}
int
ccn_uri_append(struct ccn_charbuf *c,
               const unsigned char *ccnb,
               size_t size,
               int includescheme)
{
    int ncomp = 0;
    const unsigned char *comp = NULL;
    size_t compsize = 0;
    struct ccn_buf_decoder decoder;
    struct ccn_buf_decoder *d = ccn_buf_decoder_start(&decoder, ccnb, size);
    if (ccn_buf_match_dtag(d, CCN_DTAG_Interest)    ||
        ccn_buf_match_dtag(d, CCN_DTAG_ContentObject)) {
        ccn_buf_advance(d);
        if (ccn_buf_match_dtag(d, CCN_DTAG_Signature))
            ccn_buf_advance_past_element(d);
    }
    if (!ccn_buf_match_dtag(d, CCN_DTAG_Name))
        return(-1);
    if (includescheme)
        ccn_charbuf_append_string(c, "ccnx:");
    ccn_buf_advance(d);
    while (ccn_buf_match_dtag(d, CCN_DTAG_Component)) {
        ccn_buf_advance(d);
        compsize = 0;
        if (ccn_buf_match_blob(d, &comp, &compsize))
            ccn_buf_advance(d);
        ccn_buf_check_close(d);
        if (d->decoder.state < 0)
            return(d->decoder.state);
        ncomp += 1;
        ccn_charbuf_append(c, "/", 1);
        ccn_uri_append_percentescaped(c, comp, compsize);
    }
    ccn_buf_check_close(d);
    if (d->decoder.state < 0)
        return (d->decoder.state);
    if (ncomp == 0)
        ccn_charbuf_append(c, "/", 1);
    return(ncomp);
}
Beispiel #22
0
/**
 * Create a seqwriter for writing data to a versioned, segmented stream.
 *
 * @param name is a ccnb-encoded Name.  It will be provided with a version
 *        based on the current time unless it already ends in a version
 *        component.
 */
struct ccn_seqwriter *
ccn_seqw_create(struct ccn *h, struct ccn_charbuf *name)
{
    struct ccn_seqwriter *w = NULL;
    struct ccn_charbuf *nb = NULL;
    struct ccn_charbuf *nv = NULL;
    int res;
    
    w = calloc(1, sizeof(*w));
    if (w == NULL)
        return(NULL);
    nb = ccn_charbuf_create();
    ccn_charbuf_append(nb, name->buf, name->length);
    nv = ccn_charbuf_create();
    ccn_charbuf_append(nv, name->buf, name->length);
    res = ccn_create_version(h, nv, CCN_V_NOW, 0, 0);
    if (res < 0 || nb == NULL) {
        ccn_charbuf_destroy(&nv);
        ccn_charbuf_destroy(&nb);
        free(w);
        return(NULL);
    }
    
    w->cl.p = &seqw_incoming_interest;
    w->cl.data = w;
    w->nb = nb;
    w->nv = nv;
    w->buffer = ccn_charbuf_create();
    w->h = h;
    w->seqnum = 0;
    w->interests_possibly_pending = 1;
    res = ccn_set_interest_filter(h, nb, &(w->cl));
    if (res < 0) {
        ccn_charbuf_destroy(&w->nb);
        ccn_charbuf_destroy(&w->nv);
        ccn_charbuf_destroy(&w->buffer);
        free(w);
        return(NULL);
    }
    return(w);
}
Beispiel #23
0
/**
 * Base loop for the background CCN task
 *
 * This is the main execution loop for the background task responsible for
 * interacting with the CCN network. It is from this point that many of the above methods are
 * called to work the inbound messages from ccnx as well as sending out the data messages.
 *
 * \param data		the task context information setup by the parent sink element thread
 */
static void
ccn_event_thread (void *data)
{
  Gstccnxsink *me = (Gstccnxsink *) data;
  struct ccn_charbuf *filtName;
  struct ccn_charbuf *temp;
  int res = 0;

  GST_DEBUG ("CCNxSink event: *** event thread starting");

  temp = ccn_charbuf_create ();
  filtName = ccn_charbuf_create ();

  /* A closure is what defines what to do when an inbound interest arrives */
  if ((me->ccn_closure = calloc (1, sizeof (struct ccn_closure))) == NULL) {
    GST_ELEMENT_ERROR (me, RESOURCE, READ, (NULL), ("closure alloc failed"));
    return;
  }

  /* We setup the closure to contain the sink element context reference, and also tell it what function to call */
  me->ccn_closure->data = me;
  me->ccn_closure->p = new_interests;
  me->timeouts = 0;
  ccn_charbuf_append (filtName, me->name->buf, me->name->length);

  /* This call will set up a handler for interests we expect to get from clients */

  // hDump(DUMP_ADDR(filtName->buf), DUMP_SIZE(filtName->length));
  ccn_set_interest_filter (me->ccn, filtName, me->ccn_closure);
  GST_DEBUG ("CCNxSink event: interest filter registered\n");

  /* Some debugging information */
  temp->length = 0;
  ccn_uri_append (temp, me->name->buf, me->name->length, TRUE);
  GST_DEBUG ("CCNxSink event: using uri: %s\n", ccn_charbuf_as_string (temp));

  /* Now that the interest is registered, we loop around waiting for something to do */
  /* We pass control to ccnx for a while so it can work with any incoming or outgoing data */
  /* and then we check our fifo queue for work to do. That's about it! */
  /* We check to see if any problems have caused our ccnd connection to fail, and we reconnect */
  while (res >= 0) {
    GST_DEBUG ("CCNxSink event: *** looping");
    res = ccn_run (me->ccn, 50);
    check_fifo (me);
    if (res < 0 && ccn_get_connection_fd (me->ccn) == -1) {
      GST_DEBUG ("CCNxSink event: need to reconnect...");
      /* Try reconnecting, after a bit of delay */
      msleep ((30 + (getpid () % 30)) * 1000);
      res = ccn_connect (me->ccn, ccndHost ());
    }
  }
  GST_DEBUG ("CCNxSink event: *** event thread ending");
}
Beispiel #24
0
static void init_all_chars_mixed_encoded(void) {
    struct ccn_charbuf *c;
    int i;
    c = ccn_charbuf_create();
    ccn_charbuf_append(c, "=", 1);
    for (i = 0; i < 256; i+=2) {
        ccn_charbuf_putf(c, "%02x%02X", i, i+1);
    }
    if (c->length >= sizeof(all_chars_mixed_encoded))
        c->length = sizeof(all_chars_mixed_encoded) - 1;
    memcpy(all_chars_mixed_encoded, c->buf, c->length);
    ccn_charbuf_destroy(&c);
}
Beispiel #25
0
static int
ccn_encode_Signature(struct ccn_charbuf *buf,
                     const char *digest_algorithm,
                     const void *witness,
                     size_t witness_size,
                     const struct ccn_signature *signature,
                     size_t signature_size)
{
    int res = 0;

    if (signature == NULL)
        return(-1);

    res |= ccn_charbuf_append_tt(buf, CCN_DTAG_Signature, CCN_DTAG);

    if (digest_algorithm != NULL) {
        res |= ccn_charbuf_append_tt(buf, CCN_DTAG_DigestAlgorithm, CCN_DTAG);
        res |= ccn_charbuf_append_tt(buf, strlen(digest_algorithm), CCN_UDATA);
        res |= ccn_charbuf_append_string(buf, digest_algorithm);
        res |= ccn_charbuf_append_closer(buf);
    }

    if (witness != NULL) {
        res |= ccn_charbuf_append_tt(buf, CCN_DTAG_Witness, CCN_DTAG);
        res |= ccn_charbuf_append_tt(buf, witness_size, CCN_BLOB);
        res |= ccn_charbuf_append(buf, witness, witness_size);
        res |= ccn_charbuf_append_closer(buf);
    }

    res |= ccn_charbuf_append_tt(buf, CCN_DTAG_SignatureBits, CCN_DTAG);
    res |= ccn_charbuf_append_tt(buf, signature_size, CCN_BLOB);
    res |= ccn_charbuf_append(buf, signature, signature_size);
    res |= ccn_charbuf_append_closer(buf);
    
    res |= ccn_charbuf_append_closer(buf);

    return(res == 0 ? 0 : -1);
}
Beispiel #26
0
static PyObject *
Name_obj_from_ccn_parsed(PyObject *py_content_object)
{
    struct ccn_charbuf *content_object;
    struct ccn_parsed_ContentObject *parsed_content_object;
    PyObject *py_ccn_name;
    PyObject *py_Name;
    struct ccn_charbuf *name;
    size_t name_begin, name_end, s;
    int r;

    assert(CCNObject_IsValid(CONTENT_OBJECT, py_content_object));

    content_object = CCNObject_Get(CONTENT_OBJECT, py_content_object);
    parsed_content_object = _pyccn_content_object_get_pco(py_content_object);
    if (!parsed_content_object)
        return NULL;

    name_begin = parsed_content_object->offset[CCN_PCO_B_Name];
    name_end = parsed_content_object->offset[CCN_PCO_E_Name];
    s = name_end - name_begin;

    debug("ContentObject_from_ccn_parsed Name len=%zd\n", s);
    if (parsed_content_object->name_ncomps <= 0) {
        PyErr_SetString(g_PyExc_CCNNameError, "No name stored (or name is"
                        " invalid) in parsed content object");
        return NULL;
    }

    py_ccn_name = CCNObject_New_charbuf(NAME, &name);
    if (!py_ccn_name)
        return NULL;

    r = ccn_charbuf_append(name, &content_object->buf[name_begin], s);
    if (r < 0) {
        Py_DECREF(py_ccn_name);
        return PyErr_NoMemory();
    }

#if DEBUG_MSG
    debug("Name: ");
    dump_charbuf(name, stderr);
    debug("\n");
#endif

    py_Name = Name_obj_from_ccn(py_ccn_name);
    Py_DECREF(py_ccn_name);

    return py_Name;
}
Beispiel #27
0
int NdnMediaProcess::checkInterest()
{
    int res = 0;
    QHash<QString,UserDataBuf *>::iterator it; 
	ruMutex->lock();
    for ( it = qhRemoteUser.begin(); it != qhRemoteUser.end(); ++it ) {
        if (!it.value()->interested) {
            /* Use a template to express our order preference for the first packet. */
            struct ccn_charbuf *templ = ccn_charbuf_create();
            struct ccn_charbuf *path = ccn_charbuf_create();
            ccn_charbuf_append_tt(templ, CCN_DTAG_Interest, CCN_DTAG);
            ccn_charbuf_append_tt(templ, CCN_DTAG_Name, CCN_DTAG);
            ccn_charbuf_append_closer(templ);
            ccn_charbuf_append_tt(templ, CCN_DTAG_ChildSelector, CCN_DTAG);
            ccn_charbuf_append_tt(templ, 1, CCN_UDATA);
            ccn_charbuf_append(templ, "1", 1);	/* low bit 1: rightmost */
            ccn_charbuf_append_closer(templ); /*<ChildSelector>*/
            ccn_charbuf_append_closer(templ);
			ccn_name_from_uri(path, it.key().toLocal8Bit().constData());
			ccn_name_append_str(path, "audio");
            if (res >= 0) {
                if (it.value()->data_buf.callback->p == NULL) {fprintf(stderr, "data_buf.callback is NULL!\n"); exit(1); }
				/*
				int c = 0;
				while (pthread_mutex_trylock(&ccn_mutex) != 0) {
					c++;
					if (c > 10000000) {
						fprintf(stderr, "cannot obtain lock! %s:%d\n", __FILE__, __LINE__);
						std::exit(1);
					}
				}
				*/
				pthread_mutex_lock(&ccn_mutex);
                res = ccn_express_interest(ndnState.ccn, path, it.value()->data_buf.callback, templ);
				pthread_mutex_unlock(&ccn_mutex);
                it.value()->interested = 1;
				fprintf(stderr, "short interest sent\n");
            }
            if (res < 0) {
				fprintf(stderr, "sending the first interest failed\n");
				exit(1);
			}
            ccn_charbuf_destroy(&path);
            ccn_charbuf_destroy(&templ);
        }
    }
	ruMutex->unlock();
    return res;
}
Beispiel #28
0
Name
ParsedContentObject::keyName() const
{
  if (m_pco.offset[CCN_PCO_E_KeyName_Name] > m_pco.offset[CCN_PCO_B_KeyName_Name])
  {
    CharbufPtr ptr = boost::make_shared<Charbuf>();
    ccn_charbuf_append(ptr->getBuf(), head(m_bytes) + m_pco.offset[CCN_PCO_B_KeyName_Name], m_pco.offset[CCN_PCO_E_KeyName_Name] - m_pco.offset[CCN_PCO_B_KeyName_Name]);

    return Name(*ptr);
  }
  else
  {
    return Name();
  }
}
Beispiel #29
0
/**
 * Append a tagged BLOB
 *
 * This is a ccnb-encoded element with containing the BLOB as content
 * @param c is the buffer to append to.
 * @param dtag is the element's dtab
 * @param data points to the binary data
 * @param size is the size of the data, in bytes
 * @returns 0 for success or -1 for error.
 */
int
ccnb_append_tagged_blob(struct ccn_charbuf *c,
                        enum ccn_dtag dtag,
                        const void *data,
                        size_t size)
{
    int res;

    res = ccn_charbuf_append_tt(c, dtag, CCN_DTAG);
    if (size != 0) {
        res |= ccn_charbuf_append_tt(c, size, CCN_BLOB);
        res |= ccn_charbuf_append(c, data, size);
    }
    res |= ccn_charbuf_append_closer(c);
    return(res == 0 ? 0 : -1);
}
Beispiel #30
0
/**
 * Append a ccnb start marker
 *
 * This forms the basic building block of ccnb-encoded data.
 * @param c is the buffer to append to.
 * @param val is the numval, intepreted according to tt (see enum ccn_tt).
 * @param tt is the type field.
 * @returns 0 for success or -1 for error.
 */
int
ccn_charbuf_append_tt(struct ccn_charbuf *c, size_t val, enum ccn_tt tt)
{
    unsigned char buf[1+8*((sizeof(val)+6)/7)];
    unsigned char *p = &(buf[sizeof(buf)-1]);
    int n = 1;
    p[0] = (CCN_TT_HBIT & ~CCN_CLOSE) |
           ((val & CCN_MAX_TINY) << CCN_TT_BITS) |
           (CCN_TT_MASK & tt);
    val >>= (7-CCN_TT_BITS);
    while (val != 0) {
        (--p)[0] = (((unsigned char)val) & ~CCN_TT_HBIT) | CCN_CLOSE;
        n++;
        val >>= 7;
    }
    return(ccn_charbuf_append(c, p, n));
}