1 /*
2 * Copyright (C) 2008-2014 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
17 #define LOG_TAG "SocketListener"
18
19 #include <errno.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <sys/select.h>
23 #include <sys/socket.h>
24 #include <sys/time.h>
25 #include <sys/types.h>
26 #include <sys/un.h>
27 #include <unistd.h>
28
29 #include <cutils/sockets.h>
30 #include <log/log.h>
31 #include <sysutils/SocketListener.h>
32 #include <sysutils/SocketClient.h>
33
34 #define CtrlPipe_Shutdown 0
35 #define CtrlPipe_Wakeup 1
36
SocketListener(const char * socketName,bool listen)37 SocketListener::SocketListener(const char *socketName, bool listen) {
38 init(socketName, -1, listen, false);
39 }
40
SocketListener(int socketFd,bool listen)41 SocketListener::SocketListener(int socketFd, bool listen) {
42 init(NULL, socketFd, listen, false);
43 }
44
SocketListener(const char * socketName,bool listen,bool useCmdNum)45 SocketListener::SocketListener(const char *socketName, bool listen, bool useCmdNum) {
46 init(socketName, -1, listen, useCmdNum);
47 }
48
init(const char * socketName,int socketFd,bool listen,bool useCmdNum)49 void SocketListener::init(const char *socketName, int socketFd, bool listen, bool useCmdNum) {
50 mListen = listen;
51 mSocketName = socketName;
52 mSock = socketFd;
53 mUseCmdNum = useCmdNum;
54 pthread_mutex_init(&mClientsLock, NULL);
55 mClients = new SocketClientCollection();
56 }
57
~SocketListener()58 SocketListener::~SocketListener() {
59 if (mSocketName && mSock > -1)
60 close(mSock);
61
62 if (mCtrlPipe[0] != -1) {
63 close(mCtrlPipe[0]);
64 close(mCtrlPipe[1]);
65 }
66 SocketClientCollection::iterator it;
67 for (it = mClients->begin(); it != mClients->end();) {
68 (*it)->decRef();
69 it = mClients->erase(it);
70 }
71 delete mClients;
72 }
73
startListener()74 int SocketListener::startListener() {
75 return startListener(4);
76 }
77
startListener(int backlog)78 int SocketListener::startListener(int backlog) {
79
80 if (!mSocketName && mSock == -1) {
81 SLOGE("Failed to start unbound listener");
82 errno = EINVAL;
83 return -1;
84 } else if (mSocketName) {
85 if ((mSock = android_get_control_socket(mSocketName)) < 0) {
86 SLOGE("Obtaining file descriptor socket '%s' failed: %s",
87 mSocketName, strerror(errno));
88 return -1;
89 }
90 SLOGV("got mSock = %d for %s", mSock, mSocketName);
91 fcntl(mSock, F_SETFD, FD_CLOEXEC);
92 }
93
94 if (mListen && listen(mSock, backlog) < 0) {
95 SLOGE("Unable to listen on socket (%s)", strerror(errno));
96 return -1;
97 } else if (!mListen)
98 mClients->push_back(new SocketClient(mSock, false, mUseCmdNum));
99
100 if (pipe(mCtrlPipe)) {
101 SLOGE("pipe failed (%s)", strerror(errno));
102 return -1;
103 }
104
105 if (pthread_create(&mThread, NULL, SocketListener::threadStart, this)) {
106 SLOGE("pthread_create (%s)", strerror(errno));
107 return -1;
108 }
109
110 return 0;
111 }
112
stopListener()113 int SocketListener::stopListener() {
114 char c = CtrlPipe_Shutdown;
115 int rc;
116
117 rc = TEMP_FAILURE_RETRY(write(mCtrlPipe[1], &c, 1));
118 if (rc != 1) {
119 SLOGE("Error writing to control pipe (%s)", strerror(errno));
120 return -1;
121 }
122
123 void *ret;
124 if (pthread_join(mThread, &ret)) {
125 SLOGE("Error joining to listener thread (%s)", strerror(errno));
126 return -1;
127 }
128 close(mCtrlPipe[0]);
129 close(mCtrlPipe[1]);
130 mCtrlPipe[0] = -1;
131 mCtrlPipe[1] = -1;
132
133 if (mSocketName && mSock > -1) {
134 close(mSock);
135 mSock = -1;
136 }
137
138 SocketClientCollection::iterator it;
139 for (it = mClients->begin(); it != mClients->end();) {
140 delete (*it);
141 it = mClients->erase(it);
142 }
143 return 0;
144 }
145
threadStart(void * obj)146 void *SocketListener::threadStart(void *obj) {
147 SocketListener *me = reinterpret_cast<SocketListener *>(obj);
148
149 me->runListener();
150 pthread_exit(NULL);
151 return NULL;
152 }
153
runListener()154 void SocketListener::runListener() {
155
156 SocketClientCollection pendingList;
157
158 while(1) {
159 SocketClientCollection::iterator it;
160 fd_set read_fds;
161 int rc = 0;
162 int max = -1;
163
164 FD_ZERO(&read_fds);
165
166 if (mListen) {
167 max = mSock;
168 FD_SET(mSock, &read_fds);
169 }
170
171 FD_SET(mCtrlPipe[0], &read_fds);
172 if (mCtrlPipe[0] > max)
173 max = mCtrlPipe[0];
174
175 pthread_mutex_lock(&mClientsLock);
176 for (it = mClients->begin(); it != mClients->end(); ++it) {
177 // NB: calling out to an other object with mClientsLock held (safe)
178 int fd = (*it)->getSocket();
179 FD_SET(fd, &read_fds);
180 if (fd > max) {
181 max = fd;
182 }
183 }
184 pthread_mutex_unlock(&mClientsLock);
185 SLOGV("mListen=%d, max=%d, mSocketName=%s", mListen, max, mSocketName);
186 if ((rc = select(max + 1, &read_fds, NULL, NULL, NULL)) < 0) {
187 if (errno == EINTR)
188 continue;
189 SLOGE("select failed (%s) mListen=%d, max=%d", strerror(errno), mListen, max);
190 sleep(1);
191 continue;
192 } else if (!rc)
193 continue;
194
195 if (FD_ISSET(mCtrlPipe[0], &read_fds)) {
196 char c = CtrlPipe_Shutdown;
197 TEMP_FAILURE_RETRY(read(mCtrlPipe[0], &c, 1));
198 if (c == CtrlPipe_Shutdown) {
199 break;
200 }
201 continue;
202 }
203 if (mListen && FD_ISSET(mSock, &read_fds)) {
204 int c = TEMP_FAILURE_RETRY(accept4(mSock, nullptr, nullptr, SOCK_CLOEXEC));
205 if (c < 0) {
206 SLOGE("accept failed (%s)", strerror(errno));
207 sleep(1);
208 continue;
209 }
210 pthread_mutex_lock(&mClientsLock);
211 mClients->push_back(new SocketClient(c, true, mUseCmdNum));
212 pthread_mutex_unlock(&mClientsLock);
213 }
214
215 /* Add all active clients to the pending list first */
216 pendingList.clear();
217 pthread_mutex_lock(&mClientsLock);
218 for (it = mClients->begin(); it != mClients->end(); ++it) {
219 SocketClient* c = *it;
220 // NB: calling out to an other object with mClientsLock held (safe)
221 int fd = c->getSocket();
222 if (FD_ISSET(fd, &read_fds)) {
223 pendingList.push_back(c);
224 c->incRef();
225 }
226 }
227 pthread_mutex_unlock(&mClientsLock);
228
229 /* Process the pending list, since it is owned by the thread,
230 * there is no need to lock it */
231 while (!pendingList.empty()) {
232 /* Pop the first item from the list */
233 it = pendingList.begin();
234 SocketClient* c = *it;
235 pendingList.erase(it);
236 /* Process it, if false is returned, remove from list */
237 if (!onDataAvailable(c)) {
238 release(c, false);
239 }
240 c->decRef();
241 }
242 }
243 }
244
release(SocketClient * c,bool wakeup)245 bool SocketListener::release(SocketClient* c, bool wakeup) {
246 bool ret = false;
247 /* if our sockets are connection-based, remove and destroy it */
248 if (mListen && c) {
249 /* Remove the client from our array */
250 SLOGV("going to zap %d for %s", c->getSocket(), mSocketName);
251 pthread_mutex_lock(&mClientsLock);
252 SocketClientCollection::iterator it;
253 for (it = mClients->begin(); it != mClients->end(); ++it) {
254 if (*it == c) {
255 mClients->erase(it);
256 ret = true;
257 break;
258 }
259 }
260 pthread_mutex_unlock(&mClientsLock);
261 if (ret) {
262 ret = c->decRef();
263 if (wakeup) {
264 char b = CtrlPipe_Wakeup;
265 TEMP_FAILURE_RETRY(write(mCtrlPipe[1], &b, 1));
266 }
267 }
268 }
269 return ret;
270 }
271
sendBroadcast(int code,const char * msg,bool addErrno)272 void SocketListener::sendBroadcast(int code, const char *msg, bool addErrno) {
273 SocketClientCollection safeList;
274
275 /* Add all active clients to the safe list first */
276 safeList.clear();
277 pthread_mutex_lock(&mClientsLock);
278 SocketClientCollection::iterator i;
279
280 for (i = mClients->begin(); i != mClients->end(); ++i) {
281 SocketClient* c = *i;
282 c->incRef();
283 safeList.push_back(c);
284 }
285 pthread_mutex_unlock(&mClientsLock);
286
287 while (!safeList.empty()) {
288 /* Pop the first item from the list */
289 i = safeList.begin();
290 SocketClient* c = *i;
291 safeList.erase(i);
292 // broadcasts are unsolicited and should not include a cmd number
293 if (c->sendMsg(code, msg, addErrno, false)) {
294 SLOGW("Error sending broadcast (%s)", strerror(errno));
295 }
296 c->decRef();
297 }
298 }
299
runOnEachSocket(SocketClientCommand * command)300 void SocketListener::runOnEachSocket(SocketClientCommand *command) {
301 SocketClientCollection safeList;
302
303 /* Add all active clients to the safe list first */
304 safeList.clear();
305 pthread_mutex_lock(&mClientsLock);
306 SocketClientCollection::iterator i;
307
308 for (i = mClients->begin(); i != mClients->end(); ++i) {
309 SocketClient* c = *i;
310 c->incRef();
311 safeList.push_back(c);
312 }
313 pthread_mutex_unlock(&mClientsLock);
314
315 while (!safeList.empty()) {
316 /* Pop the first item from the list */
317 i = safeList.begin();
318 SocketClient* c = *i;
319 safeList.erase(i);
320 command->runSocketCommand(c);
321 c->decRef();
322 }
323 }
324