Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
OLD
GSwifi_httpd.cpp
- Committer:
- gsfan
- Date:
- 2012-11-08
- Revision:
- 20:151b5a4fdd29
- Parent:
- 19:cad912f5a6ba
File content as of revision 20:151b5a4fdd29:
#include "dbg.h" #include "mbed.h" #include "GSwifi.h" #ifdef GS_USE_HTTPD #define HTTPD_REQUEST 0 #define HTTPD_HEAD 1 #define HTTPD_SPACE 2 #define HTTPD_BODY 3 #define HTTPD_ERROR 4 #define MIMETABLE_NUM 7 struct { char ext[6]; char type[20]; } mimetable[MIMETABLE_NUM] = { {".txt", "text/plain"}, {".html", "text/html"}, {".htm", "text/html"}, {".css", "text/css"}, {".jpg", "image/jpeg"}, {".png", "image/png"}, {".gif", "image/gif"}, }; 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); /* // newSock(_cid, GSTYPE_SERVER, GSPROT_HTTPD, &GSwifi::poll_httpd); // newSock(_cid, GSTYPE_SERVER, GSPROT_HTTPD, reinterpret_cast<onGsReceiveFunc>(&GSwifi::poll_httpd)); void (GSwifi::*f1)(int,int) = &GSwifi::poll_httpd; onGsReceiveFunc f2 = reinterpret_cast<onGsReceiveFunc>(f1); newSock(_cid, GSTYPE_SERVER, GSPROT_HTTPD, f2); */ 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: %d %s (%d)\r\n", cid, _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 = GSPROT_HTTPGET; j = 4; } else if (strncmp(_httpd[cid].buf, "POST ", 5) == 0) { _httpd[cid].type = GSPROT_HTTPPOST; 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; // no body } 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) { // found _httpd[cid].host = _gs_sock[cid].host; _httpd[cid].file = &_httpd[cid].uri[j]; _httpd[cid].query = NULL; for (; j < strlen(_httpd[cid].uri); j ++) { if (_httpd[cid].uri[j] == '?') { // query string _httpd[cid].uri[j] = 0; _httpd[cid].query = &_httpd[cid].uri[j + 1]; break; } } if (_handler[i].dir) { // file httpd_request(cid, &_httpd[cid], _handler[i].dir); flg = 1; } else if (_handler[i].onHttpCgi) { // cgi _handler[i].onHttpCgi(cid, &_httpd[cid]); _httpd[cid].keepalive = 0; LOG("%d.%d.%d.%d ", _httpd[cid].host.getIp()[0], _httpd[cid].host.getIp()[1], _httpd[cid].host.getIp()[2], _httpd[cid].host.getIp()[3]); LOG("%s %s %d 200 -\r\n", _httpd[cid].type == GSPROT_HTTPGET ? "GET" : "POST", _httpd[cid].uri, _httpd[cid].length); flg = 1; } break; } } if (! flg) { // not found send_httpd_error(cid, 403); } if (_httpd[cid].keepalive) { _httpd[cid].mode = HTTPD_REQUEST; _httpd[cid].len = 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, GS_httpd *gshttpd, char *dir) { FILE *fp; int i, len; char buf[HTTPD_BUF_SIZE]; char file[HTTPD_URI_SIZE]; strcpy(file, dir); strcat(file, gshttpd->file); if (file[strlen(file) - 1] == '/') { strcat(file, "index.htm"); } DBG("file: %s\r\n", file); fp = fopen(file, "r"); if (fp) { send(cid, "HTTP/1.1 200 OK\r\n", 17); { // file size i = ftell(fp); fseek(fp, 0, SEEK_END); len = ftell(fp); fseek(fp, i, SEEK_SET); } sprintf(buf, "Content-Length: %d\r\n", len); send(cid, buf, strlen(buf)); sprintf(buf, "Content-Type: %s\r\n", mimetype(file)); send(cid, buf, strlen(buf)); if (gshttpd->keepalive) { 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 defined(TARGET_LPC1768) || defined(TARGET_LPC2368) if (feof(fp)) break; #endif } fclose(fp); LOG("%d.%d.%d.%d ", _httpd[cid].host.getIp()[0], _httpd[cid].host.getIp()[1], _httpd[cid].host.getIp()[2], _httpd[cid].host.getIp()[3]); LOG("%s %s %d 200 %d\r\n", _httpd[cid].type == GSPROT_HTTPGET ? "GET" : "POST", _httpd[cid].uri, _httpd[cid].length, len); return 0; } send_httpd_error(cid, 404); return -1; } char *GSwifi::mimetype (char *file) { int i, j; DBG("<%s>\r\n", file); for (i = 0; i < MIMETABLE_NUM; i ++) { j = strlen(mimetable[i].ext); if (strncmp(&file[strlen(file) - j], mimetable[i].ext, j) == NULL) { return mimetable[i].type; } } return mimetable[0].type; } 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); LOG("%d.%d.%d.%d ", _httpd[cid].host.getIp()[0], _httpd[cid].host.getIp()[1], _httpd[cid].host.getIp()[2], _httpd[cid].host.getIp()[3]); LOG("%s %s %d %d -\r\n", _httpd[cid].type == GSPROT_HTTPGET ? "GET" : "POST", _httpd[cid].uri, _httpd[cid].length, err); } int GSwifi::attach_httpd (const char *uri, const 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 (const 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; } } #endif