00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <errno.h>
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023 #include <string.h>
00024 #include <unistd.h>
00025 #include <ccn/bloom.h>
00026 #include <ccn/ccn.h>
00027 #include <ccn/charbuf.h>
00028 #include <ccn/uri.h>
00029 #include <ccn/ccn_private.h>
00030
00031 #define FF 0xff
00032
00033
00034
00035
00036
00037 static void
00038 append_filter_all(struct ccn_charbuf *c)
00039 {
00040 ccn_charbuf_append_tt(c, CCN_DTAG_Any, CCN_DTAG);
00041 ccn_charbuf_append_closer(c);
00042 }
00043
00044
00045
00046
00047
00048 static void
00049 answer_passive(struct ccn_charbuf *templ)
00050 {
00051 ccn_charbuf_append_tt(templ, CCN_DTAG_AnswerOriginKind, CCN_DTAG);
00052 ccn_charbuf_append_tt(templ, 1, CCN_UDATA);
00053 ccn_charbuf_append(templ, "1", 1);
00054 ccn_charbuf_append_closer(templ);
00055 }
00056
00057
00058
00059
00060
00061 static void
00062 answer_highest(struct ccn_charbuf *templ)
00063 {
00064 ccnb_tagged_putf(templ, CCN_DTAG_ChildSelector, "1");
00065 }
00066
00067 static void
00068 append_future_vcomp(struct ccn_charbuf *templ)
00069 {
00070
00071 unsigned char b[7] = {CCN_MARKER_VERSION + 1, 0, 0, 0, 0, 0, 0};
00072 ccn_charbuf_append_tt(templ, CCN_DTAG_Component, CCN_DTAG);
00073 ccn_charbuf_append_tt(templ, sizeof(b), CCN_BLOB);
00074 ccn_charbuf_append(templ, b, sizeof(b));
00075 ccn_charbuf_append_closer(templ);
00076 }
00077
00078 static struct ccn_charbuf *
00079 resolve_templ(struct ccn_charbuf *templ, unsigned const char *vcomp, int size)
00080 {
00081 if (templ == NULL)
00082 templ = ccn_charbuf_create();
00083 if (size < 3 || size > 16) {
00084 ccn_charbuf_destroy(&templ);
00085 return(NULL);
00086 }
00087 templ->length = 0;
00088 ccn_charbuf_append_tt(templ, CCN_DTAG_Interest, CCN_DTAG);
00089 ccn_charbuf_append_tt(templ, CCN_DTAG_Name, CCN_DTAG);
00090 ccn_charbuf_append_closer(templ);
00091 ccn_charbuf_append_tt(templ, CCN_DTAG_Exclude, CCN_DTAG);
00092 append_filter_all(templ);
00093 ccn_charbuf_append_tt(templ, CCN_DTAG_Component, CCN_DTAG);
00094 ccn_charbuf_append_tt(templ, size, CCN_BLOB);
00095 ccn_charbuf_append(templ, vcomp, size);
00096 ccn_charbuf_append_closer(templ);
00097 append_future_vcomp(templ);
00098 append_filter_all(templ);
00099 ccn_charbuf_append_closer(templ);
00100 answer_highest(templ);
00101 answer_passive(templ);
00102 ccn_charbuf_append_closer(templ);
00103 return(templ);
00104 }
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123 int
00124 ccn_resolve_version(struct ccn *h, struct ccn_charbuf *name,
00125 int versioning_flags, int timeout_ms)
00126 {
00127 int res;
00128 int myres = -1;
00129 struct ccn_parsed_ContentObject pco_space = { 0 };
00130 struct ccn_charbuf *templ = NULL;
00131 struct ccn_charbuf *prefix = ccn_charbuf_create();
00132 struct ccn_charbuf *cobj = ccn_charbuf_create();
00133 struct ccn_parsed_ContentObject *pco = &pco_space;
00134 struct ccn_indexbuf *ndx = ccn_indexbuf_create();
00135 const unsigned char *vers = NULL;
00136 size_t vers_size = 0;
00137 int n;
00138 struct ccn_indexbuf *nix = ccn_indexbuf_create();
00139 unsigned char lowtime[7] = {CCN_MARKER_VERSION, 0, FF, FF, FF, FF, FF};
00140
00141 if ((versioning_flags & ~CCN_V_NESTOK & ~CCN_V_EST) != CCN_V_HIGH) {
00142 ccn_seterror(h, EINVAL);
00143 ccn_perror(h, "ccn_resolve_version is only implemented for versioning_flags = CCN_V_HIGH(EST)");
00144 goto Finish;
00145 }
00146 n = ccn_name_split(name, nix);
00147 if (n < 0)
00148 goto Finish;
00149 if ((versioning_flags & CCN_V_NESTOK) == 0) {
00150 res = ccn_name_comp_get(name->buf, nix, n - 1, &vers, &vers_size);
00151 if (res >= 0 && vers_size == 7 && vers[0] == CCN_MARKER_VERSION) {
00152 myres = 0;
00153 goto Finish;
00154 }
00155 }
00156 templ = resolve_templ(templ, lowtime, sizeof(lowtime));
00157 ccn_charbuf_append(prefix, name->buf, name->length);
00158 cobj->length = 0;
00159 res = ccn_get(h, prefix, templ, timeout_ms, cobj, pco, ndx, 0);
00160 while (cobj->length != 0) {
00161 if (pco->type == CCN_CONTENT_NACK)
00162 break;
00163 res = ccn_name_comp_get(cobj->buf, ndx, n, &vers, &vers_size);
00164 if (res < 0)
00165 break;
00166 if (vers_size == 7 && vers[0] == CCN_MARKER_VERSION) {
00167
00168 name->length = 0;
00169 ccn_charbuf_append(name, prefix->buf, prefix->length);
00170 ccn_name_append(name, vers, vers_size);
00171 myres = 0;
00172 if ((versioning_flags & CCN_V_EST) == 0)
00173 break;
00174 templ = resolve_templ(templ, vers, vers_size);
00175 if (templ == NULL) break;
00176 cobj->length = 0;
00177 res = ccn_get(h, prefix, templ, timeout_ms, cobj, pco, ndx,
00178 CCN_GET_NOKEYWAIT);
00179 }
00180 else break;
00181 }
00182 Finish:
00183 ccn_charbuf_destroy(&prefix);
00184 ccn_charbuf_destroy(&cobj);
00185 ccn_indexbuf_destroy(&ndx);
00186 ccn_indexbuf_destroy(&nix);
00187 ccn_charbuf_destroy(&templ);
00188 return(myres);
00189 }
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214 int
00215 ccn_create_version(struct ccn *h, struct ccn_charbuf *name,
00216 int versioning_flags, intmax_t secs, int nsecs)
00217 {
00218 size_t i;
00219 size_t j;
00220 size_t lc = 0;
00221 size_t oc = 0;
00222 int n;
00223 struct ccn_indexbuf *nix = NULL;
00224 int myres = -1;
00225 int already_versioned = 0;
00226 int ok_flags = (CCN_V_REPLACE | CCN_V_HIGH | CCN_V_NOW | CCN_V_NESTOK);
00227
00228
00229 nix = ccn_indexbuf_create();
00230 n = ccn_name_split(name, nix);
00231 if (n < 0)
00232 goto Finish;
00233 if ((versioning_flags & ~ok_flags) != 0)
00234 goto Finish;
00235
00236 if (n >= 1) {
00237 oc = nix->buf[n-1];
00238 lc = nix->buf[n] - oc;
00239 if (lc <= 11 && lc >= 6 && name->buf[oc + 2] == CCN_MARKER_VERSION)
00240 already_versioned = 1;
00241 }
00242 myres = 0;
00243 if (already_versioned &&
00244 (versioning_flags & (CCN_V_REPLACE | CCN_V_NESTOK)) == 0)
00245 goto Finish;
00246 name->length -= 1;
00247 i = name->length;
00248 myres |= ccn_charbuf_append_tt(name, CCN_DTAG_Component, CCN_DTAG);
00249 if ((versioning_flags & CCN_V_NOW) != 0)
00250 myres |= ccnb_append_now_blob(name, CCN_MARKER_VERSION);
00251 else {
00252 myres |= ccnb_append_timestamp_blob(name, CCN_MARKER_VERSION, secs, nsecs);
00253 }
00254 myres |= ccn_charbuf_append_closer(name);
00255 if (myres < 0) {
00256 name->length = i;
00257 goto CloseName;
00258 }
00259 j = name->length;
00260 if (already_versioned && (versioning_flags & CCN_V_REPLACE) != 0) {
00261 oc = nix->buf[n-1];
00262 lc = nix->buf[n] - oc;
00263 if ((versioning_flags & CCN_V_HIGH) != 0 &&
00264 memcmp(name->buf + oc, name->buf + i, j - i) > 0) {
00265
00266 name->length = i;
00267
00268 myres = -1;
00269 goto CloseName;
00270 }
00271 memmove(name->buf + oc, name->buf + i, j - i);
00272 name->length -= lc;
00273 }
00274 CloseName:
00275 myres |= ccn_charbuf_append_closer(name);
00276 Finish:
00277 myres = (myres < 0) ? -1 : 0;
00278 ccn_indexbuf_destroy(&nix);
00279 return(myres);
00280 }