瀏覽代碼

Merge pull request #235 from paullouisageneau/auto-mid

Automatically set candidate mid if missing
Paul-Louis Ageneau 4 年之前
父節點
當前提交
dcb0a0282e
共有 7 個文件被更改,包括 54 次插入46 次删除
  1. 6 2
      include/rtc/candidate.hpp
  2. 2 3
      include/rtc/description.hpp
  3. 1 1
      include/rtc/peerconnection.hpp
  4. 30 24
      src/candidate.cpp
  5. 1 1
      src/capi.cpp
  6. 8 6
      src/description.cpp
  7. 6 9
      src/peerconnection.cpp

+ 6 - 2
include/rtc/candidate.hpp

@@ -31,7 +31,11 @@ public:
 	enum class Type { Unknown, Host, ServerReflexive, PeerReflexive, Relayed };
 	enum class TransportType { Unknown, Udp, TcpActive, TcpPassive, TcpSo, TcpUnknown };
 
-	Candidate(string candidate = "", string mid = "");
+	Candidate();
+	Candidate(string candidate);
+	Candidate(string candidate, string mid);
+
+	void hintMid(string mid);
 
 	enum class ResolveMode { Simple, Lookup };
 	bool resolve(ResolveMode mode = ResolveMode::Simple);
@@ -50,7 +54,7 @@ public:
 
 private:
 	string mCandidate;
-	string mMid;
+	std::optional<string> mMid;
 
 	// Extracted on resolution
 	Family mFamily;

+ 2 - 3
include/rtc/description.hpp

@@ -38,9 +38,8 @@ public:
 	enum class Role { ActPass, Passive, Active };
 	enum class Direction { SendOnly, RecvOnly, SendRecv, Inactive, Unknown };
 
-	Description(const string &sdp, const string &typeString = "");
-	Description(const string &sdp, Type type);
-	Description(const string &sdp, Type type, Role role);
+	Description(const string &sdp, Type type = Type::Unspec, Role role = Role::ActPass);
+	Description(const string &sdp, string typeString);
 
 	Type type() const;
 	string typeString() const;

+ 1 - 1
include/rtc/peerconnection.hpp

@@ -75,7 +75,7 @@ public:
 		HaveRemotePranswer = RTC_SIGNALING_HAVE_REMOTE_PRANSWER,
 	} rtcSignalingState;
 
-	PeerConnection(void);
+	PeerConnection();
 	PeerConnection(const Configuration &config);
 	~PeerConnection();
 

+ 30 - 24
src/candidate.cpp

@@ -28,8 +28,8 @@
 #include <ws2tcpip.h>
 #else
 #include <netdb.h>
-#include <sys/socket.h>
 #include <netinet/in.h>
+#include <sys/socket.h>
 #endif
 
 #include <sys/types.h>
@@ -48,23 +48,32 @@ inline bool hasprefix(const string &str, const string &prefix) {
 
 namespace rtc {
 
-Candidate::Candidate(string candidate, string mid)
+Candidate::Candidate()
     : mFamily(Family::Unresolved), mType(Type::Unknown), mTransportType(TransportType::Unknown),
-      mPort(0), mPriority(0) {
+      mPort(0), mPriority(0) {}
 
-	if (!candidate.empty()) {
-		const std::array prefixes{"a=", "candidate:"};
-		for (const string &prefix : prefixes)
-			if (hasprefix(candidate, prefix))
-				candidate.erase(0, prefix.size());
-	}
+Candidate::Candidate(string candidate) : Candidate() {
+	const std::array prefixes{"a=", "candidate:"};
+	for (const string &prefix : prefixes)
+		if (hasprefix(candidate, prefix))
+			candidate.erase(0, prefix.size());
 
 	mCandidate = std::move(candidate);
-	mMid = std::move(mid);
+}
+
+Candidate::Candidate(string candidate, string mid)
+    : Candidate(std::move(candidate)) {
+    if(!mid.empty())
+		mMid.emplace(std::move(mid));
+}
+
+void Candidate::hintMid(string mid) {
+	if (!mMid)
+		mMid.emplace(std::move(mid));
 }
 
 bool Candidate::resolve(ResolveMode mode) {
-	using TypeMap_t = std::unordered_map<string, Type>;	
+	using TypeMap_t = std::unordered_map<string, Type>;
 	using TcpTypeMap_t = std::unordered_map<string, TransportType>;
 
 	static const TypeMap_t TypeMap = {{"host", Type::Host},
@@ -79,12 +88,11 @@ bool Candidate::resolve(ResolveMode mode) {
 	if (mFamily != Family::Unresolved)
 		return true;
 
-	if(mCandidate.empty())
+	if (mCandidate.empty())
 		throw std::logic_error("Candidate is empty");
 
 	PLOG_VERBOSE << "Resolving candidate (mode="
-				 << (mode == ResolveMode::Simple ? "simple" : "lookup")
-				 << "): " << mCandidate;
+	             << (mode == ResolveMode::Simple ? "simple" : "lookup") << "): " << mCandidate;
 
 	// See RFC 8445 for format
 	std::istringstream iss(mCandidate);
@@ -100,17 +108,16 @@ bool Candidate::resolve(ResolveMode mode) {
 			mType = it->second;
 		else
 			mType = Type::Unknown;
-		
+
 		if (transport == "UDP" || transport == "udp") {
 			mTransportType = TransportType::Udp;
-		}
-		else if (transport == "TCP" || transport == "tcp") {
+		} else if (transport == "TCP" || transport == "tcp") {
 			std::istringstream iss(left);
 			string tcptype_, tcptype;
-			if(iss >> tcptype_ >> tcptype && tcptype_ == "tcptype") {
+			if (iss >> tcptype_ >> tcptype && tcptype_ == "tcptype") {
 				if (auto it = TcpTypeMap.find(tcptype); it != TcpTypeMap.end())
 					mTransportType = it->second;
-				else 
+				else
 					mTransportType = TransportType::TcpUnknown;
 
 			} else {
@@ -127,8 +134,7 @@ bool Candidate::resolve(ResolveMode mode) {
 		if (mTransportType == TransportType::Udp) {
 			hints.ai_socktype = SOCK_DGRAM;
 			hints.ai_protocol = IPPROTO_UDP;
-		}
-		else if (mTransportType != TransportType::Unknown) {
+		} else if (mTransportType != TransportType::Unknown) {
 			hints.ai_socktype = SOCK_STREAM;
 			hints.ai_protocol = IPPROTO_TCP;
 		}
@@ -146,11 +152,11 @@ bool Candidate::resolve(ResolveMode mode) {
 					if (getnameinfo(p->ai_addr, socklen_t(p->ai_addrlen), nodebuffer,
 					                MAX_NUMERICNODE_LEN, servbuffer, MAX_NUMERICSERV_LEN,
 					                NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
-						
+
 						mAddress = nodebuffer;
 						mPort = uint16_t(std::stoul(servbuffer));
 						mFamily = p->ai_family == AF_INET6 ? Family::Ipv6 : Family::Ipv4;
-						
+
 						const char sp{' '};
 						std::ostringstream oss;
 						oss << foundation << sp << component << sp << transport << sp << priority;
@@ -173,7 +179,7 @@ bool Candidate::resolve(ResolveMode mode) {
 
 string Candidate::candidate() const { return "candidate:" + mCandidate; }
 
-string Candidate::mid() const { return mMid; }
+string Candidate::mid() const { return mMid.value_or("0"); }
 
 Candidate::operator string() const {
 	std::ostringstream line;

+ 1 - 1
src/capi.cpp

@@ -528,7 +528,7 @@ int rtcSetRemoteDescription(int pc, const char *sdp, const char *type) {
 		if (!sdp)
 			throw std::invalid_argument("Unexpected null pointer for remote description");
 
-		peerConnection->setRemoteDescription({string(sdp), type ? string(type) : ""});
+		peerConnection->setRemoteDescription({string(sdp), type ? string(type) : "" });
 	});
 }
 

+ 8 - 6
src/description.cpp

@@ -66,11 +66,6 @@ template <typename T> T to_integer(string_view s) {
 
 namespace rtc {
 
-Description::Description(const string &sdp, const string &typeString)
-    : Description(sdp, stringToType(typeString)) {}
-
-Description::Description(const string &sdp, Type type) : Description(sdp, type, Role::ActPass) {}
-
 Description::Description(const string &sdp, Type type, Role role)
     : mType(Type::Unspec), mRole(role) {
 	hintType(type);
@@ -141,6 +136,10 @@ Description::Description(const string &sdp, Type type, Role role)
 	}
 }
 
+Description::Description(const string &sdp, string typeString)
+    : Description(sdp, !typeString.empty() ? stringToType(typeString) : Type::Unspec, Role::ActPass) {
+}
+
 Description::Type Description::type() const { return mType; }
 
 string Description::typeString() const { return typeToString(mType); }
@@ -173,12 +172,15 @@ void Description::setFingerprint(string fingerprint) {
 }
 
 void Description::addCandidate(Candidate candidate) {
+	candidate.hintMid(bundleMid());
 	mCandidates.emplace_back(std::move(candidate));
 }
 
 void Description::addCandidates(std::vector<Candidate> candidates) {
-	for(auto candidate : candidates)
+	for(Candidate candidate : candidates) {
+		candidate.hintMid(bundleMid());
 		mCandidates.emplace_back(std::move(candidate));
+	}
 }
 
 void Description::endCandidates() { mEnded = true; }

+ 6 - 9
src/peerconnection.cpp

@@ -1030,9 +1030,12 @@ void PeerConnection::processRemoteDescription(Description description) {
 }
 
 void PeerConnection::processRemoteCandidate(Candidate candidate) {
+	std::lock_guard lock(mRemoteDescriptionMutex);
 	auto iceTransport = std::atomic_load(&mIceTransport);
-	if (!iceTransport)
-		throw std::logic_error("Remote candidate set without remote description");
+	if (!mRemoteDescription || !iceTransport)
+		throw std::logic_error("Got a remote candidate without remote description");
+
+	candidate.hintMid(mRemoteDescription->bundleMid());
 
 	if (candidate.resolve(Candidate::ResolveMode::Simple)) {
 		iceTransport->addRemoteCandidate(candidate);
@@ -1048,13 +1051,7 @@ void PeerConnection::processRemoteCandidate(Candidate candidate) {
 		t.detach();
 	}
 
-	{
-		std::lock_guard lock(mRemoteDescriptionMutex);
-		if (!mRemoteDescription)
-			throw std::logic_error("Got a remote candidate without remote description");
-
-		mRemoteDescription->addCandidate(candidate);
-	}
+	mRemoteDescription->addCandidate(std::move(candidate));
 }
 
 void PeerConnection::triggerDataChannel(weak_ptr<DataChannel> weakDataChannel) {