Пример #1
0
void content_received(struct ccn_upcall_info *info, struct ccn_closure *selfp) {
    UserDataBuf *userBuf  = (UserDataBuf *)selfp->data;
    struct data_buffer *buffer = &userBuf->data_buf;
    const unsigned char *content_value;
    NDNState *state = buffer->state;

	const unsigned char *ccnb = info->content_ccnb;
	size_t ccnb_size = info->pco->offset[CCN_PCO_E];
	struct ccn_indexbuf *comps = info->content_comps;

	/* Append it to the queue */
	struct buf_list *b;
	b = (struct buf_list *)calloc(1, sizeof(*b));
	b->link = NULL;
	ccn_content_get_value(ccnb, ccnb_size, info->pco,
			&content_value, &b->len);
	b->buf = malloc(b->len);
	memcpy(b->buf, content_value, b->len);
	if (buffer->buflist == NULL)
		buffer->buflist = b;
	else {
		struct buf_list *p = buffer->buflist;
		while (p->link != NULL)
			p = p->link;
		p->link = b;
	}
	/*emit the signal for get the data out of the buffer*/
	state->emitSignal(userBuf->user_name);
}
Пример #2
0
extern int
SyncCacheEntryFetch(struct SyncHashCacheEntry *ce) {
    // causes the cache entry to fetched from the repo
    char *here = "Sync.SyncCacheEntryFetch";
    int res = 0;
    if (ce == NULL) {
        // not an entry
        res = -1;
    } else if (ce->ncL != NULL) {
        // it's already here
        res = 0;
    } else if ((ce->state & SyncHashState_stored) == 0) {
        // it's never been stored, fail quietly
        res = -1;
    } else {
        // at this point we try to fetch it from the local repo
        // a failure should complain
        struct SyncRootStruct *root = ce->head->root;
        struct SyncBaseStruct *base = root->base;
        struct ccn_charbuf *name = SyncNameForLocalNode(root, ce->hash);
        struct ccn_charbuf *content = ccn_charbuf_create();
        char *why = "no fetch";
        struct ccn_parsed_ContentObject pcos;
        
        res = SyncLocalRepoFetch(base, name, content, &pcos);
        if (res >= 0) {
            // parse the object
            const unsigned char *xp = NULL;
            size_t xs = 0;
            // get the encoded node
            res = ccn_content_get_value(content->buf, content->length,
                                        &pcos, &xp, &xs);
            if (res < 0)
                why = "ccn_content_get_value failed";
            else {
                struct ccn_buf_decoder ds;
                struct ccn_buf_decoder *d = ccn_buf_decoder_start(&ds, xp, xs);
                struct SyncNodeComposite *nc = SyncAllocComposite(root->base);
                res |= SyncParseComposite(nc, d);
                if (res < 0) {
                    // failed, so back out of the allocations
                    why = "bad parse";
                    SyncFreeComposite(nc);
                    nc = NULL;
                } else {
                    res = 1;
                    SyncNodeIncRC(nc);
                    ce->ncL = nc;
                    ce->state |= SyncHashState_stored;
                }
            }
        }
        if (res < 0)
            if (root->base->debug >= CCNL_ERROR)
                SyncNoteUri(root, here, why, name);
        ccn_charbuf_destroy(&name);
        ccn_charbuf_destroy(&content);
    }
    return res;
}
Пример #3
0
// extractNode parses and creates a sync tree node from an upcall info
// returns NULL if there was any kind of error
static struct SyncNodeComposite *
extractNode(struct SyncRootStruct *root, struct ccn_upcall_info *info) {
    // first, find the content
    char *here = "sync_track.extractNode";
    const unsigned char *cp = NULL;
    size_t cs = 0;
    size_t ccnb_size = info->pco->offset[CCN_PCO_E];
    const unsigned char *ccnb = info->content_ccnb;
    int res = ccn_content_get_value(ccnb, ccnb_size, info->pco,
                                    &cp, &cs);
    if (res < 0 || cs < DEFAULT_HASH_BYTES) {
        SyncNoteFailed(root, here, "ccn_content_get_value", __LINE__);
        return NULL;
    }
    
    // second, parse the object
    struct SyncNodeComposite *nc = SyncAllocComposite(root->base);
    struct ccn_buf_decoder ds;
    struct ccn_buf_decoder *d = ccn_buf_decoder_start(&ds, cp, cs);
    res |= SyncParseComposite(nc, d);
    if (res < 0) {
        // failed, so back out of the allocations
        SyncNoteFailed(root, here, "bad parse", -res);
        SyncFreeComposite(nc);
        nc = NULL;
    }
    return nc;
}
Пример #4
0
/**
 *
 * Create new face by sending out a request Interest
 * The actual new face instance is returned
 * 
 */
static 
struct ccn_face_instance *create_face(struct ccn *h, struct ccn_charbuf *local_scope_template,
        struct ccn_charbuf *no_name, struct ccn_face_instance *face_instance)
{
	struct ccn_charbuf *newface = NULL;
	struct ccn_charbuf *signed_info = NULL;
	struct ccn_charbuf *temp = NULL;
	struct ccn_charbuf *name = NULL;
	struct ccn_charbuf *resultbuf = NULL;
	struct ccn_parsed_ContentObject pcobuf = {0};
	struct ccn_face_instance *new_face_instance = NULL;
	const unsigned char *ptr = NULL;
	size_t length = 0;
	int res = 0;

	/* Encode the given face instance */
	newface = ccn_charbuf_create();
	ccnb_append_face_instance(newface, face_instance);

	temp = ccn_charbuf_create();
	res = ccn_sign_content(h, temp, no_name, NULL, newface->buf, newface->length);
	resultbuf = ccn_charbuf_create();

	/* Construct the Interest name that will create the face */
	name = ccn_charbuf_create();
	ccn_name_init(name);
	ccn_name_append_str(name, "ccnx");
	ccn_name_append(name, face_instance->ccnd_id, face_instance->ccnd_id_size);
	ccn_name_append_str(name, face_instance->action);
	ccn_name_append(name, temp->buf, temp->length);

	/* send Interest to retrieve Data that contains the newly created face */
	res = ccn_get(h, name, local_scope_template, 1000, resultbuf, &pcobuf, NULL, 0);
	ON_ERROR_CLEANUP(res);

	/* decode Data to get the actual face instance */
	res = ccn_content_get_value(resultbuf->buf, resultbuf->length, &pcobuf, &ptr, &length);
	ON_ERROR_CLEANUP(res);

	new_face_instance = ccn_face_instance_parse(ptr, length);

	ccn_charbuf_destroy(&newface);
	ccn_charbuf_destroy(&signed_info);
	ccn_charbuf_destroy(&temp);
	ccn_charbuf_destroy(&resultbuf);
	ccn_charbuf_destroy(&name);

	return new_face_instance;

	cleanup:
		ccn_charbuf_destroy(&newface);
		ccn_charbuf_destroy(&signed_info);
		ccn_charbuf_destroy(&temp);
		ccn_charbuf_destroy(&resultbuf);
		ccn_charbuf_destroy(&name);

	return NULL;
}
Пример #5
0
/*
 * newServerHandler
 *
 * Expecting a string containing the URI for the client
 */
static enum ccn_upcall_res
newServerHandler(struct ccn_closure *selfp,
        enum ccn_upcall_kind kind,
        struct ccn_upcall_info *info)
{
    dropbear_log(LOG_WARNING,"Enter newServerHandler");
    dropbear_log(LOG_WARNING,"Got interest matching %d components, kind = %d\n", info->matched_comps, kind);
    int result;

    const unsigned char *ccnb = NULL;
    size_t ccnb_size;

    void *data = NULL;
    size_t data_size = 0;

    switch (kind) {
        case CCN_UPCALL_CONTENT:
            break;
        case CCN_UPCALL_INTEREST_TIMED_OUT:
            return CCN_UPCALL_RESULT_REEXPRESS;
        case CCN_UPCALL_CONTENT_UNVERIFIED:
            // TODO: fix verification
            break;
        default:
            return CCN_UPCALL_RESULT_ERR;
    }

    dropbear_log(LOG_WARNING,"Interest to");
    print_ccnb_name(info);

    ccnb = info->content_ccnb;
    ccnb_size = info->pco->offset[CCN_PCO_E];

    result = ccn_content_get_value(ccnb, ccnb_size, info->pco, (const unsigned char **)&data, &data_size);
    if( result < 0 )
        dropbear_exit("Could not parse reply message");

    dropbear_log(LOG_WARNING,"newServerHandler: parsing contents");
    if( strncmp((char *)data,"ccnx:/",6) == 0 ) {
        cli_opts.remote_name_str = (char *)data;
        dropbear_log(LOG_WARNING,"newServerHandler: matches: %s (%d)",data,data_size);
        ses.remote_name = ccn_charbuf_create();
        result = ccn_name_from_uri(ses.remote_name,cli_opts.remote_name_str);
        if( result < 0 )
            dropbear_exit("Did not find expected uri in server response");

        // Start a new session
        dropbear_log(LOG_WARNING,"Connected to server at");
        print_ccnb_charbuf(ses.remote_name);
        
        cli_session(cli_opts.ccnxdomain,cli_opts.remote_name_str);

        return CCN_UPCALL_RESULT_OK;
    } else {
        dropbear_log(LOG_WARNING,"newServerHandler: doesn't match");
        return CCN_UPCALL_RESULT_ERR;
    }
}
Пример #6
0
BytesPtr
ParsedContentObject::contentPtr() const
{
  const unsigned char *content;
  size_t len;
  int res = ccn_content_get_value(head(m_bytes), m_pco.offset[CCN_PCO_E], &m_pco, &content, &len);
  if (res < 0)
  {
    boost::throw_exception(MisformedContentObjectException());
  }

  return readRawPtr (content, len);
}
Пример #7
0
int
decode_message(struct ccn_charbuf *message, struct path * name_path, char *data, size_t len,
               const void *verkey) {
    struct ccn_parsed_ContentObject content;
    struct ccn_indexbuf *comps = ccn_indexbuf_create();
    const unsigned char * content_value;
    size_t content_length;

    int res = 0;
    int i;

    memset(&content, 0x33, sizeof(content));

    if (ccn_parse_ContentObject(message->buf, message->length, &content, comps) != 0) {
        printf("Decode failed to parse object\n");
        res = -1;
    }

    if (comps->n-1 != name_path->count) {
        printf("Decode got wrong number of path components: %d vs. %d\n",
            (int)(comps->n-1), name_path->count);
        res = -1;
    }
    for (i=0; i<name_path->count; i++) {
        if (ccn_name_comp_strcmp(message->buf, comps, i, name_path->comps[i]) != 0) {
            printf("Decode mismatch on path component %d\n", i);
            res = -1;
        }
    }
    if (ccn_content_get_value(message->buf, message->length, &content,
        &content_value, &content_length) != 0) {
        printf("Cannot retrieve content value\n");
        res = -1;
    } else if (content_length != len) {
        printf("Decode mismatch on content length %d vs. %d\n",
            (int)content_length, (int)len);
        res = -1;
    } else if (memcmp(content_value, data, len) != 0) {
        printf("Decode mismatch of content\n");
        res = -1;
    }

    if (ccn_verify_signature(message->buf, message->length, &content, verkey) != 1) {
        printf("Signature did not verify\n");
        res = -1;
    }

    ccn_indexbuf_destroy(&comps);
    return res;

}
Пример #8
0
void GroupManager::incomingContent(ccn_upcall_info *info) {
    size_t len = 0;
    unsigned char *valuep = NULL;
    ccn_content_get_value(info->content_ccnb, info->pco->offset[CCN_PCO_E],
                          info->pco,
                          (const unsigned char **)&valuep, &len);

    if (-1 == parseXmlUserList(valuep, len)) {
        debug("Invalid user list format received"); 
    }
	
	if (valuep != NULL) {
		valuep = NULL;
	}

	// already have the lock
	enumerate();
}
Пример #9
0
static enum ccn_upcall_res
incoming_handler(
    struct ccn_closure* selfp,
    enum ccn_upcall_kind kind,
    struct ccn_upcall_info* info)
{
    unsigned int i;
    int res;
    const unsigned char *ptr;
    size_t length;

    printf("Received response (kind: %d)\n", kind);
    switch(kind) {
    case CCN_UPCALL_FINAL:
        printf("deregistering handler\n");
        return CCN_UPCALL_RESULT_OK;

    case CCN_UPCALL_CONTENT:
        printf("received content\n");
        res = ccn_content_get_value(info->content_ccnb, info->pco->offset[CCN_PCO_E], info->pco, &ptr, &length);

        printf("Output: ");
        for (i = 0; i < length; i++) {
            putchar(ptr[i]);
        }
        break;

    case CCN_UPCALL_INTEREST_TIMED_OUT:
        printf("request timed out - retrying\n");
        return CCN_UPCALL_RESULT_REEXPRESS;

    case CCN_UPCALL_CONTENT_UNVERIFIED:
    case CCN_UPCALL_CONTENT_BAD:
        printf("error\n");
        return CCN_UPCALL_RESULT_ERR;

    default:
        printf("Unexpected response\n");
        return CCN_UPCALL_RESULT_ERR;
    }

    return CCN_UPCALL_RESULT_OK;
}
Пример #10
0
/**
 * Request the current segment number from the ccnx data producer
 *
 * This is a request for meta data for the media stream the user has named with their URI.
 * We assume that they want to join the media broadcast from what is currently being published
 * and \em not want to start from the beginning...although there is good reason for that too.
 *
 * Getting this data is done by expressing interests in the meta data. The producer of the
 * media stream will catch this through one of its ccnx filters and produce this meta data
 * back through the network to us.
 *
 * \param h		ccnx context handle
 * \param name	the content name for which we desire the meta data
 * \param timeout	how long to wait around
 * \return the segment number to ask for first, 0 on timeout
 */
static uintmax_t *
get_segment (struct ccn *h, struct ccn_charbuf *name, int timeout)
{
  struct ccn_charbuf *hn;
  uintmax_t *result = NULL;
  int res = 0;

  GST_INFO ("get_segment step 1");
  hn = ccn_charbuf_create ();
  // ccn_name_append_components(hn, name->buf, 0, name->length );
  ccn_charbuf_append_charbuf (hn, name);
  ccn_name_from_uri (hn, "_meta_/.segment");
  // ccn_name_append_str(hn, "_meta_");
  // ccn_name_append_str(hn, ".segment");
  GST_INFO ("get_segment step 2");
  // res = ccn_resolve_version(h, hn, CCN_V_HIGHEST, timeout);
  GST_INFO ("get_segment step 3, res: %d", res);
  if (res == 0) {
    struct ccn_charbuf *ho = ccn_charbuf_create ();
    struct ccn_parsed_ContentObject pcobuf = { 0 };
    const unsigned char *hc;
    size_t hcs;

    // hDump(DUMP_ADDR(hn->buf), DUMP_SIZE(hn->length));
    GST_INFO ("get_segment step 10");
    res = ccn_get (h, hn, NULL, timeout, ho, &pcobuf, NULL, 0);
    GST_INFO ("get_segment step 11, res: %d", res);
    if (res >= 0) {
      hc = ho->buf;
      hcs = ho->length;
      // hDump( DUMP_ADDR(hc), DUMP_SIZE(hcs));
      ccn_content_get_value (hc, hcs, &pcobuf, &hc, &hcs);
      // hDump( DUMP_ADDR(hc), DUMP_SIZE(hcs));
      result = calloc (1, sizeof (uintmax_t));
      memcpy (result, hc, sizeof (uintmax_t));
    }
    ccn_charbuf_destroy (&ho);
  }
  GST_INFO ("get_segment step 9");
  ccn_charbuf_destroy (&hn);
  return (result);
}
Пример #11
0
/**
 * Read a slice (from a repository) given the name.
 * @param h is the ccn_handle on which to read.
 * @param name is the charbuf containing the name of the sync slice to be read.
 * @param slice is a pointer to a ccns_slice object which will be filled in
 *  on successful return.
 * @returns 0 on success, -1 otherwise.
 */
int
ccns_read_slice(struct ccn *h, struct ccn_charbuf *name,
                struct ccns_slice *slice) {
    struct ccn_parsed_ContentObject pco_space = { 0 };
    struct ccn_parsed_ContentObject *pco = &pco_space;
    struct ccn_charbuf *nc = ccn_charbuf_create_n(name->length);
    struct ccn_charbuf *cob = ccn_charbuf_create();
    const unsigned char *content;
    size_t content_length;
    int res = -1;

    if (nc == NULL || cob == NULL)
        goto Cleanup;

    ccn_charbuf_append_charbuf(nc, name);
    res = ccn_resolve_version(h, nc,  CCN_V_HIGHEST, 100); // XXX: timeout
    if (res < 0)
        goto Cleanup;
    if (res == 0) {
        // TODO: check if the last component is a segment number, chop it off, try again.
    }
    res = ccn_get(h, nc, NULL, 100, cob, pco, NULL, 0);
    if (res < 0)
        goto Cleanup;
    if (pco->type != CCN_CONTENT_DATA) {
        res = -1;
        goto Cleanup;
    }
    res = ccn_content_get_value(cob->buf, cob->length, pco,
                                &content, &content_length);
    if (res < 0)
        goto Cleanup;
    res = slice_parse(slice, content, content_length);

Cleanup:
    ccn_charbuf_destroy(&nc);
    ccn_charbuf_destroy(&cob);
    return (res);
}
Пример #12
0
static PyObject *
Content_from_ccn_parsed(struct ccn_charbuf *content_object,
                        struct ccn_parsed_ContentObject *parsed_content_object)
{
    const char *value;
    size_t size;
    PyObject *py_content;
    int r;

    r = ccn_content_get_value(content_object->buf, content_object->length,
                              parsed_content_object, (const unsigned char **) &value, &size);
    if (r < 0) {
        PyErr_Format(g_PyExc_CCNError, "ccn_content_get_value() returned"
                     " %d", r);
        return NULL;
    }

    py_content = PyBytes_FromStringAndSize(value, size);
    if (!py_content)
        return NULL;

    return py_content;
}
Пример #13
0
enum ccn_upcall_res CcnLAC_fetchFaceidCb(struct ccn_closure* selfp, enum ccn_upcall_kind kind, struct ccn_upcall_info* info) {
	CcnLAC self = (CcnLAC)selfp->data;
	switch (kind) {
		case CCN_UPCALL_FINAL: {
			free(selfp);
			return CCN_UPCALL_RESULT_OK;
		}
		case CCN_UPCALL_INTEREST_TIMED_OUT: {
			return CCN_UPCALL_RESULT_REEXPRESS;
		}
		case CCN_UPCALL_CONTENT_UNVERIFIED:
		case CCN_UPCALL_CONTENT_KEYMISSING:
		case CCN_UPCALL_CONTENT_RAW:
		case CCN_UPCALL_CONTENT: {
			struct ccn_forwarding_entry* fe = NULL;
			const unsigned char* fe_ccnb = NULL;
			size_t fe_ccnb_size = 0;
			int res = ccn_content_get_value(info->content_ccnb, info->pco->offset[CCN_PCO_E], info->pco, &fe_ccnb, &fe_ccnb_size);
			if (res == 0) fe = ccn_forwarding_entry_parse(fe_ccnb, fe_ccnb_size);
			if (fe != NULL) {
				self->faceid = fe->faceid;
				ccn_forwarding_entry_destroy(&fe);
			} else {
				self->error = true;
			}
			PollMgr_detach(self->pm, ccn_get_connection_fd(self->ccnh), &CcnLAC_initPollCb, self);
			void* emptyPDU = malloc(CCN_EMPTY_PDU_LENGTH);
			memcpy(emptyPDU, CCN_EMPTY_PDU, CCN_EMPTY_PDU_LENGTH);
			NBS_write(self->nbs, emptyPDU, 0, CCN_EMPTY_PDU_LENGTH, NULL);
			NBS_pollAttach(self->nbs, self->pm);
			return CCN_UPCALL_RESULT_OK;
		}
		default: {
			return CCN_UPCALL_RESULT_ERR;
		}
	}
}
Пример #14
0
// creates a full structure without action, if proto == "face" only the
// faceid (from cmd_host parameter) and lifetime will be filled in.
struct ccn_face_instance *
parse_ccn_face_instance(struct ccndc_data *self,
                        const char *cmd_proto,
                        const char *cmd_host,     const char *cmd_port,
                        const char *cmd_mcastttl, const char *cmd_mcastif,
                        int freshness)
{
    struct ccn_face_instance *entry;
    struct addrinfo hints = {.ai_family = AF_UNSPEC, .ai_flags = (AI_ADDRCONFIG)};
    struct addrinfo mcasthints = {.ai_family = AF_UNSPEC, .ai_flags = (AI_ADDRCONFIG | AI_NUMERICHOST)};
    struct addrinfo *raddrinfo = NULL;
    struct addrinfo *mcastifaddrinfo = NULL;
    char rhostnamebuf [NI_MAXHOST];
    char rhostportbuf [NI_MAXSERV];
    int off_address = -1, off_port = -1, off_source_address = -1;
    int res;
    int socktype;
    
    entry = calloc(1, sizeof(*entry));
    if (entry == NULL) {
        ccndc_warn(__LINE__, "Fatal error: memory allocation failed");
        goto ExitOnError;
    }
    // allocate storage for Face data
    entry->store = ccn_charbuf_create();
    if (entry->store == NULL) {
        ccndc_warn(__LINE__, "Fatal error: memory allocation failed");
        goto ExitOnError;
    }
    // copy static info
    entry->ccnd_id = (const unsigned char *)self->ccnd_id;
    entry->ccnd_id_size = self->ccnd_id_size;
    
    if (cmd_proto == NULL) {
        ccndc_warn(__LINE__, "command error, missing address type\n");
        goto ExitOnError;
    }
    if (strcasecmp(cmd_proto, "udp") == 0) {
        entry->descr.ipproto = IPPROTO_UDP;
        socktype = SOCK_DGRAM;
    } else if (strcasecmp(cmd_proto, "tcp") == 0) {
        entry->descr.ipproto = IPPROTO_TCP;
        socktype = SOCK_STREAM;
    } else if (strcasecmp(cmd_proto, "face") == 0) {
        errno = 0;
        unsigned long faceid = strtoul(cmd_host, (char **)NULL, 10);
        if (errno == ERANGE || errno == EINVAL || faceid > UINT_MAX || faceid == 0) {
            ccndc_warn(__LINE__, "command error, face number invalid or out of range '%s'\n", cmd_host);
            goto ExitOnError;
        }
        entry->faceid = (unsigned) faceid;
        entry->lifetime = freshness;
        return (entry);
    } else {
        ccndc_warn(__LINE__, "command error, unrecognized address type '%s'\n", cmd_proto);
        goto ExitOnError;
    }
    
    if (cmd_host == NULL) {
        ccndc_warn(__LINE__, "command error, missing hostname\n");
        goto ExitOnError;
    }
    
    if (cmd_port == NULL || cmd_port[0] == 0)
        cmd_port = CCN_DEFAULT_UNICAST_PORT;
    
    hints.ai_socktype = socktype;
    res = getaddrinfo(cmd_host, cmd_port, &hints, &raddrinfo);
    if (res != 0 || raddrinfo == NULL) {
        ccndc_warn(__LINE__, "command error, getaddrinfo for host [%s] port [%s]: %s\n", cmd_host, cmd_port, gai_strerror(res));
        goto ExitOnError;
    }
    res = getnameinfo(raddrinfo->ai_addr, raddrinfo->ai_addrlen,
                      rhostnamebuf, sizeof(rhostnamebuf),
                      rhostportbuf, sizeof(rhostportbuf),
                      NI_NUMERICHOST | NI_NUMERICSERV);
    freeaddrinfo(raddrinfo);
    if (res != 0) {
        ccndc_warn(__LINE__, "command error, getnameinfo: %s\n", gai_strerror(res));
        goto ExitOnError;
    }
    
    off_address = entry->store->length;
    res = ccn_charbuf_append(entry->store, rhostnamebuf, strlen(rhostnamebuf)+1);
    if (res != 0) {
        ccndc_warn(__LINE__, "Cannot append to charbuf");
        goto ExitOnError;
    }
    
    off_port = entry->store->length;
    res = ccn_charbuf_append(entry->store, rhostportbuf, strlen(rhostportbuf)+1);
    if (res != 0) {
        ccndc_warn(__LINE__, "Cannot append to charbuf");
        goto ExitOnError;
    }
    
    entry->descr.mcast_ttl = -1;
    if (cmd_mcastttl != NULL) {
        char *endptr;
        entry->descr.mcast_ttl = strtol(cmd_mcastttl, &endptr, 10); 
        if ((endptr != &cmd_mcastttl[strlen(cmd_mcastttl)]) ||
            entry->descr.mcast_ttl < 0 || entry->descr.mcast_ttl > 255) {
            ccndc_warn(__LINE__, "command error, invalid multicast ttl: %s\n", cmd_mcastttl);
            goto ExitOnError;
        }
    }
    
    if (cmd_mcastif != NULL) {
        res = getaddrinfo(cmd_mcastif, NULL, &mcasthints, &mcastifaddrinfo);
        if (res != 0) {
            ccndc_warn(__LINE__, "command error, incorrect multicat interface [%s]: "
                       "mcastifaddr getaddrinfo: %s\n", cmd_mcastif, gai_strerror(res));
            goto ExitOnError;
        }
        
        res = getnameinfo(mcastifaddrinfo->ai_addr, mcastifaddrinfo->ai_addrlen,
                          rhostnamebuf, sizeof(rhostnamebuf),
                          NULL, 0,
                          NI_NUMERICHOST | NI_NUMERICSERV);
        freeaddrinfo(mcastifaddrinfo);
        if (res != 0) {
            ccndc_warn(__LINE__, "command error, getnameinfo: %s\n", gai_strerror(res));
            goto ExitOnError;
        }
        
        off_source_address = entry->store->length;
        res = ccn_charbuf_append(entry->store, rhostnamebuf, strlen(rhostnamebuf)+1);
        if (res != 0) {
            ccndc_warn(__LINE__, "Cannot append to charbuf");
            goto ExitOnError;
        }
    }
    
    entry->descr.address = (const char *)(entry->store->buf + off_address);
    entry->descr.port = (const char *)(entry->store->buf + off_port);
    if (off_source_address >= 0) {
        entry->descr.source_address = (const char *)(entry->store->buf + off_source_address);
    }
    
    entry->lifetime = freshness;
    
    return entry;
    
ExitOnError:
    ccn_face_instance_destroy(&entry);
    return (NULL);
}

struct ccn_face_instance *
parse_ccn_face_instance_from_face(struct ccndc_data *self,
                                  const char *cmd_faceid)
{
    struct ccn_face_instance *entry = calloc(1, sizeof(*entry));
    
    // allocate storage for Face data
    entry->store = ccn_charbuf_create();
    
    // copy static info
    entry->ccnd_id = (const unsigned char *)self->ccnd_id;
    entry->ccnd_id_size = self->ccnd_id_size;
    
    /* destroy a face - the URI field will hold the face number */
    if (cmd_faceid == NULL) {
        ccndc_warn(__LINE__, "command error, missing face number for destroyface\n");
        goto ExitOnError;
    }
    
    char *endptr;
    int facenumber = strtol(cmd_faceid, &endptr, 10);
    if ((endptr != &cmd_faceid[strlen(cmd_faceid)]) ||
        facenumber < 0) {
        ccndc_warn(__LINE__, "command error invalid face number for destroyface: %d\n", facenumber);
        goto ExitOnError;
    }
    
    entry->faceid = facenumber;
    
    return entry;
    
ExitOnError:
    ccn_face_instance_destroy(&entry);
    return (NULL);
}



///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// "private section
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

int
ccndc_get_ccnd_id(struct ccndc_data *self)
{
    struct ccn_charbuf *name = NULL;
    struct ccn_charbuf *resultbuf = NULL;
    struct ccn_parsed_ContentObject pcobuf = {0};
    char ccndid_uri[] = "ccnx:/%C1.M.S.localhost/%C1.M.SRV/ccnd/KEY";
    const unsigned char *ccndid_result;
    int res = 0;
    
    name = ccn_charbuf_create();
    if (name == NULL) {
        ccndc_warn(__LINE__, "Unable to allocate storage for service locator name charbuf\n");
        return -1;
    }
    
    resultbuf = ccn_charbuf_create();
    if (resultbuf == NULL) {
        ccndc_warn(__LINE__, "Unable to allocate storage for result charbuf");
        res = -1;
        goto Cleanup;
    }
    
    res = ccn_name_from_uri(name, ccndid_uri);
    if (res < 0) {
        ccndc_warn(__LINE__, "Unable to parse service locator URI for ccnd key");
        goto Cleanup;
    }
    
    res = ccn_get(self->ccn_handle,
                  name,
                  self->local_scope_template,
                  4500, resultbuf, &pcobuf, NULL, 0);
    if (res < 0) {
        ccndc_warn(__LINE__, "Unable to get key from ccnd");
        goto Cleanup;
    }
    
    res = ccn_ref_tagged_BLOB (CCN_DTAG_PublisherPublicKeyDigest,
                               resultbuf->buf,
                               pcobuf.offset[CCN_PCO_B_PublisherPublicKeyDigest],
                               pcobuf.offset[CCN_PCO_E_PublisherPublicKeyDigest],
                               &ccndid_result, &self->ccnd_id_size);
    if (res < 0) {
        ccndc_warn(__LINE__, "Unable to parse ccnd response for ccnd id");
        goto Cleanup;
    }
    
    if (self->ccnd_id_size > sizeof (self->ccnd_id))
    {
        ccndc_warn(__LINE__, "Incorrect size for ccnd id in response");
        goto Cleanup;
    }
    
    memcpy(self->ccnd_id, ccndid_result, self->ccnd_id_size);
    
Cleanup:
    ccn_charbuf_destroy(&name);
    ccn_charbuf_destroy(&resultbuf);
    return (res);
}


struct ccn_face_instance *
ccndc_do_face_action(struct ccndc_data *self,
                     const char *action,
                     struct ccn_face_instance *face_instance)
{
    struct ccn_charbuf *newface = NULL;
    struct ccn_charbuf *signed_info = NULL;
    struct ccn_charbuf *temp = NULL;
    struct ccn_charbuf *name = NULL;
    struct ccn_charbuf *resultbuf = NULL;
    struct ccn_parsed_ContentObject pcobuf = {0};
    struct ccn_face_instance *new_face_instance = NULL;
    const unsigned char *ptr = NULL;
    size_t length = 0;
    int res = 0;
    
    face_instance->action = action;
    
    /* Encode the given face instance */
    newface = ccn_charbuf_create();
    ON_NULL_CLEANUP(newface);
    ON_ERROR_CLEANUP(ccnb_append_face_instance(newface, face_instance));
    
    temp = ccn_charbuf_create();
    ON_NULL_CLEANUP(temp);
    res = ccn_sign_content(self->ccn_handle, temp, self->no_name, NULL, newface->buf, newface->length);
    ON_ERROR_CLEANUP(res);
    resultbuf = ccn_charbuf_create();
    ON_NULL_CLEANUP(resultbuf);
    
    /* Construct the Interest name that will create the face */
    name = ccn_charbuf_create();
    ON_NULL_CLEANUP(name);
    ON_ERROR_CLEANUP(ccn_name_init(name));
    ON_ERROR_CLEANUP(ccn_name_append_str(name, "ccnx"));
    ON_ERROR_CLEANUP(ccn_name_append(name, face_instance->ccnd_id, face_instance->ccnd_id_size));
    ON_ERROR_CLEANUP(ccn_name_append_str(name, face_instance->action));
    ON_ERROR_CLEANUP(ccn_name_append(name, temp->buf, temp->length));
    
    res = ccn_get(self->ccn_handle, name, self->local_scope_template, 1000, resultbuf, &pcobuf, NULL, 0);
    ON_ERROR_CLEANUP(res);
    
    ON_ERROR_CLEANUP(ccn_content_get_value(resultbuf->buf, resultbuf->length, &pcobuf, &ptr, &length));
    new_face_instance = ccn_face_instance_parse(ptr, length);
    ON_NULL_CLEANUP(new_face_instance);
    ccn_charbuf_destroy(&newface);
    ccn_charbuf_destroy(&signed_info);
    ccn_charbuf_destroy(&temp);
    ccn_charbuf_destroy(&resultbuf);
    ccn_charbuf_destroy(&name);
    return (new_face_instance);
    
Cleanup:
    ccn_charbuf_destroy(&newface);
    ccn_charbuf_destroy(&signed_info);
    ccn_charbuf_destroy(&temp);
    ccn_charbuf_destroy(&resultbuf);
    ccn_charbuf_destroy(&name);
    ccn_face_instance_destroy(&new_face_instance);
    return (NULL);
}

int
ccndc_do_prefix_action(struct ccndc_data *self,
                       const char *action,
                       struct ccn_forwarding_entry *forwarding_entry)
{
    struct ccn_charbuf *temp = NULL;
    struct ccn_charbuf *resultbuf = NULL;
    struct ccn_charbuf *signed_info = NULL;
    struct ccn_charbuf *name = NULL;
    struct ccn_charbuf *prefixreg = NULL;
    struct ccn_parsed_ContentObject pcobuf = {0};
    struct ccn_forwarding_entry *new_forwarding_entry = NULL;
    
    const unsigned char *ptr = NULL;
    size_t length = 0;
    int res;
    
    forwarding_entry->action = action;
    
    prefixreg = ccn_charbuf_create();
    ON_NULL_CLEANUP(prefixreg);
    ON_ERROR_CLEANUP(ccnb_append_forwarding_entry(prefixreg, forwarding_entry));
    temp = ccn_charbuf_create();
    ON_NULL_CLEANUP(temp);
    res = ccn_sign_content(self->ccn_handle, temp, self->no_name, NULL, prefixreg->buf, prefixreg->length);
    ON_ERROR_CLEANUP(res);    
    resultbuf = ccn_charbuf_create();
    ON_NULL_CLEANUP(resultbuf);
    name = ccn_charbuf_create();
    ON_ERROR_CLEANUP(ccn_name_init(name));
    ON_ERROR_CLEANUP(ccn_name_append_str(name, "ccnx"));
    ON_ERROR_CLEANUP(ccn_name_append(name, forwarding_entry->ccnd_id, forwarding_entry->ccnd_id_size));
    ON_ERROR_CLEANUP(ccn_name_append_str(name, forwarding_entry->action));
    ON_ERROR_CLEANUP(ccn_name_append(name, temp->buf, temp->length));
    res = ccn_get(self->ccn_handle, name, self->local_scope_template, 1000, resultbuf, &pcobuf, NULL, 0);
    ON_ERROR_CLEANUP(res);
    ON_ERROR_CLEANUP(ccn_content_get_value(resultbuf->buf, resultbuf->length, &pcobuf, &ptr, &length));
    new_forwarding_entry = ccn_forwarding_entry_parse(ptr, length);
    ON_NULL_CLEANUP(new_forwarding_entry);
    
    res = new_forwarding_entry->faceid;
    
    ccn_forwarding_entry_destroy(&new_forwarding_entry);
    ccn_charbuf_destroy(&signed_info);
    ccn_charbuf_destroy(&temp);
    ccn_charbuf_destroy(&resultbuf);
    ccn_charbuf_destroy(&name);
    ccn_charbuf_destroy(&prefixreg);
    
    return (res);
    
    /* This is where ON_ERROR_CLEANUP sends us in case of an error
     * and we must free any storage we allocated before returning.
     */
Cleanup:
    ccn_charbuf_destroy(&signed_info);
    ccn_charbuf_destroy(&temp);
    ccn_charbuf_destroy(&resultbuf);
    ccn_charbuf_destroy(&name);
    ccn_charbuf_destroy(&prefixreg);
    
    return (-1);
}
Пример #15
0
/**
 * 
 * Bind a prefix to a face
 *
 */
static int 
register_unregister_prefix(struct ccn *h, struct ccn_charbuf *local_scope_template,
        struct ccn_charbuf *no_name, struct ccn_charbuf *name_prefix,
        struct ccn_face_instance *face_instance, int operation)
{
	struct ccn_charbuf *temp = NULL;
	struct ccn_charbuf *resultbuf = NULL;
	struct ccn_charbuf *signed_info = NULL;
	struct ccn_charbuf *name = NULL;
	struct ccn_charbuf *prefixreg = NULL;
	struct ccn_parsed_ContentObject pcobuf = {0};
	struct ccn_forwarding_entry forwarding_entry_storage = {0};
	struct ccn_forwarding_entry *forwarding_entry = &forwarding_entry_storage;
	struct ccn_forwarding_entry *new_forwarding_entry;
	const unsigned char *ptr = NULL;
	size_t length = 0;
	int res;

	/* Register or unregister the prefix */
	forwarding_entry->action = (operation == OP_REG) ? "prefixreg" : "unreg";
	forwarding_entry->name_prefix = name_prefix;
	forwarding_entry->ccnd_id = face_instance->ccnd_id;
	forwarding_entry->ccnd_id_size = face_instance->ccnd_id_size;
	forwarding_entry->faceid = face_instance->faceid;
	forwarding_entry->flags = -1;
	forwarding_entry->lifetime = 2100;

	prefixreg = ccn_charbuf_create();
	ccnb_append_forwarding_entry(prefixreg, forwarding_entry);
	temp = ccn_charbuf_create();
	res = ccn_sign_content(h, temp, no_name, NULL, prefixreg->buf, prefixreg->length);
	resultbuf = ccn_charbuf_create();

	/* construct Interest containing prefixreg request */
	name = ccn_charbuf_create();
	ccn_name_init(name);
	ccn_name_append_str(name, "ccnx");
	ccn_name_append(name, face_instance->ccnd_id, face_instance->ccnd_id_size);
	ccn_name_append_str(name, (operation == OP_REG) ? "prefixreg" : "unreg");
	ccn_name_append(name, temp->buf, temp->length);

	/* send Interest, get Data */
	res = ccn_get(h, name, local_scope_template, 1000, resultbuf, &pcobuf, NULL, 0);
	ON_ERROR_CLEANUP(res);

	res = ccn_content_get_value(resultbuf->buf, resultbuf->length, &pcobuf, &ptr, &length);
	ON_ERROR_CLEANUP(res);
    
	/* extract new forwarding entry from Data */
	new_forwarding_entry = ccn_forwarding_entry_parse(ptr, length);
	ON_NULL_CLEANUP(new_forwarding_entry);

	res = new_forwarding_entry->faceid;

	ccn_forwarding_entry_destroy(&new_forwarding_entry);
	ccn_charbuf_destroy(&signed_info);
	ccn_charbuf_destroy(&temp);
	ccn_charbuf_destroy(&resultbuf);
	ccn_charbuf_destroy(&name);
	ccn_charbuf_destroy(&prefixreg);

	return res;

	cleanup:
		ccn_forwarding_entry_destroy(&new_forwarding_entry);
		ccn_charbuf_destroy(&signed_info);
		ccn_charbuf_destroy(&temp);
		ccn_charbuf_destroy(&resultbuf);
		ccn_charbuf_destroy(&name);
		ccn_charbuf_destroy(&prefixreg);

	return -1;
}
Пример #16
0
/**
 * Main working loop for stuff coming in from the CCNx network
 *
 * The only kind of content we work with are data messages. They are in response to the
 * interest messages we send out. The work involves 2 pieces: packing the data from ccn message
 * sizes into buffer sizes we use internally, and detecting when the stream of data is done.
 * 
 * The first is fairly simple. Each internal buffer we 'fill' is placed onto the fifo queue
 * so the main thread can take it off and reply to the pipeline request for more data.
 *
 * Determining the end of stream at the moment is a bit of a hack and could use some work.
 * \todo volunteers?  8-)
 *
 * \param	selfp		-> a context structure we created when registering this call-back
 * \param	kind		specifies the type of call-back being processed, see the \b switch statement
 * \param	info		context information about the call-back itself; interests, data, etc.
 * \return a response as to how successful we were in processing the call-back
 * \retval CCN_UPCALL_RESULT_OK		things went well
 * \retval CCN_UPCALL_RESULT_VERIFY	need to verify the contents of what we received
 * \retval CCN_UPCALL_RESULT_REEXPRESS an interest timedout waiting for data, so we try again
 * \retval CCN_UPCALL_RESULT_ERR	some error was encountered
 */
static enum ccn_upcall_res
incoming_content (struct ccn_closure *selfp,
    enum ccn_upcall_kind kind, struct ccn_upcall_info *info)
{
  Gstccnxsrc *me = GST_CCNXSRC (selfp->data);

  const unsigned char *ccnb = NULL;
  size_t ccnb_size = 0;
  const unsigned char *ib = NULL;       /* info->interest_ccnb */
  struct ccn_indexbuf *ic = NULL;
  unsigned int i;
  uintmax_t segment;
  CcnxInterestState *istate = NULL;
  gint res;
  const unsigned char *cp;
  size_t sz;
  const unsigned char *data = NULL;
  size_t data_size = 0;
  gboolean b_last = FALSE;

  GST_INFO ("content has arrived!");

  /* Do some basic sanity and type checks to see if we want to process this data */

  if (CCN_UPCALL_FINAL == kind) {
    GST_LOG_OBJECT (me, "CCN upcall final %p", selfp);
    if (me->i_bufoffset > 0) {
      GST_BUFFER_SIZE (me->buf) = me->i_bufoffset;
      fifo_put (me, me->buf);
      me->buf = gst_buffer_new_and_alloc (CCN_FIFO_BLOCK_SIZE);
      me->i_bufoffset = 0;
    }
/*
 * Should emit an eos here instead of the empty buffer
 */
    GST_BUFFER_SIZE (me->buf) = 0;
    fifo_put (me, me->buf);
    me->i_bufoffset = 0;
    return (CCN_UPCALL_RESULT_OK);
  }

  if (!info)
    return CCN_UPCALL_RESULT_ERR;       // Now why would this happen?

  // show_comps( info->content_ccnb, info->content_comps);

  if (CCN_UPCALL_INTEREST_TIMED_OUT == kind) {
    if (selfp != me->ccn_closure) {
      GST_LOG_OBJECT (me, "CCN Interest timed out on dead closure %p", selfp);
      return (CCN_UPCALL_RESULT_OK);
    }
    segment =
        ccn_ccnb_fetch_segment (info->interest_ccnb, info->interest_comps);
    GST_INFO ("...looks to be for segment: %d", segment);
    GST_LOG_OBJECT (me, "CCN upcall reexpress -- timed out");
    istate = fetchSegmentInterest (me, segment);
    if (istate) {
      if (istate->timeouts > 5) {
        GST_LOG_OBJECT (me, "CCN upcall reexpress -- too many reexpressions");
        if (segment == me->post_seg)    // We have been waiting for this one...process as an empty block to trigger other activity
          process_or_queue (me, me->post_seg, NULL, 0, FALSE);
        else
          freeInterestState (me, istate);
        post_next_interest (me);        // make sure to ask for new stuff if needed, or else we stall waiting for nothing
        return (CCN_UPCALL_RESULT_OK);
      } else {
        istate->timeouts++;
        return (CCN_UPCALL_RESULT_REEXPRESS);
      }
    } else {
      GST_LOG_OBJECT (me, "segment not found in cache: %d", segment);
      return (CCN_UPCALL_RESULT_OK);
    }

  } else if (CCN_UPCALL_CONTENT_UNVERIFIED == kind) {
    if (selfp != me->ccn_closure) {
      GST_LOG_OBJECT (me, "CCN unverified content on dead closure %p", selfp);
      return (CCN_UPCALL_RESULT_OK);
    }
    return (CCN_UPCALL_RESULT_VERIFY);

  } else if (CCN_UPCALL_CONTENT != kind) {
    GST_LOG_OBJECT (me, "CCN upcall result error");
    return (CCN_UPCALL_RESULT_ERR);
  }

  segment = ccn_ccnb_fetch_segment (info->content_ccnb, info->content_comps);
  GST_INFO ("...looks to be for segment: %d", segment);
  if (selfp != me->ccn_closure) {
    GST_LOG_OBJECT (me, "CCN content on dead closure %p", selfp);
    return (CCN_UPCALL_RESULT_OK);
  }


  /* At this point it seems we have a data message we want to process */

  ccnb = info->content_ccnb;
  ccnb_size = info->pco->offset[CCN_PCO_E];

  /* spit out some debug information */
  for (i = 0; i < 5; ++i) {
    GST_DEBUG ("%3d: ", i);
    if (0 > ccn_name_comp_get (info->content_ccnb, info->content_comps, i, &cp,
            &sz)) {
      // fprintf(stderr, "could not get comp\n");
    } else {
      // hDump( DUMP_ADDR( cp ), DUMP_SIZE( sz ) );
    }
  }

  /* go get the data and process it...note that the data pointer here is only temporary, a copy is needed to keep the data */
  ib = info->interest_ccnb;
  ic = info->interest_comps;
  res = ccn_content_get_value (ccnb, ccnb_size, info->pco, &data, &data_size);
  if (res < 0) {
    GST_LOG_OBJECT (me, "CCN error on get value of size");
    process_or_queue (me, segment, NULL, 0, FALSE);     // process null block to adjust interest array queue
    post_next_interest (me);    // Keep the data flowing
    return (CCN_UPCALL_RESULT_ERR);
  }

  /* was this the last block? [code taken from a ccnx tool */
  /* \todo  the test below should get refactored into the library */
  if (info->pco->offset[CCN_PCO_B_FinalBlockID] !=
      info->pco->offset[CCN_PCO_E_FinalBlockID]) {
    const unsigned char *finalid = NULL;
    size_t finalid_size = 0;
    const unsigned char *nameid = NULL;
    size_t nameid_size = 0;
    struct ccn_indexbuf *cc = info->content_comps;
    ccn_ref_tagged_BLOB (CCN_DTAG_FinalBlockID, ccnb,
        info->pco->offset[CCN_PCO_B_FinalBlockID],
        info->pco->offset[CCN_PCO_E_FinalBlockID], &finalid, &finalid_size);
    if (cc->n < 2)
      abort ();                 // \todo we need to behave better than this
    ccn_ref_tagged_BLOB (CCN_DTAG_Component, ccnb,
        cc->buf[cc->n - 2], cc->buf[cc->n - 1], &nameid, &nameid_size);
    if (finalid_size == nameid_size
        && 0 == memcmp (finalid, nameid, nameid_size)) {
      b_last = TRUE;
    }
  }

  /* a short block can also indicate the end, if the client isn't using FinalBlockID */
  if (data_size < CCN_CHUNK_SIZE)
    b_last = TRUE;

  /* something to process */
  process_or_queue (me, segment, data, data_size, b_last);
  post_next_interest (me);

  if (!b_last)
    return post_next_interest (me);

  return (CCN_UPCALL_RESULT_OK);

}
Пример #17
0
enum ccn_upcall_res
incoming_content(
    struct ccn_closure *selfp,
    enum ccn_upcall_kind kind,
    struct ccn_upcall_info *info)
{
    struct ccn_charbuf *name = NULL;
    struct ccn_charbuf *templ = NULL;
    struct ccn_charbuf *temp = NULL;
    const unsigned char *ccnb = NULL;
    size_t ccnb_size = 0;
    const unsigned char *data = NULL;
    size_t data_size = 0;
    size_t written;
    const unsigned char *ib = NULL; /* info->interest_ccnb */
    struct ccn_indexbuf *ic = NULL;
    int res;
    struct mydata *md = selfp->data;
    
    if (kind == CCN_UPCALL_FINAL) {
        if (md != NULL) {
            selfp->data = NULL;
            free(md);
            md = NULL;
        }
        return(CCN_UPCALL_RESULT_OK);
    }
    if (kind == CCN_UPCALL_INTEREST_TIMED_OUT)
        return(CCN_UPCALL_RESULT_REEXPRESS);
    if (kind != CCN_UPCALL_CONTENT && kind != CCN_UPCALL_CONTENT_UNVERIFIED)
        return(CCN_UPCALL_RESULT_ERR);
    if (md == NULL)
        selfp->data = md = calloc(1, sizeof(*md));
    ccnb = info->content_ccnb;
    ccnb_size = info->pco->offset[CCN_PCO_E];
    ib = info->interest_ccnb;
    ic = info->interest_comps;
    /* XXX - must verify sig, and make sure it is LEAF content */
    res = ccn_content_get_value(ccnb, ccnb_size, info->pco, &data, &data_size);
    if (res < 0) abort();
    if (data_size > CHUNK_SIZE) {
        /* For us this is spam. Give up now. */
        fprintf(stderr, "*** Segment %d found with a data size of %d."
                        " This program only works with segments of 1024 bytes."
                        " Try ccncatchunks2 instead.\n",
                        (int)selfp->intdata, (int)data_size);
        exit(1);
    }
    
    /* OK, we will accept this block. */
    
    written = fwrite(data, data_size, 1, stdout);
    if (written != 1)
        exit(1);
    
    /* A short block signals EOF for us. */
    if (data_size < CHUNK_SIZE)
        exit(0);
    
    /* Ask for the next one */
    name = ccn_charbuf_create();
    ccn_name_init(name);
    if (ic->n < 2) abort();
    res = ccn_name_append_components(name, ib, ic->buf[0], ic->buf[ic->n - 2]);
    if (res < 0) abort();
    temp = ccn_charbuf_create();
    ccn_charbuf_putf(temp, "%d", ++(selfp->intdata));
    ccn_name_append(name, temp->buf, temp->length);
    ccn_charbuf_destroy(&temp);
    templ = make_template(md, info);
    
    res = ccn_express_interest(info->h, name, selfp, templ);
    if (res < 0) abort();
    
    ccn_charbuf_destroy(&templ);
    ccn_charbuf_destroy(&name);
    
    return(CCN_UPCALL_RESULT_OK);
}
Пример #18
0
static enum ccn_upcall_res
CallMe(struct ccn_closure *selfp,
	   enum ccn_upcall_kind kind,
	   struct ccn_upcall_info *info) {
	// CallMe is the callback routine invoked by ccn_run when a registered
	// interest has something interesting happen.
    struct localClosure *req = (struct localClosure *)selfp->data;
	seg_t thisSeg = req->reqSeg;
    struct ccn_fetch_stream *fs = (struct ccn_fetch_stream *) req->fs;
	if (fs == NULL) {
		if (kind == CCN_UPCALL_FINAL) {
			// orphaned, so just get rid of it
			free(req);
			free(selfp);
		}
		return(CCN_UPCALL_RESULT_OK);
	}
	FILE *debug = fs->parent->debug;
	seg_t finalSeg = fs->finalSeg;
	ccn_fetch_flags flags = fs->parent->debugFlags;
	if (finalSeg < 0) {
		// worth a try to find the last segment
		finalSeg = GetFinalSegment(info);
		fs->finalSeg = finalSeg;
	}
    
	switch (kind) {
		case CCN_UPCALL_FINAL:
			// this is the cleanup for an expressed interest
			req = RemSegRequest(fs, req);
			if (fs->reqBusy > 0) fs->reqBusy--;
			free(selfp);
			return(CCN_UPCALL_RESULT_OK);
		case CCN_UPCALL_INTEREST_TIMED_OUT: {
			if (finalSeg >= 0 && thisSeg > finalSeg)
				// ignore this timeout quickly
				return(CCN_UPCALL_RESULT_OK);
			intmax_t dt = DeltaTime(req->startClock, GetCurrentTimeUSecs());
			if (dt >= fs->timeoutUSecs) {
				// timed out, too many retries
				// assume that this interest will never produce
				seg_t timeoutSeg = fs->timeoutSeg;
				fs->timeoutsSeen++;
				fs->segsAhead = 0;
				if (timeoutSeg < 0 || thisSeg < timeoutSeg) {
					// we can infer a new timeoutSeg
					fs->timeoutSeg = thisSeg;
				}
				if (debug != NULL && (flags & ccn_fetch_flags_NoteTimeout)) {
					fprintf(debug, 
							"** ccn_fetch timeout, %s, seg %jd",
							fs->id, thisSeg);
					fprintf(debug, 
							", dt %jd us, timeoutUSecs %jd\n",
							dt, fs->timeoutUSecs);
					fflush(debug);
				}
				return(CCN_UPCALL_RESULT_OK);
			}
			// TBD: may need to reseed bloom filter?  who to ask?
			return(CCN_UPCALL_RESULT_REEXPRESS);
		}
		case CCN_UPCALL_CONTENT_UNVERIFIED:
			return (CCN_UPCALL_RESULT_VERIFY);
		case CCN_UPCALL_CONTENT:
			if (fs->timeoutSeg >= 0 && fs->timeoutSeg <= thisSeg)
				// we will ignore this, since we are blocked
				return(CCN_UPCALL_RESULT_OK);
			break;
		default:
			// SHOULD NOT HAPPEN
			return(CCN_UPCALL_RESULT_ERR);
    }
	
	struct ccn_fetch_buffer *fb = FindBufferForSeg(fs, thisSeg);
	if (fb == NULL) {
		// we don't already have the data yet
		const unsigned char *data = NULL;
		size_t dataLen = 0;
		size_t ccnb_size = info->pco->offset[CCN_PCO_E];
		const unsigned char *ccnb = info->content_ccnb;
		int res = ccn_content_get_value(ccnb, ccnb_size, info->pco,
										&data, &dataLen);
		
		if (res < 0 || (thisSeg != finalSeg && dataLen == 0)) {
			// we got a bogus result, no data in this content!
			if (debug != NULL && (flags & ccn_fetch_flags_NoteAddRem)) {
				fprintf(debug, 
						"-- ccn_fetch no data, %s, seg %jd, final %jd",
						fs->id, thisSeg, finalSeg);
				ShowDelta(debug, req->startClock);
			}
			if (fs->zeroLenSeg < 0 || thisSeg < fs->zeroLenSeg)
				// note this problem for future reporting
				fs->zeroLenSeg = thisSeg;
		} else if (thisSeg == finalSeg && dataLen == 0) {
			// EOF, but no buffer needed
			if (fs->fileSize < 0)
				fs->fileSize = InferPosition(fs, thisSeg);
			fs->finalSeg = finalSeg-1;
			if (debug != NULL && (flags & ccn_fetch_flags_NoteFinal)) {
				fprintf(debug, 
						"-- ccn_fetch EOF, %s, seg %jd, len %d, fs %jd",
						fs->id, thisSeg,
						(int) dataLen,
						fs->fileSize);
				ShowDelta(debug, req->startClock);
			}
			
		} else {
			// alloc a buffer and transfer the data
			
			if (fs->segSize == 0) {
				// assuming fixed size segments, so any should do
				// EXCEPT for an incomplete final segment
				if (thisSeg == 0 || thisSeg < finalSeg)
					fs->segSize = dataLen;
			}
			if (thisSeg == finalSeg) fs->finalSegLen = dataLen;
			struct ccn_fetch_buffer *fb = NewBufferForSeg(fs, thisSeg, dataLen);
			memcpy(fb->buf, data, dataLen);
			if (debug != NULL && (flags & ccn_fetch_flags_NoteFill)) {
				fprintf(debug, 
						"-- ccn_fetch FillSeg, %s, seg %jd, len %d, nbuf %d",
						fs->id, thisSeg, (int) dataLen, (int) fs->nBufs);
				ShowDelta(debug, req->startClock);
			}
			if (thisSeg == finalSeg) {
				// the file size is known in segments
				if (fs->segSize <= 0) {
					// variable or unknown segment size
					if (fb->pos >= 0) {
						fs->fileSize = fb->pos + dataLen;
					}
				} else {
					// fixed segment size, so file size is now known
					fs->fileSize = thisSeg * fs->segSize + dataLen;
				}
				if (debug != NULL && (flags & ccn_fetch_flags_NoteFinal)) {
					fprintf(debug, 
							"-- ccn_fetch EOF, %s, seg %jd, len %d, fs %jd",
							fs->id, thisSeg, (int) dataLen, fs->fileSize);
					ShowDelta(debug, req->startClock);
				}
			}
			fs->segsRead++;
		}
	}
	
	ccn_set_run_timeout(fs->parent->h, 0);
	return(CCN_UPCALL_RESULT_OK);
}
Пример #19
0
int main (int argc, char **argv) {

    int res;
    //check if user supplied uri to trace
    if(argv[1] == NULL) {
        printf("Usage: trace URI\n");
        exit(1);
    }

    //get the length of user provided URI
    int argv_length = strlen(argv[1]);

    //check first six chars for ccnx:/, if present, skip them
    int skip = 0;
    res = strncmp("ccnx:/", argv[1], 6);
    if(res == 0) {
        skip = 5;
    }

    //if URI does not begins with /, exit
    if (argv[1][skip] != '/') {
        printf("URI must begin with /\n");
        exit(1);
    }

    //check if uri ends with slash, append if missing
    char *slash = "";
    if (argv[1][argv_length-1] != '/') {
        slash = "/";
    }



    //allocate memory for trace URI = /trace/user_input/random_number
    char *URI = (char *) malloc(sizeof(char)* argv_length+1); //find size of rand
    if(URI == NULL) {
        fprintf(stderr, "Can not allocate memory for URI\n");
        exit(1);
    }

    //put together the trace URI, add a random number to end of URI
    srand ((unsigned int)time (NULL)*getpid());
    sprintf(URI, "%s%s", argv[1]+skip, slash);

    //allocate memory for interest
    struct ccn_charbuf *ccnb = ccn_charbuf_create();
    if(ccnb == NULL) {
        fprintf(stderr, "Can not allocate memory for interest\n");
        exit(1);
    }

    //adding name to interest
    res = ccn_name_from_uri(ccnb, URI);
    if(res == -1) {
        fprintf(stderr, "Failed to assign name to interest");
        exit(1);
    }

    //create the ccn handle
    struct ccn *ccn = ccn_create();
    if(ccn == NULL) {
        fprintf(stderr, "Can not create ccn handle\n");
        exit(1);
    }

    //connect to ccnd
    res = ccn_connect(ccn, NULL);
    if (res == -1) {
        fprintf(stderr, "Could not connect to ccnd... exiting\n");
        exit(1);
    }

#ifdef DEBUG
    printf("Connected to CCND, return code: %d\n", res);
#endif

    //allocate buffer for response
    struct ccn_charbuf *resultbuf = ccn_charbuf_create();
    if(resultbuf == NULL) {
        fprintf(stderr, "Can not allocate memory for URI\n");
        exit(1);
    }

    //setting the parameters for ccn_get
    struct ccn_parsed_ContentObject pcobuf = { 0 };
    int timeout_ms = 6000;

    //express interest
    //res = ccn_get(ccn, ccnb, NULL, timeout_ms, resultbuf, &pcobuf, NULL, 0);

    //if cached answer is not allowed, set the template
    //make sure AnswerOriginKind is 0x0
    if(!ALLOW_CACHE) {
        struct ccn_charbuf *templ = 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); /* </Name> */
        ccn_charbuf_append_tt(templ, CCN_DTAG_AnswerOriginKind, CCN_DTAG);
        ccnb_append_number(templ,0x0);
        ccn_charbuf_append_closer(templ); /* </AnswerOriginKind> */
        ccn_charbuf_append_closer(templ);
        //send out the interest
        res = ccn_get(ccn, ccnb, templ, timeout_ms, resultbuf, &pcobuf, NULL, 0);
    } 
    
    //cached answer is allowed, don't set template
    else {
        res = ccn_get(ccn, ccnb, NULL, timeout_ms, resultbuf, &pcobuf, NULL, 0);
    }

    if (res == -1) {
        fprintf(stderr, "Did not receive answer for trace to %s\n", argv[1]);
#ifdef DEBUG
        fprintf(stderr, "Did not receive answer for trace to URI: %s\n", URI);
#endif
        exit(1);
    }

    //extract data from the response
    const unsigned char *ptr;
    size_t length;
    ptr = resultbuf->buf;
    length = resultbuf->length;
    ccn_content_get_value(ptr, length, &pcobuf, &ptr, &length);

    //check if received some data
    if(length == 0) {
        fprintf(stderr, "Received empty answer for trace to %s\n", argv[1]);
#ifdef DEBUG
        fprintf(stderr, "Received empty answer for trace to URI: %s\n", URI);
#endif
        exit(1);
    }

    //print the data
    printf("Reply: %s\n",  ptr);
    printf("Length of data: %Zu\n", length);
    exit(0);
}
Пример #20
0
int
main(int argc, char **argv)
{
    struct ccn *h = NULL;
    struct ccn_charbuf *name = NULL;
    struct ccn_charbuf *null_name = NULL;
    struct ccn_charbuf *name_prefix = NULL;
    struct ccn_charbuf *newface = NULL;
    struct ccn_charbuf *prefixreg = NULL;
    struct ccn_charbuf *resultbuf = NULL;
    struct ccn_charbuf *temp = NULL;
    struct ccn_charbuf *templ = NULL;
    const unsigned char *ptr = NULL;
    size_t length = 0;
    const char *arg = NULL;
    const char *progname = NULL;
    struct ccn_parsed_ContentObject pcobuf = {0};
    struct ccn_face_instance face_instance_storage = {0};
    struct ccn_face_instance *face_instance = &face_instance_storage;
    struct ccn_forwarding_entry forwarding_entry_storage = {0};
    struct ccn_forwarding_entry *forwarding_entry = &forwarding_entry_storage;
    struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT;
    struct ccn_charbuf *keylocator_templ = NULL;
    struct ccn_keystore *keystore = NULL;
    long expire = -1;
    int ipproto;
    unsigned char ccndid_storage[32] = {0};
    const unsigned char *ccndid = NULL;
    size_t ccndid_size = 0;
    int res;
    int opt;

    progname = argv[0];
    while ((opt = getopt(argc, argv, "h")) != -1) {
        switch (opt) {
        case 'h':
        default:
            usage(progname);
        }
    }

    /* Sanity check the URI and argument count */
    arg = argv[optind];
    if (arg == NULL)
        usage(progname);
    name = ccn_charbuf_create();
    res = ccn_name_from_uri(name, arg);
    if (res < 0) {
        fprintf(stderr, "%s: bad ccn URI: %s\n", progname, arg);
        exit(1);
    }
    if (argc - optind < 3 || argc - optind > 4)
        usage(progname);

    h = ccn_create();
    res = ccn_connect(h, NULL);
    if (res < 0) {
        ccn_perror(h, "ccn_connect");
        exit(1);
    }

    newface = ccn_charbuf_create();
    temp = ccn_charbuf_create();
    templ = ccn_charbuf_create();
    keylocator_templ = ccn_charbuf_create();

    resultbuf = ccn_charbuf_create();
    name_prefix = ccn_charbuf_create();
    null_name = ccn_charbuf_create();
    CHKRES(ccn_name_init(null_name));

    keystore = ccn_keystore_create();

    /* We need to figure out our local ccnd's CCIDID */
    /* Set up our Interest template to indicate scope 1 */
    ccn_charbuf_reset(templ);
    ccnb_element_begin(templ, CCN_DTAG_Interest);
    ccnb_element_begin(templ, CCN_DTAG_Name);
    ccnb_element_end(templ);	/* </Name> */
    ccnb_tagged_putf(templ, CCN_DTAG_Scope, "1");
    ccnb_element_end(templ);	/* </Interest> */

    ccn_charbuf_reset(name);
    CHKRES(res = ccn_name_from_uri(name, "ccnx:/%C1.M.S.localhost/%C1.M.SRV/ccnd/KEY"));
    CHKRES(res = ccn_get(h, name, templ, 200, resultbuf, &pcobuf, NULL, 0));
    res = ccn_ref_tagged_BLOB(CCN_DTAG_PublisherPublicKeyDigest,
                              resultbuf->buf,
                              pcobuf.offset[CCN_PCO_B_PublisherPublicKeyDigest],
                              pcobuf.offset[CCN_PCO_E_PublisherPublicKeyDigest],
                              &ccndid, &ccndid_size);
    CHKRES(res);
    if (ccndid_size > sizeof(ccndid_storage))
        CHKRES(-1);
    memcpy(ccndid_storage, ccndid, ccndid_size);
    ccndid = ccndid_storage;

    face_instance->action = "newface";
    face_instance->ccnd_id = ccndid;
    face_instance->ccnd_id_size = ccndid_size;
    if (strcmp(argv[optind + 1], "tcp") == 0)
        ipproto = 6;
    else if (strcmp(argv[optind + 1], "udp") == 0)
        ipproto = 17;
    else
        ipproto = atoi(argv[optind + 1]);
    face_instance->descr.ipproto = ipproto; // XXX - 6 = tcp or 17 = udp
    face_instance->descr.address = argv[optind + 2];
    face_instance->descr.port = argv[optind + 3];
    if (face_instance->descr.port == NULL)
        face_instance->descr.port = CCN_DEFAULT_UNICAST_PORT;
    face_instance->descr.mcast_ttl = -1;
    face_instance->lifetime = (~0U) >> 1;

    CHKRES(res = ccnb_append_face_instance(newface, face_instance));
    temp->length = 0;
    CHKRES(ccn_charbuf_putf(temp, "%s/.ccnx/.ccnx_keystore", getenv("HOME")));
    res = ccn_keystore_init(keystore,
                            ccn_charbuf_as_string(temp),
                            "Th1s1sn0t8g00dp8ssw0rd.");
    CHKRES(res);

    ccnb_element_begin(keylocator_templ, CCN_DTAG_SignedInfo);
    ccnb_element_begin(keylocator_templ, CCN_DTAG_KeyLocator);
    ccnb_element_begin(keylocator_templ, CCN_DTAG_Key);
    CHKRES(ccn_append_pubkey_blob(keylocator_templ, ccn_keystore_public_key(keystore)));
    ccnb_element_end(keylocator_templ);	/* </Key> */
    ccnb_element_end(keylocator_templ);	/* </KeyLocator> */
    ccnb_element_end(keylocator_templ);    /* </SignedInfo> */
    sp.template_ccnb = keylocator_templ;
    sp.sp_flags |= CCN_SP_TEMPL_KEY_LOCATOR;
    sp.freshness = expire;
    ccn_charbuf_reset(temp);
    res = ccn_sign_content(h, temp, null_name, &sp,
                           newface->buf, newface->length);
    CHKRES(res);

    /* Create the new face */
    CHKRES(ccn_name_init(name));
    CHKRES(ccn_name_append_str(name, "ccnx"));
    CHKRES(ccn_name_append(name, ccndid, ccndid_size));
    CHKRES(ccn_name_append(name, "newface", 7));
    CHKRES(ccn_name_append(name, temp->buf, temp->length));
    res = ccn_get(h, name, templ, 1000, resultbuf, &pcobuf, NULL, 0);
    if (res < 0) {
        fprintf(stderr, "no response from face creation request\n");
        exit(1);
    }
    ptr = resultbuf->buf;
    length = resultbuf->length;
    res = ccn_content_get_value(resultbuf->buf, resultbuf->length, &pcobuf, &ptr, &length);
    CHKRES(res);
    face_instance = ccn_face_instance_parse(ptr, length);
    if (face_instance == NULL)
        CHKRES(res = -1);
    CHKRES(face_instance->faceid);

    /* Finally, register the prefix */
    ccn_charbuf_reset(name_prefix);
    CHKRES(ccn_name_from_uri(name_prefix, arg));
    forwarding_entry->action = "prefixreg";
    forwarding_entry->name_prefix = name_prefix;
    forwarding_entry->ccnd_id = ccndid;
    forwarding_entry->ccnd_id_size = ccndid_size;
    forwarding_entry->faceid = face_instance->faceid;
    forwarding_entry->flags = -1; /* let ccnd decide */
    forwarding_entry->lifetime = (~0U) >> 1;
    prefixreg = ccn_charbuf_create();
    CHKRES(res = ccnb_append_forwarding_entry(prefixreg, forwarding_entry));
    ccn_charbuf_reset(temp);
    res = ccn_sign_content(h, temp, null_name, &sp,
                           prefixreg->buf, prefixreg->length);
    CHKRES(res);
    CHKRES(ccn_name_init(name));
    CHKRES(ccn_name_append_str(name, "ccnx"));
    CHKRES(ccn_name_append(name, ccndid, ccndid_size));
    CHKRES(ccn_name_append_str(name, "prefixreg"));
    CHKRES(ccn_name_append(name, temp->buf, temp->length));
    res = ccn_get(h, name, templ, 1000, resultbuf, &pcobuf, NULL, 0);
    if (res < 0) {
        fprintf(stderr, "no response from prefix registration request\n");
        exit(1);
    }
    fprintf(stderr, "Prefix %s will be forwarded to face %d\n", arg, face_instance->faceid);

    /* We're about to exit, so don't bother to free everything. */
    ccn_destroy(&h);
    exit(res < 0);
}
Пример #21
0
enum ccn_upcall_res
incoming_content(
    struct ccn_closure *selfp,
    enum ccn_upcall_kind kind,
    struct ccn_upcall_info *info)
{
    struct ccn_charbuf *name = NULL;
    struct ccn_charbuf *templ = NULL;
    struct ccn_charbuf *temp = NULL;
    const unsigned char *ccnb = NULL;
    size_t ccnb_size = 0;
    const unsigned char *data = NULL;
    size_t data_size = 0;
    // TANG: no need to write data to stdout
    //size_t written;
    const unsigned char *ib = NULL; /* info->interest_ccnb */
    struct ccn_indexbuf *ic = NULL;
    int res;
    struct mydata *md = selfp->data;
    
    if (kind == CCN_UPCALL_FINAL) {
        if (md != NULL) {
            selfp->data = NULL;
            free(md);
            md = NULL;
        }
        return(CCN_UPCALL_RESULT_OK);
    }
    if (kind == CCN_UPCALL_INTEREST_TIMED_OUT)
        return(CCN_UPCALL_RESULT_REEXPRESS);
    if (kind != CCN_UPCALL_CONTENT && kind != CCN_UPCALL_CONTENT_UNVERIFIED)
        return(CCN_UPCALL_RESULT_ERR);
    if (md == NULL)
        selfp->data = md = calloc(1, sizeof(*md));
    ccnb = info->content_ccnb;
    ccnb_size = info->pco->offset[CCN_PCO_E];
    ib = info->interest_ccnb;
    ic = info->interest_comps;
    /* XXX - must verify sig, and make sure it is LEAF content */
    res = ccn_content_get_value(ccnb, ccnb_size, info->pco, &data, &data_size);
    if (res < 0) abort();
    if (data_size > CHUNK_SIZE) {
        /* For us this is spam. Give up now. */
        fprintf(stderr, "*** Segment %d found with a data size of %d."
                        " This program only works with segments of 1024 bytes."
                        " Try ccncatchunks2 instead.\n",
                        (int)selfp->intdata, (int)data_size);
        exit(1);
    }
    
    /* OK, we will accept this block. */
    //sleep(1);
    // TANG: No need to write data to stdout, skip 3 lines
    //written = fwrite(data, data_size, 1, stdout);
    //if (written != 1)
    //    exit(1);
    
    /* A short block signals EOF for us. */
    // TANG: to support data_size smaller than 1024, skip 2 lines
    //if (data_size < CHUNK_SIZE)
    //    exit(0);
    
    /* Ask for the next one */
    name = ccn_charbuf_create();
    ccn_name_init(name);
    if (ic->n < 2) abort();
    res = ccn_name_append_components(name, ib, ic->buf[0], ic->buf[ic->n - 2]);
    if (res < 0) abort();
    temp = ccn_charbuf_create();
	//printf("intdata = %d \n ", selfp->intdata);
    ccn_charbuf_putf(temp, "%d", ++(selfp->intdata));
    ccn_name_append(name, temp->buf, temp->length);
    ccn_charbuf_destroy(&temp);
	
	if(DEBUG){
		//Print out the interest's name
		printf("Interest name = ");
		
		int myres = 0;
		struct ccn_indexbuf* ndx = ccn_indexbuf_create();
		unsigned char* mycomp = NULL;
		size_t mysize = 0;
		
		ndx->n = 0;
		myres = ccn_name_split(name, ndx);
		if(myres < 0){
			fprintf(stderr, "ccn_name_split @ ccntraffic. failed");
		}
		
		int it = 0;
		for(it = 0; it < ndx->n-1; it++){
			mysize = 0;
			myres = ccn_name_comp_get(name->buf, ndx, it, &mycomp, &mysize);
			printf("%s/", mycomp);
			mycomp = NULL;
		}
		
		printf("\n");
	}
	
    templ = make_template(md);

    res = ccn_express_interest(info->h, name, selfp, templ);
    if (res < 0) abort();
    
    ccn_charbuf_destroy(&templ);
    ccn_charbuf_destroy(&name);
    
    return(CCN_UPCALL_RESULT_OK);
}
Пример #22
0
enum ccn_upcall_res
ccn_text_handler(struct ccn_closure *selfp,
		    enum ccn_upcall_kind kind,
		    struct ccn_upcall_info *info)
{
    UserDataBuf *userBuf  = (UserDataBuf *)selfp->data;
    if (userBuf == NULL || userBuf->iNeedDestroy) {
        //if (userBuf != NULL) delete userBuf;
        //selfp->data = NULL;
        return CCN_UPCALL_RESULT_OK;
    }

	switch (kind) {
	case CCN_UPCALL_INTEREST_TIMED_OUT: {
		// if it's short Interest without seq, reexpress
		// TODO: check whether the user is still in the conference
		//	     don't re-express if it is not
		return (CCN_UPCALL_RESULT_REEXPRESS);
	}
	case CCN_UPCALL_CONTENT_UNVERIFIED:
		fprintf(stderr, "unverified content received\n");
		return CCN_UPCALL_RESULT_OK;
	case CCN_UPCALL_FINAL:
        return CCN_UPCALL_RESULT_OK;
	case CCN_UPCALL_CONTENT:
		break;
	default:
		return CCN_UPCALL_RESULT_OK;

	}

    struct data_buffer *buffer = &userBuf->data_buf;
    const unsigned char *content_value;
	size_t len;
    NDNState *state = buffer->state;

	const unsigned char *ccnb = info->content_ccnb;
	size_t ccnb_size = info->pco->offset[CCN_PCO_E];
	struct ccn_indexbuf *comps = info->content_comps;

	ccn_content_get_value(ccnb, ccnb_size, info->pco,
			&content_value, &len);

	unsigned char *msg = (unsigned char *)calloc((len + 1), sizeof(char));
	memcpy(msg, content_value, len);
	msg[len] = '\0';
	QString textMsg = (const char *)msg;
	state->emitTextMsgArrival(userBuf->user_name, textMsg);
	free(msg);

	long seq;
	const unsigned char *seqptr = NULL;
	char *endptr = NULL;
	size_t seq_size = 0;
	int k = comps->n - 2;

	seq = ccn_ref_tagged_BLOB(CCN_DTAG_Component, ccnb,
			comps->buf[k], comps->buf[k + 1],
			&seqptr, &seq_size);
	if (seq >= 0) {
		seq = strtol((const char *)seqptr, &endptr, 10);
		if (endptr != ((const char *)seqptr) + seq_size)
			seq = -1;
	}
	if (seq < 0) {
		return CCN_UPCALL_RESULT_OK;
	}

	seq++;

	struct ccn_charbuf *path = ccn_charbuf_create();
	ccn_name_init(path);
	ccn_name_append_components(path, ccnb, comps->buf[0], comps->buf[k]);
	struct ccn_charbuf *temp = ccn_charbuf_create();
	ccn_charbuf_putf(temp, "%ld", seq);
	ccn_name_append(path, temp->buf, temp->length);
	int res = ccn_express_interest(info->h, path, selfp, NULL);
	if (res < 0) {
		fprintf(stderr, "sending the first interest failed\n");
		exit(1);
	}
	ccn_charbuf_destroy(&path);
	ccn_charbuf_destroy(&temp);

    return CCN_UPCALL_RESULT_OK;
}
Пример #23
0
/**
 * Handle the incoming content messages. Extracts the data, and
 * requests the next block in sequence if the received block was
 * not the final one.
 */
enum ccn_upcall_res
incoming_content(struct ccn_closure *selfp,
                 enum ccn_upcall_kind kind,
                 struct ccn_upcall_info *info)
{
    struct ccn_charbuf *name = NULL;
    struct ccn_charbuf *templ = NULL;
    const unsigned char *ccnb = NULL;
    size_t ccnb_size = 0;
    const unsigned char *data = NULL;
    size_t data_size = 0;
    size_t written;
    const unsigned char *ib = NULL; /* info->interest_ccnb */
    struct ccn_indexbuf *ic = NULL;
    int res;
    struct mydata *md = selfp->data;
    
    if (kind == CCN_UPCALL_FINAL) {
        if (md != NULL) {
            selfp->data = NULL;
            free(md);
            md = NULL;
        }
        return(CCN_UPCALL_RESULT_OK);
    }
    if (kind == CCN_UPCALL_INTEREST_TIMED_OUT)
        return(CCN_UPCALL_RESULT_REEXPRESS);
    if (kind == CCN_UPCALL_CONTENT_UNVERIFIED)
        return(CCN_UPCALL_RESULT_VERIFY);
    if (kind != CCN_UPCALL_CONTENT)
        return(CCN_UPCALL_RESULT_ERR);
    if (md == NULL)
        selfp->data = md = calloc(1, sizeof(*md));
    ccnb = info->content_ccnb;
    ccnb_size = info->pco->offset[CCN_PCO_E];
    ib = info->interest_ccnb;
    ic = info->interest_comps;
    res = ccn_content_get_value(ccnb, ccnb_size, info->pco, &data, &data_size);
    if (res < 0) abort();
    if (info->pco->type != CCN_CONTENT_DATA) {
        /* For us this is spam. For now, give up. */
        fprintf(stderr, "*** spammed at block %d\n", (int)selfp->intdata);
        exit(1);
    }
    
    /* OK, we will accept this block. */
    if (data_size == 0)
        *(md->done) = 1;
    else {
        written = fwrite(data, data_size, 1, stdout);
        if (written != 1)
            exit(1);
    }
    // XXX The test below should get refactored into the library
    if (info->pco->offset[CCN_PCO_B_FinalBlockID] !=
        info->pco->offset[CCN_PCO_E_FinalBlockID]) {
        const unsigned char *finalid = NULL;
        size_t finalid_size = 0;
        const unsigned char *nameid = NULL;
        size_t nameid_size = 0;
        struct ccn_indexbuf *cc = info->content_comps;
        ccn_ref_tagged_BLOB(CCN_DTAG_FinalBlockID, ccnb,
                            info->pco->offset[CCN_PCO_B_FinalBlockID],
                            info->pco->offset[CCN_PCO_E_FinalBlockID],
                            &finalid,
                            &finalid_size);
        if (cc->n < 2) abort();
        ccn_ref_tagged_BLOB(CCN_DTAG_Component, ccnb,
                            cc->buf[cc->n - 2],
                            cc->buf[cc->n - 1],
                            &nameid,
                            &nameid_size);
        if (finalid_size == nameid_size &&
              0 == memcmp(finalid, nameid, nameid_size))
            *(md->done) = 1;
    }
    
    if (*(md->done)) {
        ccn_set_run_timeout(info->h, 0);
        return(CCN_UPCALL_RESULT_OK);
    }
    
    /* Ask for the next fragment */
    name = ccn_charbuf_create();
    ccn_name_init(name);
    if (ic->n < 2) abort();
    res = ccn_name_append_components(name, ib, ic->buf[0], ic->buf[ic->n - 2]);
    if (res < 0) abort();
    ccn_name_append_numeric(name, CCN_MARKER_SEQNUM, ++(selfp->intdata));
    templ = make_template(md, info);
    
    res = ccn_express_interest(info->h, name, selfp, templ);
    if (res < 0) abort();
    
    ccn_charbuf_destroy(&templ);
    ccn_charbuf_destroy(&name);
    
    return(CCN_UPCALL_RESULT_OK);
}