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();) {
     58         (*it)->decRef();
     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, false));
     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     int  rc;
    100 
    101     rc = TEMP_FAILURE_RETRY(write(mCtrlPipe[1], &c, 1));
    102     if (rc != 1) {
    103         SLOGE("Error writing to control pipe (%s)", strerror(errno));
    104         return -1;
    105     }
    106 
    107     void *ret;
    108     if (pthread_join(mThread, &ret)) {
    109         SLOGE("Error joining to listener thread (%s)", strerror(errno));
    110         return -1;
    111     }
    112     close(mCtrlPipe[0]);
    113     close(mCtrlPipe[1]);
    114     mCtrlPipe[0] = -1;
    115     mCtrlPipe[1] = -1;
    116 
    117     if (mSocketName && mSock > -1) {
    118         close(mSock);
    119         mSock = -1;
    120     }
    121 
    122     SocketClientCollection::iterator it;
    123     for (it = mClients->begin(); it != mClients->end();) {
    124         delete (*it);
    125         it = mClients->erase(it);
    126     }
    127     return 0;
    128 }
    129 
    130 void *SocketListener::threadStart(void *obj) {
    131     SocketListener *me = reinterpret_cast<SocketListener *>(obj);
    132 
    133     me->runListener();
    134     pthread_exit(NULL);
    135     return NULL;
    136 }
    137 
    138 void SocketListener::runListener() {
    139 
    140     SocketClientCollection *pendingList = new SocketClientCollection();
    141 
    142     while(1) {
    143         SocketClientCollection::iterator it;
    144         fd_set read_fds;
    145         int rc = 0;
    146         int max = -1;
    147 
    148         FD_ZERO(&read_fds);
    149 
    150         if (mListen) {
    151             max = mSock;
    152             FD_SET(mSock, &read_fds);
    153         }
    154 
    155         FD_SET(mCtrlPipe[0], &read_fds);
    156         if (mCtrlPipe[0] > max)
    157             max = mCtrlPipe[0];
    158 
    159         pthread_mutex_lock(&mClientsLock);
    160         for (it = mClients->begin(); it != mClients->end(); ++it) {
    161             int fd = (*it)->getSocket();
    162             FD_SET(fd, &read_fds);
    163             if (fd > max)
    164                 max = fd;
    165         }
    166         pthread_mutex_unlock(&mClientsLock);
    167 
    168         if ((rc = select(max + 1, &read_fds, NULL, NULL, NULL)) < 0) {
    169             if (errno == EINTR)
    170                 continue;
    171             SLOGE("select failed (%s)", strerror(errno));
    172             sleep(1);
    173             continue;
    174         } else if (!rc)
    175             continue;
    176 
    177         if (FD_ISSET(mCtrlPipe[0], &read_fds))
    178             break;
    179         if (mListen && FD_ISSET(mSock, &read_fds)) {
    180             struct sockaddr addr;
    181             socklen_t alen;
    182             int c;
    183 
    184             do {
    185                 alen = sizeof(addr);
    186                 c = accept(mSock, &addr, &alen);
    187             } while (c < 0 && errno == EINTR);
    188             if (c < 0) {
    189                 SLOGE("accept failed (%s)", strerror(errno));
    190                 sleep(1);
    191                 continue;
    192             }
    193             pthread_mutex_lock(&mClientsLock);
    194             mClients->push_back(new SocketClient(c, true));
    195             pthread_mutex_unlock(&mClientsLock);
    196         }
    197 
    198         /* Add all active clients to the pending list first */
    199         pendingList->clear();
    200         pthread_mutex_lock(&mClientsLock);
    201         for (it = mClients->begin(); it != mClients->end(); ++it) {
    202             int fd = (*it)->getSocket();
    203             if (FD_ISSET(fd, &read_fds)) {
    204                 pendingList->push_back(*it);
    205             }
    206         }
    207         pthread_mutex_unlock(&mClientsLock);
    208 
    209         /* Process the pending list, since it is owned by the thread,
    210          * there is no need to lock it */
    211         while (!pendingList->empty()) {
    212             /* Pop the first item from the list */
    213             it = pendingList->begin();
    214             SocketClient* c = *it;
    215             pendingList->erase(it);
    216             /* Process it, if false is returned and our sockets are
    217              * connection-based, remove and destroy it */
    218             if (!onDataAvailable(c) && mListen) {
    219                 /* Remove the client from our array */
    220                 pthread_mutex_lock(&mClientsLock);
    221                 for (it = mClients->begin(); it != mClients->end(); ++it) {
    222                     if (*it == c) {
    223                         mClients->erase(it);
    224                         break;
    225                     }
    226                 }
    227                 pthread_mutex_unlock(&mClientsLock);
    228                 /* Remove our reference to the client */
    229                 c->decRef();
    230             }
    231         }
    232     }
    233     delete pendingList;
    234 }
    235 
    236 void SocketListener::sendBroadcast(int code, const char *msg, bool addErrno) {
    237     pthread_mutex_lock(&mClientsLock);
    238     SocketClientCollection::iterator i;
    239 
    240     for (i = mClients->begin(); i != mClients->end(); ++i) {
    241         if ((*i)->sendMsg(code, msg, addErrno)) {
    242             SLOGW("Error sending broadcast (%s)", strerror(errno));
    243         }
    244     }
    245     pthread_mutex_unlock(&mClientsLock);
    246 }
    247 
    248 void SocketListener::sendBroadcast(const char *msg) {
    249     pthread_mutex_lock(&mClientsLock);
    250     SocketClientCollection::iterator i;
    251 
    252     for (i = mClients->begin(); i != mClients->end(); ++i) {
    253         if ((*i)->sendMsg(msg)) {
    254             SLOGW("Error sending broadcast (%s)", strerror(errno));
    255         }
    256     }
    257     pthread_mutex_unlock(&mClientsLock);
    258 }
    259