capi_websocketserver.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  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 void RTC_API openCallback(int ws, void *ptr) {
  33. printf("WebSocket: Connection open\n");
  34. if (rtcSendMessage(ws, MESSAGE, -1) < 0) { // negative size indicates a null-terminated string
  35. fprintf(stderr, "rtcSendMessage failed\n");
  36. failed = true;
  37. return;
  38. }
  39. }
  40. static void RTC_API closedCallback(int ws, void *ptr) { printf("WebSocket: Connection closed"); }
  41. static void RTC_API messageCallback(int ws, const char *message, int size, void *ptr) {
  42. if (size < 0 && strcmp(message, MESSAGE) == 0) {
  43. printf("WebSocket: Received expected message\n");
  44. success = true;
  45. } else {
  46. fprintf(stderr, "Received UNEXPECTED message\n");
  47. failed = true;
  48. }
  49. }
  50. static void RTC_API serverOpenCallback(int ws, void *ptr) {
  51. printf("WebSocketServer: Client connection open\n");
  52. char path[256];
  53. if (rtcGetWebSocketPath(ws, path, 256) < 0) {
  54. fprintf(stderr, "rtcGetWebSocketPath failed\n");
  55. failed = true;
  56. return;
  57. }
  58. if (strcmp(path, "/mypath") != 0) {
  59. fprintf(stderr, "Wrong WebSocket path: %s\n", path);
  60. failed = true;
  61. }
  62. }
  63. static void RTC_API serverClosedCallback(int ws, void *ptr) {
  64. printf("WebSocketServer: Client connection closed\n");
  65. }
  66. static void RTC_API serverMessageCallback(int ws, const char *message, int size, void *ptr) {
  67. if (rtcSendMessage(ws, message, size) < 0) {
  68. fprintf(stderr, "rtcSendMessage failed\n");
  69. failed = true;
  70. }
  71. }
  72. static void RTC_API serverClientCallback(int wsserver, int ws, void *ptr) {
  73. char address[256];
  74. if (rtcGetWebSocketRemoteAddress(ws, address, 256) < 0) {
  75. fprintf(stderr, "rtcGetWebSocketRemoteAddress failed\n");
  76. failed = true;
  77. return;
  78. }
  79. printf("WebSocketServer: Received client connection from %s", address);
  80. rtcSetOpenCallback(ws, serverOpenCallback);
  81. rtcSetClosedCallback(ws, serverClosedCallback);
  82. rtcSetMessageCallback(ws, serverMessageCallback);
  83. }
  84. int test_capi_websocketserver_main() {
  85. const char *url = "wss://localhost:48081/mypath";
  86. const uint16_t port = 48081;
  87. int wsserver = -1;
  88. int ws = -1;
  89. int attempts;
  90. rtcInitLogger(RTC_LOG_DEBUG, nullptr);
  91. rtcWsServerConfiguration serverConfig;
  92. memset(&serverConfig, 0, sizeof(serverConfig));
  93. serverConfig.port = port;
  94. serverConfig.enableTls = true;
  95. // serverConfig.certificatePemFile = ...
  96. // serverConfig.keyPemFile = ...
  97. wsserver = rtcCreateWebSocketServer(&serverConfig, serverClientCallback);
  98. if (wsserver < 0)
  99. goto error;
  100. if (rtcGetWebSocketServerPort(wsserver) != int(port)) {
  101. fprintf(stderr, "rtcGetWebSocketServerPort failed\n");
  102. goto error;
  103. }
  104. rtcWsConfiguration config;
  105. memset(&config, 0, sizeof(config));
  106. config.disableTlsVerification = true;
  107. ws = rtcCreateWebSocketEx(url, &config);
  108. if (ws < 0)
  109. goto error;
  110. rtcSetOpenCallback(ws, openCallback);
  111. rtcSetClosedCallback(ws, closedCallback);
  112. rtcSetMessageCallback(ws, messageCallback);
  113. attempts = 10;
  114. while (!success && !failed && attempts--)
  115. sleep(1);
  116. if (failed)
  117. goto error;
  118. rtcDeleteWebSocket(ws);
  119. sleep(1);
  120. rtcDeleteWebSocketServer(wsserver);
  121. sleep(1);
  122. printf("Success\n");
  123. return 0;
  124. error:
  125. if (ws >= 0)
  126. rtcDeleteWebSocket(ws);
  127. if (wsserver >= 0)
  128. rtcDeleteWebSocketServer(wsserver);
  129. return -1;
  130. }
  131. #include <stdexcept>
  132. void test_capi_websocketserver() {
  133. if (test_capi_websocketserver_main())
  134. throw std::runtime_error("WebSocketServer test failed");
  135. }
  136. #endif