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, NULL);
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 if (content_msg == NULL) {
00527 ccnr_debug_ccnb(ccnr, __LINE__, "Policy read failed for", NULL,
00528 name->buf, name->length);
00529 goto Bail;
00530 }
00531 res = ccn_parse_ContentObject(content_msg, r_store_content_size(ccnr, content), &pco, nc);
00532 res = ccn_ref_tagged_BLOB(CCN_DTAG_Content, content_msg,
00533 pco.offset[CCN_PCO_B_Content],
00534 pco.offset[CCN_PCO_E_Content],
00535 &buf, &length);
00536 ccn_charbuf_append(policy, buf, length);
00537 final = r_util_is_final_pco(content_msg, &pco, nc);
00538 } while (!final);
00539
00540 pp = ccnr_parsed_policy_create();
00541 if (pp == NULL) {
00542 ccnr_msg(ccnr, "Parsed policy allocation error");
00543 goto Bail;
00544 }
00545 memmove(pp->version, vers, vers_size);
00546 if (r_proto_parse_policy(ccnr, policy->buf, policy->length, pp) < 0) {
00547 ccnr_msg(ccnr, "Malformed policy");
00548 goto Bail;
00549 }
00550 res = strcmp((char *)pp->store->buf + pp->global_prefix_offset,
00551 (char *)ccnr->parsed_policy->store->buf + ccnr->parsed_policy->global_prefix_offset);
00552 if (0 != res) {
00553 ccnr_msg(ccnr, "Policy global prefix mismatch");
00554 goto Bail;
00555 }
00556 policy_link_cob = ccnr_init_policy_link_cob(ccnr, ccnr->direct_client, name);
00557 if (policy_link_cob != NULL)
00558 ccnr->policy_link_cob = policy_link_cob;
00559 policyFileName = ccn_charbuf_create();
00560 ccn_charbuf_putf(policyFileName, "%s/repoPolicy", ccnr->directory);
00561 fd = open(ccn_charbuf_as_string(policyFileName), O_WRONLY | O_CREAT, 0666);
00562 if (fd < 0) {
00563 ccnr_msg(ccnr, "open policy: %s (errno = %d)", strerror(errno), errno);
00564 goto Bail;
00565 }
00566 lseek(fd, 0, SEEK_SET);
00567 res = write(fd, ccnr->policy_link_cob->buf, ccnr->policy_link_cob->length);
00568 if (res == -1) {
00569 ccnr_msg(ccnr, "write policy: %s (errno = %d)", strerror(errno), errno);
00570 goto Bail;
00571 }
00572 res = ftruncate(fd, ccnr->policy_link_cob->length);
00573 if (res == -1) {
00574 ccnr_msg(ccnr, "Policy truncate %u :%s (errno = %d)",
00575 fd, strerror(errno), errno);
00576 goto Bail;
00577 }
00578 close(fd);
00579 fd = -1;
00580 r_proto_deactivate_policy(ccnr, ccnr->parsed_policy);
00581 ccnr_parsed_policy_destroy(&ccnr->parsed_policy);
00582 ccnr->parsed_policy = pp;
00583 r_proto_activate_policy(ccnr, pp);
00584
00585 ans = 0;
00586
00587 Bail:
00588 ccn_charbuf_destroy(&name);
00589 ccn_indexbuf_destroy(&nc);
00590 ccn_charbuf_destroy(&policy);
00591 ccn_charbuf_destroy(&policyFileName);
00592 if (fd >= 0) close(fd);
00593 return (ans);
00594
00595 }
00596
00597 static int
00598 r_proto_policy_complete(struct ccn_closure *selfp,
00599 enum ccn_upcall_kind kind,
00600 struct ccn_upcall_info *info)
00601 {
00602 struct ccnr_expect_content *md = selfp->data;
00603 struct ccnr_handle *ccnr = (struct ccnr_handle *)md->ccnr;
00604 const unsigned char *ccnb;
00605 size_t ccnb_size;
00606 const unsigned char *vers = NULL;
00607 size_t vers_size = 0;
00608 struct ccn_indexbuf *cc;
00609 struct ccn_charbuf *name;
00610 int res;
00611
00612
00613
00614
00615 ccnb = info->content_ccnb;
00616 ccnb_size = info->pco->offset[CCN_PCO_E];
00617 cc = info->content_comps;
00618 ccn_name_comp_get(ccnb, cc, cc->n - 3, &vers, &vers_size);
00619 if (vers_size != 7 || vers[0] != CCN_MARKER_VERSION)
00620 return(-1);
00621 if (memcmp(vers, ccnr->parsed_policy->version, sizeof(ccnr->parsed_policy->version)) <= 0) {
00622 if (CCNSHOULDLOG(ccnr, LM_128, CCNL_INFO))
00623 ccnr_debug_ccnb(ccnr, __LINE__, "r_proto_policy_complete older policy ignored", NULL,
00624 ccnb, ccnb_size);
00625 return (-1);
00626 }
00627
00628 name = ccn_charbuf_create();
00629 res = ccn_name_init(name);
00630 ccn_name_append_components(name, ccnb, cc->buf[0], cc->buf[cc->n - 2]);
00631 ccn_schedule_event(ccnr->sched, 500, r_proto_policy_update, name, 0);
00632 if (CCNSHOULDLOG(ccnr, LM_128, CCNL_FINEST))
00633 ccnr_msg(ccnr,"r_proto_policy_complete update scheduled");
00634
00635 return (0);
00636 }
00637
00638 static enum ccn_upcall_res
00639 r_proto_start_write(struct ccn_closure *selfp,
00640 enum ccn_upcall_kind kind,
00641 struct ccn_upcall_info *info,
00642 int marker_comp)
00643 {
00644 struct ccnr_handle *ccnr = NULL;
00645 struct ccn_charbuf *templ = NULL;
00646 struct ccn_closure *incoming = NULL;
00647 struct ccnr_expect_content *expect_content = NULL;
00648 struct ccn_charbuf *reply_body = NULL;
00649 struct ccn_charbuf *name = NULL;
00650 struct ccn_indexbuf *ic = NULL;
00651 enum ccn_upcall_res ans = CCN_UPCALL_RESULT_ERR;
00652 struct ccn_charbuf *msg = NULL;
00653 int res = 0;
00654 int start = 0;
00655 int end = 0;
00656 int is_policy = 0;
00657 int i;
00658 struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT;
00659
00660
00661
00662
00663
00664
00665 ccnr = (struct ccnr_handle *)selfp->data;
00666 if (ccnr->start_write_scope_limit < 3) {
00667 start = info->pi->offset[CCN_PI_B_Scope];
00668 end = info->pi->offset[CCN_PI_E_Scope];
00669 if (start == end || info->pi->scope > ccnr->start_write_scope_limit) {
00670 if (CCNSHOULDLOG(ccnr, LM_128, CCNL_INFO))
00671 ccnr_msg(ccnr, "r_proto_start_write: interest scope exceeds limit");
00672 return(CCN_UPCALL_RESULT_OK);
00673 }
00674 }
00675
00676 start = info->pi->offset[CCN_PI_B_Name];
00677 end = info->interest_comps->buf[marker_comp - 1];
00678 name = ccn_charbuf_create();
00679 ccn_charbuf_append(name, info->interest_ccnb + start, end - start);
00680 ccn_charbuf_append_closer(name);
00681 if (0 ==ccn_compare_names(name->buf, name->length,
00682 ccnr->policy_name->buf, ccnr->policy_name->length))
00683 is_policy = 1;
00684
00685
00686 start = info->pi->offset[CCN_PI_B_Name];
00687 end = info->interest_comps->buf[info->pi->prefix_comps];
00688 name->length = 0;
00689 ccn_charbuf_append(name, info->interest_ccnb + start, end - start);
00690 ccn_charbuf_append_closer(name);
00691 msg = ccn_charbuf_create();
00692 reply_body = ccn_charbuf_create();
00693 r_proto_append_repo_info(ccnr, reply_body, NULL, NULL);
00694 sp.freshness = 12;
00695 res = ccn_sign_content(info->h, msg, name, &sp,
00696 reply_body->buf, reply_body->length);
00697 if (res < 0)
00698 goto Bail;
00699 if (CCNSHOULDLOG(ccnr, LM_128, CCNL_FINE))
00700 ccnr_debug_ccnb(ccnr, __LINE__, "r_proto_start_write response", NULL,
00701 msg->buf, msg->length);
00702 res = ccn_put(info->h, msg->buf, msg->length);
00703 if (res < 0) {
00704 ccnr_debug_ccnb(ccnr, __LINE__, "r_proto_start_write ccn_put FAILED", NULL,
00705 msg->buf, msg->length);
00706 goto Bail;
00707 }
00708
00709
00710 expect_content = calloc(1, sizeof(*expect_content));
00711 if (expect_content == NULL)
00712 goto Bail;
00713 expect_content->ccnr = ccnr;
00714 expect_content->final = -1;
00715 for (i = 0; i < CCNR_PIPELINE; i++)
00716 expect_content->outstanding[i] = -1;
00717 if (is_policy) {
00718 expect_content->expect_complete = &r_proto_policy_complete;
00719 if (CCNSHOULDLOG(ccnr, LM_128, CCNL_FINE))
00720 ccnr_msg(ccnr, "r_proto_start_write: is policy file");
00721 }
00722 incoming = calloc(1, sizeof(*incoming));
00723 if (incoming == NULL)
00724 goto Bail;
00725 incoming->p = &r_proto_expect_content;
00726 incoming->data = expect_content;
00727 templ = r_proto_mktemplate(expect_content, NULL);
00728 ic = info->interest_comps;
00729 ccn_name_init(name);
00730 ccn_name_append_components(name, info->interest_ccnb, ic->buf[0], ic->buf[marker_comp]);
00731 ccn_name_append_numeric(name, CCN_MARKER_SEQNUM, 0);
00732 expect_content->outstanding[0] = 0;
00733 res = ccn_express_interest(info->h, name, incoming, templ);
00734 if (res >= 0) {
00735
00736 incoming = NULL;
00737 expect_content = NULL;
00738 ans = CCN_UPCALL_RESULT_INTEREST_CONSUMED;
00739 }
00740 else {
00741 ccnr_debug_ccnb(ccnr, __LINE__, "r_proto_start_write ccn_express_interest FAILED", NULL,
00742 name->buf, name->length);
00743 goto Bail;
00744 }
00745
00746 Bail:
00747 if (incoming != NULL)
00748 free(incoming);
00749 if (expect_content != NULL)
00750 free(expect_content);
00751 ccn_charbuf_destroy(&templ);
00752 ccn_charbuf_destroy(&name);
00753 ccn_charbuf_destroy(&reply_body);
00754 ccn_charbuf_destroy(&msg);
00755 return(ans);
00756 }
00757
00758 static enum ccn_upcall_res
00759 r_proto_start_write_checked(struct ccn_closure *selfp,
00760 enum ccn_upcall_kind kind,
00761 struct ccn_upcall_info *info,
00762 int marker_comp)
00763 {
00764 struct ccnr_handle *ccnr = NULL;
00765 enum ccn_upcall_res ans = CCN_UPCALL_RESULT_OK;
00766 struct ccn_indexbuf *ic = NULL;
00767 struct content_entry *content = NULL;
00768 struct ccn_parsed_interest parsed_interest = {0};
00769 struct ccn_parsed_interest *pi = &parsed_interest;
00770 struct ccn_charbuf *name = NULL;
00771 struct ccn_charbuf *interest = NULL;
00772 struct ccn_indexbuf *comps = NULL;
00773 struct ccn_charbuf *msg = NULL;
00774 struct ccn_charbuf *reply_body = NULL;
00775 int start = 0;
00776 int end = 0;
00777 struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT;
00778 int res = 0;
00779
00780
00781 ccnr = (struct ccnr_handle *)selfp->data;
00782 if (ccnr->start_write_scope_limit < 3) {
00783 start = info->pi->offset[CCN_PI_B_Scope];
00784 end = info->pi->offset[CCN_PI_E_Scope];
00785 if (start == end || info->pi->scope > ccnr->start_write_scope_limit) {
00786 if (CCNSHOULDLOG(ccnr, LM_128, CCNL_INFO))
00787 ccnr_msg(ccnr, "r_proto_start_write_checked: interest scope exceeds limit");
00788 return(CCN_UPCALL_RESULT_OK);
00789 }
00790 }
00791 name = ccn_charbuf_create();
00792 ccn_name_init(name);
00793 ic = info->interest_comps;
00794 ccn_name_append_components(name, info->interest_ccnb, ic->buf[0], ic->buf[marker_comp]);
00795 ccn_name_append_components(name, info->interest_ccnb, ic->buf[marker_comp + 2], ic->buf[ic->n - 1]);
00796
00797 interest = ccn_charbuf_create();
00798 ccnb_element_begin(interest, CCN_DTAG_Interest);
00799 ccn_charbuf_append_charbuf(interest, name);
00800 ccnb_element_end(interest);
00801
00802 comps = ccn_indexbuf_create();
00803 res = ccn_parse_interest(interest->buf, interest->length, pi, comps);
00804 if (res < 0)
00805 abort();
00806 if (CCNSHOULDLOG(ccnr, LM_128, CCNL_FINE))
00807 ccnr_debug_ccnb(ccnr, __LINE__, "r_proto_start_write_checked looking for", NULL,
00808 interest->buf, interest->length);
00809 content = r_store_lookup(ccnr, interest->buf, pi, comps);
00810 ccn_charbuf_destroy(&interest);
00811 ccn_indexbuf_destroy(&comps);
00812 if (content == NULL) {
00813 if (CCNSHOULDLOG(ccnr, LM_128, CCNL_FINE))
00814 ccnr_msg(ccnr, "r_proto_start_write_checked: NOT PRESENT");
00815
00816 return(r_proto_start_write(selfp, kind, info, marker_comp));
00817 }
00818
00819
00820
00821
00822
00823
00824
00825 msg = ccn_charbuf_create();
00826 reply_body = ccn_charbuf_create();
00827 r_proto_append_repo_info(ccnr, reply_body, name, NULL);
00828 start = info->pi->offset[CCN_PI_B_Name];
00829 end = info->interest_comps->buf[info->pi->prefix_comps];
00830 name->length = 0;
00831 ccn_charbuf_append(name, info->interest_ccnb + start, end - start);
00832 ccn_charbuf_append_closer(name);
00833 sp.freshness = 12;
00834 res = ccn_sign_content(info->h, msg, name, &sp,
00835 reply_body->buf, reply_body->length);
00836 if (res < 0)
00837 goto Bail;
00838 if (CCNSHOULDLOG(ccnr, LM_128, CCNL_FINE))
00839 ccnr_msg(ccnr, "r_proto_start_write_checked PRESENT");
00840 res = ccn_put(info->h, msg->buf, msg->length);
00841 if (res < 0) {
00842
00843 ccnr_debug_ccnb(ccnr, __LINE__, "r_proto_start_write_checked ccn_put FAILED", NULL,
00844 msg->buf, msg->length);
00845 }
00846
00847 Bail:
00848 ccn_charbuf_destroy(&name);
00849 ccn_charbuf_destroy(&reply_body);
00850 ccn_charbuf_destroy(&msg);
00851 return(ans);
00852 }
00853
00854
00855
00856
00857
00858 static int
00859 r_proto_check_exclude(struct ccnr_handle *ccnr,
00860 struct ccn_upcall_info *info,
00861 struct ccn_charbuf *name)
00862 {
00863 struct ccn_buf_decoder decoder;
00864 struct ccn_buf_decoder *d = NULL;
00865 const unsigned char *comp = NULL;
00866 size_t comp_size;
00867 size_t name_comp_size;
00868 struct ccn_indexbuf *name_comps = NULL;
00869 const unsigned char *name_string = NULL;
00870 int nc;
00871 int ci;
00872 int res;
00873 int ans = 0;
00874
00875 if (info->pi->offset[CCN_PI_B_Exclude] < info->pi->offset[CCN_PI_E_Exclude]) {
00876 d = ccn_buf_decoder_start(&decoder,
00877 info->interest_ccnb + info->pi->offset[CCN_PI_B_Exclude],
00878 info->pi->offset[CCN_PI_E_Exclude] -
00879 info->pi->offset[CCN_PI_B_Exclude]);
00880
00881
00882
00883 if (ccn_buf_match_dtag(d, CCN_DTAG_Exclude)) {
00884 ccn_buf_advance(d);
00885 } else
00886 goto Bail;
00887
00888 name_comps = ccn_indexbuf_create();
00889 nc = ccn_name_split(name, name_comps);
00890
00891
00892 ci = info->interest_comps->n;
00893 res = ccn_name_comp_get(name->buf, name_comps, ci - 1, &name_string, &name_comp_size);
00894 if (res < 0)
00895 goto Bail;
00896 while (ccn_buf_match_dtag(d, CCN_DTAG_Component)) {
00897 ccn_buf_advance(d);
00898 comp_size = 0;
00899 if (ccn_buf_match_blob(d, &comp, &comp_size))
00900 ccn_buf_advance(d);
00901 ccn_buf_check_close(d);
00902 if (comp_size == name_comp_size) {
00903 res = memcmp(comp, name_string, comp_size);
00904 if (res == 0) {
00905 ans = 1;
00906 goto Bail;
00907 }
00908 if (res > 0)
00909 break;
00910 }
00911 }
00912 }
00913
00914 Bail:
00915 ccn_indexbuf_destroy(&name_comps);
00916 if (CCNSHOULDLOG(ccnr, LM_8, CCNL_FINE))
00917 ccnr_msg(ccnr, "r_proto_check_exclude: do%s exclude", (ans == 1) ? "" : " not");
00918 return(ans);
00919 }
00920
00921 #define ENUMERATION_STATE_TICK_MICROSEC 1000000
00922
00923
00924
00925 static int
00926 reap_enumerations(struct ccn_schedule *sched,
00927 void *clienth,
00928 struct ccn_scheduled_event *ev,
00929 int flags)
00930 {
00931 struct ccnr_handle *ccnr = clienth;
00932 struct hashtb_enumerator ee;
00933 struct hashtb_enumerator *e = ⅇ
00934 struct enum_state *es = NULL;
00935 int i;
00936
00937 if ((flags & CCN_SCHEDULE_CANCEL) != 0) {
00938 ccnr->reap_enumerations = NULL;
00939 return(0);
00940 }
00941 hashtb_start(ccnr->enum_state_tab, e);
00942 for (es = e->data; es != NULL; es = e->data) {
00943 if (es->active != ES_ACTIVE &&
00944 r_util_timecmp(es->lastuse_sec + es->lifetime, es->lastuse_usec,
00945 ccnr->sec, ccnr->usec) <= 0) {
00946 if (CCNSHOULDLOG(ccnr, LM_8, CCNL_FINER))
00947 ccnr_debug_ccnb(ccnr, __LINE__, "reap enumeration state", NULL,
00948 es->name->buf, es->name->length);
00949 ccn_charbuf_destroy(&es->name);
00950 ccn_charbuf_destroy(&es->interest);
00951 ccn_charbuf_destroy(&es->reply_body);
00952 ccn_indexbuf_destroy(&es->interest_comps);
00953 for (i = 0; i < ENUM_N_COBS; i++)
00954 ccn_charbuf_destroy(&(es->cob[i]));
00955
00956 hashtb_delete(e);
00957 }
00958 hashtb_next(e);
00959 }
00960 hashtb_end(e);
00961 if (hashtb_n(ccnr->enum_state_tab) == 0) {
00962 ccnr->reap_enumerations = NULL;
00963 return(0);
00964 }
00965 return(ENUMERATION_STATE_TICK_MICROSEC);
00966 }
00967 static void
00968 reap_enumerations_needed(struct ccnr_handle *ccnr)
00969 {
00970 if (ccnr->reap_enumerations == NULL)
00971 ccnr->reap_enumerations = ccn_schedule_event(ccnr->sched,
00972 ENUMERATION_STATE_TICK_MICROSEC,
00973 reap_enumerations,
00974 NULL, 0);
00975 }
00976
00977 static enum ccn_upcall_res
00978 r_proto_begin_enumeration(struct ccn_closure *selfp,
00979 enum ccn_upcall_kind kind,
00980 struct ccn_upcall_info *info,
00981 int marker_comp)
00982 {
00983 struct ccnr_handle *ccnr = NULL;
00984 enum ccn_upcall_res ans = CCN_UPCALL_RESULT_ERR;
00985 struct ccn_parsed_interest parsed_interest = {0};
00986 struct ccn_parsed_interest *pi = &parsed_interest;
00987 struct hashtb_enumerator enumerator = {0};
00988 struct hashtb_enumerator *e = &enumerator;
00989 struct ccn_charbuf *name = NULL;
00990 struct ccn_charbuf *cob = NULL;
00991 struct ccn_charbuf *interest = NULL;
00992 struct ccn_indexbuf *comps = NULL;
00993 int res;
00994 struct content_entry *content = NULL;
00995 struct enum_state *es = NULL;
00996
00997 ccnr = (struct ccnr_handle *)selfp->data;
00998
00999 name = ccn_charbuf_create();
01000 ccn_name_init(name);
01001 ccn_name_append_components(name, info->interest_ccnb,
01002 info->interest_comps->buf[0],
01003 info->interest_comps->buf[marker_comp]);
01004
01005 interest = ccn_charbuf_create();
01006 ccnb_element_begin(interest, CCN_DTAG_Interest);
01007 ccn_charbuf_append_charbuf(interest, name);
01008 ccnb_element_end(interest);
01009
01010
01011 comps = ccn_indexbuf_create();
01012 res = ccn_parse_interest(interest->buf, interest->length, pi, comps);
01013 if (res < 0)
01014 abort();
01015
01016 hashtb_start(ccnr->enum_state_tab, e);
01017 res = hashtb_seek(e, name->buf, name->length, 0);
01018 es = e->data;
01019 if (CCNSHOULDLOG(ccnr, LM_8, CCNL_FINE))
01020 ccnr_debug_ccnb(ccnr, __LINE__, "enumeration: begin hash key", NULL,
01021 name->buf, name->length);
01022
01023
01024 if (res == HT_OLD_ENTRY && es->active != ES_INACTIVE) {
01025 if (es->next_segment > 0)
01026 cob = es->cob[(es->next_segment - 1) % ENUM_N_COBS];
01027 if (cob && ccn_content_matches_interest(cob->buf, cob->length, 1, NULL,
01028 info->interest_ccnb, info->pi->offset[CCN_PI_E], info->pi)) {
01029 if (CCNSHOULDLOG(ccnr, LM_8, CCNL_FINER))
01030 ccnr_msg(ccnr, "enumeration: duplicate request for last cob");
01031 ccn_put(info->h, cob->buf, cob->length);
01032 es->cob_deferred[(es->next_segment - 1) % ENUM_N_COBS] = 0;
01033 ans = CCN_UPCALL_RESULT_INTEREST_CONSUMED;
01034 } else {
01035 if (CCNSHOULDLOG(ccnr, LM_8, CCNL_FINEST)) {
01036 ccnr_msg(ccnr, "enumeration: restart of active enumeration, or excluded");
01037 ccnr_debug_ccnb(ccnr, __LINE__, "enum interest: ", NULL, info->interest_ccnb, info->pi->offset[CCN_PI_E]);
01038 if (cob != NULL)
01039 ccnr_debug_ccnb(ccnr, __LINE__, "enum cob content: ", NULL, cob->buf, cob->length);
01040 }
01041 ans = CCN_UPCALL_RESULT_OK;
01042 }
01043 hashtb_end(e);
01044 goto Bail;
01045 }
01046
01047 ccn_name_append_components(name, info->interest_ccnb,
01048 info->interest_comps->buf[marker_comp],
01049 info->interest_comps->buf[marker_comp + 1]);
01050
01051 ccn_name_append(name, ccnr->ccnr_keyid->buf, ccnr->ccnr_keyid->length);
01052
01053 if (res == HT_NEW_ENTRY || es->starting_cookie != ccnr->cookie) {
01054
01055 res = ccn_create_version(info->h, name, CCN_V_NOW, 0, 0);
01056 if (es->name != NULL)
01057 ccn_charbuf_destroy(&es->name);
01058 es->name = ccn_charbuf_create();
01059 ccn_charbuf_append_charbuf(es->name, name);
01060 es->starting_cookie = ccnr->cookie;
01061 }
01062 ccn_charbuf_destroy(&name);
01063
01064 if (CCNSHOULDLOG(ccnr, LM_8, CCNL_FINE))
01065 ccnr_debug_ccnb(ccnr, __LINE__, "begin enum: result name", NULL,
01066 es->name->buf, es->name->length);
01067
01068 if (r_proto_check_exclude(ccnr, info, es->name) > 0) {
01069 hashtb_end(e);
01070 goto Bail;
01071 }
01072
01073
01074 content = r_store_find_first_match_candidate(ccnr, interest->buf, pi);
01075 if (content != NULL &&
01076 !r_store_content_matches_interest_prefix(ccnr, content, interest->buf, interest->length))
01077 content = NULL;
01078 ccn_charbuf_destroy(&es->cob[0]);
01079 es->cob[0] = ccn_charbuf_create();
01080 memset(es->cob_deferred, 0, sizeof(es->cob_deferred));
01081 ccn_charbuf_destroy(&es->reply_body);
01082 es->reply_body = ccn_charbuf_create();
01083 ccnb_element_begin(es->reply_body, CCN_DTAG_Collection);
01084 es->content = content;
01085 ccn_charbuf_destroy(&es->interest);
01086 es->interest = interest;
01087 interest = NULL;
01088 ccn_indexbuf_destroy(&es->interest_comps);
01089 es->interest_comps = comps;
01090 comps = NULL;
01091 es->next_segment = 0;
01092 es->lastuse_sec = ccnr->sec;
01093 es->lastuse_usec = ccnr->usec;
01094 if (content) {
01095 es->lifetime = 3 * ccn_interest_lifetime_seconds(info->interest_ccnb, pi);
01096 es->active = ES_ACTIVE;
01097 } else {
01098 es->lifetime = ccn_interest_lifetime_seconds(info->interest_ccnb, pi);
01099 es->active = ES_PENDING;
01100 }
01101 hashtb_end(e);
01102 reap_enumerations_needed(ccnr);
01103 if (content)
01104 ans = r_proto_continue_enumeration(selfp, kind, info, marker_comp);
01105 else
01106 ans = CCN_UPCALL_RESULT_OK;
01107 Bail:
01108 ccn_charbuf_destroy(&name);
01109 ccn_charbuf_destroy(&interest);
01110 ccn_indexbuf_destroy(&comps);
01111 return(ans);
01112 }
01113
01114 static enum ccn_upcall_res
01115 r_proto_continue_enumeration(struct ccn_closure *selfp,
01116 enum ccn_upcall_kind kind,
01117 struct ccn_upcall_info *info,
01118 int marker_comp) {
01119
01120
01121
01122
01123 struct ccn_charbuf *hashkey = NULL;
01124 struct ccn_charbuf *result_name = NULL;
01125 struct ccn_charbuf *cob = NULL;
01126 struct ccn_indexbuf *ic = NULL;
01127 intmax_t segment;
01128 struct enum_state *es = NULL;
01129 struct ccnr_handle *ccnr = NULL;
01130 struct hashtb_enumerator enumerator = {0};
01131 struct hashtb_enumerator *e = &enumerator;
01132 struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT;
01133 int cobs_deferred;
01134 int i;
01135 int res = 0;
01136
01137 ccnr = (struct ccnr_handle *)selfp->data;
01138 ic = info->interest_comps;
01139 hashkey=ccn_charbuf_create();
01140 ccn_name_init(hashkey);
01141 ccn_name_append_components(hashkey, info->interest_ccnb,
01142 info->interest_comps->buf[0],
01143 info->interest_comps->buf[marker_comp]);
01144 hashtb_start(ccnr->enum_state_tab, e);
01145 res = hashtb_seek(e, hashkey->buf, hashkey->length, 0);
01146 ccn_charbuf_destroy(&hashkey);
01147 if (res != HT_OLD_ENTRY) {
01148 hashtb_end(e);
01149 return(CCN_UPCALL_RESULT_ERR);
01150 }
01151 es = e->data;
01152 if (es->active != ES_ACTIVE && es->active != ES_ACTIVE_PENDING_INACTIVE) {
01153 hashtb_end(e);
01154 return(CCN_UPCALL_RESULT_ERR);
01155 }
01156
01157 segment = r_util_segment_from_component(info->interest_ccnb,
01158 ic->buf[ic->n - 2],
01159 ic->buf[ic->n - 1]);
01160 if (CCNSHOULDLOG(ccnr, LM_8, CCNL_FINE))
01161 ccnr_msg(ccnr, "enumeration: requested %jd :: expected %jd", segment, es->next_segment);
01162 if (segment >= 0 && segment != es->next_segment) {
01163
01164 if (segment > es->next_segment + (ENUM_N_COBS / 2)) {
01165 if (CCNSHOULDLOG(ccnr, LM_8, CCNL_FINER))
01166 ccnr_msg(ccnr, "enumeration: ignoring future segment requested %jd :: expected %jd", segment, es->next_segment);
01167 hashtb_end(e);
01168 return (CCN_UPCALL_RESULT_OK);
01169 }
01170
01171 if (segment >= es->next_segment - ENUM_N_COBS) {
01172 cob = es->cob[segment % ENUM_N_COBS];
01173 if (cob &&
01174 ccn_content_matches_interest(cob->buf, cob->length, 1, NULL,
01175 info->interest_ccnb, info->pi->offset[CCN_PI_E], info->pi)) {
01176 if (CCNSHOULDLOG(ccnr, LM_8, CCNL_FINER))
01177 ccnr_msg(ccnr, "enumeration: putting cob for out-of-order segment %jd",
01178 segment);
01179 ccn_put(info->h, cob->buf, cob->length);
01180 es->cob_deferred[segment % ENUM_N_COBS] = 0;
01181 if (es->active == ES_ACTIVE_PENDING_INACTIVE) {
01182 for (i = 0, cobs_deferred = 0; i < ENUM_N_COBS; i++) {
01183 cobs_deferred += es->cob_deferred[i];
01184 }
01185 if (cobs_deferred == 0)
01186 goto EnumerationComplete;
01187 }
01188 hashtb_end(e);
01189 return (CCN_UPCALL_RESULT_INTEREST_CONSUMED);
01190 }
01191 }
01192 }
01193 NextSegment:
01194 if (CCNSHOULDLOG(ccnr, blah, CCNL_FINE))
01195 ccnr_msg(ccnr, "enumeration: generating segment %jd", es->next_segment);
01196 es->lastuse_sec = ccnr->sec;
01197 es->lastuse_usec = ccnr->usec;
01198 while (es->content != NULL &&
01199 r_store_content_matches_interest_prefix(ccnr, es->content,
01200 es->interest->buf,
01201 es->interest->length)) {
01202 int save = es->reply_body->length;
01203 ccnb_element_begin(es->reply_body, CCN_DTAG_Link);
01204 ccnb_element_begin(es->reply_body, CCN_DTAG_Name);
01205 ccnb_element_end(es->reply_body);
01206 res = r_store_name_append_components(es->reply_body, ccnr, es->content, es->interest_comps->n - 1, 1);
01207 ccnb_element_end(es->reply_body);
01208 if (res == 0) {
01209
01210 es->reply_body->length = save;
01211 es->content = r_store_next_child_at_level(ccnr, es->content, es->interest_comps->n - 1);
01212 continue;
01213 }
01214 if (res != 1) {
01215 ccnr_debug_ccnb(ccnr, __LINE__, "oops", NULL, es->interest->buf, es->interest->length);
01216 ccnr_debug_content(ccnr, __LINE__, "oops", NULL, es->content);
01217 abort();
01218 }
01219 es->content = r_store_next_child_at_level(ccnr, es->content, es->interest_comps->n - 1);
01220 if (es->reply_body->length >= 4096) {
01221 result_name = ccn_charbuf_create();
01222 ccn_charbuf_append_charbuf(result_name, es->name);
01223 ccn_name_append_numeric(result_name, CCN_MARKER_SEQNUM, es->next_segment);
01224 sp.freshness = 60;
01225 cob = es->cob[es->next_segment % ENUM_N_COBS];
01226 if (cob == NULL) {
01227 cob = ccn_charbuf_create();
01228 es->cob[es->next_segment % ENUM_N_COBS] = cob;
01229 }
01230 cob->length = 0;
01231 res = ccn_sign_content(info->h, cob, result_name, &sp,
01232 es->reply_body->buf, 4096);
01233 ccn_charbuf_destroy(&result_name);
01234 if (segment == -1 || segment == es->next_segment) {
01235 if (CCNSHOULDLOG(ccnr, blah, CCNL_FINER))
01236 ccnr_msg(ccnr, "enumeration: putting cob for segment %jd", es->next_segment);
01237 ccn_put(info->h, cob->buf, cob->length);
01238 } else {
01239 es->cob_deferred[es->next_segment % ENUM_N_COBS] = 1;
01240 }
01241 es->next_segment++;
01242 memmove(es->reply_body->buf, es->reply_body->buf + 4096, es->reply_body->length - 4096);
01243 es->reply_body->length -= 4096;
01244 if (segment >= es->next_segment)
01245 goto NextSegment;
01246 hashtb_end(e);
01247 return (CCN_UPCALL_RESULT_INTEREST_CONSUMED);
01248 }
01249 }
01250
01251 ccnb_element_end(es->reply_body);
01252 result_name = ccn_charbuf_create();
01253 ccn_charbuf_append_charbuf(result_name, es->name);
01254 ccn_name_append_numeric(result_name, CCN_MARKER_SEQNUM, es->next_segment);
01255 sp.freshness = 60;
01256 sp.sp_flags |= CCN_SP_FINAL_BLOCK;
01257 cob = es->cob[es->next_segment % ENUM_N_COBS];
01258 if (cob == NULL) {
01259 cob = ccn_charbuf_create();
01260 es->cob[es->next_segment % ENUM_N_COBS] = cob;
01261 }
01262 cob->length = 0;
01263 res = ccn_sign_content(info->h, cob, result_name, &sp, es->reply_body->buf,
01264 es->reply_body->length);
01265 ccn_charbuf_destroy(&result_name);
01266 if (CCNSHOULDLOG(ccnr, blah, CCNL_FINER))
01267 ccnr_msg(ccnr, "enumeration: putting final cob for segment %jd", es->next_segment);
01268 ccn_put(info->h, cob->buf, cob->length);
01269 es->cob_deferred[es->next_segment % ENUM_N_COBS] = 0;
01270 for (i = 0, cobs_deferred = 0; i < ENUM_N_COBS; i++) {
01271 cobs_deferred += es->cob_deferred[i];
01272 }
01273 if (cobs_deferred > 0) {
01274 if (CCNSHOULDLOG(ccnr, blah, CCNL_FINER))
01275 ccnr_msg(ccnr, "enumeration: %d pending cobs, inactive pending complete",
01276 cobs_deferred);
01277 es->active = ES_ACTIVE_PENDING_INACTIVE;
01278 hashtb_end(e);
01279 return (CCN_UPCALL_RESULT_INTEREST_CONSUMED);
01280 }
01281 EnumerationComplete:
01282 if (CCNSHOULDLOG(ccnr, blah, CCNL_FINER))
01283 ccnr_msg(ccnr, "enumeration: inactive", es->next_segment);
01284
01285 es->active = ES_INACTIVE;
01286 ccn_charbuf_destroy(&es->interest);
01287 ccn_charbuf_destroy(&es->reply_body);
01288 for (i = 0; i < ENUM_N_COBS; i++)
01289 ccn_charbuf_destroy(&es->cob[i]);
01290 ccn_indexbuf_destroy(&es->interest_comps);
01291 hashtb_end(e);
01292 return(CCN_UPCALL_RESULT_INTEREST_CONSUMED);
01293 }
01294
01295 void
01296 r_proto_dump_enums(struct ccnr_handle *ccnr)
01297 {
01298 struct enum_state *es = NULL;
01299 struct hashtb_enumerator enumerator = {0};
01300 struct hashtb_enumerator *e = &enumerator;
01301
01302 for (hashtb_start(ccnr->enum_state_tab, e); e->data != NULL; hashtb_next(e)) {
01303 es = e->data;
01304 ccnr_msg(ccnr, "Enumeration active: %d, next segment %d, cookie %u",
01305 es->active, es->next_segment, es->starting_cookie);
01306 ccnr_debug_ccnb(ccnr, __LINE__, " enum name", NULL,
01307 es->name->buf, es->name->length);
01308
01309 }
01310 hashtb_end(e);
01311 }
01312
01313 static enum ccn_upcall_res
01314 r_proto_bulk_import(struct ccn_closure *selfp,
01315 enum ccn_upcall_kind kind,
01316 struct ccn_upcall_info *info,
01317 int marker_comp)
01318 {
01319 enum ccn_upcall_res ans = CCN_UPCALL_RESULT_ERR;
01320 struct ccnr_handle *ccnr = NULL;
01321 struct ccn_charbuf *filename = NULL;
01322 struct ccn_charbuf *filename2 = NULL;
01323 const unsigned char *mstart = NULL;
01324 size_t mlength;
01325 struct ccn_indexbuf *ic = NULL;
01326 struct ccn_charbuf *msg = NULL;
01327 struct ccn_charbuf *name = NULL;
01328 struct ccn_charbuf *reply_body = NULL;
01329 struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT;
01330 const char *infostring = "OK";
01331 int res;
01332
01333 ccnr = (struct ccnr_handle *)selfp->data;
01334 ccn_name_comp_get(info->interest_ccnb, info->interest_comps, marker_comp,
01335 &mstart, &mlength);
01336 if (mlength <= strlen(REPO_AF) + 1 || mstart[strlen(REPO_AF)] != '~') {
01337 infostring = "missing or malformed bulk import name component";
01338 ccnr_msg(ccnr, "r_proto_bulk_import: %s", infostring);
01339 goto Reply;
01340 }
01341 mstart += strlen(REPO_AF) + 1;
01342 mlength -= (strlen(REPO_AF) + 1);
01343 if (memchr(mstart, '/', mlength) != NULL) {
01344 infostring = "bulk import filename must not include directory";
01345 ccnr_msg(ccnr, "r_proto_bulk_import: %s", infostring);
01346 goto Reply;
01347 }
01348 filename = ccn_charbuf_create();
01349 ccn_charbuf_append_string(filename, "import/");
01350 ccn_charbuf_append(filename, mstart, mlength);
01351 res = r_init_map_and_process_file(ccnr, filename, 0);
01352 if (res == 1) {
01353 infostring = "unable to open bulk import file";
01354 ccnr_msg(ccnr, "r_proto_bulk_import: %s", infostring);
01355 goto Reply;
01356 }
01357 if (res < 0) {
01358 infostring = "error parsing bulk import file";
01359 ccnr_msg(ccnr, "r_proto_bulk_import: %s", infostring);
01360 goto Reply;
01361 }
01362
01363 filename->length = 0;
01364 ccn_charbuf_putf(filename, "%s/import/", ccnr->directory);
01365 ccn_charbuf_append(filename, mstart, mlength);
01366 filename2 = ccn_charbuf_create();
01367 ccn_charbuf_putf(filename2, "%s/import/.", ccnr->directory);
01368 ccn_charbuf_append(filename2, mstart, mlength);
01369 res = rename(ccn_charbuf_as_string(filename),
01370 ccn_charbuf_as_string(filename2));
01371 if (res < 0) {
01372 infostring = "error renaming bulk import file";
01373 ccnr_msg(ccnr, "r_proto_bulk_import: %s", infostring);
01374 goto Reply;
01375 }
01376 filename->length = 0;
01377 ccn_charbuf_append_string(filename, "import/.");
01378 ccn_charbuf_append(filename, mstart, mlength);
01379 res = r_init_map_and_process_file(ccnr, filename, 1);
01380 if (res < 0) {
01381 infostring = "error merging bulk import file";
01382 ccnr_msg(ccnr, "r_proto_bulk_import: %s", infostring);
01383
01384 }
01385 if (CCNSHOULDLOG(ccnr, sdfdf, CCNL_FINE))
01386 ccnr_msg(ccnr, "unlinking bulk import file %s", ccn_charbuf_as_string(filename2));
01387 unlink(ccn_charbuf_as_string(filename2));
01388
01389 Reply:
01390
01391 name = ccn_charbuf_create();
01392 ccn_name_init(name);
01393 ic = info->interest_comps;
01394 ccn_name_append_components(name, info->interest_ccnb, ic->buf[0], ic->buf[ic->n - 1]);
01395
01396 msg = ccn_charbuf_create();
01397 reply_body = ccn_charbuf_create();
01398 r_proto_append_repo_info(ccnr, reply_body, NULL, infostring);
01399 sp.freshness = 12;
01400 res = ccn_sign_content(info->h, msg, name, &sp,
01401 reply_body->buf, reply_body->length);
01402 if (res < 0)
01403 goto Bail;
01404 res = ccn_put(info->h, msg->buf, msg->length);
01405 if (res < 0) {
01406 ccnr_debug_ccnb(ccnr, __LINE__, "r_proto_bulk_import ccn_put FAILED", NULL,
01407 msg->buf, msg->length);
01408 goto Bail;
01409 }
01410 ans = CCN_UPCALL_RESULT_INTEREST_CONSUMED;
01411
01412 Bail:
01413 if (filename != NULL) ccn_charbuf_destroy(&filename);
01414 if (filename2 != NULL) ccn_charbuf_destroy(&filename2);
01415 if (name != NULL) ccn_charbuf_destroy(&name);
01416 if (msg != NULL) ccn_charbuf_destroy(&msg);
01417 if (reply_body != NULL) ccn_charbuf_destroy(&reply_body);
01418 return (ans);
01419 }
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433 PUBLIC int
01434 r_proto_policy_append_basic(struct ccnr_handle *ccnr,
01435 struct ccn_charbuf *policy,
01436 const char *version, const char *local_name,
01437 const char *global_prefix)
01438 {
01439 int res;
01440 res = ccnb_element_begin(policy, CCN_DTAG_Policy);
01441 res |= ccnb_tagged_putf(policy, CCN_DTAG_PolicyVersion, "%s", version);
01442 res |= ccnb_tagged_putf(policy, CCN_DTAG_LocalName, "%s", local_name);
01443 res |= ccnb_tagged_putf(policy, CCN_DTAG_GlobalPrefix, "%s", global_prefix);
01444 res |= ccnb_element_end(policy);
01445 return (res);
01446 }
01447 PUBLIC int
01448 r_proto_policy_append_namespace(struct ccnr_handle *ccnr,
01449 struct ccn_charbuf *policy,
01450 const char *namespace)
01451 {
01452 int res;
01453 if (policy->length < 2)
01454 return(-1);
01455 policy->length--;
01456 res = ccnb_tagged_putf(policy, CCN_DTAG_Namespace, "%s", namespace);
01457 ccnb_element_end(policy);
01458 return(res);
01459 }
01460
01461
01462
01463
01464
01465 PUBLIC int
01466 r_proto_parse_policy(struct ccnr_handle *ccnr, const unsigned char *buf, size_t length,
01467 struct ccnr_parsed_policy *pp)
01468 {
01469 int res = 0;
01470 struct ccn_buf_decoder decoder;
01471 struct ccn_buf_decoder *d = ccn_buf_decoder_start(&decoder, buf,
01472 length);
01473 if (ccn_buf_match_dtag(d, CCN_DTAG_Policy)) {
01474 ccn_buf_advance(d);
01475 pp->policy_version_offset = ccn_parse_tagged_string(d, CCN_DTAG_PolicyVersion, pp->store);
01476 pp->local_name_offset = ccn_parse_tagged_string(d, CCN_DTAG_LocalName, pp->store);
01477 pp->global_prefix_offset = ccn_parse_tagged_string(d, CCN_DTAG_GlobalPrefix, pp->store);
01478 pp->namespaces->n = 0;
01479 while (ccn_buf_match_dtag(d, CCN_DTAG_Namespace)) {
01480 ccn_indexbuf_append_element(pp->namespaces, ccn_parse_tagged_string(d, CCN_DTAG_Namespace, pp->store));
01481 }
01482 ccn_buf_check_close(d);
01483 } else {
01484 return(-1);
01485 }
01486 return (res);
01487 }
01488
01489
01490
01491
01492
01493 int
01494 r_proto_initiate_key_fetch(struct ccnr_handle *ccnr,
01495 const unsigned char *msg,
01496 struct ccn_parsed_ContentObject *pco,
01497 int use_link,
01498 ccnr_cookie a)
01499 {
01500
01501
01502
01503
01504 int res;
01505 struct ccn_charbuf *key_name = NULL;
01506 struct ccn_closure *key_closure = NULL;
01507 struct ccn_charbuf *templ = NULL;
01508 struct ccnr_expect_content *expect_content = NULL;
01509 const unsigned char *namestart = NULL;
01510 int namelen = 0;
01511 int keynamelen;
01512 int i;
01513
01514 keynamelen = (pco->offset[CCN_PCO_E_KeyName_Name] -
01515 pco->offset[CCN_PCO_B_KeyName_Name]);
01516 if (use_link) {
01517
01518 if (pco->type == CCN_CONTENT_LINK) {
01519
01520 const unsigned char *data = NULL;
01521 size_t data_size = 0;
01522 struct ccn_buf_decoder decoder;
01523 struct ccn_buf_decoder *d;
01524 res = ccn_content_get_value(msg, pco->offset[CCN_PCO_E], pco,
01525 &data, &data_size);
01526 if (res < 0)
01527 return(-1);
01528 d = ccn_buf_decoder_start(&decoder, data, data_size);
01529 if (ccn_buf_match_dtag(d, CCN_DTAG_Link)) {
01530 int start = 0;
01531 int end = 0;
01532 ccn_buf_advance(d);
01533 start = d->decoder.token_index;
01534 ccn_parse_Name(d, NULL);
01535 end = d->decoder.token_index;
01536 ccn_buf_check_close(d);
01537 if (d->decoder.state < 0)
01538 return(-1);
01539 namestart = data + start;
01540 namelen = end - start;
01541 if (namelen == keynamelen &&
01542 0 == memcmp(namestart, msg + pco->offset[CCN_PCO_B_KeyName_Name], namelen)) {
01543
01544
01545
01546
01547 if (CCNSHOULDLOG(ccnr, sdfdf, CCNL_FINE))
01548 ccnr_debug_ccnb(ccnr, __LINE__, "keyfetch_link_opt",
01549 NULL, namestart, namelen);
01550 return(-1);
01551 }
01552 }
01553 }
01554 }
01555 else {
01556
01557 namestart = msg + pco->offset[CCN_PCO_B_KeyName_Name];
01558 namelen = (pco->offset[CCN_PCO_E_KeyName_Name] -
01559 pco->offset[CCN_PCO_B_KeyName_Name]);
01560 }
01561
01562
01563
01564 if (namelen == 0 || a == 0)
01565 return(-1);
01566 key_name = ccn_charbuf_create();
01567 ccn_charbuf_append(key_name, namestart, namelen);
01568
01569 templ = ccn_charbuf_create();
01570 ccn_charbuf_append_tt(templ, CCN_DTAG_Interest, CCN_DTAG);
01571 ccn_charbuf_append(templ, key_name->buf, key_name->length);
01572 ccnb_tagged_putf(templ, CCN_DTAG_MinSuffixComponents, "%d", 1);
01573 ccnb_tagged_putf(templ, CCN_DTAG_MaxSuffixComponents, "%d", 3);
01574 if (pco->offset[CCN_PCO_B_KeyName_Pub] < pco->offset[CCN_PCO_E_KeyName_Pub]) {
01575 ccn_charbuf_append(templ,
01576 msg + pco->offset[CCN_PCO_B_KeyName_Pub],
01577 (pco->offset[CCN_PCO_E_KeyName_Pub] -
01578 pco->offset[CCN_PCO_B_KeyName_Pub]));
01579 }
01580 ccn_charbuf_append_closer(templ);
01581
01582 if (r_sync_lookup(ccnr, templ, NULL) == 0) {
01583 res = 1;
01584
01585
01586 }
01587 else {
01588
01589 res = -1;
01590 expect_content = calloc(1, sizeof(*expect_content));
01591 if (expect_content == NULL)
01592 goto Bail;
01593 expect_content->ccnr = ccnr;
01594 expect_content->final = -1;
01595 for (i = 0; i < CCNR_PIPELINE; i++)
01596 expect_content->outstanding[i] = -1;
01597
01598 expect_content->keyfetch = a;
01599 key_closure = calloc(1, sizeof(*key_closure));
01600 if (key_closure == NULL)
01601 goto Bail;
01602 key_closure->p = &r_proto_expect_content;
01603 key_closure->data = expect_content;
01604 res = ccn_express_interest(ccnr->direct_client, key_name, key_closure, templ);
01605 if (res >= 0) {
01606 if (CCNSHOULDLOG(ccnr, sdfdf, CCNL_FINE))
01607 ccnr_debug_ccnb(ccnr, __LINE__, "keyfetch_start",
01608 NULL, templ->buf, templ->length);
01609 key_closure = NULL;
01610 expect_content = NULL;
01611 res = 0;
01612 }
01613 }
01614 Bail:
01615 if (key_closure != NULL)
01616 free(key_closure);
01617 if (expect_content != NULL)
01618 free(expect_content);
01619 ccn_charbuf_destroy(&key_name);
01620 ccn_charbuf_destroy(&templ);
01621 return(res);
01622 }
01623