Fix nice agent crash

This commit is contained in:
dijunkun
2023-10-17 10:54:40 +08:00
parent ca4f379d3b
commit 18b2a4a175
3 changed files with 141 additions and 76 deletions

View File

@@ -18,67 +18,17 @@ IceAgent::IceAgent(bool offer_peer, std::string &stun_ip, uint16_t stun_port,
controlling_(offer_peer) {} controlling_(offer_peer) {}
IceAgent::~IceAgent() { IceAgent::~IceAgent() {
exit_thread_ = TRUE; if (!destroyed_) {
g_thread_join(gexamplethread_); DestroyIceAgent();
} }
g_object_unref(agent_);
void *IceAgent::CreateNiceAgent(void *data) {
if (!data) {
return nullptr;
}
IceAgent *ice_agent_ptr = (IceAgent *)data;
ice_agent_ptr->gloop_ = g_main_loop_new(NULL, FALSE);
// Create the nice agent_
ice_agent_ptr->agent_ =
nice_agent_new_reliable(g_main_loop_get_context(ice_agent_ptr->gloop_),
NICE_COMPATIBILITY_RFC5245);
if (ice_agent_ptr->agent_ == NULL) {
LOG_ERROR("Failed to create agent_");
}
g_object_set(ice_agent_ptr->agent_, "stun-server",
ice_agent_ptr->stun_ip_.c_str(), NULL);
g_object_set(ice_agent_ptr->agent_, "stun-server-port",
ice_agent_ptr->stun_port_, NULL);
g_object_set(ice_agent_ptr->agent_, "controlling-mode",
ice_agent_ptr->controlling_, NULL);
// Connect to the signals
g_signal_connect(ice_agent_ptr->agent_, "candidate-gathering-done",
G_CALLBACK(ice_agent_ptr->on_gathering_done_),
ice_agent_ptr->user_ptr_);
g_signal_connect(ice_agent_ptr->agent_, "new-selected-pair",
G_CALLBACK(ice_agent_ptr->on_candidate_),
ice_agent_ptr->user_ptr_);
g_signal_connect(ice_agent_ptr->agent_, "component-state-changed",
G_CALLBACK(ice_agent_ptr->on_state_changed_),
ice_agent_ptr->user_ptr_);
// Create a new stream with one component
ice_agent_ptr->stream_id_ = nice_agent_add_stream(ice_agent_ptr->agent_, 1);
if (ice_agent_ptr->stream_id_ == 0) {
LOG_ERROR("Failed to add stream");
}
// nice_agent_set_stream_name(ice_agent_ptr->agent_, stream_id_, "video");
// Attach to the component to receive the data
// Without this call, candidates cannot be gathered
nice_agent_attach_recv(ice_agent_ptr->agent_, ice_agent_ptr->stream_id_, 1,
g_main_loop_get_context(ice_agent_ptr->gloop_),
ice_agent_ptr->on_recv_, ice_agent_ptr->user_ptr_);
g_main_loop_run(ice_agent_ptr->gloop_);
} }
int IceAgent::CreateIceAgent(nice_cb_state_changed_t on_state_changed, int IceAgent::CreateIceAgent(nice_cb_state_changed_t on_state_changed,
nice_cb_candidate_t on_candidate, nice_cb_candidate_t on_candidate,
nice_cb_gathering_done_t on_gathering_done, nice_cb_gathering_done_t on_gathering_done,
nice_cb_recv_t on_recv, void *user_ptr) { nice_cb_recv_t on_recv, void *user_ptr) {
destroyed_ = false;
on_state_changed_ = on_state_changed; on_state_changed_ = on_state_changed;
on_candidate_ = on_candidate; on_candidate_ = on_candidate;
on_gathering_done_ = on_gathering_done; on_gathering_done_ = on_gathering_done;
@@ -87,27 +37,85 @@ int IceAgent::CreateIceAgent(nice_cb_state_changed_t on_state_changed,
g_networking_init(); g_networking_init();
// gloop_ = g_main_loop_new(NULL, FALSE); exit_nice_thread_ = false;
exit_thread_ = FALSE;
// gexamplethread_ = g_thread_new("example thread", &CreateNiceAgent, this);
// g_main_loop_run(gloop_); nice_thread_.reset(new std::thread([this]() {
g_thread_.reset(new std::thread(std::bind(&IceAgent::CreateNiceAgent, this))); gloop_ = g_main_loop_new(nullptr, false);
agent_ = nice_agent_new_reliable(g_main_loop_get_context(gloop_),
NICE_COMPATIBILITY_RFC5245);
if (agent_ == nullptr) {
LOG_ERROR("Failed to create agent_");
}
g_object_set(agent_, "stun-server", stun_ip_.c_str(), nullptr);
g_object_set(agent_, "stun-server-port", stun_port_, nullptr);
g_object_set(agent_, "controlling-mode", controlling_, nullptr);
g_signal_connect(agent_, "candidate-gathering-done",
G_CALLBACK(on_gathering_done_), user_ptr_);
g_signal_connect(agent_, "new-selected-pair", G_CALLBACK(on_candidate_),
user_ptr_);
g_signal_connect(agent_, "component-state-changed",
G_CALLBACK(on_state_changed_), user_ptr_);
stream_id_ = nice_agent_add_stream(agent_, 1);
if (stream_id_ == 0) {
LOG_ERROR("Failed to add stream");
}
nice_agent_set_stream_name(agent_, stream_id_, "video");
nice_agent_attach_recv(agent_, stream_id_, 1,
g_main_loop_get_context(gloop_), on_recv_,
user_ptr_);
nice_inited_ = true;
g_main_loop_run(gloop_);
exit_nice_thread_ = true;
g_main_loop_unref(gloop_);
}));
do {
g_usleep(1000);
} while (!nice_inited_);
LOG_INFO("Nice agent init finish"); LOG_INFO("Nice agent init finish");
g_usleep(100000);
return 0; return 0;
} }
int IceAgent::DestoryIceAgent() { int IceAgent::DestroyIceAgent() {
g_object_unref(agent_); if (!nice_inited_) {
LOG_ERROR("Nice agent has not been initialized");
return -1;
}
destroyed_ = true;
g_main_loop_quit(gloop_);
if (nice_thread_->joinable()) {
nice_thread_->join();
}
LOG_ERROR("Destroy nice agent success");
return 0; return 0;
} }
char *IceAgent::GenerateLocalSdp() { char *IceAgent::GenerateLocalSdp() {
if (!nice_inited_) {
LOG_ERROR("Nice agent has not been initialized");
return nullptr;
}
if (nullptr == agent_) { if (nullptr == agent_) {
LOG_INFO("agent_ is nullptr"); LOG_ERROR("Nice agent is nullptr");
return nullptr;
}
if (destroyed_) {
LOG_ERROR("Nice agent is destroyed");
return nullptr; return nullptr;
} }
@@ -118,6 +126,21 @@ char *IceAgent::GenerateLocalSdp() {
} }
int IceAgent::SetRemoteSdp(const char *remote_sdp) { int IceAgent::SetRemoteSdp(const char *remote_sdp) {
if (!nice_inited_) {
LOG_ERROR("Nice agent has not been initialized");
return -1;
}
if (nullptr == agent_) {
LOG_ERROR("Nice agent is nullptr");
return -1;
}
if (destroyed_) {
LOG_ERROR("Nice agent is destroyed");
return -1;
}
int ret = nice_agent_parse_remote_sdp(agent_, remote_sdp); int ret = nice_agent_parse_remote_sdp(agent_, remote_sdp);
if (ret > 0) { if (ret > 0) {
return 0; return 0;
@@ -128,6 +151,21 @@ int IceAgent::SetRemoteSdp(const char *remote_sdp) {
} }
int IceAgent::GatherCandidates() { int IceAgent::GatherCandidates() {
if (!nice_inited_) {
LOG_ERROR("Nice agent has not been initialized");
return -1;
}
if (nullptr == agent_) {
LOG_ERROR("Nice agent is nullptr");
return -1;
}
if (destroyed_) {
LOG_ERROR("Nice agent is destroyed");
return -1;
}
if (!nice_agent_gather_candidates(agent_, stream_id_)) { if (!nice_agent_gather_candidates(agent_, stream_id_)) {
LOG_ERROR("Failed to start candidate gathering"); LOG_ERROR("Failed to start candidate gathering");
return -1; return -1;
@@ -137,12 +175,42 @@ int IceAgent::GatherCandidates() {
} }
NiceComponentState IceAgent::GetIceState() { NiceComponentState IceAgent::GetIceState() {
if (!nice_inited_) {
LOG_ERROR("Nice agent has not been initialized");
return NiceComponentState::NICE_COMPONENT_STATE_LAST;
}
if (nullptr == agent_) {
LOG_ERROR("Nice agent is nullptr");
return NiceComponentState::NICE_COMPONENT_STATE_LAST;
}
if (destroyed_) {
LOG_ERROR("Nice agent is destroyed");
return NiceComponentState::NICE_COMPONENT_STATE_LAST;
}
state_ = nice_agent_get_component_state(agent_, stream_id_, 1); state_ = nice_agent_get_component_state(agent_, stream_id_, 1);
return state_; return state_;
} }
int IceAgent::Send(const char *data, size_t size) { int IceAgent::Send(const char *data, size_t size) {
if (!nice_inited_) {
LOG_ERROR("Nice agent has not been initialized");
return -1;
}
if (nullptr == agent_) {
LOG_ERROR("Nice agent is nullptr");
return -1;
}
if (destroyed_) {
LOG_ERROR("Nice agent is destroyed");
return -1;
}
if (NiceComponentState::NICE_COMPONENT_STATE_READY != if (NiceComponentState::NICE_COMPONENT_STATE_READY !=
nice_agent_get_component_state(agent_, stream_id_, 1)) { nice_agent_get_component_state(agent_, stream_id_, 1)) {
return -1; return -1;

View File

@@ -8,8 +8,6 @@
#include "glib.h" #include "glib.h"
#include "nice/agent.h" #include "nice/agent.h"
#define NICE_MAX_SDP_STRING_LEN 4096
typedef void (*nice_cb_state_changed_t)(NiceAgent* agent, guint stream_id, typedef void (*nice_cb_state_changed_t)(NiceAgent* agent, guint stream_id,
guint component_id, guint component_id,
NiceComponentState state, NiceComponentState state,
@@ -35,7 +33,7 @@ class IceAgent {
nice_cb_gathering_done_t on_gathering_done, nice_cb_gathering_done_t on_gathering_done,
nice_cb_recv_t on_recv, void* user_ptr); nice_cb_recv_t on_recv, void* user_ptr);
int DestoryIceAgent(); int DestroyIceAgent();
char* GenerateLocalSdp(); char* GenerateLocalSdp();
@@ -49,8 +47,6 @@ class IceAgent {
int Send(const char* data, size_t size); int Send(const char* data, size_t size);
static void* CreateNiceAgent(void* data);
public: public:
std::string stun_ip_ = ""; std::string stun_ip_ = "";
uint16_t stun_port_ = 0; uint16_t stun_port_ = 0;
@@ -59,16 +55,17 @@ class IceAgent {
std::string turn_username_ = ""; std::string turn_username_ = "";
std::string turn_password_ = ""; std::string turn_password_ = "";
std::unique_ptr<std::thread> g_thread_; std::unique_ptr<std::thread> nice_thread_;
NiceAgent* agent_ = nullptr; std::atomic<NiceAgent*> agent_ = nullptr;
GMainLoop* gloop_; std::atomic<GMainLoop*> gloop_ = nullptr;
GThread* gexamplethread_; std::atomic<bool> nice_inited_ = false;
gboolean exit_thread_;
gboolean exit_nice_thread_ = false;
bool controlling_ = false; bool controlling_ = false;
uint32_t stream_id_ = 0; uint32_t stream_id_ = 0;
// char local_sdp_[NICE_MAX_SDP_STRING_LEN];
char* local_sdp_ = nullptr; char* local_sdp_ = nullptr;
NiceComponentState state_; NiceComponentState state_ = NiceComponentState::NICE_COMPONENT_STATE_LAST;
bool destroyed_ = false;
nice_cb_state_changed_t on_state_changed_; nice_cb_state_changed_t on_state_changed_;
nice_cb_candidate_t on_candidate_; nice_cb_candidate_t on_candidate_;

View File

@@ -175,7 +175,7 @@ int IceTransmission::InitIceTransmission(std::string &stun_ip, int stun_port,
int IceTransmission::DestroyIceTransmission() { int IceTransmission::DestroyIceTransmission() {
LOG_INFO("[{}->{}] Destroy ice transmission", user_id_, remote_user_id_); LOG_INFO("[{}->{}] Destroy ice transmission", user_id_, remote_user_id_);
return ice_agent_->DestoryIceAgent(); return ice_agent_->DestroyIceAgent();
} }
int IceTransmission::SetTransmissionId(const std::string &transmission_id) { int IceTransmission::SetTransmissionId(const std::string &transmission_id) {