00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <stdlib.h>
00021 #include <string.h>
00022 #include <strings.h>
00023
00024 #include <ccn/ccn.h>
00025 #include <ccn/charbuf.h>
00026 #include <ccn/coding.h>
00027 #include <ccn/digest.h>
00028 #include <ccn/indexbuf.h>
00029 #include <ccn/schedule.h>
00030 #include <ccnr/ccnr_msg.h>
00031
00032 #include "SyncPrivate.h"
00033 #include "SyncActions.h"
00034 #include "SyncHashCache.h"
00035 #include "SyncUtil.h"
00036 #include "SyncRoot.h"
00037
00038
00039
00040
00041
00042
00043
00044
00045 static struct SyncNameAccum *
00046 copyFilter(struct SyncNameAccum *filter) {
00047 int i = 0;
00048 int len = filter->len;
00049 struct SyncNameAccum *canon = SyncAllocNameAccum(len);
00050 for (i = 0; i < len; i++) {
00051 struct ccn_charbuf *name = filter->ents[i].name;
00052 struct ccn_charbuf *copy = ccn_charbuf_create();
00053 ccn_charbuf_append_charbuf(copy, name);
00054 canon->ents[i].name = copy;
00055 canon->ents[i].data = filter->ents[i].data;
00056
00057 }
00058 canon->len = len;
00059 return canon;
00060 }
00061
00062
00063
00064
00065
00066
00067 static struct SyncNameAccum *
00068 canonFilter(struct SyncBaseStruct *base, struct SyncNameAccum *filter) {
00069 struct SyncPrivate *priv = base->priv;
00070 struct SyncNameAccumList *filters = priv->filters;
00071 while (filters != NULL) {
00072 struct SyncNameAccum *accum = filters->accum;
00073 if (accum != NULL) {
00074 if (accum->len == filter->len) {
00075 int i = 0;
00076 int equal = 1;
00077 while (i < filter->len) {
00078 struct ccn_charbuf *x = filter->ents[i].name;
00079 struct ccn_charbuf *y = accum->ents[i].name;
00080 if (SyncCmpNames(x, y) != 0) {
00081 equal = 0;
00082 break;
00083 }
00084 i++;
00085 }
00086 if (equal)
00087
00088 return accum;
00089 }
00090 }
00091 filters = filters->next;
00092 }
00093
00094 struct SyncNameAccum *canon = copyFilter(filter);
00095 filters = NEW_STRUCT(1, SyncNameAccumList);
00096 filters->next = priv->filters;
00097 priv->filters = filters;
00098 filters->accum = canon;
00099 return canon;
00100 }
00101
00102 extern struct SyncRootStruct *
00103 SyncAddRoot(struct SyncBaseStruct *base,
00104 const struct ccn_charbuf *topoPrefix,
00105 const struct ccn_charbuf *namingPrefix,
00106 struct SyncNameAccum *filter) {
00107 struct SyncRootStruct *root = NEW_STRUCT(1, SyncRootStruct);
00108 struct SyncPrivate *priv = base->priv;
00109 int newTopo = 0;
00110 root->base = base;
00111 root->priv = NEW_STRUCT(1, SyncRootPrivate);
00112 root->priv->stats = NEW_STRUCT(1, SyncRootStats);
00113 sync_time now = SyncCurrentTime();
00114 root->priv->lastAdvise = now;
00115 root->priv->lastUpdate = now;
00116 root->priv->stablePoint = CCNR_NULL_HWM;
00117 root->priv->lastUpdate = CCNR_NULL_HWM;
00118 root->priv->sliceBusy = -1;
00119 base->lastRootId++;
00120 root->rootId = base->lastRootId;
00121 if (topoPrefix != NULL) {
00122 int oldLen = priv->topoAccum->len;
00123 root->topoPrefix = SyncNameAccumCanon(priv->topoAccum, topoPrefix);
00124 if (oldLen < priv->topoAccum->len) newTopo++;
00125 }
00126 if (namingPrefix != NULL) {
00127 root->namingPrefix = SyncNameAccumCanon(priv->prefixAccum, namingPrefix);
00128 }
00129 if (filter != NULL) {
00130 root->filter = canonFilter(base, filter);
00131 }
00132 struct SyncRootStruct *lag = priv->rootHead;
00133 while (lag != NULL) {
00134 struct SyncRootStruct *next = lag->next;
00135 if (next == NULL) break;
00136 lag = next;
00137 }
00138 if (lag != NULL) lag->next = root;
00139 else priv->rootHead = root;
00140 priv->nRoots++;
00141 struct SyncHashCacheHead *ch = SyncHashCacheCreate(root, 64);
00142 root->ch = ch;
00143 root->currentHash = ccn_charbuf_create();
00144
00145
00146 root->namesToAdd = SyncAllocNameAccum(0);
00147 root->namesToFetch = SyncAllocNameAccum(0);
00148
00149 root->sliceCoding = ccn_charbuf_create();
00150 root->sliceHash = ccn_charbuf_create();
00151 if (SyncRootAppendSlice(root->sliceCoding, root) >= 0) {
00152
00153 struct ccn_digest *cow = ccn_digest_create(CCN_DIGEST_DEFAULT);
00154 size_t sz = ccn_digest_size(cow);
00155 unsigned char *dst = ccn_charbuf_reserve(root->sliceHash, sz);
00156 ccn_digest_init(cow);
00157 ccn_digest_update(cow, root->sliceCoding->buf, root->sliceCoding->length);
00158 ccn_digest_final(cow, dst, sz);
00159 root->sliceHash->length = sz;
00160 ccn_digest_destroy(&cow);
00161 }
00162
00163 SyncRegisterInterests(root);
00164 return root;
00165 }
00166
00167 extern struct SyncRootStruct *
00168 SyncRemRoot(struct SyncRootStruct *root) {
00169 if (root == NULL || root->base == NULL || root->compare != NULL)
00170
00171 return root;
00172 struct SyncActionData *actions = root->actions;
00173 root->actions = NULL;
00174 while (actions != NULL) {
00175
00176 struct SyncActionData *next = actions->next;
00177 actions->root = NULL;
00178 actions->next = NULL;
00179 actions = next;
00180 }
00181 struct SyncBaseStruct *base = root->base;
00182 struct SyncPrivate *priv = base->priv;
00183 struct SyncRootStruct *lag = NULL;
00184 struct SyncRootStruct *this = priv->rootHead;
00185 while (this != NULL) {
00186 struct SyncRootStruct *next = this->next;
00187 if (this == root) {
00188 struct SyncRootPrivate *rp = root->priv;
00189 if (lag != NULL) lag->next = next;
00190 else priv->rootHead = next;
00191 if (root->ch != NULL)
00192 root->ch = SyncHashCacheFree(root->ch);
00193 if (root->currentHash != NULL)
00194 ccn_charbuf_destroy(&root->currentHash);
00195 if (root->namesToAdd != NULL)
00196 SyncFreeNameAccumAndNames(root->namesToAdd);
00197 if (root->namesToFetch != NULL)
00198 SyncFreeNameAccumAndNames(root->namesToFetch);
00199 if (root->sliceCoding != NULL)
00200 ccn_charbuf_destroy(&root->sliceCoding);
00201 if (root->sliceHash != NULL)
00202 ccn_charbuf_destroy(&root->sliceHash);
00203 if (rp != NULL) {
00204 if (rp->stats != NULL) free(rp->stats);
00205 struct SyncHashInfoList *list = rp->remoteSeen;
00206 while (list != NULL) {
00207 struct SyncHashInfoList *lag = list;
00208 list = list->next;
00209 free(lag);
00210 }
00211 free(rp);
00212 }
00213 free(root);
00214 priv->nRoots--;
00215 break;
00216 }
00217 lag = this;
00218 this = next;
00219 }
00220 return NULL;
00221 }
00222
00223 extern struct SyncRootStruct *
00224 SyncRootDecodeAndAdd(struct SyncBaseStruct *base,
00225 struct ccn_buf_decoder *d) {
00226 struct SyncRootStruct *root = NULL;
00227 if (ccn_buf_match_dtag(d, CCN_DTAG_SyncConfigSlice)) {
00228 int oops = 0;
00229 ccn_buf_advance(d);
00230 uintmax_t vers = SyncParseUnsigned(d, CCN_DTAG_SyncVersion);
00231 if (vers == SLICE_VERSION) {
00232 struct ccn_charbuf *topo = SyncExtractName(d);
00233 struct ccn_charbuf *prefix = SyncExtractName(d);
00234 struct SyncNameAccum *filter = SyncAllocNameAccum(4);
00235 if (ccn_buf_match_dtag(d, CCN_DTAG_SyncConfigSliceList)) {
00236 ccn_buf_advance(d);
00237 while (ccn_buf_match_dtag(d, CCN_DTAG_SyncConfigSliceOp)) {
00238 uintmax_t op = SyncParseUnsigned(d, CCN_DTAG_SyncConfigSliceOp);
00239 struct ccn_charbuf *clause = SyncExtractName(d);
00240 if (op != 0 || clause == NULL) {
00241 oops++;
00242 break;
00243 }
00244 SyncNameAccumAppend(filter, clause, op);
00245 }
00246 ccn_buf_check_close(d);
00247 if (SyncCheckDecodeErr(d)) oops++;
00248 }
00249 ccn_buf_check_close(d);
00250 if (SyncCheckDecodeErr(d)) oops++;
00251 if (oops == 0) {
00252 root = SyncAddRoot(base, topo, prefix, filter);
00253 }
00254
00255 if (topo != NULL) ccn_charbuf_destroy(&topo);
00256 if (prefix != NULL) ccn_charbuf_destroy(&prefix);
00257 if (filter != NULL) SyncFreeNameAccumAndNames(filter);
00258 }
00259 }
00260 return root;
00261 }
00262
00263 static int
00264 appendName(struct ccn_charbuf *cb, struct ccn_charbuf *name) {
00265
00266
00267 int res = 0;
00268 if (name == NULL) {
00269 name = ccn_charbuf_create();
00270 ccn_name_init(name);
00271 res |= ccn_charbuf_append_charbuf(cb, name);
00272 ccn_charbuf_destroy(&name);
00273 } else
00274 res |= ccn_charbuf_append_charbuf(cb, name);
00275 return res;
00276 }
00277
00278 extern int
00279 SyncRootAppendSlice(struct ccn_charbuf *cb, struct SyncRootStruct *root) {
00280 int res = 0;
00281 res |= ccnb_element_begin(cb, CCN_DTAG_SyncConfigSlice);
00282 res |= SyncAppendTaggedNumber(cb, CCN_DTAG_SyncVersion, SLICE_VERSION);
00283 res |= appendName(cb, root->topoPrefix);
00284 res |= appendName(cb, root->namingPrefix);
00285 res |= ccnb_element_begin(cb, CCN_DTAG_SyncConfigSliceList);
00286 struct SyncNameAccum *filter = root->filter;
00287 if (res >= 0 && filter != NULL) {
00288 int i = 0;
00289 for (i = 0; i < filter->len; i++) {
00290 struct ccn_charbuf *clause = filter->ents[i].name;
00291 res |= SyncAppendTaggedNumber(cb, CCN_DTAG_SyncConfigSliceOp, 0);
00292 res |= ccn_charbuf_append_charbuf(cb, clause);
00293 if (res < 0) break;
00294 }
00295 }
00296 res |= ccnb_element_end(cb);
00297 res |= ccnb_element_end(cb);
00298 return res;
00299 }
00300
00301 extern struct SyncHashCacheEntry *
00302 SyncRootTopEntry(struct SyncRootStruct *root) {
00303 if (root->currentHash->length > 0) {
00304 struct ccn_charbuf *hash = root->currentHash;
00305 struct SyncHashCacheEntry *ent = SyncHashLookup(root->ch,
00306 hash->buf,
00307 hash->length);
00308 return ent;
00309 }
00310 return NULL;
00311 }
00312
00313 extern enum SyncRootLookupCode
00314 SyncRootLookupName(struct SyncRootStruct *root,
00315 const struct ccn_charbuf *name) {
00316 int skip = 0;
00317 if (name == NULL)
00318
00319 return SyncRootLookupCode_error;
00320 if (root->namingPrefix != NULL) {
00321 skip = SyncPrefixMatch(root->namingPrefix, name, 0);
00322 if (skip < 0) return SyncRootLookupCode_error;
00323 if (skip == 0) return SyncRootLookupCode_none;
00324 }
00325 skip = SyncComponentCount(root->namingPrefix);
00326 enum SyncRootLookupCode res = SyncRootLookupCode_covered;
00327 struct SyncNameAccum *filter = root->filter;
00328 if (filter != NULL && filter->len > 0) {
00329
00330 int i = 0;
00331 res = SyncRootLookupCode_none;
00332 for (i = 0; i < filter->len; i++) {
00333 struct ccn_charbuf *pat = filter->ents[i].name;
00334 int match = SyncPatternMatch(pat, name, skip);
00335 if (match < 0) {
00336 res = SyncRootLookupCode_error;
00337 break;
00338 }
00339 if (match > 0) {
00340 res = SyncRootLookupCode_covered;
00341 break;
00342 }
00343 }
00344 if (res == SyncRootLookupCode_none && root->base->debug > 16) {
00345 struct ccn_charbuf *uri = ccn_charbuf_create();
00346 ccn_uri_append(uri, name->buf, name->length, 0);
00347 char *str = ccn_charbuf_as_string(uri);
00348 ccnr_msg(root->base->ccnr, "SyncRootLookupName, rejected %s", str);
00349 ccn_charbuf_destroy(&uri);
00350 }
00351 }
00352 return res;
00353 }
00354
00355