nexus: Move to a line based protocol (similar to FTP) + fix bugs

Signed-off-by: San Mehat <san@google.com>
diff --git a/nexus/CommandListener.cpp b/nexus/CommandListener.cpp
index 02ede15..e9a358c 100644
--- a/nexus/CommandListener.cpp
+++ b/nexus/CommandListener.cpp
@@ -47,11 +47,11 @@
                
 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));
-
-    cli->sendMsg(buffer);
+    if (c->enable())
+        cli->sendMsg(400, "Failed to enable wifi", true);
+    else
+        cli->sendMsg(200, "Wifi Enabled", false);
     return 0;
 }
 
@@ -61,10 +61,11 @@
                
 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));
-    cli->sendMsg(buffer);
+    if (c->disable())
+        cli->sendMsg(400, "Failed to disable wifi", true);
+    else
+        cli->sendMsg(200, "Wifi Disabled", false);
     return 0;
 }
 
@@ -77,7 +78,6 @@
 
     WifiController *wc = (WifiController *) NetworkManager::Instance()->findController("WIFI");
 
-    char buffer[32];
     int mode = 0;
     char *bword, *last;
 
@@ -93,8 +93,11 @@
 
     mode = atoi(bword);
 
-    sprintf(buffer, "WIFI_SCAN:%d", (wc->setScanMode(mode) ? errno : 0));
-    cli->sendMsg(buffer);
+    if (wc->setScanMode(mode))
+        cli->sendMsg(400, "Failed to set scan mode", true);
+    else
+        cli->sendMsg(200, "Scan mode set", false);
+
     return 0;
 }
 
@@ -112,16 +115,16 @@
     char buffer[256];
     
     for(it = src->begin(); it != src->end(); ++it) {
-        sprintf(buffer, "WIFI_SCAN_RESULT:%s:%u:%d:%s:%s",
+        sprintf(buffer, "%s:%u:%d:%s:%s",
                 (*it)->getBssid(), (*it)->getFreq(), (*it)->getLevel(),
                 (*it)->getFlags(), (*it)->getSsid());
-        cli->sendMsg(buffer);
+        cli->sendMsg(125, buffer, false);
         delete (*it);
         it = src->erase(it);
     }
 
     delete src;
-    cli->sendMsg("WIFI_SCAN_RESULT:0");
+    cli->sendMsg(200, "Scan results complete", false);
     return 0;
 }
 
@@ -134,10 +137,11 @@
                
 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));
-    cli->sendMsg(buffer);
+    if (c->enable())
+        cli->sendMsg(400, "Failed to enable VPN", true);
+    else
+        cli->sendMsg(200, "VPN enabled", false);
     return 0;
 }
 
@@ -147,9 +151,10 @@
                
 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));
-    cli->sendMsg(buffer);
+    if (c->disable())
+        cli->sendMsg(400, "Failed to disable VPN", true);
+    else
+        cli->sendMsg(200, "VPN disabled", false);
     return 0;
 }
diff --git a/nexus/ScanResult.cpp b/nexus/ScanResult.cpp
index b7237b5..dc7599a 100644
--- a/nexus/ScanResult.cpp
+++ b/nexus/ScanResult.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 #include <stdlib.h>
+#include <ctype.h>
 
 #define LOG_TAG "ScanResult"
 #include <cutils/log.h>
@@ -24,30 +25,53 @@
 }
 
 ScanResult::ScanResult(char *rawResult) {
-    char *tok, *next = NULL;
+    char *p = rawResult, *q = rawResult;
+    char tmp[255];
 
-    if (!(tok = strtok_r(rawResult, "\t", &next)))
-        goto out_bad;
-    mBssid = strdup(tok);
+    // BSSID
+    for (q = p; *q != '\t'; ++q);
+    strncpy(tmp, p, (q - p));
+    tmp[q-p] = '\0';
+    mBssid = strdup(tmp);
+    ++q;
 
-    if (!(tok = strtok_r(NULL, "\t", &next)))
-        goto out_bad;
-    mFreq = atoi(tok);
+    // FREQ
+    for (p = q; *q != '\t'; ++q);
+    strncpy(tmp, p, (q - p));
+    tmp[q-p] = '\0';
+    mFreq = atoi(tmp);
+    ++q;
 
-    if (!(tok = strtok_r(NULL, "\t", &next)))
-        goto out_bad;
-    mLevel = atoi(tok);
+    // LEVEL 
+    for (p = q; *q != '\t'; ++q);
+    strncpy(tmp, p, (q - p));
+    tmp[q-p] = '\0';
+    mLevel = atoi(tmp);
+    ++q;
 
-    if (!(tok = strtok_r(rawResult, "\t", &next)))
-        goto out_bad;
-    mFlags = strdup(tok);
+    // FLAGS
+    for (p = q; *q != '\t'; ++q);
+    strncpy(tmp, p, (q - p));
+    tmp[q-p] = '\0';
+    mFlags = strdup(tmp);
+    ++q;
 
-    if (!(tok = strtok_r(rawResult, "\t", &next)))
-        goto out_bad;
-    mSsid = strdup(tok);
+    // XXX: For some reason Supplicant sometimes sends a double-tab here.
+    // haven't had time to dig into it ...
+    if (*q == '\t')
+        q++;
+ 
+    for (p = q; *q != '\t'; ++q) {
+        if (*q == '\0')
+            break;
+    }
+
+    strncpy(tmp, p, (q - p));
+    tmp[q-p] = '\0';
+    mSsid = strdup(tmp);
+    ++q;
 
     return;
-
  out_bad:
     LOGW("Malformatted scan result (%s)", rawResult);
 }
diff --git a/nexus/Supplicant.cpp b/nexus/Supplicant.cpp
index d809e6e..63ab503 100644
--- a/nexus/Supplicant.cpp
+++ b/nexus/Supplicant.cpp
@@ -15,12 +15,16 @@
  */
 
 #include <stdlib.h>
+#include <sys/types.h>
+#include <fcntl.h>
 #include <errno.h>
 
 #define LOG_TAG "Supplicant"
 #include <cutils/log.h>
 #include <cutils/properties.h>
 
+#include "private/android_filesystem_config.h"
+
 #undef HAVE_LIBC_SYSTEM_PROPERTIES
 
 #ifdef HAVE_LIBC_SYSTEM_PROPERTIES
@@ -41,6 +45,9 @@
 #define DRIVER_PROP_NAME "wlan.driver.status"
 #define SUPPLICANT_NAME  "wpa_supplicant"
 #define SUPP_PROP_NAME   "init.svc.wpa_supplicant"
+#define SUPP_CONFIG_TEMPLATE "/system/etc/wifi/wpa_supplicant.conf"
+#define SUPP_CONFIG_FILE "/data/misc/wifi/wpa_supplicant.conf"
+
 
 Supplicant::Supplicant() {
     mCtrl = NULL;
@@ -55,7 +62,10 @@
 }
 
 int Supplicant::start() {
-    // XXX: Validate supplicant config file
+
+    if (setupConfig()) {
+        LOGW("Unable to setup supplicant.conf");
+    }
     
     char status[PROPERTY_VALUE_MAX] = {'\0'};
     int count = 200;
@@ -66,7 +76,6 @@
 
     if (property_get(SUPP_PROP_NAME, status, NULL) &&
         !strcmp(status, "running")) {
-        LOGD("Supplicant already started");
     } else {
 #ifdef HAVE_LIBC_SYSTEM_PROPERTIES
         pi = __system_property_find(SUPP_PROP_NAME);
@@ -93,7 +102,7 @@
             }
 #else
             if (property_get(SUPP_PROP_NAME, status, NULL)) {
-                if (strcmp(status, "running") == 0)
+                if (!strcmp(status, "running"))
                     break;
             }
 #endif
@@ -348,9 +357,9 @@
         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);
+        char tmp[128];
+        sprintf(tmp, "%d scan results ready", mLatestScanResults->size());
+        NetworkManager::Instance()->getBroadcaster()->sendBroadcast(600, tmp, false);
         pthread_mutex_unlock(&mLatestScanResultsLock);
         free(reply);
     } else {
@@ -403,4 +412,52 @@
 
     pthread_mutex_unlock(&mLatestScanResultsLock);
     return d;
-};
+}
+
+int Supplicant::setupConfig() {
+    char buf[2048];
+    int srcfd, destfd;
+    int nread;
+
+    if (access(SUPP_CONFIG_FILE, R_OK|W_OK) == 0) {
+        return 0;
+    } else if (errno != ENOENT) {
+        LOGE("Cannot access \"%s\": %s", SUPP_CONFIG_FILE, strerror(errno));
+        return -1;
+    }
+
+    srcfd = open(SUPP_CONFIG_TEMPLATE, O_RDONLY);
+    if (srcfd < 0) {
+        LOGE("Cannot open \"%s\": %s", SUPP_CONFIG_TEMPLATE, strerror(errno));
+        return -1;
+    }
+
+    destfd = open(SUPP_CONFIG_FILE, O_CREAT|O_WRONLY, 0660);
+    if (destfd < 0) {
+        close(srcfd);
+        LOGE("Cannot create \"%s\": %s", SUPP_CONFIG_FILE, strerror(errno));
+        return -1;
+    }
+
+    while ((nread = read(srcfd, buf, sizeof(buf))) != 0) {
+        if (nread < 0) {
+            LOGE("Error reading \"%s\": %s", SUPP_CONFIG_TEMPLATE, strerror(errno));
+            close(srcfd);
+            close(destfd);
+            unlink(SUPP_CONFIG_FILE);
+            return -1;
+        }
+        write(destfd, buf, nread);
+    }
+
+    close(destfd);
+    close(srcfd);
+
+    if (chown(SUPP_CONFIG_FILE, AID_SYSTEM, AID_WIFI) < 0) {
+        LOGE("Error changing group ownership of %s to %d: %s",
+             SUPP_CONFIG_FILE, AID_WIFI, strerror(errno));
+        unlink(SUPP_CONFIG_FILE);
+        return -1;
+    }
+    return 0;
+}
diff --git a/nexus/Supplicant.h b/nexus/Supplicant.h
index 2a25ea2..3a79623 100644
--- a/nexus/Supplicant.h
+++ b/nexus/Supplicant.h
@@ -67,6 +67,7 @@
 private:
     int connectToSupplicant();
     int sendCommand(const char *cmd, char *reply, size_t *reply_len);
+    int setupConfig();
 };
 
 #endif
diff --git a/nexus/TiwlanWifiController.cpp b/nexus/TiwlanWifiController.cpp
index 10606a1..2dc1eb3 100644
--- a/nexus/TiwlanWifiController.cpp
+++ b/nexus/TiwlanWifiController.cpp
@@ -67,15 +67,6 @@
 }
 
 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);
+    // Always load the firmware
     return false;
 }
diff --git a/nexus/WifiController.cpp b/nexus/WifiController.cpp
index 806141c..cba00ec 100644
--- a/nexus/WifiController.cpp
+++ b/nexus/WifiController.cpp
@@ -93,11 +93,8 @@
     return -1;
 }
 
-void WifiController::sendStatusBroadcast(const char *msg) {
-    char tmp[255];
-
-    sprintf(tmp, "WIFI_STATUS:%s", msg);
-    NetworkManager::Instance()->getBroadcaster()->sendBroadcast(tmp);
+void WifiController::sendStatusBroadcast(char *msg) {
+    NetworkManager::Instance()->getBroadcaster()->sendBroadcast(600, msg, false);
 }
 
 int WifiController::disable() {
diff --git a/nexus/WifiController.h b/nexus/WifiController.h
index 38aea81..ba26cb8 100644
--- a/nexus/WifiController.h
+++ b/nexus/WifiController.h
@@ -77,7 +77,7 @@
     virtual bool isFirmwareLoaded() = 0;
     virtual bool isPoweredUp() = 0;
 
-    void sendStatusBroadcast(const char *msg);
+    void sendStatusBroadcast(char *msg);
 };
 
 #endif
diff --git a/nexus/main.cpp b/nexus/main.cpp
index 0a0b43f..9945034 100644
--- a/nexus/main.cpp
+++ b/nexus/main.cpp
@@ -54,6 +54,8 @@
         exit (1);
     }
 
+    // XXX: we'll use the main thread for the NetworkManager eventuall
+    
     while(1) {
         sleep(1000);
     }
diff --git a/nexus/nexctl.c b/nexus/nexctl.c
index c326558..4ad73c4 100644
--- a/nexus/nexctl.c
+++ b/nexus/nexctl.c
@@ -31,10 +31,6 @@
 
 #include <private/android_filesystem_config.h>
 
-static void signal_handler(int sig) {
-    fprintf(stdout, "{ interrupt! }\n");
-}
-
 int main(int argc, char **argv) {
     int sock;
 
@@ -47,56 +43,81 @@
 
     printf("Connected to nexus\n");
 
+    char line[255];
+    char *buffer = malloc(4096);
+    int cursor = 0;
+    int col = 0;
+
     while(1) {
         fd_set read_fds;
         struct timeval to;
         int rc = 0;
 
-        signal(SIGINT, SIG_DFL);
-
-        printf("-> ");
-        fflush(stdout);
-
-        char buffer[255];
-        if (!fgets(buffer, sizeof(buffer) -1, stdin)) {
-            printf("Exiting...\n");
-            exit(0);
-        }
-
-        buffer[strlen(buffer) -1] = 0;
-
-        if (write(sock, buffer, strlen(buffer) +1) < 0) {
-            fprintf(stderr, "Error writing data (%s)\n", strerror(errno));
-            exit(2);
-        }
-
-wait:
         to.tv_sec = 10;
         to.tv_usec = 0;
+
         FD_ZERO(&read_fds);
         FD_SET(sock, &read_fds);
+        FD_SET(0, &read_fds);
+
+        if (col == 0) {
+            fprintf(stdout, "-> ");
+            fflush(stdout);
+            col = 3;
+        }
     
-        signal(SIGINT, signal_handler);
-     
         if ((rc = select(sock +1, &read_fds, NULL, NULL, &to)) < 0) {
-            if (errno == EINTR)
-                continue;
             fprintf(stderr, "Error in select (%s)\n", strerror(errno));
             exit(2);
         } else if (!rc) {
-            printf("{response timeout}\n");
             continue;
         } else if (FD_ISSET(sock, &read_fds)) {
-             if ((rc = read(sock, buffer, sizeof(buffer)-1)) <= 0) {
+            memset(buffer, 0, 4096);
+            if ((rc = read(sock, buffer, 4096)) <= 0) {
                  fprintf(stderr, "Error reading response (%s)\n", strerror(errno));
                  exit(2);
-             }
-            printf(" %s\n", buffer);
-            goto wait;
+            }
+            int i;
+            for (i = 0; i < col; i++) {
+                fprintf(stdout, "%c", 8);
+            }
+
+            printf("%s", buffer);
+            printf("-> ");
+            for (i = 0; i < cursor; i++) {
+                fprintf(stdout, "%c", line[i]);
+            }
+            fflush(stdout);
+        } else if (FD_ISSET(0, &read_fds)) {
+            char c;
+
+            if ((rc = read(0, &c, 1)) < 0) {
+                fprintf(stderr, "Error reading from terminal (%s)\n", strerror(errno));
+                exit(2);
+            } else if (!rc) {
+                fprintf(stderr, "0 length read from terminal\n");
+                exit(2);
+            }
+
+            fprintf(stdout, "%c", c);
+            fflush(stdout);
+
+            line[cursor] = c;
+
+            if (c == '\n') {
+                if ((rc = write(sock, line, strlen(line))) < 0) {
+                    fprintf(stderr, "Error writing to nexus (%s)\n", strerror(errno));
+                    exit(2);
+                }
+                memset(line, 0, sizeof(line));
+                cursor = 0;
+                col = 0;
+            } else {
+                cursor++;
+                col++;
+            }
         }
     }
 
-
     exit(0);
-
 }