PUBLIC struct content_entry * process_incoming_content(struct ccnr_handle *h, struct fdholder *fdholder, unsigned char *msg, size_t size) { struct ccn_parsed_ContentObject obj = {0}; int res; struct content_entry *content = NULL; ccnr_accession accession = CCNR_NULL_ACCESSION; content = calloc(1, sizeof(*content)); if (content == NULL) goto Bail; content->cob = ccn_charbuf_create(); if (content->cob == NULL) goto Bail; res = ccn_charbuf_append(content->cob, msg, size); if (res < 0) goto Bail; content->size = size; res = r_store_set_flatname(h, content, &obj); if (res < 0) goto Bail; ccnr_meter_bump(h, fdholder->meter[FM_DATI], 1); content->accession = CCNR_NULL_ACCESSION; r_store_enroll_content(h, content); if (CCNSHOULDLOG(h, LM_4, CCNL_FINE)) ccnr_debug_content(h, __LINE__, "content_from", fdholder, content); res = r_store_content_btree_insert(h, content, &obj, &accession); if (res < 0) goto Bail; if (res == 0) { /* Content was there, with an accession */ if (CCNSHOULDLOG(h, LM_4, CCNL_FINER)) ccnr_debug_content(h, __LINE__, "content_duplicate", fdholder, content); h->content_dups_recvd++; r_store_forget_content(h, &content); content = r_store_content_from_accession(h, accession); if (content == NULL) goto Bail; } r_store_set_content_timer(h, content, &obj); r_match_match_interests(h, content, &obj, NULL, fdholder); return(content); Bail: r_store_forget_content(h, &content); return(content); }
/** * Send data to the fdholder. * * No direct error result is provided; the fdholder state is updated as needed. */ PUBLIC void r_io_send(struct ccnr_handle *h, struct fdholder *fdholder, const void *data, size_t size, off_t *offsetp) { ssize_t res; off_t offset = -1; if (offsetp != NULL) *offsetp = (off_t)-1; if ((fdholder->flags & CCNR_FACE_NOSEND) != 0) return; if (fdholder->outbuf != NULL) { ccn_charbuf_append(fdholder->outbuf, data, size); return; } if (fdholder == h->face0) { ccnr_meter_bump(h, fdholder->meter[FM_BYTO], size); ccn_dispatch_message(h->internal_client, (void *)data, size); r_dispatch_process_internal_client_buffer(h); return; } if ((fdholder->flags & CCNR_FACE_CCND) != 0) { /* Writes here need to go via the direct client's handle. */ ccnr_meter_bump(h, fdholder->meter[FM_BYTO], size); res = ccn_put(h->direct_client, data, size); if (res < 0 && CCNSHOULDLOG(h, r_io_send, CCNL_WARNING)) ccnr_msg(h, "ccn_put failed"); if (res == 1 && CCNSHOULDLOG(h, r_io_send, CCNL_FINEST)) ccnr_msg(h, "ccn_put deferred output for later send"); return; } if ((fdholder->flags & CCNR_FACE_REPODATA) != 0) { offset = lseek(fdholder->filedesc, 0, SEEK_END); if (offset == (off_t)-1) { ccnr_msg(h, "lseek(%d): %s", fdholder->filedesc, strerror(errno)); return; } if (offsetp != NULL) *offsetp = offset; if (fdholder->filedesc == h->active_out_fd) { if (offset != h->stable && h->stable != 0) ccnr_msg(h, "expected file size %ju, found %ju", (uintmax_t)h->stable, (uintmax_t)offset); h->stable = offset + size; } } if ((fdholder->flags & CCNR_FACE_DGRAM) == 0) res = write(fdholder->filedesc, data, size); else res = sendto(sending_fd(h, fdholder), data, size, 0, (struct sockaddr *)fdholder->name->buf, fdholder->name->length); if (res > 0) ccnr_meter_bump(h, fdholder->meter[FM_BYTO], res); if (res == size) return; if (res == -1) { res = handle_send_error(h, errno, fdholder, data, size); if (res == -1) return; } if ((fdholder->flags & CCNR_FACE_DGRAM) != 0) { ccnr_msg(h, "sendto short"); return; } if ((fdholder->flags & CCNR_FACE_REPODATA) != 0) { // need to truncate back to last known good object then exit. ccnr_msg(h, "Unrecoverable write error writing to repository. Content NOT stored."); ftruncate(fdholder->filedesc, offset); h->running = 0; return; } fdholder->outbufindex = 0; fdholder->outbuf = ccn_charbuf_create(); if (fdholder->outbuf == NULL) { ccnr_msg(h, "do_write: %s", strerror(errno)); return; } ccn_charbuf_append(fdholder->outbuf, ((const unsigned char *)data) + res, size - res); }