BluetoothServer.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 "Bluetooth.h"
00021 #include "BluetoothServer.h"
00022 #include "debug/Log.h"
00023 
00024 #include <errno.h>
00025 #include <sys/types.h>
00026 #include <sys/socket.h>
00027 #include <netinet/in.h>
00028 
00029 namespace oasys {
00030 
00031 BluetoothServer::BluetoothServer(int socktype,
00032                                  BluetoothSocket::proto_t proto,
00033                                  char* logbase)
00034     : BluetoothSocket(socktype, proto, logbase)
00035 {
00036 }
00037 
00038 int
00039 BluetoothServer::listen()
00040 {
00041     // In Bluetooth, piconets are formed by one Master
00042     // connecting to up to seven Slaves.  The device
00043     // performing connect() is the Master ... thus the
00044     // device performing listen()/accept() is the Slave.
00045     logf(LOG_DEBUG, "listening");
00046     ASSERT(fd_ != -1);
00047 
00048     if (::listen(fd_, SOMAXCONN) == -1) {
00049         logf(LOG_ERR, "error in listen(): %s",strerror(errno));
00050         return -1;
00051     }
00052     
00053     set_state(LISTENING);
00054     return 0;
00055 }
00056     
00057 int
00058 BluetoothServer::accept(int *fd, bdaddr_t *addr, u_int8_t *channel)
00059 {
00060     ASSERTF(state_ == LISTENING,
00061             "accept() expected state LISTENING, not %s", statetoa(state_));
00062     
00063     struct sockaddr sa;
00064     socklen_t sl = sizeof(sa);
00065     memset(&sa,0,sl);
00066 
00067     int ret = ::accept(fd_,&sa,&sl);
00068     if (ret == -1) {
00069         logf(LOG_ERR, "error in accept(): %s",strerror(errno));
00070         return ret;
00071     }
00072     
00073     *fd = ret;
00074 
00075     switch(proto_) {
00076     case RFCOMM:
00077         rc_ = (struct sockaddr_rc*) &sa;
00078         bacpy(addr,&rc_->rc_bdaddr);
00079         *channel = rc_->rc_channel;
00080         break;
00081     default:
00082         ASSERTF(0,"not implemented for %s",prototoa((proto_t)proto_));
00083         break;
00084     }
00085 
00086     monitor(IO::ACCEPT, 0); // XXX/bowei
00087 
00088     return 0;
00089 }
00090 
00091 int
00092 BluetoothServer::timeout_accept(int *fd, bdaddr_t *addr, u_int8_t *channel,
00093                                 int timeout_ms)
00094 {
00095     int ret = poll_sockfd(POLLIN, NULL, timeout_ms);
00096 
00097     if (ret != 1) return ret;
00098     ASSERT(ret == 1);
00099 
00100     ret = accept(fd, addr, channel);
00101 
00102     if (ret < 0) {
00103         return IOERROR;
00104     }
00105 
00106     monitor(IO::ACCEPT, 0); // XXX/bowei
00107 
00108     return 0;
00109 }
00110 
00111 void
00112 BluetoothServerThread::run()
00113 {
00114     int fd;
00115     bdaddr_t addr;
00116     u_int8_t channel;
00117 
00118     while (1) {
00119         // check if someone has told us to quit by setting the
00120         // should_stop flag. if so, we're all done.
00121         if (should_stop())
00122             break;
00123 
00124         // check the accept_timeout parameter to see if we should
00125         // block or poll when calling accept
00126         int ret;
00127         if (accept_timeout_ == -1) {
00128             ret = accept(&fd, &addr, &channel);
00129         } else {
00130             ret = timeout_accept(&fd, &addr, &channel, accept_timeout_);
00131             if (ret == IOTIMEOUT)
00132                 continue;
00133         }
00134 
00135         if (ret != 0) {
00136             if (errno == EINTR || ret == IOINTR) 
00137                 continue;
00138 
00139             logf(LOG_ERR, "error %d in accept(): %d %s",
00140                  ret, errno, strerror(errno));
00141             close();
00142 
00143             ASSERT(errno != 0);
00144 
00145             break;
00146         }
00147         
00148         logf(LOG_DEBUG, "accepted connection fd %d from %s(%d)",
00149              fd, bd2str(addr), channel);
00150 
00151         set_remote_addr(addr);
00152 
00153         accepted(fd, addr, channel);
00154     }
00155 }
00156 
00157 int
00158 BluetoothServerThread::bind_listen_start(bdaddr_t local_addr,
00159                                   u_int8_t local_channel)
00160 {
00161     if(bind(local_addr, local_channel) != 0)
00162         return -1;
00163 
00164     if(listen() != 0)
00165         return -1;
00166 
00167     start();
00168 
00169     return 0;
00170 }
00171 
00172 } // namespace oasys
00173 #endif /* OASYS_BLUETOOTH_ENABLED */

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