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
48c4a895b7094461c98101924cf096680bfb7856f1San MehatSocketListener::~SocketListener() {
49c4a895b7094461c98101924cf096680bfb7856f1San Mehat    if (mSocketName && mSock > -1)
50c4a895b7094461c98101924cf096680bfb7856f1San Mehat        close(mSock);
51c4a895b7094461c98101924cf096680bfb7856f1San Mehat
52c4a895b7094461c98101924cf096680bfb7856f1San Mehat    if (mCtrlPipe[0] != -1) {
53c4a895b7094461c98101924cf096680bfb7856f1San Mehat        close(mCtrlPipe[0]);
54c4a895b7094461c98101924cf096680bfb7856f1San Mehat        close(mCtrlPipe[1]);
55c4a895b7094461c98101924cf096680bfb7856f1San Mehat    }
56c4a895b7094461c98101924cf096680bfb7856f1San Mehat    SocketClientCollection::iterator it;
57c4a895b7094461c98101924cf096680bfb7856f1San Mehat    for (it = mClients->begin(); it != mClients->end(); ++it) {
58c4a895b7094461c98101924cf096680bfb7856f1San Mehat        delete (*it);
59c4a895b7094461c98101924cf096680bfb7856f1San Mehat        it = mClients->erase(it);
60c4a895b7094461c98101924cf096680bfb7856f1San Mehat    }
61c4a895b7094461c98101924cf096680bfb7856f1San Mehat    delete mClients;
62c4a895b7094461c98101924cf096680bfb7856f1San Mehat}
63c4a895b7094461c98101924cf096680bfb7856f1San Mehat
64fa644ffe944c01a9b00f8d7676d58394fabee285San Mehatint SocketListener::startListener() {
65168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat
66168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat    if (!mSocketName && mSock == -1) {
677e8529a8b528fd30586aa037f15a31b29582c537San Mehat        SLOGE("Failed to start unbound listener");
68168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat        errno = EINVAL;
69168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat        return -1;
70168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat    } else if (mSocketName) {
71168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat        if ((mSock = android_get_control_socket(mSocketName)) < 0) {
727e8529a8b528fd30586aa037f15a31b29582c537San Mehat            SLOGE("Obtaining file descriptor socket '%s' failed: %s",
73168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat                 mSocketName, strerror(errno));
74168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat            return -1;
75168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat        }
76168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat    }
77168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat
78fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    if (mListen && listen(mSock, 4) < 0) {
797e8529a8b528fd30586aa037f15a31b29582c537San Mehat        SLOGE("Unable to listen on socket (%s)", strerror(errno));
80fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat        return -1;
81df6c1b91e3813886070f35929583c30cfaead918San Mehat    } else if (!mListen)
82fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat        mClients->push_back(new SocketClient(mSock));
83168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat
84c4a895b7094461c98101924cf096680bfb7856f1San Mehat    if (pipe(mCtrlPipe)) {
857e8529a8b528fd30586aa037f15a31b29582c537San Mehat        SLOGE("pipe failed (%s)", strerror(errno));
86fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat        return -1;
87c4a895b7094461c98101924cf096680bfb7856f1San Mehat    }
88fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat
89c4a895b7094461c98101924cf096680bfb7856f1San Mehat    if (pthread_create(&mThread, NULL, SocketListener::threadStart, this)) {
907e8529a8b528fd30586aa037f15a31b29582c537San Mehat        SLOGE("pthread_create (%s)", strerror(errno));
91fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat        return -1;
92c4a895b7094461c98101924cf096680bfb7856f1San Mehat    }
93fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat
94fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    return 0;
95fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat}
96fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat
97fa644ffe944c01a9b00f8d7676d58394fabee285San Mehatint SocketListener::stopListener() {
98fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    char c = 0;
99fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat
100fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    if (write(mCtrlPipe[1], &c, 1) != 1) {
1017e8529a8b528fd30586aa037f15a31b29582c537San Mehat        SLOGE("Error writing to control pipe (%s)", strerror(errno));
102fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat        return -1;
103fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    }
104fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat
105fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    void *ret;
106fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    if (pthread_join(mThread, &ret)) {
1077e8529a8b528fd30586aa037f15a31b29582c537San Mehat        SLOGE("Error joining to listener thread (%s)", strerror(errno));
108fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat        return -1;
109fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    }
110dbdb0db516fa4935ff7b5c05914932099237d808San Mehat    close(mCtrlPipe[0]);
111dbdb0db516fa4935ff7b5c05914932099237d808San Mehat    close(mCtrlPipe[1]);
112c4a895b7094461c98101924cf096680bfb7856f1San Mehat    mCtrlPipe[0] = -1;
113c4a895b7094461c98101924cf096680bfb7856f1San Mehat    mCtrlPipe[1] = -1;
114c4a895b7094461c98101924cf096680bfb7856f1San Mehat
115c4a895b7094461c98101924cf096680bfb7856f1San Mehat    if (mSocketName && mSock > -1) {
116c4a895b7094461c98101924cf096680bfb7856f1San Mehat        close(mSock);
117c4a895b7094461c98101924cf096680bfb7856f1San Mehat        mSock = -1;
118c4a895b7094461c98101924cf096680bfb7856f1San Mehat    }
119c4a895b7094461c98101924cf096680bfb7856f1San Mehat
120c4a895b7094461c98101924cf096680bfb7856f1San Mehat    SocketClientCollection::iterator it;
121c4a895b7094461c98101924cf096680bfb7856f1San Mehat    for (it = mClients->begin(); it != mClients->end(); ++it) {
122c4a895b7094461c98101924cf096680bfb7856f1San Mehat        delete (*it);
123c4a895b7094461c98101924cf096680bfb7856f1San Mehat        it = mClients->erase(it);
124c4a895b7094461c98101924cf096680bfb7856f1San Mehat    }
125fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    return 0;
126fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat}
127fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat
128fa644ffe944c01a9b00f8d7676d58394fabee285San Mehatvoid *SocketListener::threadStart(void *obj) {
129fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    SocketListener *me = reinterpret_cast<SocketListener *>(obj);
130fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat
131fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    me->runListener();
132fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    pthread_exit(NULL);
133fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    return NULL;
134fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat}
135fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat
136fa644ffe944c01a9b00f8d7676d58394fabee285San Mehatvoid SocketListener::runListener() {
137fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat
138168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat    while(1) {
139fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat        SocketClientCollection::iterator it;
140168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat        fd_set read_fds;
141168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat        int rc = 0;
142fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat        int max = 0;
143fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat
144168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat        FD_ZERO(&read_fds);
145168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat
146fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat        if (mListen) {
147168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat            max = mSock;
148fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat            FD_SET(mSock, &read_fds);
149168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat        }
150168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat
151fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat        FD_SET(mCtrlPipe[0], &read_fds);
152fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat        if (mCtrlPipe[0] > max)
153fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat            max = mCtrlPipe[0];
154fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat
155fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat        pthread_mutex_lock(&mClientsLock);
156fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat        for (it = mClients->begin(); it != mClients->end(); ++it) {
157fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat            FD_SET((*it)->getSocket(), &read_fds);
158fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat            if ((*it)->getSocket() > max)
159fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat                max = (*it)->getSocket();
160fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat        }
161fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat        pthread_mutex_unlock(&mClientsLock);
16203f0d27f6c49530a91402ed42f8ca4b2fda04b9fSan Mehat
163df6c1b91e3813886070f35929583c30cfaead918San Mehat        if ((rc = select(max + 1, &read_fds, NULL, NULL, NULL)) < 0) {
1647e8529a8b528fd30586aa037f15a31b29582c537San Mehat            SLOGE("select failed (%s)", strerror(errno));
165fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat            sleep(1);
166168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat            continue;
167df6c1b91e3813886070f35929583c30cfaead918San Mehat        } else if (!rc)
168fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat            continue;
169fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat
170dbdb0db516fa4935ff7b5c05914932099237d808San Mehat        if (FD_ISSET(mCtrlPipe[0], &read_fds))
171fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat            break;
172fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat        if (mListen && FD_ISSET(mSock, &read_fds)) {
173fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat            struct sockaddr addr;
174fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat            socklen_t alen = sizeof(addr);
175fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat            int c;
176fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat
177fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat            if ((c = accept(mSock, &addr, &alen)) < 0) {
1787e8529a8b528fd30586aa037f15a31b29582c537San Mehat                SLOGE("accept failed (%s)", strerror(errno));
179fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat                sleep(1);
180fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat                continue;
181168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat            }
182fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat            pthread_mutex_lock(&mClientsLock);
183fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat            mClients->push_back(new SocketClient(c));
184fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat            pthread_mutex_unlock(&mClientsLock);
185fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat        }
186fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat
187fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat        do {
188fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat            pthread_mutex_lock(&mClientsLock);
189fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat            for (it = mClients->begin(); it != mClients->end(); ++it) {
190fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat                int fd = (*it)->getSocket();
191fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat                if (FD_ISSET(fd, &read_fds)) {
192fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat                    pthread_mutex_unlock(&mClientsLock);
193fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat                    if (!onDataAvailable(*it)) {
194fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat                        close(fd);
195fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat                        pthread_mutex_lock(&mClientsLock);
196fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat                        delete *it;
197fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat                        it = mClients->erase(it);
198fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat                        pthread_mutex_unlock(&mClientsLock);
199fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat                    }
200fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat                    FD_CLR(fd, &read_fds);
201fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat                    continue;
202fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat                }
203168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat            }
204fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat            pthread_mutex_unlock(&mClientsLock);
205fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat        } while (0);
206168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat    }
207168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat}
208168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat
209db017545796747115b8797f03e662b0f398a7c7bSan Mehatvoid SocketListener::sendBroadcast(int code, const char *msg, bool addErrno) {
210fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    pthread_mutex_lock(&mClientsLock);
211fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    SocketClientCollection::iterator i;
212fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat
213fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    for (i = mClients->begin(); i != mClients->end(); ++i) {
214d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat        if ((*i)->sendMsg(code, msg, addErrno)) {
2157e8529a8b528fd30586aa037f15a31b29582c537San Mehat            SLOGW("Error sending broadcast (%s)", strerror(errno));
216fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat        }
217fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    }
218fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    pthread_mutex_unlock(&mClientsLock);
219fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat}
220fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat
221db017545796747115b8797f03e662b0f398a7c7bSan Mehatvoid SocketListener::sendBroadcast(const char *msg) {
222fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    pthread_mutex_lock(&mClientsLock);
223fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    SocketClientCollection::iterator i;
224fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat
225fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    for (i = mClients->begin(); i != mClients->end(); ++i) {
226d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat        if ((*i)->sendMsg(msg)) {
2277e8529a8b528fd30586aa037f15a31b29582c537San Mehat            SLOGW("Error sending broadcast (%s)", strerror(errno));
228fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat        }
229fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    }
230fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat    pthread_mutex_unlock(&mClientsLock);
231168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat}
232