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

Generated on Thu Feb 16 00:43:58 2012 for Content-Centric Networking in C by  doxygen 1.5.6