ccn_bulkdata.c
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <assert.h>
00021 #include <stdint.h>
00022 #include <stdlib.h>
00023 #include <string.h>
00024
00025 #include <ccn/bloom.h>
00026 #include <ccn/ccn.h>
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 typedef void ccn_seqfunc(uintmax_t x, void *param,
00043 struct ccn_charbuf *resultbuf);
00044
00045
00046
00047
00048 extern ccn_seqfunc ccn_decimal_seqfunc;
00049 extern ccn_seqfunc ccn_binary_seqfunc;
00050
00051
00052
00053
00054
00055 void
00056 ccn_decimal_seqfunc(uintmax_t x, void *param, struct ccn_charbuf *resultbuf)
00057 {
00058 (void)param;
00059 assert(resultbuf->length == 0);
00060 ccn_charbuf_putf(resultbuf, "%ju", x);
00061 }
00062
00063
00064
00065
00066
00067 void
00068 ccn_binary_seqfunc(uintmax_t x, void *param, struct ccn_charbuf *resultbuf)
00069 {
00070 uintmax_t m;
00071 int n;
00072 unsigned char *b;
00073 (void)param;
00074 for (n = 0, m = 0; x < m; n++)
00075 m = (m << 8) | 0xff;
00076 b = ccn_charbuf_reserve(resultbuf, n + 1);
00077 resultbuf->length = n + 1;
00078 for (; n >= 0; n--, x >>= 8)
00079 b[n] = x & 0xff;
00080 }
00081
00082
00083
00084
00085 struct bulkdata {
00086 ccn_seqfunc *seqfunc;
00087 void *seqfunc_param;
00088 struct pending *first;
00089 struct ccn_closure *client;
00090 uintmax_t next_expected;
00091 struct ccn_charbuf *name_prefix;
00092 int prefix_comps;
00093
00094 };
00095
00096 struct pending {
00097 struct pending *prev;
00098 struct pending *next;
00099 struct bulkdata *parent;
00100 uintmax_t x;
00101 struct ccn_closure closure;
00102 unsigned char *content_ccnb;
00103 size_t content_size;
00104 };
00105
00106 static enum ccn_upcall_res deliver_content(struct ccn *h, struct bulkdata *b);
00107 static void express_bulkdata_interest(struct ccn *h, struct pending *b);
00108
00109
00110
00111
00112 enum ccn_upcall_res
00113 imcoming_bulkdata(struct ccn_closure *selfp,
00114 enum ccn_upcall_kind kind,
00115 struct ccn_upcall_info *info)
00116 {
00117 struct bulkdata *b;
00118 struct pending *p = selfp->data;
00119 enum ccn_upcall_res res = CCN_UPCALL_RESULT_ERR;
00120
00121 assert(selfp == &p->closure);
00122 b = p->parent;
00123
00124 switch (kind) {
00125 case CCN_UPCALL_FINAL:
00126 p->prev->next = p->next->prev;
00127 p->next->prev = p->prev->next;
00128 if (b != NULL && p == b->first)
00129 b->first = (p == p->next) ? NULL : p->next;
00130 if (p->content_ccnb != NULL)
00131 free(p->content_ccnb);
00132 free(p);
00133 return(CCN_UPCALL_RESULT_OK);
00134 case CCN_UPCALL_CONTENT:
00135 case CCN_UPCALL_CONTENT_UNVERIFIED:
00136 case CCN_UPCALL_CONTENT_BAD:
00137
00138 break;
00139 case CCN_UPCALL_INTEREST_TIMED_OUT:
00140
00141 return(CCN_UPCALL_RESULT_REEXPRESS);
00142 default:
00143 return(CCN_UPCALL_RESULT_ERR);
00144 }
00145
00146
00147 if (p->content_ccnb == NULL) {
00148 if (p->x == b->next_expected) {
00149
00150 res = (*b->client->p)(b->client, kind, info);
00151 if (res == CCN_UPCALL_RESULT_OK) {
00152 b->next_expected += 1;
00153 b->first = (p == p->next) ? NULL : p->next;
00154 p->prev->next = p->next->prev;
00155 p->next->prev = p->prev->next;
00156 p->next = p->prev = p;
00157 p->parent = NULL;
00158 }
00159
00160 }
00161 else if (p->content_ccnb == NULL) {
00162
00163 size_t size = info->pco->offset[CCN_PCO_E];
00164 selfp->refcount++;
00165 p->content_ccnb = malloc(size);
00166 memcpy(p->content_ccnb, info->content_ccnb, size);
00167 p->content_size = size;
00168 }
00169 }
00170 while (b->first != NULL && b->first->x == b->next_expected &&
00171 b->first->content_ccnb != NULL) {
00172 res = deliver_content(info->h, b);
00173 if (res != CCN_UPCALL_RESULT_OK)
00174 break;
00175 }
00176 if (b->first == NULL) {
00177
00178 return(CCN_UPCALL_RESULT_OK);
00179 }
00180 for (p = b->first; p->x >= b->next_expected; p = p->next) {
00181
00182 if (p->content_ccnb == NULL)
00183 express_bulkdata_interest(info->h, p);
00184 }
00185 return(CCN_UPCALL_RESULT_OK);
00186 }
00187
00188 static void
00189 express_bulkdata_interest(struct ccn *h, struct pending *p)
00190 {
00191 int res;
00192 struct bulkdata *b = NULL;
00193 int prefix_comps = -1;
00194 int addl_comps = -1;
00195 struct ccn_charbuf *name = NULL;
00196 struct ccn_charbuf *templ = NULL;
00197 struct ccn_charbuf *seq = NULL;
00198
00199 b = p->parent;
00200 if (b == NULL)
00201 return;
00202 name = ccn_charbuf_create();
00203 templ = ccn_charbuf_create();
00204 seq = ccn_charbuf_create();
00205
00206 ccn_charbuf_append(name, b->name_prefix->buf, b->name_prefix->length);
00207
00208 seq->length = 0;
00209 (*b->seqfunc)(p->x, b->seqfunc_param, seq);
00210 ccn_name_append(name, seq->buf, seq->length);
00211 prefix_comps = -1;
00212 addl_comps = 1;
00213
00214 ccn_charbuf_append_tt(templ, CCN_DTAG_Interest, CCN_DTAG);
00215
00216 ccn_charbuf_append_tt(templ, CCN_DTAG_Name, CCN_DTAG);
00217 ccn_charbuf_append_closer(templ);
00218
00219
00220
00221 ccn_charbuf_append_closer(templ);
00222 res = ccn_express_interest(h, name, &p->closure, templ);
00223 assert(res >= 0);
00224 ccn_charbuf_destroy(&name);
00225 ccn_charbuf_destroy(&templ);
00226 ccn_charbuf_destroy(&seq);
00227 }
00228
00229
00230
00231
00232
00233 static enum ccn_upcall_res
00234 deliver_content(struct ccn *h, struct bulkdata *b)
00235 {
00236 struct ccn_upcall_info info = {0};
00237 struct ccn_parsed_ContentObject obj = {0};
00238 struct pending *p = b->first;
00239 int res;
00240 enum ccn_upcall_res ans;
00241 assert(p != NULL && p->x == b->next_expected && p->content_ccnb != NULL);
00242 info.pco = &obj;
00243 info.content_comps = ccn_indexbuf_create();
00244 res = ccn_parse_ContentObject(p->content_ccnb, p->content_size,
00245 &obj, info.content_comps);
00246 assert(res >= 0);
00247 info.content_ccnb = p->content_ccnb;
00248 info.matched_comps = info.content_comps->n - 2;
00249
00250 ans = (*b->client->p)(b->client, CCN_UPCALL_CONTENT, &info);
00251
00252 info.content_ccnb = NULL;
00253 free(p->content_ccnb);
00254 p->content_ccnb = NULL;
00255 p->content_size = 0;
00256 ccn_indexbuf_destroy(&info.content_comps);
00257 if (ans == CCN_UPCALL_RESULT_OK) {
00258 struct ccn_closure *old = &p->closure;
00259 if ((--(old->refcount)) == 0) {
00260 info.pco = NULL;
00261 (old->p)(old, CCN_UPCALL_FINAL, &info);
00262 }
00263 }
00264 return(ans);
00265 }