00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023 #include <string.h>
00024 #include <unistd.h>
00025 #include <ccn/ccn.h>
00026 #include <ccn/charbuf.h>
00027 #include <ccn/uri.h>
00028
00029
00030
00031
00032 static void
00033 usage(const char *progname)
00034 {
00035 fprintf(stderr,
00036 "%s [-a] ccnx:/a/b ...\n"
00037 " Reads streams at"
00038 " the given ccn URIs and writes to stdout\n"
00039 " -a - allow stale data\n",
00040 progname);
00041 exit(1);
00042 }
00043
00044 struct mydata {
00045 int *done;
00046 int allow_stale;
00047 };
00048
00049
00050
00051
00052
00053
00054 struct ccn_charbuf *
00055 make_template(struct mydata *md, struct ccn_upcall_info *info)
00056 {
00057 struct ccn_charbuf *templ = ccn_charbuf_create();
00058 ccn_charbuf_append_tt(templ, CCN_DTAG_Interest, CCN_DTAG);
00059 ccn_charbuf_append_tt(templ, CCN_DTAG_Name, CCN_DTAG);
00060 ccn_charbuf_append_closer(templ);
00061
00062 ccn_charbuf_append_tt(templ, CCN_DTAG_MinSuffixComponents, CCN_DTAG);
00063 ccnb_append_number(templ, 1);
00064 ccn_charbuf_append_closer(templ);
00065 if (md->allow_stale) {
00066 ccn_charbuf_append_tt(templ, CCN_DTAG_AnswerOriginKind, CCN_DTAG);
00067 ccnb_append_number(templ, CCN_AOK_DEFAULT | CCN_AOK_STALE);
00068 ccn_charbuf_append_closer(templ);
00069 }
00070 ccn_charbuf_append_closer(templ);
00071 return(templ);
00072 }
00073
00074
00075
00076
00077
00078
00079 enum ccn_upcall_res
00080 incoming_content(struct ccn_closure *selfp,
00081 enum ccn_upcall_kind kind,
00082 struct ccn_upcall_info *info)
00083 {
00084 struct ccn_charbuf *name = NULL;
00085 struct ccn_charbuf *templ = NULL;
00086 const unsigned char *ccnb = NULL;
00087 size_t ccnb_size = 0;
00088 const unsigned char *data = NULL;
00089 size_t data_size = 0;
00090 size_t written;
00091 const unsigned char *ib = NULL;
00092 struct ccn_indexbuf *ic = NULL;
00093 int res;
00094 struct mydata *md = selfp->data;
00095
00096 if (kind == CCN_UPCALL_FINAL) {
00097 if (md != NULL) {
00098 selfp->data = NULL;
00099 free(md);
00100 md = NULL;
00101 }
00102 return(CCN_UPCALL_RESULT_OK);
00103 }
00104 if (kind == CCN_UPCALL_INTEREST_TIMED_OUT)
00105 return(CCN_UPCALL_RESULT_REEXPRESS);
00106 if (kind == CCN_UPCALL_CONTENT_UNVERIFIED)
00107 return(CCN_UPCALL_RESULT_VERIFY);
00108 if (kind != CCN_UPCALL_CONTENT)
00109 return(CCN_UPCALL_RESULT_ERR);
00110 if (md == NULL)
00111 selfp->data = md = calloc(1, sizeof(*md));
00112 ccnb = info->content_ccnb;
00113 ccnb_size = info->pco->offset[CCN_PCO_E];
00114 ib = info->interest_ccnb;
00115 ic = info->interest_comps;
00116 res = ccn_content_get_value(ccnb, ccnb_size, info->pco, &data, &data_size);
00117 if (res < 0) abort();
00118 if (info->pco->type != CCN_CONTENT_DATA) {
00119
00120 fprintf(stderr, "*** spammed at block %d\n", (int)selfp->intdata);
00121 exit(1);
00122 }
00123
00124
00125 if (data_size == 0)
00126 *(md->done) = 1;
00127 else {
00128 written = fwrite(data, data_size, 1, stdout);
00129 if (written != 1)
00130 exit(1);
00131 }
00132
00133 if (info->pco->offset[CCN_PCO_B_FinalBlockID] !=
00134 info->pco->offset[CCN_PCO_E_FinalBlockID]) {
00135 const unsigned char *finalid = NULL;
00136 size_t finalid_size = 0;
00137 const unsigned char *nameid = NULL;
00138 size_t nameid_size = 0;
00139 struct ccn_indexbuf *cc = info->content_comps;
00140 ccn_ref_tagged_BLOB(CCN_DTAG_FinalBlockID, ccnb,
00141 info->pco->offset[CCN_PCO_B_FinalBlockID],
00142 info->pco->offset[CCN_PCO_E_FinalBlockID],
00143 &finalid,
00144 &finalid_size);
00145 if (cc->n < 2) abort();
00146 ccn_ref_tagged_BLOB(CCN_DTAG_Component, ccnb,
00147 cc->buf[cc->n - 2],
00148 cc->buf[cc->n - 1],
00149 &nameid,
00150 &nameid_size);
00151 if (finalid_size == nameid_size &&
00152 0 == memcmp(finalid, nameid, nameid_size))
00153 *(md->done) = 1;
00154 }
00155
00156 if (*(md->done)) {
00157 ccn_set_run_timeout(info->h, 0);
00158 return(CCN_UPCALL_RESULT_OK);
00159 }
00160
00161
00162 name = ccn_charbuf_create();
00163 ccn_name_init(name);
00164 if (ic->n < 2) abort();
00165 res = ccn_name_append_components(name, ib, ic->buf[0], ic->buf[ic->n - 2]);
00166 if (res < 0) abort();
00167 ccn_name_append_numeric(name, CCN_MARKER_SEQNUM, ++(selfp->intdata));
00168 templ = make_template(md, info);
00169
00170 res = ccn_express_interest(info->h, name, selfp, templ);
00171 if (res < 0) abort();
00172
00173 ccn_charbuf_destroy(&templ);
00174 ccn_charbuf_destroy(&name);
00175
00176 return(CCN_UPCALL_RESULT_OK);
00177 }
00178
00179
00180
00181
00182
00183 int
00184 main(int argc, char **argv)
00185 {
00186 struct ccn *ccn = NULL;
00187 struct ccn_charbuf *name = NULL;
00188 struct ccn_charbuf *templ = NULL;
00189 struct ccn_closure *incoming = NULL;
00190 const char *arg = NULL;
00191 int i;
00192 int res;
00193 int opt;
00194 struct mydata *mydata;
00195 int allow_stale = 0;
00196 int *done;
00197 int exit_status = 0;
00198
00199 done = calloc(1, sizeof(*done));
00200
00201 while ((opt = getopt(argc, argv, "ha")) != -1) {
00202 switch (opt) {
00203 case 'a':
00204 allow_stale = 1;
00205 break;
00206 case 'h':
00207 default:
00208 usage(argv[0]);
00209 }
00210 }
00211 arg = argv[optind];
00212 if (arg == NULL)
00213 usage(argv[0]);
00214 name = ccn_charbuf_create();
00215
00216 for (i = optind; argv[i] != NULL; i++) {
00217 name->length = 0;
00218 res = ccn_name_from_uri(name, argv[i]);
00219 if (res < 0) {
00220 fprintf(stderr, "%s: bad ccn URI: %s\n", argv[0], argv[i]);
00221 exit(1);
00222 }
00223 }
00224 for (i = optind; (arg = argv[i]) != NULL; i++) {
00225 *done = 0;
00226 name->length = 0;
00227 res = ccn_name_from_uri(name, arg);
00228 ccn = ccn_create();
00229 if (ccn_connect(ccn, NULL) == -1) {
00230 perror("Could not connect to ccnd");
00231 exit(1);
00232 }
00233 ccn_resolve_version(ccn, name, CCN_V_HIGHEST, 50);
00234 ccn_name_append_numeric(name, CCN_MARKER_SEQNUM, 0);
00235 incoming = calloc(1, sizeof(*incoming));
00236 incoming->p = &incoming_content;
00237 mydata = calloc(1, sizeof(*mydata));
00238 mydata->allow_stale = allow_stale;
00239 mydata->done = done;
00240 incoming->data = mydata;
00241 templ = make_template(mydata, NULL);
00242 ccn_express_interest(ccn, name, incoming, templ);
00243 ccn_charbuf_destroy(&templ);
00244
00245 res = ccn_run(ccn, 200);
00246 if ((!*done) && incoming->intdata == 0) {
00247 fprintf(stderr, "%s: not found: %s\n", argv[0], arg);
00248 res = -1;
00249 }
00250
00251 while (res >= 0 && !*done) {
00252 fflush(stdout);
00253 res = ccn_run(ccn, 333);
00254 }
00255 if (res < 0)
00256 exit_status = 1;
00257 ccn_destroy(&ccn);
00258 fflush(stdout);
00259 free(incoming);
00260 incoming = NULL;
00261 }
00262 ccn_charbuf_destroy(&name);
00263 free(done);
00264 exit(exit_status);
00265 }