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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 #include "mbed.h"
00002 #include "EthernetInterface.h"
00003 #include "SDFileSystem.h"
00004 #include <stdio.h>
00005 #include <string.h>
00006 
00007 #define HTTPD_SERVER_PORT   80
00008 #define HTTPD_MAX_REQ_LENGTH   1023
00009 #define HTTPD_MAX_HDR_LENGTH   255
00010 #define HTTPD_MAX_FNAME_LENGTH   127
00011 #define I2C_BUFFER_SIZE 63
00012 
00013 SDFileSystem sd(p5, p6, p7, p8, "sd"); //
00014 I2C i2c(p28, p27);
00015 EthernetInterface eth;
00016 TCPSocketServer server;
00017 TCPSocketConnection client;
00018 
00019 char buffer[HTTPD_MAX_REQ_LENGTH+1];
00020 char httpHeader[HTTPD_MAX_HDR_LENGTH+1];
00021 char filename[HTTPD_MAX_FNAME_LENGTH+1];
00022 char data[I2C_BUFFER_SIZE];
00023 char *uristr;
00024 char *eou;
00025 char *qrystr;
00026 
00027 FILE *fp;
00028 int rdCnt;
00029 
00030 void cmd_i2c_write(char* qry)
00031 {
00032     int addr = 0;
00033     int dlen = 0;
00034     int dtmp = 0;
00035     if (sscanf(qry, "%2x", &addr) == 1) {
00036         qry += 2;
00037         printf("Addr: %x Data: ", addr);
00038         while (sscanf(qry, "&%2x", &dtmp) == 1) {
00039             data[dlen] = dtmp;
00040             qry +=3;
00041             dlen +=1;
00042             printf("%x ", dtmp);
00043         }
00044         printf("Bytes: %d\r\n ", dlen);
00045     } else {
00046         dlen = -1;
00047         printf("Invalid address: %s\r\n", qry);
00048     }
00049     if (dlen > 0 ) {
00050         printf("Write %d bytes to %x\r\n", dlen, addr);
00051         i2c.write(addr, data, dlen);
00052     }
00053     sprintf(httpHeader,"HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: Close\r\n\r\n%d", dlen);
00054     client.send(httpHeader,strlen(httpHeader));
00055 }
00056 
00057 void cmd_i2c_read(char* qry)
00058 {
00059     int addr = 0;
00060     int dlen = 0;
00061     if (sscanf(qry, "%2x", &addr) == 1) {
00062         qry += 2;
00063         printf("Read from addr %x ", addr);
00064         if (sscanf(qry, "&%2x", &dlen) == 1) {
00065             if (i2c.read(addr, data, dlen)!=0) {
00066                 dlen = -1;
00067                 printf("failed\r\n");
00068             } else {
00069                 printf("%d bytes\r\n ", dlen);
00070             }
00071         } else {
00072             printf("\r\nInvalid data length: %s\r\n", qry);
00073         }
00074     } else {
00075         dlen = -1;
00076         printf("Invalid address: %s\r\n", qry);
00077     }
00078     sprintf(httpHeader,"HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: Close\r\n\r\n%d", dlen);
00079     client.send(httpHeader,strlen(httpHeader));
00080     while (dlen > 0) {
00081         dlen -= 1;
00082         sprintf(httpHeader," %x", data[dlen]);
00083         client.send(httpHeader,strlen(httpHeader));
00084     }
00085 }
00086 
00087 void cmd_i2c_addr_read(char* qry)
00088 {
00089     int addr = 0;
00090     int radd = 0;
00091     int dlen = 0;
00092     if (sscanf(qry, "%2x", &addr) == 1) {
00093         qry += 2;
00094         printf("Addressed Read from I2C addr %x ", addr);
00095         if (sscanf(qry, "&%2x", &radd) == 1) {
00096             qry += 3;
00097             printf("reg addr %x ", radd);
00098             if (sscanf(qry, "&%2x", &dlen) == 1) {
00099                 data[0] = radd;
00100                 i2c.write(addr, data, 1, false);
00101                 if (i2c.read(addr, data, dlen)!=0) {
00102                     dlen = -1;
00103                     printf("failed\r\n");
00104                 } else {
00105                     printf("%d bytes\r\n ", dlen);
00106                 }
00107             } else {
00108                 printf("\r\nInvalid data length: %s\r\n", qry);
00109             }
00110         } else {
00111             dlen = -1;
00112             printf("Invalid register address: %s\r\n", qry);
00113 
00114         }
00115     } else {
00116         dlen = -1;
00117         printf("Invalid address: %s\r\n", qry);
00118     }
00119     sprintf(httpHeader,"HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: Close\r\n\r\n%d", dlen);
00120     client.send(httpHeader,strlen(httpHeader));
00121     while (dlen > 0) {
00122         dlen -= 1;
00123         sprintf(httpHeader," %x", data[dlen]);
00124         client.send(httpHeader,strlen(httpHeader));
00125     }
00126 }
00127 void get_file(char* uri)
00128 {
00129     char *lstchr = strrchr(uri, NULL) -1;
00130     if ('/' == *lstchr) {
00131         printf("Open directory /sd%s\n", uri);
00132         *lstchr = 0;
00133         sprintf(filename, "/sd%s", uri);
00134         DIR *d = opendir(filename);
00135         if (d != NULL) {
00136             sprintf(httpHeader,"HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: Close\r\n\r\n");
00137             client.send(httpHeader,strlen(httpHeader));
00138             sprintf(httpHeader,"<html><head><title>Directory Listing</title></head><body><h1>%s</h1><ul>", uri);
00139             client.send(httpHeader,strlen(httpHeader));
00140             struct dirent *p;
00141             while((p = readdir(d)) != NULL) {
00142                 printf("%s\n", p->d_name);
00143                 sprintf(httpHeader,"<li>%s</li>", p->d_name);
00144                 client.send(httpHeader,strlen(httpHeader));
00145             }
00146         }
00147         closedir(d);
00148         printf("Directory closed\n");
00149         sprintf(httpHeader,"</ul></body></html>");
00150         client.send(httpHeader,strlen(httpHeader));
00151     } else {
00152         sprintf(filename, "/sd%s", uri);
00153         fp = fopen(filename, "r");
00154         if (fp == NULL) {
00155             sprintf(httpHeader,"HTTP/1.1 404 Not Found \r\nContent-Type: text\r\nConnection: Close\r\n\r\n");
00156             client.send(httpHeader,strlen(httpHeader));
00157             client.send(uri,strlen(uri));
00158         } else {
00159             sprintf(httpHeader,"HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: Close\r\n\r\n");
00160             client.send(httpHeader,strlen(httpHeader));
00161             while ((rdCnt = fread(buffer, sizeof( char ), 1024, fp)) == 1024) {
00162                 client.send(buffer, rdCnt);
00163             }
00164             client.send(buffer, rdCnt);
00165             fclose(fp);
00166         }
00167     }
00168 }
00169 
00170 void get_cgi(char* uri, char* qry)
00171 {
00172     if (!strncmp(uri, "i2cW", 4)) { // i2cW [addr] [data] [data] [data] ...
00173         cmd_i2c_write(qry);
00174     } else if (!strncmp(uri, "i2cR", 4)) { // i2cR [addr] [count]
00175         cmd_i2c_read(qry);
00176     } else if (!strncmp(uri, "i2cAR", 5)) { // i2cAR [addr] [radd] [count]
00177         cmd_i2c_addr_read(qry);
00178     } else {
00179         sprintf(httpHeader,"HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: Close\r\n\r\n");
00180         client.send(httpHeader,strlen(httpHeader));
00181         sprintf(httpHeader,"<html><head><title>Unrecognized CGI Command</title></head><body><h1>Unrecognized CGI Command</h1>");
00182         client.send(httpHeader,strlen(httpHeader));
00183         sprintf(httpHeader,"<h2>Command: %s</h2>", uri);
00184         client.send(httpHeader,strlen(httpHeader));
00185         sprintf(httpHeader,"<h2>Query: %s</h2>", qry);
00186         client.send(httpHeader,strlen(httpHeader));
00187         sprintf(httpHeader,"<h2>Supported Commands: </h2><ul>");
00188         client.send(httpHeader,strlen(httpHeader));
00189         sprintf(httpHeader,"<li>i2cR [addr] [count]");
00190         client.send(httpHeader,strlen(httpHeader));
00191         sprintf(httpHeader,"<li>i2cAR [addr] [radd] [count]");
00192         client.send(httpHeader,strlen(httpHeader));
00193         sprintf(httpHeader,"<li>i2cW [addr] [data] [data] [data] ...");
00194         client.send(httpHeader,strlen(httpHeader));
00195         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.");
00196         client.send(httpHeader,strlen(httpHeader));
00197         sprintf(httpHeader,"</body></html>");
00198         client.send(httpHeader,strlen(httpHeader));
00199     }
00200 }
00201 
00202 
00203 int main (void)
00204 {
00205 //    EthernetInterface eth;
00206     eth.init(); //Use DHCP
00207     eth.connect();
00208     printf("IP Address is %s\n", eth.getIPAddress());
00209 
00210 //    TCPSocketServer server;
00211     server.bind(HTTPD_SERVER_PORT);
00212     server.listen();
00213 
00214     while (true) {
00215         printf("\nWait for new connection...\r\n");
00216         server.accept(client);
00217         client.set_blocking(false, 1500); // Timeout after (1.5)s
00218 
00219         printf("Connection from: %s\r\n", client.get_address());
00220         while (true) {
00221             int n = client.receive(buffer, sizeof(buffer));
00222             if (n <= 0) break;
00223             printf("Recieved Data: %d\r\n\r\n%.*s\r\n",n,n,buffer);
00224             if (n >= 1024) {
00225                 sprintf(httpHeader,"HTTP/1.1 413 Request Entity Too Large \r\nContent-Type: text\r\nConnection: Close\r\n\r\n");
00226                 client.send(httpHeader,strlen(httpHeader));
00227                 client.send(buffer,n);
00228                 break;
00229             } else {
00230                 buffer[n]=0;
00231             }
00232             if (!strncmp(buffer, "GET ", 4)) {
00233                 uristr = buffer + 4;
00234                 eou = strstr(uristr, " ");
00235                 if (eou == NULL) {
00236                     sprintf(httpHeader,"HTTP/1.1 400 Bad Request \r\nContent-Type: text\r\nConnection: Close\r\n\r\n");
00237                     client.send(httpHeader,strlen(httpHeader));
00238                     client.send(buffer,n);
00239                 } else {
00240                     *eou = 0;
00241                     qrystr = strstr(uristr, "?");
00242                     if (qrystr != NULL) {
00243                         *qrystr = 0;
00244                         qrystr++;
00245                     }
00246                     if (!strncmp(uristr, "/cgi/", 5)) {
00247                         get_cgi(uristr+5, qrystr);
00248                     } else {
00249                         get_file(uristr);
00250                     }
00251                 }
00252             }
00253         }
00254 
00255         client.close();
00256     }
00257 }