more handlers
Dependents: bandwidth-meter-net mbedRail24v
Fork of Tiny-HTTPD by
HTTPD_ws.cpp
00001 /* Copyright (C) 2013 Hiroshi Suga, 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 "HTTPD.h" 00020 #include "sha1.h" 00021 00022 void HTTPD::recvWS (int id, char c) { 00023 00024 switch (_state[id].mode) { 00025 case MODE_WEBSOCKET: 00026 if (_state[id].n == 0) { 00027 // flag 00028 _state[id].websocket_opcode = c & 0x0f; 00029 _state[id].websocket_flg = c << 8; 00030 _state[id].n ++; 00031 } else 00032 if (_state[id].n == 1) { 00033 // length 7bit 00034 _state[id].websocket_flg |= c; 00035 _state[id].length = c & 0x7f; 00036 _state[id].n ++; 00037 if (_state[id].length < 126) { 00038 _state[id].n = 0; 00039 if (_state[id].length) { 00040 if (_state[id].websocket_flg & 0x0080) { 00041 _state[id].mode = MODE_WEBSOCKET_MASK; 00042 } else { 00043 _state[id].mode = MODE_WEBSOCKET_BODY; 00044 } 00045 } else { 00046 _state[id].mode = MODE_WEBSOCKET_ENTER; 00047 } 00048 DBG("ws length %d\r\n", _state[id].length); 00049 } 00050 } else { 00051 // length 16bit,64bit 00052 if (_state[id].n == 2) { 00053 _state[id].length = c; 00054 _state[id].n ++; 00055 } else 00056 if (_state[id].n < 9 && (_state[id].websocket_flg & 0x7f) == 127) { 00057 // 64bit 00058 _state[id].length = (_state[id].length << 8) | c; 00059 _state[id].n ++; 00060 } else { 00061 // end 00062 _state[id].length = (_state[id].length << 8) | c; 00063 _state[id].n = 0; 00064 if (_state[id].websocket_flg & 0x0080) { 00065 _state[id].mode = MODE_WEBSOCKET_MASK; 00066 } else { 00067 _state[id].mode = MODE_WEBSOCKET_BODY; 00068 } 00069 DBG("ws length2 %d\r\n", _state[id].length); 00070 } 00071 } 00072 break; 00073 case MODE_WEBSOCKET_MASK: 00074 // masking key 00075 _state[id].websocket_mask[_state[id].n] = c; 00076 _state[id].n ++; 00077 if (_state[id].n >= 4) { 00078 _state[id].n = 0; 00079 _state[id].mode = MODE_WEBSOCKET_BODY; 00080 DBG("ws mask\r\n"); 00081 } 00082 break; 00083 case MODE_WEBSOCKET_BODY: 00084 // payload 00085 if (_state[id].websocket_flg & 0x0080) { 00086 // un-mask 00087 _state[id].buf->queue(c ^ _state[id].websocket_mask[_state[id].n & 0x03]); 00088 } else { 00089 _state[id].buf->queue(c); 00090 } 00091 _state[id].n ++; 00092 if (_state[id].n >= _state[id].length) { 00093 _state[id].mode = MODE_WEBSOCKET_ENTER; 00094 } 00095 break; 00096 } 00097 } 00098 00099 int HTTPD::parseWebsocket (int id) { 00100 int i; 00101 00102 DBG("ws opcode %d\r\n", _state[id].websocket_opcode); 00103 switch (_state[id].websocket_opcode) { 00104 case 0x00: // continuation 00105 break; 00106 case 0x01: // text 00107 case 0x02: // binary 00108 i = getHandler(_state[id].uri); 00109 if (i >= 0) { 00110 if (_handler[i].funcCgi) { 00111 // cgi 00112 _handler[i].funcCgi(id); 00113 } 00114 } 00115 break; 00116 case 0x08: // close 00117 _state[id].client->close(); 00118 break; 00119 case 0x09: // ping 00120 { 00121 char pong[_state[id].n + 2]; 00122 pong[0] = 0x8a; 00123 pong[1] = 0x04; 00124 for (i = 0; i < _state[id].length; i ++) { 00125 if (_state[id].buf->dequeue(&pong[i + 2]) == false) break; 00126 } 00127 _state[id].client->send_all(pong, _state[id].length + 2); 00128 } 00129 break; 00130 case 0x0a: // pong 00131 break; 00132 default: 00133 break; 00134 } 00135 _state[id].n = 0; 00136 _state[id].length = 0; 00137 return 0; 00138 } 00139 00140 int HTTPD::acceptWebsocket (int id) { 00141 char buf[HTTPD_CMD_SIZE], buf2[HTTPD_CMD_SIZE]; 00142 00143 DBG("websocket accept: %d\r\n", id); 00144 00145 strcpy(buf, "HTTP/1.1 101 Switching Protocols\r\n"); 00146 _state[id].client->send_all(buf, strlen(buf)); 00147 strcpy(buf, "Upgrade: websocket\r\n"); 00148 _state[id].client->send_all(buf, strlen(buf)); 00149 strcpy(buf, "Connection: Upgrade\r\n"); 00150 _state[id].client->send_all(buf, strlen(buf)); 00151 00152 strcpy(buf, "Sec-WebSocket-Accept: "); 00153 _state[id].client->send_all(buf, strlen(buf)); 00154 strcpy(buf, _state[id].websocket_key); 00155 strcat(buf, "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"); 00156 sha1(buf, strlen(buf), buf2); 00157 base64encode(buf2, 20, buf, sizeof(buf)); 00158 _state[id].client->send_all(buf, strlen(buf)); 00159 strcpy(buf, "\r\n\r\n"); 00160 _state[id].client->send_all(buf, strlen(buf)); 00161 _state[id].client->set_blocking(true, HTTPD_TIMEOUT * 100); 00162 return 0; 00163 } 00164 00165 int HTTPD::sendWebsocket (int id, const char *buf, int len, const char *mask) { 00166 HTTPD *httpd = HTTPD::getInstance(); 00167 int i = 0, r; 00168 char tmp[10]; 00169 00170 tmp[i++] = 0x81; // single, text frame 00171 if (len < 126) { 00172 tmp[i++] = (mask == NULL ? 0 : 0x80) | len; 00173 } else { 00174 tmp[i++] = (mask == NULL ? 0 : 0x80) | 126; 00175 tmp[i++] = (len >> 8) & 0xff; 00176 tmp[i++] = len & 0xff; 00177 } 00178 if (mask) { 00179 memcpy(&tmp[i], mask, 4); 00180 i += 4; 00181 } 00182 r = httpd->_state[id].client->send_all(tmp, i); 00183 00184 if (r >= 0) { 00185 if (mask) { 00186 char tmp2[len]; 00187 for (i = 0; i < len; i ++) { 00188 tmp2[i] = buf[i] ^ mask[i & 0x03]; 00189 } 00190 r = httpd->_state[id].client->send_all(tmp2, len); 00191 } else { 00192 r = httpd->_state[id].client->send_all((char*)buf, len); 00193 } 00194 } 00195 return r; 00196 } 00197 00198
Generated on Sun Jul 24 2022 08:41:21 by 1.7.2