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             struct sockaddr addr;
203             socklen_t alen;
204             int c;
205 
206             do {
207                 alen = sizeof(addr);
208                 c = accept(mSock, &addr, &alen);
209                 SLOGV("%s got %d from accept", mSocketName, c);
210             } while (c < 0 && errno == EINTR);
211             if (c < 0) {
212                 SLOGE("accept failed (%s)", strerror(errno));
213                 sleep(1);
214                 continue;
215             }
216             fcntl(c, F_SETFD, FD_CLOEXEC);
217             pthread_mutex_lock(&mClientsLock);
218             mClients->push_back(new SocketClient(c, true, mUseCmdNum));
219             pthread_mutex_unlock(&mClientsLock);
220         }
221 
222         /* Add all active clients to the pending list first */
223         pendingList.clear();
224         pthread_mutex_lock(&mClientsLock);
225         for (it = mClients->begin(); it != mClients->end(); ++it) {
226             SocketClient* c = *it;
227             // NB: calling out to an other object with mClientsLock held (safe)
228             int fd = c->getSocket();
229             if (FD_ISSET(fd, &read_fds)) {
230                 pendingList.push_back(c);
231                 c->incRef();
232             }
233         }
234         pthread_mutex_unlock(&mClientsLock);
235 
236         /* Process the pending list, since it is owned by the thread,
237          * there is no need to lock it */
238         while (!pendingList.empty()) {
239             /* Pop the first item from the list */
240             it = pendingList.begin();
241             SocketClient* c = *it;
242             pendingList.erase(it);
243             /* Process it, if false is returned, remove from list */
244             if (!onDataAvailable(c)) {
245                 release(c, false);
246             }
247             c->decRef();
248         }
249     }
250 }
251 
release(SocketClient * c,bool wakeup)252 bool SocketListener::release(SocketClient* c, bool wakeup) {
253     bool ret = false;
254     /* if our sockets are connection-based, remove and destroy it */
255     if (mListen && c) {
256         /* Remove the client from our array */
257         SLOGV("going to zap %d for %s", c->getSocket(), mSocketName);
258         pthread_mutex_lock(&mClientsLock);
259         SocketClientCollection::iterator it;
260         for (it = mClients->begin(); it != mClients->end(); ++it) {
261             if (*it == c) {
262                 mClients->erase(it);
263                 ret = true;
264                 break;
265             }
266         }
267         pthread_mutex_unlock(&mClientsLock);
268         if (ret) {
269             ret = c->decRef();
270             if (wakeup) {
271                 char b = CtrlPipe_Wakeup;
272                 TEMP_FAILURE_RETRY(write(mCtrlPipe[1], &b, 1));
273             }
274         }
275     }
276     return ret;
277 }
278 
sendBroadcast(int code,const char * msg,bool addErrno)279 void SocketListener::sendBroadcast(int code, const char *msg, bool addErrno) {
280     SocketClientCollection safeList;
281 
282     /* Add all active clients to the safe list first */
283     safeList.clear();
284     pthread_mutex_lock(&mClientsLock);
285     SocketClientCollection::iterator i;
286 
287     for (i = mClients->begin(); i != mClients->end(); ++i) {
288         SocketClient* c = *i;
289         c->incRef();
290         safeList.push_back(c);
291     }
292     pthread_mutex_unlock(&mClientsLock);
293 
294     while (!safeList.empty()) {
295         /* Pop the first item from the list */
296         i = safeList.begin();
297         SocketClient* c = *i;
298         safeList.erase(i);
299         // broadcasts are unsolicited and should not include a cmd number
300         if (c->sendMsg(code, msg, addErrno, false)) {
301             SLOGW("Error sending broadcast (%s)", strerror(errno));
302         }
303         c->decRef();
304     }
305 }
306 
runOnEachSocket(SocketClientCommand * command)307 void SocketListener::runOnEachSocket(SocketClientCommand *command) {
308     SocketClientCollection safeList;
309 
310     /* Add all active clients to the safe list first */
311     safeList.clear();
312     pthread_mutex_lock(&mClientsLock);
313     SocketClientCollection::iterator i;
314 
315     for (i = mClients->begin(); i != mClients->end(); ++i) {
316         SocketClient* c = *i;
317         c->incRef();
318         safeList.push_back(c);
319     }
320     pthread_mutex_unlock(&mClientsLock);
321 
322     while (!safeList.empty()) {
323         /* Pop the first item from the list */
324         i = safeList.begin();
325         SocketClient* c = *i;
326         safeList.erase(i);
327         command->runSocketCommand(c);
328         c->decRef();
329     }
330 }
331