diff -r 000000000000 -r 2b3e5ec03512 apps/dtncpd/dtncpd.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/apps/dtncpd/dtncpd.c Thu Apr 21 14:57:45 2011 +0100 @@ -0,0 +1,361 @@ +/* + * Copyright 2004-2006 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "dtn_api.h" + +#define BUFSIZE 16 +#define BUNDLE_DIR_DEFAULT INSTALL_LOCALSTATEDIR "/dtn/dtncpd-incoming" + +static const char *progname; + +void +usage() +{ + fprintf(stderr, "usage: %s [ directory ]\n", progname); + fprintf(stderr, " optional directory parameter is where incoming " + "files will get put\n"); + fprintf(stderr, " (defaults to: %s)\n", BUNDLE_DIR_DEFAULT); + exit(1); +} + +int +main(int argc, const char** argv) +{ + int i; + int ret; + dtn_handle_t handle; + dtn_endpoint_id_t local_eid; + dtn_reg_info_t reginfo; + dtn_reg_id_t regid; + dtn_bundle_spec_t bundle; + dtn_bundle_payload_t payload; + const char* endpoint_demux; + int debug = 1; + + char * bundle_dir = 0; + + char host[PATH_MAX]; + int host_len; + char * dirpath; + char * filename; + char filepath[PATH_MAX]; + time_t current; + + char * buffer; + char s_buffer[BUFSIZE + 1]; + + int bufsize, marker, maxwrite; + + FILE * target; + + // force stdout to always be line buffered, even if output is + // redirected to a pipe or file + setvbuf(stdout, (char *)NULL, _IOLBF, 0); + + s_buffer[BUFSIZE] = '\0'; + + struct stat st; + + progname = argv[0]; + + if (argc > 2) { + usage(); + } + else if (argc == 2) + { + if (argv[1][0] == '-') { + usage(); + } + bundle_dir = (char *) argv[1]; + } + else + { + bundle_dir = BUNDLE_DIR_DEFAULT; + } + + if (access(bundle_dir, W_OK | X_OK) == -1) { + fprintf(stderr, "can't access directory '%s': %s\n", + bundle_dir, strerror(errno)); + usage(); + } + + if (stat(bundle_dir, &st) == -1) { + fprintf(stderr, "can't stat directory '%s': %s\n", + bundle_dir, strerror(errno)); + usage(); + } + + if (!S_ISDIR(st.st_mode)) { + fprintf(stderr, "path '%s' is not a directory\n", + bundle_dir); + usage(); + } + + // open the ipc handle + if (debug) printf("opening connection to dtn router...\n"); + int err = dtn_open(&handle); + if (err != DTN_SUCCESS) { + fprintf(stderr, "fatal error opening dtn handle: %s\n", + dtn_strerror(err)); + exit(1); + } + + // build a local eid based on the configuration of our dtn + // router plus the demux string + endpoint_demux = "/dtncp/recv?file=*"; + dtn_build_local_eid(handle, &local_eid, endpoint_demux); + if (debug) printf("local_eid [%s]\n", local_eid.uri); + + // try to find an existin registration, or create a new + // registration based on this eid + ret = dtn_find_registration(handle, &local_eid, ®id); + if (ret == 0) { + if (debug) printf("dtn_find_registration succeeded, regid 0x%x\n", + regid); + + // bind the current handle to the new registration + dtn_bind(handle, regid); + + } else if (dtn_errno(handle) == DTN_ENOTFOUND) { + memset(®info, 0, sizeof(reginfo)); + dtn_copy_eid(®info.endpoint, &local_eid); + reginfo.flags = DTN_REG_DEFER; + reginfo.regid = DTN_REGID_NONE; + reginfo.expiration = 60 * 60; + if ((ret = dtn_register(handle, ®info, ®id)) != 0) { + fprintf(stderr, "error creating registration: %d (%s)\n", + ret, dtn_strerror(dtn_errno(handle))); + exit(1); + } + + if (debug) printf("dtn_register succeeded, regid 0x%x\n", regid); + + } else { + fprintf(stderr, "error in dtn_find_registration: %s", + dtn_strerror(dtn_errno(handle))); + exit(1); + } + + // loop waiting for bundles + while(1) + { + // change this to _MEM here to receive into memory then write the file + // ourselves. (So this code shows both ways to do it.) + // XXX/demmer better would be to have a cmd line option + dtn_bundle_payload_location_t file_or_mem = DTN_PAYLOAD_FILE; + + memset(&bundle, 0, sizeof(bundle)); + memset(&payload, 0, sizeof(payload)); + memset(&dirpath, 0, sizeof(dirpath)); + memset(&filename, 0, sizeof(filename)); + memset(&filepath, 0, sizeof(filepath)); + memset(&host, 0, sizeof(host)); + memset(&st, 0, sizeof(st)); + + printf("dtn_recv [%s]...\n", local_eid.uri); + + if ((ret = dtn_recv(handle, &bundle, + file_or_mem, &payload, -1)) < 0) + { + fprintf(stderr, "error getting recv reply: %d (%s)\n", + ret, dtn_strerror(dtn_errno(handle))); + exit(1); + } + + // mark time received + current = time(NULL); + + if (strncmp(bundle.source.uri, "dtn://", 6) != 0) + { + fprintf(stderr, "bundle source uri '%s' must be a dtn:// uri\n", + bundle.source.uri); + exit(1); + } + + // grab the sending authority and service tag (i.e. the path) + host_len = strchr(&bundle.source.uri[6], '/') - &bundle.source.uri[6]; + strncpy(host, &bundle.source.uri[6], host_len); + + // extract directory from destination path (everything + // following std demux, except the '*') + endpoint_demux = "/dtncp/recv?file="; + dirpath = strstr(bundle.dest.uri, endpoint_demux); + if (!dirpath) { + fprintf(stderr, "can't find %s demux in uri '%s'\n", + endpoint_demux, bundle.dest.uri); + exit(1); + } + + dirpath += strlen(endpoint_demux); // skip std demux + if (dirpath[0] == '/') dirpath++; // skip leading slash + + // filename is everything following last / + filename = strrchr(dirpath, '/'); + if (filename == 0) + { + filename = dirpath; + dirpath = ""; + } + else + { + filename[0] = '\0'; // null terminate path + filename++; // next char; + } + + // recursively create full directory path + // XXX/demmer system -- yuck! + sprintf(filepath, "mkdir -p %s/%s/%s", bundle_dir, host, dirpath); + system(filepath); + + // create file name + sprintf(filepath, "%s/%s/%s/%s", bundle_dir, host, dirpath, filename); + + // bundle name is the name of the bundle payload file + buffer = payload.filename.filename_val; + // bufsize is the length of the payload file (not what we want to print) + bufsize = payload.filename.filename_len; + // st contains (among other things) size of payload file + ret = stat(buffer, &st); + + printf ("======================================\n"); + printf (" File Received at %s\n", ctime(¤t)); + printf (" host : %s\n", host); + printf (" path : %s\n", dirpath); + printf (" file : %s\n", filename); + printf (" loc : %s\n", filepath); + printf (" size : %d bytes\n", (int) st.st_size); + + + if (file_or_mem == DTN_PAYLOAD_FILE) { + int cmdlen = 5 + strlen(buffer) + strlen(filepath); + char *cmd = malloc(cmdlen); + + if (cmd) { + snprintf(cmd, cmdlen, "mv %.*s %s", bufsize, buffer, + filepath); + system(cmd); + printf("Moving payload to final filename: '%s'\n", cmd); + free(cmd); + } else { + printf("Out of memory. Find file in %*s.\n", bufsize, + buffer); + } + } else { + + target = fopen(filepath, "w"); + + if (target == NULL) + { + fprintf(stderr, "Error opening file for writing %s\n", + filepath); + continue; + } + if (debug) printf ("--------------------------------------\n"); + + marker = 0; + while (marker < bufsize) + { + // write 256 bytes at a time + i=0; + maxwrite = (marker + 256) > bufsize? bufsize-marker : 256; + while (i < maxwrite) + { + i += fwrite(buffer + marker + i, 1, maxwrite - i, target); + } + + if (debug) + { + for (i=0; i < maxwrite; i++) + { + if (buffer[marker] >= ' ' && buffer[marker] <= '~') + s_buffer[marker%BUFSIZE] = buffer[i]; + else + s_buffer[marker%BUFSIZE] = '.'; + + if (marker%BUFSIZE == 0) // new line every 16 bytes + { + printf("%07x ", marker); + } + else if (marker%2 == 0) + { + printf(" "); // space every 2 bytes + } + + printf("%02x", buffer[i] & 0xff); + + // print character summary (a la emacs hexl-mode) + if (marker%BUFSIZE == BUFSIZE-1) + { + printf(" | %s\n", s_buffer); + } + marker ++; + } + } + else + { + marker += maxwrite; + } + } + + fclose(target); + + // round off last line + if (debug && marker % BUFSIZE != 0) + { + while (marker % BUFSIZE !=0) + { + s_buffer[marker%BUFSIZE] = ' '; + + if (marker%2 == 0) + { + printf(" "); // space every 2 bytes + } + + printf(" "); + + // print character summary (a la emacs hexl-mode) + if (marker%BUFSIZE == BUFSIZE-1) + { + printf(" | %s\n", s_buffer); + } + marker ++; + } + } + printf (" size : %d bytes\n", bufsize); + } + + printf ("======================================\n"); + dtn_free_payload(&payload); + } + + dtn_close(handle); + + return 0; +}