// replace ~x~ in buf with calculated web_int_callback(x) and put buf to web_conn.msgbuf void tc_parse_buf(TCP_SERV_CONN *ts_conn, uint8 *buf, int32_t len) { WEB_SRV_CONN *web_conn = (WEB_SRV_CONN *)ts_conn->linkd; while(len > 0) { int32_t cmp = web_find_cbs(buf, len); if(cmp >= 0) { // callback (~) has been found int32 cmp2 = web_find_cbs(buf + cmp + 1, len - cmp - 1); // find closing '~' uint8 cbs_not_closed = (cmp2 < 1) * 2; if(web_conn->msgbuflen + cmp + cbs_not_closed > web_conn->msgbufsize) break; // overflow os_memcpy(&web_conn->msgbuf[web_conn->msgbuflen], buf, cmp + cbs_not_closed); web_conn->msgbuflen += cmp + cbs_not_closed; buf += cmp + 1 + cbs_not_closed; len -= cmp + 1 + cbs_not_closed; if(!cbs_not_closed) { // parse uint8 c = buf[cmp2]; buf[cmp2] = '\0'; web_int_callback(ts_conn, buf); buf[cmp2] = c; buf += cmp2 + 1; // skip closing '~' len -= cmp2 + 1; } } else { if(web_conn->msgbuflen + len > web_conn->msgbufsize) break; // overflow os_memcpy(&web_conn->msgbuf[web_conn->msgbuflen], buf, len); web_conn->msgbuflen += len; break; } } }
void ICACHE_FLASH_ATTR web_fini(const uint8 * fname) { struct buf_fini *p = (struct buf_fini *) os_zalloc(sizeof(struct buf_fini)); if(p == NULL) { #if DEBUGSOO > 1 os_printf("Error mem!\n"); #endif return; } TCP_SERV_CONN * ts_conn = &p->ts_conn; WEB_SRV_CONN * web_conn = &p->web_conn; web_conn->bffiles[0] = WEBFS_INVALID_HANDLE; web_conn->bffiles[1] = WEBFS_INVALID_HANDLE; web_conn->bffiles[2] = WEBFS_INVALID_HANDLE; web_conn->bffiles[3] = WEBFS_INVALID_HANDLE; ts_conn->linkd = (uint8 *)web_conn; ts_conn->sizeo = FINI_BUF_SIZE; ts_conn->pbufo = p->buf; rom_strcpy(ts_conn->pbufo, (void *)fname, MAX_FILE_NAME_SIZE); #if DEBUGSOO > 1 os_printf("Run ini file: %s\n", ts_conn->pbufo); #endif if(!web_inc_fopen(ts_conn, ts_conn->pbufo)) { #if DEBUGSOO > 1 os_printf("file not found!\n"); #endif return; } if(fatCache.flags & WEBFS_FLAG_ISZIPPED) { #if DEBUGSOO > 1 os_printf("\nError: file is ZIPped!\n"); #endif web_inc_fclose(web_conn); return; } user_uart_wait_tx_fifo_empty(1,1000); while(1) { web_conn->msgbufsize = ts_conn->sizeo; web_conn->msgbuflen = 0; uint8 *pstr = web_conn->msgbuf = ts_conn->pbufo; if(CheckSCB(SCB_RETRYCB)) { // повторный callback? да #if DEBUGSOO > 2 os_printf("rcb "); #endif if(web_conn->func_web_cb != NULL) web_conn->func_web_cb(ts_conn); if(CheckSCB(SCB_RETRYCB)) break; // повторить ещё раз? да. } uint16 len = WEBFSGetArray(web_conn->webfile, pstr, FINI_BUF_SIZE); #if DEBUGSOO > 3 os_printf("ReadF[%u]=%u\n", web_conn->webfile, len); #endif if(len) { // есть байты в файле pstr[len] = '\0'; int sslen = 0; while(pstr[sslen] == '\n' || pstr[sslen] == '\r') sslen++; if(sslen == 0) { int nslen = find_crlf(pstr, len); if(nslen != 0) { pstr[nslen] = '\0'; // закрыть string calback-а while((nslen < len) && (pstr[nslen] == '\n' || pstr[nslen] == '\r')) nslen++; #if DEBUGSOO > 3 os_printf("String:%s\n", pstr); #endif if(!os_memcmp((void*)pstr, "inc:", 4)) { // "inc:file_name" if(!web_inc_fopen(ts_conn, &pstr[4])) { #if DEBUGSOO > 1 os_printf("file not found!"); #endif }; } else web_int_callback(ts_conn); }; sslen = nslen; }; // откат файла WEBFSStubs[web_conn->webfile].addr -= len; WEBFSStubs[web_conn->webfile].bytesRem += len; // передвинуть указатель в файле на считанные байты с учетом маркера, без добавки длины для передачи WEBFSStubs[web_conn->webfile].addr += sslen; WEBFSStubs[web_conn->webfile].bytesRem -= sslen; } else if(web_inc_fclose(web_conn)) { if(web_conn->web_disc_cb != NULL) web_conn->web_disc_cb(web_conn->web_disc_par); return; } } }
//============================================================================= bool ICACHE_FLASH_ATTR websock_rx_data(TCP_SERV_CONN *ts_conn) { // HTTP_CONN *CurHTTP; WEB_SRV_CONN *web_conn = (WEB_SRV_CONN *)ts_conn->linkd; if(web_conn == NULL) return false; WS_FRSTAT *ws = &web_conn->ws; uint16 len; uint8 *pstr; #if DEBUGSOO > 3 os_printf("ws_rx[%u]%u ", ts_conn->sizei, ts_conn->cntri); #endif if(ts_conn->sizei == 0) return true; // докачивать tcpsrv_unrecved_win(ts_conn); if((ws->flg & WS_FLG_CLOSE) != 0) { // убить буфер ts_conn->pbufi, конец давно :) web_feee_bufi(ts_conn); SetSCB(SCB_DISCONNECT); return false; } if(ts_conn->sizei > MAX_RX_BUF_SIZE) { #if DEBUGSOO > 0 os_printf("ws:rxbuf_full! "); #endif // убить буфер ts_conn->pbufi и ответить ошибкой WS_CLOSE_UNEXPECTED_ERROR web_feee_bufi(ts_conn); websock_tx_close_err(ts_conn, WS_CLOSE_MESSAGE_TOO_BIG); // WS_CLOSE_UNEXPECTED_ERROR); SetSCB(SCB_DISCONNECT); return false; } pstr = ts_conn->pbufi;// + ts_conn->cntri; len = ts_conn->sizei;// - ts_conn->cntri; while(ts_conn->cntri < ts_conn->sizei || (ws->flg & WS_FLG_FIN) != 0) { pstr = ts_conn->pbufi;// + ts_conn->cntri; len = ts_conn->sizei;// - ts_conn->cntri; if((ws->flg & WS_FLG_FIN) != 0 // обработка || ws->frame_len > ws->cur_len) { ws->flg &= ~WS_FLG_FIN; len = mMIN(ws->frame_len - ws->cur_len, mMIN(MAX_WS_DATA_BLK_SIZE, len)); // размаскировать if((ws->flg & WS_FLG_MASK) != 0) WebsocketMask(ws, pstr, len); #if DEBUGSOO > 3 os_printf("wsfr[%u]blk[%u]at:%u ", ws->frame_len, len, ws->cur_len); #endif switch(ws->status) { case sw_frs_binary: #if DEBUGSOO > 1 os_printf("ws:bin "); #endif if(ws->frame_len != 0) { // пока просто эхо uint32 opcode = WS_OPCODE_BINARY; if(ws->cur_len != 0) opcode = WS_OPCODE_CONTINUE; if(ws->frame_len == ws->cur_len + len) opcode |= WS_FRAGMENT_FIN; if(websock_tx_frame(ts_conn, opcode, pstr, len) != ERR_OK) { return false; // не докачивать, ошибка или закрытие } } ws->cur_len += len; ts_conn->cntri += len; break; case sw_frs_text: #if DEBUGSOO > 1 os_printf("ws:txt "); #if DEBUGSOO > 2 if(ws->frame_len != 0) { uint8 tt = pstr[len]; pstr[len] = 0; os_printf("'%s' ", pstr); pstr[len] = tt; } #endif #endif if(ws->frame_len == ws->cur_len + len && ws->frame_len != 0) { // полное соо web_conn->msgbufsize = tcp_sndbuf(ts_conn->pcb); // сколько можем выввести сейчас? if (web_conn->msgbufsize < MIN_SEND_SIZE) { #if DEBUGSOO > 0 os_printf("ws:sndbuf=%u! ", web_conn->msgbufsize); #endif websock_tx_close_err(ts_conn, WS_CLOSE_UNEXPECTED_ERROR); SetSCB(SCB_FCLOSE|SCB_DISCONNECT); return false; } if(ws->frame_len == (sizeof(txt_wsping)-1) && rom_xstrcmp(pstr, txt_wsping) != 0){ copy_s4d1(pstr, (void *)txt_wspong, sizeof(txt_wspong) - 1); if(websock_tx_frame(ts_conn, WS_OPCODE_TEXT | WS_FRAGMENT_FIN, pstr, sizeof(txt_wspong) - 1) != ERR_OK) { return false; // не докачивать, ошибка или закрытие } } else { web_conn->msgbuf = (uint8 *) os_malloc(web_conn->msgbufsize); if (web_conn->msgbuf == NULL) { #if DEBUGSOO > 0 os_printf("ws:mem!\n"); #endif websock_tx_close_err(ts_conn, WS_CLOSE_UNEXPECTED_ERROR); SetSCB(SCB_FCLOSE|SCB_DISCONNECT); return false; }; web_conn->msgbuflen = 0; uint32 opcode; if(CheckSCB(SCB_RETRYCB)) { // повторный callback? да if(web_conn->func_web_cb != NULL) web_conn->func_web_cb(ts_conn); if(!CheckSCB(SCB_RETRYCB)) { ClrSCB(SCB_FCLOSE | SCB_DISCONNECT); opcode = WS_OPCODE_CONTINUE | WS_FRAGMENT_FIN; } else opcode = WS_OPCODE_CONTINUE; } else { pstr[len] = '\0'; uint8 *vstr = os_strchr(pstr, '='); if(vstr != NULL) { *vstr++ = '\0'; web_int_vars(ts_conn, pstr, vstr); } else { web_conn->msgbuf[0] = 0; web_int_callback(ts_conn, pstr); } if(CheckSCB(SCB_RETRYCB)) opcode = WS_OPCODE_TEXT; else { ClrSCB(SCB_FCLOSE | SCB_DISCONNECT); opcode = WS_OPCODE_TEXT | WS_FRAGMENT_FIN; } } if(web_conn->msgbuflen != 0) { if(websock_tx_frame(ts_conn, opcode, web_conn->msgbuf, web_conn->msgbuflen) != ERR_OK) { os_free(web_conn->msgbuf); web_conn->msgbuf = NULL; return false; // не докачивать, ошибка или закрытие } } os_free(web_conn->msgbuf); web_conn->msgbuf = NULL; if(CheckSCB(SCB_RETRYCB)) return false; } } /* if(0) { uint32 opcode = WS_OPCODE_TEXT; if(ws->cur_len != 0) opcode = WS_OPCODE_CONTINUE; if(ws->frame_len == ws->cur_len + len) opcode |= WS_FRAGMENT_FIN; if(websock_tx_frame(ts_conn, opcode, pstr, len) != ERR_OK) { return false; // не докачивать, ошибка или закрытие } } */ ws->cur_len += len; ts_conn->cntri += len; return true; // докачивать // break; // break; case sw_frs_ping: #if DEBUGSOO > 1 os_printf("ws:ping "); #endif { uint32 opcode = WS_OPCODE_PONG; if(ws->cur_len != 0) opcode = WS_OPCODE_CONTINUE; if(ws->frame_len == ws->cur_len + len) opcode |= WS_FRAGMENT_FIN; if(websock_tx_frame(ts_conn, opcode, pstr, len) != ERR_OK) { return false; // не докачивать, ошибка или закрытие } } ws->cur_len += len; ts_conn->cntri += len; return true; // докачивать // break; case sw_frs_pong: #if DEBUGSOO > 1 os_printf("ws:pong "); #endif ws->cur_len += len; ts_conn->cntri += len; break; // return true; case sw_frs_close: #if DEBUGSOO > 1 os_printf("ws:close "); #endif // if((ws->flg & WS_FLG_CLOSE) == 0) { { if(len >= 2) { uint32 close_code = (pstr[0]<<8) | pstr[1]; #if DEBUGSOO > 1 os_printf("code:%d ", close_code); #endif if(close_code == WS_CLOSE_NORMAL) websock_tx_close_err(ts_conn, WS_CLOSE_NORMAL); // else websock_tx_frame(ts_conn, WS_OPCODE_CLOSE | WS_FRAGMENT_FIN, NULL, 0); } else { websock_tx_close_err(ts_conn, WS_CLOSE_NORMAL); // websock_tx_frame(ts_conn, WS_OPCODE_CLOSE | WS_FRAGMENT_FIN, NULL, 0); } } ts_conn->flag.pcb_time_wait_free = 1; SetSCB(SCB_DISCONNECT); // ts_conn->cntri = ts_conn->sizei; /* ws->cur_len += len; ts_conn->cntri += len; */ return false; default: #if DEBUGSOO > 0 os_printf("ws:f?! "); #endif websock_tx_close_err(ts_conn, WS_CLOSE_UNEXPECTED_ERROR); SetSCB(SCB_DISCONNECT); // ts_conn->cntri = ts_conn->sizei; return false; } } else if(ws->cur_len >= ws->frame_len) { // прием и разбор нового фрейма if((ws->flg & WS_FLG_FIN) != 0) { // обработка #if DEBUGSOO > 3 os_printf("ws_rx:fin=%u ", ws->cur_len); #endif } else { uint32 ret = WebsocketHead(ws, pstr, len); if(ret >= WS_CLOSE_NORMAL) { // error или close #if DEBUGSOO > 0 os_printf("ws:txerr=%u ", ret); #endif websock_tx_close_err(ts_conn, ret); // ts_conn->cntri = ts_conn->sizei; // убить буфер ts_conn->pbufi return false; // error } else if(ret == 0) { #if DEBUGSOO > 3 os_printf("ws_rx... "); #endif return true; // докачивать } ts_conn->cntri += ws->head_len; // вычесть заголовок /* switch(ws->status) { case sw_frs_binary: break; case sw_frs_text: if(ws->frame_len > MAX_RX_BUF_SIZE) { websock_tx_close_err(ts_conn, WS_CLOSE_MESSAGE_TOO_BIG); return false; } break; } */ } } #if DEBUGSOO > 3 os_printf("trim%u-%u ", ts_conn->sizei, ts_conn->sizei - ts_conn->cntri ); #endif if(!web_trim_bufi(ts_conn, &ts_conn->pbufi[ts_conn->cntri], ts_conn->sizei - ts_conn->cntri)) { #if DEBUGSOO > 0 os_printf("ws:trim_err! "); #endif // убить буфер ts_conn->pbufi и ответить ошибкой WS_CLOSE_UNEXPECTED_ERROR websock_tx_close_err(ts_conn, WS_CLOSE_UNEXPECTED_ERROR); SetSCB(SCB_DISCONNECT); // ts_conn->cntri = ts_conn->sizei; return false; }; } return false; // не докачивать, ошибка или закрытие }