예제 #1
0
// 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;
		}
	}
}
예제 #2
0
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;
		}
	}
}
예제 #3
0
//=============================================================================
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; // не докачивать, ошибка или закрытие
}