Browse Source

Fixed late candidates triggering DTLS init twice

Paul-Louis Ageneau 5 years ago
parent
commit
281eea2cec
5 changed files with 32 additions and 9 deletions
  1. 2 0
      include/rtc/peerconnection.hpp
  2. 1 1
      src/dtlstransport.cpp
  3. 19 2
      src/peerconnection.cpp
  4. 8 6
      src/sctptransport.cpp
  5. 2 0
      src/sctptransport.hpp

+ 2 - 0
include/rtc/peerconnection.hpp

@@ -91,6 +91,7 @@ private:
 	std::shared_ptr<DtlsTransport> initDtlsTransport();
 	std::shared_ptr<SctpTransport> initSctpTransport();
 
+	void endLocalCandidates();
 	bool checkFingerprint(const std::string &fingerprint) const;
 	void forwardMessage(message_ptr message);
 	void forwardBufferedAmount(uint16_t stream, size_t amount);
@@ -114,6 +115,7 @@ private:
 	std::shared_ptr<IceTransport> mIceTransport;
 	std::shared_ptr<DtlsTransport> mDtlsTransport;
 	std::shared_ptr<SctpTransport> mSctpTransport;
+	std::recursive_mutex mInitMutex;
 
 	std::unordered_map<unsigned int, std::weak_ptr<DataChannel>> mDataChannels;
 

+ 1 - 1
src/dtlstransport.cpp

@@ -87,7 +87,6 @@ DtlsTransport::DtlsTransport(shared_ptr<IceTransport> lower, shared_ptr<Certific
 DtlsTransport::~DtlsTransport() {
 	stop();
 
-	gnutls_bye(mSession, GNUTLS_SHUT_RDWR);
 	gnutls_deinit(mSession);
 }
 
@@ -98,6 +97,7 @@ void DtlsTransport::stop() {
 
 	if (mRecvThread.joinable()) {
 		mIncomingQueue.stop();
+		gnutls_bye(mSession, GNUTLS_SHUT_RDWR);
 		mRecvThread.join();
 	}
 }

+ 19 - 2
src/peerconnection.cpp

@@ -210,6 +210,10 @@ void PeerConnection::onGatheringStateChange(std::function<void(GatheringState st
 }
 
 shared_ptr<IceTransport> PeerConnection::initIceTransport(Description::Role role) {
+	std::lock_guard lock(mInitMutex);
+	if (auto transport = std::atomic_load(&mIceTransport))
+		return transport;
+
 	auto transport = std::make_shared<IceTransport>(
 	    mConfig, role, std::bind(&PeerConnection::processLocalCandidate, this, _1),
 	    [this](IceTransport::State state) {
@@ -237,8 +241,7 @@ shared_ptr<IceTransport> PeerConnection::initIceTransport(Description::Role role
 			    changeGatheringState(GatheringState::InProgress);
 			    break;
 		    case IceTransport::GatheringState::Complete:
-			    if (mLocalDescription)
-				    mLocalDescription->endCandidates();
+			    endLocalCandidates();
 			    changeGatheringState(GatheringState::Complete);
 			    break;
 		    default:
@@ -251,6 +254,10 @@ shared_ptr<IceTransport> PeerConnection::initIceTransport(Description::Role role
 }
 
 shared_ptr<DtlsTransport> PeerConnection::initDtlsTransport() {
+	std::lock_guard lock(mInitMutex);
+	if (auto transport = std::atomic_load(&mDtlsTransport))
+		return transport;
+
 	auto lower = std::atomic_load(&mIceTransport);
 	auto transport = std::make_shared<DtlsTransport>(
 	    lower, mCertificate, std::bind(&PeerConnection::checkFingerprint, this, _1),
@@ -275,6 +282,10 @@ shared_ptr<DtlsTransport> PeerConnection::initDtlsTransport() {
 }
 
 shared_ptr<SctpTransport> PeerConnection::initSctpTransport() {
+	std::lock_guard lock(mInitMutex);
+	if (auto transport = std::atomic_load(&mSctpTransport))
+		return transport;
+
 	uint16_t sctpPort = remoteDescription()->sctpPort().value_or(DEFAULT_SCTP_PORT);
 	auto lower = std::atomic_load(&mDtlsTransport);
 	auto transport = std::make_shared<SctpTransport>(
@@ -301,6 +312,12 @@ shared_ptr<SctpTransport> PeerConnection::initSctpTransport() {
 	return transport;
 }
 
+void PeerConnection::endLocalCandidates() {
+	std::lock_guard lock(mLocalDescriptionMutex);
+	if (mLocalDescription)
+		mLocalDescription->endCandidates();
+}
+
 bool PeerConnection::checkFingerprint(const std::string &fingerprint) const {
 	std::lock_guard lock(mRemoteDescriptionMutex);
 	if (auto expectedFingerprint =

+ 8 - 6
src/sctptransport.cpp

@@ -145,7 +145,6 @@ SctpTransport::SctpTransport(std::shared_ptr<Transport> lower, uint16_t port,
 SctpTransport::~SctpTransport() {
 	stop();
 
-	usrsctp_shutdown(mSock, SHUT_RDWR);
 	usrsctp_close(mSock);
 	usrsctp_deregister_address(this);
 
@@ -158,12 +157,15 @@ void SctpTransport::stop() {
 	Transport::stop();
 	onRecv(nullptr);
 
-	mSendQueue.stop();
+	if (!mShutdown.exchange(true)) {
+		mSendQueue.stop();
+		usrsctp_shutdown(mSock, SHUT_RDWR);
 
-	// Unblock incoming
-	std::unique_lock<std::mutex> lock(mConnectMutex);
-	mConnectDataSent = true;
-	mConnectCondition.notify_all();
+		// Unblock incoming
+		std::unique_lock<std::mutex> lock(mConnectMutex);
+		mConnectDataSent = true;
+		mConnectCondition.notify_all();
+	}
 }
 
 void SctpTransport::connect() {

+ 2 - 0
src/sctptransport.hpp

@@ -95,6 +95,8 @@ private:
 	std::condition_variable mConnectCondition;
 	bool mConnectDataSent = false;
 
+	std::atomic<bool> mShutdown = false;
+
 	state_callback mStateChangeCallback;
 	std::atomic<State> mState;