capi_websocketserver.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. /**
  2. * Copyright (c) 2021 Paul-Louis Ageneau
  3. *
  4. * This Source Code Form is subject to the terms of the Mozilla Public
  5. * License, v. 2.0. If a copy of the MPL was not distributed with this
  6. * file, You can obtain one at https://mozilla.org/MPL/2.0/.
  7. */
  8. #include <rtc/rtc.h>
  9. #if RTC_ENABLE_WEBSOCKET
  10. #include <cstdio>
  11. #include <cstdlib>
  12. #include <cstring>
  13. #ifdef _WIN32
  14. #include <windows.h>
  15. static void sleep(unsigned int secs) { Sleep(secs * 1000); }
  16. #else
  17. #include <unistd.h> // for sleep
  18. #endif
  19. static const char *MESSAGE = "Hello, this is a C API WebSocket test!";
  20. static bool success = false;
  21. static bool failed = false;
  22. static int wsclient = -1;
  23. static void RTC_API openCallback(int ws, void *ptr) {
  24. printf("WebSocket: Connection open\n");
  25. if (rtcSendMessage(ws, MESSAGE, -1) < 0) { // negative size indicates a null-terminated string
  26. fprintf(stderr, "rtcSendMessage failed\n");
  27. failed = true;
  28. return;
  29. }
  30. }
  31. static void RTC_API closedCallback(int ws, void *ptr) { printf("WebSocket: Connection closed"); }
  32. static void RTC_API messageCallback(int ws, const char *message, int size, void *ptr) {
  33. if (size < 0 && strcmp(message, MESSAGE) == 0) {
  34. printf("WebSocket: Received expected message\n");
  35. success = true;
  36. } else {
  37. fprintf(stderr, "Received UNEXPECTED message\n");
  38. failed = true;
  39. }
  40. }
  41. static void RTC_API serverOpenCallback(int ws, void *ptr) {
  42. printf("WebSocketServer: Client connection open\n");
  43. char path[256];
  44. if (rtcGetWebSocketPath(ws, path, 256) < 0) {
  45. fprintf(stderr, "rtcGetWebSocketPath failed\n");
  46. failed = true;
  47. return;
  48. }
  49. if (strcmp(path, "/mypath") != 0) {
  50. fprintf(stderr, "Wrong WebSocket path: %s\n", path);
  51. failed = true;
  52. }
  53. }
  54. static void RTC_API serverClosedCallback(int ws, void *ptr) {
  55. printf("WebSocketServer: Client connection closed\n");
  56. }
  57. static void RTC_API serverMessageCallback(int ws, const char *message, int size, void *ptr) {
  58. if (rtcSendMessage(ws, message, size) < 0) {
  59. fprintf(stderr, "rtcSendMessage failed\n");
  60. failed = true;
  61. }
  62. }
  63. static void RTC_API serverClientCallback(int wsserver, int ws, void *ptr) {
  64. wsclient = ws;
  65. char address[256];
  66. if (rtcGetWebSocketRemoteAddress(ws, address, 256) < 0) {
  67. fprintf(stderr, "rtcGetWebSocketRemoteAddress failed\n");
  68. failed = true;
  69. return;
  70. }
  71. printf("WebSocketServer: Received client connection from %s", address);
  72. rtcSetOpenCallback(ws, serverOpenCallback);
  73. rtcSetClosedCallback(ws, serverClosedCallback);
  74. rtcSetMessageCallback(ws, serverMessageCallback);
  75. }
  76. int test_capi_websocketserver_main() {
  77. const char *url = "wss://localhost:48081/mypath";
  78. const uint16_t port = 48081;
  79. int wsserver = -1;
  80. int ws = -1;
  81. int attempts;
  82. rtcInitLogger(RTC_LOG_DEBUG, nullptr);
  83. rtcWsServerConfiguration serverConfig;
  84. memset(&serverConfig, 0, sizeof(serverConfig));
  85. serverConfig.port = port;
  86. serverConfig.enableTls = true;
  87. // serverConfig.certificatePemFile = ...
  88. // serverConfig.keyPemFile = ...
  89. wsserver = rtcCreateWebSocketServer(&serverConfig, serverClientCallback);
  90. if (wsserver < 0)
  91. goto error;
  92. if (rtcGetWebSocketServerPort(wsserver) != int(port)) {
  93. fprintf(stderr, "rtcGetWebSocketServerPort failed\n");
  94. goto error;
  95. }
  96. rtcWsConfiguration config;
  97. memset(&config, 0, sizeof(config));
  98. config.disableTlsVerification = true;
  99. ws = rtcCreateWebSocketEx(url, &config);
  100. if (ws < 0)
  101. goto error;
  102. rtcSetOpenCallback(ws, openCallback);
  103. rtcSetClosedCallback(ws, closedCallback);
  104. rtcSetMessageCallback(ws, messageCallback);
  105. attempts = 10;
  106. while (!success && !failed && attempts--)
  107. sleep(1);
  108. if (!success || failed)
  109. goto error;
  110. rtcDeleteWebSocket(wsclient);
  111. sleep(1);
  112. rtcDeleteWebSocket(ws);
  113. sleep(1);
  114. rtcDeleteWebSocketServer(wsserver);
  115. sleep(1);
  116. printf("Success\n");
  117. return 0;
  118. error:
  119. if (wsclient >= 0)
  120. rtcDeleteWebSocket(wsclient);
  121. if (ws >= 0)
  122. rtcDeleteWebSocket(ws);
  123. if (wsserver >= 0)
  124. rtcDeleteWebSocketServer(wsserver);
  125. return -1;
  126. }
  127. #include <stdexcept>
  128. void test_capi_websocketserver() {
  129. if (test_capi_websocketserver_main())
  130. throw std::runtime_error("WebSocketServer test failed");
  131. }
  132. #endif