Compare commits
	
		
			1 Commits
		
	
	
		
			feature/te
			...
			bsergean-p
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					56f5527726 | 
							
								
								
									
										19
									
								
								.github/workflows/stale.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								.github/workflows/stale.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					name: Mark stale issues and pull requests
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					on:
 | 
				
			||||||
 | 
					  schedule:
 | 
				
			||||||
 | 
					  - cron: "0 0 * * *"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					jobs:
 | 
				
			||||||
 | 
					  stale:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    steps:
 | 
				
			||||||
 | 
					    - uses: actions/stale@v1
 | 
				
			||||||
 | 
					      with:
 | 
				
			||||||
 | 
					        repo-token: ${{ secrets.GITHUB_TOKEN }}
 | 
				
			||||||
 | 
					        stale-issue-message: 'Stale issue message'
 | 
				
			||||||
 | 
					        stale-pr-message: 'Stale pull request message'
 | 
				
			||||||
 | 
					        stale-issue-label: 'no-issue-activity'
 | 
				
			||||||
 | 
					        stale-pr-label: 'no-pr-activity'
 | 
				
			||||||
@@ -11,7 +11,6 @@ project(ixwebsocket C CXX)
 | 
				
			|||||||
set (CMAKE_CXX_STANDARD 11)
 | 
					set (CMAKE_CXX_STANDARD 11)
 | 
				
			||||||
set (CXX_STANDARD_REQUIRED ON)
 | 
					set (CXX_STANDARD_REQUIRED ON)
 | 
				
			||||||
set (CMAKE_CXX_EXTENSIONS OFF)
 | 
					set (CMAKE_CXX_EXTENSIONS OFF)
 | 
				
			||||||
set (CMAKE_EXPORT_COMPILE_COMMANDS yes)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
option (BUILD_DEMO OFF)
 | 
					option (BUILD_DEMO OFF)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -67,7 +66,6 @@ set( IXWEBSOCKET_SOURCES
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
set( IXWEBSOCKET_HEADERS
 | 
					set( IXWEBSOCKET_HEADERS
 | 
				
			||||||
    ixwebsocket/IXBase64.h
 | 
					 | 
				
			||||||
    ixwebsocket/IXBench.h
 | 
					    ixwebsocket/IXBench.h
 | 
				
			||||||
    ixwebsocket/IXCancellationRequest.h
 | 
					    ixwebsocket/IXCancellationRequest.h
 | 
				
			||||||
    ixwebsocket/IXConnectionState.h
 | 
					    ixwebsocket/IXConnectionState.h
 | 
				
			||||||
@@ -251,7 +249,7 @@ if (WIN32)
 | 
				
			|||||||
  endif()
 | 
					  endif()
 | 
				
			||||||
endif()
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (UNIX AND NOT APPLE)
 | 
					if (UNIX)
 | 
				
			||||||
  set(THREADS_PREFER_PTHREAD_FLAG TRUE)
 | 
					  set(THREADS_PREFER_PTHREAD_FLAG TRUE)
 | 
				
			||||||
  find_package(Threads)
 | 
					  find_package(Threads)
 | 
				
			||||||
  target_link_libraries(ixwebsocket PRIVATE Threads::Threads)
 | 
					  target_link_libraries(ixwebsocket PRIVATE Threads::Threads)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -35,7 +35,6 @@ int main()
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // Connect to a server with encryption
 | 
					    // Connect to a server with encryption
 | 
				
			||||||
    // See https://machinezone.github.io/IXWebSocket/usage/#tls-support-and-configuration
 | 
					    // See https://machinezone.github.io/IXWebSocket/usage/#tls-support-and-configuration
 | 
				
			||||||
    //     https://github.com/machinezone/IXWebSocket/issues/386#issuecomment-1105235227 (self signed certificates)
 | 
					 | 
				
			||||||
    std::string url("wss://echo.websocket.org");
 | 
					    std::string url("wss://echo.websocket.org");
 | 
				
			||||||
    webSocket.setUrl(url);
 | 
					    webSocket.setUrl(url);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,12 +2,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
All changes to this project will be documented in this file.
 | 
					All changes to this project will be documented in this file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## [11.4.3] - 2022-05-13
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Set shorter thread names
 | 
					 | 
				
			||||||
BoringSSL fix with SNI
 | 
					 | 
				
			||||||
Websocket computed header is valid Base64
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## [11.4.1] - 2022-04-23
 | 
					## [11.4.1] - 2022-04-23
 | 
				
			||||||
 | 
					
 | 
				
			||||||
vckpg + cmake fix, to handle zlib as a dependency better
 | 
					vckpg + cmake fix, to handle zlib as a dependency better
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -54,7 +54,7 @@ To use the installed package within a cmake project, use the following:
 | 
				
			|||||||
 # include headers
 | 
					 # include headers
 | 
				
			||||||
 include_directories(${IXWEBSOCKET_INCLUDE_DIR})
 | 
					 include_directories(${IXWEBSOCKET_INCLUDE_DIR})
 | 
				
			||||||
 # ...
 | 
					 # ...
 | 
				
			||||||
 target_link_libraries(${PROJECT_NAME} ... ${IXWEBSOCKET_LIBRARY}) # Cmake will automatically fail the generation if the lib was not found, i.e is set to NOTFOUND
 | 
					 target_link_libraries(${PROJECT_NAME} ... ${IXWEBSOCKET_LIBRARY}) # Cmake will automatically fail the generation if the lib was not found, i.e is set to NOTFOUNS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -301,9 +301,7 @@ This api was actually changed to take a weak_ptr<WebSocket> as the first argumen
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// Run a server on localhost at a given port.
 | 
					// Run a server on localhost at a given port.
 | 
				
			||||||
// Bound host name, max connections and listen backlog can also be passed in as parameters.
 | 
					// Bound host name, max connections and listen backlog can also be passed in as parameters.
 | 
				
			||||||
int port = 8008;
 | 
					ix::WebSocketServer server(port);
 | 
				
			||||||
std::string host("127.0.0.1"); // If you need this server to be accessible on a different machine, use "0.0.0.0"
 | 
					 | 
				
			||||||
ix::WebSocketServer server(port, host);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
server.setOnConnectionCallback(
 | 
					server.setOnConnectionCallback(
 | 
				
			||||||
    [&server](std::weak_ptr<WebSocket> webSocket,
 | 
					    [&server](std::weak_ptr<WebSocket> webSocket,
 | 
				
			||||||
@@ -386,9 +384,7 @@ The webSocket reference is guaranteed to be always valid ; by design the callbac
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// Run a server on localhost at a given port.
 | 
					// Run a server on localhost at a given port.
 | 
				
			||||||
// Bound host name, max connections and listen backlog can also be passed in as parameters.
 | 
					// Bound host name, max connections and listen backlog can also be passed in as parameters.
 | 
				
			||||||
int port = 8008;
 | 
					ix::WebSocketServer server(port);
 | 
				
			||||||
std::string host("127.0.0.1"); // If you need this server to be accessible on a different machine, use "0.0.0.0"
 | 
					 | 
				
			||||||
ix::WebSocketServer server(port, host);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
server.setOnClientMessageCallback([](std::shared_ptr<ix::ConnectionState> connectionState, ix::WebSocket & webSocket, const ix::WebSocketMessagePtr & msg) {
 | 
					server.setOnClientMessageCallback([](std::shared_ptr<ix::ConnectionState> connectionState, ix::WebSocket & webSocket, const ix::WebSocketMessagePtr & msg) {
 | 
				
			||||||
    // The ConnectionState object contains information about the connection,
 | 
					    // The ConnectionState object contains information about the connection,
 | 
				
			||||||
@@ -628,5 +624,3 @@ For a client, specifying `caFile` can be used if connecting to a server that use
 | 
				
			|||||||
For a server, specifying `caFile` implies that:
 | 
					For a server, specifying `caFile` implies that:
 | 
				
			||||||
1. You require clients to present a certificate
 | 
					1. You require clients to present a certificate
 | 
				
			||||||
1. It must be signed by one of the trusted roots in the file
 | 
					1. It must be signed by one of the trusted roots in the file
 | 
				
			||||||
 | 
					 | 
				
			||||||
By default, a destination's hostname is always validated against the certificate that it presents. To accept certificates with any hostname, set `ix::SocketTLSOptions::disable_hostname_validation` to `true`.
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,125 +0,0 @@
 | 
				
			|||||||
#ifndef _MACARON_BASE64_H_
 | 
					 | 
				
			||||||
#define _MACARON_BASE64_H_
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * The MIT License (MIT)
 | 
					 | 
				
			||||||
 * Copyright (c) 2016 tomykaira
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Permission is hereby granted, free of charge, to any person obtaining
 | 
					 | 
				
			||||||
 * a copy of this software and associated documentation files (the
 | 
					 | 
				
			||||||
 * "Software"), to deal in the Software without restriction, including
 | 
					 | 
				
			||||||
 * without limitation the rights to use, copy, modify, merge, publish,
 | 
					 | 
				
			||||||
 * distribute, sublicense, and/or sell copies of the Software, and to
 | 
					 | 
				
			||||||
 * permit persons to whom the Software is furnished to do so, subject to
 | 
					 | 
				
			||||||
 * the following conditions:
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * The above copyright notice and this permission notice shall be
 | 
					 | 
				
			||||||
 * included in all copies or substantial portions of the Software.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 | 
					 | 
				
			||||||
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 | 
					 | 
				
			||||||
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 | 
					 | 
				
			||||||
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 | 
					 | 
				
			||||||
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 | 
					 | 
				
			||||||
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 | 
					 | 
				
			||||||
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <cstdint>
 | 
					 | 
				
			||||||
#include <string>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace macaron {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class Base64 {
 | 
					 | 
				
			||||||
 public:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  static std::string Encode(const std::string data) {
 | 
					 | 
				
			||||||
    static constexpr char sEncodingTable[] = {
 | 
					 | 
				
			||||||
      'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
 | 
					 | 
				
			||||||
      'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
 | 
					 | 
				
			||||||
      'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
 | 
					 | 
				
			||||||
      'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
 | 
					 | 
				
			||||||
      'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
 | 
					 | 
				
			||||||
      'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
 | 
					 | 
				
			||||||
      'w', 'x', 'y', 'z', '0', '1', '2', '3',
 | 
					 | 
				
			||||||
      '4', '5', '6', '7', '8', '9', '+', '/'
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    size_t in_len = data.size();
 | 
					 | 
				
			||||||
    size_t out_len = 4 * ((in_len + 2) / 3);
 | 
					 | 
				
			||||||
    std::string ret(out_len, '\0');
 | 
					 | 
				
			||||||
    size_t i;
 | 
					 | 
				
			||||||
    char *p = const_cast<char*>(ret.c_str());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for (i = 0; i < in_len - 2; i += 3) {
 | 
					 | 
				
			||||||
      *p++ = sEncodingTable[(data[i] >> 2) & 0x3F];
 | 
					 | 
				
			||||||
      *p++ = sEncodingTable[((data[i] & 0x3) << 4) | ((int) (data[i + 1] & 0xF0) >> 4)];
 | 
					 | 
				
			||||||
      *p++ = sEncodingTable[((data[i + 1] & 0xF) << 2) | ((int) (data[i + 2] & 0xC0) >> 6)];
 | 
					 | 
				
			||||||
      *p++ = sEncodingTable[data[i + 2] & 0x3F];
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (i < in_len) {
 | 
					 | 
				
			||||||
      *p++ = sEncodingTable[(data[i] >> 2) & 0x3F];
 | 
					 | 
				
			||||||
      if (i == (in_len - 1)) {
 | 
					 | 
				
			||||||
        *p++ = sEncodingTable[((data[i] & 0x3) << 4)];
 | 
					 | 
				
			||||||
        *p++ = '=';
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      else {
 | 
					 | 
				
			||||||
        *p++ = sEncodingTable[((data[i] & 0x3) << 4) | ((int) (data[i + 1] & 0xF0) >> 4)];
 | 
					 | 
				
			||||||
        *p++ = sEncodingTable[((data[i + 1] & 0xF) << 2)];
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      *p++ = '=';
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return ret;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  static std::string Decode(const std::string& input, std::string& out) {
 | 
					 | 
				
			||||||
    static constexpr unsigned char kDecodingTable[] = {
 | 
					 | 
				
			||||||
      64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
 | 
					 | 
				
			||||||
      64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
 | 
					 | 
				
			||||||
      64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
 | 
					 | 
				
			||||||
      52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
 | 
					 | 
				
			||||||
      64,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
 | 
					 | 
				
			||||||
      15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
 | 
					 | 
				
			||||||
      64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
 | 
					 | 
				
			||||||
      41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64,
 | 
					 | 
				
			||||||
      64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
 | 
					 | 
				
			||||||
      64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
 | 
					 | 
				
			||||||
      64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
 | 
					 | 
				
			||||||
      64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
 | 
					 | 
				
			||||||
      64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
 | 
					 | 
				
			||||||
      64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
 | 
					 | 
				
			||||||
      64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
 | 
					 | 
				
			||||||
      64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    size_t in_len = input.size();
 | 
					 | 
				
			||||||
    if (in_len % 4 != 0) return "Input data size is not a multiple of 4";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    size_t out_len = in_len / 4 * 3;
 | 
					 | 
				
			||||||
    if (input[in_len - 1] == '=') out_len--;
 | 
					 | 
				
			||||||
    if (input[in_len - 2] == '=') out_len--;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    out.resize(out_len);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for (size_t i = 0, j = 0; i < in_len;) {
 | 
					 | 
				
			||||||
      uint32_t a = input[i] == '=' ? 0 & i++ : kDecodingTable[static_cast<int>(input[i++])];
 | 
					 | 
				
			||||||
      uint32_t b = input[i] == '=' ? 0 & i++ : kDecodingTable[static_cast<int>(input[i++])];
 | 
					 | 
				
			||||||
      uint32_t c = input[i] == '=' ? 0 & i++ : kDecodingTable[static_cast<int>(input[i++])];
 | 
					 | 
				
			||||||
      uint32_t d = input[i] == '=' ? 0 & i++ : kDecodingTable[static_cast<int>(input[i++])];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      uint32_t triple = (a << 3 * 6) + (b << 2 * 6) + (c << 1 * 6) + (d << 0 * 6);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      if (j < out_len) out[j++] = (triple >> 2 * 8) & 0xFF;
 | 
					 | 
				
			||||||
      if (j < out_len) out[j++] = (triple >> 1 * 8) & 0xFF;
 | 
					 | 
				
			||||||
      if (j < out_len) out[j++] = (triple >> 0 * 8) & 0xFF;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return "";
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif /* _MACARON_BASE64_H_ */
 | 
					 | 
				
			||||||
@@ -6,7 +6,7 @@
 | 
				
			|||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <chrono>
 | 
					#include <chrono>
 | 
				
			||||||
#include <cstdint>
 | 
					#include <stdint.h>
 | 
				
			||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace ix
 | 
					namespace ix
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,9 +7,9 @@
 | 
				
			|||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <atomic>
 | 
					#include <atomic>
 | 
				
			||||||
#include <cstdint>
 | 
					 | 
				
			||||||
#include <functional>
 | 
					#include <functional>
 | 
				
			||||||
#include <memory>
 | 
					#include <memory>
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace ix
 | 
					namespace ix
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,7 +23,6 @@
 | 
				
			|||||||
#include <chrono>
 | 
					#include <chrono>
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
#include <thread>
 | 
					#include <thread>
 | 
				
			||||||
#include <utility>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
// mingw build quirks
 | 
					// mingw build quirks
 | 
				
			||||||
#if defined(_WIN32) && defined(__GNUC__)
 | 
					#if defined(_WIN32) && defined(__GNUC__)
 | 
				
			||||||
@@ -45,7 +44,7 @@ namespace ix
 | 
				
			|||||||
        ;
 | 
					        ;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    DNSLookup::AddrInfoPtr DNSLookup::getAddrInfo(const std::string& hostname,
 | 
					    struct addrinfo* DNSLookup::getAddrInfo(const std::string& hostname,
 | 
				
			||||||
                                            int port,
 | 
					                                            int port,
 | 
				
			||||||
                                            std::string& errMsg)
 | 
					                                            std::string& errMsg)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@@ -64,10 +63,10 @@ namespace ix
 | 
				
			|||||||
            errMsg = gai_strerror(getaddrinfo_result);
 | 
					            errMsg = gai_strerror(getaddrinfo_result);
 | 
				
			||||||
            res = nullptr;
 | 
					            res = nullptr;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return AddrInfoPtr{ res, freeaddrinfo };
 | 
					        return res;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    DNSLookup::AddrInfoPtr DNSLookup::resolve(std::string& errMsg,
 | 
					    struct addrinfo* DNSLookup::resolve(std::string& errMsg,
 | 
				
			||||||
                                        const CancellationRequest& isCancellationRequested,
 | 
					                                        const CancellationRequest& isCancellationRequested,
 | 
				
			||||||
                                        bool cancellable)
 | 
					                                        bool cancellable)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@@ -75,7 +74,12 @@ namespace ix
 | 
				
			|||||||
                           : resolveUnCancellable(errMsg, isCancellationRequested);
 | 
					                           : resolveUnCancellable(errMsg, isCancellationRequested);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    DNSLookup::AddrInfoPtr DNSLookup::resolveUnCancellable(
 | 
					    void DNSLookup::release(struct addrinfo* addr)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        freeaddrinfo(addr);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct addrinfo* DNSLookup::resolveUnCancellable(
 | 
				
			||||||
        std::string& errMsg, const CancellationRequest& isCancellationRequested)
 | 
					        std::string& errMsg, const CancellationRequest& isCancellationRequested)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        errMsg = "no error";
 | 
					        errMsg = "no error";
 | 
				
			||||||
@@ -90,7 +94,7 @@ namespace ix
 | 
				
			|||||||
        return getAddrInfo(_hostname, _port, errMsg);
 | 
					        return getAddrInfo(_hostname, _port, errMsg);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    DNSLookup::AddrInfoPtr DNSLookup::resolveCancellable(
 | 
					    struct addrinfo* DNSLookup::resolveCancellable(
 | 
				
			||||||
        std::string& errMsg, const CancellationRequest& isCancellationRequested)
 | 
					        std::string& errMsg, const CancellationRequest& isCancellationRequested)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        errMsg = "no error";
 | 
					        errMsg = "no error";
 | 
				
			||||||
@@ -153,7 +157,7 @@ namespace ix
 | 
				
			|||||||
        // gone, so we use temporary variables (res) or we pass in by copy everything that
 | 
					        // gone, so we use temporary variables (res) or we pass in by copy everything that
 | 
				
			||||||
        // getAddrInfo needs to work.
 | 
					        // getAddrInfo needs to work.
 | 
				
			||||||
        std::string errMsg;
 | 
					        std::string errMsg;
 | 
				
			||||||
        auto res = getAddrInfo(hostname, port, errMsg);
 | 
					        struct addrinfo* res = getAddrInfo(hostname, port, errMsg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (auto lock = self.lock())
 | 
					        if (auto lock = self.lock())
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@@ -177,13 +181,13 @@ namespace ix
 | 
				
			|||||||
        return _errMsg;
 | 
					        return _errMsg;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void DNSLookup::setRes(DNSLookup::AddrInfoPtr addr)
 | 
					    void DNSLookup::setRes(struct addrinfo* addr)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        std::lock_guard<std::mutex> lock(_resMutex);
 | 
					        std::lock_guard<std::mutex> lock(_resMutex);
 | 
				
			||||||
        _res = std::move(addr);
 | 
					        _res = addr;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    DNSLookup::AddrInfoPtr DNSLookup::getRes()
 | 
					    struct addrinfo* DNSLookup::getRes()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        std::lock_guard<std::mutex> lock(_resMutex);
 | 
					        std::lock_guard<std::mutex> lock(_resMutex);
 | 
				
			||||||
        return _res;
 | 
					        return _res;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,7 +12,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "IXCancellationRequest.h"
 | 
					#include "IXCancellationRequest.h"
 | 
				
			||||||
#include <atomic>
 | 
					#include <atomic>
 | 
				
			||||||
#include <cstdint>
 | 
					 | 
				
			||||||
#include <memory>
 | 
					#include <memory>
 | 
				
			||||||
#include <mutex>
 | 
					#include <mutex>
 | 
				
			||||||
#include <set>
 | 
					#include <set>
 | 
				
			||||||
@@ -25,21 +24,22 @@ namespace ix
 | 
				
			|||||||
    class DNSLookup : public std::enable_shared_from_this<DNSLookup>
 | 
					    class DNSLookup : public std::enable_shared_from_this<DNSLookup>
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        using AddrInfoPtr = std::shared_ptr<addrinfo>;
 | 
					 | 
				
			||||||
        DNSLookup(const std::string& hostname, int port, int64_t wait = DNSLookup::kDefaultWait);
 | 
					        DNSLookup(const std::string& hostname, int port, int64_t wait = DNSLookup::kDefaultWait);
 | 
				
			||||||
        ~DNSLookup() = default;
 | 
					        ~DNSLookup() = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        AddrInfoPtr resolve(std::string& errMsg,
 | 
					        struct addrinfo* resolve(std::string& errMsg,
 | 
				
			||||||
                                 const CancellationRequest& isCancellationRequested,
 | 
					                                 const CancellationRequest& isCancellationRequested,
 | 
				
			||||||
                                 bool cancellable = true);
 | 
					                                 bool cancellable = true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void release(struct addrinfo* addr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private:
 | 
					    private:
 | 
				
			||||||
        AddrInfoPtr resolveCancellable(std::string& errMsg,
 | 
					        struct addrinfo* resolveCancellable(std::string& errMsg,
 | 
				
			||||||
                                            const CancellationRequest& isCancellationRequested);
 | 
					                                            const CancellationRequest& isCancellationRequested);
 | 
				
			||||||
        AddrInfoPtr resolveUnCancellable(std::string& errMsg,
 | 
					        struct addrinfo* resolveUnCancellable(std::string& errMsg,
 | 
				
			||||||
                                              const CancellationRequest& isCancellationRequested);
 | 
					                                              const CancellationRequest& isCancellationRequested);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        AddrInfoPtr getAddrInfo(const std::string& hostname,
 | 
					        static struct addrinfo* getAddrInfo(const std::string& hostname,
 | 
				
			||||||
                                            int port,
 | 
					                                            int port,
 | 
				
			||||||
                                            std::string& errMsg);
 | 
					                                            std::string& errMsg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -48,15 +48,15 @@ namespace ix
 | 
				
			|||||||
        void setErrMsg(const std::string& errMsg);
 | 
					        void setErrMsg(const std::string& errMsg);
 | 
				
			||||||
        const std::string& getErrMsg();
 | 
					        const std::string& getErrMsg();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void setRes(AddrInfoPtr addr);
 | 
					        void setRes(struct addrinfo* addr);
 | 
				
			||||||
        AddrInfoPtr getRes();
 | 
					        struct addrinfo* getRes();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        std::string _hostname;
 | 
					        std::string _hostname;
 | 
				
			||||||
        int _port;
 | 
					        int _port;
 | 
				
			||||||
        int64_t _wait;
 | 
					        int64_t _wait;
 | 
				
			||||||
        const static int64_t kDefaultWait;
 | 
					        const static int64_t kDefaultWait;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        AddrInfoPtr _res;
 | 
					        struct addrinfo* _res;
 | 
				
			||||||
        std::mutex _resMutex;
 | 
					        std::mutex _resMutex;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        std::string _errMsg;
 | 
					        std::string _errMsg;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,7 +9,6 @@
 | 
				
			|||||||
#include "IXProgressCallback.h"
 | 
					#include "IXProgressCallback.h"
 | 
				
			||||||
#include "IXWebSocketHttpHeaders.h"
 | 
					#include "IXWebSocketHttpHeaders.h"
 | 
				
			||||||
#include <atomic>
 | 
					#include <atomic>
 | 
				
			||||||
#include <cstdint>
 | 
					 | 
				
			||||||
#include <tuple>
 | 
					#include <tuple>
 | 
				
			||||||
#include <unordered_map>
 | 
					#include <unordered_map>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,7 +12,6 @@
 | 
				
			|||||||
#include "IXUserAgent.h"
 | 
					#include "IXUserAgent.h"
 | 
				
			||||||
#include "IXWebSocketHttpHeaders.h"
 | 
					#include "IXWebSocketHttpHeaders.h"
 | 
				
			||||||
#include <assert.h>
 | 
					#include <assert.h>
 | 
				
			||||||
#include <cstdint>
 | 
					 | 
				
			||||||
#include <cstring>
 | 
					#include <cstring>
 | 
				
			||||||
#include <iomanip>
 | 
					#include <iomanip>
 | 
				
			||||||
#include <random>
 | 
					#include <random>
 | 
				
			||||||
@@ -140,9 +139,8 @@ namespace ix
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        std::string protocol, host, path, query;
 | 
					        std::string protocol, host, path, query;
 | 
				
			||||||
        int port;
 | 
					        int port;
 | 
				
			||||||
        bool isProtocolDefaultPort;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!UrlParser::parse(url, protocol, host, path, query, port, isProtocolDefaultPort))
 | 
					        if (!UrlParser::parse(url, protocol, host, path, query, port))
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            std::stringstream ss;
 | 
					            std::stringstream ss;
 | 
				
			||||||
            ss << "Cannot parse url: " << url;
 | 
					            ss << "Cannot parse url: " << url;
 | 
				
			||||||
@@ -175,12 +173,7 @@ namespace ix
 | 
				
			|||||||
        // Build request string
 | 
					        // Build request string
 | 
				
			||||||
        std::stringstream ss;
 | 
					        std::stringstream ss;
 | 
				
			||||||
        ss << verb << " " << path << " HTTP/1.1\r\n";
 | 
					        ss << verb << " " << path << " HTTP/1.1\r\n";
 | 
				
			||||||
        ss << "Host: " << host;
 | 
					        ss << "Host: " << host << "\r\n";
 | 
				
			||||||
        if (!isProtocolDefaultPort)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            ss << ":" << port;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        ss << "\r\n";
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef IXWEBSOCKET_USE_ZLIB
 | 
					#ifdef IXWEBSOCKET_USE_ZLIB
 | 
				
			||||||
        if (args->compress && !args->onChunkCallback)
 | 
					        if (args->compress && !args->onChunkCallback)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,7 +10,6 @@
 | 
				
			|||||||
#include "IXNetSystem.h"
 | 
					#include "IXNetSystem.h"
 | 
				
			||||||
#include "IXSocketConnect.h"
 | 
					#include "IXSocketConnect.h"
 | 
				
			||||||
#include "IXUserAgent.h"
 | 
					#include "IXUserAgent.h"
 | 
				
			||||||
#include <cstdint>
 | 
					 | 
				
			||||||
#include <cstring>
 | 
					#include <cstring>
 | 
				
			||||||
#include <fstream>
 | 
					#include <fstream>
 | 
				
			||||||
#include <sstream>
 | 
					#include <sstream>
 | 
				
			||||||
@@ -41,29 +40,6 @@ namespace
 | 
				
			|||||||
        auto vec = res.second;
 | 
					        auto vec = res.second;
 | 
				
			||||||
        return std::make_pair(res.first, std::string(vec.begin(), vec.end()));
 | 
					        return std::make_pair(res.first, std::string(vec.begin(), vec.end()));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    std::string response_head_file(const std::string& file_name){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (std::string::npos != file_name.find(".html") || std::string::npos != file_name.find(".htm"))
 | 
					 | 
				
			||||||
            return "text/html";
 | 
					 | 
				
			||||||
        else if (std::string::npos != file_name.find(".css"))
 | 
					 | 
				
			||||||
            return "text/css";
 | 
					 | 
				
			||||||
        else if (std::string::npos != file_name.find(".js") || std::string::npos != file_name.find(".mjs"))
 | 
					 | 
				
			||||||
            return "application/x-javascript";
 | 
					 | 
				
			||||||
        else if (std::string::npos != file_name.find(".ico"))
 | 
					 | 
				
			||||||
            return "image/x-icon";
 | 
					 | 
				
			||||||
        else if (std::string::npos != file_name.find(".png"))
 | 
					 | 
				
			||||||
            return "image/png";
 | 
					 | 
				
			||||||
        else if (std::string::npos != file_name.find(".jpg") || std::string::npos != file_name.find(".jpeg"))
 | 
					 | 
				
			||||||
            return "image/jpeg";
 | 
					 | 
				
			||||||
        else if (std::string::npos != file_name.find(".gif"))
 | 
					 | 
				
			||||||
            return "image/gif";
 | 
					 | 
				
			||||||
        else if (std::string::npos != file_name.find(".svg"))
 | 
					 | 
				
			||||||
            return "image/svg+xml";
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
            return "application/octet-stream";
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
} // namespace
 | 
					} // namespace
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace ix
 | 
					namespace ix
 | 
				
			||||||
@@ -75,14 +51,28 @@ namespace ix
 | 
				
			|||||||
                           int backlog,
 | 
					                           int backlog,
 | 
				
			||||||
                           size_t maxConnections,
 | 
					                           size_t maxConnections,
 | 
				
			||||||
                           int addressFamily,
 | 
					                           int addressFamily,
 | 
				
			||||||
                           int timeoutSecs,
 | 
					                           int timeoutSecs)
 | 
				
			||||||
                           int handshakeTimeoutSecs)
 | 
					        : SocketServer(port, host, backlog, maxConnections, addressFamily)
 | 
				
			||||||
        : WebSocketServer(port, host, backlog, maxConnections, handshakeTimeoutSecs, addressFamily)
 | 
					        , _connectedClientsCount(0)
 | 
				
			||||||
        , _timeoutSecs(timeoutSecs)
 | 
					        , _timeoutSecs(timeoutSecs)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        setDefaultConnectionCallback();
 | 
					        setDefaultConnectionCallback();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    HttpServer::~HttpServer()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        stop();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void HttpServer::stop()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        stopAcceptingConnections();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // FIXME: cancelling / closing active clients ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        SocketServer::stop();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void HttpServer::setOnConnectionCallback(const OnConnectionCallback& callback)
 | 
					    void HttpServer::setOnConnectionCallback(const OnConnectionCallback& callback)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        _onConnectionCallback = callback;
 | 
					        _onConnectionCallback = callback;
 | 
				
			||||||
@@ -91,35 +81,34 @@ namespace ix
 | 
				
			|||||||
    void HttpServer::handleConnection(std::unique_ptr<Socket> socket,
 | 
					    void HttpServer::handleConnection(std::unique_ptr<Socket> socket,
 | 
				
			||||||
                                      std::shared_ptr<ConnectionState> connectionState)
 | 
					                                      std::shared_ptr<ConnectionState> connectionState)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        _connectedClientsCount++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        auto ret = Http::parseRequest(socket, _timeoutSecs);
 | 
					        auto ret = Http::parseRequest(socket, _timeoutSecs);
 | 
				
			||||||
        // FIXME: handle errors in parseRequest
 | 
					        // FIXME: handle errors in parseRequest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (std::get<0>(ret))
 | 
					        if (std::get<0>(ret))
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            auto request = std::get<2>(ret);
 | 
					            auto response = _onConnectionCallback(std::get<2>(ret), connectionState);
 | 
				
			||||||
            std::shared_ptr<ix::HttpResponse> response;
 | 
					            if (!Http::sendResponse(response, socket))
 | 
				
			||||||
            if (request->headers["Upgrade"] == "websocket")
 | 
					 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                WebSocketServer::handleUpgrade(std::move(socket), connectionState, request);
 | 
					                logError("Cannot send response");
 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                auto response = _onConnectionCallback(request, connectionState);
 | 
					 | 
				
			||||||
                if (!Http::sendResponse(response, socket))
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    logError("Cannot send response");
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        connectionState->setTerminated();
 | 
					        connectionState->setTerminated();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        _connectedClientsCount--;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    size_t HttpServer::getConnectedClientsCount()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return _connectedClientsCount;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void HttpServer::setDefaultConnectionCallback()
 | 
					    void HttpServer::setDefaultConnectionCallback()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        setOnConnectionCallback(
 | 
					        setOnConnectionCallback(
 | 
				
			||||||
            [this](HttpRequestPtr request,
 | 
					            [this](HttpRequestPtr request,
 | 
				
			||||||
                   std::shared_ptr<ConnectionState> connectionState) -> HttpResponsePtr
 | 
					                   std::shared_ptr<ConnectionState> connectionState) -> HttpResponsePtr {
 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                std::string uri(request->uri);
 | 
					                std::string uri(request->uri);
 | 
				
			||||||
                if (uri.empty() || uri == "/")
 | 
					                if (uri.empty() || uri == "/")
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
@@ -128,7 +117,6 @@ namespace ix
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                WebSocketHttpHeaders headers;
 | 
					                WebSocketHttpHeaders headers;
 | 
				
			||||||
                headers["Server"] = userAgent();
 | 
					                headers["Server"] = userAgent();
 | 
				
			||||||
                headers["Content-Type"] = response_head_file(uri);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                std::string path("." + uri);
 | 
					                std::string path("." + uri);
 | 
				
			||||||
                auto res = readAsString(path);
 | 
					                auto res = readAsString(path);
 | 
				
			||||||
@@ -177,9 +165,9 @@ namespace ix
 | 
				
			|||||||
        // See https://developer.mozilla.org/en-US/docs/Web/HTTP/Redirections
 | 
					        // See https://developer.mozilla.org/en-US/docs/Web/HTTP/Redirections
 | 
				
			||||||
        //
 | 
					        //
 | 
				
			||||||
        setOnConnectionCallback(
 | 
					        setOnConnectionCallback(
 | 
				
			||||||
            [this, redirectUrl](HttpRequestPtr request,
 | 
					            [this,
 | 
				
			||||||
                                std::shared_ptr<ConnectionState> connectionState) -> HttpResponsePtr
 | 
					             redirectUrl](HttpRequestPtr request,
 | 
				
			||||||
            {
 | 
					                          std::shared_ptr<ConnectionState> connectionState) -> HttpResponsePtr {
 | 
				
			||||||
                WebSocketHttpHeaders headers;
 | 
					                WebSocketHttpHeaders headers;
 | 
				
			||||||
                headers["Server"] = userAgent();
 | 
					                headers["Server"] = userAgent();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -210,8 +198,7 @@ namespace ix
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        setOnConnectionCallback(
 | 
					        setOnConnectionCallback(
 | 
				
			||||||
            [this](HttpRequestPtr request,
 | 
					            [this](HttpRequestPtr request,
 | 
				
			||||||
                   std::shared_ptr<ConnectionState> connectionState) -> HttpResponsePtr
 | 
					                   std::shared_ptr<ConnectionState> connectionState) -> HttpResponsePtr {
 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                WebSocketHttpHeaders headers;
 | 
					                WebSocketHttpHeaders headers;
 | 
				
			||||||
                headers["Server"] = userAgent();
 | 
					                headers["Server"] = userAgent();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,8 +7,8 @@
 | 
				
			|||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "IXHttp.h"
 | 
					#include "IXHttp.h"
 | 
				
			||||||
 | 
					#include "IXSocketServer.h"
 | 
				
			||||||
#include "IXWebSocket.h"
 | 
					#include "IXWebSocket.h"
 | 
				
			||||||
#include "IXWebSocketServer.h"
 | 
					 | 
				
			||||||
#include <functional>
 | 
					#include <functional>
 | 
				
			||||||
#include <memory>
 | 
					#include <memory>
 | 
				
			||||||
#include <mutex>
 | 
					#include <mutex>
 | 
				
			||||||
@@ -19,7 +19,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace ix
 | 
					namespace ix
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    class HttpServer final : public WebSocketServer
 | 
					    class HttpServer final : public SocketServer
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        using OnConnectionCallback =
 | 
					        using OnConnectionCallback =
 | 
				
			||||||
@@ -30,8 +30,9 @@ namespace ix
 | 
				
			|||||||
                   int backlog = SocketServer::kDefaultTcpBacklog,
 | 
					                   int backlog = SocketServer::kDefaultTcpBacklog,
 | 
				
			||||||
                   size_t maxConnections = SocketServer::kDefaultMaxConnections,
 | 
					                   size_t maxConnections = SocketServer::kDefaultMaxConnections,
 | 
				
			||||||
                   int addressFamily = SocketServer::kDefaultAddressFamily,
 | 
					                   int addressFamily = SocketServer::kDefaultAddressFamily,
 | 
				
			||||||
                   int timeoutSecs = HttpServer::kDefaultTimeoutSecs,
 | 
					                   int timeoutSecs = HttpServer::kDefaultTimeoutSecs);
 | 
				
			||||||
                   int handshakeTimeoutSecs = WebSocketServer::kDefaultHandShakeTimeoutSecs);
 | 
					        virtual ~HttpServer();
 | 
				
			||||||
 | 
					        virtual void stop() final;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void setOnConnectionCallback(const OnConnectionCallback& callback);
 | 
					        void setOnConnectionCallback(const OnConnectionCallback& callback);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -40,10 +41,10 @@ namespace ix
 | 
				
			|||||||
        void makeDebugServer();
 | 
					        void makeDebugServer();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        int getTimeoutSecs();
 | 
					        int getTimeoutSecs();
 | 
				
			||||||
 | 
					 | 
				
			||||||
    private:
 | 
					    private:
 | 
				
			||||||
        // Member variables
 | 
					        // Member variables
 | 
				
			||||||
        OnConnectionCallback _onConnectionCallback;
 | 
					        OnConnectionCallback _onConnectionCallback;
 | 
				
			||||||
 | 
					        std::atomic<int> _connectedClientsCount;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const static int kDefaultTimeoutSecs;
 | 
					        const static int kDefaultTimeoutSecs;
 | 
				
			||||||
        int _timeoutSecs;
 | 
					        int _timeoutSecs;
 | 
				
			||||||
@@ -51,6 +52,7 @@ namespace ix
 | 
				
			|||||||
        // Methods
 | 
					        // Methods
 | 
				
			||||||
        virtual void handleConnection(std::unique_ptr<Socket>,
 | 
					        virtual void handleConnection(std::unique_ptr<Socket>,
 | 
				
			||||||
                                      std::shared_ptr<ConnectionState> connectionState) final;
 | 
					                                      std::shared_ptr<ConnectionState> connectionState) final;
 | 
				
			||||||
 | 
					        virtual size_t getConnectedClientsCount() final;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void setDefaultConnectionCallback();
 | 
					        void setDefaultConnectionCallback();
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,8 +6,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <cstdint>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef _WIN32
 | 
					#ifdef _WIN32
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef WIN32_LEAN_AND_MEAN
 | 
					#ifndef WIN32_LEAN_AND_MEAN
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,8 +6,8 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <cstdint>
 | 
					 | 
				
			||||||
#include <memory>
 | 
					#include <memory>
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace ix
 | 
					namespace ix
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,8 +5,8 @@
 | 
				
			|||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "IXSelectInterrupt.h"
 | 
					#include "IXSelectInterrupt.h"
 | 
				
			||||||
#include <cstdint>
 | 
					 | 
				
			||||||
#include <mutex>
 | 
					#include <mutex>
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
#include <deque>
 | 
					#include <deque>
 | 
				
			||||||
#ifdef _WIN32
 | 
					#ifdef _WIN32
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,7 +7,6 @@
 | 
				
			|||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "IXSelectInterrupt.h"
 | 
					#include "IXSelectInterrupt.h"
 | 
				
			||||||
#include <cstdint>
 | 
					 | 
				
			||||||
#include <mutex>
 | 
					#include <mutex>
 | 
				
			||||||
#include <stdint.h>
 | 
					#include <stdint.h>
 | 
				
			||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,6 +14,7 @@
 | 
				
			|||||||
#include <array>
 | 
					#include <array>
 | 
				
			||||||
#include <assert.h>
 | 
					#include <assert.h>
 | 
				
			||||||
#include <fcntl.h>
 | 
					#include <fcntl.h>
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,7 +7,6 @@
 | 
				
			|||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <atomic>
 | 
					#include <atomic>
 | 
				
			||||||
#include <cstdint>
 | 
					 | 
				
			||||||
#include <functional>
 | 
					#include <functional>
 | 
				
			||||||
#include <memory>
 | 
					#include <memory>
 | 
				
			||||||
#include <mutex>
 | 
					#include <mutex>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -205,9 +205,7 @@ namespace ix
 | 
				
			|||||||
                _sslContext, SocketAppleSSL::readFromSocket, SocketAppleSSL::writeToSocket);
 | 
					                _sslContext, SocketAppleSSL::readFromSocket, SocketAppleSSL::writeToSocket);
 | 
				
			||||||
            SSLSetConnection(_sslContext, (SSLConnectionRef)(long) _sockfd);
 | 
					            SSLSetConnection(_sslContext, (SSLConnectionRef)(long) _sockfd);
 | 
				
			||||||
            SSLSetProtocolVersionMin(_sslContext, kTLSProtocol12);
 | 
					            SSLSetProtocolVersionMin(_sslContext, kTLSProtocol12);
 | 
				
			||||||
 | 
					            SSLSetPeerDomainName(_sslContext, host.c_str(), host.size());
 | 
				
			||||||
            if (!_tlsOptions.disable_hostname_validation)
 | 
					 | 
				
			||||||
                SSLSetPeerDomainName(_sslContext, host.c_str(), host.size());
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (_tlsOptions.isPeerVerifyDisabled())
 | 
					            if (_tlsOptions.isPeerVerifyDisabled())
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -102,7 +102,7 @@ namespace ix
 | 
				
			|||||||
        // First do DNS resolution
 | 
					        // First do DNS resolution
 | 
				
			||||||
        //
 | 
					        //
 | 
				
			||||||
        auto dnsLookup = std::make_shared<DNSLookup>(hostname, port);
 | 
					        auto dnsLookup = std::make_shared<DNSLookup>(hostname, port);
 | 
				
			||||||
        auto res = dnsLookup->resolve(errMsg, isCancellationRequested);
 | 
					        struct addrinfo* res = dnsLookup->resolve(errMsg, isCancellationRequested);
 | 
				
			||||||
        if (res == nullptr)
 | 
					        if (res == nullptr)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            return -1;
 | 
					            return -1;
 | 
				
			||||||
@@ -112,7 +112,7 @@ namespace ix
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        // iterate through the records to find a working peer
 | 
					        // iterate through the records to find a working peer
 | 
				
			||||||
        struct addrinfo* address;
 | 
					        struct addrinfo* address;
 | 
				
			||||||
        for (address = res.get(); address != nullptr; address = address->ai_next)
 | 
					        for (address = res; address != nullptr; address = address->ai_next)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            //
 | 
					            //
 | 
				
			||||||
            // Second try to connect to the remote host
 | 
					            // Second try to connect to the remote host
 | 
				
			||||||
@@ -124,6 +124,7 @@ namespace ix
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        freeaddrinfo(res);
 | 
				
			||||||
        return sockfd;
 | 
					        return sockfd;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,7 +14,6 @@
 | 
				
			|||||||
#include "IXNetSystem.h"
 | 
					#include "IXNetSystem.h"
 | 
				
			||||||
#include "IXSocket.h"
 | 
					#include "IXSocket.h"
 | 
				
			||||||
#include "IXSocketConnect.h"
 | 
					#include "IXSocketConnect.h"
 | 
				
			||||||
#include <cstdint>
 | 
					 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef _WIN32
 | 
					#ifdef _WIN32
 | 
				
			||||||
@@ -49,7 +48,7 @@ namespace ix
 | 
				
			|||||||
        mbedtls_pk_init(&_pkey);
 | 
					        mbedtls_pk_init(&_pkey);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool SocketMbedTLS::loadSystemCertificates(std::string& /* errorMsg */)
 | 
					    bool SocketMbedTLS::loadSystemCertificates(std::string& errorMsg)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
#ifdef _WIN32
 | 
					#ifdef _WIN32
 | 
				
			||||||
        DWORD flags = CERT_STORE_READONLY_FLAG | CERT_STORE_OPEN_EXISTING_FLAG |
 | 
					        DWORD flags = CERT_STORE_READONLY_FLAG | CERT_STORE_OPEN_EXISTING_FLAG |
 | 
				
			||||||
@@ -196,13 +195,10 @@ namespace ix
 | 
				
			|||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!_tlsOptions.disable_hostname_validation)
 | 
					        if (!host.empty() && mbedtls_ssl_set_hostname(&_ssl, host.c_str()) != 0)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (!host.empty() && mbedtls_ssl_set_hostname(&_ssl, host.c_str()) != 0)
 | 
					            errMsg = "SNI setup failed";
 | 
				
			||||||
            {
 | 
					            return false;
 | 
				
			||||||
                errMsg = "SNI setup failed";
 | 
					 | 
				
			||||||
                return false;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -301,11 +301,7 @@ namespace ix
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool SocketOpenSSL::openSSLCheckServerCert(SSL* ssl,
 | 
					    bool SocketOpenSSL::openSSLCheckServerCert(SSL* ssl,
 | 
				
			||||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L
 | 
					 | 
				
			||||||
                                               const std::string& hostname,
 | 
					                                               const std::string& hostname,
 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
                                               const std::string& /* hostname */,
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
                                               std::string& errMsg)
 | 
					                                               std::string& errMsg)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        X509* server_cert = SSL_get_peer_certificate(ssl);
 | 
					        X509* server_cert = SSL_get_peer_certificate(ssl);
 | 
				
			||||||
@@ -394,11 +390,6 @@ namespace ix
 | 
				
			|||||||
            int connect_result = SSL_connect(_ssl_connection);
 | 
					            int connect_result = SSL_connect(_ssl_connection);
 | 
				
			||||||
            if (connect_result == 1)
 | 
					            if (connect_result == 1)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                if (_tlsOptions.disable_hostname_validation)
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    return true;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                return openSSLCheckServerCert(_ssl_connection, host, errMsg);
 | 
					                return openSSLCheckServerCert(_ssl_connection, host, errMsg);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            int reason = SSL_get_error(_ssl_connection, connect_result);
 | 
					            int reason = SSL_get_error(_ssl_connection, connect_result);
 | 
				
			||||||
@@ -763,11 +754,8 @@ namespace ix
 | 
				
			|||||||
            // (The docs say that this should work from 1.0.2, and is the default from
 | 
					            // (The docs say that this should work from 1.0.2, and is the default from
 | 
				
			||||||
            // 1.1.0, but it does not. To be on the safe side, the manual test
 | 
					            // 1.1.0, but it does not. To be on the safe side, the manual test
 | 
				
			||||||
            // below is enabled for all versions prior to 1.1.0.)
 | 
					            // below is enabled for all versions prior to 1.1.0.)
 | 
				
			||||||
            if (!_tlsOptions.disable_hostname_validation)
 | 
					            X509_VERIFY_PARAM* param = SSL_get0_param(_ssl_connection);
 | 
				
			||||||
            {
 | 
					            X509_VERIFY_PARAM_set1_host(param, host.c_str(), 0);
 | 
				
			||||||
                X509_VERIFY_PARAM* param = SSL_get0_param(_ssl_connection);
 | 
					 | 
				
			||||||
                X509_VERIFY_PARAM_set1_host(param, host.c_str(), host.size());
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
            handshakeSuccessful = openSSLClientHandshake(host, errMsg, isCancellationRequested);
 | 
					            handshakeSuccessful = openSSLClientHandshake(host, errMsg, isCancellationRequested);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -268,10 +268,7 @@ namespace ix
 | 
				
			|||||||
        // Set the socket to non blocking mode, so that accept calls are not blocking
 | 
					        // Set the socket to non blocking mode, so that accept calls are not blocking
 | 
				
			||||||
        SocketConnect::configure(_serverFd);
 | 
					        SocketConnect::configure(_serverFd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Use a cryptic name to stay within the 16 bytes limit thread name limitation
 | 
					        setThreadName("SocketServer::accept");
 | 
				
			||||||
        // $ echo Srv:gc:64000 | wc -c
 | 
					 | 
				
			||||||
        // 13
 | 
					 | 
				
			||||||
        setThreadName("Srv:ac:" + std::to_string(_port));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (;;)
 | 
					        for (;;)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@@ -428,10 +425,7 @@ namespace ix
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    void SocketServer::runGC()
 | 
					    void SocketServer::runGC()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        // Use a cryptic name to stay within the 16 bytes limit thread name limitation
 | 
					        setThreadName("SocketServer::GC");
 | 
				
			||||||
        // $ echo Srv:gc:64000 | wc -c
 | 
					 | 
				
			||||||
        // 13
 | 
					 | 
				
			||||||
        setThreadName("Srv:gc:" + std::to_string(_port));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (;;)
 | 
					        for (;;)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -33,9 +33,6 @@ namespace ix
 | 
				
			|||||||
        // whether tls is enabled, used for server code
 | 
					        // whether tls is enabled, used for server code
 | 
				
			||||||
        bool tls = false;
 | 
					        bool tls = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // whether to skip validating the peer's hostname against the certificate presented
 | 
					 | 
				
			||||||
        bool disable_hostname_validation = false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        bool hasCertAndKey() const;
 | 
					        bool hasCertAndKey() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        bool isUsingSystemDefaults() const;
 | 
					        bool isUsingSystemDefaults() const;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -333,19 +333,6 @@ namespace
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        return Result;
 | 
					        return Result;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    int getProtocolPort(const std::string& protocol)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if (protocol == "ws" || protocol == "http")
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            return 80;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else if (protocol == "wss" || protocol == "https")
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            return 443;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return -1;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
} // namespace
 | 
					} // namespace
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace ix
 | 
					namespace ix
 | 
				
			||||||
@@ -356,18 +343,6 @@ namespace ix
 | 
				
			|||||||
                          std::string& path,
 | 
					                          std::string& path,
 | 
				
			||||||
                          std::string& query,
 | 
					                          std::string& query,
 | 
				
			||||||
                          int& port)
 | 
					                          int& port)
 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        bool isProtocolDefaultPort;
 | 
					 | 
				
			||||||
        return parse(url, protocol, host, path, query, port, isProtocolDefaultPort);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    bool UrlParser::parse(const std::string& url,
 | 
					 | 
				
			||||||
                              std::string& protocol,
 | 
					 | 
				
			||||||
                              std::string& host,
 | 
					 | 
				
			||||||
                              std::string& path,
 | 
					 | 
				
			||||||
                              std::string& query,
 | 
					 | 
				
			||||||
                              int& port,
 | 
					 | 
				
			||||||
                              bool& isProtocolDefaultPort)
 | 
					 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        clParseURL res = clParseURL::ParseURL(url);
 | 
					        clParseURL res = clParseURL::ParseURL(url);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -381,12 +356,23 @@ namespace ix
 | 
				
			|||||||
        path = res.m_Path;
 | 
					        path = res.m_Path;
 | 
				
			||||||
        query = res.m_Query;
 | 
					        query = res.m_Query;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const auto protocolPort = getProtocolPort(protocol);
 | 
					 | 
				
			||||||
        if (!res.GetPort(&port))
 | 
					        if (!res.GetPort(&port))
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            port = protocolPort;
 | 
					            if (protocol == "ws" || protocol == "http")
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                port = 80;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else if (protocol == "wss" || protocol == "https")
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                port = 443;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                // Invalid protocol. Should be caught by regex check
 | 
				
			||||||
 | 
					                // but this missing branch trigger cpplint linter.
 | 
				
			||||||
 | 
					                return false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        isProtocolDefaultPort = port == protocolPort;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (path.empty())
 | 
					        if (path.empty())
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,13 +19,5 @@ namespace ix
 | 
				
			|||||||
                          std::string& path,
 | 
					                          std::string& path,
 | 
				
			||||||
                          std::string& query,
 | 
					                          std::string& query,
 | 
				
			||||||
                          int& port);
 | 
					                          int& port);
 | 
				
			||||||
 | 
					 | 
				
			||||||
        static bool parse(const std::string& url,
 | 
					 | 
				
			||||||
                          std::string& protocol,
 | 
					 | 
				
			||||||
                          std::string& host,
 | 
					 | 
				
			||||||
                          std::string& path,
 | 
					 | 
				
			||||||
                          std::string& query,
 | 
					 | 
				
			||||||
                          int& port,
 | 
					 | 
				
			||||||
                          bool& isProtocolDefaultPort);
 | 
					 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
} // namespace ix
 | 
					} // namespace ix
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,7 +16,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "IXUuid.h"
 | 
					#include "IXUuid.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <cstdint>
 | 
					 | 
				
			||||||
#include <iomanip>
 | 
					#include <iomanip>
 | 
				
			||||||
#include <random>
 | 
					#include <random>
 | 
				
			||||||
#include <sstream>
 | 
					#include <sstream>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,7 +13,6 @@
 | 
				
			|||||||
#include "IXWebSocketHandshake.h"
 | 
					#include "IXWebSocketHandshake.h"
 | 
				
			||||||
#include <cassert>
 | 
					#include <cassert>
 | 
				
			||||||
#include <cmath>
 | 
					#include <cmath>
 | 
				
			||||||
#include <cstdint>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace
 | 
					namespace
 | 
				
			||||||
@@ -40,11 +39,9 @@ namespace ix
 | 
				
			|||||||
        , _handshakeTimeoutSecs(kDefaultHandShakeTimeoutSecs)
 | 
					        , _handshakeTimeoutSecs(kDefaultHandShakeTimeoutSecs)
 | 
				
			||||||
        , _enablePong(kDefaultEnablePong)
 | 
					        , _enablePong(kDefaultEnablePong)
 | 
				
			||||||
        , _pingIntervalSecs(kDefaultPingIntervalSecs)
 | 
					        , _pingIntervalSecs(kDefaultPingIntervalSecs)
 | 
				
			||||||
        , _pingType(SendMessageKind::Ping)
 | 
					 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        _ws.setOnCloseCallback(
 | 
					        _ws.setOnCloseCallback(
 | 
				
			||||||
            [this](uint16_t code, const std::string& reason, size_t wireSize, bool remote)
 | 
					            [this](uint16_t code, const std::string& reason, size_t wireSize, bool remote) {
 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                _onMessageCallback(
 | 
					                _onMessageCallback(
 | 
				
			||||||
                    ix::make_unique<WebSocketMessage>(WebSocketMessageType::Close,
 | 
					                    ix::make_unique<WebSocketMessage>(WebSocketMessageType::Close,
 | 
				
			||||||
                                                      emptyMsg,
 | 
					                                                      emptyMsg,
 | 
				
			||||||
@@ -103,17 +100,6 @@ namespace ix
 | 
				
			|||||||
        return _perMessageDeflateOptions;
 | 
					        return _perMessageDeflateOptions;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void WebSocket::setPingMessage(const std::string& sendMessage, SendMessageKind pingType)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        std::lock_guard<std::mutex> lock(_configMutex);
 | 
					 | 
				
			||||||
        _pingMessage = sendMessage;
 | 
					 | 
				
			||||||
        _ws.setPingMessage(_pingMessage, pingType);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    const std::string WebSocket::getPingMessage() const
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        std::lock_guard<std::mutex> lock(_configMutex);
 | 
					 | 
				
			||||||
        return _pingMessage;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    void WebSocket::setPingInterval(int pingIntervalSecs)
 | 
					    void WebSocket::setPingInterval(int pingIntervalSecs)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        std::lock_guard<std::mutex> lock(_configMutex);
 | 
					        std::lock_guard<std::mutex> lock(_configMutex);
 | 
				
			||||||
@@ -246,7 +232,7 @@ namespace ix
 | 
				
			|||||||
        if (_pingIntervalSecs > 0)
 | 
					        if (_pingIntervalSecs > 0)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            // Send a heart beat right away
 | 
					            // Send a heart beat right away
 | 
				
			||||||
            _ws.sendHeartBeat(_pingType);
 | 
					            _ws.sendHeartBeat();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return status;
 | 
					        return status;
 | 
				
			||||||
@@ -254,8 +240,7 @@ namespace ix
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    WebSocketInitResult WebSocket::connectToSocket(std::unique_ptr<Socket> socket,
 | 
					    WebSocketInitResult WebSocket::connectToSocket(std::unique_ptr<Socket> socket,
 | 
				
			||||||
                                                   int timeoutSecs,
 | 
					                                                   int timeoutSecs,
 | 
				
			||||||
                                                   bool enablePerMessageDeflate,
 | 
					                                                   bool enablePerMessageDeflate)
 | 
				
			||||||
                                                   HttpRequestPtr request)
 | 
					 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            std::lock_guard<std::mutex> lock(_configMutex);
 | 
					            std::lock_guard<std::mutex> lock(_configMutex);
 | 
				
			||||||
@@ -264,7 +249,7 @@ namespace ix
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        WebSocketInitResult status =
 | 
					        WebSocketInitResult status =
 | 
				
			||||||
            _ws.connectToSocket(std::move(socket), timeoutSecs, enablePerMessageDeflate, request);
 | 
					            _ws.connectToSocket(std::move(socket), timeoutSecs, enablePerMessageDeflate);
 | 
				
			||||||
        if (!status.success)
 | 
					        if (!status.success)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            return status;
 | 
					            return status;
 | 
				
			||||||
@@ -281,7 +266,7 @@ namespace ix
 | 
				
			|||||||
        if (_pingIntervalSecs > 0)
 | 
					        if (_pingIntervalSecs > 0)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            // Send a heart beat right away
 | 
					            // Send a heart beat right away
 | 
				
			||||||
            _ws.sendHeartBeat(_pingType);
 | 
					            _ws.sendHeartBeat();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return status;
 | 
					        return status;
 | 
				
			||||||
@@ -399,9 +384,8 @@ namespace ix
 | 
				
			|||||||
                [this](const std::string& msg,
 | 
					                [this](const std::string& msg,
 | 
				
			||||||
                       size_t wireSize,
 | 
					                       size_t wireSize,
 | 
				
			||||||
                       bool decompressionError,
 | 
					                       bool decompressionError,
 | 
				
			||||||
                       WebSocketTransport::MessageKind messageKind)
 | 
					                       WebSocketTransport::MessageKind messageKind) {
 | 
				
			||||||
                {
 | 
					                    WebSocketMessageType webSocketMessageType{WebSocketMessageType::Error};
 | 
				
			||||||
                    WebSocketMessageType webSocketMessageType {WebSocketMessageType::Error};
 | 
					 | 
				
			||||||
                    switch (messageKind)
 | 
					                    switch (messageKind)
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        case WebSocketTransport::MessageKind::MSG_TEXT:
 | 
					                        case WebSocketTransport::MessageKind::MSG_TEXT:
 | 
				
			||||||
@@ -519,13 +503,13 @@ namespace ix
 | 
				
			|||||||
        return sendMessage(text, SendMessageKind::Text, onProgressCallback);
 | 
					        return sendMessage(text, SendMessageKind::Text, onProgressCallback);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    WebSocketSendInfo WebSocket::ping(const std::string& text, SendMessageKind pingType)
 | 
					    WebSocketSendInfo WebSocket::ping(const std::string& text)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        // Standard limit ping message size
 | 
					        // Standard limit ping message size
 | 
				
			||||||
        constexpr size_t pingMaxPayloadSize = 125;
 | 
					        constexpr size_t pingMaxPayloadSize = 125;
 | 
				
			||||||
        if (text.size() > pingMaxPayloadSize) return WebSocketSendInfo(false);
 | 
					        if (text.size() > pingMaxPayloadSize) return WebSocketSendInfo(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return sendMessage(text, pingType);
 | 
					        return sendMessage(text, SendMessageKind::Ping);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    WebSocketSendInfo WebSocket::sendMessage(const IXWebSocketSendData& message,
 | 
					    WebSocketSendInfo WebSocket::sendMessage(const IXWebSocketSendData& message,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,12 +16,11 @@
 | 
				
			|||||||
#include "IXWebSocketHttpHeaders.h"
 | 
					#include "IXWebSocketHttpHeaders.h"
 | 
				
			||||||
#include "IXWebSocketMessage.h"
 | 
					#include "IXWebSocketMessage.h"
 | 
				
			||||||
#include "IXWebSocketPerMessageDeflateOptions.h"
 | 
					#include "IXWebSocketPerMessageDeflateOptions.h"
 | 
				
			||||||
#include "IXWebSocketSendData.h"
 | 
					 | 
				
			||||||
#include "IXWebSocketSendInfo.h"
 | 
					#include "IXWebSocketSendInfo.h"
 | 
				
			||||||
 | 
					#include "IXWebSocketSendData.h"
 | 
				
			||||||
#include "IXWebSocketTransport.h"
 | 
					#include "IXWebSocketTransport.h"
 | 
				
			||||||
#include <atomic>
 | 
					#include <atomic>
 | 
				
			||||||
#include <condition_variable>
 | 
					#include <condition_variable>
 | 
				
			||||||
#include <cstdint>
 | 
					 | 
				
			||||||
#include <mutex>
 | 
					#include <mutex>
 | 
				
			||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
#include <thread>
 | 
					#include <thread>
 | 
				
			||||||
@@ -54,8 +53,6 @@ namespace ix
 | 
				
			|||||||
        void setPerMessageDeflateOptions(
 | 
					        void setPerMessageDeflateOptions(
 | 
				
			||||||
            const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions);
 | 
					            const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions);
 | 
				
			||||||
        void setTLSOptions(const SocketTLSOptions& socketTLSOptions);
 | 
					        void setTLSOptions(const SocketTLSOptions& socketTLSOptions);
 | 
				
			||||||
        void setPingMessage(const std::string& sendMessage,
 | 
					 | 
				
			||||||
                            SendMessageKind pingType = SendMessageKind::Ping);
 | 
					 | 
				
			||||||
        void setPingInterval(int pingIntervalSecs);
 | 
					        void setPingInterval(int pingIntervalSecs);
 | 
				
			||||||
        void enablePong();
 | 
					        void enablePong();
 | 
				
			||||||
        void disablePong();
 | 
					        void disablePong();
 | 
				
			||||||
@@ -91,7 +88,7 @@ namespace ix
 | 
				
			|||||||
                                       const OnProgressCallback& onProgressCallback = nullptr);
 | 
					                                       const OnProgressCallback& onProgressCallback = nullptr);
 | 
				
			||||||
        WebSocketSendInfo sendText(const std::string& text,
 | 
					        WebSocketSendInfo sendText(const std::string& text,
 | 
				
			||||||
                                   const OnProgressCallback& onProgressCallback = nullptr);
 | 
					                                   const OnProgressCallback& onProgressCallback = nullptr);
 | 
				
			||||||
        WebSocketSendInfo ping(const std::string& text,SendMessageKind pingType = SendMessageKind::Ping);
 | 
					        WebSocketSendInfo ping(const std::string& text);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void close(uint16_t code = WebSocketCloseConstants::kNormalClosureCode,
 | 
					        void close(uint16_t code = WebSocketCloseConstants::kNormalClosureCode,
 | 
				
			||||||
                   const std::string& reason = WebSocketCloseConstants::kNormalClosureMessage);
 | 
					                   const std::string& reason = WebSocketCloseConstants::kNormalClosureMessage);
 | 
				
			||||||
@@ -106,7 +103,6 @@ namespace ix
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        const std::string getUrl() const;
 | 
					        const std::string getUrl() const;
 | 
				
			||||||
        const WebSocketPerMessageDeflateOptions getPerMessageDeflateOptions() const;
 | 
					        const WebSocketPerMessageDeflateOptions getPerMessageDeflateOptions() const;
 | 
				
			||||||
        const std::string getPingMessage() const;
 | 
					 | 
				
			||||||
        int getPingInterval() const;
 | 
					        int getPingInterval() const;
 | 
				
			||||||
        size_t bufferedAmount() const;
 | 
					        size_t bufferedAmount() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -132,8 +128,7 @@ namespace ix
 | 
				
			|||||||
        // Server
 | 
					        // Server
 | 
				
			||||||
        WebSocketInitResult connectToSocket(std::unique_ptr<Socket>,
 | 
					        WebSocketInitResult connectToSocket(std::unique_ptr<Socket>,
 | 
				
			||||||
                                            int timeoutSecs,
 | 
					                                            int timeoutSecs,
 | 
				
			||||||
                                            bool enablePerMessageDeflate,
 | 
					                                            bool enablePerMessageDeflate);
 | 
				
			||||||
                                            HttpRequestPtr request = nullptr);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        WebSocketTransport _ws;
 | 
					        WebSocketTransport _ws;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -174,8 +169,6 @@ namespace ix
 | 
				
			|||||||
        // Optional ping and pong timeout
 | 
					        // Optional ping and pong timeout
 | 
				
			||||||
        int _pingIntervalSecs;
 | 
					        int _pingIntervalSecs;
 | 
				
			||||||
        int _pingTimeoutSecs;
 | 
					        int _pingTimeoutSecs;
 | 
				
			||||||
        std::string _pingMessage;
 | 
					 | 
				
			||||||
        SendMessageKind _pingType;
 | 
					 | 
				
			||||||
        static const int kDefaultPingIntervalSecs;
 | 
					        static const int kDefaultPingIntervalSecs;
 | 
				
			||||||
        static const int kDefaultPingTimeoutSecs;
 | 
					        static const int kDefaultPingTimeoutSecs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,7 +6,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "IXWebSocketHandshake.h"
 | 
					#include "IXWebSocketHandshake.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "IXBase64.h"
 | 
					 | 
				
			||||||
#include "IXHttp.h"
 | 
					#include "IXHttp.h"
 | 
				
			||||||
#include "IXSocketConnect.h"
 | 
					#include "IXSocketConnect.h"
 | 
				
			||||||
#include "IXStrCaseCompare.h"
 | 
					#include "IXStrCaseCompare.h"
 | 
				
			||||||
@@ -18,6 +17,7 @@
 | 
				
			|||||||
#include <random>
 | 
					#include <random>
 | 
				
			||||||
#include <sstream>
 | 
					#include <sstream>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace ix
 | 
					namespace ix
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    WebSocketHandshake::WebSocketHandshake(
 | 
					    WebSocketHandshake::WebSocketHandshake(
 | 
				
			||||||
@@ -106,10 +106,15 @@ namespace ix
 | 
				
			|||||||
            return WebSocketInitResult(false, 0, ss.str());
 | 
					            return WebSocketInitResult(false, 0, ss.str());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Generate a random 16 bytes string and base64 encode it.
 | 
					        //
 | 
				
			||||||
 | 
					        // Generate a random 24 bytes string which looks like it is base64 encoded
 | 
				
			||||||
 | 
					        // y3JJHMbDL1EzLkh9GBhXDw==
 | 
				
			||||||
 | 
					        // 0cb3Vd9HkbpVVumoS3Noka==
 | 
				
			||||||
        //
 | 
					        //
 | 
				
			||||||
        // See https://stackoverflow.com/questions/18265128/what-is-sec-websocket-key-for
 | 
					        // See https://stackoverflow.com/questions/18265128/what-is-sec-websocket-key-for
 | 
				
			||||||
        std::string secWebSocketKey = macaron::Base64::Encode(genRandomString(16));
 | 
					        //
 | 
				
			||||||
 | 
					        std::string secWebSocketKey = genRandomString(22);
 | 
				
			||||||
 | 
					        secWebSocketKey += "==";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        std::stringstream ss;
 | 
					        std::stringstream ss;
 | 
				
			||||||
        ss << "GET " << path << " HTTP/1.1\r\n";
 | 
					        ss << "GET " << path << " HTTP/1.1\r\n";
 | 
				
			||||||
@@ -240,42 +245,28 @@ namespace ix
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    WebSocketInitResult WebSocketHandshake::serverHandshake(int timeoutSecs,
 | 
					    WebSocketInitResult WebSocketHandshake::serverHandshake(int timeoutSecs,
 | 
				
			||||||
                                                            bool enablePerMessageDeflate,
 | 
					                                                            bool enablePerMessageDeflate)
 | 
				
			||||||
                                                            HttpRequestPtr request)
 | 
					 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        _requestInitCancellation = false;
 | 
					        _requestInitCancellation = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        auto isCancellationRequested =
 | 
					        auto isCancellationRequested =
 | 
				
			||||||
            makeCancellationRequestWithTimeout(timeoutSecs, _requestInitCancellation);
 | 
					            makeCancellationRequestWithTimeout(timeoutSecs, _requestInitCancellation);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        std::string method;
 | 
					        // Read first line
 | 
				
			||||||
        std::string uri;
 | 
					        auto lineResult = _socket->readLine(isCancellationRequested);
 | 
				
			||||||
        std::string httpVersion;
 | 
					        auto lineValid = lineResult.first;
 | 
				
			||||||
 | 
					        auto line = lineResult.second;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (request)
 | 
					        if (!lineValid)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            method = request->method;
 | 
					            return sendErrorResponse(400, "Error reading HTTP request line");
 | 
				
			||||||
            uri = request->uri;
 | 
					 | 
				
			||||||
            httpVersion = request->version;
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            // Read first line
 | 
					 | 
				
			||||||
            auto lineResult = _socket->readLine(isCancellationRequested);
 | 
					 | 
				
			||||||
            auto lineValid = lineResult.first;
 | 
					 | 
				
			||||||
            auto line = lineResult.second;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (!lineValid)
 | 
					        // Validate request line (GET /foo HTTP/1.1\r\n)
 | 
				
			||||||
            {
 | 
					        auto requestLine = Http::parseRequestLine(line);
 | 
				
			||||||
                return sendErrorResponse(400, "Error reading HTTP request line");
 | 
					        auto method = std::get<0>(requestLine);
 | 
				
			||||||
            }
 | 
					        auto uri = std::get<1>(requestLine);
 | 
				
			||||||
 | 
					        auto httpVersion = std::get<2>(requestLine);
 | 
				
			||||||
            // Validate request line (GET /foo HTTP/1.1\r\n)
 | 
					 | 
				
			||||||
            auto requestLine = Http::parseRequestLine(line);
 | 
					 | 
				
			||||||
            method = std::get<0>(requestLine);
 | 
					 | 
				
			||||||
            uri = std::get<1>(requestLine);
 | 
					 | 
				
			||||||
            httpVersion = std::get<2>(requestLine);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (method != "GET")
 | 
					        if (method != "GET")
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@@ -288,22 +279,14 @@ namespace ix
 | 
				
			|||||||
                                     "Invalid HTTP version, need HTTP/1.1, got: " + httpVersion);
 | 
					                                     "Invalid HTTP version, need HTTP/1.1, got: " + httpVersion);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        WebSocketHttpHeaders headers;
 | 
					        // Retrieve and validate HTTP headers
 | 
				
			||||||
        if (request)
 | 
					        auto result = parseHttpHeaders(_socket, isCancellationRequested);
 | 
				
			||||||
        {
 | 
					        auto headersValid = result.first;
 | 
				
			||||||
            headers = request->headers;
 | 
					        auto headers = result.second;
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            // Retrieve and validate HTTP headers
 | 
					 | 
				
			||||||
            auto result = parseHttpHeaders(_socket, isCancellationRequested);
 | 
					 | 
				
			||||||
            auto headersValid = result.first;
 | 
					 | 
				
			||||||
            headers = result.second;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (!headersValid)
 | 
					        if (!headersValid)
 | 
				
			||||||
            {
 | 
					        {
 | 
				
			||||||
                return sendErrorResponse(400, "Error parsing HTTP headers");
 | 
					            return sendErrorResponse(400, "Error parsing HTTP headers");
 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (headers.find("sec-websocket-key") == headers.end())
 | 
					        if (headers.find("sec-websocket-key") == headers.end())
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,7 +7,6 @@
 | 
				
			|||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "IXCancellationRequest.h"
 | 
					#include "IXCancellationRequest.h"
 | 
				
			||||||
#include "IXHttp.h"
 | 
					 | 
				
			||||||
#include "IXSocket.h"
 | 
					#include "IXSocket.h"
 | 
				
			||||||
#include "IXWebSocketHttpHeaders.h"
 | 
					#include "IXWebSocketHttpHeaders.h"
 | 
				
			||||||
#include "IXWebSocketInitResult.h"
 | 
					#include "IXWebSocketInitResult.h"
 | 
				
			||||||
@@ -36,9 +35,7 @@ namespace ix
 | 
				
			|||||||
                                            int port,
 | 
					                                            int port,
 | 
				
			||||||
                                            int timeoutSecs);
 | 
					                                            int timeoutSecs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        WebSocketInitResult serverHandshake(int timeoutSecs,
 | 
					        WebSocketInitResult serverHandshake(int timeoutSecs, bool enablePerMessageDeflate);
 | 
				
			||||||
                                            bool enablePerMessageDeflate,
 | 
					 | 
				
			||||||
                                            HttpRequestPtr request = nullptr);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private:
 | 
					    private:
 | 
				
			||||||
        std::string genRandomString(const int len);
 | 
					        std::string genRandomString(const int len);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -46,8 +46,6 @@
 | 
				
			|||||||
 *
 | 
					 *
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <cstdint>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "IXWebSocketPerMessageDeflate.h"
 | 
					#include "IXWebSocketPerMessageDeflate.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "IXUniquePtr.h"
 | 
					#include "IXUniquePtr.h"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,7 +10,6 @@
 | 
				
			|||||||
#include "zlib.h"
 | 
					#include "zlib.h"
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#include <array>
 | 
					#include <array>
 | 
				
			||||||
#include <cstdint>
 | 
					 | 
				
			||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
#include <vector>
 | 
					#include <vector>
 | 
				
			||||||
#include "IXWebSocketSendData.h"
 | 
					#include "IXWebSocketSendData.h"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,7 +6,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <cstdint>
 | 
					 | 
				
			||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace ix
 | 
					namespace ix
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,129 +1,128 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 *  IXWebSocketSendData.h
 | 
					 *  IXWebSocketSendData.h
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *  WebSocket (Binary/Text) send data buffer
 | 
					 *  WebSocket (Binary/Text) send data buffer
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <cstdint>
 | 
					#include <string>
 | 
				
			||||||
#include <string>
 | 
					#include <vector>
 | 
				
			||||||
#include <vector>
 | 
					#include <iterator>
 | 
				
			||||||
#include <iterator>
 | 
					
 | 
				
			||||||
 | 
					namespace ix
 | 
				
			||||||
namespace ix
 | 
					{
 | 
				
			||||||
{
 | 
					    /*
 | 
				
			||||||
    /*
 | 
					    * IXWebSocketSendData implements a wrapper for std::string, std:vector<char/uint8_t> and char*.
 | 
				
			||||||
    * IXWebSocketSendData implements a wrapper for std::string, std:vector<char/uint8_t> and char*.
 | 
					    * It removes the necessarity to copy the data or string into a std::string 
 | 
				
			||||||
    * It removes the necessarity to copy the data or string into a std::string 
 | 
					    */
 | 
				
			||||||
    */
 | 
					    class IXWebSocketSendData {
 | 
				
			||||||
    class IXWebSocketSendData {
 | 
					    public:
 | 
				
			||||||
    public:
 | 
					
 | 
				
			||||||
 | 
					        template<typename T>
 | 
				
			||||||
        template<typename T>
 | 
					        struct IXWebSocketSendData_const_iterator
 | 
				
			||||||
        struct IXWebSocketSendData_const_iterator
 | 
					            //: public std::iterator<std::forward_iterator_tag, T>
 | 
				
			||||||
            //: public std::iterator<std::forward_iterator_tag, T>
 | 
					        {
 | 
				
			||||||
        {
 | 
					            typedef IXWebSocketSendData_const_iterator<T> const_iterator;
 | 
				
			||||||
            typedef IXWebSocketSendData_const_iterator<T> const_iterator;
 | 
					
 | 
				
			||||||
 | 
					            using iterator_category = std::forward_iterator_tag;
 | 
				
			||||||
            using iterator_category = std::forward_iterator_tag;
 | 
					            using difference_type = std::ptrdiff_t;
 | 
				
			||||||
            using difference_type = std::ptrdiff_t;
 | 
					            using value_type = T;
 | 
				
			||||||
            using value_type = T;
 | 
					            using pointer = value_type*;
 | 
				
			||||||
            using pointer = value_type*;
 | 
					            using reference = const value_type&;
 | 
				
			||||||
            using reference = const value_type&;
 | 
					
 | 
				
			||||||
 | 
					            pointer _ptr;
 | 
				
			||||||
            pointer _ptr;
 | 
					        public:
 | 
				
			||||||
        public:
 | 
					            IXWebSocketSendData_const_iterator() : _ptr(nullptr) {}
 | 
				
			||||||
            IXWebSocketSendData_const_iterator() : _ptr(nullptr) {}
 | 
					            IXWebSocketSendData_const_iterator(pointer ptr) : _ptr(ptr) {}
 | 
				
			||||||
            IXWebSocketSendData_const_iterator(pointer ptr) : _ptr(ptr) {}
 | 
					            ~IXWebSocketSendData_const_iterator() {}
 | 
				
			||||||
            ~IXWebSocketSendData_const_iterator() {}
 | 
					
 | 
				
			||||||
 | 
					            const_iterator  operator++(int) { return const_iterator(_ptr++); }
 | 
				
			||||||
            const_iterator  operator++(int) { return const_iterator(_ptr++); }
 | 
					            const_iterator& operator++() { ++_ptr; return *this; }
 | 
				
			||||||
            const_iterator& operator++() { ++_ptr; return *this; }
 | 
					            reference       operator* () const { return *_ptr; }
 | 
				
			||||||
            reference       operator* () const { return *_ptr; }
 | 
					            pointer         operator->() const { return _ptr; }
 | 
				
			||||||
            pointer         operator->() const { return _ptr; }
 | 
					            const_iterator  operator+ (const difference_type offset) const { return const_iterator(_ptr + offset); }
 | 
				
			||||||
            const_iterator  operator+ (const difference_type offset) const { return const_iterator(_ptr + offset); }
 | 
					            const_iterator  operator- (const difference_type offset) const { return const_iterator(_ptr - offset); }
 | 
				
			||||||
            const_iterator  operator- (const difference_type offset) const { return const_iterator(_ptr - offset); }
 | 
					            difference_type operator- (const const_iterator& rhs) const { return _ptr - rhs._ptr; }
 | 
				
			||||||
            difference_type operator- (const const_iterator& rhs) const { return _ptr - rhs._ptr; }
 | 
					            bool            operator==(const const_iterator& rhs) const { return _ptr == rhs._ptr; }
 | 
				
			||||||
            bool            operator==(const const_iterator& rhs) const { return _ptr == rhs._ptr; }
 | 
					            bool            operator!=(const const_iterator& rhs) const { return _ptr != rhs._ptr; }
 | 
				
			||||||
            bool            operator!=(const const_iterator& rhs) const { return _ptr != rhs._ptr; }
 | 
					            const_iterator& operator+=(const difference_type offset) { _ptr += offset; return *this; }
 | 
				
			||||||
            const_iterator& operator+=(const difference_type offset) { _ptr += offset; return *this; }
 | 
					            const_iterator& operator-=(const difference_type offset) { _ptr -= offset; return *this; }
 | 
				
			||||||
            const_iterator& operator-=(const difference_type offset) { _ptr -= offset; return *this; }
 | 
					        };
 | 
				
			||||||
        };
 | 
					
 | 
				
			||||||
 | 
					        using const_iterator = IXWebSocketSendData_const_iterator<char>;
 | 
				
			||||||
        using const_iterator = IXWebSocketSendData_const_iterator<char>;
 | 
					
 | 
				
			||||||
 | 
					        /* The assigned std::string must be kept alive for the lifetime of the input buffer */
 | 
				
			||||||
        /* The assigned std::string must be kept alive for the lifetime of the input buffer */
 | 
					        IXWebSocketSendData(const std::string& str)
 | 
				
			||||||
        IXWebSocketSendData(const std::string& str)
 | 
					            : _data(str.data())
 | 
				
			||||||
            : _data(str.data())
 | 
					            , _size(str.size())
 | 
				
			||||||
            , _size(str.size())
 | 
					        {
 | 
				
			||||||
        {
 | 
					        }
 | 
				
			||||||
        }
 | 
					
 | 
				
			||||||
 | 
					        /* The assigned std::vector must be kept alive for the lifetime of the input buffer */
 | 
				
			||||||
        /* The assigned std::vector must be kept alive for the lifetime of the input buffer */
 | 
					        IXWebSocketSendData(const std::vector<char>& v)
 | 
				
			||||||
        IXWebSocketSendData(const std::vector<char>& v)
 | 
					            : _data(v.data())
 | 
				
			||||||
            : _data(v.data())
 | 
					            , _size(v.size())
 | 
				
			||||||
            , _size(v.size())
 | 
					        {
 | 
				
			||||||
        {
 | 
					        }
 | 
				
			||||||
        }
 | 
					
 | 
				
			||||||
 | 
					        /* The assigned std::vector must be kept alive for the lifetime of the input buffer */
 | 
				
			||||||
        /* The assigned std::vector must be kept alive for the lifetime of the input buffer */
 | 
					        IXWebSocketSendData(const std::vector<uint8_t>& v)
 | 
				
			||||||
        IXWebSocketSendData(const std::vector<uint8_t>& v)
 | 
					            : _data(reinterpret_cast<const char*>(v.data()))
 | 
				
			||||||
            : _data(reinterpret_cast<const char*>(v.data()))
 | 
					            , _size(v.size())
 | 
				
			||||||
            , _size(v.size())
 | 
					        {
 | 
				
			||||||
        {
 | 
					        }
 | 
				
			||||||
        }
 | 
					
 | 
				
			||||||
 | 
					        /* The assigned memory must be kept alive for the lifetime of the input buffer */
 | 
				
			||||||
        /* The assigned memory must be kept alive for the lifetime of the input buffer */
 | 
					        IXWebSocketSendData(const char* data, size_t size)
 | 
				
			||||||
        IXWebSocketSendData(const char* data, size_t size)
 | 
					            : _data(data)
 | 
				
			||||||
            : _data(data)
 | 
					            , _size(data == nullptr ? 0 : size)
 | 
				
			||||||
            , _size(data == nullptr ? 0 : size)
 | 
					        {
 | 
				
			||||||
        {
 | 
					        }
 | 
				
			||||||
        }
 | 
					
 | 
				
			||||||
 | 
					        bool empty() const
 | 
				
			||||||
        bool empty() const
 | 
					        {
 | 
				
			||||||
        {
 | 
					            return _data == nullptr || _size == 0;
 | 
				
			||||||
            return _data == nullptr || _size == 0;
 | 
					        }
 | 
				
			||||||
        }
 | 
					
 | 
				
			||||||
 | 
					        const char* c_str() const
 | 
				
			||||||
        const char* c_str() const
 | 
					        {
 | 
				
			||||||
        {
 | 
					            return _data;
 | 
				
			||||||
            return _data;
 | 
					        }
 | 
				
			||||||
        }
 | 
					
 | 
				
			||||||
 | 
					        const char* data() const
 | 
				
			||||||
        const char* data() const
 | 
					        {
 | 
				
			||||||
        {
 | 
					            return _data;
 | 
				
			||||||
            return _data;
 | 
					        }
 | 
				
			||||||
        }
 | 
					
 | 
				
			||||||
 | 
					        size_t size() const
 | 
				
			||||||
        size_t size() const
 | 
					        {
 | 
				
			||||||
        {
 | 
					            return _size;
 | 
				
			||||||
            return _size;
 | 
					        }
 | 
				
			||||||
        }
 | 
					
 | 
				
			||||||
 | 
					        inline const_iterator begin() const
 | 
				
			||||||
        inline const_iterator begin() const
 | 
					        {
 | 
				
			||||||
        {
 | 
					            return const_iterator(const_cast<char*>(_data));
 | 
				
			||||||
            return const_iterator(const_cast<char*>(_data));
 | 
					        }
 | 
				
			||||||
        }
 | 
					
 | 
				
			||||||
 | 
					        inline const_iterator end() const
 | 
				
			||||||
        inline const_iterator end() const
 | 
					        {
 | 
				
			||||||
        {
 | 
					            return const_iterator(const_cast<char*>(_data) + _size);
 | 
				
			||||||
            return const_iterator(const_cast<char*>(_data) + _size);
 | 
					        }
 | 
				
			||||||
        }
 | 
					
 | 
				
			||||||
 | 
					        inline const_iterator cbegin() const
 | 
				
			||||||
        inline const_iterator cbegin() const
 | 
					        {
 | 
				
			||||||
        {
 | 
					            return begin();
 | 
				
			||||||
            return begin();
 | 
					        }
 | 
				
			||||||
        }
 | 
					
 | 
				
			||||||
 | 
					        inline const_iterator cend() const
 | 
				
			||||||
        inline const_iterator cend() const
 | 
					        {
 | 
				
			||||||
        {
 | 
					            return end();
 | 
				
			||||||
            return end();
 | 
					        }
 | 
				
			||||||
        }
 | 
					
 | 
				
			||||||
 | 
					    private:
 | 
				
			||||||
    private:
 | 
					        const char* _data;
 | 
				
			||||||
        const char* _data;
 | 
					        const size_t _size;
 | 
				
			||||||
        const size_t _size;
 | 
					    };
 | 
				
			||||||
    };
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -79,16 +79,7 @@ namespace ix
 | 
				
			|||||||
    void WebSocketServer::handleConnection(std::unique_ptr<Socket> socket,
 | 
					    void WebSocketServer::handleConnection(std::unique_ptr<Socket> socket,
 | 
				
			||||||
                                           std::shared_ptr<ConnectionState> connectionState)
 | 
					                                           std::shared_ptr<ConnectionState> connectionState)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        handleUpgrade(std::move(socket), connectionState);
 | 
					        setThreadName("WebSocketServer::" + connectionState->getId());
 | 
				
			||||||
 | 
					 | 
				
			||||||
        connectionState->setTerminated();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void WebSocketServer::handleUpgrade(std::unique_ptr<Socket> socket,
 | 
					 | 
				
			||||||
                                        std::shared_ptr<ConnectionState> connectionState,
 | 
					 | 
				
			||||||
                                        HttpRequestPtr request)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        setThreadName("Srv:ws:" + connectionState->getId());
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        auto webSocket = std::make_shared<WebSocket>();
 | 
					        auto webSocket = std::make_shared<WebSocket>();
 | 
				
			||||||
        if (_onConnectionCallback)
 | 
					        if (_onConnectionCallback)
 | 
				
			||||||
@@ -98,7 +89,7 @@ namespace ix
 | 
				
			|||||||
            if (!webSocket->isOnMessageCallbackRegistered())
 | 
					            if (!webSocket->isOnMessageCallbackRegistered())
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                logError("WebSocketServer Application developer error: Server callback improperly "
 | 
					                logError("WebSocketServer Application developer error: Server callback improperly "
 | 
				
			||||||
                         "registered.");
 | 
					                         "registerered.");
 | 
				
			||||||
                logError("Missing call to setOnMessageCallback inside setOnConnectionCallback.");
 | 
					                logError("Missing call to setOnMessageCallback inside setOnConnectionCallback.");
 | 
				
			||||||
                connectionState->setTerminated();
 | 
					                connectionState->setTerminated();
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
@@ -108,8 +99,9 @@ namespace ix
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            WebSocket* webSocketRawPtr = webSocket.get();
 | 
					            WebSocket* webSocketRawPtr = webSocket.get();
 | 
				
			||||||
            webSocket->setOnMessageCallback(
 | 
					            webSocket->setOnMessageCallback(
 | 
				
			||||||
                [this, webSocketRawPtr, connectionState](const WebSocketMessagePtr& msg)
 | 
					                [this, webSocketRawPtr, connectionState](const WebSocketMessagePtr& msg) {
 | 
				
			||||||
                { _onClientMessageCallback(connectionState, *webSocketRawPtr, msg); });
 | 
					                    _onClientMessageCallback(connectionState, *webSocketRawPtr, msg);
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@@ -138,7 +130,7 @@ namespace ix
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        auto status = webSocket->connectToSocket(
 | 
					        auto status = webSocket->connectToSocket(
 | 
				
			||||||
            std::move(socket), _handshakeTimeoutSecs, _enablePerMessageDeflate, request);
 | 
					            std::move(socket), _handshakeTimeoutSecs, _enablePerMessageDeflate);
 | 
				
			||||||
        if (status.success)
 | 
					        if (status.success)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            // Process incoming messages and execute callbacks
 | 
					            // Process incoming messages and execute callbacks
 | 
				
			||||||
@@ -163,6 +155,8 @@ namespace ix
 | 
				
			|||||||
                logError("Cannot delete client");
 | 
					                logError("Cannot delete client");
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        connectionState->setTerminated();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::set<std::shared_ptr<WebSocket>> WebSocketServer::getClients()
 | 
					    std::set<std::shared_ptr<WebSocket>> WebSocketServer::getClients()
 | 
				
			||||||
@@ -182,30 +176,28 @@ namespace ix
 | 
				
			|||||||
    //
 | 
					    //
 | 
				
			||||||
    void WebSocketServer::makeBroadcastServer()
 | 
					    void WebSocketServer::makeBroadcastServer()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        setOnClientMessageCallback(
 | 
					        setOnClientMessageCallback([this](std::shared_ptr<ConnectionState> connectionState,
 | 
				
			||||||
            [this](std::shared_ptr<ConnectionState> connectionState,
 | 
					                                          WebSocket& webSocket,
 | 
				
			||||||
                   WebSocket& webSocket,
 | 
					                                          const WebSocketMessagePtr& msg) {
 | 
				
			||||||
                   const WebSocketMessagePtr& msg)
 | 
					            auto remoteIp = connectionState->getRemoteIp();
 | 
				
			||||||
 | 
					            if (msg->type == ix::WebSocketMessageType::Message)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                auto remoteIp = connectionState->getRemoteIp();
 | 
					                for (auto&& client : getClients())
 | 
				
			||||||
                if (msg->type == ix::WebSocketMessageType::Message)
 | 
					 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    for (auto&& client : getClients())
 | 
					                    if (client.get() != &webSocket)
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        if (client.get() != &webSocket)
 | 
					                        client->send(msg->str, msg->binary);
 | 
				
			||||||
                        {
 | 
					 | 
				
			||||||
                            client->send(msg->str, msg->binary);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                            // Make sure the OS send buffer is flushed before moving on
 | 
					                        // Make sure the OS send buffer is flushed before moving on
 | 
				
			||||||
                            do
 | 
					                        do
 | 
				
			||||||
                            {
 | 
					                        {
 | 
				
			||||||
                                std::chrono::duration<double, std::milli> duration(500);
 | 
					                            std::chrono::duration<double, std::milli> duration(500);
 | 
				
			||||||
                                std::this_thread::sleep_for(duration);
 | 
					                            std::this_thread::sleep_for(duration);
 | 
				
			||||||
                            } while (client->bufferedAmount() != 0);
 | 
					                        } while (client->bufferedAmount() != 0);
 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            });
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool WebSocketServer::listenAndStart()
 | 
					    bool WebSocketServer::listenAndStart()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -55,7 +55,6 @@ namespace ix
 | 
				
			|||||||
        int getHandshakeTimeoutSecs();
 | 
					        int getHandshakeTimeoutSecs();
 | 
				
			||||||
        bool isPongEnabled();
 | 
					        bool isPongEnabled();
 | 
				
			||||||
        bool isPerMessageDeflateEnabled();
 | 
					        bool isPerMessageDeflateEnabled();
 | 
				
			||||||
 | 
					 | 
				
			||||||
    private:
 | 
					    private:
 | 
				
			||||||
        // Member variables
 | 
					        // Member variables
 | 
				
			||||||
        int _handshakeTimeoutSecs;
 | 
					        int _handshakeTimeoutSecs;
 | 
				
			||||||
@@ -74,10 +73,5 @@ namespace ix
 | 
				
			|||||||
        virtual void handleConnection(std::unique_ptr<Socket> socket,
 | 
					        virtual void handleConnection(std::unique_ptr<Socket> socket,
 | 
				
			||||||
                                      std::shared_ptr<ConnectionState> connectionState);
 | 
					                                      std::shared_ptr<ConnectionState> connectionState);
 | 
				
			||||||
        virtual size_t getConnectedClientsCount() final;
 | 
					        virtual size_t getConnectedClientsCount() final;
 | 
				
			||||||
 | 
					 | 
				
			||||||
    protected:
 | 
					 | 
				
			||||||
        void handleUpgrade(std::unique_ptr<Socket> socket,
 | 
					 | 
				
			||||||
                           std::shared_ptr<ConnectionState> connectionState,
 | 
					 | 
				
			||||||
                           HttpRequestPtr request = nullptr);
 | 
					 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
} // namespace ix
 | 
					} // namespace ix
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -45,6 +45,7 @@
 | 
				
			|||||||
#include <cstdarg>
 | 
					#include <cstdarg>
 | 
				
			||||||
#include <cstdlib>
 | 
					#include <cstdlib>
 | 
				
			||||||
#include <sstream>
 | 
					#include <sstream>
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
#include <thread>
 | 
					#include <thread>
 | 
				
			||||||
@@ -53,6 +54,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace ix
 | 
					namespace ix
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    const std::string WebSocketTransport::kPingMessage("ixwebsocket::heartbeat");
 | 
				
			||||||
    const int WebSocketTransport::kDefaultPingIntervalSecs(-1);
 | 
					    const int WebSocketTransport::kDefaultPingIntervalSecs(-1);
 | 
				
			||||||
    const bool WebSocketTransport::kDefaultEnablePong(true);
 | 
					    const bool WebSocketTransport::kDefaultEnablePong(true);
 | 
				
			||||||
    const int WebSocketTransport::kClosingMaximumWaitingDelayInMs(300);
 | 
					    const int WebSocketTransport::kClosingMaximumWaitingDelayInMs(300);
 | 
				
			||||||
@@ -71,9 +73,6 @@ namespace ix
 | 
				
			|||||||
        , _closingTimePoint(std::chrono::steady_clock::now())
 | 
					        , _closingTimePoint(std::chrono::steady_clock::now())
 | 
				
			||||||
        , _enablePong(kDefaultEnablePong)
 | 
					        , _enablePong(kDefaultEnablePong)
 | 
				
			||||||
        , _pingIntervalSecs(kDefaultPingIntervalSecs)
 | 
					        , _pingIntervalSecs(kDefaultPingIntervalSecs)
 | 
				
			||||||
        , _setCustomMessage(false)
 | 
					 | 
				
			||||||
        , _kPingMessage("ixwebsocket::heartbeat")
 | 
					 | 
				
			||||||
        , _pingType(SendMessageKind::Ping)
 | 
					 | 
				
			||||||
        , _pongReceived(false)
 | 
					        , _pongReceived(false)
 | 
				
			||||||
        , _pingCount(0)
 | 
					        , _pingCount(0)
 | 
				
			||||||
        , _lastSendPingTimePoint(std::chrono::steady_clock::now())
 | 
					        , _lastSendPingTimePoint(std::chrono::steady_clock::now())
 | 
				
			||||||
@@ -171,8 +170,7 @@ namespace ix
 | 
				
			|||||||
    // Server
 | 
					    // Server
 | 
				
			||||||
    WebSocketInitResult WebSocketTransport::connectToSocket(std::unique_ptr<Socket> socket,
 | 
					    WebSocketInitResult WebSocketTransport::connectToSocket(std::unique_ptr<Socket> socket,
 | 
				
			||||||
                                                            int timeoutSecs,
 | 
					                                                            int timeoutSecs,
 | 
				
			||||||
                                                            bool enablePerMessageDeflate,
 | 
					                                                            bool enablePerMessageDeflate)
 | 
				
			||||||
                                                            HttpRequestPtr request)
 | 
					 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        std::lock_guard<std::mutex> lock(_socketMutex);
 | 
					        std::lock_guard<std::mutex> lock(_socketMutex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -189,8 +187,7 @@ namespace ix
 | 
				
			|||||||
                                              _perMessageDeflateOptions,
 | 
					                                              _perMessageDeflateOptions,
 | 
				
			||||||
                                              _enablePerMessageDeflate);
 | 
					                                              _enablePerMessageDeflate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        auto result =
 | 
					        auto result = webSocketHandshake.serverHandshake(timeoutSecs, enablePerMessageDeflate);
 | 
				
			||||||
            webSocketHandshake.serverHandshake(timeoutSecs, enablePerMessageDeflate, request);
 | 
					 | 
				
			||||||
        if (result.success)
 | 
					        if (result.success)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            setReadyState(ReadyState::OPEN);
 | 
					            setReadyState(ReadyState::OPEN);
 | 
				
			||||||
@@ -251,51 +248,13 @@ namespace ix
 | 
				
			|||||||
        return now - _lastSendPingTimePoint > std::chrono::seconds(_pingIntervalSecs);
 | 
					        return now - _lastSendPingTimePoint > std::chrono::seconds(_pingIntervalSecs);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void WebSocketTransport::setPingMessage(const std::string& message, SendMessageKind pingType)
 | 
					    WebSocketSendInfo WebSocketTransport::sendHeartBeat()
 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        _setCustomMessage = true;
 | 
					 | 
				
			||||||
        _kPingMessage = message;
 | 
					 | 
				
			||||||
        _pingType = pingType;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    WebSocketSendInfo WebSocketTransport::sendHeartBeat(SendMessageKind pingMessage)
 | 
					 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        _pongReceived = false;
 | 
					        _pongReceived = false;
 | 
				
			||||||
        std::stringstream ss;
 | 
					        std::stringstream ss;
 | 
				
			||||||
 | 
					        ss << kPingMessage << "::" << _pingIntervalSecs << "s"
 | 
				
			||||||
        ss << _kPingMessage;
 | 
					           << "::" << _pingCount++;
 | 
				
			||||||
        if (!_setCustomMessage)
 | 
					        return sendPing(ss.str());
 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            ss << "::" << _pingIntervalSecs << "s"
 | 
					 | 
				
			||||||
               << "::" << _pingCount++;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        if (pingMessage == SendMessageKind::Ping)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            return sendPing(ss.str());
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else if (pingMessage == SendMessageKind::Binary)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            WebSocketSendInfo info = sendBinary(ss.str(), nullptr);
 | 
					 | 
				
			||||||
            if (info.success)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                std::lock_guard<std::mutex> lck(_lastSendPingTimePointMutex);
 | 
					 | 
				
			||||||
                _lastSendPingTimePoint = std::chrono::steady_clock::now();
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            return info;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else if (pingMessage == SendMessageKind::Text)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            WebSocketSendInfo info = sendText(ss.str(), nullptr);
 | 
					 | 
				
			||||||
            if (info.success)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                std::lock_guard<std::mutex> lck(_lastSendPingTimePointMutex);
 | 
					 | 
				
			||||||
                _lastSendPingTimePoint = std::chrono::steady_clock::now();
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            return info;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // unknow type ping message
 | 
					 | 
				
			||||||
        return {};
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool WebSocketTransport::closingDelayExceeded()
 | 
					    bool WebSocketTransport::closingDelayExceeded()
 | 
				
			||||||
@@ -311,9 +270,7 @@ namespace ix
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            if (pingIntervalExceeded())
 | 
					            if (pingIntervalExceeded())
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                // If it is not a 'ping' message of ping type, there is no need to judge whether
 | 
					                if (!_pongReceived)
 | 
				
			||||||
                // pong will receive it
 | 
					 | 
				
			||||||
                if (_pingType == SendMessageKind::Ping && !_pongReceived)
 | 
					 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    // ping response (PONG) exceeds the maximum delay, close the connection
 | 
					                    // ping response (PONG) exceeds the maximum delay, close the connection
 | 
				
			||||||
                    close(WebSocketCloseConstants::kInternalErrorCode,
 | 
					                    close(WebSocketCloseConstants::kInternalErrorCode,
 | 
				
			||||||
@@ -321,7 +278,7 @@ namespace ix
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
                else
 | 
					                else
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    sendHeartBeat(_pingType);
 | 
					                    sendHeartBeat();
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,17 +18,15 @@
 | 
				
			|||||||
#include "IXWebSocketHttpHeaders.h"
 | 
					#include "IXWebSocketHttpHeaders.h"
 | 
				
			||||||
#include "IXWebSocketPerMessageDeflate.h"
 | 
					#include "IXWebSocketPerMessageDeflate.h"
 | 
				
			||||||
#include "IXWebSocketPerMessageDeflateOptions.h"
 | 
					#include "IXWebSocketPerMessageDeflateOptions.h"
 | 
				
			||||||
#include "IXWebSocketSendData.h"
 | 
					 | 
				
			||||||
#include "IXWebSocketSendInfo.h"
 | 
					#include "IXWebSocketSendInfo.h"
 | 
				
			||||||
 | 
					#include "IXWebSocketSendData.h"
 | 
				
			||||||
#include <atomic>
 | 
					#include <atomic>
 | 
				
			||||||
#include <cstdint>
 | 
					 | 
				
			||||||
#include <functional>
 | 
					#include <functional>
 | 
				
			||||||
#include <list>
 | 
					#include <list>
 | 
				
			||||||
#include <memory>
 | 
					#include <memory>
 | 
				
			||||||
#include <mutex>
 | 
					#include <mutex>
 | 
				
			||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
#include <vector>
 | 
					#include <vector>
 | 
				
			||||||
#include <deque>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace ix
 | 
					namespace ix
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -88,8 +86,7 @@ namespace ix
 | 
				
			|||||||
        // Server
 | 
					        // Server
 | 
				
			||||||
        WebSocketInitResult connectToSocket(std::unique_ptr<Socket> socket,
 | 
					        WebSocketInitResult connectToSocket(std::unique_ptr<Socket> socket,
 | 
				
			||||||
                                            int timeoutSecs,
 | 
					                                            int timeoutSecs,
 | 
				
			||||||
                                            bool enablePerMessageDeflate,
 | 
					                                            bool enablePerMessageDeflate);
 | 
				
			||||||
                                            HttpRequestPtr request = nullptr);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        PollResult poll();
 | 
					        PollResult poll();
 | 
				
			||||||
        WebSocketSendInfo sendBinary(const IXWebSocketSendData& message,
 | 
					        WebSocketSendInfo sendBinary(const IXWebSocketSendData& message,
 | 
				
			||||||
@@ -111,12 +108,8 @@ namespace ix
 | 
				
			|||||||
        void dispatch(PollResult pollResult, const OnMessageCallback& onMessageCallback);
 | 
					        void dispatch(PollResult pollResult, const OnMessageCallback& onMessageCallback);
 | 
				
			||||||
        size_t bufferedAmount() const;
 | 
					        size_t bufferedAmount() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // set ping heartbeat message
 | 
					 | 
				
			||||||
        void setPingMessage(const std::string& message, SendMessageKind pingType);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // internal
 | 
					        // internal
 | 
				
			||||||
        // send any type of ping packet, not only 'ping' type
 | 
					        WebSocketSendInfo sendHeartBeat();
 | 
				
			||||||
        WebSocketSendInfo sendHeartBeat(SendMessageKind pingType);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private:
 | 
					    private:
 | 
				
			||||||
        std::string _url;
 | 
					        std::string _url;
 | 
				
			||||||
@@ -157,7 +150,7 @@ namespace ix
 | 
				
			|||||||
        // Contains all messages that were fetched in the last socket read.
 | 
					        // Contains all messages that were fetched in the last socket read.
 | 
				
			||||||
        // This could be a mix of control messages (Close, Ping, etc...) and
 | 
					        // This could be a mix of control messages (Close, Ping, etc...) and
 | 
				
			||||||
        // data messages. That buffer is resized
 | 
					        // data messages. That buffer is resized
 | 
				
			||||||
        std::deque<uint8_t> _rxbuf;
 | 
					        std::vector<uint8_t> _rxbuf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Contains all messages that are waiting to be sent
 | 
					        // Contains all messages that are waiting to be sent
 | 
				
			||||||
        std::vector<uint8_t> _txbuf;
 | 
					        std::vector<uint8_t> _txbuf;
 | 
				
			||||||
@@ -221,10 +214,7 @@ namespace ix
 | 
				
			|||||||
        std::atomic<bool> _pongReceived;
 | 
					        std::atomic<bool> _pongReceived;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        static const int kDefaultPingIntervalSecs;
 | 
					        static const int kDefaultPingIntervalSecs;
 | 
				
			||||||
 | 
					        static const std::string kPingMessage;
 | 
				
			||||||
        bool _setCustomMessage;
 | 
					 | 
				
			||||||
        std::string _kPingMessage;
 | 
					 | 
				
			||||||
        SendMessageKind _pingType;
 | 
					 | 
				
			||||||
        std::atomic<uint64_t> _pingCount;
 | 
					        std::atomic<uint64_t> _pingCount;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // We record when ping are being sent so that we can know when to send the next one
 | 
					        // We record when ping are being sent so that we can know when to send the next one
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,4 +6,4 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define IX_WEBSOCKET_VERSION "11.4.3"
 | 
					#define IX_WEBSOCKET_VERSION "11.4.1"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,20 +0,0 @@
 | 
				
			|||||||
-----BEGIN CERTIFICATE-----
 | 
					 | 
				
			||||||
MIIDNDCCAhwCFCl+O/rR8flqYKKvD0iwkucFwMaLMA0GCSqGSIb3DQEBCwUAMEEx
 | 
					 | 
				
			||||||
FDASBgNVBAoMC21hY2hpbmV6b25lMRQwEgYDVQQKDAtJWFdlYlNvY2tldDETMBEG
 | 
					 | 
				
			||||||
A1UEAwwKdHJ1c3RlZC1jYTAgFw0yMjA4MjMyMDM2MjVaGA80MjgxMDYwMTIwMzYy
 | 
					 | 
				
			||||||
NVowajELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMREwDwYDVQQHDAhCZXJrZWxl
 | 
					 | 
				
			||||||
eTEbMBkGA1UECgwSRHVtbXkgT3JnYW5pemF0aW9uMR4wHAYDVQQDDBVub3QuYS52
 | 
					 | 
				
			||||||
YWxpZC5ob3N0Lm5hbWUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC2
 | 
					 | 
				
			||||||
9N806IjCvA82zfk9CPNwaEHOygNDJSXaZ38YDSI4C+Wf2imnMxrLQKaoccHUi+9L
 | 
					 | 
				
			||||||
4rQN/hSCg+uTULQUZ0iyssGDaIh4IcAeoEcNlXYHTrgP+aAaby3q5zeZ80K3+6e4
 | 
					 | 
				
			||||||
rqcuBPV2lLszJu3XXwEKbDSxW3De0gc2N8m9DN8Lx7i70DRf0F4m6RIMFF/kHXwa
 | 
					 | 
				
			||||||
zZLeG7rZb4xL684lmmQsWtk5Z600CvrBtUE7fQ7bhy0QhSt66kdTSL8IKQrbWcGj
 | 
					 | 
				
			||||||
q0tggFlOqeyZSi73gqUiAIuGO8/tRgmp4HygNyC24jpOB5nObOPPJTUEf5Mk1Bum
 | 
					 | 
				
			||||||
kD5a+yL6YbVdhiaK17wbAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAKsLXGLfO1IZ
 | 
					 | 
				
			||||||
LbofGc7/TCQwRayR3RdG4864PBy97KfJWyizg7Wm4X4yPFRG+6q3X5NKW32Ew9lI
 | 
					 | 
				
			||||||
jXulXCTjWOiSxiG4Pk20uczkOhWVHFdnS9gZvykPC/ElxBKPalT6MMstZWxpElsk
 | 
					 | 
				
			||||||
rCDKXj4LkD0po8bZrjlgSZQQQk6XMRkoRai2GWLJqIjaNCSF8nqb1wM/1OE1tAwi
 | 
					 | 
				
			||||||
polO1eFMA24yypvlXcNrNXjqcQ7LaoQFQltmi/RV+uTk7EK2F2jgYVzJ/pe2ET0i
 | 
					 | 
				
			||||||
RIMbGZTlAiemDGL9SpMsxftG6fSmP6QqDqYExmmPlZMLprb2da/2kelWFA+VkvdG
 | 
					 | 
				
			||||||
zFrnIcyfMY4=
 | 
					 | 
				
			||||||
-----END CERTIFICATE-----
 | 
					 | 
				
			||||||
@@ -1,27 +0,0 @@
 | 
				
			|||||||
-----BEGIN RSA PRIVATE KEY-----
 | 
					 | 
				
			||||||
MIIEpAIBAAKCAQEAtvTfNOiIwrwPNs35PQjzcGhBzsoDQyUl2md/GA0iOAvln9op
 | 
					 | 
				
			||||||
pzMay0CmqHHB1IvvS+K0Df4UgoPrk1C0FGdIsrLBg2iIeCHAHqBHDZV2B064D/mg
 | 
					 | 
				
			||||||
Gm8t6uc3mfNCt/unuK6nLgT1dpS7Mybt118BCmw0sVtw3tIHNjfJvQzfC8e4u9A0
 | 
					 | 
				
			||||||
X9BeJukSDBRf5B18Gs2S3hu62W+MS+vOJZpkLFrZOWetNAr6wbVBO30O24ctEIUr
 | 
					 | 
				
			||||||
eupHU0i/CCkK21nBo6tLYIBZTqnsmUou94KlIgCLhjvP7UYJqeB8oDcgtuI6TgeZ
 | 
					 | 
				
			||||||
zmzjzyU1BH+TJNQbppA+Wvsi+mG1XYYmite8GwIDAQABAoIBAGRzAXG9EglI01mV
 | 
					 | 
				
			||||||
sPfvyCi5NRhiFXRyGtxU4pTD8TuwXHxtfV0NU/KwJlBpVLBrvBCAAbeE/qHB6D9T
 | 
					 | 
				
			||||||
metx4ZorRs/tPrAmZ6LpANnWa50LfUdYGK0qyZ0lIYPm6YS2KJnfWm6LznEyq60j
 | 
					 | 
				
			||||||
/IW45YthaXTO7aOI0OjVrG+dd4CxU1g1NtCQ9bdDMDjfXFVnoOifXIl8W22eRMoZ
 | 
					 | 
				
			||||||
LzCz+0sI0R0LenXCPT566de21F0NDkIK7NaQ1l5BMX4PA+RsN3cZlzyruA1woPKI
 | 
					 | 
				
			||||||
aBR2LQGNrBfDVGMATtUm89RpWAftb8FmXqYUsM7zAzTO6dViitiB7OFlw7Ax15YH
 | 
					 | 
				
			||||||
MTj5zGECgYEA35ocEEMfyahBN70bjyiqOHlzKwFjDl9DsUf8xqHsNhYAL+GrOK9A
 | 
					 | 
				
			||||||
8lN5ByzcnbV3TJtU4WYbPgQJld8gXFx4h3eS+SkA/ASkAdtgHfdMImZ1v7k3TIPf
 | 
					 | 
				
			||||||
DXOCsHzELsQY6OgiI572Nwzx/Tl+0dFwaOfLjU9iEmmqL667j1Y4NiMCgYEA0Xch
 | 
					 | 
				
			||||||
9K/vwZ1I9gM3ySvG40R2TRriC9Bf8jwrEWeRsWNvBcqtMMrgwAMsMCKDugSZR7n6
 | 
					 | 
				
			||||||
o3WZV6mpvYVLFx0b93v07i7EpFP27kMw3gLNBKX62snR9JbqwAMK7tktgLds5pKM
 | 
					 | 
				
			||||||
DvLHuAQ9XMMXMLX7WlSyhmtFeU7IDulTSHHqdakCgYEAywITCpy2xpKRK7bwx4gH
 | 
					 | 
				
			||||||
C6EQc/IdahYJ0nHmSL0IRY6x+sbrelp7H8ezcVVEs5bmylGYvc/DWgm2XjCnI9P8
 | 
					 | 
				
			||||||
xhlFAhw9PZJFCT6QRISaxfy6WSgi0cBEieTeubd9MmxtpT/khuyy5AZHyj0iLAL4
 | 
					 | 
				
			||||||
CPayMwjopIj0r7f3p8qC3HsCgYBmq2kmYVI4aZrIkv02CtIatYTy+DlSJxnQRvOp
 | 
					 | 
				
			||||||
PUWpWB6kDRrk7pxJIYT4NwKwG+7xvFQA6PR3hn7fmUUcGDWMEeMVGDFkho9ja+W4
 | 
					 | 
				
			||||||
/FB3dc/Gi+PwakS4RwWF20e1brLfNXeXICMKrHFTVYC5bIm+VgOHZW8RLa9bt7wN
 | 
					 | 
				
			||||||
p2CPuQKBgQCjW+rCODmMzEues/I143mYMDdZ1IschtWGiXBNrpkHm/DcZSutbacm
 | 
					 | 
				
			||||||
5C7Kwv44pfA90NHDTjuaIgRgfeUTawkrl8uPXEuj80mW72agf5oS8lJzD+2jibCj
 | 
					 | 
				
			||||||
Q4K52G+0LaTxHLZxufil28Rgja01c0mTcuLbhKtCgHl5EHP19wOKEg==
 | 
					 | 
				
			||||||
-----END RSA PRIVATE KEY-----
 | 
					 | 
				
			||||||
@@ -19,9 +19,13 @@ TEST_CASE("dns", "[net]")
 | 
				
			|||||||
        auto dnsLookup = std::make_shared<DNSLookup>("www.google.com", 80);
 | 
					        auto dnsLookup = std::make_shared<DNSLookup>("www.google.com", 80);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        std::string errMsg;
 | 
					        std::string errMsg;
 | 
				
			||||||
        auto res = dnsLookup->resolve(errMsg, [] { return false; });
 | 
					        struct addrinfo* res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        res = dnsLookup->resolve(errMsg, [] { return false; });
 | 
				
			||||||
        std::cerr << "Error message: " << errMsg << std::endl;
 | 
					        std::cerr << "Error message: " << errMsg << std::endl;
 | 
				
			||||||
        REQUIRE(res != nullptr);
 | 
					        REQUIRE(res != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        dnsLookup->release(res);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    SECTION("Test resolving a non-existing hostname")
 | 
					    SECTION("Test resolving a non-existing hostname")
 | 
				
			||||||
@@ -29,7 +33,7 @@ TEST_CASE("dns", "[net]")
 | 
				
			|||||||
        auto dnsLookup = std::make_shared<DNSLookup>("wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww", 80);
 | 
					        auto dnsLookup = std::make_shared<DNSLookup>("wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww", 80);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        std::string errMsg;
 | 
					        std::string errMsg;
 | 
				
			||||||
        auto res = dnsLookup->resolve(errMsg, [] { return false; });
 | 
					        struct addrinfo* res = dnsLookup->resolve(errMsg, [] { return false; });
 | 
				
			||||||
        std::cerr << "Error message: " << errMsg << std::endl;
 | 
					        std::cerr << "Error message: " << errMsg << std::endl;
 | 
				
			||||||
        REQUIRE(res == nullptr);
 | 
					        REQUIRE(res == nullptr);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -40,7 +44,7 @@ TEST_CASE("dns", "[net]")
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        std::string errMsg;
 | 
					        std::string errMsg;
 | 
				
			||||||
        // The callback returning true means we are requesting cancellation
 | 
					        // The callback returning true means we are requesting cancellation
 | 
				
			||||||
        auto res = dnsLookup->resolve(errMsg, [] { return true; });
 | 
					        struct addrinfo* res = dnsLookup->resolve(errMsg, [] { return true; });
 | 
				
			||||||
        std::cerr << "Error message: " << errMsg << std::endl;
 | 
					        std::cerr << "Error message: " << errMsg << std::endl;
 | 
				
			||||||
        REQUIRE(res == nullptr);
 | 
					        REQUIRE(res == nullptr);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,9 +7,7 @@
 | 
				
			|||||||
#include "catch.hpp"
 | 
					#include "catch.hpp"
 | 
				
			||||||
#include <cstdint>
 | 
					#include <cstdint>
 | 
				
			||||||
#include <iostream>
 | 
					#include <iostream>
 | 
				
			||||||
#include <ixwebsocket/IXGetFreePort.h>
 | 
					 | 
				
			||||||
#include <ixwebsocket/IXHttpClient.h>
 | 
					#include <ixwebsocket/IXHttpClient.h>
 | 
				
			||||||
#include <ixwebsocket/IXHttpServer.h>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
using namespace ix;
 | 
					using namespace ix;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -97,52 +95,6 @@ TEST_CASE("http_client", "[http]")
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined(IXWEBSOCKET_USE_TLS) && !defined(IXWEBSOCKET_USE_SECURE_TRANSPORT)
 | 
					 | 
				
			||||||
    SECTION("Disable hostname validation")
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        static auto test_cert_with_wrong_name = [](bool validate_hostname)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            int port = getFreePort();
 | 
					 | 
				
			||||||
            ix::HttpServer server(port, "127.0.0.1");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            SocketTLSOptions tlsOptionsServer;
 | 
					 | 
				
			||||||
            tlsOptionsServer.tls = true;
 | 
					 | 
				
			||||||
            tlsOptionsServer.caFile = "NONE";
 | 
					 | 
				
			||||||
            tlsOptionsServer.certFile = "./.certs/wrong-name-server-crt.pem";
 | 
					 | 
				
			||||||
            tlsOptionsServer.keyFile = "./.certs/wrong-name-server-key.pem";
 | 
					 | 
				
			||||||
            server.setTLSOptions(tlsOptionsServer);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            auto res = server.listen();
 | 
					 | 
				
			||||||
            REQUIRE(res.first);
 | 
					 | 
				
			||||||
            server.start();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            HttpClient httpClient;
 | 
					 | 
				
			||||||
            SocketTLSOptions tlsOptionsClient;
 | 
					 | 
				
			||||||
            tlsOptionsClient.caFile = "./.certs/trusted-ca-crt.pem";
 | 
					 | 
				
			||||||
            tlsOptionsClient.disable_hostname_validation = validate_hostname;
 | 
					 | 
				
			||||||
            httpClient.setTLSOptions(tlsOptionsClient);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            std::string url("https://localhost:" + std::to_string(port));
 | 
					 | 
				
			||||||
            auto args = httpClient.createRequest(url);
 | 
					 | 
				
			||||||
            args->connectTimeout = 10;
 | 
					 | 
				
			||||||
            args->transferTimeout = 10;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            auto response = httpClient.get(url, args);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            std::cerr << "Status: " << response->statusCode << std::endl;
 | 
					 | 
				
			||||||
            std::cerr << "Error code: " << (int) response->errorCode << std::endl;
 | 
					 | 
				
			||||||
            std::cerr << "Error message: " << response->errorMsg << std::endl;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            server.stop();
 | 
					 | 
				
			||||||
            return std::make_tuple(response->errorCode, response->statusCode);
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        REQUIRE(test_cert_with_wrong_name(false) ==
 | 
					 | 
				
			||||||
                std::make_tuple(HttpErrorCode::CannotConnect, 0));
 | 
					 | 
				
			||||||
        REQUIRE(test_cert_with_wrong_name(true) == std::make_tuple(HttpErrorCode::Ok, 404));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    SECTION("Async API, one call")
 | 
					    SECTION("Async API, one call")
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        bool async = true;
 | 
					        bool async = true;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										31
									
								
								ws/ws.cpp
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								ws/ws.cpp
									
									
									
									
									
								
							@@ -77,6 +77,24 @@ namespace
 | 
				
			|||||||
        return std::make_pair(res.first, std::string(vec.begin(), vec.end()));
 | 
					        return std::make_pair(res.first, std::string(vec.begin(), vec.end()));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Assume the file exists
 | 
				
			||||||
 | 
					    std::string readBytes(const std::string& path)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::vector<uint8_t> memblock;
 | 
				
			||||||
 | 
					        std::ifstream file(path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        file.seekg(0, file.end);
 | 
				
			||||||
 | 
					        std::streamoff size = file.tellg();
 | 
				
			||||||
 | 
					        file.seekg(0, file.beg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        memblock.reserve((size_t) size);
 | 
				
			||||||
 | 
					        memblock.insert(
 | 
				
			||||||
 | 
					            memblock.begin(), std::istream_iterator<char>(file), std::istream_iterator<char>());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::string bytes(memblock.begin(), memblock.end());
 | 
				
			||||||
 | 
					        return bytes;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::string truncate(const std::string& str, size_t n)
 | 
					    std::string truncate(const std::string& str, size_t n)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if (str.size() < n)
 | 
					        if (str.size() < n)
 | 
				
			||||||
@@ -89,6 +107,12 @@ namespace
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool fileExists(const std::string& fileName)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::ifstream infile(fileName);
 | 
				
			||||||
 | 
					        return infile.good();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::string extractFilename(const std::string& path)
 | 
					    std::string extractFilename(const std::string& path)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        std::string::size_type idx;
 | 
					        std::string::size_type idx;
 | 
				
			||||||
@@ -892,8 +916,9 @@ namespace ix
 | 
				
			|||||||
        auto dnsLookup = std::make_shared<DNSLookup>(hostname, 80);
 | 
					        auto dnsLookup = std::make_shared<DNSLookup>(hostname, 80);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        std::string errMsg;
 | 
					        std::string errMsg;
 | 
				
			||||||
 | 
					        struct addrinfo* res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        auto res = dnsLookup->resolve(errMsg, [] { return false; });
 | 
					        res = dnsLookup->resolve(errMsg, [] { return false; });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        auto addr = res->ai_addr;
 | 
					        auto addr = res->ai_addr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -2461,8 +2486,10 @@ int main(int argc, char** argv)
 | 
				
			|||||||
    bool verbose = false;
 | 
					    bool verbose = false;
 | 
				
			||||||
    bool save = false;
 | 
					    bool save = false;
 | 
				
			||||||
    bool quiet = false;
 | 
					    bool quiet = false;
 | 
				
			||||||
 | 
					    bool fluentd = false;
 | 
				
			||||||
    bool compress = false;
 | 
					    bool compress = false;
 | 
				
			||||||
    bool compressRequest = false;
 | 
					    bool compressRequest = false;
 | 
				
			||||||
 | 
					    bool stress = false;
 | 
				
			||||||
    bool disableAutomaticReconnection = false;
 | 
					    bool disableAutomaticReconnection = false;
 | 
				
			||||||
    bool disablePerMessageDeflate = false;
 | 
					    bool disablePerMessageDeflate = false;
 | 
				
			||||||
    bool greetings = false;
 | 
					    bool greetings = false;
 | 
				
			||||||
@@ -2478,6 +2505,7 @@ int main(int argc, char** argv)
 | 
				
			|||||||
    int transferTimeout = 1800;
 | 
					    int transferTimeout = 1800;
 | 
				
			||||||
    int maxRedirects = 5;
 | 
					    int maxRedirects = 5;
 | 
				
			||||||
    int delayMs = -1;
 | 
					    int delayMs = -1;
 | 
				
			||||||
 | 
					    int count = 1;
 | 
				
			||||||
    int msgCount = 1000 * 1000;
 | 
					    int msgCount = 1000 * 1000;
 | 
				
			||||||
    uint32_t maxWaitBetweenReconnectionRetries = 10 * 1000; // 10 seconds
 | 
					    uint32_t maxWaitBetweenReconnectionRetries = 10 * 1000; // 10 seconds
 | 
				
			||||||
    int pingIntervalSecs = 30;
 | 
					    int pingIntervalSecs = 30;
 | 
				
			||||||
@@ -2501,7 +2529,6 @@ int main(int argc, char** argv)
 | 
				
			|||||||
                        "A (comma/space/colon) separated list of ciphers to use for TLS");
 | 
					                        "A (comma/space/colon) separated list of ciphers to use for TLS");
 | 
				
			||||||
        app->add_flag("--tls", tlsOptions.tls, "Enable TLS (server only)");
 | 
					        app->add_flag("--tls", tlsOptions.tls, "Enable TLS (server only)");
 | 
				
			||||||
        app->add_flag("--verify_none", verifyNone, "Disable peer cert verification");
 | 
					        app->add_flag("--verify_none", verifyNone, "Disable peer cert verification");
 | 
				
			||||||
        app->add_flag("--disable-hostname-validation", tlsOptions.disable_hostname_validation, "Disable validation of certificates' hostnames");
 | 
					 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    app.add_flag("--version", version, "Print ws version");
 | 
					    app.add_flag("--version", version, "Print ws version");
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user