xref: /curl/docs/examples/websocket.c (revision d4b85890)
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  * WebSocket using CONNECT_ONLY
26  * </DESC>
27  */
28 #include <stdio.h>
29 #include <string.h>
30 #ifdef _WIN32
31 #include <windows.h>
32 #define sleep(s) Sleep((DWORD)(s))
33 #else
34 #include <unistd.h>
35 #endif
36 
37 #include <curl/curl.h>
38 
ping(CURL * curl,const char * send_payload)39 static int ping(CURL *curl, const char *send_payload)
40 {
41   size_t sent;
42   CURLcode result =
43     curl_ws_send(curl, send_payload, strlen(send_payload), &sent, 0,
44                  CURLWS_PING);
45   return (int)result;
46 }
47 
recv_pong(CURL * curl,const char * expected_payload)48 static int recv_pong(CURL *curl, const char *expected_payload)
49 {
50   size_t rlen;
51   const struct curl_ws_frame *meta;
52   char buffer[256];
53   CURLcode result = curl_ws_recv(curl, buffer, sizeof(buffer), &rlen, &meta);
54   if(!result) {
55     if(meta->flags & CURLWS_PONG) {
56       int same = 0;
57       fprintf(stderr, "ws: got PONG back\n");
58       if(rlen == strlen(expected_payload)) {
59         if(!memcmp(expected_payload, buffer, rlen)) {
60           fprintf(stderr, "ws: got the same payload back\n");
61           same = 1;
62         }
63       }
64       if(!same)
65         fprintf(stderr, "ws: did NOT get the same payload back\n");
66     }
67     else {
68       fprintf(stderr, "recv_pong: got %u bytes rflags %x\n", (int)rlen,
69               meta->flags);
70     }
71   }
72   fprintf(stderr, "ws: curl_ws_recv returned %u, received %u\n",
73           (unsigned int)result, (unsigned int)rlen);
74   return (int)result;
75 }
76 
recv_any(CURL * curl)77 static CURLcode recv_any(CURL *curl)
78 {
79   size_t rlen;
80   const struct curl_ws_frame *meta;
81   char buffer[256];
82 
83   return curl_ws_recv(curl, buffer, sizeof(buffer), &rlen, &meta);
84 }
85 
86 /* close the connection */
websocket_close(CURL * curl)87 static void websocket_close(CURL *curl)
88 {
89   size_t sent;
90   (void)curl_ws_send(curl, "", 0, &sent, 0, CURLWS_CLOSE);
91 }
92 
websocket(CURL * curl)93 static void websocket(CURL *curl)
94 {
95   int i = 0;
96   do {
97     recv_any(curl);
98     if(ping(curl, "foobar"))
99       return;
100     if(recv_pong(curl, "foobar")) {
101       return;
102     }
103     sleep(2);
104   } while(i++ < 10);
105   websocket_close(curl);
106 }
107 
main(void)108 int main(void)
109 {
110   CURL *curl;
111   CURLcode res;
112 
113   curl = curl_easy_init();
114   if(curl) {
115     curl_easy_setopt(curl, CURLOPT_URL, "wss://example.com");
116 
117     curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 2L); /* websocket style */
118 
119     /* Perform the request, res gets the return code */
120     res = curl_easy_perform(curl);
121     /* Check for errors */
122     if(res != CURLE_OK)
123       fprintf(stderr, "curl_easy_perform() failed: %s\n",
124               curl_easy_strerror(res));
125     else {
126       /* connected and ready */
127       websocket(curl);
128     }
129 
130     /* always cleanup */
131     curl_easy_cleanup(curl);
132   }
133   return 0;
134 }
135