From 26217357f4f2737e4fdbacf5cf8d0793ac596e0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kosi=C5=84ski?= Date: Thu, 15 Aug 2019 18:40:37 -0700 Subject: [PATCH] Add output redirection. This adds a function to set the C stream used for reporting messages, as well as the ability to turn off messages altogether. --- easywsclient.cpp | 79 +++++++++++++++++++++++++++++++++++------------- easywsclient.hpp | 5 +++ 2 files changed, 63 insertions(+), 21 deletions(-) diff --git a/easywsclient.cpp b/easywsclient.cpp index 0770870..24d012b 100644 --- a/easywsclient.cpp +++ b/easywsclient.cpp @@ -79,7 +79,7 @@ using easywsclient::BytesCallback_Imp; namespace { // private module-only namespace -socket_t hostname_connect(const std::string& hostname, int port) { +socket_t hostname_connect(const std::string& hostname, int port, FILE *messageStream) { struct addrinfo hints; struct addrinfo *result; struct addrinfo *p; @@ -92,8 +92,10 @@ socket_t hostname_connect(const std::string& hostname, int port) { snprintf(sport, 16, "%d", port); if ((ret = getaddrinfo(hostname.c_str(), sport, &hints, &result)) != 0) { - fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(ret)); - return 1; + if (messageStream) { + fprintf(messageStream, "getaddrinfo: %s\n", gai_strerror(ret)); + } + return 1; } for(p = result; p != NULL; p = p->ai_next) { @@ -218,7 +220,9 @@ class _RealWebSocket : public easywsclient::WebSocket rxbuf.resize(N); closesocket(sockfd); readyState = CLOSED; - fputs(ret < 0 ? "Connection error!\n" : "Connection closed!\n", stderr); + if (messageStream) { + fputs(ret < 0 ? "Connection error!\n" : "Connection closed!\n", messageStream); + } break; } else { @@ -234,7 +238,9 @@ class _RealWebSocket : public easywsclient::WebSocket else if (ret <= 0) { closesocket(sockfd); readyState = CLOSED; - fputs(ret < 0 ? "Connection error!\n" : "Connection closed!\n", stderr); + if (messageStream) { + fputs(ret < 0 ? "Connection error!\n" : "Connection closed!\n", messageStream); + } break; } else { @@ -314,7 +320,9 @@ class _RealWebSocket : public easywsclient::WebSocket // if it were valid. So just close() and return immediately // for now. isRxBad = true; - fprintf(stderr, "ERROR: Frame has invalid frame length. Closing.\n"); + if (messageStream) { + fprintf(messageStream, "ERROR: Frame has invalid frame length. Closing.\n"); + } close(); return; } @@ -358,7 +366,12 @@ class _RealWebSocket : public easywsclient::WebSocket } else if (ws.opcode == wsheader_type::PONG) { } else if (ws.opcode == wsheader_type::CLOSE) { close(); } - else { fprintf(stderr, "ERROR: Got unexpected WebSocket message.\n"); close(); } + else { + if (messageStream) { + fprintf(messageStream, "ERROR: Got unexpected WebSocket message.\n"); + } + close(); + } rxbuf.erase(rxbuf.begin(), rxbuf.begin() + ws.header_size+(size_t)ws.N); } @@ -453,17 +466,21 @@ class _RealWebSocket : public easywsclient::WebSocket }; -easywsclient::WebSocket::pointer from_url(const std::string& url, bool useMask, const std::string& origin) { +easywsclient::WebSocket::pointer from_url(const std::string& url, bool useMask, const std::string& origin, FILE *messageStream) { char host[512]; int port; char path[512]; if (url.size() >= 512) { - fprintf(stderr, "ERROR: url size limit exceeded: %s\n", url.c_str()); - return NULL; + if (messageStream) { + fprintf(messageStream, "ERROR: url size limit exceeded: %s\n", url.c_str()); + } + return NULL; } if (origin.size() >= 200) { - fprintf(stderr, "ERROR: origin size limit exceeded: %s\n", origin.c_str()); - return NULL; + if (messageStream) { + fprintf(messageStream, "ERROR: origin size limit exceeded: %s\n", origin.c_str()); + } + return NULL; } if (false) { } else if (sscanf(url.c_str(), "ws://%[^:/]:%d/%s", host, &port, path) == 3) { @@ -479,13 +496,19 @@ easywsclient::WebSocket::pointer from_url(const std::string& url, bool useMask, path[0] = '\0'; } else { - fprintf(stderr, "ERROR: Could not parse WebSocket url: %s\n", url.c_str()); + //if (messageStream) { + // fprintf(messageStream, "ERROR: Could not parse WebSocket url: %s\n", url.c_str()); + //} return NULL; } - //fprintf(stderr, "easywsclient: connecting: host=%s port=%d path=/%s\n", host, port, path); - socket_t sockfd = hostname_connect(host, port); + if (messageStream) { + fprintf(messageStream, "easywsclient: connecting: host=%s port=%d path=/%s\n", host, port, path); + } + socket_t sockfd = hostname_connect(host, port, messageStream); if (sockfd == INVALID_SOCKET) { - fprintf(stderr, "Unable to connect to %s:%d\n", host, port); + if (messageStream) { + fprintf(messageStream, "Unable to connect to %s:%d\n", host, port); + } return NULL; } { @@ -510,8 +533,18 @@ easywsclient::WebSocket::pointer from_url(const std::string& url, bool useMask, snprintf(line, 1024, "\r\n"); ::send(sockfd, line, strlen(line), 0); for (i = 0; i < 2 || (i < 1023 && line[i-2] != '\r' && line[i-1] != '\n'); ++i) { if (recv(sockfd, line+i, 1, 0) == 0) { return NULL; } } line[i] = 0; - if (i == 1023) { fprintf(stderr, "ERROR: Got invalid status line connecting to: %s\n", url.c_str()); return NULL; } - if (sscanf(line, "HTTP/1.1 %d", &status) != 1 || status != 101) { fprintf(stderr, "ERROR: Got bad status connecting to %s: %s", url.c_str(), line); return NULL; } + if (i == 1023) { + if (messageStream) { + fprintf(messageStream, "ERROR: Got invalid status line connecting to: %s\n", url.c_str()); + } + return NULL; + } + if (sscanf(line, "HTTP/1.1 %d", &status) != 1 || status != 101) { + if (messageStream) { + fprintf(messageStream, "ERROR: Got bad status connecting to %s: %s", url.c_str(), line); + } + return NULL; + } // TODO: verify response headers, while (true) { for (i = 0; i < 2 || (i < 1023 && line[i-2] != '\r' && line[i-1] != '\n'); ++i) { if (recv(sockfd, line+i, 1, 0) == 0) { return NULL; } } @@ -526,7 +559,9 @@ easywsclient::WebSocket::pointer from_url(const std::string& url, bool useMask, #else fcntl(sockfd, F_SETFL, O_NONBLOCK); #endif - //fprintf(stderr, "Connected to: %s\n", url.c_str()); + //if (messageStream) { + // fprintf(messageStream, "Connected to: %s\n", url.c_str()); + //} return easywsclient::WebSocket::pointer(new _RealWebSocket(sockfd, useMask)); } @@ -536,6 +571,8 @@ easywsclient::WebSocket::pointer from_url(const std::string& url, bool useMask, namespace easywsclient { +FILE *WebSocket::messageStream = stderr; + WebSocket::pointer WebSocket::create_dummy() { static pointer dummy = pointer(new _DummyWebSocket); return dummy; @@ -543,11 +580,11 @@ WebSocket::pointer WebSocket::create_dummy() { WebSocket::pointer WebSocket::from_url(const std::string& url, const std::string& origin) { - return ::from_url(url, true, origin); + return ::from_url(url, true, origin, messageStream); } WebSocket::pointer WebSocket::from_url_no_mask(const std::string& url, const std::string& origin) { - return ::from_url(url, false, origin); + return ::from_url(url, false, origin, messageStream); } diff --git a/easywsclient.hpp b/easywsclient.hpp index 08c4a7b..42bf052 100644 --- a/easywsclient.hpp +++ b/easywsclient.hpp @@ -8,6 +8,7 @@ // wget https://raw.github.com/dhbaird/easywsclient/master/easywsclient.hpp // wget https://raw.github.com/dhbaird/easywsclient/master/easywsclient.cpp +#include #include #include @@ -62,7 +63,11 @@ class WebSocket { _dispatchBinary(callback); } + // Sets the C stream where diagnostic messages are written. Set to NULL to disable all output. + static void setMessageStream(FILE *stream) { messageStream = stream; } + protected: + static FILE* messageStream; virtual void _dispatch(Callback_Imp& callable) = 0; virtual void _dispatchBinary(BytesCallback_Imp& callable) = 0; };