diff --git a/src/ice/ice_agent.cpp b/src/ice/ice_agent.cpp index 0d366a5..147f484 100644 --- a/src/ice/ice_agent.cpp +++ b/src/ice/ice_agent.cpp @@ -5,10 +5,11 @@ #include "log.h" -IceAgent::IceAgent(bool offer_peer, std::string &stun_ip, uint16_t stun_port, - std::string &turn_ip, uint16_t turn_port, +IceAgent::IceAgent(bool trickle_ice, bool offer_peer, std::string &stun_ip, + uint16_t stun_port, std::string &turn_ip, uint16_t turn_port, std::string &turn_username, std::string &turn_password) - : stun_ip_(stun_ip), + : trickle_ice_(trickle_ice), + stun_ip_(stun_ip), stun_port_(stun_port), turn_ip_(turn_ip), turn_port_(turn_port), @@ -21,6 +22,9 @@ IceAgent::~IceAgent() { DestroyIceAgent(); } g_object_unref(agent_); + g_free(ice_ufrag_); + g_free(ice_password_); + g_free(stream_sdp_); } int IceAgent::CreateIceAgent(nice_cb_state_changed_t on_state_changed, @@ -46,7 +50,9 @@ int IceAgent::CreateIceAgent(nice_cb_state_changed_t on_state_changed, agent_ = nice_agent_new_full( g_main_loop_get_context(gloop_), NICE_COMPATIBILITY_RFC5245, - (NiceAgentOption)(NICE_AGENT_OPTION_ICE_TRICKLE)); + (NiceAgentOption)(trickle_ice_ ? NICE_AGENT_OPTION_ICE_TRICKLE | + NICE_AGENT_OPTION_RELIABLE + : NICE_AGENT_OPTION_RELIABLE)); if (agent_ == nullptr) { LOG_ERROR("Failed to create agent_"); @@ -55,7 +61,6 @@ 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-port", stun_port_, 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_CALLBACK(on_gathering_done_), user_ptr_); @@ -82,8 +87,6 @@ int IceAgent::CreateIceAgent(nice_cb_state_changed_t on_state_changed, // true, // NULL); - // 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_, user_ptr_); @@ -130,32 +133,11 @@ int IceAgent::DestroyIceAgent() { 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::GetLocalStreamSdp() { + stream_sdp_ = nice_agent_generate_local_stream_sdp(agent_, stream_id_, true); + return stream_sdp_; } -char *IceAgent::GetLocalUfrag() { return ufrag_; } - -char *IceAgent::GetLocalPassword() { return password_; } - char *IceAgent::GenerateLocalSdp() { if (!nice_inited_) { LOG_ERROR("Nice agent has not been initialized"); @@ -195,41 +177,14 @@ int IceAgent::SetRemoteSdp(const char *remote_sdp) { } int ret = nice_agent_parse_remote_sdp(agent_, remote_sdp); - if (ret > 0) { + if (ret >= 0) { return 0; } else { - LOG_ERROR("Failed to parse remote data: [{}]", remote_sdp); + LOG_ERROR("Failed to parse remote sdp: [{}]", remote_sdp); 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() { if (!nice_inited_) { LOG_ERROR("Nice agent has not been initialized"); diff --git a/src/ice/ice_agent.h b/src/ice/ice_agent.h index 24ecda0..37b7af0 100644 --- a/src/ice/ice_agent.h +++ b/src/ice/ice_agent.h @@ -29,9 +29,9 @@ typedef void (*nice_cb_recv_t)(NiceAgent* agent, guint stream_id, class IceAgent { public: - IceAgent(bool offer_peer, std::string& stun_ip, uint16_t stun_port, - std::string& turn_ip, uint16_t turn_port, std::string& turn_username, - std::string& turn_password); + IceAgent(bool trickle_ice, bool offer_peer, std::string& stun_ip, + uint16_t stun_port, std::string& turn_ip, uint16_t turn_port, + std::string& turn_username, std::string& turn_password); ~IceAgent(); int CreateIceAgent(nice_cb_state_changed_t on_state_changed, @@ -42,18 +42,12 @@ class IceAgent { int DestroyIceAgent(); - int GetLocalCredentials(); - - char* GetLocalIceUfrag(); - - char* GetLocalIcePassword(); + char* GetLocalStreamSdp(); char* GenerateLocalSdp(); int SetRemoteSdp(const char* remote_sdp); - int AddCandidate(const char* candidate); - int GatherCandidates(); NiceComponentState GetIceState(); @@ -76,9 +70,11 @@ class IceAgent { std::atomic nice_inited_{false}; gboolean exit_nice_thread_ = false; + bool trickle_ice_ = true; bool controlling_ = false; gchar* ice_ufrag_ = nullptr; gchar* ice_password_ = nullptr; + gchar* stream_sdp_ = nullptr; uint32_t stream_id_ = 0; uint32_t n_components_ = 1; char* local_sdp_ = nullptr; diff --git a/src/pc/peer_connection.cpp b/src/pc/peer_connection.cpp index cfcbdf5..486b46b 100644 --- a/src/pc/peer_connection.cpp +++ b/src/pc/peer_connection.cpp @@ -361,7 +361,7 @@ int PeerConnection::Leave() { void PeerConnection::ProcessSignal(const std::string &signal) { auto j = json::parse(signal); std::string type = j["type"]; - LOG_INFO("signal type: {}", type); + // LOG_INFO("signal type: {}", type); switch (HASH_STRING_PIECE(type.c_str())) { case "ws_connection_id"_H: { ws_connection_id_ = j["ws_connection_id"].get(); @@ -425,9 +425,9 @@ void PeerConnection::ProcessSignal(const std::string &signal) { // continue; // } ice_transmission_list_[remote_user_id] = - std::make_unique(true, transmission_id, user_id_, - remote_user_id, ws_transport_, - on_ice_status_change_); + std::make_unique( + trickle_ice_, true, transmission_id, user_id_, remote_user_id, + ws_transport_, on_ice_status_change_); ice_transmission_list_[remote_user_id]->SetOnReceiveVideoFunc( on_receive_video_); @@ -463,87 +463,87 @@ void PeerConnection::ProcessSignal(const std::string &signal) { break; } case "offer"_H: { - std::string remote_sdp = j["sdp"].get(); + std::string transmission_id = j["transmission_id"].get(); + std::string remote_user_id = j["remote_user_id"].get(); + LOG_INFO("[{}] receive offer from [{}]", user_id_, remote_user_id); - if (remote_sdp.empty()) { - LOG_INFO("Invalid remote sdp"); - } else { - std::string transmission_id = j["transmission_id"].get(); - std::string sdp = j["sdp"].get(); - std::string remote_user_id = j["remote_user_id"].get(); - LOG_INFO("[{}] receive offer from [{}]", user_id_, remote_user_id); - - if (0 != CreateVideoCodec(hardware_acceleration_)) { - LOG_ERROR("Create video codec failed"); - } - - if (0 != CreateAudioCodec()) { - LOG_ERROR("Create audio codec failed"); - } - - ice_transmission_list_[remote_user_id] = - std::make_unique(false, transmission_id, user_id_, - remote_user_id, ws_transport_, - on_ice_status_change_); - - ice_transmission_list_[remote_user_id]->SetOnReceiveVideoFunc( - on_receive_video_); - ice_transmission_list_[remote_user_id]->SetOnReceiveAudioFunc( - on_receive_audio_); - ice_transmission_list_[remote_user_id]->SetOnReceiveDataFunc( - on_receive_data_); - ice_transmission_list_[remote_user_id]->InitIceTransmission( - cfg_stun_server_ip_, stun_server_port_, cfg_turn_server_ip_, - turn_server_port_, cfg_turn_server_username_, - cfg_turn_server_password_, - av1_encoding_ ? RtpPacket::AV1 : RtpPacket::H264); - ice_transmission_list_[remote_user_id]->SetTransmissionId( - transmission_id_); - ice_transmission_list_[remote_user_id]->SetRemoteSdp(remote_sdp); - ice_transmission_list_[remote_user_id]->GatherCandidates(); - on_connection_status_(ConnectionStatus::Connecting, user_data_); + if (0 != CreateVideoCodec(hardware_acceleration_)) { + LOG_ERROR("Create video codec failed"); } + + if (0 != CreateAudioCodec()) { + LOG_ERROR("Create audio codec failed"); + } + + ice_transmission_list_[remote_user_id] = + std::make_unique( + trickle_ice_, false, transmission_id, user_id_, remote_user_id, + ws_transport_, on_ice_status_change_); + + ice_transmission_list_[remote_user_id]->SetOnReceiveVideoFunc( + on_receive_video_); + ice_transmission_list_[remote_user_id]->SetOnReceiveAudioFunc( + on_receive_audio_); + ice_transmission_list_[remote_user_id]->SetOnReceiveDataFunc( + on_receive_data_); + ice_transmission_list_[remote_user_id]->InitIceTransmission( + cfg_stun_server_ip_, stun_server_port_, cfg_turn_server_ip_, + turn_server_port_, cfg_turn_server_username_, + cfg_turn_server_password_, + av1_encoding_ ? RtpPacket::AV1 : RtpPacket::H264); + ice_transmission_list_[remote_user_id]->SetTransmissionId( + transmission_id_); + + if (j.contains("sdp")) { + on_connection_status_(ConnectionStatus::Connecting, user_data_); + std::string remote_sdp = j["sdp"].get(); + ice_transmission_list_[remote_user_id]->SetRemoteSdp(remote_sdp); + if (trickle_ice_) { + sdp_without_cands_ = remote_sdp; + ice_transmission_list_[remote_user_id]->SendAnswer(); + } + ice_transmission_list_[remote_user_id]->GatherCandidates(); + } else { + LOG_ERROR("Invalid offer msg"); + } + break; } case "answer"_H: { - std::string remote_sdp = j["sdp"].get(); - if (remote_sdp.empty()) { - LOG_INFO("remote_sdp is empty"); - } else { - std::string transmission_id = j["transmission_id"].get(); - std::string sdp = j["sdp"].get(); - std::string remote_user_id = j["remote_user_id"].get(); - - LOG_INFO("[{}] receive answer from [{}]", user_id_, remote_user_id); - + on_connection_status_(ConnectionStatus::Connecting, user_data_); + std::string transmission_id = j["transmission_id"].get(); + std::string remote_user_id = j["remote_user_id"].get(); + if (j.contains("sdp")) { + std::string remote_sdp = j["sdp"].get(); if (ice_transmission_list_.find(remote_user_id) != ice_transmission_list_.end()) { ice_transmission_list_[remote_user_id]->SetRemoteSdp(remote_sdp); + if (trickle_ice_) { + sdp_without_cands_ = remote_sdp; + ice_transmission_list_[remote_user_id]->GatherCandidates(); + } } - - on_connection_status_(ConnectionStatus::Connecting, user_data_); + } else { + LOG_ERROR("Invalid answer msg"); } + break; } - case "offer_candidate"_H: { + case "new_candidate"_H: { std::string transmission_id = j["transmission_id"].get(); std::string new_candidate = j["sdp"].get(); std::string remote_user_id = j["remote_user_id"].get(); - LOG_INFO("[{}] receive new candidate from [{}]", user_id_, - remote_user_id); + // LOG_INFO("[{}] receive new candidate from [{}]:[{}]", user_id_, + // remote_user_id, new_candidate); if (ice_transmission_list_.find(remote_user_id) != ice_transmission_list_.end()) { - ice_transmission_list_[remote_user_id]->AddCandidate(new_candidate); + ice_transmission_list_[remote_user_id]->SetRemoteSdp( + sdp_without_cands_ + new_candidate); } break; } - case "answer_candidate"_H: { - std::string transmission_id = j["transmission_id"].get(); - std::string new_candidate = j["sdp"].get(); - break; - } default: { break; } diff --git a/src/pc/peer_connection.h b/src/pc/peer_connection.h index 3979c9c..3e32eb8 100644 --- a/src/pc/peer_connection.h +++ b/src/pc/peer_connection.h @@ -97,6 +97,7 @@ class PeerConnection { int turn_server_port_ = 0; bool hardware_acceleration_ = false; bool av1_encoding_ = false; + bool trickle_ice_ = true; private: std::shared_ptr ws_transport_ = nullptr; @@ -109,6 +110,7 @@ class PeerConnection { SignalStatus signal_status_ = SignalStatus::SignalClosed; std::mutex signal_status_mutex_; std::atomic leave_{false}; + std::string sdp_without_cands_ = ""; private: std::map> diff --git a/src/transmission/ice_transmission.cpp b/src/transmission/ice_transmission.cpp index d39dc75..634ed94 100644 --- a/src/transmission/ice_transmission.cpp +++ b/src/transmission/ice_transmission.cpp @@ -12,11 +12,12 @@ using nlohmann::json; IceTransmission::IceTransmission( - bool offer_peer, std::string &transmission_id, std::string &user_id, - std::string &remote_user_id, + bool trickle_ice, bool offer_peer, std::string &transmission_id, + std::string &user_id, std::string &remote_user_id, std::shared_ptr ice_ws_transmission, std::function on_ice_status_change) - : offer_peer_(offer_peer), + : trickle_ice_(trickle_ice), + offer_peer_(offer_peer), transmission_id_(transmission_id), user_id_(user_id), remote_user_id_(remote_user_id), @@ -147,9 +148,9 @@ int IceTransmission::InitIceTransmission( remote_user_id_.size()); }); - ice_agent_ = - std::make_unique(offer_peer_, stun_ip, stun_port, turn_ip, - turn_port, turn_username, turn_password); + ice_agent_ = std::make_unique(trickle_ice_, offer_peer_, stun_ip, + stun_port, turn_ip, turn_port, + turn_username, turn_password); ice_agent_->CreateIceAgent( [](NiceAgent *agent, guint stream_id, guint component_id, @@ -180,16 +181,18 @@ int IceTransmission::InitIceTransmission( cand = (NiceCandidate *)i->data; if (g_strcmp0(cand->foundation, foundation) == 0) { ice_transmission_obj->new_local_candidate_ = - nice_agent_generate_local_sdp(agent); + nice_agent_generate_local_candidate_sdp(agent, cand); json message = { - {"type", "offer_candidate"}, + {"type", "new_candidate"}, {"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_); + // LOG_INFO("[{}] Send new candidate to [{}]]:[{}]", + // ice_transmission_obj->user_id_, + // ice_transmission_obj->remote_user_id_, + // ice_transmission_obj->new_local_candidate_); if (ice_transmission_obj->ice_ws_transport_) { ice_transmission_obj->ice_ws_transport_->Send(message.dump()); @@ -202,20 +205,19 @@ int IceTransmission::InitIceTransmission( }, [](NiceAgent *agent, guint stream_id, gpointer user_ptr) { // non-trickle - // if (user_ptr) { - // IceTransmission *ice_transmission_obj = - // static_cast(user_ptr); - // LOG_INFO("[{}] gather_done", ice_transmission_obj->user_id_); + if (user_ptr) { + IceTransmission *ice_transmission_obj = + static_cast(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(); - // } - // } + if (!ice_transmission_obj->trickle_ice_) { + if (ice_transmission_obj->offer_peer_) { + ice_transmission_obj->SendOffer(); + } else { + ice_transmission_obj->SendAnswer(); + } + } + } }, [](NiceAgent *agent, guint stream_id, guint component_id, const char *lfoundation, const char *rfoundation, gpointer user_ptr) { @@ -265,23 +267,19 @@ int IceTransmission::SetTransmissionId(const std::string &transmission_id) { int IceTransmission::JoinTransmission() { LOG_INFO("[{}] Join transmission", user_id_); - CreateOffer(); + if (trickle_ice_) { + SendOffer(); + } else { + GatherCandidates(); + } return 0; } int IceTransmission::GatherCandidates() { int ret = ice_agent_->GatherCandidates(); - while (ret) { - LOG_ERROR("Gather candidates failed, retry"); - ret = ice_agent_->GatherCandidates(); + if (ret < 0) { + LOG_ERROR("Gather candidates failed"); } - LOG_INFO("[{}] Gather candidates", user_id_); - return 0; -} - -int IceTransmission::GetLocalSdp() { - local_sdp_ = ice_agent_->GenerateLocalSdp(); - LOG_INFO("[{}] generate local sdp", user_id_); return 0; } @@ -292,47 +290,14 @@ int IceTransmission::SetRemoteSdp(const std::string &remote_sdp) { 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() { - LOG_INFO("[{}] create offer", user_id_); - 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; -} - int IceTransmission::SendOffer() { json message = {{"type", "offer"}, {"transmission_id", transmission_id_}, {"user_id", user_id_}, {"remote_user_id", remote_user_id_}, - {"sdp", local_sdp_}}; - // LOG_INFO("Send offer:\n{}", message.dump()); + {"sdp", trickle_ice_ ? ice_agent_->GetLocalStreamSdp() + : ice_agent_->GenerateLocalSdp()}}; + // LOG_INFO("Send offer with sdp:[{}]", message.dump()); if (ice_ws_transport_) { ice_ws_transport_->Send(message.dump()); @@ -341,22 +306,19 @@ int IceTransmission::SendOffer() { return 0; } -int IceTransmission::CreateAnswer() { - GetLocalSdp(); - return 0; -} - int IceTransmission::SendAnswer() { json message = {{"type", "answer"}, {"transmission_id", transmission_id_}, - {"sdp", local_sdp_}, {"user_id", user_id_}, - {"remote_user_id", remote_user_id_}}; - + {"remote_user_id", remote_user_id_}, + {"sdp", trickle_ice_ ? ice_agent_->GetLocalStreamSdp() + : ice_agent_->GenerateLocalSdp()}}; + // LOG_INFO("Send answer with sdp:[{}]", message.dump()); if (ice_ws_transport_) { ice_ws_transport_->Send(message.dump()); LOG_INFO("[{}->{}] send answer", user_id_, remote_user_id_); } + return 0; } diff --git a/src/transmission/ice_transmission.h b/src/transmission/ice_transmission.h index ef777f2..c301101 100644 --- a/src/transmission/ice_transmission.h +++ b/src/transmission/ice_transmission.h @@ -32,8 +32,9 @@ class IceTransmission { }; public: - IceTransmission(bool offer_peer, std::string &transmission_id, - std::string &user_id, std::string &remote_user_id, + IceTransmission(bool trickle_ice, bool offer_peer, + std::string &transmission_id, std::string &user_id, + std::string &remote_user_id, std::shared_ptr ice_ws_transmission, std::function on_ice_status_change); ~IceTransmission(); @@ -80,20 +81,12 @@ class IceTransmission { public: int GatherCandidates(); - int SendLocalCredentials(); - - int GetLocalSdp(); + int SendLocalStreamSdp(); int SetRemoteSdp(const std::string &remote_sdp); - int AddCandidate(const std::string &candidate); - - int CreateOffer(); - int SendOffer(); - int CreateAnswer(); - int SendAnswer(); private: