BluetoothSocket.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 <errno.h>
00021 #include "BluetoothSocket.h"
00022 
00023 namespace oasys {
00024 
00025 int BluetoothSocket::abort_on_error_ = 0;
00026 
00027 BluetoothSocket::BluetoothSocket(int socktype,
00028                                  proto_t proto,
00029                                  const char* logbase)
00030     : Logger("BluetoothSocket", logbase)
00031 {
00032     state_ = INIT;
00033     memset(&local_addr_,0,sizeof(bdaddr_t));
00034     channel_ = 0;
00035     memset(&remote_addr_,0,sizeof(bdaddr_t));
00036     fd_ = -1;
00037     socktype_ = socktype;
00038     proto_ = (proto_t) proto;
00039     logfd_ = true; 
00040 }
00041 
00042 BluetoothSocket::BluetoothSocket(int socktype, proto_t proto, int sock,
00043                    bdaddr_t remote_addr, u_int8_t channel,
00044                    const char* logbase)
00045     : Logger("BluetoothSocket", logbase)
00046 {
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     set_channel(channel);
00054     set_remote_addr(remote_addr);
00055 
00056     configure();
00057 }
00058 
00059 BluetoothSocket::~BluetoothSocket()
00060 {
00061     close();
00062 }
00063 
00064 void
00065 BluetoothSocket::init_socket()
00066 {
00067     // should only be called at real init time or after a call to close()
00068     ASSERT(state_ == INIT || state_ == FINI);
00069     ASSERT(fd_ == -1);
00070     state_ = INIT;
00071 
00072     fd_ = socket(PF_BLUETOOTH, socktype_, (int) proto_);
00073     if (fd_ == -1) {
00074         logf(LOG_ERR, "error creating socket: %s", strerror(errno));
00075         if(errno==EBADFD) close();
00076         return;
00077     }
00078 
00079     if (logfd_)
00080         Logger::logpath_appendf("/%s/%d",
00081                                 prototoa((proto_t)proto_),
00082                                 fd_);
00083 
00084     logf(LOG_DEBUG, "created socket %d of protocol %s", fd_, 
00085          prototoa((proto_t)proto_));
00086 
00087     configure(); 
00088 }
00089 
00090 const char*
00091 BluetoothSocket::statetoa(state_t state)
00092 {
00093     switch (state) {
00094         case INIT:          return "INIT";
00095         case LISTENING:     return "LISTENING";
00096         case CONNECTING:    return "CONNECTING";
00097         case ESTABLISHED:   return "ESTABLISHED";
00098         case RDCLOSED:      return "RDCLOSED";
00099         case WRCLOSED:      return "WRCLOSED";
00100         case CLOSED:        return "CLOSED";
00101         case FINI:          return "FINI";
00102     }
00103     ASSERT(0);
00104     return NULL;
00105 }
00106 
00107 void
00108 BluetoothSocket::set_state(state_t state)
00109 {
00110     logf(LOG_DEBUG, "state %s -> %s", statetoa(state_), 
00111          statetoa(state));
00112     state_ = state;
00113 }
00114 
00115 const char* 
00116 BluetoothSocket::prototoa(proto_t proto)
00117 {
00118     switch (proto) {
00119         case L2CAP:    return "L2CAP";
00120         case HCI:      return "HCI";
00121         case SCO:      return "SCO";
00122         case RFCOMM:   return "RFCOMM";
00123         case BNEP:     return "BNEP";
00124         case CMTP:     return "CMTP";
00125         case HIDP:     return "HIDP";
00126         case AVDTP:    return "AVDTP";
00127     }
00128     ASSERT(0);
00129     return NULL;
00130 }
00131 
00132 void 
00133 BluetoothSocket::set_proto(proto_t proto)
00134 {
00135     logf(LOG_DEBUG, "protocol %s -> %s", prototoa((proto_t)proto_), 
00136          prototoa((proto_t)proto));
00137     proto_ = proto;
00138 }
00139 
00140 int
00141 BluetoothSocket::bind(bdaddr_t local_addr, u_int8_t local_channel)
00142 {
00143     struct sockaddr sa;
00144 
00145     if (fd_ == -1) init_socket();
00146 
00147     set_local_addr(local_addr);
00148     set_channel(local_channel);
00149 
00150     if (!params_.silent_connect_)
00151     logf(LOG_DEBUG, "binding to %s(%d)", bd2str(local_addr),local_channel);
00152 
00153     memset(&sa,0,sizeof(sa));
00154     switch(proto_) {
00155     case RFCOMM:
00156         // from net/bluetooth/rfcomm/core.c
00157         ASSERT(channel_ >= 1 && channel_ <= 30);
00158         rc_ = (struct sockaddr_rc*)&sa;
00159         rc_->rc_family = AF_BLUETOOTH;
00160         rc_->rc_channel = channel_;
00161         bacpy(&rc_->rc_bdaddr,&local_addr_);
00162         break;
00163     default:
00164         ASSERTF(0,"unsupported protocol %s",prototoa((proto_t)proto_));
00165         break;
00166     }
00167 
00168     if(::bind(fd_,&sa,sizeof(sa)) != 0) {
00169         log_level_t level = LOG_ERR;
00170         if(errno == EADDRINUSE) level = LOG_DEBUG;
00171         if (!params_.silent_connect_)
00172         logf(level, "failed to bind to %s(%d): %s",
00173              bd2str(local_addr), channel_, strerror(errno));
00174         if(errno==EBADFD) close();
00175         return -1;
00176     }
00177 
00178     return 0;
00179 }
00180 
00181 int
00182 BluetoothSocket::bind()
00183 {
00184     return bind(local_addr_,channel_);
00185 }
00186 
00187 int
00188 BluetoothSocket::connect()
00189 {
00190     // In Bluetooth, piconets are formed by one Master
00191     // connecting to up to seven Slaves, simultaneously
00192     // The device performing connect() is Master
00193 
00194     struct sockaddr sa;
00195 
00196     if (state_ == ESTABLISHED) 
00197         return 0;
00198 
00199     if (fd_ == -1) init_socket();
00200 
00201     log_debug("connecting to %s(%d)",bd2str(remote_addr_),channel_);
00202 
00203     memset(&sa,0,sizeof(sa));
00204     switch(proto_) {
00205     case RFCOMM:
00206         // from net/bluetooth/rfcomm/core.c
00207         ASSERT(channel_ >= 1 && channel_ <= 30);
00208         rc_ = (struct sockaddr_rc*)&sa;
00209         rc_->rc_family = AF_BLUETOOTH;
00210         rc_->rc_channel = channel_;
00211         bacpy(&rc_->rc_bdaddr,&remote_addr_);
00212         break;
00213     default:
00214         ASSERTF(0,"unsupported protocol %s",prototoa((proto_t)proto_));
00215         break;
00216     }
00217 
00218     set_state(CONNECTING);
00219 
00220     if (::connect(fd_,&sa,sizeof(sa)) < 0) {
00221         if (errno == EISCONN && !params_.silent_connect_)
00222             log_debug("already connected to %s-%u",
00223                       bd2str(remote_addr_), channel_);
00224         else if (errno == EINPROGRESS && !params_.silent_connect_) {
00225             log_debug("delayed connect to %s-%u",
00226                       bd2str(remote_addr_), channel_);
00227         } else if(errno==EBADFD) {
00228             if (!params_.silent_connect_) log_err("EBADFD");
00229             close();
00230         } else {
00231             if (!params_.silent_connect_)
00232                 log_debug("error connecting to %s(%d): %s",
00233                           bd2str(remote_addr_), channel_, strerror(errno));
00234         }
00235         return -1;
00236     }
00237 
00238     set_state(ESTABLISHED);
00239 
00240     return 0;
00241 }
00242 
00243 int
00244 BluetoothSocket::async_connect_result()
00245 {
00246     ASSERT(state_ == CONNECTING);
00247 
00248     int result;
00249     socklen_t len = sizeof(result);
00250     logf(LOG_DEBUG, "getting connect result");
00251     if (::getsockopt(fd_, SOL_SOCKET, SO_ERROR, &result, &len) != 0) {
00252         logf(LOG_ERR, "error getting connect result: %s", strerror(errno));
00253         return errno;
00254     }
00255 
00256     if (result == 0) {
00257         state_ = ESTABLISHED;
00258     }
00259 
00260     return result;
00261 }
00262 
00263 int
00264 BluetoothSocket::connect(bdaddr_t remote_addr, u_int8_t remote_channel)
00265 {
00266     set_remote_addr(remote_addr);
00267     set_channel(remote_channel);
00268 
00269     return connect();
00270 }
00271 
00272 void
00273 BluetoothSocket::configure()
00274 {
00275     ASSERT(fd_ != -1);
00276 
00277     if (params_.reuseaddr_) {
00278         int y = 1;
00279         logf(LOG_DEBUG, "setting SO_REUSEADDR");
00280         if (::setsockopt(fd_, SOL_SOCKET, SO_REUSEADDR, &y, sizeof y) != 0) {
00281             logf(LOG_WARN, "error setting SO_REUSEADDR: %s",
00282                  strerror(errno));
00283         }
00284     }
00285 
00286     if (params_.recv_bufsize_ > 0) {
00287         logf(LOG_DEBUG, "setting SO_RCVBUF to %d",
00288              params_.recv_bufsize_);
00289         if (::setsockopt(fd_, SOL_SOCKET, SO_RCVBUF,
00290                          &params_.recv_bufsize_,
00291                          sizeof(params_.recv_bufsize_)) < 0)
00292         {
00293             logf(LOG_WARN, "error setting SO_RCVBUF to %d: %s",
00294                  params_.recv_bufsize_, strerror(errno)); 
00295         }
00296     }
00297 
00298     if (params_.send_bufsize_ > 0) {
00299         logf(LOG_DEBUG, "setting SO_SNDBUF to %d",
00300              params_.send_bufsize_);
00301         if (::setsockopt(fd_, SOL_SOCKET, SO_SNDBUF,
00302                          &params_.send_bufsize_,
00303                          sizeof(params_.send_bufsize_)) < 0)
00304         {
00305             logf(LOG_WARN, "error setting SO_SNDBUF to %d: %s",
00306                  params_.send_bufsize_, strerror(errno)); 
00307         }
00308     }
00309 
00310 }
00311 
00312 int
00313 BluetoothSocket::close()
00314 {
00315     logf(LOG_DEBUG, "closing socket in state %s", statetoa(state_));
00316 
00317     if (fd_ == -1) {
00318         ASSERT(state_ == INIT || state_ == FINI);
00319         return 0;
00320     }
00321 
00322     if (::close(fd_) != 0) {
00323         logf(LOG_ERR, "error closing socket in state %s: %s",
00324                 statetoa(state_), strerror(errno));
00325         return -1;
00326     }
00327 
00328     set_state(FINI);
00329     fd_ = -1;
00330     return 0;
00331 }
00332 
00333 int
00334 BluetoothSocket::shutdown(int how)
00335 {
00336     const char* howstr;
00337 
00338     switch (how) {
00339         case SHUT_RD:   howstr = "R";  break;
00340         case SHUT_WR:   howstr = "W";  break;
00341         case SHUT_RDWR: howstr = "RW"; break;
00342 
00343         default:
00344             logf(LOG_ERR, "shutdown invalid mode %d", how);
00345             return -1;
00346     }
00347 
00348     logf(LOG_DEBUG, "shutdown(%s) state %s", howstr, statetoa(state_));
00349 
00350     if (state_ == INIT || state_ == FINI) {
00351         ASSERT(fd_ == -1);
00352         return 0;
00353     }
00354 
00355     if (::shutdown(fd_, how) != 0) {
00356         logf(LOG_ERR, "error in shutdown(%s) state %s: %s",
00357              howstr, statetoa(state_), strerror(errno));
00358     } 
00359     if (state_ == ESTABLISHED) {
00360         if (how == SHUT_RD)     { set_state(RDCLOSED); }
00361         if (how == SHUT_WR)     { set_state(WRCLOSED); }
00362         if (how == SHUT_RDWR)   { set_state(CLOSED); } 
00363 
00364     } else if (state_ == RDCLOSED && how == SHUT_WR) {
00365         set_state(CLOSED);
00366 
00367     } else if (state_ == WRCLOSED && how == SHUT_RD) {
00368         set_state(CLOSED);
00369 
00370     } else {
00371         logf(LOG_ERR, "invalid state %s for shutdown(%s)",
00372              statetoa(state_), howstr);
00373         return -1;
00374     }
00375 
00376     return 0; 
00377 }
00378 
00379 int
00380 BluetoothSocket::send(const char* bp, size_t len, int flags)
00381 {
00382     return IO::send(fd_, bp, len, flags, get_notifier(), logpath_);
00383 }
00384 
00385 int
00386 BluetoothSocket::recv(char* bp, size_t len, int flags)
00387 {
00388     return IO::recv(fd_, bp, len, flags, get_notifier(), logpath_);
00389 }
00390 
00391 int
00392 BluetoothSocket::fd()
00393 {
00394     return fd_;
00395 }
00396 
00397 void
00398 BluetoothSocket::local_addr(bdaddr_t& addr)
00399 {
00400     if (!bacmp(&addr,&local_addr_)) get_local();
00401     bacpy(&addr,&local_addr_);
00402 }
00403 
00404 u_int8_t
00405 BluetoothSocket::channel()
00406 {
00407     if (channel_ == 0) get_local();
00408     return channel_;
00409 }
00410 
00411 void
00412 BluetoothSocket::remote_addr(bdaddr_t& addr)
00413 {
00414     if (!bacmp(&addr,&remote_addr_)) get_remote();
00415     bacpy(&addr,&remote_addr_);
00416 }
00417 
00418 void
00419 BluetoothSocket::set_local_addr(bdaddr_t& addr)
00420 {
00421     bacpy(&local_addr_,&addr);
00422 }
00423 
00424 void
00425 BluetoothSocket::set_channel(u_int8_t channel)
00426 {
00427     // from net/bluetooth/rfcomm/core.c
00428     ASSERT(channel >= 1 && channel <= 30);
00429     channel_ = channel;
00430 }
00431 
00432 void
00433 BluetoothSocket::set_remote_addr(bdaddr_t& addr)
00434 {
00435     bacpy(&remote_addr_,&addr);
00436 }
00437 
00438 void
00439 BluetoothSocket::get_local()
00440 {
00441     if (fd_ < 0)
00442         return;
00443 
00444     socklen_t slen = sizeof(struct sockaddr);
00445     struct sockaddr sa;
00446     memset(&sa,0,slen);
00447     if(::getsockname(fd_, &sa, &slen) == 0) {
00448         switch (proto_) { 
00449             case RFCOMM:
00450                 rc_ = (struct sockaddr_rc *) &sa;
00451                 bacpy(&local_addr_,&rc_->rc_bdaddr);
00452                 channel_ = rc_->rc_channel;
00453                 break;
00454             // not implemented
00455             default:
00456                 ASSERTF(0,"not implemented for %s",prototoa((proto_t)proto_));
00457                 break;
00458         }
00459     }
00460 }
00461 
00462 void
00463 BluetoothSocket::get_remote()
00464 {
00465     if (fd_ < 0)
00466         return;
00467 
00468     socklen_t slen = sizeof(struct sockaddr);
00469     struct sockaddr sa;
00470     memset(&sa,0,slen);
00471     if(::getpeername(fd_, &sa, &slen) == 0) {
00472         switch (proto_) {
00473             case RFCOMM:
00474                 rc_ = (struct sockaddr_rc *) &sa;
00475                 bacpy(&remote_addr_,&rc_->rc_bdaddr);
00476                 channel_ = rc_->rc_channel;
00477                 break;
00478             // not implemented
00479             default:
00480                 ASSERTF(0,"not implemented for %s",prototoa((proto_t)proto_));
00481                 break;
00482         }
00483     }
00484 }
00485 
00486 int
00487 BluetoothSocket::poll_sockfd(int events, int* revents, int timeout_ms)
00488 {
00489     short s_events = events;
00490     short s_revents = 0;
00491 
00492     int cc = IO::poll_single(fd_, s_events, &s_revents, timeout_ms,
00493                              get_notifier(), logpath_);
00494 
00495     if (revents != 0) {
00496         *revents = s_revents;
00497     }
00498 
00499     return cc;
00500 }
00501 
00502 } // namespace oasys
00503 #endif /* OASYS_BLUETOOTH_ENABLED */

Generated on Thu Jun 7 12:54:25 2007 for DTN Reference Implementation by  doxygen 1.5.1