diff options
36 files changed, 758 insertions, 417 deletions
diff --git a/include/sysutils/FrameworkClient.h b/include/sysutils/FrameworkClient.h new file mode 100644 index 0000000..1eb112a --- /dev/null +++ b/include/sysutils/FrameworkClient.h @@ -0,0 +1,21 @@ +#ifndef _FRAMEWORK_CLIENT_H +#define _FRAMEWORK_CLIENT_H + +#include "../../../frameworks/base/include/utils/List.h" + +#include <pthread.h> + +class FrameworkClient { + int mSocket; + pthread_mutex_t mWriteMutex; + +public: + FrameworkClient(int sock); + virtual ~FrameworkClient() {} + + int sendMsg(char *msg); + int sendMsg(char *msg, char *data); +}; + +typedef android::List<FrameworkClient *> FrameworkClientCollection; +#endif diff --git a/include/sysutils/FrameworkCommand.h b/include/sysutils/FrameworkCommand.h index 952e99a..5b50247 100644 --- a/include/sysutils/FrameworkCommand.h +++ b/include/sysutils/FrameworkCommand.h @@ -18,6 +18,7 @@ #include "../../../frameworks/base/include/utils/List.h" +class SocketClient; class FrameworkCommand { private: @@ -28,7 +29,7 @@ public: FrameworkCommand(const char *cmd); virtual ~FrameworkCommand() { } - virtual int runCommand(char *data); + virtual int runCommand(SocketClient *c, char *data) = 0; const char *getCommand() { return mCommand; } }; diff --git a/include/sysutils/FrameworkListener.h b/include/sysutils/FrameworkListener.h index 1454a6f..8a83c33 100644 --- a/include/sysutils/FrameworkListener.h +++ b/include/sysutils/FrameworkListener.h @@ -19,6 +19,8 @@ #include "SocketListener.h" #include "FrameworkCommand.h" +class SocketClient; + class FrameworkListener : public SocketListener { private: FrameworkCommandCollection *mCommands; @@ -29,9 +31,9 @@ public: protected: void registerCmd(FrameworkCommand *cmd); - virtual bool onDataAvailable(int socket); + virtual bool onDataAvailable(SocketClient *c); private: - void dispatchCommand(char *cmd); + void dispatchCommand(SocketClient *c, char *cmd); }; #endif diff --git a/include/sysutils/FrameworkManager.h b/include/sysutils/FrameworkManager.h deleted file mode 100644 index 8a24d33..0000000 --- a/include/sysutils/FrameworkManager.h +++ /dev/null @@ -1,40 +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. - */ -#ifndef _FRAMEWORKMANAGER_H -#define _FRAMEWORKMANAGER_H - -#include <pthread.h> - -class FrameworkListener; - -class FrameworkManager { - int mDoorbell; // Socket used to accept connections from framework - int mFwSock; // Socket used to communicate with framework - const char *mSocketName; - - FrameworkListener *mListener; - - pthread_mutex_t mWriteMutex; - -public: - FrameworkManager(FrameworkListener *Listener); - virtual ~FrameworkManager() {} - - int run(); - int sendMsg(char *msg); - int sendMsg(char *msg, char *data); -}; -#endif diff --git a/include/sysutils/NetlinkListener.h b/include/sysutils/NetlinkListener.h index 8ac811c..6dcc005 100644 --- a/include/sysutils/NetlinkListener.h +++ b/include/sysutils/NetlinkListener.h @@ -27,6 +27,6 @@ public: NetlinkListener(int socket); virtual ~NetlinkListener() {} protected: - virtual bool onDataAvailable(int socket); + virtual bool onDataAvailable(SocketClient *cli); }; #endif diff --git a/include/sysutils/SocketClient.h b/include/sysutils/SocketClient.h new file mode 100644 index 0000000..39ec7ae --- /dev/null +++ b/include/sysutils/SocketClient.h @@ -0,0 +1,23 @@ +#ifndef _SOCKET_CLIENT_H +#define _SOCKET_CLIENT_H + +#include "../../../frameworks/base/include/utils/List.h" + +#include <pthread.h> + +class SocketClient { + int mSocket; + pthread_mutex_t mWriteMutex; + +public: + SocketClient(int sock); + virtual ~SocketClient() {} + + int getSocket() { return mSocket; } + + int sendMsg(char *msg); + int sendMsg(char *msg, char *data); +}; + +typedef android::List<SocketClient *> SocketClientCollection; +#endif diff --git a/include/sysutils/SocketListener.h b/include/sysutils/SocketListener.h index f079dba..be97421 100644 --- a/include/sysutils/SocketListener.h +++ b/include/sysutils/SocketListener.h @@ -16,20 +16,35 @@ #ifndef _SOCKETLISTENER_H #define _SOCKETLISTENER_H +#include <pthread.h> + +#include <sysutils/SocketClient.h> + class SocketListener { - int mSock; - int mCsock; - int mAcceptClients; - const char *mSocketName; + int mSock; + const char *mSocketName; + SocketClientCollection *mClients; + pthread_mutex_t mClientsLock; + bool mListen; + int mCtrlPipe[2]; + pthread_t mThread; public: - SocketListener(const char *socketName, bool acceptClients); - SocketListener(int socketFd, bool acceptClients); + SocketListener(const char *socketNames, bool listen); + SocketListener(int socketFd, bool listen); virtual ~SocketListener() {} - virtual int run(); + int startListener(); + int stopListener(); + + void sendBroadcast(char *msg); + void sendBroadcast(char *msg, char *data); protected: - virtual bool onDataAvailable(int socket); + virtual bool onDataAvailable(SocketClient *c) = 0; + +private: + static void *threadStart(void *obj); + void runListener(); }; #endif 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); } + diff --git a/nexus/Android.mk b/nexus/Android.mk index e76cb27..7cf4a1f 100644 --- a/nexus/Android.mk +++ b/nexus/Android.mk @@ -19,6 +19,7 @@ LOCAL_SRC_FILES:= \ SupplicantListener.cpp \ VpnController.cpp \ ScanResult.cpp \ + WifiScanner.cpp \ LOCAL_MODULE:= nexus diff --git a/nexus/CommandListener.cpp b/nexus/CommandListener.cpp index cdb1db5..02ede15 100644 --- a/nexus/CommandListener.cpp +++ b/nexus/CommandListener.cpp @@ -19,60 +19,64 @@ #define LOG_TAG "CommandListener" #include <cutils/log.h> +#include <sysutils/SocketClient.h> + #include "CommandListener.h" #include "Controller.h" #include "NetworkManager.h" #include "WifiController.h" -CommandListener::CommandListener(NetworkManager *netman) : +CommandListener::CommandListener() : FrameworkListener("nexus") { - mNetman = netman; - - registerCmd(new WifiEnableCmd(netman)); - registerCmd(new WifiDisableCmd(netman)); - registerCmd(new WifiScanCmd(netman)); + registerCmd(new WifiEnableCmd()); + registerCmd(new WifiDisableCmd()); + registerCmd(new WifiScanCmd()); + registerCmd(new WifiScanResultsCmd()); - registerCmd(new VpnEnableCmd(netman)); - registerCmd(new VpnDisableCmd(netman)); + registerCmd(new VpnEnableCmd()); + registerCmd(new VpnDisableCmd()); } /* ------------- * Wifi Commands * ------------ */ -CommandListener::WifiEnableCmd::WifiEnableCmd(NetworkManager *netman) : - NexusCommand("wifi_enable", netman) { +CommandListener::WifiEnableCmd::WifiEnableCmd() : + NexusCommand("wifi_enable") { } -int CommandListener::WifiEnableCmd::runCommand(char *data) { - Controller *c = mNetman->findController("WIFI"); +int CommandListener::WifiEnableCmd::runCommand(SocketClient *cli, char *data) { + Controller *c = NetworkManager::Instance()->findController("WIFI"); char buffer[32]; sprintf(buffer, "WIFI_ENABLE:%d", (c->enable() ? errno : 0)); - mNetman->getFrameworkManager()->sendMsg(buffer); + + cli->sendMsg(buffer); return 0; } -CommandListener::WifiDisableCmd::WifiDisableCmd(NetworkManager *netman) : - NexusCommand("wifi_disable", netman) { +CommandListener::WifiDisableCmd::WifiDisableCmd() : + NexusCommand("wifi_disable") { } -int CommandListener::WifiDisableCmd::runCommand(char *data) { - Controller *c = mNetman->findController("WIFI"); +int CommandListener::WifiDisableCmd::runCommand(SocketClient *cli, char *data) { + Controller *c = NetworkManager::Instance()->findController("WIFI"); char buffer[32]; sprintf(buffer, "WIFI_DISABLE:%d", (c->disable() ? errno : 0)); - mNetman->getFrameworkManager()->sendMsg(buffer); + cli->sendMsg(buffer); return 0; } -CommandListener::WifiScanCmd::WifiScanCmd(NetworkManager *netman) : - NexusCommand("wifi_scan", netman) { +CommandListener::WifiScanCmd::WifiScanCmd() : + NexusCommand("wifi_scan") { } -int CommandListener::WifiScanCmd::runCommand(char *data) { +int CommandListener::WifiScanCmd::runCommand(SocketClient *cli, char *data) { LOGD("WifiScanCmd(%s)", data); - WifiController *wc = (WifiController *) mNetman->findController("WIFI"); + + WifiController *wc = (WifiController *) NetworkManager::Instance()->findController("WIFI"); + char buffer[32]; int mode = 0; char *bword, *last; @@ -90,35 +94,62 @@ int CommandListener::WifiScanCmd::runCommand(char *data) { mode = atoi(bword); sprintf(buffer, "WIFI_SCAN:%d", (wc->setScanMode(mode) ? errno : 0)); - mNetman->getFrameworkManager()->sendMsg(buffer); + cli->sendMsg(buffer); + return 0; +} + +CommandListener::WifiScanResultsCmd::WifiScanResultsCmd() : + NexusCommand("wifi_scan_results") { +} + +int CommandListener::WifiScanResultsCmd::runCommand(SocketClient *cli, char *data) { + NetworkManager *nm = NetworkManager::Instance(); + + WifiController *wc = (WifiController *) nm->findController("WIFI"); + + ScanResultCollection *src = wc->createScanResults(); + ScanResultCollection::iterator it; + char buffer[256]; + + for(it = src->begin(); it != src->end(); ++it) { + sprintf(buffer, "WIFI_SCAN_RESULT:%s:%u:%d:%s:%s", + (*it)->getBssid(), (*it)->getFreq(), (*it)->getLevel(), + (*it)->getFlags(), (*it)->getSsid()); + cli->sendMsg(buffer); + delete (*it); + it = src->erase(it); + } + + delete src; + cli->sendMsg("WIFI_SCAN_RESULT:0"); return 0; } /* ------------ * Vpn Commands * ------------ */ -CommandListener::VpnEnableCmd::VpnEnableCmd(NetworkManager *netman) : - NexusCommand("vpn_enable", netman) { +CommandListener::VpnEnableCmd::VpnEnableCmd() : + NexusCommand("vpn_enable") { } -int CommandListener::VpnEnableCmd::runCommand(char *data) { - Controller *c = mNetman->findController("VPN"); +int CommandListener::VpnEnableCmd::runCommand(SocketClient *cli, char *data) { + Controller *c = NetworkManager::Instance()->findController("VPN"); char buffer[32]; sprintf(buffer, "VPN_ENABLE:%d", (c->enable() ? errno : 0)); - mNetman->getFrameworkManager()->sendMsg(buffer); + cli->sendMsg(buffer); return 0; } -CommandListener::VpnDisableCmd::VpnDisableCmd(NetworkManager *netman) : - NexusCommand("vpn_disable", netman) { +CommandListener::VpnDisableCmd::VpnDisableCmd() : + NexusCommand("vpn_disable") { } -int CommandListener::VpnDisableCmd::runCommand(char *data) { - Controller *c = mNetman->findController("VPN"); +int CommandListener::VpnDisableCmd::runCommand(SocketClient *cli, char *data) { + Controller *c = NetworkManager::Instance()->findController("VPN"); char buffer[32]; sprintf(buffer, "VPN_DISABLE:%d", (c->disable() ? errno : 0)); - mNetman->getFrameworkManager()->sendMsg(buffer); + cli->sendMsg(buffer); return 0; } diff --git a/nexus/CommandListener.h b/nexus/CommandListener.h index 261c093..064eab8 100644 --- a/nexus/CommandListener.h +++ b/nexus/CommandListener.h @@ -19,50 +19,52 @@ #include <sysutils/FrameworkListener.h> #include "NexusCommand.h" -class NetworkManager; - class CommandListener : public FrameworkListener { -protected: - NetworkManager *mNetman; - public: - CommandListener(NetworkManager *netman); + CommandListener(); virtual ~CommandListener() {} private: class WifiEnableCmd : public NexusCommand { public: - WifiEnableCmd(NetworkManager *); + WifiEnableCmd(); virtual ~WifiEnableCmd() {} - int runCommand(char *data); + int runCommand(SocketClient *c, char *data); }; class WifiDisableCmd : public NexusCommand { public: - WifiDisableCmd(NetworkManager *); + WifiDisableCmd(); virtual ~WifiDisableCmd() {} - int runCommand(char *data); + int runCommand(SocketClient *c, char *data); }; class WifiScanCmd : public NexusCommand { public: - WifiScanCmd(NetworkManager *); + WifiScanCmd(); virtual ~WifiScanCmd() {} - int runCommand(char *data); + int runCommand(SocketClient *c, char *data); + }; + + class WifiScanResultsCmd : public NexusCommand { + public: + WifiScanResultsCmd(); + virtual ~WifiScanResultsCmd() {} + int runCommand(SocketClient *c, char *data); }; class VpnEnableCmd : public NexusCommand { public: - VpnEnableCmd(NetworkManager *); + VpnEnableCmd(); virtual ~VpnEnableCmd() {} - int runCommand(char *data); + int runCommand(SocketClient *c, char *data); }; class VpnDisableCmd : public NexusCommand { public: - VpnDisableCmd(NetworkManager *); + VpnDisableCmd(); virtual ~VpnDisableCmd() {} - int runCommand(char *data); + int runCommand(SocketClient *c, char *data); }; }; diff --git a/nexus/NetworkManager.cpp b/nexus/NetworkManager.cpp index 9c64945..3b823d1 100644 --- a/nexus/NetworkManager.cpp +++ b/nexus/NetworkManager.cpp @@ -21,36 +21,30 @@ #include <cutils/log.h> #include "NetworkManager.h" -#include "CommandListener.h" -#include "LoopController.h" -#include "VpnController.h" -#include "TiwlanWifiController.h" +NetworkManager *NetworkManager::sInstance = NULL; + +NetworkManager *NetworkManager::Instance() { + if (!sInstance) + sInstance = new NetworkManager(); + return sInstance; +} NetworkManager::NetworkManager() { - mListener = new CommandListener(this); - mFm = new FrameworkManager(mListener); + mBroadcaster = NULL; mControllers = new ControllerCollection(); } int NetworkManager::run() { - LOGD("NetworkManager::start()"); - - // XXX: Factory needed - addController(new LoopController()); - addController(new TiwlanWifiController("/system/lib/modules/wlan.ko", "wlan", "")); - addController(new VpnController()); - //addController(new GenericController("rmnet0")); - if (startControllers()) { LOGW("Unable to start all controllers (%s)", strerror(errno)); } - mFm->run(); return 0; } -void NetworkManager::addController(Controller *c) { +int NetworkManager::attachController(Controller *c) { mControllers->push_back(c); + return 0; } int NetworkManager::startControllers() { diff --git a/nexus/NetworkManager.h b/nexus/NetworkManager.h index 8f362a9..0ac4a4d 100644 --- a/nexus/NetworkManager.h +++ b/nexus/NetworkManager.h @@ -16,31 +16,36 @@ #ifndef _NETWORKMANAGER_H #define _NETWORKMANAGER_H -#include "Controller.h" +#include <sysutils/SocketListener.h> -#include <sysutils/FrameworkManager.h> +#include "Controller.h" class NetworkManager { private: - FrameworkListener *mListener; - FrameworkManager *mFm; + static NetworkManager *sInstance; + +private: ControllerCollection *mControllers; + SocketListener *mBroadcaster; public: - NetworkManager(); virtual ~NetworkManager() {} int run(); + int attachController(Controller *controller); + + Controller *findController(const char *name); + + void setBroadcaster(SocketListener *sl) { mBroadcaster = sl; } + SocketListener *getBroadcaster() { return mBroadcaster; } + + static NetworkManager *Instance(); + private: - void addController(Controller *c); int startControllers(); int stopControllers(); - -public: - Controller *findController(const char *name); - ControllerCollection *getControllers() { return mControllers; } - FrameworkManager *getFrameworkManager() { return mFm; } + NetworkManager(); public: // XXX: Extract these into an interface diff --git a/nexus/NexusCommand.cpp b/nexus/NexusCommand.cpp index 090113c..92bb1c3 100644 --- a/nexus/NexusCommand.cpp +++ b/nexus/NexusCommand.cpp @@ -15,7 +15,6 @@ */ #include "NexusCommand.h" -NexusCommand::NexusCommand(const char *cmd, NetworkManager *netman) : +NexusCommand::NexusCommand(const char *cmd) : FrameworkCommand(cmd) { - mNetman = netman; } diff --git a/nexus/NexusCommand.h b/nexus/NexusCommand.h index 204541c..1482998 100644 --- a/nexus/NexusCommand.h +++ b/nexus/NexusCommand.h @@ -18,14 +18,9 @@ #include <sysutils/FrameworkCommand.h> -class NetworkManager; - class NexusCommand : public FrameworkCommand { -protected: - NetworkManager *mNetman; - public: - NexusCommand(const char *cmd, NetworkManager *netman); + NexusCommand(const char *cmd); virtual ~NexusCommand() {} }; diff --git a/nexus/ScanResult.h b/nexus/ScanResult.h index 79b2b65..f70a1a9 100644 --- a/nexus/ScanResult.h +++ b/nexus/ScanResult.h @@ -38,6 +38,7 @@ public: const char *getBssid() { return mBssid; } uint32_t getFreq() { return mFreq; } + int getLevel() { return mLevel; } const char *getFlags() { return mFlags; } const char *getSsid() { return mSsid; } }; diff --git a/nexus/Supplicant.cpp b/nexus/Supplicant.cpp index 215a8b3..d809e6e 100644 --- a/nexus/Supplicant.cpp +++ b/nexus/Supplicant.cpp @@ -13,6 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +#include <stdlib.h> #include <errno.h> #define LOG_TAG "Supplicant" @@ -31,6 +33,7 @@ #include "SupplicantState.h" #include "SupplicantEvent.h" #include "ScanResult.h" +#include "NetworkManager.h" #include "libwpa_client/wpa_ctrl.h" @@ -52,7 +55,6 @@ Supplicant::Supplicant() { } int Supplicant::start() { - LOGD("start():"); // XXX: Validate supplicant config file char status[PROPERTY_VALUE_MAX] = {'\0'}; @@ -63,47 +65,47 @@ int Supplicant::start() { #endif if (property_get(SUPP_PROP_NAME, status, NULL) && - strcmp(status, "running") == 0) { - return 0; - } - - wpa_ctrl_cleanup(); + !strcmp(status, "running")) { + LOGD("Supplicant already started"); + } else { #ifdef HAVE_LIBC_SYSTEM_PROPERTIES - pi = __system_property_find(SUPP_PROP_NAME); - if (pi != NULL) - serial = pi->serial; + pi = __system_property_find(SUPP_PROP_NAME); + if (pi != NULL) + serial = pi->serial; #endif - property_set("ctl.start", SUPPLICANT_NAME); - sched_yield(); - while (count--) { + LOGD("Starting Supplicant"); + property_set("ctl.start", SUPPLICANT_NAME); + sched_yield(); + while (count--) { #ifdef HAVE_LIBC_SYSTEM_PROPERTIES - if (!pi) - pi = __system_property_find(SUPP_PROP_NAME); - if (pi) { - __system_property_read(pi, NULL, status); - if (strcmp(status, "running") == 0) - return 0; - else if (pi->serial != serial && - strcmp(status, "stopped") == 0) { - errno = EIO; - return -1; + if (!pi) + pi = __system_property_find(SUPP_PROP_NAME); + if (pi) { + __system_property_read(pi, NULL, status); + if (strcmp(status, "running") == 0) + break; + else if (pi->serial != serial && + strcmp(status, "stopped") == 0) { + errno = EIO; + return -1; + } } - } #else - if (property_get(SUPP_PROP_NAME, status, NULL)) { - if (strcmp(status, "running") == 0) - break; - } + if (property_get(SUPP_PROP_NAME, status, NULL)) { + if (strcmp(status, "running") == 0) + break; + } #endif - usleep(100000); + usleep(100000); + } + if (!count) { + errno = ETIMEDOUT; + return -1; + } } - if (!count) { - errno = ETIMEDOUT; - return -1; - } - + wpa_ctrl_cleanup(); if (connectToSupplicant()) { LOGE("Error connecting to supplicant (%s)\n", strerror(errno)); return -1; @@ -112,7 +114,6 @@ int Supplicant::start() { } int Supplicant::stop() { - LOGD("stop()"); char supp_status[PROPERTY_VALUE_MAX] = {'\0'}; int count = 50; @@ -124,9 +125,11 @@ int Supplicant::stop() { if (property_get(SUPP_PROP_NAME, supp_status, NULL) && strcmp(supp_status, "stopped") == 0) { + LOGD("Supplicant already stopped"); return 0; } + LOGD("Stopping Supplicant"); property_set("ctl.stop", SUPPLICANT_NAME); sched_yield(); @@ -153,24 +156,29 @@ int Supplicant::stop() { return -1; } - LOGD("Stopped OK"); + LOGD("Supplicant shutdown"); return 0; } bool Supplicant::isStarted() { char supp_status[PROPERTY_VALUE_MAX] = {'\0'}; - if (!property_get(SUPP_PROP_NAME, supp_status, NULL) || - !strcmp(supp_status, "running")) { - return false; - } - return true; + + int rc = property_get(SUPP_PROP_NAME, supp_status, NULL); + + LOGD("rc = %d, property = '%s'", rc, supp_status); + + if (!strcmp(supp_status, "running")) + return true; + + return false; } int Supplicant::connectToSupplicant() { char ifname[256]; char supp_status[PROPERTY_VALUE_MAX] = {'\0'}; + LOGD("connectToSupplicant()"); if (!property_get(SUPP_PROP_NAME, supp_status, NULL) || strcmp(supp_status, "running") != 0) { LOGE("Supplicant not running, cannot connect"); @@ -213,13 +221,14 @@ int Supplicant::sendCommand(const char *cmd, char *reply, size_t *reply_len) return -1; } - LOGD("sendCommand(): -> '%s'", cmd); +// LOGD("sendCommand(): -> '%s'", cmd); int rc; if ((rc = wpa_ctrl_request(mCtrl, cmd, strlen(cmd), reply, reply_len, NULL)) == -2) { errno = ETIMEDOUT; return -1; } else if (rc < 0 || !strncmp(reply, "FAIL", 4)) { + LOGW("sendCommand(): <- '%s'", reply); errno = EIO; return -1; } @@ -228,7 +237,7 @@ int Supplicant::sendCommand(const char *cmd, char *reply, size_t *reply_len) !strncmp(cmd, "SCAN_RESULTS", 12)) reply[*reply_len] = '\0'; - LOGD("sendCommand(): <- '%s'", reply); +// LOGD("sendCommand(): <- '%s'", reply); return 0; } @@ -332,12 +341,16 @@ int Supplicant::onScanResultsEvent(SupplicantEvent *evt) { if (!strtok_r(reply, "\n", &linep_next)) { free(reply); - return 0;; + pthread_mutex_unlock(&mLatestScanResultsLock); + return 0; } while((linep = strtok_r(NULL, "\n", &linep_next))) mLatestScanResults->push_back(new ScanResult(linep)); - + + char tmp[32]; + sprintf(tmp, "WIFI_SCAN_RESULTS_READY:%d", mLatestScanResults->size()); + NetworkManager::Instance()->getBroadcaster()->sendBroadcast(tmp); pthread_mutex_unlock(&mLatestScanResultsLock); free(reply); } else { @@ -347,8 +360,24 @@ int Supplicant::onScanResultsEvent(SupplicantEvent *evt) { } int Supplicant::onStateChangeEvent(SupplicantEvent *evt) { - LOGD("onStateChangeEvent(%s)", evt->getEvent()); - // XXX: Update mState + char *bword, *last; + char *tmp = strdup(evt->getEvent()); + + if (!(bword = strtok_r(tmp, " ", &last))) { + LOGE("Malformatted state update (%s)", evt->getEvent()); + free(tmp); + return 0; + } + + if (!(bword = strtok_r(NULL, " ", &last))) { + LOGE("Malformatted state update (%s)", evt->getEvent()); + free(tmp); + return 0; + } + + mState = atoi(&bword[strlen("state=")]); + LOGD("State changed to %d", mState); + free(tmp); return 0; } @@ -363,7 +392,7 @@ int Supplicant::onDriverStateEvent(SupplicantEvent *evt) { } // XXX: Use a cursor + smartptr instead -const ScanResultCollection *Supplicant::getLatestScanResults() { +ScanResultCollection *Supplicant::createLatestScanResults() { ScanResultCollection *d = new ScanResultCollection(); ScanResultCollection::iterator i; diff --git a/nexus/Supplicant.h b/nexus/Supplicant.h index 46a9e86..2a25ea2 100644 --- a/nexus/Supplicant.h +++ b/nexus/Supplicant.h @@ -46,7 +46,7 @@ public: int getState() { return mState; } - const ScanResultCollection *getLatestScanResults(); + ScanResultCollection *createLatestScanResults(); // XXX: Extract these into an interface public: diff --git a/nexus/SupplicantListener.cpp b/nexus/SupplicantListener.cpp index 16306b5..76e9945 100644 --- a/nexus/SupplicantListener.cpp +++ b/nexus/SupplicantListener.cpp @@ -30,31 +30,9 @@ SupplicantListener::SupplicantListener(Supplicant *supplicant, struct wpa_ctrl * SocketListener(wpa_ctrl_get_fd(monitor), false) { mSupplicant = supplicant; mMonitor = monitor; - mThread = NULL; } -int SupplicantListener::startListener() { - LOGD("startListener()"); - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - - return pthread_create(&mThread, &attr, &SupplicantListener::threadStart, this); -} - -int SupplicantListener::stopListener() { - errno = -ENOSYS; - return -1; -} - -void *SupplicantListener::threadStart(void *obj) { - LOGD("threadStart(): Worker thread started"); - reinterpret_cast<SupplicantListener *>(obj)->run(); - LOGD("threadStart(): Worker thread exited"); - return NULL; -} - -bool SupplicantListener::onDataAvailable(int socket) { +bool SupplicantListener::onDataAvailable(SocketClient *cli) { char buf[255]; size_t buflen = sizeof(buf); int rc; @@ -62,7 +40,7 @@ bool SupplicantListener::onDataAvailable(int socket) { if ((rc = wpa_ctrl_recv(mMonitor, buf, &nread))) { LOGE("wpa_ctrl_recv failed (%s)", strerror(errno)); - return -errno; + return false; } buf[nread] = '\0'; @@ -108,7 +86,9 @@ bool SupplicantListener::onDataAvailable(int socket) { delete evt; - if (rc) + if (rc) { + LOGW("Handler %d (%s) error: %s", evt->getType(), evt->getEvent(), strerror(errno)); return false; + } return true; } diff --git a/nexus/SupplicantListener.h b/nexus/SupplicantListener.h index 3d27a68..95bad9a 100644 --- a/nexus/SupplicantListener.h +++ b/nexus/SupplicantListener.h @@ -16,33 +16,27 @@ #ifndef _SUPPLICANTLISTENER_H__ #define _SUPPLICANTLISTENER_H__ -#include <pthread.h> - #include <sysutils/SocketListener.h> struct wpa_ctrl; class Supplicant; +class SocketClient; class SupplicantListener: public SocketListener { private: struct wpa_ctrl *mMonitor; Supplicant *mSupplicant; - pthread_t mThread; public: SupplicantListener(Supplicant *supplicant, struct wpa_ctrl *monitor); virtual ~SupplicantListener() {} - int startListener(); - int stopListener(); struct wpa_ctrl *getMonitor() { return mMonitor; } Supplicant *getSupplicant() { return mSupplicant; } protected: - virtual bool onDataAvailable(int socket); + virtual bool onDataAvailable(SocketClient *c); -private: - static void *threadStart(void *obj); }; #endif diff --git a/nexus/SupplicantState.h b/nexus/SupplicantState.h index f2cf603..e85dcb5 100644 --- a/nexus/SupplicantState.h +++ b/nexus/SupplicantState.h @@ -18,16 +18,16 @@ class SupplicantState { public: - static const int UNKNOWN = 0; - static const int DISCONNECTED = 1; - static const int INACTIVE = 2; - static const int SCANNING = 3; - static const int ASSOCIATING = 4; - static const int ASSOCIATED = 5; - static const int FOURWAY_HANDSHAKE = 6; - static const int GROUP_HANDSHAKE = 7; - static const int COMPLETED = 8; - static const int IDLE = 9; + static const int UNKNOWN = -1; + static const int DISCONNECTED = 0; + static const int INACTIVE = 1; + static const int SCANNING = 2; + static const int ASSOCIATING = 3; + static const int ASSOCIATED = 4; + static const int FOURWAY_HANDSHAKE = 5; + static const int GROUP_HANDSHAKE = 6; + static const int COMPLETED = 7; + static const int IDLE = 8; }; #endif diff --git a/nexus/TiwlanWifiController.cpp b/nexus/TiwlanWifiController.cpp index ec83825..10606a1 100644 --- a/nexus/TiwlanWifiController.cpp +++ b/nexus/TiwlanWifiController.cpp @@ -65,3 +65,17 @@ int TiwlanWifiController::loadFirmware() { property_set(DRIVER_PROP_NAME, "timeout"); return -1; } + +bool TiwlanWifiController::isFirmwareLoaded() { + char driver_status[PROPERTY_VALUE_MAX]; + if (property_get(DRIVER_PROP_NAME, driver_status, NULL)) { + if (!strcmp(driver_status, "ok")) + return true; + else { + LOGD("Driver status '%s'", driver_status); + return false; + } + } + LOGW("Unable to get property '%s'", DRIVER_PROP_NAME); + return false; +} diff --git a/nexus/TiwlanWifiController.h b/nexus/TiwlanWifiController.h index a93d610..f17ef51 100644 --- a/nexus/TiwlanWifiController.h +++ b/nexus/TiwlanWifiController.h @@ -27,5 +27,6 @@ public: virtual int powerDown(); virtual bool isPoweredUp(); virtual int loadFirmware(); + virtual bool isFirmwareLoaded(); }; #endif diff --git a/nexus/WifiController.cpp b/nexus/WifiController.cpp index 8a7e33f..806141c 100644 --- a/nexus/WifiController.cpp +++ b/nexus/WifiController.cpp @@ -21,6 +21,8 @@ #include "Supplicant.h" #include "WifiController.h" +#include "WifiScanner.h" +#include "NetworkManager.h" WifiController::WifiController(char *modpath, char *modname, char *modargs) : Controller("WIFI") { @@ -29,6 +31,7 @@ WifiController::WifiController(char *modpath, char *modname, char *modargs) : strncpy(mModuleArgs, modargs, sizeof(mModuleArgs)); mSupplicant = new Supplicant(); + mScanner = new WifiScanner(mSupplicant, 10); mCurrentScanMode = 0; } @@ -42,26 +45,36 @@ int WifiController::stop() { } int WifiController::enable() { - if (!isPoweredUp() && powerUp()) { - LOGE("Powerup failed (%s)", strerror(errno)); - return -1; + if (!isPoweredUp()) { + sendStatusBroadcast("POWERING_UP"); + if (powerUp()) { + LOGE("Powerup failed (%s)", strerror(errno)); + return -1; + } } - + if (mModuleName[0] != '\0' && !isKernelModuleLoaded(mModuleName)) { + sendStatusBroadcast("LOADING_DRIVER"); if (loadKernelModule(mModulePath, mModuleArgs)) { LOGE("Kernel module load failed (%s)", strerror(errno)); goto out_powerdown; } } - if (loadFirmware()) { - LOGE("Firmware load failed (%s)", strerror(errno)); - goto out_powerdown; + if (!isFirmwareLoaded()) { + sendStatusBroadcast("LOADING_FIRMWARE"); + if (loadFirmware()) { + LOGE("Firmware load failed (%s)", strerror(errno)); + goto out_powerdown; + } } - if (!mSupplicant->isStarted() && mSupplicant->start()) { - LOGE("Supplicant start failed (%s)", strerror(errno)); - goto out_unloadmodule; + if (!mSupplicant->isStarted()) { + sendStatusBroadcast("STARTING_SUPPLICANT"); + if (mSupplicant->start()) { + LOGE("Supplicant start failed (%s)", strerror(errno)); + goto out_unloadmodule; + } } return 0; @@ -80,24 +93,38 @@ out_powerdown: return -1; } +void WifiController::sendStatusBroadcast(const char *msg) { + char tmp[255]; + + sprintf(tmp, "WIFI_STATUS:%s", msg); + NetworkManager::Instance()->getBroadcaster()->sendBroadcast(tmp); +} + int WifiController::disable() { - LOGD("disable()"); - if (mSupplicant->isStarted() && mSupplicant->stop()) { - LOGE("Supplicant stop failed (%s)", strerror(errno)); - return -1; - } + if (mSupplicant->isStarted()) { + sendStatusBroadcast("STOPPING_SUPPLICANT"); + if (mSupplicant->stop()) { + LOGE("Supplicant stop failed (%s)", strerror(errno)); + return -1; + } + } else + LOGW("disable(): Supplicant not running?"); if (mModuleName[0] != '\0' && isKernelModuleLoaded(mModuleName)) { + sendStatusBroadcast("UNLOADING_DRIVER"); if (unloadKernelModule(mModuleName)) { LOGE("Unable to unload module (%s)", strerror(errno)); return -1; } } - if (isPoweredUp() && powerDown()) { - LOGE("Powerdown failed (%s)", strerror(errno)); - return -1; + if (isPoweredUp()) { + sendStatusBroadcast("POWERING_DOWN"); + if (powerDown()) { + LOGE("Powerdown failed (%s)", strerror(errno)); + return -1; + } } return 0; } @@ -106,7 +133,7 @@ int WifiController::loadFirmware() { return 0; } -int WifiController::setScanMode(int mode) { +int WifiController::setScanMode(uint32_t mode) { int rc = 0; if (mCurrentScanMode == mode) @@ -114,21 +141,15 @@ int WifiController::setScanMode(int mode) { if (!(mode & SCAN_ENABLE_MASK)) { if (mCurrentScanMode & SCAN_REPEAT_MASK) - stopPeriodicScan(); + mScanner->stopPeriodicScan(); } else if (mode & SCAN_REPEAT_MASK) - rc = startPeriodicScan(); + rc = mScanner->startPeriodicScan(mode & SCAN_ACTIVE_MASK); else rc = mSupplicant->triggerScan(mode & SCAN_ACTIVE_MASK); return rc; } -int WifiController::startPeriodicScan() { - errno = -ENOSYS; - return -1; -} - -int WifiController::stopPeriodicScan() { - errno = -ENOSYS; - return -1; +ScanResultCollection *WifiController::createScanResults() { + return mSupplicant->createLatestScanResults(); } diff --git a/nexus/WifiController.h b/nexus/WifiController.h index 6d00513..38aea81 100644 --- a/nexus/WifiController.h +++ b/nexus/WifiController.h @@ -22,6 +22,9 @@ class NetInterface; class Supplicant; +class WifiScanner; + +#include "ScanResult.h" class WifiController : public Controller { public: @@ -40,8 +43,8 @@ private: char mModulePath[255]; char mModuleName[64]; char mModuleArgs[255]; - int mCurrentScanMode; - + uint32_t mCurrentScanMode; + WifiScanner *mScanner; public: WifiController(char *modpath, char *modname, char *modargs); @@ -53,6 +56,8 @@ public: int enable(); int disable(); + ScanResultCollection *createScanResults(); + int getType(); char *getModulePath() { return mModulePath; } @@ -62,17 +67,17 @@ public: Supplicant *getSupplicant() { return mSupplicant; } int getScanMode() { return mCurrentScanMode; } - int setScanMode(int mode); + int setScanMode(uint32_t mode); protected: virtual int powerUp() = 0; virtual int powerDown() = 0; virtual int loadFirmware(); + + virtual bool isFirmwareLoaded() = 0; virtual bool isPoweredUp() = 0; -private: - int startPeriodicScan(); - int stopPeriodicScan(); + void sendStatusBroadcast(const char *msg); }; #endif diff --git a/nexus/WifiScanner.cpp b/nexus/WifiScanner.cpp new file mode 100644 index 0000000..590d895 --- /dev/null +++ b/nexus/WifiScanner.cpp @@ -0,0 +1,96 @@ +#include <errno.h> +#include <pthread.h> + +#define LOG_TAG "WifiScanner" +#include <cutils/log.h> + +#include "WifiScanner.h" +#include "Supplicant.h" + +extern "C" int pthread_cancel(pthread_t thread); + +WifiScanner::WifiScanner(Supplicant *suppl, int period) { + mSuppl = suppl; + mPeriod = period; + mActive = false; + mWorkerRunning = false; + mAbortRequest = false; + pthread_mutex_init(&mAbortRequestLock, NULL); + pthread_mutex_init(&mWorkerLock, NULL); +} + +int WifiScanner::startPeriodicScan(bool active) { + mActive = active; + + pthread_mutex_lock(&mWorkerLock); + if (mWorkerRunning) { + errno = EBUSY; + return -1; + } + + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + + if (pthread_create(&mWorker, &attr, WifiScanner::threadStart, this)) + return -1; + + return 0; +} + +void *WifiScanner::threadStart(void *obj) { + WifiScanner *me = reinterpret_cast<WifiScanner *>(obj); + me->run(); + pthread_exit(NULL); + return NULL; +} + +void WifiScanner::threadCleanup(void *obj) { + WifiScanner *me = reinterpret_cast<WifiScanner *>(obj); + + me->mWorkerRunning = false; + pthread_mutex_unlock(&me->mWorkerLock); + + if (me->mAbortRequest) { + me->mAbortRequest = false; + pthread_mutex_unlock(&me->mAbortRequestLock); + } +} + +int WifiScanner::stopPeriodicScan() { + pthread_mutex_lock(&mAbortRequestLock); + pthread_mutex_lock(&mWorkerLock); + if (mWorkerRunning) + mAbortRequest = true; + pthread_mutex_unlock(&mWorkerLock); + pthread_mutex_unlock(&mAbortRequestLock); + + return 0; +} + +void WifiScanner::run() { + LOGD("Thread started"); + + mWorkerRunning = true; + pthread_cleanup_push(WifiScanner::threadCleanup, this); + pthread_mutex_unlock(&mWorkerLock); + + while(1) { + LOGD("Triggering periodic scan"); + if (mSuppl->triggerScan(mActive)) { + LOGW("Error triggering scan (%s)", strerror(errno)); + } + + sleep(mPeriod); + pthread_mutex_lock(&mAbortRequestLock); + if (mAbortRequest) { + LOGD("Abort request!"); + goto out; + } + pthread_mutex_unlock(&mAbortRequestLock); + } + +out: + pthread_cleanup_pop(1); + pthread_mutex_unlock(&mWorkerLock); +} diff --git a/nexus/WifiScanner.h b/nexus/WifiScanner.h new file mode 100644 index 0000000..9ba1309 --- /dev/null +++ b/nexus/WifiScanner.h @@ -0,0 +1,36 @@ +#ifndef _WIFISCANNER_H +#define _WIFISCANNER_H + +#include <pthread.h> + +class Supplicant; + +class WifiScanner { + pthread_t mWorker; + pthread_mutex_t mWorkerLock; + bool mWorkerRunning; + bool mAbortRequest; + pthread_mutex_t mAbortRequestLock; + + Supplicant *mSuppl; + int mPeriod; + bool mActive; + + +public: + WifiScanner(Supplicant *suppl, int period); + virtual ~WifiScanner() {} + + int getPeriod() { return mPeriod; } + + int startPeriodicScan(bool active); + int stopPeriodicScan(); + +private: + static void *threadStart(void *obj); + static void threadCleanup(void *obj); + + void run(); +}; + +#endif diff --git a/nexus/main.cpp b/nexus/main.cpp index a26a14d..0a0b43f 100644 --- a/nexus/main.cpp +++ b/nexus/main.cpp @@ -20,22 +20,44 @@ #include "cutils/log.h" #include "NetworkManager.h" +#include "CommandListener.h" -int main() { - NetworkManager *nm; +#include "LoopController.h" +#include "VpnController.h" +#include "TiwlanWifiController.h" +int main() { LOGI("Nexus version 0.1 firing up"); - if (!(nm = new NetworkManager())) { + CommandListener *cl = new CommandListener(); + + NetworkManager *nm; + if (!(nm = NetworkManager::Instance())) { LOGE("Unable to create NetworkManager"); exit (-1); }; - if (nm->run()) { + nm->setBroadcaster((SocketListener *) cl); + + nm->attachController(new LoopController()); + nm->attachController(new TiwlanWifiController("/system/lib/modules/wlan.ko", "wlan", "")); + nm->attachController(new VpnController()); + + + if (NetworkManager::Instance()->run()) { LOGE("Unable to Run NetworkManager (%s)", strerror(errno)); exit (1); } + if (cl->startListener()) { + LOGE("Unable to start CommandListener (%s)", strerror(errno)); + exit (1); + } + + while(1) { + sleep(1000); + } + LOGI("Nexus exiting"); exit(0); } diff --git a/nexus/nexctl.c b/nexus/nexctl.c index 6d117c7..c326558 100644 --- a/nexus/nexctl.c +++ b/nexus/nexctl.c @@ -65,14 +65,13 @@ int main(int argc, char **argv) { buffer[strlen(buffer) -1] = 0; - printf("sending '%s'\n", buffer); if (write(sock, buffer, strlen(buffer) +1) < 0) { fprintf(stderr, "Error writing data (%s)\n", strerror(errno)); exit(2); } wait: - to.tv_sec = 5; + to.tv_sec = 10; to.tv_usec = 0; FD_ZERO(&read_fds); FD_SET(sock, &read_fds); @@ -88,12 +87,11 @@ wait: printf("{response timeout}\n"); continue; } else if (FD_ISSET(sock, &read_fds)) { -printf("got data!\n"); - if ((rc = read(sock, buffer, sizeof(buffer)-1)) < 0) { + if ((rc = read(sock, buffer, sizeof(buffer)-1)) <= 0) { fprintf(stderr, "Error reading response (%s)\n", strerror(errno)); exit(2); } - printf(" |%s|\n", buffer); + printf(" %s\n", buffer); goto wait; } } |