SocketListener.cpp revision 168415b822cae1f8b54ef09c41c11a9b97b87f40
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
28168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat#include <cutils/sockets.h>
29168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat
30168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat#include <sysutils/SocketListener.h>
31168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat
32168415b822cae1f8b54ef09c41c11a9b97b87f40San MehatSocketListener::SocketListener(const char *socketName, bool acceptClients) {
33168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat    mAcceptClients = acceptClients;
34168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat    mCsock = -1;
35168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat    mSocketName = socketName;
36168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat    mSock = -1;
37168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat}
38168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat
39168415b822cae1f8b54ef09c41c11a9b97b87f40San MehatSocketListener::SocketListener(int socketFd, bool acceptClients) {
40168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat    mAcceptClients = acceptClients;
41168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat    mCsock = -1;
42168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat    mSocketName = NULL;
43168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat    mSock = socketFd;
44168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat}
45168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat
46168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehatint SocketListener::run() {
47168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat
48168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat    if (!mSocketName && mSock == -1) {
49168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat        errno = EINVAL;
50168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat        return -1;
51168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat    } else if (mSocketName) {
52168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat        if ((mSock = android_get_control_socket(mSocketName)) < 0) {
53168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat            LOGE("Obtaining file descriptor socket '%s' failed: %s",
54168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat                 mSocketName, strerror(errno));
55168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat            return -1;
56168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat        }
57168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat    }
58168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat
59168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat    if (mAcceptClients) {
60168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat        if (listen(mSock, 4) < 0) {
61168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat            LOGE("Unable to listen on socket (%s)", strerror(errno));
62168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat            return -1;
63168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat        }
64168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat    }
65168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat
66168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat    while(1) {
67168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat        fd_set read_fds;
68168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat        struct timeval to;
69168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat        int max = 0;
70168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat        int rc = 0;
71168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat
72168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat        to.tv_sec = 60 * 60;
73168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat        to.tv_usec = 0;
74168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat
75168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat        FD_ZERO(&read_fds);
76168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat
77168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat        if ((mAcceptClients == false) ||
78168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat            (mAcceptClients == true && mCsock == -1)) {
79168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat            FD_SET(mSock, &read_fds);
80168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat            max = mSock;
81168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat        } else if (mCsock != -1) {
82168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat            FD_SET(mCsock, &read_fds);
83168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat            max = mCsock;
84168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat        }
85168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat
86168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat        if ((rc = select(max + 1, &read_fds, NULL, NULL, &to)) < 0) {
87168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat            LOGE("select failed (%s)", strerror(errno));
88168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat            return -errno;
89168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat        } else if (!rc)
90168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat            continue;
91168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat        else if (FD_ISSET(mSock, &read_fds)) {
92168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat            /*
93168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat             * If we're accepting client connections then
94168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat             * accept and gobble the event. Otherwise
95168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat             * pass it on to the handlers.
96168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat             */
97168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat            if (mAcceptClients) {
98168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat                struct sockaddr addr;
99168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat                socklen_t alen = sizeof(addr);
100168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat
101168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat                if ((mCsock = accept(mSock, &addr, &alen)) < 0) {
102168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat                    LOGE("accept failed (%s)", strerror(errno));
103168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat                    return -errno;
104168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat                }
105168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat                LOGD("SocketListener client connection accepted");
106168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat            } else if (!onDataAvailable(mSock)) {
107168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat                LOGW("SocketListener closing listening socket (Will shut down)");
108168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat                close(mSock);
109168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat                return -ESHUTDOWN;
110168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat            }
111168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat        } else if ((FD_ISSET(mCsock, &read_fds)) &&
112168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat                   !onDataAvailable(mCsock)) {
113168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat                /*
114168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat                 * Once mCsock == -1, we'll start
115168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat                 * accepting connections on mSock again.
116168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat                 */
117168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat                LOGD("SocketListener closing client socket");
118168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat                close(mCsock);
119168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat                mCsock = -1;
120168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat            }
121168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat    }
122168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat    return 0;
123168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat}
124168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat
125168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehatbool SocketListener::onDataAvailable(int socket) {
126168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat    return false;
127168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat}
128