00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <errno.h>
00024 #include <stdint.h>
00025 #include <stdlib.h>
00026 #include <stdio.h>
00027 #include <fcntl.h>
00028 #include <string.h>
00029 #include <sys/errno.h>
00030 #include <sys/stat.h>
00031 #include <sys/types.h>
00032 #include <unistd.h>
00033 #include <ccn/ccn.h>
00034 #include <ccn/charbuf.h>
00035 #include <ccn/ccn_private.h>
00036 #include <ccn/schedule.h>
00037 #include <ccn/sockaddrutil.h>
00038 #include <ccn/uri.h>
00039 #include <ccn/coding.h>
00040 #include <sync/SyncBase.h>
00041 #include "ccnr_private.h"
00042
00043 #include "ccnr_proto.h"
00044
00045 #include "ccnr_dispatch.h"
00046 #include "ccnr_forwarding.h"
00047 #include "ccnr_init.h"
00048 #include "ccnr_io.h"
00049 #include "ccnr_msg.h"
00050 #include "ccnr_sendq.h"
00051 #include "ccnr_store.h"
00052 #include "ccnr_sync.h"
00053 #include "ccnr_util.h"
00054
00055 #define CCNR_MAX_RETRY 5
00056
00057 static enum ccn_upcall_res
00058 r_proto_start_write(struct ccn_closure *selfp,
00059 enum ccn_upcall_kind kind,
00060 struct ccn_upcall_info *info,
00061 int marker_comp);
00062
00063 static enum ccn_upcall_res
00064 r_proto_start_write_checked(struct ccn_closure *selfp,
00065 enum ccn_upcall_kind kind,
00066 struct ccn_upcall_info *info,
00067 int marker_comp);
00068
00069 static enum ccn_upcall_res
00070 r_proto_begin_enumeration(struct ccn_closure *selfp,
00071 enum ccn_upcall_kind kind,
00072 struct ccn_upcall_info *info,
00073 int marker_comp);
00074
00075 static enum ccn_upcall_res
00076 r_proto_continue_enumeration(struct ccn_closure *selfp,
00077 enum ccn_upcall_kind kind,
00078 struct ccn_upcall_info *info,
00079 int marker_comp);
00080
00081 static enum ccn_upcall_res
00082 r_proto_bulk_import(struct ccn_closure *selfp,
00083 enum ccn_upcall_kind kind,
00084 struct ccn_upcall_info *info,
00085 int marker_comp);
00086 static int
00087 name_comp_equal_prefix(const unsigned char *data,
00088 const struct ccn_indexbuf *indexbuf,
00089 unsigned int i, const void *buf, size_t length);
00090
00091 PUBLIC enum ccn_upcall_res
00092 r_proto_answer_req(struct ccn_closure *selfp,
00093 enum ccn_upcall_kind kind,
00094 struct ccn_upcall_info *info)
00095 {
00096 struct ccn_charbuf *msg = NULL;
00097 struct ccn_charbuf *name = NULL;
00098 struct ccn_charbuf *keylocator = NULL;
00099 struct ccn_charbuf *signed_info = NULL;
00100 struct ccn_charbuf *reply_body = NULL;
00101 struct ccnr_handle *ccnr = NULL;
00102 struct content_entry *content = NULL;
00103 int res = 0;
00104 int ncomps;
00105 int marker_comp;
00106
00107
00108 switch (kind) {
00109 case CCN_UPCALL_FINAL:
00110 free(selfp);
00111 return(CCN_UPCALL_RESULT_OK);
00112 case CCN_UPCALL_INTEREST:
00113 break;
00114 case CCN_UPCALL_CONSUMED_INTEREST:
00115 return(CCN_UPCALL_RESULT_OK);
00116 default:
00117 return(CCN_UPCALL_RESULT_ERR);
00118 }
00119 ccnr = (struct ccnr_handle *)selfp->data;
00120 if (CCNSHOULDLOG(ccnr, LM_128, CCNL_FINE))
00121 ccnr_debug_ccnb(ccnr, __LINE__, "r_proto_answer_req", NULL,
00122 info->interest_ccnb, info->pi->offset[CCN_PI_E]);
00123
00124 content = r_store_lookup(ccnr, info->interest_ccnb, info->pi, info->interest_comps);
00125 if (content != NULL) {
00126 struct fdholder *fdholder = r_io_fdholder_from_fd(ccnr, ccn_get_connection_fd(info->h));
00127 if (fdholder != NULL)
00128 r_sendq_face_send_queue_insert(ccnr, r_io_fdholder_from_fd(ccnr, ccn_get_connection_fd(info->h)), content);
00129 res = CCN_UPCALL_RESULT_INTEREST_CONSUMED;
00130 goto Finish;
00131 }
00132
00133 if ((info->pi->answerfrom & CCN_AOK_NEW) == 0) {
00134 goto Bail;
00135 }
00136
00137
00138 ncomps = info->interest_comps->n;
00139 if (((marker_comp = ncomps - 2) >= 0) &&
00140 0 == r_util_name_comp_compare(info->interest_ccnb, info->interest_comps, marker_comp, NAME_BE, strlen(NAME_BE))) {
00141 if (CCNSHOULDLOG(ccnr, LM_8, CCNL_FINER))
00142 ccnr_debug_ccnb(ccnr, __LINE__, "name_enumeration", NULL,
00143 info->interest_ccnb, info->pi->offset[CCN_PI_E]);
00144 res = r_proto_begin_enumeration(selfp, kind, info, marker_comp);
00145 goto Finish;
00146 } else if (((marker_comp = ncomps - 3) >= 0) &&
00147 0 == r_util_name_comp_compare(info->interest_ccnb, info->interest_comps, marker_comp, NAME_BE, strlen(NAME_BE)) &&
00148 0 == r_util_name_comp_compare(info->interest_ccnb, info->interest_comps, marker_comp + 1, ccnr->ccnr_keyid->buf, ccnr->ccnr_keyid->length)) {
00149 if (CCNSHOULDLOG(ccnr, LM_8, CCNL_FINER))
00150 ccnr_debug_ccnb(ccnr, __LINE__, "name_enumeration_repoid", NULL,
00151 info->interest_ccnb, info->pi->offset[CCN_PI_E]);
00152 res = r_proto_begin_enumeration(selfp, kind, info, marker_comp);
00153 goto Finish;
00154 } else if (((marker_comp = ncomps - 5) >= 0) &&
00155 0 == r_util_name_comp_compare(info->interest_ccnb, info->interest_comps, marker_comp, NAME_BE, strlen(NAME_BE)) &&
00156 0 == r_util_name_comp_compare(info->interest_ccnb, info->interest_comps, marker_comp + 1, ccnr->ccnr_keyid->buf, ccnr->ccnr_keyid->length)) {
00157 if (CCNSHOULDLOG(ccnr, LM_8, CCNL_FINER))
00158 ccnr_debug_ccnb(ccnr, __LINE__, "name_enumeration_continuation",
00159 NULL, info->interest_ccnb, info->pi->offset[CCN_PI_E]);
00160 res = r_proto_continue_enumeration(selfp, kind, info, marker_comp);
00161 goto Finish;
00162 } else if (((marker_comp = ncomps - 3) > 0) &&
00163 0 == r_util_name_comp_compare(info->interest_ccnb, info->interest_comps, marker_comp, REPO_SW, strlen(REPO_SW))) {
00164 if (CCNSHOULDLOG(ccnr, LM_8, CCNL_FINER))
00165 ccnr_debug_ccnb(ccnr, __LINE__, "repo_start_write", NULL,
00166 info->interest_ccnb, info->pi->offset[CCN_PI_E]);
00167 res = r_proto_start_write(selfp, kind, info, marker_comp);
00168 goto Finish;
00169 } else if (((marker_comp = ncomps - 5) > 0) &&
00170 0 == r_util_name_comp_compare(info->interest_ccnb, info->interest_comps, marker_comp, REPO_SWC, strlen(REPO_SWC))) {
00171 if (CCNSHOULDLOG(ccnr, LM_8, CCNL_FINER))
00172 ccnr_debug_ccnb(ccnr, __LINE__, "repo_start_write_checked",
00173 NULL, info->interest_ccnb, info->pi->offset[CCN_PI_E]);
00174 res = r_proto_start_write_checked(selfp, kind, info, marker_comp);
00175 goto Finish;
00176 } else if (((marker_comp = 0) == 0) &&
00177 name_comp_equal_prefix(info->interest_ccnb, info->interest_comps, marker_comp, REPO_AF, strlen(REPO_AF))) {
00178 if (CCNSHOULDLOG(ccnr, LM_8, CCNL_FINER))
00179 ccnr_debug_ccnb(ccnr, __LINE__, "repo_bulk_import",
00180 NULL, info->interest_ccnb, info->pi->offset[CCN_PI_E]);
00181 res = r_proto_bulk_import(selfp, kind, info, marker_comp);
00182 goto Finish;
00183 }
00184 goto Bail;
00185 Bail:
00186 res = CCN_UPCALL_RESULT_ERR;
00187 Finish:
00188 ccn_charbuf_destroy(&msg);
00189 ccn_charbuf_destroy(&name);
00190 ccn_charbuf_destroy(&keylocator);
00191 ccn_charbuf_destroy(&reply_body);
00192 ccn_charbuf_destroy(&signed_info);
00193 return(res);
00194 }
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204 static int
00205 name_comp_equal_prefix(const unsigned char *data,
00206 const struct ccn_indexbuf *indexbuf,
00207 unsigned int i, const void *buf, size_t length)
00208 {
00209 const unsigned char *comp_ptr;
00210 size_t comp_size;
00211
00212 if (ccn_name_comp_get(data, indexbuf, i, &comp_ptr, &comp_size) != 0)
00213 return(0);
00214 if (comp_size < length || memcmp(comp_ptr, buf, length) != 0)
00215 return(0);
00216 return(1);
00217 }
00218
00219 PUBLIC void
00220 r_proto_uri_listen(struct ccnr_handle *ccnr, struct ccn *ccn, const char *uri,
00221 ccn_handler p, intptr_t intdata)
00222 {
00223 struct ccn_charbuf *name;
00224 struct ccn_closure *closure = NULL;
00225
00226 name = ccn_charbuf_create();
00227 ccn_name_from_uri(name, uri);
00228 if (p != NULL) {
00229 closure = calloc(1, sizeof(*closure));
00230 closure->p = p;
00231 closure->data = ccnr;
00232 closure->intdata = intdata;
00233 }
00234 ccn_set_interest_filter(ccn, name, closure);
00235 ccn_charbuf_destroy(&name);
00236 }
00237
00238
00239 PUBLIC void
00240 r_proto_init(struct ccnr_handle *ccnr) {
00241
00242 }
00243
00244
00245
00246
00247
00248 PUBLIC void
00249 r_proto_activate_policy(struct ccnr_handle *ccnr, struct ccnr_parsed_policy *pp) {
00250 int i;
00251
00252 for (i = 0; i < pp->namespaces->n; i++) {
00253 if (CCNSHOULDLOG(ccnr, sdfdf, CCNL_INFO))
00254 ccnr_msg(ccnr, "Adding listener for policy namespace %s",
00255 (char *)pp->store->buf + pp->namespaces->buf[i]);
00256 r_proto_uri_listen(ccnr, ccnr->direct_client,
00257 (char *)pp->store->buf + pp->namespaces->buf[i],
00258 r_proto_answer_req, 0);
00259 }
00260 if (CCNSHOULDLOG(ccnr, sdfdf, CCNL_INFO))
00261 ccnr_msg(ccnr, "Adding listener for policy global prefix %s",
00262 (char *)pp->store->buf + pp->global_prefix_offset);
00263 r_proto_uri_listen(ccnr, ccnr->direct_client,
00264 (char *)pp->store->buf + pp->global_prefix_offset,
00265 r_proto_answer_req, 0);
00266 }
00267
00268
00269
00270 PUBLIC void
00271 r_proto_deactivate_policy(struct ccnr_handle *ccnr, struct ccnr_parsed_policy *pp) {
00272 int i;
00273
00274 if (CCNSHOULDLOG(ccnr, sdfdf, CCNL_INFO))
00275 ccnr_msg(ccnr, "Removing listener for policy global prefix %s",
00276 (char *)pp->store->buf + pp->global_prefix_offset);
00277 r_proto_uri_listen(ccnr, ccnr->direct_client,
00278 (char *)pp->store->buf + pp->global_prefix_offset,
00279 NULL, 0);
00280 for (i = 0; i < pp->namespaces->n; i++) {
00281 if (CCNSHOULDLOG(ccnr, sdfdf, CCNL_INFO))
00282 ccnr_msg(ccnr, "Removing listener for policy namespace %s",
00283 (char *)pp->store->buf + pp->namespaces->buf[i]);
00284 r_proto_uri_listen(ccnr, ccnr->direct_client,
00285 (char *)pp->store->buf + pp->namespaces->buf[i],
00286 NULL, 0);
00287 }
00288
00289 }
00290
00291
00292
00293
00294
00295 PUBLIC int
00296 r_proto_append_repo_info(struct ccnr_handle *ccnr,
00297 struct ccn_charbuf *rinfo,
00298 struct ccn_charbuf *names,
00299 const char *info) {
00300 int res;
00301 struct ccn_charbuf *name = ccn_charbuf_create();
00302 if (name == NULL) return (-1);
00303 res = ccnb_element_begin(rinfo, CCN_DTAG_RepositoryInfo);
00304 res |= ccnb_tagged_putf(rinfo, CCN_DTAG_Version, "%s", "1.1");
00305 res |= ccnb_tagged_putf(rinfo, CCN_DTAG_Type, "%s", (names != NULL) ? "DATA" : "INFO");
00306 res |= ccnb_tagged_putf(rinfo, CCN_DTAG_RepositoryVersion, "%s", "2.0");
00307 res |= ccnb_element_begin(rinfo, CCN_DTAG_GlobalPrefixName);
00308 res |= ccnb_element_end(rinfo);
00309 ccn_name_init(name);
00310 res |= ccn_name_from_uri(name, (char *)ccnr->parsed_policy->store->buf + ccnr->parsed_policy->global_prefix_offset);
00311 res |= ccn_name_append_components(rinfo, name->buf, 1, name->length - 1);
00312 res |= ccnb_tagged_putf(rinfo, CCN_DTAG_LocalName, "%s", "Repository");
00313 if (names != NULL)
00314 res |= ccn_charbuf_append_charbuf(rinfo, names);
00315 if (info != NULL)
00316 res |= ccnb_tagged_putf(rinfo, CCN_DTAG_InfoString, "%s", info);
00317
00318 res |= ccnb_element_end(rinfo);
00319 ccn_charbuf_destroy(&name);
00320 return (res);
00321 }
00322
00323 static struct ccn_charbuf *
00324 r_proto_mktemplate(struct ccnr_expect_content *md, struct ccn_upcall_info *info)
00325 {
00326 struct ccn_charbuf *templ = ccn_charbuf_create();
00327 ccnb_element_begin(templ, CCN_DTAG_Interest);
00328 ccnb_element_begin(templ, CCN_DTAG_Name);
00329 ccnb_element_end(templ);
00330
00331
00332 ccnb_tagged_putf(templ, CCN_DTAG_MinSuffixComponents, "%d", 1);
00333 ccnb_tagged_putf(templ, CCN_DTAG_MaxSuffixComponents, "%d", 1);
00334 ccnb_element_end(templ);
00335 return(templ);
00336 }
00337
00338 PUBLIC enum ccn_upcall_res
00339 r_proto_expect_content(struct ccn_closure *selfp,
00340 enum ccn_upcall_kind kind,
00341 struct ccn_upcall_info *info)
00342 {
00343 struct ccn_charbuf *name = NULL;
00344 struct ccn_charbuf *templ = NULL;
00345 const unsigned char *ccnb = NULL;
00346 size_t ccnb_size = 0;
00347 const unsigned char *ib = NULL;
00348 struct ccn_indexbuf *ic = NULL;
00349 int res;
00350 struct ccnr_expect_content *md = selfp->data;
00351 struct ccnr_handle *ccnr = NULL;
00352 struct content_entry *content = NULL;
00353 int i;
00354 int empty_slots;
00355 intmax_t segment;
00356
00357 if (kind == CCN_UPCALL_FINAL) {
00358 if (md != NULL) {
00359 selfp->data = NULL;
00360 free(md);
00361 md = NULL;
00362 }
00363 free(selfp);
00364 return(CCN_UPCALL_RESULT_OK);
00365 }
00366 if (md == NULL) {
00367 return(CCN_UPCALL_RESULT_ERR);
00368 }
00369 if (md->done)
00370 return(CCN_UPCALL_RESULT_ERR);
00371 ccnr = (struct ccnr_handle *)md->ccnr;
00372 if (kind == CCN_UPCALL_INTEREST_TIMED_OUT) {
00373 if (md->tries > CCNR_MAX_RETRY) {
00374 ccnr_debug_ccnb(ccnr, __LINE__, "fetch_failed", NULL,
00375 info->interest_ccnb, info->pi->offset[CCN_PI_E]);
00376 return(CCN_UPCALL_RESULT_ERR);
00377 }
00378 md->tries++;
00379 return(CCN_UPCALL_RESULT_REEXPRESS);
00380 }
00381 if (kind == CCN_UPCALL_CONTENT_UNVERIFIED) {
00382
00383 if (CCNSHOULDLOG(ccnr, sdfdf, CCNL_FINE))
00384 ccnr_debug_ccnb(ccnr, __LINE__, "key_needed", NULL, info->content_ccnb, info->pco->offset[CCN_PCO_E]);
00385 }
00386 switch (kind) {
00387 case CCN_UPCALL_CONTENT:
00388 case CCN_UPCALL_CONTENT_UNVERIFIED:
00389 #if (CCN_API_VERSION >= 4004)
00390 case CCN_UPCALL_CONTENT_RAW:
00391 case CCN_UPCALL_CONTENT_KEYMISSING:
00392 #endif
00393 break;
00394 default:
00395 return(CCN_UPCALL_RESULT_ERR);
00396 }
00397
00398 ccnb = info->content_ccnb;
00399 ccnb_size = info->pco->offset[CCN_PCO_E];
00400 ib = info->interest_ccnb;
00401 ic = info->interest_comps;
00402
00403 content = process_incoming_content(ccnr, r_io_fdholder_from_fd(ccnr, ccn_get_connection_fd(info->h)),
00404 (void *)ccnb, ccnb_size);
00405 if (content == NULL) {
00406 ccnr_msg(ccnr, "r_proto_expect_content: failed to process incoming content");
00407 return(CCN_UPCALL_RESULT_ERR);
00408 }
00409 r_store_commit_content(ccnr, content);
00410 r_proto_initiate_key_fetch(ccnr, ccnb, info->pco, 0,
00411 r_store_content_cookie(ccnr, content));
00412
00413 md->tries = 0;
00414 segment = r_util_segment_from_component(ib, ic->buf[ic->n - 2], ic->buf[ic->n - 1]);
00415
00416 if (ccn_is_final_block(info) == 1)
00417 md->final = segment;
00418
00419 if (md->keyfetch != 0 && segment <= 0) {
00420
00421 if (info->pco->type == CCN_CONTENT_LINK) {
00422 r_proto_initiate_key_fetch(ccnr, ccnb, info->pco, 1, md->keyfetch);
00423 }
00424 else if (info->pco->type == CCN_CONTENT_KEY) {
00425 if (CCNSHOULDLOG(ccnr, sdfdf, CCNL_FINE))
00426 ccnr_msg(ccnr, "key_arrived %u", (unsigned)(md->keyfetch));
00427
00428 }
00429 else {
00430
00431 ccnr_msg(ccnr, "ERROR - got something else when trying to fetch key for item %u", (unsigned)(md->keyfetch));
00432 }
00433 }
00434
00435
00436 if (segment < 0) {
00437 if (md->expect_complete != NULL) {
00438 (md->expect_complete)(selfp, kind, info);
00439 }
00440 return(CCN_UPCALL_RESULT_OK);
00441 }
00442
00443
00444 empty_slots = 0;
00445 for (i = 0; i < CCNR_PIPELINE; i++) {
00446 if (md->outstanding[i] == segment || ((md->final > -1) && (md->outstanding[i] > md->final)))
00447 md->outstanding[i] = -1;
00448 if (md->outstanding[i] == -1)
00449 empty_slots++;
00450
00451 }
00452 md->done = (md->final > -1) && (empty_slots == CCNR_PIPELINE);
00453
00454
00455 if (md->done && (md->expect_complete != NULL))
00456 (md->expect_complete)(selfp, kind, info);
00457
00458 if (md->final > -1) {
00459 return (CCN_UPCALL_RESULT_OK);
00460 }
00461
00462 name = ccn_charbuf_create();
00463 if (ic->n < 2) abort();
00464 templ = r_proto_mktemplate(md, info);
00465
00466 for (i = 0; i < CCNR_PIPELINE; i++) {
00467 if (md->outstanding[i] == -1) {
00468 ccn_name_init(name);
00469 res = ccn_name_append_components(name, ib, ic->buf[0], ic->buf[ic->n - 2]);
00470 if (res < 0) abort();
00471 ccn_name_append_numeric(name, CCN_MARKER_SEQNUM, ++(selfp->intdata));
00472 res = ccn_express_interest(info->h, name, selfp, templ);
00473 if (res < 0) abort();
00474 md->outstanding[i] = selfp->intdata;
00475 }
00476 }
00477 ccn_charbuf_destroy(&templ);
00478 ccn_charbuf_destroy(&name);
00479
00480 return(CCN_UPCALL_RESULT_OK);
00481 }
00482
00483 static int
00484 r_proto_policy_update(struct ccn_schedule *sched,
00485 void *clienth,
00486 struct ccn_scheduled_event *ev,
00487 int flags)
00488 {
00489 struct ccnr_handle *ccnr = clienth;
00490 struct ccn_charbuf *name = ev->evdata;
00491 struct content_entry *content = NULL;
00492 const unsigned char *content_msg = NULL;
00493 const unsigned char *vers = NULL;
00494 size_t vers_size = 0;
00495 struct ccn_parsed_ContentObject pco = {0};
00496 struct ccn_indexbuf *nc;
00497 struct ccn_charbuf *policy = NULL;
00498 struct ccn_charbuf *policy_link_cob = NULL;
00499 struct ccn_charbuf *policyFileName = NULL;
00500 const unsigned char *buf = NULL;
00501 size_t length = 0;
00502 struct ccnr_parsed_policy *pp;
00503 int segment = -1;
00504 int final = 0;
00505 int res;
00506 int ans = -1;
00507 int fd = -1;
00508
00509 if ((flags & CCN_SCHEDULE_CANCEL) != 0) {
00510 ans = 0;
00511 goto Bail;
00512 }
00513
00514 policy = ccn_charbuf_create();
00515 nc = ccn_indexbuf_create();
00516 do {
00517 ccn_name_append_numeric(name, CCN_MARKER_SEQNUM, ++segment);
00518 content = r_store_lookup_ccnb(ccnr, name->buf, name->length);
00519 if (content == NULL) {
00520 ccnr_debug_ccnb(ccnr, __LINE__, "policy lookup failed for", NULL,
00521 name->buf, name->length);
00522 goto Bail;
00523 }
00524 ccn_name_chop(name, NULL, -1);
00525 content_msg = r_store_content_base(ccnr, content);
00526 res = ccn_parse_ContentObject(content_msg, r_store_content_size(ccnr, content), &pco, nc);
00527 res = ccn_ref_tagged_BLOB(CCN_DTAG_Content, content_msg,
00528 pco.offset[CCN_PCO_B_Content],
00529 pco.offset[CCN_PCO_E_Content],
00530 &buf, &length);
00531 ccn_charbuf_append(policy, buf, length);
00532 final = r_util_is_final_pco(content_msg, &pco, nc);
00533 } while (!final);
00534
00535 pp = ccnr_parsed_policy_create();
00536 if (pp == NULL) {
00537 ccnr_msg(ccnr, "Parsed policy allocation error");
00538 goto Bail;
00539 }
00540 memmove(pp->version, vers, vers_size);
00541 if (r_proto_parse_policy(ccnr, policy->buf, policy->length, pp) < 0) {
00542 ccnr_msg(ccnr, "Malformed policy");
00543 goto Bail;
00544 }
00545 res = strcmp((char *)pp->store->buf + pp->global_prefix_offset,
00546 (char *)ccnr->parsed_policy->store->buf + ccnr->parsed_policy->global_prefix_offset);
00547 if (0 != res) {
00548 ccnr_msg(ccnr, "Policy global prefix mismatch");
00549 goto Bail;
00550 }
00551 policy_link_cob = ccnr_init_policy_link_cob(ccnr, ccnr->direct_client, name);
00552 if (policy_link_cob != NULL)
00553 ccnr->policy_link_cob = policy_link_cob;
00554 policyFileName = ccn_charbuf_create();
00555 ccn_charbuf_putf(policyFileName, "%s/repoPolicy", ccnr->directory);
00556 fd = open(ccn_charbuf_as_string(policyFileName), O_WRONLY | O_CREAT, 0666);
00557 if (fd < 0) {
00558 ccnr_msg(ccnr, "open policy: %s (errno = %d)", strerror(errno), errno);
00559 goto Bail;
00560 }
00561 lseek(fd, 0, SEEK_SET);
00562 res = write(fd, ccnr->policy_link_cob->buf, ccnr->policy_link_cob->length);
00563 if (res == -1) {
00564 ccnr_msg(ccnr, "write policy: %s (errno = %d)", strerror(errno), errno);
00565 goto Bail;
00566 }
00567 res = ftruncate(fd, ccnr->policy_link_cob->length);
00568 if (res == -1) {
00569 ccnr_msg(ccnr, "Policy truncate %u :%s (errno = %d)",
00570 fd, strerror(errno), errno);
00571 goto Bail;
00572 }
00573 close(fd);
00574 fd = -1;
00575 r_proto_deactivate_policy(ccnr, ccnr->parsed_policy);
00576 ccnr_parsed_policy_destroy(&ccnr->parsed_policy);
00577 ccnr->parsed_policy = pp;
00578 r_proto_activate_policy(ccnr, pp);
00579
00580 ans = 0;
00581
00582 Bail:
00583 ccn_charbuf_destroy(&name);
00584 ccn_indexbuf_destroy(&nc);
00585 ccn_charbuf_destroy(&policy);
00586 ccn_charbuf_destroy(&policyFileName);
00587 if (fd >= 0) close(fd);
00588 return (ans);
00589
00590 }
00591
00592 static int
00593 r_proto_policy_complete(struct ccn_closure *selfp,
00594 enum ccn_upcall_kind kind,
00595 struct ccn_upcall_info *info)
00596 {
00597 struct ccnr_expect_content *md = selfp->data;
00598 struct ccnr_handle *ccnr = (struct ccnr_handle *)md->ccnr;
00599 const unsigned char *ccnb;
00600 size_t ccnb_size;
00601 const unsigned char *vers = NULL;
00602 size_t vers_size = 0;
00603 struct ccn_indexbuf *cc;
00604 struct ccn_charbuf *name;
00605 int res;
00606
00607
00608
00609
00610 ccnb = info->content_ccnb;
00611 ccnb_size = info->pco->offset[CCN_PCO_E];
00612 cc = info->content_comps;
00613 ccn_name_comp_get(ccnb, cc, cc->n - 3, &vers, &vers_size);
00614 if (vers_size != 7 || vers[0] != CCN_MARKER_VERSION)
00615 return(-1);
00616 if (memcmp(vers, ccnr->parsed_policy->version, sizeof(ccnr->parsed_policy->version)) <= 0) {
00617 if (CCNSHOULDLOG(ccnr, LM_128, CCNL_INFO))
00618 ccnr_debug_ccnb(ccnr, __LINE__, "r_proto_policy_complete older policy ignored", NULL,
00619 ccnb, ccnb_size);
00620 return (-1);
00621 }
00622
00623 name = ccn_charbuf_create();
00624 res = ccn_name_init(name);
00625 ccn_name_append_components(name, ccnb, cc->buf[0], cc->buf[cc->n - 2]);
00626 ccn_schedule_event(ccnr->sched, 500, r_proto_policy_update, name, 0);
00627 if (CCNSHOULDLOG(ccnr, LM_128, CCNL_FINEST))
00628 ccnr_msg(ccnr,"r_proto_policy_complete update scheduled");
00629
00630 return (0);
00631 }
00632
00633 static enum ccn_upcall_res
00634 r_proto_start_write(struct ccn_closure *selfp,
00635 enum ccn_upcall_kind kind,
00636 struct ccn_upcall_info *info,
00637 int marker_comp)
00638 {
00639 struct ccnr_handle *ccnr = NULL;
00640 struct ccn_charbuf *templ = NULL;
00641 struct ccn_closure *incoming = NULL;
00642 struct ccnr_expect_content *expect_content = NULL;
00643 struct ccn_charbuf *reply_body = NULL;
00644 struct ccn_charbuf *name = NULL;
00645 struct ccn_indexbuf *ic = NULL;
00646 enum ccn_upcall_res ans = CCN_UPCALL_RESULT_ERR;
00647 struct ccn_charbuf *msg = NULL;
00648 int res = 0;
00649 int start = 0;
00650 int end = 0;
00651 int is_policy = 0;
00652 int i;
00653 struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT;
00654
00655
00656
00657
00658
00659
00660 ccnr = (struct ccnr_handle *)selfp->data;
00661 if (ccnr->start_write_scope_limit < 3) {
00662 start = info->pi->offset[CCN_PI_B_Scope];
00663 end = info->pi->offset[CCN_PI_E_Scope];
00664 if (start == end || info->pi->scope > ccnr->start_write_scope_limit) {
00665 if (CCNSHOULDLOG(ccnr, LM_128, CCNL_INFO))
00666 ccnr_msg(ccnr, "r_proto_start_write: interest scope exceeds limit");
00667 return(CCN_UPCALL_RESULT_OK);
00668 }
00669 }
00670
00671 start = info->pi->offset[CCN_PI_B_Name];
00672 end = info->interest_comps->buf[marker_comp - 1];
00673 name = ccn_charbuf_create();
00674 ccn_charbuf_append(name, info->interest_ccnb + start, end - start);
00675 ccn_charbuf_append_closer(name);
00676 if (0 ==ccn_compare_names(name->buf, name->length,
00677 ccnr->policy_name->buf, ccnr->policy_name->length))
00678 is_policy = 1;
00679
00680
00681 start = info->pi->offset[CCN_PI_B_Name];
00682 end = info->interest_comps->buf[info->pi->prefix_comps];
00683 name->length = 0;
00684 ccn_charbuf_append(name, info->interest_ccnb + start, end - start);
00685 ccn_charbuf_append_closer(name);
00686 msg = ccn_charbuf_create();
00687 reply_body = ccn_charbuf_create();
00688 r_proto_append_repo_info(ccnr, reply_body, NULL, NULL);
00689 sp.freshness = 12;
00690 res = ccn_sign_content(info->h, msg, name, &sp,
00691 reply_body->buf, reply_body->length);
00692 if (res < 0)
00693 goto Bail;
00694 if (CCNSHOULDLOG(ccnr, LM_128, CCNL_FINE))
00695 ccnr_debug_ccnb(ccnr, __LINE__, "r_proto_start_write response", NULL,
00696 msg->buf, msg->length);
00697 res = ccn_put(info->h, msg->buf, msg->length);
00698 if (res < 0) {
00699 ccnr_debug_ccnb(ccnr, __LINE__, "r_proto_start_write ccn_put FAILED", NULL,
00700 msg->buf, msg->length);
00701 goto Bail;
00702 }
00703
00704
00705 expect_content = calloc(1, sizeof(*expect_content));
00706 if (expect_content == NULL)
00707 goto Bail;
00708 expect_content->ccnr = ccnr;
00709 expect_content->final = -1;
00710 for (i = 0; i < CCNR_PIPELINE; i++)
00711 expect_content->outstanding[i] = -1;
00712 if (is_policy) {
00713 expect_content->expect_complete = &r_proto_policy_complete;
00714 if (CCNSHOULDLOG(ccnr, LM_128, CCNL_FINE))
00715 ccnr_msg(ccnr, "r_proto_start_write: is policy file");
00716 }
00717 incoming = calloc(1, sizeof(*incoming));
00718 if (incoming == NULL)
00719 goto Bail;
00720 incoming->p = &r_proto_expect_content;
00721 incoming->data = expect_content;
00722 templ = r_proto_mktemplate(expect_content, NULL);
00723 ic = info->interest_comps;
00724 ccn_name_init(name);
00725 ccn_name_append_components(name, info->interest_ccnb, ic->buf[0], ic->buf[marker_comp]);
00726 ccn_name_append_numeric(name, CCN_MARKER_SEQNUM, 0);
00727 expect_content->outstanding[0] = 0;
00728 res = ccn_express_interest(info->h, name, incoming, templ);
00729 if (res >= 0) {
00730
00731 incoming = NULL;
00732 expect_content = NULL;
00733 ans = CCN_UPCALL_RESULT_INTEREST_CONSUMED;
00734 }
00735 else {
00736 ccnr_debug_ccnb(ccnr, __LINE__, "r_proto_start_write ccn_express_interest FAILED", NULL,
00737 name->buf, name->length);
00738 goto Bail;
00739 }
00740
00741 Bail:
00742 if (incoming != NULL)
00743 free(incoming);
00744 if (expect_content != NULL)
00745 free(expect_content);
00746 ccn_charbuf_destroy(&templ);
00747 ccn_charbuf_destroy(&name);
00748 ccn_charbuf_destroy(&reply_body);
00749 ccn_charbuf_destroy(&msg);
00750 return(ans);
00751 }
00752
00753 static enum ccn_upcall_res
00754 r_proto_start_write_checked(struct ccn_closure *selfp,
00755 enum ccn_upcall_kind kind,
00756 struct ccn_upcall_info *info,
00757 int marker_comp)
00758 {
00759 struct ccnr_handle *ccnr = NULL;
00760 enum ccn_upcall_res ans = CCN_UPCALL_RESULT_OK;
00761 struct ccn_indexbuf *ic = NULL;
00762 struct content_entry *content = NULL;
00763 struct ccn_parsed_interest parsed_interest = {0};
00764 struct ccn_parsed_interest *pi = &parsed_interest;
00765 struct ccn_charbuf *name = NULL;
00766 struct ccn_charbuf *interest = NULL;
00767 struct ccn_indexbuf *comps = NULL;
00768 struct ccn_charbuf *msg = NULL;
00769 struct ccn_charbuf *reply_body = NULL;
00770 int start = 0;
00771 int end = 0;
00772 struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT;
00773 int res = 0;
00774
00775
00776 ccnr = (struct ccnr_handle *)selfp->data;
00777 if (ccnr->start_write_scope_limit < 3) {
00778 start = info->pi->offset[CCN_PI_B_Scope];
00779 end = info->pi->offset[CCN_PI_E_Scope];
00780 if (start == end || info->pi->scope > ccnr->start_write_scope_limit) {
00781 if (CCNSHOULDLOG(ccnr, LM_128, CCNL_INFO))
00782 ccnr_msg(ccnr, "r_proto_start_write_checked: interest scope exceeds limit");
00783 return(CCN_UPCALL_RESULT_OK);
00784 }
00785 }
00786 name = ccn_charbuf_create();
00787 ccn_name_init(name);
00788 ic = info->interest_comps;
00789 ccn_name_append_components(name, info->interest_ccnb, ic->buf[0], ic->buf[marker_comp]);
00790 ccn_name_append_components(name, info->interest_ccnb, ic->buf[marker_comp + 2], ic->buf[ic->n - 1]);
00791
00792 interest = ccn_charbuf_create();
00793 ccnb_element_begin(interest, CCN_DTAG_Interest);
00794 ccn_charbuf_append_charbuf(interest, name);
00795 ccnb_element_end(interest);
00796
00797 comps = ccn_indexbuf_create();
00798 res = ccn_parse_interest(interest->buf, interest->length, pi, comps);
00799 if (res < 0)
00800 abort();
00801 if (CCNSHOULDLOG(ccnr, LM_128, CCNL_FINE))
00802 ccnr_debug_ccnb(ccnr, __LINE__, "r_proto_start_write_checked looking for", NULL,
00803 interest->buf, interest->length);
00804 content = r_store_lookup(ccnr, interest->buf, pi, comps);
00805 ccn_charbuf_destroy(&interest);
00806 ccn_indexbuf_destroy(&comps);
00807 if (content == NULL) {
00808 if (CCNSHOULDLOG(ccnr, LM_128, CCNL_FINE))
00809 ccnr_msg(ccnr, "r_proto_start_write_checked: NOT PRESENT");
00810
00811 return(r_proto_start_write(selfp, kind, info, marker_comp));
00812 }
00813
00814
00815
00816
00817
00818
00819
00820 msg = ccn_charbuf_create();
00821 reply_body = ccn_charbuf_create();
00822 r_proto_append_repo_info(ccnr, reply_body, name, NULL);
00823 start = info->pi->offset[CCN_PI_B_Name];
00824 end = info->interest_comps->buf[info->pi->prefix_comps];
00825 name->length = 0;
00826 ccn_charbuf_append(name, info->interest_ccnb + start, end - start);
00827 ccn_charbuf_append_closer(name);
00828 sp.freshness = 12;
00829 res = ccn_sign_content(info->h, msg, name, &sp,
00830 reply_body->buf, reply_body->length);
00831 if (res < 0)
00832 goto Bail;
00833 if (CCNSHOULDLOG(ccnr, LM_128, CCNL_FINE))
00834 ccnr_msg(ccnr, "r_proto_start_write_checked PRESENT");
00835 res = ccn_put(info->h, msg->buf, msg->length);
00836 if (res < 0) {
00837
00838 ccnr_debug_ccnb(ccnr, __LINE__, "r_proto_start_write_checked ccn_put FAILED", NULL,
00839 msg->buf, msg->length);
00840 }
00841
00842 Bail:
00843 ccn_charbuf_destroy(&name);
00844 ccn_charbuf_destroy(&reply_body);
00845 ccn_charbuf_destroy(&msg);
00846 return(ans);
00847 }
00848
00849
00850
00851
00852
00853 static int
00854 r_proto_check_exclude(struct ccnr_handle *ccnr,
00855 struct ccn_upcall_info *info,
00856 struct ccn_charbuf *name)
00857 {
00858 struct ccn_buf_decoder decoder;
00859 struct ccn_buf_decoder *d = NULL;
00860 const unsigned char *comp = NULL;
00861 size_t comp_size;
00862 size_t name_comp_size;
00863 struct ccn_indexbuf *name_comps = NULL;
00864 const unsigned char *name_string = NULL;
00865 int nc;
00866 int ci;
00867 int res;
00868 int ans = 0;
00869
00870 if (info->pi->offset[CCN_PI_B_Exclude] < info->pi->offset[CCN_PI_E_Exclude]) {
00871 d = ccn_buf_decoder_start(&decoder,
00872 info->interest_ccnb + info->pi->offset[CCN_PI_B_Exclude],
00873 info->pi->offset[CCN_PI_E_Exclude] -
00874 info->pi->offset[CCN_PI_B_Exclude]);
00875
00876
00877
00878 if (ccn_buf_match_dtag(d, CCN_DTAG_Exclude)) {
00879 ccn_buf_advance(d);
00880 } else
00881 goto Bail;
00882
00883 name_comps = ccn_indexbuf_create();
00884 nc = ccn_name_split(name, name_comps);
00885
00886
00887 ci = info->interest_comps->n;
00888 res = ccn_name_comp_get(name->buf, name_comps, ci - 1, &name_string, &name_comp_size);
00889 if (res < 0)
00890 goto Bail;
00891 while (ccn_buf_match_dtag(d, CCN_DTAG_Component)) {
00892 ccn_buf_advance(d);
00893 comp_size = 0;
00894 if (ccn_buf_match_blob(d, &comp, &comp_size))
00895 ccn_buf_advance(d);
00896 ccn_buf_check_close(d);
00897 if (comp_size == name_comp_size) {
00898 res = memcmp(comp, name_string, comp_size);
00899 if (res == 0) {
00900 ans = 1;
00901 goto Bail;
00902 }
00903 if (res > 0)
00904 break;
00905 }
00906 }
00907 }
00908
00909 Bail:
00910 ccn_indexbuf_destroy(&name_comps);
00911 if (CCNSHOULDLOG(ccnr, LM_8, CCNL_FINE))
00912 ccnr_msg(ccnr, "r_proto_check_exclude: do%s exclude", (ans == 1) ? "" : " not");
00913 return(ans);
00914 }
00915
00916 #define ENUMERATION_STATE_TICK_MICROSEC 1000000
00917
00918
00919
00920 static int
00921 reap_enumerations(struct ccn_schedule *sched,
00922 void *clienth,
00923 struct ccn_scheduled_event *ev,
00924 int flags)
00925 {
00926 struct ccnr_handle *ccnr = clienth;
00927 struct hashtb_enumerator ee;
00928 struct hashtb_enumerator *e = ⅇ
00929 struct enum_state *es = NULL;
00930
00931 if ((flags & CCN_SCHEDULE_CANCEL) != 0) {
00932 ccnr->reap_enumerations = NULL;
00933 return(0);
00934 }
00935 hashtb_start(ccnr->enum_state_tab, e);
00936 for (es = e->data; es != NULL; es = e->data) {
00937 if (es->active != ES_ACTIVE &&
00938 r_util_timecmp(es->lastuse_sec + es->lifetime, es->lastuse_usec,
00939 ccnr->sec, ccnr->usec) <= 0) {
00940 if (CCNSHOULDLOG(ccnr, LM_8, CCNL_FINER))
00941 ccnr_debug_ccnb(ccnr, __LINE__, "reap enumeration state", NULL,
00942 es->name->buf, es->name->length);
00943
00944 ccn_charbuf_destroy(&es->name);
00945
00946 hashtb_delete(e);
00947 }
00948 hashtb_next(e);
00949 }
00950 hashtb_end(e);
00951 if (hashtb_n(ccnr->enum_state_tab) == 0) {
00952 ccnr->reap_enumerations = NULL;
00953 return(0);
00954 }
00955 return(ENUMERATION_STATE_TICK_MICROSEC);
00956 }
00957 static void
00958 reap_enumerations_needed(struct ccnr_handle *ccnr)
00959 {
00960 if (ccnr->reap_enumerations == NULL)
00961 ccnr->reap_enumerations = ccn_schedule_event(ccnr->sched,
00962 ENUMERATION_STATE_TICK_MICROSEC,
00963 reap_enumerations,
00964 NULL, 0);
00965 }
00966
00967 static enum ccn_upcall_res
00968 r_proto_begin_enumeration(struct ccn_closure *selfp,
00969 enum ccn_upcall_kind kind,
00970 struct ccn_upcall_info *info,
00971 int marker_comp)
00972 {
00973 struct ccnr_handle *ccnr = NULL;
00974 enum ccn_upcall_res ans = CCN_UPCALL_RESULT_ERR;
00975 struct ccn_parsed_interest parsed_interest = {0};
00976 struct ccn_parsed_interest *pi = &parsed_interest;
00977 struct hashtb_enumerator enumerator = {0};
00978 struct hashtb_enumerator *e = &enumerator;
00979 struct ccn_charbuf *name = NULL;
00980 struct ccn_charbuf *cob = NULL;
00981 struct ccn_charbuf *interest = NULL;
00982 struct ccn_indexbuf *comps = NULL;
00983 int res;
00984 struct content_entry *content = NULL;
00985 struct enum_state *es = NULL;
00986
00987 ccnr = (struct ccnr_handle *)selfp->data;
00988
00989 name = ccn_charbuf_create();
00990 ccn_name_init(name);
00991 ccn_name_append_components(name, info->interest_ccnb,
00992 info->interest_comps->buf[0],
00993 info->interest_comps->buf[marker_comp]);
00994
00995 interest = ccn_charbuf_create();
00996 ccnb_element_begin(interest, CCN_DTAG_Interest);
00997 ccn_charbuf_append_charbuf(interest, name);
00998 ccnb_element_end(interest);
00999
01000
01001 comps = ccn_indexbuf_create();
01002 res = ccn_parse_interest(interest->buf, interest->length, pi, comps);
01003 if (res < 0)
01004 abort();
01005
01006 hashtb_start(ccnr->enum_state_tab, e);
01007 res = hashtb_seek(e, name->buf, name->length, 0);
01008 es = e->data;
01009 if (CCNSHOULDLOG(ccnr, LM_8, CCNL_FINE))
01010 ccnr_debug_ccnb(ccnr, __LINE__, "enumeration: begin hash key", NULL,
01011 name->buf, name->length);
01012
01013 if (res == HT_OLD_ENTRY && es->active != ES_INACTIVE) {
01014 if (es->next_segment > 0)
01015 cob = es->cob[(es->next_segment - 1) % ENUM_N_COBS];
01016 if (cob && ccn_content_matches_interest(cob->buf, cob->length, 1, NULL,
01017 info->interest_ccnb, info->pi->offset[CCN_PI_E], info->pi)) {
01018 if (CCNSHOULDLOG(ccnr, LM_8, CCNL_FINER))
01019 ccnr_msg(ccnr, "enumeration: duplicate request for last cob");
01020 ccn_put(info->h, cob->buf, cob->length);
01021 ans = CCN_UPCALL_RESULT_INTEREST_CONSUMED;
01022 } else {
01023 if (CCNSHOULDLOG(ccnr, LM_8, CCNL_FINEST)) {
01024 ccnr_msg(ccnr, "enumeration: restart of active enumeration, or excluded");
01025 ccnr_debug_ccnb(ccnr, __LINE__, "enum interest: ", NULL, info->interest_ccnb, info->pi->offset[CCN_PI_E]);
01026 if (cob != NULL)
01027 ccnr_debug_ccnb(ccnr, __LINE__, "enum cob content: ", NULL, cob->buf, cob->length);
01028 }
01029 ans = CCN_UPCALL_RESULT_OK;
01030 }
01031 hashtb_end(e);
01032 goto Bail;
01033 }
01034
01035 ccn_name_append_components(name, info->interest_ccnb,
01036 info->interest_comps->buf[marker_comp],
01037 info->interest_comps->buf[marker_comp + 1]);
01038
01039 ccn_name_append(name, ccnr->ccnr_keyid->buf, ccnr->ccnr_keyid->length);
01040
01041 if (res == HT_NEW_ENTRY || es->starting_cookie != ccnr->cookie) {
01042
01043 res = ccn_create_version(info->h, name, CCN_V_NOW, 0, 0);
01044 if (es->name != NULL)
01045 ccn_charbuf_destroy(&es->name);
01046 es->name = ccn_charbuf_create();
01047 ccn_charbuf_append_charbuf(es->name, name);
01048 es->starting_cookie = ccnr->cookie;
01049 }
01050 ccn_charbuf_destroy(&name);
01051
01052 if (CCNSHOULDLOG(ccnr, LM_8, CCNL_FINE))
01053 ccnr_debug_ccnb(ccnr, __LINE__, "begin enum: result name", NULL,
01054 es->name->buf, es->name->length);
01055
01056 if (r_proto_check_exclude(ccnr, info, es->name) > 0) {
01057 hashtb_end(e);
01058 goto Bail;
01059 }
01060
01061
01062 content = r_store_find_first_match_candidate(ccnr, interest->buf, pi);
01063 if (content != NULL &&
01064 !r_store_content_matches_interest_prefix(ccnr, content, interest->buf, interest->length))
01065 content = NULL;
01066 es->cob[0] = ccn_charbuf_create();
01067 es->reply_body = ccn_charbuf_create();
01068 ccnb_element_begin(es->reply_body, CCN_DTAG_Collection);
01069 es->content = content;
01070 es->interest = interest;
01071 es->interest_comps = comps;
01072 es->next_segment = 0;
01073 es->lastuse_sec = ccnr->sec;
01074 es->lastuse_usec = ccnr->usec;
01075 if (content) {
01076 es->lifetime = 3 * ccn_interest_lifetime_seconds(info->interest_ccnb, pi);
01077 es->active = ES_ACTIVE;
01078 } else {
01079 es->lifetime = ccn_interest_lifetime_seconds(info->interest_ccnb, pi);
01080 es->active = ES_PENDING;
01081 }
01082 hashtb_end(e);
01083 reap_enumerations_needed(ccnr);
01084 if (content)
01085 ans = r_proto_continue_enumeration(selfp, kind, info, marker_comp);
01086 else
01087 ans = CCN_UPCALL_RESULT_OK;
01088 return(ans);
01089
01090 Bail:
01091 ccn_charbuf_destroy(&name);
01092 ccn_charbuf_destroy(&interest);
01093 ccn_indexbuf_destroy(&comps);
01094 return(ans);
01095 }
01096
01097 static enum ccn_upcall_res
01098 r_proto_continue_enumeration(struct ccn_closure *selfp,
01099 enum ccn_upcall_kind kind,
01100 struct ccn_upcall_info *info,
01101 int marker_comp) {
01102
01103
01104
01105
01106 struct ccn_charbuf *hashkey = NULL;
01107 struct ccn_charbuf *result_name = NULL;
01108 struct ccn_charbuf *cob = NULL;
01109 struct ccn_indexbuf *ic = NULL;
01110 intmax_t segment;
01111 struct enum_state *es = NULL;
01112 struct ccnr_handle *ccnr = NULL;
01113 struct hashtb_enumerator enumerator = {0};
01114 struct hashtb_enumerator *e = &enumerator;
01115 struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT;
01116 int i;
01117 int res = 0;
01118 int ans = CCN_UPCALL_RESULT_ERR;
01119
01120 ccnr = (struct ccnr_handle *)selfp->data;
01121 ic = info->interest_comps;
01122 hashkey=ccn_charbuf_create();
01123 ccn_name_init(hashkey);
01124 ccn_name_append_components(hashkey, info->interest_ccnb,
01125 info->interest_comps->buf[0],
01126 info->interest_comps->buf[marker_comp]);
01127 hashtb_start(ccnr->enum_state_tab, e);
01128 res = hashtb_seek(e, hashkey->buf, hashkey->length, 0);
01129 ccn_charbuf_destroy(&hashkey);
01130 if (res != HT_OLD_ENTRY) {
01131 goto Bail;
01132 }
01133 es = e->data;
01134 if (es->active != ES_ACTIVE) {
01135 hashtb_end(e);
01136 return(ans);
01137 }
01138
01139 segment = r_util_segment_from_component(info->interest_ccnb,
01140 ic->buf[ic->n - 2],
01141 ic->buf[ic->n - 1]);
01142 if (CCNSHOULDLOG(ccnr, LM_8, CCNL_FINE))
01143 ccnr_msg(ccnr, "enumeration: requested %jd :: expected %jd", segment, es->next_segment);
01144 if (segment >= 0 && segment != es->next_segment) {
01145
01146 if (segment > es->next_segment + (ENUM_N_COBS / 2)) {
01147 if (CCNSHOULDLOG(ccnr, LM_8, CCNL_FINER))
01148 ccnr_msg(ccnr, "enumeration: ignoring future segment requested %jd :: expected %jd", segment, es->next_segment);
01149 hashtb_end(e);
01150 return (CCN_UPCALL_RESULT_OK);
01151 }
01152
01153 if (segment >= es->next_segment - ENUM_N_COBS) {
01154 cob = es->cob[segment % ENUM_N_COBS];
01155 if (cob &&
01156 ccn_content_matches_interest(cob->buf, cob->length, 1, NULL,
01157 info->interest_ccnb, info->pi->offset[CCN_PI_E], info->pi)) {
01158 if (CCNSHOULDLOG(ccnr, LM_8, CCNL_FINER))
01159 ccnr_msg(ccnr, "enumeration: processing dup request for segment %jd", segment);
01160 ccn_put(info->h, cob->buf, cob->length);
01161 hashtb_end(e);
01162 return (CCN_UPCALL_RESULT_INTEREST_CONSUMED);
01163 }
01164 }
01165 }
01166 NextSegment:
01167 if (CCNSHOULDLOG(ccnr, blah, CCNL_FINE))
01168 ccnr_msg(ccnr, "enumeration: generating segment %jd", es->next_segment);
01169 es->lastuse_sec = ccnr->sec;
01170 es->lastuse_usec = ccnr->usec;
01171 while (es->content != NULL &&
01172 r_store_content_matches_interest_prefix(ccnr, es->content,
01173 es->interest->buf,
01174 es->interest->length)) {
01175 int save = es->reply_body->length;
01176 ccnb_element_begin(es->reply_body, CCN_DTAG_Link);
01177 ccnb_element_begin(es->reply_body, CCN_DTAG_Name);
01178 ccnb_element_end(es->reply_body);
01179 res = r_store_name_append_components(es->reply_body, ccnr, es->content, es->interest_comps->n - 1, 1);
01180 ccnb_element_end(es->reply_body);
01181 if (res == 0) {
01182
01183 es->reply_body->length = save;
01184 es->content = r_store_next_child_at_level(ccnr, es->content, es->interest_comps->n - 1);
01185 continue;
01186 }
01187 if (res != 1) {
01188 ccnr_debug_ccnb(ccnr, __LINE__, "oops", NULL, es->interest->buf, es->interest->length);
01189 ccnr_debug_content(ccnr, __LINE__, "oops", NULL, es->content);
01190 abort();
01191 }
01192 es->content = r_store_next_child_at_level(ccnr, es->content, es->interest_comps->n - 1);
01193 if (es->reply_body->length >= 4096) {
01194 result_name = ccn_charbuf_create();
01195 ccn_charbuf_append_charbuf(result_name, es->name);
01196 ccn_name_append_numeric(result_name, CCN_MARKER_SEQNUM, es->next_segment);
01197 sp.freshness = 60;
01198 cob = es->cob[es->next_segment % ENUM_N_COBS];
01199 if (cob == NULL) {
01200 cob = ccn_charbuf_create();
01201 es->cob[es->next_segment % ENUM_N_COBS] = cob;
01202 }
01203 cob->length = 0;
01204 res = ccn_sign_content(info->h, cob, result_name, &sp,
01205 es->reply_body->buf, 4096);
01206 ccn_charbuf_destroy(&result_name);
01207 if (CCNSHOULDLOG(ccnr, blah, CCNL_FINER))
01208 ccnr_msg(ccnr, "enumeration: putting cob for segment %jd, req %jd", es->next_segment, segment);
01209 if (segment == -1 || segment == es->next_segment)
01210 ccn_put(info->h, cob->buf, cob->length);
01211 es->next_segment++;
01212 memmove(es->reply_body->buf, es->reply_body->buf + 4096, es->reply_body->length - 4096);
01213 es->reply_body->length -= 4096;
01214 if (segment >= es->next_segment)
01215 goto NextSegment;
01216 hashtb_end(e);
01217 return (CCN_UPCALL_RESULT_INTEREST_CONSUMED);
01218 }
01219 }
01220
01221 ccnb_element_end(es->reply_body);
01222 result_name = ccn_charbuf_create();
01223 ccn_charbuf_append_charbuf(result_name, es->name);
01224 ccn_name_append_numeric(result_name, CCN_MARKER_SEQNUM, es->next_segment);
01225 sp.freshness = 60;
01226 sp.sp_flags |= CCN_SP_FINAL_BLOCK;
01227 cob = es->cob[es->next_segment % ENUM_N_COBS];
01228 if (cob == NULL) {
01229 cob = ccn_charbuf_create();
01230 es->cob[es->next_segment % ENUM_N_COBS] = cob;
01231 }
01232 cob->length = 0;
01233 res = ccn_sign_content(info->h, cob, result_name, &sp, es->reply_body->buf,
01234 es->reply_body->length);
01235 ccn_charbuf_destroy(&result_name);
01236 if (CCNSHOULDLOG(ccnr, blah, CCNL_FINER))
01237 ccnr_msg(ccnr, "enumeration: putting final cob for segment %jd", es->next_segment);
01238 ccn_put(info->h, cob->buf, cob->length);
01239 es->active = ES_INACTIVE;
01240 ans = CCN_UPCALL_RESULT_INTEREST_CONSUMED;
01241
01242 Bail:
01243 if (es != NULL) {
01244
01245 ccn_charbuf_destroy(&es->interest);
01246 ccn_charbuf_destroy(&es->reply_body);
01247 for (i = 0; i < ENUM_N_COBS; i++)
01248 ccn_charbuf_destroy(&es->cob[i]);
01249 ccn_indexbuf_destroy(&es->interest_comps);
01250 }
01251 hashtb_end(e);
01252 return(ans);
01253 }
01254
01255 void
01256 r_proto_dump_enums(struct ccnr_handle *ccnr)
01257 {
01258 struct enum_state *es = NULL;
01259 struct hashtb_enumerator enumerator = {0};
01260 struct hashtb_enumerator *e = &enumerator;
01261
01262 for (hashtb_start(ccnr->enum_state_tab, e); e->data != NULL; hashtb_next(e)) {
01263 es = e->data;
01264 ccnr_msg(ccnr, "Enumeration active: %d, next segment %d, cookie %u",
01265 es->active, es->next_segment, es->starting_cookie);
01266 ccnr_debug_ccnb(ccnr, __LINE__, " enum name", NULL,
01267 es->name->buf, es->name->length);
01268
01269 }
01270 hashtb_end(e);
01271 }
01272
01273 static enum ccn_upcall_res
01274 r_proto_bulk_import(struct ccn_closure *selfp,
01275 enum ccn_upcall_kind kind,
01276 struct ccn_upcall_info *info,
01277 int marker_comp)
01278 {
01279 enum ccn_upcall_res ans = CCN_UPCALL_RESULT_ERR;
01280 struct ccnr_handle *ccnr = NULL;
01281 struct ccn_charbuf *filename = NULL;
01282 struct ccn_charbuf *filename2 = NULL;
01283 const unsigned char *mstart = NULL;
01284 size_t mlength;
01285 struct ccn_indexbuf *ic = NULL;
01286 struct ccn_charbuf *msg = NULL;
01287 struct ccn_charbuf *name = NULL;
01288 struct ccn_charbuf *reply_body = NULL;
01289 struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT;
01290 const char *infostring = "OK";
01291 int res;
01292
01293 ccnr = (struct ccnr_handle *)selfp->data;
01294 ccn_name_comp_get(info->interest_ccnb, info->interest_comps, marker_comp,
01295 &mstart, &mlength);
01296 if (mlength <= strlen(REPO_AF) + 1 || mstart[strlen(REPO_AF)] != '~') {
01297 infostring = "missing or malformed bulk import name component";
01298 ccnr_msg(ccnr, "r_proto_bulk_import: %s", infostring);
01299 goto Reply;
01300 }
01301 mstart += strlen(REPO_AF) + 1;
01302 mlength -= (strlen(REPO_AF) + 1);
01303 if (memchr(mstart, '/', mlength) != NULL) {
01304 infostring = "bulk import filename must not include directory";
01305 ccnr_msg(ccnr, "r_proto_bulk_import: %s", infostring);
01306 goto Reply;
01307 }
01308 filename = ccn_charbuf_create();
01309 ccn_charbuf_append_string(filename, "import/");
01310 ccn_charbuf_append(filename, mstart, mlength);
01311 res = r_init_map_and_process_file(ccnr, filename, 0);
01312 if (res == 1) {
01313 infostring = "unable to open bulk import file";
01314 ccnr_msg(ccnr, "r_proto_bulk_import: %s", infostring);
01315 goto Reply;
01316 }
01317 if (res < 0) {
01318 infostring = "error parsing bulk import file";
01319 ccnr_msg(ccnr, "r_proto_bulk_import: %s", infostring);
01320 goto Reply;
01321 }
01322
01323 filename->length = 0;
01324 ccn_charbuf_putf(filename, "%s/import/", ccnr->directory);
01325 ccn_charbuf_append(filename, mstart, mlength);
01326 filename2 = ccn_charbuf_create();
01327 ccn_charbuf_putf(filename2, "%s/import/.", ccnr->directory);
01328 ccn_charbuf_append(filename2, mstart, mlength);
01329 res = rename(ccn_charbuf_as_string(filename),
01330 ccn_charbuf_as_string(filename2));
01331 if (res < 0) {
01332 infostring = "error renaming bulk import file";
01333 ccnr_msg(ccnr, "r_proto_bulk_import: %s", infostring);
01334 goto Reply;
01335 }
01336 filename->length = 0;
01337 ccn_charbuf_append_string(filename, "import/.");
01338 ccn_charbuf_append(filename, mstart, mlength);
01339 res = r_init_map_and_process_file(ccnr, filename, 1);
01340 if (res < 0) {
01341 infostring = "error merging bulk import file";
01342 ccnr_msg(ccnr, "r_proto_bulk_import: %s", infostring);
01343
01344 }
01345 if (CCNSHOULDLOG(ccnr, sdfdf, CCNL_FINE))
01346 ccnr_msg(ccnr, "unlinking bulk import file %s", ccn_charbuf_as_string(filename2));
01347 unlink(ccn_charbuf_as_string(filename2));
01348
01349 Reply:
01350
01351 name = ccn_charbuf_create();
01352 ccn_name_init(name);
01353 ic = info->interest_comps;
01354 ccn_name_append_components(name, info->interest_ccnb, ic->buf[0], ic->buf[ic->n - 1]);
01355
01356 msg = ccn_charbuf_create();
01357 reply_body = ccn_charbuf_create();
01358 r_proto_append_repo_info(ccnr, reply_body, NULL, infostring);
01359 sp.freshness = 12;
01360 res = ccn_sign_content(info->h, msg, name, &sp,
01361 reply_body->buf, reply_body->length);
01362 if (res < 0)
01363 goto Bail;
01364 res = ccn_put(info->h, msg->buf, msg->length);
01365 if (res < 0) {
01366 ccnr_debug_ccnb(ccnr, __LINE__, "r_proto_bulk_import ccn_put FAILED", NULL,
01367 msg->buf, msg->length);
01368 goto Bail;
01369 }
01370 ans = CCN_UPCALL_RESULT_INTEREST_CONSUMED;
01371
01372 Bail:
01373 if (filename != NULL) ccn_charbuf_destroy(&filename);
01374 if (filename2 != NULL) ccn_charbuf_destroy(&filename2);
01375 if (name != NULL) ccn_charbuf_destroy(&name);
01376 if (msg != NULL) ccn_charbuf_destroy(&msg);
01377 if (reply_body != NULL) ccn_charbuf_destroy(&reply_body);
01378 return (ans);
01379 }
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393 PUBLIC int
01394 r_proto_policy_append_basic(struct ccnr_handle *ccnr,
01395 struct ccn_charbuf *policy,
01396 const char *version, const char *local_name,
01397 const char *global_prefix)
01398 {
01399 int res;
01400 res = ccnb_element_begin(policy, CCN_DTAG_Policy);
01401 res |= ccnb_tagged_putf(policy, CCN_DTAG_PolicyVersion, "%s", version);
01402 res |= ccnb_tagged_putf(policy, CCN_DTAG_LocalName, "%s", local_name);
01403 res |= ccnb_tagged_putf(policy, CCN_DTAG_GlobalPrefix, "%s", global_prefix);
01404 res |= ccnb_element_end(policy);
01405 return (res);
01406 }
01407 PUBLIC int
01408 r_proto_policy_append_namespace(struct ccnr_handle *ccnr,
01409 struct ccn_charbuf *policy,
01410 const char *namespace)
01411 {
01412 int res;
01413 if (policy->length < 2)
01414 return(-1);
01415 policy->length--;
01416 res = ccnb_tagged_putf(policy, CCN_DTAG_Namespace, "%s", namespace);
01417 ccnb_element_end(policy);
01418 return(res);
01419 }
01420
01421
01422
01423
01424
01425 PUBLIC int
01426 r_proto_parse_policy(struct ccnr_handle *ccnr, const unsigned char *buf, size_t length,
01427 struct ccnr_parsed_policy *pp)
01428 {
01429 int res = 0;
01430 struct ccn_buf_decoder decoder;
01431 struct ccn_buf_decoder *d = ccn_buf_decoder_start(&decoder, buf,
01432 length);
01433 if (ccn_buf_match_dtag(d, CCN_DTAG_Policy)) {
01434 ccn_buf_advance(d);
01435 pp->policy_version_offset = ccn_parse_tagged_string(d, CCN_DTAG_PolicyVersion, pp->store);
01436 pp->local_name_offset = ccn_parse_tagged_string(d, CCN_DTAG_LocalName, pp->store);
01437 pp->global_prefix_offset = ccn_parse_tagged_string(d, CCN_DTAG_GlobalPrefix, pp->store);
01438 pp->namespaces->n = 0;
01439 while (ccn_buf_match_dtag(d, CCN_DTAG_Namespace)) {
01440 ccn_indexbuf_append_element(pp->namespaces, ccn_parse_tagged_string(d, CCN_DTAG_Namespace, pp->store));
01441 }
01442 ccn_buf_check_close(d);
01443 } else {
01444 return(-1);
01445 }
01446 return (res);
01447 }
01448
01449
01450
01451
01452
01453 int
01454 r_proto_initiate_key_fetch(struct ccnr_handle *ccnr,
01455 const unsigned char *msg,
01456 struct ccn_parsed_ContentObject *pco,
01457 int use_link,
01458 ccnr_cookie a)
01459 {
01460
01461
01462
01463
01464 int res;
01465 struct ccn_charbuf *key_name = NULL;
01466 struct ccn_closure *key_closure = NULL;
01467 struct ccn_charbuf *templ = NULL;
01468 struct ccnr_expect_content *expect_content = NULL;
01469 const unsigned char *namestart = NULL;
01470 int namelen = 0;
01471 int keynamelen;
01472 int i;
01473
01474 keynamelen = (pco->offset[CCN_PCO_E_KeyName_Name] -
01475 pco->offset[CCN_PCO_B_KeyName_Name]);
01476 if (use_link) {
01477
01478 if (pco->type == CCN_CONTENT_LINK) {
01479
01480 const unsigned char *data = NULL;
01481 size_t data_size = 0;
01482 struct ccn_buf_decoder decoder;
01483 struct ccn_buf_decoder *d;
01484 res = ccn_content_get_value(msg, pco->offset[CCN_PCO_E], pco,
01485 &data, &data_size);
01486 if (res < 0)
01487 return(-1);
01488 d = ccn_buf_decoder_start(&decoder, data, data_size);
01489 if (ccn_buf_match_dtag(d, CCN_DTAG_Link)) {
01490 int start = 0;
01491 int end = 0;
01492 ccn_buf_advance(d);
01493 start = d->decoder.token_index;
01494 ccn_parse_Name(d, NULL);
01495 end = d->decoder.token_index;
01496 ccn_buf_check_close(d);
01497 if (d->decoder.state < 0)
01498 return(-1);
01499 namestart = data + start;
01500 namelen = end - start;
01501 if (namelen == keynamelen &&
01502 0 == memcmp(namestart, msg + pco->offset[CCN_PCO_B_KeyName_Name], namelen)) {
01503
01504
01505
01506
01507 if (CCNSHOULDLOG(ccnr, sdfdf, CCNL_FINE))
01508 ccnr_debug_ccnb(ccnr, __LINE__, "keyfetch_link_opt",
01509 NULL, namestart, namelen);
01510 return(-1);
01511 }
01512 }
01513 }
01514 }
01515 else {
01516
01517 namestart = msg + pco->offset[CCN_PCO_B_KeyName_Name];
01518 namelen = (pco->offset[CCN_PCO_E_KeyName_Name] -
01519 pco->offset[CCN_PCO_B_KeyName_Name]);
01520 }
01521
01522
01523
01524 if (namelen == 0 || a == 0)
01525 return(-1);
01526 key_name = ccn_charbuf_create();
01527 ccn_charbuf_append(key_name, namestart, namelen);
01528
01529 templ = ccn_charbuf_create();
01530 ccn_charbuf_append_tt(templ, CCN_DTAG_Interest, CCN_DTAG);
01531 ccn_charbuf_append(templ, key_name->buf, key_name->length);
01532 ccnb_tagged_putf(templ, CCN_DTAG_MinSuffixComponents, "%d", 1);
01533 ccnb_tagged_putf(templ, CCN_DTAG_MaxSuffixComponents, "%d", 3);
01534 if (pco->offset[CCN_PCO_B_KeyName_Pub] < pco->offset[CCN_PCO_E_KeyName_Pub]) {
01535 ccn_charbuf_append(templ,
01536 msg + pco->offset[CCN_PCO_B_KeyName_Pub],
01537 (pco->offset[CCN_PCO_E_KeyName_Pub] -
01538 pco->offset[CCN_PCO_B_KeyName_Pub]));
01539 }
01540 ccn_charbuf_append_closer(templ);
01541
01542 if (r_sync_lookup(ccnr, templ, NULL) == 0) {
01543 res = 1;
01544
01545
01546 }
01547 else {
01548
01549 res = -1;
01550 expect_content = calloc(1, sizeof(*expect_content));
01551 if (expect_content == NULL)
01552 goto Bail;
01553 expect_content->ccnr = ccnr;
01554 expect_content->final = -1;
01555 for (i = 0; i < CCNR_PIPELINE; i++)
01556 expect_content->outstanding[i] = -1;
01557
01558 expect_content->keyfetch = a;
01559 key_closure = calloc(1, sizeof(*key_closure));
01560 if (key_closure == NULL)
01561 goto Bail;
01562 key_closure->p = &r_proto_expect_content;
01563 key_closure->data = expect_content;
01564 res = ccn_express_interest(ccnr->direct_client, key_name, key_closure, templ);
01565 if (res >= 0) {
01566 if (CCNSHOULDLOG(ccnr, sdfdf, CCNL_FINE))
01567 ccnr_debug_ccnb(ccnr, __LINE__, "keyfetch_start",
01568 NULL, templ->buf, templ->length);
01569 key_closure = NULL;
01570 expect_content = NULL;
01571 res = 0;
01572 }
01573 }
01574 Bail:
01575 if (key_closure != NULL)
01576 free(key_closure);
01577 if (expect_content != NULL)
01578 free(expect_content);
01579 ccn_charbuf_destroy(&key_name);
01580 ccn_charbuf_destroy(&templ);
01581 return(res);
01582 }
01583