Files
2025-12-03 11:12:34 +08:00

277 lines
8.1 KiB
C

#include "websocket_api.h"
#include "os/os_compat.h"
#ifdef WEBSOCKET_MEMHEAP_DEBUG
#include "mem_leak_test.h"
#endif
#include "ifly_socket.h"
#include "ui/ui_api.h"
#include "cJSON.h"
#include "app_config.h"
#if TCFG_IFLYTEK_ENABLE
#define LOG_TAG_CONST NET_IFLY
#define LOG_TAG "[IFLY_SOCKET]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
#define LOG_CLI_ENABLE
#include "debug.h"
#define IFLY_SOCKET_KILL_TASK_NAME "ifly_socket_kill"
struct ifly_socket_info {
struct websocket_struct socket_info;
u8 force_stop; // 强制结束
};
extern int task_kill(const char *name);
extern void websockets_sleep(unsigned int ms);
static void task_kill_callback(char *buf)
{
log_info("[msg]>>>>>>>>>>>*buf=%s", buf);
task_kill(buf);
}
static void ifly_socket_kill_task_main(void *priv)
{
int msg[16];
while (1) {
os_taskq_pend(NULL, msg, ARRAY_SIZE(msg));
}
}
int ifly_socket_kill_task_create(void)
{
int err = os_task_create(ifly_socket_kill_task_main,
NULL,
5,
256,
256,
IFLY_SOCKET_KILL_TASK_NAME);
return err;
}
void ifly_socket_kill_task_release(void)
{
if (!strcmp(os_current_task(), IFLY_SOCKET_KILL_TASK_NAME)) {
task_kill(IFLY_SOCKET_KILL_TASK_NAME);
return ;
}
int msg[4];
msg[0] = (int)task_kill_callback;
msg[1] = 1;
msg[2] = (int)IFLY_SOCKET_KILL_TASK_NAME;
os_taskq_post_type("app_core", Q_CALLBACK, 3, msg);
}
static void websockets_client_reg(struct websocket_struct *websockets_info, ifly_socket_param *ifly_socket)
{
memset(websockets_info, 0, sizeof(struct websocket_struct));
websockets_info->_init = websockets_client_socket_init;
websockets_info->_exit = websockets_client_socket_exit;
websockets_info->_handshack = webcockets_client_socket_handshack;
websockets_info->_send = websockets_client_socket_send;
websockets_info->_recv_thread = websockets_client_socket_recv_thread;
websockets_info->_heart_thread = websockets_client_socket_heart_thread;
websockets_info->_recv_cb = ifly_socket->recv_cb;
websockets_info->_recv = NULL;
websockets_info->websocket_mode = ifly_socket->socket_mode;
websockets_info->kill_task = IFLY_SOCKET_KILL_TASK_NAME;
}
static int websockets_client_init(struct websocket_struct *websockets_info, u8 *url, const char *origin_str, const char *user_agent_str)
{
websockets_info->ip_or_url = url;
websockets_info->origin_str = origin_str;
websockets_info->user_agent_str = user_agent_str;
websockets_info->recv_time_out = 1000;
//应用层和库的版本检测,结构体不一样则返回出错
int err = websockets_struct_check(sizeof(struct websocket_struct));
if (err == FALSE) {
return err;
}
return websockets_info->_init(websockets_info);
}
static int websockets_client_handshack(struct websocket_struct *websockets_info)
{
return websockets_info->_handshack(websockets_info);
}
static int websockets_client_send(struct websocket_struct *websockets_info, u8 *buf, int len, char type)
{
//SSL加密时一次发送数据不能超过16K,用户需要自己分包
return websockets_info->_send(websockets_info, buf, len, type);
}
static void websockets_client_exit(struct websocket_struct *websockets_info)
{
websockets_info->_exit(websockets_info);
}
static void ifly_socket_task_main(void *priv)
{
int err;
ifly_socket_event_enum ifly_evt = IFLY_SOCKET_EVT_END;
ifly_socket_param *ifly_socket = (ifly_socket_param *)priv;
struct ifly_socket_info *info = (struct ifly_socket_info *)ifly_socket->socket_hdl;
const char *origin_str = "http://coolaf.com";
log_info(" . ----------------- Client Websocket ------------------\r\n");
/* 0 . malloc buffer */
struct websocket_struct *websockets_info = &info->socket_info;
/* 1 . register */
websockets_client_reg(websockets_info, ifly_socket);
/* 2 . init */
err = websockets_client_init(websockets_info, ifly_socket->auth, origin_str, NULL);
if (FALSE == err) {
log_error(" . ! Cilent websocket init error !!!\r\n");
ifly_evt = IFLY_SOCKET_EVT_INIT_ERROR;
goto exit_ws;
}
/* 3 . hanshack */
err = websockets_client_handshack(websockets_info);
if (FALSE == err) {
log_error(" . ! Handshake error !!!\r\n");
ifly_evt = IFLY_SOCKET_EVT_HANSHACK_ERROR;
goto exit_ws;
}
log_info(" . Handshake success \r\n");
/* 4 . CreateThread */
err = os_task_create(websockets_info->_heart_thread,
websockets_info,
3,
1024,
0,
"websocket_client_heart");
if (err == 0) {
websockets_info->ping_thread_id = 1;
} else {
websockets_info->ping_thread_id = 0;
}
err = os_task_create(websockets_info->_recv_thread,
websockets_info,
2,
1024,
0,
"websocket_client_recv");
if (err == 0) {
websockets_info->recv_thread_id = 1;
} else {
websockets_info->recv_thread_id = 0;
}
ifly_socket->event_cb(IFLY_SOCKET_EVT_INIT_OK, ifly_socket);
/* 5 . recv or send data */
while (1) {
u8 *send_buf = NULL;
u32 send_len = 0;
if (websockets_info->websocket_valid == INVALID_ESTABLISHED) {
//websocket底层断开连接
ifly_evt = IFLY_SOCKET_EVT_ACCIDENT_END;
goto exit_ws;
}
if (info->force_stop) {
ifly_evt = IFLY_SOCKET_EVT_FORCE_END;
goto exit_ws;
}
err = ifly_socket->get_send(&send_buf, &send_len);
if (err == false) {
// 获取不到数据,正常退出
goto exit_ws;
}
if ((send_buf == NULL) || (send_len == 0)) {
continue;
}
err = websockets_client_send(websockets_info, send_buf, send_len, WCT_TXTDATA);
if (FALSE == err) {
log_error(" . ! send err !!!\r\n");
ifly_socket->event_cb(IFLY_SOCKET_EVT_SEND_ERROR, send_buf);
goto exit_ws;
}
ifly_socket->event_cb(IFLY_SOCKET_EVT_SEND_OK, send_buf);
}
exit_ws:
/* 6 . exit */
ifly_socket->event_cb(ifly_evt, ifly_socket);
if (websockets_info->ping_thread_id) {
websockets_info->ping_kill_flag = 1;
}
if (websockets_info->recv_thread_id) {
websockets_info->recv_kill_flag = 1;
}
while (websockets_info->recv_kill_flag || websockets_info->ping_kill_flag) {
os_time_dly(1);
}
websockets_client_exit(websockets_info);
ifly_socket->event_cb(IFLY_SOCKET_EVT_EXIT, ifly_socket);
free(ifly_socket->socket_hdl);
ifly_socket->socket_hdl = NULL;
int msg[5];
msg[0] = (int)task_kill_callback;
msg[1] = 1;
msg[2] = (int)os_current_task();
err = os_taskq_post_type("app_core", Q_CALLBACK, 3, msg);
os_time_dly(-1);
}
bool ifly_websocket_client_create(ifly_socket_param *ifly_socket)
{
ifly_socket->socket_hdl = zalloc(sizeof(struct ifly_socket_info));
if (ifly_socket->socket_hdl == NULL) {
return false;
}
os_task_create(ifly_socket_task_main,
ifly_socket,
3,
2048,
0,
ifly_socket->task_name);
return true;
}
void ifly_websocket_client_release(ifly_socket_param *ifly_socket, u32 to_ms)
{
if (ifly_socket && ifly_socket->socket_hdl) {
struct ifly_socket_info *info = (struct ifly_socket_info *)ifly_socket->socket_hdl;
info->force_stop = 1;
if (!strcmp(os_current_task(), ifly_socket->task_name)) {
// 任务内部调用
return ;
}
// 其他任务调用
while (ifly_socket->socket_hdl) {
os_time_dly(1);
if (to_ms <= 10) {
break;
}
to_ms -= 10;
}
}
}
#endif