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