|
IBR-DTNSuite 0.6
|
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 ibrcommon::BLOB::tmppath = ibrcommon::File("/tmp"); 00065 00066 opterr = 0; 00067 00068 while ((c = getopt (argc, argv, "w:")) != -1) 00069 switch (c) 00070 { 00071 case 'w': 00072 ibrcommon::BLOB::tmppath = ibrcommon::File(optarg); 00073 break; 00074 00075 case '?': 00076 if (optopt == 'w') 00077 fprintf (stderr, "Option -%c requires an argument.\n", optopt); 00078 else if (isprint (optopt)) 00079 fprintf (stderr, "Unknown option `-%c'.\n", optopt); 00080 else 00081 fprintf (stderr, 00082 "Unknown option character `\\x%x'.\n", 00083 optopt); 00084 return 1; 00085 00086 default: 00087 print_help(); 00088 abort(); 00089 } 00090 00091 int optindex = 0; 00092 for (index = optind; index < argc; index++) 00093 { 00094 switch (optindex) 00095 { 00096 case 0: 00097 _appname = std::string(argv[index]); 00098 break; 00099 00100 case 1: 00101 _shell = std::string(argv[index]); 00102 break; 00103 00104 case 2: 00105 _script = std::string(argv[index]); 00106 break; 00107 } 00108 00109 optindex++; 00110 } 00111 00112 // print help if not enough parameters are set 00113 if (optindex < 2) { print_help(); exit(0); } 00114 00115 return 0; 00116 } 00117 00118 void term(int signal) 00119 { 00120 if (signal >= 1) 00121 { 00122 _running = false; 00123 if (_conn != NULL) _conn->close(); 00124 exit(0); 00125 } 00126 } 00127 00128 /* 00129 * main application method 00130 */ 00131 int main(int argc, char** argv) 00132 { 00133 // catch process signals 00134 signal(SIGINT, term); 00135 signal(SIGTERM, term); 00136 00137 // read the configuration 00138 if (init(argc, argv) > 0) 00139 { 00140 return (EXIT_FAILURE); 00141 } 00142 00143 // backoff for reconnect 00144 size_t backoff = 2; 00145 00146 // loop, if no stop if requested 00147 while (_running) 00148 { 00149 try { 00150 // Create a stream to the server using TCP. 00151 ibrcommon::tcpclient conn("127.0.0.1", 4550); 00152 00153 // enable nodelay option 00154 conn.enableNoDelay(); 00155 00156 // set the connection globally 00157 _conn = &conn; 00158 00159 // Initiate a client for synchronous receiving 00160 dtn::api::Client client(_appname, conn); 00161 00162 // Connect to the server. Actually, this function initiate the 00163 // stream protocol by starting the thread and sending the contact header. 00164 client.connect(); 00165 00166 // reset backoff if connected 00167 backoff = 2; 00168 00169 // check the connection 00170 while (_running) 00171 { 00172 // receive the bundle 00173 dtn::api::Bundle b = client.getBundle(); 00174 00175 // get the reference to the blob 00176 ibrcommon::BLOB::Reference ref = b.getData(); 00177 00178 // get a temporary file name 00179 ibrcommon::TemporaryFile file(ibrcommon::BLOB::tmppath, "bundle"); 00180 00181 // write data to temporary file 00182 try { 00183 std::fstream out(file.getPath().c_str(), ios::out|ios::binary|ios::trunc); 00184 out.exceptions(std::ios::badbit | std::ios::eofbit); 00185 out << ref.iostream()->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 (const ios_base::failure&) { 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 &ex) { 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 }