for TwitterMbed
Fork of GSwifi_old by
Diff: GSwifi_httpd.cpp
- Revision:
- 18:4b97804c37d1
- Child:
- 19:cad912f5a6ba
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GSwifi_httpd.cpp Thu Nov 01 02:55:57 2012 +0000 @@ -0,0 +1,284 @@ +#include "dbg.h" +#include "mbed.h" +#include "GSwifi.h" + +#define HTTPD_REQUEST 0 +#define HTTPD_HEAD 1 +#define HTTPD_SPACE 2 +#define HTTPD_BODY 3 +#define HTTPD_ERROR 4 + +int GSwifi::httpd (int port) { + int i; + char cmd[GS_CMD_SIZE]; + + if (! _connect || _status != GSSTAT_READY) return -1; + + for (i = 0; i < 16; i ++) { + _httpd[i].mode = HTTPD_REQUEST; + _httpd[i].buf = NULL; + _httpd[i].uri = NULL; + } + _handler_count = 0; + + sprintf(cmd, "AT+NSTCP=%d", port); + if (command(cmd, GSRES_CONNECT)) return -1; + + newSock(_cid, GSTYPE_SERVER, GSPROT_HTTPD, NULL); + return _cid; +} + +void GSwifi::poll_httpd (int cid, int len) { + int i, j, flg = 0; + char c; + + if (len == 0) { + _httpd[cid].mode = HTTPD_REQUEST; + _httpd[cid].len = 0; + _httpd[cid].keepalive = 0; + return; + } + + while (_gs_sock[cid].connect && _gs_sock[cid].data->use()) { + flg = 0; + if (_httpd[cid].buf == NULL) { + _httpd[cid].buf = new char[HTTPD_BUF_SIZE]; + } + for (j = 0; j < len; j ++) { + _gs_sock[cid].data->get(&c); + if (c == '\r') continue; + if (c == '\n' && _httpd[cid].mode != HTTPD_BODY) break; + + if (_httpd[cid].len < HTTPD_BUF_SIZE - 1) { + _httpd[cid].buf[_httpd[cid].len] = c; + } + _httpd[cid].len ++; + if (_httpd[cid].len >= _httpd[cid].length && _httpd[cid].mode == HTTPD_BODY) break; + } + if (j >= len) return; + if (_httpd[cid].len < HTTPD_BUF_SIZE) { + _httpd[cid].buf[_httpd[cid].len] = 0; + DBG("httpd: %d %s (%d)\r\n", _httpd[cid].mode, _httpd[cid].buf, _httpd[cid].len); + } + + switch (_httpd[cid].mode) { + case HTTPD_REQUEST: + if (strncmp(_httpd[cid].buf, "GET ", 4) == 0) { + _httpd[cid].type = 0; + j = 4; + } else + if (strncmp(_httpd[cid].buf, "POST ", 5) == 0) { + _httpd[cid].type = 1; + j = 5; + } else { + _httpd[cid].mode = HTTPD_ERROR; + break; + } + + for (i = j; i < _httpd[cid].len; i ++) { + if (_httpd[cid].buf[i] == ' ') break; + } + i = i - j; + if (i) { + if (_httpd[cid].uri == NULL) { + _httpd[cid].uri = new char[HTTPD_URI_SIZE]; + } + strncpy(_httpd[cid].uri, &_httpd[cid].buf[j], i); + _httpd[cid].uri[i] = 0; + } + _httpd[cid].mode = HTTPD_HEAD; + _httpd[cid].length = 0; + DBG("uri: %s\r\n", _httpd[cid].uri); + break; + + case HTTPD_HEAD: + if (_httpd[cid].len == 0) { + _httpd[cid].mode = HTTPD_BODY; + if (_httpd[cid].length == 0) flg = 1; + } else + if (strncmp(_httpd[cid].buf, "Content-length: ", 16) == 0) { + _httpd[cid].length = atoi(&_httpd[cid].buf[16]); + } else + if (strncmp(_httpd[cid].buf, "Connection: Keep-Alive", 22) == 0) { + if (! _httpd[cid].keepalive) { + _httpd[cid].keepalive = HTTPD_KEEPALIVE; + } + } + break; + + case HTTPD_BODY: + if (_httpd[cid].len >= _httpd[cid].length) { + DBG("body: %s\r\n", _httpd[cid].buf); + flg = 1; + } + break; + } + + if (flg) { + // http request + _httpd[cid].buf[_httpd[cid].len] = 0; + // scan handler + flg = 0; + for (i = 0; i < _handler_count; i ++) { + j = strlen(_handler[i].uri); + if (strncmp(_httpd[cid].uri, _handler[i].uri, j) == NULL) { + if (_handler[i].dir) { + // file + httpd_request(cid, _handler[i].dir, &_httpd[cid].uri[j], _httpd[cid].keepalive); + flg = 1; + } else + if (_handler[i].onHttpCgi) { + // cgi + _handler[i].onHttpCgi(cid, &_httpd[cid].uri[j], _httpd[cid].buf, _httpd[cid].len); + flg = 1; + } + break; + } + } + if (! flg) { + send_httpd_error(cid, 403); + } + + if (_httpd[cid].keepalive) { + _httpd[cid].mode = HTTPD_REQUEST; + _httpd[cid].len = 0; + _httpd[cid].type = 0; + _httpd[cid].length = 0; + _httpd[cid].keepalive --; + } else { + close(cid); + } + } + + if (_httpd[cid].mode == HTTPD_ERROR) { + send_httpd_error(cid, 400); + } + + _httpd[cid].len = 0; + } +} + +int GSwifi::httpd_request (int cid, char *dir, char *file, int keep) { + FILE *fp; + int i, j; + char buf[100], tmp[20]; + + strcpy(buf, dir); + strcat(buf, file); + if (buf[strlen(buf) - 1] == '/') { + strcat(buf, "index.htm"); + } + DBG("file: %s\r\n", buf); + + fp = fopen(buf, "r"); + if (fp) { + strcpy(buf, "HTTP/1.1 200 OK\r\n"); + send(cid, buf, strlen(buf)); + { + j = ftell(fp); + fseek(fp, 0, SEEK_END); + i = ftell(fp); + fseek(fp, j, SEEK_SET); + } + sprintf(buf, "Content-Length: %d\r\n", i); + send(cid, buf, strlen(buf)); + j = strlen(file); + if (j == 0 || strncmp(&file[j - 4], ".htm", 4)) { + strcpy(tmp, "text/html"); + } else + if (strncmp(&file[j - 4], ".jpg", 4)) { + strcpy(tmp, "image/jpeg"); + } else + if (strncmp(&file[j - 4], ".png", 4)) { + strcpy(tmp, "image/png"); + } else + if (strncmp(&file[j - 4], ".gif", 4)) { + strcpy(tmp, "image/gif"); + } else { + strcpy(tmp, "text/plain"); + } + sprintf(buf, "Content-Type: %s\r\n", tmp); + send(cid, buf, strlen(buf)); + if (keep) { + strcpy(buf, "Connection: Keep-Alive\r\n"); + } else { + strcpy(buf, "Connection: close\r\n"); + } + send(cid, buf, strlen(buf)); + strcpy(buf, "Server: GSwifi httpd\r\n"); + send(cid, buf, strlen(buf)); + send(cid, "\r\n", 2); + + for (;;) { + i = fread(buf, sizeof(char), sizeof(buf), fp); + if (i == 0) break; + send(cid, buf, i); + if (feof(fp)) break; + } + fclose(fp); + return 0; + } + + send_httpd_error(cid, 404); + return -1; +} + +void GSwifi::send_httpd_error (int cid, int err) { + char buf[100], msg[30]; + + switch (err) { + case 400: + strcpy(msg, "Bad Request"); + break; + case 403: + strcpy(msg, "Forbidden"); + break; + case 404: + strcpy(msg, "Not Found"); + break; + case 500: + default: + strcpy(msg, "Internal Server Error"); + break; + } + DBG("httpd error: %d %d %s\r\n", cid, err, msg); + + sprintf(buf, "HTTP/1.1 %d %s\r\n", err, msg); + send(cid, buf, strlen(buf)); + strcpy(buf, "Content-Type: text/html\r\n"); + send(cid, buf, strlen(buf)); + send(cid, "\r\n", 2); + + sprintf(buf, "<html><head><title>%d %s</title></head>\r\n", err, msg); + send(cid, buf, strlen(buf)); + sprintf(buf, "<body><h1>%s</h1></body></html>\r\n", msg); + send(cid, buf, strlen(buf)); + close(cid); +} + +int GSwifi::attach_httpd (char *uri, char *dir) { + if (_handler_count < HTTPD_HANDLE) { + _handler[_handler_count].uri = new char[strlen(uri) + 1]; + strcpy(_handler[_handler_count].uri, uri); + _handler[_handler_count].dir = new char[strlen(dir) + 1]; + strcpy(_handler[_handler_count].dir, dir); + _handler[_handler_count].onHttpCgi = NULL; + _handler_count ++; + return 0; + } else { + return -1; + } +} + +int GSwifi::attach_httpd (char *uri, onHttpdCgiFunc ponHttpCgi) { + if (_handler_count < HTTPD_HANDLE) { + _handler[_handler_count].uri = new char[strlen(uri) + 1]; + strcpy(_handler[_handler_count].uri, uri); + _handler[_handler_count].dir = NULL; + _handler[_handler_count].onHttpCgi = ponHttpCgi; + _handler_count ++; + return 0; + } else { + return -1; + } +}