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 static ssize_t
00031 read_full(int fd, unsigned char *buf, size_t size)
00032 {
00033 size_t i;
00034 ssize_t res = 0;
00035 for (i = 0; i < size; i += res) {
00036 res = read(fd, buf + i, size - i);
00037 if (res == -1) {
00038 if (errno == EAGAIN || errno == EINTR)
00039 res = 0;
00040 else
00041 return(res);
00042 }
00043 else if (res == 0)
00044 break;
00045 }
00046 return(i);
00047 }
00048
00049 static void
00050 usage(const char *progname)
00051 {
00052 fprintf(stderr,
00053 "%s [-fhv] [-V seg] [-x freshness_seconds] [-t type]"
00054 " ccnx:/some/place\n"
00055 " Reads data from stdin and sends it to the local ccnd"
00056 " as a single ContentObject under the given URI"
00057 "\n"
00058 " -h - print this message and exit"
00059 "\n"
00060 " -k key_uri - use this name for key locator"
00061 "\n"
00062 " -f - force - send content even if no interest received"
00063 "\n"
00064 " -v - verbose"
00065 "\n"
00066 " -V seg - generate version, use seg as name suffix"
00067 "\n"
00068 " -w seconds - fail after this long if no interest arrives"
00069 "\n"
00070 " -x seconds - set FreshnessSeconds"
00071 "\n"
00072 " -t ( DATA | ENCR | GONE | KEY | LINK | NACK ) - set type"
00073 "\n", progname);
00074 exit(1);
00075 }
00076
00077 enum ccn_upcall_res
00078 incoming_interest(
00079 struct ccn_closure *selfp,
00080 enum ccn_upcall_kind kind,
00081 struct ccn_upcall_info *info)
00082 {
00083 struct ccn_charbuf *cob = selfp->data;
00084 int res;
00085
00086 switch (kind) {
00087 case CCN_UPCALL_FINAL:
00088 break;
00089 case CCN_UPCALL_INTEREST:
00090 if (ccn_content_matches_interest(cob->buf, cob->length,
00091 1, NULL,
00092 info->interest_ccnb, info->pi->offset[CCN_PI_E],
00093 info->pi)) {
00094 res = ccn_put(info->h, cob->buf, cob->length);
00095 if (res >= 0) {
00096 selfp->intdata = 1;
00097 ccn_set_run_timeout(info->h, 0);
00098 return(CCN_UPCALL_RESULT_INTEREST_CONSUMED);
00099 }
00100 }
00101 break;
00102 default:
00103 break;
00104 }
00105 return(CCN_UPCALL_RESULT_OK);
00106 }
00107
00108 int
00109 main(int argc, char **argv)
00110 {
00111 const char *progname = argv[0];
00112 struct ccn *ccn = NULL;
00113 struct ccn_charbuf *name = NULL;
00114 struct ccn_charbuf *pname = NULL;
00115 struct ccn_charbuf *temp = NULL;
00116 long expire = -1;
00117 int versioned = 0;
00118 size_t blocksize = 8*1024;
00119 int status = 0;
00120 int res;
00121 ssize_t read_res;
00122 unsigned char *buf = NULL;
00123 enum ccn_content_type content_type = CCN_CONTENT_DATA;
00124 struct ccn_closure in_interest = {.p=&incoming_interest};
00125 const char *postver = NULL;
00126 const char *key_uri = NULL;
00127 int force = 0;
00128 int verbose = 0;
00129 int timeout = -1;
00130 int setfinal = 0;
00131 struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT;
00132
00133 while ((res = getopt(argc, argv, "fhk:lvV:t:w:x:")) != -1) {
00134 switch (res) {
00135 case 'f':
00136 force = 1;
00137 break;
00138 case 'l':
00139 setfinal = 1;
00140 break;
00141 case 'k':
00142 key_uri = optarg;
00143 break;
00144 case 'x':
00145 expire = atol(optarg);
00146 if (expire <= 0)
00147 usage(progname);
00148 break;
00149 case 'v':
00150 verbose = 1;
00151 break;
00152 case 'V':
00153 versioned = 1;
00154 postver = optarg;
00155 if (0 == memcmp(postver, "%00", 3))
00156 setfinal = 1;
00157 break;
00158 case 'w':
00159 timeout = atol(optarg);
00160 if (timeout <= 0)
00161 usage(progname);
00162 timeout *= 1000;
00163 break;
00164 case 't':
00165 if (0 == strcasecmp(optarg, "DATA")) {
00166 content_type = CCN_CONTENT_DATA;
00167 break;
00168 }
00169 if (0 == strcasecmp(optarg, "ENCR")) {
00170 content_type = CCN_CONTENT_ENCR;
00171 break;
00172 }
00173 if (0 == strcasecmp(optarg, "GONE")) {
00174 content_type = CCN_CONTENT_GONE;
00175 break;
00176 }
00177 if (0 == strcasecmp(optarg, "KEY")) {
00178 content_type = CCN_CONTENT_KEY;
00179 break;
00180 }
00181 if (0 == strcasecmp(optarg, "LINK")) {
00182 content_type = CCN_CONTENT_LINK;
00183 break;
00184 }
00185 if (0 == strcasecmp(optarg, "NACK")) {
00186 content_type = CCN_CONTENT_NACK;
00187 break;
00188 }
00189 content_type = atoi(optarg);
00190 if (content_type > 0 && content_type <= 0xffffff)
00191 break;
00192 fprintf(stderr, "Unknown content type %s\n", optarg);
00193
00194 default:
00195 case 'h':
00196 usage(progname);
00197 break;
00198 }
00199 }
00200 argc -= optind;
00201 argv += optind;
00202 if (argv[0] == NULL)
00203 usage(progname);
00204 name = ccn_charbuf_create();
00205 res = ccn_name_from_uri(name, argv[0]);
00206 if (res < 0) {
00207 fprintf(stderr, "%s: bad ccn URI: %s\n", progname, argv[0]);
00208 exit(1);
00209 }
00210 if (argv[1] != NULL)
00211 fprintf(stderr, "%s warning: extra arguments ignored\n", progname);
00212
00213
00214 pname = ccn_charbuf_create();
00215 ccn_charbuf_append(pname, name->buf, name->length);
00216
00217
00218 ccn = ccn_create();
00219 if (ccn_connect(ccn, NULL) == -1) {
00220 perror("Could not connect to ccnd");
00221 exit(1);
00222 }
00223
00224
00225 buf = calloc(1, blocksize);
00226 read_res = read_full(0, buf, blocksize);
00227 if (read_res < 0) {
00228 perror("read");
00229 read_res = 0;
00230 status = 1;
00231 }
00232
00233
00234 if (versioned) {
00235 res = ccn_create_version(ccn, name, CCN_V_REPLACE | CCN_V_NOW | CCN_V_HIGH, 0, 0);
00236 if (res < 0) {
00237 fprintf(stderr, "%s: ccn_create_version() failed\n", progname);
00238 exit(1);
00239 }
00240 if (postver != NULL) {
00241 res = ccn_name_from_uri(name, postver);
00242 if (res < 0) {
00243 fprintf(stderr, "-V %s: invalid name suffix\n", postver);
00244 exit(0);
00245 }
00246 }
00247 }
00248 temp = ccn_charbuf_create();
00249
00250
00251 if (setfinal)
00252 sp.sp_flags |= CCN_SP_FINAL_BLOCK;
00253
00254 if (res < 0) {
00255 fprintf(stderr, "Failed to create signed_info (res == %d)\n", res);
00256 exit(1);
00257 }
00258
00259
00260 sp.type = content_type;
00261
00262
00263 if (expire >= 0) {
00264 if (sp.template_ccnb == NULL) {
00265 sp.template_ccnb = ccn_charbuf_create();
00266 ccn_charbuf_append_tt(sp.template_ccnb, CCN_DTAG_SignedInfo, CCN_DTAG);
00267 }
00268 else if (sp.template_ccnb->length > 0) {
00269 sp.template_ccnb->length--;
00270 }
00271 ccnb_tagged_putf(sp.template_ccnb, CCN_DTAG_FreshnessSeconds, "%ld", expire);
00272 sp.sp_flags |= CCN_SP_TEMPL_FRESHNESS;
00273 ccn_charbuf_append_closer(sp.template_ccnb);
00274 }
00275
00276
00277 if (key_uri != NULL) {
00278 struct ccn_charbuf *c = ccn_charbuf_create();
00279 res = ccn_name_from_uri(c, key_uri);
00280 if (res < 0) {
00281 fprintf(stderr, "%s is not a valid ccnx URI\n", key_uri);
00282 exit(1);
00283 }
00284 if (sp.template_ccnb == NULL) {
00285 sp.template_ccnb = ccn_charbuf_create();
00286 ccn_charbuf_append_tt(sp.template_ccnb, CCN_DTAG_SignedInfo, CCN_DTAG);
00287 }
00288 else if (sp.template_ccnb->length > 0) {
00289 sp.template_ccnb->length--;
00290 }
00291 ccn_charbuf_append_tt(sp.template_ccnb, CCN_DTAG_KeyLocator, CCN_DTAG);
00292 ccn_charbuf_append_tt(sp.template_ccnb, CCN_DTAG_KeyName, CCN_DTAG);
00293 ccn_charbuf_append(sp.template_ccnb, c->buf, c->length);
00294 ccn_charbuf_append_closer(sp.template_ccnb);
00295 ccn_charbuf_append_closer(sp.template_ccnb);
00296 sp.sp_flags |= CCN_SP_TEMPL_KEY_LOCATOR;
00297 ccn_charbuf_append_closer(sp.template_ccnb);
00298 ccn_charbuf_destroy(&c);
00299 }
00300
00301
00302 temp->length = 0;
00303 res = ccn_sign_content(ccn, temp, name, &sp, buf, read_res);
00304 if (res != 0) {
00305 fprintf(stderr, "Failed to encode ContentObject (res == %d)\n", res);
00306 exit(1);
00307 }
00308 if (read_res == blocksize) {
00309 read_res = read_full(0, buf, 1);
00310 if (read_res == 1) {
00311 fprintf(stderr, "%s: warning - truncated data\n", argv[0]);
00312 status = 1;
00313 }
00314 }
00315 free(buf);
00316 buf = NULL;
00317 if (force) {
00318
00319 res = ccn_put(ccn, temp->buf, temp->length);
00320 if (res < 0) {
00321 fprintf(stderr, "ccn_put failed (res == %d)\n", res);
00322 exit(1);
00323 }
00324 }
00325 else {
00326 in_interest.data = temp;
00327
00328 res = ccn_set_interest_filter(ccn, pname, &in_interest);
00329 if (res < 0) {
00330 fprintf(stderr, "Failed to register interest (res == %d)\n", res);
00331 exit(1);
00332 }
00333 res = ccn_run(ccn, timeout);
00334 if (in_interest.intdata == 0) {
00335 if (verbose)
00336 fprintf(stderr, "Nobody's interested\n");
00337 exit(1);
00338 }
00339 }
00340
00341 if (verbose) {
00342 struct ccn_charbuf *uri = ccn_charbuf_create();
00343 uri->length = 0;
00344 ccn_uri_append(uri, name->buf, name->length, 1);
00345 printf("wrote %s\n", ccn_charbuf_as_string(uri));
00346 ccn_charbuf_destroy(&uri);
00347 }
00348 ccn_destroy(&ccn);
00349 ccn_charbuf_destroy(&name);
00350 ccn_charbuf_destroy(&pname);
00351 ccn_charbuf_destroy(&temp);
00352 ccn_charbuf_destroy(&sp.template_ccnb);
00353 exit(status);
00354 }