mirror of
https://github.com/curl/curl.git
synced 2026-06-04 23:04:22 +03:00
examples/websocket.c: check for CURLE_AGAIN on recv_pong()
The example file docs/examples/websocket.c does not work out of the box, because the recv_pong() function does not consider that the curl_ws_recv() function might return CURLE_AGAIN if there is no data to read, causing the program to terminate prematurely. This commit addresses this by using select(2) to make receiving pong blocking, and thus being able to continue with the main loop. This also occurs in the example file sendrecv.c, which also makes use of select(2) for sending and receiving data, which I based on for this commit.
This commit is contained in:
parent
f274fc5c68
commit
e8d0cd0e95
1 changed files with 73 additions and 20 deletions
|
|
@ -30,6 +30,39 @@
|
|||
#include <unistd.h>
|
||||
#include <curl/curl.h>
|
||||
|
||||
/* Auxiliary function that waits on the socket. */
|
||||
static int wait_on_socket(curl_socket_t sockfd, long timeout_ms)
|
||||
{
|
||||
struct timeval tv;
|
||||
fd_set infd, outfd, errfd;
|
||||
int res;
|
||||
|
||||
tv.tv_sec = timeout_ms / 1000;
|
||||
tv.tv_usec = (int)(timeout_ms % 1000) * 1000;
|
||||
|
||||
FD_ZERO(&infd);
|
||||
FD_ZERO(&outfd);
|
||||
FD_ZERO(&errfd);
|
||||
|
||||
/* Avoid this warning with pre-2020 Cygwin/MSYS releases:
|
||||
* warning: conversion to 'long unsigned int' from 'curl_socket_t' {aka 'int'}
|
||||
* may change the sign of the result [-Wsign-conversion]
|
||||
*/
|
||||
#if defined(__GNUC__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||
#endif
|
||||
FD_SET(sockfd, &errfd); /* always check for error */
|
||||
FD_SET(sockfd, &infd);
|
||||
#if defined(__GNUC__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
/* select() returns the number of signalled sockets or -1 */
|
||||
res = select((int)sockfd + 1, &infd, &outfd, &errfd, &tv);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int ping(CURL *curl, const char *send_payload)
|
||||
{
|
||||
size_t sent;
|
||||
|
|
@ -44,27 +77,47 @@ static int recv_pong(CURL *curl, const char *expected_payload)
|
|||
size_t rlen;
|
||||
const struct curl_ws_frame *meta;
|
||||
char buffer[256];
|
||||
CURLcode result = curl_ws_recv(curl, buffer, sizeof(buffer), &rlen, &meta);
|
||||
if(!result) {
|
||||
if(meta->flags & CURLWS_PONG) {
|
||||
int same = 0;
|
||||
fprintf(stderr, "ws: got PONG back\n");
|
||||
if(rlen == strlen(expected_payload)) {
|
||||
if(!memcmp(expected_payload, buffer, rlen)) {
|
||||
fprintf(stderr, "ws: got the same payload back\n");
|
||||
same = 1;
|
||||
}
|
||||
}
|
||||
if(!same)
|
||||
fprintf(stderr, "ws: did NOT get the same payload back\n");
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "recv_pong: got %u bytes rflags %x\n", (int)rlen,
|
||||
meta->flags);
|
||||
}
|
||||
CURLcode result;
|
||||
curl_socket_t sockfd;
|
||||
|
||||
result = curl_easy_getinfo(curl, CURLINFO_ACTIVESOCKET, &sockfd);
|
||||
|
||||
if(result != CURLE_OK) {
|
||||
printf("Error: %s\n", curl_easy_strerror(result));
|
||||
return 1;
|
||||
}
|
||||
fprintf(stderr, "ws: curl_ws_recv returned %u, received %u\n",
|
||||
(unsigned int)result, (unsigned int)rlen);
|
||||
|
||||
do {
|
||||
result = curl_ws_recv(curl, buffer, sizeof(buffer), &rlen, &meta);
|
||||
if(result == CURLE_AGAIN && !wait_on_socket(sockfd, 1000)) {
|
||||
printf("Error: timeout.\n");
|
||||
break;
|
||||
}
|
||||
} while (result == CURLE_AGAIN);
|
||||
|
||||
if(result != CURLE_OK) {
|
||||
fprintf(stderr, "ws: curl_ws_recv returned %u, received %u\n",
|
||||
(unsigned int)result, (unsigned int)rlen);
|
||||
return (int)result;
|
||||
}
|
||||
|
||||
if(meta->flags & CURLWS_PONG) {
|
||||
int same = 0;
|
||||
fprintf(stderr, "ws: got PONG back\n");
|
||||
if(rlen == strlen(expected_payload)) {
|
||||
if(!memcmp(expected_payload, buffer, rlen)) {
|
||||
fprintf(stderr, "ws: got the same payload back\n");
|
||||
same = 1;
|
||||
}
|
||||
}
|
||||
if(!same)
|
||||
fprintf(stderr, "ws: did NOT get the same payload back\n");
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "recv_pong: got %u bytes rflags %x\n", (int)rlen,
|
||||
meta->flags);
|
||||
}
|
||||
|
||||
return (int)result;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue