00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <stdio.h>
00021 #include <stdlib.h>
00022 #include <string.h>
00023 #include <unistd.h>
00024 #include <ccn/ccn.h>
00025 #include <ccn/charbuf.h>
00026 #include <ccn/uri.h>
00027
00028 static void
00029 usage(const char *progname)
00030 {
00031 fprintf(stderr,
00032 "%s [-a] ccnx:/a/b\n"
00033 " Reads stuff written by ccnsendchunks under"
00034 " the given uri and writes to stdout\n"
00035 " -a - allow stale data\n",
00036 progname);
00037 exit(1);
00038 }
00039
00040 struct mydata {
00041 int allow_stale;
00042 };
00043
00044 struct ccn_charbuf *
00045 make_template(struct mydata *md, struct ccn_upcall_info *info)
00046 {
00047 struct ccn_charbuf *templ = ccn_charbuf_create();
00048 ccn_charbuf_append_tt(templ, CCN_DTAG_Interest, CCN_DTAG);
00049 ccn_charbuf_append_tt(templ, CCN_DTAG_Name, CCN_DTAG);
00050 ccn_charbuf_append_closer(templ);
00051
00052 ccn_charbuf_append_tt(templ, CCN_DTAG_MaxSuffixComponents, CCN_DTAG);
00053 ccnb_append_number(templ, 1);
00054 ccn_charbuf_append_closer(templ);
00055 if (md->allow_stale) {
00056 ccn_charbuf_append_tt(templ, CCN_DTAG_AnswerOriginKind, CCN_DTAG);
00057 ccnb_append_number(templ, CCN_AOK_DEFAULT | CCN_AOK_STALE);
00058 ccn_charbuf_append_closer(templ);
00059 }
00060 ccn_charbuf_append_closer(templ);
00061 return(templ);
00062 }
00063
00064 #define CHUNK_SIZE 1024
00065
00066 enum ccn_upcall_res
00067 incoming_content(
00068 struct ccn_closure *selfp,
00069 enum ccn_upcall_kind kind,
00070 struct ccn_upcall_info *info)
00071 {
00072 struct ccn_charbuf *name = NULL;
00073 struct ccn_charbuf *templ = NULL;
00074 struct ccn_charbuf *temp = NULL;
00075 const unsigned char *ccnb = NULL;
00076 size_t ccnb_size = 0;
00077 const unsigned char *data = NULL;
00078 size_t data_size = 0;
00079 size_t written;
00080 const unsigned char *ib = NULL;
00081 struct ccn_indexbuf *ic = NULL;
00082 int res;
00083 struct mydata *md = selfp->data;
00084
00085 if (kind == CCN_UPCALL_FINAL) {
00086 if (md != NULL) {
00087 selfp->data = NULL;
00088 free(md);
00089 md = NULL;
00090 }
00091 return(CCN_UPCALL_RESULT_OK);
00092 }
00093 if (kind == CCN_UPCALL_INTEREST_TIMED_OUT)
00094 return(CCN_UPCALL_RESULT_REEXPRESS);
00095 if (kind != CCN_UPCALL_CONTENT && kind != CCN_UPCALL_CONTENT_UNVERIFIED)
00096 return(CCN_UPCALL_RESULT_ERR);
00097 if (md == NULL)
00098 selfp->data = md = calloc(1, sizeof(*md));
00099 ccnb = info->content_ccnb;
00100 ccnb_size = info->pco->offset[CCN_PCO_E];
00101 ib = info->interest_ccnb;
00102 ic = info->interest_comps;
00103
00104 res = ccn_content_get_value(ccnb, ccnb_size, info->pco, &data, &data_size);
00105 if (res < 0) abort();
00106 if (data_size > CHUNK_SIZE) {
00107
00108 fprintf(stderr, "*** Segment %d found with a data size of %d."
00109 " This program only works with segments of 1024 bytes."
00110 " Try ccncatchunks2 instead.\n",
00111 (int)selfp->intdata, (int)data_size);
00112 exit(1);
00113 }
00114
00115
00116
00117 written = fwrite(data, data_size, 1, stdout);
00118 if (written != 1)
00119 exit(1);
00120
00121
00122 if (data_size < CHUNK_SIZE)
00123 exit(0);
00124
00125
00126 name = ccn_charbuf_create();
00127 ccn_name_init(name);
00128 if (ic->n < 2) abort();
00129 res = ccn_name_append_components(name, ib, ic->buf[0], ic->buf[ic->n - 2]);
00130 if (res < 0) abort();
00131 temp = ccn_charbuf_create();
00132 ccn_charbuf_putf(temp, "%d", ++(selfp->intdata));
00133 ccn_name_append(name, temp->buf, temp->length);
00134 ccn_charbuf_destroy(&temp);
00135 templ = make_template(md, info);
00136
00137 res = ccn_express_interest(info->h, name, selfp, templ);
00138 if (res < 0) abort();
00139
00140 ccn_charbuf_destroy(&templ);
00141 ccn_charbuf_destroy(&name);
00142
00143 return(CCN_UPCALL_RESULT_OK);
00144 }
00145
00146 int
00147 main(int argc, char **argv)
00148 {
00149 struct ccn *ccn = NULL;
00150 struct ccn_charbuf *name = NULL;
00151 struct ccn_charbuf *templ = NULL;
00152 struct ccn_closure *incoming = NULL;
00153 const char *arg = NULL;
00154 int res;
00155 int opt;
00156 struct mydata *mydata;
00157 int allow_stale = 0;
00158
00159 while ((opt = getopt(argc, argv, "ha")) != -1) {
00160 switch (opt) {
00161 case 'a':
00162 allow_stale = 1;
00163 break;
00164 case 'h':
00165 default:
00166 usage(argv[0]);
00167 }
00168 }
00169 arg = argv[optind];
00170 if (arg == NULL)
00171 usage(argv[0]);
00172 name = ccn_charbuf_create();
00173 res = ccn_name_from_uri(name, arg);
00174 if (res < 0) {
00175 fprintf(stderr, "%s: bad ccn URI: %s\n", argv[0], arg);
00176 exit(1);
00177 }
00178 if (argv[optind + 1] != NULL)
00179 fprintf(stderr, "%s warning: extra arguments ignored\n", argv[0]);
00180 ccn = ccn_create();
00181 if (ccn_connect(ccn, NULL) == -1) {
00182 perror("Could not connect to ccnd");
00183 exit(1);
00184 }
00185 ccn_name_append(name, "0", 1);
00186 incoming = calloc(1, sizeof(*incoming));
00187 incoming->p = &incoming_content;
00188 mydata = calloc(1, sizeof(*mydata));
00189 mydata->allow_stale = allow_stale;
00190 incoming->data = mydata;
00191 templ = make_template(mydata, NULL);
00192 ccn_express_interest(ccn, name, incoming, templ);
00193 ccn_charbuf_destroy(&templ);
00194 ccn_charbuf_destroy(&name);
00195
00196 res = ccn_run(ccn, 200);
00197 if (incoming->intdata == 0) {
00198 fprintf(stderr, "%s: not found: %s\n", argv[0], arg);
00199 exit(1);
00200 }
00201
00202 while (res >= 0) {
00203 fflush(stdout);
00204 res = ccn_run(ccn, 200);
00205 }
00206 ccn_destroy(&ccn);
00207 exit(res < 0);
00208 }