|
IBR-DTNSuite 0.6
|
00001 /* 00002 * dtninbox.cpp 00003 * 00004 * Created on: 20.11.2009 00005 * Author: morgenro 00006 */ 00007 00008 #include "config.h" 00009 #include "ibrdtn/api/Client.h" 00010 #include "ibrdtn/api/FileBundle.h" 00011 #include "ibrcommon/net/tcpclient.h" 00012 #include "ibrcommon/thread/Mutex.h" 00013 #include "ibrcommon/thread/MutexLock.h" 00014 #include "ibrdtn/data/PayloadBlock.h" 00015 #include "ibrdtn/data/Bundle.h" 00016 #include "ibrcommon/data/BLOB.h" 00017 #include "ibrcommon/data/File.h" 00018 #include "ibrcommon/appstreambuf.h" 00019 00020 #include <stdlib.h> 00021 #include <iostream> 00022 #include <map> 00023 #include <vector> 00024 #include <csignal> 00025 #include <sys/types.h> 00026 00027 using namespace ibrcommon; 00028 00029 void print_help() 00030 { 00031 cout << "-- dtninbox (IBR-DTN) --" << endl; 00032 cout << "Syntax: dtninbox [options] <name> <inbox>" << endl; 00033 cout << " <name> the application name" << endl; 00034 cout << " <inbox> directory where incoming files should be placed" << endl; 00035 cout << "* optional parameters *" << endl; 00036 cout << " -h|--help display this text" << endl; 00037 cout << " -w|--workdir temporary work directory" << endl; 00038 } 00039 00040 map<string,string> readconfiguration(int argc, char** argv) 00041 { 00042 // print help if not enough parameters are set 00043 if (argc < 3) { print_help(); exit(0); } 00044 00045 map<string,string> ret; 00046 00047 ret["name"] = argv[argc - 2]; 00048 ret["inbox"] = argv[argc - 1]; 00049 00050 for (int i = 0; i < (argc - 2); i++) 00051 { 00052 string arg = argv[i]; 00053 00054 // print help if requested 00055 if (arg == "-h" || arg == "--help") 00056 { 00057 print_help(); 00058 exit(0); 00059 } 00060 00061 if ((arg == "-w" || arg == "--workdir") && (argc > i)) 00062 { 00063 ret["workdir"] = argv[i + 1]; 00064 } 00065 } 00066 00067 return ret; 00068 } 00069 00070 // set this variable to false to stop the app 00071 bool _running = true; 00072 00073 // global connection 00074 ibrcommon::tcpclient *_conn = NULL; 00075 00076 void term(int signal) 00077 { 00078 if (signal >= 1) 00079 { 00080 _running = false; 00081 if (_conn != NULL) _conn->close(); 00082 exit(0); 00083 } 00084 } 00085 00086 /* 00087 * main application method 00088 */ 00089 int main(int argc, char** argv) 00090 { 00091 // catch process signals 00092 signal(SIGINT, term); 00093 signal(SIGTERM, term); 00094 00095 // read the configuration 00096 map<string,string> conf = readconfiguration(argc, argv); 00097 00098 // init working directory 00099 if (conf.find("workdir") != conf.end()) 00100 { 00101 ibrcommon::BLOB::tmppath = File(conf["workdir"]); 00102 } 00103 00104 // backoff for reconnect 00105 size_t backoff = 2; 00106 00107 // check outbox for files 00108 File outbox(conf["outbox"]); 00109 00110 // loop, if no stop if requested 00111 while (_running) 00112 { 00113 try { 00114 // Create a stream to the server using TCP. 00115 ibrcommon::tcpclient conn("127.0.0.1", 4550); 00116 00117 // enable nodelay option 00118 conn.enableNoDelay(); 00119 00120 // set the connection globally 00121 _conn = &conn; 00122 00123 // Initiate a client for synchronous receiving 00124 dtn::api::Client client(conf["name"], conn); 00125 00126 // Connect to the server. Actually, this function initiate the 00127 // stream protocol by starting the thread and sending the contact header. 00128 client.connect(); 00129 00130 // reset backoff if connected 00131 backoff = 2; 00132 00133 // check the connection 00134 while (_running) 00135 { 00136 // receive the bundle 00137 dtn::api::Bundle b = client.getBundle(); 00138 00139 // get the reference to the blob 00140 ibrcommon::BLOB::Reference ref = b.getData(); 00141 00142 // create the extract command 00143 stringstream cmdstream; cmdstream << "tar -x -C " << conf["inbox"]; 00144 00145 // create a tar handler 00146 appstreambuf extractor(cmdstream.str(), appstreambuf::MODE_WRITE); 00147 ostream stream(&extractor); 00148 00149 // write the payload to the extractor 00150 stream << ref.iostream()->rdbuf(); 00151 00152 // flush the stream 00153 stream.flush(); 00154 } 00155 00156 // close the client connection 00157 client.close(); 00158 00159 // close the connection 00160 conn.close(); 00161 00162 // set the global connection to NULL 00163 _conn = NULL; 00164 } catch (const ibrcommon::tcpclient::SocketException&) { 00165 // set the global connection to NULL 00166 _conn = NULL; 00167 00168 if (_running) 00169 { 00170 cout << "Connection to bundle daemon failed. Retry in " << backoff << " seconds." << endl; 00171 sleep(backoff); 00172 00173 // if backoff < 10 minutes 00174 if (backoff < 600) 00175 { 00176 // set a new backoff 00177 backoff = backoff * 2; 00178 } 00179 } 00180 } catch (const ibrcommon::IOException&) { 00181 // set the global connection to NULL 00182 _conn = NULL; 00183 00184 if (_running) 00185 { 00186 cout << "Connection to bundle daemon failed. Retry in " << backoff << " seconds." << endl; 00187 sleep(backoff); 00188 00189 // if backoff < 10 minutes 00190 if (backoff < 600) 00191 { 00192 // set a new backoff 00193 backoff = backoff * 2; 00194 } 00195 } 00196 } catch (const std::exception&) { 00197 // set the global connection to NULL 00198 _conn = NULL; 00199 } 00200 } 00201 00202 return (EXIT_SUCCESS); 00203 }