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