仿照这个#ifdef CFG_DEVMGR_MASTER
#include <uci.h>
#include <uci_blobmsg.h>
#include "api_config.h"
#include "devmgr_dev_api.h"
#include "devmgr_config.h"
#include "devmgr_global.h"
#include "devmgr_dev_ctrl.h"
#include "tapo_error.h"
#define P2PD_PORT 929
static int tcp_connect_local_server(int port)
{
struct sockaddr_in serv_addr;
int fd = -1;
fd = socket(AF_INET, SOCK_STREAM, 0);
if(-1 == fd)
{
goto end;
}
bzero(&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(port);
inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr);
if (connect(fd, (const struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
goto error_end;
}
goto end;
error_end:
close(fd);
fd = -1;
end:
return fd;
}
static int send_and_recv_p2pd_msg(char *msg, int len, char *out, int outlen)
{
int fd = -1;
struct timeval send_timeout = {1, 0};
struct timeval recv_timeout = {3, 0};
int rlen = 0;
fd = tcp_connect_local_server(P2PD_PORT);
if (fd < 0)
{
DBG_ERR("connect p2pd error");
return -1;
}
setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (void *)&send_timeout, sizeof(struct timeval));
setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (void *)&recv_timeout, sizeof(struct timeval));
write(fd, msg, strlen(msg));
memset(out, 0, outlen);
rlen = read(fd, out, outlen - 1);
close(fd);
return (rlen > 0) ? 0 : -1;
}
static int api_p2p_request_p2p(
struct ubus_app *uapp, struct blob_buf* bBuf, struct blob_attr *msg)
{
DM_PRINT("in api_p2p_request_p2p\n");
int err = SLP_ENONE;
struct blob_buf b = {0};
struct ubus_app_ext *uapp_ext = container_of(uapp, struct ubus_app_ext, uapp);
struct dev_node *dev = (struct dev_node *)uapp_ext->arg;
char *msg_ptr = NULL;
char out[256] = {0};
void *table = NULL;
if (!dev || !msg) {
return -1;
}
blobmsg_add_string(bBuf, "method", "request_p2p");
table = blobmsg_open_table(bBuf, "result");
struct blobmsg (
blobmsg_string pub_ip,
blobmsg_int32 pub_port,
blobmsg_string stun_url,
blobmsg_string pri_ip,
blobmsg_int32 nat_type,
blobmsg_int32 pri_port,
)(req, msg, false);
if (!req.pub_ip || !req.pub_port || !req.stun_url ||
!req.pri_ip || !req.nat_type || !req.pri_port) {
DBG_ERR( "request_p2p format blobmsg err\n");
err = IPC_INTF_PARA_ERR;
goto error_leave;
}
blobmsg_buf_init(&b);
blobmsg_add_string(&b, "request", "prepare_p2p");
void *tb1 = NULL;
void *tb2 = NULL;
tb1 = blobmsg_open_table(&b, "params");
if(tb1) {
blobmsg_add_string(&b, "deviceId", dev->devid);
blobmsg_add_string(&b, "stun_url", blobmsg_get_string(req.stun_url));
blobmsg_add_u32(&b, "nat_type", blobmsg_get_u32(req.nat_type));
tb2 = blobmsg_open_table(&b, "peer_addr");
if(tb2) {
blobmsg_add_string(&b, "pub_ip", blobmsg_get_string(req.pub_ip));
blobmsg_add_u32(&b, "pub_port", blobmsg_get_u32(req.pub_port));
blobmsg_add_string(&b, "pri_ip", blobmsg_get_string(req.pri_ip));
blobmsg_add_u32(&b, "pri_port", blobmsg_get_u32(req.pri_port));
blobmsg_close_table(&b, tb2);
}
blobmsg_close_table(&b, tb1);
}
msg_ptr = blobmsg_format_json(b.head, TRUE);
send_and_recv_p2pd_msg(msg_ptr, strlen(msg_ptr), out, sizeof(out));
blob_buf_init(&b, 0);
if (!blobmsg_add_json_from_string(&b, out)){
err = SLP_ESYSTEM;
DBG_ERR("blobmsg_add_json_from_string fail\n");
goto fail;
}
struct blobmsg (
blobmsg_int32 error_code,
blobmsg_table result,
)(resp,b.head,false);
if (!resp.error_code){
err = SLP_ESYSTEM;
DBG_ERR("data.error_code is null\n");
goto fail;
} else {
err = blobmsg_get_u32(resp.error_code);
}
if(resp.result) {
struct blobmsg (
blobmsg_int32 is_ready,
blobmsg_string sid,
blobmsg_table dev_addr,
blobmsg_int32 nat_type,
)(re,resp.result,false);
if (re.is_ready){
blobmsg_add_u32(bBuf, "is_ready", blobmsg_get_u32(re.is_ready));
}else {
DBG_ERR("data.is_ready is null\n");
}
if (re.sid){
blobmsg_add_string(bBuf, "sid", blobmsg_get_string(re.sid));
}else {
DBG_ERR("data.sid is null\n");
}
if (re.dev_addr){
struct blobmsg (
blobmsg_string pub_ip,
blobmsg_int32 pub_port,
blobmsg_string pri_ip,
blobmsg_int32 pri_port,
)(rep,re.dev_addr,false);
if (rep.pub_ip){
blobmsg_add_string(bBuf, "pub_ip", blobmsg_get_string(rep.pub_ip));
}else {
DBG_ERR("rep.pub_ip is null\n");
}
if (rep.pub_port){
blobmsg_add_u32(bBuf, "pub_port", blobmsg_get_u32(rep.pub_port));
}else {
DBG_ERR("rep.pub_port is null\n");
}
if (rep.pri_ip){
blobmsg_add_string(bBuf, "pri_ip", blobmsg_get_string(rep.pri_ip));
}else {
DBG_ERR("rep.pri_ip is null\n");
}
if (rep.pri_port){
blobmsg_add_u32(bBuf, "pri_port", blobmsg_get_u32(rep.pri_port));
}else {
DBG_ERR("rep.pri_port is null\n");
}
}else {
DBG_ERR("data.dev_addr is null\n");
}
if (re.nat_type){
blobmsg_add_u32(bBuf, "nat_type", blobmsg_get_u32(re.nat_type));
}else {
DBG_ERR("data.nat_type is null\n");
}
}else {
err = SLP_ESYSTEM;
DBG_ERR("parse response result error\n");
goto fail;
}
fail:
free(msg_ptr);
error_leave:
blob_buf_free(&b);
if (table) {
blobmsg_close_table(bBuf, table);
}
blobmsg_add_u32(bBuf, "error_code", err);
return 0;
}
static int api_p2p_is_p2p_ready(
struct ubus_app *uapp, struct blob_buf* bBuf, struct blob_attr *msg)
{
DM_PRINT("in api_p2p_request_p2p\n");
int err = DEVICE_OK;
struct blob_buf b = {0};
struct ubus_app_ext *uapp_ext = container_of(uapp, struct ubus_app_ext, uapp);
struct dev_node *dev = (struct dev_node *)uapp_ext->arg;
char *msg_ptr = NULL;
char out[256] = {0};
void *table = NULL;
if (!dev || !msg) {
return -1;
}
blobmsg_add_string(bBuf, "method", "is_p2p_ready");
table = blobmsg_open_table(bBuf, "result");
struct blobmsg (
blobmsg_string sid,
)(req, msg, false);
if (!req.sid) {
DBG_ERR( "is_p2p_ready format blobmsg err\n");
err = DEVICE_PARAM_ERR;
goto error_leave;
}
blobmsg_buf_init(&b);
blobmsg_add_string(&b, "request", "is_p2p_ready");
void *tb1 = blobmsg_open_table(&b, "params");
if(tb1) {
blobmsg_add_string(&b, "sid", blobmsg_get_string(req.sid));
blobmsg_close_table(&b, tb1);
}
msg_ptr = blobmsg_format_json(b.head, TRUE);
send_and_recv_p2pd_msg(msg_ptr, strlen(msg_ptr), out, sizeof(out));
blobmsg_buf_init(&b);
if (!blobmsg_add_json_from_string(&b, out)){
err = DEVICE_PARAM_ERR;
DBG_ERR("blobmsg_add_json_from_string fail\n");
goto fail;
}
struct blobmsg (
blobmsg_int32 error_code,
blobmsg_string error_msg,
blobmsg_table result,
)(resp,b.head,false);
if (!resp.error_code){
err = P2P_P2PD_RESPONSE_ERROR;
DBG_ERR("data.error_code is null\n");
goto fail;
} else {
err = blobmsg_get_u32(resp.error_code);
}
if(resp.result) {
struct blobmsg (
blobmsg_int32 is_ready,
blobmsg_string sid,
blobmsg_table dev_addr,
blobmsg_int32 nat_type,
)(re,resp.result,false);
if (re.is_ready){
blobmsg_add_u32(bBuf, "is_ready", blobmsg_get_u32(re.is_ready));
}else {
DBG_ERR("data.is_ready is null\n");
}
if (re.sid){
blobmsg_add_string(bBuf, "sid", blobmsg_get_string(re.sid));
}else {
DBG_ERR("data.sid is null\n");
}
if (re.dev_addr){
struct blobmsg (
blobmsg_string pub_ip,
blobmsg_int32 pub_port,
blobmsg_string pri_ip,
blobmsg_int32 pri_port,
)(rep,re.dev_addr,false);
if (rep.pub_ip){
blobmsg_add_string(bBuf, "pub_ip", blobmsg_get_string(rep.pub_ip));
}else {
DBG_ERR("rep.pub_ip is null\n");
}
if (rep.pub_port){
blobmsg_add_u32(bBuf, "pub_port", blobmsg_get_u32(rep.pub_port));
}else {
DBG_ERR("rep.pub_port is null\n");
}
if (rep.pri_ip){
blobmsg_add_string(bBuf, "pri_ip", blobmsg_get_string(rep.pri_ip));
}else {
DBG_ERR("rep.pri_ip is null\n");
}
if (rep.pri_port){
blobmsg_add_u32(bBuf, "pri_port", blobmsg_get_u32(rep.pri_port));
}else {
DBG_ERR("rep.pri_port is null\n");
}
}else {
DBG_ERR("data.dev_addr is null\n");
}
if (re.nat_type){
blobmsg_add_u32(bBuf, "nat_type", blobmsg_get_u32(re.nat_type));
}else {
DBG_ERR("data.nat_type is null\n");
}
}else {
err = P2P_P2PD_RESPONSE_ERROR;
DBG_ERR("parse response result error\n");
goto fail;
}
fail:
free(msg_ptr);
error_leave:
blob_buf_free(&b);
if (table) {
blobmsg_close_table(bBuf, table);
}
blobmsg_add_u32(bBuf, "error_code", err);
return 0;
}
struct cmd_handler tapo_api_tapo_p2p[] = {
{
DEVCTL_CMD_S,
"request_p2p",
api_p2p_request_p2p
},
{
DEVCTL_CMD_G,
"is_p2p_ready",
api_p2p_is_p2p_ready
},
{DEVCTL_CMD_N, NULL, NULL}
};
DEVMGR_CMD_ADD(
tapo_api,
tapo_p2p, // name
"p2p", // domain
"", // config
tapo_api_tapo_p2p
);
#endif改写
/******************************************************************************
*
* Copyright (c) 2018 TP-LINK Technologies CO.,LTD.
* All rights reserved.
*
* FILE NAME : upnpc_web.c
* VERSION : 1.0
* DESCRIPTION : web界面操作upnp条目,刷新web upnp界面的显示状态
*
* AUTHOR : Deng Peng (dengpeng@tp-link.com.cn)
* CREATE DATE : 05/07/2019
*
* HISTORY :
* 01 05/07/2019 Deng Peng Create.
*
******************************************************************************/
#include <arpa/inet.h> /* for AF_INET */
#include <string.h> /* for memset() */
#include <sys/time.h>
#include <stdlib.h>
#include "nsd_common.h"
#include "slp_model.h"
#include "upnpc.h"
#include "port_mapping.h"
#include "dms_tool.h"
#ifdef UPNPC_ENABLE
#define DEFAULT_HTTP_PORT 80
#define DEFAULT_RTSP_PORT 554
#define DEFAULT_VHTTPD_PORT 8080
#define DEFAULT_ONVIF_PORT 2020
#define HTTPS_SERVER_PORT 8443
#ifdef WEBRTC_SUPPORT
#define PORT_MAX_LENGTH 6
const U16 webrtc_server_port[] = {64444, 64445, 64446, 64447, 64448};//最大拉流数为5,所以定义好5个内部端口
//最大拉流数为5,定义好5个和路由器交互的str
const char description_upnpc_webrtc_str[][DESCRIPTION_UPNPC_WEBRTC_STR_LENGTH] = {"webrtc_1", "webrtc_2", "webrtc_3", "webrtc_4" ,"webrtc_5"};
#define PORT_INTERVAL 100
#endif
#define CONFLICT_MAPPING_ENTRY_ERROR_CODE 718
#define NO_SUCH_ENTRY_ERROR_CODE 714
#define CHECK_PORT_MAPPING_STATUS_INTERVAL 60*3 /* 定时查询特定条目间隔时间 */
LOCAL S32 g_check_timer = -1;
BOOL g_upnpc_uhttpd_mapped = FALSE; /* 当前的uhttpd条目是否已生效 */
BOOL g_upnpc_rtsp_mapped = FALSE; /* 当前的rtsp条目是否已生效 */
BOOL g_upnpc_vhttpd_mapped = FALSE; /* 当前的vhttpd条目是否已生效 */
#ifdef WEBRTC_SUPPORT
BOOL g_upnpc_webrtc_mapped[CLIENTS_CONN_MAX];/* 当前的webrtc条目是否已生效 */
#endif
LOCAL U16 cur_added_uhttpd_ext_port = 0; /* 当前生效的uhttpd外部端口号 */
LOCAL U16 cur_added_rtsp_ext_port = 0; /* 当前生效的rtsp外部端口号 */
LOCAL U16 cur_added_vhttpd_ext_port = 0; /* 当前生效的vhttpd外部端口号*/
#ifdef WEBRTC_SUPPORT
LOCAL U16 cur_added_webrtc_ext_port[CLIENTS_CONN_MAX];/* 当前生效的webrtc外部端口号*/
#endif
LINK_STATUS s_link_status = {0};
LOCAL void upnpc_add_entry(U16 external_port, U16 internal_port,
const char * desc, upnp_action_done_cb upnp_action_done_handle
#ifdef WEBRTC_SUPPORT
, BOOL is_udp
#endif
);
LOCAL void upnpc_delete_entry(U16 external_port, const char * desc,
upnp_action_done_cb upnp_action_done_handle
#ifdef WEBRTC_SUPPORT
, BOOL is_udp
#endif
);
LOCAL S32 upnpc_add_entry_done_cb(UPNP_ENTYR_INFO *info);
LOCAL S32 upnpc_delete_entry_done_cb(UPNP_ENTYR_INFO *info);
LOCAL S32 upnpc_delete_conflict_entry_done_cb(UPNP_ENTYR_INFO *info);
LOCAL void upnpc_timer(S32 param);
LOCAL void upnpc_save_pub_ip(dms_handler_t *handler, U8 *mbuf, U32 mlen, U32 sender_dms_id)
{
if (!handler || !mbuf)
{
UPNPC_ERROR("upnpc_save_pub_ip input nullptr!");
return ;
}
UPNPC_PUB_IP *event = (UPNPC_PUB_IP*)mbuf;
save_pub_ip(event->pub_ip,strlen(event->pub_ip));
return;
}
#define MAX_PORT 30000
#define MIN_PORT 10000
/*生成范围在MIN_PORT - MAX_PORT之间的随机端口号并返回*/
LOCAL U16 generate_external_mapping_port()
{
srand((U16)time(NULL));
return (rand() % (MAX_PORT - MIN_PORT + 1) + MIN_PORT);
}
#ifdef WEBRTC_SUPPORT
#define WEBRTC_MAX_PORT 50000
#define WEBRTC_MIN_PORT 30000
LOCAL U16 webrtc_generate_external_mapping_port()
{
srand((U16)time(NULL));
return (rand() % (WEBRTC_MAX_PORT - WEBRTC_MIN_PORT + 1) + WEBRTC_MIN_PORT);
}
#endif
LOCAL S32 upnpc_add_entry_done_cb(UPNP_ENTYR_INFO *info)
{
const char *desc = NULL;
if (NULL == info)
{
UPNPC_ERROR("info is null");
return ERROR;
}
if (info->action != PORT_MAPPING_ACTION_ADD)
{
UPNPC_ERROR("invalid action[%d]", info->action);
return ERROR;
}
if (UPNPC_ENTRY_FLAG_UHTTPD != info->entry_flag
&& UPNPC_ENTRY_FLAG_RTSP != info->entry_flag
&& UPNPC_ENTRY_FLAG_VHTTPD != info->entry_flag
#ifdef WEBRTC_SUPPORT
&& UPNPC_ENTRY_FLAG_WEBRTC_1 != info->entry_flag
&& UPNPC_ENTRY_FLAG_WEBRTC_2 != info->entry_flag
&& UPNPC_ENTRY_FLAG_WEBRTC_3 != info->entry_flag
&& UPNPC_ENTRY_FLAG_WEBRTC_4 != info->entry_flag
&& UPNPC_ENTRY_FLAG_WEBRTC_5 != info->entry_flag
#endif
)
{
UPNPC_ERROR("invalid entry_flag[%d]", info->entry_flag);
return ERROR;
}
/* 如果添加失败 */
if (FALSE == info->action_successed)
{
/* 如果添加失败的原因是“条目冲突”,则尝试删除旧条目后再次添加 */
if (CONFLICT_MAPPING_ENTRY_ERROR_CODE == info->error_code)
{
if (UPNPC_ENTRY_FLAG_UHTTPD == info->entry_flag)
{
desc = DESCRIPTION_UPNPC_UHTTPD_STR;
}
else if (UPNPC_ENTRY_FLAG_RTSP == info->entry_flag)
{
desc = DESCRIPTION_UPNPC_RTSP_STR;
}
else if (UPNPC_ENTRY_FLAG_VHTTPD == info->entry_flag)
{
desc = DESCRIPTION_UPNPC_VHTTPD_STR;
}
#ifdef WEBRTC_SUPPORT
else
{
BOOL find_flag = FALSE;
for (int i = 0; i < CLIENTS_CONN_MAX; i++)
{
if ((UPNPC_ENTRY_FLAG_WEBRTC_1 + i) == info->entry_flag)
{
desc = description_upnpc_webrtc_str[i];
find_flag = TRUE;
break;
}
}
if (!find_flag)
{
UPNPC_INFO("ENTRY FLAG ERROR!");
return ERROR;
}
}
#else
else
{
UPNPC_INFO("ENTRY FLAG ERROR!");
return ERROR;
}
#endif
UPNPC_INFO("the to be added entry is confilict, delete it and try again.");
delete_port_mapping(info->external_port, info->protocol, desc, upnpc_delete_conflict_entry_done_cb);
return OK;
}
else
{
UPNPC_INFO("error_code:%d", info->error_code);
return OK;
}
}
if (UPNPC_ENTRY_FLAG_UHTTPD == info->entry_flag)
{
cur_added_uhttpd_ext_port = info->external_port;
g_upnpc_uhttpd_mapped = TRUE;
}
else if(UPNPC_ENTRY_FLAG_RTSP == info->entry_flag)
{
cur_added_rtsp_ext_port = info->external_port;
g_upnpc_rtsp_mapped = TRUE;
}
else if(UPNPC_ENTRY_FLAG_VHTTPD == info->entry_flag)
{
cur_added_vhttpd_ext_port = info->external_port;
g_upnpc_vhttpd_mapped = TRUE;
}
#ifdef WEBRTC_SUPPORT
else
{
BOOL find_flag = FALSE;
for (int i = 0; i < CLIENTS_CONN_MAX; i++)
{
if ((UPNPC_ENTRY_FLAG_WEBRTC_1 + i) == info->entry_flag)
{
cur_added_webrtc_ext_port[i] = info->external_port;
g_upnpc_webrtc_mapped[i] = TRUE;
UPNPC_RTC_PORT port = {{0}, {0}};
sprintf(port.rtc_port, "%d", cur_added_webrtc_ext_port[i]);
sprintf(port.inner_port, "%d", webrtc_server_port[i]);
msg_send(UPNPC_SAVE_RTC_PORT_MSG_MID, (U8 *)&port, sizeof(UPNPC_RTC_PORT));
find_flag = TRUE;
break;
}
}
if (!find_flag)
{
UPNPC_ERROR("info->entry_flag error = %d", info->entry_flag);
return ERROR;
}
}
#else
else
{
UPNPC_ERROR("info->entry_flag error = %d", info->entry_flag);
return ERROR;
}
#endif
add_web_entry_record(info->external_port, info->internal_port, info->protocol, info->description);
return OK;
}
LOCAL S32 upnpc_delete_entry_done_cb(UPNP_ENTYR_INFO *info)
{
if (NULL == info)
{
UPNPC_ERROR("info is null");
return ERROR;
}
if (info->action != PORT_MAPPING_ACTION_DELETE)
{
UPNPC_ERROR("invalid action[%d]", info->action);
return ERROR;
}
if (info->action_successed || NO_SUCH_ENTRY_ERROR_CODE == info->error_code)
{
if (UPNPC_ENTRY_FLAG_UHTTPD == info->entry_flag)
{
cur_added_uhttpd_ext_port = 0;
g_upnpc_uhttpd_mapped = FALSE;
}
else if (UPNPC_ENTRY_FLAG_RTSP == info->entry_flag)
{
cur_added_rtsp_ext_port = 0;
g_upnpc_rtsp_mapped = FALSE;
}
else if (UPNPC_ENTRY_FLAG_VHTTPD == info->entry_flag)
{
cur_added_vhttpd_ext_port = 0;
g_upnpc_vhttpd_mapped = FALSE;
}
#ifdef WEBRTC_SUPPORT
else
{
BOOL find_flag = FALSE;
for (int i = 0; i < CLIENTS_CONN_MAX; i++)
{
if ((UPNPC_ENTRY_FLAG_WEBRTC_1 + i) == info->entry_flag)
{
cur_added_webrtc_ext_port[i] = 0;
g_upnpc_webrtc_mapped[i] = FALSE;
UPNPC_RTC_PORT port = {{0}, {0}};
sprintf(port.rtc_port, "%d", cur_added_webrtc_ext_port[i]);
sprintf(port.inner_port, "%d", webrtc_server_port[i]);
msg_send(UPNPC_SAVE_RTC_PORT_MSG_MID, (U8 *)&port, sizeof(UPNPC_RTC_PORT));
find_flag = TRUE;
break;
}
}
if (!find_flag)
{
UPNPC_ERROR("invalid entry_flag!");
return ERROR;
}
}
#else
else
{
UPNPC_ERROR("invalid entry_flag!");
return ERROR;
}
#endif
}
return OK;
}
LOCAL S32 add_uhttpd_entry_from_config(PORT_MAPPING_PROTOCOL_TYPE protocol)
{
UPNPC_INFO upnpc_info;
UPNPC_UHTTPD upnpc_uhttpd;
UHTTPD_MAIN uhttpd;
U16 ext_port = 0;
memset(&upnpc_info, 0, sizeof(upnpc_info));
ds_read(UPNPC_INFO_PATH, &upnpc_info, sizeof(upnpc_info));
if (FALSE == upnpc_info.enabled)
{
return OK;
}
/* 从配置文件读取内部端口 */
memset(&uhttpd, 0, sizeof(uhttpd));
if ((0 == ds_read(UHTTPD_MAINSEC_PATH, &uhttpd, sizeof(uhttpd))) ||
(0 == uhttpd.listen_http))
{
uhttpd.listen_http = DEFAULT_HTTP_PORT;
}
memset(&upnpc_uhttpd, 0, sizeof(upnpc_uhttpd));
ds_read(UPNPC_UHTTPD_PATH, &upnpc_uhttpd, sizeof(upnpc_uhttpd));
if (0 == upnpc_uhttpd.ext_port)
{
upnpc_uhttpd.ext_port = DEFAULT_HTTP_PORT;
}
/* 手动模式外部端口号从配置读取,自动模式外部端口号与内部端口号相同 */
ext_port = (MODE_AUTO == upnpc_info.mode) ? uhttpd.listen_http : upnpc_uhttpd.ext_port;
/* 添加映射条目 */
add_port_mapping(ext_port, uhttpd.listen_http, protocol, DESCRIPTION_UPNPC_UHTTPD_STR, upnpc_add_entry_done_cb);
return OK;
}
LOCAL S32 add_rtsp_entry_from_config(PORT_MAPPING_PROTOCOL_TYPE protocol)
{
UPNPC_INFO upnpc_info;
UPNPC_RTSP upnpc_rtsp;
CET_RTSP rtsp;
U16 ext_port = 0;
memset(&upnpc_info, 0, sizeof(upnpc_info));
ds_read(UPNPC_INFO_PATH, &upnpc_info, sizeof(upnpc_info));
if (FALSE == upnpc_info.enabled)
{
return OK;
}
/* 从用户配置读取内部端口 */
memset(&rtsp, 0, sizeof(rtsp));
if ((0 == ds_read(CET_RTSP_PATH, &rtsp, sizeof(rtsp))) ||
(0 == rtsp.port))
{
rtsp.port = DEFAULT_RTSP_PORT;
}
memset(&upnpc_rtsp, 0, sizeof(upnpc_rtsp));
ds_read(UPNPC_RTSP_PATH, &upnpc_rtsp, sizeof(upnpc_rtsp));
if (0 == upnpc_rtsp.ext_port)
{
upnpc_rtsp.ext_port = DEFAULT_RTSP_PORT;
}
/* 手动模式外部端口号从配置读取,自动模式外部端口号与内部端口号相同 */
ext_port = (MODE_AUTO == upnpc_info.mode) ? rtsp.port : upnpc_rtsp.ext_port;
/* 添加映射条目 */
add_port_mapping(ext_port, rtsp.port, protocol, DESCRIPTION_UPNPC_RTSP_STR, upnpc_add_entry_done_cb);
return OK;
}
LOCAL S32 vhttpd_entry_from_config(PORT_MAPPING_PROTOCOL_TYPE protocol)
{
UPNPC_INFO upnpc_info;
UPNPC_VHTTPD vhttp;
U16 ext_port = 0;
memset(&upnpc_info, 0, sizeof(upnpc_info));
memset(&vhttp, 0, sizeof(vhttp));
ds_read(UPNPC_INFO_PATH, &upnpc_info, sizeof(upnpc_info));
if (FALSE == upnpc_info.enabled)
{
return OK;
}
ds_read(UPNPC_VHTTPD_PATH, &vhttp, sizeof(vhttp));
if (upnpc_info.mode == MODE_AUTO)
{
ext_port = generate_external_mapping_port();
}
else
{
ext_port = vhttp.ext_port;
}
add_port_mapping(ext_port, HTTPS_SERVER_PORT, protocol, DESCRIPTION_UPNPC_VHTTPD_STR, upnpc_add_entry_done_cb);
return OK;
}
#ifdef WEBRTC_SUPPORT
LOCAL S32 webrtc_entry_from_config(PORT_MAPPING_PROTOCOL_TYPE protocol, int index)
{
UPNPC_INFO upnpc_info;
U16 ext_port = 0;
memset(&upnpc_info, 0, sizeof(upnpc_info));
ds_read(UPNPC_INFO_PATH, &upnpc_info, sizeof(upnpc_info));
if (FALSE == upnpc_info.enabled)
{
return OK;
}
if (upnpc_info.mode == MODE_AUTO)
{
ext_port = webrtc_generate_external_mapping_port();
}
else
{
ext_port = webrtc_server_port[index];
}
add_port_mapping(ext_port, webrtc_server_port[index], protocol, description_upnpc_webrtc_str[index], upnpc_add_entry_done_cb);
return OK;
}
#endif
LOCAL S32 upnpc_delete_conflict_entry_done_cb(UPNP_ENTYR_INFO *info)
{
if (NULL == info)
{
UPNPC_ERROR("info is null");
return ERROR;
}
if (info->action != PORT_MAPPING_ACTION_DELETE)
{
UPNPC_ERROR("invalid action[%d]", info->action);
return ERROR;
}
/* 如果删除冲突条目成功,则重新添加条目 */
if ((info->action_successed) || (NO_SUCH_ENTRY_ERROR_CODE == info->error_code))
{
if (UPNPC_ENTRY_FLAG_UHTTPD == info->entry_flag)
{
cur_added_uhttpd_ext_port = 0;
g_upnpc_uhttpd_mapped = FALSE;
add_uhttpd_entry_from_config(info->protocol);
}
else if (UPNPC_ENTRY_FLAG_RTSP == info->entry_flag)
{
cur_added_rtsp_ext_port = 0;
g_upnpc_rtsp_mapped = FALSE;
add_rtsp_entry_from_config(info->protocol);
}
else if (UPNPC_ENTRY_FLAG_VHTTPD == info->entry_flag)
{
cur_added_vhttpd_ext_port = 0;
g_upnpc_vhttpd_mapped = FALSE;
vhttpd_entry_from_config(info->protocol);
}
#ifdef WEBRTC_SUPPORT
else
{
for (int i = 0; i < CLIENTS_CONN_MAX; i++)
{
if ((UPNPC_ENTRY_FLAG_WEBRTC_1 + i) == info->entry_flag)
{
cur_added_webrtc_ext_port[i] = 0;
g_upnpc_webrtc_mapped[i] = FALSE;
webrtc_entry_from_config(info->protocol, i);
break;
}
}
}
#endif
return OK;
}
/* 删除冲突条目失败,记录到log */
UPNPC_INFO("delete confilct entry failed. ext_port %hu", info->external_port);
return OK;
}
LOCAL void upnpc_add_entry(U16 external_port, U16 internal_port,
const char * desc, upnp_action_done_cb upnp_action_done_handle
#ifdef WEBRTC_SUPPORT
, BOOL is_udp
#endif
)
{
if (FALSE == is_linked_up() )
{
UPNPC_DEBUG("link down, link status = %d ",is_linked_up());
return;
}
UPNPC_DEBUG("begin to add mapping");
add_port_mapping(external_port, internal_port,
#ifdef WEBRTC_SUPPORT
is_udp ? PORT_MAPPING_PROTOCOL_UDP : PORT_MAPPING_PROTOCOL_TCP
#else
PORT_MAPPING_PROTOCOL_TCP
#endif
, desc, upnp_action_done_handle);
}
LOCAL void upnpc_delete_entry(U16 external_port, const char * desc,
upnp_action_done_cb upnp_action_done_handle
#ifdef WEBRTC_SUPPORT
, BOOL is_udp
#endif
)
{
if (FALSE == is_linked_up() || FALSE == is_igd_available())
{
return;
}
if (OK == delete_web_entry_record(external_port,
#ifdef WEBRTC_SUPPORT
is_udp ? PORT_MAPPING_PROTOCOL_UDP : PORT_MAPPING_PROTOCOL_TCP
#else
PORT_MAPPING_PROTOCOL_TCP
#endif
))
{
delete_port_mapping(external_port,
#ifdef WEBRTC_SUPPORT
is_udp ? PORT_MAPPING_PROTOCOL_UDP : PORT_MAPPING_PROTOCOL_TCP
#else
PORT_MAPPING_PROTOCOL_TCP
#endif
, desc, upnp_action_done_handle);
}
}
LOCAL void upnpc_check_entry_status(U16 external_port, U16 internal_port,
const char * desc, upnp_action_done_cb upnp_action_done_handle
#ifdef WEBRTC_SUPPORT
, BOOL is_udp
#endif
)
{
if (FALSE == is_linked_up() || FALSE == is_igd_available())
{
g_upnpc_rtsp_mapped = FALSE;
g_upnpc_uhttpd_mapped = FALSE;
g_upnpc_vhttpd_mapped = FALSE;
#ifdef WEBRTC_SUPPORT
for (int i = 0; i < CLIENTS_CONN_MAX; i++)
{
g_upnpc_webrtc_mapped[i] = FALSE;
}
#endif
delete_web_entry_record(external_port,
#ifdef WEBRTC_SUPPORT
is_udp ? PORT_MAPPING_PROTOCOL_UDP : PORT_MAPPING_PROTOCOL_TCP
#else
PORT_MAPPING_PROTOCOL_TCP
#endif
);
return;
}
get_specific_port_mapping(external_port, internal_port,
#ifdef WEBRTC_SUPPORT
is_udp ? PORT_MAPPING_PROTOCOL_UDP : PORT_MAPPING_PROTOCOL_TCP
#else
PORT_MAPPING_PROTOCOL_TCP
#endif
, desc, upnp_action_done_handle);
}
LOCAL S32 upnpc_get_entry_alive_done_cb(UPNP_ENTYR_INFO *info)
{
if (NULL == info)
{
UPNPC_ERROR("info is null");
return ERROR;
}
if (info->action != PORT_MAPPING_ACTION_GET_SPECIFIC)
{
UPNPC_ERROR("invalid action[%d]", info->action);
return ERROR;
}
if (info->still_alive == FALSE)
{
if (UPNPC_ENTRY_FLAG_UHTTPD == info->entry_flag)
{
g_upnpc_uhttpd_mapped = FALSE;
}
else if (UPNPC_ENTRY_FLAG_RTSP == info->entry_flag)
{
g_upnpc_rtsp_mapped = FALSE;
}
else if (UPNPC_ENTRY_FLAG_VHTTPD == info->entry_flag)
{
g_upnpc_vhttpd_mapped = FALSE;
}
#ifdef WEBRTC_SUPPORT
else
{
for (int i = 0; i < CLIENTS_CONN_MAX; i++)
{
if ((UPNPC_ENTRY_FLAG_WEBRTC_1 + i) == info->entry_flag)
{
g_upnpc_webrtc_mapped[i] = FALSE;
break;
}
}
}
#endif
delete_web_entry_record(info->external_port, info->protocol);
}
return OK;
}
LOCAL S32 recv_continuous_fail_time = 0;
#define RECV_FAIL_RETRY_INTER 3
#define RECV_MAX_RETRY_TIMES 3
LOCAL S32 upnpc_check_alive_and_add(UPNP_ENTYR_INFO *info)
{
if (NULL == info)
{
UPNPC_ERROR("info is null");
return ERROR;
}
if (info->action != PORT_MAPPING_ACTION_GET_SPECIFIC)
{
UPNPC_ERROR("invalid action[%d]", info->action);
return ERROR;
}
if (info->recv_successed == FALSE)
{
recv_continuous_fail_time++;
if (recv_continuous_fail_time >= RECV_MAX_RETRY_TIMES)
{
recv_continuous_fail_time = 0;
return ERROR;
}
inet_add_timer(upnpc_timer, 0, RECV_FAIL_RETRY_INTER, EXECUTE_SINGLE);
return ERROR;
}
/* recv http成功,将连续失败次数置为0 */
recv_continuous_fail_time = 0;
if (info->still_alive == FALSE)
{
reload_web_entries();
}
return OK;
}
#define MAX_PORT_MAPPING_NUM 4
LOCAL void upnpc_timer(S32 param)
{
NODE *node = NULL;
NODE *next = NULL;
UPNP_ENTRY_MAP *map_info = NULL;
NODE *web_list_head = get_web_entry_list_head();
if (web_list_head == NULL)
{
UPNPC_DEBUG("web_list_head == NULL!");
return;
}
list_for_each_safe(node, next, web_list_head)
{
map_info = (UPNP_ENTRY_MAP *)node;
get_specific_port_mapping(map_info->external_port, map_info->internal_port, map_info->protocol,
map_info->description, upnpc_check_alive_and_add);
}
}
LOCAL BOOL check_vhttpd_status = FALSE;
LOCAL STATUS get_upnp_status_json(DS_HANDLE_CONTEXT *context, JSON_OBJPTR resp_array_obj)
{
JSON_OBJPTR obj = NULL;
JSON_OBJPTR item_obj = NULL;
char ip_str[sizeof("255.255.255.255")] = {0};
LINK_STATUS link_status;
char *status_str = NULL;
LOCAL time_t last_call_time = 0;
time_t now = 0;
now = time(NULL);
/* 如果距离上次进入web upnp界面的时间超过3s(浏览器是每2s请求一次),则认为用户是从其他界面进入web的upnp页面,
* 首次进入该界面需要发送查询条目状态的报文 */
if (now - last_call_time > 3)
{
check_vhttpd_status = TRUE;
}
last_call_time = now;
memset(&link_status, 0, sizeof(link_status));
ds_read(LINK_STATUS_PATH, &link_status, sizeof(link_status));
if (NULL == inet_ntop(AF_INET, &link_status.ipaddr, ip_str, sizeof("255.255.255.255")))
{
return ERROR;
}
/* 构造vhttpd条目 */
obj = jso_new_obj();
jso_add_string(obj, "ipaddr", ip_str);
status_str = g_upnpc_vhttpd_mapped ? "on" : "off";
jso_add_string(obj, "status", status_str);
jso_add_string(obj, "proto", "TCP");
jso_add_string_from_int(obj, "inner_port", HTTPS_SERVER_PORT); //内部端口
jso_add_string(obj, "desc", "vhttpd");
jso_add_string_from_int(obj, "ext_port", cur_added_vhttpd_ext_port); //外部端口
/* 向路由器查询web界面添加的http条目是否依然生效 */
if (g_upnpc_vhttpd_mapped && TRUE == check_vhttpd_status)
{
check_vhttpd_status = FALSE;
upnpc_check_entry_status(cur_added_vhttpd_ext_port, HTTPS_SERVER_PORT,
DESCRIPTION_UPNPC_UHTTPD_STR, upnpc_get_entry_alive_done_cb
#ifdef WEBRTC_SUPPORT
, FALSE
#endif
);
}
item_obj = jso_new_obj();
jso_obj_add(item_obj, "vhttpd", obj);
jso_array_add(resp_array_obj, item_obj);
return OK;
}
LOCAL STATUS get_upnp_communicate_status(DS_HANDLE_CONTEXT *context, JSON_OBJPTR resp_array_obj)
{
if (!context )
return SLP_EINVARG;
UPNPC_STATUS upnpc_status = {{0}};
get_upnp_status(&upnpc_status);
jso_add_string(resp_array_obj, "status", upnpc_status.status);
jso_add_string(resp_array_obj, "timestamp",upnpc_status.timestamp);
return SLP_ENONE;
}
LOCAL STATUS set_upnp_communicate_status(DS_HANDLE_CONTEXT *context, JSON_OBJPTR obj)
{
if (NULL == context || NULL == obj || NULL == context->res_obj)
{
return SLP_EINVARG;
}
const char *status = NULL;
const char *timestamp = NULL;
UPNPC_STATUS upnpc_status = {{0}};
status = jso_obj_get_string_origin(obj, "status");
if (NULL == status)
{
return SLP_EINVARG;
}
timestamp = jso_obj_get_string_origin(obj,"timestamp");
if (NULL == timestamp)
{
return SLP_EINVARG;
}
snprintf(upnpc_status.status,STATUS_STR_LENTH,"%s",status);
upnpc_status.status[STATUS_STR_LENTH-1] = '\0';
snprintf(upnpc_status.timestamp,TIME_STAMP_LENTH,"%s",timestamp);
upnpc_status.timestamp[TIME_STAMP_LENTH-1] = '\0';
set_upnp_status(&upnpc_status);
UPNPC_DEBUG("set timestamp = %s, status = %d !",upnpc_status.timestamp,upnpc_status.status);
return SLP_ENONE;
}
LOCAL STATUS get_pub_ip_json(DS_HANDLE_CONTEXT *context, JSON_OBJPTR resp_array_obj)
{
if (!context || !context->res_obj)
return SLP_EINVARG;
jso_add_string(resp_array_obj, "ip", get_pub_ip());
UPNPC_DEBUG("get pub ip = %s",get_pub_ip());
return SLP_ENONE;
}
LOCAL STATUS get_upnpc_info(DS_HANDLE_CONTEXT *context, JSON_OBJPTR resp_array_obj)
{
if (!context)
{
UPNPC_INFO("get_upnpc_info error! ");
return SLP_EINVARG;
}
JSON_OBJPTR upnpc_info = NULL;
UPNPC_INFO info = {0};
if ( 0 == ds_read(UPNPC_INFO_PATH, &info, sizeof(UPNPC_INFO)))
{
UPNPC_ERROR("ds read upnpc info error!");
return ERROR;
}
upnpc_info = jso_new_obj();
jso_obj_add(resp_array_obj, "upnpc_info", upnpc_info);
const char * enabled = (info.enabled)? "on":"off";
jso_add_string(upnpc_info, "enabled", enabled);
const char * mode = (MODE_AUTO == info.mode) ? "auto" : "manual";
jso_add_string(upnpc_info, "mode", mode);
UPNPC_DEBUG("get_upnpc_info, enabled = %s , mode = %s",enabled,mode);
return SLP_ENONE;
}
LOCAL STATUS set_upnpc_info(DS_HANDLE_CONTEXT *context, JSON_OBJPTR obj)
{
if (NULL == context || NULL == obj)
{
return SLP_EINVARG;
}
const char *enabled = NULL;
const char *mode = NULL;
UPNPC_INFO info = {0};
UPNPC_INFO old_info = {0};
enabled = jso_obj_get_string_origin(obj, "enabled");
if (enabled == NULL)
{
UPNPC_ERROR("get enabled failed!");
return SLP_EINVARG;
}
mode = jso_obj_get_string_origin(obj, "mode");
if (mode == NULL)
{
UPNPC_ERROR("get mode failed!");
return SLP_EINVARG;
}
info.enabled = (!strcmp(enabled,"on"))?TRUE:FALSE;
info.mode = (!strcmp(mode,"auto"))?MODE_AUTO:MODE_MANUAL;
if (0 == ds_read(UPNPC_INFO_PATH,&old_info,sizeof(UPNPC_INFO)))
{
UPNPC_ERROR("read upnpc info failed");
return SLP_EEXPT;
}
if (!memcmp(&old_info,&info,sizeof(UPNPC_INFO)))
{
UPNPC_INFO("status not change");
return SLP_ENONE;
}
if (0 == ds_advanced_write(UPNPC_INFO_PATH,&info,sizeof(UPNPC_INFO),DS_FLAG_SAVE_FLASH))
{
UPNPC_ERROR("write upnpc info failed!");
return SLP_EEXPT;
}
UPNPC_DEBUG("set_upnpc_info enabled = %d, mode = %d",info.enabled,info.mode);
reload_web_entries();
return SLP_ENONE;
}
LOCAL S32 add_vhttpd_entry()
{
int ret = 0;
UPNPC_INFO upnpc_info;
UPNPC_VHTTPD vhttpd_info;
U16 vhttpd_external_port = 0;
memset(&upnpc_info, 0, sizeof(upnpc_info));
memset(&vhttpd_info, 0, sizeof(vhttpd_info));
ds_read(UPNPC_INFO_PATH, &upnpc_info, sizeof(upnpc_info));
if (FALSE == upnpc_info.enabled)
{
UPNPC_DEBUG("upnpc_info not enable ");
return OK;
}
ds_read(UPNPC_VHTTPD_PATH,&vhttpd_info,sizeof(vhttpd_info));
if (MODE_AUTO == upnpc_info.mode)
{
vhttpd_external_port = generate_external_mapping_port();
}
else
{
vhttpd_external_port = vhttpd_info.ext_port;
}
UPNPC_DEBUG("add mapping port = %d",vhttpd_external_port);
/* 添加映射条目 */
g_upnpc_vhttpd_mapped = FALSE;
cur_added_vhttpd_ext_port = FALSE;
upnpc_add_entry(vhttpd_external_port, HTTPS_SERVER_PORT,
DESCRIPTION_UPNPC_VHTTPD_STR, upnpc_add_entry_done_cb
#ifdef WEBRTC_SUPPORT
, FALSE
#endif
);
/*添加到list中的操作必须在对应节点的add_uhttpd/rtsp/..._entry函数执行*/
/*不能放在done cb中,因为cb有可能不被调用 */
return ret;
}
#ifdef WEBRTC_SUPPORT
LOCAL S32 add_webrtc_entry(int index)
{
int ret = 0;
UPNPC_INFO upnpc_info;
U16 webrtc_external_port = 0;
memset(&upnpc_info, 0, sizeof(upnpc_info));
ds_read(UPNPC_INFO_PATH, &upnpc_info, sizeof(upnpc_info));
if (FALSE == upnpc_info.enabled)
{
UPNPC_DEBUG("upnpc_info not enable ");
return OK;
}
if (MODE_AUTO == upnpc_info.mode)
{
webrtc_external_port = webrtc_generate_external_mapping_port() + (webrtc_server_port[index] - webrtc_server_port[0]) * PORT_INTERVAL;
}
else
{
webrtc_external_port = webrtc_server_port[index];
}
UPNPC_DEBUG("add mapping port = %d",webrtc_external_port);
/* 添加映射条目 */
g_upnpc_webrtc_mapped[index] = FALSE;
cur_added_webrtc_ext_port[index] = FALSE;
upnpc_add_entry(webrtc_external_port, webrtc_server_port[index],
description_upnpc_webrtc_str[index], upnpc_add_entry_done_cb, TRUE);
/*添加到list中的操作必须在对应节点的add_uhttpd/rtsp/..._entry函数执行*/
/*不能放在done cb中,因为函数多层调用提前返回cb有可能不被调用 */
return ret;
}
#endif
LOCAL S32 reload_uhttpd()
{
/* 暂时不添加web相关条目 */
return 0;
}
LOCAL S32 reload_rtsp()
{
/* 暂时不添加web相关条目 */
return 0;
}
LOCAL S32 reload_vhttpd()
{
UPNPC_INFO upnpc_info;
/* 读取UPNPC配置 /upnpc/upnpc_info */
memset(&upnpc_info, 0, sizeof(upnpc_info));
ds_read(UPNPC_INFO_PATH, &upnpc_info, sizeof(upnpc_info));
if (TRUE == g_upnpc_vhttpd_mapped && 0 != cur_added_vhttpd_ext_port)
{
UPNPC_ERROR("del old mapping");
g_upnpc_vhttpd_mapped = FALSE;
upnpc_delete_entry(cur_added_vhttpd_ext_port,
DESCRIPTION_UPNPC_VHTTPD_STR,upnpc_delete_entry_done_cb
#ifdef WEBRTC_SUPPORT
, FALSE
#endif
);
}
/* 当upnp被启用时,添加 vhttpd 条目 */
if (TRUE == upnpc_info.enabled)
{
UPNPC_ERROR("upnp enable begin to add entry");
add_vhttpd_entry();
}
return OK;
}
#ifdef WEBRTC_SUPPORT
LOCAL S32 reload_webrtc(int index)
{
UPNPC_INFO upnpc_info;
/* 读取UPNPC配置 /upnpc/upnpc_info */
memset(&upnpc_info, 0, sizeof(upnpc_info));
ds_read(UPNPC_INFO_PATH, &upnpc_info, sizeof(upnpc_info));
if (TRUE == g_upnpc_webrtc_mapped[index] && 0 != cur_added_webrtc_ext_port[index])
{
UPNPC_ERROR("del old mapping");
g_upnpc_webrtc_mapped[index] = FALSE;
upnpc_delete_entry(cur_added_webrtc_ext_port[index],
description_upnpc_webrtc_str[index],upnpc_delete_entry_done_cb, TRUE);
}
/* 当upnp被启用时,添加 webrtc 条目 */
if (TRUE == upnpc_info.enabled)
{
UPNPC_ERROR("upnp enable begin to add entry");
add_webrtc_entry(index);
}
return OK;
}
#endif
S32 reload_web_entries()
{
UPNPC_DEBUG("reload_web_entries");
reload_vhttpd();
#ifdef WEBRTC_SUPPORT
for (int i = 0; i < CLIENTS_CONN_MAX; i++)
{
reload_webrtc(i);
}
#endif
return OK;
}
LOCAL S32 upnpc_reload(DS_MSG *msg)
{
LINK_STATUS link_status = {0};
S32 ret = OK;
if (msg == NULL)
{
UPNPC_ERROR("Parameter wrong.");
return SLP_EGENERIC;
}
/* 当upnp开关、模式被更改时,重新添加uhttpd、rtsp条目 */
if (ds_path_id_exist(msg->id, msg->num, UPNPC_INFO_PATH))
{
reload_web_entries();
goto out;
}
/* 当在web端口界面更改内部端口时,重新添加uhttpd、rtsp条目 */
if (ds_path_id_exist(msg->id, msg->num, UHTTPD_MAINSEC_PATH)
|| ds_path_id_exist(msg->id, msg->num, CET_RTSP_PATH))
{
reload_web_entries();
goto out;
}
/* 当在web upnp界面更改uhttpd外部端口时,重新添加uhttpd条目 */
if (ds_path_id_exist(msg->id, msg->num, UPNPC_UHTTPD_PATH))
{
reload_uhttpd();
}
/* 当在web upnp界面更改rtsp外部端口时,重新添加rtsp条目 */
if (ds_path_id_exist(msg->id, msg->num, UPNPC_RTSP_PATH))
{
reload_rtsp();
}
/* 当网关、设备ip有变化时,重新添加全部生效的条目 */
if (ds_path_id_exist(msg->id, msg->num, LINK_STATUS_PATH))
{
if (0 == ds_read(LINK_STATUS_PATH, &link_status, sizeof(LINK_STATUS)))
{
UPNPC_ERROR("ds read %s return 0", LINK_STATUS_PATH);
return ERROR;
}
/* 由未连接变为连接 */
if (link_status.link_status == LINK_UP && link_status.link_status != s_link_status.link_status)
{
UPNPC_DEBUG("link_status changed to link!");
update_igd_ip();
reload_web_entries();
}
/* ipaddr发生变化 */
else if (link_status.ipaddr != s_link_status.ipaddr && link_status.ipaddr != 0)
{
UPNPC_DEBUG("ipaddr changed!");
/* 当本机ip变化后,重新加载一下upnp条目 */
reload_web_entries();
}
/* 网关发生变化 */
else if (link_status.gateway != s_link_status.gateway)
{
UPNPC_DEBUG("gateway changed!");
update_igd_ip();
reload_web_entries();
}
memset(&s_link_status, 0, sizeof(LINK_STATUS));
ds_read(LINK_STATUS_PATH, &s_link_status, sizeof(LINK_STATUS));
}
out:
UPNPC_INFO("reload over");
return ret;
}
LOCAL S32 upnpc_init(void)
{
ds_register_get_json("upnpc", "upnp_status", NULL, get_upnp_status_json);
ds_register_get_json("upnpc", "pub_ip","pub_ip", get_pub_ip_json);
ds_register_get_json("upnpc", "communicate","communicate", get_upnp_communicate_status );
ds_register_action("upnpc", "communicate", set_upnp_communicate_status);
ds_register_get_json("upnpc", "upnpc_info","upnpc_info", get_upnpc_info);
ds_register_action("upnpc", "upnpc_info", set_upnpc_info );
/* ubus call */
//msg_attach_handler(MSGID_DMS_CMD, upnpc_call_handle);
/* 其他模块通过dms消息添加/删除upnp映射条目 */
//msg_attach_handler(UPNPC_CONTROL_MID, upnpc_control_msg_handle);
msg_attach_handler(UPNPC_SAVE_PUB_IP_MSG_MID, upnpc_save_pub_ip);
UPNPC_INFO("upnpc init over");
return OK;
}
LOCAL S32 upnpc_start(void)
{
memset(&s_link_status, 0, sizeof(LINK_STATUS));
if (0 == ds_read(LINK_STATUS_PATH, &s_link_status, sizeof(LINK_STATUS)))
{
UPNPC_ERROR("ds read %s return 0", LINK_STATUS_PATH);
return ERROR;
}
UPNPC_INFO("start over");
/* 每隔2min对映射状态进行一次检查 */
if (g_check_timer == -1)
{
UPNPC_DEBUG("add timer");
g_check_timer = inet_add_timer(upnpc_timer, 0, CHECK_PORT_MAPPING_STATUS_INTERVAL, EXECUTE_FOREVER);
}
return OK;
}
LOCAL void upnpc_main()
{
DS_DAT_MON_DESC upnpc_data_monitor[] =
{
DS_DAT_MON(UPNPC_INFO_PATH, DATA_ATTRI_NOTIFY),
DS_DAT_MON(UHTTPD_MAINSEC_PATH, DATA_ATTRI_NOTIFY),
DS_DAT_MON(CET_RTSP_PATH, DATA_ATTRI_NOTIFY),
DS_DAT_MON(UPNPC_UHTTPD_PATH, DATA_ATTRI_NOTIFY),
DS_DAT_MON(UPNPC_RTSP_PATH, DATA_ATTRI_NOTIFY),
DS_DAT_MON(LINK_STATUS_PATH, DATA_ATTRI_NOTIFY),
DS_DAT_MON(UPNPC_VHTTPD_PATH, DATA_ATTRI_NOTIFY),
};
DS_MOD_DESC upnpc_module =
DS_STRUCT_MOD(UPNPC_MODULE_NAME, upnpc_init, NULL, upnpc_reload,
upnpc_start, NULL, NULL, upnpc_data_monitor);
MODULE *module_node = ds_register_module(UPNPC_MODULE_NAME, &upnpc_module);
SDM_ASSERT(NULL != module_node);
}
NSD_INIT(upnpc_main);
#endif
最新发布