IBR-DTNSuite  0.10
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>
28 #include <ibrcommon/Logger.h>
29 
30 #include <csignal>
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;
38  cout << "* optional parameters *" << endl;
39  cout << " -h|--help display this text" << endl;
40  cout << " --file <filename> write the incoming data to the a file instead of the standard output" << endl;
41  cout << " --name <name> set the application name (e.g. filetransfer)" << endl;
42  cout << " --timeout <seconds> receive timeout in seconds" << endl;
43  cout << " --count <number> receive that many bundles" << endl;
44  cout << " --group <group> join a group" << endl;
45  cout << " -U <socket> use UNIX domain sockets" << endl;
46 }
47 
50 
51 int h = 0;
52 bool _stdout = true;
53 
54 void term(int signal)
55 {
56  if (!_stdout)
57  {
58  std::cout << h << " bundles received." << std::endl;
59  }
60 
61  if (signal >= 1)
62  {
63  if (_client != NULL)
64  {
65  _client->close();
66  _conn->close();
67  }
68  }
69 }
70 
71 int main(int argc, char *argv[])
72 {
73  // logging options
75 
76  // error filter
77  unsigned char loglevel = 0;
78 
79  // catch process signals
80  signal(SIGINT, term);
81  signal(SIGTERM, term);
82 
83  int ret = EXIT_SUCCESS;
84  string filename = "";
85  string name = "filetransfer";
87  int timeout = 0;
88  int count = 1;
89  ibrcommon::File unixdomain;
90 
91  for (int i = 0; i < argc; ++i)
92  {
93  string arg = argv[i];
94 
95  // print help if requested
96  if (arg == "-h" || arg == "--help")
97  {
98  print_help();
99  return ret;
100  }
101 
102  if (arg == "--logging")
103  {
105  }
106 
107  if (arg == "--debug")
108  {
110  }
111 
112  if (arg == "--name" && argc > i)
113  {
114  name = argv[i + 1];
115  }
116 
117  if (arg == "--file" && argc > i)
118  {
119  filename = argv[i + 1];
120  _stdout = false;
121  }
122 
123  if (arg == "--timeout" && argc > i)
124  {
125  timeout = atoi(argv[i + 1]);
126  }
127 
128  if (arg == "--group" && argc > i)
129  {
130  group = std::string(argv[i + 1]);
131  }
132 
133  if (arg == "--count" && argc > i)
134  {
135  count = atoi(argv[i + 1]);
136  }
137 
138  if (arg == "-U" && argc > i)
139  {
140  if (++i > argc)
141  {
142  std::cout << "argument missing!" << std::endl;
143  return -1;
144  }
145 
146  unixdomain = ibrcommon::File(argv[i]);
147  }
148  }
149 
150  if (loglevel > 0)
151  {
152  // add logging to the cerr
153  ibrcommon::Logger::addStream(std::cerr, loglevel, logopts);
154  }
155 
156  try {
157  // Create a stream to the server using TCP.
158  ibrcommon::clientsocket *sock = NULL;
159 
160  // check if the unixdomain socket exists
161  if (unixdomain.exists())
162  {
163  // connect to the unix domain socket
164  sock = new ibrcommon::filesocket(unixdomain);
165  }
166  else
167  {
168  // connect to the standard local api port
169  ibrcommon::vaddress addr("localhost", 4550);
170  sock = new ibrcommon::tcpsocket(addr);
171  }
172 
173  ibrcommon::socketstream conn(sock);
174 
175  // Initiate a client for synchronous receiving
176  dtn::api::Client client(name, group, conn);
177 
178  // export objects for the signal handler
179  _conn = &conn;
180  _client = &client;
181 
182  // Connect to the server. Actually, this function initiate the
183  // stream protocol by starting the thread and sending the contact header.
184  client.connect();
185 
186  std::fstream file;
187 
188  if (!_stdout)
189  {
190  std::cout << "Wait for incoming bundle... " << std::endl;
191  file.open(filename.c_str(), ios::in|ios::out|ios::binary|ios::trunc);
192  file.exceptions(std::ios::badbit | std::ios::eofbit);
193  }
194 
195  for(h = 0; h < count; ++h)
196  {
197  // receive the bundle
198  dtn::data::Bundle b = client.getBundle(timeout);
199 
200  // get the reference to the blob
202 
203  // write the data to output
204  if (_stdout)
205  {
206  std::cout << ref.iostream()->rdbuf() << std::flush;
207  }
208  else
209  {
210  // write data to temporary file
211  try {
212  std::cout << "Bundle received (" << (h + 1) << ")." << endl;
213 
214  file << ref.iostream()->rdbuf();
215  } catch (const ios_base::failure&) {
216 
217  }
218  }
219  }
220 
221  if (!_stdout)
222  {
223  file.close();
224  std::cout << "done." << std::endl;
225  }
226 
227  // Shutdown the client connection.
228  client.close();
229 
230  // close the tcp connection
231  conn.close();
232  } catch (const dtn::api::ConnectionTimeoutException&) {
233  std::cerr << "Timeout." << std::endl;
234  ret = EXIT_FAILURE;
235  } catch (const dtn::api::ConnectionAbortedException&) {
236  std::cerr << "Aborted." << std::endl;
237  ret = EXIT_FAILURE;
238  } catch (const dtn::api::ConnectionException&) {
239  } catch (const std::exception &ex) {
240  std::cerr << "Error: " << ex.what() << std::endl;
241  ret = EXIT_FAILURE;
242  }
243 
244  return ret;
245 }