// my_response is used to handle a reply static enum ccn_upcall_res my_response(struct ccn_closure *selfp, enum ccn_upcall_kind kind, struct ccn_upcall_info *info) { static char *here = "sync_track.my_response"; enum ccn_upcall_res ret = CCN_UPCALL_RESULT_ERR; switch (kind) { case CCN_UPCALL_FINAL: free(selfp); ret = CCN_UPCALL_RESULT_OK; break; case CCN_UPCALL_CONTENT_UNVERIFIED: ret = CCN_UPCALL_RESULT_VERIFY; break; case CCN_UPCALL_CONTENT_KEYMISSING: ret = CCN_UPCALL_RESULT_FETCHKEY; break; case CCN_UPCALL_INTEREST_TIMED_OUT: { struct sync_diff_fetch_data *fd = selfp->data; //enum local_flags flags = selfp->intdata; if (fd == NULL) break; struct sync_diff_data *diff_data = fd->diff_data; if (diff_data == NULL) break; struct ccns_handle *ch = diff_data->client_data; free_fetch_data(ch, fd); start_round(ch, 10); ret = CCN_UPCALL_RESULT_OK; break; } case CCN_UPCALL_CONTENT_RAW: case CCN_UPCALL_CONTENT: { struct sync_diff_fetch_data *fd = selfp->data; enum local_flags flags = selfp->intdata; if (fd == NULL) break; struct sync_diff_data *diff_data = fd->diff_data; if (diff_data == NULL) break; struct SyncRootStruct *root = diff_data->root; if (root == NULL) break; struct ccns_handle *ch = diff_data->client_data; struct SyncNodeComposite *nc = extractNode(root, info); if (ch->debug >= CCNL_FINE) { char fs[1024]; int pos = 0; switch (flags) { case LF_NULL: pos += snprintf(fs+pos, sizeof(fs)-pos, "null"); break; case LF_ADVISE: pos += snprintf(fs+pos, sizeof(fs)-pos, "advise"); break; case LF_NODE: pos += snprintf(fs+pos, sizeof(fs)-pos, "node"); break; default: pos += snprintf(fs+pos, sizeof(fs)-pos, "??%d", flags); break; } if (nc != NULL) pos += snprintf(fs+pos, sizeof(fs)-pos, ", nc OK"); struct ccn_charbuf *nm = SyncNameForIndexbuf(info->content_ccnb, info->content_comps); struct ccn_charbuf *uri = SyncUriForName(nm); pos += snprintf(fs+pos, sizeof(fs)-pos, ", %s", ccn_charbuf_as_string(uri)); SyncNoteSimple(diff_data->root, here, fs); ccn_charbuf_destroy(&nm); ccn_charbuf_destroy(&uri); } if (nc != NULL) { // the node exists, so store it // TBD: check the hash? struct ccns_handle *ch = diff_data->client_data; struct SyncHashCacheEntry *ce = SyncHashEnter(root->ch, nc->hash->buf, nc->hash->length, SyncHashState_remote); if (flags == LF_ADVISE) { ch->hashSeen = SyncNoteHash(ch->hashSeen, ce); if (ch->next_ce == NULL) // have to have an initial place to start ch->next_ce = ce; } if (ce->ncR == NULL) { // store the node ce->ncR = nc; SyncNodeIncRC(nc); } else { // flush the node SyncNodeDecRC(nc); nc = NULL; } if (flags != LF_NULL) { // from start_interest start_round(ch, 10); } else { // from sync_diff sync_diff_note_node(diff_data, ce); } ret = CCN_UPCALL_RESULT_OK; } free_fetch_data(ch, fd); break; default: // SHOULD NOT HAPPEN break; } } return ret; }
static enum ccn_upcall_res advise_interest_arrived(struct ccn_closure *selfp, enum ccn_upcall_kind kind, struct ccn_upcall_info *info) { // the reason to have a listener is to be able to listen for changes // in the collection without relying on the replies to our root advise // interests, which may not receive timely replies (althoug they eventually // get replies) static char *here = "sync_track.advise_interest_arrived"; enum ccn_upcall_res ret = CCN_UPCALL_RESULT_ERR; switch (kind) { case CCN_UPCALL_FINAL: free(selfp); ret = CCN_UPCALL_RESULT_OK; break; case CCN_UPCALL_INTEREST: { struct ccns_handle *ch = selfp->data; if (ch == NULL) { // this got cancelled ret = CCN_UPCALL_RESULT_OK; break; } struct sync_diff_data *diff_data = ch->diff_data; struct SyncRootStruct *root = ch->root; //struct SyncBaseStruct *base = root->base; int skipToHash = SyncComponentCount(diff_data->root->topoPrefix) + 2; // skipToHash gets to the new hash // topo + marker + sliceHash const unsigned char *hp = NULL; size_t hs = 0; if (ch->debug >= CCNL_FINE) { struct ccn_charbuf *name = SyncNameForIndexbuf(info->interest_ccnb, info->interest_comps); SyncNoteUri(root, here, "entered", name); ccn_charbuf_destroy(&name); } int cres = ccn_name_comp_get(info->interest_ccnb, info->interest_comps, skipToHash, &hp, &hs); if (cres < 0) { if (ch->debug >= CCNL_INFO) SyncNoteSimple(diff_data->root, here, "wrong number of interest name components"); break; } struct SyncHashCacheEntry *ce = SyncHashEnter(root->ch, hp, hs, SyncHashState_remote); if (ce == NULL || ce->state & SyncHashState_covered) { // should not be added if (ch->debug >= CCNL_FINE) SyncNoteSimple(diff_data->root, here, "skipped"); } else { // remember the remote hash, maybe start something if (ch->debug >= CCNL_FINE) SyncNoteSimple(diff_data->root, here, "noting"); ch->hashSeen = SyncNoteHash(ch->hashSeen, ce); start_interest(diff_data); } ret = CCN_UPCALL_RESULT_OK; break; } default: // SHOULD NOT HAPPEN break; } return ret; }
// Enumeration support extern int SyncNotifyContent(struct SyncBaseStruct *base, int enumeration, ccnr_accession item, struct ccn_charbuf *name) { // here for any updates, whether from time-based enumeration // or from prefix-based enumeration char *here = "Sync.SyncNotifyContent"; if (base != NULL && base->ccnr != NULL) { struct SyncPrivate *priv = base->priv; int debug = base->debug; if (name == NULL) { // end of an enumeration if (enumeration == 0) { if (debug >= CCNL_WARNING) ccnr_msg(base->ccnr, "%s, end of time-based enum?", here); } else if (enumeration == priv->sliceEnum) { priv->sliceEnum = 0; if (debug >= CCNL_INFO) ccnr_msg(base->ccnr, "%s, all slice names seen", here); } else if (enumeration == priv->sliceBusy) { priv->sliceBusy = 0; struct SyncRootStruct *root = priv->rootHead; while (root != NULL) { struct SyncRootPrivate *rp = root->priv; if (enumeration == rp->sliceBusy) { rp->sliceBusy = 0; if (debug >= CCNL_INFO) SyncNoteSimple(root, here, "slice enum done"); break; } root = root->next; } // may need a new enumeration started root = priv->rootHead; while (root != NULL) { struct SyncRootPrivate *rp = root->priv; if (rp->sliceBusy < 0) { SyncStartSliceEnum(root); break; } root = root->next; } } else { if (debug >= CCNL_WARNING) ccnr_msg(base->ccnr, "%s, end of what enum?", here); } return -1; } if (debug >= CCNL_FINE) { struct ccn_charbuf *uri = SyncUriForName(name); ccnr_msg(base->ccnr, "%s, enum %d, %s!", here, enumeration, ccn_charbuf_as_string(uri)); ccn_charbuf_destroy(&uri); } struct ccn_indexbuf *comps = priv->comps; int splitRes = ccn_name_split(name, comps); if (splitRes < 0) { // really hould not happen! but it does not hurt to log and ignore it if (debug >= CCNL_SEVERE) ccnr_msg(base->ccnr, "%s, invalid name!", here); return 0; } unsigned char *comp0 = NULL; size_t size0 = 0; unsigned char *comp1 = NULL; size_t size1 = 0; ccn_name_comp_get(name->buf, comps, 0, (const unsigned char **) &comp0, &size0); ccn_name_comp_get(name->buf, comps, 1, (const unsigned char **) &comp1, &size1); ccnr_accession mark = item; if (SyncPrefixMatch(priv->localHostPrefix, name, 0)) { // to the local host, don't update the stable target mark = CCNR_NULL_ACCESSION; if (SyncPrefixMatch(priv->sliceCmdPrefix, name, 0)) // this is a new slice SyncHandleSlice(base, name); } if (mark != CCNR_NULL_ACCESSION) priv->stableTarget = ccnr_hwm_update(base->ccnr, priv->stableTarget, mark); // add the name to any applicable roots SyncAddName(base, name, item); return 0; } return -1; }