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