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