IBR-DTNSuite
0.8
|
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 #include <unistd.h> 00027 00028 using namespace ibrcommon; 00029 00030 void print_help() 00031 { 00032 cout << "-- dtninbox (IBR-DTN) --" << endl; 00033 cout << "Syntax: dtninbox [options] <name> <inbox>" << endl; 00034 cout << " <name> the application name" << endl; 00035 cout << " <inbox> directory where incoming files should be placed" << endl; 00036 cout << "* optional parameters *" << endl; 00037 cout << " -h|--help display this text" << endl; 00038 cout << " -w|--workdir temporary work directory" << endl; 00039 } 00040 00041 map<string,string> readconfiguration(int argc, char** argv) 00042 { 00043 // print help if not enough parameters are set 00044 if (argc < 3) { print_help(); exit(0); } 00045 00046 map<string,string> ret; 00047 00048 ret["name"] = argv[argc - 2]; 00049 ret["inbox"] = argv[argc - 1]; 00050 00051 for (int i = 0; i < (argc - 2); i++) 00052 { 00053 string arg = argv[i]; 00054 00055 // print help if requested 00056 if (arg == "-h" || arg == "--help") 00057 { 00058 print_help(); 00059 exit(0); 00060 } 00061 00062 if ((arg == "-w" || arg == "--workdir") && (argc > i)) 00063 { 00064 ret["workdir"] = argv[i + 1]; 00065 } 00066 } 00067 00068 return ret; 00069 } 00070 00071 // set this variable to false to stop the app 00072 bool _running = true; 00073 00074 // global connection 00075 ibrcommon::tcpclient *_conn = NULL; 00076 00077 void term(int signal) 00078 { 00079 if (signal >= 1) 00080 { 00081 _running = false; 00082 if (_conn != NULL) _conn->close(); 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::File blob_path(conf["workdir"]); 00102 00103 if (blob_path.exists()) 00104 { 00105 ibrcommon::BLOB::changeProvider(new ibrcommon::FileBLOBProvider(blob_path), true); 00106 } 00107 } 00108 00109 // backoff for reconnect 00110 size_t backoff = 2; 00111 00112 // check outbox for files 00113 File outbox(conf["outbox"]); 00114 00115 // loop, if no stop if requested 00116 while (_running) 00117 { 00118 try { 00119 // Create a stream to the server using TCP. 00120 ibrcommon::tcpclient conn("127.0.0.1", 4550); 00121 00122 // enable nodelay option 00123 conn.enableNoDelay(); 00124 00125 // set the connection globally 00126 _conn = &conn; 00127 00128 // Initiate a client for synchronous receiving 00129 dtn::api::Client client(conf["name"], conn); 00130 00131 // Connect to the server. Actually, this function initiate the 00132 // stream protocol by starting the thread and sending the contact header. 00133 client.connect(); 00134 00135 // reset backoff if connected 00136 backoff = 2; 00137 00138 // check the connection 00139 while (_running) 00140 { 00141 // receive the bundle 00142 dtn::api::Bundle b = client.getBundle(); 00143 00144 // get the reference to the blob 00145 ibrcommon::BLOB::Reference ref = b.getData(); 00146 00147 // create the extract command 00148 stringstream cmdstream; cmdstream << "tar -x -C " << conf["inbox"]; 00149 00150 // create a tar handler 00151 appstreambuf extractor(cmdstream.str(), appstreambuf::MODE_WRITE); 00152 ostream stream(&extractor); 00153 00154 // write the payload to the extractor 00155 stream << ref.iostream()->rdbuf(); 00156 00157 // flush the stream 00158 stream.flush(); 00159 } 00160 00161 // close the client connection 00162 client.close(); 00163 00164 // close the connection 00165 conn.close(); 00166 00167 // set the global connection to NULL 00168 _conn = NULL; 00169 } catch (const ibrcommon::tcpclient::SocketException&) { 00170 // set the global connection to NULL 00171 _conn = NULL; 00172 00173 if (_running) 00174 { 00175 cout << "Connection to bundle daemon failed. Retry in " << backoff << " seconds." << endl; 00176 sleep(backoff); 00177 00178 // if backoff < 10 minutes 00179 if (backoff < 600) 00180 { 00181 // set a new backoff 00182 backoff = backoff * 2; 00183 } 00184 } 00185 } catch (const ibrcommon::IOException&) { 00186 // set the global connection to NULL 00187 _conn = NULL; 00188 00189 if (_running) 00190 { 00191 cout << "Connection to bundle daemon failed. Retry in " << backoff << " seconds." << endl; 00192 sleep(backoff); 00193 00194 // if backoff < 10 minutes 00195 if (backoff < 600) 00196 { 00197 // set a new backoff 00198 backoff = backoff * 2; 00199 } 00200 } 00201 } catch (const std::exception&) { 00202 // set the global connection to NULL 00203 _conn = NULL; 00204 } 00205 } 00206 00207 return (EXIT_SUCCESS); 00208 }