00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 #include <config.h>
00044 #ifdef XERCES_C_ENABLED
00045
00046 #include <iostream>
00047 #include <map>
00048 #include <sys/ioctl.h>
00049 #include <tcl.h>
00050 #include <string.h>
00051 #include <netinet/in.h>
00052
00053 #include "ExternalRouter.h"
00054 #include "bundling/BundleDaemon.h"
00055 #include "bundling/BundleActions.h"
00056 #include "contacts/ContactManager.h"
00057 #include "reg/RegistrationTable.h"
00058
00059 #include <oasys/io/UDPClient.h>
00060 #include <oasys/tclcmd/TclCommand.h>
00061 #include <oasys/io/IO.h>
00062
00063 namespace dtn {
00064
00065 ExternalRouter::ExternalRouter()
00066 : BundleRouter("ExternalRouter", "external")
00067 {
00068 log_notice("Initializing ExternalRouter");
00069 }
00070
00071 ExternalRouter::~ExternalRouter()
00072 {
00073 delete srv_;
00074 delete hello_;
00075 delete reg_;
00076 delete route_table_;
00077 }
00078
00079
00080 void
00081 ExternalRouter::initialize()
00082 {
00083
00084 route_table_ = new RouteTable("external");
00085
00086
00087 reg_ = new ERRegistration(this);
00088
00089
00090 hello_ = new HelloTimer(this);
00091
00092
00093 BundleDaemon::instance()->set_rtr_shutdown(
00094 external_rtr_shutdown, (void *) 0);
00095
00096
00097 srv_ = new ModuleServer();
00098 srv_->start();
00099
00100 if (ExternalRouter::client_validation) {
00101 oasys::StringBuffer alert_with_ns(
00102 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
00103 "<dtn eid=\"%s\" hello_interval=\"%i\" alert=\"justBooted\" "
00104 "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
00105 "xsi:noNamespaceSchemaLocation=\"file://%s\"/>",
00106 BundleDaemon::instance()->local_eid().c_str(),
00107 ExternalRouter::hello_interval,
00108 ExternalRouter::schema.c_str());
00109
00110 srv_->eventq->push_back(
00111 new std::string(alert_with_ns.c_str()));
00112 } else {
00113 oasys::StringBuffer alert(
00114 "<dtn eid=\"%s\" hello_interval=\"%i\" alert=\"justBooted\"/>",
00115 BundleDaemon::instance()->local_eid().c_str(),
00116 ExternalRouter::hello_interval);
00117
00118 srv_->eventq->push_back(
00119 new std::string(alert.c_str()));
00120 }
00121
00122 hello_->schedule_in(ExternalRouter::hello_interval * 1000);
00123 }
00124
00125
00126 void
00127 ExternalRouter::get_routing_state(oasys::StringBuffer* buf)
00128 {
00129 EndpointIDVector long_eids;
00130 buf->appendf("Static route table for %s router(s):\n", name_.c_str());
00131 route_table_->dump(buf, &long_eids);
00132
00133 if (long_eids.size() > 0) {
00134 buf->appendf("\nLong Endpoint IDs referenced above:\n");
00135 for (u_int i = 0; i < long_eids.size(); ++i) {
00136 buf->appendf("\t[%d]: %s\n", i, long_eids[i].c_str());
00137 }
00138 buf->appendf("\n");
00139 }
00140
00141 buf->append("\nClass of Service (COS) bits:\n"
00142 "\tB: Bulk N: Normal E: Expedited\n\n");
00143 }
00144
00145
00146 void
00147 ExternalRouter::build_route_report(oasys::SerializeAction *a)
00148 {
00149 oasys::ScopeLock l(route_table_->lock(),
00150 "ExternalRouter::build_route_report");
00151
00152 const RouteEntryVec *re = route_table_->route_table();
00153 RouteEntryVec::const_iterator i;
00154
00155 a->begin_action();
00156
00157 for(i = re->begin(); i != re->end(); ++i) {
00158 a->process("route_entry", *i);
00159 }
00160
00161 a->end_action();
00162 }
00163
00164
00165 void
00166 ExternalRouter::handle_event(BundleEvent *event)
00167 {
00168 static oasys::StringBuffer front_matter(
00169 "<dtn eid=\"%s\">",
00170 BundleDaemon::instance()->local_eid().c_str());
00171
00172 static oasys::StringBuffer front_matter_with_ns(
00173 "<?xml version=\"1.0\" encoding=\"UTF-8\"?><dtn eid=\"%s\" "
00174 "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
00175 "xsi:noNamespaceSchemaLocation=\"file://%s\">",
00176 BundleDaemon::instance()->local_eid().c_str(),
00177 ExternalRouter::schema.c_str());
00178
00179
00180 if ((event->type_ == BUNDLE_DELIVERED) ||
00181 (event->type_ == LINK_CREATE) ||
00182 (event->type_ == REASSEMBLY_COMPLETED)) {
00183
00184 return;
00185 } else if (event->type_ == BUNDLE_RECEIVED) {
00186
00187
00188 BundleReceivedEvent *bre = dynamic_cast< BundleReceivedEvent * >(event);
00189 if (bre->bundleref_->owner_ == "daemon") return;
00190 } else if (event->type_ == ROUTE_ADD) {
00191
00192 RouteAddEvent *rae = dynamic_cast< RouteAddEvent * >(event);
00193 route_table_->add_entry(rae->entry_);
00194 } else if (event->type_ == ROUTE_DEL) {
00195
00196 RouteDelEvent *rae = dynamic_cast< RouteDelEvent * >(event);
00197 route_table_->del_entries(rae->dest_);
00198 } else if (event->type_ == BUNDLE_TRANSMITTED) {
00199
00200 BundleTransmittedEvent *event = dynamic_cast< BundleTransmittedEvent * >(event);
00201 if(event->contact_ == NULL)
00202 {
00203 return;
00204 }
00205 } else if (event->type_ == BUNDLE_TRANSMIT_FAILED) {
00206
00207 BundleTransmitFailedEvent *event = dynamic_cast< BundleTransmitFailedEvent * >(event);
00208 if(event->contact_ == NULL)
00209 {
00210 return;
00211 }
00212 }
00213
00214
00215 oasys::StringBuffer event_buf;
00216
00217 if (ExternalRouter::client_validation)
00218 event_buf.append(front_matter_with_ns.c_str());
00219 else
00220 event_buf.append(front_matter.c_str());
00221
00222 oasys::XMLMarshal event_a(event_buf.expandable_buf(),
00223 event_to_str(event->type_, true));
00224
00225 if (event->type_ == ROUTE_REPORT)
00226
00227 build_route_report(&event_a);
00228 else
00229 event_a.action(event);
00230
00231 event_buf.append("</dtn>");
00232
00233
00234 log_debug("ExternalRouter::handle_event (%s) sending:\n %s\n",
00235 event_to_str(event->type_), event_buf.c_str());
00236 srv_->eventq->push_back(new std::string(event_buf.c_str()));
00237 }
00238
00239 void
00240 ExternalRouter::shutdown()
00241 {
00242
00243 if (ExternalRouter::client_validation) {
00244 oasys::StringBuffer alert_with_ns(
00245 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
00246 "<dtn eid=\"%s\" alert=\"shuttingDown\" "
00247 "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
00248 "xsi:noNamespaceSchemaLocation=\"file://%s\"/>",
00249 BundleDaemon::instance()->local_eid().c_str(),
00250 ExternalRouter::schema.c_str());
00251
00252 srv_->eventq->push_back(
00253 new std::string(alert_with_ns.c_str()));
00254 } else {
00255 oasys::StringBuffer alert(
00256 "<dtn eid=\"%s\" alert=\"shuttingDown\"/>",
00257 BundleDaemon::instance()->local_eid().c_str());
00258
00259 srv_->eventq->push_back(
00260 new std::string(alert.c_str()));
00261 }
00262 }
00263
00264 ExternalRouter::ModuleServer::ModuleServer()
00265 : IOHandlerBase(new oasys::Notifier("/router/external/moduleserver")),
00266 Thread("/router/external/moduleserver"),
00267 parser_(ExternalRouter::server_validation,
00268 ExternalRouter::schema.c_str()),
00269 lock_(new oasys::SpinLock())
00270 {
00271
00272
00273 const int on = 1;
00274 setsockopt(fd(), SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
00275 bind(htonl(INADDR_ANY), ExternalRouter::server_port);
00276
00277
00278 ip_mreq mreq;
00279 mreq.imr_multiaddr.s_addr = htonl(INADDR_ALLRTRS_GROUP);
00280 mreq.imr_interface.s_addr = htonl(INADDR_ANY);
00281 setsockopt(fd(), IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
00282
00283
00284 in_addr src_if;
00285 src_if.s_addr = htonl(INADDR_LOOPBACK);
00286 setsockopt(fd(), IPPROTO_IP, IP_MULTICAST_IF, &src_if, sizeof(src_if));
00287
00288
00289 Thread::set_flag(Thread::DELETE_ON_EXIT);
00290
00291 set_logfd(false);
00292
00293 eventq = new oasys::MsgQueue< std::string * >(logpath_, lock_);
00294 }
00295
00296 ExternalRouter::ModuleServer::~ModuleServer()
00297 {
00298
00299 std::string *event;
00300 while (eventq->try_pop(&event))
00301 delete event;
00302
00303 delete eventq;
00304 }
00305
00306
00307 void
00308 ExternalRouter::ModuleServer::run()
00309 {
00310
00311
00312 struct pollfd pollfds[2];
00313
00314 struct pollfd* event_poll = &pollfds[0];
00315 event_poll->fd = eventq->read_fd();
00316 event_poll->events = POLLIN;
00317
00318 struct pollfd* sock_poll = &pollfds[1];
00319 sock_poll->fd = fd();
00320 sock_poll->events = POLLIN;
00321
00322 while (1) {
00323 if (should_stop()) return;
00324
00325
00326 int ret = oasys::IO::poll_multiple(pollfds, 2, -1,
00327 get_notifier());
00328
00329 if (ret == oasys::IOINTR) {
00330 log_debug("module server interrupted");
00331 set_should_stop();
00332 continue;
00333 }
00334
00335 if (ret == oasys::IOERROR) {
00336 log_debug("module server error");
00337 set_should_stop();
00338 continue;
00339 }
00340
00341
00342 if (event_poll->revents & POLLIN) {
00343 std::string *event;
00344 if (eventq->try_pop(&event)) {
00345 ASSERT(event != NULL)
00346 sendto(const_cast< char * >(event->c_str()),
00347 event->size(), 0,
00348 htonl(INADDR_ALLRTRS_GROUP),
00349 ExternalRouter::server_port);
00350 delete event;
00351 }
00352 }
00353
00354 if (sock_poll->revents & POLLIN) {
00355 char buf[MAX_UDP_PACKET];
00356 in_addr_t raddr;
00357 u_int16_t rport;
00358 int bytes;
00359
00360 bytes = recvfrom(buf, MAX_UDP_PACKET, 0, &raddr, &rport);
00361 buf[bytes] = '\0';
00362
00363 process_action(buf);
00364 }
00365 }
00366 }
00367
00368
00369 void
00370 ExternalRouter::ModuleServer::process_action(const char *payload)
00371 {
00372
00373 parser_.reset_error();
00374
00375
00376 const char *event_tag = parser_.parse(payload);
00377
00378
00379 if (parser_.error()) {
00380 log_debug("received invalid message");
00381 return;
00382 }
00383
00384
00385 do {
00386 BundleEvent *action = instantiate(event_tag);
00387
00388 if (! action) continue;
00389
00390
00391 parser_.action(action);
00392
00393
00394 BundleDaemon::post(action);
00395 } while ((event_tag = parser_.parse()) != 0);
00396 }
00397
00398
00399
00400 BundleEvent *
00401 ExternalRouter::ModuleServer::instantiate(const char *event_tag) {
00402 std::string action(event_tag);
00403
00404 if (action.find("send_bundle_request") != std::string::npos)
00405 return new BundleSendRequest();
00406 else if (action.find("cancel_bundle_request") != std::string::npos)
00407 return new BundleCancelRequest();
00408 else if (action.find("inject_bundle_request") != std::string::npos)
00409 return new BundleInjectRequest();
00410 else if (action.find("open_link_request") != std::string::npos)
00411 return new LinkStateChangeRequest(oasys::Builder::builder(),
00412 Link::OPENING, ContactEvent::NO_INFO);
00413 else if (action.find("create_link_request") != std::string::npos)
00414 return new LinkCreateRequest();
00415 else if (action.find("link_query") != std::string::npos)
00416 return new LinkQueryRequest();
00417 else if (action.find("contact_query") != std::string::npos)
00418 return new ContactQueryRequest();
00419 else if (action.find("bundle_query") != std::string::npos)
00420 return new BundleQueryRequest();
00421 else if (action.find("route_query") != std::string::npos)
00422 return new RouteQueryRequest();
00423
00424 return 0;
00425 }
00426
00427 ExternalRouter::HelloTimer::HelloTimer(ExternalRouter *router)
00428 : router_(router)
00429 {
00430 }
00431
00432 ExternalRouter::HelloTimer::~HelloTimer()
00433 {
00434 cancel();
00435 }
00436
00437
00438 void
00439 ExternalRouter::HelloTimer::timeout(const struct timeval &)
00440 {
00441 static oasys::StringBuffer hello(
00442 "<dtn eid=\"%s\" hello_interval=\"%i\"/>",
00443 BundleDaemon::instance()->local_eid().c_str(),
00444 ExternalRouter::hello_interval);
00445
00446 static oasys::StringBuffer hello_with_ns(
00447 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
00448 "<dtn eid=\"%s\" hello_interval=\"%i\" "
00449 "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
00450 "xsi:noNamespaceSchemaLocation=\"file://%s\"/>",
00451 BundleDaemon::instance()->local_eid().c_str(),
00452 ExternalRouter::hello_interval,
00453 ExternalRouter::schema.c_str());
00454
00455
00456 if (ExternalRouter::client_validation)
00457 router_->srv_->eventq->push_back(new std::string(hello_with_ns.c_str()));
00458 else
00459 router_->srv_->eventq->push_back(new std::string(hello.c_str()));
00460
00461 schedule_in(ExternalRouter::hello_interval * 1000);
00462 }
00463
00464 ExternalRouter::ERRegistration::ERRegistration(ExternalRouter *router)
00465 : Registration(Registration::EXTERNALROUTER_REGID,
00466 EndpointID(BundleDaemon::instance()->local_eid().str() +
00467 EXTERNAL_ROUTER_SERVICE_TAG),
00468 Registration::DEFER, 0),
00469 router_(router)
00470 {
00471 logpathf("/reg/admin");
00472
00473 BundleDaemon::post(new RegistrationAddedEvent(this, EVENTSRC_ADMIN));
00474 }
00475
00476
00477 void
00478 ExternalRouter::ERRegistration::deliver_bundle(Bundle *bundle)
00479 {
00480 BundleDeliveryEvent *delivery =
00481 new BundleDeliveryEvent(bundle, EVENTSRC_PEER);
00482
00483 router_->handle_event(delivery);
00484 delete delivery;
00485
00486 BundleDaemon::post(new BundleDeliveredEvent(bundle, this));
00487 }
00488
00489
00490 void external_rtr_shutdown(void *)
00491 {
00492 BundleDaemon::instance()->router()->shutdown();
00493 }
00494
00495
00496 u_int16_t ExternalRouter::server_port = 8001;
00497 u_int16_t ExternalRouter::hello_interval = 30;
00498 std::string ExternalRouter::schema = "/etc/dtn.router.xsd";
00499 bool ExternalRouter::server_validation = true;
00500 bool ExternalRouter::client_validation = false;
00501
00502 }
00503 #endif // XERCES_C_ENABLED