GSwifiInterface library (interface for GainSpan Wi-Fi GS1011 modules) Please see https://mbed.org/users/gsfan/notebook/GSwifiInterface/

Dependents:   GSwifiInterface_HelloWorld GSwifiInterface_HelloServo GSwifiInterface_UDPEchoServer GSwifiInterface_UDPEchoClient ... more

Fork of WiflyInterface by mbed official

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers GSwifi_httpd.cpp Source File

GSwifi_httpd.cpp

00001 /* Copyright (C) 2013 gsfan, MIT License
00002  *
00003  * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
00004  * and associated documentation files (the "Software"), to deal in the Software without restriction,
00005  * including without limitation the rights to use, copy, modify, merge, publish, distribute,
00006  * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
00007  * furnished to do so, subject to the following conditions:
00008  *
00009  * The above copyright notice and this permission notice shall be included in all copies or
00010  * substantial portions of the Software.
00011  *
00012  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
00013  * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00014  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
00015  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00016  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00017  */
00018 
00019 #include "GSwifi.h"
00020 
00021 #ifdef CFG_ENABLE_HTTPD
00022 
00023 int GSwifi::httpd (int port) {
00024     int i;
00025 
00026     if (!isAssociated() || _state.status != STAT_READY) return -1;
00027 
00028     memset(&_httpd, 0, sizeof(_httpd));
00029     for (i = 0; i < CFG_MAX_SOCKETS; i ++) {
00030         _httpd[i].mode = HTTPDMODE_REQUEST;
00031         _httpd[i].buf = _con[i].buf;
00032     }
00033 #ifdef CFG_ENABLE_RTOS
00034 #ifdef CFG_EXTENDED_MEMORY2
00035     int n = CFG_EXTENDED_SIZE2 / CFG_MAX_SOCKETS;
00036     for (i = 0; i < CFG_MAX_SOCKETS; i ++) {
00037         _httpd[i].uri = (char*)(CFG_EXTENDED_MEMORY2 + (n * i));
00038 #ifdef CFG_ENABLE_RTOS
00039         _httpd[i].websocket_key = (char*)malloc(30);
00040 #endif
00041     }
00042 #else // CFG_EXTENDED_MEMORY
00043     for (i = 0; i < CFG_MAX_SOCKETS; i ++) {
00044         _httpd[i].uri = (char*)malloc(CFG_CMD_SIZE);
00045 #ifdef CFG_ENABLE_RTOS
00046         _httpd[i].websocket_key = (char*)malloc(30);
00047 #endif
00048     }
00049 #endif // CFG_EXTENDED_MEMORY
00050 #endif
00051     _handler_count = 0;
00052 
00053     _httpd_cid = listen(PROTO_TCP, port);
00054     if (_httpd_cid < 0) return -1;
00055 
00056     _con[_httpd_cid].protocol = PROTO_HTTPD;
00057     return _httpd_cid;
00058 }
00059 
00060 void GSwifi::httpdRecvData (int cid, char c) {
00061 
00062     switch (_httpd[cid].mode) {
00063     case HTTPDMODE_REQUEST:
00064 #ifndef CFG_ENABLE_RTOS
00065         if (_con[cid].buf == NULL) {
00066             _con[cid].buf = new CircBuffer<char>(CFG_DATA_SIZE);
00067         }
00068 #endif
00069         _httpd[cid].buf = _con[cid].buf;
00070         if (_httpd[cid].buf != NULL) {
00071             _httpd[cid].buf->flush();
00072         }
00073         _httpd[cid].keepalive = 0;
00074         if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) {
00075             if (_httpd[cid].buf != NULL) {
00076                 _httpd[cid].buf->queue(c);
00077             }
00078             _httpd[cid].mode = HTTPDMODE_REQUEST_STR;
00079         }
00080         break;
00081     case HTTPDMODE_REQUEST_STR:
00082         switch (c) {
00083         case 0:
00084         case 0x0d: // CR
00085             break;
00086         case 0x0a: // LF
00087             if (httpdParseRequest(cid)) {
00088                 _httpd[cid].mode = HTTPDMODE_REQUEST_STR;
00089             } else {
00090                 _httpd[cid].mode = HTTPDMODE_HEADER;
00091             }
00092             _httpd[cid].enter = 0;
00093             break;
00094         default:
00095             if (_httpd[cid].buf != NULL) {
00096                 _httpd[cid].buf->queue(c);
00097             }
00098             break;
00099         }
00100         break;
00101     case HTTPDMODE_HEADER:
00102         switch (c) {
00103         case 0:
00104         case 0x0d: // CR
00105             break;
00106         case 0x0a: // LF
00107 //            if (_httpd[cid].buf != NULL && _httpd[cid].buf->available() == 0) {
00108 //                if ((_httpd[cid].enter == 0x0d && c == 0x0a) || (_httpd[cid].enter == 0x0a && c == 0x0a)) {
00109                 if (_httpd[cid].enter == 0x0a && c == 0x0a) {
00110                     if (_httpd[cid].buf != NULL) {
00111                         _httpd[cid].buf->flush();
00112                     }
00113 #ifdef CFG_ENABLE_WEBSOCKET
00114                     if (_httpd[cid].websocket) {
00115                         INFO("MODE_WEBSOCKET_BEGIN");
00116                         _httpd[cid].mode = HTTPDMODE_WEBSOCKET_BEGIN;
00117                     } else
00118 #endif
00119                     if (_httpd[cid].length) {
00120                         INFO("MODE_BODY");
00121                         _httpd[cid].mode = HTTPDMODE_BODY;
00122                     } else {
00123                         INFO("MODE_ENTER");
00124                         _httpd[cid].mode = HTTPDMODE_ENTER;
00125                         _con[cid].received = true;
00126                     }
00127                 }
00128 //                break;
00129 //            }
00130 
00131             _httpd[cid].enter = c;
00132             httpdParseHeader(cid);
00133             break;
00134         default:
00135             if (_httpd[cid].buf != NULL) {
00136                 _httpd[cid].buf->queue(c);
00137             }
00138             _httpd[cid].enter = 0;
00139             break;
00140         }
00141         break;
00142     case HTTPDMODE_BODY:
00143         if (_httpd[cid].buf != NULL) {
00144             _httpd[cid].buf->queue(c);
00145             if (_httpd[cid].buf->available() >= _httpd[cid].length) {
00146                 _httpd[cid].mode = HTTPDMODE_ENTER;
00147                 _con[cid].received = true;
00148             }
00149         }
00150         break;
00151 #ifdef CFG_ENABLE_WEBSOCKET
00152     case HTTPDMODE_WEBSOCKET:
00153     case HTTPDMODE_WEBSOCKET_MASK:
00154     case HTTPDMODE_WEBSOCKET_BODY:
00155         wsRecvData(cid, c);
00156         break;
00157 #endif
00158     }
00159 }
00160 
00161 void GSwifi::httpdPoll () {
00162     for (int cid = 0; cid < 16; cid ++) {
00163         if (isConnected(cid) && _con[cid].protocol == PROTO_HTTPD) {
00164 
00165     if (_httpd[cid].mode == HTTPDMODE_ENTER) {
00166         int i = httpdGetHandler(_httpd[cid].uri);
00167         if (i >= 0) { 
00168             if (_httpd_handler[i].dir) {
00169                 // file
00170                 httpdFile(cid, _httpd_handler[i].dir);
00171             } else
00172             if (_httpd_handler[i].func && !_httpd_handler[i].ws) {
00173                 // cgi
00174                 _httpd_handler[i].func(cid);
00175 //                _httpd[cid].keepalive = 0;
00176             } else {
00177                 httpdError(cid, 403);
00178             }
00179         } else {
00180             httpdError(cid, 404);
00181         }
00182 
00183         if (_httpd[cid].keepalive) {
00184             DBG("keepalive %d", _httpd[cid].keepalive);
00185             _httpd[cid].keepalive --;
00186         } else {
00187             close(cid);
00188         }
00189         _httpd[cid].mode = HTTPDMODE_REQUEST;
00190 #ifdef CFG_ENABLE_WEBSOCKET
00191     } else
00192     if (_httpd[cid].mode == HTTPDMODE_WEBSOCKET_BEGIN) {
00193         wsAccept(cid);
00194         _httpd[cid].mode = HTTPDMODE_WEBSOCKET;
00195     } else
00196     if (_httpd[cid].mode == HTTPDMODE_WEBSOCKET_ENTER) {
00197         wsParseRequest(cid);
00198         _httpd[cid].mode = HTTPDMODE_WEBSOCKET;
00199 #endif
00200     }
00201 
00202         } // PROTO_HTTPD
00203     } // for
00204 }
00205 
00206 int GSwifi::httpdParseRequest (int cid) {
00207     int i, j, len;
00208     char buf[CFG_CMD_SIZE];
00209 
00210     if (_httpd[cid].buf == NULL) return 0;
00211     for (len = 0; len < sizeof(buf); len++) {
00212         if (_httpd[cid].buf->dequeue(&buf[len]) == false) break;
00213     }
00214     buf[len] = 0;
00215 
00216     if (strnicmp(buf, "GET ", 4) == 0) {
00217         _httpd[cid].req = REQ_HTTPGET;
00218         j = 4;
00219     } else
00220     if (strnicmp(buf, "POST ", 5) == 0) {
00221         _httpd[cid].req = REQ_HTTPPOST;
00222         j = 5;
00223     } else {
00224         return -1;
00225     }
00226 #ifndef CFG_ENABLE_RTOS
00227     if (_httpd[cid].uri == NULL)
00228         _httpd[cid].uri = (char*)malloc(CFG_CMD_SIZE);
00229 #endif
00230     for (i = 0; i < len - j; i ++) {
00231         _httpd[cid].uri[i] = buf[i + j];
00232         if (buf[i + j] == ' ' || i >= CFG_CMD_SIZE - 1) {
00233             _httpd[cid].uri[i] = 0;
00234             INFO("URI %d '%s'", _httpd[cid].req, _httpd[cid].uri);
00235             _httpd[cid].mode = HTTPDMODE_HEADER;
00236             if (_httpd[cid].buf != NULL) {
00237                 _httpd[cid].buf->flush();
00238             }
00239             _httpd[cid].length = 0;
00240             _httpd[cid].n = 0;
00241             _httpd[cid].filename = NULL;
00242             _httpd[cid].querystring = NULL;
00243 #ifdef CFG_ENABLE_WEBSOCKET
00244             _httpd[cid].websocket = 0;
00245 #endif
00246             break;
00247         }
00248     }
00249 
00250     i = httpdGetHandler(_httpd[cid].uri);
00251     if (i >= 0) { 
00252         _httpd[cid].filename = &_httpd[cid].uri[strlen(_httpd_handler[i].uri)];
00253         for (i = 0; i < strlen(_httpd[cid].filename); i ++) {
00254             if (_httpd[cid].filename[i] == '?') {
00255                 _httpd[cid].filename[i] = 0;
00256                 _httpd[cid].querystring = _httpd[cid].filename + i + 1;
00257                 break;
00258             }
00259         }
00260         INFO("FILE '%s' QUERY '%s'", _httpd[cid].filename, _httpd[cid].querystring);
00261     }
00262     return 0;
00263 }
00264 
00265 #define HEADER_TABLE_NUM 5
00266 int GSwifi::httpdParseHeader (int cid) {
00267     int i;
00268     char buf[CFG_CMD_SIZE];
00269     static const struct HEADER_TABLE {
00270         const char header[24];
00271         void (GSwifi::*func)(int id, const char*);
00272     } header_table[HEADER_TABLE_NUM] = {
00273       {"Content-Length:",         &GSwifi::reqContentLength},
00274       {"Connection:",             &GSwifi::reqConnection},
00275       {"Upgrade: websocket",      &GSwifi::reqUpgrade},
00276       {"Sec-WebSocket-Version:",  &GSwifi::reqWebSocketVersion},
00277       {"Sec-WebSocket-Key:",      &GSwifi::reqWebSocketKey},
00278     };
00279 
00280     if (_httpd[cid].buf == NULL) return 0;
00281     for (i = 0; i < sizeof(buf); i++) {
00282         if (_httpd[cid].buf->dequeue(&buf[i]) == false) break;
00283     }
00284     buf[i] = 0;
00285 
00286     for (i = 0; i < HEADER_TABLE_NUM; i ++) {
00287         if (strnicmp(buf, header_table[i].header, strlen(header_table[i].header)) == 0) {
00288             DBG("parse header %d '%s'\r\n", i, buf);
00289             if (header_table[i].func != NULL) {
00290                 (this->*(header_table[i].func))(cid, buf);
00291             }
00292             return 0;
00293         }
00294     }
00295 
00296     return -1;
00297 }
00298 
00299 void GSwifi::reqContentLength (int cid, const char *buf) {
00300     _httpd[cid].length = atoi(&buf[16]);
00301 }
00302 
00303 void GSwifi::reqConnection (int cid, const char *buf) {
00304     if (strnicmp(&buf[12], "Keep-Alive", 10) == 0) {
00305         if (_httpd[cid].keepalive == 0)
00306             _httpd[cid].keepalive = CFG_HTTPD_KEEPALIVE;
00307     } else {
00308         _httpd[cid].keepalive = 0;
00309     }
00310 }
00311 
00312 #ifdef CFG_ENABLE_WEBSOCKET
00313 void GSwifi::reqUpgrade (int cid, const char *buf) {
00314     if (! _httpd[cid].websocket) _httpd[cid].websocket = 1;
00315 }
00316 
00317 void GSwifi::reqWebSocketVersion (int cid, const char *buf) {
00318     _httpd[cid].websocket = atoi(&buf[23]);
00319 }
00320 
00321 void GSwifi::reqWebSocketKey (int cid, const char *buf) {
00322 #ifndef CFG_ENABLE_RTOS
00323     if (_httpd[cid].websocket_key == NULL) {
00324         _httpd[cid].websocket_key = (char*)malloc(30);
00325     }
00326 #endif
00327     strncpy(_httpd[cid].websocket_key, &buf[19], 30);
00328 }
00329 #else
00330 void GSwifi::reqUpgrade (int cid, const char *buf) {
00331 }
00332 void GSwifi::reqWebSocketVersion (int cid, const char *buf) {
00333 }
00334 void GSwifi::reqWebSocketKey (int cid, const char *buf) {
00335 }
00336 #endif
00337 
00338 #endif