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