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.
Fork of GSwifi_old by
GSwifi_httpd.cpp
00001 #include "dbg.h" 00002 #include "mbed.h" 00003 #include "GSwifi.h" 00004 #include "sha1.h" 00005 #include <string.h> 00006 00007 #ifdef GS_USE_HTTPD 00008 00009 #define MIMETABLE_NUM 8 00010 struct { 00011 char ext[6]; 00012 char type[24]; 00013 } mimetable[MIMETABLE_NUM] = { 00014 {".txt", "text/plain"}, 00015 {".html", "text/html"}, 00016 {".htm", "text/html"}, 00017 {".css", "text/css"}, 00018 {".js", "application/javascript"}, 00019 {".jpg", "image/jpeg"}, 00020 {".png", "image/png"}, 00021 {".gif", "image/gif"}, 00022 }; 00023 00024 int GSwifi::httpd (int port) { 00025 int i; 00026 char cmd[GS_CMD_SIZE]; 00027 00028 if (! _connect || _status != GSSTAT_READY) return -1; 00029 00030 memset(&_httpd, 0, sizeof(_httpd)); 00031 for (i = 0; i < 16; i ++) { 00032 _httpd[i].mode = GSHTTPDMODE_REQUEST; 00033 } 00034 _handler_count = 0; 00035 00036 sprintf(cmd, "AT+NSTCP=%d", port); 00037 if (command(cmd, GSRES_CONNECT)) return -1; 00038 00039 newSock(_cid, GSTYPE_SERVER, GSPROT_HTTPD, NULL); 00040 /* 00041 // newSock(_cid, GSTYPE_SERVER, GSPROT_HTTPD, &GSwifi::poll_httpd); 00042 // newSock(_cid, GSTYPE_SERVER, GSPROT_HTTPD, reinterpret_cast<onGsReceiveFunc>(&GSwifi::poll_httpd)); 00043 void (GSwifi::*f1)(int,int) = &GSwifi::poll_httpd; 00044 onGsReceiveFunc f2 = reinterpret_cast<onGsReceiveFunc>(f1); 00045 newSock(_cid, GSTYPE_SERVER, GSPROT_HTTPD, f2); 00046 */ 00047 return _cid; 00048 } 00049 00050 void GSwifi::poll_httpd (int cid, int len) { 00051 int i, j, flg = 0; 00052 char c; 00053 00054 if (len == 0) { 00055 // start request 00056 _httpd[cid].mode = GSHTTPDMODE_REQUEST; 00057 _httpd[cid].len = 0; 00058 _httpd[cid].keepalive = 0; 00059 #ifdef GS_USE_WEBSOCKET 00060 _httpd[cid].websocket = 0; 00061 #endif 00062 return; 00063 } 00064 00065 #ifdef GS_USE_WEBSOCKET 00066 if (_httpd[cid].mode >= GSHTTPDMODE_WEBSOCKET) { 00067 poll_websocket(cid, len); 00068 return; 00069 } 00070 #endif 00071 00072 while (_gs_sock[cid].connect && _gs_sock[cid].data->use()) { 00073 flg = 0; 00074 if (_httpd[cid].buf == NULL) { 00075 _httpd[cid].buf = new char[HTTPD_BUF_SIZE]; 00076 } 00077 // get 1 line 00078 for (j = 0; j < len; j ++) { 00079 _gs_sock[cid].data->get(&c); 00080 if (c == '\r') continue; 00081 if (c == '\n' && _httpd[cid].mode != GSHTTPDMODE_BODY) break; 00082 00083 if (_httpd[cid].len < HTTPD_BUF_SIZE - 1) { 00084 _httpd[cid].buf[_httpd[cid].len] = c; 00085 } 00086 _httpd[cid].len ++; 00087 if (_httpd[cid].mode == GSHTTPDMODE_BODY && _httpd[cid].len >= _httpd[cid].length) break; // end of body 00088 } 00089 if (j >= len) return; // continue 00090 if (_httpd[cid].len < HTTPD_BUF_SIZE) { 00091 _httpd[cid].buf[_httpd[cid].len] = 0; 00092 DBG("httpd %d: %d %s (%d)\r\n", cid, _httpd[cid].mode, _httpd[cid].buf, _httpd[cid].len); 00093 } 00094 00095 // parse 00096 switch (_httpd[cid].mode) { 00097 case GSHTTPDMODE_REQUEST: 00098 if (strnicmp(_httpd[cid].buf, "GET ", 4) == 0) { 00099 _httpd[cid].type = GSPROT_HTTPGET; 00100 j = 4; 00101 } else 00102 if (strnicmp(_httpd[cid].buf, "POST ", 5) == 0) { 00103 _httpd[cid].type = GSPROT_HTTPPOST; 00104 j = 5; 00105 } else { 00106 _httpd[cid].mode = GSHTTPDMODE_ERROR; 00107 break; 00108 } 00109 00110 // get uri 00111 for (i = j; i < _httpd[cid].len; i ++) { 00112 if (_httpd[cid].buf[i] == ' ') break; 00113 } 00114 i = i - j; 00115 if (i) { 00116 if (_httpd[cid].uri == NULL) { 00117 _httpd[cid].uri = new char[HTTPD_URI_SIZE]; 00118 } 00119 strncpy(_httpd[cid].uri, &_httpd[cid].buf[j], i); 00120 _httpd[cid].uri[i] = 0; 00121 } 00122 _httpd[cid].mode = GSHTTPDMODE_HEAD; 00123 _httpd[cid].length = 0; 00124 DBG("uri: %s\r\n", _httpd[cid].uri); 00125 break; 00126 00127 case GSHTTPDMODE_HEAD: 00128 if (_httpd[cid].len == 0) { 00129 // blank line (end of header) 00130 _httpd[cid].mode = GSHTTPDMODE_BODY; 00131 if (_httpd[cid].length == 0) flg = 1; // no body 00132 #ifdef GS_USE_WEBSOCKET 00133 if (_httpd[cid].websocket && _httpd[cid].websocket_key) { 00134 // enter websocket 00135 _httpd[cid].mode = GSHTTPDMODE_WEBSOCKET; 00136 _httpd[cid].len = 0; 00137 flg = 1; 00138 } 00139 #endif 00140 } else 00141 if (strnicmp(_httpd[cid].buf, "Content-Length: ", 16) == 0) { 00142 _httpd[cid].length = atoi(&_httpd[cid].buf[16]); 00143 } else 00144 if (strnicmp(_httpd[cid].buf, "Connection: Keep-Alive", 22) == 0) { 00145 if (! _httpd[cid].keepalive) { 00146 _httpd[cid].keepalive = HTTPD_KEEPALIVE; 00147 } 00148 #ifdef GS_USE_WEBSOCKET 00149 } else 00150 if (strnicmp(_httpd[cid].buf, "Upgrade: websocket", 18) == 0) { 00151 if (! _httpd[cid].websocket) _httpd[cid].websocket = 1; 00152 } else 00153 if (strnicmp(_httpd[cid].buf, "Sec-WebSocket-Version: ", 23) == 0) { 00154 _httpd[cid].websocket = atoi(&_httpd[cid].buf[23]); 00155 } else 00156 if (strnicmp(_httpd[cid].buf, "Sec-WebSocket-Key: ", 19) == 0) { 00157 if (_httpd[cid].websocket_key == NULL) { 00158 _httpd[cid].websocket_key = new char[30]; 00159 } 00160 strncpy(_httpd[cid].websocket_key, &_httpd[cid].buf[19], 30); 00161 #endif 00162 } 00163 break; 00164 00165 case GSHTTPDMODE_BODY: 00166 if (_httpd[cid].len >= _httpd[cid].length) { 00167 DBG("body: %s\r\n", _httpd[cid].buf); 00168 flg = 1; 00169 } 00170 break; 00171 00172 } 00173 00174 #ifdef GS_USE_WEBSOCKET 00175 if (flg && _httpd[cid].mode == GSHTTPDMODE_WEBSOCKET) { 00176 // websocket 00177 _httpd[cid].host = _gs_sock[cid].host; 00178 j = strlen(_handler[i].uri); 00179 _httpd[cid].file = &_httpd[cid].uri[j]; 00180 _httpd[cid].query = NULL; 00181 00182 send_websocket_accept(cid); 00183 break; // exit while 00184 00185 } else 00186 #endif 00187 if (flg) { 00188 // http request 00189 _httpd[cid].buf[_httpd[cid].len] = 0; 00190 00191 i = get_handler(_httpd[cid].uri); 00192 if (i >= 0) { 00193 _httpd[cid].host = _gs_sock[cid].host; 00194 j = strlen(_handler[i].uri); 00195 _httpd[cid].file = &_httpd[cid].uri[j]; 00196 _httpd[cid].query = NULL; 00197 for (; j < strlen(_httpd[cid].uri); j ++) { 00198 if (_httpd[cid].uri[j] == '?') { 00199 // query string 00200 _httpd[cid].uri[j] = 0; 00201 _httpd[cid].query = &_httpd[cid].uri[j + 1]; 00202 break; 00203 } 00204 } 00205 00206 if (_handler[i].dir) { 00207 // file 00208 httpd_request(cid, &_httpd[cid], _handler[i].dir); 00209 flg = 1; 00210 } else 00211 if (_handler[i].onHttpCgi) { 00212 // cgi 00213 _handler[i].onHttpCgi(cid, &_httpd[cid]); 00214 _httpd[cid].keepalive = 0; 00215 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]); 00216 LOG("%s %s %d 200 -\r\n", _httpd[cid].type == GSPROT_HTTPGET ? "GET" : "POST", _httpd[cid].uri, _httpd[cid].length); 00217 flg = 1; 00218 } 00219 } else { 00220 // not found 00221 send_httpd_error(cid, 403); 00222 } 00223 00224 if (_httpd[cid].keepalive) { 00225 _httpd[cid].mode = GSHTTPDMODE_REQUEST; 00226 _httpd[cid].len = 0; 00227 _httpd[cid].length = 0; 00228 _httpd[cid].keepalive --; 00229 } else { 00230 close(cid); 00231 } 00232 } 00233 00234 if (_httpd[cid].mode == GSHTTPDMODE_ERROR) { 00235 send_httpd_error(cid, 400); 00236 } 00237 00238 _httpd[cid].len = 0; 00239 } // while 00240 } 00241 00242 int GSwifi::get_handler (char *uri) { 00243 int i, j; 00244 00245 for (i = 0; i < _handler_count; i ++) { 00246 j = strlen(_handler[i].uri); 00247 if (strncmp(uri, _handler[i].uri, j) == NULL) { 00248 // found 00249 return i; 00250 } 00251 } 00252 return -1; 00253 } 00254 00255 int GSwifi::httpd_request (int cid, GS_httpd *gshttpd, char *dir) { 00256 FILE *fp; 00257 int i, len; 00258 char buf[HTTPD_BUF_SIZE]; 00259 char file[HTTPD_URI_SIZE]; 00260 00261 strcpy(file, dir); 00262 strcat(file, gshttpd->file); 00263 if (file[strlen(file) - 1] == '/') { 00264 strcat(file, "index.html"); 00265 } 00266 DBG("file: %s\r\n", file); 00267 00268 fp = fopen(file, "r"); 00269 if (fp) { 00270 send(cid, "HTTP/1.1 200 OK\r\n", 17); 00271 { 00272 // file size 00273 i = ftell(fp); 00274 fseek(fp, 0, SEEK_END); 00275 len = ftell(fp); 00276 fseek(fp, i, SEEK_SET); 00277 } 00278 sprintf(buf, "Content-Length: %d\r\n", len); 00279 send(cid, buf, strlen(buf)); 00280 sprintf(buf, "Content-Type: %s\r\n", mimetype(file)); 00281 send(cid, buf, strlen(buf)); 00282 if (gshttpd->keepalive) { 00283 strcpy(buf, "Connection: Keep-Alive\r\n"); 00284 } else { 00285 strcpy(buf, "Connection: close\r\n"); 00286 } 00287 send(cid, buf, strlen(buf)); 00288 strcpy(buf, "Server: GSwifi httpd\r\n"); 00289 send(cid, buf, strlen(buf)); 00290 send(cid, "\r\n", 2); 00291 00292 for (;;) { 00293 i = fread(buf, sizeof(char), sizeof(buf), fp); 00294 if (i <= 0) break; 00295 if (! _gs_sock[cid].connect) break; 00296 send(cid, buf, i); 00297 #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) 00298 if (feof(fp)) break; 00299 #endif 00300 } 00301 fclose(fp); 00302 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]); 00303 LOG("%s %s %d 200 %d\r\n", _httpd[cid].type == GSPROT_HTTPGET ? "GET" : "POST", _httpd[cid].uri, _httpd[cid].length, len); 00304 return 0; 00305 } 00306 00307 send_httpd_error(cid, 404); 00308 return -1; 00309 } 00310 00311 char *GSwifi::mimetype (char *file) { 00312 int i, j; 00313 00314 DBG("<%s>\r\n", file); 00315 for (i = 0; i < MIMETABLE_NUM; i ++) { 00316 j = strlen(mimetable[i].ext); 00317 if (strnicmp(&file[strlen(file) - j], mimetable[i].ext, j) == NULL) { 00318 return mimetable[i].type; 00319 } 00320 } 00321 return mimetable[0].type; 00322 } 00323 00324 int GSwifi::strnicmp (char *p1, char *p2, int n) { 00325 int i, r; 00326 char c1, c2; 00327 00328 for (i = 0; i < n; i ++) { 00329 c1 = (p1[i] >= 'a' && p1[i] <= 'z') ? p1[i] - ('a' - 'A'): p1[i]; 00330 c2 = (p2[i] >= 'a' && p2[i] <= 'z') ? p2[i] - ('a' - 'A'): p2[i]; 00331 r = c1 - c2; 00332 if (r) break; 00333 } 00334 return r; 00335 } 00336 00337 void GSwifi::send_httpd_error (int cid, int err) { 00338 char buf[100], msg[30]; 00339 00340 switch (err) { 00341 case 400: 00342 strcpy(msg, "Bad Request"); 00343 break; 00344 case 403: 00345 strcpy(msg, "Forbidden"); 00346 break; 00347 case 404: 00348 strcpy(msg, "Not Found"); 00349 break; 00350 case 500: 00351 default: 00352 strcpy(msg, "Internal Server Error"); 00353 break; 00354 } 00355 DBG("httpd error: %d %d %s\r\n", cid, err, msg); 00356 00357 sprintf(buf, "HTTP/1.1 %d %s\r\n", err, msg); 00358 send(cid, buf, strlen(buf)); 00359 strcpy(buf, "Content-Type: text/html\r\n"); 00360 send(cid, buf, strlen(buf)); 00361 send(cid, "\r\n", 2); 00362 00363 sprintf(buf, "<html><head><title>%d %s</title></head>\r\n", err, msg); 00364 send(cid, buf, strlen(buf)); 00365 sprintf(buf, "<body><h1>%s</h1></body></html>\r\n", msg); 00366 send(cid, buf, strlen(buf)); 00367 close(cid); 00368 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]); 00369 LOG("%s %s %d %d -\r\n", _httpd[cid].type == GSPROT_HTTPGET ? "GET" : "POST", _httpd[cid].uri, _httpd[cid].length, err); 00370 } 00371 00372 int GSwifi::attach_httpd (const char *uri, const char *dir) { 00373 if (_handler_count < HTTPD_HANDLE) { 00374 _handler[_handler_count].uri = new char[strlen(uri) + 1]; 00375 strcpy(_handler[_handler_count].uri, uri); 00376 _handler[_handler_count].dir = new char[strlen(dir) + 1]; 00377 strcpy(_handler[_handler_count].dir, dir); 00378 _handler[_handler_count].onHttpCgi = NULL; 00379 _handler_count ++; 00380 return 0; 00381 } else { 00382 return -1; 00383 } 00384 } 00385 00386 int GSwifi::attach_httpd (const char *uri, onHttpdCgiFunc ponHttpCgi) { 00387 if (_handler_count < HTTPD_HANDLE) { 00388 _handler[_handler_count].uri = new char[strlen(uri) + 1]; 00389 strcpy(_handler[_handler_count].uri, uri); 00390 _handler[_handler_count].dir = NULL; 00391 _handler[_handler_count].onHttpCgi = ponHttpCgi; 00392 _handler_count ++; 00393 return 0; 00394 } else { 00395 return -1; 00396 } 00397 } 00398 00399 #ifdef GS_USE_WEBSOCKET 00400 void GSwifi::poll_websocket (int cid, int len) { 00401 int i, j, flg; 00402 unsigned char c; 00403 00404 while (_gs_sock[cid].connect && _gs_sock[cid].data->use()) { 00405 flg = 0; 00406 // get 1 line 00407 for (j = 0; j < len; j ++) { 00408 _gs_sock[cid].data->get((char*)&c); 00409 // DBG("_%c", c); 00410 00411 switch (_httpd[cid].mode) { 00412 case GSHTTPDMODE_WEBSOCKET: 00413 if (_httpd[cid].len == 0) { 00414 _httpd[cid].type = c & 0x0f; 00415 _httpd[cid].websocket_flg = c << 8; 00416 _httpd[cid].len ++; 00417 } else 00418 if (_httpd[cid].len == 1) { 00419 _httpd[cid].websocket_flg |= c; 00420 _httpd[cid].length = c & 0x7f; 00421 _httpd[cid].len ++; 00422 if (_httpd[cid].length < 126) { 00423 _httpd[cid].len = 0; 00424 if (_httpd[cid].websocket_flg & 0x0080) { 00425 _httpd[cid].mode = GSHTTPDMODE_WEBSOCKET_MASK; 00426 } else { 00427 _httpd[cid].mode = GSHTTPDMODE_WEBSOCKET_BODY; 00428 } 00429 DBG("ws length %d\r\n", _httpd[cid].length); 00430 } 00431 } else { 00432 // length 16bit,64bit 00433 if (_httpd[cid].len == 2) { 00434 _httpd[cid].length = c; 00435 _httpd[cid].len ++; 00436 } else 00437 if (_httpd[cid].len < 9 && (_httpd[cid].websocket_flg & 0x7f) == 127) { 00438 // 64bit 00439 _httpd[cid].length = (_httpd[cid].length << 8) | c; 00440 _httpd[cid].len ++; 00441 } else { 00442 _httpd[cid].length = (_httpd[cid].length << 8) | c; 00443 _httpd[cid].len = 0; 00444 if (_httpd[cid].websocket_flg & 0x0080) { 00445 _httpd[cid].mode = GSHTTPDMODE_WEBSOCKET_MASK; 00446 } else { 00447 _httpd[cid].mode = GSHTTPDMODE_WEBSOCKET_BODY; 00448 } 00449 DBG("ws length2 %d\r\n", _httpd[cid].length); 00450 } 00451 } 00452 break; 00453 00454 case GSHTTPDMODE_WEBSOCKET_MASK: 00455 _httpd[cid].websocket_mask[_httpd[cid].len] = c; 00456 _httpd[cid].len ++; 00457 if (_httpd[cid].len >= 4) { 00458 _httpd[cid].len = 0; 00459 _httpd[cid].mode = GSHTTPDMODE_WEBSOCKET_BODY; 00460 DBG("ws mask\r\n"); 00461 } 00462 break; 00463 00464 case GSHTTPDMODE_WEBSOCKET_BODY: 00465 if (_httpd[cid].len < HTTPD_BUF_SIZE - 1) { 00466 if (_httpd[cid].websocket_flg & 0x0080) { 00467 _httpd[cid].buf[_httpd[cid].len] = c ^ _httpd[cid].websocket_mask[_httpd[cid].len & 0x03]; 00468 } else { 00469 _httpd[cid].buf[_httpd[cid].len] = c; 00470 } 00471 _httpd[cid].len ++; 00472 } 00473 break; 00474 } 00475 00476 if (_httpd[cid].mode == GSHTTPDMODE_WEBSOCKET_BODY && _httpd[cid].len >= _httpd[cid].length) { 00477 flg = 1; 00478 break; 00479 } 00480 } 00481 if (j >= len) return; // continue 00482 if (_httpd[cid].len < HTTPD_BUF_SIZE) { 00483 _httpd[cid].buf[_httpd[cid].len] = 0; 00484 DBG("websocket %d: (%d)\r\n", cid, _httpd[cid].len); 00485 } 00486 00487 if (flg) { 00488 // websocket request 00489 DBG("ws type %d\r\n", _httpd[cid].type); 00490 switch (_httpd[cid].type) { 00491 case 0x00: // continuation 00492 case 0x01: // text 00493 case 0x02: // binary 00494 i = get_handler(_httpd[cid].uri); 00495 if (i >= 0) { 00496 if (_handler[i].onHttpCgi) { 00497 // cgi 00498 _handler[i].onHttpCgi(cid, &_httpd[cid]); 00499 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]); 00500 LOG("%s %s %d 200 -\r\n", "WEBSOCKET", _httpd[cid].uri, _httpd[cid].length); 00501 flg = 1; 00502 } 00503 } 00504 break; 00505 00506 case 0x08: // close 00507 close(cid); 00508 break; 00509 00510 case 0x09: // ping 00511 _gs_putc(0x8a); // pong 00512 _gs_putc(0x04); 00513 for (i = 0; i < _httpd[cid].len; i ++) { 00514 _gs_putc(_httpd[cid].buf[i]); 00515 } 00516 break; 00517 00518 case 0x0a: // pong 00519 break; 00520 } 00521 _httpd[cid].mode = GSHTTPDMODE_WEBSOCKET; 00522 _httpd[cid].len = 0; 00523 _httpd[cid].length = 0; 00524 } 00525 } // while 00526 } 00527 00528 int GSwifi::send_websocket (int cid, const char *buf, int len) { 00529 int r; 00530 char tmp[10]; 00531 00532 tmp[0] = 0x81; // single, text frame 00533 if (len < 126) { 00534 tmp[1] = len; 00535 r = send(cid, tmp, 2); 00536 } else { 00537 tmp[1] = 126; 00538 tmp[2] = (len >> 8) & 0xff; 00539 tmp[3] = len & 0xff; 00540 r = send(cid, tmp, 4); 00541 } 00542 if (r == 0) { 00543 r = send(cid, buf, len); 00544 } 00545 return r; 00546 } 00547 00548 void GSwifi::send_websocket_accept (int cid) { 00549 char buf[100], buf2[20]; 00550 00551 DBG("websocket accept: %d\r\n", cid); 00552 00553 send(cid, "HTTP/1.1 101 Switching Protocols\r\n", 34); 00554 send(cid, "Upgrade: websocket\r\n", 20); 00555 send(cid, "Connection: Upgrade\r\n", 21); 00556 00557 send(cid, "Sec-WebSocket-Accept: ", 22); 00558 strcpy(buf, _httpd[cid].websocket_key); 00559 strcat(buf, "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"); 00560 sha1(buf, strlen(buf), buf2); 00561 base64encode(buf2, 20, buf, sizeof(buf)); 00562 send(cid, buf, strlen(buf)); 00563 send(cid, "\r\n", 2); 00564 // send(cid, "Sec-WebSocket-Protocol: chat\r\n", 30); 00565 send(cid, "\r\n", 2); 00566 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]); 00567 LOG("%s %s %d 101 - %s\r\n", _httpd[cid].type == GSPROT_HTTPGET ? "GET" : "POST", _httpd[cid].uri, _httpd[cid].length, buf); 00568 } 00569 #endif 00570 00571 #endif
Generated on Mon Jul 18 2022 14:21:01 by
