IBR-DTNSuite  0.12
dtnrecv.cpp
Go to the documentation of this file.
1 /*
2  * dtnrecv.cpp
3  *
4  * Copyright (C) 2011 IBR, TU Braunschweig
5  *
6  * Written-by: Johannes Morgenroth <morgenroth@ibr.cs.tu-bs.de>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21 
22 #include "config.h"
23 #include <ibrdtn/api/Client.h>
24 #include <ibrcommon/net/socket.h>
26 #include <ibrcommon/thread/Mutex.h>
29 #include <ibrcommon/Logger.h>
30 
31 #include <sys/types.h>
32 #include <iostream>
33 
34 void print_help()
35 {
36  cout << "-- dtnrecv (IBR-DTN) --" << endl;
37  cout << "Syntax: dtnrecv [options]" << endl << endl;
38  cout << "* optional parameters *" << endl;
39  cout << " -h|--help Display this text" << endl;
40  cout << " --file <path> Write the incoming data to the a file instead of the" << endl;
41  cout << " standard output" << endl;
42  cout << " --name <name> Set the application name (e.g. filetransfer)" << endl;
43  cout << " --timeout <seconds>" << endl;
44  cout << " Receive timeout in seconds" << endl;
45  cout << " --count <n> Receive that many bundles" << endl;
46  cout << " --group <group> Join a group" << endl;
47  cout << " -U <socket> Connect to UNIX domain socket API" << endl;
48 }
49 
52 
53 int h = 0;
54 bool _stdout = true;
55 
56 void term(int signal)
57 {
58  if (!_stdout)
59  {
60  std::cout << h << " bundles received." << std::endl;
61  }
62 
63  if (signal >= 1)
64  {
65  if (_client != NULL)
66  {
67  _client->close();
68  _conn->close();
69  }
70  }
71 }
72 
73 int main(int argc, char *argv[])
74 {
75  // logging options
77 
78  // error filter
79  unsigned char loglevel = 0;
80 
81  // create signal handler
82  ibrcommon::SignalHandler sighandler(term);
83  sighandler.handle(SIGINT);
84  sighandler.handle(SIGTERM);
85  sighandler.initialize();
86 
87  int ret = EXIT_SUCCESS;
88  string filename = "";
89  string name = "filetransfer";
91  int timeout = 0;
92  int count = 1;
93  ibrcommon::File unixdomain;
94 
95  for (int i = 0; i < argc; ++i)
96  {
97  string arg = argv[i];
98 
99  // print help if requested
100  if (arg == "-h" || arg == "--help")
101  {
102  print_help();
103  return ret;
104  }
105 
106  if (arg == "--logging")
107  {
109  }
110 
111  if (arg == "--debug")
112  {
114  }
115 
116  if (arg == "--name" && argc > i)
117  {
118  name = argv[i + 1];
119  }
120 
121  if (arg == "--file" && argc > i)
122  {
123  filename = argv[i + 1];
124  _stdout = false;
125  }
126 
127  if (arg == "--timeout" && argc > i)
128  {
129  timeout = atoi(argv[i + 1]);
130  }
131 
132  if (arg == "--group" && argc > i)
133  {
134  group = std::string(argv[i + 1]);
135  }
136 
137  if (arg == "--count" && argc > i)
138  {
139  count = atoi(argv[i + 1]);
140  }
141 
142  if (arg == "-U" && argc > i)
143  {
144  if (++i > argc)
145  {
146  std::cout << "argument missing!" << std::endl;
147  return -1;
148  }
149 
150  unixdomain = ibrcommon::File(argv[i]);
151  }
152  }
153 
154  if (loglevel > 0)
155  {
156  // add logging to the cerr
157  ibrcommon::Logger::addStream(std::cerr, loglevel, logopts);
158  }
159 
160  try {
161  // Create a stream to the server using TCP.
162  ibrcommon::clientsocket *sock = NULL;
163 
164  // check if the unixdomain socket exists
165  if (unixdomain.exists())
166  {
167  // connect to the unix domain socket
168  sock = new ibrcommon::filesocket(unixdomain);
169  }
170  else
171  {
172  // connect to the standard local api port
173  ibrcommon::vaddress addr("localhost", 4550);
174  sock = new ibrcommon::tcpsocket(addr);
175  }
176 
177  ibrcommon::socketstream conn(sock);
178 
179  // Initiate a client for synchronous receiving
180  dtn::api::Client client(name, group, conn);
181 
182  // export objects for the signal handler
183  _conn = &conn;
184  _client = &client;
185 
186  // Connect to the server. Actually, this function initiate the
187  // stream protocol by starting the thread and sending the contact header.
188  client.connect();
189 
190  std::fstream file;
191 
192  if (!_stdout)
193  {
194  std::cout << "Wait for incoming bundle... " << std::endl;
195  file.open(filename.c_str(), ios::in|ios::out|ios::binary|ios::trunc);
196  file.exceptions(std::ios::badbit | std::ios::eofbit);
197  }
198 
199  for(h = 0; h < count; ++h)
200  {
201  // receive the bundle
202  dtn::data::Bundle b = client.getBundle(timeout);
203 
204  // get the reference to the blob
206 
207  // write the data to output
208  if (_stdout)
209  {
210  std::cout << ref.iostream()->rdbuf() << std::flush;
211  }
212  else
213  {
214  // write data to temporary file
215  try {
216  std::cout << "Bundle received (" << (h + 1) << ")." << endl;
217 
218  file << ref.iostream()->rdbuf();
219  } catch (const ios_base::failure&) {
220 
221  }
222  }
223  }
224 
225  if (!_stdout)
226  {
227  file.close();
228  std::cout << "done." << std::endl;
229  }
230 
231  // Shutdown the client connection.
232  client.close();
233 
234  // close the tcp connection
235  conn.close();
236  } catch (const dtn::api::ConnectionTimeoutException&) {
237  std::cerr << "Timeout." << std::endl;
238  ret = EXIT_FAILURE;
239  } catch (const dtn::api::ConnectionAbortedException&) {
240  std::cerr << "Aborted." << std::endl;
241  ret = EXIT_FAILURE;
242  } catch (const dtn::api::ConnectionException&) {
243  } catch (const std::exception &ex) {
244  std::cerr << "Error: " << ex.what() << std::endl;
245  ret = EXIT_FAILURE;
246  }
247 
248  return ret;
249 }