libsysutils: New C++ system convenience library

        This library contains re-usable classes for common
    system level daemons. Initial consumers of this library
    are 'nexus' and 'vold2'

Signed-off-by: San Mehat <san@google.com>
diff --git a/Android.mk b/Android.mk
index 8b79ceb..fa2f6f8 100644
--- a/Android.mk
+++ b/Android.mk
@@ -21,6 +21,7 @@
   include $(addprefix $(LOCAL_PATH)/,$(addsuffix /Android.mk, \
 	      adb \
 	      libcutils \
+	      libsysutils \
 	      liblog \
 	      libnetutils \
 	      libpixelflinger \
diff --git a/include/sysutils/FrameworkCommand.h b/include/sysutils/FrameworkCommand.h
new file mode 100644
index 0000000..952e99a
--- /dev/null
+++ b/include/sysutils/FrameworkCommand.h
@@ -0,0 +1,37 @@
+/*
+ * 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 __FRAMEWORK_CMD_HANDLER_H
+#define __FRAMEWORK_CMD_HANDLER_H
+
+#include "../../../frameworks/base/include/utils/List.h"
+
+
+class FrameworkCommand { 
+private:
+    const char *mCommand;
+
+public:
+
+    FrameworkCommand(const char *cmd);
+    virtual ~FrameworkCommand() { }
+
+    virtual int runCommand(char *data);
+
+    const char *getCommand() { return mCommand; }
+};
+
+typedef android::List<FrameworkCommand *> FrameworkCommandCollection;
+#endif
diff --git a/include/sysutils/FrameworkListener.h b/include/sysutils/FrameworkListener.h
new file mode 100644
index 0000000..1454a6f
--- /dev/null
+++ b/include/sysutils/FrameworkListener.h
@@ -0,0 +1,37 @@
+/*
+ * 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 _FRAMEWORKSOCKETLISTENER_H
+#define _FRAMEWORKSOCKETLISTENER_H
+
+#include "SocketListener.h"
+#include "FrameworkCommand.h"
+
+class FrameworkListener : public SocketListener {
+private:
+    FrameworkCommandCollection *mCommands;
+
+public:
+    FrameworkListener(const char *socketName);
+    virtual ~FrameworkListener() {}
+
+protected:
+    void registerCmd(FrameworkCommand *cmd);
+    virtual bool onDataAvailable(int socket);
+
+private:
+    void dispatchCommand(char *cmd);
+};
+#endif
diff --git a/include/sysutils/FrameworkManager.h b/include/sysutils/FrameworkManager.h
new file mode 100644
index 0000000..8a24d33
--- /dev/null
+++ b/include/sysutils/FrameworkManager.h
@@ -0,0 +1,40 @@
+/*
+ * 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/NetlinkEvent.h b/include/sysutils/NetlinkEvent.h
new file mode 100644
index 0000000..95e83a3
--- /dev/null
+++ b/include/sysutils/NetlinkEvent.h
@@ -0,0 +1,44 @@
+/*
+ * 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 _NETLINKEVENT_H
+#define _NETLINKEVENT_H
+
+#define NL_PARAMS_MAX 32
+
+class NetlinkEvent {
+    int  mSeq;
+    char *mPath;
+    int  mAction;
+    char *mSubsystem;
+    char *mParams[NL_PARAMS_MAX];
+
+public:
+    const static int NlActionUnknown;
+    const static int NlActionAdd;
+    const static int NlActionRemove;
+    const static int NlActionChange;
+
+    NetlinkEvent();
+    virtual ~NetlinkEvent();
+
+    bool decode(char *buffer, int size);
+    const char *findParam(const char *paramName);
+
+    const char *getSubsystem() { return mSubsystem; }
+    int getAction() { return mAction; }
+};
+
+#endif
diff --git a/include/sysutils/NetlinkListener.h b/include/sysutils/NetlinkListener.h
new file mode 100644
index 0000000..8ac811c
--- /dev/null
+++ b/include/sysutils/NetlinkListener.h
@@ -0,0 +1,32 @@
+/*
+ * 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 _NETLINKLISTENER_H
+#define _NETLINKLISTENER_H
+
+#include "SocketListener.h"
+
+class NetlinkEvent;
+
+class NetlinkListener : public SocketListener {
+    char mBuffer[64 * 1024];
+
+public:
+    NetlinkListener(int socket);
+    virtual ~NetlinkListener() {}
+protected:
+    virtual bool onDataAvailable(int socket);
+};
+#endif
diff --git a/include/sysutils/SocketListener.h b/include/sysutils/SocketListener.h
new file mode 100644
index 0000000..f079dba
--- /dev/null
+++ b/include/sysutils/SocketListener.h
@@ -0,0 +1,35 @@
+/*
+ * 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 _SOCKETLISTENER_H
+#define _SOCKETLISTENER_H
+
+class SocketListener {
+    int mSock;
+    int mCsock;
+    int mAcceptClients;
+    const char *mSocketName;
+
+public:
+    SocketListener(const char *socketName, bool acceptClients);
+    SocketListener(int socketFd, bool acceptClients);
+
+    virtual ~SocketListener() {}
+    virtual int run();
+
+protected:
+    virtual bool onDataAvailable(int socket);
+};
+#endif
diff --git a/libsysutils/Android.mk b/libsysutils/Android.mk
new file mode 100644
index 0000000..0b15c12
--- /dev/null
+++ b/libsysutils/Android.mk
@@ -0,0 +1,21 @@
+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    \
+
+LOCAL_MODULE:= libsysutils
+
+LOCAL_C_INCLUDES := $(KERNEL_HEADERS) 
+
+LOCAL_CFLAGS := 
+
+LOCAL_SHARED_LIBRARIES := libcutils
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/libsysutils/src/FrameworkCommand.cpp b/libsysutils/src/FrameworkCommand.cpp
new file mode 100644
index 0000000..0444de5
--- /dev/null
+++ b/libsysutils/src/FrameworkCommand.cpp
@@ -0,0 +1,32 @@
+/*
+ * 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 <errno.h>
+
+#define LOG_TAG "FrameworkCommand"
+
+#include <cutils/log.h>
+
+#include <sysutils/FrameworkCommand.h>
+
+FrameworkCommand::FrameworkCommand(const char *cmd) {
+    mCommand = cmd;
+}
+
+int FrameworkCommand::runCommand(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
new file mode 100644
index 0000000..bbf3f3a
--- /dev/null
+++ b/libsysutils/src/FrameworkListener.cpp
@@ -0,0 +1,76 @@
+/*
+ * 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 <errno.h>
+
+#define LOG_TAG "FrameworkListener"
+
+#include <cutils/log.h>
+
+#include <sysutils/FrameworkListener.h>
+#include <sysutils/FrameworkCommand.h>
+
+FrameworkListener::FrameworkListener(const char *socketName) :
+                            SocketListener(socketName, true) {
+    mCommands = new FrameworkCommandCollection();
+}
+
+bool FrameworkListener::onDataAvailable(int socket) {
+    char buffer[101];
+    int len;
+
+    if ((len = read(socket, buffer, sizeof(buffer) -1)) < 0) {
+        LOGE("read() failed (%s)", strerror(errno));
+        return errno;
+    } else if (!len) {
+        LOGW("Lost connection to client");
+        return false;
+    }
+
+    int start = 0;
+    int i;
+
+    buffer[len] = '\0';
+
+    for (i = 0; i < len; i++) {
+        if (buffer[i] == '\0') {
+            dispatchCommand(buffer + start);
+            start = i + 1;
+        }
+    }
+    return true;
+}
+
+void FrameworkListener::registerCmd(FrameworkCommand *cmd) {
+    mCommands->push_back(cmd);
+}
+
+void FrameworkListener::dispatchCommand(char *cmd) {
+    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)) {
+                LOGW("Handler '%s' error (%s)", c->getCommand(), strerror(errno));
+            }
+            return;
+        }
+    }
+
+    LOGE("No cmd handlers defined for '%s'", cmd);
+}
+
diff --git a/libsysutils/src/FrameworkManager.cpp b/libsysutils/src/FrameworkManager.cpp
new file mode 100644
index 0000000..5dceb9f
--- /dev/null
+++ b/libsysutils/src/FrameworkManager.cpp
@@ -0,0 +1,83 @@
+/*
+ * 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/NetlinkEvent.cpp b/libsysutils/src/NetlinkEvent.cpp
new file mode 100644
index 0000000..69cd3e7
--- /dev/null
+++ b/libsysutils/src/NetlinkEvent.cpp
@@ -0,0 +1,93 @@
+/*
+ * 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 <stdlib.h>
+
+#define LOG_TAG "NetlinkEvent"
+#include <cutils/log.h>
+
+#include <sysutils/NetlinkEvent.h>
+
+const int NetlinkEvent::NlActionUnknown = 0;
+const int NetlinkEvent::NlActionAdd = 1;
+const int NetlinkEvent::NlActionRemove = 2;
+const int NetlinkEvent::NlActionChange = 3;
+
+NetlinkEvent::NetlinkEvent() {
+    mAction = NlActionUnknown;
+}
+
+NetlinkEvent::~NetlinkEvent() {
+    int i;
+    if (mPath)
+        free(mPath);
+    if (mSubsystem)
+        free(mSubsystem);
+    for (i = 0; i < NL_PARAMS_MAX; i++) {
+        if (!mParams[i])
+            break;
+        free(mParams[i]);
+    }
+}
+
+bool NetlinkEvent::decode(char *buffer, int size) {
+    char *s = buffer;
+    char *end;
+    int param_idx = 0;
+    int i;
+    int first = 1;
+
+    end = s + size;
+    while (s < end) {
+        if (first) {
+            char *p;
+            for (p = s; *p != '@'; p++);
+            p++;
+            mPath = strdup(p);
+            first = 0;
+        } else {
+            if (!strncmp(s, "ACTION=", strlen("ACTION="))) {
+                char *a = s + strlen("ACTION=");
+                if (!strcmp(a, "add"))
+                    mAction = NlActionAdd;
+                else if (!strcmp(a, "remove"))
+                    mAction = NlActionRemove;
+                else if (!strcmp(a, "change"))
+                    mAction = NlActionChange;
+            } else if (!strncmp(s, "SEQNUM=", strlen("SEQNUM="))) 
+                mSeq = atoi(s + strlen("SEQNUM="));
+            else if (!strncmp(s, "SUBSYSTEM=", strlen("SUBSYSTEM="))) 
+                mSubsystem = strdup(s + strlen("SUBSYSTEM="));
+            else
+                mParams[param_idx++] = strdup(s);
+        }
+        s+= strlen(s) + 1;
+    }
+    return true;
+}
+
+const char *NetlinkEvent::findParam(const char *paramName) {
+    int i;
+
+    for (i = 0; i < NL_PARAMS_MAX; i++) {
+        if (!mParams[i])
+            break;
+        if (!strncmp(mParams[i], paramName, strlen(paramName)))
+            return &mParams[i][strlen(paramName) + 1];
+    }
+
+    LOGE("NetlinkEvent::FindParam(): Parameter '%s' not found", paramName);
+    return NULL;
+}
diff --git a/libsysutils/src/NetlinkListener.cpp b/libsysutils/src/NetlinkListener.cpp
new file mode 100644
index 0000000..d871341
--- /dev/null
+++ b/libsysutils/src/NetlinkListener.cpp
@@ -0,0 +1,53 @@
+/*
+ * 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 <errno.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#define LOG_TAG "NetlinkListener"
+#include <cutils/log.h>
+
+#include <sysutils/NetlinkListener.h>
+#include <sysutils/NetlinkEvent.h>
+
+NetlinkListener::NetlinkListener(int socket) :
+                            SocketListener(socket, false) {
+}
+
+bool NetlinkListener::onDataAvailable(int socket)
+{
+    LOGD("NetlinkListener::onDataAvailable()");
+
+    int count;
+
+    if ((count = recv(socket, mBuffer, sizeof(mBuffer), 0)) < 0) {
+        LOGE("recv failed (%s)", strerror(errno));
+        return false;
+    }
+
+    NetlinkEvent *evt = new NetlinkEvent();
+    if (!evt->decode(mBuffer, count)) {
+        LOGE("Error decoding NetlinkEvent");
+        goto out;
+    }
+
+    LOGD("Ignoring '%s' netlink event", evt->getSubsystem());
+
+out:
+    delete evt;
+    return true;
+}
diff --git a/libsysutils/src/SocketListener.cpp b/libsysutils/src/SocketListener.cpp
new file mode 100644
index 0000000..f92e30d
--- /dev/null
+++ b/libsysutils/src/SocketListener.cpp
@@ -0,0 +1,127 @@
+/*
+ * 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>
+
+#define LOG_TAG "SocketListener"
+#include <cutils/log.h>
+
+#include <cutils/sockets.h>
+
+#include <sysutils/SocketListener.h>
+
+SocketListener::SocketListener(const char *socketName, bool acceptClients) {
+    mAcceptClients = acceptClients;
+    mCsock = -1;
+    mSocketName = socketName;
+    mSock = -1;
+}
+
+SocketListener::SocketListener(int socketFd, bool acceptClients) {
+    mAcceptClients = acceptClients;
+    mCsock = -1;
+    mSocketName = NULL;
+    mSock = socketFd;
+}
+
+int SocketListener::run() {
+
+    if (!mSocketName && mSock == -1) {
+        errno = EINVAL;
+        return -1;
+    } else if (mSocketName) {
+        if ((mSock = android_get_control_socket(mSocketName)) < 0) {
+            LOGE("Obtaining file descriptor socket '%s' failed: %s",
+                 mSocketName, strerror(errno));
+            return -1;
+        }
+    }
+
+    if (mAcceptClients) {
+        if (listen(mSock, 4) < 0) {
+            LOGE("Unable to listen on socket (%s)", strerror(errno));
+            return -1;
+        }
+    }
+
+    while(1) {
+        fd_set read_fds;
+        struct timeval to;
+        int max = 0;
+        int rc = 0;
+
+        to.tv_sec = 60 * 60;
+        to.tv_usec = 0;
+
+        FD_ZERO(&read_fds);
+
+        if ((mAcceptClients == false) ||
+            (mAcceptClients == true && mCsock == -1)) {
+            FD_SET(mSock, &read_fds);
+            max = mSock;
+        } else if (mCsock != -1) {
+            FD_SET(mCsock, &read_fds);
+            max = mCsock;
+        }
+
+        if ((rc = select(max + 1, &read_fds, NULL, NULL, &to)) < 0) {
+            LOGE("select failed (%s)", strerror(errno));
+            return -errno;
+        } else if (!rc)
+            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 ((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;
+            }
+    }
+    return 0;
+}
+
+bool SocketListener::onDataAvailable(int socket) {
+    return false;
+}