IBR-DTNSuite  0.10
dtnsend.cpp
Go to the documentation of this file.
1 /*
2  * dtnsend.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>
25 #include <ibrcommon/thread/Mutex.h>
27 #include <ibrcommon/data/BLOB.h>
28 #include <ibrcommon/Logger.h>
29 
30 #include <iostream>
31 
32 void print_help()
33 {
34  cout << "-- dtnsend (IBR-DTN) --" << endl;
35  cout << "Syntax: dtnsend [options] <dst> <filename>" << endl;
36  cout << " <dst> set the destination eid (e.g. dtn://node/filetransfer)" << endl;
37  cout << " <filename> the file to transfer" << endl;
38  cout << "* optional parameters *" << endl;
39  cout << " -h|--help display this text" << endl;
40  cout << " --src <name> set the source application name (e.g. filetransfer)" << endl;
41  cout << " -p <0..2> set the bundle priority (0 = low, 1 = normal, 2 = high)" << endl;
42  cout << " -g receiver is a destination group" << endl;
43  cout << " --lifetime <seconds>" << endl;
44  cout << " set the lifetime of outgoing bundles; default: 3600" << endl;
45  cout << " -U <socket> use UNIX domain sockets" << endl;
46  cout << " -n <copies> create <copies> bundle copies" << endl;
47  cout << " --encrypt request encryption on the bundle layer" << endl;
48  cout << " --sign request signature on the bundle layer" << endl;
49  cout << " --custody request custody transfer of the bundle" << endl;
50  cout << " --compression request compression of the payload" << endl;
51 
52 }
53 
54 int main(int argc, char *argv[])
55 {
56  bool error = false;
57  string file_destination = "dtn://local/filetransfer";
58  string file_source = "";
59  unsigned int lifetime = 3600;
60  bool use_stdin = false;
61  std::string filename;
62  ibrcommon::File unixdomain;
63  int priority = 1;
64  int copies = 1;
65  bool bundle_encryption = false;
66  bool bundle_signed = false;
67  bool bundle_custody = false;
68  bool bundle_compression = false;
69  bool bundle_group = false;
70 
71 // ibrcommon::Logger::setVerbosity(99);
72 // ibrcommon::Logger::addStream(std::cout, ibrcommon::Logger::LOGGER_ALL, ibrcommon::Logger::LOG_DATETIME | ibrcommon::Logger::LOG_LEVEL);
73 
74  std::list<std::string> arglist;
75 
76  for (int i = 0; i < argc; ++i)
77  {
78  if (argv[i][0] == '-')
79  {
80  std::string arg = argv[i];
81 
82  // print help if requested
83  if (arg == "-h" || arg == "--help")
84  {
85  print_help();
86  return 0;
87  }
88  else if (arg == "--encrypt")
89  {
90  bundle_encryption = true;
91  }
92  else if (arg == "--sign")
93  {
94  bundle_signed = true;
95  }
96  else if (arg == "--custody")
97  {
98  bundle_custody = true;
99  }
100  else if (arg == "--compression")
101  {
102  bundle_compression = true;
103  }
104  else if (arg == "--src" && argc > i)
105  {
106  if (++i > argc)
107  {
108  std::cout << "argument missing!" << std::endl;
109  return -1;
110  }
111 
112  file_source = argv[i];
113  }
114  else if (arg == "--lifetime" && argc > i)
115  {
116  if (++i > argc)
117  {
118  std::cout << "argument missing!" << std::endl;
119  return -1;
120  }
121 
122  stringstream data; data << argv[i];
123  data >> lifetime;
124  }
125  else if (arg == "-p" && argc > i)
126  {
127  if (++i > argc)
128  {
129  std::cout << "argument missing!" << std::endl;
130  return -1;
131  }
132  stringstream data; data << argv[i];
133  data >> priority;
134  }
135  else if (arg == "-U" && argc > i)
136  {
137  if (++i > argc)
138  {
139  std::cout << "argument missing!" << std::endl;
140  return -1;
141  }
142 
143  unixdomain = ibrcommon::File(argv[i]);
144  }
145  else if (arg == "-n" && argc > i)
146  {
147  if (++i > argc)
148  {
149  std::cout << "argument missing!" << std::endl;
150  return -1;
151  }
152 
153  stringstream data; data << argv[i];
154  data >> copies;
155 
156  if( copies < 1 ) {
157  std::cout << "invalid number of bundle copies!" << std::endl;
158  return -1;
159  }
160  }
161  else if (arg == "-g")
162  {
163  bundle_group = true;
164  }
165  else
166  {
167  std::cout << "invalid argument " << arg << std::endl;
168  return -1;
169  }
170  }
171  else
172  {
173  arglist.push_back(argv[i]);
174  }
175  }
176 
177  if (arglist.size() <= 1)
178  {
179  print_help();
180  return -1;
181  } else if (arglist.size() == 2)
182  {
183  std::list<std::string>::iterator iter = arglist.begin(); ++iter;
184 
185  // the first parameter is the destination
186  file_destination = (*iter);
187 
188  use_stdin = true;
189  }
190  else if (arglist.size() > 2)
191  {
192  std::list<std::string>::iterator iter = arglist.begin(); ++iter;
193 
194  // the first parameter is the destination
195  file_destination = (*iter); ++iter;
196 
197  // the second parameter is the filename
198  filename = (*iter);
199  }
200 
201  try {
202  // Create a stream to the server using TCP.
203  ibrcommon::clientsocket *sock = NULL;
204 
205  // check if the unixdomain socket exists
206  if (unixdomain.exists())
207  {
208  // connect to the unix domain socket
209  sock = new ibrcommon::filesocket(unixdomain);
210  }
211  else
212  {
213  ibrcommon::vaddress addr("localhost", 4550);
214 
215  // connect to the standard local api port
216  sock = new ibrcommon::tcpsocket(addr);
217  }
218 
219  ibrcommon::socketstream conn(sock);
220 
221  try {
222  // Initiate a client for synchronous receiving
223  dtn::api::Client client(file_source, conn, dtn::api::Client::MODE_SENDONLY);
224 
225  // Connect to the server. Actually, this function initiate the
226  // stream protocol by starting the thread and sending the contact header.
227  client.connect();
228 
229  // target address
230  EID addr = EID(file_destination);
231 
232  try {
233  if (use_stdin)
234  {
235  cout << "Transfer stdin to " << addr.getString() << endl;
236 
237  // create an empty BLOB
239 
240  // copy cin to a BLOB
241  (*ref.iostream()) << cin.rdbuf();
242 
243  for(int u=0; u<copies; ++u){
245 
246  // set the destination
247  b.destination = file_destination;
248 
249  // add payload block with the reference
250  b.push_back(ref);
251 
252  // set destination address to non-singleton
253  if (bundle_group) b.set(dtn::data::PrimaryBlock::DESTINATION_IS_SINGLETON, false);
254 
255  // enable encryption if requested
256  if (bundle_encryption) b.set(dtn::data::PrimaryBlock::DTNSEC_REQUEST_ENCRYPT, true);
257 
258  // enable signature if requested
259  if (bundle_signed) b.set(dtn::data::PrimaryBlock::DTNSEC_REQUEST_SIGN, true);
260 
261  // enable custody transfer if requested
262  if (bundle_custody) {
264  b.custodian = dtn::data::EID("api:me");
265  }
266 
267  // enable compression
268  if (bundle_compression) b.set(dtn::data::PrimaryBlock::IBRDTN_REQUEST_COMPRESSION, true);
269 
270  // set the lifetime
271  b.lifetime = lifetime;
272 
273  // set the bundles priority
275 
276  // send the bundle
277  client << b;
278 
279  if (copies > 1)
280  {
281  std::cout << "sent copy #" << (u+1) << std::endl;
282  }
283  }
284  }
285  else
286  {
287  cout << "Transfer file \"" << filename << "\" to " << addr.getString() << endl;
288 
289  // open file as read-only BLOB
291 
292  for(int u=0; u<copies; ++u){
293  // create a bundle from the file
295 
296  // set the destination
297  b.destination = file_destination;
298 
299  // add payload block with the reference
300  b.push_back(ref);
301 
302  // set destination address to non-singleton
303  if (bundle_group) b.set(dtn::data::PrimaryBlock::DESTINATION_IS_SINGLETON, false);
304 
305  // enable encryption if requested
306  if (bundle_encryption) b.set(dtn::data::PrimaryBlock::DTNSEC_REQUEST_ENCRYPT, true);
307 
308  // enable signature if requested
309  if (bundle_signed) b.set(dtn::data::PrimaryBlock::DTNSEC_REQUEST_SIGN, true);
310 
311  // enable custody transfer if requested
312  if (bundle_custody) {
314  b.custodian = dtn::data::EID("api:me");
315  }
316 
317  // enable compression
318  if (bundle_compression) b.set(dtn::data::PrimaryBlock::IBRDTN_REQUEST_COMPRESSION, true);
319 
320  // set the lifetime
321  b.lifetime = lifetime;
322 
323  // set the bundles priority
325 
326  // send the bundle
327  client << b;
328 
329  if (copies > 1)
330  {
331  std::cout << "sent copy #" << (u+1) << std::endl;
332  }
333  }
334  }
335 
336  // flush the buffers
337  client.flush();
338  } catch (const ibrcommon::IOException &ex) {
339  std::cerr << "Error while sending bundle." << std::endl;
340  std::cerr << "\t" << ex.what() << std::endl;
341  error = true;
342  }
343 
344  // Shutdown the client connection.
345  client.close();
346 
347  } catch (const ibrcommon::IOException &ex) {
348  cout << "Error: " << ex.what() << endl;
349  error = true;
350  } catch (const dtn::api::ConnectionException&) {
351  // connection already closed, the daemon was faster
352  }
353 
354  // close the tcpstream
355  conn.close();
356  } catch (const std::exception &ex) {
357  cout << "Error: " << ex.what() << endl;
358  error = true;
359  }
360 
361  if (error) return -1;
362 
363  return 0;
364 }