277 lines
8.1 KiB
C
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
|
|
|