Browse Source

Reduced SCTP retransmission count and max RTO

Paul-Louis Ageneau 5 years ago
parent
commit
f930cfbe44
5 changed files with 49 additions and 17 deletions
  1. 2 4
      src/datachannel.cpp
  2. 27 13
      src/dtlstransport.cpp
  3. 2 0
      src/peerconnection.cpp
  4. 17 0
      src/sctptransport.cpp
  5. 1 0
      src/sctptransport.hpp

+ 2 - 4
src/datachannel.cpp

@@ -79,10 +79,8 @@ DataChannel::~DataChannel() {
 
 void DataChannel::close() {
 	mIsClosed = true;
-	if (mIsOpen.exchange(false))
-		if (mSctpTransport)
-			mSctpTransport->reset(mStream);
-
+	if (mIsOpen.exchange(false) && mSctpTransport)
+		mSctpTransport->reset(mStream);
 	mSctpTransport.reset();
 }
 

+ 27 - 13
src/dtlstransport.cpp

@@ -20,10 +20,13 @@
 #include "icetransport.hpp"
 
 #include <cassert>
+#include <chrono>
 #include <cstring>
 #include <exception>
 #include <iostream>
 
+using namespace std::chrono;
+
 using std::shared_ptr;
 using std::string;
 using std::unique_ptr;
@@ -123,7 +126,12 @@ bool DtlsTransport::send(message_ptr message) {
 	return check_gnutls(ret);
 }
 
-void DtlsTransport::incoming(message_ptr message) { mIncomingQueue.push(message); }
+void DtlsTransport::incoming(message_ptr message) {
+	if (message)
+		mIncomingQueue.push(message);
+	else
+		mIncomingQueue.stop();
+}
 
 void DtlsTransport::changeState(State state) {
 	if (mState.exchange(state) != state)
@@ -188,6 +196,7 @@ void DtlsTransport::runRecvLoop() {
 		PLOG_ERROR << "DTLS recv: " << e.what();
 	}
 
+	PLOG_INFO << "DTLS disconnected";
 	changeState(State::Disconnected);
 	recv(nullptr);
 }
@@ -232,24 +241,22 @@ ssize_t DtlsTransport::WriteCallback(gnutls_transport_ptr_t ptr, const void *dat
 
 ssize_t DtlsTransport::ReadCallback(gnutls_transport_ptr_t ptr, void *data, size_t maxlen) {
 	DtlsTransport *t = static_cast<DtlsTransport *>(ptr);
-	auto next = t->mIncomingQueue.pop();
-	auto message = next ? *next : nullptr;
-	if (!message) {
-		// Closed
+	if (auto next = t->mIncomingQueue.pop()) {
+		auto message = *next;
+		ssize_t len = std::min(maxlen, message->size());
+		std::memcpy(data, message->data(), len);
 		gnutls_transport_set_errno(t->mSession, 0);
-		return 0;
+		return len;
 	}
-
-	ssize_t len = std::min(maxlen, message->size());
-	std::memcpy(data, message->data(), len);
+	// Closed
 	gnutls_transport_set_errno(t->mSession, 0);
-	return len;
+	return 0;
 }
 
 int DtlsTransport::TimeoutCallback(gnutls_transport_ptr_t ptr, unsigned int ms) {
 	DtlsTransport *t = static_cast<DtlsTransport *>(ptr);
 	if (ms != GNUTLS_INDEFINITE_TIMEOUT)
-		t->mIncomingQueue.wait(std::chrono::milliseconds(ms));
+		t->mIncomingQueue.wait(milliseconds(ms));
 	else
 		t->mIncomingQueue.wait();
 	return !t->mIncomingQueue.empty() ? 1 : 0;
@@ -293,7 +300,7 @@ bool check_openssl_ret(SSL *ssl, int ret, const string &message = "OpenSSL error
 		return true;
 	}
 	if (err == SSL_ERROR_ZERO_RETURN) {
-		PLOG_INFO << "The TLS connection has been cleanly closed";
+		PLOG_DEBUG << "The TLS connection has been cleanly closed";
 		return false;
 	}
 	string str = openssl_error_string(err);
@@ -414,7 +421,12 @@ bool DtlsTransport::send(message_ptr message) {
 	return true;
 }
 
-void DtlsTransport::incoming(message_ptr message) { mIncomingQueue.push(message); }
+void DtlsTransport::incoming(message_ptr message) {
+	if (message)
+		mIncomingQueue.push(message);
+	else
+		mIncomingQueue.stop();
+}
 
 void DtlsTransport::changeState(State state) {
 	if (mState.exchange(state) != state)
@@ -466,9 +478,11 @@ void DtlsTransport::runRecvLoop() {
 	}
 
 	if (mState == State::Connected) {
+		PLOG_INFO << "DTLS disconnected";
 		changeState(State::Disconnected);
 		recv(nullptr);
 	} else {
+		PLOG_INFO << "DTLS handshake failed";
 		changeState(State::Failed);
 	}
 }

+ 2 - 0
src/peerconnection.cpp

@@ -298,9 +298,11 @@ shared_ptr<SctpTransport> PeerConnection::initSctpTransport() {
 			    openDataChannels();
 			    break;
 		    case SctpTransport::State::Failed:
+			    remoteCloseDataChannels();
 			    changeState(State::Failed);
 			    break;
 		    case SctpTransport::State::Disconnected:
+			    remoteCloseDataChannels();
 			    changeState(State::Disconnected);
 			    break;
 		    default:

+ 17 - 0
src/sctptransport.cpp

@@ -37,6 +37,14 @@ void SctpTransport::GlobalInit() {
 	if (InstancesCount++ == 0) {
 		usrsctp_init(0, &SctpTransport::WriteCallback, nullptr);
 		usrsctp_sysctl_set_sctp_ecn_enable(0);
+		usrsctp_sysctl_set_sctp_init_rtx_max_default(5);
+		usrsctp_sysctl_set_sctp_path_rtx_max_default(5);
+		usrsctp_sysctl_set_sctp_assoc_rtx_max_default(5);              // single path
+		usrsctp_sysctl_set_sctp_rto_min_default(1 * 1000);             // ms
+		usrsctp_sysctl_set_sctp_rto_max_default(10 * 1000);            // ms
+		usrsctp_sysctl_set_sctp_rto_initial_default(1 * 1000);         // ms
+		usrsctp_sysctl_set_sctp_init_rto_max_default(10 * 1000);       // ms
+		usrsctp_sysctl_set_sctp_heartbeat_interval_default(10 * 1000); // ms
 	}
 }
 
@@ -159,6 +167,7 @@ void SctpTransport::stop() {
 	onRecv(nullptr);
 
 	if (!mShutdown.exchange(true)) {
+		flush();
 		mSendQueue.stop();
 		usrsctp_shutdown(mSock, SHUT_RDWR);
 
@@ -206,6 +215,11 @@ bool SctpTransport::send(message_ptr message) {
 	return false;
 }
 
+void SctpTransport::flush() {
+	std::lock_guard lock(mSendMutex);
+	trySendQueue();
+}
+
 void SctpTransport::reset(unsigned int stream) {
 	using srs_t = struct sctp_reset_streams;
 	const size_t len = sizeof(srs_t) + sizeof(uint16_t);
@@ -334,6 +348,7 @@ int SctpTransport::handleRecv(struct socket *sock, union sctp_sockstore addr, co
                               size_t len, struct sctp_rcvinfo info, int flags) {
 	try {
 		if (!data) {
+			PLOG_INFO << "SCTP connection closed";
 			recv(nullptr);
 			return 0;
 		}
@@ -454,12 +469,14 @@ void SctpTransport::processNotification(const union sctp_notification *notify, s
 	case SCTP_ASSOC_CHANGE: {
 		const struct sctp_assoc_change &assoc_change = notify->sn_assoc_change;
 		if (assoc_change.sac_state == SCTP_COMM_UP) {
+			PLOG_INFO << "SCTP connected";
 			changeState(State::Connected);
 		} else {
 			if (mState == State::Connecting) {
 				PLOG_ERROR << "SCTP connection failed";
 				changeState(State::Failed);
 			} else {
+				PLOG_INFO << "SCTP disconnected";
 				changeState(State::Disconnected);
 			}
 		}

+ 1 - 0
src/sctptransport.hpp

@@ -52,6 +52,7 @@ public:
 
 	void stop() override;
 	bool send(message_ptr message) override; // false if buffered
+	void flush();
 	void reset(unsigned int stream);
 
 private: