IBR-DTNSuite  0.10
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"
28 #include "ibrdtn/data/Bundle.h"
29 #include "ibrcommon/data/BLOB.h"
30 #include "ibrcommon/data/File.h"
31 #include "ibrcommon/appstreambuf.h"
32 
33 #include <stdlib.h>
34 #include <iostream>
35 #include <map>
36 #include <vector>
37 #include <csignal>
38 #include <sys/types.h>
39 #include <unistd.h>
40 
41 using namespace ibrcommon;
42 
43 void print_help()
44 {
45  cout << "-- dtninbox (IBR-DTN) --" << endl;
46  cout << "Syntax: dtninbox [options] <name> <inbox>" << endl;
47  cout << " <name> the application name" << endl;
48  cout << " <inbox> directory where incoming files should be placed" << endl;
49  cout << "* optional parameters *" << endl;
50  cout << " -h|--help display this text" << endl;
51  cout << " -w|--workdir temporary work directory" << endl;
52 }
53 
54 map<string,string> readconfiguration(int argc, char** argv)
55 {
56  // print help if not enough parameters are set
57  if (argc < 3) { print_help(); exit(0); }
58 
59  map<string,string> ret;
60 
61  ret["name"] = argv[argc - 2];
62  ret["inbox"] = argv[argc - 1];
63 
64  for (int i = 0; i < (argc - 2); ++i)
65  {
66  string arg = argv[i];
67 
68  // print help if requested
69  if (arg == "-h" || arg == "--help")
70  {
71  print_help();
72  exit(0);
73  }
74 
75  if ((arg == "-w" || arg == "--workdir") && (argc > i))
76  {
77  ret["workdir"] = argv[i + 1];
78  }
79  }
80 
81  return ret;
82 }
83 
84 // set this variable to false to stop the app
85 bool _running = true;
86 
87 // global connection
89 
90 void term(int signal)
91 {
92  if (signal >= 1)
93  {
94  _running = false;
95  if (_conn != NULL) _conn->close();
96  }
97 }
98 
99 /*
100  * main application method
101  */
102 int main(int argc, char** argv)
103 {
104  // catch process signals
105  signal(SIGINT, term);
106  signal(SIGTERM, term);
107 
108  // read the configuration
109  map<string,string> conf = readconfiguration(argc, argv);
110 
111  // init working directory
112  if (conf.find("workdir") != conf.end())
113  {
114  ibrcommon::File blob_path(conf["workdir"]);
115 
116  if (blob_path.exists())
117  {
119  }
120  }
121 
122  // backoff for reconnect
123  unsigned int backoff = 2;
124 
125  // check outbox for files
126  File outbox(conf["outbox"]);
127 
128  // loop, if no stop if requested
129  while (_running)
130  {
131  try {
132  // Create a stream to the server using TCP.
133  ibrcommon::vaddress addr("localhost", 4550);
135 
136  // set the connection globally
137  _conn = &conn;
138 
139  // Initiate a client for synchronous receiving
140  dtn::api::Client client(conf["name"], conn);
141 
142  // Connect to the server. Actually, this function initiate the
143  // stream protocol by starting the thread and sending the contact header.
144  client.connect();
145 
146  // reset backoff if connected
147  backoff = 2;
148 
149  // check the connection
150  while (_running)
151  {
152  // receive the bundle
153  dtn::data::Bundle b = client.getBundle();
154 
155  // get the reference to the blob
157 
158  // create the extract command
159  stringstream cmdstream; cmdstream << "tar -x -C " << conf["inbox"];
160 
161  // create a tar handler
162  appstreambuf extractor(cmdstream.str(), appstreambuf::MODE_WRITE);
163  ostream stream(&extractor);
164 
165  // write the payload to the extractor
166  stream << ref.iostream()->rdbuf();
167 
168  // flush the stream
169  stream.flush();
170  }
171 
172  // close the client connection
173  client.close();
174 
175  // close the connection
176  conn.close();
177 
178  // set the global connection to NULL
179  _conn = NULL;
180  } catch (const ibrcommon::socket_exception&) {
181  // set the global connection to NULL
182  _conn = NULL;
183 
184  if (_running)
185  {
186  cout << "Connection to bundle daemon failed. Retry in " << backoff << " seconds." << endl;
187  sleep(backoff);
188 
189  // if backoff < 10 minutes
190  if (backoff < 600)
191  {
192  // set a new backoff
193  backoff = backoff * 2;
194  }
195  }
196  } catch (const ibrcommon::IOException&) {
197  // set the global connection to NULL
198  _conn = NULL;
199 
200  if (_running)
201  {
202  cout << "Connection to bundle daemon failed. Retry in " << backoff << " seconds." << endl;
203  sleep(backoff);
204 
205  // if backoff < 10 minutes
206  if (backoff < 600)
207  {
208  // set a new backoff
209  backoff = backoff * 2;
210  }
211  }
212  } catch (const std::exception&) {
213  // set the global connection to NULL
214  _conn = NULL;
215  }
216  }
217 
218  return (EXIT_SUCCESS);
219 }