IBR-DTNSuite  0.12
ManagementConnection.cpp
Go to the documentation of this file.
1 /*
2  * ManagementConnection.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 "Configuration.h"
24 #include "DTNTPWorker.h"
25 #include "ManagementConnection.h"
26 #include "storage/BundleResult.h"
27 #include "core/BundleCore.h"
28 #include "core/Node.h"
31 
32 #include "core/EventDispatcher.h"
33 #include "core/GlobalEvent.h"
42 
43 #include <ibrdtn/utils/Clock.h>
44 #include <ibrdtn/utils/Utils.h>
45 
46 #include <ibrcommon/Logger.h>
50 
51 #include <iomanip>
52 
53 namespace dtn
54 {
55  namespace api
56  {
58  : ProtocolHandler(client, stream)
59  {
60  }
61 
63  {
64  }
65 
67  {
68  std::string buffer = "";
69  _stream << ClientHandler::API_STATUS_OK << " SWITCHED TO MANAGEMENT" << std::endl;
70 
71  // run as long the stream is ok
72  while (_stream.good())
73  {
74  getline(_stream, buffer);
75 
76  if (buffer.length() == 0) continue;
77 
78  // search for '\r\n' and remove the '\r'
79  std::string::reverse_iterator iter = buffer.rbegin();
80  if ( (*iter) == '\r' ) buffer = buffer.substr(0, buffer.length() - 1);
81 
82  std::vector<std::string> cmd = dtn::utils::Utils::tokenize(" ", buffer);
83  if (cmd.empty()) continue;
84 
85  if (cmd[0] == "exit")
86  {
87  // return to previous level
88  break;
89  }
90  else
91  {
92  // forward to standard command set
93  processCommand(cmd);
94  }
95  }
96  }
97 
99  {
100  }
101 
103  {
104  }
105 
107  {
108  }
109 
110  void ManagementConnection::processCommand(const std::vector<std::string> &cmd)
111  {
112  class BundleFilter : public dtn::storage::BundleSelector
113  {
114  public:
115  BundleFilter()
116  {};
117 
118  virtual ~BundleFilter() {};
119 
120  virtual dtn::data::Size limit() const throw () { return 0; };
121 
122  virtual bool shouldAdd(const dtn::data::MetaBundle&) const throw (dtn::storage::BundleSelectorException)
123  {
124  return true;
125  }
126  };
127 
128  try {
129  if (cmd[0] == "neighbor")
130  {
131  if (cmd.size() < 2) throw ibrcommon::Exception("not enough parameters");
132 
133  if (cmd[1] == "list")
134  {
135  const std::set<dtn::core::Node> nlist = dtn::core::BundleCore::getInstance().getConnectionManager().getNeighbors();
136 
137  _stream << ClientHandler::API_STATUS_OK << " NEIGHBOR LIST" << std::endl;
138  for (std::set<dtn::core::Node>::const_iterator iter = nlist.begin(); iter != nlist.end(); ++iter)
139  {
140  _stream << (*iter).getEID().getString() << std::endl;
141  }
142  _stream << std::endl;
143  }
144  else
145  {
146  _stream << ClientHandler::API_STATUS_BAD_REQUEST << " UNKNOWN COMMAND" << std::endl;
147  }
148  }
149  else if (cmd[0] == "interface")
150  {
151  if (cmd[1] == "address")
152  {
153  try {
155 
156  // the interface is defined as the 3rd parameter
157  ibrcommon::vinterface iface(cmd[3]);
158 
159  // TODO: Throw out the 4th parameter. Previously used to define the
160  // address family.
161 
162  // the new address is defined as 5th parameter
163  ibrcommon::vaddress addr(cmd[5], "");
164 
165  if (cmd[2] == "add")
166  {
168  lm.raiseEvent(evt);
169  _stream << ClientHandler::API_STATUS_OK << " ADDRESS ADDED" << std::endl;
170  }
171  else if (cmd[2] == "del")
172  {
174  lm.raiseEvent(evt);
175  _stream << ClientHandler::API_STATUS_OK << " ADDRESS REMOVED" << std::endl;
176  }
177  else
178  {
179  _stream << ClientHandler::API_STATUS_BAD_REQUEST << " UNKNOWN COMMAND" << std::endl;
180  }
181  } catch (const std::bad_cast&) {
182  _stream << ClientHandler::API_STATUS_NOT_ALLOWED << " FEATURE NOT AVAILABLE" << std::endl;
183  };
184  }
185  else
186  {
187  _stream << ClientHandler::API_STATUS_BAD_REQUEST << " UNKNOWN COMMAND" << std::endl;
188  }
189  }
190  else if (cmd[0] == "connection")
191  {
192  // need to process the connection arguments
193  // the arguments look like:
194  // <eid> [tcp|udp|file] [add|del] <ip> <port> <global|local>
195  dtn::core::Node n(cmd[1]);
197 
198  if (cmd.size() > 6) {
199  if (cmd[6] == "global") {
201  } else {
203  }
204  }
205 
206  if (cmd[2] == "tcp")
207  {
208  if (cmd[3] == "add")
209  {
210  std::string uri = "ip=" + cmd[4] + ";port=" + cmd[5] + ";";
211  n.add(dtn::core::Node::URI(t, dtn::core::Node::CONN_TCPIP, uri, 0, 10));
213 
214  _stream << ClientHandler::API_STATUS_OK << " CONNECTION ADDED" << std::endl;
215  }
216  else if (cmd[3] == "del")
217  {
218  std::string uri = "ip=" + cmd[4] + ";port=" + cmd[5] + ";";
219  n.add(dtn::core::Node::URI(t, dtn::core::Node::CONN_TCPIP, uri, 0, 10));
221 
222  _stream << ClientHandler::API_STATUS_OK << " CONNECTION REMOVED" << std::endl;
223  }
224  }
225  else if (cmd[2] == "udp")
226  {
227  if (cmd[3] == "add")
228  {
229  std::string uri = "ip=" + cmd[4] + ";port=" + cmd[5] + ";";
230  n.add(dtn::core::Node::URI(t, dtn::core::Node::CONN_UDPIP, uri, 0, 10));
232 
233  _stream << ClientHandler::API_STATUS_OK << " CONNECTION ADDED" << std::endl;
234  }
235  else if (cmd[3] == "del")
236  {
237  std::string uri = "ip=" + cmd[4] + ";port=" + cmd[5] + ";";
238  n.add(dtn::core::Node::URI(t, dtn::core::Node::CONN_UDPIP, uri, 0, 10));
240 
241  _stream << ClientHandler::API_STATUS_OK << " CONNECTION REMOVED" << std::endl;
242  }
243  }
244  else if (cmd[2] == "file")
245  {
246  if (cmd[3] == "add")
247  {
250 
251  _stream << ClientHandler::API_STATUS_OK << " CONNECTION ADDED" << std::endl;
252  }
253  else if (cmd[3] == "del")
254  {
257 
258  _stream << ClientHandler::API_STATUS_OK << " CONNECTION REMOVED" << std::endl;
259  }
260  }
261  }
262  else if (cmd[0] == "logcat")
263  {
265  _stream << std::endl;
266  }
267  else if (cmd[0] == "core")
268  {
269  if (cmd[1] == "shutdown")
270  {
271  // send shutdown signal
273  _stream << ClientHandler::API_STATUS_OK << " SHUTDOWN" << std::endl;
274  }
275  else if (cmd[1] == "reload")
276  {
277  // send reload signal
279  _stream << ClientHandler::API_STATUS_OK << " RELOAD" << std::endl;
280  }
281  else if (cmd[1] == "resume")
282  {
283  // send powersave signal
285  _stream << ClientHandler::API_STATUS_OK << " RESUME" << std::endl;
286  }
287  else if (cmd[1] == "suspend")
288  {
289  // send suspend signal
291  _stream << ClientHandler::API_STATUS_OK << " SUSPEND" << std::endl;
292  }
293  else if (cmd[1] == "start_discovery")
294  {
295  // send wakeup signal
297  _stream << ClientHandler::API_STATUS_OK << " DISCOVERY START" << std::endl;
298  }
299  else if (cmd[1] == "stop_discovery")
300  {
301  // send wakeup signal
303  _stream << ClientHandler::API_STATUS_OK << " DISCOVERY STOP" << std::endl;
304  }
305  else if (cmd[1] == "internet_off")
306  {
307  // send internet off signal
309  _stream << ClientHandler::API_STATUS_OK << " INTERNET OFF" << std::endl;
310  }
311  else if (cmd[1] == "internet_on")
312  {
313  // send internet off signal
315  _stream << ClientHandler::API_STATUS_OK << " INTERNET ON" << std::endl;
316  }
317  }
318  else if (cmd[0] == "bundle")
319  {
320  if (cmd[1] == "list")
321  {
322  // get storage object
324  BundleFilter filter;
325 
326  _stream << ClientHandler::API_STATUS_OK << " BUNDLE LIST" << std::endl;
328 
329  try {
330  bcore.getStorage().get(filter, blist);
331 
332  for (std::list<dtn::data::MetaBundle>::const_iterator iter = blist.begin(); iter != blist.end(); ++iter)
333  {
334  const dtn::data::MetaBundle &b = *iter;
335  _stream << b.toString() << ";" << b.destination.getString() << ";" << std::endl;
336  }
337  } catch (const dtn::storage::NoBundleFoundException&) { }
338 
339  // last line empty
340  _stream << std::endl;
341  }
342  else if (cmd[1] == "clear")
343  {
344  // clear the storage
346  _stream << ClientHandler::API_STATUS_OK << " STORAGE CLEARED" << std::endl;
347  }
348  }
349  else if (cmd[0] == "routing")
350  {
351  if (cmd.size() < 3) throw ibrcommon::Exception("not enough parameters");
352 
353  if ( cmd[1] == "prophet" )
354  {
356 
357  // lock the extension list during the processing
359 
360  const dtn::routing::BaseRouter::extension_list& routingExtensions = router.getExtensions();
361  dtn::routing::BaseRouter::extension_list::const_iterator it;
362 
363  /* find the prophet extension in the BaseRouter */
364 
365  for(it = routingExtensions.begin(); it != routingExtensions.end(); ++it)
366  {
367  try
368  {
369  const dtn::routing::ProphetRoutingExtension& prophet_extension = dynamic_cast<const dtn::routing::ProphetRoutingExtension&>(**it);
370 
371  if ( cmd[2] == "info" ){
373 
374  _stream << ClientHandler::API_STATUS_OK << " ROUTING PROPHET INFO" << std::endl;
375  _stream << *dp_map << std::endl;
376  } else if ( cmd[2] == "acknowledgements" ) {
378 
379  _stream << ClientHandler::API_STATUS_OK << " ROUTING PROPHET ACKNOWLEDGEMENTS" << std::endl;
380  for (dtn::routing::AcknowledgementSet::const_iterator iter = (*ack_set).begin(); iter != (*ack_set).end(); ++iter)
381  {
382  const dtn::data::MetaBundle &ack = (*iter);
383  _stream << ack.toString() << " | " << ack.expiretime.toString() << std::endl;
384  }
385  _stream << std::endl;
386  } else {
387  throw ibrcommon::Exception("malformed command");
388  }
389 
390  break;
391  } catch (const std::bad_cast&) { }
392  }
393  if(it == routingExtensions.end())
394  {
395  /* no prophet routing extension found */
396  _stream << ClientHandler::API_STATUS_NOT_ACCEPTABLE << " ROUTING PROPHET EXTENSION NOT FOUND" << std::endl;
397  }
398  } else if ( cmd[1] == "static" ) {
399  if (cmd.size() < 5) throw ibrcommon::Exception("not enough parameters");
400 
401  if (cmd[2] == "add")
402  {
404  _stream << ClientHandler::API_STATUS_OK << " ROUTE ADDED FOR " << cmd[3] << " THROUGH " << cmd[4] << std::endl;
405  }
406  else if (cmd[2] == "del")
407  {
409  _stream << ClientHandler::API_STATUS_OK << " ROUTE REMOVED FOR " << cmd[3] << " THROUGH " << cmd[4] << std::endl;
410  }
411  } else {
412  throw ibrcommon::Exception("malformed command");
413  }
414  }
415  else if (cmd[0] == "stats")
416  {
417  if (cmd.size() < 2) throw ibrcommon::Exception("not enough parameters");
418 
419  if ( cmd[1] == "info" ) {
420  _stream << ClientHandler::API_STATUS_OK << " STATS INFO" << std::endl;
421  _stream << "Uptime: " << dtn::utils::Clock::getUptime().get<size_t>() << std::endl;
422  _stream << "Neighbors: " << dtn::core::BundleCore::getInstance().getConnectionManager().getNeighbors().size() << std::endl;
423  _stream << "Storage-size: " << dtn::core::BundleCore::getInstance().getStorage().size() << std::endl;
424  _stream << std::endl;
425  } else if ( cmd[1] == "timesync" ) {
426  _stream << ClientHandler::API_STATUS_OK << " STATS TIMESYNC" << std::endl;
427  _stream << "Timestamp: " << dtn::utils::Clock::getTime().get<size_t>() << std::endl;
428  _stream << "Offset: " << std::setprecision(6) << dtn::utils::Clock::toDouble(dtn::utils::Clock::getOffset()) << std::endl;
429  _stream << "Rating: " << std::setprecision(16) << dtn::utils::Clock::getRating() << std::endl;
431 
433 
434  _stream << "Base: " << std::setprecision(16) << state.base_rating << std::endl;
435  _stream << "Psi: " << std::setprecision(16) << state.psi << std::endl;
436  _stream << "Sigma: " << std::setprecision(16) << state.sigma << std::endl;
437  _stream << "Threshold: " << std::setprecision(6) << state.sync_threshold << std::endl;
438 
439  _stream << std::endl;
440  } else if ( cmd[1] == "bundles" ) {
441  _stream << ClientHandler::API_STATUS_OK << " STATS BUNDLES" << std::endl;
442  _stream << "Stored: " << dtn::core::BundleCore::getInstance().getStorage().count() << std::endl;
450  _stream << std::endl;
451  } else if ( cmd[1] == "convergencelayers" ) {
452  _stream << ClientHandler::API_STATUS_OK << " STATS CONVERGENCELAYERS" << std::endl;
453 
456 
457  for (dtn::net::ConvergenceLayer::stats_data::const_iterator iter = data.begin(); iter != data.end(); ++iter) {
458  const dtn::net::ConvergenceLayer::stats_pair &pair = (*iter);
459  _stream << pair.first << ": " << pair.second << std::endl;
460  }
461  _stream << std::endl;
462  } else if ( cmd[1] == "reset" ) {
470 
471  // reset cl stats
473 
474  _stream << ClientHandler::API_STATUS_ACCEPTED << " STATS RESET" << std::endl;
475  } else {
476  throw ibrcommon::Exception("malformed command");
477  }
478  }
479  else
480  {
481  _stream << ClientHandler::API_STATUS_BAD_REQUEST << " UNKNOWN COMMAND" << std::endl;
482  }
483  } catch (const std::exception&) {
484  _stream << ClientHandler::API_STATUS_BAD_REQUEST << " ERROR" << std::endl;
485  }
486  }
487  } /* namespace api */
488 } /* namespace dtn */