for TwitterMbed
Fork of GSwifi_old by
GSwifi_httpd.cpp
- Committer:
- gsfan
- Date:
- 2012-11-01
- Revision:
- 18:4b97804c37d1
- Child:
- 19:cad912f5a6ba
File content as of revision 18:4b97804c37d1:
#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; } }