/******************************************************************************
Copyright © 2018-2018 TP-Link Systems Inc.
Filename: httpd.c
Version: 1.0
Description: http 服务模块
Author: liyijieliyijie@tp-link.com.cn
Date: 2018-9-10
******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <netinet/tcp.h>
#include <sys/types.h>
#include <sys/socket.h>
#include “nsd_common.h”
#include “httpd.h”
#include “http_parser.h”
#include “http_auth.h”
#include “http_utils.h”
#include “http_special_request.h”
#include “libds.h”
#include “slp_model.h”
#include “http_login_err.h”
/* 服务器buf */
#define HTTPD_SRV_SOCKET_RECV_BUF_SIZE (32 * 1024)
#define HTTPD_SRV_SOCKET_SEND_BUF_SIZE (32 * 1024)
/* 连接buf */
#define HTTPD_CON_SOCKET_RECV_BUF_SIZE (64 * 1024)
#define HTTPD_CON_SOCKET_SEND_BUF_SIZE (32 * 1024)
#define HTTP_KEY_PATH “/etc/uhttpd.key”
#define HTTP_CERT_PATH “/etc/uhttpd.crt”
LOCAL CONTEXT g_context_array[HTTP_MAX_CONTEXT];
LOCAL HTTP_GROUP_SRV g_http_group_srv[GROUP_MAX];
LOCAL S32 g_last_context = 0;
UHTTPD_MAIN g_uhttp_main;
LOCAL S32 g_https_sock = -1;
LOCAL S32 g_http_sock = -1;
LOCAL S32 g_https_inet_idx = -1;
LOCAL S32 g_http_inet_idx = -1;
LOCAL S32 g_http_sock_default = -1;
LOCAL S32 g_http_inet_idx_default = -1;
#ifdef LOCAL_PROTOCOL_SECURE
BOOL g_is_factory_mode = 0;
#endif
LOCAL void uhttpd_create_crt_key();
LOCAL void init_group_srv(void)
{
S32 index = 0;
for (index = 0; index < GROUP_MAX; index++) { g_http_group_srv[index].match_port = NULL; g_http_group_srv[index].match_auth = NULL; g_http_group_srv[index].data_srv = NULL; g_http_group_srv[index].make_rsp = NULL;
#if defined(INCLUDE_UPNP_SERVER)
g_http_group_srv[index].make_rsp_extend = NULL;
#endif
}
}
S32 http_group_srv_add(S32 group, void *match_port, void *match_auth, void *data_srv, void *make_rsp)
{
g_http_group_srv[group].match_port = match_port;
g_http_group_srv[group].match_auth = match_auth;
g_http_group_srv[group].data_srv = data_srv;
g_http_group_srv[group].make_rsp = make_rsp;
return OK;
}
#if defined(INCLUDE_UPNP_SERVER)
S32 http_group_srv_add_rsp_extend(S32 group, void *make_rsp_extend)
{
g_http_group_srv[group].make_rsp_extend = make_rsp_extend;
return OK;
}
#endif
HTTP_GROUP_SRV *http_get_group_srv_addr(S32 group)
{
if (group < GROUP_HTTPD || group >= GROUP_MAX)
{
return NULL;
}
return &g_http_group_srv[group];
}
#ifdef LOCAL_PROTOCOL_SECURE
BOOL is_factory_test_mode()
{
FACTORY_TEST_MODE factory_test_mode = {0};
if(0 == ds_read(FACTORY_TEST_MODE_PATH, &factory_test_mode, sizeof(FACTORY_TEST_MODE)))
{
return FALSE;
}
return factory_test_mode.enabled;
}
BOOL get_factory_mode_from_httpd()
{
return g_is_factory_mode;
}
#endif
U16 get_group_default_port(void)
{
return g_uhttp_main.listen_http;
}
LOCAL S32 https_match_port(U16 port)
{
return (port == g_uhttp_main.listen_https);
}
LOCAL S32 http_match_port(U16 port)
{
return (port == g_uhttp_main.listen_http);
}
LOCAL void match_group_port(CONTEXT *context, U16 port)
{
S32 i;
for (i = 0; i < GROUP_MAX; ++i) { /* 验证用户端口 */ if (NULL != g_http_group_srv[i].match_port && TRUE == g_http_group_srv[i].match_port(port)) { context->group_srv = &g_http_group_srv[i]; context->port = port; return; } }
}
BOOL check_group(CONTEXT *context, HTTP_GROUP_TYPE group)
{
return (group < GROUP_MAX && context && context->group_srv == &g_http_group_srv[group]);
}
/* 根据 port 判断服务 */
void match_group(CONTEXT *context, S32 sock)
{
U16 port = sock_port_get(sock);
/* 根据端口判断组 */ match_group_port(context, port); /* 没有匹配到端口默认使用 HTTPD */ if (NULL == context->group_srv) { if (port == HTTP_PORT && g_uhttp_main.listen_http != HTTP_PORT) { /* 当web端口不为80时,80端口支持onvif请求接入,但不处理web请求 * 此时应无法匹配到group_srv */ context->group_srv = &g_http_group_srv[GROUP_ONVIF]; context->port = HTTP_PORT; }
#ifdef INCLUDE_UPNP_SERVER
else if (port == SOAP_PORT)
{
context->group_srv = &g_http_group_srv[GROUP_UPNP];
context->port = SOAP_PORT;
}
#endif
else
{
context->group_srv = &g_http_group_srv[GROUP_HTTPD];
context->port = g_uhttp_main.listen_http;
}
}
return;
}
LOCAL void context_free(CONTEXT *context)
{
if (NULL == context || TRUE == context->keep_forever)
{
return;
}
if (context->is_https == TRUE) { if (context->ssl_ctx != NULL) { if (tpssl_svr_uninit(context->ssl_ctx) != 0) { HTTPD_ERROR("ssl server uninit fail"); } /* ssl已设置sock,tpssl_svr_uninit()则已关闭sock,将sock置-1,避免重复关闭 */ if (context->is_ssl_setfd) { context->sock = -1; } } } if (context->sock > 0) { shutdown(context->sock, SHUT_RDWR); close(context->sock); context->sock = -1; } context->idle = TRUE; context->parser = NULL;
}
LOCAL CONTEXT context_alloc() / 分配可用context,没有的话用LRU算法淘汰一条 */
{
S32 index = 0;
S32 lru = (g_last_context + 1) % HTTP_MAX_CONTEXT;
S32 timeout = HTTP_CONTEXT_TIMEOUT;
/* 找到第一个可用的context. */ for (index = 0; index < HTTP_MAX_CONTEXT; index++) { g_last_context = (g_last_context + 1) % HTTP_MAX_CONTEXT; if (TRUE == g_context_array[g_last_context].keep_forever) { continue; } if (TRUE == g_context_array[g_last_context].idle) { return &g_context_array[g_last_context]; } if (g_context_array[g_last_context].timeout < timeout) { timeout = g_context_array[g_last_context].timeout; lru = g_last_context; } } /* 全部被占用,强制老化最近最少被使用的条目。 */ context_free(&g_context_array[lru]); g_last_context = lru; return &g_context_array[lru];
}
LOCAL S32 context_flush(S32 max_sock, fd_set *rdset, fd_set wrset) / 更新select的读写集合和maxfd? */
{
S32 index = 0;
NSD_ASSERT(NULL != rdset); for (index = 0; index < HTTP_MAX_CONTEXT; index++) { if (TRUE == g_context_array[index].idle) { continue; } if ((g_context_array[index].sock <= 0) || (NULL == g_context_array[index].parser)) { context_free(&g_context_array[index]); continue; } max_sock = sock_fd_add(g_context_array[index].sock, max_sock, rdset); } return max_sock;
}
LOCAL S32 http_call_handle(fd_set *rdset)
{
S32 index = 0;
S32 http_status = OK;
NSD_ASSERT(NULL != rdset); for (index = 0; index < HTTP_MAX_CONTEXT; index++) { if (TRUE == g_context_array[index].idle) { continue; } if ((g_context_array[index].sock <= 0) || (NULL == g_context_array[index].parser)) { context_free(&g_context_array[index]); continue; } if (FALSE != FD_ISSET(g_context_array[index].sock, rdset)) { if (g_context_array[index].is_https == 1 && g_context_array[index].is_ssl_success == 0) { int ret = 0; HTTPD_DEBUG("ssl handshake fail, ssl handshake num %d, continue.", g_context_array[index].ssl_handshake_num); ret = tpssl_svr_handshake(g_context_array[index].ssl_ctx); g_context_array[index].ssl_handshake_num++; if (0 == ret) { g_context_array[index].is_ssl_success = 1; } else if (ret != TPSSL_ERROR_WANT_READ && ret != TPSSL_ERROR_WANT_WRITE) { HTTPD_ERROR("tpssl_svr_handshake err ret: -0x%x, free context.", -ret); context_free(&g_context_array[index]); } continue; } http_status = g_context_array[index].parser(&g_context_array[index]); g_context_array[index].timeout = HTTP_CONTEXT_TIMEOUT; if (RESERVE == http_status) /* reserve就保留 */ { HTTPD_ERROR("context parser reserve."); g_context_array[index].timeout = HTTP_CONTEXT_TIMEOUT + HTTP_RECV_CONTENT_TIMEOUT; continue; } if ((FALSE == g_context_array[index].keep_forever) && ((ERROR == http_status) || ((FALSE == g_context_array[index].keepalive) && (g_context_array[index].async_buffer_len < 1)))) { context_free(&g_context_array[index]); } } } return OK;
}
LOCAL void context_check_timer(void)
{
S32 index = 0;
for (index = 0; index < HTTP_MAX_CONTEXT; index++) { if (TRUE == g_context_array[index].idle) { continue; } if ((g_context_array[index].sock <= 0) || (NULL == g_context_array[index].parser)) { context_free(&g_context_array[index]); continue; } if (g_context_array[index].timeout <= 0) { context_free(&g_context_array[index]); } /* 对于即未老化,又还没有关闭的连接,检查该context是否还需要发送数据, 通常是资源文件过大,链路拥堵时,不能够立刻完成发送,则在这里继续发送。 考虑到现实情况,目前只处理静态页面发送不处理异步接收的情形。luhan add 2015.12.22. */ else if (g_context_array[index].async_buffer_len > 0) { if (ERROR == http_send_async_buffer(&g_context_array[index])) { context_free(&g_context_array[index]); } if ((FALSE == g_context_array[index].keepalive) && (g_context_array[index].async_buffer_len < 1)) { context_free(&g_context_array[index]); /* 已完成发送则关闭该连接。*/ } } g_context_array[index].timeout--; }
}
LOCAL void http_check_timer(void)
{
context_check_timer();
session_check_timer();
unlock_check_timer();
}
LOCAL CONTEXT * socket_handle(int sock)
{
CONTEXT *context = NULL;
struct linger lgr = {0};
struct sockaddr_in client = {0};
S32 length = sizeof(struct sockaddr);
S32 sock_opt = 1;
S32 buf_size = 0;
/* 传入的监听套接字非法。 */ if (-1 == sock) { return NULL; } /* 申请缓存,用于接受http请求。 */ /* 申请新的链接。 */ context = context_alloc(); NSD_ASSERT(NULL != context); context->sock = accept(sock, (struct sockaddr*)&client, (socklen_t *)&length); if (-1 == context->sock) { goto http_handle_error; } /* 设置为非阻塞模式。 */ if (ERROR == sock_non_block(context->sock)) { HTTPD_ERROR("Http socket set non block error."); goto http_handle_error; } sock_opt = 1; if (ERROR == setsockopt(context->sock, IPPROTO_TCP, TCP_NODELAY, &sock_opt, sizeof(sock_opt))) { goto http_handle_error; } lgr.l_onoff = 1; lgr.l_linger = 5; if (ERROR == setsockopt(context->sock, SOL_SOCKET, SO_LINGER, (const char*)&lgr, sizeof(lgr))) { goto http_handle_error; } /* 设置缓存大小 */ buf_size = HTTPD_CON_SOCKET_RECV_BUF_SIZE; if (ERROR == setsockopt(context->sock, SOL_SOCKET, SO_RCVBUF, &buf_size, sizeof(buf_size))) { HTTPD_ERROR("Set sock rcv buf error."); } buf_size = HTTPD_CON_SOCKET_SEND_BUF_SIZE; if (ERROR == setsockopt(context->sock, SOL_SOCKET, SO_SNDBUF, &buf_size, sizeof(buf_size))) { HTTPD_ERROR("Set sock rcv buf error."); } context->parser = http_parser; memcpy(&context->client, &client, sizeof(struct sockaddr_in)); context->head_buf = NULL; context->head_end = NULL; context->head_buf_end = NULL; context->hbuf_data_end = NULL; context->content_buf = NULL; context->content_start = NULL; context->content_end = NULL; context->content_buf_end = NULL; context->idle = FALSE; context->code = HTTP_REQ_OK; /* 默认为请求都是OK的。*/ context->async_buffer_len = 0; context->recv_count = 0; context->remove_first_boundary = FALSE; context->timeout = HTTP_CONTEXT_TIMEOUT; context->group_srv = NULL; context->onvif_soap = NULL; context->keep_forever = FALSE; context->is_ssl_setfd = 0; context->is_ssl_success = 0; context->ssl_handshake_num = 0; context->is_http_header_parser_done = 0; context->is_reserve = 0;
#ifdef MAKEROOM_BEFORE_UPGRADE
context->is_upgrade = 0;
#endif
return context;
http_handle_error:
context_free(context);
return NULL;
}
LOCAL STATUS http_handle(int sock)
{
CONTEXT *context = NULL;
if ((context = socket_handle(sock)) == NULL)
return ERROR;
context->is_https = FALSE; match_group(context, sock); return OK;
}
LOCAL STATUS https_handle(int sock)
{
int ret = 0;
CONTEXT *context = NULL;
CRT_KEY crt_key_params;
if ((context = socket_handle(sock)) == NULL)
return ERROR;
context->is_https = TRUE; memset(&crt_key_params, 0, sizeof(CRT_KEY)); ds_read(UHTTPD_CRT_KEY_PATH, &crt_key_params, sizeof(CRT_KEY)); if (strlen(crt_key_params.cert_pem) == 0) { ret = tpssl_MakeCaCertPem(crt_key_params.cert_pem, crt_key_params.key_pem, RSA_CRT_PEM_LEN, RSA_KEY_PRIVATE_PEM_LEN); if (ret != 0) { HTTPD_ERROR("tpssl_MakeCaCertPem fail"); return -1; } ds_advanced_write(UHTTPD_CRT_KEY_PATH, &crt_key_params, sizeof(CRT_KEY), DS_FLAG_SAVE_FLASH); } context->ssl_ctx = tpssl_svr_init(crt_key_params.cert_pem, crt_key_params.key_pem, 0, 1); tpssl_svr_set_bio(context->ssl_ctx, context->sock); /* tpssl_svr_set_bio() 会将sockfd设置给ssl */ context->is_ssl_setfd = 1; ret = tpssl_svr_handshake(context->ssl_ctx); if (0 == ret) { context->is_ssl_success = 1; } else { HTTPD_DEBUG("ret = -0x%x\n", -ret); } match_group(context, sock); return OK;
}
#ifdef OPENAPI_SUPPORT
LOCAL STATUS openapi_handle(int sock)
{
int ret = 0;
OPENAPI_PSK g_client_psk = {{0}};
CONTEXT *context = NULL; if ((context = socket_handle(sock)) == NULL) return ERROR; context->is_https = TRUE; memset(&g_client_psk, 0, sizeof(g_client_psk)); ds_read(OPENAPI_PSK_PATH, &g_client_psk, sizeof(OPENAPI_PSK)); context->ssl_ctx = tpssl_svr_init_openapi(g_client_psk); tpssl_svr_set_bio(context->ssl_ctx, context->sock); /* tpssl_svr_set_bio() 会将sockfd设置给ssl */ context->is_ssl_setfd = 1; ret = tpssl_svr_handshake(context->ssl_ctx); if (0 == ret) { context->is_ssl_success = 1; } else { HTTPD_DEBUG("ret = -0x%x\n", -ret); } match_group(context, sock); return OK;
}
#endif
LOCAL S32 http_create_sock(U16 listen_port)
{
S32 sock = -1;
S32 buf_size = 0;
S32 on = 1;
struct sockaddr_in addr;
if (-1 == (sock = socket(AF_INET, SOCK_STREAM, 0))) { HTTPD_ERROR("Create http socket error."); return -1; } setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); memset(&addr, 0, sizeof(struct sockaddr_in)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htons(INADDR_ANY); addr.sin_port = htons(listen_port); if (bind(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in))) { HTTPD_ERROR("socket bind failed."); close(sock); return -1; } /* 设置为监听模式。 */ if (listen(sock, HTTP_MAX_ACCEPT) == ERROR) { HTTPD_ERROR("Http socket listen error."); close(sock); return -1; } /* 设置为非阻塞模式。 */ if (ERROR == sock_non_block(sock)) { HTTPD_ERROR("Http socket set non block error."); close(sock); return -1; } /* 设置缓存大小 */ buf_size = HTTPD_SRV_SOCKET_RECV_BUF_SIZE; if (ERROR == setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &buf_size, sizeof(buf_size))) { HTTPD_ERROR("Set sock rcv buf error."); } buf_size = HTTPD_SRV_SOCKET_SEND_BUF_SIZE; if (ERROR == setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &buf_size, sizeof(buf_size))) { HTTPD_ERROR("Set sock rcv buf error."); } return sock;
}
S32 http_group_listen_port(S32 group, U16 listen_port, S32 *out_sock)
{
S32 sock = -1;
S32 index = -1;
sock = http_create_sock(listen_port); if (sock == -1) { goto out; } if (group == GROUP_HTTPD) { inet_add_timer((void*)http_check_timer, 0, 1, EXECUTE_FOREVER); index = inet_add_socket(sock, (void*)http_handle, (void*)context_flush, (void*)http_call_handle); } else if (group == GROUP_HTTPSD) { inet_add_timer((void*)http_check_timer, 0, 1, EXECUTE_FOREVER); index = inet_add_socket(sock, (void*)https_handle, (void*)context_flush, (void*)http_call_handle); }
#ifdef OPENAPI_SUPPORT
else if (group == GROUP_OPENAPI)
{
inet_add_timer((void*)http_check_timer, 0, 1, EXECUTE_FOREVER);
index = inet_add_socket(sock, (void*)openapi_handle, (void*)context_flush, (void*)http_call_handle); HTTPD_DEBUG("listening openapi sock=%d\n",sock); }
#endif
else { /* Admin用户组常驻inetd,它已把所有contextArray刷新Flush到inetd的rd_set中了。 故不用再注册Flush函数和会话处理httpCallHandle函数。*/ index = inet_add_socket(sock, (void*)http_handle, NULL, NULL); } if (index < 0) { HTTPD_ERROR("Http(group-%d) socket add to listen array error.", group); close(sock); sock = -1; index = -1; }
out:
if (out_sock != NULL)
{
*out_sock = sock;
}
return index;
}
LOCAL S32 uhttpd_init()
{
S32 index = 0;
memset(g_context_array, 0, sizeof(g_context_array)); for (index = 0; index < HTTP_MAX_CONTEXT; index++) { g_context_array[index].idle = TRUE; g_context_array[index].sock = -1; g_context_array[index].parser = NULL; } init_group_srv(); http_auth_init(); http_parser_init(); special_request_init(); return OK;
}
LOCAL STATUS uhttpd_get_enabled()
{
UHTTPD_MAIN uhttpd_main = {0};
if (0 == ds_read(UHTTPD_MAINSEC_PATH, &uhttpd_main, sizeof(UHTTPD_MAIN))) { return OK; } if (uhttpd_main.enabled) { return OK; } return ERROR;
}
LOCAL void uhttpd_create_crt_key()
{
CRT_KEY crt_key_params;
int ret = 0;
memset(&crt_key_params, 0, sizeof(CRT_KEY));
if (0 == ds_read(UHTTPD_CRT_KEY_PATH, &crt_key_params, sizeof(CRT_KEY))) { HTTPD_ERROR("read %s error", UHTTPD_CRT_KEY_PATH); return; } if (strlen(crt_key_params.cert_pem) != 0) { return; /* 已经生成过crt和key */ } ret = tpssl_MakeCaCertPem(crt_key_params.cert_pem, crt_key_params.key_pem, RSA_CRT_PEM_LEN, RSA_KEY_PRIVATE_PEM_LEN); if (ret != 0) { HTTPD_ERROR("tpssl_MakeCaCertPem fail"); return; } ds_advanced_write(UHTTPD_CRT_KEY_PATH, &crt_key_params, sizeof(CRT_KEY), DS_FLAG_SAVE_FLASH);
}
LOCAL S32 uhttpd_start()
{
memset(&g_uhttp_main, 0, sizeof(UHTTPD_MAIN));
if (OK != ds_convert_init()) { HTTPD_ERROR("Init convert failed."); return ERROR; } if (ds_read(UHTTPD_MAINSEC_PATH, (void*)(&g_uhttp_main), sizeof(UHTTPD_MAIN)) == 0) { HTTPD_ERROR("Http read config error."); return ERROR; } if (uhttpd_get_enabled() != OK) { HTTPD_ERROR("uhttpd disable"); return OK; } if (g_uhttp_main.https_enabled) { /* 增加对应用户组的参数和相关处理函数 */ http_group_srv_add(GROUP_HTTPSD, https_match_port, http_match_user_auth, http_proc_data_srv, http_admin_make_rsp); if (0 > (g_https_inet_idx = http_group_listen_port(GROUP_HTTPSD, g_uhttp_main.listen_https, &g_https_sock))) { HTTPD_ERROR("Https server start failed!"); return ERROR; } } if (g_uhttp_main.http_enabled) { /* 增加对应用户组的参数和相关处理函数 */ http_group_srv_add(GROUP_HTTPD, http_match_port, http_match_user_auth, http_proc_data_srv, http_admin_make_rsp); if (0 > (g_http_inet_idx = http_group_listen_port(GROUP_HTTPD, g_uhttp_main.listen_http, &g_http_sock))) { HTTPD_ERROR("Http server start failed!"); return ERROR; } } /* 用于支持ONVIF协议80端口接入 */ if (g_uhttp_main.listen_http != HTTP_PORT) { if (0 > (g_http_inet_idx_default = http_group_listen_port(GROUP_ONVIF, HTTP_PORT, &g_http_sock_default))) { HTTPD_ERROR("Http server start failed!"); return ERROR; } }
#ifdef LOCAL_PROTOCOL_SECURE
g_is_factory_mode = is_factory_test_mode();
#endif
uhttpd_create_crt_key(); HTTPD_DEBUG("Http server start!"); return OK;
}
LOCAL BOOL uhttpd_stop()
{
UHTTPD_MAIN uhttp_main;
if (uhttpd_get_enabled() != OK) { HTTPD_ERROR("uhttpd disable"); return SLP_ENONE; } memset(&uhttp_main, 0, sizeof(uhttp_main)); ds_read(UHTTPD_MAINSEC_PATH, &uhttp_main, sizeof(UHTTPD_MAIN)); if ((uhttp_main.listen_http == g_uhttp_main.listen_http) && (uhttp_main.listen_https == g_uhttp_main.listen_https)) { return FALSE; } if (g_uhttp_main.https_enabled) { inet_del_socket(g_https_inet_idx); close(g_https_sock); } if (g_uhttp_main.http_enabled) { inet_del_socket(g_http_inet_idx); close(g_http_sock); } g_https_inet_idx = -1; g_https_sock = -1; g_http_inet_idx = -1; g_http_sock = -1; if (g_http_inet_idx_default > 0) { inet_del_socket(g_http_inet_idx_default); g_http_inet_idx_default = -1; } if (g_http_sock_default > 0) { close(g_http_sock_default); g_http_sock_default = -1; } return TRUE;
}
LOCAL S32 uhttpd_reload(DS_MSG *msg)
{
SYSTEM_ONBOARDING_STATUS onboarding_status = {0};
if (ds_read(SYSTEM_ONBOARDING_STATUS_PATH, (U8 *)&onboarding_status, sizeof(SYSTEM_ONBOARDING_STATUS)) == 0)
{
printf(“tdpd read onboarding status fail.”);
return SLP_EINVARG;
}
if (uhttpd_get_enabled() != OK) { HTTPD_ERROR("uhttpd disable"); return SLP_ENONE; } if (TRUE == ds_path_id_exist(msg->id, msg->num, UHTTPD_MAINSEC_PATH)) { if (uhttpd_stop()) { uhttpd_start(); } } if (TRUE == ds_path_id_exist(msg->id, msg->num, ROOT_PATH)) { if (onboarding_status.finished) { clean_session(); } }
#ifdef LOCAL_PROTOCOL_SECURE
if(TRUE == ds_path_id_exist(msg->id, msg->num, FACTORY_TEST_MODE_PATH))
{
g_is_factory_mode = is_factory_test_mode();
}
#endif
if (TRUE == ds_path_id_exist(msg->id, msg->num, UPGRADE_STATUS_PATH)) { UPGRADE_STATUS upgrade_status; memset(&upgrade_status, 0, sizeof(upgrade_status)); ds_read(UPGRADE_STATUS_PATH, &upgrade_status, sizeof(upgrade_status)); if (upgrade_status.status == 1) { //状态 1 正在写flash 不允许http操作 if (g_https_inet_idx > 0) { inet_del_socket(g_https_inet_idx); g_https_inet_idx = -1; } if (g_https_sock > 0) { close(g_https_sock); g_https_sock = -1; } if (g_http_inet_idx > 0) { inet_del_socket(g_http_inet_idx); g_http_inet_idx = -1; } if (g_http_sock > 0) { close(g_http_sock); g_http_sock = -1; } if (g_http_inet_idx_default > 0) { inet_del_socket(g_http_inet_idx_default); g_http_inet_idx_default = -1; } if (g_http_sock_default > 0) { close(g_http_sock_default); g_http_sock_default = -1; } /* 如果ds模块正在启动,则终止启动timer */ ds_stop_start_timer(); //发送消息给云客户端 断开连接 CLOUD_CLIENT_IN_MSG cloud_client_out_msg; memset(&cloud_client_out_msg, 0, sizeof(cloud_client_out_msg)); cloud_client_out_msg.type = CC_IN_TYPE_FORBID_CONN; NSD_SEND(CLOUD_CLIENT_IN_MSG_ID, (U8 *)&cloud_client_out_msg, sizeof(cloud_client_out_msg)); HTTPD_DEBUG("cloud_client_out_msg.type:%d", cloud_client_out_msg.type); } } return SLP_ENONE;
}
LOCAL S32 httpd_stop()
{
#if defined(TP_TAPO_RESET_WIFI_SUPPORT) && defined(LOCAL_PROTOCOL_SECURE)
msg_detach_handler(WLAN_RESET_WIFI_CONFIG_ID, wifi_reset_check_handle);
#endif
return OK;
}
LOCAL void httpd_main()
{
#ifdef HOMEKIT_ONBOARDING_SUPPORT
DS_OPT_DESC hk_obd_setup_info_options[] =
{
DS_STR_OPT(HK_OBD_SETUP_INFO, setup_code, OPT_FLAG_NORM),
DS_STR_OPT(HK_OBD_SETUP_INFO, setup_payload, OPT_FLAG_NORM),
};
DS_SEG_DESC hk_obd_setup_info_segments[] =
{
DS_STRUCT_SEG(“hk_obd_setup_info”, SEG_LIM_RW, SEG_GROUP_ROOT, HK_OBD_SETUP_INFO, hk_obd_setup_info_options),
};
DS_SECT_DESC hk_obd_setup_info_sections[] =
{
DS_STRUCT_SECT(“hk_obd_setup_info”, hk_obd_setup_info_segments),
};
DS_TBL_DESC uhttpd_table[] =
{
DS_STRUCT_TBL(“uhttpd”, TBL_ATTR_CFG, hk_obd_setup_info_sections),
};
DS_DAT_MON_DESC uhttpd_data_monitor[] = { DS_DAT_MON(UHTTPD_MAINSEC_PATH, DATA_ATTRI_NOTIFY), DS_DAT_MON(ROOT_PATH,DATA_ATTRI_NOTIFY), DS_DAT_MON(UPGRADE_STATUS_PATH,DATA_ATTRI_NOTIFY),
#ifdef LOCAL_PROTOCOL_SECURE
DS_DAT_MON(FACTORY_TEST_MODE_PATH,DATA_ATTRI_NOTIFY),
#endif
};
DS_MOD_DESC uhttpd_module = DS_STRUCT_MOD(UHTTPD_MODULE_NAME, uhttpd_init, NULL, uhttpd_reload, uhttpd_start, httpd_stop, uhttpd_table, uhttpd_data_monitor);
#else
DS_DAT_MON_DESC uhttpd_data_monitor[] =
{
DS_DAT_MON(UHTTPD_MAINSEC_PATH, DATA_ATTRI_NOTIFY),
DS_DAT_MON(ROOT_PATH,DATA_ATTRI_NOTIFY),
DS_DAT_MON(UPGRADE_STATUS_PATH,DATA_ATTRI_NOTIFY),
#ifdef LOCAL_PROTOCOL_SECURE
DS_DAT_MON(FACTORY_TEST_MODE_PATH,DATA_ATTRI_NOTIFY),
#endif
};
DS_MOD_DESC uhttpd_module = DS_STRUCT_MOD(UHTTPD_MODULE_NAME, uhttpd_init, NULL, uhttpd_reload, uhttpd_start, httpd_stop, NULL, uhttpd_data_monitor);
#endif
MODULE *module_node = ds_register_module(UHTTPD_MODULE_NAME, &uhttpd_module); NSD_ASSERT(NULL != module_node);
}
NSD_INIT(httpd_main);