dtncpd.c

Go to the documentation of this file.
00001 /*
00002  *    Copyright 2004-2006 Intel Corporation
00003  * 
00004  *    Licensed under the Apache License, Version 2.0 (the "License");
00005  *    you may not use this file except in compliance with the License.
00006  *    You may obtain a copy of the License at
00007  * 
00008  *        http://www.apache.org/licenses/LICENSE-2.0
00009  * 
00010  *    Unless required by applicable law or agreed to in writing, software
00011  *    distributed under the License is distributed on an "AS IS" BASIS,
00012  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  *    See the License for the specific language governing permissions and
00014  *    limitations under the License.
00015  */
00016 
00017 
00018 #include <stdio.h>
00019 #include <stdlib.h>
00020 #include <string.h>
00021 #include <strings.h>
00022 #include <time.h>
00023 #include <unistd.h>
00024 #include <errno.h>
00025 #include <sys/types.h>
00026 #include <sys/stat.h>
00027 #include <sys/time.h>
00028 #include "dtn_api.h"
00029 
00030 #define BUFSIZE 16
00031 #define BUNDLE_DIR_DEFAULT "/var/lib/dtn/dtncpd-incoming"
00032 
00033 static const char *progname;
00034 
00035 void
00036 usage()
00037 {
00038     fprintf(stderr, "usage: %s [ directory ]\n", progname);
00039     fprintf(stderr, "    optional directory parameter is where incoming "
00040                     "files will get put\n");
00041     fprintf(stderr, "    (defaults to: %s)\n", BUNDLE_DIR_DEFAULT);
00042     exit(1);
00043 }
00044 
00045 int
00046 main(int argc, const char** argv)
00047 {
00048     int i;
00049     int ret;
00050     dtn_handle_t handle;
00051     dtn_endpoint_id_t local_eid;
00052     dtn_reg_info_t reginfo;
00053     dtn_reg_id_t regid;
00054     dtn_bundle_spec_t bundle;
00055     dtn_bundle_payload_t payload;
00056     char* endpoint;
00057     int debug = 1;
00058 
00059     char * bundle_dir = 0;
00060 
00061     char host[PATH_MAX];
00062     int host_len;
00063     char * dirpath;
00064     char * filename;
00065     char filepath[PATH_MAX];
00066     time_t current;
00067 
00068     char * buffer;
00069     char s_buffer[BUFSIZE + 1];
00070 
00071     int bufsize, marker, maxwrite;
00072 
00073     FILE * target;
00074 
00075     // force stdout to always be line buffered, even if output is
00076     // redirected to a pipe or file
00077     setvbuf(stdout, (char *)NULL, _IOLBF, 0);
00078     
00079     s_buffer[BUFSIZE] = '\0';
00080 
00081     struct stat st;
00082 
00083     progname = argv[0];
00084     
00085     if (argc > 2) {
00086         usage();
00087     }
00088     else if (argc == 2)
00089     {
00090         if (argv[1][0] == '-') {
00091             usage();
00092         }
00093         bundle_dir = (char *) argv[1];
00094     }
00095     else
00096     {
00097         bundle_dir = BUNDLE_DIR_DEFAULT;
00098     }
00099 
00100     if (access(bundle_dir, W_OK | X_OK) == -1) {
00101         fprintf(stderr, "can't access directory '%s': %s\n",
00102                 bundle_dir, strerror(errno));
00103         usage();
00104     }
00105 
00106     if (stat(bundle_dir, &st) == -1) { 
00107         fprintf(stderr, "can't stat directory '%s': %s\n",
00108                 bundle_dir, strerror(errno));
00109         usage();
00110     }
00111 
00112     if (!S_ISDIR(st.st_mode)) {
00113         fprintf(stderr, "path '%s' is not a directory\n",
00114                 bundle_dir);
00115         usage();
00116     }
00117 
00118     // designated endpoint
00119     endpoint = "/dtncp/recv?*";
00120 
00121     // open the ipc handle
00122     if (debug) printf("opening connection to dtn router...\n");
00123     int err = dtn_open(&handle);
00124     if (err != DTN_SUCCESS) {
00125         fprintf(stderr, "fatal error opening dtn handle: %s\n",
00126                 dtn_strerror(err));
00127         exit(1);
00128     }
00129 
00130     // build a local eid based on the configuration of our dtn
00131     // router plus the demux string
00132     dtn_build_local_eid(handle, &local_eid, endpoint);
00133     if (debug) printf("local_eid [%s]\n", local_eid.uri);
00134 
00135     // try to find an existin registration, or create a new
00136     // registration based on this eid
00137     ret = dtn_find_registration(handle, &local_eid, &regid);
00138     if (ret == 0) {
00139         if (debug) printf("dtn_find_registration succeeded, regid 0x%x\n",
00140                           regid);
00141         
00142         // bind the current handle to the new registration
00143         dtn_bind(handle, regid);
00144         
00145     } else if (dtn_errno(handle) == DTN_ENOTFOUND) {
00146         memset(&reginfo, 0, sizeof(reginfo));
00147         dtn_copy_eid(&reginfo.endpoint, &local_eid);
00148         reginfo.failure_action = DTN_REG_DEFER;
00149         reginfo.regid = DTN_REGID_NONE;
00150         reginfo.expiration = 60 * 60;
00151         if ((ret = dtn_register(handle, &reginfo, &regid)) != 0) {
00152             fprintf(stderr, "error creating registration: %d (%s)\n",
00153                     ret, dtn_strerror(dtn_errno(handle)));
00154             exit(1);
00155         }
00156     
00157         if (debug) printf("dtn_register succeeded, regid 0x%x\n", regid);
00158 
00159     } else {
00160         fprintf(stderr, "error in dtn_find_registration: %s",
00161                 dtn_strerror(dtn_errno(handle)));
00162         exit(1);
00163     }
00164     
00165     // loop waiting for bundles
00166     while(1)
00167     {
00168         // change this to _MEM here to receive into memory then write the file
00169         // ourselves. (So this code shows both ways to do it.)
00170         // XXX/demmer better would be to have a cmd line option
00171         dtn_bundle_payload_location_t file_or_mem = DTN_PAYLOAD_FILE;
00172 
00173         memset(&bundle, 0, sizeof(bundle));
00174         memset(&payload, 0, sizeof(payload));
00175         memset(&dirpath, 0, sizeof(dirpath));
00176         memset(&filename, 0, sizeof(filename));
00177         memset(&filepath, 0, sizeof(filepath));
00178         memset(&host, 0, sizeof(host));
00179         memset(&st, 0, sizeof(st));
00180         
00181         printf("dtn_recv [%s]...\n", local_eid.uri);
00182     
00183         if ((ret = dtn_recv(handle, &bundle,
00184                             file_or_mem, &payload, -1)) < 0)
00185         {
00186             fprintf(stderr, "error getting recv reply: %d (%s)\n",
00187                     ret, dtn_strerror(dtn_errno(handle)));
00188             exit(1);
00189         }
00190 
00191         // mark time received
00192         current = time(NULL);
00193 
00194         if (strncmp(bundle.source.uri, "dtn://", 6) != 0)
00195         {
00196             fprintf(stderr, "bundle source uri '%s' must be a dtn:// uri\n",
00197                     bundle.source.uri);
00198             exit(1);
00199         }
00200 
00201         // grab the sending authority and service tag (i.e. the path)
00202         host_len = strchr(&bundle.source.uri[6], '/') - &bundle.source.uri[6];
00203         strncpy(host, &bundle.source.uri[6], host_len);
00204         
00205         // extract directory from destination path (everything
00206         // following std demux)
00207         dirpath = strstr(bundle.dest.uri, "/dtncp/recv?");
00208         if (!dirpath) {
00209             fprintf(stderr, "can't find /dtncp/recv? in uri '%s'\n",
00210                     bundle.dest.uri);
00211             exit(1);
00212         }
00213         
00214         dirpath += 12; // skip /dtncp/recv?
00215         if (dirpath[0] == '/') dirpath++; // skip leading slash
00216 
00217         // filename is everything following last /
00218         filename = strrchr(dirpath, '/');
00219         if (filename == 0)
00220         {
00221             filename = dirpath;
00222             dirpath = "";
00223         }
00224         else
00225         {
00226             filename[0] = '\0'; // null terminate path
00227             filename++; // next char;
00228         }
00229 
00230         // recursively create full directory path
00231         // XXX/demmer system -- yuck!
00232         sprintf(filepath, "mkdir -p %s/%s/%s", bundle_dir, host, dirpath);
00233         system(filepath);
00234         
00235         // create file name
00236         sprintf(filepath, "%s/%s/%s/%s", bundle_dir, host, dirpath, filename);
00237         
00238         // bundle name is the name of the bundle payload file
00239         buffer = payload.buf.buf_val;
00240         // bufsize is the length of the payload file (not what we want to print)
00241         bufsize = payload.buf.buf_len;
00242         // st contains (among other things) size of payload file
00243         ret = stat(buffer, &st);
00244 
00245         printf ("======================================\n");
00246         printf (" File Received at %s\n", ctime(&current));
00247         printf ("   host   : %s\n", host);
00248         printf ("   path   : %s\n", dirpath);
00249         printf ("   file   : %s\n", filename);
00250         printf ("   loc    : %s\n", filepath);
00251         printf ("   size   : %d bytes\n", (int) st.st_size);
00252         
00253 
00254         if (file_or_mem == DTN_PAYLOAD_FILE) {
00255             int cmdlen = 5 + strlen(buffer) + strlen(filepath);
00256             char *cmd = malloc(cmdlen);
00257 
00258             if (cmd) {
00259                 snprintf(cmd, cmdlen, "mv %.*s %s", bufsize, buffer,
00260                          filepath);
00261                 system(cmd);
00262                 printf("Moving payload to final filename: '%s'\n", cmd);
00263                 free(cmd);
00264             } else {
00265                 printf("Out of memory. Find file in %*s.\n", bufsize,
00266                         buffer);
00267             }
00268         } else {
00269 
00270             target = fopen(filepath, "w");
00271 
00272             if (target == NULL)
00273             {
00274                 fprintf(stderr, "Error opening file for writing %s\n",
00275                          filepath);
00276                 continue;
00277             }
00278             if (debug) printf ("--------------------------------------\n");
00279         
00280             marker = 0;
00281             while (marker < bufsize)
00282             {
00283                 // write 256 bytes at a time
00284                 i=0;
00285                 maxwrite = (marker + 256) > bufsize? bufsize-marker : 256;
00286                 while (i < maxwrite)
00287                 {
00288                     i += fwrite(buffer + marker + i, 1, maxwrite - i, target);
00289                 }
00290             
00291                 if (debug)
00292                 {
00293                     for (i=0; i < maxwrite; i++)
00294                     {
00295                         if (buffer[marker] >= ' ' && buffer[marker] <= '~')
00296                             s_buffer[marker%BUFSIZE] = buffer[i];
00297                         else
00298                             s_buffer[marker%BUFSIZE] = '.';
00299                     
00300                         if (marker%BUFSIZE == 0) // new line every 16 bytes
00301                         {
00302                             printf("%07x ", marker);
00303                         }
00304                         else if (marker%2 == 0)
00305                         {
00306                             printf(" "); // space every 2 bytes
00307                         }
00308                     
00309                         printf("%02x", buffer[i] & 0xff);
00310                     
00311                         // print character summary (a la emacs hexl-mode)
00312                         if (marker%BUFSIZE == BUFSIZE-1)
00313                         {
00314                             printf(" |  %s\n", s_buffer);
00315                         }
00316                         marker ++;
00317                     }
00318                 }
00319                 else
00320                 {
00321                     marker += maxwrite;
00322                 }
00323             }
00324     
00325             fclose(target);
00326     
00327             // round off last line
00328             if (debug && marker % BUFSIZE != 0)
00329             {
00330                 while (marker % BUFSIZE !=0)
00331                 {
00332                     s_buffer[marker%BUFSIZE] = ' ';
00333     
00334                     if (marker%2 == 0)
00335                     {
00336                         printf(" "); // space every 2 bytes
00337                     }
00338                         
00339                     printf("  ");
00340                         
00341                     // print character summary (a la emacs hexl-mode)
00342                     if (marker%BUFSIZE == BUFSIZE-1)
00343                     {
00344                         printf(" |  %s\n", s_buffer);
00345                     }
00346                     marker ++;
00347                 }
00348             }
00349             printf ("   size   : %d bytes\n", bufsize);
00350         }
00351     
00352         printf ("======================================\n");
00353         dtn_free_payload(&payload);
00354     }
00355 
00356     dtn_close(handle);
00357     
00358     return 0;
00359 }

Generated on Sat Sep 8 08:36:16 2007 for DTN Reference Implementation by  doxygen 1.5.3