dtncpd.c

Go to the documentation of this file.
00001 /*
00002  * IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By
00003  * downloading, copying, installing or using the software you agree to
00004  * this license. If you do not agree to this license, do not download,
00005  * install, copy or use the software.
00006  * 
00007  * Intel Open Source License 
00008  * 
00009  * Copyright (c) 2004 Intel Corporation. All rights reserved. 
00010  * 
00011  * Redistribution and use in source and binary forms, with or without
00012  * modification, are permitted provided that the following conditions are
00013  * met:
00014  * 
00015  *   Redistributions of source code must retain the above copyright
00016  *   notice, this list of conditions and the following disclaimer.
00017  * 
00018  *   Redistributions in binary form must reproduce the above copyright
00019  *   notice, this list of conditions and the following disclaimer in the
00020  *   documentation and/or other materials provided with the distribution.
00021  * 
00022  *   Neither the name of the Intel Corporation nor the names of its
00023  *   contributors may be used to endorse or promote products derived from
00024  *   this software without specific prior written permission.
00025  *  
00026  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00027  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00028  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00029  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL OR
00030  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00031  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00032  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00033  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00034  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00035  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00036  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00037  */
00038 
00039 #include <stdio.h>
00040 #include <stdlib.h>
00041 #include <string.h>
00042 #include <strings.h>
00043 #include <time.h>
00044 #include <unistd.h>
00045 #include <errno.h>
00046 #include <sys/types.h>
00047 #include <sys/stat.h>
00048 #include <sys/time.h>
00049 #include "dtn_api.h"
00050 
00051 #define BUFSIZE 16
00052 #define BUNDLE_DIR_DEFAULT "/var/lib/dtn/dtncpd-incoming"
00053 
00054 static const char *progname;
00055 
00056 void
00057 usage()
00058 {
00059     fprintf(stderr, "usage: %s [ directory ]\n", progname);
00060     fprintf(stderr, "    optional directory parameter is where incoming "
00061                     "files will get put\n");
00062     fprintf(stderr, "    (defaults to: %s)\n", BUNDLE_DIR_DEFAULT);
00063     exit(1);
00064 }
00065 
00066 int
00067 main(int argc, const char** argv)
00068 {
00069     int i;
00070     int ret;
00071     dtn_handle_t handle;
00072     dtn_endpoint_id_t local_eid;
00073     dtn_reg_info_t reginfo;
00074     dtn_reg_id_t regid;
00075     dtn_bundle_spec_t bundle;
00076     dtn_bundle_payload_t payload;
00077     char* endpoint;
00078     int debug = 1;
00079 
00080     char * bundle_dir = 0;
00081 
00082     char host[PATH_MAX];
00083     int host_len;
00084     char * dirpath;
00085     char * filename;
00086     char filepath[PATH_MAX];
00087     time_t current;
00088 
00089     char * buffer;
00090     char s_buffer[BUFSIZE + 1];
00091 
00092     int bufsize, marker, maxwrite;
00093 
00094     FILE * target;
00095 
00096     // force stdout to always be line buffered, even if output is
00097     // redirected to a pipe or file
00098     setvbuf(stdout, (char *)NULL, _IOLBF, 0);
00099     
00100     s_buffer[BUFSIZE] = '\0';
00101 
00102     struct stat st;
00103 
00104     progname = argv[0];
00105     
00106     if (argc > 2) {
00107         usage();
00108     }
00109     else if (argc == 2)
00110     {
00111         if (argv[1][0] == '-') {
00112             usage();
00113         }
00114         bundle_dir = (char *) argv[1];
00115     }
00116     else
00117     {
00118         bundle_dir = BUNDLE_DIR_DEFAULT;
00119     }
00120 
00121     if (access(bundle_dir, W_OK | X_OK) == -1) {
00122         fprintf(stderr, "can't access directory '%s': %s\n",
00123                 bundle_dir, strerror(errno));
00124         usage();
00125     }
00126 
00127     if (stat(bundle_dir, &st) == -1) { 
00128         fprintf(stderr, "can't stat directory '%s': %s\n",
00129                 bundle_dir, strerror(errno));
00130         usage();
00131     }
00132 
00133     if (!S_ISDIR(st.st_mode)) {
00134         fprintf(stderr, "path '%s' is not a directory\n",
00135                 bundle_dir);
00136         usage();
00137     }
00138 
00139     // designated endpoint
00140     endpoint = "/dtncp/recv?*";
00141 
00142     // open the ipc handle
00143     if (debug) printf("opening connection to dtn router...\n");
00144     int err = dtn_open(&handle);
00145     if (err != DTN_SUCCESS) {
00146         fprintf(stderr, "fatal error opening dtn handle: %s\n",
00147                 dtn_strerror(err));
00148         exit(1);
00149     }
00150 
00151     // build a local eid based on the configuration of our dtn
00152     // router plus the demux string
00153     dtn_build_local_eid(handle, &local_eid, endpoint);
00154     if (debug) printf("local_eid [%s]\n", local_eid.uri);
00155 
00156     // try to find an existin registration, or create a new
00157     // registration based on this eid
00158     ret = dtn_find_registration(handle, &local_eid, &regid);
00159     if (ret == 0) {
00160         if (debug) printf("dtn_find_registration succeeded, regid 0x%x\n",
00161                           regid);
00162         
00163         // bind the current handle to the new registration
00164         dtn_bind(handle, regid);
00165         
00166     } else if (dtn_errno(handle) == DTN_ENOTFOUND) {
00167         memset(&reginfo, 0, sizeof(reginfo));
00168         dtn_copy_eid(&reginfo.endpoint, &local_eid);
00169         reginfo.failure_action = DTN_REG_DEFER;
00170         reginfo.regid = DTN_REGID_NONE;
00171         reginfo.expiration = 60 * 60;
00172         if ((ret = dtn_register(handle, &reginfo, &regid)) != 0) {
00173             fprintf(stderr, "error creating registration: %d (%s)\n",
00174                     ret, dtn_strerror(dtn_errno(handle)));
00175             exit(1);
00176         }
00177     
00178         if (debug) printf("dtn_register succeeded, regid 0x%x\n", regid);
00179 
00180     } else {
00181         fprintf(stderr, "error in dtn_find_registration: %s",
00182                 dtn_strerror(dtn_errno(handle)));
00183         exit(1);
00184     }
00185     
00186     // loop waiting for bundles
00187     while(1)
00188     {
00189         // change this to _MEM here to receive into memory then write the file
00190         // ourselves. (So this code shows both ways to do it.)
00191         // XXX/demmer better would be to have a cmd line option
00192         dtn_bundle_payload_location_t file_or_mem = DTN_PAYLOAD_FILE;
00193 
00194         memset(&bundle, 0, sizeof(bundle));
00195         memset(&payload, 0, sizeof(payload));
00196         
00197         printf("dtn_recv [%s]...\n", local_eid.uri);
00198     
00199         if ((ret = dtn_recv(handle, &bundle,
00200                             file_or_mem, &payload, -1)) < 0)
00201         {
00202             fprintf(stderr, "error getting recv reply: %d (%s)\n",
00203                     ret, dtn_strerror(dtn_errno(handle)));
00204             exit(1);
00205         }
00206 
00207         // mark time received
00208         current = time(NULL);
00209 
00210         if (strncmp(bundle.source.uri, "dtn://", 6) != 0)
00211         {
00212             fprintf(stderr, "bundle source uri '%s' must be a dtn:// uri\n",
00213                     bundle.source.uri);
00214             exit(1);
00215         }
00216 
00217         // grab the sending authority and service tag (i.e. the path)
00218         host_len = strchr(&bundle.source.uri[6], '/') - &bundle.source.uri[6];
00219         strncpy(host, &bundle.source.uri[6], host_len);
00220         
00221         // extract directory from destination path (everything
00222         // following std demux)
00223         dirpath = strstr(bundle.dest.uri, "/dtncp/recv?");
00224         if (!dirpath) {
00225             fprintf(stderr, "can't find /dtncp/recv? in uri '%s'\n",
00226                     bundle.dest.uri);
00227             exit(1);
00228         }
00229         
00230         dirpath += 12; // skip /dtncp/recv?
00231         if (dirpath[0] == '/') dirpath++; // skip leading slash
00232 
00233         // filename is everything following last /
00234         filename = strrchr(dirpath, '/');
00235         if (filename == 0)
00236         {
00237             filename = dirpath;
00238             dirpath = "";
00239         }
00240         else
00241         {
00242             filename[0] = '\0'; // null terminate path
00243             filename++; // next char;
00244         }
00245 
00246         // recursively create full directory path
00247         // XXX/demmer system -- yuck!
00248         sprintf(filepath, "mkdir -p %s/%s/%s", bundle_dir, host, dirpath);
00249         system(filepath);
00250         
00251         // create file name
00252         sprintf(filepath, "%s/%s/%s/%s", bundle_dir, host, dirpath, filename);
00253         
00254         // bundle name is the name of the bundle payload file
00255         buffer = payload.dtn_bundle_payload_t_u.buf.buf_val;
00256         bufsize = payload.dtn_bundle_payload_t_u.buf.buf_len;
00257 
00258         printf ("======================================\n");
00259         printf (" File Received at %s\n", ctime(&current));
00260         printf ("   host   : %s\n", host);
00261         printf ("   path   : %s\n", dirpath);
00262         printf ("   file   : %s\n", filename);
00263         printf ("   size   : %d bytes\n", bufsize);
00264         printf ("   loc    : %s\n", filepath);
00265         
00266         if (debug) printf ("--------------------------------------\n");
00267 
00268         if (file_or_mem == DTN_PAYLOAD_FILE) {
00269             int cmdlen = 5 + strlen(buffer) + strlen(filepath);
00270             char *cmd = malloc(cmdlen);
00271 
00272             if (cmd) {
00273                 snprintf(cmd, cmdlen, "mv %.*s %s", bufsize, buffer,
00274                          filepath);
00275                 printf("Moving payload to final filename: '%s'\n", cmd);
00276                 system(cmd);
00277                 free(cmd);
00278             } else {
00279                 printf("Out of memory. Find file in %*s.\n", bufsize,
00280                         buffer);
00281             }
00282         } else {
00283 
00284             target = fopen(filepath, "w");
00285 
00286             if (target == NULL)
00287             {
00288                 fprintf(stderr, "Error opening file for writing %s\n",
00289                          filepath);
00290                 continue;
00291             }
00292         
00293             marker = 0;
00294             while (marker < bufsize)
00295             {
00296                 // write 256 bytes at a time
00297                 i=0;
00298                 maxwrite = (marker + 256) > bufsize? bufsize-marker : 256;
00299                 while (i < maxwrite)
00300                 {
00301                     i += fwrite(buffer + marker + i, 1, maxwrite - i, target);
00302                 }
00303             
00304                 if (debug)
00305                 {
00306                     for (i=0; i < maxwrite; i++)
00307                     {
00308                         if (buffer[marker] >= ' ' && buffer[marker] <= '~')
00309                             s_buffer[marker%BUFSIZE] = buffer[i];
00310                         else
00311                             s_buffer[marker%BUFSIZE] = '.';
00312                     
00313                         if (marker%BUFSIZE == 0) // new line every 16 bytes
00314                         {
00315                             printf("%07x ", marker);
00316                         }
00317                         else if (marker%2 == 0)
00318                         {
00319                             printf(" "); // space every 2 bytes
00320                         }
00321                     
00322                         printf("%02x", buffer[i] & 0xff);
00323                     
00324                         // print character summary (a la emacs hexl-mode)
00325                         if (marker%BUFSIZE == BUFSIZE-1)
00326                         {
00327                             printf(" |  %s\n", s_buffer);
00328                         }
00329                         marker ++;
00330                     }
00331                 }
00332                 else
00333                 {
00334                     marker += maxwrite;
00335                 }
00336             }
00337     
00338             fclose(target);
00339     
00340             // round off last line
00341             if (debug && marker % BUFSIZE != 0)
00342             {
00343                 while (marker % BUFSIZE !=0)
00344                 {
00345                     s_buffer[marker%BUFSIZE] = ' ';
00346     
00347                     if (marker%2 == 0)
00348                     {
00349                         printf(" "); // space every 2 bytes
00350                     }
00351                         
00352                     printf("  ");
00353                         
00354                     // print character summary (a la emacs hexl-mode)
00355                     if (marker%BUFSIZE == BUFSIZE-1)
00356                     {
00357                         printf(" |  %s\n", s_buffer);
00358                     }
00359                     marker ++;
00360                 }
00361             }
00362         }
00363     
00364         printf ("======================================\n");
00365     }
00366 
00367     dtn_close(handle);
00368     
00369     return 0;
00370 }

Generated on Fri Dec 22 14:47:58 2006 for DTN Reference Implementation by  doxygen 1.5.1