capi_websocketserver.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. /**
  2. * Copyright (c) 2021 Paul-Louis Ageneau
  3. *
  4. * This library is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Lesser General Public
  6. * License as published by the Free Software Foundation; either
  7. * version 2.1 of the License, or (at your option) any later version.
  8. *
  9. * This library is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Lesser General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Lesser General Public
  15. * License along with this library; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. */
  18. #include <rtc/rtc.h>
  19. #if RTC_ENABLE_WEBSOCKET
  20. #include <cstdio>
  21. #include <cstdlib>
  22. #include <cstring>
  23. #ifdef _WIN32
  24. #include <windows.h>
  25. static void sleep(unsigned int secs) { Sleep(secs * 1000); }
  26. #else
  27. #include <unistd.h> // for sleep
  28. #endif
  29. static const char *MESSAGE = "Hello, this is a C API WebSocket test!";
  30. static bool success = false;
  31. static bool failed = false;
  32. static int wsclient = -1;
  33. static void RTC_API openCallback(int ws, void *ptr) {
  34. printf("WebSocket: Connection open\n");
  35. if (rtcSendMessage(ws, MESSAGE, -1) < 0) { // negative size indicates a null-terminated string
  36. fprintf(stderr, "rtcSendMessage failed\n");
  37. failed = true;
  38. return;
  39. }
  40. }
  41. static void RTC_API closedCallback(int ws, void *ptr) { printf("WebSocket: Connection closed"); }
  42. static void RTC_API messageCallback(int ws, const char *message, int size, void *ptr) {
  43. if (size < 0 && strcmp(message, MESSAGE) == 0) {
  44. printf("WebSocket: Received expected message\n");
  45. success = true;
  46. } else {
  47. fprintf(stderr, "Received UNEXPECTED message\n");
  48. failed = true;
  49. }
  50. }
  51. static void RTC_API serverOpenCallback(int ws, void *ptr) {
  52. printf("WebSocketServer: Client connection open\n");
  53. char path[256];
  54. if (rtcGetWebSocketPath(ws, path, 256) < 0) {
  55. fprintf(stderr, "rtcGetWebSocketPath failed\n");
  56. failed = true;
  57. return;
  58. }
  59. if (strcmp(path, "/mypath") != 0) {
  60. fprintf(stderr, "Wrong WebSocket path: %s\n", path);
  61. failed = true;
  62. }
  63. }
  64. static void RTC_API serverClosedCallback(int ws, void *ptr) {
  65. printf("WebSocketServer: Client connection closed\n");
  66. }
  67. static void RTC_API serverMessageCallback(int ws, const char *message, int size, void *ptr) {
  68. if (rtcSendMessage(ws, message, size) < 0) {
  69. fprintf(stderr, "rtcSendMessage failed\n");
  70. failed = true;
  71. }
  72. }
  73. static void RTC_API serverClientCallback(int wsserver, int ws, void *ptr) {
  74. wsclient = ws;
  75. char address[256];
  76. if (rtcGetWebSocketRemoteAddress(ws, address, 256) < 0) {
  77. fprintf(stderr, "rtcGetWebSocketRemoteAddress failed\n");
  78. failed = true;
  79. return;
  80. }
  81. printf("WebSocketServer: Received client connection from %s", address);
  82. rtcSetOpenCallback(ws, serverOpenCallback);
  83. rtcSetClosedCallback(ws, serverClosedCallback);
  84. rtcSetMessageCallback(ws, serverMessageCallback);
  85. }
  86. int test_capi_websocketserver_main() {
  87. const char *url = "wss://localhost:48081/mypath";
  88. const uint16_t port = 48081;
  89. int wsserver = -1;
  90. int ws = -1;
  91. int attempts;
  92. rtcInitLogger(RTC_LOG_DEBUG, nullptr);
  93. rtcWsServerConfiguration serverConfig;
  94. memset(&serverConfig, 0, sizeof(serverConfig));
  95. serverConfig.port = port;
  96. serverConfig.enableTls = true;
  97. // serverConfig.certificatePemFile = ...
  98. // serverConfig.keyPemFile = ...
  99. wsserver = rtcCreateWebSocketServer(&serverConfig, serverClientCallback);
  100. if (wsserver < 0)
  101. goto error;
  102. if (rtcGetWebSocketServerPort(wsserver) != int(port)) {
  103. fprintf(stderr, "rtcGetWebSocketServerPort failed\n");
  104. goto error;
  105. }
  106. rtcWsConfiguration config;
  107. memset(&config, 0, sizeof(config));
  108. config.disableTlsVerification = true;
  109. ws = rtcCreateWebSocketEx(url, &config);
  110. if (ws < 0)
  111. goto error;
  112. rtcSetOpenCallback(ws, openCallback);
  113. rtcSetClosedCallback(ws, closedCallback);
  114. rtcSetMessageCallback(ws, messageCallback);
  115. attempts = 10;
  116. while (!success && !failed && attempts--)
  117. sleep(1);
  118. if (!success || failed)
  119. goto error;
  120. rtcDeleteWebSocket(wsclient);
  121. sleep(1);
  122. rtcDeleteWebSocket(ws);
  123. sleep(1);
  124. rtcDeleteWebSocketServer(wsserver);
  125. sleep(1);
  126. printf("Success\n");
  127. return 0;
  128. error:
  129. if (wsclient >= 0)
  130. rtcDeleteWebSocket(wsclient);
  131. if (ws >= 0)
  132. rtcDeleteWebSocket(ws);
  133. if (wsserver >= 0)
  134. rtcDeleteWebSocketServer(wsserver);
  135. return -1;
  136. }
  137. #include <stdexcept>
  138. void test_capi_websocketserver() {
  139. if (test_capi_websocketserver_main())
  140. throw std::runtime_error("WebSocketServer test failed");
  141. }
  142. #endif