Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 #include <stdio.h>
     17 #include <errno.h>
     18 #include <stdlib.h>
     19 #include <sys/socket.h>
     20 #include <sys/select.h>
     21 #include <sys/time.h>
     22 #include <sys/types.h>
     23 #include <sys/un.h>
     24 
     25 #define LOG_TAG "SocketListener"
     26 #include <cutils/log.h>
     27 #include <cutils/sockets.h>
     28 
     29 #include <sysutils/SocketListener.h>
     30 #include <sysutils/SocketClient.h>
     31 
     32 SocketListener::SocketListener(const char *socketName, bool listen) {
     33     mListen = listen;
     34     mSocketName = socketName;
     35     mSock = -1;
     36     pthread_mutex_init(&mClientsLock, NULL);
     37     mClients = new SocketClientCollection();
     38 }
     39 
     40 SocketListener::SocketListener(int socketFd, bool listen) {
     41     mListen = listen;
     42     mSocketName = NULL;
     43     mSock = socketFd;
     44     pthread_mutex_init(&mClientsLock, NULL);
     45     mClients = new SocketClientCollection();
     46 }
     47 
     48 SocketListener::~SocketListener() {
     49     if (mSocketName && mSock > -1)
     50         close(mSock);
     51 
     52     if (mCtrlPipe[0] != -1) {
     53         close(mCtrlPipe[0]);
     54         close(mCtrlPipe[1]);
     55     }
     56     SocketClientCollection::iterator it;
     57     for (it = mClients->begin(); it != mClients->end(); ++it) {
     58         delete (*it);
     59         it = mClients->erase(it);
     60     }
     61     delete mClients;
     62 }
     63 
     64 int SocketListener::startListener() {
     65 
     66     if (!mSocketName && mSock == -1) {
     67         SLOGE("Failed to start unbound listener");
     68         errno = EINVAL;
     69         return -1;
     70     } else if (mSocketName) {
     71         if ((mSock = android_get_control_socket(mSocketName)) < 0) {
     72             SLOGE("Obtaining file descriptor socket '%s' failed: %s",
     73                  mSocketName, strerror(errno));
     74             return -1;
     75         }
     76     }
     77 
     78     if (mListen && listen(mSock, 4) < 0) {
     79         SLOGE("Unable to listen on socket (%s)", strerror(errno));
     80         return -1;
     81     } else if (!mListen)
     82         mClients->push_back(new SocketClient(mSock));
     83 
     84     if (pipe(mCtrlPipe)) {
     85         SLOGE("pipe failed (%s)", strerror(errno));
     86         return -1;
     87     }
     88 
     89     if (pthread_create(&mThread, NULL, SocketListener::threadStart, this)) {
     90         SLOGE("pthread_create (%s)", strerror(errno));
     91         return -1;
     92     }
     93 
     94     return 0;
     95 }
     96 
     97 int SocketListener::stopListener() {
     98     char c = 0;
     99 
    100     if (write(mCtrlPipe[1], &c, 1) != 1) {
    101         SLOGE("Error writing to control pipe (%s)", strerror(errno));
    102         return -1;
    103     }
    104 
    105     void *ret;
    106     if (pthread_join(mThread, &ret)) {
    107         SLOGE("Error joining to listener thread (%s)", strerror(errno));
    108         return -1;
    109     }
    110     close(mCtrlPipe[0]);
    111     close(mCtrlPipe[1]);
    112     mCtrlPipe[0] = -1;
    113     mCtrlPipe[1] = -1;
    114 
    115     if (mSocketName && mSock > -1) {
    116         close(mSock);
    117         mSock = -1;
    118     }
    119 
    120     SocketClientCollection::iterator it;
    121     for (it = mClients->begin(); it != mClients->end(); ++it) {
    122         delete (*it);
    123         it = mClients->erase(it);
    124     }
    125     return 0;
    126 }
    127 
    128 void *SocketListener::threadStart(void *obj) {
    129     SocketListener *me = reinterpret_cast<SocketListener *>(obj);
    130 
    131     me->runListener();
    132     pthread_exit(NULL);
    133     return NULL;
    134 }
    135 
    136 void SocketListener::runListener() {
    137 
    138     while(1) {
    139         SocketClientCollection::iterator it;
    140         fd_set read_fds;
    141         int rc = 0;
    142         int max = 0;
    143 
    144         FD_ZERO(&read_fds);
    145 
    146         if (mListen) {
    147             max = mSock;
    148             FD_SET(mSock, &read_fds);
    149         }
    150 
    151         FD_SET(mCtrlPipe[0], &read_fds);
    152         if (mCtrlPipe[0] > max)
    153             max = mCtrlPipe[0];
    154 
    155         pthread_mutex_lock(&mClientsLock);
    156         for (it = mClients->begin(); it != mClients->end(); ++it) {
    157             FD_SET((*it)->getSocket(), &read_fds);
    158             if ((*it)->getSocket() > max)
    159                 max = (*it)->getSocket();
    160         }
    161         pthread_mutex_unlock(&mClientsLock);
    162 
    163         if ((rc = select(max + 1, &read_fds, NULL, NULL, NULL)) < 0) {
    164             SLOGE("select failed (%s)", strerror(errno));
    165             sleep(1);
    166             continue;
    167         } else if (!rc)
    168             continue;
    169 
    170         if (FD_ISSET(mCtrlPipe[0], &read_fds))
    171             break;
    172         if (mListen && FD_ISSET(mSock, &read_fds)) {
    173             struct sockaddr addr;
    174             socklen_t alen = sizeof(addr);
    175             int c;
    176 
    177             if ((c = accept(mSock, &addr, &alen)) < 0) {
    178                 SLOGE("accept failed (%s)", strerror(errno));
    179                 sleep(1);
    180                 continue;
    181             }
    182             pthread_mutex_lock(&mClientsLock);
    183             mClients->push_back(new SocketClient(c));
    184             pthread_mutex_unlock(&mClientsLock);
    185         }
    186 
    187         do {
    188             pthread_mutex_lock(&mClientsLock);
    189             for (it = mClients->begin(); it != mClients->end(); ++it) {
    190                 int fd = (*it)->getSocket();
    191                 if (FD_ISSET(fd, &read_fds)) {
    192                     pthread_mutex_unlock(&mClientsLock);
    193                     if (!onDataAvailable(*it)) {
    194                         close(fd);
    195                         pthread_mutex_lock(&mClientsLock);
    196                         delete *it;
    197                         it = mClients->erase(it);
    198                         pthread_mutex_unlock(&mClientsLock);
    199                     }
    200                     FD_CLR(fd, &read_fds);
    201                     pthread_mutex_lock(&mClientsLock);
    202                     continue;
    203                 }
    204             }
    205             pthread_mutex_unlock(&mClientsLock);
    206         } while (0);
    207     }
    208 }
    209 
    210 void SocketListener::sendBroadcast(int code, const char *msg, bool addErrno) {
    211     pthread_mutex_lock(&mClientsLock);
    212     SocketClientCollection::iterator i;
    213 
    214     for (i = mClients->begin(); i != mClients->end(); ++i) {
    215         if ((*i)->sendMsg(code, msg, addErrno)) {
    216             SLOGW("Error sending broadcast (%s)", strerror(errno));
    217         }
    218     }
    219     pthread_mutex_unlock(&mClientsLock);
    220 }
    221 
    222 void SocketListener::sendBroadcast(const char *msg) {
    223     pthread_mutex_lock(&mClientsLock);
    224     SocketClientCollection::iterator i;
    225 
    226     for (i = mClients->begin(); i != mClients->end(); ++i) {
    227         if ((*i)->sendMsg(msg)) {
    228             SLOGW("Error sending broadcast (%s)", strerror(errno));
    229         }
    230     }
    231     pthread_mutex_unlock(&mClientsLock);
    232 }
    233