1168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat/*
2168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * Copyright (C) 2008 The Android Open Source Project
3168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat *
4168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * Licensed under the Apache License, Version 2.0 (the "License");
5168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * you may not use this file except in compliance with the License.
6168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * You may obtain a copy of the License at
7168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat *
8168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat *      http://www.apache.org/licenses/LICENSE-2.0
9168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat *
10168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * Unless required by applicable law or agreed to in writing, software
11168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * distributed under the License is distributed on an "AS IS" BASIS,
12168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * See the License for the specific language governing permissions and
14168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * limitations under the License.
15168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat */
16168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat#include <stdio.h>
17168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat#include <errno.h>
18168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat#include <stdlib.h>
19168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat#include <sys/socket.h>
20168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat#include <sys/select.h>
21168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat#include <sys/time.h>
22168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat#include <sys/types.h>
23168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat#include <sys/un.h>
24168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat
25168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat#define LOG_TAG "SocketListener"
26168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat#include <cutils/log.h>
27168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat#include <cutils/sockets.h>
28168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat
29168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat#include <sysutils/SocketListener.h>
30fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat#include <sysutils/SocketClient.h>
31168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat
328702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt#define LOG_NDEBUG 0
338702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt
34fa644ffe944c01a9b00f8d7676d58394fabee285San MehatSocketListener::SocketListener(const char *socketName, bool listen) {
358702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt    init(socketName, -1, listen, false);
36168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat}
37168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat
38fa644ffe944c01a9b00f8d7676d58394fabee285San MehatSocketListener::SocketListener(int socketFd, bool listen) {
398702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt    init(NULL, socketFd, listen, false);
408702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt}
418702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt
428702bb17f40022e970e8acd40b348d074e39afc7Robert GreenwaltSocketListener::SocketListener(const char *socketName, bool listen, bool useCmdNum) {
438702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt    init(socketName, -1, listen, useCmdNum);
448702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt}
458702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt
468702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwaltvoid SocketListener::init(const char *socketName, int socketFd, bool listen, bool useCmdNum) {
47fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    mListen = listen;
488702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt    mSocketName = socketName;
49168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat    mSock = socketFd;
508702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt    mUseCmdNum = useCmdNum;
51fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    pthread_mutex_init(&mClientsLock, NULL);
52fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    mClients = new SocketClientCollection();
53168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat}
54168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat
55c4a895b7094461c98101924cf096680bfb7856f1San MehatSocketListener::~SocketListener() {
56c4a895b7094461c98101924cf096680bfb7856f1San Mehat    if (mSocketName && mSock > -1)
57c4a895b7094461c98101924cf096680bfb7856f1San Mehat        close(mSock);
58c4a895b7094461c98101924cf096680bfb7856f1San Mehat
59c4a895b7094461c98101924cf096680bfb7856f1San Mehat    if (mCtrlPipe[0] != -1) {
60c4a895b7094461c98101924cf096680bfb7856f1San Mehat        close(mCtrlPipe[0]);
61c4a895b7094461c98101924cf096680bfb7856f1San Mehat        close(mCtrlPipe[1]);
62c4a895b7094461c98101924cf096680bfb7856f1San Mehat    }
63c4a895b7094461c98101924cf096680bfb7856f1San Mehat    SocketClientCollection::iterator it;
64100c0e2dab243da3a5351f1acbcdc560af10a405David 'Digit' Turner    for (it = mClients->begin(); it != mClients->end();) {
6513aa8ad44570bceef73115cea749b11f30888530Brad Fitzpatrick        (*it)->decRef();
66c4a895b7094461c98101924cf096680bfb7856f1San Mehat        it = mClients->erase(it);
67c4a895b7094461c98101924cf096680bfb7856f1San Mehat    }
68c4a895b7094461c98101924cf096680bfb7856f1San Mehat    delete mClients;
69c4a895b7094461c98101924cf096680bfb7856f1San Mehat}
70c4a895b7094461c98101924cf096680bfb7856f1San Mehat
71fa644ffe944c01a9b00f8d7676d58394fabee285San Mehatint SocketListener::startListener() {
72168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat
73168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat    if (!mSocketName && mSock == -1) {
747e8529a8b528fd30586aa037f15a31b29582c537San Mehat        SLOGE("Failed to start unbound listener");
75168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat        errno = EINVAL;
76168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat        return -1;
77168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat    } else if (mSocketName) {
78168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat        if ((mSock = android_get_control_socket(mSocketName)) < 0) {
797e8529a8b528fd30586aa037f15a31b29582c537San Mehat            SLOGE("Obtaining file descriptor socket '%s' failed: %s",
80168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat                 mSocketName, strerror(errno));
81168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat            return -1;
82168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat        }
838702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt        SLOGV("got mSock = %d for %s", mSock, mSocketName);
84168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat    }
85168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat
86fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    if (mListen && listen(mSock, 4) < 0) {
877e8529a8b528fd30586aa037f15a31b29582c537San Mehat        SLOGE("Unable to listen on socket (%s)", strerror(errno));
88fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat        return -1;
89df6c1b91e3813886070f35929583c30cfaead918San Mehat    } else if (!mListen)
908702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt        mClients->push_back(new SocketClient(mSock, false, mUseCmdNum));
91168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat
92c4a895b7094461c98101924cf096680bfb7856f1San Mehat    if (pipe(mCtrlPipe)) {
937e8529a8b528fd30586aa037f15a31b29582c537San Mehat        SLOGE("pipe failed (%s)", strerror(errno));
94fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat        return -1;
95c4a895b7094461c98101924cf096680bfb7856f1San Mehat    }
96fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat
97c4a895b7094461c98101924cf096680bfb7856f1San Mehat    if (pthread_create(&mThread, NULL, SocketListener::threadStart, this)) {
987e8529a8b528fd30586aa037f15a31b29582c537San Mehat        SLOGE("pthread_create (%s)", strerror(errno));
99fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat        return -1;
100c4a895b7094461c98101924cf096680bfb7856f1San Mehat    }
101fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat
102fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    return 0;
103fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat}
104fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat
105fa644ffe944c01a9b00f8d7676d58394fabee285San Mehatint SocketListener::stopListener() {
106fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    char c = 0;
107100c0e2dab243da3a5351f1acbcdc560af10a405David 'Digit' Turner    int  rc;
108fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat
109100c0e2dab243da3a5351f1acbcdc560af10a405David 'Digit' Turner    rc = TEMP_FAILURE_RETRY(write(mCtrlPipe[1], &c, 1));
110100c0e2dab243da3a5351f1acbcdc560af10a405David 'Digit' Turner    if (rc != 1) {
1117e8529a8b528fd30586aa037f15a31b29582c537San Mehat        SLOGE("Error writing to control pipe (%s)", strerror(errno));
112fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat        return -1;
113fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    }
114fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat
115fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    void *ret;
116fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    if (pthread_join(mThread, &ret)) {
1177e8529a8b528fd30586aa037f15a31b29582c537San Mehat        SLOGE("Error joining to listener thread (%s)", strerror(errno));
118fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat        return -1;
119fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    }
120dbdb0db516fa4935ff7b5c05914932099237d808San Mehat    close(mCtrlPipe[0]);
121dbdb0db516fa4935ff7b5c05914932099237d808San Mehat    close(mCtrlPipe[1]);
122c4a895b7094461c98101924cf096680bfb7856f1San Mehat    mCtrlPipe[0] = -1;
123c4a895b7094461c98101924cf096680bfb7856f1San Mehat    mCtrlPipe[1] = -1;
124c4a895b7094461c98101924cf096680bfb7856f1San Mehat
125c4a895b7094461c98101924cf096680bfb7856f1San Mehat    if (mSocketName && mSock > -1) {
126c4a895b7094461c98101924cf096680bfb7856f1San Mehat        close(mSock);
127c4a895b7094461c98101924cf096680bfb7856f1San Mehat        mSock = -1;
128c4a895b7094461c98101924cf096680bfb7856f1San Mehat    }
129c4a895b7094461c98101924cf096680bfb7856f1San Mehat
130c4a895b7094461c98101924cf096680bfb7856f1San Mehat    SocketClientCollection::iterator it;
131100c0e2dab243da3a5351f1acbcdc560af10a405David 'Digit' Turner    for (it = mClients->begin(); it != mClients->end();) {
132c4a895b7094461c98101924cf096680bfb7856f1San Mehat        delete (*it);
133c4a895b7094461c98101924cf096680bfb7856f1San Mehat        it = mClients->erase(it);
134c4a895b7094461c98101924cf096680bfb7856f1San Mehat    }
135fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    return 0;
136fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat}
137fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat
138fa644ffe944c01a9b00f8d7676d58394fabee285San Mehatvoid *SocketListener::threadStart(void *obj) {
139fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    SocketListener *me = reinterpret_cast<SocketListener *>(obj);
140fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat
141fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    me->runListener();
142fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    pthread_exit(NULL);
143fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    return NULL;
144fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat}
145fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat
146fa644ffe944c01a9b00f8d7676d58394fabee285San Mehatvoid SocketListener::runListener() {
147fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat
148100c0e2dab243da3a5351f1acbcdc560af10a405David 'Digit' Turner    SocketClientCollection *pendingList = new SocketClientCollection();
149100c0e2dab243da3a5351f1acbcdc560af10a405David 'Digit' Turner
150168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat    while(1) {
151fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat        SocketClientCollection::iterator it;
152168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat        fd_set read_fds;
153168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat        int rc = 0;
154100c0e2dab243da3a5351f1acbcdc560af10a405David 'Digit' Turner        int max = -1;
155fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat
156168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat        FD_ZERO(&read_fds);
157168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat
158fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat        if (mListen) {
159168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat            max = mSock;
160fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat            FD_SET(mSock, &read_fds);
161168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat        }
162168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat
163fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat        FD_SET(mCtrlPipe[0], &read_fds);
164fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat        if (mCtrlPipe[0] > max)
165fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat            max = mCtrlPipe[0];
166fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat
167fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat        pthread_mutex_lock(&mClientsLock);
168fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat        for (it = mClients->begin(); it != mClients->end(); ++it) {
169100c0e2dab243da3a5351f1acbcdc560af10a405David 'Digit' Turner            int fd = (*it)->getSocket();
170100c0e2dab243da3a5351f1acbcdc560af10a405David 'Digit' Turner            FD_SET(fd, &read_fds);
171100c0e2dab243da3a5351f1acbcdc560af10a405David 'Digit' Turner            if (fd > max)
172100c0e2dab243da3a5351f1acbcdc560af10a405David 'Digit' Turner                max = fd;
173fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat        }
174fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat        pthread_mutex_unlock(&mClientsLock);
1758702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt        SLOGV("mListen=%d, max=%d, mSocketName=%s", mListen, max, mSocketName);
176df6c1b91e3813886070f35929583c30cfaead918San Mehat        if ((rc = select(max + 1, &read_fds, NULL, NULL, NULL)) < 0) {
177100c0e2dab243da3a5351f1acbcdc560af10a405David 'Digit' Turner            if (errno == EINTR)
178100c0e2dab243da3a5351f1acbcdc560af10a405David 'Digit' Turner                continue;
1798702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt            SLOGE("select failed (%s) mListen=%d, max=%d", strerror(errno), mListen, max);
180fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat            sleep(1);
181168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat            continue;
182df6c1b91e3813886070f35929583c30cfaead918San Mehat        } else if (!rc)
183fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat            continue;
184fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat
185dbdb0db516fa4935ff7b5c05914932099237d808San Mehat        if (FD_ISSET(mCtrlPipe[0], &read_fds))
186fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat            break;
187fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat        if (mListen && FD_ISSET(mSock, &read_fds)) {
188fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat            struct sockaddr addr;
189100c0e2dab243da3a5351f1acbcdc560af10a405David 'Digit' Turner            socklen_t alen;
190fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat            int c;
191fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat
192100c0e2dab243da3a5351f1acbcdc560af10a405David 'Digit' Turner            do {
193100c0e2dab243da3a5351f1acbcdc560af10a405David 'Digit' Turner                alen = sizeof(addr);
194100c0e2dab243da3a5351f1acbcdc560af10a405David 'Digit' Turner                c = accept(mSock, &addr, &alen);
1958702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt                SLOGV("%s got %d from accept", mSocketName, c);
196100c0e2dab243da3a5351f1acbcdc560af10a405David 'Digit' Turner            } while (c < 0 && errno == EINTR);
197100c0e2dab243da3a5351f1acbcdc560af10a405David 'Digit' Turner            if (c < 0) {
1987e8529a8b528fd30586aa037f15a31b29582c537San Mehat                SLOGE("accept failed (%s)", strerror(errno));
199fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat                sleep(1);
200fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat                continue;
201168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat            }
202fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat            pthread_mutex_lock(&mClientsLock);
2038702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt            mClients->push_back(new SocketClient(c, true, mUseCmdNum));
204fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat            pthread_mutex_unlock(&mClientsLock);
205fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat        }
206fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat
207100c0e2dab243da3a5351f1acbcdc560af10a405David 'Digit' Turner        /* Add all active clients to the pending list first */
208100c0e2dab243da3a5351f1acbcdc560af10a405David 'Digit' Turner        pendingList->clear();
209100c0e2dab243da3a5351f1acbcdc560af10a405David 'Digit' Turner        pthread_mutex_lock(&mClientsLock);
210100c0e2dab243da3a5351f1acbcdc560af10a405David 'Digit' Turner        for (it = mClients->begin(); it != mClients->end(); ++it) {
211100c0e2dab243da3a5351f1acbcdc560af10a405David 'Digit' Turner            int fd = (*it)->getSocket();
212100c0e2dab243da3a5351f1acbcdc560af10a405David 'Digit' Turner            if (FD_ISSET(fd, &read_fds)) {
213100c0e2dab243da3a5351f1acbcdc560af10a405David 'Digit' Turner                pendingList->push_back(*it);
214100c0e2dab243da3a5351f1acbcdc560af10a405David 'Digit' Turner            }
215100c0e2dab243da3a5351f1acbcdc560af10a405David 'Digit' Turner        }
216100c0e2dab243da3a5351f1acbcdc560af10a405David 'Digit' Turner        pthread_mutex_unlock(&mClientsLock);
217100c0e2dab243da3a5351f1acbcdc560af10a405David 'Digit' Turner
218100c0e2dab243da3a5351f1acbcdc560af10a405David 'Digit' Turner        /* Process the pending list, since it is owned by the thread,
219100c0e2dab243da3a5351f1acbcdc560af10a405David 'Digit' Turner         * there is no need to lock it */
220100c0e2dab243da3a5351f1acbcdc560af10a405David 'Digit' Turner        while (!pendingList->empty()) {
221100c0e2dab243da3a5351f1acbcdc560af10a405David 'Digit' Turner            /* Pop the first item from the list */
222100c0e2dab243da3a5351f1acbcdc560af10a405David 'Digit' Turner            it = pendingList->begin();
223100c0e2dab243da3a5351f1acbcdc560af10a405David 'Digit' Turner            SocketClient* c = *it;
224100c0e2dab243da3a5351f1acbcdc560af10a405David 'Digit' Turner            pendingList->erase(it);
2258795007a4aedb0860f6e7b838984ba8104f2febcVernon Tang            /* Process it, if false is returned and our sockets are
2268795007a4aedb0860f6e7b838984ba8104f2febcVernon Tang             * connection-based, remove and destroy it */
2278795007a4aedb0860f6e7b838984ba8104f2febcVernon Tang            if (!onDataAvailable(c) && mListen) {
228100c0e2dab243da3a5351f1acbcdc560af10a405David 'Digit' Turner                /* Remove the client from our array */
2298702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt                SLOGV("going to zap %d for %s", c->getSocket(), mSocketName);
230100c0e2dab243da3a5351f1acbcdc560af10a405David 'Digit' Turner                pthread_mutex_lock(&mClientsLock);
231100c0e2dab243da3a5351f1acbcdc560af10a405David 'Digit' Turner                for (it = mClients->begin(); it != mClients->end(); ++it) {
232100c0e2dab243da3a5351f1acbcdc560af10a405David 'Digit' Turner                    if (*it == c) {
233100c0e2dab243da3a5351f1acbcdc560af10a405David 'Digit' Turner                        mClients->erase(it);
234100c0e2dab243da3a5351f1acbcdc560af10a405David 'Digit' Turner                        break;
235fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat                    }
236fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat                }
237100c0e2dab243da3a5351f1acbcdc560af10a405David 'Digit' Turner                pthread_mutex_unlock(&mClientsLock);
2384520246d3534c087f3e9253c34f99dd1e45b7bd7Xianzhu Wang                /* Remove our reference to the client */
2394520246d3534c087f3e9253c34f99dd1e45b7bd7Xianzhu Wang                c->decRef();
240168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat            }
241100c0e2dab243da3a5351f1acbcdc560af10a405David 'Digit' Turner        }
242168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat    }
243100c0e2dab243da3a5351f1acbcdc560af10a405David 'Digit' Turner    delete pendingList;
244168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat}
245168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat
246db017545796747115b8797f03e662b0f398a7c7bSan Mehatvoid SocketListener::sendBroadcast(int code, const char *msg, bool addErrno) {
247fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    pthread_mutex_lock(&mClientsLock);
248fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    SocketClientCollection::iterator i;
249fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat
250fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    for (i = mClients->begin(); i != mClients->end(); ++i) {
2518702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt        // broadcasts are unsolicited and should not include a cmd number
2528702bb17f40022e970e8acd40b348d074e39afc7Robert Greenwalt        if ((*i)->sendMsg(code, msg, addErrno, false)) {
253a8185a622e368d1957e18a3ee9d29d45eda12cfcGuang Zhu            SLOGW("Error sending broadcast (%s)", strerror(errno));
254a8185a622e368d1957e18a3ee9d29d45eda12cfcGuang Zhu        }
255a8185a622e368d1957e18a3ee9d29d45eda12cfcGuang Zhu    }
256a8185a622e368d1957e18a3ee9d29d45eda12cfcGuang Zhu    pthread_mutex_unlock(&mClientsLock);
257a8185a622e368d1957e18a3ee9d29d45eda12cfcGuang Zhu}
258