IBR-DTNSuite  0.10
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 "ManagementConnection.h"
25 #include "storage/BundleResult.h"
26 #include "core/BundleCore.h"
27 #include "core/Node.h"
30 
31 #include "core/EventDispatcher.h"
32 #include "core/GlobalEvent.h"
41 
42 #include <ibrdtn/utils/Clock.h>
43 #include <ibrdtn/utils/Utils.h>
44 
45 #include <ibrcommon/Logger.h>
49 
50 #include <iomanip>
51 
52 namespace dtn
53 {
54  namespace api
55  {
57  : ProtocolHandler(client, stream)
58  {
59  }
60 
62  {
63  }
64 
66  {
67  std::string buffer = "";
68  _stream << ClientHandler::API_STATUS_OK << " SWITCHED TO MANAGEMENT" << std::endl;
69 
70  // run as long the stream is ok
71  while (_stream.good())
72  {
73  getline(_stream, buffer);
74 
75  if (buffer.length() == 0) continue;
76 
77  // search for '\r\n' and remove the '\r'
78  std::string::reverse_iterator iter = buffer.rbegin();
79  if ( (*iter) == '\r' ) buffer = buffer.substr(0, buffer.length() - 1);
80 
81  std::vector<std::string> cmd = dtn::utils::Utils::tokenize(" ", buffer);
82  if (cmd.empty()) continue;
83 
84  if (cmd[0] == "exit")
85  {
86  // return to previous level
87  break;
88  }
89  else
90  {
91  // forward to standard command set
92  processCommand(cmd);
93  }
94  }
95  }
96 
98  {
99  }
100 
102  {
103  }
104 
106  {
107  }
108 
109  void ManagementConnection::processCommand(const std::vector<std::string> &cmd)
110  {
111  class BundleFilter : public dtn::storage::BundleSelector
112  {
113  public:
114  BundleFilter()
115  {};
116 
117  virtual ~BundleFilter() {};
118 
119  virtual dtn::data::Size limit() const throw () { return 0; };
120 
121  virtual bool shouldAdd(const dtn::data::MetaBundle&) const throw (dtn::storage::BundleSelectorException)
122  {
123  return true;
124  }
125  };
126 
127  try {
128  if (cmd[0] == "neighbor")
129  {
130  if (cmd.size() < 2) throw ibrcommon::Exception("not enough parameters");
131 
132  if (cmd[1] == "list")
133  {
134  const std::set<dtn::core::Node> nlist = dtn::core::BundleCore::getInstance().getConnectionManager().getNeighbors();
135 
136  _stream << ClientHandler::API_STATUS_OK << " NEIGHBOR LIST" << std::endl;
137  for (std::set<dtn::core::Node>::const_iterator iter = nlist.begin(); iter != nlist.end(); ++iter)
138  {
139  _stream << (*iter).getEID().getString() << std::endl;
140  }
141  _stream << std::endl;
142  }
143  else
144  {
145  _stream << ClientHandler::API_STATUS_BAD_REQUEST << " UNKNOWN COMMAND" << std::endl;
146  }
147  }
148  else if (cmd[0] == "interface")
149  {
150  if (cmd[1] == "address")
151  {
152  try {
154 
155  // the interface is defined as the 3rd parameter
156  ibrcommon::vinterface iface(cmd[3]);
157 
158  // TODO: Throw out the 4th parameter. Previously used to define the
159  // address family.
160 
161  // the new address is defined as 5th parameter
162  ibrcommon::vaddress addr(cmd[5], "");
163 
164  if (cmd[2] == "add")
165  {
167  lm.raiseEvent(evt);
168  _stream << ClientHandler::API_STATUS_OK << " ADDRESS ADDED" << std::endl;
169  }
170  else if (cmd[2] == "del")
171  {
173  lm.raiseEvent(evt);
174  _stream << ClientHandler::API_STATUS_OK << " ADDRESS REMOVED" << std::endl;
175  }
176  else
177  {
178  _stream << ClientHandler::API_STATUS_BAD_REQUEST << " UNKNOWN COMMAND" << std::endl;
179  }
180  } catch (const std::bad_cast&) {
181  _stream << ClientHandler::API_STATUS_NOT_ALLOWED << " FEATURE NOT AVAILABLE" << std::endl;
182  };
183  }
184  else
185  {
186  _stream << ClientHandler::API_STATUS_BAD_REQUEST << " UNKNOWN COMMAND" << std::endl;
187  }
188  }
189  else if (cmd[0] == "connection")
190  {
191  // need to process the connection arguments
192  // the arguments look like:
193  // <eid> [tcp|udp|file] [add|del] <ip> <port> <global|local>
194  dtn::core::Node n(cmd[1]);
196 
197  if (cmd.size() > 6) {
198  if (cmd[6] == "global") {
200  } else {
202  }
203  }
204 
205  if (cmd[2] == "tcp")
206  {
207  if (cmd[3] == "add")
208  {
209  std::string uri = "ip=" + cmd[4] + ";port=" + cmd[5] + ";";
210  n.add(dtn::core::Node::URI(t, dtn::core::Node::CONN_TCPIP, uri, 0, 10));
212 
213  _stream << ClientHandler::API_STATUS_OK << " CONNECTION ADDED" << std::endl;
214  }
215  else if (cmd[3] == "del")
216  {
217  std::string uri = "ip=" + cmd[4] + ";port=" + cmd[5] + ";";
218  n.add(dtn::core::Node::URI(t, dtn::core::Node::CONN_TCPIP, uri, 0, 10));
220 
221  _stream << ClientHandler::API_STATUS_OK << " CONNECTION REMOVED" << std::endl;
222  }
223  }
224  else if (cmd[2] == "udp")
225  {
226  if (cmd[3] == "add")
227  {
228  std::string uri = "ip=" + cmd[4] + ";port=" + cmd[5] + ";";
229  n.add(dtn::core::Node::URI(t, dtn::core::Node::CONN_UDPIP, uri, 0, 10));
231 
232  _stream << ClientHandler::API_STATUS_OK << " CONNECTION ADDED" << std::endl;
233  }
234  else if (cmd[3] == "del")
235  {
236  std::string uri = "ip=" + cmd[4] + ";port=" + cmd[5] + ";";
237  n.add(dtn::core::Node::URI(t, dtn::core::Node::CONN_UDPIP, uri, 0, 10));
239 
240  _stream << ClientHandler::API_STATUS_OK << " CONNECTION REMOVED" << std::endl;
241  }
242  }
243  else if (cmd[2] == "file")
244  {
245  if (cmd[3] == "add")
246  {
249 
250  _stream << ClientHandler::API_STATUS_OK << " CONNECTION ADDED" << std::endl;
251  }
252  else if (cmd[3] == "del")
253  {
256 
257  _stream << ClientHandler::API_STATUS_OK << " CONNECTION REMOVED" << std::endl;
258  }
259  }
260  }
261  else if (cmd[0] == "logcat")
262  {
264  _stream << std::endl;
265  }
266  else if (cmd[0] == "core")
267  {
268  if (cmd[1] == "shutdown")
269  {
270  // send shutdown signal
272  _stream << ClientHandler::API_STATUS_OK << " SHUTDOWN" << std::endl;
273  }
274  else if (cmd[1] == "reload")
275  {
276  // send reload signal
278  _stream << ClientHandler::API_STATUS_OK << " RELOAD" << std::endl;
279  }
280  else if (cmd[1] == "powersave")
281  {
282  // send powersave signal
284  _stream << ClientHandler::API_STATUS_OK << " POWERSAVE" << std::endl;
285  }
286  else if (cmd[1] == "suspend")
287  {
288  // send suspend signal
290  _stream << ClientHandler::API_STATUS_OK << " SUSPEND" << std::endl;
291  }
292  else if (cmd[1] == "wakeup")
293  {
294  // send wakeup signal
296  _stream << ClientHandler::API_STATUS_OK << " WAKEUP" << std::endl;
297  }
298  else if (cmd[1] == "internet_off")
299  {
300  // send internet off signal
302  _stream << ClientHandler::API_STATUS_OK << " INTERNET OFF" << std::endl;
303  }
304  else if (cmd[1] == "internet_on")
305  {
306  // send internet off signal
308  _stream << ClientHandler::API_STATUS_OK << " INTERNET ON" << std::endl;
309  }
310  }
311  else if (cmd[0] == "bundle")
312  {
313  if (cmd[1] == "list")
314  {
315  // get storage object
317  BundleFilter filter;
318 
319  _stream << ClientHandler::API_STATUS_OK << " BUNDLE LIST" << std::endl;
321 
322  try {
323  bcore.getStorage().get(filter, blist);
324 
325  for (std::list<dtn::data::MetaBundle>::const_iterator iter = blist.begin(); iter != blist.end(); ++iter)
326  {
327  const dtn::data::MetaBundle &b = *iter;
328  _stream << b.toString() << ";" << b.destination.getString() << ";" << std::endl;
329  }
330  } catch (const dtn::storage::NoBundleFoundException&) { }
331 
332  // last line empty
333  _stream << std::endl;
334  }
335  }
336  else if (cmd[0] == "routing")
337  {
338  if (cmd.size() < 3) throw ibrcommon::Exception("not enough parameters");
339 
340  if ( cmd[1] == "prophet" )
341  {
343 
344  // lock the extension list during the processing
346 
347  const dtn::routing::BaseRouter::extension_list& routingExtensions = router.getExtensions();
348  dtn::routing::BaseRouter::extension_list::const_iterator it;
349 
350  /* find the prophet extension in the BaseRouter */
351 
352  for(it = routingExtensions.begin(); it != routingExtensions.end(); ++it)
353  {
354  try
355  {
356  const dtn::routing::ProphetRoutingExtension& prophet_extension = dynamic_cast<const dtn::routing::ProphetRoutingExtension&>(**it);
357 
358  if ( cmd[2] == "info" ){
360 
361  _stream << ClientHandler::API_STATUS_OK << " ROUTING PROPHET INFO" << std::endl;
362  _stream << *dp_map << std::endl;
363  } else if ( cmd[2] == "acknowledgements" ) {
365 
366  _stream << ClientHandler::API_STATUS_OK << " ROUTING PROPHET ACKNOWLEDGEMENTS" << std::endl;
367  for (dtn::routing::AcknowledgementSet::const_iterator iter = (*ack_set).begin(); iter != (*ack_set).end(); ++iter)
368  {
369  const dtn::data::MetaBundle &ack = (*iter);
370  _stream << ack.toString() << " | " << ack.expiretime.toString() << std::endl;
371  }
372  _stream << std::endl;
373  } else {
374  throw ibrcommon::Exception("malformed command");
375  }
376 
377  break;
378  } catch (const std::bad_cast&) { }
379  }
380  if(it == routingExtensions.end())
381  {
382  /* no prophet routing extension found */
383  _stream << ClientHandler::API_STATUS_NOT_ACCEPTABLE << " ROUTING PROPHET EXTENSION NOT FOUND" << std::endl;
384  }
385  } else {
386  throw ibrcommon::Exception("malformed command");
387  }
388  }
389  else if (cmd[0] == "stats")
390  {
391  if (cmd.size() < 2) throw ibrcommon::Exception("not enough parameters");
392 
393  if ( cmd[1] == "info" ) {
394  _stream << ClientHandler::API_STATUS_OK << " STATS INFO" << std::endl;
395  _stream << "Uptime: " << dtn::utils::Clock::getUptime().get<size_t>() << std::endl;
396  _stream << "Neighbors: " << dtn::core::BundleCore::getInstance().getConnectionManager().getNeighbors().size() << std::endl;
397  _stream << "Storage-size: " << dtn::core::BundleCore::getInstance().getStorage().size() << std::endl;
398  _stream << std::endl;
399  } else if ( cmd[1] == "timesync" ) {
400  _stream << ClientHandler::API_STATUS_OK << " STATS TIMESYNC" << std::endl;
401  _stream << "Timestamp: " << dtn::utils::Clock::getTime().get<size_t>() << std::endl;
402  _stream << "Offset: " << std::setprecision(6) << dtn::utils::Clock::toDouble(dtn::utils::Clock::getOffset()) << std::endl;
403  _stream << "Rating: " << std::setprecision(16) << dtn::utils::Clock::getRating() << std::endl;
405  _stream << std::endl;
406  } else if ( cmd[1] == "bundles" ) {
407  _stream << ClientHandler::API_STATUS_OK << " STATS BUNDLES" << std::endl;
408  _stream << "Stored: " << dtn::core::BundleCore::getInstance().getStorage().count() << std::endl;
416  _stream << std::endl;
417  } else if ( cmd[1] == "convergencelayers" ) {
419 
420  _stream << ClientHandler::API_STATUS_OK << " STATS CONVERGENCELAYERS" << std::endl;
421  for (ConnectionManager::stats_list::const_iterator iter = list.begin(); iter != list.end(); ++iter) {
422  const ConnectionManager::stats_pair &pair = (*iter);
423  const ConvergenceLayer::stats_map &map = pair.second;
424 
425  for (ConvergenceLayer::stats_map::const_iterator map_it = map.begin(); map_it != map.end(); ++map_it) {
426  _stream << dtn::core::Node::toString(pair.first) << "|" << (*map_it).first << ": " << (*map_it).second << std::endl;
427  }
428  }
429  _stream << std::endl;
430  } else if ( cmd[1] == "reset" ) {
438 
439  // reset cl stats
441 
442  _stream << ClientHandler::API_STATUS_ACCEPTED << " STATS RESET" << std::endl;
443  } else {
444  throw ibrcommon::Exception("malformed command");
445  }
446  }
447  else
448  {
449  _stream << ClientHandler::API_STATUS_BAD_REQUEST << " UNKNOWN COMMAND" << std::endl;
450  }
451  } catch (const std::exception&) {
452  _stream << ClientHandler::API_STATUS_BAD_REQUEST << " ERROR" << std::endl;
453  }
454  }
455  } /* namespace api */
456 } /* namespace dtn */