apps/dtncpd/dtncpd.c
changeset 0 2b3e5ec03512
equal deleted inserted replaced
-1:000000000000 0:2b3e5ec03512
       
     1 /*
       
     2  *    Copyright 2004-2006 Intel Corporation
       
     3  * 
       
     4  *    Licensed under the Apache License, Version 2.0 (the "License");
       
     5  *    you may not use this file except in compliance with the License.
       
     6  *    You may obtain a copy of the License at
       
     7  * 
       
     8  *        http://www.apache.org/licenses/LICENSE-2.0
       
     9  * 
       
    10  *    Unless required by applicable law or agreed to in writing, software
       
    11  *    distributed under the License is distributed on an "AS IS" BASIS,
       
    12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       
    13  *    See the License for the specific language governing permissions and
       
    14  *    limitations under the License.
       
    15  */
       
    16 
       
    17 #ifdef HAVE_CONFIG_H
       
    18 #  include <dtn-config.h>
       
    19 #endif
       
    20 
       
    21 #include <stdio.h>
       
    22 #include <stdlib.h>
       
    23 #include <string.h>
       
    24 #include <strings.h>
       
    25 #include <time.h>
       
    26 #include <unistd.h>
       
    27 #include <errno.h>
       
    28 #include <sys/types.h>
       
    29 #include <sys/stat.h>
       
    30 #include <sys/time.h>
       
    31 #include "dtn_api.h"
       
    32 
       
    33 #define BUFSIZE 16
       
    34 #define BUNDLE_DIR_DEFAULT INSTALL_LOCALSTATEDIR "/dtn/dtncpd-incoming"
       
    35 
       
    36 static const char *progname;
       
    37 
       
    38 void
       
    39 usage()
       
    40 {
       
    41     fprintf(stderr, "usage: %s [ directory ]\n", progname);
       
    42     fprintf(stderr, "    optional directory parameter is where incoming "
       
    43                     "files will get put\n");
       
    44     fprintf(stderr, "    (defaults to: %s)\n", BUNDLE_DIR_DEFAULT);
       
    45     exit(1);
       
    46 }
       
    47 
       
    48 int
       
    49 main(int argc, const char** argv)
       
    50 {
       
    51     int i;
       
    52     int ret;
       
    53     dtn_handle_t handle;
       
    54     dtn_endpoint_id_t local_eid;
       
    55     dtn_reg_info_t reginfo;
       
    56     dtn_reg_id_t regid;
       
    57     dtn_bundle_spec_t bundle;
       
    58     dtn_bundle_payload_t payload;
       
    59     const char* endpoint_demux;
       
    60     int debug = 1;
       
    61 
       
    62     char * bundle_dir = 0;
       
    63 
       
    64     char host[PATH_MAX];
       
    65     int host_len;
       
    66     char * dirpath;
       
    67     char * filename;
       
    68     char filepath[PATH_MAX];
       
    69     time_t current;
       
    70 
       
    71     char * buffer;
       
    72     char s_buffer[BUFSIZE + 1];
       
    73 
       
    74     int bufsize, marker, maxwrite;
       
    75 
       
    76     FILE * target;
       
    77 
       
    78     // force stdout to always be line buffered, even if output is
       
    79     // redirected to a pipe or file
       
    80     setvbuf(stdout, (char *)NULL, _IOLBF, 0);
       
    81     
       
    82     s_buffer[BUFSIZE] = '\0';
       
    83 
       
    84     struct stat st;
       
    85 
       
    86     progname = argv[0];
       
    87     
       
    88     if (argc > 2) {
       
    89         usage();
       
    90     }
       
    91     else if (argc == 2)
       
    92     {
       
    93         if (argv[1][0] == '-') {
       
    94             usage();
       
    95         }
       
    96         bundle_dir = (char *) argv[1];
       
    97     }
       
    98     else
       
    99     {
       
   100         bundle_dir = BUNDLE_DIR_DEFAULT;
       
   101     }
       
   102 
       
   103     if (access(bundle_dir, W_OK | X_OK) == -1) {
       
   104         fprintf(stderr, "can't access directory '%s': %s\n",
       
   105                 bundle_dir, strerror(errno));
       
   106         usage();
       
   107     }
       
   108 
       
   109     if (stat(bundle_dir, &st) == -1) { 
       
   110         fprintf(stderr, "can't stat directory '%s': %s\n",
       
   111                 bundle_dir, strerror(errno));
       
   112         usage();
       
   113     }
       
   114 
       
   115     if (!S_ISDIR(st.st_mode)) {
       
   116         fprintf(stderr, "path '%s' is not a directory\n",
       
   117                 bundle_dir);
       
   118         usage();
       
   119     }
       
   120 
       
   121     // open the ipc handle
       
   122     if (debug) printf("opening connection to dtn router...\n");
       
   123     int err = dtn_open(&handle);
       
   124     if (err != DTN_SUCCESS) {
       
   125         fprintf(stderr, "fatal error opening dtn handle: %s\n",
       
   126                 dtn_strerror(err));
       
   127         exit(1);
       
   128     }
       
   129 
       
   130     // build a local eid based on the configuration of our dtn
       
   131     // router plus the demux string
       
   132     endpoint_demux = "/dtncp/recv?file=*";
       
   133     dtn_build_local_eid(handle, &local_eid, endpoint_demux);
       
   134     if (debug) printf("local_eid [%s]\n", local_eid.uri);
       
   135 
       
   136     // try to find an existin registration, or create a new
       
   137     // registration based on this eid
       
   138     ret = dtn_find_registration(handle, &local_eid, &regid);
       
   139     if (ret == 0) {
       
   140         if (debug) printf("dtn_find_registration succeeded, regid 0x%x\n",
       
   141                           regid);
       
   142         
       
   143         // bind the current handle to the new registration
       
   144         dtn_bind(handle, regid);
       
   145         
       
   146     } else if (dtn_errno(handle) == DTN_ENOTFOUND) {
       
   147         memset(&reginfo, 0, sizeof(reginfo));
       
   148         dtn_copy_eid(&reginfo.endpoint, &local_eid);
       
   149         reginfo.flags = DTN_REG_DEFER;
       
   150         reginfo.regid = DTN_REGID_NONE;
       
   151         reginfo.expiration = 60 * 60;
       
   152         if ((ret = dtn_register(handle, &reginfo, &regid)) != 0) {
       
   153             fprintf(stderr, "error creating registration: %d (%s)\n",
       
   154                     ret, dtn_strerror(dtn_errno(handle)));
       
   155             exit(1);
       
   156         }
       
   157     
       
   158         if (debug) printf("dtn_register succeeded, regid 0x%x\n", regid);
       
   159 
       
   160     } else {
       
   161         fprintf(stderr, "error in dtn_find_registration: %s",
       
   162                 dtn_strerror(dtn_errno(handle)));
       
   163         exit(1);
       
   164     }
       
   165     
       
   166     // loop waiting for bundles
       
   167     while(1)
       
   168     {
       
   169         // change this to _MEM here to receive into memory then write the file
       
   170         // ourselves. (So this code shows both ways to do it.)
       
   171         // XXX/demmer better would be to have a cmd line option
       
   172         dtn_bundle_payload_location_t file_or_mem = DTN_PAYLOAD_FILE;
       
   173 
       
   174         memset(&bundle, 0, sizeof(bundle));
       
   175         memset(&payload, 0, sizeof(payload));
       
   176         memset(&dirpath, 0, sizeof(dirpath));
       
   177         memset(&filename, 0, sizeof(filename));
       
   178         memset(&filepath, 0, sizeof(filepath));
       
   179         memset(&host, 0, sizeof(host));
       
   180         memset(&st, 0, sizeof(st));
       
   181         
       
   182         printf("dtn_recv [%s]...\n", local_eid.uri);
       
   183     
       
   184         if ((ret = dtn_recv(handle, &bundle,
       
   185                             file_or_mem, &payload, -1)) < 0)
       
   186         {
       
   187             fprintf(stderr, "error getting recv reply: %d (%s)\n",
       
   188                     ret, dtn_strerror(dtn_errno(handle)));
       
   189             exit(1);
       
   190         }
       
   191 
       
   192         // mark time received
       
   193         current = time(NULL);
       
   194 
       
   195         if (strncmp(bundle.source.uri, "dtn://", 6) != 0)
       
   196         {
       
   197             fprintf(stderr, "bundle source uri '%s' must be a dtn:// uri\n",
       
   198                     bundle.source.uri);
       
   199             exit(1);
       
   200         }
       
   201 
       
   202         // grab the sending authority and service tag (i.e. the path)
       
   203         host_len = strchr(&bundle.source.uri[6], '/') - &bundle.source.uri[6];
       
   204         strncpy(host, &bundle.source.uri[6], host_len);
       
   205         
       
   206         // extract directory from destination path (everything
       
   207         // following std demux, except the '*')
       
   208         endpoint_demux = "/dtncp/recv?file=";
       
   209         dirpath = strstr(bundle.dest.uri, endpoint_demux);
       
   210         if (!dirpath) {
       
   211             fprintf(stderr, "can't find %s demux in uri '%s'\n",
       
   212                     endpoint_demux, bundle.dest.uri);
       
   213             exit(1);
       
   214         }
       
   215         
       
   216         dirpath += strlen(endpoint_demux); // skip std demux
       
   217         if (dirpath[0] == '/') dirpath++; // skip leading slash
       
   218 
       
   219         // filename is everything following last /
       
   220         filename = strrchr(dirpath, '/');
       
   221         if (filename == 0)
       
   222         {
       
   223             filename = dirpath;
       
   224             dirpath = "";
       
   225         }
       
   226         else
       
   227         {
       
   228             filename[0] = '\0'; // null terminate path
       
   229             filename++; // next char;
       
   230         }
       
   231 
       
   232         // recursively create full directory path
       
   233         // XXX/demmer system -- yuck!
       
   234         sprintf(filepath, "mkdir -p %s/%s/%s", bundle_dir, host, dirpath);
       
   235         system(filepath);
       
   236         
       
   237         // create file name
       
   238         sprintf(filepath, "%s/%s/%s/%s", bundle_dir, host, dirpath, filename);
       
   239         
       
   240         // bundle name is the name of the bundle payload file
       
   241         buffer = payload.filename.filename_val;
       
   242         // bufsize is the length of the payload file (not what we want to print)
       
   243         bufsize = payload.filename.filename_len;
       
   244         // st contains (among other things) size of payload file
       
   245         ret = stat(buffer, &st);
       
   246 
       
   247         printf ("======================================\n");
       
   248         printf (" File Received at %s\n", ctime(&current));
       
   249         printf ("   host   : %s\n", host);
       
   250         printf ("   path   : %s\n", dirpath);
       
   251         printf ("   file   : %s\n", filename);
       
   252         printf ("   loc    : %s\n", filepath);
       
   253         printf ("   size   : %d bytes\n", (int) st.st_size);
       
   254         
       
   255 
       
   256         if (file_or_mem == DTN_PAYLOAD_FILE) {
       
   257             int cmdlen = 5 + strlen(buffer) + strlen(filepath);
       
   258             char *cmd = malloc(cmdlen);
       
   259 
       
   260             if (cmd) {
       
   261                 snprintf(cmd, cmdlen, "mv %.*s %s", bufsize, buffer,
       
   262                          filepath);
       
   263                 system(cmd);
       
   264                 printf("Moving payload to final filename: '%s'\n", cmd);
       
   265                 free(cmd);
       
   266             } else {
       
   267                 printf("Out of memory. Find file in %*s.\n", bufsize,
       
   268                         buffer);
       
   269             }
       
   270         } else {
       
   271 
       
   272             target = fopen(filepath, "w");
       
   273 
       
   274             if (target == NULL)
       
   275             {
       
   276                 fprintf(stderr, "Error opening file for writing %s\n",
       
   277                          filepath);
       
   278                 continue;
       
   279             }
       
   280             if (debug) printf ("--------------------------------------\n");
       
   281         
       
   282             marker = 0;
       
   283             while (marker < bufsize)
       
   284             {
       
   285                 // write 256 bytes at a time
       
   286                 i=0;
       
   287                 maxwrite = (marker + 256) > bufsize? bufsize-marker : 256;
       
   288                 while (i < maxwrite)
       
   289                 {
       
   290                     i += fwrite(buffer + marker + i, 1, maxwrite - i, target);
       
   291                 }
       
   292             
       
   293                 if (debug)
       
   294                 {
       
   295                     for (i=0; i < maxwrite; i++)
       
   296                     {
       
   297                         if (buffer[marker] >= ' ' && buffer[marker] <= '~')
       
   298                             s_buffer[marker%BUFSIZE] = buffer[i];
       
   299                         else
       
   300                             s_buffer[marker%BUFSIZE] = '.';
       
   301                     
       
   302                         if (marker%BUFSIZE == 0) // new line every 16 bytes
       
   303                         {
       
   304                             printf("%07x ", marker);
       
   305                         }
       
   306                         else if (marker%2 == 0)
       
   307                         {
       
   308                             printf(" "); // space every 2 bytes
       
   309                         }
       
   310                     
       
   311                         printf("%02x", buffer[i] & 0xff);
       
   312                     
       
   313                         // print character summary (a la emacs hexl-mode)
       
   314                         if (marker%BUFSIZE == BUFSIZE-1)
       
   315                         {
       
   316                             printf(" |  %s\n", s_buffer);
       
   317                         }
       
   318                         marker ++;
       
   319                     }
       
   320                 }
       
   321                 else
       
   322                 {
       
   323                     marker += maxwrite;
       
   324                 }
       
   325             }
       
   326     
       
   327             fclose(target);
       
   328     
       
   329             // round off last line
       
   330             if (debug && marker % BUFSIZE != 0)
       
   331             {
       
   332                 while (marker % BUFSIZE !=0)
       
   333                 {
       
   334                     s_buffer[marker%BUFSIZE] = ' ';
       
   335     
       
   336                     if (marker%2 == 0)
       
   337                     {
       
   338                         printf(" "); // space every 2 bytes
       
   339                     }
       
   340                         
       
   341                     printf("  ");
       
   342                         
       
   343                     // print character summary (a la emacs hexl-mode)
       
   344                     if (marker%BUFSIZE == BUFSIZE-1)
       
   345                     {
       
   346                         printf(" |  %s\n", s_buffer);
       
   347                     }
       
   348                     marker ++;
       
   349                 }
       
   350             }
       
   351             printf ("   size   : %d bytes\n", bufsize);
       
   352         }
       
   353     
       
   354         printf ("======================================\n");
       
   355         dtn_free_payload(&payload);
       
   356     }
       
   357 
       
   358     dtn_close(handle);
       
   359     
       
   360     return 0;
       
   361 }