ws-pingpong.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. /***************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
  9. *
  10. * This software is licensed as described in the file COPYING, which
  11. * you should have received as part of this distribution. The terms
  12. * are also available at https://curl.se/docs/copyright.html.
  13. *
  14. * You may opt to use, copy, modify, merge, publish, distribute and/or sell
  15. * copies of the Software, and permit persons to whom the Software is
  16. * furnished to do so, under the terms of the COPYING file.
  17. *
  18. * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
  19. * KIND, either express or implied.
  20. *
  21. * SPDX-License-Identifier: curl
  22. *
  23. ***************************************************************************/
  24. /* <DESC>
  25. * WebSockets pingpong
  26. * </DESC>
  27. */
  28. /* curl stuff */
  29. #include "curl_setup.h"
  30. #include <curl/curl.h>
  31. #include <stdio.h>
  32. #include <stdlib.h>
  33. #include <string.h>
  34. #ifdef _WIN32
  35. #ifndef WIN32_LEAN_AND_MEAN
  36. #define WIN32_LEAN_AND_MEAN
  37. #endif
  38. #include <windows.h>
  39. #else
  40. #include <sys/time.h>
  41. #endif
  42. #ifndef CURL_DISABLE_WEBSOCKETS
  43. static CURLcode ping(CURL *curl, const char *send_payload)
  44. {
  45. size_t sent;
  46. CURLcode result =
  47. curl_ws_send(curl, send_payload, strlen(send_payload), &sent, 0,
  48. CURLWS_PING);
  49. fprintf(stderr,
  50. "ws: curl_ws_send returned %u, sent %u\n", (int)result, (int)sent);
  51. return result;
  52. }
  53. static CURLcode recv_pong(CURL *curl, const char *expected_payload)
  54. {
  55. size_t rlen;
  56. const struct curl_ws_frame *meta;
  57. char buffer[256];
  58. CURLcode result = curl_ws_recv(curl, buffer, sizeof(buffer), &rlen, &meta);
  59. if(result) {
  60. fprintf(stderr, "ws: curl_ws_recv returned %u, received %ld\n",
  61. (int)result, (long)rlen);
  62. return result;
  63. }
  64. if(!(meta->flags & CURLWS_PONG)) {
  65. fprintf(stderr, "recv_pong: wrong frame, got %d bytes rflags %x\n",
  66. (int)rlen, meta->flags);
  67. return CURLE_RECV_ERROR;
  68. }
  69. fprintf(stderr, "ws: got PONG back\n");
  70. if(rlen == strlen(expected_payload) &&
  71. !memcmp(expected_payload, buffer, rlen)) {
  72. fprintf(stderr, "ws: got the same payload back\n");
  73. return CURLE_OK;
  74. }
  75. fprintf(stderr, "ws: did NOT get the same payload back\n");
  76. return CURLE_RECV_ERROR;
  77. }
  78. /* just close the connection */
  79. static void websocket_close(CURL *curl)
  80. {
  81. size_t sent;
  82. CURLcode result =
  83. curl_ws_send(curl, "", 0, &sent, 0, CURLWS_CLOSE);
  84. fprintf(stderr,
  85. "ws: curl_ws_send returned %u, sent %u\n", (int)result, (int)sent);
  86. }
  87. static CURLcode pingpong(CURL *curl, const char *payload)
  88. {
  89. CURLcode res;
  90. int i;
  91. res = ping(curl, payload);
  92. if(res)
  93. return res;
  94. for(i = 0; i < 10; ++i) {
  95. fprintf(stderr, "Receive pong\n");
  96. res = recv_pong(curl, payload);
  97. if(res == CURLE_AGAIN) {
  98. #ifdef _WIN32
  99. Sleep(100);
  100. #else
  101. usleep(100*1000);
  102. #endif
  103. continue;
  104. }
  105. websocket_close(curl);
  106. return res;
  107. }
  108. websocket_close(curl);
  109. return CURLE_RECV_ERROR;
  110. }
  111. #endif
  112. int main(int argc, char *argv[])
  113. {
  114. #ifndef CURL_DISABLE_WEBSOCKETS
  115. CURL *curl;
  116. CURLcode res = CURLE_OK;
  117. const char *url, *payload;
  118. if(argc != 3) {
  119. fprintf(stderr, "usage: ws-pingpong url payload\n");
  120. return 2;
  121. }
  122. url = argv[1];
  123. payload = argv[2];
  124. curl_global_init(CURL_GLOBAL_ALL);
  125. curl = curl_easy_init();
  126. if(curl) {
  127. curl_easy_setopt(curl, CURLOPT_URL, url);
  128. /* use the callback style */
  129. curl_easy_setopt(curl, CURLOPT_USERAGENT, "ws-pingpong");
  130. curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
  131. curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 2L); /* websocket style */
  132. res = curl_easy_perform(curl);
  133. fprintf(stderr, "curl_easy_perform() returned %u\n", (int)res);
  134. if(res == CURLE_OK)
  135. res = pingpong(curl, payload);
  136. /* always cleanup */
  137. curl_easy_cleanup(curl);
  138. }
  139. curl_global_cleanup();
  140. return (int)res;
  141. #else /* !CURL_DISABLE_WEBSOCKETS */
  142. (void)argc;
  143. (void)argv;
  144. fprintf(stderr, "WebSockets not enabled in libcurl\n");
  145. return 1;
  146. #endif /* CURL_DISABLE_WEBSOCKETS */
  147. }