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