SocketListener.cpp revision 581edc1b6c3799238cfb674dfddb97db44f2818e
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 35SocketListener::SocketListener(const char *socketName, bool listen) { 36 init(socketName, -1, listen, false); 37} 38 39SocketListener::SocketListener(int socketFd, bool listen) { 40 init(NULL, socketFd, listen, false); 41} 42 43SocketListener::SocketListener(const char *socketName, bool listen, bool useCmdNum) { 44 init(socketName, -1, listen, useCmdNum); 45} 46 47void 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 56SocketListener::~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 72int SocketListener::startListener() { 73 return startListener(4); 74} 75 76int 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 110int 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 143void *SocketListener::threadStart(void *obj) { 144 SocketListener *me = reinterpret_cast<SocketListener *>(obj); 145 146 me->runListener(); 147 pthread_exit(NULL); 148 return NULL; 149} 150 151void 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 250bool 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 277void 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 305void 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