doubao_chat/lib/net/tencent/tvs_sdk/src/tvs_dns.c

388 lines
9.1 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "tvs_http_client.h"
#include "tvs_http_manager.h"
#include "mongoose.h"
#define TVS_LOG_DEBUG_MODULE "DNS"
#include "tvs_log.h"
#include "tvs_config.h"
#include "tvs_echo.h"
#include "tvs_ip_provider.h"
#include "tvs_dns.h"
#include "tvs_threads.h"
#include "os/os_api.h"
#define HTTP_DNS_PATH "http://119.29.29.29:80/d?dn="
static long g_last_dns_time = 0;
static int g_http_dns_ip = 0;
static int g_system_dns_ip = 0;
static int g_http_dns_ip_tmp = 0;
static int g_system_dns_ip_tmp = 0;
// 兜底IP
#define BACKUP_IP "183.3.225.67"
static int g_tvs_dns_pid = NULL;
static void *g_tvs_dns_mutex = NULL;
static int g_tvs_dns_start;
#define DNS_REFRESH_TIMER 40 // 更新DNS的时间间隔
typedef struct {
int ip_addr;
} tvs_http_dns_param;
TVS_LOCKER_DEFINE
extern void tvs_dns_fetch_all();
void tvs_dns_retry_dns(tvs_http_client_callback_exit_loop should_exit_func,
tvs_http_client_callback_should_cancel should_cancel_func, void *exit_param)
{
long cur_time = os_wrapper_get_time_ms();
if (g_last_dns_time == 0 || cur_time - g_last_dns_time > 600 * 1000) {
TVS_LOG_PRINTF("dns timeout, begin\n");
g_last_dns_time = cur_time;
// 超时,重新获取一次dns
tvs_dns_fetch_all(should_exit_func, should_cancel_func, exit_param);
}
}
void tvs_http_dns_callback_on_connect(void *connection, int error_code, tvs_http_client_param *param)
{
//TVS_LOG_PRINTF("send iplist connect\n");
}
void tvs_http_dns_callback_on_response(void *connection, int ret_code, const char *response, int response_len, tvs_http_client_param *param)
{
if (ret_code == 200) {
unsigned int a, b, c, d = 0;
if (response_len > 0 && response != NULL) {
char *ip_str = malloc(response_len + 1);
if (ip_str == NULL) {
TVS_LOG_PRINTF("get resonse ip OOM\n");
return;
}
memset(ip_str, 0, response_len + 1);
strncpy(ip_str, response, response_len);
if (sscanf(ip_str, "%u.%u.%u.%u", &a, &b, &c, &d) == 4) {
tvs_http_dns_param *dns_param = (tvs_http_dns_param *)param->user_data;
dns_param->ip_addr =
mg_htonl(((uint32_t) a << 24) | ((uint32_t) b << 16) | c << 8 | d);
//TVS_LOG_PRINTF("get resonse ip %s, %d\n", response, dns_param->ip_addr);
}
free(ip_str);
}
} else {
TVS_LOG_PRINTF("get resonse err %d - %.*s\n", ret_code, response_len, response);
}
}
void tvs_http_dns_callback_on_close(void *connection, int by_server, tvs_http_client_param *param) { }
int tvs_http_dns_callback_on_send_request(void *connection, const char *path, const char *host, const char *extra_header, const char *payload, tvs_http_client_param *param)
{
tvs_http_send_normal_get_request((struct mg_connection *)connection, path, strlen(path), host, strlen(host));
return 0;
}
bool tvs_http_dns_callback_on_loop(void *connection, tvs_http_client_param *param)
{
return false;
}
int tvs_http_dns_start(const char *host,
tvs_http_client_callback_exit_loop should_exit_func,
tvs_http_client_callback_should_cancel should_cancel_func,
void *exit_param,
int *ip_addr)
{
if (host == NULL || strlen(host) <= 0) {
TVS_LOG_PRINTF("%s -- invalid host\n", __func__);
return -1;
}
int max_buf_len = 200;
char *http_dns_url = malloc(max_buf_len);
if (NULL == http_dns_url) {
TVS_LOG_PRINTF("%s -- OOM\n", __func__);
return -1;
}
memset(http_dns_url, 0, max_buf_len);
sprintf(http_dns_url, "%s%s", HTTP_DNS_PATH, host);
//TVS_LOG_PRINTF("send http dns url %s\n", http_dns_url);
tvs_http_client_callback cb = { 0 };
cb.cb_on_close = tvs_http_dns_callback_on_close;
cb.cb_on_connect = tvs_http_dns_callback_on_connect;
cb.cb_on_loop = tvs_http_dns_callback_on_loop;
cb.cb_on_request = tvs_http_dns_callback_on_send_request;
cb.cb_on_response = tvs_http_dns_callback_on_response;
cb.exit_loop = should_exit_func;
cb.should_cancel = should_cancel_func;
cb.exit_loop_param = exit_param;
tvs_http_client_config config = { 0 };
tvs_http_client_param http_param = { 0 };
tvs_http_dns_param http_dns_param = { 0 };
int ret = tvs_http_client_request_with_forceip(http_dns_url, NULL, NULL, &http_dns_param, &config, &cb, &http_param, false, 0);
if (http_dns_url != NULL) {
free(http_dns_url);
}
*ip_addr = http_dns_param.ip_addr;
TVS_LOG_PRINTF("send http dns result %d\n", *ip_addr);
return ret;
}
extern int mg_resolve2(const char *host, struct in_addr *ina);
int tvs_resolve(const char *host, int *ina)
{
return mg_resolve2(host, (struct in_addr *)ina);
}
int tvs_dns_system_start(const char *host)
{
int ipaddr = 0;
tvs_resolve(host, &ipaddr);
return ipaddr;
}
void tvs_dns_fetch_all(tvs_http_client_callback_exit_loop should_exit_func,
tvs_http_client_callback_should_cancel should_cancel_func, void *exit_param)
{
const char *host = tvs_config_get_current_host();
int ipaddr = 0;
tvs_http_dns_start(host, should_exit_func, should_cancel_func, exit_param, &ipaddr);
TVS_LOG_PRINTF("tvs_dns_fetch_all http dns %d \n", ipaddr);
if (ipaddr != 0) {
do_lock();
g_http_dns_ip = ipaddr;
g_http_dns_ip_tmp = g_http_dns_ip;
TVS_LOG_PRINTF("get http dns %d - %s\n", ipaddr, inet_ntoa(*(struct in_addr *)&ipaddr));
do_unlock();
}
ipaddr = tvs_dns_system_start(host);
if (ipaddr != 0) {
do_lock();
if (g_http_dns_ip != ipaddr) {
g_system_dns_ip = ipaddr;
TVS_LOG_PRINTF("get system dns %d - %s\n", ipaddr, inet_ntoa(*(struct in_addr *)&ipaddr));
} else {
g_system_dns_ip = 0;
}
g_system_dns_ip_tmp = g_system_dns_ip;
do_unlock();
}
}
bool tvs_http_dns_check_start()
{
return true;
}
bool tvs_http_dns_remove_ip(int ip_addr)
{
if (ip_addr == 0) {
return false;
}
do_lock();
if (g_http_dns_ip_tmp == ip_addr) {
g_http_dns_ip_tmp = 0;
}
do_unlock();
return true;
}
int tvs_http_dns_get_count()
{
return 1;
}
int tvs_system_dns_get_count()
{
return 1;
}
int tvs_http_dns_get_next_ip(int index)
{
if (index != 0) {
return 0;
}
do_lock();
int ip = g_http_dns_ip_tmp;
do_unlock();
return ip;
}
bool tvs_system_dns_check_start()
{
return true;
}
int tvs_system_dns_get_next_ip(int index)
{
if (index != 0) {
return 0;
}
do_lock();
int ip = g_system_dns_ip_tmp;
do_unlock();
return ip;
}
bool tvs_system_dns_remove_ip(int ip_addr)
{
if (ip_addr == 0) {
return false;
}
do_lock();
if (g_system_dns_ip_tmp == ip_addr) {
g_system_dns_ip_tmp = 0;
}
do_unlock();
return true;
}
static void dns_thread_func(tvs_thread_handle_t *thread_handle_t);
int tvs_dns_init()
{
TVS_LOCKER_INIT
return 0;
}
int tvs_dns_uninit()
{
TVS_LOCKER_UNINIT
return 0;
}
void tvs_dns_get_first_ip()
{
// 首次连接,获取DNS IP,不进行echo校验,直接设置为valid ip
tvs_dns_fetch_all(NULL, NULL, NULL);
do_lock();
int ip = g_http_dns_ip == 0 ? g_system_dns_ip : g_http_dns_ip;
do_unlock();
if (ip != 0) {
tvs_ip_provider_set_valid_ip(ip, true);
} else {
// 如果系统dns和http dns都没有,那么使用兜底IP
tvs_ip_provider_set_valid_ip_ex(BACKUP_IP, true);
}
}
static void dns_thread_func(tvs_thread_handle_t *thread_handle_t)
{
tvs_dns_fetch_all(NULL, NULL, NULL);
int validip = 0;
do_lock();
int http_ip = g_http_dns_ip;
int system_ip = g_system_dns_ip;
do_unlock();
bool ret = tvs_echo_start(http_ip);
if (!ret) {
ret = tvs_echo_start(system_ip);
if (ret) {
validip = system_ip;
}
} else {
validip = http_ip;
}
if (validip != 0) {
tvs_ip_provider_set_valid_ip(validip, true);
}
}
static void tvs_dns_timer_func(void *param)
{
while (g_tvs_dns_start) {
dns_thread_func(NULL);
os_wrapper_wait_signal(g_tvs_dns_mutex, DNS_REFRESH_TIMER * 60 * 1000);
}
}
static void tvs_dns_refresh_start()
{
if (!g_tvs_dns_pid) {
if (!g_tvs_dns_mutex) {
g_tvs_dns_mutex = os_wrapper_create_signal_mutex(0);
}
g_tvs_dns_start = 1;
thread_fork("tvs_dns_thread", 20, 1024, 0, &g_tvs_dns_pid, tvs_dns_timer_func, NULL);
}
}
void tvs_dns_refresh_stop()
{
if (g_tvs_dns_pid) {
g_tvs_dns_start = 0;
os_wrapper_post_signal(g_tvs_dns_mutex);
thread_kill(&g_tvs_dns_pid, KILL_WAIT);
g_tvs_dns_pid = 0;
os_wrapper_delete_signal_mutex(&g_tvs_dns_mutex);
}
}
void tvs_dns_on_network_changed(bool connected)
{
TVS_LOG_PRINTF("network changed,dns:%d\n", connected);
if (connected) {
// 网络重连的时候,需要刷新DNS IP
tvs_dns_refresh_start();
} else {
tvs_dns_refresh_stop();
}
}