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