diff options
-rw-r--r-- | include/sysutils/FrameworkListener.h | 7 | ||||
-rw-r--r-- | include/sysutils/SocketClient.h | 17 | ||||
-rw-r--r-- | include/sysutils/SocketListener.h | 8 | ||||
-rw-r--r-- | libsysutils/src/FrameworkListener.cpp | 38 | ||||
-rw-r--r-- | libsysutils/src/SocketClient.cpp | 59 | ||||
-rw-r--r-- | libsysutils/src/SocketListener.cpp | 45 |
6 files changed, 120 insertions, 54 deletions
diff --git a/include/sysutils/FrameworkListener.h b/include/sysutils/FrameworkListener.h index 142f50c..756bacf 100644 --- a/include/sysutils/FrameworkListener.h +++ b/include/sysutils/FrameworkListener.h @@ -24,11 +24,17 @@ class SocketClient; class FrameworkListener : public SocketListener { public: static const int CMD_ARGS_MAX = 16; + + /* 1 out of errorRate will be dropped */ + int errorRate; private: + int mCommandCount; + bool mWithSeq; FrameworkCommandCollection *mCommands; public: FrameworkListener(const char *socketName); + FrameworkListener(const char *socketName, bool withSeq); virtual ~FrameworkListener() {} protected: @@ -37,5 +43,6 @@ protected: private: void dispatchCommand(SocketClient *c, char *data); + void init(const char *socketName, bool withSeq); }; #endif diff --git a/include/sysutils/SocketClient.h b/include/sysutils/SocketClient.h index cee863f..65a5b1b 100644 --- a/include/sysutils/SocketClient.h +++ b/include/sysutils/SocketClient.h @@ -4,6 +4,7 @@ #include "List.h" #include <pthread.h> +#include <cutils/atomic.h> #include <sys/types.h> class SocketClient { @@ -24,20 +25,27 @@ class SocketClient { pthread_mutex_t mRefCountMutex; int mRefCount; + int mCmdNum; + + bool mUseCmdNum; + public: SocketClient(int sock, bool owned); + SocketClient(int sock, bool owned, bool useCmdNum); virtual ~SocketClient(); int getSocket() { return mSocket; } pid_t getPid() const { return mPid; } uid_t getUid() const { return mUid; } gid_t getGid() const { return mGid; } + void setCmdNum(int cmdNum) { android_atomic_release_store(cmdNum, &mCmdNum); } + int getCmdNum() { return mCmdNum; } // Send null-terminated C strings: int sendMsg(int code, const char *msg, bool addErrno); - int sendMsg(const char *msg); + int sendMsg(int code, const char *msg, bool addErrno, bool useCmdNum); - // Sending binary data: + //Sending binary data: int sendData(const void *data, int len); // Optional reference counting. Reference count starts at 1. If @@ -46,6 +54,11 @@ public: // decRef() when it's done with the client. void incRef(); bool decRef(); // returns true at 0 (but note: SocketClient already deleted) + +private: + // Send null-terminated C strings + int sendMsg(const char *msg); + void init(int socket, bool owned, bool useCmdNum); }; typedef android::sysutils::List<SocketClient *> SocketClientCollection; diff --git a/include/sysutils/SocketListener.h b/include/sysutils/SocketListener.h index 6592b01..8f56230 100644 --- a/include/sysutils/SocketListener.h +++ b/include/sysutils/SocketListener.h @@ -21,16 +21,18 @@ #include <sysutils/SocketClient.h> class SocketListener { - int mSock; + bool mListen; const char *mSocketName; + int mSock; SocketClientCollection *mClients; pthread_mutex_t mClientsLock; - bool mListen; int mCtrlPipe[2]; pthread_t mThread; + bool mUseCmdNum; public: SocketListener(const char *socketName, bool listen); + SocketListener(const char *socketName, bool listen, bool useCmdNum); SocketListener(int socketFd, bool listen); virtual ~SocketListener(); @@ -38,7 +40,6 @@ public: int stopListener(); void sendBroadcast(int code, const char *msg, bool addErrno); - void sendBroadcast(const char *msg); protected: virtual bool onDataAvailable(SocketClient *c) = 0; @@ -46,5 +47,6 @@ protected: private: static void *threadStart(void *obj); void runListener(); + void init(const char *socketName, int socketFd, bool listen, bool useCmdNum); }; #endif diff --git a/libsysutils/src/FrameworkListener.cpp b/libsysutils/src/FrameworkListener.cpp index 90be754..6731cf1 100644 --- a/libsysutils/src/FrameworkListener.cpp +++ b/libsysutils/src/FrameworkListener.cpp @@ -25,9 +25,21 @@ #include <sysutils/FrameworkCommand.h> #include <sysutils/SocketClient.h> +FrameworkListener::FrameworkListener(const char *socketName, bool withSeq) : + SocketListener(socketName, true, withSeq) { + init(socketName, withSeq); +} + FrameworkListener::FrameworkListener(const char *socketName) : - SocketListener(socketName, true) { + SocketListener(socketName, true, false) { + init(socketName, false); +} + +void FrameworkListener::init(const char *socketName, bool withSeq) { mCommands = new FrameworkCommandCollection(); + errorRate = 0; + mCommandCount = 0; + mWithSeq = withSeq; } bool FrameworkListener::onDataAvailable(SocketClient *c) { @@ -69,6 +81,7 @@ void FrameworkListener::dispatchCommand(SocketClient *cli, char *data) { bool esc = false; bool quote = false; int k; + bool haveCmdNum = !mWithSeq; memset(argv, 0, sizeof(argv)); memset(tmp, 0, sizeof(tmp)); @@ -115,9 +128,20 @@ void FrameworkListener::dispatchCommand(SocketClient *cli, char *data) { *q = *p++; if (!quote && *q == ' ') { *q = '\0'; - if (argc >= CMD_ARGS_MAX) - goto overflow; - argv[argc++] = strdup(tmp); + if (!haveCmdNum) { + char *endptr; + int cmdNum = (int)strtol(tmp, &endptr, 0); + if (endptr == NULL || *endptr != '\0') { + cli->sendMsg(500, "Invalid sequence number", false); + goto out; + } + cli->setCmdNum(cmdNum); + haveCmdNum = true; + } else { + if (argc >= CMD_ARGS_MAX) + goto overflow; + argv[argc++] = strdup(tmp); + } memset(tmp, 0, sizeof(tmp)); q = tmp; continue; @@ -140,6 +164,12 @@ void FrameworkListener::dispatchCommand(SocketClient *cli, char *data) { goto out; } + if (errorRate && (++mCommandCount % errorRate == 0)) { + /* ignore this command - let the timeout handler handle it */ + SLOGE("Faking a timeout"); + goto out; + } + for (i = mCommands->begin(); i != mCommands->end(); ++i) { FrameworkCommand *c = *i; diff --git a/libsysutils/src/SocketClient.cpp b/libsysutils/src/SocketClient.cpp index 722dcb2..d9fc48c 100644 --- a/libsysutils/src/SocketClient.cpp +++ b/libsysutils/src/SocketClient.cpp @@ -10,16 +10,25 @@ #include <sysutils/SocketClient.h> -SocketClient::SocketClient(int socket, bool owned) - : mSocket(socket) - , mSocketOwned(owned) - , mPid(-1) - , mUid(-1) - , mGid(-1) - , mRefCount(1) -{ +SocketClient::SocketClient(int socket, bool owned) { + init(socket, owned, false); +} + +SocketClient::SocketClient(int socket, bool owned, bool useCmdNum) { + init(socket, owned, useCmdNum); +} + +void SocketClient::init(int socket, bool owned, bool useCmdNum) { + mSocket = socket; + mSocketOwned = owned; + mUseCmdNum = useCmdNum; pthread_mutex_init(&mWriteMutex, NULL); pthread_mutex_init(&mRefCountMutex, NULL); + mPid = -1; + mUid = -1; + mGid = -1; + mRefCount = 1; + mCmdNum = 0; struct ucred creds; socklen_t szCreds = sizeof(creds); @@ -41,26 +50,32 @@ SocketClient::~SocketClient() } int SocketClient::sendMsg(int code, const char *msg, bool addErrno) { + return sendMsg(code, msg, addErrno, mUseCmdNum); +} + +int SocketClient::sendMsg(int code, const char *msg, bool addErrno, bool useCmdNum) { char *buf; - const char* arg; - const char* fmt; - char tmp[1]; - int len; + int ret = 0; if (addErrno) { - fmt = "%.3d %s (%s)"; - arg = strerror(errno); + if (useCmdNum) { + ret = asprintf(&buf, "%d %d %s (%s)", code, getCmdNum(), msg, strerror(errno)); + } else { + ret = asprintf(&buf, "%d %s (%s)", code, msg, strerror(errno)); + } } else { - fmt = "%.3d %s"; - arg = NULL; + if (useCmdNum) { + ret = asprintf(&buf, "%d %d %s", code, getCmdNum(), msg); + } else { + ret = asprintf(&buf, "%d %s", code, msg); + } } - /* Measure length of required buffer */ - len = snprintf(tmp, sizeof tmp, fmt, code, msg, arg); - /* Allocate in the stack, then write to it */ - buf = (char*)alloca(len+1); - snprintf(buf, len+1, fmt, code, msg, arg); /* Send the zero-terminated message */ - return sendMsg(buf); + if (ret != -1) { + ret = sendMsg(buf); + free(buf); + } + return ret; } int SocketClient::sendMsg(const char *msg) { diff --git a/libsysutils/src/SocketListener.cpp b/libsysutils/src/SocketListener.cpp index 3f871ea..0361641 100644 --- a/libsysutils/src/SocketListener.cpp +++ b/libsysutils/src/SocketListener.cpp @@ -29,18 +29,25 @@ #include <sysutils/SocketListener.h> #include <sysutils/SocketClient.h> +#define LOG_NDEBUG 0 + SocketListener::SocketListener(const char *socketName, bool listen) { - mListen = listen; - mSocketName = socketName; - mSock = -1; - pthread_mutex_init(&mClientsLock, NULL); - mClients = new SocketClientCollection(); + init(socketName, -1, listen, false); } SocketListener::SocketListener(int socketFd, bool listen) { + init(NULL, socketFd, listen, false); +} + +SocketListener::SocketListener(const char *socketName, bool listen, bool useCmdNum) { + init(socketName, -1, listen, useCmdNum); +} + +void SocketListener::init(const char *socketName, int socketFd, bool listen, bool useCmdNum) { mListen = listen; - mSocketName = NULL; + mSocketName = socketName; mSock = socketFd; + mUseCmdNum = useCmdNum; pthread_mutex_init(&mClientsLock, NULL); mClients = new SocketClientCollection(); } @@ -73,13 +80,14 @@ int SocketListener::startListener() { mSocketName, strerror(errno)); return -1; } + SLOGV("got mSock = %d for %s", mSock, mSocketName); } if (mListen && listen(mSock, 4) < 0) { SLOGE("Unable to listen on socket (%s)", strerror(errno)); return -1; } else if (!mListen) - mClients->push_back(new SocketClient(mSock, false)); + mClients->push_back(new SocketClient(mSock, false, mUseCmdNum)); if (pipe(mCtrlPipe)) { SLOGE("pipe failed (%s)", strerror(errno)); @@ -164,11 +172,11 @@ void SocketListener::runListener() { max = fd; } pthread_mutex_unlock(&mClientsLock); - + SLOGV("mListen=%d, max=%d, mSocketName=%s", mListen, max, mSocketName); if ((rc = select(max + 1, &read_fds, NULL, NULL, NULL)) < 0) { if (errno == EINTR) continue; - SLOGE("select failed (%s)", strerror(errno)); + SLOGE("select failed (%s) mListen=%d, max=%d", strerror(errno), mListen, max); sleep(1); continue; } else if (!rc) @@ -184,6 +192,7 @@ void SocketListener::runListener() { do { alen = sizeof(addr); c = accept(mSock, &addr, &alen); + SLOGV("%s got %d from accept", mSocketName, c); } while (c < 0 && errno == EINTR); if (c < 0) { SLOGE("accept failed (%s)", strerror(errno)); @@ -191,7 +200,7 @@ void SocketListener::runListener() { continue; } pthread_mutex_lock(&mClientsLock); - mClients->push_back(new SocketClient(c, true)); + mClients->push_back(new SocketClient(c, true, mUseCmdNum)); pthread_mutex_unlock(&mClientsLock); } @@ -217,6 +226,7 @@ void SocketListener::runListener() { * connection-based, remove and destroy it */ if (!onDataAvailable(c) && mListen) { /* Remove the client from our array */ + SLOGV("going to zap %d for %s", c->getSocket(), mSocketName); pthread_mutex_lock(&mClientsLock); for (it = mClients->begin(); it != mClients->end(); ++it) { if (*it == c) { @@ -238,19 +248,8 @@ void SocketListener::sendBroadcast(int code, const char *msg, bool addErrno) { SocketClientCollection::iterator i; for (i = mClients->begin(); i != mClients->end(); ++i) { - if ((*i)->sendMsg(code, msg, addErrno)) { - SLOGW("Error sending broadcast (%s)", strerror(errno)); - } - } - pthread_mutex_unlock(&mClientsLock); -} - -void SocketListener::sendBroadcast(const char *msg) { - pthread_mutex_lock(&mClientsLock); - SocketClientCollection::iterator i; - - for (i = mClients->begin(); i != mClients->end(); ++i) { - if ((*i)->sendMsg(msg)) { + // broadcasts are unsolicited and should not include a cmd number + if ((*i)->sendMsg(code, msg, addErrno, false)) { SLOGW("Error sending broadcast (%s)", strerror(errno)); } } |