SocketListener.cpp revision fa644ffe944c01a9b00f8d7676d58394fabee285
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; 64fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat } else if (!mListen) { 65fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat mClients->push_back(new SocketClient(mSock)); 66fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat LOGD("Created phantom client"); 67168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat } 68168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 69fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat if (pipe(mCtrlPipe)) 70fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat return -1; 71fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat 72fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat if (pthread_create(&mThread, NULL, SocketListener::threadStart, this)) 73fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat return -1; 74fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat 75fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat return 0; 76fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat} 77fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat 78fa644ffe944c01a9b00f8d7676d58394fabee285San Mehatint SocketListener::stopListener() { 79fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat char c = 0; 80fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat 81fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat if (write(mCtrlPipe[1], &c, 1) != 1) { 82fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat LOGE("Error writing to control pipe (%s)", strerror(errno)); 83fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat return -1; 84fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat } 85fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat 86fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat LOGD("Signaled listener thread - waiting for it to die"); 87fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat void *ret; 88fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat if (pthread_join(mThread, &ret)) { 89fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat LOGE("Error joining to listener thread (%s)", strerror(errno)); 90fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat return -1; 91fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat } 92fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat LOGD("Listener stopped"); 93fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat return 0; 94fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat} 95fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat 96fa644ffe944c01a9b00f8d7676d58394fabee285San Mehatvoid *SocketListener::threadStart(void *obj) { 97fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat SocketListener *me = reinterpret_cast<SocketListener *>(obj); 98fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat 99fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat me->runListener(); 100fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat LOGD("Listener thread shutting down"); 101fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat pthread_exit(NULL); 102fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat return NULL; 103fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat} 104fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat 105fa644ffe944c01a9b00f8d7676d58394fabee285San Mehatvoid SocketListener::runListener() { 106fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat 107168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat while(1) { 108fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat SocketClientCollection::iterator it; 109168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat fd_set read_fds; 110168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat struct timeval to; 111168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat int rc = 0; 112168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 113168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat to.tv_sec = 60 * 60; 114168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat to.tv_usec = 0; 115168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 116fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat int max = 0; 117fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat 118168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat FD_ZERO(&read_fds); 119168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 120fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat if (mListen) { 121168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat max = mSock; 122fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat FD_SET(mSock, &read_fds); 123168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat } 124168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 125fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat FD_SET(mCtrlPipe[0], &read_fds); 126fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat if (mCtrlPipe[0] > max) 127fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat max = mCtrlPipe[0]; 128fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat 129fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat pthread_mutex_lock(&mClientsLock); 130fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat for (it = mClients->begin(); it != mClients->end(); ++it) { 131fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat FD_SET((*it)->getSocket(), &read_fds); 132fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat if ((*it)->getSocket() > max) 133fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat max = (*it)->getSocket(); 134fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat } 135fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat pthread_mutex_unlock(&mClientsLock); 136fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat 137168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat if ((rc = select(max + 1, &read_fds, NULL, NULL, &to)) < 0) { 138168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat LOGE("select failed (%s)", strerror(errno)); 139fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat sleep(1); 140168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat continue; 141fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat } else if (!rc) { 142fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat LOGD("select timeout"); 143fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat continue; 144fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat } 145fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat 146fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat if (FD_ISSET(mCtrlPipe[0], &read_fds)) { 147fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat LOGD("Control message received"); 148fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat break; 149fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat } 150fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat if (mListen && FD_ISSET(mSock, &read_fds)) { 151fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat struct sockaddr addr; 152fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat socklen_t alen = sizeof(addr); 153fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat int c; 154fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat 155fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat if ((c = accept(mSock, &addr, &alen)) < 0) { 156fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat LOGE("accept failed (%s)", strerror(errno)); 157fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat sleep(1); 158fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat continue; 159168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat } 160fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat LOGD("SocketListener client connection accepted"); 161fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat pthread_mutex_lock(&mClientsLock); 162fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat mClients->push_back(new SocketClient(c)); 163fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat pthread_mutex_unlock(&mClientsLock); 164fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat } 165fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat 166fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat do { 167fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat pthread_mutex_lock(&mClientsLock); 168fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat for (it = mClients->begin(); it != mClients->end(); ++it) { 169fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat int fd = (*it)->getSocket(); 170fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat if (FD_ISSET(fd, &read_fds)) { 171fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat pthread_mutex_unlock(&mClientsLock); 172fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat if (!onDataAvailable(*it)) { 173fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat LOGD("SocketListener closing client socket"); 174fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat close(fd); 175fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat pthread_mutex_lock(&mClientsLock); 176fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat delete *it; 177fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat it = mClients->erase(it); 178fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat pthread_mutex_unlock(&mClientsLock); 179fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat } 180fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat FD_CLR(fd, &read_fds); 181fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat continue; 182fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat } 183168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat } 184fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat pthread_mutex_unlock(&mClientsLock); 185fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat } while (0); 186168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat } 187168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat} 188168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 189fa644ffe944c01a9b00f8d7676d58394fabee285San Mehatvoid SocketListener::sendBroadcast(char *msg) { 190fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat pthread_mutex_lock(&mClientsLock); 191fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat SocketClientCollection::iterator i; 192fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat 193fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat for (i = mClients->begin(); i != mClients->end(); ++i) { 194fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat if ((*i)->sendMsg(msg)) { 195fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat LOGW("Error sending broadcast (%s)", strerror(errno)); 196fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat } 197fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat } 198fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat pthread_mutex_unlock(&mClientsLock); 199fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat} 200fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat 201fa644ffe944c01a9b00f8d7676d58394fabee285San Mehatvoid SocketListener::sendBroadcast(char *msg, char *data) { 202fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat pthread_mutex_lock(&mClientsLock); 203fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat SocketClientCollection::iterator i; 204fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat 205fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat for (i = mClients->begin(); i != mClients->end(); ++i) { 206fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat if ((*i)->sendMsg(msg, data)) { 207fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat LOGW("Error sending broadcast (%s)", strerror(errno)); 208fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat } 209fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat } 210fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat pthread_mutex_unlock(&mClientsLock); 211168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat} 212fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat 213