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     }
90 
91     if (mListen && listen(mSock, backlog) < 0) {
92         SLOGE("Unable to listen on socket (%s)", strerror(errno));
93         return -1;
94     } else if (!mListen)
95         mClients->push_back(new SocketClient(mSock, false, mUseCmdNum));
96 
97     if (pipe(mCtrlPipe)) {
98         SLOGE("pipe failed (%s)", strerror(errno));
99         return -1;
100     }
101 
102     if (pthread_create(&mThread, NULL, SocketListener::threadStart, this)) {
103         SLOGE("pthread_create (%s)", strerror(errno));
104         return -1;
105     }
106 
107     return 0;
108 }
109 
stopListener()110 int SocketListener::stopListener() {
111     char c = CtrlPipe_Shutdown;
112     int  rc;
113 
114     rc = TEMP_FAILURE_RETRY(write(mCtrlPipe[1], &c, 1));
115     if (rc != 1) {
116         SLOGE("Error writing to control pipe (%s)", strerror(errno));
117         return -1;
118     }
119 
120     void *ret;
121     if (pthread_join(mThread, &ret)) {
122         SLOGE("Error joining to listener thread (%s)", strerror(errno));
123         return -1;
124     }
125     close(mCtrlPipe[0]);
126     close(mCtrlPipe[1]);
127     mCtrlPipe[0] = -1;
128     mCtrlPipe[1] = -1;
129 
130     if (mSocketName && mSock > -1) {
131         close(mSock);
132         mSock = -1;
133     }
134 
135     SocketClientCollection::iterator it;
136     for (it = mClients->begin(); it != mClients->end();) {
137         delete (*it);
138         it = mClients->erase(it);
139     }
140     return 0;
141 }
142 
threadStart(void * obj)143 void *SocketListener::threadStart(void *obj) {
144     SocketListener *me = reinterpret_cast<SocketListener *>(obj);
145 
146     me->runListener();
147     pthread_exit(NULL);
148     return NULL;
149 }
150 
runListener()151 void SocketListener::runListener() {
152 
153     SocketClientCollection pendingList;
154 
155     while(1) {
156         SocketClientCollection::iterator it;
157         fd_set read_fds;
158         int rc = 0;
159         int max = -1;
160 
161         FD_ZERO(&read_fds);
162 
163         if (mListen) {
164             max = mSock;
165             FD_SET(mSock, &read_fds);
166         }
167 
168         FD_SET(mCtrlPipe[0], &read_fds);
169         if (mCtrlPipe[0] > max)
170             max = mCtrlPipe[0];
171 
172         pthread_mutex_lock(&mClientsLock);
173         for (it = mClients->begin(); it != mClients->end(); ++it) {
174             // NB: calling out to an other object with mClientsLock held (safe)
175             int fd = (*it)->getSocket();
176             FD_SET(fd, &read_fds);
177             if (fd > max) {
178                 max = fd;
179             }
180         }
181         pthread_mutex_unlock(&mClientsLock);
182         SLOGV("mListen=%d, max=%d, mSocketName=%s", mListen, max, mSocketName);
183         if ((rc = select(max + 1, &read_fds, NULL, NULL, NULL)) < 0) {
184             if (errno == EINTR)
185                 continue;
186             SLOGE("select failed (%s) mListen=%d, max=%d", strerror(errno), mListen, max);
187             sleep(1);
188             continue;
189         } else if (!rc)
190             continue;
191 
192         if (FD_ISSET(mCtrlPipe[0], &read_fds)) {
193             char c = CtrlPipe_Shutdown;
194             TEMP_FAILURE_RETRY(read(mCtrlPipe[0], &c, 1));
195             if (c == CtrlPipe_Shutdown) {
196                 break;
197             }
198             continue;
199         }
200         if (mListen && FD_ISSET(mSock, &read_fds)) {
201             struct sockaddr addr;
202             socklen_t alen;
203             int c;
204 
205             do {
206                 alen = sizeof(addr);
207                 c = accept(mSock, &addr, &alen);
208                 SLOGV("%s got %d from accept", mSocketName, c);
209             } while (c < 0 && errno == EINTR);
210             if (c < 0) {
211                 SLOGE("accept failed (%s)", strerror(errno));
212                 sleep(1);
213                 continue;
214             }
215             pthread_mutex_lock(&mClientsLock);
216             mClients->push_back(new SocketClient(c, true, mUseCmdNum));
217             pthread_mutex_unlock(&mClientsLock);
218         }
219 
220         /* Add all active clients to the pending list first */
221         pendingList.clear();
222         pthread_mutex_lock(&mClientsLock);
223         for (it = mClients->begin(); it != mClients->end(); ++it) {
224             SocketClient* c = *it;
225             // NB: calling out to an other object with mClientsLock held (safe)
226             int fd = c->getSocket();
227             if (FD_ISSET(fd, &read_fds)) {
228                 pendingList.push_back(c);
229                 c->incRef();
230             }
231         }
232         pthread_mutex_unlock(&mClientsLock);
233 
234         /* Process the pending list, since it is owned by the thread,
235          * there is no need to lock it */
236         while (!pendingList.empty()) {
237             /* Pop the first item from the list */
238             it = pendingList.begin();
239             SocketClient* c = *it;
240             pendingList.erase(it);
241             /* Process it, if false is returned, remove from list */
242             if (!onDataAvailable(c)) {
243                 release(c, false);
244             }
245             c->decRef();
246         }
247     }
248 }
249 
release(SocketClient * c,bool wakeup)250 bool SocketListener::release(SocketClient* c, bool wakeup) {
251     bool ret = false;
252     /* if our sockets are connection-based, remove and destroy it */
253     if (mListen && c) {
254         /* Remove the client from our array */
255         SLOGV("going to zap %d for %s", c->getSocket(), mSocketName);
256         pthread_mutex_lock(&mClientsLock);
257         SocketClientCollection::iterator it;
258         for (it = mClients->begin(); it != mClients->end(); ++it) {
259             if (*it == c) {
260                 mClients->erase(it);
261                 ret = true;
262                 break;
263             }
264         }
265         pthread_mutex_unlock(&mClientsLock);
266         if (ret) {
267             ret = c->decRef();
268             if (wakeup) {
269                 char b = CtrlPipe_Wakeup;
270                 TEMP_FAILURE_RETRY(write(mCtrlPipe[1], &b, 1));
271             }
272         }
273     }
274     return ret;
275 }
276 
sendBroadcast(int code,const char * msg,bool addErrno)277 void SocketListener::sendBroadcast(int code, const char *msg, bool addErrno) {
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         // broadcasts are unsolicited and should not include a cmd number
298         if (c->sendMsg(code, msg, addErrno, false)) {
299             SLOGW("Error sending broadcast (%s)", strerror(errno));
300         }
301         c->decRef();
302     }
303 }
304 
runOnEachSocket(SocketClientCommand * command)305 void SocketListener::runOnEachSocket(SocketClientCommand *command) {
306     SocketClientCollection safeList;
307 
308     /* Add all active clients to the safe list first */
309     safeList.clear();
310     pthread_mutex_lock(&mClientsLock);
311     SocketClientCollection::iterator i;
312 
313     for (i = mClients->begin(); i != mClients->end(); ++i) {
314         SocketClient* c = *i;
315         c->incRef();
316         safeList.push_back(c);
317     }
318     pthread_mutex_unlock(&mClientsLock);
319 
320     while (!safeList.empty()) {
321         /* Pop the first item from the list */
322         i = safeList.begin();
323         SocketClient* c = *i;
324         safeList.erase(i);
325         command->runSocketCommand(c);
326         c->decRef();
327     }
328 }
329