IBR-DTNSuite  0.10
dtnstream.cpp
Go to the documentation of this file.
1 /*
2  * dtnstream.cpp
3  *
4  * The application dtnstream can transfer a data stream to another instance of dtnstream.
5  * It uses an extension block to mark the sequence of the stream.
6  *
7  * Copyright (C) 2011 IBR, TU Braunschweig
8  *
9  * Written-by: Johannes Morgenroth <morgenroth@ibr.cs.tu-bs.de>
10  *
11  * Licensed under the Apache License, Version 2.0 (the "License");
12  * you may not use this file except in compliance with the License.
13  * You may obtain a copy of the License at
14  *
15  * http://www.apache.org/licenses/LICENSE-2.0
16  *
17  * Unless required by applicable law or agreed to in writing, software
18  * distributed under the License is distributed on an "AS IS" BASIS,
19  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20  * See the License for the specific language governing permissions and
21  * limitations under the License.
22  *
23  */
24 
25 #include "config.h"
26 #include "streaming/BundleStream.h"
27 #include <ibrdtn/api/Client.h>
28 #include <ibrdtn/data/EID.h>
29 #include <ibrcommon/net/socket.h>
30 #include <ibrcommon/data/File.h>
31 #include <iostream>
32 #include <unistd.h>
33 
34 void print_help()
35 {
36  std::cout << "-- dtnstream (IBR-DTN) --" << std::endl;
37  std::cout << "Syntax: dtnstream [options]" << std::endl;
38  std::cout << "" << std::endl;
39  std::cout << "* common options *" << std::endl;
40  std::cout << " -h display this text" << std::endl;
41  std::cout << " -U <socket> use UNIX domain sockets" << std::endl;
42  std::cout << " -s <identifier> set the source identifier (e.g. stream)" << std::endl;
43  std::cout << "" << std::endl;
44  std::cout << "* send options *" << std::endl;
45  std::cout << " -d <destination> set the destination eid (e.g. dtn://node/stream)" << std::endl;
46  std::cout << " -G destination is a group" << std::endl;
47  std::cout << " -C <bytes> set the max. chunk size (max. size of each bundle)" << std::endl;
48  std::cout << " -c <bytes> set the min. chunk size (min. size of each bundle)" << std::endl;
49  std::cout << " -p <0..2> set the bundle priority (0 = low, 1 = normal, 2 = high)" << endl;
50  std::cout << " -l <seconds> set the lifetime of stream chunks default: 30" << std::endl;
51  std::cout << " -E request encryption on the bundle layer" << std::endl;
52  std::cout << " -S request signature on the bundle layer" << std::endl;
53  std::cout << " -f Enable flow-control using Status Reports" << std::endl;
54  std::cout << "" << std::endl;
55  std::cout << "* receive options *" << std::endl;
56  std::cout << " -g <group> join a destination group" << std::endl;
57  std::cout << " -t <seconds> set the timeout of the buffer" << std::endl;
58  std::cout << " -w wait for the bundle with seqno zero" << std::endl;
59  std::cout << "" << std::endl;
60 }
61 
62 int main(int argc, char *argv[])
63 {
64  int opt = 0;
65  dtn::data::EID _destination;
66  std::string _source = "stream";
67  int _priority = 1;
68  unsigned int _lifetime = 30;
69  unsigned int _receive_timeout = 0;
70 
71  size_t _min_chunk_size = 4096;
72  size_t _max_chunk_size = 512000;
73 
74  dtn::data::EID _group;
75  bool _bundle_encryption = false;
76  bool _bundle_signed = false;
77  bool _bundle_group = false;
78  bool _wait_seq_zero = false;
79  bool _flow_control = false;
80  ibrcommon::File _unixdomain;
81 
82  while((opt = getopt(argc, argv, "hg:Gd:t:s:c:C:p:l:ESU:wf")) != -1)
83  {
84  switch (opt)
85  {
86  case 'h':
87  print_help();
88  return 0;
89 
90  case 'd':
91  _destination = std::string(optarg);
92  break;
93 
94  case 'g':
95  _group = std::string(optarg);
96  break;
97 
98  case 'G':
99  _bundle_group = true;
100  break;
101 
102  case 's':
103  _source = optarg;
104  break;
105 
106  case 'c':
107  _min_chunk_size = atoi(optarg);
108  break;
109 
110  case 'C':
111  _max_chunk_size = atoi(optarg);
112  break;
113 
114  case 't':
115  _receive_timeout = atoi(optarg);
116  break;
117 
118  case 'p':
119  _priority = atoi(optarg);
120  break;
121 
122  case 'l':
123  _lifetime = atoi(optarg);
124  break;
125 
126  case 'E':
127  _bundle_encryption = true;
128  break;
129 
130  case 'S':
131  _bundle_signed = true;
132  break;
133 
134  case 'U':
135  _unixdomain = ibrcommon::File(optarg);
136  break;
137 
138  case 'w':
139  _wait_seq_zero = true;
140  break;
141 
142  case 'f':
143  _flow_control = true;
144  break;
145 
146  default:
147  std::cout << "unknown command" << std::endl;
148  return -1;
149  }
150  }
151 
152  try {
153  // Create a stream to the server using TCP.
154  ibrcommon::clientsocket *sock = NULL;
155 
156  // check if the unixdomain socket exists
157  if (_unixdomain.exists())
158  {
159  // connect to the unix domain socket
160  sock = new ibrcommon::filesocket(_unixdomain);
161  }
162  else
163  {
164  // connect to the standard local api port
165  ibrcommon::vaddress addr("localhost", 4550);
166  sock = new ibrcommon::tcpsocket(addr);
167  }
168 
169  ibrcommon::socketstream conn(sock);
170 
171  // Initiate a derivated client
172  BundleStream bs(conn, _min_chunk_size, _max_chunk_size, _source, _group, _wait_seq_zero);
173 
174  // set flow-control as requested
175  bs.setAutoFlush(_flow_control);
176 
177  // set the receive timeout
178  bs.setReceiveTimeout(_receive_timeout);
179 
180  // Connect to the server. Actually, this function initiate the
181  // stream protocol by starting the thread and sending the contact header.
182  bs.connect();
183 
184  // transmitter mode
185  if (_destination != dtn::data::EID())
186  {
187  bs.base().destination = _destination;
189  bs.base().lifetime = _lifetime;
190  if (_bundle_encryption) bs.base().set(dtn::data::PrimaryBlock::DTNSEC_REQUEST_ENCRYPT, true);
191  if (_bundle_signed) bs.base().set(dtn::data::PrimaryBlock::DTNSEC_REQUEST_SIGN, true);
192  if (_bundle_group) bs.base().set(dtn::data::PrimaryBlock::DESTINATION_IS_SINGLETON, false);
193  std::ostream stream(&bs.rdbuf());
194  stream << std::cin.rdbuf() << std::flush;
195  }
196  // receiver mode
197  else
198  {
199  std::istream stream(&bs.rdbuf());
200  std::cout << stream.rdbuf() << std::flush;
201  }
202 
203  // Shutdown the client connection.
204  bs.close();
205  conn.close();
206  } catch (const ibrcommon::socket_exception&) {
207  std::cerr << "Can not connect to the daemon. Does it run?" << std::endl;
208  return -1;
209  } catch (const std::exception&) {
210 
211  }
212 }