Przeglądaj źródła

Added WebSocketServer to C API

Paul-Louis Ageneau 4 lat temu
rodzic
commit
5b532f7ab4

+ 30 - 6
include/rtc/rtc.h

@@ -306,21 +306,23 @@ RTC_EXPORT int rtcGetPreviousTrackSenderReportTimestamp(int id, uint32_t *timest
 // Set NeedsToReport flag in RtcpSrReporter handler identified by given track id
 RTC_EXPORT int rtcSetNeedsToSendRtcpSr(int id);
 
-/// Get all available payload types for given codec and stores them in buffer, does nothing if buffer is NULL
-int rtcGetTrackPayloadTypesForCodec(int tr, const char * ccodec, int * buffer, int size);
+/// Get all available payload types for given codec and stores them in buffer, does nothing if
+/// buffer is NULL
+int rtcGetTrackPayloadTypesForCodec(int tr, const char *ccodec, int *buffer, int size);
 
 /// Get all SSRCs for given track
-int rtcGetSsrcsForTrack(int tr, uint32_t * buffer, int count);
+int rtcGetSsrcsForTrack(int tr, uint32_t *buffer, int count);
 
 /// Get CName for SSRC
-int rtcGetCNameForSsrc(int tr, uint32_t ssrc, char * cname, int cnameSize);
+int rtcGetCNameForSsrc(int tr, uint32_t ssrc, char *cname, int cnameSize);
 
 /// Get all SSRCs for given media type in given SDP
 /// @param mediaType Media type (audio/video)
-int rtcGetSsrcsForType(const char * mediaType, const char * sdp, uint32_t * buffer, int bufferSize);
+int rtcGetSsrcsForType(const char *mediaType, const char *sdp, uint32_t *buffer, int bufferSize);
 
 /// Set SSRC for given media type in given SDP
-int rtcSetSsrcForType(const char * mediaType, const char * sdp, char * buffer, const int bufferSize, rtcSsrcForTypeInit * init);
+int rtcSetSsrcForType(const char *mediaType, const char *sdp, char *buffer, const int bufferSize,
+                      rtcSsrcForTypeInit *init);
 
 #endif // RTC_ENABLE_MEDIA
 
@@ -336,6 +338,28 @@ RTC_EXPORT int rtcCreateWebSocket(const char *url); // returns ws id
 RTC_EXPORT int rtcCreateWebSocketEx(const char *url, const rtcWsConfiguration *config);
 RTC_EXPORT int rtcDeleteWebsocket(int ws);
 
+RTC_EXPORT int rtcGetWebSocketRemoteAddress(int ws, char *buffer, int size);
+RTC_EXPORT int rtcGetWebSocketPath(int ws, char *buffer, int size);
+
+// WebSocketServer
+
+typedef void(RTC_API *rtcWebSocketClientCallbackFunc)(int wsserver, int ws, void *ptr);
+
+typedef struct {
+	uint16_t port;                  // 0 means automatic selection
+	bool enableTls;                 // if true, enable TLS (WSS)
+	const char *certificatePemFile; // NULL for autogenerated certificate
+	const char *keyPemFile;         // NULL for autogenerated certificate
+	const char *keyPemPass;         // NULL if no pass
+} rtcWsServerConfiguration;
+
+RTC_EXPORT int rtcCreateWebSocketServer(const rtcWsServerConfiguration *config,
+                                        rtcWebSocketClientCallbackFunc cb); // returns wsserver id
+RTC_EXPORT int rtcDeleteWebsocketServer(int wsserver);
+
+RTC_EXPORT int rtcSetWebSocketClientCallback(int wsserver, rtcWebSocketClientCallbackFunc cb);
+RTC_EXPORT int rtcGetWebSocketServerPort(int wsserver);
+
 #endif
 
 // DataChannel, Track, and WebSocket common API

+ 1 - 1
include/rtc/websocketserver.hpp

@@ -36,7 +36,7 @@ class RTC_CPP_EXPORT WebSocketServer final : private CheshireCat<impl::WebSocket
 public:
 	struct Configuration {
 		uint16_t port = 8080;
-		bool secure = false;
+		bool enableTls = false;
 		optional<string> certificatePemFile;
 		optional<string> keyPemFile;
 		optional<string> keyPemPass;

+ 118 - 22
src/capi.cpp

@@ -43,6 +43,7 @@ std::unordered_map<int, shared_ptr<RtpPacketizationConfig>> rtpConfigMap;
 #endif
 #if RTC_ENABLE_WEBSOCKET
 std::unordered_map<int, shared_ptr<WebSocket>> webSocketMap;
+std::unordered_map<int, shared_ptr<WebSocketServer>> webSocketServerMap;
 #endif
 std::unordered_map<int, void *> userPointerMap;
 std::mutex mutex;
@@ -193,6 +194,7 @@ createRtpPacketizationConfig(const rtcPacketizationHandlerInit *init) {
 #endif // RTC_ENABLE_MEDIA
 
 #if RTC_ENABLE_WEBSOCKET
+
 shared_ptr<WebSocket> getWebSocket(int id) {
 	std::lock_guard lock(mutex);
 	if (auto it = webSocketMap.find(id); it != webSocketMap.end())
@@ -215,6 +217,30 @@ void eraseWebSocket(int ws) {
 		throw std::invalid_argument("WebSocket ID does not exist");
 	userPointerMap.erase(ws);
 }
+
+shared_ptr<WebSocketServer> getWebSocketServer(int id) {
+	std::lock_guard lock(mutex);
+	if (auto it = webSocketServerMap.find(id); it != webSocketServerMap.end())
+		return it->second;
+	else
+		throw std::invalid_argument("WebSocketServer ID does not exist");
+}
+
+int emplaceWebSocketServer(shared_ptr<WebSocketServer> ptr) {
+	std::lock_guard lock(mutex);
+	int wsserver = ++lastId;
+	webSocketServerMap.emplace(std::make_pair(wsserver, ptr));
+	userPointerMap.emplace(std::make_pair(wsserver, nullptr));
+	return wsserver;
+}
+
+void eraseWebSocketServer(int wsserver) {
+	std::lock_guard lock(mutex);
+	if (webSocketServerMap.erase(wsserver) == 0)
+		throw std::invalid_argument("WebSocketServer ID does not exist");
+	userPointerMap.erase(wsserver);
+}
+
 #endif
 
 shared_ptr<Channel> getChannel(int id) {
@@ -268,21 +294,21 @@ int copyAndReturn(binary b, char *buffer, int size) {
 	return int(b.size());
 }
 
-template<typename T>
-int copyAndReturn(std::vector<T> b, T *buffer, int size) {
+template <typename T> int copyAndReturn(std::vector<T> b, T *buffer, int size) {
 	if (!buffer)
 		return int(b.size());
 
 	if (size < int(b.size()))
 		return RTC_ERR_TOO_SMALL;
-    std::copy(b.begin(), b.end(), buffer);
+	std::copy(b.begin(), b.end(), buffer);
 	return int(b.size());
 }
 
 #if RTC_ENABLE_MEDIA
 // function is used in RTC_ENABLE_MEDIA only
 string lowercased(string str) {
-	std::transform(str.begin(), str.end(), str.begin(), [](unsigned char c) { return std::tolower(c); });
+	std::transform(str.begin(), str.end(), str.begin(),
+	               [](unsigned char c) { return std::tolower(c); });
 	return str;
 }
 #endif // RTC_ENABLE_MEDIA
@@ -326,7 +352,7 @@ int rtcCreatePeerConnection(const rtcConfiguration *config) {
 		if (config->maxMessageSize)
 			c.maxMessageSize = size_t(config->maxMessageSize);
 
-		return emplacePeerConnection(std::make_shared<PeerConnection>(c));
+		return emplacePeerConnection(std::make_shared<PeerConnection>(std::move(c)));
 	});
 }
 
@@ -384,9 +410,7 @@ int rtcCreateDataChannelEx(int pc, const char *label, const rtcDataChannelInit *
 }
 
 int rtcIsOpen(int cid) {
-	return wrap([cid] {
-        return getChannel(cid)->isOpen();
-	});
+	return wrap([cid] { return getChannel(cid)->isOpen(); });
 }
 
 int rtcDeleteDataChannel(int dc) {
@@ -527,7 +551,8 @@ int rtcGetTrackDescription(int tr, char *buffer, int size) {
 
 #if RTC_ENABLE_MEDIA
 
-void setSSRC(Description::Media *description, uint32_t ssrc, const char *_name, const char *_msid, const char *_trackID) {
+void setSSRC(Description::Media *description, uint32_t ssrc, const char *_name, const char *_msid,
+             const char *_trackID) {
 
 	optional<string> name = nullopt;
 	if (_name) {
@@ -677,7 +702,7 @@ int rtcSetNeedsToSendRtcpSr(int id) {
 	});
 }
 
-int rtcGetTrackPayloadTypesForCodec(int tr, const char * ccodec, int * buffer, int size) {
+int rtcGetTrackPayloadTypesForCodec(int tr, const char *ccodec, int *buffer, int size) {
 	return wrap([&] {
 		auto track = getTrack(tr);
 		auto codec = lowercased(string(ccodec));
@@ -694,7 +719,7 @@ int rtcGetTrackPayloadTypesForCodec(int tr, const char * ccodec, int * buffer, i
 	});
 }
 
-int rtcGetSsrcsForTrack(int tr, uint32_t * buffer, int count) {
+int rtcGetSsrcsForTrack(int tr, uint32_t *buffer, int count) {
 	return wrap([&] {
 		auto track = getTrack(tr);
 		auto ssrcs = track->description().getSSRCs();
@@ -702,7 +727,7 @@ int rtcGetSsrcsForTrack(int tr, uint32_t * buffer, int count) {
 	});
 }
 
-int rtcGetCNameForSsrc(int tr, uint32_t ssrc, char * cname, int cnameSize) {
+int rtcGetCNameForSsrc(int tr, uint32_t ssrc, char *cname, int cnameSize) {
 	return wrap([&] {
 		auto track = getTrack(tr);
 		auto description = track->description();
@@ -715,7 +740,7 @@ int rtcGetCNameForSsrc(int tr, uint32_t ssrc, char * cname, int cnameSize) {
 	});
 }
 
-int rtcGetSsrcsForType(const char * mediaType, const char * sdp, uint32_t * buffer, int bufferSize) {
+int rtcGetSsrcsForType(const char *mediaType, const char *sdp, uint32_t *buffer, int bufferSize) {
 	return wrap([&] {
 		auto type = lowercased(string(mediaType));
 		auto oldSDP = string(sdp);
@@ -735,8 +760,8 @@ int rtcGetSsrcsForType(const char * mediaType, const char * sdp, uint32_t * buff
 	});
 }
 
-int rtcSetSsrcForType(const char * mediaType, const char * sdp, char * buffer, const int bufferSize,
-					  rtcSsrcForTypeInit * init) {
+int rtcSetSsrcForType(const char *mediaType, const char *sdp, char *buffer, const int bufferSize,
+                      rtcSsrcForTypeInit *init) {
 	return wrap([&] {
 		auto type = lowercased(string(mediaType));
 		auto prevSDP = string(sdp);
@@ -761,19 +786,22 @@ int rtcSetSsrcForType(const char * mediaType, const char * sdp, char * buffer, c
 
 int rtcCreateWebSocket(const char *url) {
 	return wrap([&] {
-		auto ws = std::make_shared<WebSocket>();
-		ws->open(url);
-		return emplaceWebSocket(ws);
+		auto webSocket = std::make_shared<WebSocket>();
+		webSocket->open(url);
+		return emplaceWebSocket(webSocket);
 	});
 }
 
 int rtcCreateWebSocketEx(const char *url, const rtcWsConfiguration *config) {
 	return wrap([&] {
+		if(!url || !config)
+			return RTC_ERR_INVALID;
+
 		WebSocket::Configuration c;
 		c.disableTlsVerification = config->disableTlsVerification;
-		auto ws = std::make_shared<WebSocket>(c);
-		ws->open(url);
-		return emplaceWebSocket(ws);
+		auto webSocket = std::make_shared<WebSocket>(std::move(c));
+		webSocket->open(url);
+		return emplaceWebSocket(webSocket);
 	});
 }
 
@@ -792,6 +820,73 @@ int rtcDeleteWebsocket(int ws) {
 	});
 }
 
+int rtcGetWebSocketRemoteAddress(int ws, char *buffer, int size) {
+	return wrap([&] {
+		auto webSocket = getWebSocket(ws);
+		if (auto remoteAddress = webSocket->remoteAddress())
+			return copyAndReturn(*remoteAddress, buffer, size);
+		else
+			return RTC_ERR_NOT_AVAIL;
+	});
+}
+
+int rtcGetWebSocketPath(int ws, char *buffer, int size) {
+	return wrap([&] {
+		auto webSocket = getWebSocket(ws);
+		if (auto path = webSocket->path())
+			return copyAndReturn(*path, buffer, size);
+		else
+			return RTC_ERR_NOT_AVAIL;
+	});
+}
+
+RTC_EXPORT int rtcCreateWebSocketServer(const rtcWsServerConfiguration *config,
+                                        rtcWebSocketClientCallbackFunc cb) {
+	return wrap([&] {
+		if(!config || !cb)
+			return RTC_ERR_INVALID;
+
+		WebSocketServer::Configuration c;
+		c.port = config->port;
+		c.enableTls = config->enableTls;
+		c.certificatePemFile = config->certificatePemFile
+		                           ? make_optional(string(config->certificatePemFile))
+		                           : nullopt;
+		c.keyPemFile = config->keyPemFile ? make_optional(string(config->keyPemFile)) : nullopt;
+		c.keyPemPass = config->keyPemPass ? make_optional(string(config->keyPemPass)) : nullopt;
+		auto webSocketServer = std::make_shared<WebSocketServer>(std::move(c));
+		int wsserver = emplaceWebSocketServer(webSocketServer);
+
+		webSocketServer->onClient([wsserver, cb](shared_ptr<WebSocket> webSocket) {
+			int ws = emplaceWebSocket(webSocket);
+			if (auto ptr = getUserPointer(wsserver)) {
+				rtcSetUserPointer(wsserver, *ptr);
+				cb(wsserver, ws, *ptr);
+			}
+		});
+
+		return RTC_ERR_SUCCESS;
+	});
+}
+
+RTC_EXPORT int rtcDeleteWebsocketServer(int wsserver) {
+	return wrap([&] {
+		auto webSocketServer = getWebSocketServer(wsserver);
+		webSocketServer->onClient(nullptr);
+		webSocketServer->stop();
+
+		eraseWebSocketServer(wsserver);
+		return RTC_ERR_SUCCESS;
+	});
+}
+
+RTC_EXPORT int rtcGetWebSocketServerPort(int wsserver) {
+	return wrap([&] {
+		auto webSocketServer = getWebSocketServer(wsserver);
+		return int(webSocketServer->port());
+	});
+}
+
 #endif
 
 int rtcSetLocalDescriptionCallback(int pc, rtcDescriptionCallbackFunc cb) {
@@ -1272,7 +1367,8 @@ int rtcSetSctpSettings(const rtcSctpSettings *settings) {
 			s.maxRetransmitTimeout = std::chrono::milliseconds(settings->maxRetransmitTimeoutMs);
 
 		if (settings->initialRetransmitTimeoutMs > 0)
-			s.initialRetransmitTimeout = std::chrono::milliseconds(settings->initialRetransmitTimeoutMs);
+			s.initialRetransmitTimeout =
+			    std::chrono::milliseconds(settings->initialRetransmitTimeoutMs);
 
 		if (settings->maxRetransmitAttempts > 0)
 			s.maxRetransmitAttempts = settings->maxRetransmitAttempts;

+ 1 - 1
src/impl/websocketserver.cpp

@@ -32,7 +32,7 @@ WebSocketServer::WebSocketServer(Configuration config_)
       mStopped(false) {
 	PLOG_VERBOSE << "Creating WebSocketServer";
 
-	if (config.secure) {
+	if (config.enableTls) {
 		if (config.certificatePemFile && config.keyPemFile) {
 			mCertificate = std::make_shared<Certificate>(Certificate::FromFile(
 			    *config.certificatePemFile, *config.keyPemFile, config.keyPemPass.value_or("")));

+ 1 - 1
test/websocketserver.cpp

@@ -38,7 +38,7 @@ void test_websocketserver() {
 
 	WebSocketServer::Configuration serverConfig;
 	serverConfig.port = 48080;
-	serverConfig.secure = true;
+	serverConfig.enableTls = true;
 	// serverConfig.certificatePemFile = ...
 	// serverConfig.keyPemFile = ...
 	WebSocketServer server(std::move(serverConfig));