mirror of
				https://github.com/kunkundi/crossdesk.git
				synced 2025-10-26 20:25:34 +08:00 
			
		
		
		
	Refactor connection create process
This commit is contained in:
		
							
								
								
									
										289
									
								
								src/ice/ice_transmission.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										289
									
								
								src/ice/ice_transmission.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,289 @@ | ||||
| #include "ice_transmission.h" | ||||
|  | ||||
| #include <map> | ||||
| #include <nlohmann/json.hpp> | ||||
| #include <thread> | ||||
|  | ||||
| #include "log.h" | ||||
|  | ||||
| using nlohmann::json; | ||||
|  | ||||
| constexpr size_t HASH_STRING_PIECE(const char *string_piece) { | ||||
|   std::size_t result = 0; | ||||
|   while (*string_piece) { | ||||
|     result = (result * 131) + *string_piece++; | ||||
|   } | ||||
|   return result; | ||||
| } | ||||
|  | ||||
| constexpr size_t operator"" _H(const char *string_piece, size_t) { | ||||
|   return HASH_STRING_PIECE(string_piece); | ||||
| } | ||||
|  | ||||
| const std::vector<std::string> ice_status = { | ||||
|     "JUICE_STATE_DISCONNECTED", "JUICE_STATE_GATHERING", | ||||
|     "JUICE_STATE_CONNECTING",   "JUICE_STATE_CONNECTED", | ||||
|     "JUICE_STATE_COMPLETED",    "JUICE_STATE_FAILED"}; | ||||
|  | ||||
| IceTransmission::IceTransmission( | ||||
|     WsTransmission *ice_ws_transmission, | ||||
|     std::function<void(const char *, size_t)> on_receive_ice_msg) | ||||
|     : ice_ws_transport_(ice_ws_transmission), | ||||
|       on_receive_ice_msg_cb_(on_receive_ice_msg) {} | ||||
|  | ||||
| IceTransmission::~IceTransmission() {} | ||||
|  | ||||
| int IceTransmission::InitIceTransmission(std::string &ip, int port) { | ||||
|   ice_agent_ = new IceAgent(ip, port); | ||||
|  | ||||
|   ice_agent_->CreateIceAgent( | ||||
|       [](juice_agent_t *agent, juice_state_t state, void *user_ptr) { | ||||
|         LOG_INFO("state_change: {}", ice_status[state]); | ||||
|       }, | ||||
|       [](juice_agent_t *agent, const char *sdp, void *user_ptr) { | ||||
|         LOG_INFO("candadite: {}", sdp); | ||||
|         // trickle | ||||
|         // static_cast<IceTransmission | ||||
|         // *>(user_ptr)->SendOfferLocalCandidate(sdp); | ||||
|       }, | ||||
|       [](juice_agent_t *agent, void *user_ptr) { | ||||
|         LOG_INFO("gather_done"); | ||||
|         // non-trickle | ||||
|         if (user_ptr) { | ||||
|           static_cast<IceTransmission *>(user_ptr)->GetLocalSdp(); | ||||
|           static_cast<IceTransmission *>(user_ptr)->SendOffer(); | ||||
|         } | ||||
|       }, | ||||
|       [](juice_agent_t *agent, const char *data, size_t size, void *user_ptr) { | ||||
|         if (user_ptr && | ||||
|             static_cast<IceTransmission *>(user_ptr)->on_receive_ice_msg_cb_) { | ||||
|           static_cast<IceTransmission *>(user_ptr)->on_receive_ice_msg_cb_( | ||||
|               data, size); | ||||
|         } | ||||
|       }, | ||||
|       this); | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int IceTransmission::InitIceTransmission(std::string &ip, int port, | ||||
|                                          std::string const &id) { | ||||
|   transmission_id_ = id; | ||||
|  | ||||
|   ice_agent_ = new IceAgent(ip, port); | ||||
|  | ||||
|   ice_agent_->CreateIceAgent( | ||||
|       [](juice_agent_t *agent, juice_state_t state, void *user_ptr) { | ||||
|         LOG_INFO("state_change: {}", ice_status[state]); | ||||
|       }, | ||||
|       [](juice_agent_t *agent, const char *sdp, void *user_ptr) { | ||||
|         LOG_INFO("candadite: {}", sdp); | ||||
|         // trickle | ||||
|         // static_cast<PeerConnection | ||||
|         // *>(user_ptr)->SendAnswerLocalCandidate(sdp); | ||||
|       }, | ||||
|       [](juice_agent_t *agent, void *user_ptr) { | ||||
|         LOG_INFO("gather_done"); | ||||
|         // non-trickle | ||||
|         if (user_ptr) { | ||||
|           static_cast<IceTransmission *>(user_ptr)->CreateAnswer(); | ||||
|           static_cast<IceTransmission *>(user_ptr)->SendAnswer(); | ||||
|         } | ||||
|       }, | ||||
|       [](juice_agent_t *agent, const char *data, size_t size, void *user_ptr) { | ||||
|         if (user_ptr && | ||||
|             static_cast<IceTransmission *>(user_ptr)->on_receive_ice_msg_cb_) { | ||||
|           static_cast<IceTransmission *>(user_ptr)->on_receive_ice_msg_cb_( | ||||
|               data, size); | ||||
|         } | ||||
|       }, | ||||
|       this); | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int IceTransmission::DestroyIceTransmission() { | ||||
|   if (ice_agent_) { | ||||
|     delete ice_agent_; | ||||
|   } | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int IceTransmission::CreateTransmission(const std::string &transmission_id) { | ||||
|   LOG_INFO("Create transport"); | ||||
|   offer_peer_ = true; | ||||
|  | ||||
|   // if (SignalStatus::Connected != signal_status_) { | ||||
|   //   LOG_ERROR("Not connect to signalserver"); | ||||
|   //   return -1; | ||||
|   // } | ||||
|  | ||||
|   json message = {{"type", "create_transmission"}, | ||||
|                   {"transmission_id", transmission_id}}; | ||||
|   if (ice_ws_transport_) { | ||||
|     ice_ws_transport_->Send(message.dump()); | ||||
|     LOG_INFO("Send msg: {}", message.dump().c_str()); | ||||
|   } | ||||
|  | ||||
|   // CreateOffer(); | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int IceTransmission::JoinTransmission(const std::string &transmission_id) { | ||||
|   LOG_INFO("Join transport"); | ||||
|   offer_peer_ = false; | ||||
|   transmission_id_ = transmission_id; | ||||
|  | ||||
|   // if (SignalStatus::Connected != signal_status_) { | ||||
|   //   LOG_ERROR("Not connect to signalserver"); | ||||
|   //   return -1; | ||||
|   // } | ||||
|  | ||||
|   // QueryRemoteSdp(transmission_id); | ||||
|   CreateOffer(); | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int IceTransmission::GatherCandidates() { | ||||
|   ice_agent_->GatherCandidates(); | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int IceTransmission::GetLocalSdp() { | ||||
|   local_sdp_ = ice_agent_->GenerateLocalSdp(); | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int IceTransmission::SetRemoteSdp(const std::string &remote_sdp) { | ||||
|   ice_agent_->SetRemoteSdp(remote_sdp.c_str()); | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int IceTransmission::AddRemoteCandidate(const std::string &remote_candidate) { | ||||
|   ice_agent_->AddRemoteCandidates(remote_candidate.c_str()); | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int IceTransmission::CreateOffer() { | ||||
|   LOG_INFO("Create offer"); | ||||
|   GatherCandidates(); | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int IceTransmission::SendOffer() { | ||||
|   json message = {{"type", "offer"}, | ||||
|                   {"transmission_id", transmission_id_}, | ||||
|                   {"sdp", local_sdp_}}; | ||||
|   LOG_INFO("Send offer:\n{}", message.dump().c_str()); | ||||
|  | ||||
|   if (ice_ws_transport_) { | ||||
|     ice_ws_transport_->Send(message.dump()); | ||||
|   } | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int IceTransmission::QueryRemoteSdp(std::string transmission_id) { | ||||
|   json message = {{"type", "query_remote_sdp"}, | ||||
|                   {"transmission_id", transmission_id_}}; | ||||
|   LOG_INFO("Query remote sdp"); | ||||
|  | ||||
|   if (ice_ws_transport_) { | ||||
|     ice_ws_transport_->Send(message.dump()); | ||||
|   } | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int IceTransmission::CreateAnswer() { | ||||
|   GetLocalSdp(); | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int IceTransmission::SendAnswer() { | ||||
|   json message = {{"type", "answer"}, | ||||
|                   {"transmission_id", transmission_id_}, | ||||
|                   {"sdp", local_sdp_}}; | ||||
|   LOG_INFO("Send answer:\n{}", message.dump().c_str()); | ||||
|  | ||||
|   if (ice_ws_transport_) { | ||||
|     ice_ws_transport_->Send(message.dump()); | ||||
|   } | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int IceTransmission::SendOfferLocalCandidate( | ||||
|     const std::string &remote_candidate) { | ||||
|   json message = {{"type", "offer_candidate"}, | ||||
|                   {"transmission_id", transmission_id_}, | ||||
|                   {"sdp", remote_candidate}}; | ||||
|   LOG_INFO("Send candidate:\n{}", message.dump().c_str()); | ||||
|  | ||||
|   if (ice_ws_transport_) { | ||||
|     ice_ws_transport_->Send(message.dump()); | ||||
|   } | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int IceTransmission::SendAnswerLocalCandidate( | ||||
|     const std::string &remote_candidate) { | ||||
|   json message = {{"type", "answer_candidate"}, | ||||
|                   {"transmission_id", transmission_id_}, | ||||
|                   {"sdp", remote_candidate}}; | ||||
|   LOG_INFO("Send candidate:\n{}", message.dump().c_str()); | ||||
|  | ||||
|   if (ice_ws_transport_) { | ||||
|     ice_ws_transport_->Send(message.dump()); | ||||
|   } | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int IceTransmission::SendData(const char *data, size_t size) { | ||||
|   ice_agent_->Send(data, size); | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| void IceTransmission::OnReceiveMessage(const std::string &msg) { | ||||
|   auto j = json::parse(msg); | ||||
|   LOG_INFO("msg: {}", msg.c_str()); | ||||
|  | ||||
|   std::string type = j["type"]; | ||||
|  | ||||
|   switch (HASH_STRING_PIECE(type.c_str())) { | ||||
|     case "offer"_H: { | ||||
|       break; | ||||
|     } | ||||
|     case "transmission_id"_H: { | ||||
|       if (j["status"].get<std::string>() == "success") { | ||||
|         transmission_id_ = j["transmission_id"].get<std::string>(); | ||||
|         LOG_INFO("Create transmission success with id [{}]", transmission_id_); | ||||
|         // SendOffer(); | ||||
|       } else if (j["status"].get<std::string>() == "fail") { | ||||
|         LOG_WARN("Create transmission failed with id [{}], due to [{}]", | ||||
|                  transmission_id_, j["reason"].get<std::string>().c_str()); | ||||
|       } | ||||
|       break; | ||||
|     } | ||||
|     case "remote_sdp"_H: { | ||||
|       remote_sdp_ = j["sdp"].get<std::string>(); | ||||
|  | ||||
|       if (remote_sdp_.empty()) { | ||||
|         LOG_INFO("Offer peer not ready, wait 1 second and requery remote sdp"); | ||||
|         std::this_thread::sleep_for(std::chrono::milliseconds(1000)); | ||||
|         QueryRemoteSdp(transmission_id_); | ||||
|       } else { | ||||
|         LOG_INFO("Receive remote sdp [{}]", remote_sdp_); | ||||
|         SetRemoteSdp(remote_sdp_); | ||||
|  | ||||
|         if (!offer_peer_) { | ||||
|           GatherCandidates(); | ||||
|         } | ||||
|       } | ||||
|       break; | ||||
|     } | ||||
|     case "candidate"_H: { | ||||
|       std::string candidate = j["sdp"].get<std::string>(); | ||||
|       LOG_INFO("Receive candidate [{}]", candidate); | ||||
|       AddRemoteCandidate(candidate); | ||||
|       break; | ||||
|     } | ||||
|     default: | ||||
|       break; | ||||
|   } | ||||
| } | ||||
| @@ -1,25 +1,25 @@ | ||||
| #ifndef _ICE_TRANSPORT_H_ | ||||
| #define _ICE_TRANSPORT_H_ | ||||
| #ifndef _ICE_TRANSMISSION_H_ | ||||
| #define _ICE_TRANSMISSION_H_ | ||||
| 
 | ||||
| #include <iostream> | ||||
| 
 | ||||
| #include "ice_agent.h" | ||||
| #include "ws_transport.h" | ||||
| #include "ws_transmission.h" | ||||
| 
 | ||||
| class IceTransport { | ||||
| class IceTransmission { | ||||
|  public: | ||||
|   IceTransport(WsTransport *ice_ws_transport, | ||||
|   IceTransmission(WsTransmission *ice_ws_transmission, | ||||
|                   std::function<void(const char *, size_t)> on_receive_ice_msg); | ||||
| 
 | ||||
|   ~IceTransport(); | ||||
|   ~IceTransmission(); | ||||
| 
 | ||||
|   int InitIceTransport(std::string &ip, int port); | ||||
|   int InitIceTransport(std::string &ip, int port, std::string const &id); | ||||
|   int InitIceTransmission(std::string &ip, int port); | ||||
|   int InitIceTransmission(std::string &ip, int port, std::string const &id); | ||||
| 
 | ||||
|   int DestroyIceTransport(); | ||||
|   int DestroyIceTransmission(); | ||||
| 
 | ||||
|   int CreateTransport(); | ||||
|   int CreateTransport(std::string transport_id); | ||||
|   int CreateTransmission(const std::string &transmission_id); | ||||
|   int JoinTransmission(const std::string &transmission_id); | ||||
| 
 | ||||
|   int SendData(const char *data, size_t size); | ||||
| 
 | ||||
| @@ -32,7 +32,7 @@ class IceTransport { | ||||
| 
 | ||||
|   int GetLocalSdp(); | ||||
| 
 | ||||
|   int QueryRemoteSdp(std::string transport_id); | ||||
|   int QueryRemoteSdp(std::string transmission_id); | ||||
| 
 | ||||
|   int SetRemoteSdp(const std::string &remote_sdp); | ||||
| 
 | ||||
| @@ -52,14 +52,14 @@ class IceTransport { | ||||
| 
 | ||||
|  private: | ||||
|   IceAgent *ice_agent_ = nullptr; | ||||
|   WsTransport *ice_ws_transport_ = nullptr; | ||||
|   WsTransmission *ice_ws_transport_ = nullptr; | ||||
|   std::function<void(const char *, size_t)> on_receive_ice_msg_cb_ = nullptr; | ||||
|   std::string local_sdp_; | ||||
|   std::string remote_sdp_; | ||||
|   std::string local_candidates_; | ||||
|   std::string remote_candidates_; | ||||
|   unsigned int connection_id_ = 0; | ||||
|   std::string transport_id_ = ""; | ||||
|   std::string transmission_id_ = ""; | ||||
|   bool offer_peer_ = true; | ||||
| }; | ||||
| 
 | ||||
| @@ -1,278 +0,0 @@ | ||||
| #include "ice_transport.h" | ||||
|  | ||||
| #include <map> | ||||
| #include <nlohmann/json.hpp> | ||||
| #include <thread> | ||||
|  | ||||
| #include "log.h" | ||||
|  | ||||
| using nlohmann::json; | ||||
|  | ||||
| static const std::map<std::string, unsigned int> siganl_types{ | ||||
|     {"connection_id", 1}, | ||||
|     {"offer", 2}, | ||||
|     {"transport_id", 3}, | ||||
|     {"remote_sdp", 4}, | ||||
|     {"candidate", 5}}; | ||||
|  | ||||
| const std::vector<std::string> ice_status = { | ||||
|     "JUICE_STATE_DISCONNECTED", "JUICE_STATE_GATHERING", | ||||
|     "JUICE_STATE_CONNECTING",   "JUICE_STATE_CONNECTED", | ||||
|     "JUICE_STATE_COMPLETED",    "JUICE_STATE_FAILED"}; | ||||
|  | ||||
| IceTransport::IceTransport( | ||||
|     WsTransport *ice_ws_transport, | ||||
|     std::function<void(const char *, size_t)> on_receive_ice_msg) | ||||
|     : ice_ws_transport_(ice_ws_transport), | ||||
|       on_receive_ice_msg_cb_(on_receive_ice_msg) {} | ||||
|  | ||||
| IceTransport::~IceTransport() {} | ||||
|  | ||||
| int IceTransport::InitIceTransport(std::string &ip, int port) { | ||||
|   ice_agent_ = new IceAgent(ip, port); | ||||
|  | ||||
|   ice_agent_->CreateIceAgent( | ||||
|       [](juice_agent_t *agent, juice_state_t state, void *user_ptr) { | ||||
|         LOG_INFO("state_change: {}", ice_status[state]); | ||||
|       }, | ||||
|       [](juice_agent_t *agent, const char *sdp, void *user_ptr) { | ||||
|         LOG_INFO("candadite: {}", sdp); | ||||
|         // trickle | ||||
|         // static_cast<IceTransport | ||||
|         // *>(user_ptr)->SendOfferLocalCandidate(sdp); | ||||
|       }, | ||||
|       [](juice_agent_t *agent, void *user_ptr) { | ||||
|         LOG_INFO("gather_done"); | ||||
|         // non-trickle | ||||
|         if (user_ptr) { | ||||
|           static_cast<IceTransport *>(user_ptr)->GetLocalSdp(); | ||||
|           static_cast<IceTransport *>(user_ptr)->SendOffer(); | ||||
|         } | ||||
|       }, | ||||
|       [](juice_agent_t *agent, const char *data, size_t size, void *user_ptr) { | ||||
|         if (user_ptr && | ||||
|             static_cast<IceTransport *>(user_ptr)->on_receive_ice_msg_cb_) { | ||||
|           static_cast<IceTransport *>(user_ptr)->on_receive_ice_msg_cb_(data, | ||||
|                                                                         size); | ||||
|         } | ||||
|       }, | ||||
|       this); | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int IceTransport::InitIceTransport(std::string &ip, int port, | ||||
|                                    std::string const &id) { | ||||
|   transport_id_ = id; | ||||
|  | ||||
|   ice_agent_ = new IceAgent(ip, port); | ||||
|  | ||||
|   ice_agent_->CreateIceAgent( | ||||
|       [](juice_agent_t *agent, juice_state_t state, void *user_ptr) { | ||||
|         LOG_INFO("state_change: {}", ice_status[state]); | ||||
|       }, | ||||
|       [](juice_agent_t *agent, const char *sdp, void *user_ptr) { | ||||
|         LOG_INFO("candadite: {}", sdp); | ||||
|         // trickle | ||||
|         // static_cast<PeerConnection | ||||
|         // *>(user_ptr)->SendAnswerLocalCandidate(sdp); | ||||
|       }, | ||||
|       [](juice_agent_t *agent, void *user_ptr) { | ||||
|         LOG_INFO("gather_done"); | ||||
|         // non-trickle | ||||
|         if (user_ptr) { | ||||
|           static_cast<IceTransport *>(user_ptr)->CreateAnswer(); | ||||
|           static_cast<IceTransport *>(user_ptr)->SendAnswer(); | ||||
|         } | ||||
|       }, | ||||
|       [](juice_agent_t *agent, const char *data, size_t size, void *user_ptr) { | ||||
|         if (user_ptr && | ||||
|             static_cast<IceTransport *>(user_ptr)->on_receive_ice_msg_cb_) { | ||||
|           static_cast<IceTransport *>(user_ptr)->on_receive_ice_msg_cb_(data, | ||||
|                                                                         size); | ||||
|         } | ||||
|       }, | ||||
|       this); | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int IceTransport::DestroyIceTransport() { | ||||
|   if (ice_agent_) { | ||||
|     delete ice_agent_; | ||||
|   } | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int IceTransport::CreateTransport() { | ||||
|   LOG_INFO("Create transport"); | ||||
|   offer_peer_ = true; | ||||
|  | ||||
|   // if (SignalStatus::Connected != signal_status_) { | ||||
|   //   LOG_ERROR("Not connect to signalserver"); | ||||
|   //   return -1; | ||||
|   // } | ||||
|  | ||||
|   json message = {{"type", "create_transport"}}; | ||||
|   if (ice_ws_transport_) { | ||||
|     ice_ws_transport_->Send(message.dump()); | ||||
|     LOG_INFO("Send msg: {}", message.dump().c_str()); | ||||
|   } | ||||
|  | ||||
|   CreateOffer(); | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int IceTransport::CreateTransport(std::string transport_id) { | ||||
|   LOG_INFO("Join transport"); | ||||
|   offer_peer_ = false; | ||||
|   transport_id_ = transport_id; | ||||
|  | ||||
|   // if (SignalStatus::Connected != signal_status_) { | ||||
|   //   LOG_ERROR("Not connect to signalserver"); | ||||
|   //   return -1; | ||||
|   // } | ||||
|  | ||||
|   QueryRemoteSdp(transport_id); | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int IceTransport::GatherCandidates() { | ||||
|   ice_agent_->GatherCandidates(); | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int IceTransport::GetLocalSdp() { | ||||
|   local_sdp_ = ice_agent_->GenerateLocalSdp(); | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int IceTransport::SetRemoteSdp(const std::string &remote_sdp) { | ||||
|   ice_agent_->SetRemoteSdp(remote_sdp.c_str()); | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int IceTransport::AddRemoteCandidate(const std::string &remote_candidate) { | ||||
|   ice_agent_->AddRemoteCandidates(remote_candidate.c_str()); | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int IceTransport::CreateOffer() { | ||||
|   LOG_INFO("Create offer"); | ||||
|   GatherCandidates(); | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int IceTransport::SendOffer() { | ||||
|   json message = { | ||||
|       {"type", "offer"}, {"transport_id", transport_id_}, {"sdp", local_sdp_}}; | ||||
|   LOG_INFO("Send offer:\n{}", message.dump().c_str()); | ||||
|  | ||||
|   if (ice_ws_transport_) { | ||||
|     ice_ws_transport_->Send(message.dump()); | ||||
|   } | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int IceTransport::QueryRemoteSdp(std::string transport_id) { | ||||
|   json message = {{"type", "query_remote_sdp"}, | ||||
|                   {"transport_id", transport_id_}}; | ||||
|   LOG_INFO("Query remote sdp"); | ||||
|  | ||||
|   if (ice_ws_transport_) { | ||||
|     ice_ws_transport_->Send(message.dump()); | ||||
|   } | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int IceTransport::CreateAnswer() { | ||||
|   GetLocalSdp(); | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int IceTransport::SendAnswer() { | ||||
|   json message = { | ||||
|       {"type", "answer"}, {"transport_id", transport_id_}, {"sdp", local_sdp_}}; | ||||
|   LOG_INFO("Send answer:\n{}", message.dump().c_str()); | ||||
|  | ||||
|   if (ice_ws_transport_) { | ||||
|     ice_ws_transport_->Send(message.dump()); | ||||
|   } | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int IceTransport::SendOfferLocalCandidate(const std::string &remote_candidate) { | ||||
|   json message = {{"type", "offer_candidate"}, | ||||
|                   {"transport_id", transport_id_}, | ||||
|                   {"sdp", remote_candidate}}; | ||||
|   LOG_INFO("Send candidate:\n{}", message.dump().c_str()); | ||||
|  | ||||
|   if (ice_ws_transport_) { | ||||
|     ice_ws_transport_->Send(message.dump()); | ||||
|   } | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int IceTransport::SendAnswerLocalCandidate( | ||||
|     const std::string &remote_candidate) { | ||||
|   json message = {{"type", "answer_candidate"}, | ||||
|                   {"transport_id", transport_id_}, | ||||
|                   {"sdp", remote_candidate}}; | ||||
|   LOG_INFO("Send candidate:\n{}", message.dump().c_str()); | ||||
|  | ||||
|   if (ice_ws_transport_) { | ||||
|     ice_ws_transport_->Send(message.dump()); | ||||
|   } | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int IceTransport::SendData(const char *data, size_t size) { | ||||
|   ice_agent_->Send(data, size); | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| void IceTransport::OnReceiveMessage(const std::string &msg) { | ||||
|   auto j = json::parse(msg); | ||||
|   LOG_INFO("msg: {}", msg.c_str()); | ||||
|  | ||||
|   std::string type = j["type"]; | ||||
|   auto itr = siganl_types.find(type); | ||||
|   if (itr != siganl_types.end()) { | ||||
|     LOG_INFO("msg type :{}", itr->first); | ||||
|     switch (itr->second) { | ||||
|       case 2: { | ||||
|         break; | ||||
|       } | ||||
|       case 3: { | ||||
|         transport_id_ = j["transport_id"].get<std::string>(); | ||||
|         LOG_INFO("Receive local peer transport_id [{}]", transport_id_); | ||||
|         // SendOffer(); | ||||
|         break; | ||||
|       } | ||||
|       case 4: { | ||||
|         remote_sdp_ = j["sdp"].get<std::string>(); | ||||
|  | ||||
|         if (remote_sdp_.empty()) { | ||||
|           LOG_INFO( | ||||
|               "Offer peer not ready, wait 1 second and requery remote sdp"); | ||||
|           std::this_thread::sleep_for(std::chrono::milliseconds(1000)); | ||||
|           QueryRemoteSdp(transport_id_); | ||||
|         } else { | ||||
|           LOG_INFO("Receive remote sdp [{}]", remote_sdp_); | ||||
|           SetRemoteSdp(remote_sdp_); | ||||
|  | ||||
|           if (!offer_peer_) { | ||||
|             GatherCandidates(); | ||||
|           } | ||||
|         } | ||||
|         break; | ||||
|       } | ||||
|       case 5: { | ||||
|         std::string candidate = j["sdp"].get<std::string>(); | ||||
|         LOG_INFO("Receive candidate [{}]", candidate); | ||||
|         AddRemoteCandidate(candidate); | ||||
|         break; | ||||
|       } | ||||
|       default: | ||||
|         break; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @@ -11,7 +11,7 @@ using nlohmann::json; | ||||
| static const std::map<std::string, unsigned int> siganl_types{ | ||||
|     {"ws_connection_id", 1}, | ||||
|     {"offer", 2}, | ||||
|     {"transport_id", 3}, | ||||
|     {"transmission_id", 3}, | ||||
|     {"remote_sdp", 4}, | ||||
|     {"candidate", 5}}; | ||||
|  | ||||
| @@ -19,7 +19,7 @@ PeerConnection::PeerConnection() {} | ||||
|  | ||||
| PeerConnection::~PeerConnection() {} | ||||
|  | ||||
| int PeerConnection::Init(PeerConnectionParams params) { | ||||
| int PeerConnection::Create(PeerConnectionParams params, const std::string &id) { | ||||
|   INIReader reader(params.cfg_path); | ||||
|   std::string cfg_signal_server_ip = reader.Get("signal server", "ip", "-1"); | ||||
|   std::string cfg_signal_server_port = | ||||
| @@ -35,7 +35,7 @@ int PeerConnection::Init(PeerConnectionParams params) { | ||||
|  | ||||
|   on_receive_ws_msg_ = [this](const std::string &msg) { | ||||
|     do { | ||||
|     } while (!ice_transport_); | ||||
|     } while (!ice_transmission_); | ||||
|     auto j = json::parse(msg); | ||||
|     std::string type = j["type"]; | ||||
|     auto itr = siganl_types.find(type); | ||||
| @@ -50,7 +50,7 @@ int PeerConnection::Init(PeerConnectionParams params) { | ||||
|           break; | ||||
|         } | ||||
|         default: { | ||||
|           ice_transport_->OnReceiveMessage(msg); | ||||
|           ice_transmission_->OnReceiveMessage(msg); | ||||
|           break; | ||||
|         } | ||||
|       } | ||||
| @@ -62,24 +62,24 @@ int PeerConnection::Init(PeerConnectionParams params) { | ||||
|     LOG_INFO("Receive data: [{}]", msg.c_str()); | ||||
|   }; | ||||
|  | ||||
|   ws_transport_ = new WsTransport(on_receive_ws_msg_); | ||||
|   ws_transport_ = new WsTransmission(on_receive_ws_msg_); | ||||
|   uri_ = "ws://" + cfg_signal_server_ip + ":" + cfg_signal_server_port; | ||||
|   if (ws_transport_) { | ||||
|     ws_transport_->Connect(uri_); | ||||
|   } | ||||
|  | ||||
|   ice_transport_ = new IceTransport(ws_transport_, on_receive_ice_msg_); | ||||
|   ice_transport_->InitIceTransport(cfg_stun_server_ip, stun_server_port); | ||||
|   ice_transmission_ = new IceTransmission(ws_transport_, on_receive_ice_msg_); | ||||
|   ice_transmission_->InitIceTransmission(cfg_stun_server_ip, stun_server_port); | ||||
|  | ||||
|   do { | ||||
|     LOG_INFO("GetSignalStatus = {}", GetSignalStatus()); | ||||
|   } while (SignalStatus::Connected != GetSignalStatus()); | ||||
|  | ||||
|   ice_transport_->CreateTransport(); | ||||
|   ice_transmission_->CreateTransmission(id); | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int PeerConnection::Init(PeerConnectionParams params, std::string const &id) { | ||||
| int PeerConnection::Join(PeerConnectionParams params, const std::string &id) { | ||||
|   INIReader reader(params.cfg_path); | ||||
|   std::string cfg_signal_server_ip = reader.Get("signal server", "ip", "-1"); | ||||
|   std::string cfg_signal_server_port = | ||||
| @@ -93,7 +93,7 @@ int PeerConnection::Init(PeerConnectionParams params, std::string const &id) { | ||||
|  | ||||
|   on_receive_ws_msg_ = [this](const std::string &msg) { | ||||
|     do { | ||||
|     } while (!ice_transport_); | ||||
|     } while (!ice_transmission_); | ||||
|     auto j = json::parse(msg); | ||||
|     std::string type = j["type"]; | ||||
|     auto itr = siganl_types.find(type); | ||||
| @@ -108,7 +108,7 @@ int PeerConnection::Init(PeerConnectionParams params, std::string const &id) { | ||||
|           break; | ||||
|         } | ||||
|         default: { | ||||
|           ice_transport_->OnReceiveMessage(msg); | ||||
|           ice_transmission_->OnReceiveMessage(msg); | ||||
|           break; | ||||
|         } | ||||
|       } | ||||
| @@ -120,22 +120,23 @@ int PeerConnection::Init(PeerConnectionParams params, std::string const &id) { | ||||
|     LOG_INFO("Receive data: [{}]", msg.c_str()); | ||||
|   }; | ||||
|  | ||||
|   transport_id_ = id; | ||||
|   transmission_id_ = id; | ||||
|  | ||||
|   ws_transport_ = new WsTransport(on_receive_ws_msg_); | ||||
|   ws_transport_ = new WsTransmission(on_receive_ws_msg_); | ||||
|   uri_ = "ws://" + cfg_signal_server_ip + ":" + cfg_signal_server_port; | ||||
|   if (ws_transport_) { | ||||
|     ws_transport_->Connect(uri_); | ||||
|   } | ||||
|  | ||||
|   ice_transport_ = new IceTransport(ws_transport_, on_receive_ice_msg_); | ||||
|   ice_transport_->InitIceTransport(cfg_stun_server_ip, stun_server_port, id); | ||||
|   ice_transmission_ = new IceTransmission(ws_transport_, on_receive_ice_msg_); | ||||
|   ice_transmission_->InitIceTransmission(cfg_stun_server_ip, stun_server_port, | ||||
|                                          id); | ||||
|  | ||||
|   do { | ||||
|     LOG_INFO("GetSignalStatus = {}", GetSignalStatus()); | ||||
|   } while (SignalStatus::Connected != GetSignalStatus()); | ||||
|  | ||||
|   ice_transport_->CreateTransport(transport_id_); | ||||
|   ice_transmission_->JoinTransmission(transmission_id_); | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| @@ -149,6 +150,6 @@ int PeerConnection::Destroy() { | ||||
| SignalStatus PeerConnection::GetSignalStatus() { return signal_status_; } | ||||
|  | ||||
| int PeerConnection::SendData(const char *data, size_t size) { | ||||
|   ice_transport_->SendData(data, size); | ||||
|   ice_transmission_->SendData(data, size); | ||||
|   return 0; | ||||
| } | ||||
| @@ -3,8 +3,8 @@ | ||||
|  | ||||
| #include <iostream> | ||||
|  | ||||
| #include "ice_transport.h" | ||||
| #include "ws_transport.h" | ||||
| #include "ice_transmission.h" | ||||
| #include "ws_transmission.h" | ||||
|  | ||||
| enum SignalStatus { Connecting = 0, Connected, Closed }; | ||||
|  | ||||
| @@ -25,8 +25,8 @@ class PeerConnection { | ||||
|   ~PeerConnection(); | ||||
|  | ||||
|  public: | ||||
|   int Init(PeerConnectionParams params); | ||||
|   int Init(PeerConnectionParams params, std::string const &id); | ||||
|   int Create(PeerConnectionParams params, const std::string &id = ""); | ||||
|   int Join(PeerConnectionParams params, const std::string &id); | ||||
|   int Destroy(); | ||||
|  | ||||
|   SignalStatus GetSignalStatus(); | ||||
| @@ -35,12 +35,12 @@ class PeerConnection { | ||||
|  | ||||
|  private: | ||||
|   std::string uri_ = ""; | ||||
|   WsTransport *ws_transport_ = nullptr; | ||||
|   IceTransport *ice_transport_ = nullptr; | ||||
|   WsTransmission *ws_transport_ = nullptr; | ||||
|   IceTransmission *ice_transmission_ = nullptr; | ||||
|   std::function<void(const std::string &)> on_receive_ws_msg_ = nullptr; | ||||
|   std::function<void(const char *, size_t)> on_receive_ice_msg_ = nullptr; | ||||
|   unsigned int ws_connection_id_ = 0; | ||||
|   std::string transport_id_ = ""; | ||||
|   std::string transmission_id_ = ""; | ||||
|   SignalStatus signal_status_ = SignalStatus::Closed; | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -5,7 +5,7 @@ | ||||
|  | ||||
| #include "ice_agent.h" | ||||
| #include "log.h" | ||||
| #include "ws_transport.h" | ||||
| #include "ws_transmission.h" | ||||
| #include "x.h" | ||||
|  | ||||
| using nlohmann::json; | ||||
| @@ -23,12 +23,17 @@ PeerPtr *CreatePeer(const Params *params) { | ||||
| } | ||||
|  | ||||
| int CreateConnection(PeerPtr *peer_ptr) { | ||||
|   peer_ptr->peer_connection->Init(peer_ptr->pc_params); | ||||
|   peer_ptr->peer_connection->Create(peer_ptr->pc_params); | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int CreateConnection(PeerPtr *peer_ptr, const char *connection_id) { | ||||
|   peer_ptr->peer_connection->Create(peer_ptr->pc_params, connection_id); | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int JoinConnection(PeerPtr *peer_ptr, const char *connection_id) { | ||||
|   peer_ptr->peer_connection->Init(peer_ptr->pc_params, connection_id); | ||||
|   peer_ptr->peer_connection->Join(peer_ptr->pc_params, connection_id); | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,14 +1,14 @@ | ||||
| #include "ws_transport.h" | ||||
| #include "ws_transmission.h" | ||||
| 
 | ||||
| #include "log.h" | ||||
| 
 | ||||
| WsTransport::WsTransport( | ||||
| WsTransmission::WsTransmission( | ||||
|     std::function<void(const std::string &)> on_receive_msg_cb) | ||||
|     : on_receive_msg_(on_receive_msg_cb) {} | ||||
| 
 | ||||
| WsTransport::~WsTransport() {} | ||||
| WsTransmission::~WsTransmission() {} | ||||
| 
 | ||||
| void WsTransport::OnReceiveMessage(const std::string &msg) { | ||||
| void WsTransmission::OnReceiveMessage(const std::string &msg) { | ||||
|   LOG_INFO("Receive msg: {}", msg); | ||||
|   if (on_receive_msg_) { | ||||
|     on_receive_msg_(msg); | ||||
							
								
								
									
										18
									
								
								src/ws/ws_transmission.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/ws/ws_transmission.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| #ifndef _WS_TRANSMISSION_H_ | ||||
| #define _WS_TRANSMISSION_H_ | ||||
|  | ||||
| #include "ws_core.h" | ||||
|  | ||||
| class WsTransmission : public WsCore { | ||||
|  public: | ||||
|   WsTransmission(std::function<void(const std::string &)> on_receive_msg_cb); | ||||
|   ~WsTransmission(); | ||||
|  | ||||
|  public: | ||||
|   void OnReceiveMessage(const std::string &msg); | ||||
|  | ||||
|  private: | ||||
|   std::function<void(const std::string &)> on_receive_msg_ = nullptr; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| @@ -1,18 +0,0 @@ | ||||
| #ifndef _WS_TRANSPORT_H_ | ||||
| #define _WS_TRANSPORT_H_ | ||||
|  | ||||
| #include "ws_core.h" | ||||
|  | ||||
| class WsTransport : public WsCore { | ||||
|  public: | ||||
|   WsTransport(std::function<void(const std::string &)> on_receive_msg_cb); | ||||
|   ~WsTransport(); | ||||
|  | ||||
|  public: | ||||
|   void OnReceiveMessage(const std::string &msg); | ||||
|  | ||||
|  private: | ||||
|   std::function<void(const std::string &)> on_receive_msg_ = nullptr; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| @@ -6,8 +6,12 @@ int main(int argc, char** argv) { | ||||
|   Params params; | ||||
|   params.cfg_path = "../../../../config/config.ini"; | ||||
| 
 | ||||
|   std::string transmission_id = "000000"; | ||||
|   // std::cout << "Please input which transmisson want to join: ";
 | ||||
|   // std::cin >> transmission_id;
 | ||||
| 
 | ||||
|   PeerPtr* peer = CreatePeer(¶ms); | ||||
|   JoinConnection(peer, "000000"); | ||||
|   JoinConnection(peer, transmission_id.c_str()); | ||||
| 
 | ||||
|   std::string msg = "Offer peer"; | ||||
| 
 | ||||
| @@ -14,13 +14,13 @@ constexpr size_t operator"" _H(const char* string_piece, size_t) { | ||||
|   return HASH_STRING_PIECE(string_piece); | ||||
| } | ||||
|  | ||||
| std::string gen_random_6() { | ||||
| const std::string gen_random_6() { | ||||
|   static const char alphanum[] = "0123456789"; | ||||
|   std::string tmp_s; | ||||
|   tmp_s.reserve(6); | ||||
|   std::string random_id; | ||||
|   random_id.reserve(6); | ||||
|  | ||||
|   for (int i = 0; i < 6; ++i) { | ||||
|     tmp_s += alphanum[rand() % (sizeof(alphanum) - 1)]; | ||||
|     random_id += alphanum[rand() % (sizeof(alphanum) - 1)]; | ||||
|   } | ||||
|  | ||||
|   return "000000"; | ||||
| @@ -105,56 +105,84 @@ void SignalServer::on_message(websocketpp::connection_hdl hdl, | ||||
|   std::string type = j["type"]; | ||||
|  | ||||
|   switch (HASH_STRING_PIECE(type.c_str())) { | ||||
|     case "create_transport"_H: { | ||||
|       transport_id_ = gen_random_6(); | ||||
|       LOG_INFO("Generate transport_id [{}]", transport_id_); | ||||
|       json message = {{"type", "transport_id"}, | ||||
|                       {"transport_id", transport_id_}}; | ||||
|     case "create_transmission"_H: { | ||||
|       transmission_id_ = j["transmission_id"]; | ||||
|       LOG_INFO("Receive create transmission request with id [{}]", | ||||
|                transmission_id_); | ||||
|       if (transmission_list_.find(transmission_id_) == | ||||
|           transmission_list_.end()) { | ||||
|         if (transmission_id_.empty()) { | ||||
|           transmission_id_ = gen_random_6(); | ||||
|           while (transmission_list_.find(transmission_id_) != | ||||
|                  transmission_list_.end()) { | ||||
|             transmission_id_ = gen_random_6(); | ||||
|           } | ||||
|           LOG_INFO( | ||||
|               "Transmission id is empty, generate a new one for this request " | ||||
|               "[{}]", | ||||
|               transmission_id_); | ||||
|         } | ||||
|         transmission_list_.insert(transmission_id_); | ||||
|         LOG_INFO("Create transmission id [{}]", transmission_id_); | ||||
|         json message = {{"type", "transmission_id"}, | ||||
|                         {"transmission_id", transmission_id_}, | ||||
|                         {"status", "success"}}; | ||||
|         send_msg(hdl, message); | ||||
|       } else { | ||||
|         LOG_INFO("Transmission id [{}] already exist", transmission_id_); | ||||
|         json message = {{"type", "transmission_id"}, | ||||
|                         {"transmission_id", transmission_id_}, | ||||
|                         {"status", "fail"}, | ||||
|                         {"reason", "Transmission id exist"}}; | ||||
|         send_msg(hdl, message); | ||||
|       } | ||||
|  | ||||
|       break; | ||||
|     } | ||||
|     case "offer"_H: { | ||||
|       std::string transport_id = j["transport_id"]; | ||||
|       std::string transmission_id = j["transmission_id"]; | ||||
|       std::string sdp = j["sdp"]; | ||||
|       LOG_INFO("Save transport_id[{}] with offer sdp[{}]", transport_id, sdp); | ||||
|       LOG_INFO("Save transmission_id[{}] with offer sdp[{}]", transmission_id, | ||||
|                sdp); | ||||
|       // ws_handle_manager_.BindHandleToConnection(hdl, ); | ||||
|       offer_sdp_map_[transport_id] = sdp; | ||||
|       offer_hdl_map_[transport_id] = hdl; | ||||
|       offer_sdp_map_[transmission_id] = sdp; | ||||
|       offer_hdl_map_[transmission_id] = hdl; | ||||
|       break; | ||||
|     } | ||||
|     case "query_remote_sdp"_H: { | ||||
|       std::string transport_id = j["transport_id"]; | ||||
|       std::string sdp = offer_sdp_map_[transport_id]; | ||||
|       std::string transmission_id = j["transmission_id"]; | ||||
|       std::string sdp = offer_sdp_map_[transmission_id]; | ||||
|       LOG_INFO("send offer sdp [{}]", sdp.c_str()); | ||||
|       json message = {{"type", "remote_sdp"}, {"sdp", sdp}}; | ||||
|       send_msg(hdl, message); | ||||
|       break; | ||||
|     } | ||||
|     case "answer"_H: { | ||||
|       std::string transport_id = j["transport_id"]; | ||||
|       std::string transmission_id = j["transmission_id"]; | ||||
|       std::string sdp = j["sdp"]; | ||||
|       LOG_INFO("Save transport_id[{}] with answer sdp[{}]", transport_id, sdp); | ||||
|       answer_sdp_map_[transport_id] = sdp; | ||||
|       answer_hdl_map_[transport_id] = hdl; | ||||
|       LOG_INFO("Save transmission_id[{}] with answer sdp[{}]", transmission_id, | ||||
|                sdp); | ||||
|       answer_sdp_map_[transmission_id] = sdp; | ||||
|       answer_hdl_map_[transmission_id] = hdl; | ||||
|       LOG_INFO("send answer sdp [{}]", sdp.c_str()); | ||||
|       json message = {{"type", "remote_sdp"}, {"sdp", sdp}}; | ||||
|       send_msg(offer_hdl_map_[transport_id], message); | ||||
|       send_msg(offer_hdl_map_[transmission_id], message); | ||||
|       break; | ||||
|     } | ||||
|     case "offer_candidate"_H: { | ||||
|       std::string transport_id = j["transport_id"]; | ||||
|       std::string transmission_id = j["transmission_id"]; | ||||
|       std::string candidate = j["sdp"]; | ||||
|       LOG_INFO("send candidate [{}]", candidate.c_str()); | ||||
|       json message = {{"type", "candidate"}, {"sdp", candidate}}; | ||||
|       send_msg(answer_hdl_map_[transport_id], message); | ||||
|       send_msg(answer_hdl_map_[transmission_id], message); | ||||
|       break; | ||||
|     } | ||||
|     case "answer_candidate"_H: { | ||||
|       std::string transport_id = j["transport_id"]; | ||||
|       std::string transmission_id = j["transmission_id"]; | ||||
|       std::string candidate = j["sdp"]; | ||||
|       LOG_INFO("send candidate [{}]", candidate.c_str()); | ||||
|       json message = {{"type", "candidate"}, {"sdp", candidate}}; | ||||
|       send_msg(offer_hdl_map_[transport_id], message); | ||||
|       send_msg(offer_hdl_map_[transmission_id], message); | ||||
|       break; | ||||
|     } | ||||
|     default: | ||||
|   | ||||
| @@ -4,6 +4,7 @@ | ||||
| #include <functional> | ||||
| #include <map> | ||||
| #include <nlohmann/json.hpp> | ||||
| #include <set> | ||||
| #include <string> | ||||
| #include <websocketpp/config/asio_no_tls.hpp> | ||||
| #include <websocketpp/server.hpp> | ||||
| @@ -43,7 +44,10 @@ class SignalServer { | ||||
|       ws_connections_; | ||||
|   std::map<room_id, connection_id> rooms_; | ||||
|   unsigned int ws_connection_id_ = 0; | ||||
|   std::string transport_id_ = "000000"; | ||||
|   std::string transmission_id_ = "000000"; | ||||
|  | ||||
|   std::set<std::string> transmission_list_; | ||||
|  | ||||
|   std::map<std::string, std::string> offer_sdp_map_; | ||||
|   std::map<std::string, std::string> answer_sdp_map_; | ||||
|   std::map<std::string, websocketpp::connection_hdl> offer_hdl_map_; | ||||
|   | ||||
| @@ -78,14 +78,14 @@ target("signal_server") | ||||
|     add_packages("asio", "nlohmann_json", "spdlog") | ||||
|     add_includedirs("thirdparty/websocketpp/include") | ||||
|  | ||||
| target("offer") | ||||
| target("host") | ||||
|     set_kind("binary") | ||||
|     add_deps("projectx") | ||||
|     add_files("tests/peerconnection/offer.cpp") | ||||
|     add_files("tests/peerconnection/host.cpp") | ||||
|     add_includedirs("src/interface") | ||||
|  | ||||
| target("answer") | ||||
| target("guest") | ||||
|     set_kind("binary") | ||||
|     add_deps("projectx") | ||||
|     add_files("tests/peerconnection/answer.cpp") | ||||
|     add_files("tests/peerconnection/guest.cpp") | ||||
|     add_includedirs("src/interface") | ||||
		Reference in New Issue
	
	Block a user