Merge pull request #1344 from wolfmanjm/upstreamedge
[clinton/Smoothieware.git] / src / libs / Network / uip / Network.cpp
index c7aa6ea..3a12df1 100644 (file)
@@ -24,6 +24,9 @@
 #include "dhcpc.h"
 #include "sftpd.h"
 
+#ifndef NOPLAN9
+#include "plan9.h"
+#endif
 
 #include <mri.h>
 
 #define network_enable_checksum CHECKSUM("enable")
 #define network_webserver_checksum CHECKSUM("webserver")
 #define network_telnet_checksum CHECKSUM("telnet")
+#define network_plan9_checksum CHECKSUM("plan9")
 #define network_mac_override_checksum CHECKSUM("mac_override")
 #define network_ip_address_checksum CHECKSUM("ip_address")
+#define network_hostname_checksum CHECKSUM("hostname")
 #define network_ip_gateway_checksum CHECKSUM("ip_gateway")
 #define network_ip_mask_checksum CHECKSUM("ip_mask")
 
@@ -42,24 +47,26 @@ extern "C" void uip_log(char *m)
     printf("uIP log message: %s\n", m);
 }
 
-static bool webserver_enabled, telnet_enabled, use_dhcp;
-static Network *theNetwork;
-static Sftpd *sftpd;
-static CommandQueue *command_q= CommandQueue::getInstance();
+static Network* theNetwork;
 
-Network* Network::instance;
 Network::Network()
 {
+    theNetwork= this;
     ethernet = new LPC17XX_Ethernet();
     tickcnt= 0;
-    theNetwork= this;
     sftpd= NULL;
-    instance= this;
+    hostname = NULL;
+    plan9_enabled= false;
+    command_q= CommandQueue::getInstance();
 }
 
 Network::~Network()
 {
     delete ethernet;
+    if (hostname != NULL) {
+        delete hostname;
+    }
+    theNetwork= nullptr;
 }
 
 static uint32_t getSerialNumberHash()
@@ -78,7 +85,7 @@ static uint32_t getSerialNumberHash()
     return crc32((uint8_t *)&result[1], 4 * 4);
 }
 
-static bool parse_ip_str(const string &s, uint8_t *a, int len, char sep = '.')
+static bool parse_ip_str(const string &s, uint8_t *a, int len, int base=10, char sep = '.')
 {
     int p = 0;
     const char *n;
@@ -91,7 +98,25 @@ static bool parse_ip_str(const string &s, uint8_t *a, int len, char sep = '.')
         } else {
             n = s.substr(p).c_str();
         }
-        a[i] = atoi(n);
+        a[i] = (int)strtol(n, NULL, base);
+    }
+    return true;
+}
+
+static bool parse_hostname(const string &s)
+{
+    const std::string::size_type str_len = s.size();
+    if(str_len > 63){
+        return false;
+    }
+    for (unsigned int i = 0; i < str_len; i++) {
+        const char c = s.at(i);
+        if(!(c >= 'a' && c <= 'z')
+                && !(c >= 'A' && c <= 'Z')
+                && !(i != 0 && c >= '0' && c <= '9')
+                && !(i != 0 && i != str_len - 1 && c == '-')){
+            return false;
+        }
     }
     return true;
 }
@@ -106,10 +131,10 @@ void Network::on_module_loaded()
 
     webserver_enabled = THEKERNEL->config->value( network_checksum, network_webserver_checksum, network_enable_checksum )->by_default(false)->as_bool();
     telnet_enabled = THEKERNEL->config->value( network_checksum, network_telnet_checksum, network_enable_checksum )->by_default(false)->as_bool();
-
+    plan9_enabled = THEKERNEL->config->value( network_checksum, network_plan9_checksum, network_enable_checksum )->by_default(false)->as_bool();
     string mac = THEKERNEL->config->value( network_checksum, network_mac_override_checksum )->by_default("")->as_string();
     if (mac.size() == 17 ) { // parse mac address
-        if (!parse_ip_str(mac, mac_address, 6, ':')) {
+        if (!parse_ip_str(mac, mac_address, 6, 16, ':')) {
             printf("Invalid MAC address: %s\n", mac.c_str());
             printf("Network not started due to errors in config");
             return;
@@ -128,12 +153,20 @@ void Network::on_module_loaded()
     ethernet->set_mac(mac_address);
 
     // get IP address, mask and gateway address here....
-    bool bad = false;
     string s = THEKERNEL->config->value( network_checksum, network_ip_address_checksum )->by_default("auto")->as_string();
     if (s == "auto") {
         use_dhcp = true;
-
+        s = THEKERNEL->config->value( network_checksum, network_hostname_checksum )->as_string();
+        if (!s.empty()) {
+            if(parse_hostname(s)){
+                hostname = new char [s.length() + 1];
+                strcpy(hostname, s.c_str());
+            }else{
+                printf("Invalid hostname: %s\n", s.c_str());
+            }
+        }
     } else {
+        bool bad = false;
         use_dhcp = false;
         if (!parse_ip_str(s, ipaddr, 4)) {
             printf("Invalid IP address: %s\n", s.c_str());
@@ -149,7 +182,6 @@ void Network::on_module_loaded()
             printf("Invalid IP gateway: %s\n", s.c_str());
             bad = true;
         }
-
         if (bad) {
             printf("Network not started due to errors in config");
             return;
@@ -203,7 +235,7 @@ void Network::on_idle(void *argument)
 {
     if (!ethernet->isUp()) return;
 
-    int len;
+    int len= sizeof(uip_buf); // set maximum size
     if (ethernet->_receive_frame(uip_buf, &len)) {
         uip_len = len;
         this->handlePacket();
@@ -260,7 +292,7 @@ void Network::on_idle(void *argument)
     }
 }
 
-static void setup_servers()
+void Network::setup_servers()
 {
     if (webserver_enabled) {
         // Initialize the HTTP server, listen to port 80.
@@ -274,6 +306,14 @@ static void setup_servers()
         printf("Telnetd initialized\n");
     }
 
+#ifndef NOPLAN9
+    if (plan9_enabled) {
+        // Initialize the plan9 server
+        Plan9::init();
+        printf("Plan9 initialized\n");
+    }
+#endif
+
     // sftpd service, which is lazily created on reciept of first packet
     uip_listen(HTONS(115));
 }
@@ -338,7 +378,7 @@ void Network::init(void)
 
     }else{
     #if UIP_CONF_UDP
-        dhcpc_init(mac_address, sizeof(mac_address));
+        dhcpc_init(mac_address, sizeof(mac_address), hostname);
         dhcpc_request();
         printf("Getting IP address....\n");
     #endif
@@ -348,9 +388,18 @@ void Network::init(void)
 void Network::on_main_loop(void *argument)
 {
     // issue commands here if any available
-    while(command_q->pop()) {
-        // keep feeding them until empty
-    }
+    // while(command_q->pop()) {
+    //     // keep feeding them until empty
+    // }
+
+    // issue one comamnd per iteration of main loop like USB serial does
+    command_q->pop();
+
+}
+
+extern "C" const char *get_query_string()
+{
+    return THEKERNEL->get_query_string().c_str();
 }
 
 // select between webserver and telnetd server
@@ -358,20 +407,26 @@ extern "C" void app_select_appcall(void)
 {
     switch (uip_conn->lport) {
         case HTONS(80):
-            if (webserver_enabled) httpd_appcall();
+            if (theNetwork->webserver_enabled) httpd_appcall();
             break;
 
         case HTONS(23):
-            if (telnet_enabled) Telnetd::appcall();
+            if (theNetwork->telnet_enabled) Telnetd::appcall();
             break;
 
+#ifndef NOPLAN9
+        case HTONS(564):
+            if (theNetwork->plan9_enabled) Plan9::appcall();
+            break;
+#endif
+
         case HTONS(115):
-            if(sftpd == NULL) {
-                sftpd= new Sftpd();
-                sftpd->init();
+            if(theNetwork->sftpd == NULL) {
+                theNetwork->sftpd= new Sftpd();
+                theNetwork->sftpd->init();
                 printf("Created sftpd service\n");
             }
-            sftpd->appcall();
+            theNetwork->sftpd->appcall();
             break;
 
         default: