Compare commits
	
		
			1 Commits
		
	
	
		
			v7.8.8
			...
			feature/ma
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					8192da790f | 
@@ -1,48 +1,13 @@
 | 
			
		||||
# Changelog
 | 
			
		||||
All changes to this project will be documented in this file.
 | 
			
		||||
 | 
			
		||||
## [7.8.7] - 2019-12-28
 | 
			
		||||
 | 
			
		||||
(mbedtls) fix related to private key file parsing and initialization
 | 
			
		||||
 | 
			
		||||
## [7.8.6] - 2019-12-28
 | 
			
		||||
 | 
			
		||||
(ws cobra to sentry/statsd) fix for handling null events properly for empty queues + use queue to send data to statsd
 | 
			
		||||
 | 
			
		||||
## [7.8.5] - 2019-12-28
 | 
			
		||||
 | 
			
		||||
(ws cobra to sentry) handle null events for empty queues
 | 
			
		||||
 | 
			
		||||
## [7.8.4] - 2019-12-27
 | 
			
		||||
 | 
			
		||||
(ws cobra to sentry) game is picked in a fair manner, so that all games get the same share of sent events
 | 
			
		||||
 | 
			
		||||
## [7.8.3] - 2019-12-27
 | 
			
		||||
 | 
			
		||||
(ws cobra to sentry) refactor queue related code into a class
 | 
			
		||||
 | 
			
		||||
## [7.8.2] - 2019-12-25
 | 
			
		||||
 | 
			
		||||
(ws cobra to sentry) bound the queue size used to hold up cobra messages before they are sent to sentry. Default queue size is a 100 messages. Without such limit the program runs out of memory when a subscriber receive a lot of messages that cannot make it to sentry
 | 
			
		||||
 | 
			
		||||
## [7.8.1] - 2019-12-25
 | 
			
		||||
 | 
			
		||||
(ws client) use correct compilation defines so that spdlog is not used as a header only library (reduce binary size and increase compilation speed)
 | 
			
		||||
 | 
			
		||||
## [7.8.0] - 2019-12-24
 | 
			
		||||
 | 
			
		||||
(ws client) all commands use spdlog instead of std::cerr or std::cout for logging
 | 
			
		||||
 | 
			
		||||
## [7.6.5] - 2019-12-24
 | 
			
		||||
 | 
			
		||||
(cobra client) send a websocket ping every 30s to keep the connection opened
 | 
			
		||||
 | 
			
		||||
## [7.6.4] - 2019-12-22
 | 
			
		||||
 | 
			
		||||
(client) error handling, quote url in error case when failing to parse one
 | 
			
		||||
(ws) ws_cobra_publish: register callbacks before connecting
 | 
			
		||||
(doc) mention mbedtls in supported ssl server backend
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## [7.6.3] - 2019-12-20
 | 
			
		||||
 | 
			
		||||
(tls) add a simple description of the TLS configuration routine for debugging
 | 
			
		||||
 
 | 
			
		||||
@@ -24,7 +24,6 @@ namespace ix
 | 
			
		||||
    PublishTrackerCallback CobraConnection::_publishTrackerCallback = nullptr;
 | 
			
		||||
    constexpr size_t CobraConnection::kQueueMaxSize;
 | 
			
		||||
    constexpr CobraConnection::MsgId CobraConnection::kInvalidMsgId;
 | 
			
		||||
    constexpr int CobraConnection::kPingIntervalSecs;
 | 
			
		||||
 | 
			
		||||
    CobraConnection::CobraConnection() :
 | 
			
		||||
        _webSocket(new WebSocket()),
 | 
			
		||||
@@ -229,10 +228,6 @@ namespace ix
 | 
			
		||||
                    ss << "HTTP Status: "      << msg->errorInfo.http_status << std::endl;
 | 
			
		||||
                    invokeErrorCallback(ss.str(), std::string());
 | 
			
		||||
                }
 | 
			
		||||
                else if (msg->type == ix::WebSocketMessageType::Pong)
 | 
			
		||||
                {
 | 
			
		||||
                    invokeEventCallback(ix::CobraConnection_EventType_Pong);
 | 
			
		||||
                }
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -265,7 +260,6 @@ namespace ix
 | 
			
		||||
        _webSocket->setUrl(url);
 | 
			
		||||
        _webSocket->setPerMessageDeflateOptions(webSocketPerMessageDeflateOptions);
 | 
			
		||||
        _webSocket->setTLSOptions(socketTLSOptions);
 | 
			
		||||
        _webSocket->setPingInterval(kPingIntervalSecs);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //
 | 
			
		||||
 
 | 
			
		||||
@@ -30,8 +30,7 @@ namespace ix
 | 
			
		||||
        CobraConnection_EventType_Closed = 3,
 | 
			
		||||
        CobraConnection_EventType_Subscribed = 4,
 | 
			
		||||
        CobraConnection_EventType_UnSubscribed = 5,
 | 
			
		||||
        CobraConnection_EventType_Published = 6,
 | 
			
		||||
        CobraConnection_EventType_Pong = 7
 | 
			
		||||
        CobraConnection_EventType_Published = 6
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    enum CobraConnectionPublishMode
 | 
			
		||||
@@ -216,9 +215,6 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
        // Each pdu sent should have an incremental unique id
 | 
			
		||||
        std::atomic<uint64_t> _id;
 | 
			
		||||
 | 
			
		||||
        // Frequency at which we send a websocket ping to the backing cobra connection
 | 
			
		||||
        static constexpr int kPingIntervalSecs = 30;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
} // namespace ix
 | 
			
		||||
 
 | 
			
		||||
@@ -65,10 +65,6 @@ namespace ix
 | 
			
		||||
                {
 | 
			
		||||
                    ss << "Published message " << msgId << " acked";
 | 
			
		||||
                }
 | 
			
		||||
                else if (eventType == ix::CobraConnection_EventType_Pong)
 | 
			
		||||
                {
 | 
			
		||||
                    ss << "Received websocket pong";
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                ix::IXCoreLogger::Log(ss.str().c_str());
 | 
			
		||||
        });
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,7 @@
 | 
			
		||||
#include "IXSocketConnect.h"
 | 
			
		||||
#include "IXUserAgent.h"
 | 
			
		||||
#include <fstream>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <sstream>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -105,9 +105,7 @@ namespace ix
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    OSStatus SocketAppleSSL::writeToSocket(SSLConnectionRef connection,
 | 
			
		||||
                                           const void* data,
 | 
			
		||||
                                           size_t* len)
 | 
			
		||||
    OSStatus SocketAppleSSL::writeToSocket(SSLConnectionRef connection, const void* data, size_t* len)
 | 
			
		||||
    {
 | 
			
		||||
        int fd = (int) (long) connection;
 | 
			
		||||
        if (fd < 0) return errSSLInternal;
 | 
			
		||||
@@ -148,8 +146,52 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
    bool SocketAppleSSL::accept(std::string& errMsg)
 | 
			
		||||
    {
 | 
			
		||||
        errMsg = "TLS not supported yet in server mode with apple ssl backend";
 | 
			
		||||
        return false;
 | 
			
		||||
        OSStatus status;
 | 
			
		||||
        {
 | 
			
		||||
            std::lock_guard<std::mutex> lock(_mutex);
 | 
			
		||||
 | 
			
		||||
            _sslContext = SSLCreateContext(kCFAllocatorDefault, kSSLServerSide, kSSLStreamType);
 | 
			
		||||
 | 
			
		||||
            SSLSetIOFuncs(_sslContext, SocketAppleSSL::readFromSocket, SocketAppleSSL::writeToSocket);
 | 
			
		||||
            SSLSetConnection(_sslContext, (SSLConnectionRef)(long) _sockfd);
 | 
			
		||||
            SSLSetProtocolVersionMin(_sslContext, kTLSProtocol12);
 | 
			
		||||
 | 
			
		||||
            if (_tlsOptions.isPeerVerifyDisabled())
 | 
			
		||||
            {
 | 
			
		||||
                Boolean option(1);
 | 
			
		||||
                SSLSetSessionOption(_sslContext, kSSLSessionOptionBreakOnServerAuth, option);
 | 
			
		||||
 | 
			
		||||
                do
 | 
			
		||||
                {
 | 
			
		||||
                    status = SSLHandshake(_sslContext);
 | 
			
		||||
                } while (errSSLWouldBlock == status || errSSLServerAuthCompleted == status);
 | 
			
		||||
 | 
			
		||||
                if (status == errSSLServerAuthCompleted)
 | 
			
		||||
                {
 | 
			
		||||
                    // proceed with the handshake
 | 
			
		||||
                    do
 | 
			
		||||
                    {
 | 
			
		||||
                        status = SSLHandshake(_sslContext);
 | 
			
		||||
                    } while (errSSLWouldBlock == status || errSSLServerAuthCompleted == status);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                do
 | 
			
		||||
                {
 | 
			
		||||
                    status = SSLHandshake(_sslContext);
 | 
			
		||||
                } while (errSSLWouldBlock == status || errSSLServerAuthCompleted == status);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (noErr != status)
 | 
			
		||||
        {
 | 
			
		||||
            errMsg = getSSLErrorDescription(status);
 | 
			
		||||
            close();
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // No wait support
 | 
			
		||||
@@ -167,8 +209,7 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
            _sslContext = SSLCreateContext(kCFAllocatorDefault, kSSLClientSide, kSSLStreamType);
 | 
			
		||||
 | 
			
		||||
            SSLSetIOFuncs(
 | 
			
		||||
                _sslContext, SocketAppleSSL::readFromSocket, SocketAppleSSL::writeToSocket);
 | 
			
		||||
            SSLSetIOFuncs(_sslContext, SocketAppleSSL::readFromSocket, SocketAppleSSL::writeToSocket);
 | 
			
		||||
            SSLSetConnection(_sslContext, (SSLConnectionRef)(long) _sockfd);
 | 
			
		||||
            SSLSetProtocolVersionMin(_sslContext, kTLSProtocol12);
 | 
			
		||||
            SSLSetPeerDomainName(_sslContext, host.c_str(), host.size());
 | 
			
		||||
 
 | 
			
		||||
@@ -39,7 +39,6 @@ namespace ix
 | 
			
		||||
        mbedtls_entropy_init(&_entropy);
 | 
			
		||||
        mbedtls_x509_crt_init(&_cacert);
 | 
			
		||||
        mbedtls_x509_crt_init(&_cert);
 | 
			
		||||
        mbedtls_pk_init(&_pkey);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool SocketMbedTLS::init(const std::string& host, bool isClient, std::string& errMsg)
 | 
			
		||||
@@ -82,11 +81,6 @@ namespace ix
 | 
			
		||||
                errMsg = "Cannot parse key file '" + _tlsOptions.keyFile + "'";
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
            if (mbedtls_ssl_conf_own_cert(&_conf, &_cert, &_pkey) < 0)
 | 
			
		||||
            {
 | 
			
		||||
                errMsg = "Problem configuring cert '" + _tlsOptions.certFile + "'";
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (_tlsOptions.isPeerVerifyDisabled())
 | 
			
		||||
@@ -110,6 +104,11 @@ namespace ix
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            mbedtls_ssl_conf_ca_chain(&_conf, &_cacert, NULL);
 | 
			
		||||
 | 
			
		||||
            if (_tlsOptions.hasCertAndKey())
 | 
			
		||||
            {
 | 
			
		||||
                mbedtls_ssl_conf_own_cert(&_conf, &_cert, &_pkey);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (mbedtls_ssl_setup(&_ssl, &_conf) != 0)
 | 
			
		||||
 
 | 
			
		||||
@@ -11,8 +11,8 @@
 | 
			
		||||
#include "IXSocketConnect.h"
 | 
			
		||||
#include "IXSocketFactory.h"
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <sstream>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
namespace ix
 | 
			
		||||
@@ -45,13 +45,13 @@ namespace ix
 | 
			
		||||
    void SocketServer::logError(const std::string& str)
 | 
			
		||||
    {
 | 
			
		||||
        std::lock_guard<std::mutex> lock(_logMutex);
 | 
			
		||||
        fprintf(stderr, "%s\n", str.c_str());
 | 
			
		||||
        std::cerr << str << std::endl;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void SocketServer::logInfo(const std::string& str)
 | 
			
		||||
    {
 | 
			
		||||
        std::lock_guard<std::mutex> lock(_logMutex);
 | 
			
		||||
        fprintf(stdout, "%s\n", str.c_str());
 | 
			
		||||
        std::cout << str << std::endl;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::pair<bool, std::string> SocketServer::listen()
 | 
			
		||||
 
 | 
			
		||||
@@ -6,4 +6,4 @@
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#define IX_WEBSOCKET_VERSION "7.8.7"
 | 
			
		||||
#define IX_WEBSOCKET_VERSION "7.6.4"
 | 
			
		||||
 
 | 
			
		||||
@@ -23,8 +23,6 @@ include_directories(
 | 
			
		||||
  ../ws
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
add_definitions(-DSPDLOG_COMPILED_LIB=1)
 | 
			
		||||
 | 
			
		||||
find_package(JsonCpp)
 | 
			
		||||
if (NOT JSONCPP_FOUND)
 | 
			
		||||
  include_directories(../third_party/jsoncpp)
 | 
			
		||||
@@ -100,6 +98,4 @@ target_link_libraries(ixwebsocket_unittest ixcrypto)
 | 
			
		||||
target_link_libraries(ixwebsocket_unittest ixcore)
 | 
			
		||||
target_link_libraries(ixwebsocket_unittest ixsentry)
 | 
			
		||||
 | 
			
		||||
target_link_libraries(ixwebsocket_unittest spdlog)
 | 
			
		||||
 | 
			
		||||
install(TARGETS ixwebsocket_unittest DESTINATION bin)
 | 
			
		||||
 
 | 
			
		||||
@@ -37,7 +37,9 @@ namespace
 | 
			
		||||
    class CobraChat
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        CobraChat(const std::string& user, const std::string& session, const std::string& endpoint);
 | 
			
		||||
        CobraChat(const std::string& user,
 | 
			
		||||
                   const std::string& session,
 | 
			
		||||
                   const std::string& endpoint);
 | 
			
		||||
 | 
			
		||||
        void subscribe(const std::string& channel);
 | 
			
		||||
        void start();
 | 
			
		||||
 
 | 
			
		||||
@@ -25,8 +25,6 @@ include_directories(ws ../third_party/statsd-client-cpp/src)
 | 
			
		||||
include_directories(ws ../third_party/spdlog/include)
 | 
			
		||||
include_directories(ws ../third_party/cpp-linenoise)
 | 
			
		||||
 | 
			
		||||
add_definitions(-DSPDLOG_COMPILED_LIB=1)
 | 
			
		||||
 | 
			
		||||
if (UNIX)
 | 
			
		||||
  set( STATSD_CLIENT_SOURCES ../third_party/statsd-client-cpp/src/statsd_client.cpp)
 | 
			
		||||
endif()
 | 
			
		||||
@@ -74,8 +72,6 @@ target_link_libraries(ws ixcrypto)
 | 
			
		||||
target_link_libraries(ws ixcore)
 | 
			
		||||
target_link_libraries(ws ixsentry)
 | 
			
		||||
 | 
			
		||||
target_link_libraries(ws spdlog)
 | 
			
		||||
 | 
			
		||||
if(NOT APPLE AND NOT USE_MBED_TLS)
 | 
			
		||||
  find_package(OpenSSL REQUIRED)
 | 
			
		||||
  add_definitions(${OPENSSL_DEFINITIONS})
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										27
									
								
								ws/ws.cpp
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								ws/ws.cpp
									
									
									
									
									
								
							@@ -11,6 +11,7 @@
 | 
			
		||||
 | 
			
		||||
#include <cli11/CLI11.hpp>
 | 
			
		||||
#include <fstream>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <ixcore/utils/IXCoreLogger.h>
 | 
			
		||||
#include <ixwebsocket/IXNetSystem.h>
 | 
			
		||||
#include <ixwebsocket/IXSocket.h>
 | 
			
		||||
@@ -38,13 +39,12 @@ int main(int argc, char** argv)
 | 
			
		||||
    // Display command.
 | 
			
		||||
    if (getenv("DEBUG"))
 | 
			
		||||
    {
 | 
			
		||||
        std::stringstream ss;
 | 
			
		||||
        ss << "Command: ";
 | 
			
		||||
        std::cout << "Command: ";
 | 
			
		||||
        for (int i = 0; i < argc; ++i)
 | 
			
		||||
        {
 | 
			
		||||
            ss << argv[i] << " ";
 | 
			
		||||
            std::cout << argv[i] << " ";
 | 
			
		||||
        }
 | 
			
		||||
        spdlog::info(ss.str());
 | 
			
		||||
        std::cout << std::endl;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    CLI::App app {"ws is a websocket tool"};
 | 
			
		||||
@@ -105,7 +105,6 @@ int main(int argc, char** argv)
 | 
			
		||||
    int count = 1;
 | 
			
		||||
    int jobs = 4;
 | 
			
		||||
    uint32_t maxWaitBetweenReconnectionRetries;
 | 
			
		||||
    size_t maxQueueSize = 100;
 | 
			
		||||
 | 
			
		||||
    auto addTLSOptions = [&tlsOptions, &verifyNone](CLI::App* app) {
 | 
			
		||||
        app->add_option(
 | 
			
		||||
@@ -269,9 +268,6 @@ int main(int argc, char** argv)
 | 
			
		||||
    cobra2sentry->add_option("--rolesecret", rolesecret, "Role secret")->required();
 | 
			
		||||
    cobra2sentry->add_option("--dsn", dsn, "Sentry DSN");
 | 
			
		||||
    cobra2sentry->add_option("--jobs", jobs, "Number of thread sending events to Sentry");
 | 
			
		||||
    cobra2sentry->add_option("--queue_size",
 | 
			
		||||
                             maxQueueSize,
 | 
			
		||||
                             "Size of the queue to hold messages before they are sent to Sentry");
 | 
			
		||||
    cobra2sentry->add_option("channel", channel, "Channel")->required();
 | 
			
		||||
    cobra2sentry->add_flag("-v", verbose, "Verbose");
 | 
			
		||||
    cobra2sentry->add_flag("-s", strict, "Strict mode. Error out when sending to sentry fails");
 | 
			
		||||
@@ -459,7 +455,6 @@ int main(int argc, char** argv)
 | 
			
		||||
                                          verbose,
 | 
			
		||||
                                          strict,
 | 
			
		||||
                                          jobs,
 | 
			
		||||
                                          maxQueueSize,
 | 
			
		||||
                                          tlsOptions);
 | 
			
		||||
    }
 | 
			
		||||
    else if (app.got_subcommand("cobra_metrics_to_redis"))
 | 
			
		||||
@@ -476,14 +471,8 @@ int main(int argc, char** argv)
 | 
			
		||||
    }
 | 
			
		||||
    else if (app.got_subcommand("snake"))
 | 
			
		||||
    {
 | 
			
		||||
        ret = ix::ws_snake_main(port,
 | 
			
		||||
                                hostname,
 | 
			
		||||
                                redisHosts,
 | 
			
		||||
                                redisPort,
 | 
			
		||||
                                redisPassword,
 | 
			
		||||
                                verbose,
 | 
			
		||||
                                appsConfigPath,
 | 
			
		||||
                                tlsOptions);
 | 
			
		||||
        ret = ix::ws_snake_main(
 | 
			
		||||
            port, hostname, redisHosts, redisPort, redisPassword, verbose, appsConfigPath, tlsOptions);
 | 
			
		||||
    }
 | 
			
		||||
    else if (app.got_subcommand("httpd"))
 | 
			
		||||
    {
 | 
			
		||||
@@ -507,11 +496,11 @@ int main(int argc, char** argv)
 | 
			
		||||
    }
 | 
			
		||||
    else if (version)
 | 
			
		||||
    {
 | 
			
		||||
        spdlog::info("ws {}", ix::userAgent());
 | 
			
		||||
        std::cout << "ws " << ix::userAgent() << std::endl;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        spdlog::error("A subcommand or --version is required");
 | 
			
		||||
        std::cerr << "A subcommand or --version is required" << std::endl;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ix::uninitNetSystem();
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								ws/ws.h
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								ws/ws.h
									
									
									
									
									
								
							@@ -119,7 +119,6 @@ namespace ix
 | 
			
		||||
                                bool verbose,
 | 
			
		||||
                                bool strict,
 | 
			
		||||
                                int jobs,
 | 
			
		||||
                                size_t maxQueueSize,
 | 
			
		||||
                                const ix::SocketTLSOptions& tlsOptions);
 | 
			
		||||
 | 
			
		||||
    int ws_cobra_metrics_to_redis(const std::string& appkey,
 | 
			
		||||
 
 | 
			
		||||
@@ -32,6 +32,7 @@
 | 
			
		||||
 | 
			
		||||
#include <atomic>
 | 
			
		||||
#include <condition_variable>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <ixwebsocket/IXSocket.h>
 | 
			
		||||
#include <ixwebsocket/IXWebSocket.h>
 | 
			
		||||
#include <mutex>
 | 
			
		||||
@@ -90,7 +91,7 @@ namespace ix
 | 
			
		||||
    {
 | 
			
		||||
        if (!_quiet)
 | 
			
		||||
        {
 | 
			
		||||
            spdlog::info(msg);
 | 
			
		||||
            std::cerr << msg;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -182,7 +183,7 @@ namespace ix
 | 
			
		||||
        webSocket.setOnMessageCallback([&condition, &success](const ix::WebSocketMessagePtr& msg) {
 | 
			
		||||
            if (msg->type == ix::WebSocketMessageType::Close)
 | 
			
		||||
            {
 | 
			
		||||
                spdlog::info("Report generated");
 | 
			
		||||
                std::cerr << "Report generated" << std::endl;
 | 
			
		||||
                condition.notify_one();
 | 
			
		||||
            }
 | 
			
		||||
            else if (msg->type == ix::WebSocketMessageType::Error)
 | 
			
		||||
@@ -192,7 +193,7 @@ namespace ix
 | 
			
		||||
                ss << "#retries: " << msg->errorInfo.retries << std::endl;
 | 
			
		||||
                ss << "Wait time(ms): " << msg->errorInfo.wait_time << std::endl;
 | 
			
		||||
                ss << "HTTP Status: " << msg->errorInfo.http_status << std::endl;
 | 
			
		||||
                spdlog::info(ss.str());
 | 
			
		||||
                std::cerr << ss.str() << std::endl;
 | 
			
		||||
 | 
			
		||||
                success = false;
 | 
			
		||||
            }
 | 
			
		||||
@@ -235,7 +236,7 @@ namespace ix
 | 
			
		||||
                ss << "#retries: " << msg->errorInfo.retries << std::endl;
 | 
			
		||||
                ss << "Wait time(ms): " << msg->errorInfo.wait_time << std::endl;
 | 
			
		||||
                ss << "HTTP Status: " << msg->errorInfo.http_status << std::endl;
 | 
			
		||||
                spdlog::info(ss.str());
 | 
			
		||||
                std::cerr << ss.str() << std::endl;
 | 
			
		||||
 | 
			
		||||
                condition.notify_one();
 | 
			
		||||
            }
 | 
			
		||||
@@ -268,7 +269,7 @@ namespace ix
 | 
			
		||||
    int ws_autobahn_main(const std::string& url, bool quiet)
 | 
			
		||||
    {
 | 
			
		||||
        int testCasesCount = getTestCaseCount(url);
 | 
			
		||||
        spdlog::info("Test cases count: {}", testCasesCount);
 | 
			
		||||
        std::cerr << "Test cases count: " << testCasesCount << std::endl;
 | 
			
		||||
 | 
			
		||||
        if (testCasesCount == -1)
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -4,18 +4,17 @@
 | 
			
		||||
 *  Copyright (c) 2018 Machine Zone, Inc. All rights reserved.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <ixwebsocket/IXWebSocketServer.h>
 | 
			
		||||
#include <spdlog/spdlog.h>
 | 
			
		||||
#include <sstream>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace ix
 | 
			
		||||
{
 | 
			
		||||
    int ws_broadcast_server_main(int port,
 | 
			
		||||
                                 const std::string& hostname,
 | 
			
		||||
                                 const ix::SocketTLSOptions& tlsOptions)
 | 
			
		||||
    {
 | 
			
		||||
        spdlog::info("Listening on {}:{}", hostname, port);
 | 
			
		||||
        std::cout << "Listening on " << hostname << ":" << port << std::endl;
 | 
			
		||||
 | 
			
		||||
        ix::WebSocketServer server(port, hostname);
 | 
			
		||||
        server.setTLSOptions(tlsOptions);
 | 
			
		||||
@@ -26,20 +25,20 @@ namespace ix
 | 
			
		||||
                                                const WebSocketMessagePtr& msg) {
 | 
			
		||||
                if (msg->type == ix::WebSocketMessageType::Open)
 | 
			
		||||
                {
 | 
			
		||||
                    spdlog::info("New connection");
 | 
			
		||||
                    spdlog::info("id: {}", connectionState->getId());
 | 
			
		||||
                    spdlog::info("Uri: {}", msg->openInfo.uri);
 | 
			
		||||
                    spdlog::info("Headers:");
 | 
			
		||||
                    std::cerr << "New connection" << std::endl;
 | 
			
		||||
                    std::cerr << "id: " << connectionState->getId() << std::endl;
 | 
			
		||||
                    std::cerr << "Uri: " << msg->openInfo.uri << std::endl;
 | 
			
		||||
                    std::cerr << "Headers:" << std::endl;
 | 
			
		||||
                    for (auto it : msg->openInfo.headers)
 | 
			
		||||
                    {
 | 
			
		||||
                        spdlog::info("{}: {}", it.first, it.second);
 | 
			
		||||
                        std::cerr << it.first << ": " << it.second << std::endl;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else if (msg->type == ix::WebSocketMessageType::Close)
 | 
			
		||||
                {
 | 
			
		||||
                    spdlog::info("Closed connection: code {} reason {}",
 | 
			
		||||
                                 msg->closeInfo.code,
 | 
			
		||||
                                 msg->closeInfo.reason);
 | 
			
		||||
                    std::cerr << "Closed connection"
 | 
			
		||||
                              << " code " << msg->closeInfo.code << " reason "
 | 
			
		||||
                              << msg->closeInfo.reason << std::endl;
 | 
			
		||||
                }
 | 
			
		||||
                else if (msg->type == ix::WebSocketMessageType::Error)
 | 
			
		||||
                {
 | 
			
		||||
@@ -48,29 +47,30 @@ namespace ix
 | 
			
		||||
                    ss << "#retries: " << msg->errorInfo.retries << std::endl;
 | 
			
		||||
                    ss << "Wait time(ms): " << msg->errorInfo.wait_time << std::endl;
 | 
			
		||||
                    ss << "HTTP Status: " << msg->errorInfo.http_status << std::endl;
 | 
			
		||||
                    spdlog::info(ss.str());
 | 
			
		||||
                    std::cerr << ss.str();
 | 
			
		||||
                }
 | 
			
		||||
                else if (msg->type == ix::WebSocketMessageType::Fragment)
 | 
			
		||||
                {
 | 
			
		||||
                    spdlog::info("Received message fragment");
 | 
			
		||||
                    std::cerr << "Received message fragment" << std::endl;
 | 
			
		||||
                }
 | 
			
		||||
                else if (msg->type == ix::WebSocketMessageType::Message)
 | 
			
		||||
                {
 | 
			
		||||
                    spdlog::info("Received {} bytes", msg->wireSize);
 | 
			
		||||
                    std::cerr << "Received " << msg->wireSize << " bytes" << std::endl;
 | 
			
		||||
 | 
			
		||||
                    for (auto&& client : server.getClients())
 | 
			
		||||
                    {
 | 
			
		||||
                        if (client != webSocket)
 | 
			
		||||
                        {
 | 
			
		||||
                            client->send(msg->str, msg->binary, [](int current, int total) -> bool {
 | 
			
		||||
                                spdlog::info("Step {} out of {}", current, total);
 | 
			
		||||
                                std::cerr << "Step " << current << " out of " << total << std::endl;
 | 
			
		||||
                                return true;
 | 
			
		||||
                            });
 | 
			
		||||
 | 
			
		||||
                            do
 | 
			
		||||
                            {
 | 
			
		||||
                                size_t bufferedAmount = client->bufferedAmount();
 | 
			
		||||
                                spdlog::info("{} bytes left to be sent", bufferedAmount);
 | 
			
		||||
                                std::cerr << bufferedAmount << " bytes left to be sent"
 | 
			
		||||
                                          << std::endl;
 | 
			
		||||
 | 
			
		||||
                                std::chrono::duration<double, std::milli> duration(10);
 | 
			
		||||
                                std::this_thread::sleep_for(duration);
 | 
			
		||||
@@ -84,7 +84,7 @@ namespace ix
 | 
			
		||||
        auto res = server.listen();
 | 
			
		||||
        if (!res.first)
 | 
			
		||||
        {
 | 
			
		||||
            spdlog::info(res.second);
 | 
			
		||||
            std::cerr << res.second << std::endl;
 | 
			
		||||
            return 1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -9,12 +9,11 @@
 | 
			
		||||
// Broadcast server can be ran with `ws broadcast_server`
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#include "linenoise.hpp"
 | 
			
		||||
#include "nlohmann/json.hpp"
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <ixwebsocket/IXSocket.h>
 | 
			
		||||
#include <ixwebsocket/IXWebSocket.h>
 | 
			
		||||
#include <queue>
 | 
			
		||||
#include <spdlog/spdlog.h>
 | 
			
		||||
#include <sstream>
 | 
			
		||||
 | 
			
		||||
// for convenience
 | 
			
		||||
@@ -56,7 +55,7 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
    void WebSocketChat::log(const std::string& msg)
 | 
			
		||||
    {
 | 
			
		||||
        spdlog::info(msg);
 | 
			
		||||
        std::cout << msg << std::endl;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    size_t WebSocketChat::getReceivedMessagesCount() const
 | 
			
		||||
@@ -86,21 +85,20 @@ namespace ix
 | 
			
		||||
            if (msg->type == ix::WebSocketMessageType::Open)
 | 
			
		||||
            {
 | 
			
		||||
                log("ws chat: connected");
 | 
			
		||||
                spdlog::info("Uri: {}", msg->openInfo.uri);
 | 
			
		||||
                spdlog::info("Headers:");
 | 
			
		||||
                std::cout << "Uri: " << msg->openInfo.uri << std::endl;
 | 
			
		||||
                std::cout << "Handshake Headers:" << std::endl;
 | 
			
		||||
                for (auto it : msg->openInfo.headers)
 | 
			
		||||
                {
 | 
			
		||||
                    spdlog::info("{}: {}", it.first, it.second);
 | 
			
		||||
                    std::cout << it.first << ": " << it.second << std::endl;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                spdlog::info("ws chat: user {} connected !", _user);
 | 
			
		||||
                ss << "ws chat: user " << _user << " Connected !";
 | 
			
		||||
                log(ss.str());
 | 
			
		||||
            }
 | 
			
		||||
            else if (msg->type == ix::WebSocketMessageType::Close)
 | 
			
		||||
            {
 | 
			
		||||
                ss << "ws chat user disconnected: " << _user;
 | 
			
		||||
                ss << " code " << msg->closeInfo.code;
 | 
			
		||||
                ss << " reason " << msg->closeInfo.reason << std::endl;
 | 
			
		||||
                ss << "ws chat: user " << _user << " disconnected !"
 | 
			
		||||
                   << " code " << msg->closeInfo.code << " reason " << msg->closeInfo.reason;
 | 
			
		||||
                log(ss.str());
 | 
			
		||||
            }
 | 
			
		||||
            else if (msg->type == ix::WebSocketMessageType::Message)
 | 
			
		||||
@@ -164,25 +162,25 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
    int ws_chat_main(const std::string& url, const std::string& user)
 | 
			
		||||
    {
 | 
			
		||||
        spdlog::info("Type Ctrl-D to exit prompt...");
 | 
			
		||||
        std::cout << "Type Ctrl-D to exit prompt..." << std::endl;
 | 
			
		||||
        WebSocketChat webSocketChat(url, user);
 | 
			
		||||
        webSocketChat.start();
 | 
			
		||||
 | 
			
		||||
        while (true)
 | 
			
		||||
        {
 | 
			
		||||
            // Read line
 | 
			
		||||
            std::string line;
 | 
			
		||||
            auto quit = linenoise::Readline("> ", line);
 | 
			
		||||
            std::string text;
 | 
			
		||||
            std::cout << user << " > " << std::flush;
 | 
			
		||||
            std::getline(std::cin, text);
 | 
			
		||||
 | 
			
		||||
            if (quit)
 | 
			
		||||
            if (!std::cin)
 | 
			
		||||
            {
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            webSocketChat.sendMessage(line);
 | 
			
		||||
            webSocketChat.sendMessage(text);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        spdlog::info("");
 | 
			
		||||
        std::cout << std::endl;
 | 
			
		||||
        webSocketChat.stop();
 | 
			
		||||
 | 
			
		||||
        return 0;
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,7 @@
 | 
			
		||||
#include <atomic>
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#include <fstream>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <ixcobra/IXCobraMetricsPublisher.h>
 | 
			
		||||
#include <jsoncpp/json/json.h>
 | 
			
		||||
#include <spdlog/spdlog.h>
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,7 @@
 | 
			
		||||
#include <atomic>
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#include <condition_variable>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <ixcobra/IXCobraConnection.h>
 | 
			
		||||
#include <ixsnake/IXRedisClient.h>
 | 
			
		||||
#include <mutex>
 | 
			
		||||
@@ -43,7 +44,8 @@ namespace ix
 | 
			
		||||
        auto timer = [&msgPerSeconds, &msgCount] {
 | 
			
		||||
            while (true)
 | 
			
		||||
            {
 | 
			
		||||
                spdlog::info("#messages {} msg/s {}", msgCount, msgPerSeconds);
 | 
			
		||||
                std::cout << "#messages " << msgCount << " "
 | 
			
		||||
                          << "msg/s " << msgPerSeconds << std::endl;
 | 
			
		||||
 | 
			
		||||
                msgPerSeconds = 0;
 | 
			
		||||
                auto duration = std::chrono::seconds(1);
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,7 @@
 | 
			
		||||
#include <atomic>
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#include <fstream>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <ixcobra/IXCobraMetricsPublisher.h>
 | 
			
		||||
#include <jsoncpp/json/json.h>
 | 
			
		||||
#include <mutex>
 | 
			
		||||
@@ -90,10 +91,6 @@ namespace ix
 | 
			
		||||
                spdlog::info("Published message id {} acked", msgId);
 | 
			
		||||
                messageAcked = true;
 | 
			
		||||
            }
 | 
			
		||||
            else if (eventType == ix::CobraConnection_EventType_Pong)
 | 
			
		||||
            {
 | 
			
		||||
                spdlog::info("Received websocket pong");
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        conn.connect();
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,7 @@
 | 
			
		||||
 | 
			
		||||
#include <atomic>
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <ixcobra/IXCobraConnection.h>
 | 
			
		||||
#include <spdlog/spdlog.h>
 | 
			
		||||
#include <sstream>
 | 
			
		||||
@@ -40,7 +41,8 @@ namespace ix
 | 
			
		||||
        auto timer = [&msgPerSeconds, &msgCount] {
 | 
			
		||||
            while (true)
 | 
			
		||||
            {
 | 
			
		||||
                spdlog::info("#messages {} msg/s {}", msgCount, msgPerSeconds);
 | 
			
		||||
                std::cout << "#messages " << msgCount << " "
 | 
			
		||||
                          << "msg/s " << msgPerSeconds << std::endl;
 | 
			
		||||
 | 
			
		||||
                msgPerSeconds = 0;
 | 
			
		||||
                auto duration = std::chrono::seconds(1);
 | 
			
		||||
@@ -75,7 +77,7 @@ namespace ix
 | 
			
		||||
                        [&jsonWriter, &quiet, &msgPerSeconds, &msgCount](const Json::Value& msg) {
 | 
			
		||||
                            if (!quiet)
 | 
			
		||||
                            {
 | 
			
		||||
                                spdlog::info(jsonWriter.write(msg));
 | 
			
		||||
                                std::cerr << jsonWriter.write(msg) << std::endl;
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
                            msgPerSeconds++;
 | 
			
		||||
@@ -98,10 +100,6 @@ namespace ix
 | 
			
		||||
                {
 | 
			
		||||
                    spdlog::error("Published message hacked: {}", msgId);
 | 
			
		||||
                }
 | 
			
		||||
                else if (eventType == ix::CobraConnection_EventType_Pong)
 | 
			
		||||
                {
 | 
			
		||||
                    spdlog::info("Received websocket pong");
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
        while (true)
 | 
			
		||||
 
 | 
			
		||||
@@ -7,9 +7,9 @@
 | 
			
		||||
#include <atomic>
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#include <condition_variable>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <ixcobra/IXCobraConnection.h>
 | 
			
		||||
#include <ixsentry/IXSentryClient.h>
 | 
			
		||||
#include <map>
 | 
			
		||||
#include <mutex>
 | 
			
		||||
#include <queue>
 | 
			
		||||
#include <spdlog/spdlog.h>
 | 
			
		||||
@@ -19,81 +19,6 @@
 | 
			
		||||
 | 
			
		||||
namespace ix
 | 
			
		||||
{
 | 
			
		||||
    class QueueManager
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        QueueManager(size_t maxQueueSize, std::atomic<bool>& stop)
 | 
			
		||||
            : _maxQueueSize(maxQueueSize)
 | 
			
		||||
            , _stop(stop)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Json::Value pop();
 | 
			
		||||
        void add(Json::Value msg);
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        std::map<std::string, std::queue<Json::Value>> _queues;
 | 
			
		||||
        std::mutex _mutex;
 | 
			
		||||
        std::condition_variable _condition;
 | 
			
		||||
        size_t _maxQueueSize;
 | 
			
		||||
        std::atomic<bool>& _stop;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    Json::Value QueueManager::pop()
 | 
			
		||||
    {
 | 
			
		||||
        std::unique_lock<std::mutex> lock(_mutex);
 | 
			
		||||
 | 
			
		||||
        if (_queues.empty())
 | 
			
		||||
        {
 | 
			
		||||
            Json::Value val;
 | 
			
		||||
            return val;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        std::vector<std::string> games;
 | 
			
		||||
        for (auto it : _queues)
 | 
			
		||||
        {
 | 
			
		||||
            games.push_back(it.first);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        std::random_shuffle(games.begin(), games.end());
 | 
			
		||||
        std::string game = games[0];
 | 
			
		||||
 | 
			
		||||
        spdlog::info("Sending event for game '{}'", game);
 | 
			
		||||
 | 
			
		||||
        _condition.wait(lock, [this] { return !_stop; });
 | 
			
		||||
 | 
			
		||||
        if (_queues[game].empty())
 | 
			
		||||
        {
 | 
			
		||||
            Json::Value val;
 | 
			
		||||
            return val;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        auto msg = _queues[game].front();
 | 
			
		||||
        _queues[game].pop();
 | 
			
		||||
        return msg;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void QueueManager::add(Json::Value msg)
 | 
			
		||||
    {
 | 
			
		||||
        std::unique_lock<std::mutex> lock(_mutex);
 | 
			
		||||
 | 
			
		||||
        std::string game;
 | 
			
		||||
        if (msg.isMember("device") && msg["device"].isMember("game"))
 | 
			
		||||
        {
 | 
			
		||||
            game = msg["device"]["game"].asString();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (game.empty()) return;
 | 
			
		||||
 | 
			
		||||
        // if the sending is not fast enough there is no point
 | 
			
		||||
        // in queuing too many events.
 | 
			
		||||
        if (_queues[game].size() < _maxQueueSize)
 | 
			
		||||
        {
 | 
			
		||||
            _queues[game].push(msg);
 | 
			
		||||
            _condition.notify_one();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int ws_cobra_to_sentry_main(const std::string& appkey,
 | 
			
		||||
                                const std::string& endpoint,
 | 
			
		||||
                                const std::string& rolename,
 | 
			
		||||
@@ -104,7 +29,6 @@ namespace ix
 | 
			
		||||
                                bool verbose,
 | 
			
		||||
                                bool strict,
 | 
			
		||||
                                int jobs,
 | 
			
		||||
                                size_t maxQueueSize,
 | 
			
		||||
                                const ix::SocketTLSOptions& tlsOptions)
 | 
			
		||||
    {
 | 
			
		||||
        ix::CobraConnection conn;
 | 
			
		||||
@@ -123,7 +47,9 @@ namespace ix
 | 
			
		||||
        std::atomic<bool> stop(false);
 | 
			
		||||
        std::atomic<bool> throttled(false);
 | 
			
		||||
 | 
			
		||||
        QueueManager queueManager(maxQueueSize, stop);
 | 
			
		||||
        std::condition_variable condition;
 | 
			
		||||
        std::mutex conditionVariableMutex;
 | 
			
		||||
        std::queue<Json::Value> queue;
 | 
			
		||||
 | 
			
		||||
        auto timer = [&sentCount, &receivedCount] {
 | 
			
		||||
            while (true)
 | 
			
		||||
@@ -137,93 +63,105 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
        std::thread t1(timer);
 | 
			
		||||
 | 
			
		||||
        auto sentrySender =
 | 
			
		||||
            [&queueManager, verbose, &errorSending, &sentCount, &stop, &throttled, &dsn] {
 | 
			
		||||
                SentryClient sentryClient(dsn);
 | 
			
		||||
        auto sentrySender = [&condition,
 | 
			
		||||
                             &conditionVariableMutex,
 | 
			
		||||
                             &queue,
 | 
			
		||||
                             verbose,
 | 
			
		||||
                             &errorSending,
 | 
			
		||||
                             &sentCount,
 | 
			
		||||
                             &stop,
 | 
			
		||||
                             &throttled,
 | 
			
		||||
                             &dsn] {
 | 
			
		||||
            SentryClient sentryClient(dsn);
 | 
			
		||||
 | 
			
		||||
            while (true)
 | 
			
		||||
            {
 | 
			
		||||
                Json::Value msg;
 | 
			
		||||
 | 
			
		||||
                while (true)
 | 
			
		||||
                {
 | 
			
		||||
                    Json::Value msg = queueManager.pop();
 | 
			
		||||
                    std::unique_lock<std::mutex> lock(conditionVariableMutex);
 | 
			
		||||
                    condition.wait(lock, [&queue, &stop] { return !queue.empty() && !stop; });
 | 
			
		||||
 | 
			
		||||
                    if (msg.isNull()) continue;
 | 
			
		||||
                    if (stop) return;
 | 
			
		||||
 | 
			
		||||
                    auto ret = sentryClient.send(msg, verbose);
 | 
			
		||||
                    HttpResponsePtr response = ret.first;
 | 
			
		||||
 | 
			
		||||
                    if (!response)
 | 
			
		||||
                    {
 | 
			
		||||
                        spdlog::warn("Null HTTP Response");
 | 
			
		||||
                        continue;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    if (verbose)
 | 
			
		||||
                    {
 | 
			
		||||
                        for (auto it : response->headers)
 | 
			
		||||
                        {
 | 
			
		||||
                            spdlog::info("{}: {}", it.first, it.second);
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        spdlog::info("Upload size: {}", response->uploadSize);
 | 
			
		||||
                        spdlog::info("Download size: {}", response->downloadSize);
 | 
			
		||||
 | 
			
		||||
                        spdlog::info("Status: {}", response->statusCode);
 | 
			
		||||
                        if (response->errorCode != HttpErrorCode::Ok)
 | 
			
		||||
                        {
 | 
			
		||||
                            spdlog::info("error message: {}", response->errorMsg);
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        if (response->headers["Content-Type"] != "application/octet-stream")
 | 
			
		||||
                        {
 | 
			
		||||
                            spdlog::info("payload: {}", response->payload);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    if (response->statusCode != 200)
 | 
			
		||||
                    {
 | 
			
		||||
                        spdlog::error("Error sending data to sentry: {}", response->statusCode);
 | 
			
		||||
                        spdlog::error("Body: {}", ret.second);
 | 
			
		||||
                        spdlog::error("Response: {}", response->payload);
 | 
			
		||||
                        errorSending = true;
 | 
			
		||||
 | 
			
		||||
                        // Error 429 Too Many Requests
 | 
			
		||||
                        if (response->statusCode == 429)
 | 
			
		||||
                        {
 | 
			
		||||
                            auto retryAfter = response->headers["Retry-After"];
 | 
			
		||||
                            std::stringstream ss;
 | 
			
		||||
                            ss << retryAfter;
 | 
			
		||||
                            int seconds;
 | 
			
		||||
                            ss >> seconds;
 | 
			
		||||
 | 
			
		||||
                            if (!ss.eof() || ss.fail())
 | 
			
		||||
                            {
 | 
			
		||||
                                seconds = 30;
 | 
			
		||||
                                spdlog::warn("Error parsing Retry-After header. "
 | 
			
		||||
                                             "Using {} for the sleep duration",
 | 
			
		||||
                                             seconds);
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
                            spdlog::warn("Error 429 - Too Many Requests. ws will sleep "
 | 
			
		||||
                                         "and retry after {} seconds",
 | 
			
		||||
                                         retryAfter);
 | 
			
		||||
 | 
			
		||||
                            throttled = true;
 | 
			
		||||
                            auto duration = std::chrono::seconds(seconds);
 | 
			
		||||
                            std::this_thread::sleep_for(duration);
 | 
			
		||||
                            throttled = false;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        ++sentCount;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    if (stop) return;
 | 
			
		||||
                    msg = queue.front();
 | 
			
		||||
                    queue.pop();
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
                auto ret = sentryClient.send(msg, verbose);
 | 
			
		||||
                HttpResponsePtr response = ret.first;
 | 
			
		||||
 | 
			
		||||
                if (!response)
 | 
			
		||||
                {
 | 
			
		||||
                    spdlog::warn("Null HTTP Response");
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (verbose)
 | 
			
		||||
                {
 | 
			
		||||
                    for (auto it : response->headers)
 | 
			
		||||
                    {
 | 
			
		||||
                        spdlog::info("{}: {}", it.first, it.second);
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    spdlog::info("Upload size: {}", response->uploadSize);
 | 
			
		||||
                    spdlog::info("Download size: {}", response->downloadSize);
 | 
			
		||||
 | 
			
		||||
                    spdlog::info("Status: {}", response->statusCode);
 | 
			
		||||
                    if (response->errorCode != HttpErrorCode::Ok)
 | 
			
		||||
                    {
 | 
			
		||||
                        spdlog::info("error message: {}", response->errorMsg);
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    if (response->headers["Content-Type"] != "application/octet-stream")
 | 
			
		||||
                    {
 | 
			
		||||
                        spdlog::info("payload: {}", response->payload);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (response->statusCode != 200)
 | 
			
		||||
                {
 | 
			
		||||
                    spdlog::error("Error sending data to sentry: {}", response->statusCode);
 | 
			
		||||
                    spdlog::error("Body: {}", ret.second);
 | 
			
		||||
                    spdlog::error("Response: {}", response->payload);
 | 
			
		||||
                    errorSending = true;
 | 
			
		||||
 | 
			
		||||
                    // Error 429 Too Many Requests
 | 
			
		||||
                    if (response->statusCode == 429)
 | 
			
		||||
                    {
 | 
			
		||||
                        auto retryAfter = response->headers["Retry-After"];
 | 
			
		||||
                        std::stringstream ss;
 | 
			
		||||
                        ss << retryAfter;
 | 
			
		||||
                        int seconds;
 | 
			
		||||
                        ss >> seconds;
 | 
			
		||||
 | 
			
		||||
                        if (!ss.eof() || ss.fail())
 | 
			
		||||
                        {
 | 
			
		||||
                            seconds = 30;
 | 
			
		||||
                            spdlog::warn("Error parsing Retry-After header. "
 | 
			
		||||
                                         "Using {} for the sleep duration",
 | 
			
		||||
                                         seconds);
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        spdlog::warn("Error 429 - Too Many Requests. ws will sleep "
 | 
			
		||||
                                     "and retry after {} seconds",
 | 
			
		||||
                                     retryAfter);
 | 
			
		||||
 | 
			
		||||
                        throttled = true;
 | 
			
		||||
                        auto duration = std::chrono::seconds(seconds);
 | 
			
		||||
                        std::this_thread::sleep_for(duration);
 | 
			
		||||
                        throttled = false;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    ++sentCount;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (stop) return;
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        // Create a thread pool
 | 
			
		||||
        spdlog::info("Starting {} sentry sender jobs", jobs);
 | 
			
		||||
        std::cerr << "Starting " << jobs << " sentry sender jobs" << std::endl;
 | 
			
		||||
        std::vector<std::thread> pool;
 | 
			
		||||
        for (int i = 0; i < jobs; i++)
 | 
			
		||||
        {
 | 
			
		||||
@@ -237,11 +175,13 @@ namespace ix
 | 
			
		||||
                               verbose,
 | 
			
		||||
                               &throttled,
 | 
			
		||||
                               &receivedCount,
 | 
			
		||||
                               &queueManager](ix::CobraConnectionEventType eventType,
 | 
			
		||||
                                              const std::string& errMsg,
 | 
			
		||||
                                              const ix::WebSocketHttpHeaders& headers,
 | 
			
		||||
                                              const std::string& subscriptionId,
 | 
			
		||||
                                              CobraConnection::MsgId msgId) {
 | 
			
		||||
                               &condition,
 | 
			
		||||
                               &conditionVariableMutex,
 | 
			
		||||
                               &queue](ix::CobraConnectionEventType eventType,
 | 
			
		||||
                                       const std::string& errMsg,
 | 
			
		||||
                                       const ix::WebSocketHttpHeaders& headers,
 | 
			
		||||
                                       const std::string& subscriptionId,
 | 
			
		||||
                                       CobraConnection::MsgId msgId) {
 | 
			
		||||
            if (eventType == ix::CobraConnection_EventType_Open)
 | 
			
		||||
            {
 | 
			
		||||
                spdlog::info("Subscriber connected");
 | 
			
		||||
@@ -257,11 +197,16 @@ namespace ix
 | 
			
		||||
            }
 | 
			
		||||
            else if (eventType == ix::CobraConnection_EventType_Authenticated)
 | 
			
		||||
            {
 | 
			
		||||
                spdlog::info("Subscriber authenticated");
 | 
			
		||||
                std::cerr << "Subscriber authenticated" << std::endl;
 | 
			
		||||
                conn.subscribe(channel,
 | 
			
		||||
                               filter,
 | 
			
		||||
                               [&jsonWriter, verbose, &throttled, &receivedCount, &queueManager](
 | 
			
		||||
                                   const Json::Value& msg) {
 | 
			
		||||
                               [&jsonWriter,
 | 
			
		||||
                                verbose,
 | 
			
		||||
                                &throttled,
 | 
			
		||||
                                &receivedCount,
 | 
			
		||||
                                &condition,
 | 
			
		||||
                                &conditionVariableMutex,
 | 
			
		||||
                                &queue](const Json::Value& msg) {
 | 
			
		||||
                                   if (verbose)
 | 
			
		||||
                                   {
 | 
			
		||||
                                       spdlog::info(jsonWriter.write(msg));
 | 
			
		||||
@@ -270,11 +215,18 @@ namespace ix
 | 
			
		||||
                                   // If we cannot send to sentry fast enough, drop the message
 | 
			
		||||
                                   if (throttled)
 | 
			
		||||
                                   {
 | 
			
		||||
                                       condition.notify_one();
 | 
			
		||||
                                       return;
 | 
			
		||||
                                   }
 | 
			
		||||
 | 
			
		||||
                                   ++receivedCount;
 | 
			
		||||
                                   queueManager.add(msg);
 | 
			
		||||
 | 
			
		||||
                                   {
 | 
			
		||||
                                       std::unique_lock<std::mutex> lock(conditionVariableMutex);
 | 
			
		||||
                                       queue.push(msg);
 | 
			
		||||
                                   }
 | 
			
		||||
 | 
			
		||||
                                   condition.notify_one();
 | 
			
		||||
                               });
 | 
			
		||||
            }
 | 
			
		||||
            else if (eventType == ix::CobraConnection_EventType_Subscribed)
 | 
			
		||||
@@ -293,10 +245,6 @@ namespace ix
 | 
			
		||||
            {
 | 
			
		||||
                spdlog::error("Published message hacked: {}", msgId);
 | 
			
		||||
            }
 | 
			
		||||
            else if (eventType == ix::CobraConnection_EventType_Pong)
 | 
			
		||||
            {
 | 
			
		||||
                spdlog::info("Received websocket pong");
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        while (true)
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,7 @@
 | 
			
		||||
 | 
			
		||||
#include <atomic>
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#include <condition_variable>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <ixcobra/IXCobraConnection.h>
 | 
			
		||||
#include <spdlog/spdlog.h>
 | 
			
		||||
#include <sstream>
 | 
			
		||||
@@ -17,59 +17,6 @@
 | 
			
		||||
#include <statsd_client.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
namespace
 | 
			
		||||
{
 | 
			
		||||
    class QueueManager
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        QueueManager(size_t maxQueueSize, std::atomic<bool>& stop)
 | 
			
		||||
            : _maxQueueSize(maxQueueSize)
 | 
			
		||||
            , _stop(stop)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Json::Value pop();
 | 
			
		||||
        void add(Json::Value msg);
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        std::queue<Json::Value> _queue;
 | 
			
		||||
        std::mutex _mutex;
 | 
			
		||||
        std::condition_variable _condition;
 | 
			
		||||
        size_t _maxQueueSize;
 | 
			
		||||
        std::atomic<bool>& _stop;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    Json::Value QueueManager::pop()
 | 
			
		||||
    {
 | 
			
		||||
        std::unique_lock<std::mutex> lock(_mutex);
 | 
			
		||||
 | 
			
		||||
        if (_queue.empty())
 | 
			
		||||
        {
 | 
			
		||||
            Json::Value val;
 | 
			
		||||
            return val;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        _condition.wait(lock, [this] { return !_stop; });
 | 
			
		||||
 | 
			
		||||
        auto msg = _queue.front();
 | 
			
		||||
        _queue.pop();
 | 
			
		||||
        return msg;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void QueueManager::add(Json::Value msg)
 | 
			
		||||
    {
 | 
			
		||||
        std::unique_lock<std::mutex> lock(_mutex);
 | 
			
		||||
 | 
			
		||||
        // if the sending is not fast enough there is no point
 | 
			
		||||
        // in queuing too many events.
 | 
			
		||||
        if (_queue.size() < _maxQueueSize)
 | 
			
		||||
        {
 | 
			
		||||
            _queue.push(msg);
 | 
			
		||||
            _condition.notify_one();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
} // namespace
 | 
			
		||||
 | 
			
		||||
namespace ix
 | 
			
		||||
{
 | 
			
		||||
    // fields are command line argument that can be specified multiple times
 | 
			
		||||
@@ -133,118 +80,87 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
        auto tokens = parseFields(fields);
 | 
			
		||||
 | 
			
		||||
        Json::FastWriter jsonWriter;
 | 
			
		||||
        std::atomic<uint64_t> sentCount(0);
 | 
			
		||||
        std::atomic<uint64_t> receivedCount(0);
 | 
			
		||||
        std::atomic<bool> stop(false);
 | 
			
		||||
 | 
			
		||||
        size_t maxQueueSize = 1000;
 | 
			
		||||
        QueueManager queueManager(maxQueueSize, stop);
 | 
			
		||||
 | 
			
		||||
        auto timer = [&sentCount, &receivedCount] {
 | 
			
		||||
            while (true)
 | 
			
		||||
            {
 | 
			
		||||
                spdlog::info("messages received {} sent {}", receivedCount, sentCount);
 | 
			
		||||
 | 
			
		||||
                auto duration = std::chrono::seconds(1);
 | 
			
		||||
                std::this_thread::sleep_for(duration);
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        std::thread t1(timer);
 | 
			
		||||
 | 
			
		||||
        auto statsdSender = [&queueManager, &host, &port, &sentCount, &tokens, &prefix, &stop] {
 | 
			
		||||
            // statsd client
 | 
			
		||||
            // test with netcat as a server: `nc -ul 8125`
 | 
			
		||||
            bool statsdBatch = true;
 | 
			
		||||
        // statsd client
 | 
			
		||||
        // test with netcat as a server: `nc -ul 8125`
 | 
			
		||||
        bool statsdBatch = true;
 | 
			
		||||
#ifndef _WIN32
 | 
			
		||||
            statsd::StatsdClient statsdClient(host, port, prefix, statsdBatch);
 | 
			
		||||
        statsd::StatsdClient statsdClient(host, port, prefix, statsdBatch);
 | 
			
		||||
#else
 | 
			
		||||
            int statsdClient;
 | 
			
		||||
        int statsdClient;
 | 
			
		||||
#endif
 | 
			
		||||
            while (true)
 | 
			
		||||
 | 
			
		||||
        Json::FastWriter jsonWriter;
 | 
			
		||||
        uint64_t msgCount = 0;
 | 
			
		||||
 | 
			
		||||
        conn.setEventCallback([&conn,
 | 
			
		||||
                               &channel,
 | 
			
		||||
                               &filter,
 | 
			
		||||
                               &jsonWriter,
 | 
			
		||||
                               &statsdClient,
 | 
			
		||||
                               verbose,
 | 
			
		||||
                               &tokens,
 | 
			
		||||
                               &prefix,
 | 
			
		||||
                               &msgCount](ix::CobraConnectionEventType eventType,
 | 
			
		||||
                                          const std::string& errMsg,
 | 
			
		||||
                                          const ix::WebSocketHttpHeaders& headers,
 | 
			
		||||
                                          const std::string& subscriptionId,
 | 
			
		||||
                                          CobraConnection::MsgId msgId) {
 | 
			
		||||
            if (eventType == ix::CobraConnection_EventType_Open)
 | 
			
		||||
            {
 | 
			
		||||
                Json::Value msg = queueManager.pop();
 | 
			
		||||
                spdlog::info("Subscriber connected");
 | 
			
		||||
 | 
			
		||||
                if (msg.isNull()) continue;
 | 
			
		||||
                if (stop) return;
 | 
			
		||||
 | 
			
		||||
                std::string id;
 | 
			
		||||
                for (auto&& attr : tokens)
 | 
			
		||||
                for (auto it : headers)
 | 
			
		||||
                {
 | 
			
		||||
                    id += ".";
 | 
			
		||||
                    id += extractAttr(attr, msg);
 | 
			
		||||
                    spdlog::info("{}: {}", it.first, it.second);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            if (eventType == ix::CobraConnection_EventType_Closed)
 | 
			
		||||
            {
 | 
			
		||||
                spdlog::info("Subscriber closed");
 | 
			
		||||
            }
 | 
			
		||||
            else if (eventType == ix::CobraConnection_EventType_Authenticated)
 | 
			
		||||
            {
 | 
			
		||||
                spdlog::info("Subscriber authenticated");
 | 
			
		||||
                conn.subscribe(channel,
 | 
			
		||||
                               filter,
 | 
			
		||||
                               [&jsonWriter, &statsdClient, verbose, &tokens, &prefix, &msgCount](
 | 
			
		||||
                                   const Json::Value& msg) {
 | 
			
		||||
                                   if (verbose)
 | 
			
		||||
                                   {
 | 
			
		||||
                                       spdlog::info(jsonWriter.write(msg));
 | 
			
		||||
                                   }
 | 
			
		||||
 | 
			
		||||
                sentCount += 1;
 | 
			
		||||
                                   std::string id;
 | 
			
		||||
                                   for (auto&& attr : tokens)
 | 
			
		||||
                                   {
 | 
			
		||||
                                       id += ".";
 | 
			
		||||
                                       id += extractAttr(attr, msg);
 | 
			
		||||
                                   }
 | 
			
		||||
 | 
			
		||||
                                   spdlog::info("{} {}{}", msgCount++, prefix, id);
 | 
			
		||||
 | 
			
		||||
#ifndef _WIN32
 | 
			
		||||
                statsdClient.count(id, 1);
 | 
			
		||||
                                   statsdClient.count(id, 1);
 | 
			
		||||
#endif
 | 
			
		||||
                               });
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        std::thread t2(statsdSender);
 | 
			
		||||
 | 
			
		||||
        conn.setEventCallback(
 | 
			
		||||
            [&conn, &channel, &filter, &jsonWriter, verbose, &queueManager, &receivedCount](
 | 
			
		||||
                ix::CobraConnectionEventType eventType,
 | 
			
		||||
                const std::string& errMsg,
 | 
			
		||||
                const ix::WebSocketHttpHeaders& headers,
 | 
			
		||||
                const std::string& subscriptionId,
 | 
			
		||||
                CobraConnection::MsgId msgId) {
 | 
			
		||||
                if (eventType == ix::CobraConnection_EventType_Open)
 | 
			
		||||
                {
 | 
			
		||||
                    spdlog::info("Subscriber connected");
 | 
			
		||||
 | 
			
		||||
                    for (auto it : headers)
 | 
			
		||||
                    {
 | 
			
		||||
                        spdlog::info("{}: {}", it.first, it.second);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                if (eventType == ix::CobraConnection_EventType_Closed)
 | 
			
		||||
                {
 | 
			
		||||
                    spdlog::info("Subscriber closed");
 | 
			
		||||
                }
 | 
			
		||||
                else if (eventType == ix::CobraConnection_EventType_Authenticated)
 | 
			
		||||
                {
 | 
			
		||||
                    spdlog::info("Subscriber authenticated");
 | 
			
		||||
                    conn.subscribe(channel,
 | 
			
		||||
                                   filter,
 | 
			
		||||
                                   [&jsonWriter, &queueManager, verbose, &receivedCount](
 | 
			
		||||
                                       const Json::Value& msg) {
 | 
			
		||||
                                       if (verbose)
 | 
			
		||||
                                       {
 | 
			
		||||
                                           spdlog::info(jsonWriter.write(msg));
 | 
			
		||||
                                       }
 | 
			
		||||
 | 
			
		||||
                                       receivedCount++;
 | 
			
		||||
 | 
			
		||||
                                       ++receivedCount;
 | 
			
		||||
                                       queueManager.add(msg);
 | 
			
		||||
                                   });
 | 
			
		||||
                }
 | 
			
		||||
                else if (eventType == ix::CobraConnection_EventType_Subscribed)
 | 
			
		||||
                {
 | 
			
		||||
                    spdlog::info("Subscriber: subscribed to channel {}", subscriptionId);
 | 
			
		||||
                }
 | 
			
		||||
                else if (eventType == ix::CobraConnection_EventType_UnSubscribed)
 | 
			
		||||
                {
 | 
			
		||||
                    spdlog::info("Subscriber: unsubscribed from channel {}", subscriptionId);
 | 
			
		||||
                }
 | 
			
		||||
                else if (eventType == ix::CobraConnection_EventType_Error)
 | 
			
		||||
                {
 | 
			
		||||
                    spdlog::error("Subscriber: error {}", errMsg);
 | 
			
		||||
                }
 | 
			
		||||
                else if (eventType == ix::CobraConnection_EventType_Published)
 | 
			
		||||
                {
 | 
			
		||||
                    spdlog::error("Published message hacked: {}", msgId);
 | 
			
		||||
                }
 | 
			
		||||
                else if (eventType == ix::CobraConnection_EventType_Pong)
 | 
			
		||||
                {
 | 
			
		||||
                    spdlog::info("Received websocket pong");
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
            else if (eventType == ix::CobraConnection_EventType_Subscribed)
 | 
			
		||||
            {
 | 
			
		||||
                spdlog::info("Subscriber: subscribed to channel {}", subscriptionId);
 | 
			
		||||
            }
 | 
			
		||||
            else if (eventType == ix::CobraConnection_EventType_UnSubscribed)
 | 
			
		||||
            {
 | 
			
		||||
                spdlog::info("Subscriber: unsubscribed from channel {}", subscriptionId);
 | 
			
		||||
            }
 | 
			
		||||
            else if (eventType == ix::CobraConnection_EventType_Error)
 | 
			
		||||
            {
 | 
			
		||||
                spdlog::error("Subscriber: error {}", errMsg);
 | 
			
		||||
            }
 | 
			
		||||
            else if (eventType == ix::CobraConnection_EventType_Published)
 | 
			
		||||
            {
 | 
			
		||||
                spdlog::error("Published message hacked: {}", msgId);
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        while (true)
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -5,10 +5,10 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "linenoise.hpp"
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <ixwebsocket/IXSocket.h>
 | 
			
		||||
#include <ixwebsocket/IXSocketTLSOptions.h>
 | 
			
		||||
#include <ixwebsocket/IXWebSocket.h>
 | 
			
		||||
#include <spdlog/spdlog.h>
 | 
			
		||||
#include <sstream>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -93,7 +93,7 @@ namespace ix
 | 
			
		||||
            auto key = token.substr(0, pos);
 | 
			
		||||
            auto val = token.substr(pos + 1);
 | 
			
		||||
 | 
			
		||||
            spdlog::info("{}: {}", key, val);
 | 
			
		||||
            std::cerr << key << ": " << val << std::endl;
 | 
			
		||||
            headers[key] = val;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -129,11 +129,11 @@ namespace ix
 | 
			
		||||
            if (msg->type == ix::WebSocketMessageType::Open)
 | 
			
		||||
            {
 | 
			
		||||
                log("ws_connect: connected");
 | 
			
		||||
                spdlog::info("Uri: {}", msg->openInfo.uri);
 | 
			
		||||
                spdlog::info("Headers:");
 | 
			
		||||
                std::cout << "Uri: " << msg->openInfo.uri << std::endl;
 | 
			
		||||
                std::cout << "Handshake Headers:" << std::endl;
 | 
			
		||||
                for (auto it : msg->openInfo.headers)
 | 
			
		||||
                {
 | 
			
		||||
                    spdlog::info("{}: {}", it.first, it.second);
 | 
			
		||||
                    std::cout << it.first << ": " << it.second << std::endl;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else if (msg->type == ix::WebSocketMessageType::Close)
 | 
			
		||||
@@ -145,7 +145,7 @@ namespace ix
 | 
			
		||||
            }
 | 
			
		||||
            else if (msg->type == ix::WebSocketMessageType::Message)
 | 
			
		||||
            {
 | 
			
		||||
                spdlog::info("Received {} bytes", msg->wireSize);
 | 
			
		||||
                std::cerr << "Received " << msg->wireSize << " bytes" << std::endl;
 | 
			
		||||
 | 
			
		||||
                ss << "ws_connect: received message: " << msg->str;
 | 
			
		||||
                log(ss.str());
 | 
			
		||||
@@ -160,15 +160,15 @@ namespace ix
 | 
			
		||||
            }
 | 
			
		||||
            else if (msg->type == ix::WebSocketMessageType::Fragment)
 | 
			
		||||
            {
 | 
			
		||||
                spdlog::info("Received message fragment");
 | 
			
		||||
                std::cerr << "Received message fragment" << std::endl;
 | 
			
		||||
            }
 | 
			
		||||
            else if (msg->type == ix::WebSocketMessageType::Ping)
 | 
			
		||||
            {
 | 
			
		||||
                spdlog::info("Received ping");
 | 
			
		||||
                std::cerr << "Received ping" << std::endl;
 | 
			
		||||
            }
 | 
			
		||||
            else if (msg->type == ix::WebSocketMessageType::Pong)
 | 
			
		||||
            {
 | 
			
		||||
                spdlog::info("Received pong");
 | 
			
		||||
                std::cerr << "Received pong" << std::endl;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
@@ -225,14 +225,14 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
            if (line == "/stop")
 | 
			
		||||
            {
 | 
			
		||||
                spdlog::info("Stopping connection...");
 | 
			
		||||
                std::cout << "Stopping connection..." << std::endl;
 | 
			
		||||
                webSocketChat.stop();
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (line == "/start")
 | 
			
		||||
            {
 | 
			
		||||
                spdlog::info("Starting connection...");
 | 
			
		||||
                std::cout << "Starting connection..." << std::endl;
 | 
			
		||||
                webSocketChat.start();
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
@@ -243,7 +243,7 @@ namespace ix
 | 
			
		||||
            linenoise::AddHistory(line.c_str());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        spdlog::info("");
 | 
			
		||||
        std::cout << std::endl;
 | 
			
		||||
        webSocketChat.stop();
 | 
			
		||||
 | 
			
		||||
        return 0;
 | 
			
		||||
 
 | 
			
		||||
@@ -4,8 +4,8 @@
 | 
			
		||||
 *  Copyright (c) 2018 Machine Zone, Inc. All rights reserved.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <ixwebsocket/IXWebSocketServer.h>
 | 
			
		||||
#include <spdlog/spdlog.h>
 | 
			
		||||
#include <sstream>
 | 
			
		||||
 | 
			
		||||
namespace ix
 | 
			
		||||
@@ -15,7 +15,7 @@ namespace ix
 | 
			
		||||
                            const std::string& hostname,
 | 
			
		||||
                            const ix::SocketTLSOptions& tlsOptions)
 | 
			
		||||
    {
 | 
			
		||||
        spdlog::info("Listening on {}:{}", hostname, port);
 | 
			
		||||
        std::cout << "Listening on " << hostname << ":" << port << std::endl;
 | 
			
		||||
 | 
			
		||||
        ix::WebSocketServer server(port, hostname);
 | 
			
		||||
        server.setTLSOptions(tlsOptions);
 | 
			
		||||
@@ -27,13 +27,13 @@ namespace ix
 | 
			
		||||
                    [webSocket, connectionState, greetings](const WebSocketMessagePtr& msg) {
 | 
			
		||||
                        if (msg->type == ix::WebSocketMessageType::Open)
 | 
			
		||||
                        {
 | 
			
		||||
                            spdlog::info("New connection");
 | 
			
		||||
                            spdlog::info("id: {}", connectionState->getId());
 | 
			
		||||
                            spdlog::info("Uri: {}", msg->openInfo.uri);
 | 
			
		||||
                            spdlog::info("Headers:");
 | 
			
		||||
                            std::cerr << "New connection" << std::endl;
 | 
			
		||||
                            std::cerr << "id: " << connectionState->getId() << std::endl;
 | 
			
		||||
                            std::cerr << "Uri: " << msg->openInfo.uri << std::endl;
 | 
			
		||||
                            std::cerr << "Headers:" << std::endl;
 | 
			
		||||
                            for (auto it : msg->openInfo.headers)
 | 
			
		||||
                            {
 | 
			
		||||
                                spdlog::info("{}: {}", it.first, it.second);
 | 
			
		||||
                                std::cerr << it.first << ": " << it.second << std::endl;
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
                            if (greetings)
 | 
			
		||||
@@ -43,21 +43,22 @@ namespace ix
 | 
			
		||||
                        }
 | 
			
		||||
                        else if (msg->type == ix::WebSocketMessageType::Close)
 | 
			
		||||
                        {
 | 
			
		||||
                            spdlog::info("Closed connection: client id {} code {} reason {}",
 | 
			
		||||
                                         connectionState->getId(),
 | 
			
		||||
                                         msg->closeInfo.code,
 | 
			
		||||
                                         msg->closeInfo.reason);
 | 
			
		||||
                            std::cerr << "Closed connection"
 | 
			
		||||
                                      << " code " << msg->closeInfo.code << " reason "
 | 
			
		||||
                                      << msg->closeInfo.reason << std::endl;
 | 
			
		||||
                        }
 | 
			
		||||
                        else if (msg->type == ix::WebSocketMessageType::Error)
 | 
			
		||||
                        {
 | 
			
		||||
                            spdlog::error("Connection error: {}", msg->errorInfo.reason);
 | 
			
		||||
                            spdlog::error("#retries: {}", msg->errorInfo.retries);
 | 
			
		||||
                            spdlog::error("Wait time(ms): {}", msg->errorInfo.wait_time);
 | 
			
		||||
                            spdlog::error("HTTP Status: {}", msg->errorInfo.http_status);
 | 
			
		||||
                            std::stringstream ss;
 | 
			
		||||
                            ss << "Connection error: " << msg->errorInfo.reason << std::endl;
 | 
			
		||||
                            ss << "#retries: " << msg->errorInfo.retries << std::endl;
 | 
			
		||||
                            ss << "Wait time(ms): " << msg->errorInfo.wait_time << std::endl;
 | 
			
		||||
                            ss << "HTTP Status: " << msg->errorInfo.http_status << std::endl;
 | 
			
		||||
                            std::cerr << ss.str();
 | 
			
		||||
                        }
 | 
			
		||||
                        else if (msg->type == ix::WebSocketMessageType::Message)
 | 
			
		||||
                        {
 | 
			
		||||
                            spdlog::info("Received {} bytes", msg->wireSize);
 | 
			
		||||
                            std::cerr << "Received " << msg->wireSize << " bytes" << std::endl;
 | 
			
		||||
                            webSocket->send(msg->str, msg->binary);
 | 
			
		||||
                        }
 | 
			
		||||
                    });
 | 
			
		||||
@@ -66,7 +67,7 @@ namespace ix
 | 
			
		||||
        auto res = server.listen();
 | 
			
		||||
        if (!res.first)
 | 
			
		||||
        {
 | 
			
		||||
            spdlog::error(res.second);
 | 
			
		||||
            std::cerr << res.second << std::endl;
 | 
			
		||||
            return 1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -5,10 +5,10 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <fstream>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <ixwebsocket/IXHttpClient.h>
 | 
			
		||||
#include <ixwebsocket/IXSocketTLSOptions.h>
 | 
			
		||||
#include <ixwebsocket/IXWebSocketHttpHeaders.h>
 | 
			
		||||
#include <spdlog/spdlog.h>
 | 
			
		||||
#include <sstream>
 | 
			
		||||
 | 
			
		||||
namespace ix
 | 
			
		||||
@@ -47,7 +47,7 @@ namespace ix
 | 
			
		||||
            auto key = token.substr(0, pos);
 | 
			
		||||
            auto val = token.substr(pos + 1);
 | 
			
		||||
 | 
			
		||||
            spdlog::info("{}: {}", key, val);
 | 
			
		||||
            std::cerr << key << ": " << val << std::endl;
 | 
			
		||||
            headers[key] = val;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -76,7 +76,7 @@ namespace ix
 | 
			
		||||
            auto key = token.substr(0, pos);
 | 
			
		||||
            auto val = token.substr(pos + 1);
 | 
			
		||||
 | 
			
		||||
            spdlog::info("{}: {}", key, val);
 | 
			
		||||
            std::cerr << key << ": " << val << std::endl;
 | 
			
		||||
            httpParameters[key] = val;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -108,9 +108,10 @@ namespace ix
 | 
			
		||||
        args->maxRedirects = maxRedirects;
 | 
			
		||||
        args->verbose = verbose;
 | 
			
		||||
        args->compress = compress;
 | 
			
		||||
        args->logger = [](const std::string& msg) { spdlog::info(msg); };
 | 
			
		||||
        args->logger = [](const std::string& msg) { std::cout << msg; };
 | 
			
		||||
        args->onProgressCallback = [](int current, int total) -> bool {
 | 
			
		||||
            spdlog::info("Downloaded {} bytes out of {}", current, total);
 | 
			
		||||
            std::cerr << "\r"
 | 
			
		||||
                      << "Downloaded " << current << " bytes out of " << total;
 | 
			
		||||
            return true;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
@@ -130,20 +131,20 @@ namespace ix
 | 
			
		||||
            response = httpClient.post(url, httpParameters, args);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        spdlog::info("");
 | 
			
		||||
        std::cerr << std::endl;
 | 
			
		||||
 | 
			
		||||
        for (auto it : response->headers)
 | 
			
		||||
        {
 | 
			
		||||
            spdlog::info("{}: {}", it.first, it.second);
 | 
			
		||||
            std::cerr << it.first << ": " << it.second << std::endl;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        spdlog::info("Upload size: {}", response->uploadSize);
 | 
			
		||||
        spdlog::info("Download size: {}", response->downloadSize);
 | 
			
		||||
        std::cerr << "Upload size: " << response->uploadSize << std::endl;
 | 
			
		||||
        std::cerr << "Download size: " << response->downloadSize << std::endl;
 | 
			
		||||
 | 
			
		||||
        spdlog::info("Status: {}", response->statusCode);
 | 
			
		||||
        std::cerr << "Status: " << response->statusCode << std::endl;
 | 
			
		||||
        if (response->errorCode != HttpErrorCode::Ok)
 | 
			
		||||
        {
 | 
			
		||||
            spdlog::info("error message: ", response->errorMsg);
 | 
			
		||||
            std::cerr << "error message: " << response->errorMsg << std::endl;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!headersOnly && response->errorCode == HttpErrorCode::Ok)
 | 
			
		||||
@@ -157,7 +158,7 @@ namespace ix
 | 
			
		||||
                    filename = output;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                spdlog::info("Writing to disk: {}", filename);
 | 
			
		||||
                std::cout << "Writing to disk: " << filename << std::endl;
 | 
			
		||||
                std::ofstream out(filename);
 | 
			
		||||
                out.write((char*) &response->payload.front(), response->payload.size());
 | 
			
		||||
                out.close();
 | 
			
		||||
@@ -166,13 +167,14 @@ namespace ix
 | 
			
		||||
            {
 | 
			
		||||
                if (response->headers["Content-Type"] != "application/octet-stream")
 | 
			
		||||
                {
 | 
			
		||||
                    spdlog::info("payload: {}", response->payload);
 | 
			
		||||
                    std::cout << "payload: " << response->payload << std::endl;
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    spdlog::info("Binary output can mess up your terminal.");
 | 
			
		||||
                    spdlog::info("Use the -O flag to save the file to disk.");
 | 
			
		||||
                    spdlog::info("You can also use the --output option to specify a filename.");
 | 
			
		||||
                    std::cerr << "Binary output can mess up your terminal." << std::endl;
 | 
			
		||||
                    std::cerr << "Use the -O flag to save the file to disk." << std::endl;
 | 
			
		||||
                    std::cerr << "You can also use the --output option to specify a filename."
 | 
			
		||||
                              << std::endl;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,7 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <fstream>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <ixwebsocket/IXHttpServer.h>
 | 
			
		||||
#include <spdlog/spdlog.h>
 | 
			
		||||
#include <sstream>
 | 
			
		||||
@@ -31,7 +32,7 @@ namespace ix
 | 
			
		||||
        auto res = server.listen();
 | 
			
		||||
        if (!res.first)
 | 
			
		||||
        {
 | 
			
		||||
            spdlog::error(res.second);
 | 
			
		||||
            std::cerr << res.second << std::endl;
 | 
			
		||||
            return 1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,6 @@
 | 
			
		||||
#include <ixwebsocket/IXSocket.h>
 | 
			
		||||
#include <ixwebsocket/IXSocketTLSOptions.h>
 | 
			
		||||
#include <ixwebsocket/IXWebSocket.h>
 | 
			
		||||
#include <spdlog/spdlog.h>
 | 
			
		||||
#include <sstream>
 | 
			
		||||
 | 
			
		||||
namespace ix
 | 
			
		||||
@@ -41,7 +40,7 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
    void WebSocketPingPong::log(const std::string& msg)
 | 
			
		||||
    {
 | 
			
		||||
        spdlog::info(msg);
 | 
			
		||||
        std::cout << msg << std::endl;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void WebSocketPingPong::stop()
 | 
			
		||||
@@ -57,18 +56,18 @@ namespace ix
 | 
			
		||||
        log(std::string("Connecting to url: ") + _url);
 | 
			
		||||
 | 
			
		||||
        _webSocket.setOnMessageCallback([this](const ix::WebSocketMessagePtr& msg) {
 | 
			
		||||
            spdlog::info("Received {} bytes", msg->wireSize);
 | 
			
		||||
            std::cerr << "Received " << msg->wireSize << " bytes" << std::endl;
 | 
			
		||||
 | 
			
		||||
            std::stringstream ss;
 | 
			
		||||
            if (msg->type == ix::WebSocketMessageType::Open)
 | 
			
		||||
            {
 | 
			
		||||
                log("ping_pong: connected");
 | 
			
		||||
 | 
			
		||||
                spdlog::info("Uri: {}", msg->openInfo.uri);
 | 
			
		||||
                spdlog::info("Headers:");
 | 
			
		||||
                std::cout << "Uri: " << msg->openInfo.uri << std::endl;
 | 
			
		||||
                std::cout << "Handshake Headers:" << std::endl;
 | 
			
		||||
                for (auto it : msg->openInfo.headers)
 | 
			
		||||
                {
 | 
			
		||||
                    spdlog::info("{}: {}", it.first, it.second);
 | 
			
		||||
                    std::cout << it.first << ": " << it.second << std::endl;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else if (msg->type == ix::WebSocketMessageType::Close)
 | 
			
		||||
@@ -128,7 +127,7 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
    int ws_ping_pong_main(const std::string& url, const ix::SocketTLSOptions& tlsOptions)
 | 
			
		||||
    {
 | 
			
		||||
        spdlog::info("Type Ctrl-D to exit prompt...");
 | 
			
		||||
        std::cout << "Type Ctrl-D to exit prompt..." << std::endl;
 | 
			
		||||
        WebSocketPingPong webSocketPingPong(url, tlsOptions);
 | 
			
		||||
        webSocketPingPong.start();
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -4,8 +4,8 @@
 | 
			
		||||
 *  Copyright (c) 2018 Machine Zone, Inc. All rights reserved.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <ixwebsocket/IXWebSocketServer.h>
 | 
			
		||||
#include <spdlog/spdlog.h>
 | 
			
		||||
#include <sstream>
 | 
			
		||||
 | 
			
		||||
namespace ix
 | 
			
		||||
@@ -44,7 +44,7 @@ namespace ix
 | 
			
		||||
                             const std::string& remoteUrl,
 | 
			
		||||
                             bool verbose)
 | 
			
		||||
    {
 | 
			
		||||
        spdlog::info("Listening on {}:{}", hostname, port);
 | 
			
		||||
        std::cout << "Listening on " << hostname << ":" << port << std::endl;
 | 
			
		||||
 | 
			
		||||
        ix::WebSocketServer server(port, hostname);
 | 
			
		||||
        server.setTLSOptions(tlsOptions);
 | 
			
		||||
@@ -61,39 +61,41 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
            // Server connection
 | 
			
		||||
            state->webSocket().setOnMessageCallback([webSocket, state, verbose](
 | 
			
		||||
                                                        const WebSocketMessagePtr& msg) {
 | 
			
		||||
                                                     const WebSocketMessagePtr& msg) {
 | 
			
		||||
                if (msg->type == ix::WebSocketMessageType::Open)
 | 
			
		||||
                {
 | 
			
		||||
                    spdlog::info("New connection to remote server");
 | 
			
		||||
                    spdlog::info("id: {}", state->getId());
 | 
			
		||||
                    spdlog::info("Uri: {}", msg->openInfo.uri);
 | 
			
		||||
                    spdlog::info("Headers:");
 | 
			
		||||
                    std::cerr << "New connection" << std::endl;
 | 
			
		||||
                    std::cerr << "server id: " << state->getId() << std::endl;
 | 
			
		||||
                    std::cerr << "Uri: " << msg->openInfo.uri << std::endl;
 | 
			
		||||
                    std::cerr << "Headers:" << std::endl;
 | 
			
		||||
                    for (auto it : msg->openInfo.headers)
 | 
			
		||||
                    {
 | 
			
		||||
                        spdlog::info("{}: {}", it.first, it.second);
 | 
			
		||||
                        std::cerr << it.first << ": " << it.second << std::endl;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else if (msg->type == ix::WebSocketMessageType::Close)
 | 
			
		||||
                {
 | 
			
		||||
                    spdlog::info("Closed remote server connection: client id {} code {} reason {}",
 | 
			
		||||
                                 state->getId(),
 | 
			
		||||
                                 msg->closeInfo.code,
 | 
			
		||||
                                 msg->closeInfo.reason);
 | 
			
		||||
                    std::cerr << "Closed connection"
 | 
			
		||||
                              << " code " << msg->closeInfo.code << " reason "
 | 
			
		||||
                              << msg->closeInfo.reason << std::endl;
 | 
			
		||||
                    webSocket->close(msg->closeInfo.code, msg->closeInfo.reason);
 | 
			
		||||
                    state->setTerminated();
 | 
			
		||||
                }
 | 
			
		||||
                else if (msg->type == ix::WebSocketMessageType::Error)
 | 
			
		||||
                {
 | 
			
		||||
                    spdlog::error("Connection error: {}", msg->errorInfo.reason);
 | 
			
		||||
                    spdlog::error("#retries: {}", msg->errorInfo.retries);
 | 
			
		||||
                    spdlog::error("Wait time(ms): {}", msg->errorInfo.wait_time);
 | 
			
		||||
                    spdlog::error("HTTP Status: {}", msg->errorInfo.http_status);
 | 
			
		||||
                    std::stringstream ss;
 | 
			
		||||
                    ss << "Connection error: " << msg->errorInfo.reason << std::endl;
 | 
			
		||||
                    ss << "#retries: " << msg->errorInfo.retries << std::endl;
 | 
			
		||||
                    ss << "Wait time(ms): " << msg->errorInfo.wait_time << std::endl;
 | 
			
		||||
                    ss << "HTTP Status: " << msg->errorInfo.http_status << std::endl;
 | 
			
		||||
                    std::cerr << ss.str();
 | 
			
		||||
                }
 | 
			
		||||
                else if (msg->type == ix::WebSocketMessageType::Message)
 | 
			
		||||
                {
 | 
			
		||||
                    spdlog::info("Received {} bytes from server", msg->wireSize);
 | 
			
		||||
                    std::cerr << "Received " << msg->wireSize << " bytes from server" << std::endl;
 | 
			
		||||
                    if (verbose)
 | 
			
		||||
                    {
 | 
			
		||||
                        spdlog::info("payload {}", msg->str);
 | 
			
		||||
                        std::cerr << "payload " << msg->str << std::endl;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    webSocket->send(msg->str, msg->binary);
 | 
			
		||||
@@ -101,67 +103,67 @@ namespace ix
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            // Client connection
 | 
			
		||||
            webSocket->setOnMessageCallback(
 | 
			
		||||
                [state, remoteUrl, verbose](const WebSocketMessagePtr& msg) {
 | 
			
		||||
                    if (msg->type == ix::WebSocketMessageType::Open)
 | 
			
		||||
            webSocket->setOnMessageCallback([state, remoteUrl, verbose](
 | 
			
		||||
                                                const WebSocketMessagePtr& msg) {
 | 
			
		||||
                if (msg->type == ix::WebSocketMessageType::Open)
 | 
			
		||||
                {
 | 
			
		||||
                    std::cerr << "New connection" << std::endl;
 | 
			
		||||
                    std::cerr << "client id: " << state->getId() << std::endl;
 | 
			
		||||
                    std::cerr << "Uri: " << msg->openInfo.uri << std::endl;
 | 
			
		||||
                    std::cerr << "Headers:" << std::endl;
 | 
			
		||||
                    for (auto it : msg->openInfo.headers)
 | 
			
		||||
                    {
 | 
			
		||||
                        spdlog::info("New connection from client");
 | 
			
		||||
                        spdlog::info("id: {}", state->getId());
 | 
			
		||||
                        spdlog::info("Uri: {}", msg->openInfo.uri);
 | 
			
		||||
                        spdlog::info("Headers:");
 | 
			
		||||
                        for (auto it : msg->openInfo.headers)
 | 
			
		||||
                        {
 | 
			
		||||
                            spdlog::info("{}: {}", it.first, it.second);
 | 
			
		||||
                        }
 | 
			
		||||
                        std::cerr << it.first << ": " << it.second << std::endl;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                        // Connect to the 'real' server
 | 
			
		||||
                        std::string url(remoteUrl);
 | 
			
		||||
                        url += msg->openInfo.uri;
 | 
			
		||||
                        state->webSocket().setUrl(url);
 | 
			
		||||
                        state->webSocket().disableAutomaticReconnection();
 | 
			
		||||
                        state->webSocket().start();
 | 
			
		||||
                    // Connect to the 'real' server
 | 
			
		||||
                    std::string url(remoteUrl);
 | 
			
		||||
                    url += msg->openInfo.uri;
 | 
			
		||||
                    state->webSocket().setUrl(url);
 | 
			
		||||
                    state->webSocket().disableAutomaticReconnection();
 | 
			
		||||
                    state->webSocket().start();
 | 
			
		||||
 | 
			
		||||
                        // we should sleep here for a bit until we've established the
 | 
			
		||||
                        // connection with the remote server
 | 
			
		||||
                        while (state->webSocket().getReadyState() != ReadyState::Open)
 | 
			
		||||
                        {
 | 
			
		||||
                            spdlog::info("waiting for server connection establishment");
 | 
			
		||||
                            std::this_thread::sleep_for(std::chrono::milliseconds(10));
 | 
			
		||||
                        }
 | 
			
		||||
                        spdlog::info("server connection established");
 | 
			
		||||
                    }
 | 
			
		||||
                    else if (msg->type == ix::WebSocketMessageType::Close)
 | 
			
		||||
                    // we should sleep here for a bit until we've established the
 | 
			
		||||
                    // connection with the remote server
 | 
			
		||||
                    while (state->webSocket().getReadyState() != ReadyState::Open)
 | 
			
		||||
                    {
 | 
			
		||||
                        spdlog::info("Closed client connection: client id {} code {} reason {}",
 | 
			
		||||
                                     state->getId(),
 | 
			
		||||
                                     msg->closeInfo.code,
 | 
			
		||||
                                     msg->closeInfo.reason);
 | 
			
		||||
                        state->webSocket().close(msg->closeInfo.code, msg->closeInfo.reason);
 | 
			
		||||
                        std::cerr << "waiting for server connection establishment" << std::endl;
 | 
			
		||||
                        std::this_thread::sleep_for(std::chrono::milliseconds(10));
 | 
			
		||||
                    }
 | 
			
		||||
                    else if (msg->type == ix::WebSocketMessageType::Error)
 | 
			
		||||
                    std::cerr << "server connection established" << std::endl;
 | 
			
		||||
                }
 | 
			
		||||
                else if (msg->type == ix::WebSocketMessageType::Close)
 | 
			
		||||
                {
 | 
			
		||||
                    std::cerr << "Closed connection"
 | 
			
		||||
                              << " code " << msg->closeInfo.code << " reason "
 | 
			
		||||
                              << msg->closeInfo.reason << std::endl;
 | 
			
		||||
                    state->webSocket().close(msg->closeInfo.code, msg->closeInfo.reason);
 | 
			
		||||
                }
 | 
			
		||||
                else if (msg->type == ix::WebSocketMessageType::Error)
 | 
			
		||||
                {
 | 
			
		||||
                    std::stringstream ss;
 | 
			
		||||
                    ss << "Connection error: " << msg->errorInfo.reason << std::endl;
 | 
			
		||||
                    ss << "#retries: " << msg->errorInfo.retries << std::endl;
 | 
			
		||||
                    ss << "Wait time(ms): " << msg->errorInfo.wait_time << std::endl;
 | 
			
		||||
                    ss << "HTTP Status: " << msg->errorInfo.http_status << std::endl;
 | 
			
		||||
                    std::cerr << ss.str();
 | 
			
		||||
                }
 | 
			
		||||
                else if (msg->type == ix::WebSocketMessageType::Message)
 | 
			
		||||
                {
 | 
			
		||||
                    std::cerr << "Received " << msg->wireSize << " bytes from client" << std::endl;
 | 
			
		||||
                    if (verbose)
 | 
			
		||||
                    {
 | 
			
		||||
                        spdlog::error("Connection error: {}", msg->errorInfo.reason);
 | 
			
		||||
                        spdlog::error("#retries: {}", msg->errorInfo.retries);
 | 
			
		||||
                        spdlog::error("Wait time(ms): {}", msg->errorInfo.wait_time);
 | 
			
		||||
                        spdlog::error("HTTP Status: {}", msg->errorInfo.http_status);
 | 
			
		||||
                        std::cerr << "payload " << msg->str << std::endl;
 | 
			
		||||
                    }
 | 
			
		||||
                    else if (msg->type == ix::WebSocketMessageType::Message)
 | 
			
		||||
                    {
 | 
			
		||||
                        spdlog::info("Received {} bytes from client", msg->wireSize);
 | 
			
		||||
                        if (verbose)
 | 
			
		||||
                        {
 | 
			
		||||
                            spdlog::info("payload {}", msg->str);
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        state->webSocket().send(msg->str, msg->binary);
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
                    state->webSocket().send(msg->str, msg->binary);
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        auto res = server.listen();
 | 
			
		||||
        if (!res.first)
 | 
			
		||||
        {
 | 
			
		||||
            spdlog::info(res.second);
 | 
			
		||||
            std::cerr << res.second << std::endl;
 | 
			
		||||
            return 1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,7 @@
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#include <condition_variable>
 | 
			
		||||
#include <fstream>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <ixcrypto/IXBase64.h>
 | 
			
		||||
#include <ixcrypto/IXHash.h>
 | 
			
		||||
#include <ixcrypto/IXUuid.h>
 | 
			
		||||
@@ -15,7 +16,6 @@
 | 
			
		||||
#include <ixwebsocket/IXWebSocket.h>
 | 
			
		||||
#include <msgpack11/msgpack11.hpp>
 | 
			
		||||
#include <mutex>
 | 
			
		||||
#include <spdlog/spdlog.h>
 | 
			
		||||
#include <sstream>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
@@ -75,12 +75,12 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
    void WebSocketReceiver::log(const std::string& msg)
 | 
			
		||||
    {
 | 
			
		||||
        spdlog::info(msg);
 | 
			
		||||
        std::cout << msg << std::endl;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void WebSocketReceiver::waitForConnection()
 | 
			
		||||
    {
 | 
			
		||||
        spdlog::info("{}: Connecting...", "ws_receive");
 | 
			
		||||
        std::cout << "ws_receive: Connecting..." << std::endl;
 | 
			
		||||
 | 
			
		||||
        std::unique_lock<std::mutex> lock(_conditionVariableMutex);
 | 
			
		||||
        _condition.wait(lock);
 | 
			
		||||
@@ -88,7 +88,7 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
    void WebSocketReceiver::waitForMessage()
 | 
			
		||||
    {
 | 
			
		||||
        spdlog::info("{}: Waiting for message...", "ws_receive");
 | 
			
		||||
        std::cout << "ws_receive: Waiting for message..." << std::endl;
 | 
			
		||||
 | 
			
		||||
        std::unique_lock<std::mutex> lock(_conditionVariableMutex);
 | 
			
		||||
        _condition.wait(lock);
 | 
			
		||||
@@ -124,7 +124,7 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
    void WebSocketReceiver::handleMessage(const std::string& str)
 | 
			
		||||
    {
 | 
			
		||||
        spdlog::info("ws_receive: Received message: {}", str.size());
 | 
			
		||||
        std::cerr << "ws_receive: Received message: " << str.size() << std::endl;
 | 
			
		||||
 | 
			
		||||
        std::string errMsg;
 | 
			
		||||
        MsgPack data = MsgPack::parse(str, errMsg);
 | 
			
		||||
@@ -134,17 +134,17 @@ namespace ix
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        spdlog::info("id: {}", data["id"].string_value());
 | 
			
		||||
        std::cout << "id: " << data["id"].string_value() << std::endl;
 | 
			
		||||
 | 
			
		||||
        std::vector<uint8_t> content = data["content"].binary_items();
 | 
			
		||||
        spdlog::info("ws_receive: Content size: {}", content.size());
 | 
			
		||||
        std::cout << "ws_receive: Content size: " << content.size() << std::endl;
 | 
			
		||||
 | 
			
		||||
        // Validate checksum
 | 
			
		||||
        uint64_t cksum = ix::djb2Hash(content);
 | 
			
		||||
        auto cksumRef = data["djb2_hash"].string_value();
 | 
			
		||||
 | 
			
		||||
        spdlog::info("ws_receive: Computed hash: {}", cksum);
 | 
			
		||||
        spdlog::info("ws_receive: Reference hash: {}", cksumRef);
 | 
			
		||||
        std::cout << "ws_receive: Computed hash: " << cksum << std::endl;
 | 
			
		||||
        std::cout << "ws_receive: Reference hash: " << cksumRef << std::endl;
 | 
			
		||||
 | 
			
		||||
        if (std::to_string(cksum) != cksumRef)
 | 
			
		||||
        {
 | 
			
		||||
@@ -157,12 +157,12 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
        std::string filenameTmp = filename + ".tmp";
 | 
			
		||||
 | 
			
		||||
        spdlog::info("ws_receive: Writing to disk: {}", filenameTmp);
 | 
			
		||||
        std::cout << "ws_receive: Writing to disk: " << filenameTmp << std::endl;
 | 
			
		||||
        std::ofstream out(filenameTmp);
 | 
			
		||||
        out.write((char*) &content.front(), content.size());
 | 
			
		||||
        out.close();
 | 
			
		||||
 | 
			
		||||
        spdlog::info("ws_receive: Renaming {} to {}", filenameTmp, filename);
 | 
			
		||||
        std::cout << "ws_receive: Renaming " << filenameTmp << " to " << filename << std::endl;
 | 
			
		||||
        rename(filenameTmp.c_str(), filename.c_str());
 | 
			
		||||
 | 
			
		||||
        std::map<MsgPack, MsgPack> pdu;
 | 
			
		||||
@@ -170,7 +170,7 @@ namespace ix
 | 
			
		||||
        pdu["id"] = data["id"];
 | 
			
		||||
        pdu["filename"] = data["filename"];
 | 
			
		||||
 | 
			
		||||
        spdlog::info("Sending ack to sender");
 | 
			
		||||
        std::cout << "Sending ack to sender" << std::endl;
 | 
			
		||||
        MsgPack msg(pdu);
 | 
			
		||||
        _webSocket.sendBinary(msg.dump());
 | 
			
		||||
    }
 | 
			
		||||
@@ -192,11 +192,11 @@ namespace ix
 | 
			
		||||
                _condition.notify_one();
 | 
			
		||||
 | 
			
		||||
                log("ws_receive: connected");
 | 
			
		||||
                spdlog::info("Uri: {}", msg->openInfo.uri);
 | 
			
		||||
                spdlog::info("Headers:");
 | 
			
		||||
                std::cout << "Uri: " << msg->openInfo.uri << std::endl;
 | 
			
		||||
                std::cout << "Handshake Headers:" << std::endl;
 | 
			
		||||
                for (auto it : msg->openInfo.headers)
 | 
			
		||||
                {
 | 
			
		||||
                    spdlog::info("{}: {}", it.first, it.second);
 | 
			
		||||
                    std::cout << it.first << ": " << it.second << std::endl;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else if (msg->type == ix::WebSocketMessageType::Close)
 | 
			
		||||
@@ -259,7 +259,7 @@ namespace ix
 | 
			
		||||
        std::chrono::duration<double, std::milli> duration(1000);
 | 
			
		||||
        std::this_thread::sleep_for(duration);
 | 
			
		||||
 | 
			
		||||
        spdlog::info("ws_receive: Done !");
 | 
			
		||||
        std::cout << "ws_receive: Done !" << std::endl;
 | 
			
		||||
        webSocketReceiver.stop();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -4,8 +4,8 @@
 | 
			
		||||
 *  Copyright (c) 2019 Machine Zone, Inc. All rights reserved.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <ixsnake/IXRedisClient.h>
 | 
			
		||||
#include <spdlog/spdlog.h>
 | 
			
		||||
#include <sstream>
 | 
			
		||||
 | 
			
		||||
namespace ix
 | 
			
		||||
@@ -20,7 +20,7 @@ namespace ix
 | 
			
		||||
        RedisClient redisClient;
 | 
			
		||||
        if (!redisClient.connect(hostname, port))
 | 
			
		||||
        {
 | 
			
		||||
            spdlog::info("Cannot connect to redis host");
 | 
			
		||||
            std::cerr << "Cannot connect to redis host" << std::endl;
 | 
			
		||||
            return 1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -30,10 +30,10 @@ namespace ix
 | 
			
		||||
            if (!redisClient.auth(password, authResponse))
 | 
			
		||||
            {
 | 
			
		||||
                std::stringstream ss;
 | 
			
		||||
                spdlog::info("Cannot authenticated to redis");
 | 
			
		||||
                std::cerr << "Cannot authenticated to redis" << std::endl;
 | 
			
		||||
                return 1;
 | 
			
		||||
            }
 | 
			
		||||
            spdlog::info("Auth response: {}", authResponse);
 | 
			
		||||
            std::cout << "Auth response: " << authResponse << ":" << port << std::endl;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        std::string errMsg;
 | 
			
		||||
@@ -41,7 +41,8 @@ namespace ix
 | 
			
		||||
        {
 | 
			
		||||
            if (!redisClient.publish(channel, message, errMsg))
 | 
			
		||||
            {
 | 
			
		||||
                spdlog::error("Error publishing to channel {} error {}", channel, errMsg);
 | 
			
		||||
                std::cerr << "Error publishing to channel " << channel << "error: " << errMsg
 | 
			
		||||
                          << std::endl;
 | 
			
		||||
                return 1;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,7 @@
 | 
			
		||||
 *  Copyright (c) 2019 Machine Zone, Inc. All rights reserved.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <ixsnake/IXRedisServer.h>
 | 
			
		||||
#include <spdlog/spdlog.h>
 | 
			
		||||
#include <sstream>
 | 
			
		||||
@@ -19,7 +20,7 @@ namespace ix
 | 
			
		||||
        auto res = server.listen();
 | 
			
		||||
        if (!res.first)
 | 
			
		||||
        {
 | 
			
		||||
            spdlog::info(res.second);
 | 
			
		||||
            std::cerr << res.second << std::endl;
 | 
			
		||||
            return 1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -6,8 +6,8 @@
 | 
			
		||||
 | 
			
		||||
#include <atomic>
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <ixsnake/IXRedisClient.h>
 | 
			
		||||
#include <spdlog/spdlog.h>
 | 
			
		||||
#include <sstream>
 | 
			
		||||
#include <thread>
 | 
			
		||||
 | 
			
		||||
@@ -22,7 +22,7 @@ namespace ix
 | 
			
		||||
        RedisClient redisClient;
 | 
			
		||||
        if (!redisClient.connect(hostname, port))
 | 
			
		||||
        {
 | 
			
		||||
            spdlog::info("Cannot connect to redis host");
 | 
			
		||||
            std::cerr << "Cannot connect to redis host" << std::endl;
 | 
			
		||||
            return 1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -32,10 +32,10 @@ namespace ix
 | 
			
		||||
            if (!redisClient.auth(password, authResponse))
 | 
			
		||||
            {
 | 
			
		||||
                std::stringstream ss;
 | 
			
		||||
                spdlog::info("Cannot authenticated to redis");
 | 
			
		||||
                std::cerr << "Cannot authenticated to redis" << std::endl;
 | 
			
		||||
                return 1;
 | 
			
		||||
            }
 | 
			
		||||
            spdlog::info("Auth response: {}", authResponse);
 | 
			
		||||
            std::cout << "Auth response: " << authResponse << ":" << port << std::endl;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        std::atomic<int> msgPerSeconds(0);
 | 
			
		||||
@@ -44,7 +44,7 @@ namespace ix
 | 
			
		||||
        auto callback = [&msgPerSeconds, &msgCount, verbose](const std::string& message) {
 | 
			
		||||
            if (verbose)
 | 
			
		||||
            {
 | 
			
		||||
                spdlog::info("recived: {}", message);
 | 
			
		||||
                std::cout << "received: " << message << std::endl;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            msgPerSeconds++;
 | 
			
		||||
@@ -52,13 +52,14 @@ namespace ix
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        auto responseCallback = [](const std::string& redisResponse) {
 | 
			
		||||
            spdlog::info("Redis subscribe response: {}", redisResponse);
 | 
			
		||||
            std::cout << "Redis subscribe response: " << redisResponse << std::endl;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        auto timer = [&msgPerSeconds, &msgCount] {
 | 
			
		||||
            while (true)
 | 
			
		||||
            {
 | 
			
		||||
                spdlog::info("#messages {} msg/s {}", msgCount, msgPerSeconds);
 | 
			
		||||
                std::cout << "#messages " << msgCount << " "
 | 
			
		||||
                          << "msg/s " << msgPerSeconds << std::endl;
 | 
			
		||||
 | 
			
		||||
                msgPerSeconds = 0;
 | 
			
		||||
                auto duration = std::chrono::seconds(1);
 | 
			
		||||
@@ -68,10 +69,10 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
        std::thread t(timer);
 | 
			
		||||
 | 
			
		||||
        spdlog::info("Subscribing to {} ...", channel);
 | 
			
		||||
        std::cerr << "Subscribing to " << channel << "..." << std::endl;
 | 
			
		||||
        if (!redisClient.subscribe(channel, responseCallback, callback))
 | 
			
		||||
        {
 | 
			
		||||
            spdlog::info("Error subscribing to channel {}", channel);
 | 
			
		||||
            std::cerr << "Error subscribing to channel " << channel << std::endl;
 | 
			
		||||
            return 1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,7 @@
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#include <condition_variable>
 | 
			
		||||
#include <fstream>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <ixcrypto/IXBase64.h>
 | 
			
		||||
#include <ixcrypto/IXHash.h>
 | 
			
		||||
#include <ixcrypto/IXUuid.h>
 | 
			
		||||
@@ -15,7 +16,6 @@
 | 
			
		||||
#include <ixwebsocket/IXWebSocket.h>
 | 
			
		||||
#include <msgpack11/msgpack11.hpp>
 | 
			
		||||
#include <mutex>
 | 
			
		||||
#include <spdlog/spdlog.h>
 | 
			
		||||
#include <sstream>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
@@ -68,12 +68,12 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
    void WebSocketSender::log(const std::string& msg)
 | 
			
		||||
    {
 | 
			
		||||
        spdlog::info(msg);
 | 
			
		||||
        std::cout << msg << std::endl;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void WebSocketSender::waitForConnection()
 | 
			
		||||
    {
 | 
			
		||||
        spdlog::info("{}: Connecting...", "ws_send");
 | 
			
		||||
        std::cout << "ws_send: Connecting..." << std::endl;
 | 
			
		||||
 | 
			
		||||
        std::unique_lock<std::mutex> lock(_conditionVariableMutex);
 | 
			
		||||
        _condition.wait(lock);
 | 
			
		||||
@@ -81,7 +81,7 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
    void WebSocketSender::waitForAck()
 | 
			
		||||
    {
 | 
			
		||||
        spdlog::info("{}: Waiting for ack...", "ws_send");
 | 
			
		||||
        std::cout << "ws_send: Waiting for ack..." << std::endl;
 | 
			
		||||
 | 
			
		||||
        std::unique_lock<std::mutex> lock(_conditionVariableMutex);
 | 
			
		||||
        _condition.wait(lock);
 | 
			
		||||
@@ -122,11 +122,11 @@ namespace ix
 | 
			
		||||
                _condition.notify_one();
 | 
			
		||||
 | 
			
		||||
                log("ws_send: connected");
 | 
			
		||||
                spdlog::info("Uri: {}", msg->openInfo.uri);
 | 
			
		||||
                spdlog::info("Headers:");
 | 
			
		||||
                std::cout << "Uri: " << msg->openInfo.uri << std::endl;
 | 
			
		||||
                std::cout << "Handshake Headers:" << std::endl;
 | 
			
		||||
                for (auto it : msg->openInfo.headers)
 | 
			
		||||
                {
 | 
			
		||||
                    spdlog::info("{}: {}", it.first, it.second);
 | 
			
		||||
                    std::cout << it.first << ": " << it.second << std::endl;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else if (msg->type == ix::WebSocketMessageType::Close)
 | 
			
		||||
@@ -147,14 +147,14 @@ namespace ix
 | 
			
		||||
                MsgPack data = MsgPack::parse(msg->str, errMsg);
 | 
			
		||||
                if (!errMsg.empty())
 | 
			
		||||
                {
 | 
			
		||||
                    spdlog::info("Invalid MsgPack response");
 | 
			
		||||
                    std::cerr << "Invalid MsgPack response" << std::endl;
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                std::string id = data["id"].string_value();
 | 
			
		||||
                if (_id != id)
 | 
			
		||||
                {
 | 
			
		||||
                    spdlog::info("Invalid id");
 | 
			
		||||
                    std::cerr << "Invalid id" << std::endl;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else if (msg->type == ix::WebSocketMessageType::Error)
 | 
			
		||||
@@ -201,7 +201,7 @@ namespace ix
 | 
			
		||||
            auto milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(now - _start);
 | 
			
		||||
 | 
			
		||||
            _ms = milliseconds.count();
 | 
			
		||||
            spdlog::info("{} completed in {}", _description, _ms);
 | 
			
		||||
            std::cout << _description << " completed in " << _ms << "ms" << std::endl;
 | 
			
		||||
 | 
			
		||||
            _reported = true;
 | 
			
		||||
        }
 | 
			
		||||
@@ -240,7 +240,7 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
        Bench bench("Sending file through websocket");
 | 
			
		||||
        _webSocket.sendBinary(msg.dump(), [throttle](int current, int total) -> bool {
 | 
			
		||||
            spdlog::info("ws_send: Step {} out of {}", current, total);
 | 
			
		||||
            std::cout << "ws_send: Step " << current << " out of " << total << std::endl;
 | 
			
		||||
 | 
			
		||||
            if (throttle)
 | 
			
		||||
            {
 | 
			
		||||
@@ -254,7 +254,7 @@ namespace ix
 | 
			
		||||
        do
 | 
			
		||||
        {
 | 
			
		||||
            size_t bufferedAmount = _webSocket.bufferedAmount();
 | 
			
		||||
            spdlog::info("ws_send: {} bytes left to be sent", bufferedAmount);
 | 
			
		||||
            std::cout << "ws_send: " << bufferedAmount << " bytes left to be sent" << std::endl;
 | 
			
		||||
 | 
			
		||||
            std::chrono::duration<double, std::milli> duration(10);
 | 
			
		||||
            std::this_thread::sleep_for(duration);
 | 
			
		||||
@@ -264,7 +264,7 @@ namespace ix
 | 
			
		||||
        auto duration = bench.getDuration();
 | 
			
		||||
        auto transferRate = 1000 * content.size() / duration;
 | 
			
		||||
        transferRate /= (1024 * 1024);
 | 
			
		||||
        spdlog::info("ws_send: Send transfer rate: {} MB/s", transferRate);
 | 
			
		||||
        std::cout << "ws_send: Send transfer rate: " << transferRate << "MB/s" << std::endl;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void wsSend(const std::string& url,
 | 
			
		||||
@@ -278,12 +278,12 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
        webSocketSender.waitForConnection();
 | 
			
		||||
 | 
			
		||||
        spdlog::info("ws_send: Sending...");
 | 
			
		||||
        std::cout << "ws_send: Sending..." << std::endl;
 | 
			
		||||
        webSocketSender.sendMessage(path, throttle);
 | 
			
		||||
 | 
			
		||||
        webSocketSender.waitForAck();
 | 
			
		||||
 | 
			
		||||
        spdlog::info("ws_send: Done !");
 | 
			
		||||
        std::cout << "ws_send: Done !" << std::endl;
 | 
			
		||||
        webSocketSender.stop();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -5,8 +5,8 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <fstream>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <ixsnake/IXSnakeServer.h>
 | 
			
		||||
#include <spdlog/spdlog.h>
 | 
			
		||||
#include <sstream>
 | 
			
		||||
 | 
			
		||||
namespace
 | 
			
		||||
@@ -58,11 +58,11 @@ namespace ix
 | 
			
		||||
        auto str = readAsString(appsConfigPath);
 | 
			
		||||
        if (str.empty())
 | 
			
		||||
        {
 | 
			
		||||
            spdlog::error("Cannot read content of {}", appsConfigPath);
 | 
			
		||||
            std::cout << "Cannot read content of " << appsConfigPath << std::endl;
 | 
			
		||||
            return 1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        spdlog::error(str);
 | 
			
		||||
        std::cout << str << std::endl;
 | 
			
		||||
        auto apps = nlohmann::json::parse(str);
 | 
			
		||||
        appConfig.apps = apps["apps"];
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -4,8 +4,8 @@
 | 
			
		||||
 *  Copyright (c) 2018 Machine Zone, Inc. All rights reserved.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <ixwebsocket/IXWebSocketServer.h>
 | 
			
		||||
#include <spdlog/spdlog.h>
 | 
			
		||||
#include <sstream>
 | 
			
		||||
 | 
			
		||||
namespace ix
 | 
			
		||||
@@ -14,7 +14,7 @@ namespace ix
 | 
			
		||||
                         const std::string& hostname,
 | 
			
		||||
                         const ix::SocketTLSOptions& tlsOptions)
 | 
			
		||||
    {
 | 
			
		||||
        spdlog::info("Listening on {}:{}", hostname, port);
 | 
			
		||||
        std::cout << "ws_transfer: Listening on " << hostname << ":" << port << std::endl;
 | 
			
		||||
 | 
			
		||||
        ix::WebSocketServer server(port, hostname);
 | 
			
		||||
        server.setTLSOptions(tlsOptions);
 | 
			
		||||
@@ -25,23 +25,22 @@ namespace ix
 | 
			
		||||
                                                const WebSocketMessagePtr& msg) {
 | 
			
		||||
                if (msg->type == ix::WebSocketMessageType::Open)
 | 
			
		||||
                {
 | 
			
		||||
                    spdlog::info("ws_transfer: New connection");
 | 
			
		||||
                    spdlog::info("id: {}", connectionState->getId());
 | 
			
		||||
                    spdlog::info("Uri: {}", msg->openInfo.uri);
 | 
			
		||||
                    spdlog::info("Headers:");
 | 
			
		||||
                    std::cerr << "ws_transfer: New connection" << std::endl;
 | 
			
		||||
                    std::cerr << "id: " << connectionState->getId() << std::endl;
 | 
			
		||||
                    std::cerr << "Uri: " << msg->openInfo.uri << std::endl;
 | 
			
		||||
                    std::cerr << "Headers:" << std::endl;
 | 
			
		||||
                    for (auto it : msg->openInfo.headers)
 | 
			
		||||
                    {
 | 
			
		||||
                        spdlog::info("{}: {}", it.first, it.second);
 | 
			
		||||
                        std::cerr << it.first << ": " << it.second << std::endl;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else if (msg->type == ix::WebSocketMessageType::Close)
 | 
			
		||||
                {
 | 
			
		||||
                    spdlog::info("ws_transfer: Closed connection: client id {} code {} reason {}",
 | 
			
		||||
                                 connectionState->getId(),
 | 
			
		||||
                                 msg->closeInfo.code,
 | 
			
		||||
                                 msg->closeInfo.reason);
 | 
			
		||||
                    std::cerr << "ws_transfer: [client " << connectionState->getId()
 | 
			
		||||
                              << "]: Closed connection, code " << msg->closeInfo.code << " reason "
 | 
			
		||||
                              << msg->closeInfo.reason << std::endl;
 | 
			
		||||
                    auto remaining = server.getClients().erase(webSocket);
 | 
			
		||||
                    spdlog::info("ws_transfer: {} remaining clients", remaining);
 | 
			
		||||
                    std::cerr << "ws_transfer: " << remaining << " remaining clients " << std::endl;
 | 
			
		||||
                }
 | 
			
		||||
                else if (msg->type == ix::WebSocketMessageType::Error)
 | 
			
		||||
                {
 | 
			
		||||
@@ -50,43 +49,40 @@ namespace ix
 | 
			
		||||
                    ss << "#retries: " << msg->errorInfo.retries << std::endl;
 | 
			
		||||
                    ss << "Wait time(ms): " << msg->errorInfo.wait_time << std::endl;
 | 
			
		||||
                    ss << "HTTP Status: " << msg->errorInfo.http_status << std::endl;
 | 
			
		||||
                    spdlog::info(ss.str());
 | 
			
		||||
                    std::cerr << ss.str();
 | 
			
		||||
                }
 | 
			
		||||
                else if (msg->type == ix::WebSocketMessageType::Fragment)
 | 
			
		||||
                {
 | 
			
		||||
                    spdlog::info("ws_transfer: Received message fragment ");
 | 
			
		||||
                    std::cerr << "ws_transfer: Received message fragment " << std::endl;
 | 
			
		||||
                }
 | 
			
		||||
                else if (msg->type == ix::WebSocketMessageType::Message)
 | 
			
		||||
                {
 | 
			
		||||
                    spdlog::info("ws_transfer: Received {} bytes", msg->wireSize);
 | 
			
		||||
                    std::cerr << "ws_transfer: Received " << msg->wireSize << " bytes" << std::endl;
 | 
			
		||||
                    size_t receivers = 0;
 | 
			
		||||
                    for (auto&& client : server.getClients())
 | 
			
		||||
                    {
 | 
			
		||||
                        if (client != webSocket)
 | 
			
		||||
                        {
 | 
			
		||||
                            auto readyState = client->getReadyState();
 | 
			
		||||
                            auto id = connectionState->getId();
 | 
			
		||||
 | 
			
		||||
                            if (readyState == ReadyState::Open)
 | 
			
		||||
                            {
 | 
			
		||||
                                ++receivers;
 | 
			
		||||
                                client->send(
 | 
			
		||||
                                    msg->str, msg->binary, [&id](int current, int total) -> bool {
 | 
			
		||||
                                        spdlog::info("{}: [client {}]: Step {} out of {}",
 | 
			
		||||
                                                     "ws_transfer",
 | 
			
		||||
                                                     id,
 | 
			
		||||
                                                     current,
 | 
			
		||||
                                                     total);
 | 
			
		||||
                                        return true;
 | 
			
		||||
                                    });
 | 
			
		||||
                                client->send(msg->str,
 | 
			
		||||
                                             msg->binary,
 | 
			
		||||
                                             [id = connectionState->getId()](int current,
 | 
			
		||||
                                                                             int total) -> bool {
 | 
			
		||||
                                                 std::cerr << "ws_transfer: [client " << id
 | 
			
		||||
                                                           << "]: Step " << current << " out of "
 | 
			
		||||
                                                           << total << std::endl;
 | 
			
		||||
                                                 return true;
 | 
			
		||||
                                             });
 | 
			
		||||
 | 
			
		||||
                                do
 | 
			
		||||
                                {
 | 
			
		||||
                                    size_t bufferedAmount = client->bufferedAmount();
 | 
			
		||||
 | 
			
		||||
                                    spdlog::info("{}: [client {}]: {} bytes left to send",
 | 
			
		||||
                                                 "ws_transfer",
 | 
			
		||||
                                                 id,
 | 
			
		||||
                                                 bufferedAmount);
 | 
			
		||||
                                    std::cerr << "ws_transfer: [client " << connectionState->getId()
 | 
			
		||||
                                              << "]: " << bufferedAmount
 | 
			
		||||
                                              << " bytes left to be sent, " << std::endl;
 | 
			
		||||
 | 
			
		||||
                                    std::this_thread::sleep_for(std::chrono::milliseconds(500));
 | 
			
		||||
 | 
			
		||||
@@ -100,19 +96,16 @@ namespace ix
 | 
			
		||||
                                        ? "Connecting"
 | 
			
		||||
                                        : readyState == ReadyState::Closing ? "Closing" : "Closed";
 | 
			
		||||
                                size_t bufferedAmount = client->bufferedAmount();
 | 
			
		||||
 | 
			
		||||
                                spdlog::info(
 | 
			
		||||
                                    "{}: [client {}]: has readystate {} bytes left to be sent",
 | 
			
		||||
                                    "ws_transfer",
 | 
			
		||||
                                    id,
 | 
			
		||||
                                    readyStateString,
 | 
			
		||||
                                    bufferedAmount);
 | 
			
		||||
                                std::cerr << "ws_transfer: [client " << connectionState->getId()
 | 
			
		||||
                                          << "]: has readystate '" << readyStateString << "' and "
 | 
			
		||||
                                          << bufferedAmount << " bytes left to be sent, "
 | 
			
		||||
                                          << std::endl;
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    if (!receivers)
 | 
			
		||||
                    {
 | 
			
		||||
                        spdlog::info("ws_transfer: no remaining receivers");
 | 
			
		||||
                        std::cerr << "ws_transfer: no remaining receivers" << std::endl;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
@@ -121,7 +114,7 @@ namespace ix
 | 
			
		||||
        auto res = server.listen();
 | 
			
		||||
        if (!res.first)
 | 
			
		||||
        {
 | 
			
		||||
            spdlog::info(res.second);
 | 
			
		||||
            std::cerr << res.second << std::endl;
 | 
			
		||||
            return 1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user