client: retry upstream when network restart

This commit is contained in:
Nick Peng
2020-07-12 11:12:55 +08:00
parent ce46ac58a7
commit 2148efd262
2 changed files with 81 additions and 54 deletions

View File

@@ -902,13 +902,14 @@ static int _dns_client_server_add(char *server_ip, char *server_host, int port,
return 0;
errout:
if (server_info) {
if (server_info->ping_host) {
fast_ping_stop(server_info->ping_host);
}
if (server_info->ssl_ctx) {
SSL_CTX_free(server_info->ssl_ctx);
server_info->ssl_ctx = NULL;
}
if (server_info->ping_host) {
fast_ping_stop(server_info->ping_host);
}
free(server_info);
}
@@ -1509,7 +1510,7 @@ static int _DNS_client_create_socket_tcp(struct dns_server_info *server_info)
if (connect(fd, (struct sockaddr *)&server_info->addr, server_info->ai_addrlen) != 0) {
if (errno != EINPROGRESS) {
tlog(TLOG_ERROR, "connect failed.");
tlog(TLOG_ERROR, "connect %s failed, %s", server_info->ip, strerror(errno));
goto errout;
}
}
@@ -1518,7 +1519,7 @@ static int _DNS_client_create_socket_tcp(struct dns_server_info *server_info)
event.events = EPOLLIN | EPOLLOUT;
event.data.ptr = server_info;
if (epoll_ctl(client.epoll_fd, EPOLL_CTL_ADD, fd, &event) != 0) {
tlog(TLOG_ERROR, "epoll ctl failed.");
tlog(TLOG_ERROR, "epoll ctl failed, %s", strerror(errno));
return -1;
}
@@ -1575,7 +1576,7 @@ static int _DNS_client_create_socket_tls(struct dns_server_info *server_info, ch
// setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes));
// setsockopt(fd, IPPROTO_TCP, TCP_THIN_DUPACK, &yes, sizeof(yes));
// setsockopt(fd, IPPROTO_TCP, TCP_THIN_LINEAR_TIMEOUTS, &yes, sizeof(yes));
// set_sock_keepalive(fd, 15, 3, 4);
set_sock_keepalive(fd, 15, 3, 4);
setsockopt(fd, SOL_SOCKET, SO_PRIORITY, &priority, sizeof(priority));
setsockopt(fd, IPPROTO_IP, IP_TOS, &ip_tos, sizeof(ip_tos));
@@ -2352,7 +2353,7 @@ static int _dns_client_send_data_to_buffer(struct dns_server_info *server_info,
event.events = EPOLLIN | EPOLLOUT;
event.data.ptr = server_info;
if (epoll_ctl(client.epoll_fd, EPOLL_CTL_MOD, server_info->fd, &event) != 0) {
tlog(TLOG_ERROR, "epoll ctl failed.");
tlog(TLOG_ERROR, "epoll ctl failed, %s", strerror(errno));
return -1;
}
@@ -2506,59 +2507,79 @@ static int _dns_client_send_packet(struct dns_query_struct *query, void *packet,
query->send_tick = get_tick_count();
/* send query to all dns servers */
pthread_mutex_lock(&client.server_list_lock);
list_for_each_entry_safe(group_member, tmp, &query->server_group->head, list)
{
server_info = group_member->server;
if (server_info->fd <= 0) {
ret = _dns_client_create_socket(server_info);
for (int i = 0; i < 2; i++) {
pthread_mutex_lock(&client.server_list_lock);
list_for_each_entry_safe(group_member, tmp, &query->server_group->head, list)
{
server_info = group_member->server;
if (server_info->fd <= 0) {
ret = _dns_client_create_socket(server_info);
if (ret != 0) {
continue;
}
}
atomic_inc(&query->dns_request_sent);
switch (server_info->type) {
case DNS_SERVER_UDP:
/* udp query */
ret = _dns_client_send_udp(server_info, packet, len);
send_err = errno;
break;
case DNS_SERVER_TCP:
/* tcp query */
ret = _dns_client_send_tcp(server_info, packet, len);
send_err = errno;
break;
case DNS_SERVER_TLS:
/* tls query */
ret = _dns_client_send_tls(server_info, packet, len);
send_err = errno;
break;
case DNS_SERVER_HTTPS:
/* https query */
ret = _dns_client_send_https(server_info, packet, len);
send_err = errno;
break;
default:
/* unsupport query type */
ret = -1;
break;
}
if (ret != 0) {
if (send_err != ENOMEM) {
tlog(TLOG_ERROR, "send query to %s failed, %s, type: %d", server_info->ip, strerror(send_err),
server_info->type);
} else {
tlog(TLOG_DEBUG, "send query to %s failed, %s, type: %d", server_info->ip, strerror(send_err),
server_info->type);
time_t now;
time(&now);
if (now - 5 > server_info->last_recv) {
server_info->recv_buff.len = 0;
server_info->send_buff.len = 0;
tlog(TLOG_DEBUG, "server %s not response, retry.", server_info->ip);
_dns_client_close_socket(server_info);
}
}
atomic_dec(&query->dns_request_sent);
continue;
}
time(&server_info->last_send);
}
pthread_mutex_unlock(&client.server_list_lock);
atomic_inc(&query->dns_request_sent);
switch (server_info->type) {
case DNS_SERVER_UDP:
/* udp query */
ret = _dns_client_send_udp(server_info, packet, len);
send_err = errno;
break;
case DNS_SERVER_TCP:
/* tcp query */
ret = _dns_client_send_tcp(server_info, packet, len);
send_err = errno;
break;
case DNS_SERVER_TLS:
/* tls query */
ret = _dns_client_send_tls(server_info, packet, len);
send_err = errno;
break;
case DNS_SERVER_HTTPS:
/* https query */
ret = _dns_client_send_https(server_info, packet, len);
send_err = errno;
break;
default:
/* unsupport query type */
ret = -1;
if (atomic_read(&query->dns_request_sent) > 0) {
break;
}
if (ret != 0) {
if (send_err != ENOMEM) {
tlog(TLOG_ERROR, "send query to %s failed, %s, type: %d", server_info->ip, strerror(send_err),
server_info->type);
} else {
tlog(TLOG_DEBUG, "send query to %s failed, %s, type: %d", server_info->ip, strerror(send_err),
server_info->type);
}
atomic_dec(&query->dns_request_sent);
continue;
}
time(&server_info->last_send);
}
pthread_mutex_unlock(&client.server_list_lock);
if (atomic_read(&query->dns_request_sent) <= 0) {
tlog(TLOG_ERROR, "Send query to upstream server failed.");
return -1;
}
return 0;
}

View File

@@ -339,24 +339,30 @@ static void _sig_error_exit(int signo, siginfo_t *siginfo, void *ct)
{
unsigned long PC = 0;
ucontext_t *context = ct;
const char *arch = NULL;
#if defined(__i386__)
int *pgregs = (int *)(&(context->uc_mcontext.gregs));
PC = pgregs[REG_EIP];
arch = "i386";
#elif defined(__x86_64__)
int *pgregs = (int *)(&(context->uc_mcontext.gregs));
PC = pgregs[REG_RIP];
arch = "x86_64";
#elif defined(__arm__)
PC = context->uc_mcontext.arm_pc;
arch = "arm";
#elif defined(__aarch64__)
PC = context->uc_mcontext.pc;
arch = "arm64";
#elif defined(__mips__)
PC = context->uc_mcontext.pc;
arch = "mips";
#endif
tlog(TLOG_FATAL,
"process exit with signal %d, code = %d, errno = %d, pid = %d, self = %d, pc = %#lx, addr = %#lx, build(%s "
"%s)\n",
"%s %s)\n",
signo, siginfo->si_code, siginfo->si_errno, siginfo->si_pid, getpid(), PC, (unsigned long)siginfo->si_addr,
__DATE__, __TIME__);
__DATE__, __TIME__, arch);
sleep(1);
_exit(0);