BluetoothConvergenceLayer.cc

Go to the documentation of this file.
00001 /*
00002  *    Copyright 2006 Baylor University
00003  * 
00004  *    Licensed under the Apache License, Version 2.0 (the "License");
00005  *    you may not use this file except in compliance with the License.
00006  *    You may obtain a copy of the License at
00007  * 
00008  *        http://www.apache.org/licenses/LICENSE-2.0
00009  * 
00010  *    Unless required by applicable law or agreed to in writing, software
00011  *    distributed under the License is distributed on an "AS IS" BASIS,
00012  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  *    See the License for the specific language governing permissions and
00014  *    limitations under the License.
00015  */
00016 
00017 #include <config.h>
00018 #ifdef OASYS_BLUETOOTH_ENABLED
00019 
00020 #include <oasys/bluez/Bluetooth.h>
00021 #include <oasys/bluez/BluetoothSDP.h>
00022 #include <oasys/util/Random.h>
00023 #include <oasys/util/OptParser.h>
00024 #include "bundling/BundleDaemon.h"
00025 #include "contacts/ContactManager.h"
00026 #include "BluetoothConvergenceLayer.h"
00027 
00028 namespace dtn {
00029 
00030 BluetoothConvergenceLayer::BluetoothLinkParams
00031     BluetoothConvergenceLayer::default_link_params_(true);
00032 
00033 void
00034 BluetoothConvergenceLayer::BluetoothLinkParams::serialize(
00035                                     oasys::SerializeAction *a) {
00036     char *la = batostr(&local_addr_);
00037     char *ra = batostr(&remote_addr_);
00038 
00039     a->process("local_addr", (u_char *) la);
00040     a->process("remote_addr", (u_char *) ra);
00041     a->process("channel", &channel_);
00042 
00043     // from StreamLinkParams
00044     a->process("segment_ack_enabled", &segment_ack_enabled_);
00045     a->process("negative_ack_enabled", &negative_ack_enabled_);
00046     a->process("keepalive_interval", &keepalive_interval_);
00047     a->process("segment_length", &segment_length_);
00048 
00049     // from LinkParams
00050     a->process("busy_queue_depth", &busy_queue_depth_);
00051     a->process("reactive_frag_enabled", &reactive_frag_enabled_);
00052     a->process("sendbuf_len", &sendbuf_len_);
00053     a->process("recvbuf_len", &recvbuf_len_);
00054     a->process("data_timeout", &data_timeout_);
00055 
00056     free(la);
00057     free(ra);
00058 }
00059 
00060 //----------------------------------------------------------------------
00061 BluetoothConvergenceLayer::BluetoothLinkParams::BluetoothLinkParams(
00062                                                     bool init_defaults )
00063     : StreamLinkParams(init_defaults),
00064       local_addr_(*(BDADDR_ANY)),
00065       remote_addr_(*(BDADDR_ANY)),
00066       channel_(BTCL_DEFAULT_CHANNEL)
00067 {
00068 }
00069 
00070 //----------------------------------------------------------------------
00071 BluetoothConvergenceLayer::BluetoothConvergenceLayer()
00072     : StreamConvergenceLayer("BluetoothConvergenceLayer",
00073                              "bt",BTCL_VERSION)
00074 {
00075 }
00076 
00077 //----------------------------------------------------------------------
00078 ConnectionConvergenceLayer::LinkParams*
00079 BluetoothConvergenceLayer::new_link_params()
00080 {
00081     return new BluetoothLinkParams(default_link_params_);
00082 }
00083 
00084 //----------------------------------------------------------------------
00085 bool
00086 BluetoothConvergenceLayer::parse_link_params(LinkParams* lparams,
00087                                               int argc, const char** argv,
00088                                               const char** invalidp)
00089 {
00090 
00091     BluetoothLinkParams* params = dynamic_cast<BluetoothLinkParams*>(lparams);
00092     ASSERT(params != NULL);
00093 
00094     oasys::OptParser p;
00095 
00096     p.addopt(new oasys::BdAddrOpt("local_addr",&params->local_addr_));
00097 
00098     int count = p.parse_and_shift(argc, argv, invalidp);
00099     if (count == -1) {
00100         return false; // bogus value
00101     }
00102 
00103     argc -= count;
00104 
00105     // validate the local address
00106     if (bacmp(&params->local_addr_,BDADDR_ANY) == 0) {
00107         // try again by reading address
00108         oasys::Bluetooth::hci_get_bdaddr(&params->local_addr_);
00109         if (bacmp(&params->local_addr_,BDADDR_ANY) == 0) {
00110             log_err("cannot find local Bluetooth adapter address");
00111             return false;
00112         }
00113     }
00114 
00115     // continue up to parse the parent class
00116     return StreamConvergenceLayer::parse_link_params(lparams, argc, argv,
00117                                                      invalidp);
00118 }
00119 
00120 //----------------------------------------------------------------------
00121 void
00122 BluetoothConvergenceLayer::dump_link(Link* link, oasys::StringBuffer* buf)
00123 {
00124     StreamConvergenceLayer::dump_link(link,buf);
00125     BluetoothLinkParams* params =
00126         dynamic_cast<BluetoothLinkParams*>(link->cl_info());
00127     ASSERT(params != NULL);
00128     buf->appendf("local_addr: %s\n", bd2str(params->local_addr_));
00129     buf->appendf("remote_addr: %s\n", bd2str(params->remote_addr_));
00130     buf->appendf("channel: %u\n",params->channel_);
00131 }
00132 
00133 //----------------------------------------------------------------------
00134 bool
00135 BluetoothConvergenceLayer::set_link_defaults(int argc, const char* argv[],
00136                                               const char** invalidp)
00137 {
00138     return parse_link_params(&default_link_params_, argc, argv, invalidp);
00139 }
00140 
00141 //----------------------------------------------------------------------
00142 bool
00143 BluetoothConvergenceLayer::parse_nexthop(Link* link, LinkParams* lparams)
00144 {
00145     BluetoothLinkParams* params = dynamic_cast<BluetoothLinkParams*>(lparams);
00146     ASSERT(params != NULL);
00147 
00148     std::string tmp;
00149     bdaddr_t ba;
00150     const char* p = link->nexthop();
00151     int numcolons = 5; // expecting 12 hex digits, 5 colons total
00152 
00153     while (numcolons > 0) {
00154         p = strchr(p+1, ':');
00155         if (p != NULL) {
00156             numcolons--;
00157         } else {
00158             log_warn("bad format for remote Bluetooth address: '%s'",
00159                      link->nexthop());
00160             return false;
00161         }
00162     }
00163     tmp.assign(link->nexthop(), p - link->nexthop() + 3);
00164     oasys::Bluetooth::strtoba(tmp.c_str(),&ba);
00165 
00166     bacpy(&params->remote_addr_,&ba);
00167     return true;
00168 }
00169 
00170 //----------------------------------------------------------------------
00171 CLConnection*
00172 BluetoothConvergenceLayer::new_connection(LinkParams* p) 
00173 {
00174     BluetoothLinkParams *params = dynamic_cast<BluetoothLinkParams*>(p);
00175     ASSERT(params != NULL);
00176     return new Connection(this, params);
00177 }
00178 
00179 //----------------------------------------------------------------------
00180 bool
00181 BluetoothConvergenceLayer::interface_up(Interface* iface,
00182                                          int argc, const char* argv[])
00183 {
00184     log_debug("adding interface %s", iface->name().c_str());
00185     bdaddr_t local_addr;
00186     u_int8_t channel = BTCL_DEFAULT_CHANNEL;
00187     u_int neighbor_poll_interval = 0; // defaults to off
00188 
00189     memset(&local_addr,0,sizeof(bdaddr_t));
00190 
00191     oasys::OptParser p;
00192     p.addopt(new oasys::UInt8Opt("channel",&channel));
00193     p.addopt(new oasys::UIntOpt("neighbor_poll_interval",
00194                                 &neighbor_poll_interval));
00195 
00196     const char* invalid = NULL;
00197     if (! p.parse(argc, argv, &invalid)) {
00198         log_err("error parsing interface options: invalid option '%s'",
00199                 invalid);
00200         return false;
00201     }
00202 
00203     // read adapter address from default adapter (hci0)
00204     oasys::Bluetooth::hci_get_bdaddr(&local_addr);
00205     if (bacmp(&local_addr,BDADDR_ANY) == 0) {
00206         log_err("invalid local address setting of BDADDR_ANY");
00207         return false;
00208     }
00209 
00210     if (channel < 1 || channel > 30) {
00211         log_err("invalid channel setting of %d",channel);
00212         return false;
00213     }
00214 
00215     // create a new server socket for the requested interface
00216     Listener* listener = new Listener(this);
00217     listener->logpathf("%s/iface/%s", logpath_, iface->name().c_str());
00218 
00219     int ret = listener->bind(local_addr, channel);
00220 
00221     // be a little forgiving -- if the address is in use, wait for a
00222     // bit and try again
00223     if (ret != 0 && errno == EADDRINUSE) {
00224         listener->logf(oasys::LOG_WARN,
00225                        "WARNING: error binding to requested socket: %s",
00226                        strerror(errno));
00227         listener->logf(oasys::LOG_WARN,
00228                        "waiting for 10 seconds then trying again");
00229         sleep(10);
00230 
00231         ret = listener->bind(local_addr, channel);
00232     }
00233 
00234     if (ret != 0) {
00235         return false; // error already logged
00236     }
00237 
00238     // start listening and then start the thread to loop calling accept()
00239     listener->listen();
00240     listener->start();
00241 
00242     // store the new listener object in the cl specific portion of the
00243     // interface
00244     iface->set_cl_info(listener);
00245 
00246     return true;
00247 }
00248 
00249 //----------------------------------------------------------------------
00250 bool
00251 BluetoothConvergenceLayer::interface_down(Interface* iface)
00252 {
00253     // grab the listener object, set a flag for the thread to stop and
00254     // then close the socket out from under it, which should cause the
00255     // thread to break out of the blocking call to accept() and
00256     // terminate itself
00257     Listener* listener = dynamic_cast<Listener*>(iface->cl_info());
00258     ASSERT(listener != NULL);
00259 
00260     listener->set_should_stop();
00261 
00262     listener->interrupt_from_io();
00263 
00264     while (! listener->is_stopped()) {
00265         oasys::Thread::yield();
00266     }
00267 
00268     delete listener;
00269     return true;
00270 }
00271 
00272 //----------------------------------------------------------------------
00273 void
00274 BluetoothConvergenceLayer::dump_interface(Interface* iface,
00275                                            oasys::StringBuffer* buf)
00276 {
00277     Listener* listener = dynamic_cast<Listener*>(iface->cl_info());
00278     ASSERT(listener != NULL);
00279 
00280     bdaddr_t addr;
00281     listener->local_addr(addr);
00282     buf->appendf("\tlocal_addr: %s channel: %u\n",
00283                  bd2str(addr), listener->channel());
00284 }
00285 
00286 //----------------------------------------------------------------------
00287 BluetoothConvergenceLayer::Listener::Listener(BluetoothConvergenceLayer* cl)
00288     : IOHandlerBase(new oasys::Notifier("/dtn/cl/bt/listener")),
00289       RFCOMMServerThread("/dtn/cl/bt/listener",oasys::Thread::INTERRUPTABLE),
00290       cl_(cl)
00291 {
00292     logfd_ = false;
00293 }
00294 
00295 //----------------------------------------------------------------------
00296 void
00297 BluetoothConvergenceLayer::Listener::accepted(int fd, bdaddr_t addr,
00298                                                u_int8_t channel)
00299 {
00300     log_debug("new connection from %s on channel %u", bd2str(addr),channel);
00301     Connection *conn =
00302         new Connection(cl_, &BluetoothConvergenceLayer::default_link_params_,
00303                        fd, addr, channel);
00304     conn->start();
00305 }
00306 
00307 //----------------------------------------------------------------------
00308 BluetoothConvergenceLayer::Connection::Connection(
00309         BluetoothConvergenceLayer* cl, BluetoothLinkParams* params)
00310     : StreamConvergenceLayer::Connection(
00311             "BluetoothConvergenceLayer::Connection",
00312             cl->logpath(), cl, params, true /* call connect() */)
00313 {
00314     logpathf("%s/conn/%s",cl->logpath(),bd2str(params->remote_addr_));
00315 
00316     // set the nexthop parameter for the base class
00317     set_nexthop(bd2str(params->remote_addr_));
00318 
00319     // Bluetooth socket based on RFCOMM profile stream semantics
00320     sock_ = new oasys::RFCOMMClient(logpath_);
00321     sock_->set_local_addr(params->local_addr_);
00322     sock_->logpathf("%s/sock",logpath_);
00323     sock_->set_logfd(false);
00324     sock_->set_remote_addr(params->remote_addr_);
00325     sock_->set_channel(params->channel_);
00326     sock_->init_socket(); // make sure sock_::fd_ exists for set_nonblocking
00327     // sock_->set_nonblocking(true); // defer until after connect()
00328 }
00329 
00330 //----------------------------------------------------------------------
00331 BluetoothConvergenceLayer::Connection::Connection(
00332                                 BluetoothConvergenceLayer* cl,
00333                                 BluetoothLinkParams* params,
00334                                 int fd, bdaddr_t addr, u_int8_t channel)
00335     : StreamConvergenceLayer::Connection(
00336          "BluetoothConvergenceLayer::Connection", cl->logpath(), cl, params,
00337          false /* call accept() */)
00338 {
00339     // set the nexthop parameter for the base class
00340     set_nexthop(bd2str(addr));
00341     ::bacpy(&params->remote_addr_,&addr);
00342 
00343     logpathf("%s/conn/%s-%d",cl->logpath(),bd2str(addr),channel);
00344 
00345     // set nexthop parameter for base class
00346     set_nexthop(bd2str(addr));
00347 
00348     sock_ = new oasys::RFCOMMClient(fd, addr, channel, logpath_);
00349     sock_->set_logfd(false);
00350     sock_->set_nonblocking(true);
00351 }
00352 
00353 //----------------------------------------------------------------------
00354 BluetoothConvergenceLayer::Connection::~Connection()
00355 {
00356     delete sock_;
00357 }
00358 
00359 //----------------------------------------------------------------------
00360 void
00361 BluetoothConvergenceLayer::Connection::initialize_pollfds()
00362 {
00363     sock_pollfd_ = &pollfds_[0];
00364     num_pollfds_ = 1;
00365 
00366     sock_pollfd_->fd     = sock_->fd();
00367     sock_pollfd_->events = POLLIN;
00368 
00369     if (sock_pollfd_->fd == -1) {
00370         log_err("initialize_pollfds was given a bad socket descriptor");
00371         break_contact(ContactEvent::BROKEN);
00372     }
00373 
00374     BluetoothLinkParams* params = dynamic_cast<BluetoothLinkParams*>(params_);
00375     ASSERT(params != NULL);
00376 
00377     poll_timeout_ = params->data_timeout_;
00378 
00379     if (params->keepalive_interval_ != 0 &&
00380         (params->keepalive_interval_ * 1000) < params->data_timeout_)
00381     {
00382         poll_timeout_ = params->keepalive_interval_ * 1000;
00383     }
00384 }
00385 
00386 //----------------------------------------------------------------------
00387 void
00388 BluetoothConvergenceLayer::Connection::connect()
00389 {
00390     bdaddr_t addr;
00391     sock_->remote_addr(addr);
00392 //    sock_->set_channel(params_->channel_);
00393     log_debug("connect: connecting to %s-%d",bd2str(addr),sock_->channel());
00394 
00395     ASSERT(active_connector_);
00396     ASSERT(contact_ == NULL || contact_->link()->isopening());
00397 
00398     ASSERT(sock_->state() != oasys::BluetoothSocket::ESTABLISHED);
00399 
00400     int ret = sock_->connect();
00401 
00402     if (ret == 0) {
00403         log_debug("connect: succeeded immediately");
00404         ASSERT(sock_->state() == oasys::BluetoothSocket::ESTABLISHED);
00405 
00406         sock_->set_nonblocking(true);
00407         initiate_contact();
00408 
00409 //    } else if (ret == -1 && errno == EINPROGRESS) {
00410 //        log_debug("connect: EINPROGRESS returned, waiting for write ready");
00411 //        sock_pollfd_->events |= POLLOUT;
00412 
00413     } else {
00414         log_info("failed to connect to %s: %s",bd2str(addr),strerror(errno));
00415         break_contact(ContactEvent::BROKEN);
00416     }
00417 }
00418 
00419 //----------------------------------------------------------------------
00420 void
00421 BluetoothConvergenceLayer::Connection::accept()
00422 {
00423     bdaddr_t addr;
00424     memset(&addr,0,sizeof(bdaddr_t));
00425     ASSERT(sock_->state() == oasys::BluetoothSocket::ESTABLISHED);
00426     sock_->remote_addr(addr);
00427     log_debug("accept: got connection from %s",bd2str(addr));
00428     initiate_contact();
00429 }
00430 
00431 //----------------------------------------------------------------------
00432 void
00433 BluetoothConvergenceLayer::Connection::disconnect()
00434 {
00435     if (sock_->state() != oasys::BluetoothSocket::CLOSED) {
00436         sock_->close();
00437     }
00438 }
00439 
00440 //----------------------------------------------------------------------
00441 void
00442 BluetoothConvergenceLayer::Connection::handle_poll_activity()
00443 {
00444     if ((sock_pollfd_->revents & POLLNVAL) == POLLNVAL) {
00445         log_info("invalid file descriptor -- returned POLLNVAL");
00446         break_contact(ContactEvent::BROKEN);
00447         return;
00448     }
00449 
00450     if ((sock_pollfd_->revents & POLLHUP) == POLLHUP) {
00451         log_info("remote socket closed connection -- returned POLLHUP");
00452         break_contact(ContactEvent::BROKEN);
00453         return;
00454     }
00455 
00456     if ((sock_pollfd_->revents & POLLERR) == POLLERR) {
00457         log_info("error condition on remote socket -- returned POLLERR");
00458         break_contact(ContactEvent::BROKEN);
00459         return;
00460     }
00461 
00462     // first check for write readiness, meaning either we're getting a 
00463     // notification that the deferred connect() call completed, or
00464     // that we are no longer write blocked
00465     if ((sock_pollfd_->revents & POLLOUT) == POLLOUT)
00466     {
00467         log_debug("poll returned write ready, clearing POLLOUT bit");
00468         sock_pollfd_->events &= ~POLLOUT;
00469 
00470 //        if (sock_->state() == oasys::BluetoothSocket::CONNECTING) {
00471 //            bdaddr_t addr;
00472 //            sock_->remote_addr(addr);
00473 //            int result = sock_->async_connect_result();
00474 //            if (result == 0 && sendbuf_.fullbytes() == 0) {
00475 //                log_debug("delayed connect() to %s succeeded",bd2str(addr));
00476 //                initiate_contact();
00477 
00478 //            } else {
00479 //                log_info("connection attempt to %s failed ... %s",
00480 //                         bd2str(addr),strerror(errno));
00481 //                break_contact(ContactEvent::BROKEN);
00482 //            }
00483 
00484 //            return;
00485 //        }
00486 
00487         send_data();
00488     }
00489 
00490     //check that the connection was not broken during the data send
00491     if (contact_broken_)
00492     {
00493        return;
00494     }
00495 
00496     // check for incoming data
00497     if ((sock_pollfd_->revents & POLLIN) == POLLIN) {
00498         recv_data();
00499         process_data();
00500 
00501         // Sanity check to make sure that there's space in the buffer
00502         // for a subsequent read_data() call
00503         if (recvbuf_.tailbytes() == 0) {
00504             log_err("process_data left no space in recvbuf!!");
00505         }
00506 
00507         if (! contact_broken_) {
00508             check_keepalive();
00509         }
00510 
00511     }
00512 
00513 }
00514 
00515 //----------------------------------------------------------------------
00516 void
00517 BluetoothConvergenceLayer::Connection::send_data()
00518 {
00519     // XXX/demmer this assertion is mostly for debugging to catch call
00520     // chains where the contact is broken but we're still using the
00521     // socket
00522     ASSERT(! contact_broken_);
00523 
00524     if (params_->test_write_delay_ != 0) {
00525         log_debug("send_data: sleeping for test_write_delay msecs %u",
00526                   params_->test_write_delay_);
00527 
00528         usleep(params_->test_write_delay_ * 1000);
00529     }
00530 
00531     log_debug("send_data: trying to drain %zu bytes from send buffer...",
00532               sendbuf_.fullbytes());
00533     ASSERT(sendbuf_.fullbytes() > 0);
00534     int cc = sock_->write(sendbuf_.start(), sendbuf_.fullbytes());
00535     if (cc > 0) {
00536         log_debug("send_data: wrote %d/%zu bytes from send buffer",
00537                   cc, sendbuf_.fullbytes());
00538         sendbuf_.consume(cc);
00539 
00540         if (sendbuf_.fullbytes() != 0) {
00541             log_debug("send_data: incomplete write, setting POLLOUT bit");
00542             sock_pollfd_->events |= POLLOUT;
00543         } else {
00544             if (sock_pollfd_->events & POLLOUT) {
00545                 log_debug("send_data: drained buffer, clearing POLLOUT bit");
00546                 sock_pollfd_->events &= ~POLLOUT;
00547             }
00548         }
00549 
00550     } else if (errno == EWOULDBLOCK) {
00551         log_debug("send_data: write returned EWOULDBLOCK, setting POLLOUT bit");
00552         sock_pollfd_->events |= POLLOUT;
00553 
00554     } else {
00555         log_info("send_data: remote connection unexpectedly closed: %s",
00556                  strerror(errno));
00557         break_contact(ContactEvent::BROKEN);
00558     }
00559 }
00560 
00561 //----------------------------------------------------------------------
00562 void
00563 BluetoothConvergenceLayer::Connection::recv_data()
00564 {
00565     // XXX/demmer this assertion is mostly for debugging to catch call
00566     // chains where the contact is broken but we're still using the
00567     // socket
00568     ASSERT(! contact_broken_);
00569 
00570     // this shouldn't ever happen
00571     if (recvbuf_.tailbytes() == 0) {
00572         log_err("no space in receive buffer to accept data!!!");
00573         break_contact(ContactEvent::BROKEN);
00574         return;
00575     }
00576 
00577     if (params_->test_read_delay_ != 0) {
00578         log_debug("recv_data: sleeping for test_read_delay msecs %u",
00579                   params_->test_read_delay_);
00580         usleep(params_->test_read_delay_ * 1000);
00581     }
00582 
00583     log_debug("recv_data: draining up to %zu bytes into recv buffer...",
00584               recvbuf_.tailbytes());
00585     int cc = sock_->read(recvbuf_.end(), recvbuf_.tailbytes());
00586     if (cc < 1) {
00587         log_info("remote connection unexpectedly closed: %s (%d)",
00588                  strerror(errno),errno);
00589         break_contact(ContactEvent::BROKEN);
00590         return;
00591     }
00592 
00593     log_debug("recv_data: read %d bytes, rcvbuf has %zu bytes",
00594               cc, recvbuf_.fullbytes());
00595     recvbuf_.fill(cc);
00596 }
00597 
00598 } // dtn
00599 
00600 #endif // OASYS_BLUETOOTH_ENABLED

Generated on Sat Sep 8 08:43:24 2007 for DTN Reference Implementation by  doxygen 1.5.3