1 /*
2 * Copyright (C) 2008 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 LOG_NDEBUG 0
33
SocketListener(const char * socketName,bool listen)34 SocketListener::SocketListener(const char *socketName, bool listen) {
35 init(socketName, -1, listen, false);
36 }
37
SocketListener(int socketFd,bool listen)38 SocketListener::SocketListener(int socketFd, bool listen) {
39 init(NULL, socketFd, listen, false);
40 }
41
SocketListener(const char * socketName,bool listen,bool useCmdNum)42 SocketListener::SocketListener(const char *socketName, bool listen, bool useCmdNum) {
43 init(socketName, -1, listen, useCmdNum);
44 }
45
init(const char * socketName,int socketFd,bool listen,bool useCmdNum)46 void SocketListener::init(const char *socketName, int socketFd, bool listen, bool useCmdNum) {
47 mListen = listen;
48 mSocketName = socketName;
49 mSock = socketFd;
50 mUseCmdNum = useCmdNum;
51 pthread_mutex_init(&mClientsLock, NULL);
52 mClients = new SocketClientCollection();
53 }
54
~SocketListener()55 SocketListener::~SocketListener() {
56 if (mSocketName && mSock > -1)
57 close(mSock);
58
59 if (mCtrlPipe[0] != -1) {
60 close(mCtrlPipe[0]);
61 close(mCtrlPipe[1]);
62 }
63 SocketClientCollection::iterator it;
64 for (it = mClients->begin(); it != mClients->end();) {
65 (*it)->decRef();
66 it = mClients->erase(it);
67 }
68 delete mClients;
69 }
70
startListener()71 int SocketListener::startListener() {
72
73 if (!mSocketName && mSock == -1) {
74 SLOGE("Failed to start unbound listener");
75 errno = EINVAL;
76 return -1;
77 } else if (mSocketName) {
78 if ((mSock = android_get_control_socket(mSocketName)) < 0) {
79 SLOGE("Obtaining file descriptor socket '%s' failed: %s",
80 mSocketName, strerror(errno));
81 return -1;
82 }
83 SLOGV("got mSock = %d for %s", mSock, mSocketName);
84 }
85
86 if (mListen && listen(mSock, 4) < 0) {
87 SLOGE("Unable to listen on socket (%s)", strerror(errno));
88 return -1;
89 } else if (!mListen)
90 mClients->push_back(new SocketClient(mSock, false, mUseCmdNum));
91
92 if (pipe(mCtrlPipe)) {
93 SLOGE("pipe failed (%s)", strerror(errno));
94 return -1;
95 }
96
97 if (pthread_create(&mThread, NULL, SocketListener::threadStart, this)) {
98 SLOGE("pthread_create (%s)", strerror(errno));
99 return -1;
100 }
101
102 return 0;
103 }
104
stopListener()105 int SocketListener::stopListener() {
106 char c = 0;
107 int rc;
108
109 rc = TEMP_FAILURE_RETRY(write(mCtrlPipe[1], &c, 1));
110 if (rc != 1) {
111 SLOGE("Error writing to control pipe (%s)", strerror(errno));
112 return -1;
113 }
114
115 void *ret;
116 if (pthread_join(mThread, &ret)) {
117 SLOGE("Error joining to listener thread (%s)", strerror(errno));
118 return -1;
119 }
120 close(mCtrlPipe[0]);
121 close(mCtrlPipe[1]);
122 mCtrlPipe[0] = -1;
123 mCtrlPipe[1] = -1;
124
125 if (mSocketName && mSock > -1) {
126 close(mSock);
127 mSock = -1;
128 }
129
130 SocketClientCollection::iterator it;
131 for (it = mClients->begin(); it != mClients->end();) {
132 delete (*it);
133 it = mClients->erase(it);
134 }
135 return 0;
136 }
137
threadStart(void * obj)138 void *SocketListener::threadStart(void *obj) {
139 SocketListener *me = reinterpret_cast<SocketListener *>(obj);
140
141 me->runListener();
142 pthread_exit(NULL);
143 return NULL;
144 }
145
runListener()146 void SocketListener::runListener() {
147
148 SocketClientCollection *pendingList = new SocketClientCollection();
149
150 while(1) {
151 SocketClientCollection::iterator it;
152 fd_set read_fds;
153 int rc = 0;
154 int max = -1;
155
156 FD_ZERO(&read_fds);
157
158 if (mListen) {
159 max = mSock;
160 FD_SET(mSock, &read_fds);
161 }
162
163 FD_SET(mCtrlPipe[0], &read_fds);
164 if (mCtrlPipe[0] > max)
165 max = mCtrlPipe[0];
166
167 pthread_mutex_lock(&mClientsLock);
168 for (it = mClients->begin(); it != mClients->end(); ++it) {
169 int fd = (*it)->getSocket();
170 FD_SET(fd, &read_fds);
171 if (fd > max)
172 max = fd;
173 }
174 pthread_mutex_unlock(&mClientsLock);
175 SLOGV("mListen=%d, max=%d, mSocketName=%s", mListen, max, mSocketName);
176 if ((rc = select(max + 1, &read_fds, NULL, NULL, NULL)) < 0) {
177 if (errno == EINTR)
178 continue;
179 SLOGE("select failed (%s) mListen=%d, max=%d", strerror(errno), mListen, max);
180 sleep(1);
181 continue;
182 } else if (!rc)
183 continue;
184
185 if (FD_ISSET(mCtrlPipe[0], &read_fds))
186 break;
187 if (mListen && FD_ISSET(mSock, &read_fds)) {
188 struct sockaddr addr;
189 socklen_t alen;
190 int c;
191
192 do {
193 alen = sizeof(addr);
194 c = accept(mSock, &addr, &alen);
195 SLOGV("%s got %d from accept", mSocketName, c);
196 } while (c < 0 && errno == EINTR);
197 if (c < 0) {
198 SLOGE("accept failed (%s)", strerror(errno));
199 sleep(1);
200 continue;
201 }
202 pthread_mutex_lock(&mClientsLock);
203 mClients->push_back(new SocketClient(c, true, mUseCmdNum));
204 pthread_mutex_unlock(&mClientsLock);
205 }
206
207 /* Add all active clients to the pending list first */
208 pendingList->clear();
209 pthread_mutex_lock(&mClientsLock);
210 for (it = mClients->begin(); it != mClients->end(); ++it) {
211 int fd = (*it)->getSocket();
212 if (FD_ISSET(fd, &read_fds)) {
213 pendingList->push_back(*it);
214 }
215 }
216 pthread_mutex_unlock(&mClientsLock);
217
218 /* Process the pending list, since it is owned by the thread,
219 * there is no need to lock it */
220 while (!pendingList->empty()) {
221 /* Pop the first item from the list */
222 it = pendingList->begin();
223 SocketClient* c = *it;
224 pendingList->erase(it);
225 /* Process it, if false is returned and our sockets are
226 * connection-based, remove and destroy it */
227 if (!onDataAvailable(c) && mListen) {
228 /* Remove the client from our array */
229 SLOGV("going to zap %d for %s", c->getSocket(), mSocketName);
230 pthread_mutex_lock(&mClientsLock);
231 for (it = mClients->begin(); it != mClients->end(); ++it) {
232 if (*it == c) {
233 mClients->erase(it);
234 break;
235 }
236 }
237 pthread_mutex_unlock(&mClientsLock);
238 /* Remove our reference to the client */
239 c->decRef();
240 }
241 }
242 }
243 delete pendingList;
244 }
245
sendBroadcast(int code,const char * msg,bool addErrno)246 void SocketListener::sendBroadcast(int code, const char *msg, bool addErrno) {
247 pthread_mutex_lock(&mClientsLock);
248 SocketClientCollection::iterator i;
249
250 for (i = mClients->begin(); i != mClients->end(); ++i) {
251 // broadcasts are unsolicited and should not include a cmd number
252 if ((*i)->sendMsg(code, msg, addErrno, false)) {
253 SLOGW("Error sending broadcast (%s)", strerror(errno));
254 }
255 }
256 pthread_mutex_unlock(&mClientsLock);
257 }
258