diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7721f875e..2b485144e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,6 +1,6 @@ project(lib) -file(GLOB SRCS "*.c") +file(GLOB SRCS "agent.c" "peer_connection.c" "*.c") file(GLOB HEADERS "peer.h" "peer_connection.h" "peer_signaling.h") diff --git a/src/agent.c b/src/agent.c index 0e50ab885..c92b0f1cf 100644 --- a/src/agent.c +++ b/src/agent.c @@ -320,22 +320,28 @@ static void agent_create_binding_response(Agent* agent, StunMessage* msg, Addres stun_msg_finish(msg, STUN_CREDENTIAL_SHORT_TERM, agent->local_upwd, strlen(agent->local_upwd)); } -static void agent_create_binding_request(Agent* agent, StunMessage* msg) { - uint64_t tie_breaker = 0; // always be controlled +static void agent_create_binding_request(Agent* agent, StunMessage* msg, int is_heartbeat) { // send binding request - stun_msg_create(msg, STUN_CLASS_REQUEST | STUN_METHOD_BINDING); - char username[584]; - memset(username, 0, sizeof(username)); - snprintf(username, sizeof(username), "%s:%s", agent->remote_ufrag, agent->local_ufrag); - stun_msg_write_attr(msg, STUN_ATTR_TYPE_USERNAME, strlen(username), username); - stun_msg_write_attr(msg, STUN_ATTR_TYPE_PRIORITY, 4, (char*)&agent->nominated_pair->priority); - if (agent->mode == AGENT_MODE_CONTROLLING) { - stun_msg_write_attr(msg, STUN_ATTR_TYPE_USE_CANDIDATE, 0, NULL); - stun_msg_write_attr(msg, STUN_ATTR_TYPE_ICE_CONTROLLING, 8, (char*)&tie_breaker); - } else { - stun_msg_write_attr(msg, STUN_ATTR_TYPE_ICE_CONTROLLED, 8, (char*)&tie_breaker); + if (!is_heartbeat) { + uint64_t tie_breaker = 0; // always be controlled + stun_msg_create(msg, STUN_CLASS_REQUEST | STUN_METHOD_BINDING); + char username[584]; + memset(username, 0, sizeof(username)); + snprintf(username, sizeof(username), "%s:%s", agent->remote_ufrag, agent->local_ufrag); + stun_msg_write_attr(msg, STUN_ATTR_TYPE_USERNAME, strlen(username), username); + stun_msg_write_attr(msg, STUN_ATTR_TYPE_PRIORITY, 4, (char*)&agent->nominated_pair->priority); + if (agent->mode == AGENT_MODE_CONTROLLING) { + stun_msg_write_attr(msg, STUN_ATTR_TYPE_USE_CANDIDATE, 0, NULL); + stun_msg_write_attr(msg, STUN_ATTR_TYPE_ICE_CONTROLLING, 8, (char*)&tie_breaker); + } else { + stun_msg_write_attr(msg, STUN_ATTR_TYPE_ICE_CONTROLLED, 8, (char*)&tie_breaker); + } + stun_msg_finish(msg, STUN_CREDENTIAL_SHORT_TERM, agent->remote_upwd, strlen(agent->remote_upwd)); + } + else{ + stun_msg_create(msg, STUN_CLASS_REQUEST | STUN_METHOD_BINDING); + stun_msg_finish(msg, STUN_CREDENTIAL_SHORT_TERM, agent->remote_upwd, strlen(agent->remote_upwd)); } - stun_msg_finish(msg, STUN_CREDENTIAL_SHORT_TERM, agent->remote_upwd, strlen(agent->remote_upwd)); } void agent_process_stun_request(Agent* agent, StunMessage* stun_msg, Address* addr) { @@ -447,32 +453,36 @@ void agent_set_remote_description(Agent* agent, char* description) { LOGD("candidate pairs num: %d", agent->candidate_pairs_num); } -int agent_connectivity_check(Agent* agent) { +int agent_connectivity_check(Agent* agent, int is_heartbeat) { char addr_string[ADDRSTRLEN]; uint8_t buf[1400]; StunMessage msg; + if (!is_heartbeat) { + if (agent->nominated_pair->state != ICE_CANDIDATE_STATE_INPROGRESS) { + LOGI("nominated pair is not in progress"); + return -1; + } + - if (agent->nominated_pair->state != ICE_CANDIDATE_STATE_INPROGRESS) { - LOGI("nominated pair is not in progress"); - return -1; - } - - memset(&msg, 0, sizeof(msg)); + memset(&msg, 0, sizeof(msg)); - if (agent->nominated_pair->conncheck % AGENT_CONNCHECK_PERIOD == 0) { - addr_to_string(&agent->nominated_pair->remote->addr, addr_string, sizeof(addr_string)); - LOGD("send binding request to remote ip: %s, port: %d", addr_string, agent->nominated_pair->remote->addr.port); - agent_create_binding_request(agent, &msg); - agent_socket_send(agent, &agent->nominated_pair->remote->addr, msg.buf, msg.size); - } + if (agent->nominated_pair->conncheck % AGENT_CONNCHECK_PERIOD == 0) { + addr_to_string(&agent->nominated_pair->remote->addr, addr_string, sizeof(addr_string)); + LOGD("send binding request to remote ip: %s, port: %d", addr_string, agent->nominated_pair->remote->addr.port); + agent_create_binding_request(agent, &msg, 0); + agent_socket_send(agent, &agent->nominated_pair->remote->addr, msg.buf, msg.size); + } - agent_recv(agent, buf, sizeof(buf)); + agent_recv(agent, buf, sizeof(buf)); - if (agent->nominated_pair->state == ICE_CANDIDATE_STATE_SUCCEEDED) { - agent->selected_pair = agent->nominated_pair; - return 0; + if (agent->nominated_pair->state == ICE_CANDIDATE_STATE_SUCCEEDED) { + agent->selected_pair = agent->nominated_pair; + return 0; + } + } else { + agent_create_binding_request(agent, &msg, 1); + agent_socket_send(agent, &agent->nominated_pair->remote->addr, msg.buf, msg.size); } - return -1; } diff --git a/src/agent.h b/src/agent.h index 86da0e53d..18e9e2225 100644 --- a/src/agent.h +++ b/src/agent.h @@ -84,7 +84,7 @@ void agent_set_remote_description(Agent* agent, char* description); int agent_select_candidate_pair(Agent* agent); -int agent_connectivity_check(Agent* agent); +int agent_connectivity_check(Agent* agent, int is_heartbeat); void agent_clear_candidates(Agent* agent); diff --git a/src/peer_connection.c b/src/peer_connection.c index c7709cfbb..2f7ab8f2c 100644 --- a/src/peer_connection.c +++ b/src/peer_connection.c @@ -14,6 +14,7 @@ #include "sctp.h" #include "sdp.h" + #define STATE_CHANGED(pc, curr_state) \ if (pc->oniceconnectionstatechange && pc->state != curr_state) { \ pc->oniceconnectionstatechange(curr_state, pc->config.user_data); \ @@ -29,6 +30,7 @@ struct PeerConnection { Sdp local_sdp; Sdp remote_sdp; + time_t last_binding_request_time; void (*onicecandidate)(char* sdp, void* user_data); void (*oniceconnectionstatechange)(PeerConnectionState state, void* user_data); @@ -422,7 +424,7 @@ int peer_connection_loop(PeerConnection* pc) { case PEER_CONNECTION_CHECKING: if (agent_select_candidate_pair(&pc->agent) < 0) { STATE_CHANGED(pc, PEER_CONNECTION_FAILED); - } else if (agent_connectivity_check(&pc->agent) == 0) { + } else if (agent_connectivity_check(&pc->agent, 0) == 0) { STATE_CHANGED(pc, PEER_CONNECTION_CONNECTED); } break; @@ -437,12 +439,19 @@ int peer_connection_loop(PeerConnection* pc) { sctp_create_association(&pc->sctp, &pc->dtls_srtp); pc->sctp.userdata = pc->config.user_data; } - + pc->last_binding_request_time = time(NULL); STATE_CHANGED(pc, PEER_CONNECTION_COMPLETED); } break; case PEER_CONNECTION_COMPLETED: + time_t current_time = time(NULL); + if (current_time - pc->last_binding_request_time >= 8) { + agent_connectivity_check(&pc->agent, 1); + LOGI("heartbeat sent!"); + pc->last_binding_request_time = current_time; + } + #if (CONFIG_VIDEO_BUFFER_SIZE) > 0 data = buffer_peak_head(pc->video_rb, &bytes); if (data) { @@ -502,7 +511,6 @@ int peer_connection_loop(PeerConnection* pc) { LOGW("Unknown data"); } } - if (CONFIG_KEEPALIVE_TIMEOUT > 0 && (ports_get_epoch_time() - pc->agent.binding_request_time) > CONFIG_KEEPALIVE_TIMEOUT) { LOGI("binding request timeout"); STATE_CHANGED(pc, PEER_CONNECTION_CLOSED); diff --git a/src/peer_signaling.c b/src/peer_signaling.c index 342a5798a..560715a31 100644 --- a/src/peer_signaling.c +++ b/src/peer_signaling.c @@ -209,9 +209,17 @@ static void peer_signaling_on_pub_event(const char* msg, size_t size) { break; } - if (state == PEER_CONNECTION_NEW) { - peer_connection_set_remote_description(g_ps.pc, item->valuestring); - result = cJSON_CreateString(""); + switch (state) { + case PEER_CONNECTION_NEW: + case PEER_CONNECTION_DISCONNECTED: + case PEER_CONNECTION_FAILED: + case PEER_CONNECTION_CLOSED: { + g_ps.id = id; + peer_connection_set_remote_description(g_ps.pc, item->valuestring); + } break; + default: { + error = cJSON_CreateRaw(RPC_ERROR_INTERNAL_ERROR); + } break; } } else if (strcmp(item->valuestring, RPC_METHOD_STATE) == 0) {