netd: Add skelaton support for throttling

Change-Id: I361f3c4ac30f7bb6efe4ed703405f0e843b075b4
Signed-off-by: San Mehat <san@google.com>
diff --git a/CommandListener.cpp b/CommandListener.cpp
index b04ec81..4b0b56e 100644
--- a/CommandListener.cpp
+++ b/CommandListener.cpp
@@ -101,6 +101,59 @@
         closedir(d);
         cli->sendMsg(ResponseCode::CommandOkay, "Interface list completed", false);
         return 0;
+    } else if (!strcmp(argv[1], "readrxcounter")) {
+        if (argc != 3) {
+            cli->sendMsg(ResponseCode::CommandSyntaxError,
+                    "Usage: interface readrxcounter <interface>", false);
+            return 0;
+        }
+        unsigned long rx = 0, tx = 0;
+        if (readInterfaceCounters(argv[2], &rx, &tx)) {
+            cli->sendMsg(ResponseCode::OperationFailed, "Failed to read counters", true);
+            return 0;
+        }
+
+        char *msg;
+        asprintf(&msg, "%lu", rx);
+        cli->sendMsg(ResponseCode::InterfaceRxCounterResult, msg, false);
+        free(msg);
+
+        return 0;
+    } else if (!strcmp(argv[1], "readtxcounter")) {
+        if (argc != 3) {
+            cli->sendMsg(ResponseCode::CommandSyntaxError,
+                    "Usage: interface readtxcounter <interface>", false);
+            return 0;
+        }
+        unsigned long rx = 0, tx = 0;
+        if (readInterfaceCounters(argv[2], &rx, &tx)) {
+            cli->sendMsg(ResponseCode::OperationFailed, "Failed to read counters", true);
+            return 0;
+        }
+
+        char *msg = NULL;
+        asprintf(&msg, "%lu", tx);
+        cli->sendMsg(ResponseCode::InterfaceTxCounterResult, msg, false);
+        free(msg);
+        return 0;
+    } else if (!strcmp(argv[1], "getthrottle")) {
+        if (argc != 4) {
+            cli->sendMsg(ResponseCode::CommandSyntaxError,
+                    "Usage: interface getthrottle <interface> <rx|tx>", false);
+            return 0;
+        }
+        errno = ENOSYS;
+        cli->sendMsg(ResponseCode::OperationFailed, "Not Implemented", true);
+        return 0;
+    } else if (!strcmp(argv[1], "setthrottle")) {
+        if (argc != 5) {
+            cli->sendMsg(ResponseCode::CommandSyntaxError,
+                    "Usage: interface getthrottle <interface> <rx|tx> <kbps>", false);
+            return 0;
+        }
+        errno = ENOSYS;
+        cli->sendMsg(ResponseCode::OperationFailed, "Not Implemented", true);
+        return 0;
     } else {
         /*
          * These commands take a minimum of 3 arguments
@@ -595,3 +648,35 @@
 
     return 0;
 }
+
+int CommandListener::readInterfaceCounters(const char *iface, unsigned long *rx, unsigned long *tx) {
+    FILE *fp = fopen("/proc/net/dev", "r");
+    if (!fp) {
+        LOGE("Failed to open /proc/net/dev (%s)", strerror(errno));
+        return -1;
+    }
+
+    char buffer[512];
+
+    fgets(buffer, sizeof(buffer), fp); // Header 1
+    fgets(buffer, sizeof(buffer), fp); // Header 2
+    while(fgets(buffer, sizeof(buffer), fp)) {
+        buffer[strlen(buffer)-1] = '\0';
+
+        char name[8];
+        unsigned long d;
+        sscanf(buffer, "%6s %8lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu %8lu",
+                name, rx, &d, &d, &d, &d, &d, &d, &d, tx);
+        name[strlen(name)-1] = '\0';
+
+        if (strcmp(name, iface)) {
+            continue;
+        }
+        fclose(fp);
+        return 0;
+    }
+
+    fclose(fp);
+    errno = ENOENT;
+    return -1;
+}
diff --git a/CommandListener.h b/CommandListener.h
index 4dc77f9..2f40474 100644
--- a/CommandListener.h
+++ b/CommandListener.h
@@ -41,6 +41,8 @@
 
 private:
 
+    static int readInterfaceCounters(const char *iface, unsigned long *rx, unsigned long *tx);
+
     class UsbCmd : public NetdCommand {
     public:
         UsbCmd();
diff --git a/ResponseCode.h b/ResponseCode.h
index 9e52cec..320b6a4 100644
--- a/ResponseCode.h
+++ b/ResponseCode.h
@@ -29,13 +29,17 @@
 
 
     // 200 series - Requested action has been successfully completed
-    static const int CommandOkay              = 200;
-    static const int TetherStatusResult       = 210;
-    static const int IpFwdStatusResult        = 211;
-    static const int PanStatusResult          = 212;
-    static const int InterfaceGetCfgResult    = 213;
-    static const int SoftapStatusResult       = 214;
-    static const int UsbRNDISStatusResult     = 215;
+    static const int CommandOkay               = 200;
+    static const int TetherStatusResult        = 210;
+    static const int IpFwdStatusResult         = 211;
+    static const int PanStatusResult           = 212;
+    static const int InterfaceGetCfgResult     = 213;
+    static const int SoftapStatusResult        = 214;
+    static const int UsbRNDISStatusResult      = 215;
+    static const int InterfaceRxCounterResult  = 216;
+    static const int InterfaceTxCounterResult  = 217;
+    static const int InterfaceRxThrottleResult = 218;
+    static const int InterfaceTxThrottleResult = 219;
 
     // 400 series - The command was accepted but the requested action
     // did not take place.