|
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 } 00083 } 00084 00085 /* 00086 * main application method 00087 */ 00088 int main(int argc, char** argv) 00089 { 00090 // catch process signals 00091 signal(SIGINT, term); 00092 signal(SIGTERM, term); 00093 00094 // read the configuration 00095 map<string,string> conf = readconfiguration(argc, argv); 00096 00097 // init working directory 00098 if (conf.find("workdir") != conf.end()) 00099 { 00100 ibrcommon::File blob_path(conf["workdir"]); 00101 00102 if (blob_path.exists()) 00103 { 00104 ibrcommon::BLOB::changeProvider(new ibrcommon::FileBLOBProvider(blob_path), true); 00105 } 00106 } 00107 00108 // backoff for reconnect 00109 size_t backoff = 2; 00110 00111 // check outbox for files 00112 File outbox(conf["outbox"]); 00113 00114 // loop, if no stop if requested 00115 while (_running) 00116 { 00117 try { 00118 // Create a stream to the server using TCP. 00119 ibrcommon::tcpclient conn("127.0.0.1", 4550); 00120 00121 // enable nodelay option 00122 conn.enableNoDelay(); 00123 00124 // set the connection globally 00125 _conn = &conn; 00126 00127 // Initiate a client for synchronous receiving 00128 dtn::api::Client client(conf["name"], conn); 00129 00130 // Connect to the server. Actually, this function initiate the 00131 // stream protocol by starting the thread and sending the contact header. 00132 client.connect(); 00133 00134 // reset backoff if connected 00135 backoff = 2; 00136 00137 // check the connection 00138 while (_running) 00139 { 00140 // receive the bundle 00141 dtn::api::Bundle b = client.getBundle(); 00142 00143 // get the reference to the blob 00144 ibrcommon::BLOB::Reference ref = b.getData(); 00145 00146 // create the extract command 00147 stringstream cmdstream; cmdstream << "tar -x -C " << conf["inbox"]; 00148 00149 // create a tar handler 00150 appstreambuf extractor(cmdstream.str(), appstreambuf::MODE_WRITE); 00151 ostream stream(&extractor); 00152 00153 // write the payload to the extractor 00154 stream << ref.iostream()->rdbuf(); 00155 00156 // flush the stream 00157 stream.flush(); 00158 } 00159 00160 // close the client connection 00161 client.close(); 00162 00163 // close the connection 00164 conn.close(); 00165 00166 // set the global connection to NULL 00167 _conn = NULL; 00168 } catch (const ibrcommon::tcpclient::SocketException&) { 00169 // set the global connection to NULL 00170 _conn = NULL; 00171 00172 if (_running) 00173 { 00174 cout << "Connection to bundle daemon failed. Retry in " << backoff << " seconds." << endl; 00175 sleep(backoff); 00176 00177 // if backoff < 10 minutes 00178 if (backoff < 600) 00179 { 00180 // set a new backoff 00181 backoff = backoff * 2; 00182 } 00183 } 00184 } catch (const ibrcommon::IOException&) { 00185 // set the global connection to NULL 00186 _conn = NULL; 00187 00188 if (_running) 00189 { 00190 cout << "Connection to bundle daemon failed. Retry in " << backoff << " seconds." << endl; 00191 sleep(backoff); 00192 00193 // if backoff < 10 minutes 00194 if (backoff < 600) 00195 { 00196 // set a new backoff 00197 backoff = backoff * 2; 00198 } 00199 } 00200 } catch (const std::exception&) { 00201 // set the global connection to NULL 00202 _conn = NULL; 00203 } 00204 } 00205 00206 return (EXIT_SUCCESS); 00207 }