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 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 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 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 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