IBR-DTNSuite
0.8
|
00001 /* 00002 * dtnrecv.cpp 00003 * 00004 * Created on: 06.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 <ibrcommon/Logger.h> 00015 00016 #include <csignal> 00017 #include <sys/types.h> 00018 #include <iostream> 00019 00020 void print_help() 00021 { 00022 cout << "-- dtnrecv (IBR-DTN) --" << endl; 00023 cout << "Syntax: dtnrecv [options]" << endl; 00024 cout << "* optional parameters *" << endl; 00025 cout << " -h|--help display this text" << endl; 00026 cout << " --file <filename> write the incoming data to the a file instead of the standard output" << endl; 00027 cout << " --name <name> set the application name (e.g. filetransfer)" << endl; 00028 cout << " --timeout <seconds> receive timeout in seconds" << endl; 00029 cout << " --count <number> receive that many bundles" << endl; 00030 cout << " --group <group> join a group" << endl; 00031 cout << " -U <socket> use UNIX domain sockets" << endl; 00032 } 00033 00034 dtn::api::Client *_client = NULL; 00035 ibrcommon::tcpclient *_conn = NULL; 00036 00037 int h = 0; 00038 bool _stdout = true; 00039 00040 void term(int signal) 00041 { 00042 if (!_stdout) 00043 { 00044 std::cout << h << " bundles received." << std::endl; 00045 } 00046 00047 if (signal >= 1) 00048 { 00049 if (_client != NULL) 00050 { 00051 _client->close(); 00052 _conn->close(); 00053 } 00054 } 00055 } 00056 00057 int main(int argc, char *argv[]) 00058 { 00059 // logging options 00060 const unsigned char logopts = ibrcommon::Logger::LOG_DATETIME | ibrcommon::Logger::LOG_LEVEL; 00061 00062 // error filter 00063 unsigned char loglevel = 0; 00064 00065 // catch process signals 00066 signal(SIGINT, term); 00067 signal(SIGTERM, term); 00068 00069 int ret = EXIT_SUCCESS; 00070 string filename = ""; 00071 string name = "filetransfer"; 00072 dtn::data::EID group; 00073 int timeout = 0; 00074 int count = 1; 00075 ibrcommon::File unixdomain; 00076 00077 for (int i = 0; i < argc; i++) 00078 { 00079 string arg = argv[i]; 00080 00081 // print help if requested 00082 if (arg == "-h" || arg == "--help") 00083 { 00084 print_help(); 00085 return ret; 00086 } 00087 00088 if (arg == "--logging") 00089 { 00090 loglevel |= ibrcommon::Logger::LOGGER_ALL ^ ibrcommon::Logger::LOGGER_DEBUG; 00091 } 00092 00093 if (arg == "--debug") 00094 { 00095 loglevel |= ibrcommon::Logger::LOGGER_DEBUG; 00096 } 00097 00098 if (arg == "--name" && argc > i) 00099 { 00100 name = argv[i + 1]; 00101 } 00102 00103 if (arg == "--file" && argc > i) 00104 { 00105 filename = argv[i + 1]; 00106 _stdout = false; 00107 } 00108 00109 if (arg == "--timeout" && argc > i) 00110 { 00111 timeout = atoi(argv[i + 1]); 00112 } 00113 00114 if (arg == "--group" && argc > i) 00115 { 00116 group = std::string(argv[i + 1]); 00117 } 00118 00119 if (arg == "--count" && argc > i) 00120 { 00121 count = atoi(argv[i + 1]); 00122 } 00123 00124 if (arg == "-U" && argc > i) 00125 { 00126 if (++i > argc) 00127 { 00128 std::cout << "argument missing!" << std::endl; 00129 return -1; 00130 } 00131 00132 unixdomain = ibrcommon::File(argv[i]); 00133 } 00134 } 00135 00136 if (loglevel > 0) 00137 { 00138 // add logging to the cerr 00139 ibrcommon::Logger::addStream(std::cerr, loglevel, logopts); 00140 } 00141 00142 try { 00143 // Create a stream to the server using TCP. 00144 ibrcommon::tcpclient conn; 00145 00146 // check if the unixdomain socket exists 00147 if (unixdomain.exists()) 00148 { 00149 // connect to the unix domain socket 00150 conn.open(unixdomain); 00151 } 00152 else 00153 { 00154 // connect to the standard local api port 00155 conn.open("127.0.0.1", 4550); 00156 00157 // enable nodelay option 00158 conn.enableNoDelay(); 00159 } 00160 00161 // Initiate a client for synchronous receiving 00162 dtn::api::Client client(name, group, conn); 00163 00164 // export objects for the signal handler 00165 _conn = &conn; 00166 _client = &client; 00167 00168 // Connect to the server. Actually, this function initiate the 00169 // stream protocol by starting the thread and sending the contact header. 00170 client.connect(); 00171 00172 std::fstream file; 00173 00174 if (!_stdout) 00175 { 00176 std::cout << "Wait for incoming bundle... " << std::endl; 00177 file.open(filename.c_str(), ios::in|ios::out|ios::binary|ios::trunc); 00178 file.exceptions(std::ios::badbit | std::ios::eofbit); 00179 } 00180 00181 for(h = 0; h < count; h++) 00182 { 00183 // receive the bundle 00184 dtn::api::Bundle b = client.getBundle(timeout); 00185 00186 // get the reference to the blob 00187 ibrcommon::BLOB::Reference ref = b.getData(); 00188 00189 // write the data to output 00190 if (_stdout) 00191 { 00192 std::cout << ref.iostream()->rdbuf() << std::flush; 00193 } 00194 else 00195 { 00196 // write data to temporary file 00197 try { 00198 std::cout << "Bundle received (" << (h + 1) << ")." << endl; 00199 00200 file << ref.iostream()->rdbuf(); 00201 } catch (const ios_base::failure&) { 00202 00203 } 00204 } 00205 } 00206 00207 if (!_stdout) 00208 { 00209 file.close(); 00210 std::cout << "done." << std::endl; 00211 } 00212 00213 // Shutdown the client connection. 00214 client.close(); 00215 00216 // close the tcp connection 00217 conn.close(); 00218 } catch (const dtn::api::ConnectionTimeoutException&) { 00219 std::cerr << "Timeout." << std::endl; 00220 ret = EXIT_FAILURE; 00221 } catch (const dtn::api::ConnectionAbortedException&) { 00222 std::cerr << "Aborted." << std::endl; 00223 ret = EXIT_FAILURE; 00224 } catch (const dtn::api::ConnectionException&) { 00225 } catch (const std::exception &ex) { 00226 std::cerr << "Error: " << ex.what() << std::endl; 00227 ret = EXIT_FAILURE; 00228 } 00229 00230 return ret; 00231 }