00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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
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
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",¶ms->local_addr_));
00097
00098 int count = p.parse_and_shift(argc, argv, invalidp);
00099 if (count == -1) {
00100 return false;
00101 }
00102
00103 argc -= count;
00104
00105
00106 if (bacmp(¶ms->local_addr_,BDADDR_ANY) == 0) {
00107
00108 oasys::Bluetooth::hci_get_bdaddr(¶ms->local_addr_);
00109 if (bacmp(¶ms->local_addr_,BDADDR_ANY) == 0) {
00110 log_err("cannot find local Bluetooth adapter address");
00111 return false;
00112 }
00113 }
00114
00115
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;
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(¶ms->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;
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
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
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
00222
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;
00236 }
00237
00238
00239 listener->listen();
00240 listener->start();
00241
00242
00243
00244 iface->set_cl_info(listener);
00245
00246 return true;
00247 }
00248
00249
00250 bool
00251 BluetoothConvergenceLayer::interface_down(Interface* iface)
00252 {
00253
00254
00255
00256
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 )
00313 {
00314 logpathf("%s/conn/%s",cl->logpath(),bd2str(params->remote_addr_));
00315
00316
00317 set_nexthop(bd2str(params->remote_addr_));
00318
00319
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();
00327
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 )
00338 {
00339
00340 set_nexthop(bd2str(addr));
00341 ::bacpy(¶ms->remote_addr_,&addr);
00342
00343 logpathf("%s/conn/%s-%d",cl->logpath(),bd2str(addr),channel);
00344
00345
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
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
00410
00411
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
00463
00464
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
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487 send_data();
00488 }
00489
00490
00491 if (contact_broken_)
00492 {
00493 return;
00494 }
00495
00496
00497 if ((sock_pollfd_->revents & POLLIN) == POLLIN) {
00498 recv_data();
00499 process_data();
00500
00501
00502
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
00520
00521
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
00566
00567
00568 ASSERT(! contact_broken_);
00569
00570
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 }
00599
00600 #endif // OASYS_BLUETOOTH_ENABLED