ccnd_internal_client.c

Go to the documentation of this file.
00001 /**
00002  * @file ccnd_internal_client.c
00003  *
00004  * Internal client of ccnd, handles requests for
00005  * inspecting and controlling operation of the ccnd;
00006  * requests and responses themselves use ccn protocols.
00007  *
00008  * Part of ccnd - the CCNx Daemon.
00009  *
00010  * Copyright (C) 2009-2011 Palo Alto Research Center, Inc.
00011  *
00012  * This work is free software; you can redistribute it and/or modify it under
00013  * the terms of the GNU General Public License version 2 as published by the
00014  * Free Software Foundation.
00015  * This work is distributed in the hope that it will be useful, but WITHOUT ANY
00016  * WARRANTY; without even the implied warranty of MERCHANTABILITY or
00017  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
00018  * for more details. You should have received a copy of the GNU General Public
00019  * License along with this program; if not, write to the
00020  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00021  * Boston, MA 02110-1301, USA.
00022  */
00023 
00024 #include <errno.h>
00025 #include <stdint.h>
00026 #include <stdlib.h>
00027 #include <stdio.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 "ccnd_private.h"
00040 
00041 #if 0
00042 #define GOT_HERE ccnd_msg(ccnd, "at ccnd_internal_client.c:%d", __LINE__);
00043 #else
00044 #define GOT_HERE
00045 #endif
00046 #define CCND_NOTICE_NAME "notice.txt"
00047 
00048 #ifndef CCND_TEST_100137
00049 #define CCND_TEST_100137 0
00050 #endif
00051 
00052 #ifndef CCND_PING
00053 /* The ping responder is deprecated, but enable it by default for now */
00054 #define CCND_PING 1
00055 #endif
00056 
00057 static void ccnd_start_notice(struct ccnd_handle *ccnd);
00058 
00059 static struct ccn_charbuf *
00060 ccnd_init_service_ccnb(struct ccnd_handle *ccnd, const char *baseuri, int freshness)
00061 {
00062     struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT;
00063     struct ccn *h = ccnd->internal_client;
00064     struct ccn_charbuf *name = ccn_charbuf_create();
00065     struct ccn_charbuf *pubid = ccn_charbuf_create();
00066     struct ccn_charbuf *pubkey = ccn_charbuf_create();
00067     struct ccn_charbuf *keyid = ccn_charbuf_create();
00068     struct ccn_charbuf *cob = ccn_charbuf_create();
00069     int res;
00070     
00071     res = ccn_get_public_key(h, NULL, pubid, pubkey);
00072     if (res < 0) abort();
00073     ccn_name_from_uri(name, baseuri);
00074     ccn_charbuf_append_value(keyid, CCN_MARKER_CONTROL, 1);
00075     ccn_charbuf_append_string(keyid, ".M.K");
00076     ccn_charbuf_append_value(keyid, 0, 1);
00077     ccn_charbuf_append_charbuf(keyid, pubid);
00078     ccn_name_append(name, keyid->buf, keyid->length);
00079     ccn_create_version(h, name, 0, ccnd->starttime, ccnd->starttime_usec * 1000);
00080     sp.template_ccnb = ccn_charbuf_create();
00081     ccn_charbuf_append_tt(sp.template_ccnb, CCN_DTAG_SignedInfo, CCN_DTAG);
00082     ccn_charbuf_append_tt(sp.template_ccnb, CCN_DTAG_KeyLocator, CCN_DTAG);
00083     ccn_charbuf_append_tt(sp.template_ccnb, CCN_DTAG_KeyName, CCN_DTAG);
00084     ccn_charbuf_append_charbuf(sp.template_ccnb, name);
00085     ccn_charbuf_append_closer(sp.template_ccnb);
00086 //    ccn_charbuf_append_tt(sp.template_ccnb, CCN_DTAG_PublisherPublicKeyDigest,
00087 //                          CCN_DTAG);
00088 //    ccn_charbuf_append_charbuf(sp.template_ccnb, pubid);
00089 //    ccn_charbuf_append_closer(sp.template_ccnb);
00090     ccn_charbuf_append_closer(sp.template_ccnb);
00091     ccn_charbuf_append_closer(sp.template_ccnb);
00092     sp.sp_flags |= CCN_SP_TEMPL_KEY_LOCATOR;
00093     ccn_name_from_uri(name, "%00");
00094     sp.sp_flags |= CCN_SP_FINAL_BLOCK;
00095     sp.type = CCN_CONTENT_KEY;
00096     sp.freshness = freshness;
00097     res = ccn_sign_content(h, cob, name, &sp, pubkey->buf, pubkey->length);
00098     if (res != 0) abort();
00099     ccn_charbuf_destroy(&name);
00100     ccn_charbuf_destroy(&pubid);
00101     ccn_charbuf_destroy(&pubkey);
00102     ccn_charbuf_destroy(&keyid);
00103     ccn_charbuf_destroy(&sp.template_ccnb);
00104     return(cob);
00105 }
00106 
00107 /**
00108  * Local interpretation of selfp->intdata
00109  */
00110 #define MORECOMPS_MASK 0x007F
00111 #define MUST_VERIFY    0x0080
00112 #define MUST_VERIFY1   (MUST_VERIFY + 1)
00113 #define OPER_MASK      0xFF00
00114 #define OP_PING        0x0000
00115 #define OP_NEWFACE     0x0200
00116 #define OP_DESTROYFACE 0x0300
00117 #define OP_PREFIXREG   0x0400
00118 #define OP_SELFREG     0x0500
00119 #define OP_UNREG       0x0600
00120 #define OP_NOTICE      0x0700
00121 #define OP_SERVICE     0x0800
00122 /**
00123  * Common interest handler for ccnd_internal_client
00124  */
00125 static enum ccn_upcall_res
00126 ccnd_answer_req(struct ccn_closure *selfp,
00127                  enum ccn_upcall_kind kind,
00128                  struct ccn_upcall_info *info)
00129 {
00130     struct ccn_charbuf *msg = NULL;
00131     struct ccn_charbuf *name = NULL;
00132     struct ccn_charbuf *keylocator = NULL;
00133     struct ccn_charbuf *signed_info = NULL;
00134     struct ccn_charbuf *reply_body = NULL;
00135     struct ccnd_handle *ccnd = NULL;
00136     int res = 0;
00137     int start = 0;
00138     int end = 0;
00139     int morecomps = 0;
00140     const unsigned char *final_comp = NULL;
00141     size_t final_size = 0;
00142     struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT;
00143     
00144     switch (kind) {
00145         case CCN_UPCALL_FINAL:
00146             free(selfp);
00147             return(CCN_UPCALL_RESULT_OK);
00148         case CCN_UPCALL_INTEREST:
00149             break;
00150         case CCN_UPCALL_CONSUMED_INTEREST:
00151             return(CCN_UPCALL_RESULT_OK);
00152         default:
00153             return(CCN_UPCALL_RESULT_ERR);
00154     }
00155     ccnd = (struct ccnd_handle *)selfp->data;
00156     if ((ccnd->debug & 128) != 0)
00157         ccnd_debug_ccnb(ccnd, __LINE__, "ccnd_answer_req", NULL,
00158                         info->interest_ccnb, info->pi->offset[CCN_PI_E]);
00159     morecomps = selfp->intdata & MORECOMPS_MASK;
00160     if ((info->pi->answerfrom & CCN_AOK_NEW) == 0 &&
00161         selfp->intdata != OP_SERVICE &&
00162         selfp->intdata != OP_NOTICE)
00163         return(CCN_UPCALL_RESULT_OK);
00164     if (info->matched_comps >= info->interest_comps->n)
00165         goto Bail;
00166     if (selfp->intdata != OP_PING &&
00167         selfp->intdata != OP_NOTICE &&
00168         selfp->intdata != OP_SERVICE &&
00169         info->pi->prefix_comps != info->matched_comps + morecomps)
00170         goto Bail;
00171     if (morecomps == 1) {
00172         res = ccn_name_comp_get(info->interest_ccnb, info->interest_comps,
00173                                 info->matched_comps,
00174                                 &final_comp, &final_size);
00175         if (res < 0)
00176             goto Bail;
00177     }
00178     if ((selfp->intdata & MUST_VERIFY) != 0) {
00179         struct ccn_parsed_ContentObject pco = {0};
00180         // XXX - probably should check for message origin BEFORE verify
00181         res = ccn_parse_ContentObject(final_comp, final_size, &pco, NULL);
00182         if (res < 0) {
00183             ccnd_debug_ccnb(ccnd, __LINE__, "co_parse_failed", NULL,
00184                             info->interest_ccnb, info->pi->offset[CCN_PI_E]);
00185             goto Bail;
00186         }
00187         res = ccn_verify_content(info->h, final_comp, &pco);
00188         if (res != 0) {
00189             ccnd_debug_ccnb(ccnd, __LINE__, "co_verify_failed", NULL,
00190                             info->interest_ccnb, info->pi->offset[CCN_PI_E]);
00191             goto Bail;
00192         }
00193     }
00194     sp.freshness = 10;
00195     switch (selfp->intdata & OPER_MASK) {
00196         case OP_PING:
00197             reply_body = ccn_charbuf_create();
00198             sp.freshness = (info->pi->prefix_comps == info->matched_comps) ? 60 : 5;
00199             res = 0;
00200             break;
00201         case OP_NEWFACE:
00202             reply_body = ccn_charbuf_create();
00203             res = ccnd_req_newface(ccnd, final_comp, final_size, reply_body);
00204             break;
00205         case OP_DESTROYFACE:
00206             reply_body = ccn_charbuf_create();
00207             res = ccnd_req_destroyface(ccnd, final_comp, final_size, reply_body);
00208             break;
00209         case OP_PREFIXREG:
00210             reply_body = ccn_charbuf_create();
00211             res = ccnd_req_prefixreg(ccnd, final_comp, final_size, reply_body);
00212             break;
00213         case OP_SELFREG:
00214             reply_body = ccn_charbuf_create();
00215             res = ccnd_req_selfreg(ccnd, final_comp, final_size, reply_body);
00216             break;
00217         case OP_UNREG:
00218             reply_body = ccn_charbuf_create();
00219             res = ccnd_req_unreg(ccnd, final_comp, final_size, reply_body);
00220             break;
00221         case OP_NOTICE:
00222             ccnd_start_notice(ccnd);
00223             goto Bail;
00224             break;
00225         case OP_SERVICE:
00226             if (ccnd->service_ccnb == NULL)
00227                 ccnd->service_ccnb = ccnd_init_service_ccnb(ccnd, CCNDID_LOCAL_URI, 600);
00228             if (ccn_content_matches_interest(
00229                     ccnd->service_ccnb->buf,
00230                     ccnd->service_ccnb->length,
00231                     1,
00232                     NULL,
00233                     info->interest_ccnb,
00234                     info->pi->offset[CCN_PI_E],
00235                     info->pi
00236                 )) {
00237                 ccn_put(info->h, ccnd->service_ccnb->buf,
00238                                  ccnd->service_ccnb->length);
00239                 res = CCN_UPCALL_RESULT_INTEREST_CONSUMED;
00240                 goto Finish;
00241             }
00242             // XXX this needs refactoring.
00243             if (ccnd->neighbor_ccnb == NULL)
00244                 ccnd->neighbor_ccnb = ccnd_init_service_ccnb(ccnd, CCNDID_NEIGHBOR_URI, 5);
00245             if (ccn_content_matches_interest(
00246                     ccnd->neighbor_ccnb->buf,
00247                     ccnd->neighbor_ccnb->length,
00248                     1,
00249                     NULL,
00250                     info->interest_ccnb,
00251                     info->pi->offset[CCN_PI_E],
00252                     info->pi
00253                 )) {
00254                 ccn_put(info->h, ccnd->neighbor_ccnb->buf,
00255                                  ccnd->neighbor_ccnb->length);
00256                 res = CCN_UPCALL_RESULT_INTEREST_CONSUMED;
00257                 goto Finish;
00258             }
00259             goto Bail;
00260             break;
00261         default:
00262             goto Bail;
00263     }
00264     if (res < 0)
00265         goto Bail;
00266     if (res == CCN_CONTENT_NACK)
00267         sp.type = res;
00268     msg = ccn_charbuf_create();
00269     name = ccn_charbuf_create();
00270     start = info->pi->offset[CCN_PI_B_Name];
00271     end = info->interest_comps->buf[info->pi->prefix_comps];
00272     ccn_charbuf_append(name, info->interest_ccnb + start, end - start);
00273     ccn_charbuf_append_closer(name);
00274     res = ccn_sign_content(info->h, msg, name, &sp,
00275                            reply_body->buf, reply_body->length);
00276     if (res < 0)
00277         goto Bail;
00278     if ((ccnd->debug & 128) != 0)
00279         ccnd_debug_ccnb(ccnd, __LINE__, "ccnd_answer_req_response", NULL,
00280                         msg->buf, msg->length);
00281     res = ccn_put(info->h, msg->buf, msg->length);
00282     if (res < 0)
00283         goto Bail;
00284     if (CCND_TEST_100137)
00285         ccn_put(info->h, msg->buf, msg->length);
00286     res = CCN_UPCALL_RESULT_INTEREST_CONSUMED;
00287     goto Finish;
00288 Bail:
00289     res = CCN_UPCALL_RESULT_ERR;
00290 Finish:
00291     ccn_charbuf_destroy(&msg);
00292     ccn_charbuf_destroy(&name);
00293     ccn_charbuf_destroy(&keylocator);
00294     ccn_charbuf_destroy(&reply_body);
00295     ccn_charbuf_destroy(&signed_info);
00296     return(res);
00297 }
00298 
00299 static int
00300 ccnd_internal_client_refresh(struct ccn_schedule *sched,
00301                void *clienth,
00302                struct ccn_scheduled_event *ev,
00303                int flags)
00304 {
00305     struct ccnd_handle *ccnd = clienth;
00306     int microsec = 0;
00307     if ((flags & CCN_SCHEDULE_CANCEL) == 0 &&
00308           ccnd->internal_client != NULL &&
00309           ccnd->internal_client_refresh == ev) {
00310         microsec = ccn_process_scheduled_operations(ccnd->internal_client);
00311         if (microsec > ev->evint)
00312             microsec = ev->evint;
00313     }
00314     if (microsec <= 0 && ccnd->internal_client_refresh == ev)
00315         ccnd->internal_client_refresh = NULL;
00316     return(microsec);
00317 }
00318 
00319 #define CCND_ID_TEMPL "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
00320 
00321 static void
00322 ccnd_uri_listen(struct ccnd_handle *ccnd, const char *uri,
00323                 ccn_handler p, intptr_t intdata)
00324 {
00325     struct ccn_charbuf *name;
00326     struct ccn_charbuf *uri_modified = NULL;
00327     struct ccn_closure *closure;
00328     struct ccn_indexbuf *comps;
00329     const unsigned char *comp;
00330     size_t comp_size;
00331     size_t offset;
00332     int reg_wanted = 1;
00333     
00334     name = ccn_charbuf_create();
00335     ccn_name_from_uri(name, uri);
00336     comps = ccn_indexbuf_create();
00337     if (ccn_name_split(name, comps) < 0)
00338         abort();
00339     if (ccn_name_comp_get(name->buf, comps, 1, &comp, &comp_size) >= 0) {
00340         if (comp_size == 32 && 0 == memcmp(comp, CCND_ID_TEMPL, 32)) {
00341             /* Replace placeholder with our ccnd_id */
00342             offset = comp - name->buf;
00343             memcpy(name->buf + offset, ccnd->ccnd_id, 32);
00344             uri_modified = ccn_charbuf_create();
00345             ccn_uri_append(uri_modified, name->buf, name->length, 1);
00346             uri = (char *)uri_modified->buf;
00347             reg_wanted = 0;
00348         }
00349     }
00350     closure = calloc(1, sizeof(*closure));
00351     closure->p = p;
00352     closure->data = ccnd;
00353     closure->intdata = intdata;
00354     /* Register explicitly if needed or requested */
00355     if (reg_wanted)
00356         ccnd_reg_uri(ccnd, uri,
00357                      0, /* special faceid for internal client */
00358                      CCN_FORW_CHILD_INHERIT | CCN_FORW_ACTIVE,
00359                      0x7FFFFFFF);
00360     ccn_set_interest_filter(ccnd->internal_client, name, closure);
00361     ccn_charbuf_destroy(&name);
00362     ccn_charbuf_destroy(&uri_modified);
00363     ccn_indexbuf_destroy(&comps);
00364 }
00365 
00366 /**
00367  * Make a forwarding table entry for ccnx:/ccnx/CCNDID
00368  *
00369  * This one entry handles most of the namespace served by the
00370  * ccnd internal client.
00371  */
00372 static void
00373 ccnd_reg_ccnx_ccndid(struct ccnd_handle *ccnd)
00374 {
00375     struct ccn_charbuf *name;
00376     struct ccn_charbuf *uri;
00377     
00378     name = ccn_charbuf_create();
00379     ccn_name_from_uri(name, "ccnx:/ccnx");
00380     ccn_name_append(name, ccnd->ccnd_id, 32);
00381     uri = ccn_charbuf_create();
00382     ccn_uri_append(uri, name->buf, name->length, 1);
00383     ccnd_reg_uri(ccnd, ccn_charbuf_as_string(uri),
00384                  0, /* special faceid for internal client */
00385                  (CCN_FORW_CHILD_INHERIT |
00386                   CCN_FORW_ACTIVE        |
00387                   CCN_FORW_CAPTURE       |
00388                   CCN_FORW_ADVERTISE     ),
00389                  0x7FFFFFFF);
00390     ccn_charbuf_destroy(&name);
00391     ccn_charbuf_destroy(&uri);
00392 }
00393 
00394 #ifndef CCN_PATH_VAR_TMP
00395 #define CCN_PATH_VAR_TMP "/var/tmp"
00396 #endif
00397 
00398 /*
00399  * This is used to shroud the contents of the keystore, which mainly serves
00400  * to add integrity checking and defense against accidental misuse.
00401  * The file permissions serve for restricting access to the private keys.
00402  */
00403 #ifndef CCND_KEYSTORE_PASS
00404 #define CCND_KEYSTORE_PASS "\010\043\103\375\327\237\152\351\155"
00405 #endif
00406 
00407 int
00408 ccnd_init_internal_keystore(struct ccnd_handle *ccnd)
00409 {
00410     struct ccn_charbuf *temp = NULL;
00411     struct ccn_charbuf *cmd = NULL;
00412     struct ccn_charbuf *culprit = NULL;
00413     struct stat statbuf;
00414     const char *dir = NULL;
00415     int res = -1;
00416     size_t save;
00417     char *keystore_path = NULL;
00418     FILE *passfile;
00419     struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT;
00420     
00421     if (ccnd->internal_client == NULL)
00422         return(-1);
00423     temp = ccn_charbuf_create();
00424     cmd = ccn_charbuf_create();
00425     dir = getenv("CCND_KEYSTORE_DIRECTORY");
00426     if (dir != NULL && dir[0] == '/')
00427         ccn_charbuf_putf(temp, "%s/", dir);
00428     else
00429         ccn_charbuf_putf(temp, CCN_PATH_VAR_TMP "/.ccnx-user%d/", (int)geteuid());
00430     res = stat(ccn_charbuf_as_string(temp), &statbuf);
00431     if (res == -1) {
00432         if (errno == ENOENT)
00433             res = mkdir(ccn_charbuf_as_string(temp), 0700);
00434         if (res != 0) {
00435             culprit = temp;
00436             goto Finish;
00437         }
00438     }
00439     save = temp->length;
00440     ccn_charbuf_putf(temp, ".ccnd_keystore_%s", ccnd->portstr);
00441     keystore_path = strdup(ccn_charbuf_as_string(temp));
00442     res = stat(keystore_path, &statbuf);
00443     if (res == 0)
00444         res = ccn_load_default_key(ccnd->internal_client, keystore_path, CCND_KEYSTORE_PASS);
00445     if (res >= 0)
00446         goto Finish;
00447     /* No stored keystore that we can access; create one. */
00448     temp->length = save;
00449     ccn_charbuf_putf(temp, "p");
00450     passfile = fopen(ccn_charbuf_as_string(temp), "wb");
00451     fprintf(passfile, "%s", CCND_KEYSTORE_PASS);
00452     fclose(passfile);
00453     ccn_charbuf_putf(cmd, "%s-init-keystore-helper %s",
00454                      ccnd->progname, keystore_path);
00455     res = system(ccn_charbuf_as_string(cmd));
00456     if (res != 0) {
00457         culprit = cmd;
00458         goto Finish;
00459     }
00460     res = ccn_load_default_key(ccnd->internal_client, keystore_path, CCND_KEYSTORE_PASS);
00461 Finish:
00462     if (culprit != NULL) {
00463         ccnd_msg(ccnd, "%s: %s:\n", ccn_charbuf_as_string(culprit), strerror(errno));
00464         culprit = NULL;
00465     }
00466     res = ccn_chk_signing_params(ccnd->internal_client, NULL, &sp, NULL, NULL, NULL);
00467     if (res != 0)
00468         abort();
00469     memcpy(ccnd->ccnd_id, sp.pubid, sizeof(ccnd->ccnd_id));
00470     ccn_charbuf_destroy(&temp);
00471     ccn_charbuf_destroy(&cmd);
00472     if (keystore_path != NULL)
00473         free(keystore_path);
00474     return(res);
00475 }
00476 
00477 static int
00478 post_face_notice(struct ccnd_handle *ccnd, unsigned faceid)
00479 {
00480     struct face *face = ccnd_face_from_faceid(ccnd, faceid);
00481     struct ccn_charbuf *msg = ccn_charbuf_create();
00482     int res = -1;
00483     int port;
00484     
00485     // XXX - text version for trying out stream stuff - replace with ccnb
00486     if (face == NULL)
00487         ccn_charbuf_putf(msg, "destroyface(%u);\n", faceid);
00488     else {
00489         ccn_charbuf_putf(msg, "newface(%u, 0x%x", faceid, face->flags);
00490         if (face->addr != NULL &&
00491             (face->flags & (CCN_FACE_INET | CCN_FACE_INET6)) != 0) {
00492             ccn_charbuf_putf(msg, ", ");
00493             port = ccn_charbuf_append_sockaddr(msg, face->addr);
00494             if (port < 0)
00495                 msg->length--;
00496             else if (port > 0)
00497                 ccn_charbuf_putf(msg, ":%d", port);
00498         }
00499         ccn_charbuf_putf(msg, ");\n", faceid);
00500     }
00501     res = ccn_seqw_write(ccnd->notice, msg->buf, msg->length);
00502     ccn_charbuf_destroy(&msg);
00503     return(res);
00504 }
00505 
00506 static int
00507 ccnd_notice_push(struct ccn_schedule *sched,
00508                void *clienth,
00509                struct ccn_scheduled_event *ev,
00510                int flags)
00511 {
00512     struct ccnd_handle *ccnd = clienth;
00513     struct ccn_indexbuf *chface = NULL;
00514     int i = 0;
00515     int j = 0;
00516     int microsec = 0;
00517     int res = 0;
00518     
00519     if ((flags & CCN_SCHEDULE_CANCEL) == 0 &&
00520             ccnd->notice != NULL &&
00521             ccnd->notice_push == ev &&
00522             ccnd->chface != NULL) {
00523         chface = ccnd->chface;
00524         ccn_seqw_batch_start(ccnd->notice);
00525         for (i = 0; i < chface->n && res != -1; i++)
00526             res = post_face_notice(ccnd, chface->buf[i]);
00527         ccn_seqw_batch_end(ccnd->notice);
00528         for (j = 0; i < chface->n; i++, j++)
00529             chface->buf[j] = chface->buf[i];
00530         chface->n = j;
00531         if (res == -1)
00532             microsec = 3000;
00533     }
00534     if (microsec <= 0)
00535         ccnd->notice_push = NULL;
00536     return(microsec);
00537 }
00538 
00539 /**
00540  * Called by ccnd when a face undergoes a substantive status change that
00541  * should be reported to interested parties.
00542  *
00543  * In the destroy case, this is called from the hash table finalizer,
00544  * so it shouldn't do much directly.  Inspecting the face is OK, though.
00545  */
00546 void
00547 ccnd_face_status_change(struct ccnd_handle *ccnd, unsigned faceid)
00548 {
00549     struct ccn_indexbuf *chface = ccnd->chface;
00550     if (chface != NULL) {
00551         ccn_indexbuf_set_insert(chface, faceid);
00552         if (ccnd->notice_push == NULL)
00553             ccnd->notice_push = ccn_schedule_event(ccnd->sched, 2000,
00554                                                    ccnd_notice_push,
00555                                                    NULL, 0);
00556     }
00557 }
00558 
00559 static void
00560 ccnd_start_notice(struct ccnd_handle *ccnd)
00561 {
00562     struct ccn *h = ccnd->internal_client;
00563     struct ccn_charbuf *name = NULL;
00564     struct face *face = NULL;
00565     int i;
00566     
00567     if (h == NULL)
00568         return;
00569     if (ccnd->notice != NULL)
00570         return;
00571     if (ccnd->chface != NULL) {
00572         /* Probably should not happen. */
00573         ccnd_msg(ccnd, "ccnd_internal_client.c:%d Huh?", __LINE__);
00574         ccn_indexbuf_destroy(&ccnd->chface);
00575     }
00576     name = ccn_charbuf_create();
00577     ccn_name_from_uri(name, "ccnx:/ccnx");
00578     ccn_name_append(name, ccnd->ccnd_id, 32);
00579     ccn_name_append_str(name, CCND_NOTICE_NAME);
00580     ccnd->notice = ccn_seqw_create(h, name);
00581     ccnd->chface = ccn_indexbuf_create();
00582     for (i = 0; i < ccnd->face_limit; i++) {
00583         face = ccnd->faces_by_faceid[i];
00584         if (face != NULL)
00585             ccn_indexbuf_set_insert(ccnd->chface, face->faceid);
00586     }
00587     if (ccnd->chface->n > 0)
00588         ccnd_face_status_change(ccnd, ccnd->chface->buf[0]);
00589     ccn_charbuf_destroy(&name);
00590 }
00591 
00592 int
00593 ccnd_internal_client_start(struct ccnd_handle *ccnd)
00594 {
00595     struct ccn *h;
00596     if (ccnd->internal_client != NULL)
00597         return(-1);
00598     if (ccnd->face0 == NULL)
00599         abort();
00600     ccnd->internal_client = h = ccn_create();
00601     if (ccnd_init_internal_keystore(ccnd) < 0) {
00602         ccn_destroy(&ccnd->internal_client);
00603         return(-1);
00604     }
00605 #if (CCND_PING+0)
00606     ccnd_uri_listen(ccnd, "ccnx:/ccnx/ping",
00607                     &ccnd_answer_req, OP_PING);
00608     ccnd_uri_listen(ccnd, "ccnx:/ccnx/" CCND_ID_TEMPL "/ping",
00609                     &ccnd_answer_req, OP_PING);
00610 #endif
00611     ccnd_uri_listen(ccnd, "ccnx:/ccnx/" CCND_ID_TEMPL "/newface",
00612                     &ccnd_answer_req, OP_NEWFACE + MUST_VERIFY1);
00613     ccnd_uri_listen(ccnd, "ccnx:/ccnx/" CCND_ID_TEMPL "/destroyface",
00614                     &ccnd_answer_req, OP_DESTROYFACE + MUST_VERIFY1);
00615     ccnd_uri_listen(ccnd, "ccnx:/ccnx/" CCND_ID_TEMPL "/prefixreg",
00616                     &ccnd_answer_req, OP_PREFIXREG + MUST_VERIFY1);
00617     ccnd_uri_listen(ccnd, "ccnx:/ccnx/" CCND_ID_TEMPL "/selfreg",
00618                     &ccnd_answer_req, OP_SELFREG + MUST_VERIFY1);
00619     ccnd_uri_listen(ccnd, "ccnx:/ccnx/" CCND_ID_TEMPL "/unreg",
00620                     &ccnd_answer_req, OP_UNREG + MUST_VERIFY1);
00621     ccnd_uri_listen(ccnd, "ccnx:/ccnx/" CCND_ID_TEMPL "/" CCND_NOTICE_NAME,
00622                     &ccnd_answer_req, OP_NOTICE);
00623     ccnd_uri_listen(ccnd, "ccnx:/%C1.M.S.localhost/%C1.M.SRV/ccnd",
00624                     &ccnd_answer_req, OP_SERVICE);
00625     ccnd_uri_listen(ccnd, "ccnx:/%C1.M.S.neighborhood",
00626                     &ccnd_answer_req, OP_SERVICE);
00627     ccnd_reg_ccnx_ccndid(ccnd);
00628     ccnd_reg_uri(ccnd, "ccnx:/%C1.M.S.localhost",
00629                  0, /* special faceid for internal client */
00630                  (CCN_FORW_CHILD_INHERIT |
00631                   CCN_FORW_ACTIVE        |
00632                   CCN_FORW_LOCAL         ),
00633                  0x7FFFFFFF);
00634     ccnd->internal_client_refresh \
00635     = ccn_schedule_event(ccnd->sched, 50000,
00636                          ccnd_internal_client_refresh,
00637                          NULL, CCN_INTEREST_LIFETIME_MICROSEC);
00638     return(0);
00639 }
00640 
00641 void
00642 ccnd_internal_client_stop(struct ccnd_handle *ccnd)
00643 {
00644     ccnd->notice = NULL; /* ccn_destroy will free */
00645     if (ccnd->notice_push != NULL)
00646         ccn_schedule_cancel(ccnd->sched, ccnd->notice_push);
00647     ccn_indexbuf_destroy(&ccnd->chface);
00648     ccn_destroy(&ccnd->internal_client);
00649     ccn_charbuf_destroy(&ccnd->service_ccnb);
00650     ccn_charbuf_destroy(&ccnd->neighbor_ccnb);
00651     if (ccnd->internal_client_refresh != NULL)
00652         ccn_schedule_cancel(ccnd->sched, ccnd->internal_client_refresh);
00653 }
Generated on Fri May 13 16:27:01 2011 for Content-Centric Networking in C by  doxygen 1.6.3