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 35 SocketListener::SocketListener(const char *socketName, bool listen) { 36 init(socketName, -1, listen, false); 37 } 38 39 SocketListener::SocketListener(int socketFd, bool listen) { 40 init(NULL, socketFd, listen, false); 41 } 42 43 SocketListener::SocketListener(const char *socketName, bool listen, bool useCmdNum) { 44 init(socketName, -1, listen, useCmdNum); 45 } 46 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 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 72 int SocketListener::startListener() { 73 return startListener(4); 74 } 75 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 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 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 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 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 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 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