blob: 1b53867c3bf205425aa0084f3d3dff7ac8138b81 [file] [log] [blame]
San Mehat168415b2009-05-06 11:14:21 -07001/*
Mark Salyzyn23f04102012-01-24 20:30:10 -08002 * Copyright (C) 2008-2014 The Android Open Source Project
San Mehat168415b2009-05-06 11:14:21 -07003 *
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>
San Mehat168415b2009-05-06 11:14:21 -070027#include <cutils/sockets.h>
28
29#include <sysutils/SocketListener.h>
San Mehatfa644ff2009-05-08 11:15:53 -070030#include <sysutils/SocketClient.h>
San Mehat168415b2009-05-06 11:14:21 -070031
San Mehatfa644ff2009-05-08 11:15:53 -070032SocketListener::SocketListener(const char *socketName, bool listen) {
Robert Greenwalt8702bb12012-02-07 12:23:14 -080033 init(socketName, -1, listen, false);
San Mehat168415b2009-05-06 11:14:21 -070034}
35
San Mehatfa644ff2009-05-08 11:15:53 -070036SocketListener::SocketListener(int socketFd, bool listen) {
Robert Greenwalt8702bb12012-02-07 12:23:14 -080037 init(NULL, socketFd, listen, false);
38}
39
40SocketListener::SocketListener(const char *socketName, bool listen, bool useCmdNum) {
41 init(socketName, -1, listen, useCmdNum);
42}
43
44void SocketListener::init(const char *socketName, int socketFd, bool listen, bool useCmdNum) {
San Mehatfa644ff2009-05-08 11:15:53 -070045 mListen = listen;
Robert Greenwalt8702bb12012-02-07 12:23:14 -080046 mSocketName = socketName;
San Mehat168415b2009-05-06 11:14:21 -070047 mSock = socketFd;
Robert Greenwalt8702bb12012-02-07 12:23:14 -080048 mUseCmdNum = useCmdNum;
San Mehatfa644ff2009-05-08 11:15:53 -070049 pthread_mutex_init(&mClientsLock, NULL);
50 mClients = new SocketClientCollection();
San Mehat168415b2009-05-06 11:14:21 -070051}
52
San Mehatc4a895b2009-06-23 21:10:57 -070053SocketListener::~SocketListener() {
54 if (mSocketName && mSock > -1)
55 close(mSock);
56
57 if (mCtrlPipe[0] != -1) {
58 close(mCtrlPipe[0]);
59 close(mCtrlPipe[1]);
60 }
61 SocketClientCollection::iterator it;
David 'Digit' Turner100c0e22011-01-17 03:10:31 +010062 for (it = mClients->begin(); it != mClients->end();) {
Brad Fitzpatrick13aa8ad2011-03-17 15:41:20 -070063 (*it)->decRef();
San Mehatc4a895b2009-06-23 21:10:57 -070064 it = mClients->erase(it);
65 }
66 delete mClients;
67}
68
San Mehatfa644ff2009-05-08 11:15:53 -070069int SocketListener::startListener() {
San Mehat168415b2009-05-06 11:14:21 -070070
71 if (!mSocketName && mSock == -1) {
San Mehat7e8529a2010-03-25 09:31:42 -070072 SLOGE("Failed to start unbound listener");
San Mehat168415b2009-05-06 11:14:21 -070073 errno = EINVAL;
74 return -1;
75 } else if (mSocketName) {
76 if ((mSock = android_get_control_socket(mSocketName)) < 0) {
San Mehat7e8529a2010-03-25 09:31:42 -070077 SLOGE("Obtaining file descriptor socket '%s' failed: %s",
San Mehat168415b2009-05-06 11:14:21 -070078 mSocketName, strerror(errno));
79 return -1;
80 }
Robert Greenwalt8702bb12012-02-07 12:23:14 -080081 SLOGV("got mSock = %d for %s", mSock, mSocketName);
San Mehat168415b2009-05-06 11:14:21 -070082 }
83
San Mehatfa644ff2009-05-08 11:15:53 -070084 if (mListen && listen(mSock, 4) < 0) {
San Mehat7e8529a2010-03-25 09:31:42 -070085 SLOGE("Unable to listen on socket (%s)", strerror(errno));
San Mehatfa644ff2009-05-08 11:15:53 -070086 return -1;
San Mehatdf6c1b92009-05-13 08:58:43 -070087 } else if (!mListen)
Robert Greenwalt8702bb12012-02-07 12:23:14 -080088 mClients->push_back(new SocketClient(mSock, false, mUseCmdNum));
San Mehat168415b2009-05-06 11:14:21 -070089
San Mehatc4a895b2009-06-23 21:10:57 -070090 if (pipe(mCtrlPipe)) {
San Mehat7e8529a2010-03-25 09:31:42 -070091 SLOGE("pipe failed (%s)", strerror(errno));
San Mehatfa644ff2009-05-08 11:15:53 -070092 return -1;
San Mehatc4a895b2009-06-23 21:10:57 -070093 }
San Mehatfa644ff2009-05-08 11:15:53 -070094
San Mehatc4a895b2009-06-23 21:10:57 -070095 if (pthread_create(&mThread, NULL, SocketListener::threadStart, this)) {
San Mehat7e8529a2010-03-25 09:31:42 -070096 SLOGE("pthread_create (%s)", strerror(errno));
San Mehatfa644ff2009-05-08 11:15:53 -070097 return -1;
San Mehatc4a895b2009-06-23 21:10:57 -070098 }
San Mehatfa644ff2009-05-08 11:15:53 -070099
100 return 0;
101}
102
103int SocketListener::stopListener() {
104 char c = 0;
David 'Digit' Turner100c0e22011-01-17 03:10:31 +0100105 int rc;
San Mehatfa644ff2009-05-08 11:15:53 -0700106
David 'Digit' Turner100c0e22011-01-17 03:10:31 +0100107 rc = TEMP_FAILURE_RETRY(write(mCtrlPipe[1], &c, 1));
108 if (rc != 1) {
San Mehat7e8529a2010-03-25 09:31:42 -0700109 SLOGE("Error writing to control pipe (%s)", strerror(errno));
San Mehatfa644ff2009-05-08 11:15:53 -0700110 return -1;
111 }
112
San Mehatfa644ff2009-05-08 11:15:53 -0700113 void *ret;
114 if (pthread_join(mThread, &ret)) {
San Mehat7e8529a2010-03-25 09:31:42 -0700115 SLOGE("Error joining to listener thread (%s)", strerror(errno));
San Mehatfa644ff2009-05-08 11:15:53 -0700116 return -1;
117 }
San Mehatdbdb0db2009-05-12 15:50:26 -0700118 close(mCtrlPipe[0]);
119 close(mCtrlPipe[1]);
San Mehatc4a895b2009-06-23 21:10:57 -0700120 mCtrlPipe[0] = -1;
121 mCtrlPipe[1] = -1;
122
123 if (mSocketName && mSock > -1) {
124 close(mSock);
125 mSock = -1;
126 }
127
128 SocketClientCollection::iterator it;
David 'Digit' Turner100c0e22011-01-17 03:10:31 +0100129 for (it = mClients->begin(); it != mClients->end();) {
San Mehatc4a895b2009-06-23 21:10:57 -0700130 delete (*it);
131 it = mClients->erase(it);
132 }
San Mehatfa644ff2009-05-08 11:15:53 -0700133 return 0;
134}
135
136void *SocketListener::threadStart(void *obj) {
137 SocketListener *me = reinterpret_cast<SocketListener *>(obj);
138
139 me->runListener();
San Mehatfa644ff2009-05-08 11:15:53 -0700140 pthread_exit(NULL);
141 return NULL;
142}
143
144void SocketListener::runListener() {
145
David 'Digit' Turner100c0e22011-01-17 03:10:31 +0100146 SocketClientCollection *pendingList = new SocketClientCollection();
147
San Mehat168415b2009-05-06 11:14:21 -0700148 while(1) {
San Mehatfa644ff2009-05-08 11:15:53 -0700149 SocketClientCollection::iterator it;
San Mehat168415b2009-05-06 11:14:21 -0700150 fd_set read_fds;
San Mehat168415b2009-05-06 11:14:21 -0700151 int rc = 0;
David 'Digit' Turner100c0e22011-01-17 03:10:31 +0100152 int max = -1;
San Mehatfa644ff2009-05-08 11:15:53 -0700153
San Mehat168415b2009-05-06 11:14:21 -0700154 FD_ZERO(&read_fds);
155
San Mehatfa644ff2009-05-08 11:15:53 -0700156 if (mListen) {
San Mehat168415b2009-05-06 11:14:21 -0700157 max = mSock;
San Mehatfa644ff2009-05-08 11:15:53 -0700158 FD_SET(mSock, &read_fds);
San Mehat168415b2009-05-06 11:14:21 -0700159 }
160
San Mehatfa644ff2009-05-08 11:15:53 -0700161 FD_SET(mCtrlPipe[0], &read_fds);
162 if (mCtrlPipe[0] > max)
163 max = mCtrlPipe[0];
164
165 pthread_mutex_lock(&mClientsLock);
166 for (it = mClients->begin(); it != mClients->end(); ++it) {
Mark Salyzyn23f04102012-01-24 20:30:10 -0800167 // NB: calling out to an other object with mClientsLock held (safe)
David 'Digit' Turner100c0e22011-01-17 03:10:31 +0100168 int fd = (*it)->getSocket();
169 FD_SET(fd, &read_fds);
170 if (fd > max)
171 max = fd;
San Mehatfa644ff2009-05-08 11:15:53 -0700172 }
173 pthread_mutex_unlock(&mClientsLock);
Robert Greenwalt8702bb12012-02-07 12:23:14 -0800174 SLOGV("mListen=%d, max=%d, mSocketName=%s", mListen, max, mSocketName);
San Mehatdf6c1b92009-05-13 08:58:43 -0700175 if ((rc = select(max + 1, &read_fds, NULL, NULL, NULL)) < 0) {
David 'Digit' Turner100c0e22011-01-17 03:10:31 +0100176 if (errno == EINTR)
177 continue;
Robert Greenwalt8702bb12012-02-07 12:23:14 -0800178 SLOGE("select failed (%s) mListen=%d, max=%d", strerror(errno), mListen, max);
San Mehatfa644ff2009-05-08 11:15:53 -0700179 sleep(1);
San Mehat168415b2009-05-06 11:14:21 -0700180 continue;
San Mehatdf6c1b92009-05-13 08:58:43 -0700181 } else if (!rc)
San Mehatfa644ff2009-05-08 11:15:53 -0700182 continue;
San Mehat168415b2009-05-06 11:14:21 -0700183
San Mehatdbdb0db2009-05-12 15:50:26 -0700184 if (FD_ISSET(mCtrlPipe[0], &read_fds))
San Mehatfa644ff2009-05-08 11:15:53 -0700185 break;
San Mehatfa644ff2009-05-08 11:15:53 -0700186 if (mListen && FD_ISSET(mSock, &read_fds)) {
187 struct sockaddr addr;
David 'Digit' Turner100c0e22011-01-17 03:10:31 +0100188 socklen_t alen;
San Mehatfa644ff2009-05-08 11:15:53 -0700189 int c;
190
David 'Digit' Turner100c0e22011-01-17 03:10:31 +0100191 do {
192 alen = sizeof(addr);
193 c = accept(mSock, &addr, &alen);
Robert Greenwalt8702bb12012-02-07 12:23:14 -0800194 SLOGV("%s got %d from accept", mSocketName, c);
David 'Digit' Turner100c0e22011-01-17 03:10:31 +0100195 } while (c < 0 && errno == EINTR);
196 if (c < 0) {
San Mehat7e8529a2010-03-25 09:31:42 -0700197 SLOGE("accept failed (%s)", strerror(errno));
San Mehatfa644ff2009-05-08 11:15:53 -0700198 sleep(1);
199 continue;
200 }
San Mehatfa644ff2009-05-08 11:15:53 -0700201 pthread_mutex_lock(&mClientsLock);
Robert Greenwalt8702bb12012-02-07 12:23:14 -0800202 mClients->push_back(new SocketClient(c, true, mUseCmdNum));
San Mehatfa644ff2009-05-08 11:15:53 -0700203 pthread_mutex_unlock(&mClientsLock);
204 }
205
David 'Digit' Turner100c0e22011-01-17 03:10:31 +0100206 /* Add all active clients to the pending list first */
207 pendingList->clear();
208 pthread_mutex_lock(&mClientsLock);
209 for (it = mClients->begin(); it != mClients->end(); ++it) {
Mark Salyzyn23f04102012-01-24 20:30:10 -0800210 SocketClient* c = *it;
211 // NB: calling out to an other object with mClientsLock held (safe)
212 int fd = c->getSocket();
David 'Digit' Turner100c0e22011-01-17 03:10:31 +0100213 if (FD_ISSET(fd, &read_fds)) {
Mark Salyzyn23f04102012-01-24 20:30:10 -0800214 pendingList->push_back(c);
215 c->incRef();
San Mehat168415b2009-05-06 11:14:21 -0700216 }
David 'Digit' Turner100c0e22011-01-17 03:10:31 +0100217 }
218 pthread_mutex_unlock(&mClientsLock);
219
220 /* Process the pending list, since it is owned by the thread,
221 * there is no need to lock it */
222 while (!pendingList->empty()) {
223 /* Pop the first item from the list */
224 it = pendingList->begin();
225 SocketClient* c = *it;
226 pendingList->erase(it);
Vernon Tang87950072011-04-27 14:01:27 +1000227 /* Process it, if false is returned and our sockets are
228 * connection-based, remove and destroy it */
229 if (!onDataAvailable(c) && mListen) {
David 'Digit' Turner100c0e22011-01-17 03:10:31 +0100230 /* Remove the client from our array */
Robert Greenwalt8702bb12012-02-07 12:23:14 -0800231 SLOGV("going to zap %d for %s", c->getSocket(), mSocketName);
David 'Digit' Turner100c0e22011-01-17 03:10:31 +0100232 pthread_mutex_lock(&mClientsLock);
233 for (it = mClients->begin(); it != mClients->end(); ++it) {
234 if (*it == c) {
235 mClients->erase(it);
236 break;
237 }
238 }
239 pthread_mutex_unlock(&mClientsLock);
Xianzhu Wang45202462011-09-29 12:59:55 +0800240 /* Remove our reference to the client */
241 c->decRef();
David 'Digit' Turner100c0e22011-01-17 03:10:31 +0100242 }
Mark Salyzyn23f04102012-01-24 20:30:10 -0800243 c->decRef();
David 'Digit' Turner100c0e22011-01-17 03:10:31 +0100244 }
San Mehat168415b2009-05-06 11:14:21 -0700245 }
David 'Digit' Turner100c0e22011-01-17 03:10:31 +0100246 delete pendingList;
San Mehat168415b2009-05-06 11:14:21 -0700247}
248
San Mehatdb017542009-05-20 15:27:14 -0700249void SocketListener::sendBroadcast(int code, const char *msg, bool addErrno) {
Mark Salyzyn23f04102012-01-24 20:30:10 -0800250 SocketClientCollection safeList;
251
252 /* Add all active clients to the safe list first */
253 safeList.clear();
San Mehatd7680662009-05-12 11:16:59 -0700254 pthread_mutex_lock(&mClientsLock);
255 SocketClientCollection::iterator i;
256
257 for (i = mClients->begin(); i != mClients->end(); ++i) {
Mark Salyzyn23f04102012-01-24 20:30:10 -0800258 SocketClient* c = *i;
259 c->incRef();
260 safeList.push_back(c);
Guang Zhua8185a62012-02-07 19:13:28 -0800261 }
262 pthread_mutex_unlock(&mClientsLock);
Mark Salyzyn23f04102012-01-24 20:30:10 -0800263
264 while (!safeList.empty()) {
265 /* Pop the first item from the list */
266 i = safeList.begin();
267 SocketClient* c = *i;
268 safeList.erase(i);
269 // broadcasts are unsolicited and should not include a cmd number
270 if (c->sendMsg(code, msg, addErrno, false)) {
271 SLOGW("Error sending broadcast (%s)", strerror(errno));
272 }
273 c->decRef();
274 }
275}
276
277void SocketListener::runOnEachSocket(SocketClientCommand *command) {
278 SocketClientCollection safeList;
279
280 /* Add all active clients to the safe list first */
281 safeList.clear();
282 pthread_mutex_lock(&mClientsLock);
283 SocketClientCollection::iterator i;
284
285 for (i = mClients->begin(); i != mClients->end(); ++i) {
286 SocketClient* c = *i;
287 c->incRef();
288 safeList.push_back(c);
289 }
290 pthread_mutex_unlock(&mClientsLock);
291
292 while (!safeList.empty()) {
293 /* Pop the first item from the list */
294 i = safeList.begin();
295 SocketClient* c = *i;
296 safeList.erase(i);
297 command->runSocketCommand(c);
298 c->decRef();
299 }
Guang Zhua8185a62012-02-07 19:13:28 -0800300}