mirror of
https://github.com/kunkundi/crossdesk.git
synced 2025-10-26 20:25:34 +08:00
[feat] Implementation for trickle ice
This commit is contained in:
@@ -24,12 +24,15 @@ IceAgent::~IceAgent() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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_new_candidate_t on_new_candidate,
|
||||||
nice_cb_gathering_done_t on_gathering_done,
|
nice_cb_gathering_done_t on_gathering_done,
|
||||||
|
nice_cb_new_selected_pair_t on_new_selected_pair,
|
||||||
nice_cb_recv_t on_recv, void *user_ptr) {
|
nice_cb_recv_t on_recv, void *user_ptr) {
|
||||||
destroyed_ = false;
|
destroyed_ = false;
|
||||||
on_state_changed_ = on_state_changed;
|
on_state_changed_ = on_state_changed;
|
||||||
on_candidate_ = on_candidate;
|
on_new_selected_pair_ = on_new_selected_pair;
|
||||||
|
on_new_candidate_ = on_new_candidate;
|
||||||
|
|
||||||
on_gathering_done_ = on_gathering_done;
|
on_gathering_done_ = on_gathering_done;
|
||||||
on_recv_ = on_recv;
|
on_recv_ = on_recv;
|
||||||
user_ptr_ = user_ptr;
|
user_ptr_ = user_ptr;
|
||||||
@@ -41,9 +44,9 @@ int IceAgent::CreateIceAgent(nice_cb_state_changed_t on_state_changed,
|
|||||||
nice_thread_.reset(new std::thread([this]() {
|
nice_thread_.reset(new std::thread([this]() {
|
||||||
gloop_ = g_main_loop_new(nullptr, false);
|
gloop_ = g_main_loop_new(nullptr, false);
|
||||||
|
|
||||||
agent_ = nice_agent_new_full(g_main_loop_get_context(gloop_),
|
agent_ = nice_agent_new_full(
|
||||||
NICE_COMPATIBILITY_RFC5245,
|
g_main_loop_get_context(gloop_), NICE_COMPATIBILITY_RFC5245,
|
||||||
(NiceAgentOption)(NICE_AGENT_OPTION_RELIABLE));
|
(NiceAgentOption)(NICE_AGENT_OPTION_ICE_TRICKLE));
|
||||||
|
|
||||||
if (agent_ == nullptr) {
|
if (agent_ == nullptr) {
|
||||||
LOG_ERROR("Failed to create agent_");
|
LOG_ERROR("Failed to create agent_");
|
||||||
@@ -51,30 +54,37 @@ int IceAgent::CreateIceAgent(nice_cb_state_changed_t on_state_changed,
|
|||||||
|
|
||||||
g_object_set(agent_, "stun-server", stun_ip_.c_str(), nullptr);
|
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_, "stun-server-port", stun_port_, nullptr);
|
||||||
|
|
||||||
g_object_set(agent_, "controlling-mode", controlling_, nullptr);
|
g_object_set(agent_, "controlling-mode", controlling_, nullptr);
|
||||||
|
// g_object_set(agent_, "ice-trickle", true, nullptr);
|
||||||
|
|
||||||
g_signal_connect(agent_, "candidate-gathering-done",
|
g_signal_connect(agent_, "candidate-gathering-done",
|
||||||
G_CALLBACK(on_gathering_done_), user_ptr_);
|
G_CALLBACK(on_gathering_done_), user_ptr_);
|
||||||
g_signal_connect(agent_, "new-selected-pair", G_CALLBACK(on_candidate_),
|
g_signal_connect(agent_, "new-selected-pair",
|
||||||
|
G_CALLBACK(on_new_selected_pair_), user_ptr_);
|
||||||
|
g_signal_connect(agent_, "new-candidate", G_CALLBACK(on_new_candidate_),
|
||||||
user_ptr_);
|
user_ptr_);
|
||||||
g_signal_connect(agent_, "component-state-changed",
|
g_signal_connect(agent_, "component-state-changed",
|
||||||
G_CALLBACK(on_state_changed_), user_ptr_);
|
G_CALLBACK(on_state_changed_), user_ptr_);
|
||||||
|
|
||||||
stream_id_ = nice_agent_add_stream(agent_, 1);
|
stream_id_ = nice_agent_add_stream(agent_, n_components_);
|
||||||
if (stream_id_ == 0) {
|
if (stream_id_ == 0) {
|
||||||
LOG_ERROR("Failed to add stream");
|
LOG_ERROR("Failed to add stream");
|
||||||
}
|
}
|
||||||
|
|
||||||
nice_agent_set_stream_name(agent_, stream_id_, "video");
|
nice_agent_set_stream_name(agent_, stream_id_, "video");
|
||||||
|
|
||||||
nice_agent_set_relay_info(agent_, stream_id_, 1, turn_ip_.c_str(),
|
nice_agent_set_relay_info(agent_, stream_id_, n_components_,
|
||||||
turn_port_, turn_username_.c_str(),
|
turn_ip_.c_str(), turn_port_,
|
||||||
turn_password_.c_str(), NICE_RELAY_TYPE_TURN_UDP);
|
turn_username_.c_str(), turn_password_.c_str(),
|
||||||
|
NICE_RELAY_TYPE_TURN_UDP);
|
||||||
|
|
||||||
// g_object_set(agent_, "force-relay", true, NULL);
|
// g_object_set(agent_, "ice-tcp", false, "ice-udp", true, "force-relay",
|
||||||
|
// true,
|
||||||
|
// NULL);
|
||||||
|
|
||||||
nice_agent_attach_recv(agent_, stream_id_, 1,
|
// nice_agent_set_remote_credentials(agent_, stream_id_, ufrag, password);
|
||||||
|
|
||||||
|
nice_agent_attach_recv(agent_, stream_id_, NICE_COMPONENT_TYPE_RTP,
|
||||||
g_main_loop_get_context(gloop_), on_recv_,
|
g_main_loop_get_context(gloop_), on_recv_,
|
||||||
user_ptr_);
|
user_ptr_);
|
||||||
|
|
||||||
@@ -120,6 +130,32 @@ int IceAgent::DestroyIceAgent() {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int IceAgent::GetLocalCredentials() {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
nice_agent_get_local_credentials(agent_, stream_id_, &ice_ufrag_,
|
||||||
|
&ice_password_);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *IceAgent::GetLocalUfrag() { return ufrag_; }
|
||||||
|
|
||||||
|
char *IceAgent::GetLocalPassword() { return password_; }
|
||||||
|
|
||||||
char *IceAgent::GenerateLocalSdp() {
|
char *IceAgent::GenerateLocalSdp() {
|
||||||
if (!nice_inited_) {
|
if (!nice_inited_) {
|
||||||
LOG_ERROR("Nice agent has not been initialized");
|
LOG_ERROR("Nice agent has not been initialized");
|
||||||
@@ -162,11 +198,38 @@ int IceAgent::SetRemoteSdp(const char *remote_sdp) {
|
|||||||
if (ret > 0) {
|
if (ret > 0) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
LOG_ERROR("Failed to parse remote data");
|
LOG_ERROR("Failed to parse remote data: [{}]", remote_sdp);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int IceAgent::AddCandidate(const char *candidate) {
|
||||||
|
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_, candidate);
|
||||||
|
if (ret > 0) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
LOG_ERROR("Failed to parse remote candidate: [{}]", candidate);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int IceAgent::GatherCandidates() {
|
int IceAgent::GatherCandidates() {
|
||||||
if (!nice_inited_) {
|
if (!nice_inited_) {
|
||||||
LOG_ERROR("Nice agent has not been initialized");
|
LOG_ERROR("Nice agent has not been initialized");
|
||||||
|
|||||||
@@ -13,8 +13,13 @@ typedef void (*nice_cb_state_changed_t)(NiceAgent* agent, guint stream_id,
|
|||||||
guint component_id,
|
guint component_id,
|
||||||
NiceComponentState state,
|
NiceComponentState state,
|
||||||
gpointer data);
|
gpointer data);
|
||||||
typedef void (*nice_cb_candidate_t)(NiceAgent* agent, guint stream_id,
|
typedef void (*nice_cb_new_candidate_t)(NiceAgent* agent, guint stream_id,
|
||||||
guint component_id, const char* sdp,
|
guint component_id, gchar* foundation,
|
||||||
|
gpointer data);
|
||||||
|
typedef void (*nice_cb_new_selected_pair_t)(NiceAgent* agent, guint stream_id,
|
||||||
|
guint component_id,
|
||||||
|
const char* lfoundation,
|
||||||
|
const char* rfoundation,
|
||||||
gpointer data);
|
gpointer data);
|
||||||
typedef void (*nice_cb_gathering_done_t)(NiceAgent* agent, guint stream_id,
|
typedef void (*nice_cb_gathering_done_t)(NiceAgent* agent, guint stream_id,
|
||||||
gpointer data);
|
gpointer data);
|
||||||
@@ -30,16 +35,25 @@ class IceAgent {
|
|||||||
~IceAgent();
|
~IceAgent();
|
||||||
|
|
||||||
int CreateIceAgent(nice_cb_state_changed_t on_state_changed,
|
int CreateIceAgent(nice_cb_state_changed_t on_state_changed,
|
||||||
nice_cb_candidate_t on_candidate,
|
nice_cb_new_candidate_t on_new_candidate,
|
||||||
nice_cb_gathering_done_t on_gathering_done,
|
nice_cb_gathering_done_t on_gathering_done,
|
||||||
|
nice_cb_new_selected_pair_t on_new_selected_pair,
|
||||||
nice_cb_recv_t on_recv, void* user_ptr);
|
nice_cb_recv_t on_recv, void* user_ptr);
|
||||||
|
|
||||||
int DestroyIceAgent();
|
int DestroyIceAgent();
|
||||||
|
|
||||||
|
int GetLocalCredentials();
|
||||||
|
|
||||||
|
char* GetLocalIceUfrag();
|
||||||
|
|
||||||
|
char* GetLocalIcePassword();
|
||||||
|
|
||||||
char* GenerateLocalSdp();
|
char* GenerateLocalSdp();
|
||||||
|
|
||||||
int SetRemoteSdp(const char* remote_sdp);
|
int SetRemoteSdp(const char* remote_sdp);
|
||||||
|
|
||||||
|
int AddCandidate(const char* candidate);
|
||||||
|
|
||||||
int GatherCandidates();
|
int GatherCandidates();
|
||||||
|
|
||||||
NiceComponentState GetIceState();
|
NiceComponentState GetIceState();
|
||||||
@@ -63,14 +77,18 @@ class IceAgent {
|
|||||||
|
|
||||||
gboolean exit_nice_thread_ = false;
|
gboolean exit_nice_thread_ = false;
|
||||||
bool controlling_ = false;
|
bool controlling_ = false;
|
||||||
|
gchar* ice_ufrag_ = nullptr;
|
||||||
|
gchar* ice_password_ = nullptr;
|
||||||
uint32_t stream_id_ = 0;
|
uint32_t stream_id_ = 0;
|
||||||
|
uint32_t n_components_ = 1;
|
||||||
char* local_sdp_ = nullptr;
|
char* local_sdp_ = nullptr;
|
||||||
NiceComponentState state_ = NiceComponentState::NICE_COMPONENT_STATE_LAST;
|
NiceComponentState state_ = NiceComponentState::NICE_COMPONENT_STATE_LAST;
|
||||||
bool destroyed_ = false;
|
bool destroyed_ = false;
|
||||||
gboolean agent_closed_ = false;
|
gboolean agent_closed_ = 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_new_selected_pair_t on_new_selected_pair_;
|
||||||
|
nice_cb_new_candidate_t on_new_candidate_;
|
||||||
nice_cb_gathering_done_t on_gathering_done_;
|
nice_cb_gathering_done_t on_gathering_done_;
|
||||||
nice_cb_recv_t on_recv_;
|
nice_cb_recv_t on_recv_;
|
||||||
void* user_ptr_;
|
void* user_ptr_;
|
||||||
|
|||||||
@@ -525,6 +525,25 @@ void PeerConnection::ProcessSignal(const std::string &signal) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case "offer_candidate"_H: {
|
||||||
|
std::string transmission_id = j["transmission_id"].get<std::string>();
|
||||||
|
std::string new_candidate = j["sdp"].get<std::string>();
|
||||||
|
std::string remote_user_id = j["remote_user_id"].get<std::string>();
|
||||||
|
|
||||||
|
LOG_INFO("[{}] receive new candidate from [{}]", user_id_,
|
||||||
|
remote_user_id);
|
||||||
|
|
||||||
|
if (ice_transmission_list_.find(remote_user_id) !=
|
||||||
|
ice_transmission_list_.end()) {
|
||||||
|
ice_transmission_list_[remote_user_id]->AddCandidate(new_candidate);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "answer_candidate"_H: {
|
||||||
|
std::string transmission_id = j["transmission_id"].get<std::string>();
|
||||||
|
std::string new_candidate = j["sdp"].get<std::string>();
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -167,24 +167,59 @@ int IceTransmission::InitIceTransmission(
|
|||||||
LOG_INFO("state_change: {}", nice_component_state_to_string(state));
|
LOG_INFO("state_change: {}", nice_component_state_to_string(state));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[](NiceAgent *agent, guint stream_id, guint component_id, const char *sdp,
|
[](NiceAgent *agent, guint stream_id, guint component_id,
|
||||||
gpointer user_ptr) { LOG_INFO("candadite: {}", sdp); },
|
gchar *foundation, gpointer user_ptr) {
|
||||||
[](NiceAgent *agent, guint stream_id, gpointer user_ptr) {
|
|
||||||
// non-trickle
|
|
||||||
if (user_ptr) {
|
if (user_ptr) {
|
||||||
IceTransmission *ice_transmission_obj =
|
IceTransmission *ice_transmission_obj =
|
||||||
static_cast<IceTransmission *>(user_ptr);
|
static_cast<IceTransmission *>(user_ptr);
|
||||||
LOG_INFO("[{}] gather_done", ice_transmission_obj->user_id_);
|
|
||||||
|
|
||||||
if (ice_transmission_obj->offer_peer_) {
|
GSList *cands =
|
||||||
ice_transmission_obj->GetLocalSdp();
|
nice_agent_get_local_candidates(agent, stream_id, component_id);
|
||||||
ice_transmission_obj->SendOffer();
|
NiceCandidate *cand;
|
||||||
|
for (GSList *i = cands; i; i = i->next) {
|
||||||
|
cand = (NiceCandidate *)i->data;
|
||||||
|
if (g_strcmp0(cand->foundation, foundation) == 0) {
|
||||||
|
ice_transmission_obj->new_local_candidate_ =
|
||||||
|
nice_agent_generate_local_sdp(agent);
|
||||||
|
|
||||||
} else {
|
json message = {
|
||||||
ice_transmission_obj->CreateAnswer();
|
{"type", "offer_candidate"},
|
||||||
ice_transmission_obj->SendAnswer();
|
{"transmission_id", ice_transmission_obj->transmission_id_},
|
||||||
|
{"user_id", ice_transmission_obj->user_id_},
|
||||||
|
{"remote_user_id", ice_transmission_obj->remote_user_id_},
|
||||||
|
{"sdp", ice_transmission_obj->new_local_candidate_}};
|
||||||
|
LOG_INFO("Send new local candidate sdp:[{}]",
|
||||||
|
ice_transmission_obj->new_local_candidate_);
|
||||||
|
|
||||||
|
if (ice_transmission_obj->ice_ws_transport_) {
|
||||||
|
ice_transmission_obj->ice_ws_transport_->Send(message.dump());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_slist_free_full(cands, (GDestroyNotify)nice_candidate_free);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[](NiceAgent *agent, guint stream_id, gpointer user_ptr) {
|
||||||
|
// non-trickle
|
||||||
|
// if (user_ptr) {
|
||||||
|
// IceTransmission *ice_transmission_obj =
|
||||||
|
// static_cast<IceTransmission *>(user_ptr);
|
||||||
|
// LOG_INFO("[{}] gather_done", ice_transmission_obj->user_id_);
|
||||||
|
|
||||||
|
// if (ice_transmission_obj->offer_peer_) {
|
||||||
|
// ice_transmission_obj->GetLocalSdp();
|
||||||
|
// ice_transmission_obj->SendOffer();
|
||||||
|
|
||||||
|
// } else {
|
||||||
|
// ice_transmission_obj->CreateAnswer();
|
||||||
|
// ice_transmission_obj->SendAnswer();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
},
|
||||||
|
[](NiceAgent *agent, guint stream_id, guint component_id,
|
||||||
|
const char *lfoundation, const char *rfoundation, gpointer user_ptr) {
|
||||||
|
LOG_INFO("new selected pair: [{}] [{}]", lfoundation, rfoundation);
|
||||||
},
|
},
|
||||||
[](NiceAgent *agent, guint stream_id, guint component_id, guint size,
|
[](NiceAgent *agent, guint stream_id, guint component_id, guint size,
|
||||||
gchar *buffer, gpointer user_ptr) {
|
gchar *buffer, gpointer user_ptr) {
|
||||||
@@ -257,9 +292,37 @@ int IceTransmission::SetRemoteSdp(const std::string &remote_sdp) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int IceTransmission::AddCandidate(const std::string &candidate) {
|
||||||
|
ice_agent_->AddCandidate(candidate.c_str());
|
||||||
|
LOG_INFO("[{}] add candidate", user_id_);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int IceTransmission::CreateOffer() {
|
int IceTransmission::CreateOffer() {
|
||||||
LOG_INFO("[{}] create offer", user_id_);
|
LOG_INFO("[{}] create offer", user_id_);
|
||||||
GatherCandidates();
|
GatherCandidates();
|
||||||
|
|
||||||
|
if (trickle_ice_) {
|
||||||
|
SendLocalCredentials();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int IceTransmission::SendLocalCredentials() {
|
||||||
|
ice_agent_->GetLocalIceUfrag();
|
||||||
|
ice_agent_->GetLocalIcePassword();
|
||||||
|
|
||||||
|
json message = {{"type", "credentials"},
|
||||||
|
{"transmission_id", transmission_id_},
|
||||||
|
{"user_id", user_id_},
|
||||||
|
{"remote_user_id", remote_user_id_},
|
||||||
|
{"ufrag", ice_agent_->GetLocalIceUfrag()},
|
||||||
|
{"password", ice_agent_->GetLocalIcePassword()}};
|
||||||
|
LOG_INFO("Send credentials:\n{}", message.dump());
|
||||||
|
|
||||||
|
if (ice_ws_transport_) {
|
||||||
|
ice_ws_transport_->Send(message.dump());
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -80,10 +80,14 @@ class IceTransmission {
|
|||||||
public:
|
public:
|
||||||
int GatherCandidates();
|
int GatherCandidates();
|
||||||
|
|
||||||
|
int SendLocalCredentials();
|
||||||
|
|
||||||
int GetLocalSdp();
|
int GetLocalSdp();
|
||||||
|
|
||||||
int SetRemoteSdp(const std::string &remote_sdp);
|
int SetRemoteSdp(const std::string &remote_sdp);
|
||||||
|
|
||||||
|
int AddCandidate(const std::string &candidate);
|
||||||
|
|
||||||
int CreateOffer();
|
int CreateOffer();
|
||||||
|
|
||||||
int SendOffer();
|
int SendOffer();
|
||||||
@@ -99,8 +103,10 @@ class IceTransmission {
|
|||||||
uint8_t CheckIsDataPacket(const char *buffer, size_t size);
|
uint8_t CheckIsDataPacket(const char *buffer, size_t size);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool trickle_ice_ = true;
|
||||||
std::string local_sdp_;
|
std::string local_sdp_;
|
||||||
std::string remote_sdp_;
|
std::string remote_sdp_;
|
||||||
|
std::string new_local_candidate_;
|
||||||
std::string local_candidates_;
|
std::string local_candidates_;
|
||||||
std::string remote_candidates_;
|
std::string remote_candidates_;
|
||||||
unsigned int connection_id_ = 0;
|
unsigned int connection_id_ = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user