BluetoothSocket.cc

Go to the documentation of this file.
00001 #include <config.h>
00002 #ifdef OASYS_BLUETOOTH_ENABLED
00003 
00004 #include <stdlib.h>
00005 #include <sys/types.h>
00006 #include <sys/socket.h>
00007 #include <errno.h> 
00008 
00009 #include <bluetooth/bluetooth.h>
00010 #include <bluetooth/hci.h>
00011 #include <bluetooth/rfcomm.h>
00012 
00013 #include "../io/IO.h"
00014 #include "Bluetooth.h"
00015 #include "BluetoothSocket.h"
00016 #include "../debug/Log.h"
00017 
00018 namespace oasys {
00019 
00020 int BluetoothSocket::abort_on_error_ = 0;
00021 
00022 BluetoothSocket::BluetoothSocket(int socktype,
00023                                  proto_t proto,
00024                                  const char* logbase)
00025     : Logger("BluetoothSocket", logbase)
00026 {
00027     state_ = INIT;
00028     memset(&local_addr_,0,sizeof(bdaddr_t));
00029     channel_ = 0;
00030     memset(&remote_addr_,0,sizeof(bdaddr_t));
00031     fd_ = -1;
00032     socktype_ = socktype;
00033     proto_ = (proto_t) proto;
00034     logfd_ = true; 
00035     sa_ = NULL;
00036     slen_ = -1;
00037     reuse_addr_ = false;
00038     silent_connect_ = false;
00039 }
00040 
00041 BluetoothSocket::BluetoothSocket(int socktype, proto_t proto, int sock,
00042                    bdaddr_t remote_addr, u_int8_t remote_channel,
00043                    const char* logbase)
00044     : Logger("BluetoothSocket", logbase)
00045 {
00046     sa_ = NULL;
00047     fd_ = sock;
00048     proto_ = (proto_t) proto;
00049     logpathf("%s/%s/%d",logbase,prototoa((proto_t)proto_),sock);
00050     socktype_ = socktype;
00051     state_ = ESTABLISHED;
00052     bacpy(&local_addr_,BDADDR_ANY);
00053     channel_ = remote_channel;
00054     set_remote_addr(remote_addr);
00055 
00056     silent_connect_ = false;
00057     configure();
00058 }
00059 
00060 BluetoothSocket::~BluetoothSocket()
00061 {
00062     if (sa_ != NULL) delete sa_; 
00063     sa_ = NULL;
00064     close();
00065 }
00066 
00067 void
00068 BluetoothSocket::init_socket()
00069 {
00070     // should only be called at real init time or after a call to close()
00071     ASSERT(state_ == INIT || state_ == FINI);
00072     ASSERT(fd_ == -1);
00073     state_ = INIT;
00074 
00075     fd_ = socket(PF_BLUETOOTH, socktype_, (int) proto_);
00076     if (fd_ == -1) {
00077         logf(LOG_ERR, "error creating socket: %s", strerror(errno));
00078         if(errno==EBADFD) close();
00079         return;
00080     }
00081 
00082     if (logfd_)
00083         Logger::logpath_appendf("/%s/%d",
00084                                 prototoa((proto_t)proto_),
00085                                 fd_);
00086 
00087     logf(LOG_DEBUG, "created socket %d of protocol %s", fd_, 
00088          prototoa((proto_t)proto_));
00089 
00090     configure(); 
00091 }
00092 
00093 int
00094 BluetoothSocket::bind(bdaddr_t local_addr, u_int8_t local_channel)
00095 {
00096     if (fd_ == -1) init_socket();
00097 
00098     set_local_addr(local_addr);
00099     channel_ = local_channel;
00100 
00101     char buff[18];
00102     if (!silent_connect_)
00103     logf(LOG_DEBUG, "binding to %s(%d)", Bluetooth::batostr(&local_addr,buff),
00104          local_channel);
00105 
00106     init_sa((int)LOCAL);
00107 
00108     if(::bind(fd_,sa_,slen_) != 0) {
00109         log_level_t level = LOG_ERR;
00110         if(errno == EADDRINUSE) level = LOG_DEBUG;
00111         if (!silent_connect_)
00112         logf(level, "failed to bind to %s(%d): %s",
00113              Bluetooth::batostr(&local_addr_,buff), channel_,
00114              strerror(errno));
00115         if(errno==EBADFD) close();
00116         return -1;
00117     }
00118 
00119     return 0;
00120 }
00121 
00122 int
00123 BluetoothSocket::bind()
00124 {
00125     return bind(local_addr_,channel_);
00126 }
00127 
00128 int
00129 BluetoothSocket::connect(bdaddr_t remote_addr, u_int8_t remote_channel)
00130 {
00131     // In Bluetooth, piconets are formed by one Master
00132     // connecting to up to seven Slaves, simultaneously
00133     // The device performing connect() is Master
00134     if (fd_ == -1) init_socket();
00135 
00136     set_remote_addr(remote_addr);
00137     channel_ = remote_channel;
00138 
00139     char buff[18];
00140     log_debug("connecting to %s(%d)",Bluetooth::batostr(&remote_addr_,buff),
00141               channel_);
00142 
00143     init_sa((int)REMOTE);
00144     rc_->rc_channel=channel_;
00145     bacpy(&rc_->rc_bdaddr,&remote_addr);
00146 
00147     set_state(CONNECTING);
00148 
00149     if (::connect(fd_,sa_,slen_) < 0) {
00150         if (errno == EISCONN && !silent_connect_)
00151             log_debug("already connected to %s-%u",
00152                       Bluetooth::batostr(&remote_addr_,buff), channel_);
00153         else if (errno == EINPROGRESS && !silent_connect_) {
00154             log_debug("delayed connect to %s-%u",
00155                       Bluetooth::batostr(&remote_addr_,buff), channel_);
00156         } else if(errno==EBADFD) {
00157             if (!silent_connect_) log_err("EBADFD");
00158             close();
00159         } else {
00160             if (!silent_connect_)
00161                 log_debug("error connecting to %s(%d): %s",
00162                           Bluetooth::batostr(&remote_addr_,buff), channel_,
00163                           strerror(errno));
00164         }
00165         return -1;
00166     }
00167 
00168     set_state(ESTABLISHED);
00169 
00170     return 0;
00171 }
00172 
00173 int
00174 BluetoothSocket::async_connect_result()
00175 {
00176     ASSERT(state_ == CONNECTING);
00177 
00178     int result;
00179     socklen_t len = sizeof(result);
00180     logf(LOG_DEBUG, "getting connect result");
00181     if (::getsockopt(fd_, SOL_SOCKET, SO_ERROR, &result, &len) != 0) {
00182         logf(LOG_ERR, "error getting connect result: %s", strerror(errno));
00183         return errno;
00184     }
00185 
00186     if (result == 0) {
00187         state_ = ESTABLISHED;
00188     }
00189 
00190     return result;
00191 }
00192 
00193 int
00194 BluetoothSocket::connect()
00195 {
00196     return connect(remote_addr_,channel_);
00197 }
00198 
00199 void
00200 BluetoothSocket::configure()
00201 {
00202     ASSERT(fd_ != -1);
00203 
00204     if (params_.reuseaddr_) {
00205         int y = 1;
00206         logf(LOG_DEBUG, "setting SO_REUSEADDR");
00207         if (::setsockopt(fd_, SOL_SOCKET, SO_REUSEADDR, &y, sizeof y) != 0) {
00208             logf(LOG_WARN, "error setting SO_REUSEADDR: %s",
00209                  strerror(errno));
00210         }
00211     }
00212 
00213     if (params_.recv_bufsize_ > 0) {
00214         logf(LOG_DEBUG, "setting SO_RCVBUF to %d",
00215              params_.recv_bufsize_);
00216         if (::setsockopt(fd_, SOL_SOCKET, SO_RCVBUF,
00217                          &params_.recv_bufsize_,
00218                          sizeof(params_.recv_bufsize_)) < 0)
00219         {
00220             logf(LOG_WARN, "error setting SO_RCVBUF to %d: %s",
00221                  params_.recv_bufsize_, strerror(errno)); 
00222         }
00223     }
00224 
00225     if (params_.send_bufsize_ > 0) {
00226         logf(LOG_DEBUG, "setting SO_SNDBUF to %d",
00227              params_.send_bufsize_);
00228         if (::setsockopt(fd_, SOL_SOCKET, SO_SNDBUF,
00229                          &params_.send_bufsize_,
00230                          sizeof(params_.send_bufsize_)) < 0)
00231         {
00232             logf(LOG_WARN, "error setting SO_SNDBUF to %d: %s",
00233                  params_.send_bufsize_, strerror(errno)); 
00234         }
00235     }
00236 
00237     init_sa((int)ZERO);
00238 }
00239 
00240 int
00241 BluetoothSocket::close()
00242 {
00243     logf(LOG_DEBUG, "closing socket in state %s", statetoa(state_));
00244 
00245     if (fd_ == -1) {
00246         ASSERT(state_ == INIT || state_ == FINI);
00247         return 0;
00248     }
00249 
00250     if (::close(fd_) != 0) {
00251         logf(LOG_ERR, "error closing socket in state %s: %s",
00252                 statetoa(state_), strerror(errno));
00253         return -1;
00254     }
00255 
00256     set_state(FINI);
00257     fd_ = -1;
00258     return 0;
00259 }
00260 
00261 int
00262 BluetoothSocket::shutdown(int how)
00263 {
00264     const char* howstr;
00265 
00266     switch (how) {
00267         case SHUT_RD:   howstr = "R";  break;
00268         case SHUT_WR:   howstr = "W";  break;
00269         case SHUT_RDWR: howstr = "RW"; break;
00270 
00271         default:
00272                         logf(LOG_ERR, "shutdown invalid mode %d", how);
00273                         return -1;
00274     }
00275 
00276     logf(LOG_DEBUG, "shutdown(%s) state %s", howstr, statetoa(state_));
00277 
00278     if (state_ == INIT || state_ == FINI) {
00279         ASSERT(fd_ == -1);
00280         return 0;
00281     }
00282 
00283     if (::shutdown(fd_, how) != 0) {
00284         logf(LOG_ERR, "error in shutdown(%s) state %s: %s",
00285              howstr, statetoa(state_), strerror(errno));
00286     } 
00287     if (state_ == ESTABLISHED) {
00288         if (how == SHUT_RD)     { set_state(RDCLOSED); }
00289         if (how == SHUT_WR)     { set_state(WRCLOSED); }
00290         if (how == SHUT_RDWR)   { set_state(CLOSED); } 
00291 
00292     } else if (state_ == RDCLOSED && how == SHUT_WR) {
00293         set_state(CLOSED);
00294 
00295     } else if (state_ == WRCLOSED && how == SHUT_RD) {
00296         set_state(CLOSED);
00297 
00298     } else {
00299         logf(LOG_ERR, "invalid state %s for shutdown(%s)",
00300              statetoa(state_), howstr);
00301         return -1;
00302     }
00303 
00304     return 0; 
00305 }
00306 
00307 const char*
00308 BluetoothSocket::statetoa(state_t state)
00309 {
00310     switch (state) {
00311         case INIT:          return "INIT";
00312         case LISTENING:     return "LISTENING";
00313         case CONNECTING:    return "CONNECTING";
00314         case ESTABLISHED:   return "ESTABLISHED";
00315         case RDCLOSED:      return "RDCLOSED";
00316         case WRCLOSED:      return "WRCLOSED";
00317         case CLOSED:        return "CLOSED";
00318         case FINI:          return "FINI";
00319     }
00320     ASSERT(0);
00321     return NULL;
00322 }
00323 
00324 void
00325 BluetoothSocket::set_state(state_t state)
00326 {
00327     logf(LOG_DEBUG, "state %s -> %s", statetoa(state_), 
00328          statetoa(state));
00329     state_ = state;
00330 }
00331 
00332 const char* 
00333 BluetoothSocket::prototoa(proto_t proto)
00334 {
00335     switch (proto) {
00336         case L2CAP:    return "L2CAP";
00337         case HCI:      return "HCI";
00338         case SCO:      return "SCO";
00339         case RFCOMM:   return "RFCOMM";
00340         case BNEP:     return "BNEP";
00341         case CMTP:     return "CMTP";
00342         case HIDP:     return "HIDP";
00343         case AVDTP:    return "AVDTP";
00344     }
00345     ASSERT(0);
00346     return NULL;
00347 }
00348 
00349 void 
00350 BluetoothSocket::set_proto(proto_t proto)
00351 {
00352     logf(LOG_DEBUG, "protocol %s -> %s", prototoa((proto_t)proto_), 
00353          prototoa((proto_t)proto));
00354     proto_ = proto;
00355 }
00356 
00357 int
00358 BluetoothSocket::send(const char* bp, size_t len, int flags)
00359 {
00360     return IO::send(fd_, bp, len, flags, get_notifier(), logpath_);
00361 }
00362 
00363 int
00364 BluetoothSocket::recv(char* bp, size_t len, int flags)
00365 {
00366     return IO::recv(fd_, bp, len, flags, get_notifier(), logpath_);
00367 }
00368 
00369 int
00370 BluetoothSocket::fd()
00371 {
00372     return fd_;
00373 }
00374 
00375 bdaddr_t
00376 BluetoothSocket::local_addr()
00377 {
00378     if (!bacmp(BDADDR_ANY,&local_addr_)) get_local();
00379     return local_addr_;
00380 }
00381 
00382 void
00383 BluetoothSocket::local_addr(bdaddr_t& addr)
00384 {
00385     if (!bacmp(&addr,&local_addr_)) get_local();
00386     bacpy(&addr,&local_addr_);
00387 }
00388 
00389 u_int8_t
00390 BluetoothSocket::channel()
00391 {
00392     if (channel_ == 0) get_local();
00393     return channel_;
00394 }
00395 
00396 bdaddr_t
00397 BluetoothSocket::remote_addr()
00398 {
00399     if (!bacmp(BDADDR_ANY,&remote_addr_)) get_remote();
00400     return remote_addr_;
00401 }
00402 
00403 void
00404 BluetoothSocket::remote_addr(bdaddr_t& addr)
00405 {
00406     if (!bacmp(&addr,&remote_addr_)) get_remote();
00407     bacpy(&addr,&remote_addr_);
00408 }
00409 
00410 void
00411 BluetoothSocket::set_local_addr(bdaddr_t& addr)
00412 {
00413     bacpy(&local_addr_,&addr);
00414 }
00415 
00416 void
00417 BluetoothSocket::set_channel(u_int8_t channel)
00418 {
00419     // from net/bluetooth/rfcomm/core.c
00420     ASSERT(channel >= 1 && channel <= 30);
00421     channel_ = channel;
00422 }
00423 
00424 void
00425 BluetoothSocket::set_remote_addr(bdaddr_t& addr)
00426 {
00427     bacpy(&remote_addr_,&addr);
00428 }
00429 
00430 void
00431 BluetoothSocket::get_local()
00432 {
00433     if (fd_ < 0)
00434         return;
00435 
00436     init_sa((int)ZERO);
00437     socklen_t slen = sizeof(struct sockaddr);
00438     if(::getsockname(fd_, sa_, &slen) == 0) {
00439         switch (proto_) { 
00440             case L2CAP:
00441             case HCI:
00442             case SCO:
00443                 break; // not implemented
00444             case RFCOMM:
00445                 rc_ = (struct sockaddr_rc *) sa_;
00446                 bacpy(&local_addr_,&rc_->rc_bdaddr);
00447                 channel_ = rc_->rc_channel;
00448                 break;
00449             // not implemented
00450             case BNEP:
00451             case CMTP:
00452             case HIDP:
00453             case AVDTP:
00454             default:
00455                 break;
00456         }
00457     }
00458 }
00459 
00460 bdaddr_t*
00461 BluetoothSocket::sa_baddr()
00462 {
00463     ASSERT(sa_ != NULL);
00464     switch (proto_) {
00465         case L2CAP:
00466         case HCI:
00467         case SCO:
00468             break; // not implemented
00469         case RFCOMM:
00470             rc_ = (struct sockaddr_rc*) sa_;
00471             return &rc_->rc_bdaddr;
00472         case BNEP:
00473         case CMTP:
00474         case HIDP:
00475         case AVDTP:
00476         default:
00477             break;
00478     }
00479     ASSERT(0);
00480     return NULL;
00481 }
00482 
00483 u_int8_t
00484 BluetoothSocket::sa_channel()
00485 {
00486     ASSERT(sa_ != NULL);
00487     switch (proto_) {
00488         case L2CAP:
00489         case HCI:
00490         case SCO:
00491             break; // not implemented
00492         case RFCOMM:
00493             rc_ = (struct sockaddr_rc*) sa_;
00494             return rc_->rc_channel;
00495         case BNEP:
00496         case CMTP:
00497         case HIDP:
00498         case AVDTP:
00499         default:
00500             break;
00501     }
00502     ASSERT(0);
00503     return 0;
00504 }
00505 
00506 void
00507 BluetoothSocket::get_remote()
00508 {
00509     if (fd_ < 0)
00510         return;
00511 
00512     init_sa((int)ZERO);
00513     socklen_t slen = sizeof(struct sockaddr);
00514     if(::getpeername(fd_, sa_, &slen) == 0) {
00515         switch (proto_) {
00516             case L2CAP:
00517             case HCI:
00518             case SCO:
00519                 break; // not implemented
00520             case RFCOMM:
00521                 rc_ = (struct sockaddr_rc *) sa_;
00522                 bacpy(&remote_addr_,&rc_->rc_bdaddr);
00523                 channel_ = rc_->rc_channel;
00524                 break;
00525             case BNEP:
00526             case CMTP:
00527             case HIDP:
00528             case AVDTP:
00529             default:
00530                 break;
00531         }
00532     }
00533 }
00534 
00535 void
00536 BluetoothSocket::init_sa(int sa_type)
00537 {
00538     if (sa_ == NULL) {
00539         sa_ = new sockaddr();
00540     }
00541     memset(sa_,0,sizeof(struct sockaddr));
00542     if( sa_type == (int) ZERO ) return;
00543 
00544     switch (proto_) {
00545         case L2CAP:
00546         case HCI:
00547         case SCO:
00548             break; // not implemented
00549         case RFCOMM:
00550             // from net/bluetooth/rfcomm/core.c
00551             ASSERT(channel_ >= 1 && channel_ <= 30);
00552             slen_ = sizeof(struct sockaddr_rc);
00553             rc_ = (struct sockaddr_rc*) sa_;
00554             rc_->rc_family = AF_BLUETOOTH;
00555             if( sa_type == (int) LOCAL ) {
00556                 bacpy(&rc_->rc_bdaddr,&local_addr_);
00557                 rc_->rc_channel = channel_;
00558             } else {
00559                 bacpy(&rc_->rc_bdaddr,&remote_addr_);
00560                 rc_->rc_channel = channel_;
00561             } 
00562             return;
00563         case BNEP:
00564         case CMTP:
00565         case HIDP:
00566         case AVDTP:
00567         default:
00568             break; // not implemented
00569     } 
00570     ASSERT(0);
00571 } 
00572 
00573 int
00574 BluetoothSocket::poll_sockfd(int events, int* revents, int timeout_ms)
00575 {
00576     short s_events = events;
00577     short s_revents;
00578 
00579     int cc = IO::poll_single(fd_, s_events, &s_revents, timeout_ms,
00580                              get_notifier(), logpath_);
00581 
00582     if (revents != 0) {
00583         *revents = s_revents;
00584     }
00585 
00586     return cc;
00587 }
00588 
00589 int RFCOMMChannel::rc_channel_ = -1;
00590 SpinLock RFCOMMChannel::lock_ = SpinLock();
00591 
00592 int
00593 RFCOMMChannel::next() {
00594     ScopeLock l(&lock_,"RFCOMMChannel::next");
00595     ++rc_channel_; // starts off at zero;
00596     rc_channel_ %= 30; // never exceeds 29
00597     int next = rc_channel_ + 1;
00598     return next;
00599 }
00600 
00601 } // namespace oasys
00602 #endif /* OASYS_BLUETOOTH_ENABLED */

Generated on Fri Dec 22 14:47:57 2006 for DTN Reference Implementation by  doxygen 1.5.1