blob: acc4a67df809f5b99741ca6d973c147b9a22b1ed [file] [log] [blame]
San Mehat168415b2009-05-06 11:14:21 -07001/*
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>
San Mehat168415b2009-05-06 11:14:21 -070027#include <cutils/sockets.h>
28
29#include <sysutils/SocketListener.h>
San Mehatfa644ff2009-05-08 11:15:53 -070030#include <sysutils/SocketClient.h>
San Mehat168415b2009-05-06 11:14:21 -070031
San Mehatfa644ff2009-05-08 11:15:53 -070032SocketListener::SocketListener(const char *socketName, bool listen) {
33 mListen = listen;
San Mehat168415b2009-05-06 11:14:21 -070034 mSocketName = socketName;
35 mSock = -1;
San Mehatfa644ff2009-05-08 11:15:53 -070036 pthread_mutex_init(&mClientsLock, NULL);
37 mClients = new SocketClientCollection();
San Mehat168415b2009-05-06 11:14:21 -070038}
39
San Mehatfa644ff2009-05-08 11:15:53 -070040SocketListener::SocketListener(int socketFd, bool listen) {
41 mListen = listen;
San Mehat168415b2009-05-06 11:14:21 -070042 mSocketName = NULL;
43 mSock = socketFd;
San Mehatfa644ff2009-05-08 11:15:53 -070044 pthread_mutex_init(&mClientsLock, NULL);
45 mClients = new SocketClientCollection();
San Mehat168415b2009-05-06 11:14:21 -070046}
47
San Mehatfa644ff2009-05-08 11:15:53 -070048int SocketListener::startListener() {
San Mehat168415b2009-05-06 11:14:21 -070049
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
San Mehatfa644ff2009-05-08 11:15:53 -070061 if (mListen && listen(mSock, 4) < 0) {
62 LOGE("Unable to listen on socket (%s)", strerror(errno));
63 return -1;
San Mehatdf6c1b92009-05-13 08:58:43 -070064 } else if (!mListen)
San Mehatfa644ff2009-05-08 11:15:53 -070065 mClients->push_back(new SocketClient(mSock));
San Mehat168415b2009-05-06 11:14:21 -070066
San Mehatfa644ff2009-05-08 11:15:53 -070067 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
San Mehatfa644ff2009-05-08 11:15:53 -070084 void *ret;
85 if (pthread_join(mThread, &ret)) {
86 LOGE("Error joining to listener thread (%s)", strerror(errno));
87 return -1;
88 }
San Mehatdbdb0db2009-05-12 15:50:26 -070089 close(mCtrlPipe[0]);
90 close(mCtrlPipe[1]);
San Mehatfa644ff2009-05-08 11:15:53 -070091 return 0;
92}
93
94void *SocketListener::threadStart(void *obj) {
95 SocketListener *me = reinterpret_cast<SocketListener *>(obj);
96
97 me->runListener();
San Mehatfa644ff2009-05-08 11:15:53 -070098 pthread_exit(NULL);
99 return NULL;
100}
101
102void SocketListener::runListener() {
103
San Mehat168415b2009-05-06 11:14:21 -0700104 while(1) {
San Mehatfa644ff2009-05-08 11:15:53 -0700105 SocketClientCollection::iterator it;
San Mehat168415b2009-05-06 11:14:21 -0700106 fd_set read_fds;
San Mehat168415b2009-05-06 11:14:21 -0700107 int rc = 0;
San Mehatfa644ff2009-05-08 11:15:53 -0700108 int max = 0;
109
San Mehat168415b2009-05-06 11:14:21 -0700110 FD_ZERO(&read_fds);
111
San Mehatfa644ff2009-05-08 11:15:53 -0700112 if (mListen) {
San Mehat168415b2009-05-06 11:14:21 -0700113 max = mSock;
San Mehatfa644ff2009-05-08 11:15:53 -0700114 FD_SET(mSock, &read_fds);
San Mehat168415b2009-05-06 11:14:21 -0700115 }
116
San Mehatfa644ff2009-05-08 11:15:53 -0700117 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
San Mehatdf6c1b92009-05-13 08:58:43 -0700129 if ((rc = select(max + 1, &read_fds, NULL, NULL, NULL)) < 0) {
San Mehat168415b2009-05-06 11:14:21 -0700130 LOGE("select failed (%s)", strerror(errno));
San Mehatfa644ff2009-05-08 11:15:53 -0700131 sleep(1);
San Mehat168415b2009-05-06 11:14:21 -0700132 continue;
San Mehatdf6c1b92009-05-13 08:58:43 -0700133 } else if (!rc)
San Mehatfa644ff2009-05-08 11:15:53 -0700134 continue;
San Mehat168415b2009-05-06 11:14:21 -0700135
San Mehatdbdb0db2009-05-12 15:50:26 -0700136 if (FD_ISSET(mCtrlPipe[0], &read_fds))
San Mehatfa644ff2009-05-08 11:15:53 -0700137 break;
San Mehatfa644ff2009-05-08 11:15:53 -0700138 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 }
San Mehatfa644ff2009-05-08 11:15:53 -0700148 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;
San Mehat168415b2009-05-06 11:14:21 -0700169 }
San Mehat168415b2009-05-06 11:14:21 -0700170 }
San Mehatfa644ff2009-05-08 11:15:53 -0700171 pthread_mutex_unlock(&mClientsLock);
172 } while (0);
San Mehat168415b2009-05-06 11:14:21 -0700173 }
San Mehat168415b2009-05-06 11:14:21 -0700174}
175
San Mehatd7680662009-05-12 11:16:59 -0700176void 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
San Mehatfa644ff2009-05-08 11:15:53 -0700188void 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);
San Mehat168415b2009-05-06 11:14:21 -0700198}