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