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