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
GSwifi_httpd_ws.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_WEBSOCKET 00022 00023 #include "sha1.h" 00024 00025 int GSwifi::wsOpen (const char *host, int port, const char *uri, const char *user, const char *pwd) { 00026 int cid; 00027 char cmd[CFG_CMD_SIZE], tmp[CFG_CMD_SIZE]; 00028 char ip[17]; 00029 00030 if (!isAssociated() || _state.status != STAT_READY) return -1; 00031 00032 if (getHostByName(host, ip)) return -1; 00033 if (! port) { 00034 port = 80; 00035 } 00036 00037 cid = open(PROTO_TCP, ip, port); 00038 if (cid < 0) return -1; 00039 DBG("ws cid %d\r\n", cid); 00040 00041 // request 00042 snprintf(cmd, sizeof(cmd), "GET %s HTTP/1.1\r\n", uri); 00043 send(cid, cmd, strlen(cmd)); 00044 if (host) { 00045 snprintf(cmd, sizeof(cmd), "Host: %s\r\n", host); 00046 send(cid, cmd, strlen(cmd)); 00047 } 00048 if (user && pwd) { 00049 snprintf(cmd, sizeof(cmd), "%s:%s", user, pwd); 00050 base64encode(cmd, strlen(cmd), tmp, sizeof(tmp)); 00051 snprintf(cmd, sizeof(cmd), "Authorization: Basic %s\r\n", tmp); 00052 send(cid, cmd, strlen(cmd)); 00053 } 00054 strcpy(cmd, "Upgrade: websocket\r\n"); 00055 send(cid, cmd, strlen(cmd)); 00056 strcpy(cmd, "Connection: Upgrade\r\n"); 00057 send(cid, cmd, strlen(cmd)); 00058 getMacAddress(cmd); 00059 memcpy(&cmd[6], host, 10); 00060 base64encode(cmd, 16, tmp, sizeof(tmp)); 00061 snprintf(cmd, sizeof(cmd), "Sec-WebSocket-Key: %s\r\n", tmp); 00062 send(cid, cmd, strlen(cmd)); 00063 // strcpy(cmd, "Sec-WebSocket-Protocol: chat\r\n"); 00064 // send(cid, cmd, strlen(cmd)); 00065 strcpy(cmd, "Sec-WebSocket-Version: 13\r\n\r\n"); 00066 send(cid, cmd, strlen(cmd)); 00067 00068 if (wsWait(cid, 101)) { 00069 close(cid); 00070 return -1; 00071 } 00072 wsWait(cid, 0); 00073 return cid; 00074 } 00075 00076 int GSwifi::wsWait (int cid, int code) { 00077 Timer timeout; 00078 int i, n, len; 00079 char buf[CFG_DATA_SIZE], data[CFG_CMD_SIZE]; 00080 00081 if (code == 0) { 00082 // dummy read 00083 timeout.start(); 00084 while (timeout.read_ms() < CFG_TIMEOUT) { 00085 wait_ms(10); 00086 if (!readable(cid)) break; 00087 n = recv(cid, buf, sizeof(buf)); 00088 if (n <= 0) break; 00089 } 00090 timeout.stop(); 00091 return 0; 00092 } 00093 00094 // wait responce 00095 len = 0; 00096 timeout.start(); 00097 while (timeout.read_ms() < CFG_TIMEOUT) { 00098 wait_ms(10); 00099 n = recv(cid, buf, sizeof(buf)); 00100 for (i = 0; i < n; i ++) { 00101 if (buf[i] == '\r') continue; 00102 if (buf[i] == '\n') { 00103 if (len == 0) continue; 00104 goto next; 00105 } else 00106 if (len < sizeof(data) - 1) { 00107 data[len] = buf[i]; 00108 len ++; 00109 } 00110 } 00111 } 00112 next: 00113 data[len] = 0; 00114 timeout.stop(); 00115 DBG("ws: %s\r\n", data); 00116 00117 // check return code 00118 if (strncmp(data, "HTTP/1.1 ", 9) != 0) return -1; 00119 i = atoi(&data[9]); 00120 DBG("ws status %d\r\n", i); 00121 return i == code ? 0 : -1; 00122 } 00123 00124 int GSwifi::wsSend (int cid, const char *buf, int len, const char *mask) { 00125 int i = 0, r; 00126 char tmp[10]; 00127 00128 tmp[i++] = 0x81; // single, text frame 00129 if (len < 126) { 00130 tmp[i++] = (mask == NULL ? 0 : 0x80) | len; 00131 } else { 00132 tmp[i++] = (mask == NULL ? 0 : 0x80) | 126; 00133 tmp[i++] = (len >> 8) & 0xff; 00134 tmp[i++] = len & 0xff; 00135 } 00136 if (mask) { 00137 memcpy(&tmp[i], mask, 4); 00138 i += 4; 00139 } 00140 r = send(cid, tmp, i); 00141 00142 if (r > 0) { 00143 if (mask) { 00144 char tmp2[len]; 00145 for (i = 0; i < len; i ++) { 00146 tmp2[i] = buf[i] ^ mask[i & 0x03]; 00147 } 00148 r = send(cid, tmp2, len); 00149 } else { 00150 r = send(cid, buf, len); 00151 } 00152 } 00153 return r; 00154 } 00155 00156 #ifdef CFG_ENABLE_HTTPD 00157 00158 void GSwifi::wsRecvData (int cid, char c) { 00159 00160 switch (_httpd[cid].mode) { 00161 case HTTPDMODE_WEBSOCKET: 00162 if (_httpd[cid].n == 0) { 00163 // flag 00164 _httpd[cid].websocket_opcode = c & 0x0f; 00165 _httpd[cid].websocket_flg = c << 8; 00166 _httpd[cid].n ++; 00167 } else 00168 if (_httpd[cid].n == 1) { 00169 // length 7bit 00170 _httpd[cid].websocket_flg |= c; 00171 _httpd[cid].length = c & 0x7f; 00172 _httpd[cid].n ++; 00173 if (_httpd[cid].length < 126) { 00174 _httpd[cid].n = 0; 00175 if (_httpd[cid].length) { 00176 if (_httpd[cid].websocket_flg & 0x0080) { 00177 _httpd[cid].mode = HTTPDMODE_WEBSOCKET_MASK; 00178 } else { 00179 _httpd[cid].mode = HTTPDMODE_WEBSOCKET_BODY; 00180 } 00181 } else { 00182 _httpd[cid].mode = HTTPDMODE_WEBSOCKET_ENTER; 00183 } 00184 DBG("ws length %d\r\n", _httpd[cid].length); 00185 } 00186 } else { 00187 // length 16bit,64bit 00188 if (_httpd[cid].n == 2) { 00189 _httpd[cid].length = c; 00190 _httpd[cid].n ++; 00191 } else 00192 if (_httpd[cid].n < 9 && (_httpd[cid].websocket_flg & 0x7f) == 127) { 00193 // 64bit 00194 _httpd[cid].length = (_httpd[cid].length << 8) | c; 00195 _httpd[cid].n ++; 00196 } else { 00197 // end 00198 _httpd[cid].length = (_httpd[cid].length << 8) | c; 00199 _httpd[cid].n = 0; 00200 if (_httpd[cid].websocket_flg & 0x0080) { 00201 _httpd[cid].mode = HTTPDMODE_WEBSOCKET_MASK; 00202 } else { 00203 _httpd[cid].mode = HTTPDMODE_WEBSOCKET_BODY; 00204 } 00205 DBG("ws length2 %d\r\n", _httpd[cid].length); 00206 } 00207 } 00208 break; 00209 case HTTPDMODE_WEBSOCKET_MASK: 00210 // masking key 00211 _httpd[cid].websocket_mask[_httpd[cid].n] = c; 00212 _httpd[cid].n ++; 00213 if (_httpd[cid].n >= 4) { 00214 _httpd[cid].n = 0; 00215 _httpd[cid].mode = HTTPDMODE_WEBSOCKET_BODY; 00216 DBG("ws mask\r\n"); 00217 } 00218 break; 00219 case HTTPDMODE_WEBSOCKET_BODY: 00220 // payload 00221 if (_httpd[cid].websocket_flg & 0x0080) { 00222 // un-mask 00223 _httpd[cid].buf->queue(c ^ _httpd[cid].websocket_mask[_httpd[cid].n & 0x03]); 00224 } else { 00225 _httpd[cid].buf->queue(c); 00226 } 00227 _httpd[cid].n ++; 00228 if (_httpd[cid].n >= _httpd[cid].length) { 00229 _httpd[cid].mode = HTTPDMODE_WEBSOCKET_ENTER; 00230 _con[cid].received = true; 00231 } 00232 break; 00233 } 00234 } 00235 00236 int GSwifi::wsParseRequest (int cid) { 00237 int i; 00238 00239 DBG("ws opcode %d\r\n", _httpd[cid].websocket_opcode); 00240 switch (_httpd[cid].websocket_opcode) { 00241 case 0x00: // continuation 00242 break; 00243 case 0x01: // text 00244 case 0x02: // binary 00245 i = httpdGetHandler(_httpd[cid].uri); 00246 if (i >= 0) { 00247 if (_httpd_handler[i].func && _httpd_handler[i].ws) { 00248 // cgi 00249 _httpd_handler[i].func(cid); 00250 } 00251 } 00252 break; 00253 case 0x08: // close 00254 close(cid); 00255 break; 00256 case 0x09: // ping 00257 { 00258 char pong[_httpd[cid].n + 2]; 00259 pong[0] = 0x8a; 00260 pong[1] = 0x04; 00261 for (i = 0; i < _httpd[cid].length; i ++) { 00262 if (_httpd[cid].buf->dequeue(&pong[i + 2]) == false) break; 00263 } 00264 send(cid, pong, _httpd[cid].length + 2); 00265 } 00266 break; 00267 case 0x0a: // pong 00268 break; 00269 default: 00270 break; 00271 } 00272 _httpd[cid].n = 0; 00273 _httpd[cid].length = 0; 00274 return 0; 00275 } 00276 00277 int GSwifi::wsAccept (int cid) { 00278 char buf[CFG_CMD_SIZE], buf2[CFG_CMD_SIZE]; 00279 00280 DBG("websocket accept: %d\r\n", cid); 00281 00282 strcpy(buf, "HTTP/1.1 101 Switching Protocols\r\n"); 00283 send(cid, buf, strlen(buf)); 00284 strcpy(buf, "Upgrade: websocket\r\n"); 00285 send(cid, buf, strlen(buf)); 00286 strcpy(buf, "Connection: Upgrade\r\n"); 00287 send(cid, buf, strlen(buf)); 00288 00289 strcpy(buf, "Sec-WebSocket-Accept: "); 00290 send(cid, buf, strlen(buf)); 00291 strcpy(buf, _httpd[cid].websocket_key); 00292 strcat(buf, "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"); 00293 sha1(buf, strlen(buf), buf2); 00294 base64encode(buf2, 20, buf, sizeof(buf)); 00295 send(cid, buf, strlen(buf)); 00296 strcpy(buf, "\r\n\r\n"); 00297 send(cid, buf, strlen(buf)); 00298 return 0; 00299 } 00300 00301 #endif 00302 #endif
Generated on Thu Jul 14 2022 07:53:37 by 1.7.2