SyncUtil.c

Go to the documentation of this file.
00001 /**
00002  * @file sync/SyncUtil.c
00003  *  
00004  * Part of CCNx Sync.
00005  */
00006 /*
00007  * Copyright (C) 2011-2012 Palo Alto Research Center, Inc.
00008  *
00009  * This library is free software; you can redistribute it and/or modify it
00010  * under the terms of the GNU Lesser General Public License version 2.1
00011  * as published by the Free Software Foundation.
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00015  * Lesser General Public License for more details. You should have received
00016  * a copy of the GNU Lesser General Public License along with this library;
00017  * if not, write to the Free Software Foundation, Inc., 51 Franklin Street,
00018  * Fifth Floor, Boston, MA 02110-1301 USA.
00019  */
00020 
00021 #include "SyncBase.h"
00022 #include "SyncActions.h"
00023 #include "SyncHashCache.h"
00024 #include "SyncNode.h"
00025 #include "SyncRoot.h"
00026 #include "SyncUtil.h"
00027 #include "IndexSorter.h"
00028 #include <stdlib.h>
00029 #include <string.h>
00030 #include <strings.h>
00031 #include <sys/time.h>
00032 #include <ccnr/ccnr_msg.h>
00033 #include <ccnr/ccnr_sync.h>
00034 #include <ccn/ccn.h>
00035 #include <ccn/charbuf.h>
00036 #include <ccn/coding.h>
00037 #include <ccn/indexbuf.h>
00038 #include <ccn/uri.h>
00039 
00040 
00041 static int freshLimit = 30;             // freshness limit, in seconds
00042 
00043 // external utilities
00044 
00045 #define SET_ERR(d) SyncSetDecodeErr(d, -__LINE__)
00046 extern void
00047 SyncNoteErr(const char *msg) {
00048     char *s = getenv("CCNS_NOTE_ERR");
00049     int useStdErr = 0;
00050     if (s != NULL && s[0] != 0)
00051         useStdErr = strtol(s, NULL, 10);
00052     if (useStdErr > 0) {
00053         fprintf(stderr, "**** error in %s\n", msg);
00054         fflush(stderr);
00055     }
00056 }
00057 
00058 extern int
00059 SyncSetDecodeErr(struct ccn_buf_decoder *d, int val) {
00060     SyncNoteErr("setErr");
00061     if (d->decoder.state >= 0) d->decoder.state = val;
00062     return val;
00063 }
00064 
00065 extern int
00066 SyncCheckDecodeErr(struct ccn_buf_decoder *d) {
00067     return d->decoder.state < 0;
00068 }
00069 
00070 extern int64_t
00071 SyncCurrentTime(void) {
00072     const int64_t M = 1000*1000;
00073     struct timeval now = {0};
00074     gettimeofday(&now, 0);
00075     return now.tv_sec*M+now.tv_usec;
00076 }
00077 
00078 extern int64_t
00079 SyncDeltaTime(int64_t mt1, int64_t mt2) {
00080     return mt2-mt1;
00081 }
00082 
00083 extern struct ccn_buf_decoder *
00084 SyncInitDecoderFromCharbufRange(struct ccn_buf_decoder *d,
00085                                 const struct ccn_charbuf *cb,
00086                                 ssize_t start, ssize_t stop) {
00087     if (((size_t) stop) >  cb->length) stop = cb->length;
00088     if (start < 0 || start > stop) {
00089         SET_ERR(d); // invalid
00090     } else {
00091         ccn_buf_decoder_start(d, cb->buf+start, stop - start);
00092     }
00093     d->decoder.nest = 1;
00094     return d;
00095 }
00096 
00097 extern struct ccn_buf_decoder *
00098 SyncInitDecoderFromCharbuf(struct ccn_buf_decoder *d,
00099                            const struct ccn_charbuf *cb,
00100                            ssize_t start) {
00101     return SyncInitDecoderFromCharbufRange(d, cb, start, cb->length);
00102 }
00103 
00104 extern int
00105 SyncDecodeHexDigit(char c) {
00106     if (c >= '0' && c <= '9') return c - '0';
00107     if (c >= 'a' && c <= 'f') return 10 + c - 'a';
00108     if (c >= 'A' && c <= 'F') return 10 + c - 'A';
00109     return -1;
00110 }
00111 
00112 extern int
00113 SyncDecodeUriChar(char c) {
00114     if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')
00115         || (c >= '0' && c <= '9')
00116         || c == '/' || c == '%' || c == ':'
00117         || c == '.' || c == '-' || c == '_' || c == '~') {
00118         // valid character
00119         return c;
00120     }
00121     return -1;
00122 }
00123 
00124 extern char *
00125 SyncHexStr(const unsigned char *cp, size_t sz) {
00126     char *hex = NEW_ANY(sz*2+1, char);
00127     char *hexLit = "0123456789abcdef";
00128     int i = 0;
00129     for (i = 0; i < sz; i++) {
00130         hex[i+i] = hexLit[(cp[i] / 16) & 15];
00131         hex[i+i+1] = hexLit[cp[i] & 15];
00132     }
00133     return hex;
00134 }
00135 
00136 /////////////////////////////////////////////////////////////////
00137 // Routines for root-relative reporting.
00138 /////////////////////////////////////////////////////////////////
00139 
00140 extern int
00141 SyncNoteFailed(struct SyncRootStruct *root, char *where, char *why, int line) {
00142     if (root->base->debug >= CCNL_SEVERE)
00143         ccnr_msg(root->base->client_handle, "%s, root#%u, failed, %s, line %d",
00144                  where, root->rootId, why, line);
00145     SyncNoteErr("Sync.SyncNoteFailed");
00146     return -line;
00147 }
00148 
00149 extern void
00150 SyncNoteSimple(struct SyncRootStruct *root, char *where, char *s1) {
00151     ccnr_msg(root->base->client_handle, "%s, root#%u, %s", where, root->rootId, s1);
00152 }
00153 
00154 extern void
00155 SyncNoteSimple2(struct SyncRootStruct *root, char *where, char *s1, char *s2) {
00156     ccnr_msg(root->base->client_handle, "%s, root#%u, %s, %s", where, root->rootId, s1, s2);
00157 }
00158 
00159 extern void
00160 SyncNoteSimple3(struct SyncRootStruct *root, char *where, char *s1, char *s2, char *s3) {
00161     ccnr_msg(root->base->client_handle, "%s, root#%u, %s, %s, %s", where, root->rootId, s1, s2, s3);
00162 }
00163 
00164 extern void
00165 SyncNoteUri(struct SyncRootStruct *root, char *where, char *why, struct ccn_charbuf *name) {
00166     struct ccn_charbuf *uri = SyncUriForName(name);
00167     char *str = ccn_charbuf_as_string(uri);
00168     ccnr_msg(root->base->client_handle, "%s, root#%u, %s, %s", where, root->rootId, why, str);
00169     ccn_charbuf_destroy(&uri);
00170 }
00171 
00172 extern void
00173 SyncNoteUriBase(struct SyncBaseStruct *base, char *where, char *why, struct ccn_charbuf *name) {
00174     struct ccn_charbuf *uri = SyncUriForName(name);
00175     char *str = ccn_charbuf_as_string(uri);
00176     ccnr_msg(base->client_handle, "%s, %s, %s", where, why, str);
00177     ccn_charbuf_destroy(&uri);
00178 }
00179 
00180 /////////////////////////////////////////////////////////////////
00181 // Routines for dealing with names.
00182 /////////////////////////////////////////////////////////////////
00183 
00184 extern int
00185 SyncCmpNamesInner(struct ccn_buf_decoder *xx, struct ccn_buf_decoder *yy) {
00186     // adapted from ccn_compare_names
00187     if (ccn_buf_match_dtag(xx, CCN_DTAG_Name))
00188         ccn_buf_advance(xx);
00189     else SET_ERR(xx);
00190     if (ccn_buf_match_dtag(yy, CCN_DTAG_Name))
00191         ccn_buf_advance(yy);
00192     else SET_ERR(yy);
00193     ssize_t cmp = 0;
00194     while (SyncCheckDecodeErr(xx) == 0 && SyncCheckDecodeErr(yy) == 0) {
00195         int more_x = ccn_buf_match_dtag(xx, CCN_DTAG_Component);
00196         int more_y = ccn_buf_match_dtag(yy, CCN_DTAG_Component);
00197         cmp = more_x - more_y;
00198         if (more_x == 0 || cmp != 0)
00199             break;
00200         ccn_buf_advance(xx);
00201         ccn_buf_advance(yy);
00202         size_t xs = 0;
00203         size_t ys = 0;
00204         const unsigned char *xp = NULL;
00205         const unsigned char *yp = NULL;
00206         if (ccn_buf_match_blob(xx, &xp, &xs)) ccn_buf_advance(xx);
00207         if (ccn_buf_match_blob(yy, &yp, &ys)) ccn_buf_advance(yy);
00208         cmp = xs - ys;
00209         if (cmp != 0)
00210             break;
00211         if (xs != 0) {
00212             cmp = memcmp(xp, yp, xs);
00213             if (cmp != 0)
00214                 break;
00215         }
00216         ccn_buf_check_close(xx);
00217         ccn_buf_check_close(yy);
00218     }
00219     ccn_buf_check_close(xx);
00220     ccn_buf_check_close(yy);
00221     if (cmp > 0) return 1;
00222     if (cmp < 0) return -1;
00223     return 0;
00224 }
00225 
00226 extern int
00227 SyncCmpNames(const struct ccn_charbuf *cbx, const struct ccn_charbuf *cby) {
00228     struct ccn_buf_decoder xds;
00229     struct ccn_buf_decoder *xx = SyncInitDecoderFromCharbuf(&xds, cbx, 0);
00230     struct ccn_buf_decoder yds;
00231     struct ccn_buf_decoder *yy = SyncInitDecoderFromCharbuf(&yds, cby, 0);
00232     int cmp = SyncCmpNamesInner(xx, yy);
00233     if (SyncCheckDecodeErr(xx) || SyncCheckDecodeErr(yy)) return SYNC_BAD_CMP;
00234     return (cmp);
00235 }
00236 
00237 // tests to see if the offset refers to a name
00238 // no errors
00239 extern int
00240 SyncIsName(const struct ccn_charbuf *cb) {
00241     struct ccn_buf_decoder xds;
00242     struct ccn_buf_decoder *d = SyncInitDecoderFromCharbuf(&xds, cb, 0);
00243     if (!SyncCheckDecodeErr(d) && ccn_buf_match_dtag(d, CCN_DTAG_Name))
00244         return 1;
00245     return 0;
00246 }
00247 
00248 extern int
00249 SyncComponentCount(const struct ccn_charbuf *name) {
00250     struct ccn_buf_decoder ds;
00251     struct ccn_buf_decoder *d = SyncInitDecoderFromCharbuf(&ds, name, 0);
00252     int count = 0;
00253     if (ccn_buf_match_dtag(d, CCN_DTAG_Name)) {
00254         ccn_buf_advance(d);
00255         while (ccn_buf_match_dtag(d, CCN_DTAG_Component)) {
00256             const unsigned char *cPtr = NULL;
00257             size_t cSize = 0;
00258             ccn_buf_advance(d);
00259             if (ccn_buf_match_blob(d, &cPtr, &cSize)) ccn_buf_advance(d);
00260             ccn_buf_check_close(d);
00261             count++;
00262         }
00263         ccn_buf_check_close(d);
00264         if (!SyncCheckDecodeErr(d))
00265             return count;
00266     }
00267     return -1;
00268 }
00269 
00270 extern int
00271 SyncPatternMatch(const struct ccn_charbuf *pattern,
00272                  const struct ccn_charbuf *name,
00273                  int start) {
00274     struct ccn_buf_decoder xds;
00275     struct ccn_buf_decoder *xx = SyncInitDecoderFromCharbuf(&xds, pattern, 0);
00276     struct ccn_buf_decoder yds;
00277     struct ccn_buf_decoder *yy = SyncInitDecoderFromCharbuf(&yds, name, 0);
00278     if (!ccn_buf_match_dtag(xx, CCN_DTAG_Name)) return -1;
00279     ccn_buf_advance(xx);
00280     if (!ccn_buf_match_dtag(yy, CCN_DTAG_Name)) return -1;
00281     ccn_buf_advance(yy);
00282     int match = 0;
00283     int index = 0;
00284     while (index < start) {
00285         // skip initial components of name
00286         if (!ccn_buf_match_dtag(yy, CCN_DTAG_Component))
00287             return -1;
00288         ccn_buf_advance(yy);
00289         if (!ccn_buf_match_blob(yy, NULL, NULL))
00290             return -1;
00291         ccn_buf_advance(yy);
00292         ccn_buf_check_close(yy);
00293         index++;
00294     }
00295     while (SyncCheckDecodeErr(xx) == 0 && SyncCheckDecodeErr(yy) == 0) {
00296         int more_x = ccn_buf_match_dtag(xx, CCN_DTAG_Component);
00297         int more_y = ccn_buf_match_dtag(yy, CCN_DTAG_Component);
00298         if (more_x == 0) {
00299             // end of pattern
00300             ccn_buf_check_close(xx);
00301             if (!SyncCheckDecodeErr(xx))
00302                 return match;
00303             return -1;
00304         }
00305         if (more_y == 0) {
00306             // end of name
00307             ccn_buf_check_close(yy);
00308             if (!SyncCheckDecodeErr(yy))
00309                 return 0;
00310             return -1;
00311         }
00312         ccn_buf_advance(xx);
00313         ccn_buf_advance(yy);
00314         size_t xs = 0;
00315         size_t ys = 0;
00316         const unsigned char *xp = NULL;
00317         const unsigned char *yp = NULL;
00318         if (ccn_buf_match_blob(xx, &xp, &xs)) ccn_buf_advance(xx);
00319         if (ccn_buf_match_blob(yy, &yp, &ys)) ccn_buf_advance(yy);
00320         int star = 0;
00321         if (xs > 0 && (xp[0] == 255)) {
00322             // a component starting with FF may be a star-matcher
00323             // if not a single byte, swallow the FF
00324             xs--;
00325             xp++;
00326             if (xs == 0) star = 1;
00327         }
00328         if (star) {
00329             // star-matching
00330         } else if (xs != ys) {
00331             // name lengths differ
00332             return 0;
00333         } else {
00334             // equal sizes, check contents
00335             ssize_t cmp = memcmp(xp, yp, xs);
00336             if (cmp != 0) return 0;
00337         }
00338         match++;
00339         ccn_buf_check_close(xx);
00340         ccn_buf_check_close(yy);
00341     }
00342     return (-1);
00343 }
00344 
00345 extern int
00346 SyncPrefixMatch(const struct ccn_charbuf *prefix,
00347                 const struct ccn_charbuf *name,
00348                 int start) {
00349     struct ccn_buf_decoder xds;
00350     struct ccn_buf_decoder *xx = SyncInitDecoderFromCharbuf(&xds, prefix, 0);
00351     struct ccn_buf_decoder yds;
00352     struct ccn_buf_decoder *yy = SyncInitDecoderFromCharbuf(&yds, name, 0);
00353     if (!ccn_buf_match_dtag(xx, CCN_DTAG_Name)) return -1;
00354     ccn_buf_advance(xx);
00355     if (!ccn_buf_match_dtag(yy, CCN_DTAG_Name)) return -1;
00356     ccn_buf_advance(yy);
00357     int match = 0;
00358     int index = 0;
00359     while (index < start) {
00360         // skip initial components of name
00361         if (!ccn_buf_match_dtag(yy, CCN_DTAG_Component)) break;
00362         ccn_buf_advance(yy);
00363         if (ccn_buf_match_blob(yy, NULL, NULL)) ccn_buf_advance(yy);
00364         index++;
00365     }
00366     while (SyncCheckDecodeErr(xx) == 0 && SyncCheckDecodeErr(yy) == 0) {
00367         int more_x = ccn_buf_match_dtag(xx, CCN_DTAG_Component);
00368         int more_y = ccn_buf_match_dtag(yy, CCN_DTAG_Component);
00369         if (more_x == 0) {
00370             // end of prefix
00371             ccn_buf_check_close(xx);
00372             if (!SyncCheckDecodeErr(xx))
00373                 return match;
00374             return -1;
00375         }
00376         if (more_y == 0) {
00377             // end of name
00378             ccn_buf_check_close(yy);
00379             if (!SyncCheckDecodeErr(yy))
00380                 return 0;
00381             return -1;
00382         }
00383         ccn_buf_advance(xx);
00384         ccn_buf_advance(yy);
00385         size_t xs = 0;
00386         size_t ys = 0;
00387         const unsigned char *xp = NULL;
00388         const unsigned char *yp = NULL;
00389         if (ccn_buf_match_blob(xx, &xp, &xs)) ccn_buf_advance(xx);
00390         if (ccn_buf_match_blob(yy, &yp, &ys)) ccn_buf_advance(yy);
00391         if (xs != ys) {
00392             // name lengths differ
00393             return 0;
00394         } else if (xs > 0) {
00395             // equal sizes, check contents
00396             ssize_t cmp = memcmp(xp, yp, xs);
00397             if (cmp != 0) return 0;
00398         }
00399         match++;
00400         ccn_buf_check_close(xx);
00401         ccn_buf_check_close(yy);
00402     }
00403     return -1;
00404 }
00405 
00406 extern int
00407 SyncComponentMatch(const struct ccn_charbuf *x,
00408                    const struct ccn_charbuf *y) {
00409     struct ccn_buf_decoder xds;
00410     struct ccn_buf_decoder *xx = SyncInitDecoderFromCharbuf(&xds, x, 0);
00411     struct ccn_buf_decoder yds;
00412     struct ccn_buf_decoder *yy = SyncInitDecoderFromCharbuf(&yds, y, 0);
00413     if (!ccn_buf_match_dtag(xx, CCN_DTAG_Name)) return -1;
00414     ccn_buf_advance(xx);
00415     if (!ccn_buf_match_dtag(yy, CCN_DTAG_Name)) return -1;
00416     ccn_buf_advance(yy);
00417     int match = 0;
00418     size_t xs = 0;
00419     size_t ys = 0;
00420     const unsigned char *xp = NULL;
00421     const unsigned char *yp = NULL;
00422     for (;;) {
00423         if (!ccn_buf_match_dtag(xx, CCN_DTAG_Component)) break;
00424         if (!ccn_buf_match_dtag(yy, CCN_DTAG_Component)) break;
00425         ccn_buf_advance(xx);
00426         ccn_buf_advance(yy);
00427         if (!ccn_buf_match_blob(xx, &xp, &xs)) return -1;
00428         if (!ccn_buf_match_blob(yy, &yp, &ys)) return -1;
00429         if (xs != ys) break;
00430         ssize_t cmp = memcmp(xp, yp, xs);
00431         if (cmp != 0) break;
00432         ccn_buf_advance(xx);
00433         ccn_buf_advance(yy);
00434         ccn_buf_check_close(xx);
00435         ccn_buf_check_close(yy);
00436         match++;
00437     }
00438     if (SyncCheckDecodeErr(xx)) match = -1;
00439     if (SyncCheckDecodeErr(yy)) match = -1;
00440     return match;
00441 }
00442 
00443 extern int
00444 SyncGetComponentPtr(const struct ccn_charbuf *src, int comp,
00445                     const unsigned char **xp, ssize_t *xs) {
00446     struct ccn_buf_decoder sbd;
00447     struct ccn_buf_decoder *s = SyncInitDecoderFromCharbuf(&sbd, src, 0);
00448     if (ccn_buf_match_dtag(s, CCN_DTAG_Name) && (xp != NULL) && (xs != NULL)) {
00449         int pos = 0;
00450         ccn_buf_advance(s);
00451         while (pos <= comp) {
00452             if (!ccn_buf_match_dtag(s, CCN_DTAG_Component)) break;
00453             ccn_buf_advance(s);
00454             if (!ccn_buf_match_blob(s, xp, (size_t *) xs)) break;
00455             ccn_buf_advance(s);
00456             ccn_buf_check_close(s);
00457             if (SyncCheckDecodeErr(s)) break;
00458             if (pos == comp)
00459                 // found the component
00460                 return 0;
00461             pos++;
00462         }
00463     }
00464     return -1;
00465 }
00466 
00467 extern int
00468 SyncAppendAllComponents(struct ccn_charbuf *dst,
00469                         const struct ccn_charbuf *src) {
00470     struct ccn_buf_decoder sbd;
00471     struct ccn_buf_decoder *s = SyncInitDecoderFromCharbuf(&sbd, src, 0);
00472     int count = 0;
00473     int pos = 0;
00474     if (!ccn_buf_match_dtag(s, CCN_DTAG_Name))
00475         // src is not a name
00476         return -__LINE__;
00477     ccn_buf_advance(s);
00478     for (;;) {
00479         if (!ccn_buf_match_dtag(s, CCN_DTAG_Component)) break;
00480         ccn_buf_advance(s);
00481         const unsigned char *cPtr = NULL;
00482         size_t cSize = 0;
00483         if (ccn_buf_match_blob(s, &cPtr, &cSize)) ccn_buf_advance(s);
00484         if (ccn_name_append(dst, cPtr, cSize) < 0)
00485             return -__LINE__;
00486         count++;
00487         ccn_buf_check_close(s);
00488         if (SyncCheckDecodeErr(s)) return -__LINE__;
00489         pos++;
00490     }
00491     ccn_buf_check_close(s);
00492     if (SyncCheckDecodeErr(s)) return -__LINE__;
00493     return count;
00494 }
00495 
00496 extern struct ccn_charbuf *
00497 SyncNameForIndexbuf(const unsigned char *buf, struct ccn_indexbuf *comps) {
00498     struct ccn_charbuf *name = ccn_charbuf_create();
00499     ccn_name_init(name);
00500     int i = 0;
00501     int nComp = comps->n-1;
00502     int res = 0;
00503     for (i = 0; i < nComp; i++) {
00504         const unsigned char *cp = NULL;
00505         size_t sz = 0;
00506         res |= ccn_name_comp_get(buf, comps, i, &cp, &sz);
00507         if (res < 0) break;
00508         res |= ccn_name_append(name, cp, sz);
00509         if (res < 0) break;
00510     }
00511     if (res < 0) {
00512         SyncNoteErr("SyncNameForIndexbuf failed");
00513         ccn_charbuf_destroy(&name);
00514         return NULL;
00515     }
00516     return name;
00517 }
00518 
00519 extern struct ccn_charbuf *
00520 SyncUriForName(struct ccn_charbuf *name) {
00521     struct ccn_charbuf *ret = ccn_charbuf_create();
00522     ccn_uri_append(ret, name->buf, name->length, 0);
00523     return ret;
00524 }
00525 
00526 /////////////////////////////////////////////////////////////////
00527 // Routines for dealing with hashes.
00528 /////////////////////////////////////////////////////////////////
00529 
00530 extern void
00531 SyncGetHashPtr(const struct ccn_buf_decoder *hd,
00532                const unsigned char ** xp, ssize_t *xs) {
00533     struct ccn_buf_decoder xds = *hd;
00534     struct ccn_buf_decoder *xd = &xds;
00535     size_t us = 0;
00536     if (ccn_buf_match_dtag(xd, CCN_DTAG_SyncContentHash)) {
00537         ccn_buf_advance(xd);
00538         if (ccn_buf_match_blob(xd, xp, &us)) ccn_buf_advance(xd);
00539         ccn_buf_check_close(xd);
00540     } else if (ccn_buf_match_dtag(xd, CCN_DTAG_Component)) {
00541         ccn_buf_advance(xd);
00542         if (ccn_buf_match_blob(xd, xp, &us)) ccn_buf_advance(xd);
00543         ccn_buf_check_close(xd);
00544     } else if (ccn_buf_match_dtag(xd, CCN_DTAG_Name)) {
00545         ccn_buf_advance(xd);
00546         for (;;) {
00547             if (!ccn_buf_match_dtag(xd, CCN_DTAG_Component)) break;
00548             ccn_buf_advance(xd);
00549             if (ccn_buf_match_blob(xd, xp, &us)) ccn_buf_advance(xd);
00550             ccn_buf_check_close(xd);
00551         }
00552         ccn_buf_check_close(xd);
00553     }
00554     xs[0] = (ssize_t) us;
00555     if (SyncCheckDecodeErr(xd)) {
00556         // close bug
00557         xp[0] = NULL;
00558         xs[0] = 0;
00559         SyncSetDecodeErr(xd, -__LINE__);
00560     }
00561 }
00562 
00563 extern ssize_t
00564 SyncCmpHashesRaw(const unsigned char * xp, ssize_t xs,
00565                  const unsigned char * yp, ssize_t ys) {
00566     ssize_t cmp = xs - ys;
00567     if (cmp == 0) {
00568         cmp = memcmp(xp, yp, xs);
00569     }
00570     return cmp;
00571 }
00572 
00573 // accumulates a simple hash code into the hash accumulator
00574 // hash code is raw bytes
00575 extern void
00576 SyncAccumHashRaw(struct SyncLongHashStruct *hp,
00577                  const unsigned char * xp, size_t xs) {
00578     unsigned char *ap = hp->bytes;
00579     int as = MAX_HASH_BYTES;
00580     int aLim = hp->pos;
00581     int c = 0;
00582     if (xs < 2)
00583         SyncNoteErr("SyncAccumHashRaw, xs < 2");
00584     // first, accum from x until no more bytes
00585     while (xs > 0 && as > 0) {
00586         int val = c;
00587         xs--;
00588         as--;
00589         val = val + ap[as] + xp[xs];
00590         c = (val >> 8) & 255;
00591         ap[as] = val & 255;
00592     }
00593     // second, propagate the carry (if any)
00594     while (c > 0 && as > 0) {
00595         as--;
00596         c = c + ap[as];
00597         ap[as] = c & 255;
00598         c = (c >> 8) & 255;
00599     }
00600     // last, update the position (if less than the original)
00601     if (as < aLim) hp->pos = as;
00602 }
00603 
00604 // accumulates a simple hash code referenced by a decoder
00605 // into the hash accumulator for the composite node
00606 // non-destructive of decoder
00607 extern void
00608 SyncAccumHashInner(struct SyncLongHashStruct *hp,
00609                    const struct ccn_buf_decoder *d) {
00610     const unsigned char * xp = NULL;
00611     ssize_t xs = -1;
00612     SyncGetHashPtr(d, &xp, &xs);
00613     if (xs >= 0 && xp != NULL)
00614         SyncAccumHashRaw(hp, xp, xs);
00615 }
00616 
00617 // accumulates a simple hash code referenced by a decoder
00618 // into the hash accumulator for the composite node
00619 // non-destructive of decoder
00620 extern void
00621 SyncAccumHash(struct SyncLongHashStruct *hp, const struct ccn_charbuf *cb) {
00622     struct ccn_buf_decoder ds;
00623     struct ccn_buf_decoder *d = SyncInitDecoderFromCharbuf(&ds, cb, 0);
00624     SyncAccumHashInner(hp, d);
00625 }
00626 
00627 extern struct ccn_charbuf *
00628 SyncLongHashToBuf(const struct SyncLongHashStruct *hp) {
00629     struct ccn_charbuf *ret = ccn_charbuf_create();
00630     int pos = hp->pos;
00631     ccn_charbuf_append(ret, hp->bytes+pos, MAX_HASH_BYTES-pos);
00632     return ret;
00633 }
00634 
00635 // makes a small, unsigned hash code from a full hash
00636 // useful to speed up hash table lookups
00637 extern uint32_t
00638 SyncSmallHash(const unsigned char * xp, ssize_t xs) {
00639     uint32_t ret = 0;
00640     if (xs > 0 && xp != NULL) {
00641         int i = 0;
00642         while (i < xs && i < ((int) sizeof(ret))) {
00643             ret = (ret << 8) + (xp[i] & 255);
00644             i++;
00645         }
00646     }
00647     return ret;
00648 }
00649 
00650 
00651 
00652 /////////////////////////////////////////////////////////////////
00653 // Routines for appending numbers, hashes and names to a charbuf.
00654 /////////////////////////////////////////////////////////////////
00655 
00656 extern int
00657 SyncAppendTaggedNumber(struct ccn_charbuf *cb,
00658                        enum ccn_dtag dtag,
00659                        unsigned val) {
00660     int res = ccnb_tagged_putf(cb, dtag, "%u", val);
00661     return res;
00662 }
00663 
00664 // appends a sequence of random bytes
00665 extern int
00666 SyncAppendRandomBytes(struct ccn_charbuf *cb, int n) {
00667     size_t len = cb->length;
00668     ccn_charbuf_reserve(cb, n);
00669     unsigned char *dst = cb->buf + len;
00670     int i = 0;
00671     while (i < n) {
00672         unsigned int r = random();
00673         dst[i] = (unsigned char) (r & 255);
00674         i++;
00675     }
00676     cb->length = len + n;
00677     return 0;
00678 }
00679 
00680 // appends a random hash code as a ContentHash
00681 extern int
00682 SyncAppendRandomHash(struct ccn_charbuf *cb, int n) {
00683     int res = ccn_charbuf_append_tt(cb, CCN_DTAG_SyncContentHash, CCN_DTAG);
00684     res |= ccn_charbuf_append_tt(cb, n, CCN_BLOB);
00685     res |= SyncAppendRandomBytes(cb, n);
00686     res |= ccn_charbuf_append_closer(cb);
00687     return res;
00688 }
00689 
00690 // appends a random name of nComp random-length components plus a random hash
00691 extern int
00692 SyncAppendRandomName(struct ccn_charbuf *cb, int nComp, int maxCompLen) {
00693     struct ccn_charbuf *rb = ccn_charbuf_create();
00694     int res = ccn_charbuf_append_tt(cb, CCN_DTAG_Name, CCN_DTAG);
00695     res |= ccn_charbuf_append_closer(cb);
00696     while (nComp > 0 && res == 0) {
00697         unsigned nb = random();
00698         nb = (nb % (maxCompLen+1));
00699         ccn_charbuf_reset(rb);
00700         SyncAppendRandomBytes(rb, nb);
00701         res |= ccn_name_append(cb, rb->buf, nb);
00702         nComp--;
00703     }
00704     // always have a hash code as the last component
00705     ccn_charbuf_reset(rb);
00706     res |= SyncAppendRandomBytes(rb, DEFAULT_HASH_BYTES);
00707     res |= ccn_name_append(cb, rb->buf, rb->length);
00708     
00709     ccn_charbuf_destroy(&rb);
00710     
00711     return res;
00712 }
00713 
00714 // appendElementInner appends the ccnb encoding from the decoder to the cb output
00715 // types supported: CCN_DTAG_Name, CCN_DTAG_SyncContentHash, CCN_DTAG_BinaryValue
00716 // any error returns < 0
00717 // this routine advances the decoder!
00718 extern int
00719 SyncAppendElementInner(struct ccn_charbuf *cb, struct ccn_buf_decoder *d) {
00720     int res = 0;
00721     int src = 0;
00722     if (ccn_buf_match_dtag(d, CCN_DTAG_Name)) {
00723         ccn_buf_advance(d);
00724         int res = ccn_charbuf_append_tt(cb, CCN_DTAG_Name, CCN_DTAG);
00725         res |= ccn_charbuf_append_closer(cb);
00726         while (ccn_buf_match_dtag(d, CCN_DTAG_Component)) {
00727             const unsigned char *cPtr = NULL;
00728             size_t cSize = 0;
00729             ccn_buf_advance(d);
00730             if (ccn_buf_match_blob(d, &cPtr, &cSize)) ccn_buf_advance(d);
00731             res |= ccn_name_append(cb, cPtr, cSize);
00732             ccn_buf_check_close(d);
00733         }
00734         ccn_buf_check_close(d);
00735     } else if (ccn_buf_match_dtag(d, CCN_DTAG_SyncContentHash)) {
00736         const unsigned char *cPtr = NULL;
00737         size_t cSize = 0;
00738         ccn_buf_advance(d);
00739         if (ccn_buf_match_blob(d, &cPtr, &cSize)) ccn_buf_advance(d);
00740         res |= ccnb_append_tagged_blob(cb, CCN_DTAG_SyncContentHash, cPtr, cSize);
00741     } else if (ccn_buf_match_dtag(d, CCN_DTAG_BinaryValue)) {
00742         const unsigned char *cPtr = NULL;
00743         size_t cSize = 0;
00744         ccn_buf_advance(d);
00745         if (ccn_buf_match_blob(d, &cPtr, &cSize)) ccn_buf_advance(d);
00746         res |= ccnb_append_tagged_blob(cb, CCN_DTAG_BinaryValue, cPtr, cSize);
00747     } else res = -__LINE__;
00748     if (SyncCheckDecodeErr(d)) src = -__LINE__;
00749     if (res == 0) res = src;
00750     return res;
00751 }
00752 
00753 // appendElement appends the ccnb encoding from the src to the dst
00754 // types supported: CCN_DTAG_Name, CCN_DTAG_SyncContentHash, CCN_DTAG_BinaryValue
00755 // any error returns < 0
00756 extern int
00757 SyncAppendElement(struct ccn_charbuf *dst, const struct ccn_charbuf *src) {
00758     struct ccn_buf_decoder ds;
00759     struct ccn_buf_decoder *d = SyncInitDecoderFromCharbuf(&ds, src, 0);
00760     int res = SyncAppendElementInner(dst, d);
00761     return res;
00762 }
00763 
00764 extern struct ccn_charbuf *
00765 SyncExtractName(struct ccn_buf_decoder *d) {
00766     struct ccn_charbuf *name = NULL;
00767     if (ccn_buf_match_dtag(d, CCN_DTAG_Name)) {
00768         name = ccn_charbuf_create();
00769         int res = SyncAppendElementInner(name, d);
00770         if (res < 0) {
00771             // parse error, so get rid of the buffer
00772             ccn_charbuf_destroy(&name);
00773             SyncSetDecodeErr(d, -__LINE__);
00774         }
00775     } else
00776         SyncSetDecodeErr(d, -__LINE__);
00777     return name;
00778 }
00779 
00780 extern struct ccn_charbuf *
00781 SyncCopyName(const struct ccn_charbuf *name) {
00782     struct ccn_charbuf *ret = ccn_charbuf_create();
00783     ccn_charbuf_append_charbuf(ret, name);
00784     return ret;
00785 }
00786 
00787 ///////////////////////////////////////////////////////
00788 // Routines for simple parsing
00789 ///////////////////////////////////////////////////////
00790 
00791 extern unsigned
00792 SyncParseUnsigned(struct ccn_buf_decoder *d, enum ccn_dtag dtag) {
00793     uintmax_t val = 0;
00794     if (ccn_buf_match_dtag(d, dtag)) {
00795         ccn_buf_advance(d);
00796         if (ccn_parse_uintmax(d, &val) >= 0) {
00797             ccn_buf_check_close(d);
00798             if (SyncCheckDecodeErr(d) == 0)
00799                 return val;
00800         }
00801     }
00802     SET_ERR(d);
00803     return val;
00804 }
00805 
00806 extern ssize_t
00807 SyncParseHash(struct ccn_buf_decoder *d) {
00808     ssize_t off = d->decoder.token_index;
00809     ccn_parse_required_tagged_BLOB(d, CCN_DTAG_SyncContentHash, 0, MAX_HASH_BYTES);
00810     return off;
00811 }
00812 
00813 extern ssize_t
00814 SyncParseName(struct ccn_buf_decoder *d) {
00815     ssize_t off = d->decoder.token_index;
00816     if (ccn_buf_match_dtag(d, CCN_DTAG_Name)) {
00817         ccn_buf_advance(d);
00818         while (ccn_buf_match_dtag(d, CCN_DTAG_Component)) {
00819             ccn_buf_advance(d);
00820             if (ccn_buf_match_blob(d, NULL, NULL)) ccn_buf_advance(d);
00821             ccn_buf_check_close(d);
00822         }
00823         ccn_buf_check_close(d);
00824     } else SET_ERR(d);
00825     return off;
00826 }
00827 
00828 ////////////////////////////////////////
00829 // Name and Node Accumulators
00830 ////////////////////////////////////////
00831 
00832 extern struct SyncNameAccum *
00833 SyncAllocNameAccum(int lim) {
00834     struct SyncNameAccum *na = NEW_STRUCT(1, SyncNameAccum);
00835     if (lim < 4) lim = 4;
00836     na->lim = lim;
00837     na->ents = NEW_STRUCT(lim, SyncNameAccumEntry);
00838     return na;
00839 }
00840 
00841 extern struct SyncNameAccum *
00842 SyncFreeNameAccum(struct SyncNameAccum *na) {
00843     if (na != NULL) {
00844         if (na->ents != NULL) free(na->ents);
00845         free(na);
00846     }
00847     return NULL;
00848 }
00849 
00850 extern struct SyncNameAccum *
00851 SyncFreeNameAccumAndNames(struct SyncNameAccum *na) {
00852     if (na != NULL) {
00853         if (na->ents != NULL) {
00854             int i = 0;
00855             for (i = 0; i < na->len; i++) {
00856                 struct ccn_charbuf *name = na->ents[i].name;
00857                 if (name != NULL) {
00858                     ccn_charbuf_destroy(&name);
00859                     na->ents[i].name = NULL;
00860                 }
00861             }
00862             free(na->ents);
00863             na->ents = NULL;
00864         }
00865         free(na);
00866     }
00867     return NULL;
00868 }
00869 
00870 extern int
00871 SyncNameAccumSorter(IndexSorter_Base base,
00872                     IndexSorter_Index x, IndexSorter_Index y) {
00873     struct SyncNameAccum *na = (struct SyncNameAccum *) base->client;
00874     IndexSorter_Index len = na->len;
00875     if (x < len && y < len) {
00876         struct ccn_charbuf *cbx = na->ents[x].name;
00877         struct ccn_charbuf *cby = na->ents[y].name;
00878         int cmp = SyncCmpNames(cbx, cby);
00879         if (cmp != SYNC_BAD_CMP) return cmp;
00880     }
00881     SyncNoteErr("nameAccumSorter");
00882     return 0;
00883 }
00884 
00885 extern int
00886 SyncNameAccumAppend(struct SyncNameAccum *na,
00887                     struct ccn_charbuf *name,
00888                     intmax_t data) {
00889     if (name == NULL || name->length == 0)
00890         SyncNoteErr("SyncNameAccumAppend");
00891 
00892     struct SyncNameAccumEntry *ents = na->ents;
00893     int len = na->len;
00894     if (len == na->lim) {
00895         // expand the storage
00896         int newLim = na->lim + na->lim/2 + 4;
00897         struct SyncNameAccumEntry *newEnts = NEW_STRUCT(newLim, SyncNameAccumEntry);
00898         memcpy(newEnts, ents, len*sizeof(struct SyncNameAccumEntry));
00899         free(ents);
00900         na->lim = newLim;
00901         ents = newEnts;
00902         na->ents = newEnts;
00903     }
00904     ents[len].name = name;
00905     ents[len].data = data;
00906     na->len = len + 1;
00907     return 1;
00908 }
00909 
00910 extern struct ccn_charbuf *
00911 SyncNameAccumCanon(struct SyncNameAccum *na,
00912                    const struct ccn_charbuf *name) {
00913     struct ccn_charbuf *found = NULL;
00914     int i = 0;
00915     // scan for an existing name
00916     for (i = 0; i < na->len; i++) {
00917         int cmp = SyncCmpNames(name, na->ents[i].name);
00918         if (cmp == 0) {
00919             // existing name found, bump the count
00920             found = na->ents[i].name;
00921             na->ents[i].data++;
00922             break;
00923         }
00924     }
00925     if (found == NULL) {
00926         // make a new one and append it
00927         found = ccn_charbuf_create();
00928         ccn_charbuf_append_charbuf(found, name);
00929         SyncNameAccumAppend(na, found, 1);
00930     }
00931     return found;
00932 }
00933 
00934 extern struct SyncNodeAccum *
00935 SyncAllocNodeAccum(int lim) {
00936     struct SyncNodeAccum *na = NEW_STRUCT(1, SyncNodeAccum);
00937     if (lim < 4) lim = 4;
00938     na->lim = lim;
00939     na->ents = NEW_ANY(lim, struct SyncNodeComposite *);
00940     return na;
00941 }
00942 
00943 extern struct SyncNodeAccum *
00944 SyncFreeNodeAccum(struct SyncNodeAccum *na) {
00945     if (na != NULL) {
00946         if (na->ents != NULL) free(na->ents);
00947         free(na);
00948     }
00949     return NULL;
00950 }
00951 
00952 extern void
00953 SyncAccumNode(struct SyncNodeAccum *na, struct SyncNodeComposite *nc) {
00954     struct SyncNodeComposite **ents = na->ents;
00955     int len = na->len;
00956     if (len == na->lim) {
00957         // expand the storage
00958         int newLim = na->lim + na->lim/2 + 4;
00959         struct SyncNodeComposite **newEnts = NEW_ANY(newLim,
00960                                                      struct SyncNodeComposite *);
00961         memcpy(newEnts, ents, len*sizeof(struct SyncNodeComposite *));
00962         free(ents);
00963         na->lim = newLim;
00964         ents = newEnts;
00965         na->ents = newEnts;
00966     }
00967     ents[len] = nc;
00968     na->len = len + 1;
00969 }
00970 
00971 ///////////////////////////////////////////////////////
00972 // Routines for simple interest creation
00973 ///////////////////////////////////////////////////////
00974 
00975 static int
00976 appendLifetime(struct ccn_charbuf *cb, int lifetime) {
00977     unsigned char buf[sizeof(int32_t)];
00978     int32_t dreck = lifetime << 12;
00979     int pos = sizeof(int32_t);
00980     int res = 0;
00981     while (dreck > 0 && pos > 0) {
00982         pos--;
00983         buf[pos] = dreck & 255;
00984         dreck = dreck >> 8;
00985     }
00986     res |= ccnb_append_tagged_blob(cb, CCN_DTAG_InterestLifetime,
00987                                    buf+pos, sizeof(buf)-pos);
00988     return res;
00989 }
00990 
00991 static int
00992 appendExclusions(struct ccn_charbuf *cb, struct SyncNameAccum *excl) {
00993     if (excl != NULL) {
00994         int i = 0;
00995         ccn_charbuf_append_tt(cb, CCN_DTAG_Exclude, CCN_DTAG);
00996         for (i = 0; i < excl->len; i++) {
00997             struct ccn_charbuf *name = excl->ents[i].name;
00998             // append just the first component
00999             struct ccn_buf_decoder ds;
01000             struct ccn_buf_decoder *d = SyncInitDecoderFromCharbuf(&ds, name, 0);
01001             size_t cSize = 0;
01002             if (ccn_buf_match_dtag(d, CCN_DTAG_Name)) {
01003                 ccn_buf_advance(d);
01004                 if (ccn_buf_match_dtag(d, CCN_DTAG_Component)) {
01005                     ccn_buf_advance(d);
01006                     const unsigned char *cPtr = NULL;
01007                     if (ccn_buf_match_blob(d, &cPtr, &cSize)) {
01008                         ccn_buf_advance(d);
01009                         ccnb_append_tagged_blob(cb, CCN_DTAG_Component, cPtr, cSize);
01010                     }
01011                 }
01012             }
01013             if (cSize == 0) return -__LINE__;
01014         }
01015         ccn_charbuf_append_closer(cb); /* </Exclude> */
01016         return 1;
01017     }
01018     return 0;
01019 }
01020 
01021 extern struct ccn_charbuf *
01022 SyncGenInterest(struct ccn_charbuf *name,
01023                 int scope, int lifetime, int maxSuffix, int childPref,
01024                 struct SyncNameAccum *excl) {
01025     struct ccn_charbuf *cb = ccn_charbuf_create();
01026     ccn_charbuf_append_tt(cb, CCN_DTAG_Interest, CCN_DTAG);
01027     int res = 0;
01028     if (name == NULL) {
01029         res |= ccn_charbuf_append_tt(cb, CCN_DTAG_Name, CCN_DTAG);
01030         res |= ccn_charbuf_append_closer(cb); /* </Name> */
01031     } else {
01032         ccn_charbuf_append_charbuf(cb, name);
01033     }
01034     if (maxSuffix >= 0)
01035         ccnb_tagged_putf(cb, CCN_DTAG_MaxSuffixComponents, "%d", maxSuffix);
01036     res |= appendExclusions(cb, excl);
01037     if (childPref >= 0)
01038         // low bit determines least/most preference
01039         ccnb_tagged_putf(cb, CCN_DTAG_ChildSelector, "%d", childPref);
01040     if (scope >= 0)
01041         ccnb_tagged_putf(cb, CCN_DTAG_Scope, "%d", scope);
01042     if (lifetime > 0)
01043         appendLifetime(cb, lifetime);
01044     ccn_charbuf_append_closer(cb); /* </Interest> */
01045     if (res < 0) {
01046         ccn_charbuf_destroy(&cb);
01047     }
01048     return cb;
01049 }
01050 
01051 ///////////////////////////////////////////////////////
01052 // Routines for local repo read/write
01053 ///////////////////////////////////////////////////////
01054 
01055 #define UseLocalTopoPrefix 1
01056 extern struct ccn_charbuf *
01057 SyncNameForLocalNode(struct SyncRootStruct *root, struct ccn_charbuf *hash) {
01058     // form the name of the node
01059     // use the NodeFetch convention, but at the local host
01060     struct ccn_charbuf *sh = root->sliceHash;
01061     struct ccn_charbuf *nm = ccn_charbuf_create();
01062     int res = 0;
01063 #ifdef UseLocalTopoPrefix
01064     // new method used root->topoPrefix
01065     res |= ccn_charbuf_append_charbuf(nm, root->topoPrefix);
01066 #else    
01067     // old method used localhost instead of topoPrefix
01068      res |= ccn_name_init(nm);
01069      res |= ccn_name_append_str(nm, "\xC1.M.S.localhost");
01070 #endif
01071     res |= ccn_name_append_str(nm, "\xC1.S.nf");
01072     res |= ccn_name_append(nm, sh->buf, sh->length);
01073     res |= ccn_name_append(nm, hash->buf, hash->length);
01074     if (res < 0) ccn_charbuf_destroy(&nm);
01075     return nm;
01076 }
01077 
01078 extern int
01079 SyncPointerToContent(struct ccn_charbuf *cb, struct ccn_parsed_ContentObject *pco,
01080                      const unsigned char **xp, size_t *xs) {
01081     struct ccn_parsed_ContentObject pcos;
01082     int res = 0;
01083     if (pco == NULL) {
01084         // not already parsed, so do it now
01085         pco = &pcos;
01086         res = ccn_parse_ContentObject(cb->buf, cb->length,
01087                                       pco, NULL);
01088     }
01089     if (res >= 0)
01090         // worth trying to extract the content
01091         res = ccn_content_get_value(cb->buf, cb->length, pco, xp, xs);
01092     return res;
01093 }
01094 
01095 extern struct ccn_charbuf *
01096 SyncSignBuf(struct SyncBaseStruct *base,
01097             struct ccn_charbuf *cb,
01098             struct ccn_charbuf *name,
01099             long fresh, int flags) {
01100     struct ccn_charbuf *cob = ccn_charbuf_create();
01101     struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT;
01102     
01103     if (cb != NULL) {
01104         // signing content, will put as data
01105         sp.type = CCN_CONTENT_DATA;
01106     } else {
01107         // cb == NULL requests deletion
01108         cb = ccn_charbuf_create();
01109         sp.type = CCN_CONTENT_GONE;
01110     }
01111     sp.sp_flags |= flags;
01112     
01113     if (fresh > 0 && fresh <= freshLimit) {
01114         sp.template_ccnb = ccn_charbuf_create();
01115         ccn_charbuf_append_tt(sp.template_ccnb, CCN_DTAG_SignedInfo, CCN_DTAG);
01116         ccnb_tagged_putf(sp.template_ccnb, CCN_DTAG_FreshnessSeconds, "%ld", fresh);
01117         sp.sp_flags |= CCN_SP_TEMPL_FRESHNESS;
01118         ccn_charbuf_append_closer(sp.template_ccnb);
01119     }
01120     
01121     int res = ccn_sign_content(base->ccn,
01122                                cob,
01123                                name,
01124                                &sp,
01125                                cb->buf,
01126                                cb->length);
01127     
01128     if (sp.template_ccnb != NULL) 
01129         ccn_charbuf_destroy(&sp.template_ccnb);
01130     if (sp.type == CCN_CONTENT_GONE)
01131         ccn_charbuf_destroy(&cb);
01132     if (res < 0) {
01133         // it did not work, so return the output buffer
01134         ccn_charbuf_destroy(&cob);
01135         return NULL;
01136     }
01137     return cob;
01138 }
01139 
01140 extern int
01141 SyncLocalRepoStore(struct SyncBaseStruct *base,
01142                    struct ccn_charbuf *name,
01143                    struct ccn_charbuf *content,
01144                    int flags) {
01145     char *here = "Sync.SyncLocalRepoStore";
01146     int res = -__LINE__;
01147     struct ccn_charbuf *cob = SyncSignBuf(base, content, name, -1, flags);
01148     char *why = NULL;
01149     if (cob == NULL)
01150         why = "signing failed";
01151     else {
01152         res = r_sync_local_store(base->client_handle, cob);
01153         if (res < 0) why = "store failed";
01154         ccn_charbuf_destroy(&cob);
01155     }
01156     if (why != NULL)
01157         if (base->debug >= CCNL_ERROR)
01158             SyncNoteUriBase(base, here, why, name);
01159     return res;
01160 }
01161 
01162 extern int
01163 SyncLocalRepoFetch(struct SyncBaseStruct *base,
01164                    struct ccn_charbuf *name,
01165                    struct ccn_charbuf *cb,
01166                    struct ccn_parsed_ContentObject *pco) {
01167     char *here = "Sync.SyncLocalRepoFetch";
01168     struct ccnr_handle *ccnr = base->client_handle;
01169     struct ccn_charbuf *interest = SyncGenInterest(name, 1, 1, -1, 1, NULL);
01170     struct ccn_parsed_ContentObject pcos;
01171     if (pco == NULL) pco = &pcos;
01172     if (interest == NULL) return -__LINE__;
01173     int res = r_sync_lookup(ccnr, interest, cb);
01174     char *why = NULL;
01175     ccn_charbuf_destroy(&interest);
01176     if (res < 0) why = "fetch failed";
01177     else {
01178         res = ccn_parse_ContentObject(cb->buf, cb->length, pco, NULL);
01179         if (res < 0) why = "parse failed";
01180         else {
01181             res = ccn_verify_content(base->ccn, cb->buf, pco);
01182             if (res < 0) why = "verify failed";
01183         }
01184     }
01185     if (why != NULL)
01186         if (base->debug >= CCNL_ERROR)
01187             SyncNoteUriBase(base, here, why, name);
01188     return res;
01189 }
01190 
01191 
01192 
Generated on Tue Aug 21 14:54:19 2012 for Content-Centric Networking in C by  doxygen 1.6.3