Browse Source

Added C API WebSocketServer test

Paul-Louis Ageneau 4 years ago
parent
commit
8cd3b9e362
5 changed files with 194 additions and 9 deletions
  1. 1 0
      CMakeLists.txt
  2. 2 2
      include/rtc/rtc.h
  3. 13 7
      src/capi.cpp
  4. 169 0
      test/capi_websocketserver.cpp
  5. 9 0
      test/main.cpp

+ 1 - 0
CMakeLists.txt

@@ -167,6 +167,7 @@ set(TESTS_SOURCES
     ${CMAKE_CURRENT_SOURCE_DIR}/test/capi_track.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/test/capi_track.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/test/websocket.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/test/websocket.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/test/websocketserver.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/test/websocketserver.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/test/capi_websocketserver.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/test/benchmark.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/test/benchmark.cpp
 )
 )
 
 

+ 2 - 2
include/rtc/rtc.h

@@ -336,7 +336,7 @@ typedef struct {
 
 
 RTC_EXPORT int rtcCreateWebSocket(const char *url); // returns ws id
 RTC_EXPORT int rtcCreateWebSocket(const char *url); // returns ws id
 RTC_EXPORT int rtcCreateWebSocketEx(const char *url, const rtcWsConfiguration *config);
 RTC_EXPORT int rtcCreateWebSocketEx(const char *url, const rtcWsConfiguration *config);
-RTC_EXPORT int rtcDeleteWebsocket(int ws);
+RTC_EXPORT int rtcDeleteWebSocket(int ws);
 
 
 RTC_EXPORT int rtcGetWebSocketRemoteAddress(int ws, char *buffer, int size);
 RTC_EXPORT int rtcGetWebSocketRemoteAddress(int ws, char *buffer, int size);
 RTC_EXPORT int rtcGetWebSocketPath(int ws, char *buffer, int size);
 RTC_EXPORT int rtcGetWebSocketPath(int ws, char *buffer, int size);
@@ -355,7 +355,7 @@ typedef struct {
 
 
 RTC_EXPORT int rtcCreateWebSocketServer(const rtcWsServerConfiguration *config,
 RTC_EXPORT int rtcCreateWebSocketServer(const rtcWsServerConfiguration *config,
                                         rtcWebSocketClientCallbackFunc cb); // returns wsserver id
                                         rtcWebSocketClientCallbackFunc cb); // returns wsserver id
-RTC_EXPORT int rtcDeleteWebsocketServer(int wsserver);
+RTC_EXPORT int rtcDeleteWebSocketServer(int wsserver);
 
 
 RTC_EXPORT int rtcSetWebSocketClientCallback(int wsserver, rtcWebSocketClientCallbackFunc cb);
 RTC_EXPORT int rtcSetWebSocketClientCallback(int wsserver, rtcWebSocketClientCallbackFunc cb);
 RTC_EXPORT int rtcGetWebSocketServerPort(int wsserver);
 RTC_EXPORT int rtcGetWebSocketServerPort(int wsserver);

+ 13 - 7
src/capi.cpp

@@ -794,8 +794,11 @@ int rtcCreateWebSocket(const char *url) {
 
 
 int rtcCreateWebSocketEx(const char *url, const rtcWsConfiguration *config) {
 int rtcCreateWebSocketEx(const char *url, const rtcWsConfiguration *config) {
 	return wrap([&] {
 	return wrap([&] {
-		if(!url || !config)
-			return RTC_ERR_INVALID;
+		if (!url)
+			throw std::invalid_argument("Unexpected null pointer for URL");
+
+		if (!config)
+			throw std::invalid_argument("Unexpected null pointer for config");
 
 
 		WebSocket::Configuration c;
 		WebSocket::Configuration c;
 		c.disableTlsVerification = config->disableTlsVerification;
 		c.disableTlsVerification = config->disableTlsVerification;
@@ -805,7 +808,7 @@ int rtcCreateWebSocketEx(const char *url, const rtcWsConfiguration *config) {
 	});
 	});
 }
 }
 
 
-int rtcDeleteWebsocket(int ws) {
+int rtcDeleteWebSocket(int ws) {
 	return wrap([&] {
 	return wrap([&] {
 		auto webSocket = getWebSocket(ws);
 		auto webSocket = getWebSocket(ws);
 		webSocket->onOpen(nullptr);
 		webSocket->onOpen(nullptr);
@@ -843,8 +846,11 @@ int rtcGetWebSocketPath(int ws, char *buffer, int size) {
 RTC_EXPORT int rtcCreateWebSocketServer(const rtcWsServerConfiguration *config,
 RTC_EXPORT int rtcCreateWebSocketServer(const rtcWsServerConfiguration *config,
                                         rtcWebSocketClientCallbackFunc cb) {
                                         rtcWebSocketClientCallbackFunc cb) {
 	return wrap([&] {
 	return wrap([&] {
-		if(!config || !cb)
-			return RTC_ERR_INVALID;
+		if (!config)
+			throw std::invalid_argument("Unexpected null pointer for config");
+
+		if (!cb)
+			throw std::invalid_argument("Unexpected null pointer for client callback");
 
 
 		WebSocketServer::Configuration c;
 		WebSocketServer::Configuration c;
 		c.port = config->port;
 		c.port = config->port;
@@ -865,11 +871,11 @@ RTC_EXPORT int rtcCreateWebSocketServer(const rtcWsServerConfiguration *config,
 			}
 			}
 		});
 		});
 
 
-		return RTC_ERR_SUCCESS;
+		return wsserver;
 	});
 	});
 }
 }
 
 
-RTC_EXPORT int rtcDeleteWebsocketServer(int wsserver) {
+RTC_EXPORT int rtcDeleteWebSocketServer(int wsserver) {
 	return wrap([&] {
 	return wrap([&] {
 		auto webSocketServer = getWebSocketServer(wsserver);
 		auto webSocketServer = getWebSocketServer(wsserver);
 		webSocketServer->onClient(nullptr);
 		webSocketServer->onClient(nullptr);

+ 169 - 0
test/capi_websocketserver.cpp

@@ -0,0 +1,169 @@
+/**
+ * Copyright (c) 2021 Paul-Louis Ageneau
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <rtc/rtc.h>
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+#ifdef _WIN32
+#include <windows.h>
+static void sleep(unsigned int secs) { Sleep(secs * 1000); }
+#else
+#include <unistd.h> // for sleep
+#endif
+
+static const char *MESSAGE = "Hello, this is a C API WebSocket test!";
+
+static bool success = false;
+static bool failed = false;
+
+static void RTC_API openCallback(int ws, void *ptr) {
+	printf("WebSocket: Connection open");
+
+	if (rtcSendMessage(ws, MESSAGE, -1) < 0) { // negative size indicates a null-terminated string
+		fprintf(stderr, "rtcSendMessage failed\n");
+		failed = true;
+		return;
+	}
+}
+
+static void RTC_API closedCallback(int ws, void *ptr) { printf("WebSocket: Connection closed"); }
+
+static void RTC_API messageCallback(int ws, const char *message, int size, void *ptr) {
+	if (size < 0 && strcmp(message, MESSAGE) == 0) {
+		printf("WebSocket: Received expected message\n");
+		success = true;
+	} else {
+		fprintf(stderr, "Received UNEXPECTED message\n");
+		failed = true;
+	}
+}
+
+static void RTC_API serverOpenCallback(int ws, void *ptr) {
+	printf("WebSocketServer: Client connection open");
+
+	char path[256];
+	if (rtcGetWebSocketPath(ws, path, 256) < 0) {
+		fprintf(stderr, "rtcGetWebSocketPath failed\n");
+		failed = true;
+		return;
+	}
+
+	if (strcmp(path, "/mypath") != 0) {
+		fprintf(stderr, "Wrong WebSocket path: %s\n", path);
+		failed = true;
+	}
+}
+
+static void RTC_API serverClosedCallback(int ws, void *ptr) {
+	printf("WebSocketServer: Client connection closed\n");
+}
+
+static void RTC_API serverMessageCallback(int ws, const char *message, int size, void *ptr) {
+	if (rtcSendMessage(ws, message, size) < 0) {
+		fprintf(stderr, "rtcSendMessage failed\n");
+		failed = true;
+	}
+}
+
+static void RTC_API serverClientCallback(int wsserver, int ws, void *ptr) {
+	char address[256];
+	if (rtcGetWebSocketRemoteAddress(ws, address, 256) < 0) {
+		fprintf(stderr, "rtcGetWebSocketRemoteAddress failed\n");
+		failed = true;
+		return;
+	}
+
+	printf("WebSocketServer: Received client connection from %s", address);
+
+	rtcSetOpenCallback(ws, serverOpenCallback);
+	rtcSetClosedCallback(ws, serverClosedCallback);
+	rtcSetMessageCallback(ws, serverMessageCallback);
+}
+
+int test_capi_websocketserver_main() {
+	const char *url = "wss://localhost:48081/mypath";
+	const uint16_t port = 48081;
+	int wsserver = -1;
+	int ws = -1;
+	int attempts;
+
+	rtcInitLogger(RTC_LOG_DEBUG, nullptr);
+
+	rtcWsServerConfiguration serverConfig;
+	memset(&serverConfig, 0, sizeof(serverConfig));
+	serverConfig.port = port;
+	serverConfig.enableTls = true;
+	// serverConfig.certificatePemFile = ...
+	// serverConfig.keyPemFile = ...
+
+	wsserver = rtcCreateWebSocketServer(&serverConfig, serverClientCallback);
+	if (wsserver < 0)
+		goto error;
+
+	if(rtcGetWebSocketServerPort(wsserver) != int(port)) {
+		fprintf(stderr, "rtcGetWebSocketServerPort failed\n");
+		goto error;
+	}
+
+	rtcWsConfiguration config;
+	memset(&config, 0, sizeof(config));
+	config.disableTlsVerification = true;
+
+	ws = rtcCreateWebSocketEx(url, &config);
+	if (ws < 0)
+		goto error;
+
+	rtcSetOpenCallback(ws, openCallback);
+	rtcSetClosedCallback(ws, closedCallback);
+	rtcSetMessageCallback(ws, messageCallback);
+
+	attempts = 10;
+	while (!success && !failed && attempts--)
+		sleep(1);
+
+	if (failed)
+		goto error;
+
+	rtcDeleteWebSocket(ws);
+	sleep(1);
+
+	rtcDeleteWebSocketServer(wsserver);
+	sleep(1);
+
+	printf("Success\n");
+	return 0;
+
+error:
+	if (ws >= 0)
+		rtcDeleteWebSocket(ws);
+
+	if (wsserver >= 0)
+		rtcDeleteWebSocketServer(wsserver);
+
+	return -1;
+}
+
+#include <stdexcept>
+
+void test_capi_websocketserver() {
+	if (test_capi_websocketserver_main())
+		throw std::runtime_error("WebSocketServer test failed");
+}

+ 9 - 0
test/main.cpp

@@ -30,6 +30,7 @@ void test_capi_connectivity();
 void test_capi_track();
 void test_capi_track();
 void test_websocket();
 void test_websocket();
 void test_websocketserver();
 void test_websocketserver();
+void test_capi_websocketserver();
 size_t benchmark(chrono::milliseconds duration);
 size_t benchmark(chrono::milliseconds duration);
 
 
 void test_benchmark() {
 void test_benchmark() {
@@ -110,6 +111,14 @@ int main(int argc, char **argv) {
 		cerr << "WebSocketServer test failed: " << e.what() << endl;
 		cerr << "WebSocketServer test failed: " << e.what() << endl;
 		return -1;
 		return -1;
 	}
 	}
+	try {
+		cout << endl << "*** Running WebSocketServer C API test..." << endl;
+		test_capi_websocketserver();
+		cout << "*** Finished WebSocketServer C API test" << endl;
+	} catch (const exception &e) {
+		cerr << "WebSocketServer C API test failed: " << e.what() << endl;
+		return -1;
+	}
 #endif
 #endif
 	this_thread::sleep_for(1s);
 	this_thread::sleep_for(1s);
 	try {
 	try {