feat: 长保持连接,控制端可重启
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include "control_protocol.h"
|
||||
#include "protocol.h"
|
||||
#include "video_pipeline.h"
|
||||
|
||||
#define CONTROL_DEFAULT_PEER_ID "peer-b-ctrl"
|
||||
@@ -19,6 +20,7 @@
|
||||
typedef struct unix_dgram_client {
|
||||
int fd;
|
||||
char bind_path[108];
|
||||
char dest_path[108];
|
||||
struct sockaddr_un dest_addr;
|
||||
socklen_t dest_len;
|
||||
} unix_dgram_client_t;
|
||||
@@ -28,7 +30,9 @@ typedef struct control_bridge_stats {
|
||||
uint64_t packets_forwarded;
|
||||
uint64_t invalid_packets;
|
||||
uint64_t unix_send_errors;
|
||||
int connected;
|
||||
uint64_t reconnect_count;
|
||||
int ever_connected;
|
||||
int registered;
|
||||
char last_error[256];
|
||||
kcp_runtime_stats_t transport;
|
||||
} control_bridge_stats_t;
|
||||
@@ -109,6 +113,8 @@ static void control_bridge_stats_destroy(control_bridge_stats_t *stats) {
|
||||
pthread_mutex_destroy(&stats->mutex);
|
||||
}
|
||||
|
||||
static void unix_dgram_client_close(unix_dgram_client_t *client);
|
||||
|
||||
static void control_bridge_set_error(control_bridge_stats_t *stats, const char *message) {
|
||||
if (stats == NULL) {
|
||||
return;
|
||||
@@ -142,7 +148,8 @@ static void control_bridge_stats_snapshot(control_bridge_stats_t *stats, control
|
||||
out_stats->packets_forwarded = stats->packets_forwarded;
|
||||
out_stats->invalid_packets = stats->invalid_packets;
|
||||
out_stats->unix_send_errors = stats->unix_send_errors;
|
||||
out_stats->connected = stats->connected;
|
||||
out_stats->reconnect_count = stats->reconnect_count;
|
||||
out_stats->registered = stats->registered;
|
||||
snprintf(out_stats->last_error, sizeof(out_stats->last_error), "%s", stats->last_error);
|
||||
out_stats->transport = stats->transport;
|
||||
pthread_mutex_unlock(&stats->mutex);
|
||||
@@ -178,6 +185,7 @@ static int unix_dgram_client_init(unix_dgram_client_t *client, const char *dest_
|
||||
|
||||
memset(&client->dest_addr, 0, sizeof(client->dest_addr));
|
||||
client->dest_addr.sun_family = AF_UNIX;
|
||||
snprintf(client->dest_path, sizeof(client->dest_path), "%s", dest_path);
|
||||
snprintf(client->dest_addr.sun_path, sizeof(client->dest_addr.sun_path), "%s", dest_path);
|
||||
client->dest_len = (socklen_t) sizeof(client->dest_addr);
|
||||
return 0;
|
||||
@@ -199,6 +207,22 @@ static int unix_dgram_client_send(unix_dgram_client_t *client, const void *data,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int unix_dgram_client_reopen(unix_dgram_client_t *client) {
|
||||
char dest_path[sizeof(client->dest_path)];
|
||||
|
||||
if (client == NULL || client->dest_path[0] == '\0') {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
snprintf(dest_path, sizeof(dest_path), "%s", client->dest_path);
|
||||
unix_dgram_client_close(client);
|
||||
return unix_dgram_client_init(client, dest_path);
|
||||
}
|
||||
|
||||
static int unix_dgram_client_should_reopen(int error_code) {
|
||||
return error_code == ENOENT || error_code == ECONNREFUSED || error_code == EBADF || error_code == ENOTCONN;
|
||||
}
|
||||
|
||||
static void unix_dgram_client_close(unix_dgram_client_t *client) {
|
||||
if (client == NULL) {
|
||||
return;
|
||||
@@ -253,27 +277,56 @@ static void *control_thread_main(void *arg) {
|
||||
continue;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&state->control_stats.mutex);
|
||||
state->control_stats.connected = 1;
|
||||
state->control_stats.last_error[0] = '\0';
|
||||
pthread_mutex_unlock(&state->control_stats.mutex);
|
||||
{
|
||||
kcp_client_state_t client_state;
|
||||
|
||||
memset(&client_state, 0, sizeof(client_state));
|
||||
kcp_client_state_snapshot(client, &client_state);
|
||||
pthread_mutex_lock(&state->control_stats.mutex);
|
||||
if (state->control_stats.ever_connected) {
|
||||
state->control_stats.reconnect_count += 1;
|
||||
} else {
|
||||
state->control_stats.ever_connected = 1;
|
||||
}
|
||||
state->control_stats.registered = client_state.registered;
|
||||
snprintf(state->control_stats.last_error, sizeof(state->control_stats.last_error), "%s", client_state.last_server_error);
|
||||
pthread_mutex_unlock(&state->control_stats.mutex);
|
||||
}
|
||||
|
||||
while (!*state->stop_requested) {
|
||||
message_t msg;
|
||||
int rc;
|
||||
kcp_client_state_t client_state;
|
||||
|
||||
protocol_message_init(&msg);
|
||||
rc = kcp_client_receive_timed(client, &msg, 100);
|
||||
if (rc == 1) {
|
||||
protocol_message_clear(&msg);
|
||||
memset(&client_state, 0, sizeof(client_state));
|
||||
kcp_client_state_snapshot(client, &client_state);
|
||||
pthread_mutex_lock(&state->control_stats.mutex);
|
||||
state->control_stats.registered = client_state.registered;
|
||||
snprintf(state->control_stats.last_error, sizeof(state->control_stats.last_error), "%s", client_state.last_server_error);
|
||||
pthread_mutex_unlock(&state->control_stats.mutex);
|
||||
continue;
|
||||
}
|
||||
if (rc != 0) {
|
||||
control_bridge_set_errno_error(&state->control_stats, "control receive loop stopped");
|
||||
memset(&client_state, 0, sizeof(client_state));
|
||||
kcp_client_state_snapshot(client, &client_state);
|
||||
if (client_state.last_server_error[0] != '\0') {
|
||||
control_bridge_set_error(&state->control_stats, client_state.last_server_error);
|
||||
} else {
|
||||
control_bridge_set_errno_error(&state->control_stats, "control receive loop stopped");
|
||||
}
|
||||
protocol_message_clear(&msg);
|
||||
break;
|
||||
}
|
||||
|
||||
if (msg.type == MSG_TYPE_ERROR && strcmp(msg.from, SERVER_PEER_ID) == 0) {
|
||||
control_bridge_set_error(&state->control_stats, (const char *) msg.body);
|
||||
protocol_message_clear(&msg);
|
||||
continue;
|
||||
}
|
||||
if (state->control_expected_sender[0] != '\0' && strcmp(msg.from, state->control_expected_sender) != 0) {
|
||||
pthread_mutex_lock(&state->control_stats.mutex);
|
||||
state->control_stats.invalid_packets += 1;
|
||||
@@ -291,6 +344,21 @@ static void *control_thread_main(void *arg) {
|
||||
}
|
||||
|
||||
if (unix_dgram_client_send(&state->unix_client, msg.body, msg.body_len) != 0) {
|
||||
int send_errno = errno;
|
||||
int recovered = 0;
|
||||
|
||||
if (unix_dgram_client_should_reopen(send_errno) && unix_dgram_client_reopen(&state->unix_client) == 0) {
|
||||
recovered = unix_dgram_client_send(&state->unix_client, msg.body, msg.body_len) == 0;
|
||||
}
|
||||
if (recovered) {
|
||||
pthread_mutex_lock(&state->control_stats.mutex);
|
||||
state->control_stats.packets_forwarded += 1;
|
||||
kcp_client_runtime_stats_snapshot(client, &state->control_stats.transport);
|
||||
pthread_mutex_unlock(&state->control_stats.mutex);
|
||||
protocol_message_clear(&msg);
|
||||
continue;
|
||||
}
|
||||
errno = send_errno;
|
||||
pthread_mutex_lock(&state->control_stats.mutex);
|
||||
state->control_stats.unix_send_errors += 1;
|
||||
pthread_mutex_unlock(&state->control_stats.mutex);
|
||||
@@ -307,7 +375,7 @@ static void *control_thread_main(void *arg) {
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&state->control_stats.mutex);
|
||||
state->control_stats.connected = 0;
|
||||
state->control_stats.registered = 0;
|
||||
pthread_mutex_unlock(&state->control_stats.mutex);
|
||||
kcp_client_close(client);
|
||||
kcp_client_free(client);
|
||||
@@ -330,12 +398,13 @@ static void print_stats(daemon_state_t *state) {
|
||||
|
||||
fprintf(
|
||||
stderr,
|
||||
"[b_side_omnid] video connected=%d frames=%llu bytes=%llu srtt=%dms | control connected=%d forwarded=%llu invalid=%llu unix_err=%llu srtt=%dms\n",
|
||||
"[b_side_omnid] video registered=%d frames=%llu bytes=%llu srtt=%dms | control registered=%d reconnects=%llu forwarded=%llu invalid=%llu unix_err=%llu srtt=%dms\n",
|
||||
video_stats.connected,
|
||||
(unsigned long long) video_stats.frames_sent,
|
||||
(unsigned long long) video_stats.bytes_sent,
|
||||
video_stats.transport.srtt_ms,
|
||||
control_stats.connected,
|
||||
control_stats.registered,
|
||||
(unsigned long long) control_stats.reconnect_count,
|
||||
(unsigned long long) control_stats.packets_forwarded,
|
||||
(unsigned long long) control_stats.invalid_packets,
|
||||
(unsigned long long) control_stats.unix_send_errors,
|
||||
|
||||
Reference in New Issue
Block a user