mirror of
https://github.com/ADElectronics/RTL00_WEB_VS.git
synced 2026-06-30 18:45:39 +00:00
update
This commit is contained in:
parent
6a1f93f17b
commit
764b020238
1201 changed files with 527271 additions and 1 deletions
245
RTLGDB/Project/web/websock.c
Normal file
245
RTLGDB/Project/web/websock.c
Normal file
|
|
@ -0,0 +1,245 @@
|
|||
/******************************************************************************
|
||||
* FileName: websock.c
|
||||
* Description: websocket for web ESP8266
|
||||
* Author: PV`
|
||||
* (c) PV` 2016
|
||||
*******************************************************************************/
|
||||
#include "user_config.h"
|
||||
#ifdef WEBSOCKET_ENA
|
||||
#include "autoconf.h"
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "diag.h"
|
||||
#include "tcpsrv/tcp_srv_conn.h"
|
||||
#include "web_utils.h" // base64encode()
|
||||
#include "web_srv.h"
|
||||
//#include "phy/phy.h"
|
||||
#include "device_lock.h"
|
||||
#include "lwip/tcp.h"
|
||||
#include "websock.h"
|
||||
#include "rtl8195a/rtl_libc.h"
|
||||
#include "esp_comp.h"
|
||||
#include "hal_crypto.h"
|
||||
|
||||
// HTTP/1.1 101 Web Socket Protocol Handshake\r\n
|
||||
const uint8 WebSocketHTTPOkKey[] ICACHE_RODATA_ATTR = "HTTP/1.1 101 Switching Protocols\r\nAccess-Control-Allow-Origin: *\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: %s\r\n\r\n";
|
||||
const uint8 WebSocketAddKey[] ICACHE_RODATA_ATTR = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
|
||||
const uint8 *HTTPUpgrade = "Upgrade:";
|
||||
const uint8 *HTTPwebsocket = "websocket";
|
||||
const uint8 *HTTPSecWebSocketKey = "Sec-WebSocket-Key:";
|
||||
|
||||
//=============================================================================
|
||||
// WebSocketAcceptKey()
|
||||
// 1) взять строковое значение из заголовка Sec-WebSocket-Key и объединить со
|
||||
// строкой 258EAFA5-E914-47DA-95CA-C5AB0DC85B11
|
||||
// 2) вычислить бинарный хеш SHA-1 (бинарная строка из 20 символов) от полученной
|
||||
// в первом пункте строки
|
||||
// 3) закодировать хеш в Base64
|
||||
// skey[24+36]:'dGhlIHNhbXBsZSBub25jZQ==258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
|
||||
// cha:'b37a4f2cc0624f1690f64606cf385945b2bec4ea'
|
||||
// key[28]:'s3pPLMBiTxaQ9kYGzzhZRbK+xOo='
|
||||
//=============================================================================
|
||||
uint8 buff[maxsizeWebSocketKey + sizeWebSocketAddKey]; // [68]
|
||||
bool ICACHE_FLASH_ATTR WebSocketAcceptKey(uint8* dkey, uint8* skey)
|
||||
{
|
||||
int len = 0;
|
||||
bool ret = false;
|
||||
uint8 keybuf[CRYPTO_SHA1_DIGEST_LENGTH];
|
||||
uint8 * buff = os_malloc(maxsizeWebSocketKey + sizeWebSocketAddKey);
|
||||
if(buff) {
|
||||
while(skey[len] >= '+' && len < maxsizeWebSocketKey) {
|
||||
buff[len] = skey[len];
|
||||
len++;
|
||||
};
|
||||
if(len > minsizeWebSocketKey) {
|
||||
rtl_memcpy(&buff[len], WebSocketAddKey, sizeWebSocketAddKey+1);
|
||||
device_mutex_lock(RT_DEV_LOCK_CRYPTO);
|
||||
rtl_crypto_sha1(buff, len + sizeWebSocketAddKey, keybuf);
|
||||
device_mutex_unlock(RT_DEV_LOCK_CRYPTO);
|
||||
// rtl_cryptoEngine_info();
|
||||
len = base64encode(dkey, FileNameSize, keybuf, CRYPTO_SHA1_DIGEST_LENGTH);
|
||||
#if DEBUGSOO > 2
|
||||
os_printf("\ncha:'");
|
||||
print_hex_dump(keybuf, CRYPTO_SHA1_DIGEST_LENGTH, '\0');
|
||||
os_printf("'\n");
|
||||
os_printf("key[%u]:'%s'\n", len, dkey);
|
||||
#endif
|
||||
ret = true;
|
||||
}
|
||||
os_free(buff);
|
||||
}
|
||||
return ret;
|
||||
|
||||
}
|
||||
//=============================================================================
|
||||
// websock_mask() размаскирование блока
|
||||
//=============================================================================
|
||||
void ICACHE_FLASH_ATTR
|
||||
WebsocketMask(WS_FRSTAT *ws, uint8 *raw_data, uint32 raw_len)
|
||||
{
|
||||
uint32 i, x = ws->cur_len;
|
||||
#if DEBUGSOO > 3
|
||||
os_printf("mask[%u]%u ", raw_len, x);
|
||||
#endif
|
||||
for (i = 0; i < raw_len; i++) {
|
||||
raw_data[i] ^= ws->mask.uc[x++ & 3];
|
||||
}
|
||||
}
|
||||
//=============================================================================
|
||||
// websock_head() разбор заголовка
|
||||
//=============================================================================
|
||||
uint32 ICACHE_FLASH_ATTR
|
||||
WebsocketHead(WS_FRSTAT *ws, uint8 *raw_data, uint32 raw_len)
|
||||
{
|
||||
// определить размер заголовка фрейма
|
||||
uint32 head_len = 2;
|
||||
if(raw_len < head_len) return 0; // докачивать
|
||||
uint32 data_len = raw_data[1] & WS_SIZE1_BITS;
|
||||
if(data_len == 127) head_len = 10;
|
||||
else if(data_len == 126) head_len = 4;
|
||||
if(raw_data[1] & WS_MASK_FLG) head_len += 4;
|
||||
if(raw_len < head_len) return 0; // докачивать
|
||||
ws->head_len = head_len;
|
||||
ws->cur_len = 0;
|
||||
ws->flg = 0;
|
||||
data_len = raw_data[1] & WS_SIZE1_BITS;
|
||||
if(data_len >= 126) {
|
||||
if(data_len == 127) {
|
||||
uint32 i;
|
||||
for(i = 3; i < 6; i++) {
|
||||
if(raw_data[i] != 0) {
|
||||
ws->status = sw_frs_close;
|
||||
ws->frame_len = 0;
|
||||
return WS_CLOSE_MESSAGE_TOO_BIG;
|
||||
}
|
||||
}
|
||||
data_len = (raw_data[6] << 24) | (raw_data[7] << 16) | (raw_data[8] << 8) | raw_data[9];
|
||||
}
|
||||
else {
|
||||
data_len = (raw_data[2] << 8) | raw_data[3];
|
||||
}
|
||||
}
|
||||
if(raw_data[1] & WS_MASK_FLG) {
|
||||
ws->flg |= WS_FLG_MASK;
|
||||
ws->mask.uc[0] = raw_data[head_len-4];
|
||||
ws->mask.uc[1] = raw_data[head_len-3];
|
||||
ws->mask.uc[2] = raw_data[head_len-2];
|
||||
ws->mask.uc[3] = raw_data[head_len-1];
|
||||
}
|
||||
// else ws->mask = 0;
|
||||
uint8 opcode = raw_data[0] & WS_OPCODE_BITS;
|
||||
switch(opcode) {
|
||||
case WS_OPCODE_PING: // эхо - дублировать прием
|
||||
raw_data[0] &= ~WS_FRAGMENT_FIN;
|
||||
raw_data[0] |= WS_OPCODE_PONG;
|
||||
ws->status = sw_frs_pong;
|
||||
ws->frame_len = data_len;
|
||||
break;
|
||||
case WS_OPCODE_PONG: // эхо - дублировать прием
|
||||
ws->status = sw_frs_ping;
|
||||
ws->frame_len = data_len;
|
||||
break;
|
||||
case WS_OPCODE_CONTINUE: // продолжить
|
||||
if(ws->status == sw_frs_pong) {
|
||||
ws->frame_len = data_len;
|
||||
break;
|
||||
}
|
||||
else ws->frame_len += data_len;
|
||||
break;
|
||||
case WS_OPCODE_CLOSE: //
|
||||
ws->status = sw_frs_close;
|
||||
ws->frame_len = data_len;
|
||||
break;
|
||||
case WS_OPCODE_TEXT:
|
||||
ws->status = sw_frs_text;
|
||||
ws->frame_len = data_len;
|
||||
break;
|
||||
case WS_OPCODE_BINARY:
|
||||
ws->status = sw_frs_binary;
|
||||
ws->frame_len = data_len;
|
||||
break;
|
||||
default:
|
||||
ws->status = sw_frs_close;
|
||||
ws->frame_len = 0;
|
||||
return WS_CLOSE_WRONG_TYPE;
|
||||
}
|
||||
// uint32 len = mMIN(raw_len - head_len, data_len);
|
||||
// if((ws->flg & WS_FLG_MASK) != 0) websock_mask(ws, &raw_data[head_len], mMIN(raw_len - head_len, len));
|
||||
// ws->cur_len += len;
|
||||
if((raw_data[0] & WS_FRAGMENT_FIN) != 0) { // конец - данные на обработку
|
||||
ws->flg |= WS_FLG_FIN;
|
||||
}
|
||||
#if DEBUGSOO > 1
|
||||
os_printf("ws#%02xrx[%u] ", raw_data[0], data_len);
|
||||
#endif
|
||||
return 1;
|
||||
/*
|
||||
if(data_len + head_len <= raw_len) { // весь пакет уже в буфере?
|
||||
return 1;
|
||||
}
|
||||
return 0; // докачивать */
|
||||
}
|
||||
//=============================================================================
|
||||
// websock_tx_frame() - передача фрейма
|
||||
//=============================================================================
|
||||
err_t ICACHE_FLASH_ATTR
|
||||
WebsocketTxFrame(TCP_SERV_CONN *ts_conn, uint32 opcode, uint8 *raw_data, uint32 raw_len)
|
||||
{
|
||||
union {
|
||||
uint8 uc[8];
|
||||
uint16 uw[4];
|
||||
uint32 ud[2];
|
||||
}head;
|
||||
union {
|
||||
uint8 uc[4];
|
||||
uint16 uw[2];
|
||||
uint32 ud;
|
||||
}mask;
|
||||
if(raw_data == NULL) raw_len = 0;
|
||||
head.ud[0] = opcode;
|
||||
uint32 head_len;
|
||||
if(raw_len > 126) {
|
||||
head.uc[1] = 126;
|
||||
head.uc[2] = raw_len>>8;
|
||||
head.uc[3] = raw_len;
|
||||
head_len = 4;
|
||||
}
|
||||
else {
|
||||
head.uc[1] = raw_len;
|
||||
head_len = 2;
|
||||
};
|
||||
if(opcode & (WS_MASK_FLG << 8)) {
|
||||
mask.ud ^= rand();
|
||||
head.uc[1] |= WS_MASK_FLG;
|
||||
head.uc[head_len] = mask.uc[0];
|
||||
head.uc[head_len+1] = mask.uc[1];
|
||||
head.uc[head_len+2] = mask.uc[2];
|
||||
head.uc[head_len+3] = mask.uc[3];
|
||||
head_len += 4;
|
||||
}
|
||||
uint32 len = tcp_sndbuf(ts_conn->pcb);
|
||||
err_t err = 1; // ERR_BUF;
|
||||
if(len >= raw_len + head_len) {
|
||||
#if DEBUGSOO > 1
|
||||
os_printf("ws#%02xtx[%u] ", head.uc[0], raw_len);
|
||||
#endif
|
||||
ts_conn->flag.nagle_disabled = 0;
|
||||
tcp_nagle_disable(ts_conn->pcb);
|
||||
err = tcpsrv_int_sent_data(ts_conn, head.uc, head_len);
|
||||
ts_conn->flag.nagle_disabled = 1;
|
||||
if(err == ERR_OK && raw_len != 0) {
|
||||
if(opcode & (WS_MASK_FLG << 8)) {
|
||||
uint32 i;
|
||||
for (i = 0; i < raw_len; i++) {
|
||||
raw_data[i] ^= mask.uc[i & 3];
|
||||
}
|
||||
}
|
||||
err = tcpsrv_int_sent_data(ts_conn, raw_data, raw_len);
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
#endif // WEBSOCKET_ENA
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue