Simple HTTP Server with support for SD Card file serving and CGI commands

Dependencies:   EthernetInterface TCPEchoServer SDFileSystem mbed-rtos mbed

Fork of TCPEchoServer by mbed official

Files at this revision

API Documentation at this revision

Comitter:
gsteiert
Date:
Sat Apr 06 06:09:22 2013 +0000
Parent:
5:0f0fdadab553
Commit message:
This is a functional web server with SD card file serving and cgi I2C commands

Changed in this revision

HTTPDworking.lib Show annotated file Show diff for this revision Revisions of this file
SDFileSystem.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HTTPDworking.lib	Sat Apr 06 06:09:22 2013 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/TCPEchoServer/#0f0fdadab553
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SDFileSystem.lib	Sat Apr 06 06:09:22 2013 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/SDFileSystem/#c8f66dc765d4
--- a/main.cpp	Fri Mar 01 15:37:15 2013 +0000
+++ b/main.cpp	Sat Apr 06 06:09:22 2013 +0000
@@ -1,34 +1,257 @@
 #include "mbed.h"
 #include "EthernetInterface.h"
+#include "SDFileSystem.h"
+#include <stdio.h>
+#include <string.h>
 
-#define ECHO_SERVER_PORT   7
+#define HTTPD_SERVER_PORT   80
+#define HTTPD_MAX_REQ_LENGTH   1023
+#define HTTPD_MAX_HDR_LENGTH   255
+#define HTTPD_MAX_FNAME_LENGTH   127
+#define I2C_BUFFER_SIZE 63
+
+SDFileSystem sd(p5, p6, p7, p8, "sd"); //
+I2C i2c(p28, p27);
+EthernetInterface eth;
+TCPSocketServer server;
+TCPSocketConnection client;
+
+char buffer[HTTPD_MAX_REQ_LENGTH+1];
+char httpHeader[HTTPD_MAX_HDR_LENGTH+1];
+char filename[HTTPD_MAX_FNAME_LENGTH+1];
+char data[I2C_BUFFER_SIZE];
+char *uristr;
+char *eou;
+char *qrystr;
+
+FILE *fp;
+int rdCnt;
+
+void cmd_i2c_write(char* qry)
+{
+    int addr = 0;
+    int dlen = 0;
+    int dtmp = 0;
+    if (sscanf(qry, "%2x", &addr) == 1) {
+        qry += 2;
+        printf("Addr: %x Data: ", addr);
+        while (sscanf(qry, "&%2x", &dtmp) == 1) {
+            data[dlen] = dtmp;
+            qry +=3;
+            dlen +=1;
+            printf("%x ", dtmp);
+        }
+        printf("Bytes: %d\r\n ", dlen);
+    } else {
+        dlen = -1;
+        printf("Invalid address: %s\r\n", qry);
+    }
+    if (dlen > 0 ) {
+        printf("Write %d bytes to %x\r\n", dlen, addr);
+        i2c.write(addr, data, dlen);
+    }
+    sprintf(httpHeader,"HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: Close\r\n\r\n%d", dlen);
+    client.send(httpHeader,strlen(httpHeader));
+}
+
+void cmd_i2c_read(char* qry)
+{
+    int addr = 0;
+    int dlen = 0;
+    if (sscanf(qry, "%2x", &addr) == 1) {
+        qry += 2;
+        printf("Read from addr %x ", addr);
+        if (sscanf(qry, "&%2x", &dlen) == 1) {
+            if (i2c.read(addr, data, dlen)!=0) {
+                dlen = -1;
+                printf("failed\r\n");
+            } else {
+                printf("%d bytes\r\n ", dlen);
+            }
+        } else {
+            printf("\r\nInvalid data length: %s\r\n", qry);
+        }
+    } else {
+        dlen = -1;
+        printf("Invalid address: %s\r\n", qry);
+    }
+    sprintf(httpHeader,"HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: Close\r\n\r\n%d", dlen);
+    client.send(httpHeader,strlen(httpHeader));
+    while (dlen > 0) {
+        dlen -= 1;
+        sprintf(httpHeader," %x", data[dlen]);
+        client.send(httpHeader,strlen(httpHeader));
+    }
+}
 
-int main (void) {
-    EthernetInterface eth;
+void cmd_i2c_addr_read(char* qry)
+{
+    int addr = 0;
+    int radd = 0;
+    int dlen = 0;
+    if (sscanf(qry, "%2x", &addr) == 1) {
+        qry += 2;
+        printf("Addressed Read from I2C addr %x ", addr);
+        if (sscanf(qry, "&%2x", &radd) == 1) {
+            qry += 3;
+            printf("reg addr %x ", radd);
+            if (sscanf(qry, "&%2x", &dlen) == 1) {
+                data[0] = radd;
+                i2c.write(addr, data, 1, false);
+                if (i2c.read(addr, data, dlen)!=0) {
+                    dlen = -1;
+                    printf("failed\r\n");
+                } else {
+                    printf("%d bytes\r\n ", dlen);
+                }
+            } else {
+                printf("\r\nInvalid data length: %s\r\n", qry);
+            }
+        } else {
+            dlen = -1;
+            printf("Invalid register address: %s\r\n", qry);
+
+        }
+    } else {
+        dlen = -1;
+        printf("Invalid address: %s\r\n", qry);
+    }
+    sprintf(httpHeader,"HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: Close\r\n\r\n%d", dlen);
+    client.send(httpHeader,strlen(httpHeader));
+    while (dlen > 0) {
+        dlen -= 1;
+        sprintf(httpHeader," %x", data[dlen]);
+        client.send(httpHeader,strlen(httpHeader));
+    }
+}
+void get_file(char* uri)
+{
+    char *lstchr = strrchr(uri, NULL) -1;
+    if ('/' == *lstchr) {
+        printf("Open directory /sd%s\n", uri);
+        *lstchr = 0;
+        sprintf(filename, "/sd%s", uri);
+        DIR *d = opendir(filename);
+        if (d != NULL) {
+            sprintf(httpHeader,"HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: Close\r\n\r\n");
+            client.send(httpHeader,strlen(httpHeader));
+            sprintf(httpHeader,"<html><head><title>Directory Listing</title></head><body><h1>%s</h1><ul>", uri);
+            client.send(httpHeader,strlen(httpHeader));
+            struct dirent *p;
+            while((p = readdir(d)) != NULL) {
+                printf("%s\n", p->d_name);
+                sprintf(httpHeader,"<li>%s</li>", p->d_name);
+                client.send(httpHeader,strlen(httpHeader));
+            }
+        }
+        closedir(d);
+        printf("Directory closed\n");
+        sprintf(httpHeader,"</ul></body></html>");
+        client.send(httpHeader,strlen(httpHeader));
+    } else {
+        sprintf(filename, "/sd%s", uri);
+        fp = fopen(filename, "r");
+        if (fp == NULL) {
+            sprintf(httpHeader,"HTTP/1.1 404 Not Found \r\nContent-Type: text\r\nConnection: Close\r\n\r\n");
+            client.send(httpHeader,strlen(httpHeader));
+            client.send(uri,strlen(uri));
+        } else {
+            sprintf(httpHeader,"HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: Close\r\n\r\n");
+            client.send(httpHeader,strlen(httpHeader));
+            while ((rdCnt = fread(buffer, sizeof( char ), 1024, fp)) == 1024) {
+                client.send(buffer, rdCnt);
+            }
+            client.send(buffer, rdCnt);
+            fclose(fp);
+        }
+    }
+}
+
+void get_cgi(char* uri, char* qry)
+{
+    if (!strncmp(uri, "i2cW", 4)) { // i2cW [addr] [data] [data] [data] ...
+        cmd_i2c_write(qry);
+    } else if (!strncmp(uri, "i2cR", 4)) { // i2cR [addr] [count]
+        cmd_i2c_read(qry);
+    } else if (!strncmp(uri, "i2cAR", 5)) { // i2cAR [addr] [radd] [count]
+        cmd_i2c_addr_read(qry);
+    } else {
+        sprintf(httpHeader,"HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: Close\r\n\r\n");
+        client.send(httpHeader,strlen(httpHeader));
+        sprintf(httpHeader,"<html><head><title>Unrecognized CGI Command</title></head><body><h1>Unrecognized CGI Command</h1>");
+        client.send(httpHeader,strlen(httpHeader));
+        sprintf(httpHeader,"<h2>Command: %s</h2>", uri);
+        client.send(httpHeader,strlen(httpHeader));
+        sprintf(httpHeader,"<h2>Query: %s</h2>", qry);
+        client.send(httpHeader,strlen(httpHeader));
+        sprintf(httpHeader,"<h2>Supported Commands: </h2><ul>");
+        client.send(httpHeader,strlen(httpHeader));
+        sprintf(httpHeader,"<li>i2cR [addr] [count]");
+        client.send(httpHeader,strlen(httpHeader));
+        sprintf(httpHeader,"<li>i2cAR [addr] [radd] [count]");
+        client.send(httpHeader,strlen(httpHeader));
+        sprintf(httpHeader,"<li>i2cW [addr] [data] [data] [data] ...");
+        client.send(httpHeader,strlen(httpHeader));
+        sprintf(httpHeader,"</ul><br>addr = I2C address<br>radd = register address<br>count = number of bytes to read<br>data = data byte to send<br>All values are in two digit hexdecimal bytes.");
+        client.send(httpHeader,strlen(httpHeader));
+        sprintf(httpHeader,"</body></html>");
+        client.send(httpHeader,strlen(httpHeader));
+    }
+}
+
+
+int main (void)
+{
+//    EthernetInterface eth;
     eth.init(); //Use DHCP
     eth.connect();
     printf("IP Address is %s\n", eth.getIPAddress());
-    
-    TCPSocketServer server;
-    server.bind(ECHO_SERVER_PORT);
+
+//    TCPSocketServer server;
+    server.bind(HTTPD_SERVER_PORT);
     server.listen();
-    
+
     while (true) {
-        printf("\nWait for new connection...\n");
-        TCPSocketConnection client;
+        printf("\nWait for new connection...\r\n");
         server.accept(client);
         client.set_blocking(false, 1500); // Timeout after (1.5)s
-        
-        printf("Connection from: %s\n", client.get_address());
-        char buffer[256];
+
+        printf("Connection from: %s\r\n", client.get_address());
         while (true) {
             int n = client.receive(buffer, sizeof(buffer));
             if (n <= 0) break;
-            
-            client.send_all(buffer, n);
-            if (n <= 0) break;
+            printf("Recieved Data: %d\r\n\r\n%.*s\r\n",n,n,buffer);
+            if (n >= 1024) {
+                sprintf(httpHeader,"HTTP/1.1 413 Request Entity Too Large \r\nContent-Type: text\r\nConnection: Close\r\n\r\n");
+                client.send(httpHeader,strlen(httpHeader));
+                client.send(buffer,n);
+                break;
+            } else {
+                buffer[n]=0;
+            }
+            if (!strncmp(buffer, "GET ", 4)) {
+                uristr = buffer + 4;
+                eou = strstr(uristr, " ");
+                if (eou == NULL) {
+                    sprintf(httpHeader,"HTTP/1.1 400 Bad Request \r\nContent-Type: text\r\nConnection: Close\r\n\r\n");
+                    client.send(httpHeader,strlen(httpHeader));
+                    client.send(buffer,n);
+                } else {
+                    *eou = 0;
+                    qrystr = strstr(uristr, "?");
+                    if (qrystr != NULL) {
+                        *qrystr = 0;
+                        qrystr++;
+                    }
+                    if (!strncmp(uristr, "/cgi/", 5)) {
+                        get_cgi(uristr+5, qrystr);
+                    } else {
+                        get_file(uristr);
+                    }
+                }
+            }
         }
-        
+
         client.close();
     }
 }