00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <errno.h>
00025 #include <fcntl.h>
00026 #include <inttypes.h>
00027 #include <limits.h>
00028 #include <netdb.h>
00029 #include <poll.h>
00030 #include <signal.h>
00031 #include <stddef.h>
00032 #include <stdint.h>
00033 #include <stdio.h>
00034 #include <stdlib.h>
00035 #include <string.h>
00036 #include <time.h>
00037 #include <unistd.h>
00038 #include <arpa/inet.h>
00039 #include <sys/mman.h>
00040 #include <sys/time.h>
00041 #include <sys/socket.h>
00042 #include <sys/stat.h>
00043 #include <sys/types.h>
00044 #include <sys/un.h>
00045 #include <netinet/in.h>
00046 #include <netinet/tcp.h>
00047
00048 #include <ccn/bloom.h>
00049 #include <ccn/ccn.h>
00050 #include <ccn/ccn_private.h>
00051 #include <ccn/charbuf.h>
00052 #include <ccn/face_mgmt.h>
00053 #include <ccn/hashtb.h>
00054 #include <ccn/indexbuf.h>
00055 #include <ccn/schedule.h>
00056 #include <ccn/reg_mgmt.h>
00057 #include <ccn/uri.h>
00058
00059 #include <sync/SyncBase.h>
00060
00061 #include "ccnr_private.h"
00062
00063 #include "ccnr_init.h"
00064
00065 #include "ccnr_dispatch.h"
00066 #include "ccnr_forwarding.h"
00067 #include "ccnr_internal_client.h"
00068 #include "ccnr_io.h"
00069 #include "ccnr_msg.h"
00070 #include "ccnr_net.h"
00071 #include "ccnr_proto.h"
00072 #include "ccnr_sendq.h"
00073 #include "ccnr_store.h"
00074 #include "ccnr_sync.h"
00075 #include "ccnr_util.h"
00076
00077 static int load_policy(struct ccnr_handle *h);
00078 static int merge_files(struct ccnr_handle *h);
00079
00080
00081
00082
00083
00084
00085
00086 struct ccn_charbuf *
00087 r_init_read_config(struct ccnr_handle *h)
00088 {
00089 struct ccn_charbuf *path = NULL;
00090 struct ccn_charbuf *contents = NULL;
00091 size_t sz = 800;
00092 ssize_t sres = -1;
00093 int fd;
00094
00095 h->directory = getenv("CCNR_DIRECTORY");
00096 if (h->directory == NULL || h->directory[0] == 0)
00097 h->directory = ".";
00098 path = ccn_charbuf_create();
00099 contents = ccn_charbuf_create();
00100 if (path == NULL || contents == NULL)
00101 return(NULL);
00102 ccn_charbuf_putf(path, "%s/config", h->directory);
00103 fd = open(ccn_charbuf_as_string(path), O_RDONLY);
00104 if (fd == -1) {
00105 if (errno == ENOENT)
00106 sres = 0;
00107 else
00108 r_init_fail(h, __LINE__, ccn_charbuf_as_string(path), errno);
00109 }
00110 else {
00111 for (;;) {
00112 sres = read(fd, ccn_charbuf_reserve(contents, sz), sz);
00113 if (sres == 0)
00114 break;
00115 if (sres < 0) {
00116 r_init_fail(h, __LINE__, "Read failed reading config", errno);
00117 break;
00118 }
00119 contents->length += sres;
00120 if (contents->length > 999999) {
00121 r_init_fail(h, __LINE__, "config file too large", 0);
00122 sres = -1;
00123 break;
00124 }
00125 }
00126 close(fd);
00127 }
00128 ccn_charbuf_destroy(&path);
00129 if (sres < 0)
00130 ccn_charbuf_destroy(&contents);
00131 return(contents);
00132 }
00133
00134 static int
00135 r_init_debug_getenv(struct ccnr_handle *h, const char *envname)
00136 {
00137 const char *debugstr;
00138 int debugval;
00139
00140 debugstr = getenv(envname);
00141 debugval = ccnr_msg_level_from_string(debugstr);
00142
00143 if (debugval == 1)
00144 debugval = CCNL_WARNING;
00145 if (debugval < 0) {
00146 debugval = CCNL_FINEST;
00147 if (h != NULL)
00148 ccnr_msg(h, "%s='%s' is not valid, using FINEST", envname, debugstr);
00149 }
00150 return(debugval);
00151 }
00152
00153
00154
00155
00156 intmax_t
00157 r_init_confval(struct ccnr_handle *h, const char *key,
00158 intmax_t lo, intmax_t hi, intmax_t deflt) {
00159 const char *s;
00160 intmax_t v;
00161 char *ep;
00162
00163 if (!(lo <= deflt && deflt <= hi))
00164 abort();
00165 s = getenv(key);
00166 if (s != NULL && s[0] != 0) {
00167 ep = "x";
00168 v = strtoimax(s, &ep, 10);
00169 if (v != 0 || ep[0] == 0) {
00170 if (v > hi)
00171 v = hi;
00172 if (v < lo)
00173 v = lo;
00174 if (CCNSHOULDLOG(h, mmm, CCNL_FINEST))
00175 ccnr_msg(h, "Using %s=%jd", key, v);
00176 return(v);
00177 }
00178 }
00179 return (deflt);
00180 }
00181
00182 #define CCNR_CONFIG_PASSMASK 0x003
00183 #define CCNR_CONFIG_IGNORELINE 0x100
00184 #define CCNR_CONFIG_ERR 0x200
00185
00186
00187
00188 static void
00189 r_init_config_msg(struct ccnr_handle *h, int flags,
00190 int line, int chindex, const char *msg)
00191 {
00192 const char *problem = "Problem";
00193 int log_at = CCNL_WARNING;
00194
00195 log_at = CCNL_WARNING;
00196 if ((flags & CCNR_CONFIG_ERR) != 0) {
00197 problem = "Error";
00198 log_at = CCNL_ERROR;
00199 }
00200 if ((flags & (CCNR_CONFIG_IGNORELINE|CCNR_CONFIG_PASSMASK)) == 1 &&
00201 CCNSHOULDLOG(h, mmm, log_at)) {
00202 ccnr_msg(h, "%s in config file %s/config - line %d column %d: %s",
00203 problem, h->directory, line, chindex + 1, msg);
00204 }
00205 }
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217 int
00218 r_init_parse_config(struct ccnr_handle *h, struct ccn_charbuf *config, int pass)
00219 {
00220 struct ccn_charbuf *key = NULL;
00221 struct ccn_charbuf *value = NULL;
00222 const unsigned char *b;
00223 int line;
00224 size_t i;
00225 size_t sol;
00226 size_t len;
00227 size_t ndx;
00228 int ch;
00229 int warns = 0;
00230 int errors = 0;
00231 int use_it = 0;
00232 static const char pclegal[] =
00233 "~@%-+=:,./[]"
00234 "abcdefghijklmnopqrstuvwxyz"
00235 "0123456789"
00236 "_"
00237 "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
00238 const char *klegal = strchr(pclegal, 'a');
00239 int flags;
00240
00241 b = config->buf;
00242 len = config->length;
00243 if (len == 0)
00244 return(0);
00245 ccn_charbuf_as_string(config);
00246 key = ccn_charbuf_create();
00247 value = ccn_charbuf_create();
00248 if (key == NULL || value == NULL)
00249 return(-1);
00250
00251 if (ccn_charbuf_as_string(config) == NULL)
00252 return(-1);
00253 for (line = 1, i = 0, ch = b[0], sol = 0; i < len;) {
00254 flags = pass;
00255 use_it = 0;
00256 if (ch > ' ' && ch != '#') {
00257 key->length = value->length = 0;
00258
00259 while (i < len && ch != '\n' && ch != '=') {
00260 ccn_charbuf_append_value(key, ch, 1);
00261 ch = b[++i];
00262 }
00263 if (ch == '=')
00264 ch = b[++i];
00265 else {
00266 r_init_config_msg(h, flags, line, key->length, "missing '='");
00267 flags |= CCNR_CONFIG_IGNORELINE;
00268 warns++;
00269 ch = '\n';
00270 }
00271
00272 while (i < len && ch > ' ') {
00273 ccn_charbuf_append_value(value, ch, 1);
00274 ch = b[++i];
00275 }
00276
00277 if (key->length < 5 || (memcmp(key->buf, "CCNR_", 5) != 0 &&
00278 memcmp(key->buf, "CCNS_", 5) != 0)) {
00279 r_init_config_msg(h, flags, line, 0,
00280 "ignoring unrecognized key");
00281 flags |= CCNR_CONFIG_IGNORELINE;
00282 warns++;
00283 use_it = 0;
00284 }
00285 else
00286 use_it = 1;
00287
00288
00289 ndx = strspn(ccn_charbuf_as_string(key), klegal);
00290 if (ndx != key->length) {
00291 errors += use_it;
00292 r_init_config_msg(h, (flags | CCNR_CONFIG_ERR), line, ndx,
00293 "unexpected character in key");
00294 flags |= CCNR_CONFIG_IGNORELINE;
00295 warns++;
00296 }
00297
00298 ndx = strspn(ccn_charbuf_as_string(value), pclegal);
00299 if (ndx != value->length) {
00300 errors += use_it;
00301 r_init_config_msg(h, (flags | CCNR_CONFIG_ERR),
00302 line, key->length + 1 + ndx,
00303 "unexpected character in value");
00304 flags |= CCNR_CONFIG_IGNORELINE;
00305 warns++;
00306 }
00307 }
00308 if (ch == '#') {
00309
00310 while (i < len && ch != '\n')
00311 ch = b[++i];
00312 }
00313 while (i < len && ch <= ' ') {
00314 if (ch == '\n') {
00315 line++;
00316 sol = i;
00317 break;
00318 }
00319 if (memchr("\r\t ", ch, 3) == NULL) {
00320 r_init_config_msg(h, pass, line, i - sol,
00321 "non-whitespace control char at end of line");
00322 warns++;
00323 }
00324 ch = b[++i];
00325 }
00326 if (i == len) {
00327 r_init_config_msg(h, flags, line, i - sol,
00328 "missing newline at end of file");
00329 warns++;
00330 ch = '\n';
00331 }
00332 else if (ch == '\n')
00333 ch = b[++i];
00334 else {
00335 r_init_config_msg(h, flags, line, i - sol, "junk at end of line");
00336 flags |= CCNR_CONFIG_IGNORELINE;
00337 warns++;
00338 ch = '#';
00339 }
00340 if (flags == 0 && strcmp(ccn_charbuf_as_string(key), "CCNR_DEBUG") == 0) {
00341
00342 h->debug = 1;
00343 setenv("CCNR_DEBUG", ccn_charbuf_as_string(value), 1);
00344 h->debug = r_init_debug_getenv(h, "CCNR_DEBUG");
00345 }
00346 if (pass == 2 && use_it) {
00347 if (CCNSHOULDLOG(h, mmm, CCNL_FINEST))
00348 ccnr_msg(h, "config: %s=%s",
00349 ccn_charbuf_as_string(key),
00350 ccn_charbuf_as_string(value));
00351 setenv(ccn_charbuf_as_string(key), ccn_charbuf_as_string(value), 1);
00352 }
00353 }
00354 ccn_charbuf_destroy(&key);
00355 ccn_charbuf_destroy(&value);
00356 return(errors ? -1 : warns);
00357 }
00358
00359 static int
00360 establish_min_send_bufsize(struct ccnr_handle *h, int fd, int minsize)
00361 {
00362 int res;
00363 int bufsize;
00364 int obufsize;
00365 socklen_t bufsize_sz;
00366
00367 bufsize_sz = sizeof(bufsize);
00368 res = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &bufsize, &bufsize_sz);
00369 if (res == -1)
00370 return (res);
00371 obufsize = bufsize;
00372 if (bufsize < minsize) {
00373 bufsize = minsize;
00374 res = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize));
00375 if (res == -1)
00376 return(res);
00377 }
00378 if (CCNSHOULDLOG(h, sdfdsf, CCNL_INFO))
00379 ccnr_msg(h, "SO_SNDBUF for fd %d is %d (was %d)", fd, bufsize, obufsize);
00380 return(bufsize);
00381 }
00382
00383
00384
00385
00386
00387 static int
00388 try_tcp_instead(int fd)
00389 {
00390 struct addrinfo hints = {0};
00391 struct addrinfo *ai = NULL;
00392 const char *port = NULL;
00393 const char *proto = NULL;
00394 int res;
00395 int sock;
00396 int ans = AF_UNIX;
00397 int yes = 1;
00398
00399 proto = getenv("CCNR_PROTO");
00400 if (proto == NULL || strcasecmp(proto, "tcp") != 0)
00401 return(ans);
00402 port = getenv("CCN_LOCAL_PORT");
00403 if (port == NULL || port[0] == 0)
00404 port = "9695";
00405 hints.ai_family = AF_UNSPEC;
00406 hints.ai_socktype = SOCK_STREAM;
00407 hints.ai_flags = 0;
00408 hints.ai_protocol = 0;
00409 res = getaddrinfo(NULL, port, &hints, &ai);
00410 if (res == 0) {
00411 sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
00412 if (sock != -1) {
00413 res = connect(sock, ai->ai_addr, ai->ai_addrlen);
00414 if (res == 0) {
00415 setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes));
00416 dup2(sock, fd);
00417 ans = ai->ai_family;
00418 }
00419 else
00420 close(sock);
00421 }
00422 freeaddrinfo(ai);
00423 }
00424 return(ans);
00425 }
00426
00427 PUBLIC struct ccnr_parsed_policy *
00428 ccnr_parsed_policy_create(void)
00429 {
00430 struct ccnr_parsed_policy *pp;
00431 pp = calloc(1, sizeof(struct ccnr_parsed_policy));
00432 pp->store = ccn_charbuf_create();
00433 pp->namespaces = ccn_indexbuf_create();
00434 return(pp);
00435 }
00436
00437 PUBLIC void
00438 ccnr_parsed_policy_destroy(struct ccnr_parsed_policy **ppp)
00439 {
00440 struct ccnr_parsed_policy *pp;
00441
00442 if (*ppp == NULL)
00443 return;
00444 pp = *ppp;
00445 ccn_charbuf_destroy(&pp->store);
00446 ccn_indexbuf_destroy(&pp->namespaces);
00447 free(pp);
00448 *ppp = NULL;
00449 }
00450
00451
00452
00453
00454
00455
00456
00457 PUBLIC struct ccnr_handle *
00458 r_init_create(const char *progname, ccnr_logger logger, void *loggerdata)
00459 {
00460 char *sockname = NULL;
00461 const char *portstr = NULL;
00462 const char *listen_on = NULL;
00463 const char *d = NULL;
00464 struct ccnr_handle *h = NULL;
00465 struct hashtb_param param = {0};
00466 struct ccn_charbuf *config = NULL;
00467 int res;
00468
00469 h = calloc(1, sizeof(*h));
00470 if (h == NULL)
00471 return(h);
00472 h->notify_after = CCNR_MAX_ACCESSION;
00473 h->logger = logger;
00474 h->loggerdata = loggerdata;
00475 h->logpid = (int)getpid();
00476 h->progname = progname;
00477 h->debug = -1;
00478 config = r_init_read_config(h);
00479 if (config == NULL)
00480 goto Bail;
00481 r_init_parse_config(h, config, 0);
00482 h->debug = 1;
00483 h->debug = r_init_debug_getenv(h, "CCNR_DEBUG");
00484 res = r_init_parse_config(h, config, 1);
00485 if (res < 0) {
00486 h->running = -1;
00487 goto Bail;
00488 }
00489 r_init_parse_config(h, config, 2);
00490 sockname = r_net_get_local_sockname();
00491 h->skiplinks = ccn_indexbuf_create();
00492 h->face_limit = 10;
00493 h->fdholder_by_fd = calloc(h->face_limit, sizeof(h->fdholder_by_fd[0]));
00494 param.finalize_data = h;
00495 param.finalize = &r_fwd_finalize_nameprefix;
00496 h->nameprefix_tab = hashtb_create(sizeof(struct nameprefix_entry), ¶m);
00497 param.finalize = 0;
00498 h->propagating_tab = hashtb_create(sizeof(struct propagating_entry), ¶m);
00499 param.finalize = 0;
00500 h->enum_state_tab = hashtb_create(sizeof(struct enum_state), NULL);
00501 h->min_stale = ~0;
00502 h->max_stale = 0;
00503 h->unsol = ccn_indexbuf_create();
00504 h->ticktock.descr[0] = 'C';
00505 h->ticktock.micros_per_base = 1000000;
00506 h->ticktock.gettime = &r_util_gettime;
00507 h->ticktock.data = h;
00508 h->sched = ccn_schedule_create(h, &h->ticktock);
00509 h->starttime = h->sec;
00510 h->starttime_usec = h->usec;
00511 h->oldformatcontentgrumble = 1;
00512 h->oldformatinterestgrumble = 1;
00513 h->cob_limit = 4201;
00514 h->start_write_scope_limit = r_init_confval(h, "CCNR_START_WRITE_SCOPE_LIMIT", 0, 3, 3);
00515 h->debug = 1;
00516 h->debug = r_init_debug_getenv(h, "CCNR_DEBUG");
00517 h->syncdebug = r_init_debug_getenv(h, "CCNS_DEBUG");
00518 portstr = getenv("CCNR_STATUS_PORT");
00519 if (portstr == NULL || portstr[0] == 0 || strlen(portstr) > 10)
00520 portstr = "";
00521 h->portstr = portstr;
00522 ccnr_msg(h, "CCNR_DEBUG=%d CCNR_DIRECTORY=%s CCNR_STATUS_PORT=%s", h->debug, h->directory, h->portstr);
00523 listen_on = getenv("CCNR_LISTEN_ON");
00524 if (listen_on != NULL && listen_on[0] != 0)
00525 ccnr_msg(h, "CCNR_LISTEN_ON=%s", listen_on);
00526
00527 if (ccnr_init_repo_keystore(h, NULL) < 0) {
00528 h->running = -1;
00529 goto Bail;
00530 }
00531 r_util_reseed(h);
00532 r_store_init(h);
00533 if (h->running == -1) goto Bail;
00534 while (h->active_in_fd >= 0) {
00535 r_dispatch_process_input(h, h->active_in_fd);
00536 r_store_trim(h, h->cob_limit);
00537 ccn_schedule_run(h->sched);
00538 }
00539 ccnr_msg(h, "Repository file is indexed");
00540 if (h->face0 == NULL) {
00541 struct fdholder *fdholder;
00542 fdholder = calloc(1, sizeof(*fdholder));
00543 if (dup2(open("/dev/null", O_RDONLY), 0) == -1)
00544 ccnr_msg(h, "stdin: %s", strerror(errno));
00545 fdholder->filedesc = 0;
00546 fdholder->flags = (CCNR_FACE_GG | CCNR_FACE_NORECV);
00547 r_io_enroll_face(h, fdholder);
00548 }
00549 ccnr_direct_client_start(h);
00550 d = getenv("CCNR_SKIP_VERIFY");
00551 #if (CCN_API_VERSION >= 4004)
00552 if (d != NULL && strcmp(d, "1") == 0) {
00553 ccnr_msg(h, "CCNR_SKIP_VERIFY=%s", d);
00554 ccn_defer_verification(h->direct_client, 1);
00555 }
00556 #endif
00557 if (ccn_connect(h->direct_client, NULL) != -1) {
00558 int af = 0;
00559 int bufsize;
00560 int flags;
00561 int fd;
00562 struct fdholder *fdholder;
00563
00564 fd = ccn_get_connection_fd(h->direct_client);
00565
00566 af = try_tcp_instead(fd);
00567 flags = CCNR_FACE_CCND;
00568 if (af == AF_INET)
00569 flags |= CCNR_FACE_INET;
00570 else if (af == AF_INET6)
00571 flags |= CCNR_FACE_INET6;
00572 else
00573 flags |= CCNR_FACE_LOCAL;
00574 fdholder = r_io_record_fd(h, fd, "CCND", 5, flags);
00575 if (fdholder == NULL) abort();
00576 ccnr_uri_listen(h, h->direct_client, "ccnx:/%C1.M.S.localhost/%C1.M.SRV/repository",
00577 &ccnr_answer_req, OP_SERVICE);
00578 ccnr_uri_listen(h, h->direct_client, "ccnx:/%C1.M.S.neighborhood/%C1.M.SRV/repository",
00579 &ccnr_answer_req, OP_SERVICE);
00580 bufsize = r_init_confval(h, "CCNR_MIN_SEND_BUFSIZE", 1, 2097152, 16384);
00581 establish_min_send_bufsize(h, fd, bufsize);
00582 }
00583 else
00584 ccn_disconnect(h->direct_client);
00585 h->sync_handle = SyncNewBase(h, h->direct_client, h->sched);
00586 if (-1 == load_policy(h))
00587 goto Bail;
00588 r_net_listen_on(h, listen_on);
00589 ccnr_internal_client_start(h);
00590 r_proto_init(h);
00591 r_proto_activate_policy(h, h->parsed_policy);
00592 if (merge_files(h) == -1)
00593 r_init_fail(h, __LINE__, "Unable to merge additional repository data files.", errno);
00594 if (h->running == -1) goto Bail;
00595 SyncInit(h->sync_handle);
00596 Bail:
00597 if (sockname)
00598 free(sockname);
00599 sockname = NULL;
00600 ccn_charbuf_destroy(&config);
00601 if (h->running == -1)
00602 r_init_destroy(&h);
00603 return(h);
00604 }
00605
00606 void
00607 r_init_fail(struct ccnr_handle *ccnr, int line, const char *culprit, int err)
00608 {
00609 ccnr_msg(ccnr, "Startup failure %d %s - %s", line, culprit,
00610 (err > 0) ? strerror(err) : "");
00611 ccnr->running = -1;
00612 }
00613
00614
00615
00616
00617 PUBLIC void
00618 r_init_destroy(struct ccnr_handle **pccnr)
00619 {
00620 struct ccnr_handle *h = *pccnr;
00621 int stable;
00622 if (h == NULL)
00623 return;
00624 stable = h->active_in_fd == -1 ? 1 : 0;
00625 r_io_shutdown_all(h);
00626 ccnr_direct_client_stop(h);
00627 ccn_schedule_destroy(&h->sched);
00628 hashtb_destroy(&h->propagating_tab);
00629 hashtb_destroy(&h->nameprefix_tab);
00630 hashtb_destroy(&h->content_by_accession_tab);
00631 hashtb_destroy(&h->enum_state_tab);
00632
00633 SyncFreeBase(&h->sync_handle);
00634
00635 r_store_final(h, stable);
00636
00637 if (h->fds != NULL) {
00638 free(h->fds);
00639 h->fds = NULL;
00640 h->nfds = 0;
00641 }
00642 if (h->fdholder_by_fd != NULL) {
00643 free(h->fdholder_by_fd);
00644 h->fdholder_by_fd = NULL;
00645 h->face_limit = h->face_gen = 0;
00646 }
00647 if (h->content_by_cookie != NULL) {
00648 free(h->content_by_cookie);
00649 h->content_by_cookie = NULL;
00650 h->cookie_limit = 1;
00651 }
00652 ccn_charbuf_destroy(&h->scratch_charbuf);
00653 ccn_indexbuf_destroy(&h->skiplinks);
00654 ccn_indexbuf_destroy(&h->scratch_indexbuf);
00655 ccn_indexbuf_destroy(&h->unsol);
00656 if (h->parsed_policy != NULL) {
00657 ccn_indexbuf_destroy(&h->parsed_policy->namespaces);
00658 ccn_charbuf_destroy(&h->parsed_policy->store);
00659 free(h->parsed_policy);
00660 h->parsed_policy = NULL;
00661 }
00662 ccn_charbuf_destroy(&h->policy_link_cob);
00663 free(h);
00664 *pccnr = NULL;
00665 }
00666
00667 int
00668 r_init_map_and_process_file(struct ccnr_handle *h, struct ccn_charbuf *filename, int add_content)
00669 {
00670 int res = 0;
00671 int dres;
00672 struct stat statbuf;
00673 unsigned char *mapped_file = MAP_FAILED;
00674 unsigned char *msg;
00675 size_t size;
00676 int fd = -1;
00677 struct content_entry *content;
00678 struct ccn_skeleton_decoder *d;
00679 struct fdholder *fdholder;
00680
00681 fd = r_io_open_repo_data_file(h, ccn_charbuf_as_string(filename), 0);
00682 if (fd == -1)
00683 return(1);
00684
00685 res = fstat(fd, &statbuf);
00686 if (res != 0) {
00687 ccnr_msg(h, "stat failed for %s (fd=%d), %s (errno=%d)",
00688 ccn_charbuf_as_string(filename), fd, strerror(errno), errno);
00689 res = -errno;
00690 goto Bail;
00691 }
00692 if (statbuf.st_size == 0)
00693 goto Bail;
00694
00695 mapped_file = mmap(NULL, statbuf.st_size, PROT_READ, MAP_SHARED, fd, 0);
00696 if (mapped_file == MAP_FAILED) {
00697 ccnr_msg(h, "mmap failed for %s (fd=%d), %s (errno=%d)",
00698 ccn_charbuf_as_string(filename), fd, strerror(errno), errno);
00699 res = -errno;
00700 goto Bail;
00701 }
00702 fdholder = r_io_fdholder_from_fd(h, fd);
00703 d = &fdholder->decoder;
00704 msg = mapped_file;
00705 size = statbuf.st_size;
00706 while (d->index < size) {
00707 dres = ccn_skeleton_decode(d, msg + d->index, size - d->index);
00708 if (!CCN_FINAL_DSTATE(d->state))
00709 break;
00710 if (add_content) {
00711 content = process_incoming_content(h, fdholder, msg + d->index - dres, dres);
00712 if (content != NULL)
00713 r_store_commit_content(h, content);
00714 }
00715 }
00716
00717 if (d->index != size || !CCN_FINAL_DSTATE(d->state)) {
00718 ccnr_msg(h, "protocol error on fdholder %u (state %d), discarding %d bytes",
00719 fdholder->filedesc, d->state, (int)(size - d->index));
00720 res = -1;
00721 goto Bail;
00722 }
00723
00724 Bail:
00725 if (mapped_file != MAP_FAILED)
00726 munmap(mapped_file, statbuf.st_size);
00727 r_io_shutdown_client_fd(h, fd);
00728 return (res);
00729 }
00730
00731 static int
00732 merge_files(struct ccnr_handle *h)
00733 {
00734 int i, last_file;
00735 int res;
00736 struct ccn_charbuf *filename = ccn_charbuf_create();
00737
00738
00739 for (i = 2;; i++) {
00740 filename->length = 0;
00741 ccn_charbuf_putf(filename, "repoFile%d", i);
00742 res = r_init_map_and_process_file(h, filename, 0);
00743 if (res == 1)
00744 break;
00745 if (res < 0) {
00746 ccnr_msg(h, "Error parsing repository file %s", ccn_charbuf_as_string(filename));
00747 return (-1);
00748 }
00749 }
00750 last_file = i - 1;
00751
00752 for (i = 2; i <= last_file; i++) {
00753 filename->length = 0;
00754 ccn_charbuf_putf(filename, "repoFile%d", i);
00755 res = r_init_map_and_process_file(h, filename, 1);
00756 if (res < 0) {
00757 ccnr_msg(h, "Error in phase 2 incorporating repository file %s", ccn_charbuf_as_string(filename));
00758 return (-1);
00759 }
00760 }
00761
00762 for (i = last_file; i > 1; --i) {
00763 filename->length = 0;
00764 ccn_charbuf_putf(filename, "%s/repoFile%d", h->directory, i);
00765 if (CCNSHOULDLOG(h, LM_128, CCNL_INFO))
00766 ccnr_msg(h, "unlinking %s", ccn_charbuf_as_string(filename));
00767 unlink(ccn_charbuf_as_string(filename));
00768 }
00769 ccn_charbuf_destroy(&filename);
00770 return (0);
00771 }
00772
00773 static struct ccn_charbuf *
00774 ccnr_init_policy_cob(struct ccnr_handle *ccnr, struct ccn *h,
00775 struct ccn_charbuf *basename,
00776 int freshness, struct ccn_charbuf *content)
00777 {
00778 struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT;
00779 struct ccn_charbuf *name = ccn_charbuf_create();
00780 struct ccn_charbuf *pubid = ccn_charbuf_create();
00781 struct ccn_charbuf *pubkey = ccn_charbuf_create();
00782 struct ccn_charbuf *keyid = ccn_charbuf_create();
00783 struct ccn_charbuf *tcob = ccn_charbuf_create();
00784 struct ccn_charbuf *cob = NULL;
00785 int res;
00786
00787 res = ccn_get_public_key(h, NULL, pubid, pubkey);
00788 if (res < 0)
00789 goto Leave;
00790 res = ccn_charbuf_append_charbuf(name, basename);
00791 if (ccn_name_from_uri(name, "%00") < 0)
00792 goto Leave;
00793 sp.sp_flags |= CCN_SP_FINAL_BLOCK;
00794 sp.type = CCN_CONTENT_DATA;
00795 sp.freshness = freshness;
00796 res |= ccn_sign_content(h, tcob, name, &sp, content->buf, content->length);
00797 if (res == 0) {
00798 cob = tcob;
00799 tcob = NULL;
00800 }
00801
00802 Leave:
00803 ccn_charbuf_destroy(&name);
00804 ccn_charbuf_destroy(&pubid);
00805 ccn_charbuf_destroy(&pubkey);
00806 ccn_charbuf_destroy(&keyid);
00807 ccn_charbuf_destroy(&tcob);
00808 return (cob);
00809 }
00810
00811
00812
00813
00814
00815
00816 PUBLIC struct ccn_charbuf *
00817 ccnr_init_policy_link_cob(struct ccnr_handle *ccnr, struct ccn *h,
00818 struct ccn_charbuf *targetname)
00819 {
00820 struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT;
00821 struct ccn_charbuf *name = ccn_charbuf_create();
00822 struct ccn_charbuf *pubid = ccn_charbuf_create();
00823 struct ccn_charbuf *pubkey = ccn_charbuf_create();
00824 struct ccn_charbuf *keyid = ccn_charbuf_create();
00825 struct ccn_charbuf *content = ccn_charbuf_create();
00826 struct ccn_charbuf *cob = ccn_charbuf_create();
00827 int res;
00828
00829 res = ccn_get_public_key(h, NULL, pubid, pubkey);
00830 if (res < 0)
00831 goto Bail;
00832 if (ccn_name_from_uri(name, CCNRID_POLICY_URI) < 0)
00833 goto Bail;
00834 res |= ccn_charbuf_append_value(keyid, CCN_MARKER_CONTROL, 1);
00835 res |= ccn_charbuf_append_string(keyid, ".M.K");
00836 res |= ccn_charbuf_append_value(keyid, 0, 1);
00837 res |= ccn_charbuf_append_charbuf(keyid, pubid);
00838 res |= ccn_name_append(name, keyid->buf, keyid->length);
00839 res |= ccn_create_version(h, name, CCN_V_NOW, 0, 0);
00840 if (ccn_name_from_uri(name, "%00") < 0)
00841 goto Bail;
00842 sp.sp_flags |= CCN_SP_FINAL_BLOCK;
00843 sp.type = CCN_CONTENT_LINK;
00844 res |= ccnb_append_Link(content, targetname, "Repository Policy", NULL);
00845 if (res != 0)
00846 goto Bail;
00847 res |= ccn_sign_content(h, cob, name, &sp, content->buf, content->length);
00848 if (res != 0)
00849 goto Bail;
00850 return (cob);
00851
00852 Bail:
00853 ccn_charbuf_destroy(&name);
00854 ccn_charbuf_destroy(&pubid);
00855 ccn_charbuf_destroy(&pubkey);
00856 ccn_charbuf_destroy(&keyid);
00857 ccn_charbuf_destroy(&content);
00858 return (NULL);
00859 }
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873 static int
00874 load_policy(struct ccnr_handle *ccnr)
00875 {
00876 int fd;
00877 ssize_t res;
00878 struct content_entry *content = NULL;
00879 const unsigned char *content_msg = NULL;
00880 struct ccn_parsed_ContentObject pco = {0};
00881 struct ccn_parsed_Link pl = {0};
00882 struct ccn_indexbuf *nc = NULL;
00883 struct ccn_charbuf *basename = NULL;
00884 struct ccn_charbuf *policy = NULL;
00885 struct ccn_charbuf *policy_cob = NULL;
00886 struct ccn_charbuf *policyFileName;
00887 const char *global_prefix;
00888 const unsigned char *buf = NULL;
00889 size_t length = 0;
00890 int segment = 0;
00891 int final = 0;
00892 struct ccn_buf_decoder decoder;
00893 struct ccn_buf_decoder *d;
00894
00895 policyFileName = ccn_charbuf_create();
00896 ccn_charbuf_putf(policyFileName, "%s/repoPolicy", ccnr->directory);
00897 ccnr->parsed_policy = ccnr_parsed_policy_create();
00898 fd = open(ccn_charbuf_as_string(policyFileName), O_RDONLY);
00899 if (fd >= 0) {
00900 ccnr->policy_link_cob = ccn_charbuf_create();
00901 ccn_charbuf_reserve(ccnr->policy_link_cob, 4096);
00902 ccnr->policy_link_cob->length = 0;
00903 res = read(fd, ccnr->policy_link_cob->buf, ccnr->policy_link_cob->limit - ccnr->policy_link_cob->length);
00904 close(fd);
00905 if (res == -1) {
00906 r_init_fail(ccnr, __LINE__, "Error reading repoPolicy file.", errno);
00907 ccn_charbuf_destroy(&ccnr->policy_link_cob);
00908 ccn_charbuf_destroy(&policyFileName);
00909 return(-1);
00910 }
00911 ccnr->policy_link_cob->length = res;
00912 nc = ccn_indexbuf_create();
00913 res = ccn_parse_ContentObject(ccnr->policy_link_cob->buf,
00914 ccnr->policy_link_cob->length, &pco, nc);
00915 res = ccn_ref_tagged_BLOB(CCN_DTAG_Content, ccnr->policy_link_cob->buf,
00916 pco.offset[CCN_PCO_B_Content],
00917 pco.offset[CCN_PCO_E_Content],
00918 &buf, &length);
00919 d = ccn_buf_decoder_start(&decoder, buf, length);
00920 res = ccn_parse_Link(d, &pl, NULL);
00921 if (res <= 0) {
00922 ccnr_msg(ccnr, "Policy link is malformed.");
00923 goto CreateNewPolicy;
00924 }
00925 basename = ccn_charbuf_create();
00926 ccn_charbuf_append(basename, buf + pl.offset[CCN_PL_B_Name],
00927 pl.offset[CCN_PL_E_Name] - pl.offset[CCN_PL_B_Name]);
00928 ccnr->policy_name = ccn_charbuf_create();
00929 ccn_charbuf_append_charbuf(ccnr->policy_name, basename);
00930 ccn_name_chop(ccnr->policy_name, NULL, -1);
00931 policy = ccn_charbuf_create();
00932
00933 do {
00934 ccn_name_append_numeric(basename, CCN_MARKER_SEQNUM, segment++);
00935 content = r_store_lookup_ccnb(ccnr, basename->buf, basename->length);
00936 if (content == NULL) {
00937 ccnr_debug_ccnb(ccnr, __LINE__, "policy lookup failed for", NULL,
00938 basename->buf, basename->length);
00939 break;
00940 }
00941 ccn_name_chop(basename, NULL, -1);
00942 content_msg = r_store_content_base(ccnr, content);
00943 res = ccn_parse_ContentObject(content_msg, r_store_content_size(ccnr, content), &pco, nc);
00944 res = ccn_ref_tagged_BLOB(CCN_DTAG_Content, content_msg,
00945 pco.offset[CCN_PCO_B_Content],
00946 pco.offset[CCN_PCO_E_Content],
00947 &buf, &length);
00948 ccn_charbuf_append(policy, buf, length);
00949 final = r_util_is_final_pco(content_msg, &pco, nc);
00950 } while (!final && segment < 100);
00951 if (policy->length == 0) {
00952 ccnr_msg(ccnr, "Policy link points to empty or non-existent policy.");
00953 goto CreateNewPolicy;
00954 }
00955 if (segment >= 100) {
00956 r_init_fail(ccnr, __LINE__, "Policy link points to policy with too many segments.", 0);
00957 return(-1);
00958 }
00959 if (r_proto_parse_policy(ccnr, policy->buf, policy->length, ccnr->parsed_policy) < 0) {
00960 ccnr_msg(ccnr, "Policy link points to malformed policy.");
00961 goto CreateNewPolicy;
00962 }
00963 res = ccn_name_comp_get(content_msg, nc, nc->n - 3, &buf, &length);
00964 if (length != 7 || buf[0] != CCN_MARKER_VERSION) {
00965 ccnr_msg(ccnr, "Policy link points to unversioned policy.");
00966 goto CreateNewPolicy;
00967 }
00968 memmove(ccnr->parsed_policy->version, buf, sizeof(ccnr->parsed_policy->version));
00969 ccn_indexbuf_destroy(&nc);
00970 ccn_charbuf_destroy(&basename);
00971 ccn_charbuf_destroy(&policy);
00972 ccn_charbuf_destroy(&policyFileName);
00973 return (0);
00974 }
00975
00976 CreateNewPolicy:
00977 ccnr_msg(ccnr, "Creating new policy file.");
00978
00979 global_prefix = getenv ("CCNR_GLOBAL_PREFIX");
00980 if (global_prefix != NULL)
00981 ccnr_msg(ccnr, "CCNR_GLOBAL_PREFIX=%s", global_prefix);
00982 else
00983 global_prefix = "ccnx:/parc.com/csl/ccn/Repos";
00984 policy = ccn_charbuf_create();
00985 r_proto_policy_append_basic(ccnr, policy, "1.5", "Repository", global_prefix);
00986 r_proto_policy_append_namespace(ccnr, policy, "/");
00987 basename = ccn_charbuf_create();
00988 res = ccn_name_from_uri(basename, global_prefix);
00989 res |= ccn_name_from_uri(basename, "data/policy.xml");
00990 if (res < 0) {
00991 r_init_fail(ccnr, __LINE__, "Global prefix is not a valid URI", 0);
00992 return(-1);
00993 }
00994 ccnr->policy_name = ccn_charbuf_create();
00995 ccn_charbuf_append_charbuf(ccnr->policy_name, basename);
00996 ccn_create_version(ccnr->direct_client, basename, 0,
00997 ccnr->starttime, ccnr->starttime_usec * 1000);
00998 policy_cob = ccnr_init_policy_cob(ccnr, ccnr->direct_client, basename,
00999 600, policy);
01000
01001 r_sync_local_store(ccnr, policy_cob);
01002 ccn_charbuf_destroy(&policy_cob);
01003
01004 ccnr->policy_link_cob = ccnr_init_policy_link_cob(ccnr, ccnr->direct_client,
01005 basename);
01006 if (ccnr->policy_link_cob == NULL) {
01007 r_init_fail(ccnr, __LINE__, "Unable to create policy link object", 0);
01008 return(-1);
01009 }
01010
01011 fd = open(ccn_charbuf_as_string(policyFileName), O_WRONLY | O_CREAT, 0666);
01012 if (fd < 0) {
01013 r_init_fail(ccnr, __LINE__, "Unable to open repoPolicy file for write", errno);
01014 return(-1);
01015 }
01016 lseek(fd, 0, SEEK_SET);
01017 res = write(fd, ccnr->policy_link_cob->buf, ccnr->policy_link_cob->length);
01018 if (res == -1) {
01019 r_init_fail(ccnr, __LINE__, "Unable to write repoPolicy file", errno);
01020 return(-1);
01021 }
01022 ftruncate(fd, ccnr->policy_link_cob->length);
01023 close(fd);
01024
01025 if (r_proto_parse_policy(ccnr, policy->buf, policy->length, ccnr->parsed_policy) < 0) {
01026 r_init_fail(ccnr, __LINE__, "Unable to parse new repoPolicy file", 0);
01027 return(-1);
01028 }
01029
01030 nc = ccn_indexbuf_create();
01031 ccn_name_split(basename, nc);
01032 res = ccn_name_comp_get(basename->buf, nc, nc->n - 2, &buf, &length);
01033 if (length != 7 || buf[0] != CCN_MARKER_VERSION) {
01034 r_init_fail(ccnr, __LINE__, "Unable to get repository policy object version", 0);
01035 return(-1);
01036 }
01037 memmove(ccnr->parsed_policy->version, buf, sizeof(ccnr->parsed_policy->version));
01038 ccn_charbuf_destroy(&basename);
01039 ccn_charbuf_destroy(&policy);
01040 ccn_charbuf_destroy(&policyFileName);
01041 return(0);
01042 }
01043