SocketListener.cpp revision df6c1b91e3813886070f35929583c30cfaead918
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 48int SocketListener::startListener() { 49 50 if (!mSocketName && mSock == -1) { 51 errno = EINVAL; 52 return -1; 53 } else if (mSocketName) { 54 if ((mSock = android_get_control_socket(mSocketName)) < 0) { 55 LOGE("Obtaining file descriptor socket '%s' failed: %s", 56 mSocketName, strerror(errno)); 57 return -1; 58 } 59 } 60 61 if (mListen && listen(mSock, 4) < 0) { 62 LOGE("Unable to listen on socket (%s)", strerror(errno)); 63 return -1; 64 } else if (!mListen) 65 mClients->push_back(new SocketClient(mSock)); 66 67 if (pipe(mCtrlPipe)) 68 return -1; 69 70 if (pthread_create(&mThread, NULL, SocketListener::threadStart, this)) 71 return -1; 72 73 return 0; 74} 75 76int SocketListener::stopListener() { 77 char c = 0; 78 79 if (write(mCtrlPipe[1], &c, 1) != 1) { 80 LOGE("Error writing to control pipe (%s)", strerror(errno)); 81 return -1; 82 } 83 84 void *ret; 85 if (pthread_join(mThread, &ret)) { 86 LOGE("Error joining to listener thread (%s)", strerror(errno)); 87 return -1; 88 } 89 close(mCtrlPipe[0]); 90 close(mCtrlPipe[1]); 91 return 0; 92} 93 94void *SocketListener::threadStart(void *obj) { 95 SocketListener *me = reinterpret_cast<SocketListener *>(obj); 96 97 me->runListener(); 98 pthread_exit(NULL); 99 return NULL; 100} 101 102void SocketListener::runListener() { 103 104 while(1) { 105 SocketClientCollection::iterator it; 106 fd_set read_fds; 107 int rc = 0; 108 int max = 0; 109 110 FD_ZERO(&read_fds); 111 112 if (mListen) { 113 max = mSock; 114 FD_SET(mSock, &read_fds); 115 } 116 117 FD_SET(mCtrlPipe[0], &read_fds); 118 if (mCtrlPipe[0] > max) 119 max = mCtrlPipe[0]; 120 121 pthread_mutex_lock(&mClientsLock); 122 for (it = mClients->begin(); it != mClients->end(); ++it) { 123 FD_SET((*it)->getSocket(), &read_fds); 124 if ((*it)->getSocket() > max) 125 max = (*it)->getSocket(); 126 } 127 pthread_mutex_unlock(&mClientsLock); 128 129 if ((rc = select(max + 1, &read_fds, NULL, NULL, NULL)) < 0) { 130 LOGE("select failed (%s)", strerror(errno)); 131 sleep(1); 132 continue; 133 } else if (!rc) 134 continue; 135 136 if (FD_ISSET(mCtrlPipe[0], &read_fds)) 137 break; 138 if (mListen && FD_ISSET(mSock, &read_fds)) { 139 struct sockaddr addr; 140 socklen_t alen = sizeof(addr); 141 int c; 142 143 if ((c = accept(mSock, &addr, &alen)) < 0) { 144 LOGE("accept failed (%s)", strerror(errno)); 145 sleep(1); 146 continue; 147 } 148 pthread_mutex_lock(&mClientsLock); 149 mClients->push_back(new SocketClient(c)); 150 pthread_mutex_unlock(&mClientsLock); 151 } 152 153 do { 154 pthread_mutex_lock(&mClientsLock); 155 for (it = mClients->begin(); it != mClients->end(); ++it) { 156 int fd = (*it)->getSocket(); 157 if (FD_ISSET(fd, &read_fds)) { 158 pthread_mutex_unlock(&mClientsLock); 159 if (!onDataAvailable(*it)) { 160 LOGD("SocketListener closing client socket"); 161 close(fd); 162 pthread_mutex_lock(&mClientsLock); 163 delete *it; 164 it = mClients->erase(it); 165 pthread_mutex_unlock(&mClientsLock); 166 } 167 FD_CLR(fd, &read_fds); 168 continue; 169 } 170 } 171 pthread_mutex_unlock(&mClientsLock); 172 } while (0); 173 } 174} 175 176void SocketListener::sendBroadcast(int code, char *msg, bool addErrno) { 177 pthread_mutex_lock(&mClientsLock); 178 SocketClientCollection::iterator i; 179 180 for (i = mClients->begin(); i != mClients->end(); ++i) { 181 if ((*i)->sendMsg(code, msg, addErrno)) { 182 LOGW("Error sending broadcast (%s)", strerror(errno)); 183 } 184 } 185 pthread_mutex_unlock(&mClientsLock); 186} 187 188void SocketListener::sendBroadcast(char *msg) { 189 pthread_mutex_lock(&mClientsLock); 190 SocketClientCollection::iterator i; 191 192 for (i = mClients->begin(); i != mClients->end(); ++i) { 193 if ((*i)->sendMsg(msg)) { 194 LOGW("Error sending broadcast (%s)", strerror(errno)); 195 } 196 } 197 pthread_mutex_unlock(&mClientsLock); 198} 199