Quellcode durchsuchen

Fixed SDP handling

Paul-Louis Ageneau vor 6 Jahren
Ursprung
Commit
97c4da46c5

+ 2 - 1
src/candidate.cpp

@@ -69,7 +69,8 @@ Candidate::Candidate(string candidate, string mid) {
 					if (getnameinfo(p->ai_addr, p->ai_addrlen, nodebuffer, MAX_NUMERICNODE_LEN,
 					                servbuffer, MAX_NUMERICSERV_LEN,
 					                NI_NUMERICHOST | NI_NUMERICHOST) == 0) {
-						const string left{ss.str()};
+						string left;
+						std::getline(ss, left);
 						const char sp{' '};
 						ss.clear();
 						ss << foundation << sp << component << sp << transport << sp << priority;

+ 25 - 17
src/description.cpp

@@ -44,14 +44,12 @@ inline void trim_end(string &str) {
 
 namespace rtc {
 
-Description::Description(Role role, const string &mid) : mRole(role), mMid(mid) {
+Description::Description(Role role, const string &sdp) : mRole(role), mMid("0"), mIceUfrag("0"), mIcePwd("0") {
 	auto seed = std::chrono::system_clock::now().time_since_epoch().count();
 	std::default_random_engine generator(seed);
 	std::uniform_int_distribution<uint32_t> uniform;
 	mSessionId = std::to_string(uniform(generator));
-}
 
-Description::Description(const string &sdp) {
 	std::istringstream ss(sdp);
 	string line;
 	while (std::getline(ss, line)) {
@@ -67,13 +65,21 @@ Description::Description(const string &sdp) {
 		} else if (hasprefix(line, "a=mid:")) {
 			mMid = line.substr(line.find(':') + 1);
 		} else if (hasprefix(line, "a=fingerprint:sha-256")) {
-			mFingerprint = line.substr(line.find(':') + 1);
+			mFingerprint = line.substr(line.find(' ') + 1);
+		} else if (hasprefix(line, "a=ice-ufrag")) {
+			mIceUfrag = line.substr(line.find(':') + 1);
+		} else if (hasprefix(line, "a=ice-pwd")) {
+			mIcePwd = line.substr(line.find(':') + 1);
 		}
 	}
 }
 
 Description::Role Description::role() const { return mRole; }
 
+std::optional<string> Description::fingerprint() const {
+	return mFingerprint;
+}
+
 void Description::setFingerprint(const string &fingerprint) { mFingerprint = fingerprint; }
 
 void Description::addCandidate(Candidate candidate) {
@@ -89,19 +95,21 @@ Description::operator string() const {
 		throw std::runtime_error("Fingerprint must be set to generate a SDP");
 
     std::ostringstream sdp;
-	sdp << "v=0\r\n";
-	sdp << "o=- " << mSessionId << " 0 IN IP4 0.0.0.0\r\n";
-	sdp << "s=-\r\n";
-	sdp << "t=0 0\r\n";
-    sdp << "m=application 0 UDP/DTLS/SCTP webrtc-datachannel\r\n";
-    sdp << "c=IN IP4 0.0.0.0\r\n";
-	sdp << "a=ice-options:trickle\r\n";
-	sdp << "a=mid:" << mMid << "\r\n";
-	sdp << "a=setup:" << (mRole == Role::Active ? "active" : "passive") << "\r\n";
-	sdp << "a=dtls-id:1\r\n";
-	sdp << "a=fingerprint:sha-256 " << *mFingerprint << "\r\n";
-    sdp << "a=sctp-port:5000\r\n";
-    // sdp << "a=max-message-size:100000\r\n";
+	sdp << "v=0\n";
+	sdp << "o=- " << mSessionId << " 0 IN IP4 0.0.0.0\n";
+	sdp << "s=-\n";
+	sdp << "t=0 0\n";
+    sdp << "m=application 0 UDP/DTLS/SCTP webrtc-datachannel\n";
+    sdp << "c=IN IP4 0.0.0.0\n";
+	sdp << "a=ice-options:trickle\n";
+	sdp << "a=ice-ufrag:" << mIceUfrag << "\n";
+	sdp << "a=ice-pwd:" << mIcePwd << "\n";
+	sdp << "a=mid:" << mMid << "\n";
+	sdp << "a=setup:" << (mRole == Role::Active ? "active" : "passive") << "\n";
+	sdp << "a=dtls-id:1\n";
+	sdp << "a=fingerprint:sha-256 " << *mFingerprint << "\n";
+    sdp << "a=sctp-port:5000\n";
+    // sdp << "a=max-message-size:100000\n";
 
 	for (const auto &candidate : mCandidates) {
 		sdp << "a=candidate:" << string(candidate);

+ 3 - 2
src/description.hpp

@@ -32,10 +32,10 @@ class Description {
 public:
 	enum class Role { Passive, Active, ActPass };
 
-	Description(Role role, const string &mid = "0");
-	Description(const string &sdp);
+	Description(Role role, const string &sdp);
 
 	Role role() const;
+	std::optional<string> fingerprint() const;
 
 	void setFingerprint(const string &fingerprint);
 	void addCandidate(Candidate candidate);
@@ -47,6 +47,7 @@ private:
 	Role mRole = Role::Passive;
 	string mSessionId;
 	string mMid;
+	string mIceUfrag, mIcePwd;
 	std::optional<string> mFingerprint;
 
 	std::vector<Candidate> mCandidates;

+ 1 - 2
src/dtlstransport.cpp

@@ -92,8 +92,7 @@ bool DtlsTransport::send(message_ptr message) {
 void DtlsTransport::incoming(message_ptr message) { mIncomingQueue.push(message); }
 
 void DtlsTransport::runRecvLoop() {
-	while (!check_gnutls(gnutls_handshake(mSession), "TLS handshake failed")) {
-	}
+	while (!check_gnutls(gnutls_handshake(mSession), "TLS handshake failed")) {}
 
 	mReadyCallback();
 

+ 4 - 3
src/icetransport.cpp

@@ -40,7 +40,7 @@ IceTransport::IceTransport(const IceConfiguration &config, Description::Role rol
 
 	auto logLevelFlags = GLogLevelFlags(G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION);
 	g_log_set_handler(nullptr, logLevelFlags, LogCallback, this);
-	nice_debug_disable(true);
+	nice_debug_enable(false);
 
 	mMainLoop = decltype(mMainLoop)(g_main_loop_new(nullptr, FALSE), g_main_loop_unref);
 	if (!mMainLoop)
@@ -127,7 +127,7 @@ IceTransport::State IceTransport::state() const { return mState; }
 Description IceTransport::getLocalDescription() const {
 	std::unique_ptr<gchar[], void (*)(void *)> sdp(nice_agent_generate_local_sdp(mNiceAgent.get()),
 	                                               g_free);
-	return Description(string(sdp.get()));
+	return Description(mRole, string(sdp.get()));
 }
 
 void IceTransport::setRemoteDescription(const Description &description) {
@@ -180,8 +180,9 @@ void IceTransport::processGatheringDone() { mCandidateCallback(nullopt); }
 
 void IceTransport::changeState(uint32_t state) {
 	mState = static_cast<State>(state);
-	if (mState == State::CONNECTED)
+	if (mState == State::READY) {
 		mReadyCallback();
+	}
 }
 
 string IceTransport::getStreamName() const {

+ 1 - 1
src/icetransport.hpp

@@ -43,7 +43,7 @@ public:
 		GATHERING = NICE_COMPONENT_STATE_GATHERING,
 		CONNECTING = NICE_COMPONENT_STATE_CONNECTING,
 		CONNECTED = NICE_COMPONENT_STATE_CONNECTED,
-		COMPLETED = NICE_COMPONENT_STATE_READY,
+		READY = NICE_COMPONENT_STATE_READY,
 		FAILED = NICE_COMPONENT_STATE_FAILED
 	};
 

+ 5 - 2
src/peerconnection.cpp

@@ -23,7 +23,6 @@
 
 #include <chrono>
 #include <random>
-#include <sstream>
 
 namespace rtc {
 
@@ -42,7 +41,11 @@ const IceConfiguration *PeerConnection::config() const { return &mConfig; }
 const Certificate *PeerConnection::certificate() const { return &mCertificate; }
 
 void PeerConnection::setRemoteDescription(const string &description) {
-	Description desc(description);
+	Description desc(Description::Role::ActPass, description);
+
+	if(auto fingerprint = desc.fingerprint())
+		mRemoteFingerprint.emplace(*fingerprint);
+
 	if (!mIceTransport) {
 		initIceTransport(Description::Role::ActPass);
 		mIceTransport->setRemoteDescription(desc);

+ 32 - 41
src/sctptransport.cpp

@@ -43,18 +43,17 @@ SctpTransport::SctpTransport(std::shared_ptr<Transport> lower, ready_callback re
 	if (!mSock)
 		throw std::runtime_error("Could not create usrsctp socket, errno=" + std::to_string(errno));
 
-	struct linger linger_opt = {};
-	linger_opt.l_onoff = 1;
-	linger_opt.l_linger = 0;
-	if (usrsctp_setsockopt(mSock, SOL_SOCKET, SO_LINGER, &linger_opt, sizeof(linger_opt)))
+	struct linger sol = {};
+	sol.l_onoff = 1;
+	sol.l_linger = 0;
+	if (usrsctp_setsockopt(mSock, SOL_SOCKET, SO_LINGER, &sol, sizeof(sol)))
 		throw std::runtime_error("Could not set socket option SO_LINGER, errno=" +
 		                         std::to_string(errno));
 
-	struct sctp_paddrparams peer_param = {};
-	peer_param.spp_flags = SPP_PMTUD_DISABLE;
-	peer_param.spp_pathmtu = 1200; // TODO: MTU
-	if (usrsctp_setsockopt(mSock, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, &peer_param,
-	                       sizeof(peer_param)))
+	struct sctp_paddrparams spp = {};
+	spp.spp_flags = SPP_PMTUD_DISABLE;
+	spp.spp_pathmtu = 1200; // TODO: MTU
+	if (usrsctp_setsockopt(mSock, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, &spp, sizeof(spp)))
 		throw std::runtime_error("Could not set socket option SCTP_PEER_ADDR_PARAMS, errno=" +
 		                         std::to_string(errno));
 
@@ -70,35 +69,25 @@ SctpTransport::SctpTransport(std::shared_ptr<Transport> lower, ready_callback re
 		throw std::runtime_error("Could not set socket option SCTP_NODELAY, errno=" +
 		                         std::to_string(errno));
 
-	const static uint16_t interested_events[] = {
-	    SCTP_ASSOC_CHANGE,          SCTP_PEER_ADDR_CHANGE,       SCTP_REMOTE_ERROR,
-	    SCTP_SEND_FAILED,           SCTP_SENDER_DRY_EVENT,       SCTP_SHUTDOWN_EVENT,
-	    SCTP_ADAPTATION_INDICATION, SCTP_PARTIAL_DELIVERY_EVENT, SCTP_AUTHENTICATION_EVENT,
-	    SCTP_STREAM_RESET_EVENT,    SCTP_ASSOC_RESET_EVENT,      SCTP_STREAM_CHANGE_EVENT,
-	    SCTP_SEND_FAILED_EVENT};
-
-	struct sctp_event event = {};
-	event.se_assoc_id = SCTP_ALL_ASSOC;
-	event.se_on = 1;
-	int num_events = sizeof(interested_events) / sizeof(uint16_t);
-	for (int i = 0; i < num_events; ++i) {
-		event.se_type = interested_events[i];
-		if (usrsctp_setsockopt(mSock, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(event)))
-			throw std::runtime_error("Could not set socket option SCTP_EVENT, errno=" +
-			                         std::to_string(errno));
-	}
+	struct sctp_event se = {};
+	se.se_assoc_id = SCTP_ALL_ASSOC;
+	se.se_on = 1;
+	se.se_type = SCTP_STREAM_RESET_EVENT;
+	if (usrsctp_setsockopt(mSock, IPPROTO_SCTP, SCTP_EVENT, &se, sizeof(se)))
+		throw std::runtime_error("Could not set socket option SCTP_EVENT, errno=" +
+		                         std::to_string(errno));
 
-	struct sctp_initmsg init_msg = {};
-	init_msg.sinit_num_ostreams = 0xFF;
-	init_msg.sinit_max_instreams = 0xFF;
-	if (usrsctp_setsockopt(mSock, IPPROTO_SCTP, SCTP_INITMSG, &init_msg, sizeof(init_msg)))
+	struct sctp_initmsg sinit = {};
+	sinit.sinit_num_ostreams = 0xFF;
+	sinit.sinit_max_instreams = 0xFF;
+	if (usrsctp_setsockopt(mSock, IPPROTO_SCTP, SCTP_INITMSG, &sinit, sizeof(sinit)))
 		throw std::runtime_error("Could not set socket option SCTP_INITMSG, errno=" +
 		                         std::to_string(errno));
 
 	struct sockaddr_conn sconn = {};
 	sconn.sconn_family = AF_CONN;
-	sconn.sconn_port = htons(mRemotePort);
-	sconn.sconn_addr = (void *)this;
+	sconn.sconn_port = htons(mLocalPort);
+	sconn.sconn_addr = this;
 #ifdef HAVE_SCONN_LEN
 	sconn.sconn_len = sizeof(sconn);
 #endif
@@ -268,14 +257,14 @@ bool SctpTransport::send(message_ptr message) {
 }
 
 void SctpTransport::reset(unsigned int stream) {
-	using reset_streams_t = struct sctp_reset_streams;
-	const size_t len = sizeof(reset_streams_t) + sizeof(uint16_t);
+	using srs_t = struct sctp_reset_streams;
+	const size_t len = sizeof(srs_t) + sizeof(uint16_t);
 	std::byte buffer[len] = {};
-	reset_streams_t &reset_streams = *reinterpret_cast<reset_streams_t *>(buffer);
-	reset_streams.srs_flags = SCTP_STREAM_RESET_OUTGOING;
-	reset_streams.srs_number_streams = 1;
-	reset_streams.srs_stream_list[0] = uint16_t(stream);
-	usrsctp_setsockopt(mSock, IPPROTO_SCTP, SCTP_RESET_STREAMS, &reset_streams, len);
+	srs_t &srs = *reinterpret_cast<srs_t *>(buffer);
+	srs.srs_flags = SCTP_STREAM_RESET_OUTGOING;
+	srs.srs_number_streams = 1;
+	srs.srs_stream_list[0] = uint16_t(stream);
+	usrsctp_setsockopt(mSock, IPPROTO_SCTP, SCTP_RESET_STREAMS, &srs, len);
 }
 
 void SctpTransport::incoming(message_ptr message) {
@@ -293,11 +282,13 @@ void SctpTransport::runConnect() {
 
 	// Blocks until connection succeeds/fails
 	if (usrsctp_connect(mSock, reinterpret_cast<struct sockaddr *>(&sconn), sizeof(sconn)) != 0) {
+		std::cerr << "SCTP connection failed, errno=" << errno << std::endl;
 		mStopping = true;
 		return;
 	}
 
-        mIsReady = true;
-        mReadyCallback();
+    mIsReady = true;
+    mReadyCallback();
 }
+
 } // namespace rtc