SocketListener.cpp revision df6c1b91e3813886070f35929583c30cfaead918
1168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat/* 2168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * Copyright (C) 2008 The Android Open Source Project 3168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * 4168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * Licensed under the Apache License, Version 2.0 (the "License"); 5168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * you may not use this file except in compliance with the License. 6168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * You may obtain a copy of the License at 7168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * 8168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * http://www.apache.org/licenses/LICENSE-2.0 9168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * 10168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * Unless required by applicable law or agreed to in writing, software 11168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * distributed under the License is distributed on an "AS IS" BASIS, 12168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * See the License for the specific language governing permissions and 14168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * limitations under the License. 15168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat */ 16168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat#include <stdio.h> 17168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat#include <errno.h> 18168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat#include <stdlib.h> 19168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat#include <sys/socket.h> 20168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat#include <sys/select.h> 21168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat#include <sys/time.h> 22168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat#include <sys/types.h> 23168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat#include <sys/un.h> 24168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 25168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat#define LOG_TAG "SocketListener" 26168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat#include <cutils/log.h> 27168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat#include <cutils/sockets.h> 28168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 29168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat#include <sysutils/SocketListener.h> 30fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat#include <sysutils/SocketClient.h> 31168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 32fa644ffe944c01a9b00f8d7676d58394fabee285San MehatSocketListener::SocketListener(const char *socketName, bool listen) { 33fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat mListen = listen; 34168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat mSocketName = socketName; 35168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat mSock = -1; 36fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat pthread_mutex_init(&mClientsLock, NULL); 37fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat mClients = new SocketClientCollection(); 38168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat} 39168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 40fa644ffe944c01a9b00f8d7676d58394fabee285San MehatSocketListener::SocketListener(int socketFd, bool listen) { 41fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat mListen = listen; 42168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat mSocketName = NULL; 43168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat mSock = socketFd; 44fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat pthread_mutex_init(&mClientsLock, NULL); 45fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat mClients = new SocketClientCollection(); 46168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat} 47168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 48fa644ffe944c01a9b00f8d7676d58394fabee285San Mehatint SocketListener::startListener() { 49168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 50168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat if (!mSocketName && mSock == -1) { 51168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat errno = EINVAL; 52168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat return -1; 53168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat } else if (mSocketName) { 54168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat if ((mSock = android_get_control_socket(mSocketName)) < 0) { 55168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat LOGE("Obtaining file descriptor socket '%s' failed: %s", 56168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat mSocketName, strerror(errno)); 57168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat return -1; 58168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat } 59168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat } 60168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 61fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat if (mListen && listen(mSock, 4) < 0) { 62fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat LOGE("Unable to listen on socket (%s)", strerror(errno)); 63fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat return -1; 64df6c1b91e3813886070f35929583c30cfaead918San Mehat } else if (!mListen) 65fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat mClients->push_back(new SocketClient(mSock)); 66168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 67fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat if (pipe(mCtrlPipe)) 68fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat return -1; 69fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat 70fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat if (pthread_create(&mThread, NULL, SocketListener::threadStart, this)) 71fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat return -1; 72fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat 73fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat return 0; 74fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat} 75fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat 76fa644ffe944c01a9b00f8d7676d58394fabee285San Mehatint SocketListener::stopListener() { 77fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat char c = 0; 78fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat 79fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat if (write(mCtrlPipe[1], &c, 1) != 1) { 80fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat LOGE("Error writing to control pipe (%s)", strerror(errno)); 81fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat return -1; 82fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat } 83fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat 84fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat void *ret; 85fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat if (pthread_join(mThread, &ret)) { 86fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat LOGE("Error joining to listener thread (%s)", strerror(errno)); 87fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat return -1; 88fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat } 89dbdb0db516fa4935ff7b5c05914932099237d808San Mehat close(mCtrlPipe[0]); 90dbdb0db516fa4935ff7b5c05914932099237d808San Mehat close(mCtrlPipe[1]); 91fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat return 0; 92fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat} 93fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat 94fa644ffe944c01a9b00f8d7676d58394fabee285San Mehatvoid *SocketListener::threadStart(void *obj) { 95fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat SocketListener *me = reinterpret_cast<SocketListener *>(obj); 96fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat 97fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat me->runListener(); 98fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat pthread_exit(NULL); 99fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat return NULL; 100fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat} 101fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat 102fa644ffe944c01a9b00f8d7676d58394fabee285San Mehatvoid SocketListener::runListener() { 103fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat 104168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat while(1) { 105fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat SocketClientCollection::iterator it; 106168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat fd_set read_fds; 107168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat int rc = 0; 108fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat int max = 0; 109fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat 110168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat FD_ZERO(&read_fds); 111168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 112fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat if (mListen) { 113168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat max = mSock; 114fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat FD_SET(mSock, &read_fds); 115168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat } 116168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 117fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat FD_SET(mCtrlPipe[0], &read_fds); 118fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat if (mCtrlPipe[0] > max) 119fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat max = mCtrlPipe[0]; 120fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat 121fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat pthread_mutex_lock(&mClientsLock); 122fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat for (it = mClients->begin(); it != mClients->end(); ++it) { 123fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat FD_SET((*it)->getSocket(), &read_fds); 124fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat if ((*it)->getSocket() > max) 125fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat max = (*it)->getSocket(); 126fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat } 127fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat pthread_mutex_unlock(&mClientsLock); 128fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat 129df6c1b91e3813886070f35929583c30cfaead918San Mehat if ((rc = select(max + 1, &read_fds, NULL, NULL, NULL)) < 0) { 130168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat LOGE("select failed (%s)", strerror(errno)); 131fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat sleep(1); 132168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat continue; 133df6c1b91e3813886070f35929583c30cfaead918San Mehat } else if (!rc) 134fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat continue; 135fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat 136dbdb0db516fa4935ff7b5c05914932099237d808San Mehat if (FD_ISSET(mCtrlPipe[0], &read_fds)) 137fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat break; 138fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat if (mListen && FD_ISSET(mSock, &read_fds)) { 139fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat struct sockaddr addr; 140fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat socklen_t alen = sizeof(addr); 141fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat int c; 142fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat 143fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat if ((c = accept(mSock, &addr, &alen)) < 0) { 144fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat LOGE("accept failed (%s)", strerror(errno)); 145fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat sleep(1); 146fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat continue; 147168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat } 148fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat pthread_mutex_lock(&mClientsLock); 149fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat mClients->push_back(new SocketClient(c)); 150fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat pthread_mutex_unlock(&mClientsLock); 151fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat } 152fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat 153fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat do { 154fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat pthread_mutex_lock(&mClientsLock); 155fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat for (it = mClients->begin(); it != mClients->end(); ++it) { 156fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat int fd = (*it)->getSocket(); 157fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat if (FD_ISSET(fd, &read_fds)) { 158fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat pthread_mutex_unlock(&mClientsLock); 159fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat if (!onDataAvailable(*it)) { 160fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat LOGD("SocketListener closing client socket"); 161fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat close(fd); 162fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat pthread_mutex_lock(&mClientsLock); 163fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat delete *it; 164fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat it = mClients->erase(it); 165fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat pthread_mutex_unlock(&mClientsLock); 166fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat } 167fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat FD_CLR(fd, &read_fds); 168fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat continue; 169fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat } 170168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat } 171fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat pthread_mutex_unlock(&mClientsLock); 172fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat } while (0); 173168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat } 174168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat} 175168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 176d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehatvoid SocketListener::sendBroadcast(int code, char *msg, bool addErrno) { 177fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat pthread_mutex_lock(&mClientsLock); 178fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat SocketClientCollection::iterator i; 179fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat 180fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat for (i = mClients->begin(); i != mClients->end(); ++i) { 181d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat if ((*i)->sendMsg(code, msg, addErrno)) { 182fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat LOGW("Error sending broadcast (%s)", strerror(errno)); 183fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat } 184fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat } 185fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat pthread_mutex_unlock(&mClientsLock); 186fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat} 187fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat 188d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehatvoid SocketListener::sendBroadcast(char *msg) { 189fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat pthread_mutex_lock(&mClientsLock); 190fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat SocketClientCollection::iterator i; 191fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat 192fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat for (i = mClients->begin(); i != mClients->end(); ++i) { 193d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat if ((*i)->sendMsg(msg)) { 194fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat LOGW("Error sending broadcast (%s)", strerror(errno)); 195fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat } 196fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat } 197fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat pthread_mutex_unlock(&mClientsLock); 198168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat} 199