• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

tools/src/dtntrigger.cpp

Go to the documentation of this file.
00001 /*
00002  * dtntrigger.cpp
00003  *
00004  *  Created on: 02.07.2010
00005  *      Author: morgenro
00006  */
00007 
00008 #include "config.h"
00009 #include <ibrdtn/api/Client.h>
00010 #include <ibrcommon/net/tcpclient.h>
00011 
00012 #include <ibrcommon/data/File.h>
00013 
00031 #include <csignal>
00032 #include <ctype.h>
00033 #include <stdio.h>
00034 #include <stdlib.h>
00035 #include <unistd.h>
00036 
00037 
00038 // set this variable to false to stop the app
00039 bool _running = true;
00040 
00041 // global connection
00042 ibrcommon::tcpclient *_conn = NULL;
00043 
00044 std::string _appname = "trigger";
00045 std::string _script = "";
00046 std::string _shell = "/bin/sh";
00047 
00048 void print_help()
00049 {
00050         cout << "-- dtntrigger (IBR-DTN) --" << endl;
00051         cout << "Syntax: dtntrigger [options] <name> <shell> [trigger-script]"  << endl;
00052         cout << "<name>            the application name" << endl;
00053         cout << "<shell>           shell to execute the trigger script" << endl;
00054         cout << "[trigger-script]  optional: the trigger script to execute on incoming bundle" << endl;
00055         cout << "* optional parameters *" << endl;
00056         cout << " -h|--help        display this text" << endl;
00057         cout << " -w|--workdir     temporary work directory" << endl;
00058 }
00059 
00060 int init(int argc, char** argv)
00061 {
00062         int index;
00063         int c;
00064 
00065         opterr = 0;
00066 
00067         while ((c = getopt (argc, argv, "w:")) != -1)
00068         switch (c)
00069         {
00070                 case 'w':
00071                         ibrcommon::BLOB::tmppath = ibrcommon::File(optarg);
00072                         break;
00073 
00074                 case '?':
00075                         if (optopt == 'w')
00076                         fprintf (stderr, "Option -%c requires an argument.\n", optopt);
00077                         else if (isprint (optopt))
00078                         fprintf (stderr, "Unknown option `-%c'.\n", optopt);
00079                         else
00080                         fprintf (stderr,
00081                                          "Unknown option character `\\x%x'.\n",
00082                                          optopt);
00083                         return 1;
00084 
00085                 default:
00086                         print_help();
00087                         abort();
00088         }
00089 
00090         int optindex = 0;
00091         for (index = optind; index < argc; index++)
00092         {
00093                 switch (optindex)
00094                 {
00095                 case 0:
00096                         _appname = std::string(argv[index]);
00097                         break;
00098 
00099                 case 1:
00100                         _shell = std::string(argv[index]);
00101                         break;
00102 
00103                 case 2:
00104                         _script = std::string(argv[index]);
00105                         break;
00106                 }
00107 
00108                 optindex++;
00109         }
00110 
00111         // print help if not enough parameters are set
00112         if (optindex < 2) { print_help(); exit(0); }
00113 
00114         return 0;
00115 }
00116 
00117 void term(int signal)
00118 {
00119         if (signal >= 1)
00120         {
00121                 _running = false;
00122                 if (_conn != NULL) _conn->close();
00123                 exit(0);
00124         }
00125 }
00126 
00127 /*
00128  * main application method
00129  */
00130 int main(int argc, char** argv)
00131 {
00132         // catch process signals
00133         signal(SIGINT, term);
00134         signal(SIGTERM, term);
00135 
00136         // read the configuration
00137         if (init(argc, argv) > 0)
00138         {
00139                 return (EXIT_FAILURE);
00140         }
00141 
00142         // backoff for reconnect
00143         size_t backoff = 2;
00144 
00145         // loop, if no stop if requested
00146         while (_running)
00147         {
00148                 try {
00149                         // Create a stream to the server using TCP.
00150                         ibrcommon::tcpclient conn("127.0.0.1", 4550);
00151 
00152                         // enable nodelay option
00153                         conn.enableNoDelay();
00154 
00155                         // set the connection globally
00156                         _conn = &conn;
00157 
00158                         // Initiate a client for synchronous receiving
00159                         dtn::api::Client client(_appname, conn);
00160 
00161                         // Connect to the server. Actually, this function initiate the
00162                         // stream protocol by starting the thread and sending the contact header.
00163                         client.connect();
00164 
00165                         // reset backoff if connected
00166                         backoff = 2;
00167 
00168                         // check the connection
00169                         while (_running)
00170                         {
00171                                 // receive the bundle
00172                                 dtn::api::Bundle b = client.getBundle();
00173 
00174                                 // get the reference to the blob
00175                                 ibrcommon::BLOB::Reference ref = b.getData();
00176 
00177                                 // get a temporary file name
00178                                 ibrcommon::TemporaryFile file(ibrcommon::BLOB::tmppath, "bundle");
00179 
00180                                 // write data to temporary file
00181                                 try {
00182                                         std::fstream out(file.getPath().c_str(), ios::out|ios::binary|ios::trunc);
00183                                         out.exceptions(std::ios::badbit | std::ios::eofbit);
00184                                         ibrcommon::Mutex l(ref);
00185                                         out << (*ref).rdbuf();
00186                                         out.close();
00187 
00188                                         // call the script
00189                                         std::string cmd = _shell + " " + _script + " " + b.getSource().getString() + " " + file.getPath();
00190                                         ::system(cmd.c_str());
00191 
00192                                         // remove temporary file
00193                                         file.remove();
00194                                 } catch (ios_base::failure ex) {
00195 
00196                                 }
00197                         }
00198 
00199                         // close the client connection
00200                         client.close();
00201 
00202                         // close the connection
00203                         conn.close();
00204 
00205                         // set the global connection to NULL
00206                         _conn = NULL;
00207                 } catch (const ibrcommon::tcpclient::SocketException&) {
00208                         // set the global connection to NULL
00209                         _conn = NULL;
00210 
00211                         if (_running)
00212                         {
00213                                 cout << "Connection to bundle daemon failed. Retry in " << backoff << " seconds." << endl;
00214                                 sleep(backoff);
00215 
00216                                 // if backoff < 10 minutes
00217                                 if (backoff < 600)
00218                                 {
00219                                         // set a new backoff
00220                                         backoff = backoff * 2;
00221                                 }
00222                         }
00223                 } catch (const ibrcommon::IOException&) {
00224                         // set the global connection to NULL
00225                         _conn = NULL;
00226 
00227                         if (_running)
00228                         {
00229                                 cout << "Connection to bundle daemon failed. Retry in " << backoff << " seconds." << endl;
00230                                 sleep(backoff);
00231 
00232                                 // if backoff < 10 minutes
00233                                 if (backoff < 600)
00234                                 {
00235                                         // set a new backoff
00236                                         backoff = backoff * 2;
00237                                 }
00238                         }
00239                 } catch (const std::exception&) {
00240                         // set the global connection to NULL
00241                         _conn = NULL;
00242                 }
00243         }
00244 
00245         return (EXIT_SUCCESS);
00246 }

Generated on Thu Nov 11 2010 09:49:47 for IBR-DTNSuite by  doxygen 1.7.1