diff options
| author | San Mehat <san@google.com> | 2009-05-08 11:15:53 -0700 |
|---|---|---|
| committer | San Mehat <san@google.com> | 2009-05-10 09:26:42 -0700 |
| commit | fa644ffe944c01a9b00f8d7676d58394fabee285 (patch) | |
| tree | a19968819547c4b515c463adb48106a8d01983aa /libsysutils | |
| parent | 1441e769b2767e212a3d905bee2fd3535b484ff2 (diff) | |
| download | system_core-fa644ffe944c01a9b00f8d7676d58394fabee285.zip system_core-fa644ffe944c01a9b00f8d7676d58394fabee285.tar.gz system_core-fa644ffe944c01a9b00f8d7676d58394fabee285.tar.bz2 | |
libsysutils: Add multiple client support and fix some bugs
Diffstat (limited to 'libsysutils')
| -rw-r--r-- | libsysutils/Android.mk | 2 | ||||
| -rw-r--r-- | libsysutils/src/FrameworkClient.cpp | 41 | ||||
| -rw-r--r-- | libsysutils/src/FrameworkCommand.cpp | 2 | ||||
| -rw-r--r-- | libsysutils/src/FrameworkListener.cpp | 24 | ||||
| -rw-r--r-- | libsysutils/src/FrameworkManager.cpp | 83 | ||||
| -rw-r--r-- | libsysutils/src/NetlinkListener.cpp | 3 | ||||
| -rw-r--r-- | libsysutils/src/SocketClient.cpp | 41 | ||||
| -rw-r--r-- | libsysutils/src/SocketListener.cpp | 191 |
8 files changed, 241 insertions, 146 deletions
diff --git a/libsysutils/Android.mk b/libsysutils/Android.mk index 0b15c12..cbb1edf 100644 --- a/libsysutils/Android.mk +++ b/libsysutils/Android.mk @@ -3,12 +3,12 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ - src/FrameworkManager.cpp \ src/SocketListener.cpp \ src/FrameworkListener.cpp \ src/NetlinkListener.cpp \ src/NetlinkEvent.cpp \ src/FrameworkCommand.cpp \ + src/SocketClient.cpp \ LOCAL_MODULE:= libsysutils diff --git a/libsysutils/src/FrameworkClient.cpp b/libsysutils/src/FrameworkClient.cpp new file mode 100644 index 0000000..237bb60 --- /dev/null +++ b/libsysutils/src/FrameworkClient.cpp @@ -0,0 +1,41 @@ +#include <alloca.h> +#include <errno.h> +#include <sys/types.h> +#include <pthread.h> + +#define LOG_TAG "FrameworkClient" +#include <cutils/log.h> + +#include <sysutils/FrameworkClient.h> + +FrameworkClient::FrameworkClient(int socket) { + mSocket = socket; + pthread_mutex_init(&mWriteMutex, NULL); +} + +int FrameworkClient::sendMsg(char *msg) { + LOGD("FrameworkClient::sendMsg(%s)", msg); + if (mSocket < 0) { + errno = EHOSTUNREACH; + return -1; + } + + pthread_mutex_lock(&mWriteMutex); + if (write(mSocket, msg, strlen(msg) +1) < 0) { + LOGW("Unable to send msg '%s' (%s)", msg, strerror(errno)); + } + pthread_mutex_unlock(&mWriteMutex); + return 0; +} + +int FrameworkClient::sendMsg(char *msg, char *data) { + char *buffer = (char *) alloca(strlen(msg) + strlen(data) + 1); + if (!buffer) { + errno = -ENOMEM; + return -1; + } + strcpy(buffer, msg); + strcat(buffer, data); + return sendMsg(buffer); +} + diff --git a/libsysutils/src/FrameworkCommand.cpp b/libsysutils/src/FrameworkCommand.cpp index 0444de5..94e7426 100644 --- a/libsysutils/src/FrameworkCommand.cpp +++ b/libsysutils/src/FrameworkCommand.cpp @@ -25,7 +25,7 @@ FrameworkCommand::FrameworkCommand(const char *cmd) { mCommand = cmd; } -int FrameworkCommand::runCommand(char *data) { +int FrameworkCommand::runCommand(SocketClient *c, char *data) { LOGW("Command %s has no run handler!", getCommand()); errno = ENOSYS; return -1; diff --git a/libsysutils/src/FrameworkListener.cpp b/libsysutils/src/FrameworkListener.cpp index b920215..9210ca5 100644 --- a/libsysutils/src/FrameworkListener.cpp +++ b/libsysutils/src/FrameworkListener.cpp @@ -22,17 +22,18 @@ #include <sysutils/FrameworkListener.h> #include <sysutils/FrameworkCommand.h> +#include <sysutils/SocketClient.h> FrameworkListener::FrameworkListener(const char *socketName) : SocketListener(socketName, true) { mCommands = new FrameworkCommandCollection(); } -bool FrameworkListener::onDataAvailable(int socket) { +bool FrameworkListener::onDataAvailable(SocketClient *c) { char buffer[101]; int len; - if ((len = read(socket, buffer, sizeof(buffer) -1)) < 0) { + if ((len = read(c->getSocket(), buffer, sizeof(buffer) -1)) < 0) { LOGE("read() failed (%s)", strerror(errno)); return errno; } else if (!len) { @@ -47,7 +48,7 @@ bool FrameworkListener::onDataAvailable(int socket) { for (i = 0; i < len; i++) { if (buffer[i] == '\0') { - dispatchCommand(buffer + start); + dispatchCommand(c, buffer + start); start = i + 1; } } @@ -58,14 +59,22 @@ void FrameworkListener::registerCmd(FrameworkCommand *cmd) { mCommands->push_back(cmd); } -void FrameworkListener::dispatchCommand(char *cmd) { +void FrameworkListener::dispatchCommand(SocketClient *cli, char *cmd) { + + char *cm, *last; + + if (!(cm = strtok_r(cmd, ":", &last))) { + cli->sendMsg("BAD_MSG"); + return; + } + FrameworkCommandCollection::iterator i; for (i = mCommands->begin(); i != mCommands->end(); ++i) { FrameworkCommand *c = *i; - if (!strncmp(cmd, c->getCommand(), strlen(c->getCommand()))) { - if (c->runCommand(cmd)) { + if (!strcmp(cm, c->getCommand())) { + if (c->runCommand(cli, cmd)) { LOGW("Handler '%s' error (%s)", c->getCommand(), strerror(errno)); } return; @@ -73,5 +82,6 @@ void FrameworkListener::dispatchCommand(char *cmd) { } LOGE("No cmd handlers defined for '%s'", cmd); + cli->sendMsg("UNKNOWN_CMD"); + return; } - diff --git a/libsysutils/src/FrameworkManager.cpp b/libsysutils/src/FrameworkManager.cpp deleted file mode 100644 index 5dceb9f..0000000 --- a/libsysutils/src/FrameworkManager.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include <stdio.h> -#include <errno.h> -#include <stdlib.h> -#include <sys/socket.h> -#include <sys/select.h> -#include <sys/time.h> -#include <sys/types.h> -#include <sys/un.h> - -#include <cutils/config_utils.h> -#include <cutils/cpu_info.h> -#include <cutils/properties.h> -#include <cutils/sockets.h> - -#define LOG_TAG "FrameworkManager" -#include <cutils/log.h> - -#include <sysutils/FrameworkManager.h> -#include <sysutils/FrameworkListener.h> - -FrameworkManager::FrameworkManager(FrameworkListener *Listener) { - mDoorbell = -1; - mFwSock = -1; - mListener = Listener; - - pthread_mutex_init(&mWriteMutex, NULL); -} - -int FrameworkManager::run() { - - if (mListener->run()) { - LOGE("Error running listener (%s)", strerror(errno)); - return -1; - } - - return 0; -} - -/* ======== - * Privates - * ======== - */ - -int FrameworkManager::sendMsg(char *msg) { - LOGD("FrameworkManager::sendMsg(%s)", msg); - if (mFwSock < 0) { - errno = EHOSTUNREACH; - return -1; - } - - pthread_mutex_lock(&mWriteMutex); - if (write(mFwSock, msg, strlen(msg) +1) < 0) { - LOGW("Unable to send msg '%s' (%s)", msg, strerror(errno)); - } - pthread_mutex_unlock(&mWriteMutex); - return 0; -} - -int FrameworkManager::sendMsg(char *msg, char *data) { - char *buffer = (char *) alloca(strlen(msg) + strlen(data) + 1); - if (!buffer) { - errno = -ENOMEM; - return -1; - } - strcpy(buffer, msg); - strcat(buffer, data); - return sendMsg(buffer); -} diff --git a/libsysutils/src/NetlinkListener.cpp b/libsysutils/src/NetlinkListener.cpp index 96a616d..3ec9d9d 100644 --- a/libsysutils/src/NetlinkListener.cpp +++ b/libsysutils/src/NetlinkListener.cpp @@ -29,8 +29,9 @@ NetlinkListener::NetlinkListener(int socket) : SocketListener(socket, false) { } -bool NetlinkListener::onDataAvailable(int socket) +bool NetlinkListener::onDataAvailable(SocketClient *cli) { + int socket = cli->getSocket(); LOGD("NetlinkListener::onDataAvailable()"); int count; diff --git a/libsysutils/src/SocketClient.cpp b/libsysutils/src/SocketClient.cpp new file mode 100644 index 0000000..6db62b3 --- /dev/null +++ b/libsysutils/src/SocketClient.cpp @@ -0,0 +1,41 @@ +#include <alloca.h> +#include <errno.h> +#include <sys/types.h> +#include <pthread.h> + +#define LOG_TAG "SocketClient" +#include <cutils/log.h> + +#include <sysutils/SocketClient.h> + +SocketClient::SocketClient(int socket) { + mSocket = socket; + pthread_mutex_init(&mWriteMutex, NULL); +} + +int SocketClient::sendMsg(char *msg) { + LOGD("SocketClient::sendMsg(%s)", msg); + if (mSocket < 0) { + errno = EHOSTUNREACH; + return -1; + } + + pthread_mutex_lock(&mWriteMutex); + if (write(mSocket, msg, strlen(msg) +1) < 0) { + LOGW("Unable to send msg '%s' (%s)", msg, strerror(errno)); + } + pthread_mutex_unlock(&mWriteMutex); + return 0; +} + +int SocketClient::sendMsg(char *msg, char *data) { + char *buffer = (char *) alloca(strlen(msg) + strlen(data) + 1); + if (!buffer) { + errno = -ENOMEM; + return -1; + } + strcpy(buffer, msg); + strcat(buffer, data); + return sendMsg(buffer); +} + diff --git a/libsysutils/src/SocketListener.cpp b/libsysutils/src/SocketListener.cpp index f92e30d..cb69bfd 100644 --- a/libsysutils/src/SocketListener.cpp +++ b/libsysutils/src/SocketListener.cpp @@ -24,26 +24,28 @@ #define LOG_TAG "SocketListener" #include <cutils/log.h> - #include <cutils/sockets.h> #include <sysutils/SocketListener.h> +#include <sysutils/SocketClient.h> -SocketListener::SocketListener(const char *socketName, bool acceptClients) { - mAcceptClients = acceptClients; - mCsock = -1; +SocketListener::SocketListener(const char *socketName, bool listen) { + mListen = listen; mSocketName = socketName; mSock = -1; + pthread_mutex_init(&mClientsLock, NULL); + mClients = new SocketClientCollection(); } -SocketListener::SocketListener(int socketFd, bool acceptClients) { - mAcceptClients = acceptClients; - mCsock = -1; +SocketListener::SocketListener(int socketFd, bool listen) { + mListen = listen; mSocketName = NULL; mSock = socketFd; + pthread_mutex_init(&mClientsLock, NULL); + mClients = new SocketClientCollection(); } -int SocketListener::run() { +int SocketListener::startListener() { if (!mSocketName && mSock == -1) { errno = EINVAL; @@ -56,72 +58,155 @@ int SocketListener::run() { } } - if (mAcceptClients) { - if (listen(mSock, 4) < 0) { - LOGE("Unable to listen on socket (%s)", strerror(errno)); - return -1; - } + if (mListen && listen(mSock, 4) < 0) { + LOGE("Unable to listen on socket (%s)", strerror(errno)); + return -1; + } else if (!mListen) { + mClients->push_back(new SocketClient(mSock)); + LOGD("Created phantom client"); } + if (pipe(mCtrlPipe)) + return -1; + + if (pthread_create(&mThread, NULL, SocketListener::threadStart, this)) + return -1; + + return 0; +} + +int SocketListener::stopListener() { + char c = 0; + + if (write(mCtrlPipe[1], &c, 1) != 1) { + LOGE("Error writing to control pipe (%s)", strerror(errno)); + return -1; + } + + LOGD("Signaled listener thread - waiting for it to die"); + void *ret; + if (pthread_join(mThread, &ret)) { + LOGE("Error joining to listener thread (%s)", strerror(errno)); + return -1; + } + LOGD("Listener stopped"); + return 0; +} + +void *SocketListener::threadStart(void *obj) { + SocketListener *me = reinterpret_cast<SocketListener *>(obj); + + me->runListener(); + LOGD("Listener thread shutting down"); + pthread_exit(NULL); + return NULL; +} + +void SocketListener::runListener() { + while(1) { + SocketClientCollection::iterator it; fd_set read_fds; struct timeval to; - int max = 0; int rc = 0; to.tv_sec = 60 * 60; to.tv_usec = 0; + int max = 0; + FD_ZERO(&read_fds); - if ((mAcceptClients == false) || - (mAcceptClients == true && mCsock == -1)) { - FD_SET(mSock, &read_fds); + if (mListen) { max = mSock; - } else if (mCsock != -1) { - FD_SET(mCsock, &read_fds); - max = mCsock; + FD_SET(mSock, &read_fds); } + FD_SET(mCtrlPipe[0], &read_fds); + if (mCtrlPipe[0] > max) + max = mCtrlPipe[0]; + + pthread_mutex_lock(&mClientsLock); + for (it = mClients->begin(); it != mClients->end(); ++it) { + FD_SET((*it)->getSocket(), &read_fds); + if ((*it)->getSocket() > max) + max = (*it)->getSocket(); + } + pthread_mutex_unlock(&mClientsLock); + if ((rc = select(max + 1, &read_fds, NULL, NULL, &to)) < 0) { LOGE("select failed (%s)", strerror(errno)); - return -errno; - } else if (!rc) + sleep(1); continue; - else if (FD_ISSET(mSock, &read_fds)) { - /* - * If we're accepting client connections then - * accept and gobble the event. Otherwise - * pass it on to the handlers. - */ - if (mAcceptClients) { - struct sockaddr addr; - socklen_t alen = sizeof(addr); - - if ((mCsock = accept(mSock, &addr, &alen)) < 0) { - LOGE("accept failed (%s)", strerror(errno)); - return -errno; - } - LOGD("SocketListener client connection accepted"); - } else if (!onDataAvailable(mSock)) { - LOGW("SocketListener closing listening socket (Will shut down)"); - close(mSock); - return -ESHUTDOWN; + } else if (!rc) { + LOGD("select timeout"); + continue; + } + + if (FD_ISSET(mCtrlPipe[0], &read_fds)) { + LOGD("Control message received"); + break; + } + if (mListen && FD_ISSET(mSock, &read_fds)) { + struct sockaddr addr; + socklen_t alen = sizeof(addr); + int c; + + if ((c = accept(mSock, &addr, &alen)) < 0) { + LOGE("accept failed (%s)", strerror(errno)); + sleep(1); + continue; } - } else if ((FD_ISSET(mCsock, &read_fds)) && - !onDataAvailable(mCsock)) { - /* - * Once mCsock == -1, we'll start - * accepting connections on mSock again. - */ - LOGD("SocketListener closing client socket"); - close(mCsock); - mCsock = -1; + LOGD("SocketListener client connection accepted"); + pthread_mutex_lock(&mClientsLock); + mClients->push_back(new SocketClient(c)); + pthread_mutex_unlock(&mClientsLock); + } + + do { + pthread_mutex_lock(&mClientsLock); + for (it = mClients->begin(); it != mClients->end(); ++it) { + int fd = (*it)->getSocket(); + if (FD_ISSET(fd, &read_fds)) { + pthread_mutex_unlock(&mClientsLock); + if (!onDataAvailable(*it)) { + LOGD("SocketListener closing client socket"); + close(fd); + pthread_mutex_lock(&mClientsLock); + delete *it; + it = mClients->erase(it); + pthread_mutex_unlock(&mClientsLock); + } + FD_CLR(fd, &read_fds); + continue; + } } + pthread_mutex_unlock(&mClientsLock); + } while (0); } - return 0; } -bool SocketListener::onDataAvailable(int socket) { - return false; +void SocketListener::sendBroadcast(char *msg) { + pthread_mutex_lock(&mClientsLock); + SocketClientCollection::iterator i; + + for (i = mClients->begin(); i != mClients->end(); ++i) { + if ((*i)->sendMsg(msg)) { + LOGW("Error sending broadcast (%s)", strerror(errno)); + } + } + pthread_mutex_unlock(&mClientsLock); +} + +void SocketListener::sendBroadcast(char *msg, char *data) { + pthread_mutex_lock(&mClientsLock); + SocketClientCollection::iterator i; + + for (i = mClients->begin(); i != mClients->end(); ++i) { + if ((*i)->sendMsg(msg, data)) { + LOGW("Error sending broadcast (%s)", strerror(errno)); + } + } + pthread_mutex_unlock(&mClientsLock); } + |
