Compare commits
	
		
			27 Commits
		
	
	
		
			feature/se
			...
			user/bserg
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					cbf0b826d0 | ||
| 
						 | 
					747b4495b0 | ||
| 
						 | 
					f0b955efd2 | ||
| 
						 | 
					0c689bc382 | ||
| 
						 | 
					6bcbaea293 | ||
| 
						 | 
					0ef9e81435 | ||
| 
						 | 
					6f9e7ad245 | ||
| 
						 | 
					c1ef3f4e1d | ||
| 
						 | 
					720f57da27 | ||
| 
						 | 
					e29c0ce654 | ||
| 
						 | 
					e50974dc4b | ||
| 
						 | 
					0d83ffdf6e | ||
| 
						 | 
					c0a80264d1 | ||
| 
						 | 
					72b3ebf69e | ||
| 
						 | 
					e17309f030 | ||
| 
						 | 
					e9f4e9647e | ||
| 
						 | 
					0187735998 | ||
| 
						 | 
					d2fa1da30b | ||
| 
						 | 
					00dc631f2b | ||
| 
						 | 
					40069b50a2 | ||
| 
						 | 
					33f50e809a | ||
| 
						 | 
					9d61084e7b | ||
| 
						 | 
					1f6b497015 | ||
| 
						 | 
					afb1626ceb | ||
| 
						 | 
					c07ca74186 | ||
| 
						 | 
					4e6a57dc07 | ||
| 
						 | 
					d93f723e68 | 
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1,2 +1 @@
 | 
			
		||||
build
 | 
			
		||||
*.pyc
 | 
			
		||||
 
 | 
			
		||||
@@ -1 +1 @@
 | 
			
		||||
2.0.0
 | 
			
		||||
1.5.2
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										26
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								README.md
									
									
									
									
									
								
							@@ -37,7 +37,7 @@ webSocket.setOnMessageCallback(
 | 
			
		||||
       const ix::WebSocketOpenInfo& openInfo,
 | 
			
		||||
       const ix::WebSocketCloseInfo& closeInfo)
 | 
			
		||||
    {
 | 
			
		||||
        if (messageType == ix::WebSocketMessageType::Message)
 | 
			
		||||
        if (messageType == ix::WebSocket_MessageType_Message)
 | 
			
		||||
        {
 | 
			
		||||
            std::cout << str << std::endl;
 | 
			
		||||
        }
 | 
			
		||||
@@ -77,7 +77,7 @@ server.setOnConnectionCallback(
 | 
			
		||||
               const ix::WebSocketOpenInfo& openInfo,
 | 
			
		||||
               const ix::WebSocketCloseInfo& closeInfo)
 | 
			
		||||
            {
 | 
			
		||||
                if (messageType == ix::WebSocketMessageType::Open)
 | 
			
		||||
                if (messageType == ix::WebSocket_MessageType_Open)
 | 
			
		||||
                {
 | 
			
		||||
                    std::cerr << "New connection" << std::endl;
 | 
			
		||||
 | 
			
		||||
@@ -96,7 +96,7 @@ server.setOnConnectionCallback(
 | 
			
		||||
                        std::cerr << it.first << ": " << it.second << std::endl;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Message)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Message)
 | 
			
		||||
                {
 | 
			
		||||
                    // For an echo server, we just send back to the client whatever was received by the server
 | 
			
		||||
                    // All connected clients are available in an std::set. See the broadcast cpp example.
 | 
			
		||||
@@ -301,10 +301,10 @@ If the connection was closed and sending failed, the return value will be set to
 | 
			
		||||
 | 
			
		||||
`getReadyState()` returns the state of the connection. There are 4 possible states.
 | 
			
		||||
 | 
			
		||||
1. ReadyState::Connecting - The connection is not yet open.
 | 
			
		||||
2. ReadyState::Open       - The connection is open and ready to communicate.
 | 
			
		||||
3. ReadyState::Closing    - The connection is in the process of closing.
 | 
			
		||||
4. ReadyState::Closed     - The connection is closed or could not be opened.
 | 
			
		||||
1. WebSocket_ReadyState_Connecting - The connection is not yet open.
 | 
			
		||||
2. WebSocket_ReadyState_Open       - The connection is open and ready to communicate.
 | 
			
		||||
3. WebSocket_ReadyState_Closing    - The connection is in the process of closing.
 | 
			
		||||
4. WebSocket_MessageType_Close     - The connection is closed or could not be opened.
 | 
			
		||||
 | 
			
		||||
### Open and Close notifications
 | 
			
		||||
 | 
			
		||||
@@ -319,7 +319,7 @@ webSocket.setOnMessageCallback(
 | 
			
		||||
       const ix::WebSocketOpenInfo& openInfo,
 | 
			
		||||
       const ix::WebSocketCloseInfo& closeInfo)
 | 
			
		||||
    {
 | 
			
		||||
        if (messageType == ix::WebSocketMessageType::Open)
 | 
			
		||||
        if (messageType == ix::WebSocket_MessageType_Open)
 | 
			
		||||
        {
 | 
			
		||||
            std::cout << "send greetings" << std::endl;
 | 
			
		||||
 | 
			
		||||
@@ -330,7 +330,7 @@ webSocket.setOnMessageCallback(
 | 
			
		||||
                std::cout << it.first << ": " << it.second << std::endl;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else if (messageType == ix::WebSocketMessageType::Close)
 | 
			
		||||
        else if (messageType == ix::WebSocket_MessageType_Close)
 | 
			
		||||
        {
 | 
			
		||||
            std::cout << "disconnected" << std::endl;
 | 
			
		||||
 | 
			
		||||
@@ -345,7 +345,7 @@ webSocket.setOnMessageCallback(
 | 
			
		||||
 | 
			
		||||
### Error notification
 | 
			
		||||
 | 
			
		||||
A message will be fired when there is an error with the connection. The message type will be `ix::WebSocketMessageType::Error`. Multiple fields will be available on the event to describe the error.
 | 
			
		||||
A message will be fired when there is an error with the connection. The message type will be `ix::WebSocket_MessageType_Error`. Multiple fields will be available on the event to describe the error.
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
webSocket.setOnMessageCallback(
 | 
			
		||||
@@ -356,7 +356,7 @@ webSocket.setOnMessageCallback(
 | 
			
		||||
       const ix::WebSocketOpenInfo& openInfo,
 | 
			
		||||
       const ix::WebSocketCloseInfo& closeInfo)
 | 
			
		||||
    {
 | 
			
		||||
        if (messageType == ix::WebSocketMessageType::Error)
 | 
			
		||||
        if (messageType == ix::WebSocket_MessageType_Error)
 | 
			
		||||
        {
 | 
			
		||||
            std::stringstream ss;
 | 
			
		||||
            ss << "Error: "         << error.reason      << std::endl;
 | 
			
		||||
@@ -396,8 +396,8 @@ webSocket.setOnMessageCallback(
 | 
			
		||||
       const ix::WebSocketOpenInfo& openInfo,
 | 
			
		||||
       const ix::WebSocketCloseInfo& closeInfo)
 | 
			
		||||
    {
 | 
			
		||||
        if (messageType == ix::WebSocketMessageType::Ping ||
 | 
			
		||||
            messageType == ix::WebSocketMessageType::Pong)
 | 
			
		||||
        if (messageType == ix::WebSocket_MessageType_Ping ||
 | 
			
		||||
            messageType == ix::WebSocket_MessageType_Pong)
 | 
			
		||||
        {
 | 
			
		||||
            std::cout << "pong data: " << str << std::endl;
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -52,7 +52,7 @@ namespace ix
 | 
			
		||||
        {
 | 
			
		||||
            std::stringstream ss;
 | 
			
		||||
            ss << "Cannot parse url: " << url;
 | 
			
		||||
            return std::make_tuple(code, HttpErrorCode::UrlMalformed,
 | 
			
		||||
            return std::make_tuple(code, HttpErrorCode_UrlMalformed,
 | 
			
		||||
                                   headers, payload, ss.str(),
 | 
			
		||||
                                   uploadSize, downloadSize);
 | 
			
		||||
        }
 | 
			
		||||
@@ -63,7 +63,7 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
        if (!_socket)
 | 
			
		||||
        {
 | 
			
		||||
            return std::make_tuple(code, HttpErrorCode::CannotCreateSocket,
 | 
			
		||||
            return std::make_tuple(code, HttpErrorCode_CannotCreateSocket,
 | 
			
		||||
                                   headers, payload, errorMsg,
 | 
			
		||||
                                   uploadSize, downloadSize);
 | 
			
		||||
        }
 | 
			
		||||
@@ -116,7 +116,7 @@ namespace ix
 | 
			
		||||
        {
 | 
			
		||||
            std::stringstream ss;
 | 
			
		||||
            ss << "Cannot connect to url: " << url;
 | 
			
		||||
            return std::make_tuple(code, HttpErrorCode::CannotConnect,
 | 
			
		||||
            return std::make_tuple(code, HttpErrorCode_CannotConnect,
 | 
			
		||||
                                   headers, payload, ss.str(),
 | 
			
		||||
                                   uploadSize, downloadSize);
 | 
			
		||||
        }
 | 
			
		||||
@@ -142,7 +142,7 @@ namespace ix
 | 
			
		||||
        if (!_socket->writeBytes(req, isCancellationRequested))
 | 
			
		||||
        {
 | 
			
		||||
            std::string errorMsg("Cannot send request");
 | 
			
		||||
            return std::make_tuple(code, HttpErrorCode::SendError,
 | 
			
		||||
            return std::make_tuple(code, HttpErrorCode_SendError,
 | 
			
		||||
                                   headers, payload, errorMsg,
 | 
			
		||||
                                   uploadSize, downloadSize);
 | 
			
		||||
        }
 | 
			
		||||
@@ -156,7 +156,7 @@ namespace ix
 | 
			
		||||
        if (!lineValid)
 | 
			
		||||
        {
 | 
			
		||||
            std::string errorMsg("Cannot retrieve status line");
 | 
			
		||||
            return std::make_tuple(code, HttpErrorCode::CannotReadStatusLine,
 | 
			
		||||
            return std::make_tuple(code, HttpErrorCode_CannotReadStatusLine,
 | 
			
		||||
                                   headers, payload, errorMsg,
 | 
			
		||||
                                   uploadSize, downloadSize);
 | 
			
		||||
        }
 | 
			
		||||
@@ -171,7 +171,7 @@ namespace ix
 | 
			
		||||
        if (sscanf(line.c_str(), "HTTP/1.1 %d", &code) != 1)
 | 
			
		||||
        {
 | 
			
		||||
            std::string errorMsg("Cannot parse response code from status line");
 | 
			
		||||
            return std::make_tuple(code, HttpErrorCode::MissingStatus,
 | 
			
		||||
            return std::make_tuple(code, HttpErrorCode_MissingStatus,
 | 
			
		||||
                                   headers, payload, errorMsg,
 | 
			
		||||
                                   uploadSize, downloadSize);
 | 
			
		||||
        }
 | 
			
		||||
@@ -183,7 +183,7 @@ namespace ix
 | 
			
		||||
        if (!headersValid)
 | 
			
		||||
        {
 | 
			
		||||
            std::string errorMsg("Cannot parse http headers");
 | 
			
		||||
            return std::make_tuple(code, HttpErrorCode::HeaderParsingError,
 | 
			
		||||
            return std::make_tuple(code, HttpErrorCode_HeaderParsingError,
 | 
			
		||||
                                   headers, payload, errorMsg,
 | 
			
		||||
                                   uploadSize, downloadSize);
 | 
			
		||||
        }
 | 
			
		||||
@@ -194,7 +194,7 @@ namespace ix
 | 
			
		||||
            if (headers.find("Location") == headers.end())
 | 
			
		||||
            {
 | 
			
		||||
                std::string errorMsg("Missing location header for redirect");
 | 
			
		||||
                return std::make_tuple(code, HttpErrorCode::MissingLocation,
 | 
			
		||||
                return std::make_tuple(code, HttpErrorCode_MissingLocation,
 | 
			
		||||
                                       headers, payload, errorMsg,
 | 
			
		||||
                                       uploadSize, downloadSize);
 | 
			
		||||
            }
 | 
			
		||||
@@ -203,7 +203,7 @@ namespace ix
 | 
			
		||||
            {
 | 
			
		||||
                std::stringstream ss;
 | 
			
		||||
                ss << "Too many redirects: " << redirects;
 | 
			
		||||
                return std::make_tuple(code, HttpErrorCode::TooManyRedirects,
 | 
			
		||||
                return std::make_tuple(code, HttpErrorCode_TooManyRedirects,
 | 
			
		||||
                                       headers, payload, ss.str(),
 | 
			
		||||
                                       uploadSize, downloadSize);
 | 
			
		||||
            }
 | 
			
		||||
@@ -215,7 +215,7 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
        if (verb == "HEAD")
 | 
			
		||||
        {
 | 
			
		||||
            return std::make_tuple(code, HttpErrorCode::Ok,
 | 
			
		||||
            return std::make_tuple(code, HttpErrorCode_Ok,
 | 
			
		||||
                                   headers, payload, std::string(),
 | 
			
		||||
                                   uploadSize, downloadSize);
 | 
			
		||||
        }
 | 
			
		||||
@@ -236,7 +236,7 @@ namespace ix
 | 
			
		||||
            if (!chunkResult.first)
 | 
			
		||||
            {
 | 
			
		||||
                errorMsg = "Cannot read chunk";
 | 
			
		||||
                return std::make_tuple(code, HttpErrorCode::ChunkReadError,
 | 
			
		||||
                return std::make_tuple(code, HttpErrorCode_ChunkReadError,
 | 
			
		||||
                                       headers, payload, errorMsg,
 | 
			
		||||
                                       uploadSize, downloadSize);
 | 
			
		||||
            }
 | 
			
		||||
@@ -254,7 +254,7 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
                if (!lineResult.first)
 | 
			
		||||
                {
 | 
			
		||||
                    return std::make_tuple(code, HttpErrorCode::ChunkReadError,
 | 
			
		||||
                    return std::make_tuple(code, HttpErrorCode_ChunkReadError,
 | 
			
		||||
                                           headers, payload, errorMsg,
 | 
			
		||||
                                           uploadSize, downloadSize);
 | 
			
		||||
                }
 | 
			
		||||
@@ -281,7 +281,7 @@ namespace ix
 | 
			
		||||
                if (!chunkResult.first)
 | 
			
		||||
                {
 | 
			
		||||
                    errorMsg = "Cannot read chunk";
 | 
			
		||||
                    return std::make_tuple(code, HttpErrorCode::ChunkReadError,
 | 
			
		||||
                    return std::make_tuple(code, HttpErrorCode_ChunkReadError,
 | 
			
		||||
                                           headers, payload, errorMsg,
 | 
			
		||||
                                           uploadSize, downloadSize);
 | 
			
		||||
                }
 | 
			
		||||
@@ -292,7 +292,7 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
                if (!lineResult.first)
 | 
			
		||||
                {
 | 
			
		||||
                    return std::make_tuple(code, HttpErrorCode::ChunkReadError,
 | 
			
		||||
                    return std::make_tuple(code, HttpErrorCode_ChunkReadError,
 | 
			
		||||
                                           headers, payload, errorMsg,
 | 
			
		||||
                                           uploadSize, downloadSize);
 | 
			
		||||
                }
 | 
			
		||||
@@ -307,7 +307,7 @@ namespace ix
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            std::string errorMsg("Cannot read http body");
 | 
			
		||||
            return std::make_tuple(code, HttpErrorCode::CannotReadBody,
 | 
			
		||||
            return std::make_tuple(code, HttpErrorCode_CannotReadBody,
 | 
			
		||||
                                   headers, payload, errorMsg,
 | 
			
		||||
                                   uploadSize, downloadSize);
 | 
			
		||||
        }
 | 
			
		||||
@@ -321,14 +321,14 @@ namespace ix
 | 
			
		||||
            if (!gzipInflate(payload, decompressedPayload))
 | 
			
		||||
            {
 | 
			
		||||
                std::string errorMsg("Error decompressing payload");
 | 
			
		||||
                return std::make_tuple(code, HttpErrorCode::Gzip,
 | 
			
		||||
                return std::make_tuple(code, HttpErrorCode_Gzip,
 | 
			
		||||
                                       headers, payload, errorMsg,
 | 
			
		||||
                                       uploadSize, downloadSize);
 | 
			
		||||
            }
 | 
			
		||||
            payload = decompressedPayload;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return std::make_tuple(code, HttpErrorCode::Ok,
 | 
			
		||||
        return std::make_tuple(code, HttpErrorCode_Ok,
 | 
			
		||||
                               headers, payload, std::string(),
 | 
			
		||||
                               uploadSize, downloadSize);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -19,23 +19,23 @@
 | 
			
		||||
 | 
			
		||||
namespace ix
 | 
			
		||||
{
 | 
			
		||||
    enum class HttpErrorCode
 | 
			
		||||
    enum HttpErrorCode
 | 
			
		||||
    {
 | 
			
		||||
        Ok                       = 0,
 | 
			
		||||
        CannotConnect            = 1,
 | 
			
		||||
        Timeout                  = 2,
 | 
			
		||||
        Gzip                     = 3,
 | 
			
		||||
        UrlMalformed             = 4,
 | 
			
		||||
        CannotCreateSocket       = 5,
 | 
			
		||||
        SendError                = 6,
 | 
			
		||||
        ReadError                = 7,
 | 
			
		||||
        CannotReadStatusLine     = 8,
 | 
			
		||||
        MissingStatus            = 9,
 | 
			
		||||
        HeaderParsingError       = 10,
 | 
			
		||||
        MissingLocation          = 11,
 | 
			
		||||
        TooManyRedirects         = 12,
 | 
			
		||||
        ChunkReadError           = 13,
 | 
			
		||||
        CannotReadBody           = 14
 | 
			
		||||
        HttpErrorCode_Ok = 0,
 | 
			
		||||
        HttpErrorCode_CannotConnect = 1,
 | 
			
		||||
        HttpErrorCode_Timeout = 2,
 | 
			
		||||
        HttpErrorCode_Gzip = 3,
 | 
			
		||||
        HttpErrorCode_UrlMalformed = 4,
 | 
			
		||||
        HttpErrorCode_CannotCreateSocket = 5,
 | 
			
		||||
        HttpErrorCode_SendError = 6,
 | 
			
		||||
        HttpErrorCode_ReadError = 7,
 | 
			
		||||
        HttpErrorCode_CannotReadStatusLine = 8,
 | 
			
		||||
        HttpErrorCode_MissingStatus = 9,
 | 
			
		||||
        HttpErrorCode_HeaderParsingError = 10,
 | 
			
		||||
        HttpErrorCode_MissingLocation = 11,
 | 
			
		||||
        HttpErrorCode_TooManyRedirects = 12,
 | 
			
		||||
        HttpErrorCode_ChunkReadError = 13,
 | 
			
		||||
        HttpErrorCode_CannotReadBody = 14
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    using HttpResponse = std::tuple<int, // status
 | 
			
		||||
 
 | 
			
		||||
@@ -13,7 +13,7 @@
 | 
			
		||||
 | 
			
		||||
namespace ix
 | 
			
		||||
{
 | 
			
		||||
    class SelectInterruptEventFd final : public SelectInterrupt {
 | 
			
		||||
    class SelectInterruptEventFd : public SelectInterrupt {
 | 
			
		||||
    public:
 | 
			
		||||
        SelectInterruptEventFd();
 | 
			
		||||
        virtual ~SelectInterruptEventFd();
 | 
			
		||||
 
 | 
			
		||||
@@ -40,8 +40,6 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
    bool SelectInterruptPipe::init(std::string& errorMsg)
 | 
			
		||||
    {
 | 
			
		||||
        std::lock_guard<std::mutex> lock(_fildesMutex);
 | 
			
		||||
 | 
			
		||||
        // calling init twice is a programming error
 | 
			
		||||
        assert(_fildes[kPipeReadIndex] == -1);
 | 
			
		||||
        assert(_fildes[kPipeWriteIndex] == -1);
 | 
			
		||||
@@ -110,8 +108,6 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
    bool SelectInterruptPipe::notify(uint64_t value)
 | 
			
		||||
    {
 | 
			
		||||
        std::lock_guard<std::mutex> lock(_fildesMutex);
 | 
			
		||||
 | 
			
		||||
        int fd = _fildes[kPipeWriteIndex];
 | 
			
		||||
        if (fd == -1) return false;
 | 
			
		||||
 | 
			
		||||
@@ -122,8 +118,6 @@ namespace ix
 | 
			
		||||
    // TODO: return max uint64_t for errors ?
 | 
			
		||||
    uint64_t SelectInterruptPipe::read()
 | 
			
		||||
    {
 | 
			
		||||
        std::lock_guard<std::mutex> lock(_fildesMutex);
 | 
			
		||||
 | 
			
		||||
        int fd = _fildes[kPipeReadIndex];
 | 
			
		||||
 | 
			
		||||
        uint64_t value = 0;
 | 
			
		||||
@@ -139,8 +133,6 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
    int SelectInterruptPipe::getFd() const
 | 
			
		||||
    {
 | 
			
		||||
        std::lock_guard<std::mutex> lock(_fildesMutex);
 | 
			
		||||
 | 
			
		||||
        return _fildes[kPipeReadIndex];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -10,11 +10,10 @@
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <mutex>
 | 
			
		||||
 | 
			
		||||
namespace ix
 | 
			
		||||
{
 | 
			
		||||
    class SelectInterruptPipe final : public SelectInterrupt {
 | 
			
		||||
    class SelectInterruptPipe : public SelectInterrupt {
 | 
			
		||||
    public:
 | 
			
		||||
        SelectInterruptPipe();
 | 
			
		||||
        virtual ~SelectInterruptPipe();
 | 
			
		||||
@@ -31,7 +30,6 @@ namespace ix
 | 
			
		||||
        // happens between a control thread and a background thread, which is
 | 
			
		||||
        // blocked on select.
 | 
			
		||||
        int _fildes[2];
 | 
			
		||||
        mutable std::mutex _fildesMutex;
 | 
			
		||||
 | 
			
		||||
        // Used to identify the read/write idx
 | 
			
		||||
        static const int kPipeReadIndex;
 | 
			
		||||
 
 | 
			
		||||
@@ -73,7 +73,7 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
        struct timeval timeout;
 | 
			
		||||
        timeout.tv_sec = timeoutMs / 1000;
 | 
			
		||||
        timeout.tv_usec = 1000 * (timeoutMs % 1000);
 | 
			
		||||
        timeout.tv_usec = (timeoutMs < 1000) ? 0 : 1000 * (timeoutMs % 1000);
 | 
			
		||||
 | 
			
		||||
        // Compute the highest fd.
 | 
			
		||||
        int sockfd = _sockfd;
 | 
			
		||||
 
 | 
			
		||||
@@ -41,12 +41,12 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
    enum class PollResultType
 | 
			
		||||
    {
 | 
			
		||||
        ReadyForRead    = 0,
 | 
			
		||||
        ReadyForWrite   = 1,
 | 
			
		||||
        Timeout         = 2,
 | 
			
		||||
        Error           = 3,
 | 
			
		||||
        SendRequest     = 4,
 | 
			
		||||
        CloseRequest    = 5
 | 
			
		||||
        ReadyForRead = 0,
 | 
			
		||||
        ReadyForWrite = 1,
 | 
			
		||||
        Timeout = 2,
 | 
			
		||||
        Error = 3,
 | 
			
		||||
        SendRequest = 4,
 | 
			
		||||
        CloseRequest = 5
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class Socket {
 | 
			
		||||
 
 | 
			
		||||
@@ -20,6 +20,8 @@
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
#include <iostream>
 | 
			
		||||
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#define socketerrno errno
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,7 @@
 | 
			
		||||
 | 
			
		||||
namespace ix
 | 
			
		||||
{
 | 
			
		||||
    class SocketAppleSSL final : public Socket
 | 
			
		||||
    class SocketAppleSSL : public Socket
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        SocketAppleSSL(int fd = -1);
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,7 @@
 | 
			
		||||
#include "IXSocketConnect.h"
 | 
			
		||||
 | 
			
		||||
#include <cassert>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
 | 
			
		||||
#include <openssl/x509v3.h>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,7 @@
 | 
			
		||||
 | 
			
		||||
namespace ix
 | 
			
		||||
{
 | 
			
		||||
    class SocketOpenSSL final : public Socket
 | 
			
		||||
    class SocketOpenSSL : public Socket
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        SocketOpenSSL(int fd = -1);
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,7 @@
 | 
			
		||||
 | 
			
		||||
namespace ix
 | 
			
		||||
{
 | 
			
		||||
    class SocketSChannel final : public Socket
 | 
			
		||||
    class SocketSChannel : public Socket
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        SocketSChannel();
 | 
			
		||||
 
 | 
			
		||||
@@ -30,9 +30,7 @@ namespace ix
 | 
			
		||||
        _host(host),
 | 
			
		||||
        _backlog(backlog),
 | 
			
		||||
        _maxConnections(maxConnections),
 | 
			
		||||
        _serverFd(-1),
 | 
			
		||||
        _stop(false),
 | 
			
		||||
        _stopGc(false),
 | 
			
		||||
        _connectionStateFactory(&ConnectionState::createConnectionState)
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
@@ -126,15 +124,9 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
    void SocketServer::start()
 | 
			
		||||
    {
 | 
			
		||||
        if (!_thread.joinable())
 | 
			
		||||
        {
 | 
			
		||||
            _thread = std::thread(&SocketServer::run, this);
 | 
			
		||||
        }
 | 
			
		||||
        if (_thread.joinable()) return; // we've already been started
 | 
			
		||||
 | 
			
		||||
        if (!_gcThread.joinable())
 | 
			
		||||
        {
 | 
			
		||||
            _gcThread = std::thread(&SocketServer::runGC, this);
 | 
			
		||||
        }
 | 
			
		||||
        _thread = std::thread(&SocketServer::run, this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void SocketServer::wait()
 | 
			
		||||
@@ -150,21 +142,21 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
    void SocketServer::stop()
 | 
			
		||||
    {
 | 
			
		||||
        // Stop accepting connections, and close the 'accept' thread
 | 
			
		||||
        if (_thread.joinable())
 | 
			
		||||
        while (true)
 | 
			
		||||
        {
 | 
			
		||||
            _stop = true;
 | 
			
		||||
            _thread.join();
 | 
			
		||||
            _stop = false;
 | 
			
		||||
            if (closeTerminatedThreads()) break;
 | 
			
		||||
 | 
			
		||||
            // wait 10ms and try again later.
 | 
			
		||||
            // we could have a timeout, but if we exit of here
 | 
			
		||||
            // we leaked threads, it is quite bad.
 | 
			
		||||
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Join all threads and make sure that all connections are terminated
 | 
			
		||||
        if (_gcThread.joinable())
 | 
			
		||||
        {
 | 
			
		||||
            _stopGc = true;
 | 
			
		||||
            _gcThread.join();
 | 
			
		||||
            _stopGc = false;
 | 
			
		||||
        }
 | 
			
		||||
        if (!_thread.joinable()) return; // nothing to do
 | 
			
		||||
 | 
			
		||||
        _stop = true;
 | 
			
		||||
        _thread.join();
 | 
			
		||||
        _stop = false;
 | 
			
		||||
 | 
			
		||||
        _conditionVariable.notify_one();
 | 
			
		||||
        Socket::closeSocket(_serverFd);
 | 
			
		||||
@@ -183,7 +175,7 @@ namespace ix
 | 
			
		||||
    // field becomes true, and we can use that to know that we can join that thread
 | 
			
		||||
    // and remove it from our _connectionsThreads data structure (a list).
 | 
			
		||||
    //
 | 
			
		||||
    void SocketServer::closeTerminatedThreads()
 | 
			
		||||
    bool SocketServer::closeTerminatedThreads()
 | 
			
		||||
    {
 | 
			
		||||
        std::lock_guard<std::mutex> lock(_connectionsThreadsMutex);
 | 
			
		||||
        auto it = _connectionsThreads.begin();
 | 
			
		||||
@@ -203,6 +195,8 @@ namespace ix
 | 
			
		||||
            if (thread.joinable()) thread.join();
 | 
			
		||||
            it = _connectionsThreads.erase(it);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return _connectionsThreads.empty();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void SocketServer::run()
 | 
			
		||||
@@ -214,6 +208,12 @@ namespace ix
 | 
			
		||||
        {
 | 
			
		||||
            if (_stop) return;
 | 
			
		||||
 | 
			
		||||
            // Garbage collection to shutdown/join threads for closed connections.
 | 
			
		||||
            // We could run this in its own thread, so that we dont need to accept
 | 
			
		||||
            // a new connection to close a thread.
 | 
			
		||||
            // We could also use a condition variable to be notify when we need to do this
 | 
			
		||||
            closeTerminatedThreads();
 | 
			
		||||
 | 
			
		||||
            // Use select to check whether a new connection is in progress
 | 
			
		||||
            fd_set rfds;
 | 
			
		||||
            struct timeval timeout;
 | 
			
		||||
@@ -290,30 +290,5 @@ namespace ix
 | 
			
		||||
                                connectionState)));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    size_t SocketServer::getConnectionsThreadsCount()
 | 
			
		||||
    {
 | 
			
		||||
        std::lock_guard<std::mutex> lock(_connectionsThreadsMutex);
 | 
			
		||||
        return _connectionsThreads.size();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void SocketServer::runGC()
 | 
			
		||||
    {
 | 
			
		||||
        for (;;)
 | 
			
		||||
        {
 | 
			
		||||
            // Garbage collection to shutdown/join threads for closed connections.
 | 
			
		||||
            closeTerminatedThreads();
 | 
			
		||||
 | 
			
		||||
            // We quit this thread if all connections are closed and we received
 | 
			
		||||
            // a stop request by setting _stopGc to true.
 | 
			
		||||
            if (_stopGc && getConnectionsThreadsCount() == 0)
 | 
			
		||||
            {
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Sleep a little bit then keep cleaning up
 | 
			
		||||
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -74,12 +74,6 @@ namespace ix
 | 
			
		||||
        // background thread to wait for incoming connections
 | 
			
		||||
        std::atomic<bool> _stop;
 | 
			
		||||
        std::thread _thread;
 | 
			
		||||
        void run();
 | 
			
		||||
 | 
			
		||||
        // background thread to cleanup (join) terminated threads
 | 
			
		||||
        std::atomic<bool> _stopGc;
 | 
			
		||||
        std::thread _gcThread;
 | 
			
		||||
        void runGC();
 | 
			
		||||
 | 
			
		||||
        // the list of (connectionState, threads) for each connections
 | 
			
		||||
        ConnectionThreads _connectionsThreads;
 | 
			
		||||
@@ -93,12 +87,13 @@ namespace ix
 | 
			
		||||
        // the factory to create ConnectionState objects
 | 
			
		||||
        ConnectionStateFactory _connectionStateFactory;
 | 
			
		||||
 | 
			
		||||
        // Methods
 | 
			
		||||
        void run();
 | 
			
		||||
        virtual void handleConnection(int fd,
 | 
			
		||||
                                      std::shared_ptr<ConnectionState> connectionState) = 0;
 | 
			
		||||
        virtual size_t getConnectedClientsCount() = 0;
 | 
			
		||||
 | 
			
		||||
        // Returns true if all connection threads are joined
 | 
			
		||||
        void closeTerminatedThreads();
 | 
			
		||||
        size_t getConnectionsThreadsCount();
 | 
			
		||||
        bool closeTerminatedThreads();
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,8 @@
 | 
			
		||||
#include "IXUrlParser.h"
 | 
			
		||||
#include "LUrlParser.h"
 | 
			
		||||
 | 
			
		||||
#include <iostream>
 | 
			
		||||
 | 
			
		||||
namespace ix
 | 
			
		||||
{
 | 
			
		||||
    bool UrlParser::parse(const std::string& url,
 | 
			
		||||
@@ -64,4 +66,22 @@ namespace ix
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void UrlParser::printUrl(const std::string& url)
 | 
			
		||||
    {
 | 
			
		||||
        std::string protocol, host, path, query;
 | 
			
		||||
        int port {0};
 | 
			
		||||
 | 
			
		||||
        if (!parse(url, protocol, host, path, query, port))
 | 
			
		||||
        {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        std::cout << "[" << url << "]" << std::endl;
 | 
			
		||||
        std::cout << protocol << std::endl;
 | 
			
		||||
        std::cout << host << std::endl;
 | 
			
		||||
        std::cout << port << std::endl;
 | 
			
		||||
        std::cout << path << std::endl;
 | 
			
		||||
        std::cout << query << std::endl;
 | 
			
		||||
        std::cout << "-------------------------------" << std::endl;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -19,5 +19,7 @@ namespace ix
 | 
			
		||||
                          std::string& path,
 | 
			
		||||
                          std::string& query,
 | 
			
		||||
                          int& port);
 | 
			
		||||
 | 
			
		||||
        static void printUrl(const std::string& url);
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -51,7 +51,7 @@ namespace ix
 | 
			
		||||
        _ws.setOnCloseCallback(
 | 
			
		||||
            [this](uint16_t code, const std::string& reason, size_t wireSize, bool remote)
 | 
			
		||||
            {
 | 
			
		||||
                _onMessageCallback(WebSocketMessageType::Close, "", wireSize,
 | 
			
		||||
                _onMessageCallback(WebSocket_MessageType_Close, "", wireSize,
 | 
			
		||||
                                   WebSocketErrorInfo(), WebSocketOpenInfo(),
 | 
			
		||||
                                   WebSocketCloseInfo(code, reason, remote));
 | 
			
		||||
            }
 | 
			
		||||
@@ -144,16 +144,24 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
    void WebSocket::stop()
 | 
			
		||||
    {
 | 
			
		||||
        bool automaticReconnection = _automaticReconnection;
 | 
			
		||||
 | 
			
		||||
        // This value needs to be forced when shutting down, it is restored later
 | 
			
		||||
        _automaticReconnection = false;
 | 
			
		||||
 | 
			
		||||
        close();
 | 
			
		||||
 | 
			
		||||
        if (_thread.joinable())
 | 
			
		||||
        if (!_thread.joinable())
 | 
			
		||||
        {
 | 
			
		||||
            // wait until working thread will exit
 | 
			
		||||
            // it will exit after close operation is finished
 | 
			
		||||
            _stop = true;
 | 
			
		||||
            _thread.join();
 | 
			
		||||
            _stop = false;
 | 
			
		||||
            _automaticReconnection = automaticReconnection;
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        _stop = true;
 | 
			
		||||
        _thread.join();
 | 
			
		||||
        _stop = false;
 | 
			
		||||
 | 
			
		||||
        _automaticReconnection = automaticReconnection;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    WebSocketInitResult WebSocket::connect(int timeoutSecs)
 | 
			
		||||
@@ -172,7 +180,7 @@ namespace ix
 | 
			
		||||
            return status;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        _onMessageCallback(WebSocketMessageType::Open, "", 0,
 | 
			
		||||
        _onMessageCallback(WebSocket_MessageType_Open, "", 0,
 | 
			
		||||
                           WebSocketErrorInfo(),
 | 
			
		||||
                           WebSocketOpenInfo(status.uri, status.headers),
 | 
			
		||||
                           WebSocketCloseInfo());
 | 
			
		||||
@@ -195,7 +203,7 @@ namespace ix
 | 
			
		||||
            return status;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        _onMessageCallback(WebSocketMessageType::Open, "", 0,
 | 
			
		||||
        _onMessageCallback(WebSocket_MessageType_Open, "", 0,
 | 
			
		||||
                           WebSocketErrorInfo(),
 | 
			
		||||
                           WebSocketOpenInfo(status.uri, status.headers),
 | 
			
		||||
                           WebSocketCloseInfo());
 | 
			
		||||
@@ -204,12 +212,18 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
    bool WebSocket::isConnected() const
 | 
			
		||||
    {
 | 
			
		||||
        return getReadyState() == ReadyState::Open;
 | 
			
		||||
        return getReadyState() == WebSocket_ReadyState_Open;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool WebSocket::isClosing() const
 | 
			
		||||
    {
 | 
			
		||||
        return getReadyState() == ReadyState::Closing;
 | 
			
		||||
        return getReadyState() == WebSocket_ReadyState_Closing;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool WebSocket::isConnectedOrClosing() const
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        return isConnected() || isClosing();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void WebSocket::close(uint16_t code,
 | 
			
		||||
@@ -218,57 +232,62 @@ namespace ix
 | 
			
		||||
        _ws.close(code, reason);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void WebSocket::checkConnection(bool firstConnectionAttempt)
 | 
			
		||||
    void WebSocket::reconnectPerpetuallyIfDisconnected()
 | 
			
		||||
    {
 | 
			
		||||
        using millis = std::chrono::duration<double, std::milli>;
 | 
			
		||||
 | 
			
		||||
        uint32_t retries = 0;
 | 
			
		||||
        WebSocketErrorInfo connectErr;
 | 
			
		||||
        ix::WebSocketInitResult status;
 | 
			
		||||
        using millis = std::chrono::duration<double, std::milli>;
 | 
			
		||||
        millis duration;
 | 
			
		||||
 | 
			
		||||
        // Try to connect perpertually
 | 
			
		||||
        while (true)
 | 
			
		||||
        // Try to connect only once when we don't have automaticReconnection setup
 | 
			
		||||
        if (!isConnectedOrClosing() && !_stop && !_automaticReconnection)
 | 
			
		||||
        {
 | 
			
		||||
            if (isConnected() || isClosing() || _stop)
 | 
			
		||||
            {
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (!firstConnectionAttempt && !_automaticReconnection)
 | 
			
		||||
            {
 | 
			
		||||
                // Do not attempt to reconnect
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            firstConnectionAttempt = false;
 | 
			
		||||
 | 
			
		||||
            // Only sleep if we are retrying
 | 
			
		||||
            if (duration.count() > 0)
 | 
			
		||||
            {
 | 
			
		||||
                // to do: make sleeping conditional
 | 
			
		||||
                std::this_thread::sleep_for(duration);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Try to connect synchronously
 | 
			
		||||
            ix::WebSocketInitResult status = connect(_handshakeTimeoutSecs);
 | 
			
		||||
            status = connect(_handshakeTimeoutSecs);
 | 
			
		||||
 | 
			
		||||
            if (!status.success)
 | 
			
		||||
            {
 | 
			
		||||
                WebSocketErrorInfo connectErr;
 | 
			
		||||
                duration = millis(calculateRetryWaitMilliseconds(retries++));
 | 
			
		||||
 | 
			
		||||
                if (_automaticReconnection)
 | 
			
		||||
                connectErr.retries = retries;
 | 
			
		||||
                connectErr.wait_time = duration.count();
 | 
			
		||||
                connectErr.reason = status.errorStr;
 | 
			
		||||
                connectErr.http_status = status.http_status;
 | 
			
		||||
                _onMessageCallback(WebSocket_MessageType_Error, "", 0,
 | 
			
		||||
                                   connectErr, WebSocketOpenInfo(),
 | 
			
		||||
                                   WebSocketCloseInfo());
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            // Otherwise try to reconnect perpertually
 | 
			
		||||
            while (true)
 | 
			
		||||
            {
 | 
			
		||||
                if (isConnectedOrClosing() || _stop || !_automaticReconnection)
 | 
			
		||||
                {
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                status = connect(_handshakeTimeoutSecs);
 | 
			
		||||
 | 
			
		||||
                if (!status.success)
 | 
			
		||||
                {
 | 
			
		||||
                    duration = millis(calculateRetryWaitMilliseconds(retries++));
 | 
			
		||||
 | 
			
		||||
                    connectErr.wait_time = duration.count();
 | 
			
		||||
                    connectErr.retries = retries;
 | 
			
		||||
                }
 | 
			
		||||
                
 | 
			
		||||
                connectErr.reason      = status.errorStr;
 | 
			
		||||
                connectErr.http_status = status.http_status;
 | 
			
		||||
                    connectErr.wait_time = duration.count();
 | 
			
		||||
                    connectErr.reason = status.errorStr;
 | 
			
		||||
                    connectErr.http_status = status.http_status;
 | 
			
		||||
                    _onMessageCallback(WebSocket_MessageType_Error, "", 0,
 | 
			
		||||
                                       connectErr, WebSocketOpenInfo(),
 | 
			
		||||
                                       WebSocketCloseInfo());
 | 
			
		||||
 | 
			
		||||
                _onMessageCallback(WebSocketMessageType::Error, "", 0,
 | 
			
		||||
                                   connectErr, WebSocketOpenInfo(),
 | 
			
		||||
                                   WebSocketCloseInfo());
 | 
			
		||||
                    // Only sleep if we aren't in the middle of stopping
 | 
			
		||||
                    if (!_stop)
 | 
			
		||||
                    {
 | 
			
		||||
                        std::this_thread::sleep_for(duration);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@@ -277,27 +296,19 @@ namespace ix
 | 
			
		||||
    {
 | 
			
		||||
        setThreadName(getUrl());
 | 
			
		||||
 | 
			
		||||
        bool firstConnectionAttempt = true;
 | 
			
		||||
 | 
			
		||||
        while (true)
 | 
			
		||||
        {
 | 
			
		||||
            if (_stop && !isClosing()) return;
 | 
			
		||||
 | 
			
		||||
            // 1. Make sure we are always connected
 | 
			
		||||
            checkConnection(firstConnectionAttempt);
 | 
			
		||||
 | 
			
		||||
            firstConnectionAttempt = false;
 | 
			
		||||
 | 
			
		||||
            // if here we are closed then checkConnection was not able to connect
 | 
			
		||||
            if (getReadyState() == ReadyState::Closed)
 | 
			
		||||
            {
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            reconnectPerpetuallyIfDisconnected();
 | 
			
		||||
 | 
			
		||||
            // 2. Poll to see if there's any new data available
 | 
			
		||||
            WebSocketTransport::PollResult pollResult = _ws.poll();
 | 
			
		||||
            WebSocketTransport::PollPostTreatment pollPostTreatment = _ws.poll();
 | 
			
		||||
 | 
			
		||||
            // 3. Dispatch the incoming messages
 | 
			
		||||
            _ws.dispatch(
 | 
			
		||||
                pollResult,
 | 
			
		||||
                pollPostTreatment,
 | 
			
		||||
                [this](const std::string& msg,
 | 
			
		||||
                       size_t wireSize,
 | 
			
		||||
                       bool decompressionError,
 | 
			
		||||
@@ -306,25 +317,24 @@ namespace ix
 | 
			
		||||
                    WebSocketMessageType webSocketMessageType;
 | 
			
		||||
                    switch (messageKind)
 | 
			
		||||
                    {
 | 
			
		||||
                        default:
 | 
			
		||||
                        case WebSocketTransport::MessageKind::MSG:
 | 
			
		||||
                        case WebSocketTransport::MSG:
 | 
			
		||||
                        {
 | 
			
		||||
                            webSocketMessageType = WebSocketMessageType::Message;
 | 
			
		||||
                            webSocketMessageType = WebSocket_MessageType_Message;
 | 
			
		||||
                        } break;
 | 
			
		||||
 | 
			
		||||
                        case WebSocketTransport::MessageKind::PING:
 | 
			
		||||
                        case WebSocketTransport::PING:
 | 
			
		||||
                        {
 | 
			
		||||
                            webSocketMessageType = WebSocketMessageType::Ping;
 | 
			
		||||
                            webSocketMessageType = WebSocket_MessageType_Ping;
 | 
			
		||||
                        } break;
 | 
			
		||||
 | 
			
		||||
                        case WebSocketTransport::MessageKind::PONG:
 | 
			
		||||
                        case WebSocketTransport::PONG:
 | 
			
		||||
                        {
 | 
			
		||||
                            webSocketMessageType = WebSocketMessageType::Pong;
 | 
			
		||||
                            webSocketMessageType = WebSocket_MessageType_Pong;
 | 
			
		||||
                        } break;
 | 
			
		||||
 | 
			
		||||
                        case WebSocketTransport::MessageKind::FRAGMENT:
 | 
			
		||||
                        case WebSocketTransport::FRAGMENT:
 | 
			
		||||
                        {
 | 
			
		||||
                            webSocketMessageType = WebSocketMessageType::Fragment;
 | 
			
		||||
                            webSocketMessageType = WebSocket_MessageType_Fragment;
 | 
			
		||||
                        } break;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
@@ -337,6 +347,9 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
                    WebSocket::invokeTrafficTrackerCallback(msg.size(), true);
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            // If we aren't trying to reconnect automatically, exit if we aren't connected
 | 
			
		||||
            if (!isConnectedOrClosing() && !_automaticReconnection) return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -363,10 +376,10 @@ namespace ix
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    WebSocketSendInfo WebSocket::send(const std::string& data,
 | 
			
		||||
    WebSocketSendInfo WebSocket::send(const std::string& text,
 | 
			
		||||
                                      const OnProgressCallback& onProgressCallback)
 | 
			
		||||
    {
 | 
			
		||||
        return sendMessage(data, SendMessageKind::Binary, onProgressCallback);
 | 
			
		||||
        return sendMessage(text, SendMessageKind::Binary, onProgressCallback);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    WebSocketSendInfo WebSocket::sendText(const std::string& text,
 | 
			
		||||
@@ -429,11 +442,11 @@ namespace ix
 | 
			
		||||
    {
 | 
			
		||||
        switch (_ws.getReadyState())
 | 
			
		||||
        {
 | 
			
		||||
            case ix::WebSocketTransport::ReadyState::OPEN      : return ReadyState::Open;
 | 
			
		||||
            case ix::WebSocketTransport::ReadyState::CONNECTING: return ReadyState::Connecting;
 | 
			
		||||
            case ix::WebSocketTransport::ReadyState::CLOSING   : return ReadyState::Closing;
 | 
			
		||||
            case ix::WebSocketTransport::ReadyState::CLOSED    : return ReadyState::Closed;
 | 
			
		||||
            default: return ReadyState::Closed;
 | 
			
		||||
            case ix::WebSocketTransport::OPEN: return WebSocket_ReadyState_Open;
 | 
			
		||||
            case ix::WebSocketTransport::CONNECTING: return WebSocket_ReadyState_Connecting;
 | 
			
		||||
            case ix::WebSocketTransport::CLOSING: return WebSocket_ReadyState_Closing;
 | 
			
		||||
            case ix::WebSocketTransport::CLOSED: return WebSocket_ReadyState_Closed;
 | 
			
		||||
            default: return WebSocket_ReadyState_Closed;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -441,11 +454,11 @@ namespace ix
 | 
			
		||||
    {
 | 
			
		||||
        switch (readyState)
 | 
			
		||||
        {
 | 
			
		||||
            case ReadyState::Open      : return "OPEN";
 | 
			
		||||
            case ReadyState::Connecting: return "CONNECTING";
 | 
			
		||||
            case ReadyState::Closing   : return "CLOSING";
 | 
			
		||||
            case ReadyState::Closed    : return "CLOSED";
 | 
			
		||||
            default: return "UNKNOWN";
 | 
			
		||||
            case WebSocket_ReadyState_Open: return "OPEN";
 | 
			
		||||
            case WebSocket_ReadyState_Connecting: return "CONNECTING";
 | 
			
		||||
            case WebSocket_ReadyState_Closing: return "CLOSING";
 | 
			
		||||
            case WebSocket_ReadyState_Closed: return "CLOSED";
 | 
			
		||||
            default: return "CLOSED";
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -24,23 +24,23 @@
 | 
			
		||||
namespace ix
 | 
			
		||||
{
 | 
			
		||||
    // https://developer.mozilla.org/en-US/docs/Web/API/WebSocket#Ready_state_constants
 | 
			
		||||
    enum class ReadyState
 | 
			
		||||
    enum ReadyState
 | 
			
		||||
    {
 | 
			
		||||
        Connecting     = 0,
 | 
			
		||||
        Open           = 1,
 | 
			
		||||
        Closing        = 2,
 | 
			
		||||
        Closed         = 3
 | 
			
		||||
        WebSocket_ReadyState_Connecting = 0,
 | 
			
		||||
        WebSocket_ReadyState_Open = 1,
 | 
			
		||||
        WebSocket_ReadyState_Closing = 2,
 | 
			
		||||
        WebSocket_ReadyState_Closed = 3
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    enum class WebSocketMessageType
 | 
			
		||||
    enum WebSocketMessageType
 | 
			
		||||
    {
 | 
			
		||||
        Message        = 0,
 | 
			
		||||
        Open           = 1,
 | 
			
		||||
        Close          = 2,
 | 
			
		||||
        Error          = 3,
 | 
			
		||||
        Ping           = 4,
 | 
			
		||||
        Pong           = 5,
 | 
			
		||||
        Fragment       = 6
 | 
			
		||||
        WebSocket_MessageType_Message = 0,
 | 
			
		||||
        WebSocket_MessageType_Open = 1,
 | 
			
		||||
        WebSocket_MessageType_Close = 2,
 | 
			
		||||
        WebSocket_MessageType_Error = 3,
 | 
			
		||||
        WebSocket_MessageType_Ping = 4,
 | 
			
		||||
        WebSocket_MessageType_Pong = 5,
 | 
			
		||||
        WebSocket_MessageType_Fragment = 6
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    struct WebSocketOpenInfo
 | 
			
		||||
@@ -91,6 +91,7 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
        void setUrl(const std::string& url);
 | 
			
		||||
        void setPerMessageDeflateOptions(const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions);
 | 
			
		||||
        void setHandshakeTimeout(int handshakeTimeoutSecs);
 | 
			
		||||
        void setHeartBeatPeriod(int heartBeatPeriodSecs);
 | 
			
		||||
        void setPingInterval(int pingIntervalSecs); // alias of setHeartBeatPeriod
 | 
			
		||||
        void setPingTimeout(int pingTimeoutSecs);
 | 
			
		||||
@@ -99,15 +100,13 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
        // Run asynchronously, by calling start and stop.
 | 
			
		||||
        void start();
 | 
			
		||||
        // stop is synchronous
 | 
			
		||||
        void stop();
 | 
			
		||||
 | 
			
		||||
        // Run in blocking mode, by connecting first manually, and then calling run.
 | 
			
		||||
        WebSocketInitResult connect(int timeoutSecs);
 | 
			
		||||
        void run();
 | 
			
		||||
 | 
			
		||||
        // send binary data
 | 
			
		||||
        WebSocketSendInfo send(const std::string& data,
 | 
			
		||||
        WebSocketSendInfo send(const std::string& text,
 | 
			
		||||
                               const OnProgressCallback& onProgressCallback = nullptr);
 | 
			
		||||
        WebSocketSendInfo sendText(const std::string& text,
 | 
			
		||||
                                   const OnProgressCallback& onProgressCallback = nullptr);
 | 
			
		||||
@@ -123,8 +122,6 @@ namespace ix
 | 
			
		||||
        static void resetTrafficTrackerCallback();
 | 
			
		||||
 | 
			
		||||
        ReadyState getReadyState() const;
 | 
			
		||||
        static std::string readyStateToString(ReadyState readyState);
 | 
			
		||||
 | 
			
		||||
        const std::string& getUrl() const;
 | 
			
		||||
        const WebSocketPerMessageDeflateOptions& getPerMessageDeflateOptions() const;
 | 
			
		||||
        int getHeartBeatPeriod() const;
 | 
			
		||||
@@ -143,10 +140,13 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
        bool isConnected() const;
 | 
			
		||||
        bool isClosing() const;
 | 
			
		||||
        void checkConnection(bool firstConnectionAttempt);
 | 
			
		||||
        bool isConnectedOrClosing() const;
 | 
			
		||||
        void reconnectPerpetuallyIfDisconnected();
 | 
			
		||||
        std::string readyStateToString(ReadyState readyState);
 | 
			
		||||
        static void invokeTrafficTrackerCallback(size_t size, bool incoming);
 | 
			
		||||
 | 
			
		||||
        // Server
 | 
			
		||||
        void setSocketFileDescriptor(int fd);
 | 
			
		||||
        WebSocketInitResult connectToSocket(int fd, int timeoutSecs);
 | 
			
		||||
 | 
			
		||||
        WebSocketTransport _ws;
 | 
			
		||||
 
 | 
			
		||||
@@ -12,10 +12,10 @@ namespace ix
 | 
			
		||||
{
 | 
			
		||||
    struct WebSocketErrorInfo
 | 
			
		||||
    {
 | 
			
		||||
        uint32_t retries = 0;
 | 
			
		||||
        double wait_time = 0;
 | 
			
		||||
        int http_status = 0;
 | 
			
		||||
        uint32_t retries;
 | 
			
		||||
        double wait_time;
 | 
			
		||||
        int http_status;
 | 
			
		||||
        std::string reason;
 | 
			
		||||
        bool decompressionError = false;
 | 
			
		||||
        bool decompressionError;
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -23,6 +23,7 @@ namespace ix
 | 
			
		||||
        WebSocketPerMessageDeflateOptions(std::string extension);
 | 
			
		||||
 | 
			
		||||
        std::string generateHeader();
 | 
			
		||||
        std::string parseHeader();
 | 
			
		||||
        bool enabled() const;
 | 
			
		||||
        bool getClientNoContextTakeover() const;
 | 
			
		||||
        bool getServerNoContextTakeover() const;
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,9 @@
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
 | 
			
		||||
namespace ix
 | 
			
		||||
{
 | 
			
		||||
    struct WebSocketSendInfo
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,7 @@ namespace ix
 | 
			
		||||
    using OnConnectionCallback = std::function<void(std::shared_ptr<WebSocket>,
 | 
			
		||||
                                                    std::shared_ptr<ConnectionState>)>;
 | 
			
		||||
 | 
			
		||||
    class WebSocketServer final : public SocketServer {
 | 
			
		||||
    class WebSocketServer : public SocketServer {
 | 
			
		||||
    public:
 | 
			
		||||
        WebSocketServer(int port = SocketServer::kDefaultPort,
 | 
			
		||||
                        const std::string& host = SocketServer::kDefaultHost,
 | 
			
		||||
 
 | 
			
		||||
@@ -86,7 +86,7 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
    WebSocketTransport::WebSocketTransport() :
 | 
			
		||||
        _useMask(true),
 | 
			
		||||
        _readyState(ReadyState::CLOSED),
 | 
			
		||||
        _readyState(CLOSED),
 | 
			
		||||
        _closeCode(kInternalErrorCode),
 | 
			
		||||
        _closeReason(kInternalErrorMessage),
 | 
			
		||||
        _closeWireSize(0),
 | 
			
		||||
@@ -134,6 +134,11 @@ namespace ix
 | 
			
		||||
        {
 | 
			
		||||
            _pingIntervalOrTimeoutGCDSecs = pingIntervalSecs;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (_pingIntervalOrTimeoutGCDSecs > 0)
 | 
			
		||||
        {
 | 
			
		||||
            _nextGCDTimePoint = std::chrono::steady_clock::now() + std::chrono::seconds(_pingIntervalOrTimeoutGCDSecs);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Client
 | 
			
		||||
@@ -168,7 +173,7 @@ namespace ix
 | 
			
		||||
                                                         timeoutSecs);
 | 
			
		||||
        if (result.success)
 | 
			
		||||
        {
 | 
			
		||||
            setReadyState(ReadyState::OPEN);
 | 
			
		||||
            setReadyState(OPEN);
 | 
			
		||||
        }
 | 
			
		||||
        return result;
 | 
			
		||||
    }
 | 
			
		||||
@@ -196,22 +201,22 @@ namespace ix
 | 
			
		||||
        auto result = webSocketHandshake.serverHandshake(fd, timeoutSecs);
 | 
			
		||||
        if (result.success)
 | 
			
		||||
        {
 | 
			
		||||
            setReadyState(ReadyState::OPEN);
 | 
			
		||||
            setReadyState(OPEN);
 | 
			
		||||
        }
 | 
			
		||||
        return result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    WebSocketTransport::ReadyState WebSocketTransport::getReadyState() const
 | 
			
		||||
    WebSocketTransport::ReadyStateValues WebSocketTransport::getReadyState() const
 | 
			
		||||
    {
 | 
			
		||||
        return _readyState;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void WebSocketTransport::setReadyState(ReadyState readyState)
 | 
			
		||||
    void WebSocketTransport::setReadyState(ReadyStateValues readyStateValue)
 | 
			
		||||
    {
 | 
			
		||||
        // No state change, return
 | 
			
		||||
        if (_readyState == readyState) return;
 | 
			
		||||
        if (_readyState == readyStateValue) return;
 | 
			
		||||
 | 
			
		||||
        if (readyState == ReadyState::CLOSED)
 | 
			
		||||
        if (readyStateValue == CLOSED)
 | 
			
		||||
        {
 | 
			
		||||
            std::lock_guard<std::mutex> lock(_closeDataMutex);
 | 
			
		||||
            _onCloseCallback(_closeCode, _closeReason, _closeWireSize, _closeRemote);
 | 
			
		||||
@@ -220,12 +225,8 @@ namespace ix
 | 
			
		||||
            _closeWireSize = 0;
 | 
			
		||||
            _closeRemote = false;
 | 
			
		||||
        }
 | 
			
		||||
        else if (readyState == ReadyState::OPEN)
 | 
			
		||||
        {
 | 
			
		||||
            initTimePointsAndGCDAfterConnect();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        _readyState = readyState;
 | 
			
		||||
        _readyState = readyStateValue;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void WebSocketTransport::setOnCloseCallback(const OnCloseCallback& onCloseCallback)
 | 
			
		||||
@@ -233,23 +234,6 @@ namespace ix
 | 
			
		||||
        _onCloseCallback = onCloseCallback;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void WebSocketTransport::initTimePointsAndGCDAfterConnect()
 | 
			
		||||
    {
 | 
			
		||||
        {
 | 
			
		||||
            std::lock_guard<std::mutex> lock(_lastSendPingTimePointMutex);
 | 
			
		||||
            _lastSendPingTimePoint = std::chrono::steady_clock::now();
 | 
			
		||||
        } 
 | 
			
		||||
        {
 | 
			
		||||
            std::lock_guard<std::mutex> lock(_lastReceivePongTimePointMutex);
 | 
			
		||||
            _lastReceivePongTimePoint = std::chrono::steady_clock::now();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (_pingIntervalOrTimeoutGCDSecs > 0)
 | 
			
		||||
        {
 | 
			
		||||
            _nextGCDTimePoint = std::chrono::steady_clock::now() + std::chrono::seconds(_pingIntervalOrTimeoutGCDSecs);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Only consider send PING time points for that computation.
 | 
			
		||||
    bool WebSocketTransport::pingIntervalExceeded()
 | 
			
		||||
    {
 | 
			
		||||
@@ -278,9 +262,9 @@ namespace ix
 | 
			
		||||
        return now - _closingTimePoint > std::chrono::milliseconds(kClosingMaximumWaitingDelayInMs);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    WebSocketTransport::PollResult WebSocketTransport::poll()
 | 
			
		||||
    WebSocketTransport::PollPostTreatment WebSocketTransport::poll()
 | 
			
		||||
    {
 | 
			
		||||
        if (_readyState == ReadyState::OPEN)
 | 
			
		||||
        if (_readyState == OPEN)
 | 
			
		||||
        {
 | 
			
		||||
            // if (1) ping timeout is enabled and (2) duration since last received
 | 
			
		||||
            // ping response (PONG) exceeds the maximum delay, then close the connection
 | 
			
		||||
@@ -300,7 +284,7 @@ namespace ix
 | 
			
		||||
        
 | 
			
		||||
        // No timeout if state is not OPEN, otherwise computed
 | 
			
		||||
        // pingIntervalOrTimeoutGCD (equals to -1 if no ping and no ping timeout are set)
 | 
			
		||||
        int lastingTimeoutDelayInMs = (_readyState != ReadyState::OPEN) ? 0 : _pingIntervalOrTimeoutGCDSecs;
 | 
			
		||||
        int lastingTimeoutDelayInMs = (_readyState != OPEN) ? 0 : _pingIntervalOrTimeoutGCDSecs;
 | 
			
		||||
 | 
			
		||||
        if (_pingIntervalOrTimeoutGCDSecs > 0)
 | 
			
		||||
        {
 | 
			
		||||
@@ -319,10 +303,6 @@ namespace ix
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
        if (lastingTimeoutDelayInMs <= 0) lastingTimeoutDelayInMs = 20;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        // poll the socket
 | 
			
		||||
        PollResultType pollResult = _socket->poll(lastingTimeoutDelayInMs);
 | 
			
		||||
 | 
			
		||||
@@ -339,7 +319,7 @@ namespace ix
 | 
			
		||||
                if (result == PollResultType::Error)
 | 
			
		||||
                {
 | 
			
		||||
                    _socket->close();
 | 
			
		||||
                    setReadyState(ReadyState::CLOSED);
 | 
			
		||||
                    setReadyState(CLOSED);
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
                else if (result == PollResultType::ReadyForWrite)
 | 
			
		||||
@@ -365,7 +345,7 @@ namespace ix
 | 
			
		||||
                    
 | 
			
		||||
                    _socket->close();
 | 
			
		||||
 | 
			
		||||
                    return PollResult::AbnormalClose;
 | 
			
		||||
                    return CHECK_OR_RAISE_ABNORMAL_CLOSE_AFTER_DISPATCH;
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
@@ -384,15 +364,15 @@ namespace ix
 | 
			
		||||
            _socket->close();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (_readyState == ReadyState::CLOSING && closingDelayExceeded())
 | 
			
		||||
        if (_readyState == CLOSING && closingDelayExceeded())
 | 
			
		||||
        {
 | 
			
		||||
            _rxbuf.clear();
 | 
			
		||||
            // close code and reason were set when calling close()
 | 
			
		||||
            _socket->close();
 | 
			
		||||
            setReadyState(ReadyState::CLOSED);
 | 
			
		||||
            setReadyState(CLOSED);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return PollResult::Succeeded;
 | 
			
		||||
        return NONE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool WebSocketTransport::isSendBufferEmpty() const
 | 
			
		||||
@@ -454,7 +434,7 @@ namespace ix
 | 
			
		||||
    // |                     Payload Data continued ...                |
 | 
			
		||||
    // +---------------------------------------------------------------+
 | 
			
		||||
    //
 | 
			
		||||
    void WebSocketTransport::dispatch(WebSocketTransport::PollResult pollResult,
 | 
			
		||||
    void WebSocketTransport::dispatch(WebSocketTransport::PollPostTreatment pollPostTreatment,
 | 
			
		||||
                                      const OnMessageCallback& onMessageCallback)
 | 
			
		||||
    {
 | 
			
		||||
        while (true)
 | 
			
		||||
@@ -541,7 +521,7 @@ namespace ix
 | 
			
		||||
                //
 | 
			
		||||
                if (ws.fin && _chunks.empty())
 | 
			
		||||
                {
 | 
			
		||||
                    emitMessage(MessageKind::MSG,
 | 
			
		||||
                    emitMessage(MSG,
 | 
			
		||||
                                std::string(_rxbuf.begin()+ws.header_size,
 | 
			
		||||
                                            _rxbuf.begin()+ws.header_size+(size_t) ws.N),
 | 
			
		||||
                                ws,
 | 
			
		||||
@@ -561,12 +541,12 @@ namespace ix
 | 
			
		||||
                                             _rxbuf.begin()+ws.header_size+(size_t)ws.N));
 | 
			
		||||
                    if (ws.fin)
 | 
			
		||||
                    {
 | 
			
		||||
                        emitMessage(MessageKind::MSG, getMergedChunks(), ws, onMessageCallback);
 | 
			
		||||
                        emitMessage(MSG, getMergedChunks(), ws, onMessageCallback);
 | 
			
		||||
                        _chunks.clear();
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        emitMessage(MessageKind::FRAGMENT, std::string(), ws, onMessageCallback);
 | 
			
		||||
                        emitMessage(FRAGMENT, std::string(), ws, onMessageCallback);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@@ -584,7 +564,7 @@ namespace ix
 | 
			
		||||
                    sendData(wsheader_type::PONG, pingData, compress);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                emitMessage(MessageKind::PING, pingData, ws, onMessageCallback);
 | 
			
		||||
                emitMessage(PING, pingData, ws, onMessageCallback);
 | 
			
		||||
            }
 | 
			
		||||
            else if (ws.opcode == wsheader_type::PONG)
 | 
			
		||||
            {
 | 
			
		||||
@@ -595,7 +575,7 @@ namespace ix
 | 
			
		||||
                std::lock_guard<std::mutex> lck(_lastReceivePongTimePointMutex);
 | 
			
		||||
                _lastReceivePongTimePoint = std::chrono::steady_clock::now();
 | 
			
		||||
 | 
			
		||||
                emitMessage(MessageKind::PONG, pongData, ws, onMessageCallback);
 | 
			
		||||
                emitMessage(PONG, pongData, ws, onMessageCallback);
 | 
			
		||||
            }
 | 
			
		||||
            else if (ws.opcode == wsheader_type::CLOSE)
 | 
			
		||||
            {
 | 
			
		||||
@@ -625,7 +605,7 @@ namespace ix
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // We receive a CLOSE frame from remote and are NOT the ones who triggered the close
 | 
			
		||||
                if (_readyState != ReadyState::CLOSING)
 | 
			
		||||
                if (_readyState != CLOSING)
 | 
			
		||||
                {
 | 
			
		||||
                    // send back the CLOSE frame
 | 
			
		||||
                    sendCloseFrame(code, reason);
 | 
			
		||||
@@ -666,18 +646,18 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
        // if an abnormal closure was raised in poll, and nothing else triggered a CLOSED state in
 | 
			
		||||
        // the received and processed data then close the connection
 | 
			
		||||
        if (pollResult == PollResult::AbnormalClose)
 | 
			
		||||
        if (pollPostTreatment == CHECK_OR_RAISE_ABNORMAL_CLOSE_AFTER_DISPATCH)
 | 
			
		||||
        {
 | 
			
		||||
            _rxbuf.clear();
 | 
			
		||||
 | 
			
		||||
            // if we previously closed the connection (CLOSING state), then set state to CLOSED (code/reason were set before)
 | 
			
		||||
            if (_readyState == ReadyState::CLOSING)
 | 
			
		||||
            if (_readyState == CLOSING)
 | 
			
		||||
            {
 | 
			
		||||
                _socket->close();
 | 
			
		||||
                setReadyState(ReadyState::CLOSED);
 | 
			
		||||
                setReadyState(CLOSED);
 | 
			
		||||
            }
 | 
			
		||||
            // if we weren't closing, then close using abnormal close code and message 
 | 
			
		||||
            else if (_readyState != ReadyState::CLOSED)
 | 
			
		||||
            else if (_readyState != CLOSED)
 | 
			
		||||
            {
 | 
			
		||||
                closeSocketAndSwitchToClosedState(kAbnormalCloseCode, kAbnormalCloseMessage, 0, false);
 | 
			
		||||
            }
 | 
			
		||||
@@ -712,7 +692,7 @@ namespace ix
 | 
			
		||||
        size_t wireSize = message.size();
 | 
			
		||||
 | 
			
		||||
        // When the RSV1 bit is 1 it means the message is compressed
 | 
			
		||||
        if (_enablePerMessageDeflate && ws.rsv1 && messageKind != MessageKind::FRAGMENT)
 | 
			
		||||
        if (_enablePerMessageDeflate && ws.rsv1 && messageKind != FRAGMENT)
 | 
			
		||||
        {
 | 
			
		||||
            std::string decompressedMessage;
 | 
			
		||||
            bool success = _perMessageDeflate.decompress(message, decompressedMessage);
 | 
			
		||||
@@ -739,7 +719,7 @@ namespace ix
 | 
			
		||||
        bool compress,
 | 
			
		||||
        const OnProgressCallback& onProgressCallback)
 | 
			
		||||
    {
 | 
			
		||||
        if (_readyState != ReadyState::OPEN)
 | 
			
		||||
        if (_readyState == CLOSING || _readyState == CLOSED)
 | 
			
		||||
        {
 | 
			
		||||
            return WebSocketSendInfo();
 | 
			
		||||
        }
 | 
			
		||||
@@ -965,7 +945,7 @@ namespace ix
 | 
			
		||||
            {
 | 
			
		||||
                _socket->close();
 | 
			
		||||
 | 
			
		||||
                setReadyState(ReadyState::CLOSED);
 | 
			
		||||
                setReadyState(CLOSED);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
@@ -1008,14 +988,14 @@ namespace ix
 | 
			
		||||
            _closeWireSize = closeWireSize;
 | 
			
		||||
            _closeRemote = remote;
 | 
			
		||||
        }
 | 
			
		||||
        setReadyState(ReadyState::CLOSED);
 | 
			
		||||
        setReadyState(CLOSED);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void WebSocketTransport::close(uint16_t code, const std::string& reason, size_t closeWireSize, bool remote)
 | 
			
		||||
    {
 | 
			
		||||
        _requestInitCancellation = true;
 | 
			
		||||
 | 
			
		||||
        if (_readyState == ReadyState::CLOSING || _readyState == ReadyState::CLOSED) return;
 | 
			
		||||
        if (_readyState == CLOSING || _readyState == CLOSED) return;
 | 
			
		||||
 | 
			
		||||
        sendCloseFrame(code, reason);
 | 
			
		||||
        {
 | 
			
		||||
@@ -1029,7 +1009,7 @@ namespace ix
 | 
			
		||||
            std::lock_guard<std::mutex> lock(_closingTimePointMutex);
 | 
			
		||||
            _closingTimePoint = std::chrono::steady_clock::now();
 | 
			
		||||
        }
 | 
			
		||||
        setReadyState(ReadyState::CLOSING);
 | 
			
		||||
        setReadyState(CLOSING);
 | 
			
		||||
 | 
			
		||||
        // wake up the poll, but do not close yet
 | 
			
		||||
        _socket->wakeUpFromPoll(Socket::kSendRequest);
 | 
			
		||||
 
 | 
			
		||||
@@ -40,7 +40,7 @@ namespace ix
 | 
			
		||||
    class WebSocketTransport
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        enum class ReadyState
 | 
			
		||||
        enum ReadyStateValues
 | 
			
		||||
        {
 | 
			
		||||
            CLOSING,
 | 
			
		||||
            CLOSED,
 | 
			
		||||
@@ -48,7 +48,7 @@ namespace ix
 | 
			
		||||
            OPEN
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        enum class MessageKind
 | 
			
		||||
        enum MessageKind
 | 
			
		||||
        {
 | 
			
		||||
            MSG,
 | 
			
		||||
            PING,
 | 
			
		||||
@@ -56,10 +56,10 @@ namespace ix
 | 
			
		||||
            FRAGMENT
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        enum class PollResult
 | 
			
		||||
        enum PollPostTreatment
 | 
			
		||||
        {
 | 
			
		||||
            Succeeded,
 | 
			
		||||
            AbnormalClose
 | 
			
		||||
            NONE,
 | 
			
		||||
            CHECK_OR_RAISE_ABNORMAL_CLOSE_AFTER_DISPATCH
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        using OnMessageCallback = std::function<void(const std::string&,
 | 
			
		||||
@@ -84,7 +84,7 @@ namespace ix
 | 
			
		||||
        WebSocketInitResult connectToSocket(int fd,              // Server
 | 
			
		||||
                                            int timeoutSecs);
 | 
			
		||||
 | 
			
		||||
        PollResult poll();
 | 
			
		||||
        PollPostTreatment poll();
 | 
			
		||||
        WebSocketSendInfo sendBinary(const std::string& message,
 | 
			
		||||
                                     const OnProgressCallback& onProgressCallback);
 | 
			
		||||
        WebSocketSendInfo sendText(const std::string& message,
 | 
			
		||||
@@ -96,10 +96,10 @@ namespace ix
 | 
			
		||||
                   size_t closeWireSize = 0,
 | 
			
		||||
                   bool remote = false);
 | 
			
		||||
 | 
			
		||||
        ReadyState getReadyState() const;
 | 
			
		||||
        void setReadyState(ReadyState readyState);
 | 
			
		||||
        ReadyStateValues getReadyState() const;
 | 
			
		||||
        void setReadyState(ReadyStateValues readyStateValue);
 | 
			
		||||
        void setOnCloseCallback(const OnCloseCallback& onCloseCallback);
 | 
			
		||||
        void dispatch(PollResult pollResult,
 | 
			
		||||
        void dispatch(PollPostTreatment pollPostTreatment,
 | 
			
		||||
                      const OnMessageCallback& onMessageCallback);
 | 
			
		||||
        size_t bufferedAmount() const;
 | 
			
		||||
 | 
			
		||||
@@ -113,11 +113,11 @@ namespace ix
 | 
			
		||||
            bool mask;
 | 
			
		||||
            enum opcode_type {
 | 
			
		||||
                CONTINUATION = 0x0,
 | 
			
		||||
                TEXT_FRAME   = 0x1,
 | 
			
		||||
                TEXT_FRAME = 0x1,
 | 
			
		||||
                BINARY_FRAME = 0x2,
 | 
			
		||||
                CLOSE        = 8,
 | 
			
		||||
                PING         = 9,
 | 
			
		||||
                PONG         = 0xa,
 | 
			
		||||
                CLOSE = 8,
 | 
			
		||||
                PING = 9,
 | 
			
		||||
                PONG = 0xa,
 | 
			
		||||
            } opcode;
 | 
			
		||||
            int N0;
 | 
			
		||||
            uint64_t N;
 | 
			
		||||
@@ -153,7 +153,7 @@ namespace ix
 | 
			
		||||
        std::shared_ptr<Socket> _socket;
 | 
			
		||||
 | 
			
		||||
        // Hold the state of the connection (OPEN, CLOSED, etc...)
 | 
			
		||||
        std::atomic<ReadyState> _readyState;
 | 
			
		||||
        std::atomic<ReadyStateValues> _readyState;
 | 
			
		||||
 | 
			
		||||
        OnCloseCallback _onCloseCallback;
 | 
			
		||||
        uint16_t _closeCode;
 | 
			
		||||
@@ -220,8 +220,6 @@ namespace ix
 | 
			
		||||
        // after calling close(), if no CLOSE frame answer is received back from the remote, we should close the connexion
 | 
			
		||||
        bool closingDelayExceeded();
 | 
			
		||||
 | 
			
		||||
        void initTimePointsAndGCDAfterConnect();
 | 
			
		||||
 | 
			
		||||
        void sendCloseFrame(uint16_t code, const std::string& reason);
 | 
			
		||||
 | 
			
		||||
        void closeSocketAndSwitchToClosedState(uint16_t code,
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,7 @@
 | 
			
		||||
 *  Copyright (c) 2019 Machine Zone, Inc. All rights reserved.
 | 
			
		||||
 */
 | 
			
		||||
#include "../IXSetThreadName.h"
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <Windows.h>
 | 
			
		||||
 | 
			
		||||
namespace ix
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										7
									
								
								test/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								test/.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1,10 +1,9 @@
 | 
			
		||||
CMakeCache.txt
 | 
			
		||||
package-lock.json
 | 
			
		||||
CMakeFiles
 | 
			
		||||
ixwebsocket_unittest
 | 
			
		||||
cmake_install.cmake
 | 
			
		||||
CMakeFiles		
 | 
			
		||||
ixwebsocket_unittest	
 | 
			
		||||
cmake_install.cmake	
 | 
			
		||||
node_modules
 | 
			
		||||
ixwebsocket
 | 
			
		||||
Makefile
 | 
			
		||||
build
 | 
			
		||||
ixwebsocket_unittest.xml
 | 
			
		||||
 
 | 
			
		||||
@@ -5,11 +5,12 @@
 | 
			
		||||
cmake_minimum_required (VERSION 3.4.1)
 | 
			
		||||
project (ixwebsocket_unittest)
 | 
			
		||||
 | 
			
		||||
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/../third_party/sanitizers-cmake/cmake" ${CMAKE_MODULE_PATH})
 | 
			
		||||
find_package(Sanitizers)
 | 
			
		||||
 | 
			
		||||
set (CMAKE_CXX_STANDARD 14)
 | 
			
		||||
 | 
			
		||||
if (UNIX)
 | 
			
		||||
  set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/../third_party/sanitizers-cmake/cmake" ${CMAKE_MODULE_PATH})
 | 
			
		||||
  find_package(Sanitizers)
 | 
			
		||||
if (NOT WIN32)
 | 
			
		||||
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread")
 | 
			
		||||
  set(CMAKE_LD_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread")
 | 
			
		||||
  option(USE_TLS "Add TLS support" ON)
 | 
			
		||||
@@ -38,24 +39,18 @@ set (SOURCES
 | 
			
		||||
  IXWebSocketPingTest.cpp
 | 
			
		||||
  IXWebSocketTestConnectionDisconnection.cpp
 | 
			
		||||
  IXUrlParserTest.cpp
 | 
			
		||||
  IXWebSocketServerTest.cpp
 | 
			
		||||
  IXWebSocketPingTest.cpp
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
# Some unittest don't work on windows yet
 | 
			
		||||
if (UNIX)
 | 
			
		||||
if (NOT WIN32)
 | 
			
		||||
  list(APPEND SOURCES
 | 
			
		||||
    # IXWebSocketPingTimeoutTest.cpp # This test isn't reliable # (multiple platforms), disabling in master
 | 
			
		||||
    # IXWebSocketCloseTest.cpp       # 
 | 
			
		||||
    IXWebSocketPingTimeoutTest.cpp
 | 
			
		||||
    cmd_websocket_chat.cpp
 | 
			
		||||
  )
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
add_executable(ixwebsocket_unittest ${SOURCES})
 | 
			
		||||
 | 
			
		||||
if (UNIX)
 | 
			
		||||
  add_sanitizers(ixwebsocket_unittest)
 | 
			
		||||
endif()
 | 
			
		||||
add_sanitizers(ixwebsocket_unittest)
 | 
			
		||||
 | 
			
		||||
if (APPLE AND USE_TLS)
 | 
			
		||||
    target_link_libraries(ixwebsocket_unittest "-framework foundation" "-framework security")
 | 
			
		||||
 
 | 
			
		||||
@@ -27,6 +27,15 @@ namespace ix
 | 
			
		||||
    struct Logger
 | 
			
		||||
    {
 | 
			
		||||
        public:
 | 
			
		||||
            Logger& operator<<(const std::string& msg)
 | 
			
		||||
            {
 | 
			
		||||
                std::lock_guard<std::mutex> lock(_mutex);
 | 
			
		||||
 | 
			
		||||
                std::cerr << msg;
 | 
			
		||||
                std::cerr << std::endl;
 | 
			
		||||
                return *this;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            template <typename T>
 | 
			
		||||
            Logger& operator<<(T const& obj)
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
@@ -55,7 +55,7 @@ namespace
 | 
			
		||||
 | 
			
		||||
    bool WebSocketClient::isReady() const
 | 
			
		||||
    {
 | 
			
		||||
        return _webSocket.getReadyState() == ix::ReadyState::Open;
 | 
			
		||||
        return _webSocket.getReadyState() == ix::WebSocket_ReadyState_Open;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    uint16_t WebSocketClient::getCloseCode()
 | 
			
		||||
@@ -116,13 +116,13 @@ namespace
 | 
			
		||||
                   const ix::WebSocketCloseInfo& closeInfo)
 | 
			
		||||
            {
 | 
			
		||||
                std::stringstream ss;
 | 
			
		||||
                if (messageType == ix::WebSocketMessageType::Open)
 | 
			
		||||
                if (messageType == ix::WebSocket_MessageType_Open)
 | 
			
		||||
                {
 | 
			
		||||
                    log("client connected");
 | 
			
		||||
 | 
			
		||||
                    _webSocket.disableAutomaticReconnection();
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Close)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Close)
 | 
			
		||||
                {
 | 
			
		||||
                    log("client disconnected");
 | 
			
		||||
 | 
			
		||||
@@ -134,24 +134,24 @@ namespace
 | 
			
		||||
                    
 | 
			
		||||
                    _webSocket.disableAutomaticReconnection();
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Error)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Error)
 | 
			
		||||
                {
 | 
			
		||||
                    ss << "Error ! " << error.reason;
 | 
			
		||||
                    log(ss.str());
 | 
			
		||||
 | 
			
		||||
                    _webSocket.disableAutomaticReconnection();
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Pong)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Pong)
 | 
			
		||||
                {
 | 
			
		||||
                    ss << "Received pong message " << str;
 | 
			
		||||
                    log(ss.str());
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Ping)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Ping)
 | 
			
		||||
                {
 | 
			
		||||
                    ss << "Received ping message " << str;
 | 
			
		||||
                    log(ss.str());
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Message)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Message)
 | 
			
		||||
                {
 | 
			
		||||
                    ss << "Received message " << str;
 | 
			
		||||
                    log(ss.str());
 | 
			
		||||
@@ -190,7 +190,7 @@ namespace
 | 
			
		||||
                       const ix::WebSocketOpenInfo& openInfo,
 | 
			
		||||
                       const ix::WebSocketCloseInfo& closeInfo)
 | 
			
		||||
                    {
 | 
			
		||||
                        if (messageType == ix::WebSocketMessageType::Open)
 | 
			
		||||
                        if (messageType == ix::WebSocket_MessageType_Open)
 | 
			
		||||
                        {
 | 
			
		||||
                            Logger() << "New server connection";
 | 
			
		||||
                            Logger() << "id: " << connectionState->getId();
 | 
			
		||||
@@ -201,7 +201,7 @@ namespace
 | 
			
		||||
                                Logger() << it.first << ": " << it.second;
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        else if (messageType == ix::WebSocketMessageType::Close)
 | 
			
		||||
                        else if (messageType == ix::WebSocket_MessageType_Close)
 | 
			
		||||
                        {
 | 
			
		||||
                            log("Server closed connection");
 | 
			
		||||
 | 
			
		||||
@@ -404,4 +404,4 @@ TEST_CASE("Websocket_server_close", "[close]")
 | 
			
		||||
 | 
			
		||||
        ix::reportWebSocketTraffic();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
@@ -43,7 +43,7 @@ namespace
 | 
			
		||||
 | 
			
		||||
    bool WebSocketClient::isReady() const
 | 
			
		||||
    {
 | 
			
		||||
        return _webSocket.getReadyState() == ix::ReadyState::Open;
 | 
			
		||||
        return _webSocket.getReadyState() == ix::WebSocket_ReadyState_Open;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void WebSocketClient::stop()
 | 
			
		||||
@@ -88,30 +88,30 @@ namespace
 | 
			
		||||
                   const ix::WebSocketCloseInfo& closeInfo)
 | 
			
		||||
            {
 | 
			
		||||
                std::stringstream ss;
 | 
			
		||||
                if (messageType == ix::WebSocketMessageType::Open)
 | 
			
		||||
                if (messageType == ix::WebSocket_MessageType_Open)
 | 
			
		||||
                {
 | 
			
		||||
                    log("client connected");
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Close)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Close)
 | 
			
		||||
                {
 | 
			
		||||
                    log("client disconnected");
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Error)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Error)
 | 
			
		||||
                {
 | 
			
		||||
                    ss << "Error ! " << error.reason;
 | 
			
		||||
                    log(ss.str());
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Pong)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Pong)
 | 
			
		||||
                {
 | 
			
		||||
                    ss << "Received pong message " << str;
 | 
			
		||||
                    log(ss.str());
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Ping)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Ping)
 | 
			
		||||
                {
 | 
			
		||||
                    ss << "Received ping message " << str;
 | 
			
		||||
                    log(ss.str());
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Message)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Message)
 | 
			
		||||
                {
 | 
			
		||||
                    // too many messages to log
 | 
			
		||||
                }
 | 
			
		||||
@@ -145,7 +145,7 @@ namespace
 | 
			
		||||
                       const ix::WebSocketOpenInfo& openInfo,
 | 
			
		||||
                       const ix::WebSocketCloseInfo& closeInfo)
 | 
			
		||||
                    {
 | 
			
		||||
                        if (messageType == ix::WebSocketMessageType::Open)
 | 
			
		||||
                        if (messageType == ix::WebSocket_MessageType_Open)
 | 
			
		||||
                        {
 | 
			
		||||
                            Logger() << "New server connection";
 | 
			
		||||
                            Logger() << "id: " << connectionState->getId();
 | 
			
		||||
@@ -156,16 +156,16 @@ namespace
 | 
			
		||||
                                Logger() << it.first << ": " << it.second;
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        else if (messageType == ix::WebSocketMessageType::Close)
 | 
			
		||||
                        else if (messageType == ix::WebSocket_MessageType_Close)
 | 
			
		||||
                        {
 | 
			
		||||
                            log("Server closed connection");
 | 
			
		||||
                        }
 | 
			
		||||
                        else if (messageType == ix::WebSocketMessageType::Ping)
 | 
			
		||||
                        else if (messageType == ix::WebSocket_MessageType_Ping)
 | 
			
		||||
                        {
 | 
			
		||||
                            log("Server received a ping");
 | 
			
		||||
                            receivedPingMessages++;
 | 
			
		||||
                        }
 | 
			
		||||
                        else if (messageType == ix::WebSocketMessageType::Message)
 | 
			
		||||
                        else if (messageType == ix::WebSocket_MessageType_Message)
 | 
			
		||||
                        {
 | 
			
		||||
                            // to many messages to log
 | 
			
		||||
                            for(auto client: server.getClients())
 | 
			
		||||
@@ -413,13 +413,13 @@ TEST_CASE("Websocket_ping_no_data_sent_setHeartBeatPeriod", "[setHeartBeatPeriod
 | 
			
		||||
 | 
			
		||||
        REQUIRE(server.getClients().size() == 1);
 | 
			
		||||
 | 
			
		||||
        ix::msleep(1900);
 | 
			
		||||
        ix::msleep(1850);
 | 
			
		||||
 | 
			
		||||
        webSocketClient.stop();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        // Here we test ping interval
 | 
			
		||||
        // -> expected ping messages == 1 as 1900 seconds, 1 ping sent every second
 | 
			
		||||
        // -> expected ping messages == 1 as 1850 seconds, 1 ping sent every second
 | 
			
		||||
        REQUIRE(serverReceivedPingMessages == 1);
 | 
			
		||||
 | 
			
		||||
        // Give us 500ms for the server to notice that clients went away
 | 
			
		||||
@@ -460,7 +460,7 @@ TEST_CASE("Websocket_ping_data_sent_setHeartBeatPeriod", "[setHeartBeatPeriod]")
 | 
			
		||||
        webSocketClient.sendMessage("hello world");
 | 
			
		||||
        ix::msleep(900);
 | 
			
		||||
        webSocketClient.sendMessage("hello world");
 | 
			
		||||
        ix::msleep(1100);
 | 
			
		||||
        ix::msleep(900);
 | 
			
		||||
 | 
			
		||||
        webSocketClient.stop();
 | 
			
		||||
 | 
			
		||||
@@ -469,7 +469,7 @@ TEST_CASE("Websocket_ping_data_sent_setHeartBeatPeriod", "[setHeartBeatPeriod]")
 | 
			
		||||
 | 
			
		||||
        // Here we test ping interval
 | 
			
		||||
        // client has sent data, but ping should have been sent no matter what
 | 
			
		||||
        // -> expected ping messages == 2 as 900+900+1100 = 2900 seconds, 1 ping sent every second
 | 
			
		||||
        // -> expected ping messages == 2 as 900+900+900 = 2700 seconds, 1 ping sent every second
 | 
			
		||||
        REQUIRE(serverReceivedPingMessages == 2);
 | 
			
		||||
 | 
			
		||||
        // Give us 500ms for the server to notice that clients went away
 | 
			
		||||
 
 | 
			
		||||
@@ -52,12 +52,12 @@ namespace
 | 
			
		||||
 | 
			
		||||
    bool WebSocketClient::isReady() const
 | 
			
		||||
    {
 | 
			
		||||
        return _webSocket.getReadyState() == ix::ReadyState::Open;
 | 
			
		||||
        return _webSocket.getReadyState() == ix::WebSocket_ReadyState_Open;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool WebSocketClient::isClosed() const
 | 
			
		||||
    {
 | 
			
		||||
        return _webSocket.getReadyState() == ix::ReadyState::Closed;
 | 
			
		||||
        return _webSocket.getReadyState() == ix::WebSocket_ReadyState_Closed;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void WebSocketClient::stop()
 | 
			
		||||
@@ -97,12 +97,12 @@ namespace
 | 
			
		||||
                   const ix::WebSocketCloseInfo& closeInfo)
 | 
			
		||||
            {
 | 
			
		||||
                std::stringstream ss;
 | 
			
		||||
                if (messageType == ix::WebSocketMessageType::Open)
 | 
			
		||||
                if (messageType == ix::WebSocket_MessageType_Open)
 | 
			
		||||
                {
 | 
			
		||||
                    log("client connected");
 | 
			
		||||
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Close)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Close)
 | 
			
		||||
                {
 | 
			
		||||
                    log("client disconnected");
 | 
			
		||||
 | 
			
		||||
@@ -112,24 +112,24 @@ namespace
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Error)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Error)
 | 
			
		||||
                {
 | 
			
		||||
                    ss << "Error ! " << error.reason;
 | 
			
		||||
                    log(ss.str());
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Pong)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Pong)
 | 
			
		||||
                {
 | 
			
		||||
                    _receivedPongMessages++;
 | 
			
		||||
 | 
			
		||||
                    ss << "Received pong message " << str;
 | 
			
		||||
                    log(ss.str());
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Ping)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Ping)
 | 
			
		||||
                {
 | 
			
		||||
                    ss << "Received ping message " << str;
 | 
			
		||||
                    log(ss.str());
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Message)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Message)
 | 
			
		||||
                {
 | 
			
		||||
                    ss << "Received message " << str;
 | 
			
		||||
                    log(ss.str());
 | 
			
		||||
@@ -174,7 +174,7 @@ namespace
 | 
			
		||||
                       const ix::WebSocketOpenInfo& openInfo,
 | 
			
		||||
                       const ix::WebSocketCloseInfo& closeInfo)
 | 
			
		||||
                    {
 | 
			
		||||
                        if (messageType == ix::WebSocketMessageType::Open)
 | 
			
		||||
                        if (messageType == ix::WebSocket_MessageType_Open)
 | 
			
		||||
                        {
 | 
			
		||||
                            Logger() << "New server connection";
 | 
			
		||||
                            Logger() << "id: " << connectionState->getId();
 | 
			
		||||
@@ -185,11 +185,11 @@ namespace
 | 
			
		||||
                                Logger() << it.first << ": " << it.second;
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        else if (messageType == ix::WebSocketMessageType::Close)
 | 
			
		||||
                        else if (messageType == ix::WebSocket_MessageType_Close)
 | 
			
		||||
                        {
 | 
			
		||||
                            log("Server closed connection");
 | 
			
		||||
                        }
 | 
			
		||||
                        else if (messageType == ix::WebSocketMessageType::Ping)
 | 
			
		||||
                        else if (messageType == ix::WebSocket_MessageType_Ping)
 | 
			
		||||
                        {
 | 
			
		||||
                            log("Server received a ping");
 | 
			
		||||
                            receivedPingMessages++;
 | 
			
		||||
@@ -350,7 +350,7 @@ TEST_CASE("Websocket_no_ping_but_timeout", "[setPingTimeout]")
 | 
			
		||||
 | 
			
		||||
        REQUIRE(server.getClients().size() == 1);
 | 
			
		||||
 | 
			
		||||
        ix::msleep(2900);
 | 
			
		||||
        ix::msleep(2700);
 | 
			
		||||
 | 
			
		||||
        // Here we test ping timeout, no timeout yet
 | 
			
		||||
        REQUIRE(serverReceivedPingMessages == 0);
 | 
			
		||||
@@ -359,7 +359,7 @@ TEST_CASE("Websocket_no_ping_but_timeout", "[setPingTimeout]")
 | 
			
		||||
        REQUIRE(webSocketClient.isClosed() == false);
 | 
			
		||||
        REQUIRE(webSocketClient.closedDueToPingTimeout() == false);
 | 
			
		||||
 | 
			
		||||
        ix::msleep(200);
 | 
			
		||||
        ix::msleep(400);
 | 
			
		||||
 | 
			
		||||
        // Here we test ping timeout, timeout
 | 
			
		||||
        REQUIRE(serverReceivedPingMessages == 0);
 | 
			
		||||
@@ -410,7 +410,7 @@ TEST_CASE("Websocket_ping_timeout", "[setPingTimeout]")
 | 
			
		||||
        REQUIRE(serverReceivedPingMessages == 1);
 | 
			
		||||
        REQUIRE(webSocketClient.getReceivedPongMessages() == 0);
 | 
			
		||||
 | 
			
		||||
        ix::msleep(1100);
 | 
			
		||||
        ix::msleep(1000);
 | 
			
		||||
 | 
			
		||||
        // Here we test ping timeout, timeout
 | 
			
		||||
        REQUIRE(serverReceivedPingMessages == 1);
 | 
			
		||||
 
 | 
			
		||||
@@ -50,7 +50,7 @@ namespace ix
 | 
			
		||||
                       const ix::WebSocketOpenInfo& openInfo,
 | 
			
		||||
                       const ix::WebSocketCloseInfo& closeInfo)
 | 
			
		||||
                    {
 | 
			
		||||
                        if (messageType == ix::WebSocketMessageType::Open)
 | 
			
		||||
                        if (messageType == ix::WebSocket_MessageType_Open)
 | 
			
		||||
                        {
 | 
			
		||||
                            Logger() << "New connection";
 | 
			
		||||
                            connectionState->computeId();
 | 
			
		||||
@@ -64,11 +64,11 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
                            connectionId = connectionState->getId();
 | 
			
		||||
                        }
 | 
			
		||||
                        else if (messageType == ix::WebSocketMessageType::Close)
 | 
			
		||||
                        else if (messageType == ix::WebSocket_MessageType_Close)
 | 
			
		||||
                        {
 | 
			
		||||
                            Logger() << "Closed connection";
 | 
			
		||||
                        }
 | 
			
		||||
                        else if (messageType == ix::WebSocketMessageType::Message)
 | 
			
		||||
                        else if (messageType == ix::WebSocket_MessageType_Message)
 | 
			
		||||
                        {
 | 
			
		||||
                            for (auto&& client : server.getClients())
 | 
			
		||||
                            {
 | 
			
		||||
 
 | 
			
		||||
@@ -60,33 +60,33 @@ namespace
 | 
			
		||||
               const ix::WebSocketCloseInfo& closeInfo)
 | 
			
		||||
            {
 | 
			
		||||
                std::stringstream ss;
 | 
			
		||||
                if (messageType == ix::WebSocketMessageType::Open)
 | 
			
		||||
                if (messageType == ix::WebSocket_MessageType_Open)
 | 
			
		||||
                {
 | 
			
		||||
                    log("cmd_websocket_satori_chat: connected !");
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Close)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Close)
 | 
			
		||||
                {
 | 
			
		||||
                    log("cmd_websocket_satori_chat: disconnected !");
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Error)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Error)
 | 
			
		||||
                {
 | 
			
		||||
                    ss << "cmd_websocket_satori_chat: Error! ";
 | 
			
		||||
                    ss << error.reason;
 | 
			
		||||
                    log(ss.str());
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Message)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Message)
 | 
			
		||||
                {
 | 
			
		||||
                    log("cmd_websocket_satori_chat: received message.!");
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Ping)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Ping)
 | 
			
		||||
                {
 | 
			
		||||
                    log("cmd_websocket_satori_chat: received ping message.!");
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Pong)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Pong)
 | 
			
		||||
                {
 | 
			
		||||
                    log("cmd_websocket_satori_chat: received pong message.!");
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Fragment)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Fragment)
 | 
			
		||||
                {
 | 
			
		||||
                    log("cmd_websocket_satori_chat: received fragment.!");
 | 
			
		||||
                }
 | 
			
		||||
@@ -109,40 +109,38 @@ TEST_CASE("websocket_connections", "[websocket]")
 | 
			
		||||
{
 | 
			
		||||
    SECTION("Try to connect to invalid servers.")
 | 
			
		||||
    {
 | 
			
		||||
        IXWebSocketTestConnectionDisconnection test;
 | 
			
		||||
        IXWebSocketTestConnectionDisconnection chatA;
 | 
			
		||||
 | 
			
		||||
        test.start(GOOGLE_URL);
 | 
			
		||||
        chatA.start(GOOGLE_URL);
 | 
			
		||||
        ix::msleep(1000);
 | 
			
		||||
        test.stop();
 | 
			
		||||
        chatA.stop();
 | 
			
		||||
 | 
			
		||||
        test.start(UNKNOWN_URL);
 | 
			
		||||
        chatA.start(UNKNOWN_URL);
 | 
			
		||||
        ix::msleep(1000);
 | 
			
		||||
        test.stop();
 | 
			
		||||
        chatA.stop();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SECTION("Try to connect and disconnect with different timing, not enough time to succesfully connect")
 | 
			
		||||
    {
 | 
			
		||||
        IXWebSocketTestConnectionDisconnection test;
 | 
			
		||||
        IXWebSocketTestConnectionDisconnection chatA;
 | 
			
		||||
        for (int i = 0; i < 50; ++i)
 | 
			
		||||
        {
 | 
			
		||||
            log(std::string("Run: ") + std::to_string(i));
 | 
			
		||||
            test.start(WEBSOCKET_DOT_ORG_URL);
 | 
			
		||||
            chatA.start(WEBSOCKET_DOT_ORG_URL);
 | 
			
		||||
            ix::msleep(i);
 | 
			
		||||
            test.stop();
 | 
			
		||||
            chatA.stop();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // This test breaks on travis CI - Ubuntu Xenial + gcc + tsan
 | 
			
		||||
    // We should fix this.
 | 
			
		||||
    /*SECTION("Try to connect and disconnect with different timing, from not enough time to successfull connect")
 | 
			
		||||
    {
 | 
			
		||||
        IXWebSocketTestConnectionDisconnection test;
 | 
			
		||||
        IXWebSocketTestConnectionDisconnection chatA;
 | 
			
		||||
        for (int i = 0; i < 20; ++i)
 | 
			
		||||
        {
 | 
			
		||||
            log(std::string("Run: ") + std::to_string(i));
 | 
			
		||||
            test.start(WEBSOCKET_DOT_ORG_URL);
 | 
			
		||||
            chatA.start(WEBSOCKET_DOT_ORG_URL);
 | 
			
		||||
            ix::msleep(i*50);
 | 
			
		||||
            test.stop();
 | 
			
		||||
            chatA.stop();
 | 
			
		||||
        }
 | 
			
		||||
    }*/
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -87,7 +87,7 @@ namespace
 | 
			
		||||
 | 
			
		||||
    bool WebSocketChat::isReady() const
 | 
			
		||||
    {
 | 
			
		||||
        return _webSocket.getReadyState() == ix::ReadyState::Open;
 | 
			
		||||
        return _webSocket.getReadyState() == ix::WebSocket_ReadyState_Open;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void WebSocketChat::stop()
 | 
			
		||||
@@ -122,21 +122,21 @@ namespace
 | 
			
		||||
                   const ix::WebSocketCloseInfo& closeInfo)
 | 
			
		||||
            {
 | 
			
		||||
                std::stringstream ss;
 | 
			
		||||
                if (messageType == ix::WebSocketMessageType::Open)
 | 
			
		||||
                if (messageType == ix::WebSocket_MessageType_Open)
 | 
			
		||||
                {
 | 
			
		||||
                    ss << "cmd_websocket_chat: user "
 | 
			
		||||
                       << _user
 | 
			
		||||
                       << " Connected !";
 | 
			
		||||
                    log(ss.str());
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Close)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Close)
 | 
			
		||||
                {
 | 
			
		||||
                    ss << "cmd_websocket_chat: user "
 | 
			
		||||
                       << _user
 | 
			
		||||
                       << " disconnected !";
 | 
			
		||||
                    log(ss.str());
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Message)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Message)
 | 
			
		||||
                {
 | 
			
		||||
                    auto result = decodeMessage(str);
 | 
			
		||||
 | 
			
		||||
@@ -159,20 +159,20 @@ namespace
 | 
			
		||||
                       << _user << " > ";
 | 
			
		||||
                    log(ss.str());
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Error)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Error)
 | 
			
		||||
                {
 | 
			
		||||
                    ss << "cmd_websocket_chat: Error ! " << error.reason;
 | 
			
		||||
                    log(ss.str());
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Ping)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Ping)
 | 
			
		||||
                {
 | 
			
		||||
                    log("cmd_websocket_chat: received ping message");
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Pong)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Pong)
 | 
			
		||||
                {
 | 
			
		||||
                    log("cmd_websocket_chat: received pong message");
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Fragment)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Fragment)
 | 
			
		||||
                {
 | 
			
		||||
                    log("cmd_websocket_chat: received message fragment");
 | 
			
		||||
                }
 | 
			
		||||
@@ -228,7 +228,7 @@ namespace
 | 
			
		||||
                       const ix::WebSocketOpenInfo& openInfo,
 | 
			
		||||
                       const ix::WebSocketCloseInfo& closeInfo)
 | 
			
		||||
                    {
 | 
			
		||||
                        if (messageType == ix::WebSocketMessageType::Open)
 | 
			
		||||
                        if (messageType == ix::WebSocket_MessageType_Open)
 | 
			
		||||
                        {
 | 
			
		||||
                            Logger() << "New connection";
 | 
			
		||||
                            Logger() << "id: " << connectionState->getId();
 | 
			
		||||
@@ -239,11 +239,11 @@ namespace
 | 
			
		||||
                                Logger() << it.first << ": " << it.second;
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        else if (messageType == ix::WebSocketMessageType::Close)
 | 
			
		||||
                        else if (messageType == ix::WebSocket_MessageType_Close)
 | 
			
		||||
                        {
 | 
			
		||||
                            log("Closed connection");
 | 
			
		||||
                        }
 | 
			
		||||
                        else if (messageType == ix::WebSocketMessageType::Message)
 | 
			
		||||
                        else if (messageType == ix::WebSocket_MessageType_Message)
 | 
			
		||||
                        {
 | 
			
		||||
                            for (auto&& client : server.getClients())
 | 
			
		||||
                            {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										105
									
								
								test/run.py
									
									
									
									
									
								
							
							
						
						
									
										105
									
								
								test/run.py
									
									
									
									
									
								
							@@ -28,9 +28,9 @@ try:
 | 
			
		||||
except ImportError:
 | 
			
		||||
    hasClick = False
 | 
			
		||||
 | 
			
		||||
BUILD_TYPE = 'Debug'
 | 
			
		||||
XML_OUTPUT_FILE = 'ixwebsocket_unittest.xml'
 | 
			
		||||
TEST_EXE_PATH = None
 | 
			
		||||
 | 
			
		||||
DEFAULT_EXE = 'ixwebsocket_unittest'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Command(object):
 | 
			
		||||
    """Run system commands with timeout
 | 
			
		||||
@@ -65,7 +65,7 @@ class Command(object):
 | 
			
		||||
            return True, self.process.returncode
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def runCommand(cmd, abortOnFailure=True, timeout=None):
 | 
			
		||||
def runCommand(cmd, assertOnFailure=True, timeout=None):
 | 
			
		||||
    '''Small wrapper to run a command and make sure it succeed'''
 | 
			
		||||
 | 
			
		||||
    if timeout is None:
 | 
			
		||||
@@ -73,13 +73,16 @@ def runCommand(cmd, abortOnFailure=True, timeout=None):
 | 
			
		||||
 | 
			
		||||
    print('\nRunning', cmd)
 | 
			
		||||
    command = Command(cmd)
 | 
			
		||||
    succeed, ret = command.run(timeout)
 | 
			
		||||
    timedout, ret = command.run(timeout)
 | 
			
		||||
 | 
			
		||||
    if not succeed or ret != 0:
 | 
			
		||||
        msg = 'cmd {}\nfailed with error code {}'.format(cmd, ret)
 | 
			
		||||
    if timedout:
 | 
			
		||||
        print('Unittest timed out')
 | 
			
		||||
 | 
			
		||||
    msg = 'cmd {} failed with error code {}'.format(cmd, ret)
 | 
			
		||||
    if ret != 0:
 | 
			
		||||
        print(msg)
 | 
			
		||||
        if abortOnFailure:
 | 
			
		||||
            sys.exit(-1)
 | 
			
		||||
        if assertOnFailure:
 | 
			
		||||
            assert False
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def runCMake(sanitizer, buildDir):
 | 
			
		||||
@@ -88,6 +91,12 @@ def runCMake(sanitizer, buildDir):
 | 
			
		||||
    (remove build sub-folder).
 | 
			
		||||
    '''
 | 
			
		||||
 | 
			
		||||
    # CMake installed via Self Service ends up here.
 | 
			
		||||
    cmake_executable = '/Applications/CMake.app/Contents/bin/cmake'
 | 
			
		||||
 | 
			
		||||
    if not os.path.exists(cmake_executable):
 | 
			
		||||
        cmake_executable = 'cmake'
 | 
			
		||||
 | 
			
		||||
    sanitizersFlags = {
 | 
			
		||||
        'asan': '-DSANITIZE_ADDRESS=On',
 | 
			
		||||
        'ubsan': '-DSANITIZE_UNDEFINED=On',
 | 
			
		||||
@@ -101,22 +110,19 @@ def runCMake(sanitizer, buildDir):
 | 
			
		||||
    if not os.path.exists(cmakeExecutable):
 | 
			
		||||
        cmakeExecutable = 'cmake'
 | 
			
		||||
 | 
			
		||||
    generator = '"Unix Makefiles"'
 | 
			
		||||
    if platform.system() == 'Windows':
 | 
			
		||||
        #generator = '"NMake Makefiles"'
 | 
			
		||||
        generator = '"Visual Studio 16 2019"'
 | 
			
		||||
    else:
 | 
			
		||||
        generator = '"Unix Makefiles"'
 | 
			
		||||
        generator = '"NMake Makefiles"'
 | 
			
		||||
 | 
			
		||||
    CMAKE_BUILD_TYPE = BUILD_TYPE
 | 
			
		||||
 | 
			
		||||
    fmt = '{cmakeExecutable} -H. \
 | 
			
		||||
    fmt = '''
 | 
			
		||||
{cmakeExecutable} -H. \
 | 
			
		||||
    {sanitizerFlag} \
 | 
			
		||||
    -B"{buildDir}" \
 | 
			
		||||
    -DCMAKE_BUILD_TYPE={CMAKE_BUILD_TYPE} \
 | 
			
		||||
    -B{buildDir} \
 | 
			
		||||
    -DCMAKE_BUILD_TYPE=Debug \
 | 
			
		||||
    -DUSE_TLS=1 \
 | 
			
		||||
    -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
 | 
			
		||||
    -G{generator}'
 | 
			
		||||
 | 
			
		||||
    -G{generator}
 | 
			
		||||
'''
 | 
			
		||||
    cmakeCmd = fmt.format(**locals())
 | 
			
		||||
    runCommand(cmakeCmd)
 | 
			
		||||
 | 
			
		||||
@@ -127,10 +133,10 @@ def runTest(args, buildDir, xmlOutput, testRunName):
 | 
			
		||||
    if args is None:
 | 
			
		||||
        args = ''
 | 
			
		||||
 | 
			
		||||
    testCommand = '{} -o {} -n "{}" -r junit "{}"'.format(TEST_EXE_PATH, xmlOutput, testRunName, args)
 | 
			
		||||
 | 
			
		||||
    fmt = '{buildDir}/{DEFAULT_EXE} -o {xmlOutput} -n "{testRunName}" -r junit "{args}"'
 | 
			
		||||
    testCommand = fmt.format(**locals())
 | 
			
		||||
    runCommand(testCommand,
 | 
			
		||||
               abortOnFailure=False)
 | 
			
		||||
               assertOnFailure=False)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def validateTestSuite(xmlOutput):
 | 
			
		||||
@@ -290,7 +296,8 @@ def executeJobs(jobs):
 | 
			
		||||
def computeAllTestNames(buildDir):
 | 
			
		||||
    '''Compute all test case names, by executing the unittest in a custom mode'''
 | 
			
		||||
 | 
			
		||||
    cmd = '"{}" --list-test-names-only'.format(TEST_EXE_PATH)
 | 
			
		||||
    executable = os.path.join(buildDir, DEFAULT_EXE)
 | 
			
		||||
    cmd = '"{}" --list-test-names-only'.format(executable)
 | 
			
		||||
    names = os.popen(cmd).read().splitlines()
 | 
			
		||||
    names.sort()  # Sort test names for execution determinism
 | 
			
		||||
    return names
 | 
			
		||||
@@ -337,7 +344,7 @@ def generateXmlOutput(results, xmlOutput, testRunName, runTime):
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
        systemOut = ET.Element('system-out')
 | 
			
		||||
        systemOut.text = result['output'].decode('utf-8', 'ignore')
 | 
			
		||||
        systemOut.text = result['output'].decode('utf-8')
 | 
			
		||||
        testCase.append(systemOut)
 | 
			
		||||
 | 
			
		||||
        if not result['success']:
 | 
			
		||||
@@ -358,19 +365,16 @@ def run(testName, buildDir, sanitizer, xmlOutput, testRunName, buildOnly, useLLD
 | 
			
		||||
    runCMake(sanitizer, buildDir)
 | 
			
		||||
 | 
			
		||||
    # build with make
 | 
			
		||||
    #makeCmd = 'cmake --build '
 | 
			
		||||
    #jobs = '-j8'
 | 
			
		||||
    makeCmd = 'make'
 | 
			
		||||
    jobs = '-j8'
 | 
			
		||||
 | 
			
		||||
    #if platform.system() == 'Windows':
 | 
			
		||||
    #    makeCmd = 'nmake'
 | 
			
		||||
    if platform.system() == 'Windows':
 | 
			
		||||
        makeCmd = 'nmake'
 | 
			
		||||
 | 
			
		||||
        # nmake does not have a -j option
 | 
			
		||||
    #    jobs = ''
 | 
			
		||||
        jobs = ''
 | 
			
		||||
 | 
			
		||||
    #runCommand('{} -C {} {}'.format(makeCmd, buildDir, jobs))
 | 
			
		||||
 | 
			
		||||
    # build with cmake
 | 
			
		||||
    runCommand('cmake --build ' + buildDir)
 | 
			
		||||
    runCommand('{} -C {} {}'.format(makeCmd, buildDir, jobs))
 | 
			
		||||
 | 
			
		||||
    if buildOnly:
 | 
			
		||||
        return
 | 
			
		||||
@@ -405,7 +409,12 @@ def run(testName, buildDir, sanitizer, xmlOutput, testRunName, buildOnly, useLLD
 | 
			
		||||
            continue
 | 
			
		||||
 | 
			
		||||
        # testName can contains spaces, so we enclose them in double quotes
 | 
			
		||||
        cmd = '{} "{}" "{}" > "{}" 2>&1'.format(lldb, TEST_EXE_PATH, testName, outputPath)
 | 
			
		||||
        executable = os.path.join(buildDir, DEFAULT_EXE)
 | 
			
		||||
 | 
			
		||||
        if platform.system() == 'Windows':
 | 
			
		||||
            executable += '.exe'
 | 
			
		||||
 | 
			
		||||
        cmd = '{} "{}" "{}" > "{}" 2>&1'.format(lldb, executable, testName, outputPath)
 | 
			
		||||
 | 
			
		||||
        jobs.append({
 | 
			
		||||
            'name': testName,
 | 
			
		||||
@@ -445,6 +454,8 @@ def main():
 | 
			
		||||
    if not os.path.exists(buildDir):
 | 
			
		||||
        os.makedirs(buildDir)
 | 
			
		||||
 | 
			
		||||
    defaultOutput = DEFAULT_EXE + '.xml'
 | 
			
		||||
 | 
			
		||||
    parser = argparse.ArgumentParser(description='Build and Run the engine unittest')
 | 
			
		||||
 | 
			
		||||
    sanitizers = ['tsan', 'asan', 'ubsan', 'none']
 | 
			
		||||
@@ -470,29 +481,14 @@ def main():
 | 
			
		||||
 | 
			
		||||
    # Default sanitizer is tsan
 | 
			
		||||
    sanitizer = args.sanitizer
 | 
			
		||||
 | 
			
		||||
    if args.no_sanitizer:
 | 
			
		||||
        sanitizer = 'none'
 | 
			
		||||
    elif args.sanitizer is None:
 | 
			
		||||
    if args.sanitizer is None:
 | 
			
		||||
        sanitizer = 'tsan'
 | 
			
		||||
 | 
			
		||||
    # Sanitizers display lots of strange errors on Linux on CI,
 | 
			
		||||
    # which looks like false positives
 | 
			
		||||
    if platform.system() != 'Darwin':
 | 
			
		||||
        sanitizer = 'none'
 | 
			
		||||
 | 
			
		||||
    defaultRunName = 'ixengine_{}_{}'.format(platform.system(), sanitizer)
 | 
			
		||||
 | 
			
		||||
    xmlOutput = args.output or XML_OUTPUT_FILE
 | 
			
		||||
    xmlOutput = args.output or defaultOutput
 | 
			
		||||
    testRunName = args.run_name or os.getenv('IXENGINE_TEST_RUN_NAME') or defaultRunName
 | 
			
		||||
 | 
			
		||||
    global TEST_EXE_PATH
 | 
			
		||||
 | 
			
		||||
    if platform.system() == 'Windows':
 | 
			
		||||
        TEST_EXE_PATH = os.path.join(buildDir, BUILD_TYPE, 'ixwebsocket_unittest.exe')
 | 
			
		||||
    else:
 | 
			
		||||
        TEST_EXE_PATH = os.path.join(buildDir, 'ixwebsocket_unittest')
 | 
			
		||||
 | 
			
		||||
    if args.list:
 | 
			
		||||
        # catch2 exit with a different error code when requesting the list of files
 | 
			
		||||
        try:
 | 
			
		||||
@@ -509,6 +505,11 @@ def main():
 | 
			
		||||
        print('LLDB is only supported on Apple at this point')
 | 
			
		||||
        args.lldb = False
 | 
			
		||||
 | 
			
		||||
    # Sanitizers display lots of strange errors on Linux on CI,
 | 
			
		||||
    # which looks like false positives
 | 
			
		||||
    if platform.system() != 'Darwin':
 | 
			
		||||
        sanitizer = 'none'
 | 
			
		||||
 | 
			
		||||
    return run(args.test, buildDir, sanitizer, xmlOutput, 
 | 
			
		||||
               testRunName, args.build_only, args.lldb)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										58
									
								
								third_party/msgpack11/msgpack11.cpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										58
									
								
								third_party/msgpack11/msgpack11.cpp
									
									
									
									
										vendored
									
									
								
							@@ -119,62 +119,62 @@ static void verify_length(size_t len)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void dump(NullStruct, std::string &out) {
 | 
			
		||||
    out.push_back((char) 0xc0);
 | 
			
		||||
    out.push_back(0xc0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void dump(float value, std::string &out) {
 | 
			
		||||
    out.push_back((char) 0xca);
 | 
			
		||||
    out.push_back(0xca);
 | 
			
		||||
    dump_data(value, out);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void dump(double value, std::string &out) {
 | 
			
		||||
    out.push_back((char) 0xcb);
 | 
			
		||||
    out.push_back(0xcb);
 | 
			
		||||
    dump_data(value, out);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void dump(int8_t value, std::string &out) {
 | 
			
		||||
    if( value < -32 )
 | 
			
		||||
    {
 | 
			
		||||
        out.push_back((char) 0xd0);
 | 
			
		||||
        out.push_back(0xd0);
 | 
			
		||||
    }
 | 
			
		||||
    out.push_back(value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void dump(int16_t value, std::string &out) {
 | 
			
		||||
    out.push_back((char) 0xd1);
 | 
			
		||||
    out.push_back(0xd1);
 | 
			
		||||
    dump_data(value, out);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void dump(int32_t value, std::string &out) {
 | 
			
		||||
    out.push_back((char) 0xd2);
 | 
			
		||||
    out.push_back(0xd2);
 | 
			
		||||
    dump_data(value, out);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void dump(int64_t value, std::string &out) {
 | 
			
		||||
    out.push_back((char) 0xd3);
 | 
			
		||||
    out.push_back(0xd3);
 | 
			
		||||
    dump_data(value, out);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void dump(uint8_t value, std::string &out) {
 | 
			
		||||
    if(128 <= value)
 | 
			
		||||
    {
 | 
			
		||||
        out.push_back((char) 0xcc);
 | 
			
		||||
        out.push_back(0xcc);
 | 
			
		||||
    }
 | 
			
		||||
    out.push_back(value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void dump(uint16_t value, std::string &out) {
 | 
			
		||||
    out.push_back((char) 0xcd);
 | 
			
		||||
    out.push_back(0xcd);
 | 
			
		||||
    dump_data(value, out);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void dump(uint32_t value, std::string &out) {
 | 
			
		||||
    out.push_back((char) 0xce);
 | 
			
		||||
    out.push_back(0xce);
 | 
			
		||||
    dump_data(value, out);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void dump(uint64_t value, std::string &out) {
 | 
			
		||||
    out.push_back((char) 0xcf);
 | 
			
		||||
    out.push_back(0xcf);
 | 
			
		||||
    dump_data(value, out);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -194,19 +194,19 @@ static void dump(const std::string& value, std::string &out) {
 | 
			
		||||
    else if(len <= 0xff)
 | 
			
		||||
    {
 | 
			
		||||
        uint8_t const length = static_cast<uint8_t>(len);
 | 
			
		||||
        out.push_back((char) 0xd9);
 | 
			
		||||
        out.push_back(0xd9);
 | 
			
		||||
        out.push_back(length);
 | 
			
		||||
    }
 | 
			
		||||
    else if(len <= 0xffff)
 | 
			
		||||
    {
 | 
			
		||||
        uint16_t const length = static_cast<uint16_t>(len);
 | 
			
		||||
        out.push_back((char) 0xda);
 | 
			
		||||
        out.push_back(0xda);
 | 
			
		||||
        dump_data(length, out);
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        uint32_t const length = static_cast<uint32_t>(len);
 | 
			
		||||
        out.push_back((char) 0xdb);
 | 
			
		||||
        out.push_back(0xdb);
 | 
			
		||||
        dump_data(length, out);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -226,13 +226,13 @@ static void dump(const MsgPack::array& value, std::string &out) {
 | 
			
		||||
    else if(len <= 0xffff)
 | 
			
		||||
    {
 | 
			
		||||
        uint16_t const length = static_cast<uint16_t>(len);
 | 
			
		||||
        out.push_back((char) 0xdc);
 | 
			
		||||
        out.push_back(0xdc);
 | 
			
		||||
        dump_data(length, out);
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        uint32_t const length = static_cast<uint32_t>(len);
 | 
			
		||||
        out.push_back((char) 0xdd);
 | 
			
		||||
        out.push_back(0xdd);
 | 
			
		||||
        dump_data(length, out);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -252,13 +252,13 @@ static void dump(const MsgPack::object& value, std::string &out) {
 | 
			
		||||
    else if(len <= 0xffff)
 | 
			
		||||
    {
 | 
			
		||||
        uint16_t const length = static_cast<uint16_t>(len);
 | 
			
		||||
        out.push_back((char) 0xde);
 | 
			
		||||
        out.push_back(0xde);
 | 
			
		||||
        dump_data(length, out);
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        uint32_t const length = static_cast<uint32_t>(len);
 | 
			
		||||
        out.push_back((char) 0xdf);
 | 
			
		||||
        out.push_back(0xdf);
 | 
			
		||||
        dump_data(length, out);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -274,19 +274,19 @@ static void dump(const MsgPack::binary& value, std::string &out) {
 | 
			
		||||
    if(len <= 0xff)
 | 
			
		||||
    {
 | 
			
		||||
        uint8_t const length = static_cast<uint8_t>(len);
 | 
			
		||||
        out.push_back((char) 0xc4);
 | 
			
		||||
        out.push_back(0xc4);
 | 
			
		||||
        dump_data(length, out);
 | 
			
		||||
    }
 | 
			
		||||
    else if(len <= 0xffff)
 | 
			
		||||
    {
 | 
			
		||||
        uint16_t const length = static_cast<uint16_t>(len);
 | 
			
		||||
        out.push_back((char) 0xc5);
 | 
			
		||||
        out.push_back(0xc5);
 | 
			
		||||
        dump_data(length, out);
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        uint32_t const length = static_cast<uint32_t>(len);
 | 
			
		||||
        out.push_back((char) 0xc6);
 | 
			
		||||
        out.push_back(0xc6);
 | 
			
		||||
        dump_data(length, out);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -302,33 +302,33 @@ static void dump(const MsgPack::extension& value, std::string &out) {
 | 
			
		||||
    verify_length(len);
 | 
			
		||||
 | 
			
		||||
    if(len == 0x01) {
 | 
			
		||||
        out.push_back((char) 0xd4);
 | 
			
		||||
        out.push_back(0xd4);
 | 
			
		||||
    }
 | 
			
		||||
    else if(len == 0x02) {
 | 
			
		||||
        out.push_back((char) 0xd5);
 | 
			
		||||
        out.push_back(0xd5);
 | 
			
		||||
    }
 | 
			
		||||
    else if(len == 0x04) {
 | 
			
		||||
        out.push_back((char) 0xd6);
 | 
			
		||||
        out.push_back(0xd6);
 | 
			
		||||
    }
 | 
			
		||||
    else if(len == 0x08) {
 | 
			
		||||
        out.push_back((char) 0xd7);
 | 
			
		||||
        out.push_back(0xd7);
 | 
			
		||||
    }
 | 
			
		||||
    else if(len == 0x10) {
 | 
			
		||||
        out.push_back((char) 0xd8);
 | 
			
		||||
        out.push_back(0xd8);
 | 
			
		||||
    }
 | 
			
		||||
    else if(len <= 0xff) {
 | 
			
		||||
        uint8_t const length = static_cast<uint8_t>(len);
 | 
			
		||||
        out.push_back((char) 0xc7);
 | 
			
		||||
        out.push_back(0xc7);
 | 
			
		||||
        out.push_back(length);
 | 
			
		||||
    }
 | 
			
		||||
    else if(len <= 0xffff) {
 | 
			
		||||
        uint16_t const length = static_cast<uint16_t>(len);
 | 
			
		||||
        out.push_back((char) 0xc8);
 | 
			
		||||
        out.push_back(0xc8);
 | 
			
		||||
        dump_data(length, out);
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        uint32_t const length = static_cast<uint32_t>(len);
 | 
			
		||||
        out.push_back((char) 0xc9);
 | 
			
		||||
        out.push_back(0xc9);
 | 
			
		||||
        dump_data(length, out);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -108,7 +108,7 @@ int StatsdClient::init()
 | 
			
		||||
 | 
			
		||||
    d->sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
 | 
			
		||||
    if ( d->sock == -1 ) {
 | 
			
		||||
        snprintf(d->errmsg, sizeof(d->errmsg), "could not create socket, err=%s", strerror(errno));
 | 
			
		||||
        snprintf(d->errmsg, sizeof(d->errmsg), "could not create socket, err=%m");
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -229,7 +229,7 @@ int StatsdClient::send_to_daemon(const string &message) {
 | 
			
		||||
    ret = (int) sendto(d->sock, message.data(), message.size(), 0, (struct sockaddr *) &d->server, sizeof(d->server));
 | 
			
		||||
    if ( ret == -1) {
 | 
			
		||||
        snprintf(d->errmsg, sizeof(d->errmsg),
 | 
			
		||||
                 "sendto server fail, host=%s:%d, err=%s", d->host.c_str(), d->port, strerror(errno));
 | 
			
		||||
                 "sendto server fail, host=%s:%d, err=%m", d->host.c_str(), d->port);
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -162,7 +162,7 @@ namespace ix
 | 
			
		||||
            std::cerr << "Download size: " << downloadSize << std::endl;
 | 
			
		||||
 | 
			
		||||
            std::cerr << "Status: " << statusCode << std::endl;
 | 
			
		||||
            if (errorCode != HttpErrorCode::Ok)
 | 
			
		||||
            if (errorCode != HttpErrorCode_Ok)
 | 
			
		||||
            {
 | 
			
		||||
                std::cerr << "error message: " << errorMsg << std::endl;
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -100,14 +100,14 @@ namespace ix
 | 
			
		||||
                CobraConnection::invokeTrafficTrackerCallback(wireSize, true);
 | 
			
		||||
 | 
			
		||||
                std::stringstream ss;
 | 
			
		||||
                if (messageType == ix::WebSocketMessageType::Open)
 | 
			
		||||
                if (messageType == ix::WebSocket_MessageType_Open)
 | 
			
		||||
                {
 | 
			
		||||
                    invokeEventCallback(ix::CobraConnection_EventType_Open,
 | 
			
		||||
                                        std::string(),
 | 
			
		||||
                                        openInfo.headers);
 | 
			
		||||
                    sendHandshakeMessage();
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Close)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Close)
 | 
			
		||||
                {
 | 
			
		||||
                    _authenticated = false;
 | 
			
		||||
 | 
			
		||||
@@ -117,7 +117,7 @@ namespace ix
 | 
			
		||||
                    invokeEventCallback(ix::CobraConnection_EventType_Closed,
 | 
			
		||||
                                        ss.str());
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Message)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Message)
 | 
			
		||||
                {
 | 
			
		||||
                    Json::Value data;
 | 
			
		||||
                    Json::Reader reader;
 | 
			
		||||
@@ -187,7 +187,7 @@ namespace ix
 | 
			
		||||
                        invokeErrorCallback("Un-handled message type", str);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Error)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Error)
 | 
			
		||||
                {
 | 
			
		||||
                    std::stringstream ss;
 | 
			
		||||
                    ss << "Connection error: " << error.reason      << std::endl;
 | 
			
		||||
@@ -384,7 +384,7 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
    bool CobraConnection::isConnected() const
 | 
			
		||||
    {
 | 
			
		||||
        return _webSocket->getReadyState() == ix::ReadyState::Open;
 | 
			
		||||
        return _webSocket->getReadyState() == ix::WebSocket_ReadyState_Open;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool CobraConnection::isAuthenticated() const
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,6 @@
 | 
			
		||||
 | 
			
		||||
#include "nlohmann/json.hpp"
 | 
			
		||||
#include <sstream>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
 | 
			
		||||
namespace snake
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -65,7 +65,7 @@ namespace snake
 | 
			
		||||
                       const ix::WebSocketOpenInfo& openInfo,
 | 
			
		||||
                       const ix::WebSocketCloseInfo& closeInfo)
 | 
			
		||||
                    {
 | 
			
		||||
                        if (messageType == ix::WebSocketMessageType::Open)
 | 
			
		||||
                        if (messageType == ix::WebSocket_MessageType_Open)
 | 
			
		||||
                        {
 | 
			
		||||
                            std::cerr << "New connection" << std::endl;
 | 
			
		||||
                            std::cerr << "id: " << state->getId() << std::endl;
 | 
			
		||||
@@ -86,13 +86,13 @@ namespace snake
 | 
			
		||||
                                std::cerr << "Cannot connect to redis host" << std::endl;
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        else if (messageType == ix::WebSocketMessageType::Close)
 | 
			
		||||
                        else if (messageType == ix::WebSocket_MessageType_Close)
 | 
			
		||||
                        {
 | 
			
		||||
                            std::cerr << "Closed connection"
 | 
			
		||||
                                      << " code " << closeInfo.code
 | 
			
		||||
                                      << " reason " << closeInfo.reason << std::endl;
 | 
			
		||||
                        }
 | 
			
		||||
                        else if (messageType == ix::WebSocketMessageType::Error)
 | 
			
		||||
                        else if (messageType == ix::WebSocket_MessageType_Error)
 | 
			
		||||
                        {
 | 
			
		||||
                            std::stringstream ss;
 | 
			
		||||
                            ss << "Connection error: " << error.reason      << std::endl;
 | 
			
		||||
@@ -101,11 +101,11 @@ namespace snake
 | 
			
		||||
                            ss << "HTTP Status: "      << error.http_status << std::endl;
 | 
			
		||||
                            std::cerr << ss.str();
 | 
			
		||||
                        }
 | 
			
		||||
                        else if (messageType == ix::WebSocketMessageType::Fragment)
 | 
			
		||||
                        else if (messageType == ix::WebSocket_MessageType_Fragment)
 | 
			
		||||
                        {
 | 
			
		||||
                            std::cerr << "Received message fragment" << std::endl;
 | 
			
		||||
                        }
 | 
			
		||||
                        else if (messageType == ix::WebSocketMessageType::Message)
 | 
			
		||||
                        else if (messageType == ix::WebSocket_MessageType_Message)
 | 
			
		||||
                        {
 | 
			
		||||
                            std::cerr << "Received " << wireSize << " bytes" << std::endl;
 | 
			
		||||
                            processCobraMessage(state, webSocket, _appConfig, str);
 | 
			
		||||
 
 | 
			
		||||
@@ -28,7 +28,7 @@ namespace ix
 | 
			
		||||
                       const ix::WebSocketOpenInfo& openInfo,
 | 
			
		||||
                       const ix::WebSocketCloseInfo& closeInfo)
 | 
			
		||||
                    {
 | 
			
		||||
                        if (messageType == ix::WebSocketMessageType::Open)
 | 
			
		||||
                        if (messageType == ix::WebSocket_MessageType_Open)
 | 
			
		||||
                        {
 | 
			
		||||
                            std::cerr << "New connection" << std::endl;
 | 
			
		||||
                            std::cerr << "id: " << connectionState->getId() << std::endl;
 | 
			
		||||
@@ -39,13 +39,13 @@ namespace ix
 | 
			
		||||
                                std::cerr << it.first << ": " << it.second << std::endl;
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        else if (messageType == ix::WebSocketMessageType::Close)
 | 
			
		||||
                        else if (messageType == ix::WebSocket_MessageType_Close)
 | 
			
		||||
                        {
 | 
			
		||||
                            std::cerr << "Closed connection"
 | 
			
		||||
                                      << " code " << closeInfo.code
 | 
			
		||||
                                      << " reason " << closeInfo.reason << std::endl;
 | 
			
		||||
                        }
 | 
			
		||||
                        else if (messageType == ix::WebSocketMessageType::Error)
 | 
			
		||||
                        else if (messageType == ix::WebSocket_MessageType_Error)
 | 
			
		||||
                        {
 | 
			
		||||
                            std::stringstream ss;
 | 
			
		||||
                            ss << "Connection error: " << error.reason      << std::endl;
 | 
			
		||||
@@ -54,11 +54,11 @@ namespace ix
 | 
			
		||||
                            ss << "HTTP Status: "      << error.http_status << std::endl;
 | 
			
		||||
                            std::cerr << ss.str();
 | 
			
		||||
                        }
 | 
			
		||||
                        else if (messageType == ix::WebSocketMessageType::Fragment)
 | 
			
		||||
                        else if (messageType == ix::WebSocket_MessageType_Fragment)
 | 
			
		||||
                        {
 | 
			
		||||
                            std::cerr << "Received message fragment" << std::endl;
 | 
			
		||||
                        }
 | 
			
		||||
                        else if (messageType == ix::WebSocketMessageType::Message)
 | 
			
		||||
                        else if (messageType == ix::WebSocket_MessageType_Message)
 | 
			
		||||
                        {
 | 
			
		||||
                            std::cerr << "Received " << wireSize << " bytes" << std::endl;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -68,7 +68,7 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
    bool WebSocketChat::isReady() const
 | 
			
		||||
    {
 | 
			
		||||
        return _webSocket.getReadyState() == ix::ReadyState::Open;
 | 
			
		||||
        return _webSocket.getReadyState() == ix::WebSocket_ReadyState_Open;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void WebSocketChat::stop()
 | 
			
		||||
@@ -92,7 +92,7 @@ namespace ix
 | 
			
		||||
               const ix::WebSocketCloseInfo& closeInfo)
 | 
			
		||||
            {
 | 
			
		||||
                std::stringstream ss;
 | 
			
		||||
                if (messageType == ix::WebSocketMessageType::Open)
 | 
			
		||||
                if (messageType == ix::WebSocket_MessageType_Open)
 | 
			
		||||
                {
 | 
			
		||||
                    log("ws chat: connected");
 | 
			
		||||
                    std::cout << "Uri: " << openInfo.uri << std::endl;
 | 
			
		||||
@@ -107,7 +107,7 @@ namespace ix
 | 
			
		||||
                       << " Connected !";
 | 
			
		||||
                       log(ss.str());
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Close)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Close)
 | 
			
		||||
                {
 | 
			
		||||
                    ss << "ws chat: user "
 | 
			
		||||
                       << _user
 | 
			
		||||
@@ -116,7 +116,7 @@ namespace ix
 | 
			
		||||
                       << " reason " << closeInfo.reason;
 | 
			
		||||
                       log(ss.str());
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Message)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Message)
 | 
			
		||||
                {
 | 
			
		||||
                    auto result = decodeMessage(str);
 | 
			
		||||
 | 
			
		||||
@@ -132,7 +132,7 @@ namespace ix
 | 
			
		||||
                       << _user << " > ";
 | 
			
		||||
                    log(ss.str());
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Error)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Error)
 | 
			
		||||
                {
 | 
			
		||||
                    ss << "Connection error: " << error.reason      << std::endl;
 | 
			
		||||
                    ss << "#retries: "         << error.retries     << std::endl;
 | 
			
		||||
 
 | 
			
		||||
@@ -36,6 +36,9 @@ namespace ix
 | 
			
		||||
    {
 | 
			
		||||
        if (disableAutomaticReconnection)
 | 
			
		||||
        {
 | 
			
		||||
            std::cout << "Disabling automatic reconnection with "
 | 
			
		||||
                         "_webSocket.disableAutomaticReconnection()"
 | 
			
		||||
                         " not supported yet" << std::endl;
 | 
			
		||||
            _webSocket.disableAutomaticReconnection();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@@ -70,7 +73,7 @@ namespace ix
 | 
			
		||||
               const ix::WebSocketCloseInfo& closeInfo)
 | 
			
		||||
            {
 | 
			
		||||
                std::stringstream ss;
 | 
			
		||||
                if (messageType == ix::WebSocketMessageType::Open)
 | 
			
		||||
                if (messageType == ix::WebSocket_MessageType_Open)
 | 
			
		||||
                {
 | 
			
		||||
                    log("ws_connect: connected");
 | 
			
		||||
                    std::cout << "Uri: " << openInfo.uri << std::endl;
 | 
			
		||||
@@ -80,14 +83,14 @@ namespace ix
 | 
			
		||||
                        std::cout << it.first << ": " << it.second << std::endl;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Close)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Close)
 | 
			
		||||
                {
 | 
			
		||||
                    ss << "ws_connect: connection closed:";
 | 
			
		||||
                    ss << " code " << closeInfo.code;
 | 
			
		||||
                    ss << " reason " << closeInfo.reason << std::endl;
 | 
			
		||||
                    log(ss.str());
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Message)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Message)
 | 
			
		||||
                {
 | 
			
		||||
                    std::cerr << "Received " << wireSize << " bytes" << std::endl;
 | 
			
		||||
 | 
			
		||||
@@ -95,7 +98,7 @@ namespace ix
 | 
			
		||||
                       << str;
 | 
			
		||||
                    log(ss.str());
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Error)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Error)
 | 
			
		||||
                {
 | 
			
		||||
                    ss << "Connection error: " << error.reason      << std::endl;
 | 
			
		||||
                    ss << "#retries: "         << error.retries     << std::endl;
 | 
			
		||||
@@ -103,15 +106,15 @@ namespace ix
 | 
			
		||||
                    ss << "HTTP Status: "      << error.http_status << std::endl;
 | 
			
		||||
                    log(ss.str());
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Fragment)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Fragment)
 | 
			
		||||
                {
 | 
			
		||||
                    std::cerr << "Received message fragment" << std::endl;
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Ping)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Ping)
 | 
			
		||||
                {
 | 
			
		||||
                    std::cerr << "Received ping" << std::endl;
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Pong)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Pong)
 | 
			
		||||
                {
 | 
			
		||||
                    std::cerr << "Received pong" << std::endl;
 | 
			
		||||
                }
 | 
			
		||||
 
 | 
			
		||||
@@ -28,7 +28,7 @@ namespace ix
 | 
			
		||||
                       const ix::WebSocketOpenInfo& openInfo,
 | 
			
		||||
                       const ix::WebSocketCloseInfo& closeInfo)
 | 
			
		||||
                    {
 | 
			
		||||
                        if (messageType == ix::WebSocketMessageType::Open)
 | 
			
		||||
                        if (messageType == ix::WebSocket_MessageType_Open)
 | 
			
		||||
                        {
 | 
			
		||||
                            std::cerr << "New connection" << std::endl;
 | 
			
		||||
                            std::cerr << "id: " << connectionState->getId() << std::endl;
 | 
			
		||||
@@ -39,13 +39,13 @@ namespace ix
 | 
			
		||||
                                std::cerr << it.first << ": " << it.second << std::endl;
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        else if (messageType == ix::WebSocketMessageType::Close)
 | 
			
		||||
                        else if (messageType == ix::WebSocket_MessageType_Close)
 | 
			
		||||
                        {
 | 
			
		||||
                            std::cerr << "Closed connection"
 | 
			
		||||
                                      << " code " << closeInfo.code
 | 
			
		||||
                                      << " reason " << closeInfo.reason << std::endl;
 | 
			
		||||
                        }
 | 
			
		||||
                        else if (messageType == ix::WebSocketMessageType::Error)
 | 
			
		||||
                        else if (messageType == ix::WebSocket_MessageType_Error)
 | 
			
		||||
                        {
 | 
			
		||||
                            std::stringstream ss;
 | 
			
		||||
                            ss << "Connection error: " << error.reason      << std::endl;
 | 
			
		||||
@@ -54,7 +54,7 @@ namespace ix
 | 
			
		||||
                            ss << "HTTP Status: "      << error.http_status << std::endl;
 | 
			
		||||
                            std::cerr << ss.str();
 | 
			
		||||
                        }
 | 
			
		||||
                        else if (messageType == ix::WebSocketMessageType::Message)
 | 
			
		||||
                        else if (messageType == ix::WebSocket_MessageType_Message)
 | 
			
		||||
                        {
 | 
			
		||||
                            std::cerr << "Received "
 | 
			
		||||
                                      << wireSize << " bytes"
 | 
			
		||||
 
 | 
			
		||||
@@ -150,12 +150,12 @@ namespace ix
 | 
			
		||||
        std::cerr << "Download size: " << downloadSize << std::endl;
 | 
			
		||||
 | 
			
		||||
        std::cerr << "Status: " << statusCode << std::endl;
 | 
			
		||||
        if (errorCode != HttpErrorCode::Ok)
 | 
			
		||||
        if (errorCode != HttpErrorCode_Ok)
 | 
			
		||||
        {
 | 
			
		||||
            std::cerr << "error message: " << errorMsg << std::endl;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!headersOnly && errorCode == HttpErrorCode::Ok)
 | 
			
		||||
        if (!headersOnly && errorCode == HttpErrorCode_Ok)
 | 
			
		||||
        {
 | 
			
		||||
            if (save || !output.empty())
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
@@ -64,7 +64,7 @@ namespace ix
 | 
			
		||||
                std::cerr << "Received " << wireSize << " bytes" << std::endl;
 | 
			
		||||
 | 
			
		||||
                std::stringstream ss;
 | 
			
		||||
                if (messageType == ix::WebSocketMessageType::Open)
 | 
			
		||||
                if (messageType == ix::WebSocket_MessageType_Open)
 | 
			
		||||
                {
 | 
			
		||||
                    log("ping_pong: connected");
 | 
			
		||||
 | 
			
		||||
@@ -75,7 +75,7 @@ namespace ix
 | 
			
		||||
                        std::cout << it.first << ": " << it.second << std::endl;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Close)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Close)
 | 
			
		||||
                {
 | 
			
		||||
                    ss << "ping_pong: disconnected:"
 | 
			
		||||
                       << " code " << closeInfo.code
 | 
			
		||||
@@ -83,25 +83,25 @@ namespace ix
 | 
			
		||||
                       << str;
 | 
			
		||||
                    log(ss.str());
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Message)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Message)
 | 
			
		||||
                {
 | 
			
		||||
                    ss << "ping_pong: received message: "
 | 
			
		||||
                       << str;
 | 
			
		||||
                    log(ss.str());
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Ping)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Ping)
 | 
			
		||||
                {
 | 
			
		||||
                    ss << "ping_pong: received ping message: "
 | 
			
		||||
                       << str;
 | 
			
		||||
                    log(ss.str());
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Pong)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Pong)
 | 
			
		||||
                {
 | 
			
		||||
                    ss << "ping_pong: received pong message: "
 | 
			
		||||
                       << str;
 | 
			
		||||
                    log(ss.str());
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Error)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Error)
 | 
			
		||||
                {
 | 
			
		||||
                    ss << "Connection error: " << error.reason      << std::endl;
 | 
			
		||||
                    ss << "#retries: "         << error.retries     << std::endl;
 | 
			
		||||
 
 | 
			
		||||
@@ -191,7 +191,7 @@ namespace ix
 | 
			
		||||
               const ix::WebSocketCloseInfo& closeInfo)
 | 
			
		||||
            {
 | 
			
		||||
                std::stringstream ss;
 | 
			
		||||
                if (messageType == ix::WebSocketMessageType::Open)
 | 
			
		||||
                if (messageType == ix::WebSocket_MessageType_Open)
 | 
			
		||||
                {
 | 
			
		||||
                    _condition.notify_one();
 | 
			
		||||
 | 
			
		||||
@@ -203,21 +203,21 @@ namespace ix
 | 
			
		||||
                        std::cout << it.first << ": " << it.second << std::endl;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Close)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Close)
 | 
			
		||||
                {
 | 
			
		||||
                    ss << "ws_receive: connection closed:";
 | 
			
		||||
                    ss << " code " << closeInfo.code;
 | 
			
		||||
                    ss << " reason " << closeInfo.reason << std::endl;
 | 
			
		||||
                    log(ss.str());
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Message)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Message)
 | 
			
		||||
                {
 | 
			
		||||
                    ss << "ws_receive: transfered " << wireSize << " bytes";
 | 
			
		||||
                    log(ss.str());
 | 
			
		||||
                    handleMessage(str);
 | 
			
		||||
                    _condition.notify_one();
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Fragment)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Fragment)
 | 
			
		||||
                {
 | 
			
		||||
                    ss << "ws_receive: received fragment " << _receivedFragmentCounter++;
 | 
			
		||||
                    log(ss.str());
 | 
			
		||||
@@ -229,7 +229,7 @@ namespace ix
 | 
			
		||||
                        std::this_thread::sleep_for(duration);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Error)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Error)
 | 
			
		||||
                {
 | 
			
		||||
                    ss << "ws_receive ";
 | 
			
		||||
                    ss << "Connection error: " << error.reason      << std::endl;
 | 
			
		||||
 
 | 
			
		||||
@@ -120,7 +120,7 @@ namespace ix
 | 
			
		||||
               const ix::WebSocketCloseInfo& closeInfo)
 | 
			
		||||
            {
 | 
			
		||||
                std::stringstream ss;
 | 
			
		||||
                if (messageType == ix::WebSocketMessageType::Open)
 | 
			
		||||
                if (messageType == ix::WebSocket_MessageType_Open)
 | 
			
		||||
                {
 | 
			
		||||
                    _condition.notify_one();
 | 
			
		||||
 | 
			
		||||
@@ -132,14 +132,14 @@ namespace ix
 | 
			
		||||
                        std::cout << it.first << ": " << it.second << std::endl;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Close)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Close)
 | 
			
		||||
                {
 | 
			
		||||
                    ss << "ws_send: connection closed:";
 | 
			
		||||
                    ss << " code " << closeInfo.code;
 | 
			
		||||
                    ss << " reason " << closeInfo.reason << std::endl;
 | 
			
		||||
                    log(ss.str());
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Message)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Message)
 | 
			
		||||
                {
 | 
			
		||||
                    _condition.notify_one();
 | 
			
		||||
 | 
			
		||||
@@ -160,7 +160,7 @@ namespace ix
 | 
			
		||||
                        std::cerr << "Invalid id" << std::endl;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else if (messageType == ix::WebSocketMessageType::Error)
 | 
			
		||||
                else if (messageType == ix::WebSocket_MessageType_Error)
 | 
			
		||||
                {
 | 
			
		||||
                    ss << "ws_send ";
 | 
			
		||||
                    ss << "Connection error: " << error.reason      << std::endl;
 | 
			
		||||
 
 | 
			
		||||
@@ -28,7 +28,7 @@ namespace ix
 | 
			
		||||
                       const ix::WebSocketOpenInfo& openInfo,
 | 
			
		||||
                       const ix::WebSocketCloseInfo& closeInfo)
 | 
			
		||||
                    {
 | 
			
		||||
                        if (messageType == ix::WebSocketMessageType::Open)
 | 
			
		||||
                        if (messageType == ix::WebSocket_MessageType_Open)
 | 
			
		||||
                        {
 | 
			
		||||
                            std::cerr << "New connection" << std::endl;
 | 
			
		||||
                            std::cerr << "id: " << connectionState->getId() << std::endl;
 | 
			
		||||
@@ -39,13 +39,13 @@ namespace ix
 | 
			
		||||
                                std::cerr << it.first << ": " << it.second << std::endl;
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        else if (messageType == ix::WebSocketMessageType::Close)
 | 
			
		||||
                        else if (messageType == ix::WebSocket_MessageType_Close)
 | 
			
		||||
                        {
 | 
			
		||||
                            std::cerr << "Closed connection"
 | 
			
		||||
                                      << " code " << closeInfo.code
 | 
			
		||||
                                      << " reason " << closeInfo.reason << std::endl;
 | 
			
		||||
                        }
 | 
			
		||||
                        else if (messageType == ix::WebSocketMessageType::Error)
 | 
			
		||||
                        else if (messageType == ix::WebSocket_MessageType_Error)
 | 
			
		||||
                        {
 | 
			
		||||
                            std::stringstream ss;
 | 
			
		||||
                            ss << "Connection error: " << error.reason      << std::endl;
 | 
			
		||||
@@ -54,12 +54,12 @@ namespace ix
 | 
			
		||||
                            ss << "HTTP Status: "      << error.http_status << std::endl;
 | 
			
		||||
                            std::cerr << ss.str();
 | 
			
		||||
                        }
 | 
			
		||||
                        else if (messageType == ix::WebSocketMessageType::Fragment)
 | 
			
		||||
                        else if (messageType == ix::WebSocket_MessageType_Fragment)
 | 
			
		||||
                        {
 | 
			
		||||
                            std::cerr << "Received message fragment "
 | 
			
		||||
                                      << std::endl;
 | 
			
		||||
                        }
 | 
			
		||||
                        else if (messageType == ix::WebSocketMessageType::Message)
 | 
			
		||||
                        else if (messageType == ix::WebSocket_MessageType_Message)
 | 
			
		||||
                        {
 | 
			
		||||
                            std::cerr << "Received " << wireSize << " bytes" << std::endl;
 | 
			
		||||
                            for (auto&& client : server.getClients())
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user