IBR-DTNSuite  0.12
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>
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  // print help if not enough parameters are set
74  if (argc < 3)
75  {
76  print_help();
77  exit(EXIT_SUCCESS);
78  }
79  while(1)
80  {
81  /* getopt_long stores the option index here. */
82  int option_index = 0;
83  int c = getopt_long (argc, argv, "hw:q",
84  long_options, &option_index);
85  /* Detect the end of the options. */
86  if (c == -1)
87  break;
88 
89  switch (c)
90  {
91  case 0:
92  /* If this option set a flag, do nothing else now. */
93  if (long_options[option_index].flag != 0)
94  break;
95  printf ("option %s", long_options[option_index].name);
96  if (optarg)
97  printf (" with arg %s", optarg);
98  printf ("\n");
99  break;
100 
101  case 'h':
102  print_help();
103  exit(EXIT_SUCCESS);
104  break;
105  case 'w':
106  _conf_workdir = std::string(optarg);
107  break;
108  default:
109  abort();
110  break;
111  }
112  }
113 
114  _conf_name = std::string(argv[optind]);
115  _conf_inbox = std::string(argv[optind+1]);
116 }
117 
118 
119 
120 // set this variable to false to stop the app
121 bool _running = true;
122 
123 // global connection
125 
126 void term(int signal)
127 {
128  if (signal >= 1)
129  {
130  _running = false;
131  if (_conn != NULL) _conn->close();
132  }
133 }
134 
135 /*
136  * main application method
137  */
138 int main(int argc, char** argv)
139 {
140  // catch process signals
141  ibrcommon::SignalHandler sighandler(term);
142  sighandler.handle(SIGINT);
143  sighandler.handle(SIGTERM);
144 
145  // read the configuration
146  read_configuration(argc, argv);
147 
148  //initialize sighandler after possible exit call
149  sighandler.initialize();
150 
151  if (_conf_workdir.length() > 0)
152  {
154 
155  if (blob_path.exists())
156  {
158  }
159  }
160 
161  // backoff for reconnect
162  unsigned int backoff = 2;
163 
164  // loop, if no stop if requested
165  while (_running)
166  {
167  try {
168  // Create a stream to the server using TCP.
169  ibrcommon::vaddress addr("localhost", 4550);
171 
172  // set the connection globally
173  _conn = &conn;
174 
175  // Initiate a client for synchronous receiving
176  dtn::api::Client client(_conf_name, conn);
177 
178  // Connect to the server. Actually, this function initiate the
179  // stream protocol by starting the thread and sending the contact header.
180  client.connect();
181 
182  // reset backoff if connected
183  backoff = 2;
184 
185  // check the connection
186  while (_running)
187  {
188  // receive the bundle
189  dtn::data::Bundle b = client.getBundle();
190  if(!_conf_quiet)
191  std::cout << "received bundle: " << b.toString() << std::endl;
192 
193  // get the reference to the blob
195 
196  // write files into BLOB while it is locked
197  {
198  ibrcommon::BLOB::iostream stream = ref.iostream();
200  }
201  }
202 
203  // close the client connection
204  client.close();
205 
206  // close the connection
207  conn.close();
208 
209  // set the global connection to NULL
210  _conn = NULL;
211  } catch (const ibrcommon::socket_exception&) {
212  // set the global connection to NULL
213  _conn = NULL;
214 
215  if (_running)
216  {
217  std::cout << "Connection to bundle daemon failed. Retry in " << backoff << " seconds." << std::endl;
218  ibrcommon::Thread::sleep(backoff * 1000);
219 
220  // if backoff < 10 minutes
221  if (backoff < 600)
222  {
223  // set a new backoff
224  backoff = backoff * 2;
225  }
226  }
227  } catch (const ibrcommon::IOException&) {
228  // set the global connection to NULL
229  _conn = NULL;
230 
231  if (_running)
232  {
233  std::cout << "Connection to bundle daemon failed. Retry in " << backoff << " seconds." << std::endl;
234  ibrcommon::Thread::sleep(backoff * 1000);
235 
236  // if backoff < 10 minutes
237  if (backoff < 600)
238  {
239  // set a new backoff
240  backoff = backoff * 2;
241  }
242  }
243  } catch (const std::exception&) {
244  // set the global connection to NULL
245  _conn = NULL;
246  }
247  }
248 
249  return (EXIT_SUCCESS);
250 }