Browse Source

Added support for deprecated PPIDs String Partial and Binary Partial

Paul-Louis Ageneau 5 years ago
parent
commit
e77586fc81
2 changed files with 51 additions and 12 deletions
  1. 45 12
      src/sctptransport.cpp
  2. 6 0
      src/sctptransport.hpp

+ 45 - 12
src/sctptransport.cpp

@@ -97,7 +97,8 @@ SctpTransport::SctpTransport(std::shared_ptr<Transport> lower, uint16_t port,
 		throw std::runtime_error("Could not subscribe to event SCTP_STREAM_RESET_EVENT, errno=" +
 		throw std::runtime_error("Could not subscribe to event SCTP_STREAM_RESET_EVENT, errno=" +
 		                         std::to_string(errno));
 		                         std::to_string(errno));
 
 
-	// Disable Nagle-like algorithm to reduce delay
+	// The sender SHOULD disable the Nagle algorithm (see [RFC1122]) to minimize the latency.
+	// See https://tools.ietf.org/html/draft-ietf-rtcweb-data-channel-13#section-6.6
 	int nodelay = 1;
 	int nodelay = 1;
 	if (usrsctp_setsockopt(mSock, IPPROTO_SCTP, SCTP_NODELAY, &nodelay, sizeof(nodelay)))
 	if (usrsctp_setsockopt(mSock, IPPROTO_SCTP, SCTP_NODELAY, &nodelay, sizeof(nodelay)))
 		throw std::runtime_error("Could not set socket option SCTP_NODELAY, errno=" +
 		throw std::runtime_error("Could not set socket option SCTP_NODELAY, errno=" +
@@ -361,31 +362,63 @@ int SctpTransport::handleWrite(void *data, size_t len, uint8_t tos, uint8_t set_
 }
 }
 
 
 void SctpTransport::processData(const byte *data, size_t len, uint16_t sid, PayloadId ppid) {
 void SctpTransport::processData(const byte *data, size_t len, uint16_t sid, PayloadId ppid) {
-	Message::Type type;
+	// The usage of the PPIDs "WebRTC String Partial" and "WebRTC Binary Partial" is deprecated.
+	// See https://tools.ietf.org/html/draft-ietf-rtcweb-data-channel-13#section-6.6
+	// We handle them at reception for compatibility reasons but should never send them.
 	switch (ppid) {
 	switch (ppid) {
+	case PPID_CONTROL:
+		recv(make_message(data, data + len, Message::Control, sid));
+		break;
+
+	case PPID_STRING_PARTIAL: // deprecated
+		mPartialStringData.insert(mPartialStringData.end(), data, data + len);
+		break;
+
 	case PPID_STRING:
 	case PPID_STRING:
-		type = Message::String;
+		if (mPartialStringData.empty()) {
+			recv(make_message(data, data + len, Message::String, sid));
+		} else {
+			mPartialStringData.insert(mPartialStringData.end(), data, data + len);
+			recv(make_message(mPartialStringData.begin(), mPartialStringData.end(), Message::String,
+			                  sid));
+			mPartialStringData.clear();
+		}
 		break;
 		break;
+
 	case PPID_STRING_EMPTY:
 	case PPID_STRING_EMPTY:
-		type = Message::String;
-		len = 0;
+		// This only accounts for when the partial data is empty
+		recv(make_message(mPartialStringData.begin(), mPartialStringData.end(), Message::String,
+		                  sid));
+		mPartialStringData.clear();
 		break;
 		break;
+
+	case PPID_BINARY_PARTIAL: // deprecated
+		mPartialBinaryData.insert(mPartialBinaryData.end(), data, data + len);
+		break;
+
 	case PPID_BINARY:
 	case PPID_BINARY:
-		type = Message::Binary;
+		if (mPartialBinaryData.empty()) {
+			recv(make_message(data, data + len, Message::Binary, sid));
+		} else {
+			mPartialBinaryData.insert(mPartialBinaryData.end(), data, data + len);
+			recv(make_message(mPartialBinaryData.begin(), mPartialBinaryData.end(), Message::Binary,
+			                  sid));
+			mPartialBinaryData.clear();
+		}
 		break;
 		break;
+
 	case PPID_BINARY_EMPTY:
 	case PPID_BINARY_EMPTY:
-		type = Message::Binary;
-		len = 0;
-		break;
-	case PPID_CONTROL:
-		type = Message::Control;
+		// This only accounts for when the partial data is empty
+		recv(make_message(mPartialBinaryData.begin(), mPartialBinaryData.end(), Message::Binary,
+		                  sid));
+		mPartialBinaryData.clear();
 		break;
 		break;
+
 	default:
 	default:
 		// Unknown
 		// Unknown
 		std::cerr << "Unknown PPID: " << uint32_t(ppid) << std::endl;
 		std::cerr << "Unknown PPID: " << uint32_t(ppid) << std::endl;
 		return;
 		return;
 	}
 	}
-	recv(make_message(data, data + len, type, sid));
 }
 }
 
 
 void SctpTransport::processNotification(const union sctp_notification *notify, size_t len) {
 void SctpTransport::processNotification(const union sctp_notification *notify, size_t len) {

+ 6 - 0
src/sctptransport.hpp

@@ -54,10 +54,14 @@ public:
 	void reset(unsigned int stream);
 	void reset(unsigned int stream);
 
 
 private:
 private:
+	// Order seems wrong but these are the actual values
+	// See https://tools.ietf.org/html/draft-ietf-rtcweb-data-channel-13#section-8
 	enum PayloadId : uint32_t {
 	enum PayloadId : uint32_t {
 		PPID_CONTROL = 50,
 		PPID_CONTROL = 50,
 		PPID_STRING = 51,
 		PPID_STRING = 51,
+		PPID_BINARY_PARTIAL = 52,
 		PPID_BINARY = 53,
 		PPID_BINARY = 53,
+		PPID_STRING_PARTIAL = 54,
 		PPID_STRING_EMPTY = 56,
 		PPID_STRING_EMPTY = 56,
 		PPID_BINARY_EMPTY = 57
 		PPID_BINARY_EMPTY = 57
 	};
 	};
@@ -95,6 +99,8 @@ private:
 	state_callback mStateChangeCallback;
 	state_callback mStateChangeCallback;
 	std::atomic<State> mState;
 	std::atomic<State> mState;
 
 
+	binary mPartialStringData, mPartialBinaryData;
+
 	static int RecvCallback(struct socket *sock, union sctp_sockstore addr, void *data, size_t len,
 	static int RecvCallback(struct socket *sock, union sctp_sockstore addr, void *data, size_t len,
 	                        struct sctp_rcvinfo recv_info, int flags, void *user_data);
 	                        struct sctp_rcvinfo recv_info, int flags, void *user_data);
 	static int SendCallback(struct socket *sock, uint32_t sb_free);
 	static int SendCallback(struct socket *sock, uint32_t sb_free);