IBR-DTNSuite  0.8
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 #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 }