mirror of
				https://github.com/kunkundi/crossdesk.git
				synced 2025-10-26 20:25:34 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			302 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			302 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include "ice_agent.h"
 | |
| 
 | |
| #include <cstring>
 | |
| #include <iostream>
 | |
| 
 | |
| #include "log.h"
 | |
| 
 | |
| IceAgent::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)
 | |
|     : stun_ip_(stun_ip),
 | |
|       stun_port_(stun_port),
 | |
|       turn_ip_(turn_ip),
 | |
|       turn_port_(turn_port),
 | |
|       turn_username_(turn_username),
 | |
|       turn_password_(turn_password),
 | |
|       controlling_(offer_peer) {}
 | |
| 
 | |
| IceAgent::~IceAgent() {
 | |
|   if (!destroyed_) {
 | |
|     DestroyIceAgent();
 | |
|   }
 | |
|   g_object_unref(agent_);
 | |
| }
 | |
| 
 | |
| int IceAgent::CreateIceAgent(nice_cb_state_changed_t on_state_changed,
 | |
|                              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_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;
 | |
| 
 | |
|   g_networking_init();
 | |
| 
 | |
|   exit_nice_thread_ = false;
 | |
| 
 | |
|   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_ICE_TRICKLE));
 | |
| 
 | |
|     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_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_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_, 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_, 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_, "ice-tcp", false, "ice-udp", true, "force-relay",
 | |
|     // 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_);
 | |
| 
 | |
|     nice_inited_ = true;
 | |
| 
 | |
|     g_main_loop_run(gloop_);
 | |
|     exit_nice_thread_ = true;
 | |
|   }));
 | |
| 
 | |
|   do {
 | |
|     g_usleep(1000);
 | |
|   } while (!nice_inited_);
 | |
| 
 | |
|   LOG_INFO("Nice agent init finish");
 | |
| 
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| void cb_closed(GObject *src, GAsyncResult *res, gpointer data) {
 | |
|   NiceAgent *agent = NICE_AGENT(src);
 | |
|   g_debug("test-turn:%s: %p", G_STRFUNC, agent);
 | |
| 
 | |
|   *((gboolean *)data) = TRUE;
 | |
| }
 | |
| 
 | |
| int IceAgent::DestroyIceAgent() {
 | |
|   if (!nice_inited_) {
 | |
|     LOG_ERROR("Nice agent has not been initialized");
 | |
|     return -1;
 | |
|   }
 | |
| 
 | |
|   nice_agent_remove_stream(agent_, stream_id_);
 | |
|   nice_agent_close_async(agent_, cb_closed, &agent_closed_);
 | |
| 
 | |
|   destroyed_ = true;
 | |
|   g_main_loop_quit(gloop_);
 | |
| 
 | |
|   if (nice_thread_->joinable()) {
 | |
|     nice_thread_->join();
 | |
|   }
 | |
| 
 | |
|   LOG_INFO("Destroy nice agent success");
 | |
|   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");
 | |
|     return nullptr;
 | |
|   }
 | |
| 
 | |
|   if (nullptr == agent_) {
 | |
|     LOG_ERROR("Nice agent is nullptr");
 | |
|     return nullptr;
 | |
|   }
 | |
| 
 | |
|   if (destroyed_) {
 | |
|     LOG_ERROR("Nice agent is destroyed");
 | |
|     return nullptr;
 | |
|   }
 | |
| 
 | |
|   local_sdp_ = nice_agent_generate_local_sdp(agent_);
 | |
|   LOG_INFO("Generate local sdp:[\n{}]", local_sdp_);
 | |
| 
 | |
|   return local_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);
 | |
|   if (ret > 0) {
 | |
|     return 0;
 | |
|   } else {
 | |
|     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");
 | |
|     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_)) {
 | |
|     LOG_ERROR("Failed to start candidate gathering");
 | |
|     return -1;
 | |
|   }
 | |
| 
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| 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);
 | |
| 
 | |
|   return state_;
 | |
| }
 | |
| 
 | |
| 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 !=
 | |
|   //     nice_agent_get_component_state(agent_, stream_id_, 1)) {
 | |
|   //   LOG_ERROR("Nice agent not ready");
 | |
|   //   return -1;
 | |
|   // }
 | |
| 
 | |
|   nice_agent_send(agent_, stream_id_, 1, size, data);
 | |
|   return 0;
 | |
| } |