ws-pingpong.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  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. #if defined(__TANDEM)
  88. # include <cextdecs.h(PROCESS_DELAY_)>
  89. #endif
  90. static CURLcode pingpong(CURL *curl, const char *payload)
  91. {
  92. CURLcode res;
  93. int i;
  94. res = ping(curl, payload);
  95. if(res)
  96. return res;
  97. for(i = 0; i < 10; ++i) {
  98. fprintf(stderr, "Receive pong\n");
  99. res = recv_pong(curl, payload);
  100. if(res == CURLE_AGAIN) {
  101. #ifdef _WIN32
  102. Sleep(100);
  103. #elif defined(__TANDEM)
  104. /* NonStop only defines usleep when building for a threading model */
  105. # if defined(_PUT_MODEL_) || defined(_KLT_MODEL_)
  106. usleep(100*1000);
  107. # else
  108. PROCESS_DELAY_(100*1000);
  109. # endif
  110. #else
  111. usleep(100*1000);
  112. #endif
  113. continue;
  114. }
  115. websocket_close(curl);
  116. return res;
  117. }
  118. websocket_close(curl);
  119. return CURLE_RECV_ERROR;
  120. }
  121. #endif
  122. int main(int argc, char *argv[])
  123. {
  124. #ifndef CURL_DISABLE_WEBSOCKETS
  125. CURL *curl;
  126. CURLcode res = CURLE_OK;
  127. const char *url, *payload;
  128. if(argc != 3) {
  129. fprintf(stderr, "usage: ws-pingpong url payload\n");
  130. return 2;
  131. }
  132. url = argv[1];
  133. payload = argv[2];
  134. curl_global_init(CURL_GLOBAL_ALL);
  135. curl = curl_easy_init();
  136. if(curl) {
  137. curl_easy_setopt(curl, CURLOPT_URL, url);
  138. /* use the callback style */
  139. curl_easy_setopt(curl, CURLOPT_USERAGENT, "ws-pingpong");
  140. curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
  141. curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 2L); /* websocket style */
  142. res = curl_easy_perform(curl);
  143. fprintf(stderr, "curl_easy_perform() returned %u\n", (int)res);
  144. if(res == CURLE_OK)
  145. res = pingpong(curl, payload);
  146. /* always cleanup */
  147. curl_easy_cleanup(curl);
  148. }
  149. curl_global_cleanup();
  150. return (int)res;
  151. #else /* !CURL_DISABLE_WEBSOCKETS */
  152. (void)argc;
  153. (void)argv;
  154. fprintf(stderr, "WebSockets not enabled in libcurl\n");
  155. return 1;
  156. #endif /* CURL_DISABLE_WEBSOCKETS */
  157. }