blob: 72e128dbb0004bc626d3681d07ef53e93c8e2f26 [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 Mehatc4a895b2009-06-23 21:10:57 -070048SocketListener::~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(); ++it) {
58 delete (*it);
59 it = mClients->erase(it);
60 }
61 delete mClients;
62}
63
San Mehatfa644ff2009-05-08 11:15:53 -070064int SocketListener::startListener() {
San Mehat168415b2009-05-06 11:14:21 -070065
66 if (!mSocketName && mSock == -1) {
San Mehatc4a895b2009-06-23 21:10:57 -070067 LOGE("Failed to start unbound listener");
San Mehat168415b2009-05-06 11:14:21 -070068 errno = EINVAL;
69 return -1;
70 } else if (mSocketName) {
71 if ((mSock = android_get_control_socket(mSocketName)) < 0) {
72 LOGE("Obtaining file descriptor socket '%s' failed: %s",
73 mSocketName, strerror(errno));
74 return -1;
75 }
76 }
77
San Mehatfa644ff2009-05-08 11:15:53 -070078 if (mListen && listen(mSock, 4) < 0) {
79 LOGE("Unable to listen on socket (%s)", strerror(errno));
80 return -1;
San Mehatdf6c1b92009-05-13 08:58:43 -070081 } else if (!mListen)
San Mehatfa644ff2009-05-08 11:15:53 -070082 mClients->push_back(new SocketClient(mSock));
San Mehat168415b2009-05-06 11:14:21 -070083
San Mehatc4a895b2009-06-23 21:10:57 -070084 if (pipe(mCtrlPipe)) {
85 LOGE("pipe failed (%s)", strerror(errno));
San Mehatfa644ff2009-05-08 11:15:53 -070086 return -1;
San Mehatc4a895b2009-06-23 21:10:57 -070087 }
San Mehatfa644ff2009-05-08 11:15:53 -070088
San Mehatc4a895b2009-06-23 21:10:57 -070089 if (pthread_create(&mThread, NULL, SocketListener::threadStart, this)) {
90 LOGE("pthread_create (%s)", strerror(errno));
San Mehatfa644ff2009-05-08 11:15:53 -070091 return -1;
San Mehatc4a895b2009-06-23 21:10:57 -070092 }
San Mehatfa644ff2009-05-08 11:15:53 -070093
94 return 0;
95}
96
97int SocketListener::stopListener() {
98 char c = 0;
99
100 if (write(mCtrlPipe[1], &c, 1) != 1) {
101 LOGE("Error writing to control pipe (%s)", strerror(errno));
102 return -1;
103 }
104
San Mehatfa644ff2009-05-08 11:15:53 -0700105 void *ret;
106 if (pthread_join(mThread, &ret)) {
107 LOGE("Error joining to listener thread (%s)", strerror(errno));
108 return -1;
109 }
San Mehatdbdb0db2009-05-12 15:50:26 -0700110 close(mCtrlPipe[0]);
111 close(mCtrlPipe[1]);
San Mehatc4a895b2009-06-23 21:10:57 -0700112 mCtrlPipe[0] = -1;
113 mCtrlPipe[1] = -1;
114
115 if (mSocketName && mSock > -1) {
116 close(mSock);
117 mSock = -1;
118 }
119
120 SocketClientCollection::iterator it;
121 for (it = mClients->begin(); it != mClients->end(); ++it) {
122 delete (*it);
123 it = mClients->erase(it);
124 }
San Mehatfa644ff2009-05-08 11:15:53 -0700125 return 0;
126}
127
128void *SocketListener::threadStart(void *obj) {
129 SocketListener *me = reinterpret_cast<SocketListener *>(obj);
130
131 me->runListener();
San Mehatfa644ff2009-05-08 11:15:53 -0700132 pthread_exit(NULL);
133 return NULL;
134}
135
136void SocketListener::runListener() {
137
San Mehat168415b2009-05-06 11:14:21 -0700138 while(1) {
San Mehatfa644ff2009-05-08 11:15:53 -0700139 SocketClientCollection::iterator it;
San Mehat168415b2009-05-06 11:14:21 -0700140 fd_set read_fds;
San Mehat168415b2009-05-06 11:14:21 -0700141 int rc = 0;
San Mehatfa644ff2009-05-08 11:15:53 -0700142 int max = 0;
143
San Mehat168415b2009-05-06 11:14:21 -0700144 FD_ZERO(&read_fds);
145
San Mehatfa644ff2009-05-08 11:15:53 -0700146 if (mListen) {
San Mehat168415b2009-05-06 11:14:21 -0700147 max = mSock;
San Mehatfa644ff2009-05-08 11:15:53 -0700148 FD_SET(mSock, &read_fds);
San Mehat168415b2009-05-06 11:14:21 -0700149 }
150
San Mehatfa644ff2009-05-08 11:15:53 -0700151 FD_SET(mCtrlPipe[0], &read_fds);
152 if (mCtrlPipe[0] > max)
153 max = mCtrlPipe[0];
154
155 pthread_mutex_lock(&mClientsLock);
156 for (it = mClients->begin(); it != mClients->end(); ++it) {
157 FD_SET((*it)->getSocket(), &read_fds);
158 if ((*it)->getSocket() > max)
159 max = (*it)->getSocket();
160 }
161 pthread_mutex_unlock(&mClientsLock);
San Mehat03f0d272009-05-26 15:18:25 -0700162
San Mehatdf6c1b92009-05-13 08:58:43 -0700163 if ((rc = select(max + 1, &read_fds, NULL, NULL, NULL)) < 0) {
San Mehat168415b2009-05-06 11:14:21 -0700164 LOGE("select failed (%s)", strerror(errno));
San Mehatfa644ff2009-05-08 11:15:53 -0700165 sleep(1);
San Mehat168415b2009-05-06 11:14:21 -0700166 continue;
San Mehatdf6c1b92009-05-13 08:58:43 -0700167 } else if (!rc)
San Mehatfa644ff2009-05-08 11:15:53 -0700168 continue;
San Mehat168415b2009-05-06 11:14:21 -0700169
San Mehatdbdb0db2009-05-12 15:50:26 -0700170 if (FD_ISSET(mCtrlPipe[0], &read_fds))
San Mehatfa644ff2009-05-08 11:15:53 -0700171 break;
San Mehatfa644ff2009-05-08 11:15:53 -0700172 if (mListen && FD_ISSET(mSock, &read_fds)) {
173 struct sockaddr addr;
174 socklen_t alen = sizeof(addr);
175 int c;
176
177 if ((c = accept(mSock, &addr, &alen)) < 0) {
178 LOGE("accept failed (%s)", strerror(errno));
179 sleep(1);
180 continue;
181 }
San Mehatfa644ff2009-05-08 11:15:53 -0700182 pthread_mutex_lock(&mClientsLock);
183 mClients->push_back(new SocketClient(c));
184 pthread_mutex_unlock(&mClientsLock);
185 }
186
187 do {
188 pthread_mutex_lock(&mClientsLock);
189 for (it = mClients->begin(); it != mClients->end(); ++it) {
190 int fd = (*it)->getSocket();
191 if (FD_ISSET(fd, &read_fds)) {
192 pthread_mutex_unlock(&mClientsLock);
193 if (!onDataAvailable(*it)) {
San Mehatfa644ff2009-05-08 11:15:53 -0700194 close(fd);
195 pthread_mutex_lock(&mClientsLock);
196 delete *it;
197 it = mClients->erase(it);
198 pthread_mutex_unlock(&mClientsLock);
199 }
200 FD_CLR(fd, &read_fds);
201 continue;
San Mehat168415b2009-05-06 11:14:21 -0700202 }
San Mehat168415b2009-05-06 11:14:21 -0700203 }
San Mehatfa644ff2009-05-08 11:15:53 -0700204 pthread_mutex_unlock(&mClientsLock);
205 } while (0);
San Mehat168415b2009-05-06 11:14:21 -0700206 }
San Mehat168415b2009-05-06 11:14:21 -0700207}
208
San Mehatdb017542009-05-20 15:27:14 -0700209void SocketListener::sendBroadcast(int code, const char *msg, bool addErrno) {
San Mehatd7680662009-05-12 11:16:59 -0700210 pthread_mutex_lock(&mClientsLock);
211 SocketClientCollection::iterator i;
212
213 for (i = mClients->begin(); i != mClients->end(); ++i) {
214 if ((*i)->sendMsg(code, msg, addErrno)) {
215 LOGW("Error sending broadcast (%s)", strerror(errno));
216 }
217 }
218 pthread_mutex_unlock(&mClientsLock);
219}
220
San Mehatdb017542009-05-20 15:27:14 -0700221void SocketListener::sendBroadcast(const char *msg) {
San Mehatfa644ff2009-05-08 11:15:53 -0700222 pthread_mutex_lock(&mClientsLock);
223 SocketClientCollection::iterator i;
224
225 for (i = mClients->begin(); i != mClients->end(); ++i) {
226 if ((*i)->sendMsg(msg)) {
227 LOGW("Error sending broadcast (%s)", strerror(errno));
228 }
229 }
230 pthread_mutex_unlock(&mClientsLock);
San Mehat168415b2009-05-06 11:14:21 -0700231}