IBR-DTN  1.0.0
dtninbox.cpp
Go to the documentation of this file.
1 /*
2  * dtninbox.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>
26 #include <ibrcommon/thread/MutexLock.h>
27 #include <ibrcommon/thread/SignalHandler.h>
29 #include <ibrdtn/data/Bundle.h>
30 #include <ibrcommon/data/BLOB.h>
31 #include <ibrcommon/data/File.h>
32 #include <ibrcommon/appstreambuf.h>
33 
34 #include <stdlib.h>
35 #include <iostream>
36 #include <map>
37 #include <vector>
38 #include <sys/types.h>
39 #include <unistd.h>
40 #include <getopt.h>
41 
42 #include "io/TarUtils.h"
43 
44 //global conf values
45 string _conf_name;
46 string _conf_inbox;
47 
48 //optional parameters
50 int _conf_quiet = false;
51 
52 struct option long_options[] =
53 {
54  {"workdir", required_argument, 0, 'w'},
55  {"quiet", no_argument, 0, 'q'},
56  {0, 0, 0, 0}
57 };
58 
59 void print_help()
60 {
61  std::cout << "-- dtninbox (IBR-DTN) --" << std::endl;
62  std::cout << "Syntax: dtninbox [options] <name> <inbox>" << std::endl;
63  std::cout << " <name> The application name" << std::endl;
64  std::cout << " <inbox> Directory where incoming files should be placed" << std::endl << std::endl;
65  std::cout << "* optional parameters *" << std::endl;
66  std::cout << " -h|--help Display this text" << std::endl;
67  std::cout << " -w|--workdir Temporary work directory" << std::endl;
68  std::cout << " --quiet Only print error messages" << std::endl;
69 }
70 
71 void read_configuration(int argc, char** argv)
72 {
73  while(1)
74  {
75  /* getopt_long stores the option index here. */
76  int option_index = 0;
77  int c = getopt_long (argc, argv, "hw:q",
78  long_options, &option_index);
79  /* Detect the end of the options. */
80  if (c == -1)
81  break;
82 
83  switch (c)
84  {
85  case 0:
86  /* If this option set a flag, do nothing else now. */
87  if (long_options[option_index].flag != 0)
88  break;
89  printf ("option %s", long_options[option_index].name);
90  if (optarg)
91  printf (" with arg %s", optarg);
92  printf ("\n");
93  break;
94 
95  case 'h':
96  print_help();
97  exit(EXIT_SUCCESS);
98  break;
99  case 'w':
100  _conf_workdir = std::string(optarg);
101  break;
102  default:
103  abort();
104  break;
105  }
106  }
107 
108  // print help if not enough parameters are set
109  if ((argc - optind) < 2)
110  {
111  print_help();
112  exit(EXIT_FAILURE);
113  }
114 
115  _conf_name = std::string(argv[optind]);
116  _conf_inbox = std::string(argv[optind+1]);
117 }
118 
119 
120 
121 // set this variable to false to stop the app
122 bool _running = true;
123 
124 // global connection
125 ibrcommon::socketstream *_conn = NULL;
126 
127 void term(int signal)
128 {
129  if (signal >= 1)
130  {
131  _running = false;
132  if (_conn != NULL) _conn->close();
133  }
134 }
135 
136 /*
137  * main application method
138  */
139 int main(int argc, char** argv)
140 {
141  // catch process signals
142  ibrcommon::SignalHandler sighandler(term);
143  sighandler.handle(SIGINT);
144  sighandler.handle(SIGTERM);
145 
146  // read the configuration
147  read_configuration(argc, argv);
148 
149  //initialize sighandler after possible exit call
150  sighandler.initialize();
151 
152  if (_conf_workdir.length() > 0)
153  {
154  ibrcommon::File blob_path(_conf_workdir);
155 
156  if (blob_path.exists())
157  {
158  ibrcommon::BLOB::changeProvider(new ibrcommon::FileBLOBProvider(blob_path), true);
159  }
160  }
161 
162  // backoff for reconnect
163  unsigned int backoff = 2;
164 
165  // loop, if no stop if requested
166  while (_running)
167  {
168  try {
169  // Create a stream to the server using TCP.
170  ibrcommon::vaddress addr("localhost", 4550);
171  ibrcommon::socketstream conn(new ibrcommon::tcpsocket(addr));
172 
173  // set the connection globally
174  _conn = &conn;
175 
176  // Initiate a client for synchronous receiving
177  dtn::api::Client client(_conf_name, conn);
178 
179  // Connect to the server. Actually, this function initiate the
180  // stream protocol by starting the thread and sending the contact header.
181  client.connect();
182 
183  // reset backoff if connected
184  backoff = 2;
185 
186  // check the connection
187  while (_running)
188  {
189  // receive the bundle
190  dtn::data::Bundle b = client.getBundle();
191  if(!_conf_quiet)
192  std::cout << "received bundle: " << b.toString() << std::endl;
193 
194  // get the reference to the blob
195  ibrcommon::BLOB::Reference ref = b.find<dtn::data::PayloadBlock>().getBLOB();
196 
197  // write files into BLOB while it is locked
198  {
199  ibrcommon::BLOB::iostream stream = ref.iostream();
201  }
202  }
203 
204  // close the client connection
205  client.close();
206 
207  // close the connection
208  conn.close();
209 
210  // set the global connection to NULL
211  _conn = NULL;
212  } catch (const ibrcommon::socket_exception&) {
213  // set the global connection to NULL
214  _conn = NULL;
215 
216  if (_running)
217  {
218  std::cout << "Connection to bundle daemon failed. Retry in " << backoff << " seconds." << std::endl;
219  ibrcommon::Thread::sleep(backoff * 1000);
220 
221  // if backoff < 10 minutes
222  if (backoff < 600)
223  {
224  // set a new backoff
225  backoff = backoff * 2;
226  }
227  }
228  } catch (const ibrcommon::IOException&) {
229  // set the global connection to NULL
230  _conn = NULL;
231 
232  if (_running)
233  {
234  std::cout << "Connection to bundle daemon failed. Retry in " << backoff << " seconds." << std::endl;
235  ibrcommon::Thread::sleep(backoff * 1000);
236 
237  // if backoff < 10 minutes
238  if (backoff < 600)
239  {
240  // set a new backoff
241  backoff = backoff * 2;
242  }
243  }
244  } catch (const std::exception&) {
245  // set the global connection to NULL
246  _conn = NULL;
247  }
248  }
249 
250  return (EXIT_SUCCESS);
251 }
std::string toString() const
Definition: BundleID.cpp:190
string _conf_name
Definition: dtninbox.cpp:45
ibrcommon::socketstream * _conn
Definition: dtninbox.cpp:125
int main(int argc, char **argv)
Definition: dtninbox.cpp:139
static void read(const ibrcommon::File &extract_folder, std::istream &input)
Definition: TarUtils.cpp:88
void term(int signal)
Definition: dtninbox.cpp:127
void print_help()
Definition: dtninbox.cpp:59
dtn::data::Bundle getBundle(const dtn::data::Timeout timeout=0)
Definition: Client.cpp:209
bool _running
Definition: dtninbox.cpp:122
void read_configuration(int argc, char **argv)
Definition: dtninbox.cpp:71
struct option long_options[]
Definition: dtninbox.cpp:52
string _conf_inbox
Definition: dtninbox.cpp:46
ibrcommon::File blob_path("/tmp")
iterator find(block_t blocktype)
Definition: Bundle.cpp:307
int _conf_quiet
Definition: dtninbox.cpp:50
string _conf_workdir
Definition: dtninbox.cpp:49
void connect()
Definition: Client.cpp:113