GainSpan Wi-Fi library see: http://mbed.org/users/gsfan/notebook/gainspan_wifi/
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 Wed Jul 13 2022 01:52:46 by 1.7.2