Browse Source

Added Data Channel reliability to C API

Paul-Louis Ageneau 5 years ago
parent
commit
2967444678
2 changed files with 77 additions and 1 deletions
  1. 11 0
      include/rtc/rtc.h
  2. 66 1
      src/rtc.cpp

+ 11 - 0
include/rtc/rtc.h

@@ -78,6 +78,13 @@ typedef struct {
 	uint16_t portRangeEnd;
 } rtcConfiguration;
 
+typedef struct {
+	bool unordered;
+	bool unreliable;
+	unsigned int maxPacketLifeTime; // ignored if reliable
+	unsigned int maxRetransmits;    // ignored if reliable
+} rtcReliability;
+
 typedef void (*rtcLogCallbackFunc)(rtcLogLevel level, const char *message);
 typedef void (*rtcDataChannelCallbackFunc)(int dc, void *ptr);
 typedef void (*rtcDescriptionCallbackFunc)(const char *sdp, const char *type, void *ptr);
@@ -115,9 +122,13 @@ RTC_EXPORT int rtcGetRemoteAddress(int pc, char *buffer, int size);
 
 // DataChannel
 RTC_EXPORT int rtcCreateDataChannel(int pc, const char *label); // returns dc id
+RTC_EXPORT int rtcCreateDataChannelExt(int pc, const char *label, const char *protocol,
+                                       const rtcReliability *reliability); // returns dc id
 RTC_EXPORT int rtcDeleteDataChannel(int dc);
 
 RTC_EXPORT int rtcGetDataChannelLabel(int dc, char *buffer, int size);
+RTC_EXPORT int rtcGetDataChannelProtocol(int dc, char *buffer, int size);
+RTC_EXPORT int rtcGetDataChannelReliability(int dc, rtcReliability *reliability);
 
 // WebSocket
 #if RTC_ENABLE_WEBSOCKET

+ 66 - 1
src/rtc.cpp

@@ -29,6 +29,7 @@
 
 #include "plog/Formatters/FuncMessageFormatter.h"
 
+#include <chrono>
 #include <exception>
 #include <mutex>
 #include <type_traits>
@@ -43,6 +44,7 @@
 using namespace rtc;
 using std::shared_ptr;
 using std::string;
+using std::chrono::milliseconds;
 
 namespace {
 
@@ -241,9 +243,30 @@ int rtcDeletePeerConnection(int pc) {
 }
 
 int rtcCreateDataChannel(int pc, const char *label) {
+	return rtcCreateDataChannelExt(pc, label, nullptr, nullptr);
+}
+
+int rtcCreateDataChannelExt(int pc, const char *label, const char *protocol,
+                            const rtcReliability *reliability) {
 	return WRAP({
+		Reliability r = {};
+		if (reliability) {
+			r.unordered = reliability->unordered;
+			if (reliability->unreliable) {
+				if (reliability->maxPacketLifeTime > 0) {
+					r.type = Reliability::TYPE_PARTIAL_RELIABLE_TIMED;
+					r.rexmit = milliseconds(reliability->maxPacketLifeTime);
+				} else if (reliability->maxRetransmits > 0) {
+					r.type = Reliability::TYPE_PARTIAL_RELIABLE_REXMIT;
+					r.rexmit = int(reliability->maxRetransmits);
+				}
+			} else {
+				r.type = Reliability::TYPE_RELIABLE;
+			}
+		}
 		auto peerConnection = getPeerConnection(pc);
-		int dc = emplaceDataChannel(peerConnection->createDataChannel(string(label)));
+		int dc = emplaceDataChannel(peerConnection->createDataChannel(
+		    string(label ? label : ""), string(protocol ? protocol : ""), r));
 		if (auto ptr = getUserPointer(pc))
 			rtcSetUserPointer(dc, *ptr);
 		return dc;
@@ -447,6 +470,48 @@ int rtcGetDataChannelLabel(int dc, char *buffer, int size) {
 	});
 }
 
+int rtcGetDataChannelProtocol(int dc, char *buffer, int size) {
+	return WRAP({
+		auto dataChannel = getDataChannel(dc);
+
+		if (!buffer)
+			throw std::invalid_argument("Unexpected null pointer");
+
+		if (size <= 0)
+			return 0;
+
+		string protocol = dataChannel->protocol();
+		const char *data = protocol.data();
+		size = std::min(size - 1, int(protocol.size()));
+		std::copy(data, data + size, buffer);
+		buffer[size] = '\0';
+		return int(size + 1);
+	});
+}
+
+int rtcGetDataChannelReliability(int dc, rtcReliability *reliability) {
+	return WRAP({
+		auto dataChannel = getDataChannel(dc);
+
+		if (!reliability)
+			throw std::invalid_argument("Unexpected null pointer");
+
+		Reliability r = dataChannel->reliability();
+		std::memset(reliability, sizeof(*reliability), 0);
+		reliability->unordered = r.unordered;
+		if (r.type == Reliability::TYPE_PARTIAL_RELIABLE_TIMED) {
+			reliability->unreliable = true;
+			reliability->maxPacketLifeTime = std::get<milliseconds>(r.rexmit).count();
+		} else if (r.type == Reliability::TYPE_PARTIAL_RELIABLE_REXMIT) {
+			reliability->unreliable = true;
+			reliability->maxRetransmits = unsigned(std::get<int>(r.rexmit));
+		} else {
+			reliability->unreliable = false;
+		}
+		return 0;
+	});
+}
+
 int rtcSetOpenCallback(int id, rtcOpenCallbackFunc cb) {
 	return WRAP({
 		auto channel = getChannel(id);