Simple HTTP Server with support for SD Card file serving and CGI commands
Dependencies: EthernetInterface TCPEchoServer SDFileSystem mbed-rtos mbed
Fork of TCPEchoServer by
main.cpp
- Committer:
- gsteiert
- Date:
- 2013-04-06
- Revision:
- 6:6aa0b2a3c4e4
- Parent:
- 3:36fd3cfad85a
File content as of revision 6:6aa0b2a3c4e4:
#include "mbed.h" #include "EthernetInterface.h" #include "SDFileSystem.h" #include <stdio.h> #include <string.h> #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)); } } 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(HTTPD_SERVER_PORT); server.listen(); while (true) { printf("\nWait for new connection...\r\n"); server.accept(client); client.set_blocking(false, 1500); // Timeout after (1.5)s printf("Connection from: %s\r\n", client.get_address()); while (true) { int n = client.receive(buffer, sizeof(buffer)); 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(); } }