1--- 2c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 3SPDX-License-Identifier: curl 4Title: curl_ws_recv 5Section: 3 6Source: libcurl 7See-also: 8 - curl_easy_getinfo (3) 9 - curl_easy_perform (3) 10 - curl_easy_setopt (3) 11 - curl_ws_send (3) 12 - libcurl-ws (3) 13Protocol: 14 - WS 15Added-in: 7.86.0 16--- 17 18# NAME 19 20curl_ws_recv - receive WebSocket data 21 22# SYNOPSIS 23 24~~~c 25#include <curl/curl.h> 26 27CURLcode curl_ws_recv(CURL *curl, void *buffer, size_t buflen, 28 size_t *recv, const struct curl_ws_frame **meta); 29~~~ 30 31# DESCRIPTION 32 33Retrieves as much as possible of a received WebSocket frame into the 34*buffer*, but not more than *buflen* bytes. *recv* is set to the 35number of bytes actually stored. 36 37If the function call is successful, the *meta* pointer gets set to point to a 38*const struct curl_ws_frame* that contains information about the received 39data. That struct must not be freed and its contents must not be relied upon 40anymore once another WebSocket function is called. See curl_ws_meta(3) for more 41details on that struct. 42 43The application must check `meta->bytesleft` to determine whether the complete 44frame has been received. If more payload is pending, the application must call 45this function again with an updated *buffer* and *buflen* to resume receiving. 46This may for example happen when the data does not fit into the provided buffer 47or when not all frame data has been delivered over the network yet. 48 49If the application wants to read the metadata without consuming any payload, 50it may call this function with a *buflen* of zero. Setting *buffer* to a NULL 51pointer is permitted in this case. Note that frames without payload are consumed 52by this action. 53 54If the received message consists of multiple fragments, the *CURLWS_CONT* bit 55is set in all frames except the final one. The application is responsible for 56reassembling fragmented messages. See curl_ws_meta(3) for more details on 57*CURLWS_CONT*. 58 59# %PROTOCOLS% 60 61# EXAMPLE 62 63~~~c 64int main(void) 65{ 66 char buffer[256]; 67 size_t offset = 0; 68 CURLcode res = CURLE_OK; 69 CURL *curl = curl_easy_init(); 70 71 curl_easy_setopt(curl, CURLOPT_URL, "wss://example.com/"); 72 curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 2L); 73 /* start HTTPS connection and upgrade to WSS, then return control */ 74 curl_easy_perform(curl); 75 76 /* Note: This example neglects fragmented messages. (CURLWS_CONT bit) 77 A real application must handle them appropriately. */ 78 79 while(!res) { 80 size_t recv; 81 const struct curl_ws_frame *meta; 82 res = curl_ws_recv(curl, buffer + offset, sizeof(buffer) - offset, &recv, 83 &meta); 84 offset += recv; 85 86 if(res == CURLE_OK) { 87 if(meta->bytesleft == 0) 88 break; /* finished receiving */ 89 if(meta->bytesleft > sizeof(buffer) - offset) 90 res = CURLE_TOO_LARGE; 91 } 92 93 if(res == CURLE_AGAIN) 94 /* in real application: wait for socket here, e.g. using select() */ 95 res = CURLE_OK; 96 } 97 98 curl_easy_cleanup(curl); 99 return (int)res; 100} 101~~~ 102 103# %AVAILABILITY% 104 105# RETURN VALUE 106 107This function returns a CURLcode indicating success or error. 108 109CURLE_OK (0) means everything was OK, non-zero means an error occurred, see 110libcurl-errors(3). If CURLOPT_ERRORBUFFER(3) was set with curl_easy_setopt(3) 111there can be an error message stored in the error buffer when non-zero is 112returned. 113 114Returns **CURLE_GOT_NOTHING** if the associated connection is closed. 115 116Instead of blocking, the function returns **CURLE_AGAIN**. The correct 117behavior is then to wait for the socket to signal readability before calling 118this function again. 119 120Any other non-zero return value indicates an error. See the libcurl-errors(3) 121man page for the full list with descriptions. 122 123Returns **CURLE_GOT_NOTHING** if the associated connection is closed. 124