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/ccn.h>
00026 #include <ccn/uri.h>
00027 #include <ccn/keystore.h>
00028 #include <ccn/signing.h>
00029
00030 struct mydata {
00031 int content_received;
00032 int content_sent;
00033 int outstanding;
00034 };
00035
00036 enum ccn_upcall_res
00037 incoming_content(
00038 struct ccn_closure *selfp,
00039 enum ccn_upcall_kind kind,
00040 struct ccn_upcall_info *info)
00041 {
00042 struct mydata *md = selfp->data;
00043
00044 if (kind == CCN_UPCALL_FINAL)
00045 return(CCN_UPCALL_RESULT_OK);
00046 if (kind == CCN_UPCALL_INTEREST_TIMED_OUT)
00047 return(CCN_UPCALL_RESULT_OK);
00048 if ((kind != CCN_UPCALL_CONTENT && kind != CCN_UPCALL_CONTENT_UNVERIFIED) || md == NULL)
00049 return(CCN_UPCALL_RESULT_ERR);
00050 md->content_received++;
00051 ccn_set_run_timeout(info->h, 0);
00052 return(CCN_UPCALL_RESULT_OK);
00053 }
00054
00055 enum ccn_upcall_res
00056 incoming_interest(
00057 struct ccn_closure *selfp,
00058 enum ccn_upcall_kind kind,
00059 struct ccn_upcall_info *info)
00060 {
00061 struct mydata *md = selfp->data;
00062
00063 if (kind == CCN_UPCALL_FINAL)
00064 return(CCN_UPCALL_RESULT_OK);
00065 if (kind != CCN_UPCALL_INTEREST || md == NULL)
00066 return(CCN_UPCALL_RESULT_ERR);
00067 if ((info->pi->answerfrom & CCN_AOK_NEW) != 0) {
00068 if (md->outstanding < 10)
00069 md->outstanding = 10;
00070 ccn_set_run_timeout(info->h, 0);
00071 }
00072 return(CCN_UPCALL_RESULT_OK);
00073 }
00074
00075 ssize_t
00076 read_full(int fd, unsigned char *buf, size_t size)
00077 {
00078 size_t i;
00079 ssize_t res = 0;
00080 for (i = 0; i < size; i += res) {
00081 res = read(fd, buf + i, size - i);
00082 if (res == -1) {
00083 if (errno == EAGAIN || errno == EINTR)
00084 res = 0;
00085 else
00086 return(res);
00087 }
00088 else if (res == 0)
00089 break;
00090 }
00091 return(i);
00092 }
00093
00094 static void
00095 usage(const char *progname)
00096 {
00097 fprintf(stderr,
00098 "%s [-h] [-x freshness_seconds] [-b blocksize] URI\n"
00099 " Chops stdin into blocks (1K by default) and sends them "
00100 "as consecutively numbered ContentObjects "
00101 "under the given uri\n", progname);
00102 exit(1);
00103 }
00104
00105 int
00106 main(int argc, char **argv)
00107 {
00108 const char *progname = argv[0];
00109 struct ccn *ccn = NULL;
00110 struct ccn_charbuf *root = NULL;
00111 struct ccn_charbuf *name = NULL;
00112 struct ccn_charbuf *temp = NULL;
00113 struct ccn_charbuf *templ = NULL;
00114 struct ccn_charbuf *signed_info = NULL;
00115 struct ccn_charbuf *keylocator = NULL;
00116 struct ccn_charbuf *finalblockid = NULL;
00117 struct ccn_keystore *keystore = NULL;
00118 long expire = -1;
00119 long blocksize = 1024;
00120 int i;
00121 int status = 0;
00122 int res;
00123 ssize_t read_res;
00124 unsigned char *buf = NULL;
00125 struct mydata mydata = { 0 };
00126 struct ccn_closure in_content = {.p=&incoming_content, .data=&mydata};
00127 struct ccn_closure in_interest = {.p=&incoming_interest, .data=&mydata};
00128 while ((res = getopt(argc, argv, "hx:b:")) != -1) {
00129 switch (res) {
00130 case 'x':
00131 expire = atol(optarg);
00132 if (expire <= 0)
00133 usage(progname);
00134 break;
00135 case 'b':
00136 blocksize = atol(optarg);
00137 break;
00138 default:
00139 case 'h':
00140 usage(progname);
00141 break;
00142 }
00143 }
00144 argc -= optind;
00145 argv += optind;
00146 if (argc != 1)
00147 usage(progname);
00148 name = ccn_charbuf_create();
00149 res = ccn_name_from_uri(name, argv[0]);
00150 if (res < 0) {
00151 fprintf(stderr, "%s: bad CCN URI: %s\n", progname, argv[0]);
00152 exit(1);
00153 }
00154 ccn = ccn_create();
00155 if (ccn_connect(ccn, NULL) == -1) {
00156 perror("Could not connect to ccnd");
00157 exit(1);
00158 }
00159
00160 buf = calloc(1, blocksize);
00161 root = name;
00162 name = ccn_charbuf_create();
00163 temp = ccn_charbuf_create();
00164 templ = ccn_charbuf_create();
00165 signed_info = ccn_charbuf_create();
00166 keystore = ccn_keystore_create();
00167 temp->length = 0;
00168 ccn_charbuf_putf(temp, "%s/.ccnx/.ccnx_keystore", getenv("HOME"));
00169 res = ccn_keystore_init(keystore,
00170 ccn_charbuf_as_string(temp),
00171 "Th1s1sn0t8g00dp8ssw0rd.");
00172 if (res != 0) {
00173 printf("Failed to initialize keystore\n");
00174 exit(1);
00175 }
00176
00177 name->length = 0;
00178 ccn_charbuf_append(name, root->buf, root->length);
00179
00180
00181 ccn_set_interest_filter(ccn, name, &in_interest);
00182
00183
00184 temp->length = 0;
00185 ccn_charbuf_putf(temp, "%d", 0);
00186 ccn_name_append(name, temp->buf, temp->length);
00187 templ->length = 0;
00188 ccn_charbuf_append_tt(templ, CCN_DTAG_Interest, CCN_DTAG);
00189 ccn_charbuf_append_tt(templ, CCN_DTAG_Name, CCN_DTAG);
00190 ccn_charbuf_append_closer(templ);
00191 ccn_charbuf_append_tt(templ, CCN_DTAG_MaxSuffixComponents, CCN_DTAG);
00192 ccn_charbuf_append_tt(templ, 1, CCN_UDATA);
00193 ccn_charbuf_append(templ, "1", 1);
00194 ccn_charbuf_append_closer(templ);
00195
00196 ccn_charbuf_append_closer(templ);
00197 res = ccn_express_interest(ccn, name, &in_content, templ);
00198 if (res < 0) abort();
00199
00200
00201 keylocator = ccn_charbuf_create();
00202 ccn_charbuf_append_tt(keylocator, CCN_DTAG_KeyLocator, CCN_DTAG);
00203 ccn_charbuf_append_tt(keylocator, CCN_DTAG_Key, CCN_DTAG);
00204 res = ccn_append_pubkey_blob(keylocator, ccn_keystore_public_key(keystore));
00205 if (res < 0)
00206 ccn_charbuf_destroy(&keylocator);
00207 else {
00208 ccn_charbuf_append_closer(keylocator);
00209 ccn_charbuf_append_closer(keylocator);
00210 }
00211
00212 for (i = 0;; i++) {
00213 read_res = read_full(0, buf, blocksize);
00214 if (read_res < 0) {
00215 perror("read");
00216 read_res = 0;
00217 status = 1;
00218 }
00219 signed_info->length = 0;
00220 if (read_res < blocksize) {
00221 temp->length = 0;
00222 ccn_charbuf_putf(temp, "%d", i);
00223 ccn_name_append(name, temp->buf, temp->length);
00224 finalblockid = ccn_charbuf_create();
00225 ccn_charbuf_append_tt(finalblockid, temp->length, CCN_BLOB);
00226 ccn_charbuf_append(finalblockid, temp->buf, temp->length);
00227 }
00228 res = ccn_signed_info_create(signed_info,
00229 ccn_keystore_public_key_digest(keystore),
00230 ccn_keystore_public_key_digest_length(keystore),
00231 NULL,
00232 CCN_CONTENT_DATA,
00233 expire,
00234 finalblockid,
00235 keylocator);
00236
00237 ccn_charbuf_destroy(&keylocator);
00238 if (res < 0) {
00239 fprintf(stderr, "Failed to create signed_info (res == %d)\n", res);
00240 exit(1);
00241 }
00242 name->length = 0;
00243 ccn_charbuf_append(name, root->buf, root->length);
00244 temp->length = 0;
00245 ccn_charbuf_putf(temp, "%d", i);
00246 ccn_name_append(name, temp->buf, temp->length);
00247 temp->length = 0;
00248 ccn_charbuf_append(temp, buf, read_res);
00249 temp->length = 0;
00250 res = ccn_encode_ContentObject(temp,
00251 name,
00252 signed_info,
00253 buf,
00254 read_res,
00255 NULL,
00256 ccn_keystore_private_key(keystore));
00257 if (res != 0) {
00258 fprintf(stderr, "Failed to encode ContentObject (res == %d)\n", res);
00259 exit(1);
00260 }
00261 if (i == 0) {
00262
00263 if (mydata.content_received == 0)
00264 ccn_run(ccn, 100);
00265 if (mydata.content_received > 0) {
00266 fprintf(stderr, "%s: name is in use: %s\n", progname, argv[0]);
00267 exit(1);
00268 }
00269 mydata.outstanding++;
00270 }
00271 res = ccn_put(ccn, temp->buf, temp->length);
00272 if (res < 0) {
00273 fprintf(stderr, "ccn_put failed (res == %d)\n", res);
00274 exit(1);
00275 }
00276 if (read_res < blocksize)
00277 break;
00278 if (mydata.outstanding > 0)
00279 mydata.outstanding--;
00280 else
00281 res = 10;
00282 res = ccn_run(ccn, res * 100);
00283 if (res < 0) {
00284 status = 1;
00285 break;
00286 }
00287 }
00288
00289 free(buf);
00290 buf = NULL;
00291 ccn_charbuf_destroy(&root);
00292 ccn_charbuf_destroy(&name);
00293 ccn_charbuf_destroy(&temp);
00294 ccn_charbuf_destroy(&signed_info);
00295 ccn_charbuf_destroy(&finalblockid);
00296 ccn_keystore_destroy(&keystore);
00297 ccn_destroy(&ccn);
00298 exit(status);
00299 }