ccnr_internal_client.c

Go to the documentation of this file.
00001 /**
00002  * @file ccnr_internal_client.c
00003  * 
00004  * Part of ccnr -  CCNx Repository Daemon.
00005  *
00006  */
00007 
00008 /*
00009  * Copyright (C) 2011 Palo Alto Research Center, Inc.
00010  *
00011  * This work is free software; you can redistribute it and/or modify it under
00012  * the terms of the GNU General Public License version 2 as published by the
00013  * Free Software Foundation.
00014  * This work is distributed in the hope that it will be useful, but WITHOUT ANY
00015  * WARRANTY; without even the implied warranty of MERCHANTABILITY or
00016  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
00017  * for more details. You should have received a copy of the GNU General Public
00018  * License along with this program; if not, write to the
00019  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00020  * Boston, MA 02110-1301, USA.
00021  */
00022  
00023 #include <errno.h>
00024 #include <stdint.h>
00025 #include <stdlib.h>
00026 #include <stdio.h>
00027 #include <string.h>
00028 #include <sys/errno.h>
00029 #include <sys/stat.h>
00030 #include <sys/types.h>
00031 #include <unistd.h>
00032 #include <ccn/ccn.h>
00033 #include <ccn/charbuf.h>
00034 #include <ccn/ccn_private.h>
00035 #include <ccn/schedule.h>
00036 #include <ccn/sockaddrutil.h>
00037 #include <ccn/uri.h>
00038 #include <ccn/keystore.h>
00039 #include "ccnr_private.h"
00040 
00041 #include "ccnr_internal_client.h"
00042 
00043 #include "ccnr_forwarding.h"
00044 #include "ccnr_io.h"
00045 #include "ccnr_msg.h"
00046 #include "ccnr_proto.h"
00047 #include "ccnr_util.h"
00048 
00049 static struct ccn_charbuf *
00050 ccnr_init_service_ccnb(struct ccnr_handle *ccnr, struct ccn *h, const char *baseuri, int freshness)
00051 {
00052     struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT;
00053     struct ccn_charbuf *name = ccn_charbuf_create();
00054     struct ccn_charbuf *pubid = ccn_charbuf_create();
00055     struct ccn_charbuf *pubkey = ccn_charbuf_create();
00056     struct ccn_charbuf *keyid = ccn_charbuf_create();
00057     struct ccn_charbuf *cob = ccn_charbuf_create();
00058     int res;
00059     
00060     res = ccn_get_public_key(h, NULL, pubid, pubkey);
00061     if (res < 0) abort();
00062     ccn_name_from_uri(name, baseuri);
00063     ccn_charbuf_append_value(keyid, CCN_MARKER_CONTROL, 1);
00064     ccn_charbuf_append_string(keyid, ".M.K");
00065     ccn_charbuf_append_value(keyid, 0, 1);
00066     ccn_charbuf_append_charbuf(keyid, pubid);
00067     ccn_name_append(name, keyid->buf, keyid->length);
00068     ccn_create_version(h, name, 0, ccnr->starttime, ccnr->starttime_usec * 1000);
00069     sp.template_ccnb = ccn_charbuf_create();
00070     ccn_charbuf_append_tt(sp.template_ccnb, CCN_DTAG_SignedInfo, CCN_DTAG);
00071     ccn_charbuf_append_tt(sp.template_ccnb, CCN_DTAG_KeyLocator, CCN_DTAG);
00072     ccn_charbuf_append_tt(sp.template_ccnb, CCN_DTAG_KeyName, CCN_DTAG);
00073     ccn_charbuf_append_charbuf(sp.template_ccnb, name);
00074     ccn_charbuf_append_closer(sp.template_ccnb);
00075 //    ccn_charbuf_append_tt(sp.template_ccnb, CCN_DTAG_PublisherPublicKeyDigest,
00076 //                          CCN_DTAG);
00077 //    ccn_charbuf_append_charbuf(sp.template_ccnb, pubid);
00078 //    ccn_charbuf_append_closer(sp.template_ccnb);
00079     ccn_charbuf_append_closer(sp.template_ccnb);
00080     ccn_charbuf_append_closer(sp.template_ccnb);
00081     sp.sp_flags |= CCN_SP_TEMPL_KEY_LOCATOR;
00082     ccn_name_from_uri(name, "%00");
00083     sp.sp_flags |= CCN_SP_FINAL_BLOCK;
00084     sp.type = CCN_CONTENT_KEY;
00085     sp.freshness = freshness;
00086     res = ccn_sign_content(h, cob, name, &sp, pubkey->buf, pubkey->length);
00087     if (res != 0) abort();
00088     ccn_charbuf_destroy(&name);
00089     ccn_charbuf_destroy(&pubid);
00090     ccn_charbuf_destroy(&pubkey);
00091     ccn_charbuf_destroy(&keyid);
00092     ccn_charbuf_destroy(&sp.template_ccnb);
00093     return(cob);
00094 }
00095 
00096 /**
00097  * Common interest handler
00098  */
00099 PUBLIC enum ccn_upcall_res
00100 ccnr_answer_req(struct ccn_closure *selfp,
00101                  enum ccn_upcall_kind kind,
00102                  struct ccn_upcall_info *info)
00103 {
00104     struct ccn_charbuf *msg = NULL;
00105     struct ccn_charbuf *name = NULL;
00106     struct ccn_charbuf *keylocator = NULL;
00107     struct ccn_charbuf *signed_info = NULL;
00108     struct ccn_charbuf *reply_body = NULL;
00109     struct ccnr_handle *ccnr = NULL;
00110     int res = 0;
00111     int start = 0;
00112     int end = 0;
00113     int morecomps = 0;
00114     const unsigned char *final_comp = NULL;
00115     size_t final_size = 0;
00116     struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT;
00117     
00118     switch (kind) {
00119         case CCN_UPCALL_FINAL:
00120             free(selfp);
00121             return(CCN_UPCALL_RESULT_OK);
00122         case CCN_UPCALL_INTEREST:
00123             break;
00124         case CCN_UPCALL_CONSUMED_INTEREST:
00125             return(CCN_UPCALL_RESULT_OK);
00126         default:
00127             return(CCN_UPCALL_RESULT_ERR);
00128     }
00129     ccnr = (struct ccnr_handle *)selfp->data;
00130     if (CCNSHOULDLOG(ccnr, LM_128, CCNL_FINE))
00131         ccnr_debug_ccnb(ccnr, __LINE__, "ccnr_answer_req", NULL,
00132                         info->interest_ccnb, info->pi->offset[CCN_PI_E]);
00133     morecomps = selfp->intdata & MORECOMPS_MASK;
00134     if ((info->pi->answerfrom & CCN_AOK_NEW) == 0 &&
00135         selfp->intdata != OP_SERVICE &&
00136         selfp->intdata != OP_NOTICE)
00137         return(CCN_UPCALL_RESULT_OK);
00138     if (info->matched_comps >= info->interest_comps->n)
00139         goto Bail;
00140     if (selfp->intdata != OP_PING &&
00141         selfp->intdata != OP_NOTICE &&
00142         selfp->intdata != OP_SERVICE &&
00143         info->pi->prefix_comps != info->matched_comps + morecomps)
00144         goto Bail;
00145     if (morecomps == 1) {
00146         res = ccn_name_comp_get(info->interest_ccnb, info->interest_comps,
00147                                 info->matched_comps,
00148                                 &final_comp, &final_size);
00149         if (res < 0)
00150             goto Bail;
00151     }
00152     if ((selfp->intdata & MUST_VERIFY) != 0) {
00153         struct ccn_parsed_ContentObject pco = {0};
00154         // XXX - probably should check for message origin BEFORE verify
00155         res = ccn_parse_ContentObject(final_comp, final_size, &pco, NULL);
00156         if (res < 0) {
00157             ccnr_debug_ccnb(ccnr, __LINE__, "co_parse_failed", NULL,
00158                             info->interest_ccnb, info->pi->offset[CCN_PI_E]);
00159             goto Bail;
00160         }
00161         res = ccn_verify_content(info->h, final_comp, &pco);
00162         if (res != 0) {
00163             ccnr_debug_ccnb(ccnr, __LINE__, "co_verify_failed", NULL,
00164                             info->interest_ccnb, info->pi->offset[CCN_PI_E]);
00165             goto Bail;
00166         }
00167     }
00168     sp.freshness = 10;
00169     switch (selfp->intdata & OPER_MASK) {
00170         case OP_SERVICE:
00171             if (ccnr->service_ccnb == NULL)
00172                 ccnr->service_ccnb = ccnr_init_service_ccnb(ccnr, info->h, CCNRID_LOCAL_URI, 600);
00173             if (ccn_content_matches_interest(
00174                     ccnr->service_ccnb->buf,
00175                     ccnr->service_ccnb->length,
00176                     1,
00177                     NULL,
00178                     info->interest_ccnb,
00179                     info->pi->offset[CCN_PI_E],
00180                     info->pi
00181                 )) {
00182                 ccn_put(info->h, ccnr->service_ccnb->buf,
00183                                  ccnr->service_ccnb->length);
00184                 res = CCN_UPCALL_RESULT_INTEREST_CONSUMED;
00185                 goto Finish;
00186             }
00187             // XXX this needs refactoring.
00188             if (ccnr->neighbor_ccnb == NULL)
00189                 ccnr->neighbor_ccnb = ccnr_init_service_ccnb(ccnr, info->h, CCNRID_NEIGHBOR_URI, 5);
00190             if (ccn_content_matches_interest(
00191                     ccnr->neighbor_ccnb->buf,
00192                     ccnr->neighbor_ccnb->length,
00193                     1,
00194                     NULL,
00195                     info->interest_ccnb,
00196                     info->pi->offset[CCN_PI_E],
00197                     info->pi
00198                 )) {
00199                 ccn_put(info->h, ccnr->neighbor_ccnb->buf,
00200                                  ccnr->neighbor_ccnb->length);
00201                 res = CCN_UPCALL_RESULT_INTEREST_CONSUMED;
00202                 goto Finish;
00203             }
00204             if (ccn_content_matches_interest(
00205                                              ccnr->policy_link_cob->buf,
00206                                              ccnr->policy_link_cob->length,
00207                                              1,
00208                                              NULL,
00209                                              info->interest_ccnb,
00210                                              info->pi->offset[CCN_PI_E],
00211                                              info->pi
00212                                              )) {
00213                 ccn_put(info->h, ccnr->policy_link_cob->buf,
00214                         ccnr->policy_link_cob->length);
00215                 res = CCN_UPCALL_RESULT_INTEREST_CONSUMED;
00216                 goto Finish;
00217             }
00218             goto Bail;
00219             break;
00220         default:
00221             goto Bail;
00222     }
00223     if (res < 0)
00224         goto Bail;
00225     if (res == CCN_CONTENT_NACK)
00226         sp.type = res;
00227     msg = ccn_charbuf_create();
00228     name = ccn_charbuf_create();
00229     start = info->pi->offset[CCN_PI_B_Name];
00230     end = info->interest_comps->buf[info->pi->prefix_comps];
00231     ccn_charbuf_append(name, info->interest_ccnb + start, end - start);
00232     ccn_charbuf_append_closer(name);
00233     res = ccn_sign_content(info->h, msg, name, &sp,
00234                            reply_body->buf, reply_body->length);
00235     if (res < 0)
00236         goto Bail;
00237     if (CCNSHOULDLOG(ccnr, LM_128, CCNL_FINE))
00238         ccnr_debug_ccnb(ccnr, __LINE__, "ccnr_answer_req_response", NULL,
00239                         msg->buf, msg->length);
00240     res = ccn_put(info->h, msg->buf, msg->length);
00241     if (res < 0)
00242         goto Bail;
00243     res = CCN_UPCALL_RESULT_INTEREST_CONSUMED;
00244     goto Finish;
00245 Bail:
00246     res = CCN_UPCALL_RESULT_ERR;
00247 Finish:
00248     ccn_charbuf_destroy(&msg);
00249     ccn_charbuf_destroy(&name);
00250     ccn_charbuf_destroy(&keylocator);
00251     ccn_charbuf_destroy(&reply_body);
00252     ccn_charbuf_destroy(&signed_info);
00253     return(res);
00254 }
00255 
00256 static int
00257 ccnr_internal_client_refresh(struct ccn_schedule *sched,
00258                void *clienth,
00259                struct ccn_scheduled_event *ev,
00260                int flags)
00261 {
00262     struct ccnr_handle *ccnr = clienth;
00263     int microsec = 0;
00264     if ((flags & CCN_SCHEDULE_CANCEL) == 0 &&
00265           ccnr->internal_client != NULL &&
00266           ccnr->internal_client_refresh == ev) {
00267         microsec = ccn_process_scheduled_operations(ccnr->internal_client);
00268         if (microsec > ev->evint)
00269             microsec = ev->evint;
00270     }
00271     if (microsec <= 0 && ccnr->internal_client_refresh == ev)
00272         ccnr->internal_client_refresh = NULL;
00273     return(microsec);
00274 }
00275 
00276 #define CCNR_ID_TEMPL "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
00277 
00278 PUBLIC void
00279 ccnr_uri_listen(struct ccnr_handle *ccnr, struct ccn *ccn, const char *uri,
00280                 ccn_handler p, intptr_t intdata)
00281 {
00282     struct ccn_charbuf *name;
00283     struct ccn_charbuf *uri_modified = NULL;
00284     struct ccn_closure *closure;
00285     struct ccn_indexbuf *comps;
00286     const unsigned char *comp;
00287     size_t comp_size;
00288     size_t offset;
00289     
00290     name = ccn_charbuf_create();
00291     ccn_name_from_uri(name, uri);
00292     comps = ccn_indexbuf_create();
00293     if (ccn_name_split(name, comps) < 0)
00294         abort();
00295     if (ccn_name_comp_get(name->buf, comps, 1, &comp, &comp_size) >= 0) {
00296         if (comp_size == 32 && 0 == memcmp(comp, CCNR_ID_TEMPL, 32)) {
00297             /* Replace placeholder with our ccnr_id */
00298             offset = comp - name->buf;
00299             memcpy(name->buf + offset, ccnr->ccnr_id, 32);
00300             uri_modified = ccn_charbuf_create();
00301             ccn_uri_append(uri_modified, name->buf, name->length, 1);
00302             uri = (char *)uri_modified->buf;
00303         }
00304     }
00305     closure = calloc(1, sizeof(*closure));
00306     closure->p = p;
00307     closure->data = ccnr;
00308     closure->intdata = intdata;
00309     ccn_set_interest_filter(ccn, name, closure);
00310     ccn_charbuf_destroy(&name);
00311     ccn_charbuf_destroy(&uri_modified);
00312     ccn_indexbuf_destroy(&comps);
00313 }
00314 
00315 /*
00316  * This is used to shroud the contents of the keystore, which mainly serves
00317  * to add integrity checking and defense against accidental misuse.
00318  * The file permissions serve for restricting access to the private keys.
00319  */
00320 #ifndef CCNR_KEYSTORE_PASS
00321 #define CCNR_KEYSTORE_PASS "Th1s 1s n0t 8 g00d R3p0s1t0ry p8ssw0rd!"
00322 #endif
00323 
00324 /**
00325  *  Create the repository keystore if necessary,
00326  *  and load it into the client handle h.
00327  *
00328  *  It is permitted for h to be NULL to skip the load.
00329  *  @returns -1 if there were problems.
00330  */
00331  
00332 int
00333 ccnr_init_repo_keystore(struct ccnr_handle *ccnr, struct ccn *h)
00334 {
00335     struct ccn_charbuf *temp = NULL;
00336     struct ccn_charbuf *culprit = NULL;
00337     struct stat statbuf;
00338     int res = -1;
00339     size_t save;
00340     char *keystore_path = NULL;
00341     struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT;
00342     
00343     temp = ccn_charbuf_create();
00344     culprit = temp;
00345     ccn_charbuf_putf(temp, "%s/", ccnr->directory);
00346     res = stat(ccn_charbuf_as_string(temp), &statbuf);
00347     if (res == -1)
00348         goto Finish;
00349     if ((statbuf.st_mode & S_IFDIR) == 0) {
00350         res = -1;
00351         errno = ENOTDIR;
00352         goto Finish;
00353     }
00354     save = temp->length;
00355     ccn_charbuf_putf(temp, "ccnx_repository_keystore");
00356     keystore_path = strdup(ccn_charbuf_as_string(temp));
00357     res = stat(keystore_path, &statbuf);
00358     
00359     if (res == 0 && h != NULL)
00360         res = ccn_load_default_key(h, keystore_path, CCNR_KEYSTORE_PASS);
00361     if (res >= 0) {
00362         culprit = NULL;
00363         goto Finish;
00364     }
00365     /* No stored keystore that we can access. Create one if we can.*/
00366     res = ccn_keystore_file_init(keystore_path, CCNR_KEYSTORE_PASS, "Repository", 0, 0);
00367     if (res != 0) {
00368         res = -1;
00369         goto Finish;
00370     }
00371     if (CCNSHOULDLOG(ccnr, keystore, CCNL_WARNING))
00372         ccnr_msg(ccnr, "New repository private key saved in %s", keystore_path);
00373     if (h != NULL)
00374         res = ccn_load_default_key(h, keystore_path, CCNR_KEYSTORE_PASS);
00375 Finish:
00376     if (res >= 0 && h != NULL)
00377         res = ccn_chk_signing_params(h, NULL, &sp, NULL, NULL, NULL);
00378     if (res >= 0 && h != NULL) {
00379         memcpy(ccnr->ccnr_id, sp.pubid, sizeof(ccnr->ccnr_id));
00380         if (ccnr->ccnr_keyid == NULL)
00381             ccnr->ccnr_keyid = ccn_charbuf_create();
00382         else
00383             ccnr->ccnr_keyid->length = 0;
00384         ccn_charbuf_append_value(ccnr->ccnr_keyid, CCN_MARKER_CONTROL, 1);
00385         ccn_charbuf_append_string(ccnr->ccnr_keyid, ".M.K");
00386         ccn_charbuf_append_value(ccnr->ccnr_keyid, 0, 1);
00387         ccn_charbuf_append(ccnr->ccnr_keyid, ccnr->ccnr_id, sizeof(ccnr->ccnr_id));
00388     }
00389     if (res < 0) {
00390         ccnr->running = -1; /* Make note of init failure */
00391         if (culprit != NULL)
00392             ccnr_msg(ccnr, "Error accessing keystore - %s: %s\n",
00393                      strerror(errno), ccn_charbuf_as_string(temp));
00394     }
00395     ccn_charbuf_destroy(&temp);
00396     if (keystore_path != NULL)
00397         free(keystore_path);
00398     return(res);
00399 }
00400 
00401 static int
00402 post_face_notice(struct ccnr_handle *ccnr, unsigned filedesc)
00403 {
00404     struct fdholder *fdholder = ccnr_r_io_fdholder_from_fd(ccnr, filedesc);
00405     struct ccn_charbuf *msg = ccn_charbuf_create();
00406     int res = -1;
00407     int port;
00408     
00409     // XXX - text version for trying out stream stuff - replace with ccnb
00410     if (fdholder == NULL)
00411         ccn_charbuf_putf(msg, "destroyface(%u);\n", filedesc);
00412     else {
00413         ccn_charbuf_putf(msg, "newface(%u, 0x%x", filedesc, fdholder->flags);
00414         if (fdholder->name->length != 0 &&
00415             (fdholder->flags & (CCNR_FACE_INET | CCNR_FACE_INET6)) != 0) {
00416             ccn_charbuf_putf(msg, ", ");
00417             port = ccn_charbuf_append_sockaddr(msg, (struct sockaddr *)fdholder->name->buf);
00418             if (port < 0)
00419                 msg->length--;
00420             else if (port > 0)
00421                 ccn_charbuf_putf(msg, ":%d", port);
00422         }
00423         ccn_charbuf_putf(msg, ");\n", filedesc);
00424     }
00425     res = ccn_seqw_write(ccnr->notice, msg->buf, msg->length);
00426     ccn_charbuf_destroy(&msg);
00427     return(res);
00428 }
00429 
00430 static int
00431 ccnr_notice_push(struct ccn_schedule *sched,
00432                void *clienth,
00433                struct ccn_scheduled_event *ev,
00434                int flags)
00435 {
00436     struct ccnr_handle *ccnr = clienth;
00437     struct ccn_indexbuf *chface = NULL;
00438     int i = 0;
00439     int j = 0;
00440     int microsec = 0;
00441     int res = 0;
00442     
00443     if ((flags & CCN_SCHEDULE_CANCEL) == 0 &&
00444             ccnr->notice != NULL &&
00445             ccnr->notice_push == ev &&
00446             ccnr->chface != NULL) {
00447         chface = ccnr->chface;
00448         ccn_seqw_batch_start(ccnr->notice);
00449         for (i = 0; i < chface->n && res != -1; i++)
00450             res = post_face_notice(ccnr, chface->buf[i]);
00451         ccn_seqw_batch_end(ccnr->notice);
00452         for (j = 0; i < chface->n; i++, j++)
00453             chface->buf[j] = chface->buf[i];
00454         chface->n = j;
00455         if (res == -1)
00456             microsec = 3000;
00457     }
00458     if (microsec <= 0)
00459         ccnr->notice_push = NULL;
00460     return(microsec);
00461 }
00462 
00463 /**
00464  * Called by ccnr when a fdholder undergoes a substantive status change that
00465  * should be reported to interested parties.
00466  *
00467  * In the destroy case, this is called from the hash table finalizer,
00468  * so it shouldn't do much directly.  Inspecting the fdholder is OK, though.
00469  */
00470 void
00471 ccnr_face_status_change(struct ccnr_handle *ccnr, unsigned filedesc)
00472 {
00473     struct ccn_indexbuf *chface = ccnr->chface;
00474     if (chface != NULL) {
00475         ccn_indexbuf_set_insert(chface, filedesc);
00476         if (ccnr->notice_push == NULL)
00477             ccnr->notice_push = ccn_schedule_event(ccnr->sched, 2000,
00478                                                    ccnr_notice_push,
00479                                                    NULL, 0);
00480     }
00481 }
00482 
00483 int
00484 ccnr_internal_client_start(struct ccnr_handle *ccnr)
00485 {
00486     if (ccnr->internal_client != NULL)
00487         return(-1);
00488     if (ccnr->face0 == NULL)
00489         abort();
00490     ccnr->internal_client = ccn_create();
00491     if (ccnr_init_repo_keystore(ccnr, ccnr->internal_client) < 0) {
00492         ccn_destroy(&ccnr->internal_client);
00493         return(-1);
00494     }
00495     ccnr->internal_client_refresh = ccn_schedule_event(ccnr->sched, 50000,
00496                          ccnr_internal_client_refresh,
00497                          NULL, CCN_INTEREST_LIFETIME_MICROSEC);
00498     return(0);
00499 }
00500 
00501 void
00502 ccnr_internal_client_stop(struct ccnr_handle *ccnr)
00503 {
00504     ccnr->notice = NULL; /* ccn_destroy will free */
00505     if (ccnr->notice_push != NULL)
00506         ccn_schedule_cancel(ccnr->sched, ccnr->notice_push);
00507     ccn_indexbuf_destroy(&ccnr->chface);
00508     ccn_destroy(&ccnr->internal_client);
00509     ccn_charbuf_destroy(&ccnr->service_ccnb);
00510     ccn_charbuf_destroy(&ccnr->neighbor_ccnb);
00511     if (ccnr->internal_client_refresh != NULL)
00512         ccn_schedule_cancel(ccnr->sched, ccnr->internal_client_refresh);
00513 }
00514 
00515 // XXX - these are very similar to the above.
00516 // If we keep multiple internal handles around, this will need refactoring.
00517 
00518 
00519 static int
00520 ccnr_direct_client_refresh(struct ccn_schedule *sched,
00521                void *clienth,
00522                struct ccn_scheduled_event *ev,
00523                int flags)
00524 {
00525     struct ccnr_handle *ccnr = clienth;
00526     int microsec = 0;
00527     if ((flags & CCN_SCHEDULE_CANCEL) == 0 &&
00528           ccnr->direct_client != NULL &&
00529           ccnr->direct_client_refresh == ev) {
00530         microsec = ccn_process_scheduled_operations(ccnr->direct_client);
00531         // XXX - This is not really right, since an incoming request can cause us to need to reschedule this event.
00532         if CCNSHOULDLOG(ccnr, refresh, CCNL_FINEST)
00533             ccnr_msg(ccnr, "direct_client_refresh %d in %d usec",
00534                      ccn_get_connection_fd(ccnr->direct_client), microsec);
00535         if (microsec > ev->evint)
00536             microsec = ev->evint;
00537         if (microsec == 0)
00538             microsec = CCN_INTEREST_LIFETIME_MICROSEC;
00539     }
00540     if (microsec <= 0 && ccnr->direct_client_refresh == ev)
00541         ccnr->direct_client_refresh = NULL;
00542     return(microsec);
00543 }
00544 
00545 int
00546 ccnr_direct_client_start(struct ccnr_handle *ccnr)
00547 {
00548     ccnr->direct_client = ccn_create();
00549     if (ccnr_init_repo_keystore(ccnr, ccnr->direct_client) < 0) {
00550         ccn_destroy(&ccnr->direct_client);
00551         return(-1);
00552     }
00553     ccnr->direct_client_refresh = ccn_schedule_event(ccnr->sched, 50000,
00554                          ccnr_direct_client_refresh,
00555                          NULL, CCN_INTEREST_LIFETIME_MICROSEC);
00556     return(0);
00557 }
00558 
00559 void
00560 ccnr_direct_client_stop(struct ccnr_handle *ccnr)
00561 {
00562     if (ccnr->notice_push != NULL)
00563         ccn_schedule_cancel(ccnr->sched, ccnr->notice_push);
00564     ccn_indexbuf_destroy(&ccnr->chface);
00565     ccn_destroy(&ccnr->direct_client);
00566     ccn_charbuf_destroy(&ccnr->service_ccnb);
00567     ccn_charbuf_destroy(&ccnr->neighbor_ccnb);
00568     if (ccnr->direct_client_refresh != NULL)
00569         ccn_schedule_cancel(ccnr->sched, ccnr->direct_client_refresh);
00570 }
00571 

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