--- /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 <dtn-config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <time.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#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;
+}