IBR-DTNSuite 0.6

tools/src/dtnrecv.cpp

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