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, | ||||
|                              nice_cb_candidate_t on_candidate, | ||||
|                              nice_cb_new_candidate_t on_new_candidate, | ||||
|                              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) { | ||||
|   destroyed_ = false; | ||||
|   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_recv_ = on_recv; | ||||
|   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]() { | ||||
|     gloop_ = g_main_loop_new(nullptr, false); | ||||
|  | ||||
|     agent_ = nice_agent_new_full(g_main_loop_get_context(gloop_), | ||||
|                                  NICE_COMPATIBILITY_RFC5245, | ||||
|                                  (NiceAgentOption)(NICE_AGENT_OPTION_RELIABLE)); | ||||
|     agent_ = nice_agent_new_full( | ||||
|         g_main_loop_get_context(gloop_), NICE_COMPATIBILITY_RFC5245, | ||||
|         (NiceAgentOption)(NICE_AGENT_OPTION_ICE_TRICKLE)); | ||||
|  | ||||
|     if (agent_ == nullptr) { | ||||
|       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-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_); | ||||
|     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_); | ||||
|     g_signal_connect(agent_, "component-state-changed", | ||||
|                      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) { | ||||
|       LOG_ERROR("Failed to add stream"); | ||||
|     } | ||||
|  | ||||
|     nice_agent_set_stream_name(agent_, stream_id_, "video"); | ||||
|  | ||||
|     nice_agent_set_relay_info(agent_, stream_id_, 1, turn_ip_.c_str(), | ||||
|                               turn_port_, turn_username_.c_str(), | ||||
|                               turn_password_.c_str(), NICE_RELAY_TYPE_TURN_UDP); | ||||
|     nice_agent_set_relay_info(agent_, stream_id_, n_components_, | ||||
|                               turn_ip_.c_str(), turn_port_, | ||||
|                               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_, | ||||
|                            user_ptr_); | ||||
|  | ||||
| @@ -120,6 +130,32 @@ 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::GetLocalUfrag() { return ufrag_; } | ||||
|  | ||||
| char *IceAgent::GetLocalPassword() { return password_; } | ||||
|  | ||||
| char *IceAgent::GenerateLocalSdp() { | ||||
|   if (!nice_inited_) { | ||||
|     LOG_ERROR("Nice agent has not been initialized"); | ||||
| @@ -162,11 +198,38 @@ int IceAgent::SetRemoteSdp(const char *remote_sdp) { | ||||
|   if (ret > 0) { | ||||
|     return 0; | ||||
|   } else { | ||||
|     LOG_ERROR("Failed to parse remote data"); | ||||
|     LOG_ERROR("Failed to parse remote data: [{}]", 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"); | ||||
|   | ||||
| @@ -13,8 +13,13 @@ typedef void (*nice_cb_state_changed_t)(NiceAgent* agent, guint stream_id, | ||||
|                                         guint component_id, | ||||
|                                         NiceComponentState state, | ||||
|                                         gpointer data); | ||||
| typedef void (*nice_cb_candidate_t)(NiceAgent* agent, guint stream_id, | ||||
|                                     guint component_id, const char* sdp, | ||||
| typedef void (*nice_cb_new_candidate_t)(NiceAgent* agent, guint stream_id, | ||||
|                                         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); | ||||
| typedef void (*nice_cb_gathering_done_t)(NiceAgent* agent, guint stream_id, | ||||
|                                          gpointer data); | ||||
| @@ -30,16 +35,25 @@ class IceAgent { | ||||
|   ~IceAgent(); | ||||
|  | ||||
|   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_new_selected_pair_t on_new_selected_pair, | ||||
|                      nice_cb_recv_t on_recv, void* user_ptr); | ||||
|  | ||||
|   int DestroyIceAgent(); | ||||
|  | ||||
|   int GetLocalCredentials(); | ||||
|  | ||||
|   char* GetLocalIceUfrag(); | ||||
|  | ||||
|   char* GetLocalIcePassword(); | ||||
|  | ||||
|   char* GenerateLocalSdp(); | ||||
|  | ||||
|   int SetRemoteSdp(const char* remote_sdp); | ||||
|  | ||||
|   int AddCandidate(const char* candidate); | ||||
|  | ||||
|   int GatherCandidates(); | ||||
|  | ||||
|   NiceComponentState GetIceState(); | ||||
| @@ -63,14 +77,18 @@ class IceAgent { | ||||
|  | ||||
|   gboolean exit_nice_thread_ = false; | ||||
|   bool controlling_ = false; | ||||
|   gchar* ice_ufrag_ = nullptr; | ||||
|   gchar* ice_password_ = nullptr; | ||||
|   uint32_t stream_id_ = 0; | ||||
|   uint32_t n_components_ = 1; | ||||
|   char* local_sdp_ = nullptr; | ||||
|   NiceComponentState state_ = NiceComponentState::NICE_COMPONENT_STATE_LAST; | ||||
|   bool destroyed_ = false; | ||||
|   gboolean agent_closed_ = false; | ||||
|  | ||||
|   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_recv_t on_recv_; | ||||
|   void* user_ptr_; | ||||
|   | ||||
| @@ -525,6 +525,25 @@ void PeerConnection::ProcessSignal(const std::string &signal) { | ||||
|       } | ||||
|       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: { | ||||
|       break; | ||||
|     } | ||||
|   | ||||
| @@ -167,24 +167,59 @@ int IceTransmission::InitIceTransmission( | ||||
|           LOG_INFO("state_change: {}", nice_component_state_to_string(state)); | ||||
|         } | ||||
|       }, | ||||
|       [](NiceAgent *agent, guint stream_id, guint component_id, const char *sdp, | ||||
|          gpointer user_ptr) { LOG_INFO("candadite: {}", sdp); }, | ||||
|       [](NiceAgent *agent, guint stream_id, gpointer user_ptr) { | ||||
|         // non-trickle | ||||
|       [](NiceAgent *agent, guint stream_id, guint component_id, | ||||
|          gchar *foundation, gpointer user_ptr) { | ||||
|         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(); | ||||
|           GSList *cands = | ||||
|               nice_agent_get_local_candidates(agent, stream_id, component_id); | ||||
|           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 { | ||||
|             ice_transmission_obj->CreateAnswer(); | ||||
|             ice_transmission_obj->SendAnswer(); | ||||
|               json message = { | ||||
|                   {"type", "offer_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_); | ||||
|  | ||||
|               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, | ||||
|          gchar *buffer, gpointer user_ptr) { | ||||
| @@ -257,9 +292,37 @@ 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; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -80,10 +80,14 @@ class IceTransmission { | ||||
|  public: | ||||
|   int GatherCandidates(); | ||||
|  | ||||
|   int SendLocalCredentials(); | ||||
|  | ||||
|   int GetLocalSdp(); | ||||
|  | ||||
|   int SetRemoteSdp(const std::string &remote_sdp); | ||||
|  | ||||
|   int AddCandidate(const std::string &candidate); | ||||
|  | ||||
|   int CreateOffer(); | ||||
|  | ||||
|   int SendOffer(); | ||||
| @@ -99,8 +103,10 @@ class IceTransmission { | ||||
|   uint8_t CheckIsDataPacket(const char *buffer, size_t size); | ||||
|  | ||||
|  private: | ||||
|   bool trickle_ice_ = true; | ||||
|   std::string local_sdp_; | ||||
|   std::string remote_sdp_; | ||||
|   std::string new_local_candidate_; | ||||
|   std::string local_candidates_; | ||||
|   std::string remote_candidates_; | ||||
|   unsigned int connection_id_ = 0; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user