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 (argv[0] == NULL)
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 if (argv[1] != NULL)
00155 fprintf(stderr, "%s warning: extra arguments ignored\n", progname);
00156
00157 ccn = ccn_create();
00158 if (ccn_connect(ccn, NULL) == -1) {
00159 perror("Could not connect to ccnd");
00160 exit(1);
00161 }
00162
00163 buf = calloc(1, blocksize);
00164 root = name;
00165 name = ccn_charbuf_create();
00166 temp = ccn_charbuf_create();
00167 templ = ccn_charbuf_create();
00168 signed_info = ccn_charbuf_create();
00169 keystore = ccn_keystore_create();
00170 temp->length = 0;
00171 ccn_charbuf_putf(temp, "%s/.ccnx/.ccnx_keystore", getenv("HOME"));
00172 res = ccn_keystore_init(keystore,
00173 ccn_charbuf_as_string(temp),
00174 "Th1s1sn0t8g00dp8ssw0rd.");
00175 if (res != 0) {
00176 printf("Failed to initialize keystore\n");
00177 exit(1);
00178 }
00179
00180 name->length = 0;
00181 ccn_charbuf_append(name, root->buf, root->length);
00182
00183
00184 ccn_set_interest_filter(ccn, name, &in_interest);
00185
00186
00187 temp->length = 0;
00188 ccn_charbuf_putf(temp, "%d", 0);
00189 ccn_name_append(name, temp->buf, temp->length);
00190 templ->length = 0;
00191 ccn_charbuf_append_tt(templ, CCN_DTAG_Interest, CCN_DTAG);
00192 ccn_charbuf_append_tt(templ, CCN_DTAG_Name, CCN_DTAG);
00193 ccn_charbuf_append_closer(templ);
00194 ccn_charbuf_append_tt(templ, CCN_DTAG_MaxSuffixComponents, CCN_DTAG);
00195 ccn_charbuf_append_tt(templ, 1, CCN_UDATA);
00196 ccn_charbuf_append(templ, "1", 1);
00197 ccn_charbuf_append_closer(templ);
00198
00199 ccn_charbuf_append_closer(templ);
00200 res = ccn_express_interest(ccn, name, &in_content, templ);
00201 if (res < 0) abort();
00202
00203
00204 keylocator = ccn_charbuf_create();
00205 ccn_charbuf_append_tt(keylocator, CCN_DTAG_KeyLocator, CCN_DTAG);
00206 ccn_charbuf_append_tt(keylocator, CCN_DTAG_Key, CCN_DTAG);
00207 res = ccn_append_pubkey_blob(keylocator, ccn_keystore_public_key(keystore));
00208 if (res < 0)
00209 ccn_charbuf_destroy(&keylocator);
00210 else {
00211 ccn_charbuf_append_closer(keylocator);
00212 ccn_charbuf_append_closer(keylocator);
00213 }
00214
00215 for (i = 0;; i++) {
00216 read_res = read_full(0, buf, blocksize);
00217 if (read_res < 0) {
00218 perror("read");
00219 read_res = 0;
00220 status = 1;
00221 }
00222 signed_info->length = 0;
00223 if (read_res < blocksize) {
00224 temp->length = 0;
00225 ccn_charbuf_putf(temp, "%d", i);
00226 ccn_name_append(name, temp->buf, temp->length);
00227 finalblockid = ccn_charbuf_create();
00228 ccn_charbuf_append_tt(finalblockid, temp->length, CCN_BLOB);
00229 ccn_charbuf_append(finalblockid, temp->buf, temp->length);
00230 }
00231 res = ccn_signed_info_create(signed_info,
00232 ccn_keystore_public_key_digest(keystore),
00233 ccn_keystore_public_key_digest_length(keystore),
00234 NULL,
00235 CCN_CONTENT_DATA,
00236 expire,
00237 finalblockid,
00238 keylocator);
00239
00240 ccn_charbuf_destroy(&keylocator);
00241 if (res < 0) {
00242 fprintf(stderr, "Failed to create signed_info (res == %d)\n", res);
00243 exit(1);
00244 }
00245 name->length = 0;
00246 ccn_charbuf_append(name, root->buf, root->length);
00247 temp->length = 0;
00248 ccn_charbuf_putf(temp, "%d", i);
00249 ccn_name_append(name, temp->buf, temp->length);
00250 temp->length = 0;
00251 ccn_charbuf_append(temp, buf, read_res);
00252 temp->length = 0;
00253 res = ccn_encode_ContentObject(temp,
00254 name,
00255 signed_info,
00256 buf,
00257 read_res,
00258 NULL,
00259 ccn_keystore_private_key(keystore));
00260 if (res != 0) {
00261 fprintf(stderr, "Failed to encode ContentObject (res == %d)\n", res);
00262 exit(1);
00263 }
00264 if (i == 0) {
00265
00266 if (mydata.content_received == 0)
00267 ccn_run(ccn, 100);
00268 if (mydata.content_received > 0) {
00269 fprintf(stderr, "%s: name is in use: %s\n", progname, argv[0]);
00270 exit(1);
00271 }
00272 mydata.outstanding++;
00273 }
00274 res = ccn_put(ccn, temp->buf, temp->length);
00275 if (res < 0) {
00276 fprintf(stderr, "ccn_put failed (res == %d)\n", res);
00277 exit(1);
00278 }
00279 if (read_res < blocksize)
00280 break;
00281 if (mydata.outstanding > 0)
00282 mydata.outstanding--;
00283 else
00284 res = 10;
00285 res = ccn_run(ccn, res * 100);
00286 if (res < 0) {
00287 status = 1;
00288 break;
00289 }
00290 }
00291
00292 free(buf);
00293 buf = NULL;
00294 ccn_charbuf_destroy(&root);
00295 ccn_charbuf_destroy(&name);
00296 ccn_charbuf_destroy(&temp);
00297 ccn_charbuf_destroy(&signed_info);
00298 ccn_charbuf_destroy(&finalblockid);
00299 ccn_keystore_destroy(&keystore);
00300 ccn_destroy(&ccn);
00301 exit(status);
00302 }