Compare commits
	
		
			52 Commits
		
	
	
		
			user/bserg
			...
			user/bserg
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					fa7ef06f4d | ||
| 
						 | 
					3c9ec0aed0 | ||
| 
						 | 
					c665d65cba | ||
| 
						 | 
					5d4e897cc4 | ||
| 
						 | 
					05033714bf | ||
| 
						 | 
					fdbd213fa2 | ||
| 
						 | 
					da64d349c8 | ||
| 
						 | 
					17b01a8c66 | ||
| 
						 | 
					79dd766fab | ||
| 
						 | 
					8375b28747 | ||
| 
						 | 
					e12551f309 | ||
| 
						 | 
					6102f81710 | ||
| 
						 | 
					9f678e5962 | ||
| 
						 | 
					02a704a8c7 | ||
| 
						 | 
					dd2360ed70 | ||
| 
						 | 
					c4ab996470 | ||
| 
						 | 
					6c54b07d92 | ||
| 
						 | 
					7f9bef3b8d | ||
| 
						 | 
					12d1c5d956 | ||
| 
						 | 
					e9a4bd5617 | ||
| 
						 | 
					f34ccbfdb5 | ||
| 
						 | 
					1fa75d7fb2 | ||
| 
						 | 
					39140ef98c | ||
| 
						 | 
					e30ef4a87c | ||
| 
						 | 
					9fc94f0487 | ||
| 
						 | 
					121acdab6f | ||
| 
						 | 
					6deaa03114 | ||
| 
						 | 
					f4f30686c5 | ||
| 
						 | 
					a21aae521f | ||
| 
						 | 
					aed2356fc1 | ||
| 
						 | 
					a478f734f6 | ||
| 
						 | 
					98c579da03 | ||
| 
						 | 
					e80def0cd0 | ||
| 
						 | 
					cc8a9e883e | ||
| 
						 | 
					4d587e35d8 | ||
| 
						 | 
					50f4fd1115 | ||
| 
						 | 
					06d2b68696 | ||
| 
						 | 
					bf6f057777 | ||
| 
						 | 
					b57c1d69f2 | ||
| 
						 | 
					ff265d83f9 | ||
| 
						 | 
					5b1c97b774 | ||
| 
						 | 
					c8c81366f7 | ||
| 
						 | 
					9a37fd56d1 | ||
| 
						 | 
					7ecaff8c5d | ||
| 
						 | 
					e4b0286a25 | ||
| 
						 | 
					7ae6972306 | ||
| 
						 | 
					59cea0372b | ||
| 
						 | 
					78d88a8520 | ||
| 
						 | 
					273af25d57 | ||
| 
						 | 
					46d00360a8 | ||
| 
						 | 
					3f5935a284 | ||
| 
						 | 
					c236ff66e9 | 
							
								
								
									
										0
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
								
								
									
										9
									
								
								.travis.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								.travis.yml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					language: cpp
 | 
				
			||||||
 | 
					dist: xenial
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					compiler:
 | 
				
			||||||
 | 
					  - clang
 | 
				
			||||||
 | 
					#   - gcc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					os: osx
 | 
				
			||||||
 | 
					script: make test
 | 
				
			||||||
@@ -6,15 +6,18 @@
 | 
				
			|||||||
cmake_minimum_required(VERSION 3.4.1)
 | 
					cmake_minimum_required(VERSION 3.4.1)
 | 
				
			||||||
project(ixwebsocket C CXX)
 | 
					project(ixwebsocket C CXX)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
set (CMAKE_CXX_STANDARD 11)
 | 
					set (CMAKE_CXX_STANDARD 14)
 | 
				
			||||||
set (CXX_STANDARD_REQUIRED ON)
 | 
					set (CXX_STANDARD_REQUIRED ON)
 | 
				
			||||||
set (CMAKE_CXX_EXTENSIONS OFF)
 | 
					set (CMAKE_CXX_EXTENSIONS OFF)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic -Wshorten-64-to-32")
 | 
					if (NOT WIN32)
 | 
				
			||||||
 | 
					  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic")
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
set( IXWEBSOCKET_SOURCES
 | 
					set( IXWEBSOCKET_SOURCES
 | 
				
			||||||
    ixwebsocket/IXEventFd.cpp
 | 
					    ixwebsocket/IXEventFd.cpp
 | 
				
			||||||
    ixwebsocket/IXSocket.cpp
 | 
					    ixwebsocket/IXSocket.cpp
 | 
				
			||||||
 | 
					    ixwebsocket/IXSocketServer.cpp
 | 
				
			||||||
    ixwebsocket/IXSocketConnect.cpp
 | 
					    ixwebsocket/IXSocketConnect.cpp
 | 
				
			||||||
    ixwebsocket/IXDNSLookup.cpp
 | 
					    ixwebsocket/IXDNSLookup.cpp
 | 
				
			||||||
    ixwebsocket/IXCancellationRequest.cpp
 | 
					    ixwebsocket/IXCancellationRequest.cpp
 | 
				
			||||||
@@ -23,12 +26,14 @@ set( IXWEBSOCKET_SOURCES
 | 
				
			|||||||
    ixwebsocket/IXWebSocketTransport.cpp
 | 
					    ixwebsocket/IXWebSocketTransport.cpp
 | 
				
			||||||
    ixwebsocket/IXWebSocketHandshake.cpp
 | 
					    ixwebsocket/IXWebSocketHandshake.cpp
 | 
				
			||||||
    ixwebsocket/IXWebSocketPerMessageDeflate.cpp
 | 
					    ixwebsocket/IXWebSocketPerMessageDeflate.cpp
 | 
				
			||||||
 | 
					    ixwebsocket/IXWebSocketPerMessageDeflateCodec.cpp
 | 
				
			||||||
    ixwebsocket/IXWebSocketPerMessageDeflateOptions.cpp
 | 
					    ixwebsocket/IXWebSocketPerMessageDeflateOptions.cpp
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
set( IXWEBSOCKET_HEADERS
 | 
					set( IXWEBSOCKET_HEADERS
 | 
				
			||||||
    ixwebsocket/IXEventFd.h
 | 
					    ixwebsocket/IXEventFd.h
 | 
				
			||||||
    ixwebsocket/IXSocket.h
 | 
					    ixwebsocket/IXSocket.h
 | 
				
			||||||
 | 
					    ixwebsocket/IXSocketServer.h
 | 
				
			||||||
    ixwebsocket/IXSocketConnect.h
 | 
					    ixwebsocket/IXSocketConnect.h
 | 
				
			||||||
    ixwebsocket/IXSetThreadName.h
 | 
					    ixwebsocket/IXSetThreadName.h
 | 
				
			||||||
    ixwebsocket/IXDNSLookup.h
 | 
					    ixwebsocket/IXDNSLookup.h
 | 
				
			||||||
@@ -40,18 +45,21 @@ set( IXWEBSOCKET_HEADERS
 | 
				
			|||||||
    ixwebsocket/IXWebSocketSendInfo.h
 | 
					    ixwebsocket/IXWebSocketSendInfo.h
 | 
				
			||||||
    ixwebsocket/IXWebSocketErrorInfo.h
 | 
					    ixwebsocket/IXWebSocketErrorInfo.h
 | 
				
			||||||
    ixwebsocket/IXWebSocketPerMessageDeflate.h
 | 
					    ixwebsocket/IXWebSocketPerMessageDeflate.h
 | 
				
			||||||
 | 
					    ixwebsocket/IXWebSocketPerMessageDeflateCodec.h
 | 
				
			||||||
    ixwebsocket/IXWebSocketPerMessageDeflateOptions.h
 | 
					    ixwebsocket/IXWebSocketPerMessageDeflateOptions.h
 | 
				
			||||||
    ixwebsocket/IXWebSocketHttpHeaders.h
 | 
					    ixwebsocket/IXWebSocketHttpHeaders.h
 | 
				
			||||||
 | 
					    ixwebsocket/libwshandshake.hpp
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Platform specific code
 | 
					# Platform specific code
 | 
				
			||||||
if (APPLE)
 | 
					if (APPLE)
 | 
				
			||||||
    list( APPEND IXWEBSOCKET_SOURCES ixwebsocket/apple/IXSetThreadName_apple.cpp)
 | 
					    list( APPEND IXWEBSOCKET_SOURCES ixwebsocket/apple/IXSetThreadName_apple.cpp)
 | 
				
			||||||
 | 
					elseif (WIN32)
 | 
				
			||||||
 | 
					    list( APPEND IXWEBSOCKET_SOURCES ixwebsocket/windows/IXSetThreadName_windows.cpp)
 | 
				
			||||||
else()
 | 
					else()
 | 
				
			||||||
    list( APPEND IXWEBSOCKET_SOURCES ixwebsocket/linux/IXSetThreadName_linux.cpp)
 | 
					    list( APPEND IXWEBSOCKET_SOURCES ixwebsocket/linux/IXSetThreadName_linux.cpp)
 | 
				
			||||||
endif()
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
if (USE_TLS)
 | 
					if (USE_TLS)
 | 
				
			||||||
    add_definitions(-DIXWEBSOCKET_USE_TLS)
 | 
					    add_definitions(-DIXWEBSOCKET_USE_TLS)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -72,7 +80,33 @@ add_library( ixwebsocket STATIC
 | 
				
			|||||||
    ${IXWEBSOCKET_HEADERS}
 | 
					    ${IXWEBSOCKET_HEADERS}
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(ixwebsocket "z")
 | 
					# gcc/Linux needs -pthread
 | 
				
			||||||
 | 
					find_package(Threads)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if(UNIX AND NOT APPLE)
 | 
				
			||||||
 | 
					  find_package(OpenSSL REQUIRED)
 | 
				
			||||||
 | 
					  add_definitions(${OPENSSL_DEFINITIONS})
 | 
				
			||||||
 | 
					  message(STATUS "OpenSSL: " ${OPENSSL_VERSION})
 | 
				
			||||||
 | 
					  include_directories(${OPENSSL_INCLUDE_DIR})
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (WIN32)
 | 
				
			||||||
 | 
					  get_filename_component(libz_path
 | 
				
			||||||
 | 
					    ${PROJECT_SOURCE_DIR}/third_party/ZLIB-Windows/zlib-1.2.11_deploy_v140/release_dynamic/x64/lib/zlib.lib
 | 
				
			||||||
 | 
					    ABSOLUTE)
 | 
				
			||||||
 | 
					  add_library(libz STATIC IMPORTED)
 | 
				
			||||||
 | 
					  set_target_properties(libz PROPERTIES IMPORTED_LOCATION
 | 
				
			||||||
 | 
					    ${libz_path})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  include_directories(${PROJECT_SOURCE_DIR}/third_party/ZLIB-Windows/zlib-1.2.11_deploy_v140/include)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  target_link_libraries(ixwebsocket libz wsock32 ws2_32)
 | 
				
			||||||
 | 
					  add_definitions(-D_CRT_SECURE_NO_WARNINGS)
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					else()
 | 
				
			||||||
 | 
					  target_link_libraries(ixwebsocket 
 | 
				
			||||||
 | 
					    z ${OPENSSL_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
set( IXWEBSOCKET_INCLUDE_DIRS
 | 
					set( IXWEBSOCKET_INCLUDE_DIRS
 | 
				
			||||||
    .
 | 
					    .
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										17
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								README.md
									
									
									
									
									
								
							@@ -1,5 +1,7 @@
 | 
				
			|||||||
# General
 | 
					# General
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Introduction
 | 
					## Introduction
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[*WebSocket*](https://en.wikipedia.org/wiki/WebSocket) is a computer communications protocol, providing full-duplex
 | 
					[*WebSocket*](https://en.wikipedia.org/wiki/WebSocket) is a computer communications protocol, providing full-duplex
 | 
				
			||||||
@@ -21,7 +23,11 @@ Here is what the client API looks like.
 | 
				
			|||||||
ix::WebSocket webSocket;
 | 
					ix::WebSocket webSocket;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
std::string url("ws://localhost:8080/");
 | 
					std::string url("ws://localhost:8080/");
 | 
				
			||||||
webSocket.configure(url);
 | 
					webSocket.setUrl(url);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Optional heart beat, sent every 45 seconds when there isn't any traffic
 | 
				
			||||||
 | 
					// to make sure that load balancers do not kill an idle connection.
 | 
				
			||||||
 | 
					webSocket.setHeartBeatPeriod(45);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Setup a callback to be fired when a message or an event (open, close, error) is received
 | 
					// Setup a callback to be fired when a message or an event (open, close, error) is received
 | 
				
			||||||
webSocket.setOnMessageCallback(
 | 
					webSocket.setOnMessageCallback(
 | 
				
			||||||
@@ -303,4 +309,13 @@ A ping message can be sent to the server, with an optional data string.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
websocket.ping("ping data, optional (empty string is ok): limited to 125 bytes long");
 | 
					websocket.ping("ping data, optional (empty string is ok): limited to 125 bytes long");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Heartbeat.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You can configure an optional heart beat / keep-alive, sent every 45 seconds
 | 
				
			||||||
 | 
					when there isn't any traffic to make sure that load balancers do not kill an
 | 
				
			||||||
 | 
					idle connection.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					webSocket.setHeartBeatPeriod(45);
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										10
									
								
								appveyor.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								appveyor.yml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					image:
 | 
				
			||||||
 | 
					- Visual Studio 2017
 | 
				
			||||||
 | 
					- Ubuntu
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					install:
 | 
				
			||||||
 | 
					- ls -al
 | 
				
			||||||
 | 
					- cmd: call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat"
 | 
				
			||||||
 | 
					- python test/run.py
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					build: off
 | 
				
			||||||
@@ -11,7 +11,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic -Wshorten-64-to-
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
set (OPENSSL_PREFIX /usr/local/opt/openssl) # Homebrew openssl
 | 
					set (OPENSSL_PREFIX /usr/local/opt/openssl) # Homebrew openssl
 | 
				
			||||||
 | 
					
 | 
				
			||||||
set (CMAKE_CXX_STANDARD 11)
 | 
					set (CMAKE_CXX_STANDARD 14)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
option(USE_TLS "Add TLS support" ON)
 | 
					option(USE_TLS "Add TLS support" ON)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,7 +7,7 @@
 | 
				
			|||||||
cmake_minimum_required (VERSION 3.4.1)
 | 
					cmake_minimum_required (VERSION 3.4.1)
 | 
				
			||||||
project (cmd_websocket_chat)
 | 
					project (cmd_websocket_chat)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
set (CMAKE_CXX_STANDARD 11)
 | 
					set (CMAKE_CXX_STANDARD 14)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
option(USE_TLS "Add TLS support" ON)
 | 
					option(USE_TLS "Add TLS support" ON)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,7 +11,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic -Wshorten-64-to-
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
set (OPENSSL_PREFIX /usr/local/opt/openssl) # Homebrew openssl
 | 
					set (OPENSSL_PREFIX /usr/local/opt/openssl) # Homebrew openssl
 | 
				
			||||||
 | 
					
 | 
				
			||||||
set (CMAKE_CXX_STANDARD 11)
 | 
					set (CMAKE_CXX_STANDARD 14)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
option(USE_TLS "Add TLS support" ON)
 | 
					option(USE_TLS "Add TLS support" ON)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,7 +11,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic -Wshorten-64-to-
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
set (OPENSSL_PREFIX /usr/local/opt/openssl) # Homebrew openssl
 | 
					set (OPENSSL_PREFIX /usr/local/opt/openssl) # Homebrew openssl
 | 
				
			||||||
 | 
					
 | 
				
			||||||
set (CMAKE_CXX_STANDARD 11)
 | 
					set (CMAKE_CXX_STANDARD 14)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
option(USE_TLS "Add TLS support" ON)
 | 
					option(USE_TLS "Add TLS support" ON)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,7 +6,7 @@
 | 
				
			|||||||
cmake_minimum_required (VERSION 3.4.1)
 | 
					cmake_minimum_required (VERSION 3.4.1)
 | 
				
			||||||
project (ping_pong)
 | 
					project (ping_pong)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
set (CMAKE_CXX_STANDARD 11)
 | 
					set (CMAKE_CXX_STANDARD 14)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
option(USE_TLS "Add TLS support" ON)
 | 
					option(USE_TLS "Add TLS support" ON)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,7 +6,7 @@
 | 
				
			|||||||
cmake_minimum_required (VERSION 3.4.1)
 | 
					cmake_minimum_required (VERSION 3.4.1)
 | 
				
			||||||
project (ws_connect)
 | 
					project (ws_connect)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
set (CMAKE_CXX_STANDARD 11)
 | 
					set (CMAKE_CXX_STANDARD 14)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
option(USE_TLS "Add TLS support" ON)
 | 
					option(USE_TLS "Add TLS support" ON)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,10 +5,8 @@
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "IXDNSLookup.h"
 | 
					#include "IXDNSLookup.h"
 | 
				
			||||||
 | 
					#include "IXNetSystem.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <sys/types.h>
 | 
					 | 
				
			||||||
#include <sys/socket.h>
 | 
					 | 
				
			||||||
#include <netdb.h>
 | 
					 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
#include <chrono>
 | 
					#include <chrono>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -107,7 +105,7 @@ namespace ix
 | 
				
			|||||||
        // Good resource on thread forced termination
 | 
					        // Good resource on thread forced termination
 | 
				
			||||||
        // https://www.bo-yang.net/2017/11/19/cpp-kill-detached-thread
 | 
					        // https://www.bo-yang.net/2017/11/19/cpp-kill-detached-thread
 | 
				
			||||||
        //
 | 
					        //
 | 
				
			||||||
        _thread = std::thread(&DNSLookup::run, this);
 | 
					        _thread = std::thread(&DNSLookup::run, this, _id, _hostname, _port);
 | 
				
			||||||
        _thread.detach();
 | 
					        _thread.detach();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        std::unique_lock<std::mutex> lock(_conditionVariableMutex);
 | 
					        std::unique_lock<std::mutex> lock(_conditionVariableMutex);
 | 
				
			||||||
@@ -140,11 +138,13 @@ namespace ix
 | 
				
			|||||||
        return _res;
 | 
					        return _res;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void DNSLookup::run()
 | 
					    void DNSLookup::run(uint64_t id, const std::string& hostname, int port) // thread runner
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        uint64_t id = _id;
 | 
					        // We don't want to read or write into members variables of an object that could be
 | 
				
			||||||
 | 
					        // gone, so we use temporary variables (res) or we pass in by copy everything that 
 | 
				
			||||||
 | 
					        // getAddrInfo needs to work.
 | 
				
			||||||
        std::string errMsg;
 | 
					        std::string errMsg;
 | 
				
			||||||
        _res = getAddrInfo(_hostname, _port, errMsg);
 | 
					        struct addrinfo* res = getAddrInfo(hostname, port, errMsg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // if this isn't an active job, and the control thread is gone
 | 
					        // if this isn't an active job, and the control thread is gone
 | 
				
			||||||
        // there is not thing to do, and we don't want to touch the defunct
 | 
					        // there is not thing to do, and we don't want to touch the defunct
 | 
				
			||||||
@@ -155,9 +155,10 @@ namespace ix
 | 
				
			|||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Copy result into the member variables
 | 
				
			||||||
 | 
					        _res = res;
 | 
				
			||||||
        _errMsg = errMsg;
 | 
					        _errMsg = errMsg;
 | 
				
			||||||
        _condition.notify_one();
 | 
					        _condition.notify_one();
 | 
				
			||||||
        _done = true;
 | 
					        _done = true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -43,7 +43,7 @@ namespace ix
 | 
				
			|||||||
                                            int port,
 | 
					                                            int port,
 | 
				
			||||||
                                            std::string& errMsg);
 | 
					                                            std::string& errMsg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void run(); // thread runner
 | 
					        void run(uint64_t id, const std::string& hostname, int port); // thread runner
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        std::string _hostname;
 | 
					        std::string _hostname;
 | 
				
			||||||
        int _port;
 | 
					        int _port;
 | 
				
			||||||
@@ -56,7 +56,7 @@ namespace ix
 | 
				
			|||||||
        std::condition_variable _condition;
 | 
					        std::condition_variable _condition;
 | 
				
			||||||
        std::mutex _conditionVariableMutex;
 | 
					        std::mutex _conditionVariableMutex;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        std::atomic<uint64_t> _id;
 | 
					        uint64_t _id;
 | 
				
			||||||
        static std::atomic<uint64_t> _nextId;
 | 
					        static std::atomic<uint64_t> _nextId;
 | 
				
			||||||
        static std::set<uint64_t> _activeJobs;
 | 
					        static std::set<uint64_t> _activeJobs;
 | 
				
			||||||
        static std::mutex _activeJobsMutex;
 | 
					        static std::mutex _activeJobsMutex;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										25
									
								
								ixwebsocket/IXNetSystem.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								ixwebsocket/IXNetSystem.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *  IXNetSystem.h
 | 
				
			||||||
 | 
					 *  Author: Benjamin Sergeant
 | 
				
			||||||
 | 
					 *  Copyright (c) 2019 Machine Zone. All rights reserved.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef _WIN32
 | 
				
			||||||
 | 
					# include <WS2tcpip.h>
 | 
				
			||||||
 | 
					# include <WinSock2.h>
 | 
				
			||||||
 | 
					# include <basetsd.h>
 | 
				
			||||||
 | 
					# include <io.h>
 | 
				
			||||||
 | 
					# include <ws2def.h>
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					# include <arpa/inet.h>
 | 
				
			||||||
 | 
					# include <errno.h>
 | 
				
			||||||
 | 
					# include <netdb.h>
 | 
				
			||||||
 | 
					# include <netinet/tcp.h>
 | 
				
			||||||
 | 
					# include <sys/select.h>
 | 
				
			||||||
 | 
					# include <sys/socket.h>
 | 
				
			||||||
 | 
					# include <sys/stat.h>
 | 
				
			||||||
 | 
					# include <sys/time.h>
 | 
				
			||||||
 | 
					# include <unistd.h>
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
@@ -1,31 +0,0 @@
 | 
				
			|||||||
/*
 | 
					 | 
				
			||||||
 *  IXSetThreadName.cpp
 | 
					 | 
				
			||||||
 *  Author: Benjamin Sergeant
 | 
					 | 
				
			||||||
 *  Copyright (c) 2018 Machine Zone, Inc. All rights reserved.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
#include "IXSetThreadName.h"
 | 
					 | 
				
			||||||
#include <pthread.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace ix
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    void setThreadName(const std::string& name)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
#if defined(__linux__)
 | 
					 | 
				
			||||||
        //
 | 
					 | 
				
			||||||
        // Linux only reserve 16 bytes for its thread names
 | 
					 | 
				
			||||||
        // See prctl and PR_SET_NAME property in
 | 
					 | 
				
			||||||
        // http://man7.org/linux/man-pages/man2/prctl.2.html
 | 
					 | 
				
			||||||
        //
 | 
					 | 
				
			||||||
        pthread_setname_np(pthread_self(),
 | 
					 | 
				
			||||||
                           name.substr(0, 15).c_str());
 | 
					 | 
				
			||||||
#elif defined(__APPLE__)
 | 
					 | 
				
			||||||
        //
 | 
					 | 
				
			||||||
        // Apple is more generous with 64 chars.
 | 
					 | 
				
			||||||
        // notice how the Apple version does not take a pthread_t argument
 | 
					 | 
				
			||||||
        //
 | 
					 | 
				
			||||||
        pthread_setname_np(name.substr(0, 63).c_str());
 | 
					 | 
				
			||||||
#elif
 | 
					 | 
				
			||||||
        #error("Unsupported platform");
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -6,23 +6,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "IXSocket.h"
 | 
					#include "IXSocket.h"
 | 
				
			||||||
#include "IXSocketConnect.h"
 | 
					#include "IXSocketConnect.h"
 | 
				
			||||||
 | 
					#include "IXNetSystem.h"
 | 
				
			||||||
#ifdef _WIN32
 | 
					 | 
				
			||||||
# include <basetsd.h>
 | 
					 | 
				
			||||||
# include <WinSock2.h>
 | 
					 | 
				
			||||||
# include <ws2def.h>
 | 
					 | 
				
			||||||
# include <WS2tcpip.h>
 | 
					 | 
				
			||||||
# include <io.h>
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
# include <unistd.h>
 | 
					 | 
				
			||||||
# include <errno.h>
 | 
					 | 
				
			||||||
# include <netdb.h>
 | 
					 | 
				
			||||||
# include <netinet/tcp.h>
 | 
					 | 
				
			||||||
# include <sys/socket.h>
 | 
					 | 
				
			||||||
# include <sys/time.h>
 | 
					 | 
				
			||||||
# include <sys/select.h>
 | 
					 | 
				
			||||||
# include <sys/stat.h>
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
@@ -37,6 +21,9 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace ix 
 | 
					namespace ix 
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    const int Socket::kDefaultPollNoTimeout = -1; // No poll timeout by default
 | 
				
			||||||
 | 
					    const int Socket::kDefaultPollTimeout = kDefaultPollNoTimeout;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Socket::Socket(int fd) : 
 | 
					    Socket::Socket(int fd) : 
 | 
				
			||||||
        _sockfd(fd)
 | 
					        _sockfd(fd)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@@ -48,14 +35,8 @@ namespace ix
 | 
				
			|||||||
        close();
 | 
					        close();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void Socket::poll(const OnPollCallback& onPollCallback)
 | 
					    void Socket::poll(const OnPollCallback& onPollCallback, int timeoutSecs)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if (_sockfd == -1)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            onPollCallback();
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        fd_set rfds;
 | 
					        fd_set rfds;
 | 
				
			||||||
        FD_ZERO(&rfds);
 | 
					        FD_ZERO(&rfds);
 | 
				
			||||||
        FD_SET(_sockfd, &rfds);
 | 
					        FD_SET(_sockfd, &rfds);
 | 
				
			||||||
@@ -64,11 +45,26 @@ namespace ix
 | 
				
			|||||||
        FD_SET(_eventfd.getFd(), &rfds);
 | 
					        FD_SET(_eventfd.getFd(), &rfds);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        struct timeval timeout;
 | 
				
			||||||
 | 
					        timeout.tv_sec = timeoutSecs;
 | 
				
			||||||
 | 
					        timeout.tv_usec = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        int sockfd = _sockfd;
 | 
					        int sockfd = _sockfd;
 | 
				
			||||||
        int nfds = (std::max)(sockfd, _eventfd.getFd());
 | 
					        int nfds = (std::max)(sockfd, _eventfd.getFd());
 | 
				
			||||||
        select(nfds + 1, &rfds, nullptr, nullptr, nullptr);
 | 
					        int ret = select(nfds + 1, &rfds, nullptr, nullptr,
 | 
				
			||||||
 | 
					                         (timeoutSecs == kDefaultPollNoTimeout) ? nullptr : &timeout);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        onPollCallback();
 | 
					        PollResultType pollResult = PollResultType_ReadyForRead;
 | 
				
			||||||
 | 
					        if (ret < 0)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            pollResult = PollResultType_Error;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else if (ret == 0)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            pollResult = PollResultType_Timeout;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        onPollCallback(pollResult);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void Socket::wakeUpFromPoll()
 | 
					    void Socket::wakeUpFromPoll()
 | 
				
			||||||
@@ -100,32 +96,32 @@ namespace ix
 | 
				
			|||||||
        _sockfd = -1;
 | 
					        _sockfd = -1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int Socket::send(char* buffer, size_t length)
 | 
					    ssize_t Socket::send(char* buffer, size_t length)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        int flags = 0;
 | 
					        int flags = 0;
 | 
				
			||||||
#ifdef MSG_NOSIGNAL
 | 
					#ifdef MSG_NOSIGNAL
 | 
				
			||||||
        flags = MSG_NOSIGNAL;
 | 
					        flags = MSG_NOSIGNAL;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return (int) ::send(_sockfd, buffer, length, flags);
 | 
					        return ::send(_sockfd, buffer, length, flags);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int Socket::send(const std::string& buffer)
 | 
					    ssize_t Socket::send(const std::string& buffer)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return send((char*)&buffer[0], buffer.size());
 | 
					        return send((char*)&buffer[0], buffer.size());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int Socket::recv(void* buffer, size_t length)
 | 
					    ssize_t Socket::recv(void* buffer, size_t length)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        int flags = 0;
 | 
					        int flags = 0;
 | 
				
			||||||
#ifdef MSG_NOSIGNAL
 | 
					#ifdef MSG_NOSIGNAL
 | 
				
			||||||
        flags = MSG_NOSIGNAL;
 | 
					        flags = MSG_NOSIGNAL;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return (int) ::recv(_sockfd, (char*) buffer, length, flags);
 | 
					        return ::recv(_sockfd, (char*) buffer, length, flags);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int Socket::getErrno() const
 | 
					    int Socket::getErrno()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
#ifdef _WIN32
 | 
					#ifdef _WIN32
 | 
				
			||||||
        return WSAGetLastError();
 | 
					        return WSAGetLastError();
 | 
				
			||||||
@@ -170,7 +166,7 @@ namespace ix
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            if (isCancellationRequested()) return false;
 | 
					            if (isCancellationRequested()) return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            int ret;
 | 
					            ssize_t ret;
 | 
				
			||||||
            ret = recv(buffer, 1);
 | 
					            ret = recv(buffer, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // We read one byte, as needed, all good.
 | 
					            // We read one byte, as needed, all good.
 | 
				
			||||||
@@ -187,11 +183,16 @@ namespace ix
 | 
				
			|||||||
                fd_set rfds;
 | 
					                fd_set rfds;
 | 
				
			||||||
                struct timeval timeout;
 | 
					                struct timeval timeout;
 | 
				
			||||||
                timeout.tv_sec = 0;
 | 
					                timeout.tv_sec = 0;
 | 
				
			||||||
                timeout.tv_usec = 1 * 1000; // 1ms
 | 
					                timeout.tv_usec = 1 * 1000; // 1ms timeout
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                FD_ZERO(&rfds);
 | 
					                FD_ZERO(&rfds);
 | 
				
			||||||
                FD_SET(_sockfd, &rfds);
 | 
					                FD_SET(_sockfd, &rfds);
 | 
				
			||||||
                select(_sockfd + 1, &rfds, nullptr, nullptr, &timeout);
 | 
					
 | 
				
			||||||
 | 
					                if (select(_sockfd + 1, &rfds, nullptr, nullptr, &timeout) < 0 &&
 | 
				
			||||||
 | 
					                    (errno == EBADF || errno == EINVAL))
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    return false;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                continue;
 | 
					                continue;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@@ -213,7 +214,7 @@ namespace ix
 | 
				
			|||||||
            char* buffer = const_cast<char*>(str.c_str());
 | 
					            char* buffer = const_cast<char*>(str.c_str());
 | 
				
			||||||
            int len = (int) str.size();
 | 
					            int len = (int) str.size();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            int ret = send(buffer, len);
 | 
					            ssize_t ret = send(buffer, len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // We wrote some bytes, as needed, all good.
 | 
					            // We wrote some bytes, as needed, all good.
 | 
				
			||||||
            if (ret > 0)
 | 
					            if (ret > 0)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,21 +11,34 @@
 | 
				
			|||||||
#include <mutex>
 | 
					#include <mutex>
 | 
				
			||||||
#include <atomic>
 | 
					#include <atomic>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef _WIN32
 | 
				
			||||||
 | 
					#include <BaseTsd.h>
 | 
				
			||||||
 | 
					typedef SSIZE_T ssize_t;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "IXEventFd.h"
 | 
					#include "IXEventFd.h"
 | 
				
			||||||
#include "IXCancellationRequest.h"
 | 
					#include "IXCancellationRequest.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace ix 
 | 
					namespace ix 
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    enum PollResultType
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        PollResultType_ReadyForRead = 0,
 | 
				
			||||||
 | 
					        PollResultType_Timeout = 1,
 | 
				
			||||||
 | 
					        PollResultType_Error = 2
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class Socket {
 | 
					    class Socket {
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        using OnPollCallback = std::function<void()>;
 | 
					        using OnPollCallback = std::function<void(PollResultType)>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Socket(int fd = -1);
 | 
					        Socket(int fd = -1);
 | 
				
			||||||
        virtual ~Socket();
 | 
					        virtual ~Socket();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void configure();
 | 
					        void configure();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        virtual void poll(const OnPollCallback& onPollCallback);
 | 
					        virtual void poll(const OnPollCallback& onPollCallback,
 | 
				
			||||||
 | 
					                          int timeoutSecs = kDefaultPollTimeout);
 | 
				
			||||||
        virtual void wakeUpFromPoll();
 | 
					        virtual void wakeUpFromPoll();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Virtual methods
 | 
					        // Virtual methods
 | 
				
			||||||
@@ -35,9 +48,9 @@ namespace ix
 | 
				
			|||||||
                             const CancellationRequest& isCancellationRequested);
 | 
					                             const CancellationRequest& isCancellationRequested);
 | 
				
			||||||
        virtual void close();
 | 
					        virtual void close();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        virtual int send(char* buffer, size_t length);
 | 
					        virtual ssize_t send(char* buffer, size_t length);
 | 
				
			||||||
        virtual int send(const std::string& buffer);
 | 
					        virtual ssize_t send(const std::string& buffer);
 | 
				
			||||||
        virtual int recv(void* buffer, size_t length);
 | 
					        virtual ssize_t recv(void* buffer, size_t length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Blocking and cancellable versions, working with socket that can be set
 | 
					        // Blocking and cancellable versions, working with socket that can be set
 | 
				
			||||||
        // to non blocking mode. Used during HTTP upgrade.
 | 
					        // to non blocking mode. Used during HTTP upgrade.
 | 
				
			||||||
@@ -47,7 +60,7 @@ namespace ix
 | 
				
			|||||||
                        const CancellationRequest& isCancellationRequested);
 | 
					                        const CancellationRequest& isCancellationRequested);
 | 
				
			||||||
        std::pair<bool, std::string> readLine(const CancellationRequest& isCancellationRequested);
 | 
					        std::pair<bool, std::string> readLine(const CancellationRequest& isCancellationRequested);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        int getErrno() const;
 | 
					        static int getErrno();
 | 
				
			||||||
        static bool init(); // Required on Windows to initialize WinSocket
 | 
					        static bool init(); // Required on Windows to initialize WinSocket
 | 
				
			||||||
        static void cleanup(); // Required on Windows to cleanup WinSocket
 | 
					        static void cleanup(); // Required on Windows to cleanup WinSocket
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -57,5 +70,9 @@ namespace ix
 | 
				
			|||||||
        std::atomic<int> _sockfd;
 | 
					        std::atomic<int> _sockfd;
 | 
				
			||||||
        std::mutex _socketMutex;
 | 
					        std::mutex _socketMutex;
 | 
				
			||||||
        EventFd _eventfd;
 | 
					        EventFd _eventfd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private:
 | 
				
			||||||
 | 
					        static const int kDefaultPollTimeout;
 | 
				
			||||||
 | 
					        static const int kDefaultPollNoTimeout;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -203,7 +203,7 @@ namespace ix
 | 
				
			|||||||
        Socket::close();
 | 
					        Socket::close();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int SocketAppleSSL::send(char* buf, size_t nbyte)
 | 
					    ssize_t SocketAppleSSL::send(char* buf, size_t nbyte)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        ssize_t ret = 0;
 | 
					        ssize_t ret = 0;
 | 
				
			||||||
        OSStatus status;
 | 
					        OSStatus status;
 | 
				
			||||||
@@ -218,16 +218,16 @@ namespace ix
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        if (ret == 0 && errSSLClosedAbort != status)
 | 
					        if (ret == 0 && errSSLClosedAbort != status)
 | 
				
			||||||
            ret = -1;
 | 
					            ret = -1;
 | 
				
			||||||
        return (int) ret;
 | 
					        return ret;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int SocketAppleSSL::send(const std::string& buffer)
 | 
					    ssize_t SocketAppleSSL::send(const std::string& buffer)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return send((char*)&buffer[0], buffer.size());
 | 
					        return send((char*)&buffer[0], buffer.size());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // No wait support
 | 
					    // No wait support
 | 
				
			||||||
    int SocketAppleSSL::recv(void* buf, size_t nbyte)
 | 
					    ssize_t SocketAppleSSL::recv(void* buf, size_t nbyte)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        OSStatus status = errSSLWouldBlock;
 | 
					        OSStatus status = errSSLWouldBlock;
 | 
				
			||||||
        while (errSSLWouldBlock == status) 
 | 
					        while (errSSLWouldBlock == status) 
 | 
				
			||||||
@@ -237,7 +237,7 @@ namespace ix
 | 
				
			|||||||
            status = SSLRead(_sslContext, buf, nbyte, &processed);
 | 
					            status = SSLRead(_sslContext, buf, nbyte, &processed);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (processed > 0)
 | 
					            if (processed > 0)
 | 
				
			||||||
                return (int) processed;
 | 
					                return (ssize_t) processed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // The connection was reset, inform the caller that this 
 | 
					            // The connection was reset, inform the caller that this 
 | 
				
			||||||
            // Socket should close
 | 
					            // Socket should close
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,9 +28,9 @@ namespace ix
 | 
				
			|||||||
                             const CancellationRequest& isCancellationRequested) final;
 | 
					                             const CancellationRequest& isCancellationRequested) final;
 | 
				
			||||||
        virtual void close() final;
 | 
					        virtual void close() final;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        virtual int send(char* buffer, size_t length) final;
 | 
					        virtual ssize_t send(char* buffer, size_t length) final;
 | 
				
			||||||
        virtual int send(const std::string& buffer) final;
 | 
					        virtual ssize_t send(const std::string& buffer) final;
 | 
				
			||||||
        virtual int recv(void* buffer, size_t length) final;
 | 
					        virtual ssize_t recv(void* buffer, size_t length) final;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private:
 | 
					    private:
 | 
				
			||||||
        SSLContextRef _sslContext;
 | 
					        SSLContextRef _sslContext;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,23 +6,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "IXSocketConnect.h"
 | 
					#include "IXSocketConnect.h"
 | 
				
			||||||
#include "IXDNSLookup.h"
 | 
					#include "IXDNSLookup.h"
 | 
				
			||||||
 | 
					#include "IXNetSystem.h"
 | 
				
			||||||
#ifdef _WIN32
 | 
					 | 
				
			||||||
# include <basetsd.h>
 | 
					 | 
				
			||||||
# include <WinSock2.h>
 | 
					 | 
				
			||||||
# include <ws2def.h>
 | 
					 | 
				
			||||||
# include <WS2tcpip.h>
 | 
					 | 
				
			||||||
# include <io.h>
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
# include <unistd.h>
 | 
					 | 
				
			||||||
# include <errno.h>
 | 
					 | 
				
			||||||
# include <netdb.h>
 | 
					 | 
				
			||||||
# include <netinet/tcp.h>
 | 
					 | 
				
			||||||
# include <sys/socket.h>
 | 
					 | 
				
			||||||
# include <sys/time.h>
 | 
					 | 
				
			||||||
# include <sys/select.h>
 | 
					 | 
				
			||||||
# include <sys/stat.h>
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
#include <fcntl.h>
 | 
					#include <fcntl.h>
 | 
				
			||||||
@@ -86,31 +70,45 @@ namespace ix
 | 
				
			|||||||
            {
 | 
					            {
 | 
				
			||||||
                closeSocket(fd);
 | 
					                closeSocket(fd);
 | 
				
			||||||
                errMsg = "Cancelled";
 | 
					                errMsg = "Cancelled";
 | 
				
			||||||
                return false;
 | 
					                return -1;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
            fd_set wfds;
 | 
					            // Use select to check the status of the new connection
 | 
				
			||||||
            FD_ZERO(&wfds);
 | 
					 | 
				
			||||||
            FD_SET(fd, &wfds);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // 50ms select timeout
 | 
					 | 
				
			||||||
            struct timeval timeout;
 | 
					            struct timeval timeout;
 | 
				
			||||||
            timeout.tv_sec = 0;
 | 
					            timeout.tv_sec = 0;
 | 
				
			||||||
            timeout.tv_usec = 50 * 1000;
 | 
					            timeout.tv_usec = 10 * 1000; // 10ms timeout
 | 
				
			||||||
 | 
					            fd_set wfds;
 | 
				
			||||||
 | 
					            fd_set efds;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            select(fd + 1, nullptr, &wfds, nullptr, &timeout);
 | 
					            FD_ZERO(&wfds);
 | 
				
			||||||
 | 
					            FD_SET(fd, &wfds);
 | 
				
			||||||
 | 
					            FD_ZERO(&efds);
 | 
				
			||||||
 | 
					            FD_SET(fd, &efds);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (select(fd + 1, nullptr, &wfds, &efds, &timeout) < 0 &&
 | 
				
			||||||
 | 
					                (errno == EBADF || errno == EINVAL))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                closeSocket(fd);
 | 
				
			||||||
 | 
					                errMsg = std::string("Connect error, select error: ") + strerror(errno);
 | 
				
			||||||
 | 
					                return -1;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Nothing was written to the socket, wait again.
 | 
					            // Nothing was written to the socket, wait again.
 | 
				
			||||||
            if (!FD_ISSET(fd, &wfds)) continue;
 | 
					            if (!FD_ISSET(fd, &wfds)) continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Something was written to the socket
 | 
					            // Something was written to the socket. Check for errors.
 | 
				
			||||||
            int optval = -1;
 | 
					            int optval = -1;
 | 
				
			||||||
            socklen_t optlen = sizeof(optval);
 | 
					            socklen_t optlen = sizeof(optval);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef _WIN32
 | 
				
			||||||
 | 
					            // On connect error, in async mode, windows will write to the exceptions fds
 | 
				
			||||||
 | 
					            if (FD_ISSET(fd, &efds))
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
            // getsockopt() puts the errno value for connect into optval so 0
 | 
					            // getsockopt() puts the errno value for connect into optval so 0
 | 
				
			||||||
            // means no-error.
 | 
					            // means no-error.
 | 
				
			||||||
            if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &optval, &optlen) == -1 ||
 | 
					            if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &optval, &optlen) == -1 ||
 | 
				
			||||||
                optval != 0)
 | 
					                optval != 0)
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                closeSocket(fd);
 | 
					                closeSocket(fd);
 | 
				
			||||||
                errMsg = strerror(optval);
 | 
					                errMsg = strerror(optval);
 | 
				
			||||||
@@ -173,7 +171,7 @@ namespace ix
 | 
				
			|||||||
        // 2. make socket non blocking
 | 
					        // 2. make socket non blocking
 | 
				
			||||||
#ifdef _WIN32
 | 
					#ifdef _WIN32
 | 
				
			||||||
        unsigned long nonblocking = 1;
 | 
					        unsigned long nonblocking = 1;
 | 
				
			||||||
        ioctlsocket(_sockfd, FIONBIO, &nonblocking);
 | 
					        ioctlsocket(sockfd, FIONBIO, &nonblocking);
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
        fcntl(sockfd, F_SETFL, O_NONBLOCK); // make socket non blocking
 | 
					        fcntl(sockfd, F_SETFL, O_NONBLOCK); // make socket non blocking
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,67 +18,15 @@
 | 
				
			|||||||
#include <errno.h>
 | 
					#include <errno.h>
 | 
				
			||||||
#define socketerrno errno
 | 
					#define socketerrno errno
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
std::mutex initMutex;
 | 
					 | 
				
			||||||
bool openSSLInitialized = false;
 | 
					 | 
				
			||||||
bool openSSLInitializationSuccessful = false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
bool openSSLInitialize(std::string& errMsg)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    std::lock_guard<std::mutex> lock(initMutex);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (openSSLInitialized)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        return openSSLInitializationSuccessful;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
 | 
					 | 
				
			||||||
    if (!OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, nullptr))
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        errMsg = "OPENSSL_init_ssl failure";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        openSSLInitializationSuccessful = false;
 | 
					 | 
				
			||||||
        openSSLInitialized = true;
 | 
					 | 
				
			||||||
        return false;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
    (void) OPENSSL_config(nullptr);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    (void) OpenSSL_add_ssl_algorithms();
 | 
					 | 
				
			||||||
    (void) SSL_load_error_strings();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    openSSLInitializationSuccessful = true;
 | 
					 | 
				
			||||||
    return true;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int openssl_verify_callback(int preverify, X509_STORE_CTX *x509_ctx)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    return preverify;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* create new SSL connection state object */
 | 
					 | 
				
			||||||
SSL *openssl_create_connection(SSL_CTX *ctx, int socket)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    assert(ctx != nullptr);
 | 
					 | 
				
			||||||
    assert(socket > 0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    SSL *ssl = SSL_new(ctx);
 | 
					 | 
				
			||||||
    if (ssl)
 | 
					 | 
				
			||||||
        SSL_set_fd(ssl, socket);
 | 
					 | 
				
			||||||
    return ssl;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
} // anonymous namespace
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace ix 
 | 
					namespace ix 
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    std::atomic<bool> SocketOpenSSL::_openSSLInitializationSuccessful(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    SocketOpenSSL::SocketOpenSSL(int fd) : Socket(fd),
 | 
					    SocketOpenSSL::SocketOpenSSL(int fd) : Socket(fd),
 | 
				
			||||||
        _ssl_connection(nullptr), 
 | 
					        _ssl_connection(nullptr), 
 | 
				
			||||||
        _ssl_context(nullptr)
 | 
					        _ssl_context(nullptr)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        ;
 | 
					        std::call_once(_openSSLInitFlag, &SocketOpenSSL::openSSLInitialize, this);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    SocketOpenSSL::~SocketOpenSSL()
 | 
					    SocketOpenSSL::~SocketOpenSSL()
 | 
				
			||||||
@@ -86,6 +34,20 @@ namespace ix
 | 
				
			|||||||
        SocketOpenSSL::close();
 | 
					        SocketOpenSSL::close();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void SocketOpenSSL::openSSLInitialize()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					#if OPENSSL_VERSION_NUMBER >= 0x10100000L
 | 
				
			||||||
 | 
					        if (!OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, nullptr)) return;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					        (void) OPENSSL_config(nullptr);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        (void) OpenSSL_add_ssl_algorithms();
 | 
				
			||||||
 | 
					        (void) SSL_load_error_strings();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        _openSSLInitializationSuccessful = true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::string SocketOpenSSL::getSSLError(int ret)
 | 
					    std::string SocketOpenSSL::getSSLError(int ret)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        unsigned long e;
 | 
					        unsigned long e;
 | 
				
			||||||
@@ -153,7 +115,12 @@ namespace ix
 | 
				
			|||||||
        if (ctx)
 | 
					        if (ctx)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            // To skip verification, pass in SSL_VERIFY_NONE
 | 
					            // To skip verification, pass in SSL_VERIFY_NONE
 | 
				
			||||||
            SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, openssl_verify_callback);
 | 
					            SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER,
 | 
				
			||||||
 | 
					                               [](int preverify, X509_STORE_CTX*) -> int
 | 
				
			||||||
 | 
					                               {
 | 
				
			||||||
 | 
					                                   return preverify;
 | 
				
			||||||
 | 
					                               });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            SSL_CTX_set_verify_depth(ctx, 4);
 | 
					            SSL_CTX_set_verify_depth(ctx, 4);
 | 
				
			||||||
            SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
 | 
					            SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -283,8 +250,9 @@ namespace ix
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            std::lock_guard<std::mutex> lock(_mutex);
 | 
					            std::lock_guard<std::mutex> lock(_mutex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (!openSSLInitialize(errMsg))
 | 
					            if (!_openSSLInitializationSuccessful)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
 | 
					                errMsg = "OPENSSL_init_ssl failure";
 | 
				
			||||||
                return false;
 | 
					                return false;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -306,14 +274,15 @@ namespace ix
 | 
				
			|||||||
                errMsg += ERR_error_string(ssl_err, nullptr);
 | 
					                errMsg += ERR_error_string(ssl_err, nullptr);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            _ssl_connection = openssl_create_connection(_ssl_context, _sockfd);
 | 
					            _ssl_connection = SSL_new(_ssl_context);
 | 
				
			||||||
            if (nullptr == _ssl_connection)
 | 
					            if (_ssl_connection == nullptr)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                errMsg = "OpenSSL failed to connect";
 | 
					                errMsg = "OpenSSL failed to connect";
 | 
				
			||||||
                SSL_CTX_free(_ssl_context);
 | 
					                SSL_CTX_free(_ssl_context);
 | 
				
			||||||
                _ssl_context = nullptr;
 | 
					                _ssl_context = nullptr;
 | 
				
			||||||
                return false;
 | 
					                return false;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            SSL_set_fd(_ssl_connection, _sockfd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // SNI support
 | 
					            // SNI support
 | 
				
			||||||
            SSL_set_tlsext_host_name(_ssl_connection, host.c_str());
 | 
					            SSL_set_tlsext_host_name(_ssl_connection, host.c_str());
 | 
				
			||||||
@@ -357,7 +326,7 @@ namespace ix
 | 
				
			|||||||
        Socket::close();
 | 
					        Socket::close();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int SocketOpenSSL::send(char* buf, size_t nbyte)
 | 
					    ssize_t SocketOpenSSL::send(char* buf, size_t nbyte)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        ssize_t sent = 0;
 | 
					        ssize_t sent = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -371,7 +340,7 @@ namespace ix
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            ERR_clear_error();
 | 
					            ERR_clear_error();
 | 
				
			||||||
            int write_result = SSL_write(_ssl_connection, buf + sent, (int) nbyte);
 | 
					            ssize_t write_result = SSL_write(_ssl_connection, buf + sent, (int) nbyte);
 | 
				
			||||||
            int reason = SSL_get_error(_ssl_connection, write_result);
 | 
					            int reason = SSL_get_error(_ssl_connection, write_result);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (reason == SSL_ERROR_NONE) {
 | 
					            if (reason == SSL_ERROR_NONE) {
 | 
				
			||||||
@@ -384,16 +353,16 @@ namespace ix
 | 
				
			|||||||
                return -1;
 | 
					                return -1;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return (int) sent;
 | 
					        return sent;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int SocketOpenSSL::send(const std::string& buffer)
 | 
					    ssize_t SocketOpenSSL::send(const std::string& buffer)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return send((char*)&buffer[0], buffer.size());
 | 
					        return send((char*)&buffer[0], buffer.size());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // No wait support
 | 
					    // No wait support
 | 
				
			||||||
    int SocketOpenSSL::recv(void* buf, size_t nbyte)
 | 
					    ssize_t SocketOpenSSL::recv(void* buf, size_t nbyte)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        while (true)
 | 
					        while (true)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@@ -405,7 +374,7 @@ namespace ix
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            ERR_clear_error();
 | 
					            ERR_clear_error();
 | 
				
			||||||
            int read_result = SSL_read(_ssl_connection, buf, (int) nbyte);
 | 
					            ssize_t read_result = SSL_read(_ssl_connection, buf, (int) nbyte);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (read_result > 0)
 | 
					            if (read_result > 0)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -31,11 +31,12 @@ namespace ix
 | 
				
			|||||||
                             const CancellationRequest& isCancellationRequested) final;
 | 
					                             const CancellationRequest& isCancellationRequested) final;
 | 
				
			||||||
        virtual void close() final;
 | 
					        virtual void close() final;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        virtual int send(char* buffer, size_t length) final;
 | 
					        virtual ssize_t send(char* buffer, size_t length) final;
 | 
				
			||||||
        virtual int send(const std::string& buffer) final;
 | 
					        virtual ssize_t send(const std::string& buffer) final;
 | 
				
			||||||
        virtual int recv(void* buffer, size_t length) final;
 | 
					        virtual ssize_t recv(void* buffer, size_t length) final;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private:
 | 
					    private:
 | 
				
			||||||
 | 
					        void openSSLInitialize();
 | 
				
			||||||
        std::string getSSLError(int ret);
 | 
					        std::string getSSLError(int ret);
 | 
				
			||||||
        SSL_CTX* openSSLCreateContext(std::string& errMsg);
 | 
					        SSL_CTX* openSSLCreateContext(std::string& errMsg);
 | 
				
			||||||
        bool openSSLHandshake(const std::string& hostname, std::string& errMsg);
 | 
					        bool openSSLHandshake(const std::string& hostname, std::string& errMsg);
 | 
				
			||||||
@@ -44,10 +45,13 @@ namespace ix
 | 
				
			|||||||
                                    std::string& errMsg);
 | 
					                                    std::string& errMsg);
 | 
				
			||||||
        bool checkHost(const std::string& host, const char *pattern);
 | 
					        bool checkHost(const std::string& host, const char *pattern);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        SSL_CTX* _ssl_context;
 | 
					 | 
				
			||||||
        SSL* _ssl_connection;
 | 
					        SSL* _ssl_connection;
 | 
				
			||||||
 | 
					        SSL_CTX* _ssl_context;
 | 
				
			||||||
        const SSL_METHOD* _ssl_method;
 | 
					        const SSL_METHOD* _ssl_method;
 | 
				
			||||||
        mutable std::mutex _mutex;  // OpenSSL routines are not thread-safe
 | 
					        mutable std::mutex _mutex;  // OpenSSL routines are not thread-safe
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::once_flag _openSSLInitFlag;
 | 
				
			||||||
 | 
					        static std::atomic<bool> _openSSLInitializationSuccessful;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										228
									
								
								ixwebsocket/IXSocketServer.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										228
									
								
								ixwebsocket/IXSocketServer.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,228 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *  IXSocketServer.cpp
 | 
				
			||||||
 | 
					 *  Author: Benjamin Sergeant
 | 
				
			||||||
 | 
					 *  Copyright (c) 2018 Machine Zone, Inc. All rights reserved.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "IXSocketServer.h"
 | 
				
			||||||
 | 
					#include "IXSocket.h"
 | 
				
			||||||
 | 
					#include "IXSocketConnect.h"
 | 
				
			||||||
 | 
					#include "IXNetSystem.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					#include <sstream>
 | 
				
			||||||
 | 
					#include <future>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ix 
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const int SocketServer::kDefaultPort(8080);
 | 
				
			||||||
 | 
					    const std::string SocketServer::kDefaultHost("127.0.0.1");
 | 
				
			||||||
 | 
					    const int SocketServer::kDefaultTcpBacklog(5);
 | 
				
			||||||
 | 
					    const size_t SocketServer::kDefaultMaxConnections(32);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SocketServer::SocketServer(int port,
 | 
				
			||||||
 | 
					                               const std::string& host,
 | 
				
			||||||
 | 
					                               int backlog,
 | 
				
			||||||
 | 
					                               size_t maxConnections) :
 | 
				
			||||||
 | 
					        _port(port),
 | 
				
			||||||
 | 
					        _host(host),
 | 
				
			||||||
 | 
					        _backlog(backlog),
 | 
				
			||||||
 | 
					        _maxConnections(maxConnections),
 | 
				
			||||||
 | 
					        _stop(false)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SocketServer::~SocketServer()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        stop();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void SocketServer::logError(const std::string& str)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::lock_guard<std::mutex> lock(_logMutex);
 | 
				
			||||||
 | 
					        std::cerr << str << std::endl;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void SocketServer::logInfo(const std::string& str)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::lock_guard<std::mutex> lock(_logMutex);
 | 
				
			||||||
 | 
					        std::cout << str << std::endl;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::pair<bool, std::string> SocketServer::listen()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        struct sockaddr_in server; // server address information
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Get a socket for accepting connections.
 | 
				
			||||||
 | 
					        if ((_serverFd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            std::stringstream ss;
 | 
				
			||||||
 | 
					            ss << "SocketServer::listen() error creating socket): "
 | 
				
			||||||
 | 
					               << strerror(Socket::getErrno());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return std::make_pair(false, ss.str());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Make that socket reusable. (allow restarting this server at will)
 | 
				
			||||||
 | 
					        int enable = 1;
 | 
				
			||||||
 | 
					        if (setsockopt(_serverFd, SOL_SOCKET, SO_REUSEADDR,
 | 
				
			||||||
 | 
					                       (char*) &enable, sizeof(enable)) < 0)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            std::stringstream ss;
 | 
				
			||||||
 | 
					            ss << "SocketServer::listen() error calling setsockopt(SO_REUSEADDR) "
 | 
				
			||||||
 | 
					               << "at address " << _host << ":" << _port
 | 
				
			||||||
 | 
					               << " : " << strerror(Socket::getErrno());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            ::close(_serverFd);
 | 
				
			||||||
 | 
					            return std::make_pair(false, ss.str());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Bind the socket to the server address.
 | 
				
			||||||
 | 
					        server.sin_family = AF_INET;
 | 
				
			||||||
 | 
					        server.sin_port   = htons(_port);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Using INADDR_ANY trigger a pop-up box as binding to any address is detected 
 | 
				
			||||||
 | 
					        // by the osx firewall. We need to codesign the binary with a self-signed cert
 | 
				
			||||||
 | 
					        // to allow that, but this is a bit of a pain. (this is what node or python would do).
 | 
				
			||||||
 | 
					        //
 | 
				
			||||||
 | 
					        // Using INADDR_LOOPBACK also does not work ... while it should.
 | 
				
			||||||
 | 
					        // We default to 127.0.0.1 (localhost)
 | 
				
			||||||
 | 
					        //
 | 
				
			||||||
 | 
					        server.sin_addr.s_addr = inet_addr(_host.c_str());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (bind(_serverFd, (struct sockaddr *)&server, sizeof(server)) < 0)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            std::stringstream ss;
 | 
				
			||||||
 | 
					            ss << "SocketServer::listen() error calling bind "
 | 
				
			||||||
 | 
					               << "at address " << _host << ":" << _port
 | 
				
			||||||
 | 
					               << " : " << strerror(Socket::getErrno());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            ::close(_serverFd);
 | 
				
			||||||
 | 
					            return std::make_pair(false, ss.str());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //
 | 
				
			||||||
 | 
					        // Listen for connections. Specify the tcp backlog.
 | 
				
			||||||
 | 
					        //
 | 
				
			||||||
 | 
					        if (::listen(_serverFd, _backlog) < 0)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            std::stringstream ss;
 | 
				
			||||||
 | 
					            ss << "SocketServer::listen() error calling listen "
 | 
				
			||||||
 | 
					               << "at address " << _host << ":" << _port
 | 
				
			||||||
 | 
					               << " : " << strerror(Socket::getErrno());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            ::close(_serverFd);
 | 
				
			||||||
 | 
					            return std::make_pair(false, ss.str());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return std::make_pair(true, "");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void SocketServer::start()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (_thread.joinable()) return; // we've already been started
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        _thread = std::thread(&SocketServer::run, this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void SocketServer::wait()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::unique_lock<std::mutex> lock(_conditionVariableMutex);
 | 
				
			||||||
 | 
					        _conditionVariable.wait(lock);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void SocketServer::stop()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (!_thread.joinable()) return; // nothing to do
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        _stop = true;
 | 
				
			||||||
 | 
					        _thread.join();
 | 
				
			||||||
 | 
					        _stop = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        _conditionVariable.notify_one();
 | 
				
			||||||
 | 
					        ::close(_serverFd);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void SocketServer::run()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // Set the socket to non blocking mode, so that accept calls are not blocking
 | 
				
			||||||
 | 
					        SocketConnect::configure(_serverFd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Return value of std::async, ignored
 | 
				
			||||||
 | 
					        std::future<void> f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (;;)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (_stop) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Use select to check whether a new connection is in progress
 | 
				
			||||||
 | 
					            fd_set rfds;
 | 
				
			||||||
 | 
					            struct timeval timeout;
 | 
				
			||||||
 | 
					            timeout.tv_sec = 0;
 | 
				
			||||||
 | 
					            timeout.tv_usec = 10 * 1000; // 10ms timeout
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            FD_ZERO(&rfds);
 | 
				
			||||||
 | 
					            FD_SET(_serverFd, &rfds);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (select(_serverFd + 1, &rfds, nullptr, nullptr, &timeout) < 0 &&
 | 
				
			||||||
 | 
					                (errno == EBADF || errno == EINVAL))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                std::stringstream ss;
 | 
				
			||||||
 | 
					                ss << "SocketServer::run() error in select: "
 | 
				
			||||||
 | 
					                   << strerror(Socket::getErrno());
 | 
				
			||||||
 | 
					                logError(ss.str());
 | 
				
			||||||
 | 
					                continue;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (!FD_ISSET(_serverFd, &rfds))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                // We reached the select timeout, and no new connections are pending
 | 
				
			||||||
 | 
					                continue;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Accept a connection.
 | 
				
			||||||
 | 
					            struct sockaddr_in client; // client address information
 | 
				
			||||||
 | 
					            int clientFd;              // socket connected to client
 | 
				
			||||||
 | 
					            socklen_t addressLen = sizeof(socklen_t);
 | 
				
			||||||
 | 
					            memset(&client, 0, sizeof(client));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if ((clientFd = accept(_serverFd, (struct sockaddr *)&client, &addressLen)) < 0)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                if (Socket::getErrno() != EWOULDBLOCK)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    // FIXME: that error should be propagated
 | 
				
			||||||
 | 
					                    std::stringstream ss;
 | 
				
			||||||
 | 
					                    ss << "SocketServer::run() error accepting connection: "
 | 
				
			||||||
 | 
					                       << strerror(Socket::getErrno());
 | 
				
			||||||
 | 
					                    logError(ss.str());
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                continue;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (getConnectedClientsCount() >= _maxConnections)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                std::stringstream ss;
 | 
				
			||||||
 | 
					                ss << "SocketServer::run() reached max connections = "
 | 
				
			||||||
 | 
					                   << _maxConnections << ". "
 | 
				
			||||||
 | 
					                   << "Not accepting connection";
 | 
				
			||||||
 | 
					                logError(ss.str());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                ::close(clientFd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                continue;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Launch the handleConnection work asynchronously in its own thread.
 | 
				
			||||||
 | 
					            //
 | 
				
			||||||
 | 
					            // the destructor of a future returned by std::async blocks, 
 | 
				
			||||||
 | 
					            // so we need to declare it outside of this loop
 | 
				
			||||||
 | 
					            f = std::async(std::launch::async,
 | 
				
			||||||
 | 
					                           &SocketServer::handleConnection,
 | 
				
			||||||
 | 
					                           this,
 | 
				
			||||||
 | 
					                           clientFd);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										68
									
								
								ixwebsocket/IXSocketServer.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								ixwebsocket/IXSocketServer.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,68 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *  IXSocketServer.h
 | 
				
			||||||
 | 
					 *  Author: Benjamin Sergeant
 | 
				
			||||||
 | 
					 *  Copyright (c) 2018 Machine Zone, Inc. All rights reserved.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <utility> // pair
 | 
				
			||||||
 | 
					#include <string>
 | 
				
			||||||
 | 
					#include <set>
 | 
				
			||||||
 | 
					#include <thread>
 | 
				
			||||||
 | 
					#include <mutex>
 | 
				
			||||||
 | 
					#include <functional>
 | 
				
			||||||
 | 
					#include <memory>
 | 
				
			||||||
 | 
					#include <atomic>
 | 
				
			||||||
 | 
					#include <condition_variable>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ix 
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    class SocketServer {
 | 
				
			||||||
 | 
					    public:
 | 
				
			||||||
 | 
					        SocketServer(int port = SocketServer::kDefaultPort,
 | 
				
			||||||
 | 
					                     const std::string& host = SocketServer::kDefaultHost,
 | 
				
			||||||
 | 
					                     int backlog = SocketServer::kDefaultTcpBacklog,
 | 
				
			||||||
 | 
					                     size_t maxConnections = SocketServer::kDefaultMaxConnections);
 | 
				
			||||||
 | 
					        virtual ~SocketServer();
 | 
				
			||||||
 | 
					        virtual void stop();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const static int kDefaultPort;
 | 
				
			||||||
 | 
					        const static std::string kDefaultHost;
 | 
				
			||||||
 | 
					        const static int kDefaultTcpBacklog;
 | 
				
			||||||
 | 
					        const static size_t kDefaultMaxConnections;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void start();
 | 
				
			||||||
 | 
					        std::pair<bool, std::string> listen();
 | 
				
			||||||
 | 
					        void wait();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Logging
 | 
				
			||||||
 | 
					        void logError(const std::string& str);
 | 
				
			||||||
 | 
					        void logInfo(const std::string& str);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private:
 | 
				
			||||||
 | 
					        // Member variables
 | 
				
			||||||
 | 
					        int _port;
 | 
				
			||||||
 | 
					        std::string _host;
 | 
				
			||||||
 | 
					        int _backlog;
 | 
				
			||||||
 | 
					        size_t _maxConnections;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // socket for accepting connections
 | 
				
			||||||
 | 
					        int _serverFd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::mutex _logMutex;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::atomic<bool> _stop;
 | 
				
			||||||
 | 
					        std::thread _thread;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::condition_variable _conditionVariable;
 | 
				
			||||||
 | 
					        std::mutex _conditionVariableMutex;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Methods
 | 
				
			||||||
 | 
					        void run();
 | 
				
			||||||
 | 
					        virtual void handleConnection(int fd) = 0;
 | 
				
			||||||
 | 
					        virtual size_t getConnectedClientsCount() = 0;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -31,12 +31,14 @@ namespace ix
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    OnTrafficTrackerCallback WebSocket::_onTrafficTrackerCallback = nullptr;
 | 
					    OnTrafficTrackerCallback WebSocket::_onTrafficTrackerCallback = nullptr;
 | 
				
			||||||
    const int WebSocket::kDefaultHandShakeTimeoutSecs(60);
 | 
					    const int WebSocket::kDefaultHandShakeTimeoutSecs(60);
 | 
				
			||||||
 | 
					    const int WebSocket::kDefaultHeartBeatPeriod(-1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    WebSocket::WebSocket() :
 | 
					    WebSocket::WebSocket() :
 | 
				
			||||||
        _onMessageCallback(OnMessageCallback()),
 | 
					        _onMessageCallback(OnMessageCallback()),
 | 
				
			||||||
        _stop(false),
 | 
					        _stop(false),
 | 
				
			||||||
        _automaticReconnection(true),
 | 
					        _automaticReconnection(true),
 | 
				
			||||||
        _handshakeTimeoutSecs(kDefaultHandShakeTimeoutSecs)
 | 
					        _handshakeTimeoutSecs(kDefaultHandShakeTimeoutSecs),
 | 
				
			||||||
 | 
					        _heartBeatPeriod(kDefaultHeartBeatPeriod)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        _ws.setOnCloseCallback(
 | 
					        _ws.setOnCloseCallback(
 | 
				
			||||||
            [this](uint16_t code, const std::string& reason, size_t wireSize)
 | 
					            [this](uint16_t code, const std::string& reason, size_t wireSize)
 | 
				
			||||||
@@ -77,6 +79,18 @@ namespace ix
 | 
				
			|||||||
        return _perMessageDeflateOptions;
 | 
					        return _perMessageDeflateOptions;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void WebSocket::setHeartBeatPeriod(int hearBeatPeriod)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::lock_guard<std::mutex> lock(_configMutex);
 | 
				
			||||||
 | 
					        _heartBeatPeriod = hearBeatPeriod;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int WebSocket::getHeartBeatPeriod() const
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::lock_guard<std::mutex> lock(_configMutex);
 | 
				
			||||||
 | 
					        return _heartBeatPeriod;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void WebSocket::start()
 | 
					    void WebSocket::start()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if (_thread.joinable()) return; // we've already been started
 | 
					        if (_thread.joinable()) return; // we've already been started
 | 
				
			||||||
@@ -110,7 +124,8 @@ namespace ix
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            std::lock_guard<std::mutex> lock(_configMutex);
 | 
					            std::lock_guard<std::mutex> lock(_configMutex);
 | 
				
			||||||
            _ws.configure(_perMessageDeflateOptions);
 | 
					            _ws.configure(_perMessageDeflateOptions,
 | 
				
			||||||
 | 
					                          _heartBeatPeriod);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        WebSocketInitResult status = _ws.connectToUrl(_url, timeoutSecs);
 | 
					        WebSocketInitResult status = _ws.connectToUrl(_url, timeoutSecs);
 | 
				
			||||||
@@ -130,7 +145,7 @@ namespace ix
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            std::lock_guard<std::mutex> lock(_configMutex);
 | 
					            std::lock_guard<std::mutex> lock(_configMutex);
 | 
				
			||||||
            _ws.configure(_perMessageDeflateOptions);
 | 
					            _ws.configure(_perMessageDeflateOptions, _heartBeatPeriod);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        WebSocketInitResult status = _ws.connectToSocket(fd, timeoutSecs);
 | 
					        WebSocketInitResult status = _ws.connectToSocket(fd, timeoutSecs);
 | 
				
			||||||
@@ -331,6 +346,7 @@ namespace ix
 | 
				
			|||||||
            case ix::WebSocketTransport::CONNECTING: return WebSocket_ReadyState_Connecting;
 | 
					            case ix::WebSocketTransport::CONNECTING: return WebSocket_ReadyState_Connecting;
 | 
				
			||||||
            case ix::WebSocketTransport::CLOSING: return WebSocket_ReadyState_Closing;
 | 
					            case ix::WebSocketTransport::CLOSING: return WebSocket_ReadyState_Closing;
 | 
				
			||||||
            case ix::WebSocketTransport::CLOSED: return WebSocket_ReadyState_Closed;
 | 
					            case ix::WebSocketTransport::CLOSED: return WebSocket_ReadyState_Closed;
 | 
				
			||||||
 | 
					            default: return WebSocket_ReadyState_Closed;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -342,6 +358,7 @@ namespace ix
 | 
				
			|||||||
            case WebSocket_ReadyState_Connecting: return "CONNECTING";
 | 
					            case WebSocket_ReadyState_Connecting: return "CONNECTING";
 | 
				
			||||||
            case WebSocket_ReadyState_Closing: return "CLOSING";
 | 
					            case WebSocket_ReadyState_Closing: return "CLOSING";
 | 
				
			||||||
            case WebSocket_ReadyState_Closed: return "CLOSED";
 | 
					            case WebSocket_ReadyState_Closed: return "CLOSED";
 | 
				
			||||||
 | 
					            default: return "CLOSED";
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -60,7 +60,7 @@ namespace ix
 | 
				
			|||||||
        uint16_t code;
 | 
					        uint16_t code;
 | 
				
			||||||
        std::string reason;
 | 
					        std::string reason;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        WebSocketCloseInfo(uint64_t c = 0,
 | 
					        WebSocketCloseInfo(uint16_t c = 0,
 | 
				
			||||||
                           const std::string& r = std::string())
 | 
					                           const std::string& r = std::string())
 | 
				
			||||||
            : code(c)
 | 
					            : code(c)
 | 
				
			||||||
            , reason(r)
 | 
					            , reason(r)
 | 
				
			||||||
@@ -86,7 +86,8 @@ namespace ix
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        void setUrl(const std::string& url);
 | 
					        void setUrl(const std::string& url);
 | 
				
			||||||
        void setPerMessageDeflateOptions(const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions);
 | 
					        void setPerMessageDeflateOptions(const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions);
 | 
				
			||||||
        void setHandshakeTimeout(int _handshakeTimeoutSecs);
 | 
					        void setHandshakeTimeout(int handshakeTimeoutSecs);
 | 
				
			||||||
 | 
					        void setHeartBeatPeriod(int hearBeatPeriod);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Run asynchronously, by calling start and stop.
 | 
					        // Run asynchronously, by calling start and stop.
 | 
				
			||||||
        void start();
 | 
					        void start();
 | 
				
			||||||
@@ -107,6 +108,7 @@ namespace ix
 | 
				
			|||||||
        ReadyState getReadyState() const;
 | 
					        ReadyState getReadyState() const;
 | 
				
			||||||
        const std::string& getUrl() const;
 | 
					        const std::string& getUrl() const;
 | 
				
			||||||
        const WebSocketPerMessageDeflateOptions& getPerMessageDeflateOptions() const;
 | 
					        const WebSocketPerMessageDeflateOptions& getPerMessageDeflateOptions() const;
 | 
				
			||||||
 | 
					        int getHeartBeatPeriod() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void enableAutomaticReconnection();
 | 
					        void enableAutomaticReconnection();
 | 
				
			||||||
        void disableAutomaticReconnection();
 | 
					        void disableAutomaticReconnection();
 | 
				
			||||||
@@ -142,6 +144,10 @@ namespace ix
 | 
				
			|||||||
        std::atomic<int> _handshakeTimeoutSecs;
 | 
					        std::atomic<int> _handshakeTimeoutSecs;
 | 
				
			||||||
        static const int kDefaultHandShakeTimeoutSecs;
 | 
					        static const int kDefaultHandShakeTimeoutSecs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Optional Heartbeat
 | 
				
			||||||
 | 
					        int _heartBeatPeriod;
 | 
				
			||||||
 | 
					        static const int kDefaultHeartBeatPeriod;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        friend class WebSocketServer;
 | 
					        friend class WebSocketServer;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -116,7 +116,7 @@ namespace ix
 | 
				
			|||||||
        std::cout << "-------------------------------" << std::endl;
 | 
					        std::cout << "-------------------------------" << std::endl;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::string trim(const std::string& str)
 | 
					    std::string WebSocketHandshake::trim(const std::string& str)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        std::string out(str);
 | 
					        std::string out(str);
 | 
				
			||||||
        out.erase(std::remove(out.begin(), out.end(), ' '), out.end());
 | 
					        out.erase(std::remove(out.begin(), out.end(), ' '), out.end());
 | 
				
			||||||
@@ -354,6 +354,14 @@ namespace ix
 | 
				
			|||||||
            return WebSocketInitResult(false, status, "Error parsing HTTP headers");
 | 
					            return WebSocketInitResult(false, status, "Error parsing HTTP headers");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Check the presence of the Upgrade field
 | 
				
			||||||
 | 
					        if (headers.find("connection") == headers.end() ||
 | 
				
			||||||
 | 
					            headers["connection"] != "Upgrade")
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            std::string errorMsg("Invalid or missing connection value");
 | 
				
			||||||
 | 
					            return WebSocketInitResult(false, status, errorMsg);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        char output[29] = {};
 | 
					        char output[29] = {};
 | 
				
			||||||
        WebSocketHandshakeKeyGen::generate(secWebSocketKey.c_str(), output);
 | 
					        WebSocketHandshakeKeyGen::generate(secWebSocketKey.c_str(), output);
 | 
				
			||||||
        if (std::string(output) != headers["sec-websocket-accept"])
 | 
					        if (std::string(output) != headers["sec-websocket-accept"])
 | 
				
			||||||
@@ -466,6 +474,8 @@ namespace ix
 | 
				
			|||||||
        std::stringstream ss;
 | 
					        std::stringstream ss;
 | 
				
			||||||
        ss << "HTTP/1.1 101\r\n";
 | 
					        ss << "HTTP/1.1 101\r\n";
 | 
				
			||||||
        ss << "Sec-WebSocket-Accept: " << std::string(output) << "\r\n";
 | 
					        ss << "Sec-WebSocket-Accept: " << std::string(output) << "\r\n";
 | 
				
			||||||
 | 
					        ss << "Upgrade: websocket\r\n";
 | 
				
			||||||
 | 
					        ss << "Connection: Upgrade\r\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Parse the client headers. Does it support deflate ?
 | 
					        // Parse the client headers. Does it support deflate ?
 | 
				
			||||||
        std::string header = headers["sec-websocket-extensions"];
 | 
					        std::string header = headers["sec-websocket-extensions"];
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -75,6 +75,7 @@ namespace ix
 | 
				
			|||||||
        WebSocketInitResult sendErrorResponse(int code, const std::string& reason);
 | 
					        WebSocketInitResult sendErrorResponse(int code, const std::string& reason);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        std::tuple<std::string, std::string, std::string> parseRequestLine(const std::string& line);
 | 
					        std::tuple<std::string, std::string, std::string> parseRequestLine(const std::string& line);
 | 
				
			||||||
 | 
					        std::string trim(const std::string& str);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        std::atomic<bool>& _requestInitCancellation;
 | 
					        std::atomic<bool>& _requestInitCancellation;
 | 
				
			||||||
        std::shared_ptr<Socket> _socket;
 | 
					        std::shared_ptr<Socket> _socket;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -47,211 +47,20 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "IXWebSocketPerMessageDeflate.h"
 | 
					#include "IXWebSocketPerMessageDeflate.h"
 | 
				
			||||||
#include "IXWebSocketPerMessageDeflateOptions.h"
 | 
					#include "IXWebSocketPerMessageDeflateOptions.h"
 | 
				
			||||||
 | 
					#include "IXWebSocketPerMessageDeflateCodec.h"
 | 
				
			||||||
#include <iostream>
 | 
					 | 
				
			||||||
#include <cassert>
 | 
					 | 
				
			||||||
#include <string.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    // The passed in size (4) is important, without it the string litteral
 | 
					 | 
				
			||||||
    // is treated as a char* and the null termination (\x00) makes it 
 | 
					 | 
				
			||||||
    // look like an empty string.
 | 
					 | 
				
			||||||
    const std::string kEmptyUncompressedBlock = std::string("\x00\x00\xff\xff", 4);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const int kBufferSize = 1 << 14;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace ix
 | 
					namespace ix
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    //
 | 
					    WebSocketPerMessageDeflate::WebSocketPerMessageDeflate() :
 | 
				
			||||||
    // Compressor
 | 
					        _compressor(std::make_unique<WebSocketPerMessageDeflateCompressor>()),
 | 
				
			||||||
    //
 | 
					        _decompressor(std::make_unique<WebSocketPerMessageDeflateDecompressor>())
 | 
				
			||||||
    WebSocketPerMessageDeflateCompressor::WebSocketPerMessageDeflateCompressor()
 | 
					 | 
				
			||||||
      : _compressBufferSize(kBufferSize)
 | 
					 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        memset(&_deflateState, 0, sizeof(_deflateState));
 | 
					        ;
 | 
				
			||||||
 | 
					 | 
				
			||||||
        _deflateState.zalloc = Z_NULL;
 | 
					 | 
				
			||||||
        _deflateState.zfree = Z_NULL;
 | 
					 | 
				
			||||||
        _deflateState.opaque = Z_NULL;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    WebSocketPerMessageDeflateCompressor::~WebSocketPerMessageDeflateCompressor()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        deflateEnd(&_deflateState);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    bool WebSocketPerMessageDeflateCompressor::init(uint8_t deflateBits,
 | 
					 | 
				
			||||||
                                                    bool clientNoContextTakeOver)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        int ret = deflateInit2(
 | 
					 | 
				
			||||||
            &_deflateState,
 | 
					 | 
				
			||||||
            Z_DEFAULT_COMPRESSION,
 | 
					 | 
				
			||||||
            Z_DEFLATED,
 | 
					 | 
				
			||||||
            -1*deflateBits,
 | 
					 | 
				
			||||||
            4, // memory level 1-9
 | 
					 | 
				
			||||||
            Z_DEFAULT_STRATEGY
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (ret != Z_OK) return false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        _compressBuffer.reset(new unsigned char[_compressBufferSize]);
 | 
					 | 
				
			||||||
        _flush = (clientNoContextTakeOver)
 | 
					 | 
				
			||||||
                 ? Z_FULL_FLUSH
 | 
					 | 
				
			||||||
                 : Z_SYNC_FLUSH;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    bool WebSocketPerMessageDeflateCompressor::endsWith(const std::string& value,
 | 
					 | 
				
			||||||
                                                        const std::string& ending)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if (ending.size() > value.size()) return false;
 | 
					 | 
				
			||||||
        return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    bool WebSocketPerMessageDeflateCompressor::compress(const std::string& in,
 | 
					 | 
				
			||||||
                                                        std::string& out)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        //
 | 
					 | 
				
			||||||
        // 7.2.1.  Compression
 | 
					 | 
				
			||||||
        // 
 | 
					 | 
				
			||||||
        //    An endpoint uses the following algorithm to compress a message.
 | 
					 | 
				
			||||||
        // 
 | 
					 | 
				
			||||||
        //    1.  Compress all the octets of the payload of the message using
 | 
					 | 
				
			||||||
        //        DEFLATE.
 | 
					 | 
				
			||||||
        // 
 | 
					 | 
				
			||||||
        //    2.  If the resulting data does not end with an empty DEFLATE block
 | 
					 | 
				
			||||||
        //        with no compression (the "BTYPE" bits are set to 00), append an
 | 
					 | 
				
			||||||
        //        empty DEFLATE block with no compression to the tail end.
 | 
					 | 
				
			||||||
        // 
 | 
					 | 
				
			||||||
        //    3.  Remove 4 octets (that are 0x00 0x00 0xff 0xff) from the tail end.
 | 
					 | 
				
			||||||
        //        After this step, the last octet of the compressed data contains
 | 
					 | 
				
			||||||
        //        (possibly part of) the DEFLATE header bits with the "BTYPE" bits
 | 
					 | 
				
			||||||
        //        set to 00.
 | 
					 | 
				
			||||||
        //
 | 
					 | 
				
			||||||
        size_t output;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (in.empty())
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            uint8_t buf[6] = {0x02, 0x00, 0x00, 0x00, 0xff, 0xff};
 | 
					 | 
				
			||||||
            out.append((char *)(buf), 6);
 | 
					 | 
				
			||||||
            return true;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        _deflateState.avail_in = (uInt) in.size();
 | 
					 | 
				
			||||||
        _deflateState.next_in = (Bytef*) in.data();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        do
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            // Output to local buffer
 | 
					 | 
				
			||||||
            _deflateState.avail_out = (uInt) _compressBufferSize;
 | 
					 | 
				
			||||||
            _deflateState.next_out = _compressBuffer.get();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            deflate(&_deflateState, _flush);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            output = _compressBufferSize - _deflateState.avail_out;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            out.append((char *)(_compressBuffer.get()),output);
 | 
					 | 
				
			||||||
        } while (_deflateState.avail_out == 0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (endsWith(out, kEmptyUncompressedBlock))
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            out.resize(out.size() - 4);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    //
 | 
					 | 
				
			||||||
    // Decompressor
 | 
					 | 
				
			||||||
    //
 | 
					 | 
				
			||||||
    WebSocketPerMessageDeflateDecompressor::WebSocketPerMessageDeflateDecompressor()
 | 
					 | 
				
			||||||
      : _compressBufferSize(kBufferSize)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        memset(&_inflateState, 0, sizeof(_inflateState));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        _inflateState.zalloc = Z_NULL;
 | 
					 | 
				
			||||||
        _inflateState.zfree = Z_NULL;
 | 
					 | 
				
			||||||
        _inflateState.opaque = Z_NULL;
 | 
					 | 
				
			||||||
        _inflateState.avail_in = 0;
 | 
					 | 
				
			||||||
        _inflateState.next_in = Z_NULL;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    WebSocketPerMessageDeflateDecompressor::~WebSocketPerMessageDeflateDecompressor()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        inflateEnd(&_inflateState);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    bool WebSocketPerMessageDeflateDecompressor::init(uint8_t inflateBits,
 | 
					 | 
				
			||||||
                                                      bool clientNoContextTakeOver)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        int ret = inflateInit2(
 | 
					 | 
				
			||||||
            &_inflateState,
 | 
					 | 
				
			||||||
            -1*inflateBits
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (ret != Z_OK) return false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        _compressBuffer.reset(new unsigned char[_compressBufferSize]);
 | 
					 | 
				
			||||||
        _flush = (clientNoContextTakeOver)
 | 
					 | 
				
			||||||
                 ? Z_FULL_FLUSH
 | 
					 | 
				
			||||||
                 : Z_SYNC_FLUSH;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    bool WebSocketPerMessageDeflateDecompressor::decompress(const std::string& in,
 | 
					 | 
				
			||||||
                                                            std::string& out)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        //
 | 
					 | 
				
			||||||
        // 7.2.2.  Decompression
 | 
					 | 
				
			||||||
        // 
 | 
					 | 
				
			||||||
        //    An endpoint uses the following algorithm to decompress a message.
 | 
					 | 
				
			||||||
        // 
 | 
					 | 
				
			||||||
        //    1.  Append 4 octets of 0x00 0x00 0xff 0xff to the tail end of the
 | 
					 | 
				
			||||||
        //        payload of the message.
 | 
					 | 
				
			||||||
        // 
 | 
					 | 
				
			||||||
        //    2.  Decompress the resulting data using DEFLATE.
 | 
					 | 
				
			||||||
        // 
 | 
					 | 
				
			||||||
        std::string inFixed(in);
 | 
					 | 
				
			||||||
        inFixed += kEmptyUncompressedBlock;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        _inflateState.avail_in = (uInt) inFixed.size();
 | 
					 | 
				
			||||||
        _inflateState.next_in = (unsigned char *)(const_cast<char *>(inFixed.data()));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        do
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            _inflateState.avail_out = (uInt) _compressBufferSize;
 | 
					 | 
				
			||||||
            _inflateState.next_out = _compressBuffer.get();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            int ret = inflate(&_inflateState, Z_SYNC_FLUSH);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (ret == Z_NEED_DICT || ret == Z_DATA_ERROR || ret == Z_MEM_ERROR)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                return false; // zlib error
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            out.append(
 | 
					 | 
				
			||||||
                reinterpret_cast<char *>(_compressBuffer.get()),
 | 
					 | 
				
			||||||
                _compressBufferSize - _inflateState.avail_out
 | 
					 | 
				
			||||||
            );
 | 
					 | 
				
			||||||
        } while (_inflateState.avail_out == 0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    WebSocketPerMessageDeflate::WebSocketPerMessageDeflate()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        _compressor.reset(new WebSocketPerMessageDeflateCompressor());
 | 
					 | 
				
			||||||
        _decompressor.reset(new WebSocketPerMessageDeflateDecompressor());
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    WebSocketPerMessageDeflate::~WebSocketPerMessageDeflate()
 | 
					    WebSocketPerMessageDeflate::~WebSocketPerMessageDeflate()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        _compressor.reset();
 | 
					        ;
 | 
				
			||||||
        _decompressor.reset();
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool WebSocketPerMessageDeflate::init(const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions)
 | 
					    bool WebSocketPerMessageDeflate::init(const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -34,47 +34,14 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "zlib.h"
 | 
					 | 
				
			||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
#include <memory>
 | 
					#include <memory>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace ix 
 | 
					namespace ix 
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    class WebSocketPerMessageDeflateOptions;
 | 
					    class WebSocketPerMessageDeflateOptions;
 | 
				
			||||||
 | 
					    class WebSocketPerMessageDeflateCompressor;
 | 
				
			||||||
    class WebSocketPerMessageDeflateCompressor
 | 
					    class WebSocketPerMessageDeflateDecompressor;
 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
    public:
 | 
					 | 
				
			||||||
        WebSocketPerMessageDeflateCompressor();
 | 
					 | 
				
			||||||
        ~WebSocketPerMessageDeflateCompressor();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        bool init(uint8_t deflateBits, bool clientNoContextTakeOver);
 | 
					 | 
				
			||||||
        bool compress(const std::string& in, std::string& out);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private:
 | 
					 | 
				
			||||||
        static bool endsWith(const std::string& value, const std::string& ending);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        int _flush;
 | 
					 | 
				
			||||||
        size_t _compressBufferSize;
 | 
					 | 
				
			||||||
        std::unique_ptr<unsigned char[]> _compressBuffer;
 | 
					 | 
				
			||||||
        z_stream _deflateState;
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    class WebSocketPerMessageDeflateDecompressor
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
    public:
 | 
					 | 
				
			||||||
        WebSocketPerMessageDeflateDecompressor();
 | 
					 | 
				
			||||||
        ~WebSocketPerMessageDeflateDecompressor();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        bool init(uint8_t inflateBits, bool clientNoContextTakeOver);
 | 
					 | 
				
			||||||
        bool decompress(const std::string& in, std::string& out);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private:
 | 
					 | 
				
			||||||
        int _flush;
 | 
					 | 
				
			||||||
        size_t _compressBufferSize;
 | 
					 | 
				
			||||||
        std::unique_ptr<unsigned char[]> _compressBuffer;
 | 
					 | 
				
			||||||
        z_stream _inflateState;
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class WebSocketPerMessageDeflate
 | 
					    class WebSocketPerMessageDeflate
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@@ -87,7 +54,7 @@ namespace ix
 | 
				
			|||||||
        bool decompress(const std::string& in, std::string& out);
 | 
					        bool decompress(const std::string& in, std::string& out);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private:
 | 
					    private:
 | 
				
			||||||
        std::shared_ptr<WebSocketPerMessageDeflateCompressor> _compressor;
 | 
					        std::unique_ptr<WebSocketPerMessageDeflateCompressor> _compressor;
 | 
				
			||||||
        std::shared_ptr<WebSocketPerMessageDeflateDecompressor> _decompressor;
 | 
					        std::unique_ptr<WebSocketPerMessageDeflateDecompressor> _decompressor;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										206
									
								
								ixwebsocket/IXWebSocketPerMessageDeflateCodec.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										206
									
								
								ixwebsocket/IXWebSocketPerMessageDeflateCodec.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,206 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *  IXWebSocketPerMessageDeflateCodec.cpp
 | 
				
			||||||
 | 
					 *  Author: Benjamin Sergeant
 | 
				
			||||||
 | 
					 *  Copyright (c) 2018-2019 Machine Zone, Inc. All rights reserved.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "IXWebSocketPerMessageDeflateCodec.h"
 | 
				
			||||||
 | 
					#include "IXWebSocketPerMessageDeflateOptions.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					#include <cassert>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    // The passed in size (4) is important, without it the string litteral
 | 
				
			||||||
 | 
					    // is treated as a char* and the null termination (\x00) makes it 
 | 
				
			||||||
 | 
					    // look like an empty string.
 | 
				
			||||||
 | 
					    const std::string kEmptyUncompressedBlock = std::string("\x00\x00\xff\xff", 4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const int kBufferSize = 1 << 14;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ix
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    //
 | 
				
			||||||
 | 
					    // Compressor
 | 
				
			||||||
 | 
					    //
 | 
				
			||||||
 | 
					    WebSocketPerMessageDeflateCompressor::WebSocketPerMessageDeflateCompressor()
 | 
				
			||||||
 | 
					      : _compressBufferSize(kBufferSize)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        memset(&_deflateState, 0, sizeof(_deflateState));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        _deflateState.zalloc = Z_NULL;
 | 
				
			||||||
 | 
					        _deflateState.zfree = Z_NULL;
 | 
				
			||||||
 | 
					        _deflateState.opaque = Z_NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    WebSocketPerMessageDeflateCompressor::~WebSocketPerMessageDeflateCompressor()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        deflateEnd(&_deflateState);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool WebSocketPerMessageDeflateCompressor::init(uint8_t deflateBits,
 | 
				
			||||||
 | 
					                                                    bool clientNoContextTakeOver)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        int ret = deflateInit2(
 | 
				
			||||||
 | 
					            &_deflateState,
 | 
				
			||||||
 | 
					            Z_DEFAULT_COMPRESSION,
 | 
				
			||||||
 | 
					            Z_DEFLATED,
 | 
				
			||||||
 | 
					            -1*deflateBits,
 | 
				
			||||||
 | 
					            4, // memory level 1-9
 | 
				
			||||||
 | 
					            Z_DEFAULT_STRATEGY
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (ret != Z_OK) return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        _compressBuffer = std::make_unique<unsigned char[]>(_compressBufferSize);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        _flush = (clientNoContextTakeOver)
 | 
				
			||||||
 | 
					                 ? Z_FULL_FLUSH
 | 
				
			||||||
 | 
					                 : Z_SYNC_FLUSH;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool WebSocketPerMessageDeflateCompressor::endsWith(const std::string& value,
 | 
				
			||||||
 | 
					                                                        const std::string& ending)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (ending.size() > value.size()) return false;
 | 
				
			||||||
 | 
					        return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool WebSocketPerMessageDeflateCompressor::compress(const std::string& in,
 | 
				
			||||||
 | 
					                                                        std::string& out)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        //
 | 
				
			||||||
 | 
					        // 7.2.1.  Compression
 | 
				
			||||||
 | 
					        // 
 | 
				
			||||||
 | 
					        //    An endpoint uses the following algorithm to compress a message.
 | 
				
			||||||
 | 
					        // 
 | 
				
			||||||
 | 
					        //    1.  Compress all the octets of the payload of the message using
 | 
				
			||||||
 | 
					        //        DEFLATE.
 | 
				
			||||||
 | 
					        // 
 | 
				
			||||||
 | 
					        //    2.  If the resulting data does not end with an empty DEFLATE block
 | 
				
			||||||
 | 
					        //        with no compression (the "BTYPE" bits are set to 00), append an
 | 
				
			||||||
 | 
					        //        empty DEFLATE block with no compression to the tail end.
 | 
				
			||||||
 | 
					        // 
 | 
				
			||||||
 | 
					        //    3.  Remove 4 octets (that are 0x00 0x00 0xff 0xff) from the tail end.
 | 
				
			||||||
 | 
					        //        After this step, the last octet of the compressed data contains
 | 
				
			||||||
 | 
					        //        (possibly part of) the DEFLATE header bits with the "BTYPE" bits
 | 
				
			||||||
 | 
					        //        set to 00.
 | 
				
			||||||
 | 
					        //
 | 
				
			||||||
 | 
					        size_t output;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (in.empty())
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            uint8_t buf[6] = {0x02, 0x00, 0x00, 0x00, 0xff, 0xff};
 | 
				
			||||||
 | 
					            out.append((char *)(buf), 6);
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        _deflateState.avail_in = (uInt) in.size();
 | 
				
			||||||
 | 
					        _deflateState.next_in = (Bytef*) in.data();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        do
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            // Output to local buffer
 | 
				
			||||||
 | 
					            _deflateState.avail_out = (uInt) _compressBufferSize;
 | 
				
			||||||
 | 
					            _deflateState.next_out = _compressBuffer.get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            deflate(&_deflateState, _flush);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            output = _compressBufferSize - _deflateState.avail_out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            out.append((char *)(_compressBuffer.get()),output);
 | 
				
			||||||
 | 
					        } while (_deflateState.avail_out == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (endsWith(out, kEmptyUncompressedBlock))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            out.resize(out.size() - 4);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //
 | 
				
			||||||
 | 
					    // Decompressor
 | 
				
			||||||
 | 
					    //
 | 
				
			||||||
 | 
					    WebSocketPerMessageDeflateDecompressor::WebSocketPerMessageDeflateDecompressor()
 | 
				
			||||||
 | 
					      : _compressBufferSize(kBufferSize)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        memset(&_inflateState, 0, sizeof(_inflateState));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        _inflateState.zalloc = Z_NULL;
 | 
				
			||||||
 | 
					        _inflateState.zfree = Z_NULL;
 | 
				
			||||||
 | 
					        _inflateState.opaque = Z_NULL;
 | 
				
			||||||
 | 
					        _inflateState.avail_in = 0;
 | 
				
			||||||
 | 
					        _inflateState.next_in = Z_NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    WebSocketPerMessageDeflateDecompressor::~WebSocketPerMessageDeflateDecompressor()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        inflateEnd(&_inflateState);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool WebSocketPerMessageDeflateDecompressor::init(uint8_t inflateBits,
 | 
				
			||||||
 | 
					                                                      bool clientNoContextTakeOver)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        int ret = inflateInit2(
 | 
				
			||||||
 | 
					            &_inflateState,
 | 
				
			||||||
 | 
					            -1*inflateBits
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (ret != Z_OK) return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        _compressBuffer = std::make_unique<unsigned char[]>(_compressBufferSize);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        _flush = (clientNoContextTakeOver)
 | 
				
			||||||
 | 
					                 ? Z_FULL_FLUSH
 | 
				
			||||||
 | 
					                 : Z_SYNC_FLUSH;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool WebSocketPerMessageDeflateDecompressor::decompress(const std::string& in,
 | 
				
			||||||
 | 
					                                                            std::string& out)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        //
 | 
				
			||||||
 | 
					        // 7.2.2.  Decompression
 | 
				
			||||||
 | 
					        // 
 | 
				
			||||||
 | 
					        //    An endpoint uses the following algorithm to decompress a message.
 | 
				
			||||||
 | 
					        // 
 | 
				
			||||||
 | 
					        //    1.  Append 4 octets of 0x00 0x00 0xff 0xff to the tail end of the
 | 
				
			||||||
 | 
					        //        payload of the message.
 | 
				
			||||||
 | 
					        // 
 | 
				
			||||||
 | 
					        //    2.  Decompress the resulting data using DEFLATE.
 | 
				
			||||||
 | 
					        // 
 | 
				
			||||||
 | 
					        std::string inFixed(in);
 | 
				
			||||||
 | 
					        inFixed += kEmptyUncompressedBlock;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        _inflateState.avail_in = (uInt) inFixed.size();
 | 
				
			||||||
 | 
					        _inflateState.next_in = (unsigned char *)(const_cast<char *>(inFixed.data()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        do
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _inflateState.avail_out = (uInt) _compressBufferSize;
 | 
				
			||||||
 | 
					            _inflateState.next_out = _compressBuffer.get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            int ret = inflate(&_inflateState, Z_SYNC_FLUSH);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (ret == Z_NEED_DICT || ret == Z_DATA_ERROR || ret == Z_MEM_ERROR)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return false; // zlib error
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            out.append(
 | 
				
			||||||
 | 
					                reinterpret_cast<char *>(_compressBuffer.get()),
 | 
				
			||||||
 | 
					                _compressBufferSize - _inflateState.avail_out
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					        } while (_inflateState.avail_out == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										50
									
								
								ixwebsocket/IXWebSocketPerMessageDeflateCodec.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								ixwebsocket/IXWebSocketPerMessageDeflateCodec.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,50 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *  IXWebSocketPerMessageDeflateCodec.h
 | 
				
			||||||
 | 
					 *  Author: Benjamin Sergeant
 | 
				
			||||||
 | 
					 *  Copyright (c) 2018-2019 Machine Zone, Inc. All rights reserved.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "zlib.h"
 | 
				
			||||||
 | 
					#include <string>
 | 
				
			||||||
 | 
					#include <memory>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ix 
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    class WebSocketPerMessageDeflateCompressor
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					    public:
 | 
				
			||||||
 | 
					        WebSocketPerMessageDeflateCompressor();
 | 
				
			||||||
 | 
					        ~WebSocketPerMessageDeflateCompressor();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        bool init(uint8_t deflateBits, bool clientNoContextTakeOver);
 | 
				
			||||||
 | 
					        bool compress(const std::string& in, std::string& out);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private:
 | 
				
			||||||
 | 
					        static bool endsWith(const std::string& value, const std::string& ending);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        int _flush;
 | 
				
			||||||
 | 
					        size_t _compressBufferSize;
 | 
				
			||||||
 | 
					        std::unique_ptr<unsigned char[]> _compressBuffer;
 | 
				
			||||||
 | 
					        z_stream _deflateState;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class WebSocketPerMessageDeflateDecompressor
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					    public:
 | 
				
			||||||
 | 
					        WebSocketPerMessageDeflateDecompressor();
 | 
				
			||||||
 | 
					        ~WebSocketPerMessageDeflateDecompressor();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        bool init(uint8_t inflateBits, bool clientNoContextTakeOver);
 | 
				
			||||||
 | 
					        bool decompress(const std::string& in, std::string& out);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private:
 | 
				
			||||||
 | 
					        int _flush;
 | 
				
			||||||
 | 
					        size_t _compressBufferSize;
 | 
				
			||||||
 | 
					        std::unique_ptr<unsigned char[]> _compressBuffer;
 | 
				
			||||||
 | 
					        z_stream _inflateState;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -9,6 +9,7 @@
 | 
				
			|||||||
#include <sstream>
 | 
					#include <sstream>
 | 
				
			||||||
#include <iostream>
 | 
					#include <iostream>
 | 
				
			||||||
#include <algorithm>
 | 
					#include <algorithm>
 | 
				
			||||||
 | 
					#include <cctype>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace ix
 | 
					namespace ix
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,35 +8,22 @@
 | 
				
			|||||||
#include "IXWebSocketTransport.h"
 | 
					#include "IXWebSocketTransport.h"
 | 
				
			||||||
#include "IXWebSocket.h"
 | 
					#include "IXWebSocket.h"
 | 
				
			||||||
#include "IXSocketConnect.h"
 | 
					#include "IXSocketConnect.h"
 | 
				
			||||||
 | 
					#include "IXNetSystem.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <sstream>
 | 
					#include <sstream>
 | 
				
			||||||
#include <future>
 | 
					#include <future>
 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <netdb.h>
 | 
					 | 
				
			||||||
#include <stdio.h>
 | 
					 | 
				
			||||||
#include <arpa/inet.h>
 | 
					 | 
				
			||||||
#include <sys/socket.h>
 | 
					 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace ix 
 | 
					namespace ix 
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const int WebSocketServer::kDefaultPort(8080);
 | 
					 | 
				
			||||||
    const std::string WebSocketServer::kDefaultHost("127.0.0.1");
 | 
					 | 
				
			||||||
    const int WebSocketServer::kDefaultTcpBacklog(5);
 | 
					 | 
				
			||||||
    const size_t WebSocketServer::kDefaultMaxConnections(32);
 | 
					 | 
				
			||||||
    const int WebSocketServer::kDefaultHandShakeTimeoutSecs(3); // 3 seconds
 | 
					    const int WebSocketServer::kDefaultHandShakeTimeoutSecs(3); // 3 seconds
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    WebSocketServer::WebSocketServer(int port,
 | 
					    WebSocketServer::WebSocketServer(int port,
 | 
				
			||||||
                                     const std::string& host,
 | 
					                                     const std::string& host,
 | 
				
			||||||
                                     int backlog,
 | 
					                                     int backlog,
 | 
				
			||||||
                                     size_t maxConnections,
 | 
					                                     size_t maxConnections,
 | 
				
			||||||
                                     int handshakeTimeoutSecs) :
 | 
					                                     int handshakeTimeoutSecs) : SocketServer(port, host, backlog, maxConnections),
 | 
				
			||||||
        _port(port),
 | 
					        _handshakeTimeoutSecs(handshakeTimeoutSecs)
 | 
				
			||||||
        _host(host),
 | 
					 | 
				
			||||||
        _backlog(backlog),
 | 
					 | 
				
			||||||
        _maxConnections(maxConnections),
 | 
					 | 
				
			||||||
        _handshakeTimeoutSecs(handshakeTimeoutSecs),
 | 
					 | 
				
			||||||
        _stop(false)
 | 
					 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -46,189 +33,25 @@ namespace ix
 | 
				
			|||||||
        stop();
 | 
					        stop();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void WebSocketServer::setOnConnectionCallback(const OnConnectionCallback& callback)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        _onConnectionCallback = callback;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void WebSocketServer::logError(const std::string& str)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        std::lock_guard<std::mutex> lock(_logMutex);
 | 
					 | 
				
			||||||
        std::cerr << str << std::endl;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void WebSocketServer::logInfo(const std::string& str)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        std::lock_guard<std::mutex> lock(_logMutex);
 | 
					 | 
				
			||||||
        std::cout << str << std::endl;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    std::pair<bool, std::string> WebSocketServer::listen()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        struct sockaddr_in server; // server address information
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Get a socket for accepting connections.
 | 
					 | 
				
			||||||
        if ((_serverFd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            std::stringstream ss;
 | 
					 | 
				
			||||||
            ss << "WebSocketServer::listen() error creating socket): "
 | 
					 | 
				
			||||||
               << strerror(errno);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            return std::make_pair(false, ss.str());
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Make that socket reusable. (allow restarting this server at will)
 | 
					 | 
				
			||||||
        int enable = 1;
 | 
					 | 
				
			||||||
        if (setsockopt(_serverFd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) < 0)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            std::stringstream ss;
 | 
					 | 
				
			||||||
            ss << "WebSocketServer::listen() error calling setsockopt(SO_REUSEADDR): "
 | 
					 | 
				
			||||||
               << strerror(errno);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            return std::make_pair(false, ss.str());
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Bind the socket to the server address.
 | 
					 | 
				
			||||||
        server.sin_family = AF_INET;
 | 
					 | 
				
			||||||
        server.sin_port   = htons(_port);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Using INADDR_ANY trigger a pop-up box as binding to any address is detected 
 | 
					 | 
				
			||||||
        // by the osx firewall. We need to codesign the binary with a self-signed cert
 | 
					 | 
				
			||||||
        // to allow that, but this is a bit of a pain. (this is what node or python would do).
 | 
					 | 
				
			||||||
        //
 | 
					 | 
				
			||||||
        // Using INADDR_LOOPBACK also does not work ... while it should.
 | 
					 | 
				
			||||||
        // We default to 127.0.0.1 (localhost)
 | 
					 | 
				
			||||||
        //
 | 
					 | 
				
			||||||
        server.sin_addr.s_addr = inet_addr(_host.c_str());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (bind(_serverFd, (struct sockaddr *)&server, sizeof(server)) < 0)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            std::stringstream ss;
 | 
					 | 
				
			||||||
            ss << "WebSocketServer::listen() error calling bind: "
 | 
					 | 
				
			||||||
               << strerror(errno);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            return std::make_pair(false, ss.str());
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /*
 | 
					 | 
				
			||||||
         * Listen for connections. Specify the tcp backlog.
 | 
					 | 
				
			||||||
         */
 | 
					 | 
				
			||||||
        if (::listen(_serverFd, _backlog) != 0)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            std::stringstream ss;
 | 
					 | 
				
			||||||
            ss << "WebSocketServer::listen() error calling listen: "
 | 
					 | 
				
			||||||
               << strerror(errno);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            return std::make_pair(false, ss.str());
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return std::make_pair(true, "");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void WebSocketServer::start()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if (_thread.joinable()) return; // we've already been started
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        _thread = std::thread(&WebSocketServer::run, this);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void WebSocketServer::wait()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        std::unique_lock<std::mutex> lock(_conditionVariableMutex);
 | 
					 | 
				
			||||||
        _conditionVariable.wait(lock);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void WebSocketServer::stop()
 | 
					    void WebSocketServer::stop()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if (!_thread.joinable()) return; // nothing to do
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        auto clients = getClients();
 | 
					        auto clients = getClients();
 | 
				
			||||||
        for (auto client : clients)
 | 
					        for (auto client : clients)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            client->close();
 | 
					            client->close();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        _stop = true;
 | 
					        SocketServer::stop();
 | 
				
			||||||
        _thread.join();
 | 
					 | 
				
			||||||
        _stop = false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        _conditionVariable.notify_one();
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void WebSocketServer::run()
 | 
					    void WebSocketServer::setOnConnectionCallback(const OnConnectionCallback& callback)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        // Set the socket to non blocking mode, so that accept calls are not blocking
 | 
					        _onConnectionCallback = callback;
 | 
				
			||||||
        SocketConnect::configure(_serverFd);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Return value of std::async, ignored
 | 
					 | 
				
			||||||
        std::future<void> f;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Select arguments
 | 
					 | 
				
			||||||
        fd_set rfds;
 | 
					 | 
				
			||||||
        struct timeval timeout;
 | 
					 | 
				
			||||||
        timeout.tv_sec = 0;
 | 
					 | 
				
			||||||
        timeout.tv_usec = 10 * 1000; // 10ms
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for (;;)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            if (_stop) return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            FD_ZERO(&rfds);
 | 
					 | 
				
			||||||
            FD_SET(_serverFd, &rfds);
 | 
					 | 
				
			||||||
            select(_serverFd + 1, &rfds, nullptr, nullptr, &timeout);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (!FD_ISSET(_serverFd, &rfds))
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                // We reached the select timeout, and no new connections are pending
 | 
					 | 
				
			||||||
                continue;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // Accept a connection.
 | 
					 | 
				
			||||||
            struct sockaddr_in client; // client address information
 | 
					 | 
				
			||||||
            int clientFd;              // socket connected to client
 | 
					 | 
				
			||||||
            socklen_t addressLen = sizeof(socklen_t);
 | 
					 | 
				
			||||||
            memset(&client, 0, sizeof(client));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if ((clientFd = accept(_serverFd, (struct sockaddr *)&client, &addressLen)) < 0)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                if (errno != EWOULDBLOCK)
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    // FIXME: that error should be propagated
 | 
					 | 
				
			||||||
                    std::stringstream ss;
 | 
					 | 
				
			||||||
                    ss << "WebSocketServer::run() error accepting connection: "
 | 
					 | 
				
			||||||
                       << strerror(errno);
 | 
					 | 
				
			||||||
                    logError(ss.str());
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                continue;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (getConnectedClientsCount() >= _maxConnections)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                std::stringstream ss;
 | 
					 | 
				
			||||||
                ss << "WebSocketServer::run() reached max connections = "
 | 
					 | 
				
			||||||
                   << _maxConnections << ". "
 | 
					 | 
				
			||||||
                   << "Not accepting connection";
 | 
					 | 
				
			||||||
                logError(ss.str());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                ::close(clientFd);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                continue;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // Launch the handleConnection work asynchronously in its own thread.
 | 
					 | 
				
			||||||
            //
 | 
					 | 
				
			||||||
            // the destructor of a future returned by std::async blocks, 
 | 
					 | 
				
			||||||
            // so we need to declare it outside of this loop
 | 
					 | 
				
			||||||
            f = std::async(std::launch::async,
 | 
					 | 
				
			||||||
                           &WebSocketServer::handleConnection,
 | 
					 | 
				
			||||||
                           this,
 | 
					 | 
				
			||||||
                           clientFd);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void WebSocketServer::handleConnection(int fd)
 | 
					    void WebSocketServer::handleConnection(int fd)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        std::shared_ptr<WebSocket> webSocket(new WebSocket);
 | 
					        auto webSocket = std::make_shared<WebSocket>();
 | 
				
			||||||
        _onConnectionCallback(webSocket);
 | 
					        _onConnectionCallback(webSocket);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        webSocket->disableAutomaticReconnection();
 | 
					        webSocket->disableAutomaticReconnection();
 | 
				
			||||||
@@ -276,6 +99,7 @@ namespace ix
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    size_t WebSocketServer::getConnectedClientsCount()
 | 
					    size_t WebSocketServer::getConnectedClientsCount()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return getClients().size();
 | 
					        std::lock_guard<std::mutex> lock(_clientsMutex);
 | 
				
			||||||
 | 
					        return _clients.size();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,67 +16,40 @@
 | 
				
			|||||||
#include <condition_variable>
 | 
					#include <condition_variable>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "IXWebSocket.h"
 | 
					#include "IXWebSocket.h"
 | 
				
			||||||
 | 
					#include "IXSocketServer.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace ix 
 | 
					namespace ix 
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    using OnConnectionCallback = std::function<void(std::shared_ptr<WebSocket>)>;
 | 
					    using OnConnectionCallback = std::function<void(std::shared_ptr<WebSocket>)>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class WebSocketServer {
 | 
					    class WebSocketServer : public SocketServer {
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        WebSocketServer(int port = WebSocketServer::kDefaultPort,
 | 
					        WebSocketServer(int port = SocketServer::kDefaultPort,
 | 
				
			||||||
                        const std::string& host = WebSocketServer::kDefaultHost,
 | 
					                        const std::string& host = SocketServer::kDefaultHost,
 | 
				
			||||||
                        int backlog = WebSocketServer::kDefaultTcpBacklog,
 | 
					                        int backlog = SocketServer::kDefaultTcpBacklog,
 | 
				
			||||||
                        size_t maxConnections = WebSocketServer::kDefaultMaxConnections,
 | 
					                        size_t maxConnections = SocketServer::kDefaultMaxConnections,
 | 
				
			||||||
                        int handshakeTimeoutSecs = WebSocketServer::kDefaultHandShakeTimeoutSecs);
 | 
					                        int handshakeTimeoutSecs = WebSocketServer::kDefaultHandShakeTimeoutSecs);
 | 
				
			||||||
        virtual ~WebSocketServer();
 | 
					        virtual ~WebSocketServer();
 | 
				
			||||||
 | 
					        virtual void stop() final;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void setOnConnectionCallback(const OnConnectionCallback& callback);
 | 
					        void setOnConnectionCallback(const OnConnectionCallback& callback);
 | 
				
			||||||
        void start();
 | 
					 | 
				
			||||||
        void wait();
 | 
					 | 
				
			||||||
        void stop();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        std::pair<bool, std::string> listen();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Get all the connected clients
 | 
					        // Get all the connected clients
 | 
				
			||||||
        std::set<std::shared_ptr<WebSocket>> getClients();
 | 
					        std::set<std::shared_ptr<WebSocket>> getClients();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private:
 | 
					    private:
 | 
				
			||||||
        // Member variables
 | 
					        // Member variables
 | 
				
			||||||
        int _port;
 | 
					 | 
				
			||||||
        std::string _host;
 | 
					 | 
				
			||||||
        int _backlog;
 | 
					 | 
				
			||||||
        size_t _maxConnections;
 | 
					 | 
				
			||||||
        int _handshakeTimeoutSecs;
 | 
					        int _handshakeTimeoutSecs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        OnConnectionCallback _onConnectionCallback;
 | 
					        OnConnectionCallback _onConnectionCallback;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // socket for accepting connections
 | 
					 | 
				
			||||||
        int _serverFd;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        std::mutex _clientsMutex;
 | 
					        std::mutex _clientsMutex;
 | 
				
			||||||
        std::set<std::shared_ptr<WebSocket>> _clients;
 | 
					        std::set<std::shared_ptr<WebSocket>> _clients;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        std::mutex _logMutex;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        std::atomic<bool> _stop;
 | 
					 | 
				
			||||||
        std::thread _thread;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        std::condition_variable _conditionVariable;
 | 
					 | 
				
			||||||
        std::mutex _conditionVariableMutex;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        const static int kDefaultPort;
 | 
					 | 
				
			||||||
        const static std::string kDefaultHost;
 | 
					 | 
				
			||||||
        const static int kDefaultTcpBacklog;
 | 
					 | 
				
			||||||
        const static size_t kDefaultMaxConnections;
 | 
					 | 
				
			||||||
        const static int kDefaultHandShakeTimeoutSecs;
 | 
					        const static int kDefaultHandShakeTimeoutSecs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Methods
 | 
					        // Methods
 | 
				
			||||||
        void run();
 | 
					        virtual void handleConnection(int fd) final;
 | 
				
			||||||
        void handleConnection(int fd);
 | 
					        virtual size_t getConnectedClientsCount() final;
 | 
				
			||||||
        size_t getConnectedClientsCount();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Logging
 | 
					 | 
				
			||||||
        void logError(const std::string& str);
 | 
					 | 
				
			||||||
        void logInfo(const std::string& str);
 | 
					 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -33,12 +33,17 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace ix
 | 
					namespace ix
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    const std::string WebSocketTransport::kHeartBeatPingMessage("ixwebsocket::hearbeat");
 | 
				
			||||||
 | 
					    const int WebSocketTransport::kDefaultHeartBeatPeriod(-1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    WebSocketTransport::WebSocketTransport() :
 | 
					    WebSocketTransport::WebSocketTransport() :
 | 
				
			||||||
        _readyState(CLOSED),
 | 
					        _readyState(CLOSED),
 | 
				
			||||||
        _closeCode(0),
 | 
					        _closeCode(0),
 | 
				
			||||||
        _closeWireSize(0),
 | 
					        _closeWireSize(0),
 | 
				
			||||||
        _enablePerMessageDeflate(false),
 | 
					        _enablePerMessageDeflate(false),
 | 
				
			||||||
        _requestInitCancellation(false)
 | 
					        _requestInitCancellation(false),
 | 
				
			||||||
 | 
					        _heartBeatPeriod(kDefaultHeartBeatPeriod),
 | 
				
			||||||
 | 
					        _lastSendTimePoint(std::chrono::steady_clock::now())
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -48,10 +53,12 @@ namespace ix
 | 
				
			|||||||
        ;
 | 
					        ;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void WebSocketTransport::configure(const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions)
 | 
					    void WebSocketTransport::configure(const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions,
 | 
				
			||||||
 | 
					                                       int hearBeatPeriod)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        _perMessageDeflateOptions = perMessageDeflateOptions;
 | 
					        _perMessageDeflateOptions = perMessageDeflateOptions;
 | 
				
			||||||
        _enablePerMessageDeflate = _perMessageDeflateOptions.enabled();
 | 
					        _enablePerMessageDeflate = _perMessageDeflateOptions.enabled();
 | 
				
			||||||
 | 
					        _heartBeatPeriod = hearBeatPeriod;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Client
 | 
					    // Client
 | 
				
			||||||
@@ -149,18 +156,36 @@ namespace ix
 | 
				
			|||||||
        _onCloseCallback = onCloseCallback; 
 | 
					        _onCloseCallback = onCloseCallback; 
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool WebSocketTransport::exceedSendHeartBeatTimeOut()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::lock_guard<std::mutex> lock(_lastSendTimePointMutex);
 | 
				
			||||||
 | 
					        auto now = std::chrono::steady_clock::now();
 | 
				
			||||||
 | 
					        return now - _lastSendTimePoint > std::chrono::seconds(_heartBeatPeriod);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void WebSocketTransport::poll()
 | 
					    void WebSocketTransport::poll()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        _socket->poll(
 | 
					        _socket->poll(
 | 
				
			||||||
            [this]()
 | 
					            [this](PollResultType pollResult)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
 | 
					                // If (1) heartbeat is enabled, and (2) no data was received or
 | 
				
			||||||
 | 
					                // send for a duration exceeding our heart-beat period, send a
 | 
				
			||||||
 | 
					                // ping to the server.
 | 
				
			||||||
 | 
					                if (pollResult == PollResultType_Timeout && 
 | 
				
			||||||
 | 
					                    exceedSendHeartBeatTimeOut())
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    std::stringstream ss;
 | 
				
			||||||
 | 
					                    ss << kHeartBeatPingMessage << "::" << _heartBeatPeriod << "s";
 | 
				
			||||||
 | 
					                    sendPing(ss.str());
 | 
				
			||||||
 | 
					                    return;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                while (true) 
 | 
					                while (true) 
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    int N = (int) _rxbuf.size();
 | 
					                    int N = (int) _rxbuf.size();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    int ret;
 | 
					 | 
				
			||||||
                    _rxbuf.resize(N + 1500);
 | 
					                    _rxbuf.resize(N + 1500);
 | 
				
			||||||
                    ret = _socket->recv((char*)&_rxbuf[0] + N, 1500);
 | 
					                    ssize_t ret = _socket->recv((char*)&_rxbuf[0] + N, 1500);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if (ret < 0 && (_socket->getErrno() == EWOULDBLOCK || 
 | 
					                    if (ret < 0 && (_socket->getErrno() == EWOULDBLOCK || 
 | 
				
			||||||
                                    _socket->getErrno() == EAGAIN)) {
 | 
					                                    _socket->getErrno() == EAGAIN)) {
 | 
				
			||||||
@@ -186,7 +211,8 @@ namespace ix
 | 
				
			|||||||
                    _socket->close();
 | 
					                    _socket->close();
 | 
				
			||||||
                    setReadyState(CLOSED);
 | 
					                    setReadyState(CLOSED);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            });
 | 
					            },
 | 
				
			||||||
 | 
					            _heartBeatPeriod);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool WebSocketTransport::isSendBufferEmpty() const
 | 
					    bool WebSocketTransport::isSendBufferEmpty() const
 | 
				
			||||||
@@ -409,7 +435,7 @@ namespace ix
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            std::string decompressedMessage;
 | 
					            std::string decompressedMessage;
 | 
				
			||||||
            bool success = _perMessageDeflate.decompress(message, decompressedMessage);
 | 
					            bool success = _perMessageDeflate.decompress(message, decompressedMessage);
 | 
				
			||||||
            onMessageCallback(decompressedMessage, wireSize, not success, messageKind);
 | 
					            onMessageCallback(decompressedMessage, wireSize, !success, messageKind);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@@ -539,7 +565,7 @@ namespace ix
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        while (_txbuf.size())
 | 
					        while (_txbuf.size())
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            int ret = _socket->send((char*)&_txbuf[0], _txbuf.size());
 | 
					            ssize_t ret = _socket->send((char*)&_txbuf[0], _txbuf.size());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (ret < 0 && (_socket->getErrno() == EWOULDBLOCK || 
 | 
					            if (ret < 0 && (_socket->getErrno() == EWOULDBLOCK || 
 | 
				
			||||||
                            _socket->getErrno() == EAGAIN))
 | 
					                            _socket->getErrno() == EAGAIN))
 | 
				
			||||||
@@ -558,6 +584,9 @@ namespace ix
 | 
				
			|||||||
                _txbuf.erase(_txbuf.begin(), _txbuf.begin() + ret);
 | 
					                _txbuf.erase(_txbuf.begin(), _txbuf.begin() + ret);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::lock_guard<std::mutex> lck(_lastSendTimePointMutex);
 | 
				
			||||||
 | 
					        _lastSendTimePoint = std::chrono::steady_clock::now();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void WebSocketTransport::close()
 | 
					    void WebSocketTransport::close()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -57,7 +57,8 @@ namespace ix
 | 
				
			|||||||
        WebSocketTransport();
 | 
					        WebSocketTransport();
 | 
				
			||||||
        ~WebSocketTransport();
 | 
					        ~WebSocketTransport();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void configure(const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions);
 | 
					        void configure(const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions,
 | 
				
			||||||
 | 
					                       int hearBeatPeriod);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        WebSocketInitResult connectToUrl(const std::string& url, // Client
 | 
					        WebSocketInitResult connectToUrl(const std::string& url, // Client
 | 
				
			||||||
                                         int timeoutSecs);
 | 
					                                         int timeoutSecs);
 | 
				
			||||||
@@ -116,6 +117,16 @@ namespace ix
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        // Used to cancel dns lookup + socket connect + http upgrade
 | 
					        // Used to cancel dns lookup + socket connect + http upgrade
 | 
				
			||||||
        std::atomic<bool> _requestInitCancellation;
 | 
					        std::atomic<bool> _requestInitCancellation;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        // Optional Heartbeat
 | 
				
			||||||
 | 
					        int _heartBeatPeriod;
 | 
				
			||||||
 | 
					        static const int kDefaultHeartBeatPeriod;
 | 
				
			||||||
 | 
					        const static std::string kHeartBeatPingMessage;
 | 
				
			||||||
 | 
					        mutable std::mutex _lastSendTimePointMutex;
 | 
				
			||||||
 | 
					        std::chrono::time_point<std::chrono::steady_clock> _lastSendTimePoint;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // No data was send through the socket for longer that the hearbeat period
 | 
				
			||||||
 | 
					        bool exceedSendHeartBeatTimeOut();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void sendOnSocket();
 | 
					        void sendOnSocket();
 | 
				
			||||||
        WebSocketSendInfo sendData(wsheader_type::opcode_type type, 
 | 
					        WebSocketSendInfo sendData(wsheader_type::opcode_type type, 
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										16
									
								
								ixwebsocket/windows/IXSetThreadName_windows.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								ixwebsocket/windows/IXSetThreadName_windows.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *  IXSetThreadName_windows.cpp
 | 
				
			||||||
 | 
					 *  Author: Benjamin Sergeant
 | 
				
			||||||
 | 
					 *  Copyright (c) 2019 Machine Zone, Inc. All rights reserved.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#include "../IXSetThreadName.h"
 | 
				
			||||||
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ix
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    void setThreadName(const std::string& name)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // FIXME
 | 
				
			||||||
 | 
					        std::cerr << "setThreadName not implemented on Windows yet" << std::endl;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										11
									
								
								makefile
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								makefile
									
									
									
									
									
								
							@@ -24,8 +24,17 @@ test_server:
 | 
				
			|||||||
	(cd test && npm i ws && node broadcast-server.js)
 | 
						(cd test && npm i ws && node broadcast-server.js)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# env TEST=Websocket_server make test
 | 
					# env TEST=Websocket_server make test
 | 
				
			||||||
 | 
					# env TEST=websocket_server make test
 | 
				
			||||||
 | 
					# env TEST=heartbeat make test
 | 
				
			||||||
test:
 | 
					test:
 | 
				
			||||||
	(cd test && sh run.sh)
 | 
						python test/run.py
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# For the fork that is configured with appveyor
 | 
				
			||||||
 | 
					rebase_upstream:
 | 
				
			||||||
 | 
						git fetch upstream
 | 
				
			||||||
 | 
						git checkout master
 | 
				
			||||||
 | 
						git reset --hard upstream/master
 | 
				
			||||||
 | 
						git push origin master --force
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.PHONY: test
 | 
					.PHONY: test
 | 
				
			||||||
.PHONY: build
 | 
					.PHONY: build
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,13 +2,17 @@
 | 
				
			|||||||
# Author: Benjamin Sergeant
 | 
					# Author: Benjamin Sergeant
 | 
				
			||||||
# Copyright (c) 2018 Machine Zone, Inc. All rights reserved.
 | 
					# Copyright (c) 2018 Machine Zone, Inc. All rights reserved.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
 | 
					 | 
				
			||||||
cmake_minimum_required (VERSION 3.4.1)
 | 
					cmake_minimum_required (VERSION 3.4.1)
 | 
				
			||||||
project (ixwebsocket_unittest)
 | 
					project (ixwebsocket_unittest)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
set (CMAKE_CXX_STANDARD 11)
 | 
					set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/../third_party/sanitizers-cmake/cmake" ${CMAKE_MODULE_PATH})
 | 
				
			||||||
 | 
					find_package(Sanitizers)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
option(USE_TLS "Add TLS support" ON)
 | 
					set (CMAKE_CXX_STANDARD 14)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (NOT WIN32)
 | 
				
			||||||
 | 
					  option(USE_TLS "Add TLS support" ON)
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
add_subdirectory(${PROJECT_SOURCE_DIR}/.. ixwebsocket)
 | 
					add_subdirectory(${PROJECT_SOURCE_DIR}/.. ixwebsocket)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -16,14 +20,29 @@ include_directories(
 | 
				
			|||||||
  ${PROJECT_SOURCE_DIR}/Catch2/single_include
 | 
					  ${PROJECT_SOURCE_DIR}/Catch2/single_include
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
add_executable(ixwebsocket_unittest 
 | 
					# Shared sources
 | 
				
			||||||
 | 
					set (SOURCES 
 | 
				
			||||||
  test_runner.cpp
 | 
					  test_runner.cpp
 | 
				
			||||||
  cmd_websocket_chat.cpp
 | 
					 | 
				
			||||||
  IXWebSocketServerTest.cpp
 | 
					 | 
				
			||||||
  IXTest.cpp
 | 
					  IXTest.cpp
 | 
				
			||||||
  msgpack11.cpp
 | 
					  msgpack11.cpp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  IXDNSLookupTest.cpp
 | 
				
			||||||
 | 
					  IXSocketTest.cpp
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Some unittest don't work on windows yet
 | 
				
			||||||
 | 
					if (NOT WIN32)
 | 
				
			||||||
 | 
					  list(APPEND SOURCES 
 | 
				
			||||||
 | 
					    IXWebSocketServerTest.cpp
 | 
				
			||||||
 | 
					    IXWebSocketHeartBeatTest.cpp
 | 
				
			||||||
 | 
					    cmd_websocket_chat.cpp
 | 
				
			||||||
 | 
					    IXWebSocketTestConnectionDisconnection.cpp
 | 
				
			||||||
 | 
					  )
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					add_executable(ixwebsocket_unittest ${SOURCES})
 | 
				
			||||||
 | 
					add_sanitizers(ixwebsocket_unittest)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (APPLE AND USE_TLS)
 | 
					if (APPLE AND USE_TLS)
 | 
				
			||||||
    target_link_libraries(ixwebsocket_unittest "-framework foundation" "-framework security")
 | 
					    target_link_libraries(ixwebsocket_unittest "-framework foundation" "-framework security")
 | 
				
			||||||
endif()
 | 
					endif()
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										50
									
								
								test/IXDNSLookupTest.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								test/IXDNSLookupTest.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,50 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *  IXDNSLookupTest.cpp
 | 
				
			||||||
 | 
					 *  Author: Benjamin Sergeant
 | 
				
			||||||
 | 
					 *  Copyright (c) 2018 Machine Zone. All rights reserved.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "catch.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "IXTest.h"
 | 
				
			||||||
 | 
					#include <ixwebsocket/IXDNSLookup.h>
 | 
				
			||||||
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using namespace ix;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST_CASE("dns", "[net]")
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    SECTION("Test resolving a known hostname")
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        DNSLookup dnsLookup("www.google.com", 80);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::string errMsg;
 | 
				
			||||||
 | 
					        struct addrinfo* res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        res = dnsLookup.resolve(errMsg, [] { return false; });
 | 
				
			||||||
 | 
					        std::cerr << "Error message: " << errMsg << std::endl;
 | 
				
			||||||
 | 
					        REQUIRE(res != nullptr);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SECTION("Test resolving a non-existing hostname")
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        DNSLookup dnsLookup("wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww", 80);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::string errMsg;
 | 
				
			||||||
 | 
					        struct addrinfo* res = dnsLookup.resolve(errMsg, [] { return false; });
 | 
				
			||||||
 | 
					        std::cerr << "Error message: " << errMsg << std::endl;
 | 
				
			||||||
 | 
					        REQUIRE(res == nullptr);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SECTION("Test resolving a good hostname, with cancellation")
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        DNSLookup dnsLookup("www.google.com", 80, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::string errMsg;
 | 
				
			||||||
 | 
					        // The callback returning true means we are requesting cancellation
 | 
				
			||||||
 | 
					        struct addrinfo* res = dnsLookup.resolve(errMsg, [] { return true; });
 | 
				
			||||||
 | 
					        std::cerr << "Error message: " << errMsg << std::endl;
 | 
				
			||||||
 | 
					        REQUIRE(res == nullptr);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										92
									
								
								test/IXSocketTest.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								test/IXSocketTest.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,92 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *  IXSocketTest.cpp
 | 
				
			||||||
 | 
					 *  Author: Benjamin Sergeant
 | 
				
			||||||
 | 
					 *  Copyright (c) 2019 Machine Zone. All rights reserved.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					#include <ixwebsocket/IXSocket.h>
 | 
				
			||||||
 | 
					#include <ixwebsocket/IXCancellationRequest.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(__APPLE__) or defined(__linux__)
 | 
				
			||||||
 | 
					# ifdef __APPLE__
 | 
				
			||||||
 | 
					#  include <ixwebsocket/IXSocketAppleSSL.h>
 | 
				
			||||||
 | 
					# else
 | 
				
			||||||
 | 
					#  include <ixwebsocket/IXSocketOpenSSL.h>
 | 
				
			||||||
 | 
					# endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "IXTest.h" 
 | 
				
			||||||
 | 
					#include "catch.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using namespace ix;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ix
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    void testSocket(const std::string& host,
 | 
				
			||||||
 | 
					                    int port,
 | 
				
			||||||
 | 
					                    const std::string& request,
 | 
				
			||||||
 | 
					                    std::shared_ptr<Socket> socket,
 | 
				
			||||||
 | 
					                    int expectedStatus,
 | 
				
			||||||
 | 
					                    int timeoutSecs)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::string errMsg;
 | 
				
			||||||
 | 
					        static std::atomic<bool> requestInitCancellation(false);
 | 
				
			||||||
 | 
					        auto isCancellationRequested =
 | 
				
			||||||
 | 
					            makeCancellationRequestWithTimeout(timeoutSecs, requestInitCancellation);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        bool success = socket->connect(host, port, errMsg, isCancellationRequested);
 | 
				
			||||||
 | 
					        Logger() << "errMsg: " << errMsg;
 | 
				
			||||||
 | 
					        REQUIRE(success);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::cout << "Sending request: " << request
 | 
				
			||||||
 | 
					                  << "to " << host << ":" << port
 | 
				
			||||||
 | 
					                  << std::endl;
 | 
				
			||||||
 | 
					        REQUIRE(socket->writeBytes(request, isCancellationRequested));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        auto lineResult = socket->readLine(isCancellationRequested);
 | 
				
			||||||
 | 
					        auto lineValid = lineResult.first;
 | 
				
			||||||
 | 
					        auto line = lineResult.second;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::cout << "read error: " << strerror(Socket::getErrno()) << std::endl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        REQUIRE(lineValid);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        int status = -1;
 | 
				
			||||||
 | 
					        REQUIRE(sscanf(line.c_str(), "HTTP/1.1 %d", &status) == 1);
 | 
				
			||||||
 | 
					        REQUIRE(status == expectedStatus);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST_CASE("socket", "[socket]")
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    SECTION("Connect to google HTTP server. Send GET request without header. Should return 200")
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::shared_ptr<Socket> socket(new Socket);
 | 
				
			||||||
 | 
					        std::string host("www.google.com");
 | 
				
			||||||
 | 
					        int port = 80;
 | 
				
			||||||
 | 
					        std::string request("GET / HTTP/1.1\r\n\r\n");
 | 
				
			||||||
 | 
					        int expectedStatus = 200;
 | 
				
			||||||
 | 
					        int timeoutSecs = 3;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        testSocket(host, port, request, socket, expectedStatus, timeoutSecs);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(__APPLE__) or defined(__linux__)
 | 
				
			||||||
 | 
					    SECTION("Connect to google HTTPS server. Send GET request without header. Should return 200")
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					# ifdef __APPLE__
 | 
				
			||||||
 | 
					        std::shared_ptr<Socket> socket = std::make_shared<SocketAppleSSL>();
 | 
				
			||||||
 | 
					# else
 | 
				
			||||||
 | 
					        std::shared_ptr<Socket> socket = std::make_shared<SocketOpenSSL>();
 | 
				
			||||||
 | 
					# endif
 | 
				
			||||||
 | 
					        std::string host("www.google.com");
 | 
				
			||||||
 | 
					        int port = 443;
 | 
				
			||||||
 | 
					        std::string request("GET / HTTP/1.1\r\n\r\n");
 | 
				
			||||||
 | 
					        int expectedStatus = 200;
 | 
				
			||||||
 | 
					        int timeoutSecs = 3;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        testSocket(host, port, request, socket, expectedStatus, timeoutSecs);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -9,6 +9,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <chrono>
 | 
					#include <chrono>
 | 
				
			||||||
#include <thread>
 | 
					#include <thread>
 | 
				
			||||||
 | 
					#include <mutex>
 | 
				
			||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
#include <fstream>
 | 
					#include <fstream>
 | 
				
			||||||
#include <iostream>
 | 
					#include <iostream>
 | 
				
			||||||
@@ -18,6 +19,7 @@ namespace ix
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    std::atomic<size_t> incomingBytes(0);
 | 
					    std::atomic<size_t> incomingBytes(0);
 | 
				
			||||||
    std::atomic<size_t> outgoingBytes(0);
 | 
					    std::atomic<size_t> outgoingBytes(0);
 | 
				
			||||||
 | 
					    std::mutex Logger::_mutex;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void setupWebSocketTrafficTrackerCallback()
 | 
					    void setupWebSocketTrafficTrackerCallback()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@@ -38,9 +40,9 @@ namespace ix
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    void reportWebSocketTraffic()
 | 
					    void reportWebSocketTraffic()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        std::cout << incomingBytes << std::endl;
 | 
					        Logger() << incomingBytes;
 | 
				
			||||||
        std::cout << "Incoming bytes: " << incomingBytes << std::endl;
 | 
					        Logger() << "Incoming bytes: " << incomingBytes;
 | 
				
			||||||
        std::cout << "Outgoing bytes: " << outgoingBytes << std::endl;
 | 
					        Logger() << "Outgoing bytes: " << outgoingBytes;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void msleep(int ms)
 | 
					    void msleep(int ms)
 | 
				
			||||||
@@ -58,4 +60,10 @@ namespace ix
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        return std::to_string(seconds);
 | 
					        return std::to_string(seconds);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void log(const std::string& msg)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Logger() << msg;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,6 +9,8 @@
 | 
				
			|||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
#include <vector>
 | 
					#include <vector>
 | 
				
			||||||
#include <sstream>
 | 
					#include <sstream>
 | 
				
			||||||
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					#include <mutex>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace ix
 | 
					namespace ix
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -21,4 +23,32 @@ namespace ix
 | 
				
			|||||||
    // Record and report websocket traffic
 | 
					    // Record and report websocket traffic
 | 
				
			||||||
    void setupWebSocketTrafficTrackerCallback();
 | 
					    void setupWebSocketTrafficTrackerCallback();
 | 
				
			||||||
    void reportWebSocketTraffic();
 | 
					    void reportWebSocketTraffic();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct Logger
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            Logger& operator<<(const std::string& msg)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                std::lock_guard<std::mutex> lock(_mutex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                std::cerr << msg;
 | 
				
			||||||
 | 
					                std::cerr << std::endl;
 | 
				
			||||||
 | 
					                return *this;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            template <typename T>
 | 
				
			||||||
 | 
					            Logger& operator<<(T const& obj)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                std::lock_guard<std::mutex> lock(_mutex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                std::cerr << obj;
 | 
				
			||||||
 | 
					                std::cerr << std::endl;
 | 
				
			||||||
 | 
					                return *this;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private:
 | 
				
			||||||
 | 
					            static std::mutex _mutex;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void log(const std::string& msg);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										222
									
								
								test/IXWebSocketHeartBeatTest.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										222
									
								
								test/IXWebSocketHeartBeatTest.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,222 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *  IXWebSocketHeartBeatTest.cpp
 | 
				
			||||||
 | 
					 *  Author: Benjamin Sergeant
 | 
				
			||||||
 | 
					 *  Copyright (c) 2019 Machine Zone. All rights reserved.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					#include <sstream>
 | 
				
			||||||
 | 
					#include <queue>
 | 
				
			||||||
 | 
					#include <ixwebsocket/IXWebSocket.h>
 | 
				
			||||||
 | 
					#include <ixwebsocket/IXWebSocketServer.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "IXTest.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "catch.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using namespace ix;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    class WebSocketClient
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            WebSocketClient(int port);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            void subscribe(const std::string& channel);
 | 
				
			||||||
 | 
					            void start();
 | 
				
			||||||
 | 
					            void stop();
 | 
				
			||||||
 | 
					            bool isReady() const;
 | 
				
			||||||
 | 
					            void sendMessage(const std::string& text);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private:
 | 
				
			||||||
 | 
					            ix::WebSocket _webSocket;
 | 
				
			||||||
 | 
					            int _port;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    WebSocketClient::WebSocketClient(int port) 
 | 
				
			||||||
 | 
					        : _port(port)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        ;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool WebSocketClient::isReady() const
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return _webSocket.getReadyState() == ix::WebSocket_ReadyState_Open;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void WebSocketClient::stop()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        _webSocket.stop();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void WebSocketClient::start()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::string url;
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            std::stringstream ss;
 | 
				
			||||||
 | 
					            ss << "ws://localhost:"
 | 
				
			||||||
 | 
					               << _port 
 | 
				
			||||||
 | 
					               << "/";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            url = ss.str();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        _webSocket.setUrl(url);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // The important bit for this test. 
 | 
				
			||||||
 | 
					        // Set a 1 second hearbeat ; if no traffic is present on the connection for 1 second
 | 
				
			||||||
 | 
					        // a ping message will be sent by the client.
 | 
				
			||||||
 | 
					        _webSocket.setHeartBeatPeriod(1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::stringstream ss;
 | 
				
			||||||
 | 
					        log(std::string("Connecting to url: ") + url);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        _webSocket.setOnMessageCallback(
 | 
				
			||||||
 | 
					            [](ix::WebSocketMessageType messageType,
 | 
				
			||||||
 | 
					               const std::string& str,
 | 
				
			||||||
 | 
					               size_t wireSize,
 | 
				
			||||||
 | 
					               const ix::WebSocketErrorInfo& error,
 | 
				
			||||||
 | 
					               const ix::WebSocketOpenInfo& openInfo,
 | 
				
			||||||
 | 
					                   const ix::WebSocketCloseInfo& closeInfo)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                std::stringstream ss;
 | 
				
			||||||
 | 
					                if (messageType == ix::WebSocket_MessageType_Open)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    log("client connected");
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                else if (messageType == ix::WebSocket_MessageType_Close)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    log("client disconnected");
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                else if (messageType == ix::WebSocket_MessageType_Error)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    ss << "Error ! " << error.reason;
 | 
				
			||||||
 | 
					                    log(ss.str());
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                else if (messageType == ix::WebSocket_MessageType_Pong)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    ss << "Received pong message " << str;
 | 
				
			||||||
 | 
					                    log(ss.str());
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                else if (messageType == ix::WebSocket_MessageType_Ping)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    ss << "Received ping message " << str;
 | 
				
			||||||
 | 
					                    log(ss.str());
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                else if (messageType == ix::WebSocket_MessageType_Message)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    ss << "Received message " << str;
 | 
				
			||||||
 | 
					                    log(ss.str());
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                else
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    ss << "Invalid ix::WebSocketMessageType";
 | 
				
			||||||
 | 
					                    log(ss.str());
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        _webSocket.start();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void WebSocketClient::sendMessage(const std::string& text)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        _webSocket.send(text);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool startServer(ix::WebSocketServer& server, std::atomic<int>& receivedPingMessages)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // A dev/null server
 | 
				
			||||||
 | 
					        server.setOnConnectionCallback(
 | 
				
			||||||
 | 
					            [&server, &receivedPingMessages](std::shared_ptr<ix::WebSocket> webSocket)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                webSocket->setOnMessageCallback(
 | 
				
			||||||
 | 
					                    [webSocket, &server, &receivedPingMessages](ix::WebSocketMessageType messageType,
 | 
				
			||||||
 | 
					                       const std::string& str,
 | 
				
			||||||
 | 
					                       size_t wireSize,
 | 
				
			||||||
 | 
					                       const ix::WebSocketErrorInfo& error,
 | 
				
			||||||
 | 
					                       const ix::WebSocketOpenInfo& openInfo,
 | 
				
			||||||
 | 
					                       const ix::WebSocketCloseInfo& closeInfo)
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        if (messageType == ix::WebSocket_MessageType_Open)
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            Logger() << "New server connection";
 | 
				
			||||||
 | 
					                            Logger() << "Uri: " << openInfo.uri;
 | 
				
			||||||
 | 
					                            Logger() << "Headers:";
 | 
				
			||||||
 | 
					                            for (auto it : openInfo.headers)
 | 
				
			||||||
 | 
					                            {
 | 
				
			||||||
 | 
					                                Logger() << it.first << ": " << it.second;
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        else if (messageType == ix::WebSocket_MessageType_Close)
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            log("Server closed connection");
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        else if (messageType == ix::WebSocket_MessageType_Ping)
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            log("Server received a ping");
 | 
				
			||||||
 | 
					                            receivedPingMessages++;
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        auto res = server.listen();
 | 
				
			||||||
 | 
					        if (!res.first)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            log(res.second);
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        server.start();
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST_CASE("Websocket_heartbeat", "[heartbeat]")
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    SECTION("Make sure that ping messages are sent during heartbeat.")
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        ix::setupWebSocketTrafficTrackerCallback();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        int port = 8093;
 | 
				
			||||||
 | 
					        ix::WebSocketServer server(port);
 | 
				
			||||||
 | 
					        std::atomic<int> serverReceivedPingMessages(0);
 | 
				
			||||||
 | 
					        REQUIRE(startServer(server, serverReceivedPingMessages));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::string session = ix::generateSessionId();
 | 
				
			||||||
 | 
					        WebSocketClient webSocketClientA(port);
 | 
				
			||||||
 | 
					        WebSocketClient webSocketClientB(port);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        webSocketClientA.start();
 | 
				
			||||||
 | 
					        webSocketClientB.start();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Wait for all chat instance to be ready
 | 
				
			||||||
 | 
					        while (true)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (webSocketClientA.isReady() && webSocketClientB.isReady()) break;
 | 
				
			||||||
 | 
					            ix::msleep(10);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        REQUIRE(server.getClients().size() == 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ix::msleep(900);
 | 
				
			||||||
 | 
					        webSocketClientB.sendMessage("hello world");
 | 
				
			||||||
 | 
					        ix::msleep(900);
 | 
				
			||||||
 | 
					        webSocketClientB.sendMessage("hello world");
 | 
				
			||||||
 | 
					        ix::msleep(900);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        webSocketClientA.stop();
 | 
				
			||||||
 | 
					        webSocketClientB.stop();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        REQUIRE(serverReceivedPingMessages >= 2);
 | 
				
			||||||
 | 
					        REQUIRE(serverReceivedPingMessages <= 4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Give us 500ms for the server to notice that clients went away
 | 
				
			||||||
 | 
					        ix::msleep(500);
 | 
				
			||||||
 | 
					        REQUIRE(server.getClients().size() == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ix::reportWebSocketTraffic();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -32,17 +32,17 @@ namespace ix
 | 
				
			|||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        if (messageType == ix::WebSocket_MessageType_Open)
 | 
					                        if (messageType == ix::WebSocket_MessageType_Open)
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            std::cerr << "New connection" << std::endl;
 | 
					                            Logger() << "New connection";
 | 
				
			||||||
                            std::cerr << "Uri: " << openInfo.uri << std::endl;
 | 
					                            Logger() << "Uri: " << openInfo.uri;
 | 
				
			||||||
                            std::cerr << "Headers:" << std::endl;
 | 
					                            Logger() << "Headers:";
 | 
				
			||||||
                            for (auto it : openInfo.headers)
 | 
					                            for (auto it : openInfo.headers)
 | 
				
			||||||
                            {
 | 
					                            {
 | 
				
			||||||
                                std::cerr << it.first << ": " << it.second << std::endl;
 | 
					                                Logger() << it.first << ": " << it.second;
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        else if (messageType == ix::WebSocket_MessageType_Close)
 | 
					                        else if (messageType == ix::WebSocket_MessageType_Close)
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            std::cerr << "Closed connection" << std::endl;
 | 
					                            Logger() << "Closed connection";
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        else if (messageType == ix::WebSocket_MessageType_Message)
 | 
					                        else if (messageType == ix::WebSocket_MessageType_Message)
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
@@ -62,7 +62,7 @@ namespace ix
 | 
				
			|||||||
        auto res = server.listen();
 | 
					        auto res = server.listen();
 | 
				
			||||||
        if (!res.first)
 | 
					        if (!res.first)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            std::cerr << res.second << std::endl;
 | 
					            Logger() << res.second;
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -121,7 +121,7 @@ TEST_CASE("Websocket_server", "[websocket_server]")
 | 
				
			|||||||
        bool success = socket.connect(host, port, errMsg, isCancellationRequested);
 | 
					        bool success = socket.connect(host, port, errMsg, isCancellationRequested);
 | 
				
			||||||
        REQUIRE(success);
 | 
					        REQUIRE(success);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        std::cout << "writeBytes" << std::endl;
 | 
					        Logger() << "writeBytes";
 | 
				
			||||||
        socket.writeBytes("GET /\r\n", isCancellationRequested);
 | 
					        socket.writeBytes("GET /\r\n", isCancellationRequested);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        auto lineResult = socket.readLine(isCancellationRequested);
 | 
					        auto lineResult = socket.readLine(isCancellationRequested);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										128
									
								
								test/IXWebSocketTestConnectionDisconnection.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								test/IXWebSocketTestConnectionDisconnection.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,128 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *  IXWebSocketTestConnectionDisconnection.cpp
 | 
				
			||||||
 | 
					 *  Author: Benjamin Sergeant
 | 
				
			||||||
 | 
					 *  Copyright (c) 2017 Machine Zone. All rights reserved.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					#include <sstream>
 | 
				
			||||||
 | 
					#include <set>
 | 
				
			||||||
 | 
					#include <ixwebsocket/IXWebSocket.h>
 | 
				
			||||||
 | 
					#include "IXTest.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "catch.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using namespace ix;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const std::string WEBSOCKET_DOT_ORG_URL("wss://echo.websocket.org");
 | 
				
			||||||
 | 
					    const std::string GOOGLE_URL("wss://google.com");
 | 
				
			||||||
 | 
					    const std::string UNKNOWN_URL("wss://asdcasdcaasdcasdcasdcasdcasdcasdcasassdd.com");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    class IXWebSocketTestConnectionDisconnection
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public:
 | 
				
			||||||
 | 
					            IXWebSocketTestConnectionDisconnection();
 | 
				
			||||||
 | 
					            void start(const std::string& url);
 | 
				
			||||||
 | 
					            void stop();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private:
 | 
				
			||||||
 | 
					            ix::WebSocket _webSocket;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IXWebSocketTestConnectionDisconnection::IXWebSocketTestConnectionDisconnection()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        ;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void IXWebSocketTestConnectionDisconnection::stop()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        _webSocket.stop();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void IXWebSocketTestConnectionDisconnection::start(const std::string& url)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        _webSocket.setUrl(url);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::stringstream ss;
 | 
				
			||||||
 | 
					        log(std::string("Connecting to url: ") + url);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        _webSocket.setOnMessageCallback(
 | 
				
			||||||
 | 
					            [](ix::WebSocketMessageType messageType,
 | 
				
			||||||
 | 
					               const std::string& str,
 | 
				
			||||||
 | 
					               size_t wireSize,
 | 
				
			||||||
 | 
					               const ix::WebSocketErrorInfo& error,
 | 
				
			||||||
 | 
					               const ix::WebSocketOpenInfo& openInfo,
 | 
				
			||||||
 | 
					               const ix::WebSocketCloseInfo& closeInfo)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                std::stringstream ss;
 | 
				
			||||||
 | 
					                if (messageType == ix::WebSocket_MessageType_Open)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    log("cmd_websocket_satori_chat: connected !");
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                else if (messageType == ix::WebSocket_MessageType_Close)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    log("cmd_websocket_satori_chat: disconnected !");
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                else if (messageType == ix::WebSocket_MessageType_Error)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    log("cmd_websocket_satori_chat: Error!");
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                else if (messageType == ix::WebSocket_MessageType_Message)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    log("cmd_websocket_satori_chat: received message.!");
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                else if (messageType == ix::WebSocket_MessageType_Ping)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    log("cmd_websocket_satori_chat: received ping message.!");
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                else if (messageType == ix::WebSocket_MessageType_Pong)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    log("cmd_websocket_satori_chat: received pong message.!");
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                else
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    log("Invalid ix::WebSocketMessageType");
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Start the connection
 | 
				
			||||||
 | 
					        _webSocket.start();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// We try to connect to different servers, and make sure there are no crashes.
 | 
				
			||||||
 | 
					// FIXME: We could do more checks (make sure that we were not able to connect to unknown servers, etc...)
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					TEST_CASE("websocket_connections", "[websocket]")
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    SECTION("Try to connect to invalid servers.")
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        IXWebSocketTestConnectionDisconnection chatA;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        chatA.start(GOOGLE_URL);
 | 
				
			||||||
 | 
					        ix::msleep(1000);
 | 
				
			||||||
 | 
					        chatA.stop();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        chatA.start(UNKNOWN_URL);
 | 
				
			||||||
 | 
					        ix::msleep(1000);
 | 
				
			||||||
 | 
					        chatA.stop();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SECTION("Try to connect and disconnect with different timing.")
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        IXWebSocketTestConnectionDisconnection chatA;
 | 
				
			||||||
 | 
					        for (int i = 0; i < 50; ++i)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            log(std::string("Run: ") + std::to_string(i));
 | 
				
			||||||
 | 
					            chatA.start(WEBSOCKET_DOT_ORG_URL);
 | 
				
			||||||
 | 
					            ix::msleep(i);
 | 
				
			||||||
 | 
					            chatA.stop();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -4,11 +4,6 @@
 | 
				
			|||||||
 *  Copyright (c) 2017 Machine Zone. All rights reserved.
 | 
					 *  Copyright (c) 2017 Machine Zone. All rights reserved.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Simple chat program that talks to the node.js server at
 | 
					 | 
				
			||||||
// websocket_chat_server/broacast-server.js
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <iostream>
 | 
					#include <iostream>
 | 
				
			||||||
#include <sstream>
 | 
					#include <sstream>
 | 
				
			||||||
#include <queue>
 | 
					#include <queue>
 | 
				
			||||||
@@ -43,8 +38,6 @@ namespace
 | 
				
			|||||||
            std::pair<std::string, std::string> decodeMessage(const std::string& str);
 | 
					            std::pair<std::string, std::string> decodeMessage(const std::string& str);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private:
 | 
					        private:
 | 
				
			||||||
            void log(const std::string& msg);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            std::string _user;
 | 
					            std::string _user;
 | 
				
			||||||
            std::string _session;
 | 
					            std::string _session;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -76,11 +69,6 @@ namespace
 | 
				
			|||||||
        _webSocket.stop();
 | 
					        _webSocket.stop();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void WebSocketChat::log(const std::string& msg)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        std::cerr << msg << std::endl;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void WebSocketChat::start()
 | 
					    void WebSocketChat::start()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        std::string url("ws://localhost:8090/");
 | 
					        std::string url("ws://localhost:8090/");
 | 
				
			||||||
@@ -188,17 +176,17 @@ namespace
 | 
				
			|||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        if (messageType == ix::WebSocket_MessageType_Open)
 | 
					                        if (messageType == ix::WebSocket_MessageType_Open)
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            std::cerr << "New connection" << std::endl;
 | 
					                            Logger() << "New connection";
 | 
				
			||||||
                            std::cerr << "Uri: " << openInfo.uri << std::endl;
 | 
					                            Logger() << "Uri: " << openInfo.uri;
 | 
				
			||||||
                            std::cerr << "Headers:" << std::endl;
 | 
					                            Logger() << "Headers:";
 | 
				
			||||||
                            for (auto it : openInfo.headers)
 | 
					                            for (auto it : openInfo.headers)
 | 
				
			||||||
                            {
 | 
					                            {
 | 
				
			||||||
                                std::cerr << it.first << ": " << it.second << std::endl;
 | 
					                                Logger() << it.first << ": " << it.second;
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        else if (messageType == ix::WebSocket_MessageType_Close)
 | 
					                        else if (messageType == ix::WebSocket_MessageType_Close)
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            std::cerr << "Closed connection" << std::endl;
 | 
					                            log("Closed connection");
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        else if (messageType == ix::WebSocket_MessageType_Message)
 | 
					                        else if (messageType == ix::WebSocket_MessageType_Message)
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
@@ -218,7 +206,7 @@ namespace
 | 
				
			|||||||
        auto res = server.listen();
 | 
					        auto res = server.listen();
 | 
				
			||||||
        if (!res.first)
 | 
					        if (!res.first)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            std::cerr << res.second << std::endl;
 | 
					            log(res.second);
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										78
									
								
								test/run.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								test/run.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,78 @@
 | 
				
			|||||||
 | 
					import os
 | 
				
			||||||
 | 
					import platform
 | 
				
			||||||
 | 
					import shutil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					osName = platform.system()
 | 
				
			||||||
 | 
					print('os name = {}'.format(osName))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					root = os.path.dirname(os.path.realpath(__file__))
 | 
				
			||||||
 | 
					buildDir = os.path.join(root, 'build')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if not os.path.exists(buildDir):
 | 
				
			||||||
 | 
					    os.mkdir(buildDir)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					os.chdir(buildDir)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if osName == 'Windows':
 | 
				
			||||||
 | 
					    generator = '-G"NMake Makefiles"'
 | 
				
			||||||
 | 
					    make = 'nmake'
 | 
				
			||||||
 | 
					    testBinary ='ixwebsocket_unittest.exe'
 | 
				
			||||||
 | 
					else:
 | 
				
			||||||
 | 
					    generator = ''
 | 
				
			||||||
 | 
					    make = 'make -j6'
 | 
				
			||||||
 | 
					    testBinary ='./ixwebsocket_unittest' 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sanitizersFlags = {
 | 
				
			||||||
 | 
					    'asan': '-DSANITIZE_ADDRESS=On',
 | 
				
			||||||
 | 
					    'ubsan': '-DSANITIZE_UNDEFINED=On',
 | 
				
			||||||
 | 
					    'tsan': '-DSANITIZE_THREAD=On',
 | 
				
			||||||
 | 
					    'none': ''
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					sanitizer = 'tsan'
 | 
				
			||||||
 | 
					if osName == 'Linux':
 | 
				
			||||||
 | 
					    sanitizer = 'asan'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sanitizerFlags = sanitizersFlags[sanitizer]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cmakeCmd = 'cmake -DCMAKE_BUILD_TYPE=Debug {} {} ..'.format(generator, sanitizerFlags)
 | 
				
			||||||
 | 
					print(cmakeCmd)
 | 
				
			||||||
 | 
					ret = os.system(cmakeCmd)
 | 
				
			||||||
 | 
					assert ret == 0, 'CMake failed, exiting'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ret = os.system(make)
 | 
				
			||||||
 | 
					assert ret == 0, 'Make failed, exiting'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def findFiles(prefix):
 | 
				
			||||||
 | 
					    '''Find all files under a given directory'''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    paths = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for root, _, files in os.walk(prefix):
 | 
				
			||||||
 | 
					        for path in files:
 | 
				
			||||||
 | 
					            fullPath = os.path.join(root, path)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if os.path.islink(fullPath):
 | 
				
			||||||
 | 
					                continue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            paths.append(fullPath)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return paths
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#for path in findFiles('.'):
 | 
				
			||||||
 | 
					#    print(path)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# We need to copy the zlib DLL in the current work directory
 | 
				
			||||||
 | 
					shutil.copy(os.path.join(
 | 
				
			||||||
 | 
					    '..',
 | 
				
			||||||
 | 
					    '..',
 | 
				
			||||||
 | 
					    'third_party',
 | 
				
			||||||
 | 
					    'ZLIB-Windows',
 | 
				
			||||||
 | 
					    'zlib-1.2.11_deploy_v140',
 | 
				
			||||||
 | 
					    'release_dynamic',
 | 
				
			||||||
 | 
					    'x64',
 | 
				
			||||||
 | 
					    'bin',
 | 
				
			||||||
 | 
					    'zlib.dll'), '.')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					testCommand = '{} {}'.format(testBinary, os.getenv('TEST', ''))
 | 
				
			||||||
 | 
					ret = os.system(testCommand)
 | 
				
			||||||
 | 
					assert ret == 0, 'Test command failed'
 | 
				
			||||||
@@ -7,8 +7,14 @@
 | 
				
			|||||||
#define CATCH_CONFIG_RUNNER
 | 
					#define CATCH_CONFIG_RUNNER
 | 
				
			||||||
#include "catch.hpp"
 | 
					#include "catch.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <ixwebsocket/IXSocket.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int main(int argc, char* argv[]) 
 | 
					int main(int argc, char* argv[]) 
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    ix::Socket::init(); // for Windows
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int result = Catch::Session().run(argc, argv);
 | 
					    int result = Catch::Session().run(argc, argv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ix::Socket::cleanup(); // for Windows
 | 
				
			||||||
    return result;
 | 
					    return result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										115
									
								
								third_party/ZLIB-Windows/README.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								third_party/ZLIB-Windows/README.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,115 @@
 | 
				
			|||||||
 | 
					ZLIB DATA COMPRESSION LIBRARY
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					zlib 1.2.11 is a general purpose data compression library.  All the code is
 | 
				
			||||||
 | 
					thread safe.  The data format used by the zlib library is described by RFCs
 | 
				
			||||||
 | 
					(Request for Comments) 1950 to 1952 in the files
 | 
				
			||||||
 | 
					http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and
 | 
				
			||||||
 | 
					rfc1952 (gzip format).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					All functions of the compression library are documented in the file zlib.h
 | 
				
			||||||
 | 
					(volunteer to write man pages welcome, contact zlib@gzip.org).  A usage example
 | 
				
			||||||
 | 
					of the library is given in the file test/example.c which also tests that
 | 
				
			||||||
 | 
					the library is working correctly.  Another example is given in the file
 | 
				
			||||||
 | 
					test/minigzip.c.  The compression library itself is composed of all source
 | 
				
			||||||
 | 
					files in the root directory.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To compile all files and run the test program, follow the instructions given at
 | 
				
			||||||
 | 
					the top of Makefile.in.  In short "./configure; make test", and if that goes
 | 
				
			||||||
 | 
					well, "make install" should work for most flavors of Unix.  For Windows, use
 | 
				
			||||||
 | 
					one of the special makefiles in win32/ or contrib/vstudio/ .  For VMS, use
 | 
				
			||||||
 | 
					make_vms.com.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Questions about zlib should be sent to <zlib@gzip.org>, or to Gilles Vollant
 | 
				
			||||||
 | 
					<info@winimage.com> for the Windows DLL version.  The zlib home page is
 | 
				
			||||||
 | 
					http://zlib.net/ .  Before reporting a problem, please check this site to
 | 
				
			||||||
 | 
					verify that you have the latest version of zlib; otherwise get the latest
 | 
				
			||||||
 | 
					version and check whether the problem still exists or not.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PLEASE read the zlib FAQ http://zlib.net/zlib_faq.html before asking for help.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Mark Nelson <markn@ieee.org> wrote an article about zlib for the Jan.  1997
 | 
				
			||||||
 | 
					issue of Dr.  Dobb's Journal; a copy of the article is available at
 | 
				
			||||||
 | 
					http://marknelson.us/1997/01/01/zlib-engine/ .
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The changes made in version 1.2.11 are documented in the file ChangeLog.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Unsupported third party contributions are provided in directory contrib/ .
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					zlib is available in Java using the java.util.zip package, documented at
 | 
				
			||||||
 | 
					http://java.sun.com/developer/technicalArticles/Programming/compression/ .
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A Perl interface to zlib written by Paul Marquess <pmqs@cpan.org> is available
 | 
				
			||||||
 | 
					at CPAN (Comprehensive Perl Archive Network) sites, including
 | 
				
			||||||
 | 
					http://search.cpan.org/~pmqs/IO-Compress-Zlib/ .
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A Python interface to zlib written by A.M. Kuchling <amk@amk.ca> is
 | 
				
			||||||
 | 
					available in Python 1.5 and later versions, see
 | 
				
			||||||
 | 
					http://docs.python.org/library/zlib.html .
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					zlib is built into tcl: http://wiki.tcl.tk/4610 .
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					An experimental package to read and write files in .zip format, written on top
 | 
				
			||||||
 | 
					of zlib by Gilles Vollant <info@winimage.com>, is available in the
 | 
				
			||||||
 | 
					contrib/minizip directory of zlib.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Notes for some targets:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- For Windows DLL versions, please see win32/DLL_FAQ.txt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- For 64-bit Irix, deflate.c must be compiled without any optimization. With
 | 
				
			||||||
 | 
					  -O, one libpng test fails. The test works in 32 bit mode (with the -n32
 | 
				
			||||||
 | 
					  compiler flag). The compiler bug has been reported to SGI.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works
 | 
				
			||||||
 | 
					  when compiled with cc.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- On Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is
 | 
				
			||||||
 | 
					  necessary to get gzprintf working correctly. This is done by configure.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with
 | 
				
			||||||
 | 
					  other compilers. Use "make test" to check your compiler.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- gzdopen is not supported on RISCOS or BEOS.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- For PalmOs, see http://palmzlib.sourceforge.net/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Acknowledgments:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The deflate format used by zlib was defined by Phil Katz.  The deflate and
 | 
				
			||||||
 | 
					  zlib specifications were written by L.  Peter Deutsch.  Thanks to all the
 | 
				
			||||||
 | 
					  people who reported problems and suggested various improvements in zlib; they
 | 
				
			||||||
 | 
					  are too numerous to cite here.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Copyright notice:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 (C) 1995-2017 Jean-loup Gailly and Mark Adler
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  This software is provided 'as-is', without any express or implied
 | 
				
			||||||
 | 
					  warranty.  In no event will the authors be held liable for any damages
 | 
				
			||||||
 | 
					  arising from the use of this software.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Permission is granted to anyone to use this software for any purpose,
 | 
				
			||||||
 | 
					  including commercial applications, and to alter it and redistribute it
 | 
				
			||||||
 | 
					  freely, subject to the following restrictions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  1. The origin of this software must not be misrepresented; you must not
 | 
				
			||||||
 | 
					     claim that you wrote the original software. If you use this software
 | 
				
			||||||
 | 
					     in a product, an acknowledgment in the product documentation would be
 | 
				
			||||||
 | 
					     appreciated but is not required.
 | 
				
			||||||
 | 
					  2. Altered source versions must be plainly marked as such, and must not be
 | 
				
			||||||
 | 
					     misrepresented as being the original software.
 | 
				
			||||||
 | 
					  3. This notice may not be removed or altered from any source distribution.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Jean-loup Gailly        Mark Adler
 | 
				
			||||||
 | 
					  jloup@gzip.org          madler@alumni.caltech.edu
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If you use the zlib library in a product, we would appreciate *not* receiving
 | 
				
			||||||
 | 
					lengthy legal documents to sign.  The sources are provided for free but without
 | 
				
			||||||
 | 
					warranty of any kind.  The library has been entirely written by Jean-loup
 | 
				
			||||||
 | 
					Gailly and Mark Adler; it does not include third-party code.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If you redistribute modified sources, we would appreciate that you include in
 | 
				
			||||||
 | 
					the file ChangeLog history information documenting your changes.  Please read
 | 
				
			||||||
 | 
					the FAQ for more information on the distribution of modified source versions.
 | 
				
			||||||
							
								
								
									
										
											BIN
										
									
								
								third_party/ZLIB-Windows/zlib-1.2.11_deploy_v140/debug_dynamic/x64/bin/zlibd.dll
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								third_party/ZLIB-Windows/zlib-1.2.11_deploy_v140/debug_dynamic/x64/bin/zlibd.dll
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								third_party/ZLIB-Windows/zlib-1.2.11_deploy_v140/debug_dynamic/x64/bin/zlibd.pdb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								third_party/ZLIB-Windows/zlib-1.2.11_deploy_v140/debug_dynamic/x64/bin/zlibd.pdb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								third_party/ZLIB-Windows/zlib-1.2.11_deploy_v140/debug_dynamic/x64/lib/zlibd.exp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								third_party/ZLIB-Windows/zlib-1.2.11_deploy_v140/debug_dynamic/x64/lib/zlibd.exp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								third_party/ZLIB-Windows/zlib-1.2.11_deploy_v140/debug_dynamic/x64/lib/zlibd.ilk
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								third_party/ZLIB-Windows/zlib-1.2.11_deploy_v140/debug_dynamic/x64/lib/zlibd.ilk
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								third_party/ZLIB-Windows/zlib-1.2.11_deploy_v140/debug_dynamic/x64/lib/zlibd.lib
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								third_party/ZLIB-Windows/zlib-1.2.11_deploy_v140/debug_dynamic/x64/lib/zlibd.lib
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										536
									
								
								third_party/ZLIB-Windows/zlib-1.2.11_deploy_v140/include/zconf.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										536
									
								
								third_party/ZLIB-Windows/zlib-1.2.11_deploy_v140/include/zconf.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,536 @@
 | 
				
			|||||||
 | 
					/* zconf.h -- configuration of the zlib compression library
 | 
				
			||||||
 | 
					 * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler
 | 
				
			||||||
 | 
					 * For conditions of distribution and use, see copyright notice in zlib.h
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* @(#) $Id$ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef ZCONF_H
 | 
				
			||||||
 | 
					#define ZCONF_H
 | 
				
			||||||
 | 
					/* #undef Z_PREFIX */
 | 
				
			||||||
 | 
					/* #undef Z_HAVE_UNISTD_H */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * If you *really* need a unique prefix for all types and library functions,
 | 
				
			||||||
 | 
					 * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
 | 
				
			||||||
 | 
					 * Even better than compiling with -DZ_PREFIX would be to use configure to set
 | 
				
			||||||
 | 
					 * this permanently in zconf.h using "./configure --zprefix".
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#ifdef Z_PREFIX     /* may be set to #if 1 by ./configure */
 | 
				
			||||||
 | 
					#  define Z_PREFIX_SET
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* all linked symbols and init macros */
 | 
				
			||||||
 | 
					#  define _dist_code            z__dist_code
 | 
				
			||||||
 | 
					#  define _length_code          z__length_code
 | 
				
			||||||
 | 
					#  define _tr_align             z__tr_align
 | 
				
			||||||
 | 
					#  define _tr_flush_bits        z__tr_flush_bits
 | 
				
			||||||
 | 
					#  define _tr_flush_block       z__tr_flush_block
 | 
				
			||||||
 | 
					#  define _tr_init              z__tr_init
 | 
				
			||||||
 | 
					#  define _tr_stored_block      z__tr_stored_block
 | 
				
			||||||
 | 
					#  define _tr_tally             z__tr_tally
 | 
				
			||||||
 | 
					#  define adler32               z_adler32
 | 
				
			||||||
 | 
					#  define adler32_combine       z_adler32_combine
 | 
				
			||||||
 | 
					#  define adler32_combine64     z_adler32_combine64
 | 
				
			||||||
 | 
					#  define adler32_z             z_adler32_z
 | 
				
			||||||
 | 
					#  ifndef Z_SOLO
 | 
				
			||||||
 | 
					#    define compress              z_compress
 | 
				
			||||||
 | 
					#    define compress2             z_compress2
 | 
				
			||||||
 | 
					#    define compressBound         z_compressBound
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#  define crc32                 z_crc32
 | 
				
			||||||
 | 
					#  define crc32_combine         z_crc32_combine
 | 
				
			||||||
 | 
					#  define crc32_combine64       z_crc32_combine64
 | 
				
			||||||
 | 
					#  define crc32_z               z_crc32_z
 | 
				
			||||||
 | 
					#  define deflate               z_deflate
 | 
				
			||||||
 | 
					#  define deflateBound          z_deflateBound
 | 
				
			||||||
 | 
					#  define deflateCopy           z_deflateCopy
 | 
				
			||||||
 | 
					#  define deflateEnd            z_deflateEnd
 | 
				
			||||||
 | 
					#  define deflateGetDictionary  z_deflateGetDictionary
 | 
				
			||||||
 | 
					#  define deflateInit           z_deflateInit
 | 
				
			||||||
 | 
					#  define deflateInit2          z_deflateInit2
 | 
				
			||||||
 | 
					#  define deflateInit2_         z_deflateInit2_
 | 
				
			||||||
 | 
					#  define deflateInit_          z_deflateInit_
 | 
				
			||||||
 | 
					#  define deflateParams         z_deflateParams
 | 
				
			||||||
 | 
					#  define deflatePending        z_deflatePending
 | 
				
			||||||
 | 
					#  define deflatePrime          z_deflatePrime
 | 
				
			||||||
 | 
					#  define deflateReset          z_deflateReset
 | 
				
			||||||
 | 
					#  define deflateResetKeep      z_deflateResetKeep
 | 
				
			||||||
 | 
					#  define deflateSetDictionary  z_deflateSetDictionary
 | 
				
			||||||
 | 
					#  define deflateSetHeader      z_deflateSetHeader
 | 
				
			||||||
 | 
					#  define deflateTune           z_deflateTune
 | 
				
			||||||
 | 
					#  define deflate_copyright     z_deflate_copyright
 | 
				
			||||||
 | 
					#  define get_crc_table         z_get_crc_table
 | 
				
			||||||
 | 
					#  ifndef Z_SOLO
 | 
				
			||||||
 | 
					#    define gz_error              z_gz_error
 | 
				
			||||||
 | 
					#    define gz_intmax             z_gz_intmax
 | 
				
			||||||
 | 
					#    define gz_strwinerror        z_gz_strwinerror
 | 
				
			||||||
 | 
					#    define gzbuffer              z_gzbuffer
 | 
				
			||||||
 | 
					#    define gzclearerr            z_gzclearerr
 | 
				
			||||||
 | 
					#    define gzclose               z_gzclose
 | 
				
			||||||
 | 
					#    define gzclose_r             z_gzclose_r
 | 
				
			||||||
 | 
					#    define gzclose_w             z_gzclose_w
 | 
				
			||||||
 | 
					#    define gzdirect              z_gzdirect
 | 
				
			||||||
 | 
					#    define gzdopen               z_gzdopen
 | 
				
			||||||
 | 
					#    define gzeof                 z_gzeof
 | 
				
			||||||
 | 
					#    define gzerror               z_gzerror
 | 
				
			||||||
 | 
					#    define gzflush               z_gzflush
 | 
				
			||||||
 | 
					#    define gzfread               z_gzfread
 | 
				
			||||||
 | 
					#    define gzfwrite              z_gzfwrite
 | 
				
			||||||
 | 
					#    define gzgetc                z_gzgetc
 | 
				
			||||||
 | 
					#    define gzgetc_               z_gzgetc_
 | 
				
			||||||
 | 
					#    define gzgets                z_gzgets
 | 
				
			||||||
 | 
					#    define gzoffset              z_gzoffset
 | 
				
			||||||
 | 
					#    define gzoffset64            z_gzoffset64
 | 
				
			||||||
 | 
					#    define gzopen                z_gzopen
 | 
				
			||||||
 | 
					#    define gzopen64              z_gzopen64
 | 
				
			||||||
 | 
					#    ifdef _WIN32
 | 
				
			||||||
 | 
					#      define gzopen_w              z_gzopen_w
 | 
				
			||||||
 | 
					#    endif
 | 
				
			||||||
 | 
					#    define gzprintf              z_gzprintf
 | 
				
			||||||
 | 
					#    define gzputc                z_gzputc
 | 
				
			||||||
 | 
					#    define gzputs                z_gzputs
 | 
				
			||||||
 | 
					#    define gzread                z_gzread
 | 
				
			||||||
 | 
					#    define gzrewind              z_gzrewind
 | 
				
			||||||
 | 
					#    define gzseek                z_gzseek
 | 
				
			||||||
 | 
					#    define gzseek64              z_gzseek64
 | 
				
			||||||
 | 
					#    define gzsetparams           z_gzsetparams
 | 
				
			||||||
 | 
					#    define gztell                z_gztell
 | 
				
			||||||
 | 
					#    define gztell64              z_gztell64
 | 
				
			||||||
 | 
					#    define gzungetc              z_gzungetc
 | 
				
			||||||
 | 
					#    define gzvprintf             z_gzvprintf
 | 
				
			||||||
 | 
					#    define gzwrite               z_gzwrite
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#  define inflate               z_inflate
 | 
				
			||||||
 | 
					#  define inflateBack           z_inflateBack
 | 
				
			||||||
 | 
					#  define inflateBackEnd        z_inflateBackEnd
 | 
				
			||||||
 | 
					#  define inflateBackInit       z_inflateBackInit
 | 
				
			||||||
 | 
					#  define inflateBackInit_      z_inflateBackInit_
 | 
				
			||||||
 | 
					#  define inflateCodesUsed      z_inflateCodesUsed
 | 
				
			||||||
 | 
					#  define inflateCopy           z_inflateCopy
 | 
				
			||||||
 | 
					#  define inflateEnd            z_inflateEnd
 | 
				
			||||||
 | 
					#  define inflateGetDictionary  z_inflateGetDictionary
 | 
				
			||||||
 | 
					#  define inflateGetHeader      z_inflateGetHeader
 | 
				
			||||||
 | 
					#  define inflateInit           z_inflateInit
 | 
				
			||||||
 | 
					#  define inflateInit2          z_inflateInit2
 | 
				
			||||||
 | 
					#  define inflateInit2_         z_inflateInit2_
 | 
				
			||||||
 | 
					#  define inflateInit_          z_inflateInit_
 | 
				
			||||||
 | 
					#  define inflateMark           z_inflateMark
 | 
				
			||||||
 | 
					#  define inflatePrime          z_inflatePrime
 | 
				
			||||||
 | 
					#  define inflateReset          z_inflateReset
 | 
				
			||||||
 | 
					#  define inflateReset2         z_inflateReset2
 | 
				
			||||||
 | 
					#  define inflateResetKeep      z_inflateResetKeep
 | 
				
			||||||
 | 
					#  define inflateSetDictionary  z_inflateSetDictionary
 | 
				
			||||||
 | 
					#  define inflateSync           z_inflateSync
 | 
				
			||||||
 | 
					#  define inflateSyncPoint      z_inflateSyncPoint
 | 
				
			||||||
 | 
					#  define inflateUndermine      z_inflateUndermine
 | 
				
			||||||
 | 
					#  define inflateValidate       z_inflateValidate
 | 
				
			||||||
 | 
					#  define inflate_copyright     z_inflate_copyright
 | 
				
			||||||
 | 
					#  define inflate_fast          z_inflate_fast
 | 
				
			||||||
 | 
					#  define inflate_table         z_inflate_table
 | 
				
			||||||
 | 
					#  ifndef Z_SOLO
 | 
				
			||||||
 | 
					#    define uncompress            z_uncompress
 | 
				
			||||||
 | 
					#    define uncompress2           z_uncompress2
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#  define zError                z_zError
 | 
				
			||||||
 | 
					#  ifndef Z_SOLO
 | 
				
			||||||
 | 
					#    define zcalloc               z_zcalloc
 | 
				
			||||||
 | 
					#    define zcfree                z_zcfree
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#  define zlibCompileFlags      z_zlibCompileFlags
 | 
				
			||||||
 | 
					#  define zlibVersion           z_zlibVersion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* all zlib typedefs in zlib.h and zconf.h */
 | 
				
			||||||
 | 
					#  define Byte                  z_Byte
 | 
				
			||||||
 | 
					#  define Bytef                 z_Bytef
 | 
				
			||||||
 | 
					#  define alloc_func            z_alloc_func
 | 
				
			||||||
 | 
					#  define charf                 z_charf
 | 
				
			||||||
 | 
					#  define free_func             z_free_func
 | 
				
			||||||
 | 
					#  ifndef Z_SOLO
 | 
				
			||||||
 | 
					#    define gzFile                z_gzFile
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#  define gz_header             z_gz_header
 | 
				
			||||||
 | 
					#  define gz_headerp            z_gz_headerp
 | 
				
			||||||
 | 
					#  define in_func               z_in_func
 | 
				
			||||||
 | 
					#  define intf                  z_intf
 | 
				
			||||||
 | 
					#  define out_func              z_out_func
 | 
				
			||||||
 | 
					#  define uInt                  z_uInt
 | 
				
			||||||
 | 
					#  define uIntf                 z_uIntf
 | 
				
			||||||
 | 
					#  define uLong                 z_uLong
 | 
				
			||||||
 | 
					#  define uLongf                z_uLongf
 | 
				
			||||||
 | 
					#  define voidp                 z_voidp
 | 
				
			||||||
 | 
					#  define voidpc                z_voidpc
 | 
				
			||||||
 | 
					#  define voidpf                z_voidpf
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* all zlib structs in zlib.h and zconf.h */
 | 
				
			||||||
 | 
					#  define gz_header_s           z_gz_header_s
 | 
				
			||||||
 | 
					#  define internal_state        z_internal_state
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(__MSDOS__) && !defined(MSDOS)
 | 
				
			||||||
 | 
					#  define MSDOS
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
 | 
				
			||||||
 | 
					#  define OS2
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#if defined(_WINDOWS) && !defined(WINDOWS)
 | 
				
			||||||
 | 
					#  define WINDOWS
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
 | 
				
			||||||
 | 
					#  ifndef WIN32
 | 
				
			||||||
 | 
					#    define WIN32
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
 | 
				
			||||||
 | 
					#  if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
 | 
				
			||||||
 | 
					#    ifndef SYS16BIT
 | 
				
			||||||
 | 
					#      define SYS16BIT
 | 
				
			||||||
 | 
					#    endif
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
 | 
				
			||||||
 | 
					 * than 64k bytes at a time (needed on systems with 16-bit int).
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#ifdef SYS16BIT
 | 
				
			||||||
 | 
					#  define MAXSEG_64K
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef MSDOS
 | 
				
			||||||
 | 
					#  define UNALIGNED_OK
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __STDC_VERSION__
 | 
				
			||||||
 | 
					#  ifndef STDC
 | 
				
			||||||
 | 
					#    define STDC
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#  if __STDC_VERSION__ >= 199901L
 | 
				
			||||||
 | 
					#    ifndef STDC99
 | 
				
			||||||
 | 
					#      define STDC99
 | 
				
			||||||
 | 
					#    endif
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
 | 
				
			||||||
 | 
					#  define STDC
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
 | 
				
			||||||
 | 
					#  define STDC
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
 | 
				
			||||||
 | 
					#  define STDC
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
 | 
				
			||||||
 | 
					#  define STDC
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(__OS400__) && !defined(STDC)    /* iSeries (formerly AS/400). */
 | 
				
			||||||
 | 
					#  define STDC
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef STDC
 | 
				
			||||||
 | 
					#  ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
 | 
				
			||||||
 | 
					#    define const       /* note: need a more gentle solution here */
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(ZLIB_CONST) && !defined(z_const)
 | 
				
			||||||
 | 
					#  define z_const const
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#  define z_const
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef Z_SOLO
 | 
				
			||||||
 | 
					   typedef unsigned long z_size_t;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#  define z_longlong long long
 | 
				
			||||||
 | 
					#  if defined(NO_SIZE_T)
 | 
				
			||||||
 | 
					     typedef unsigned NO_SIZE_T z_size_t;
 | 
				
			||||||
 | 
					#  elif defined(STDC)
 | 
				
			||||||
 | 
					#    include <stddef.h>
 | 
				
			||||||
 | 
					     typedef size_t z_size_t;
 | 
				
			||||||
 | 
					#  else
 | 
				
			||||||
 | 
					     typedef unsigned long z_size_t;
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#  undef z_longlong
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Maximum value for memLevel in deflateInit2 */
 | 
				
			||||||
 | 
					#ifndef MAX_MEM_LEVEL
 | 
				
			||||||
 | 
					#  ifdef MAXSEG_64K
 | 
				
			||||||
 | 
					#    define MAX_MEM_LEVEL 8
 | 
				
			||||||
 | 
					#  else
 | 
				
			||||||
 | 
					#    define MAX_MEM_LEVEL 9
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Maximum value for windowBits in deflateInit2 and inflateInit2.
 | 
				
			||||||
 | 
					 * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
 | 
				
			||||||
 | 
					 * created by gzip. (Files created by minigzip can still be extracted by
 | 
				
			||||||
 | 
					 * gzip.)
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#ifndef MAX_WBITS
 | 
				
			||||||
 | 
					#  define MAX_WBITS   15 /* 32K LZ77 window */
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* The memory requirements for deflate are (in bytes):
 | 
				
			||||||
 | 
					            (1 << (windowBits+2)) +  (1 << (memLevel+9))
 | 
				
			||||||
 | 
					 that is: 128K for windowBits=15  +  128K for memLevel = 8  (default values)
 | 
				
			||||||
 | 
					 plus a few kilobytes for small objects. For example, if you want to reduce
 | 
				
			||||||
 | 
					 the default memory requirements from 256K to 128K, compile with
 | 
				
			||||||
 | 
					     make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
 | 
				
			||||||
 | 
					 Of course this will generally degrade compression (there's no free lunch).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   The memory requirements for inflate are (in bytes) 1 << windowBits
 | 
				
			||||||
 | 
					 that is, 32K for windowBits=15 (default value) plus about 7 kilobytes
 | 
				
			||||||
 | 
					 for small objects.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        /* Type declarations */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef OF /* function prototypes */
 | 
				
			||||||
 | 
					#  ifdef STDC
 | 
				
			||||||
 | 
					#    define OF(args)  args
 | 
				
			||||||
 | 
					#  else
 | 
				
			||||||
 | 
					#    define OF(args)  ()
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef Z_ARG /* function prototypes for stdarg */
 | 
				
			||||||
 | 
					#  if defined(STDC) || defined(Z_HAVE_STDARG_H)
 | 
				
			||||||
 | 
					#    define Z_ARG(args)  args
 | 
				
			||||||
 | 
					#  else
 | 
				
			||||||
 | 
					#    define Z_ARG(args)  ()
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* The following definitions for FAR are needed only for MSDOS mixed
 | 
				
			||||||
 | 
					 * model programming (small or medium model with some far allocations).
 | 
				
			||||||
 | 
					 * This was tested only with MSC; for other MSDOS compilers you may have
 | 
				
			||||||
 | 
					 * to define NO_MEMCPY in zutil.h.  If you don't need the mixed model,
 | 
				
			||||||
 | 
					 * just define FAR to be empty.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#ifdef SYS16BIT
 | 
				
			||||||
 | 
					#  if defined(M_I86SM) || defined(M_I86MM)
 | 
				
			||||||
 | 
					     /* MSC small or medium model */
 | 
				
			||||||
 | 
					#    define SMALL_MEDIUM
 | 
				
			||||||
 | 
					#    ifdef _MSC_VER
 | 
				
			||||||
 | 
					#      define FAR _far
 | 
				
			||||||
 | 
					#    else
 | 
				
			||||||
 | 
					#      define FAR far
 | 
				
			||||||
 | 
					#    endif
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#  if (defined(__SMALL__) || defined(__MEDIUM__))
 | 
				
			||||||
 | 
					     /* Turbo C small or medium model */
 | 
				
			||||||
 | 
					#    define SMALL_MEDIUM
 | 
				
			||||||
 | 
					#    ifdef __BORLANDC__
 | 
				
			||||||
 | 
					#      define FAR _far
 | 
				
			||||||
 | 
					#    else
 | 
				
			||||||
 | 
					#      define FAR far
 | 
				
			||||||
 | 
					#    endif
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(WINDOWS) || defined(WIN32)
 | 
				
			||||||
 | 
					   /* If building or using zlib as a DLL, define ZLIB_DLL.
 | 
				
			||||||
 | 
					    * This is not mandatory, but it offers a little performance increase.
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					#  ifdef ZLIB_DLL
 | 
				
			||||||
 | 
					#    if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
 | 
				
			||||||
 | 
					#      ifdef ZLIB_INTERNAL
 | 
				
			||||||
 | 
					#        define ZEXTERN extern __declspec(dllexport)
 | 
				
			||||||
 | 
					#      else
 | 
				
			||||||
 | 
					#        define ZEXTERN extern __declspec(dllimport)
 | 
				
			||||||
 | 
					#      endif
 | 
				
			||||||
 | 
					#    endif
 | 
				
			||||||
 | 
					#  endif  /* ZLIB_DLL */
 | 
				
			||||||
 | 
					   /* If building or using zlib with the WINAPI/WINAPIV calling convention,
 | 
				
			||||||
 | 
					    * define ZLIB_WINAPI.
 | 
				
			||||||
 | 
					    * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					#  ifdef ZLIB_WINAPI
 | 
				
			||||||
 | 
					#    ifdef FAR
 | 
				
			||||||
 | 
					#      undef FAR
 | 
				
			||||||
 | 
					#    endif
 | 
				
			||||||
 | 
					#    include <windows.h>
 | 
				
			||||||
 | 
					     /* No need for _export, use ZLIB.DEF instead. */
 | 
				
			||||||
 | 
					     /* For complete Windows compatibility, use WINAPI, not __stdcall. */
 | 
				
			||||||
 | 
					#    define ZEXPORT WINAPI
 | 
				
			||||||
 | 
					#    ifdef WIN32
 | 
				
			||||||
 | 
					#      define ZEXPORTVA WINAPIV
 | 
				
			||||||
 | 
					#    else
 | 
				
			||||||
 | 
					#      define ZEXPORTVA FAR CDECL
 | 
				
			||||||
 | 
					#    endif
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined (__BEOS__)
 | 
				
			||||||
 | 
					#  ifdef ZLIB_DLL
 | 
				
			||||||
 | 
					#    ifdef ZLIB_INTERNAL
 | 
				
			||||||
 | 
					#      define ZEXPORT   __declspec(dllexport)
 | 
				
			||||||
 | 
					#      define ZEXPORTVA __declspec(dllexport)
 | 
				
			||||||
 | 
					#    else
 | 
				
			||||||
 | 
					#      define ZEXPORT   __declspec(dllimport)
 | 
				
			||||||
 | 
					#      define ZEXPORTVA __declspec(dllimport)
 | 
				
			||||||
 | 
					#    endif
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef ZEXTERN
 | 
				
			||||||
 | 
					#  define ZEXTERN extern
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifndef ZEXPORT
 | 
				
			||||||
 | 
					#  define ZEXPORT
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifndef ZEXPORTVA
 | 
				
			||||||
 | 
					#  define ZEXPORTVA
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef FAR
 | 
				
			||||||
 | 
					#  define FAR
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if !defined(__MACTYPES__)
 | 
				
			||||||
 | 
					typedef unsigned char  Byte;  /* 8 bits */
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					typedef unsigned int   uInt;  /* 16 bits or more */
 | 
				
			||||||
 | 
					typedef unsigned long  uLong; /* 32 bits or more */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef SMALL_MEDIUM
 | 
				
			||||||
 | 
					   /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
 | 
				
			||||||
 | 
					#  define Bytef Byte FAR
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					   typedef Byte  FAR Bytef;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					typedef char  FAR charf;
 | 
				
			||||||
 | 
					typedef int   FAR intf;
 | 
				
			||||||
 | 
					typedef uInt  FAR uIntf;
 | 
				
			||||||
 | 
					typedef uLong FAR uLongf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef STDC
 | 
				
			||||||
 | 
					   typedef void const *voidpc;
 | 
				
			||||||
 | 
					   typedef void FAR   *voidpf;
 | 
				
			||||||
 | 
					   typedef void       *voidp;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					   typedef Byte const *voidpc;
 | 
				
			||||||
 | 
					   typedef Byte FAR   *voidpf;
 | 
				
			||||||
 | 
					   typedef Byte       *voidp;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC)
 | 
				
			||||||
 | 
					#  include <limits.h>
 | 
				
			||||||
 | 
					#  if (UINT_MAX == 0xffffffffUL)
 | 
				
			||||||
 | 
					#    define Z_U4 unsigned
 | 
				
			||||||
 | 
					#  elif (ULONG_MAX == 0xffffffffUL)
 | 
				
			||||||
 | 
					#    define Z_U4 unsigned long
 | 
				
			||||||
 | 
					#  elif (USHRT_MAX == 0xffffffffUL)
 | 
				
			||||||
 | 
					#    define Z_U4 unsigned short
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef Z_U4
 | 
				
			||||||
 | 
					   typedef Z_U4 z_crc_t;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					   typedef unsigned long z_crc_t;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef HAVE_UNISTD_H    /* may be set to #if 1 by ./configure */
 | 
				
			||||||
 | 
					#  define Z_HAVE_UNISTD_H
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef HAVE_STDARG_H    /* may be set to #if 1 by ./configure */
 | 
				
			||||||
 | 
					#  define Z_HAVE_STDARG_H
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef STDC
 | 
				
			||||||
 | 
					#  ifndef Z_SOLO
 | 
				
			||||||
 | 
					#    include <sys/types.h>      /* for off_t */
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(STDC) || defined(Z_HAVE_STDARG_H)
 | 
				
			||||||
 | 
					#  ifndef Z_SOLO
 | 
				
			||||||
 | 
					#    include <stdarg.h>         /* for va_list */
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef _WIN32
 | 
				
			||||||
 | 
					#  ifndef Z_SOLO
 | 
				
			||||||
 | 
					#    include <stddef.h>         /* for wchar_t */
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and
 | 
				
			||||||
 | 
					 * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even
 | 
				
			||||||
 | 
					 * though the former does not conform to the LFS document), but considering
 | 
				
			||||||
 | 
					 * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as
 | 
				
			||||||
 | 
					 * equivalently requesting no 64-bit operations
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1
 | 
				
			||||||
 | 
					#  undef _LARGEFILE64_SOURCE
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H)
 | 
				
			||||||
 | 
					#  define Z_HAVE_UNISTD_H
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifndef Z_SOLO
 | 
				
			||||||
 | 
					#  if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE)
 | 
				
			||||||
 | 
					#    include <unistd.h>         /* for SEEK_*, off_t, and _LFS64_LARGEFILE */
 | 
				
			||||||
 | 
					#    ifdef VMS
 | 
				
			||||||
 | 
					#      include <unixio.h>       /* for off_t */
 | 
				
			||||||
 | 
					#    endif
 | 
				
			||||||
 | 
					#    ifndef z_off_t
 | 
				
			||||||
 | 
					#      define z_off_t off_t
 | 
				
			||||||
 | 
					#    endif
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0
 | 
				
			||||||
 | 
					#  define Z_LFS64
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64)
 | 
				
			||||||
 | 
					#  define Z_LARGE64
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64)
 | 
				
			||||||
 | 
					#  define Z_WANT64
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if !defined(SEEK_SET) && !defined(Z_SOLO)
 | 
				
			||||||
 | 
					#  define SEEK_SET        0       /* Seek from beginning of file.  */
 | 
				
			||||||
 | 
					#  define SEEK_CUR        1       /* Seek from current position.  */
 | 
				
			||||||
 | 
					#  define SEEK_END        2       /* Set file pointer to EOF plus "offset" */
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef z_off_t
 | 
				
			||||||
 | 
					#  define z_off_t long
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if !defined(_WIN32) && defined(Z_LARGE64)
 | 
				
			||||||
 | 
					#  define z_off64_t off64_t
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#  if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO)
 | 
				
			||||||
 | 
					#    define z_off64_t __int64
 | 
				
			||||||
 | 
					#  else
 | 
				
			||||||
 | 
					#    define z_off64_t z_off_t
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* MVS linker does not support external names larger than 8 bytes */
 | 
				
			||||||
 | 
					#if defined(__MVS__)
 | 
				
			||||||
 | 
					  #pragma map(deflateInit_,"DEIN")
 | 
				
			||||||
 | 
					  #pragma map(deflateInit2_,"DEIN2")
 | 
				
			||||||
 | 
					  #pragma map(deflateEnd,"DEEND")
 | 
				
			||||||
 | 
					  #pragma map(deflateBound,"DEBND")
 | 
				
			||||||
 | 
					  #pragma map(inflateInit_,"ININ")
 | 
				
			||||||
 | 
					  #pragma map(inflateInit2_,"ININ2")
 | 
				
			||||||
 | 
					  #pragma map(inflateEnd,"INEND")
 | 
				
			||||||
 | 
					  #pragma map(inflateSync,"INSY")
 | 
				
			||||||
 | 
					  #pragma map(inflateSetDictionary,"INSEDI")
 | 
				
			||||||
 | 
					  #pragma map(compressBound,"CMBND")
 | 
				
			||||||
 | 
					  #pragma map(inflate_table,"INTABL")
 | 
				
			||||||
 | 
					  #pragma map(inflate_fast,"INFA")
 | 
				
			||||||
 | 
					  #pragma map(inflate_copyright,"INCOPY")
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* ZCONF_H */
 | 
				
			||||||
							
								
								
									
										1912
									
								
								third_party/ZLIB-Windows/zlib-1.2.11_deploy_v140/include/zlib.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1912
									
								
								third_party/ZLIB-Windows/zlib-1.2.11_deploy_v140/include/zlib.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								third_party/ZLIB-Windows/zlib-1.2.11_deploy_v140/release_dynamic/x64/bin/zlib.dll
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								third_party/ZLIB-Windows/zlib-1.2.11_deploy_v140/release_dynamic/x64/bin/zlib.dll
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								third_party/ZLIB-Windows/zlib-1.2.11_deploy_v140/release_dynamic/x64/lib/zlib.exp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								third_party/ZLIB-Windows/zlib-1.2.11_deploy_v140/release_dynamic/x64/lib/zlib.exp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								third_party/ZLIB-Windows/zlib-1.2.11_deploy_v140/release_dynamic/x64/lib/zlib.lib
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								third_party/ZLIB-Windows/zlib-1.2.11_deploy_v140/release_dynamic/x64/lib/zlib.lib
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								third_party/ZLIB-Windows/zlibwapi-1.2.11_deploy_v140/debug_dynamic/x64/bin/zlibd.dll
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								third_party/ZLIB-Windows/zlibwapi-1.2.11_deploy_v140/debug_dynamic/x64/bin/zlibd.dll
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								third_party/ZLIB-Windows/zlibwapi-1.2.11_deploy_v140/debug_dynamic/x64/bin/zlibd.pdb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								third_party/ZLIB-Windows/zlibwapi-1.2.11_deploy_v140/debug_dynamic/x64/bin/zlibd.pdb
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								third_party/ZLIB-Windows/zlibwapi-1.2.11_deploy_v140/debug_dynamic/x64/lib/zlibd.exp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								third_party/ZLIB-Windows/zlibwapi-1.2.11_deploy_v140/debug_dynamic/x64/lib/zlibd.exp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								third_party/ZLIB-Windows/zlibwapi-1.2.11_deploy_v140/debug_dynamic/x64/lib/zlibd.ilk
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								third_party/ZLIB-Windows/zlibwapi-1.2.11_deploy_v140/debug_dynamic/x64/lib/zlibd.ilk
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								third_party/ZLIB-Windows/zlibwapi-1.2.11_deploy_v140/debug_dynamic/x64/lib/zlibd.lib
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								third_party/ZLIB-Windows/zlibwapi-1.2.11_deploy_v140/debug_dynamic/x64/lib/zlibd.lib
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										536
									
								
								third_party/ZLIB-Windows/zlibwapi-1.2.11_deploy_v140/include/zconf.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										536
									
								
								third_party/ZLIB-Windows/zlibwapi-1.2.11_deploy_v140/include/zconf.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,536 @@
 | 
				
			|||||||
 | 
					/* zconf.h -- configuration of the zlib compression library
 | 
				
			||||||
 | 
					 * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler
 | 
				
			||||||
 | 
					 * For conditions of distribution and use, see copyright notice in zlib.h
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* @(#) $Id$ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef ZCONF_H
 | 
				
			||||||
 | 
					#define ZCONF_H
 | 
				
			||||||
 | 
					/* #undef Z_PREFIX */
 | 
				
			||||||
 | 
					/* #undef Z_HAVE_UNISTD_H */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * If you *really* need a unique prefix for all types and library functions,
 | 
				
			||||||
 | 
					 * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
 | 
				
			||||||
 | 
					 * Even better than compiling with -DZ_PREFIX would be to use configure to set
 | 
				
			||||||
 | 
					 * this permanently in zconf.h using "./configure --zprefix".
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#ifdef Z_PREFIX     /* may be set to #if 1 by ./configure */
 | 
				
			||||||
 | 
					#  define Z_PREFIX_SET
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* all linked symbols and init macros */
 | 
				
			||||||
 | 
					#  define _dist_code            z__dist_code
 | 
				
			||||||
 | 
					#  define _length_code          z__length_code
 | 
				
			||||||
 | 
					#  define _tr_align             z__tr_align
 | 
				
			||||||
 | 
					#  define _tr_flush_bits        z__tr_flush_bits
 | 
				
			||||||
 | 
					#  define _tr_flush_block       z__tr_flush_block
 | 
				
			||||||
 | 
					#  define _tr_init              z__tr_init
 | 
				
			||||||
 | 
					#  define _tr_stored_block      z__tr_stored_block
 | 
				
			||||||
 | 
					#  define _tr_tally             z__tr_tally
 | 
				
			||||||
 | 
					#  define adler32               z_adler32
 | 
				
			||||||
 | 
					#  define adler32_combine       z_adler32_combine
 | 
				
			||||||
 | 
					#  define adler32_combine64     z_adler32_combine64
 | 
				
			||||||
 | 
					#  define adler32_z             z_adler32_z
 | 
				
			||||||
 | 
					#  ifndef Z_SOLO
 | 
				
			||||||
 | 
					#    define compress              z_compress
 | 
				
			||||||
 | 
					#    define compress2             z_compress2
 | 
				
			||||||
 | 
					#    define compressBound         z_compressBound
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#  define crc32                 z_crc32
 | 
				
			||||||
 | 
					#  define crc32_combine         z_crc32_combine
 | 
				
			||||||
 | 
					#  define crc32_combine64       z_crc32_combine64
 | 
				
			||||||
 | 
					#  define crc32_z               z_crc32_z
 | 
				
			||||||
 | 
					#  define deflate               z_deflate
 | 
				
			||||||
 | 
					#  define deflateBound          z_deflateBound
 | 
				
			||||||
 | 
					#  define deflateCopy           z_deflateCopy
 | 
				
			||||||
 | 
					#  define deflateEnd            z_deflateEnd
 | 
				
			||||||
 | 
					#  define deflateGetDictionary  z_deflateGetDictionary
 | 
				
			||||||
 | 
					#  define deflateInit           z_deflateInit
 | 
				
			||||||
 | 
					#  define deflateInit2          z_deflateInit2
 | 
				
			||||||
 | 
					#  define deflateInit2_         z_deflateInit2_
 | 
				
			||||||
 | 
					#  define deflateInit_          z_deflateInit_
 | 
				
			||||||
 | 
					#  define deflateParams         z_deflateParams
 | 
				
			||||||
 | 
					#  define deflatePending        z_deflatePending
 | 
				
			||||||
 | 
					#  define deflatePrime          z_deflatePrime
 | 
				
			||||||
 | 
					#  define deflateReset          z_deflateReset
 | 
				
			||||||
 | 
					#  define deflateResetKeep      z_deflateResetKeep
 | 
				
			||||||
 | 
					#  define deflateSetDictionary  z_deflateSetDictionary
 | 
				
			||||||
 | 
					#  define deflateSetHeader      z_deflateSetHeader
 | 
				
			||||||
 | 
					#  define deflateTune           z_deflateTune
 | 
				
			||||||
 | 
					#  define deflate_copyright     z_deflate_copyright
 | 
				
			||||||
 | 
					#  define get_crc_table         z_get_crc_table
 | 
				
			||||||
 | 
					#  ifndef Z_SOLO
 | 
				
			||||||
 | 
					#    define gz_error              z_gz_error
 | 
				
			||||||
 | 
					#    define gz_intmax             z_gz_intmax
 | 
				
			||||||
 | 
					#    define gz_strwinerror        z_gz_strwinerror
 | 
				
			||||||
 | 
					#    define gzbuffer              z_gzbuffer
 | 
				
			||||||
 | 
					#    define gzclearerr            z_gzclearerr
 | 
				
			||||||
 | 
					#    define gzclose               z_gzclose
 | 
				
			||||||
 | 
					#    define gzclose_r             z_gzclose_r
 | 
				
			||||||
 | 
					#    define gzclose_w             z_gzclose_w
 | 
				
			||||||
 | 
					#    define gzdirect              z_gzdirect
 | 
				
			||||||
 | 
					#    define gzdopen               z_gzdopen
 | 
				
			||||||
 | 
					#    define gzeof                 z_gzeof
 | 
				
			||||||
 | 
					#    define gzerror               z_gzerror
 | 
				
			||||||
 | 
					#    define gzflush               z_gzflush
 | 
				
			||||||
 | 
					#    define gzfread               z_gzfread
 | 
				
			||||||
 | 
					#    define gzfwrite              z_gzfwrite
 | 
				
			||||||
 | 
					#    define gzgetc                z_gzgetc
 | 
				
			||||||
 | 
					#    define gzgetc_               z_gzgetc_
 | 
				
			||||||
 | 
					#    define gzgets                z_gzgets
 | 
				
			||||||
 | 
					#    define gzoffset              z_gzoffset
 | 
				
			||||||
 | 
					#    define gzoffset64            z_gzoffset64
 | 
				
			||||||
 | 
					#    define gzopen                z_gzopen
 | 
				
			||||||
 | 
					#    define gzopen64              z_gzopen64
 | 
				
			||||||
 | 
					#    ifdef _WIN32
 | 
				
			||||||
 | 
					#      define gzopen_w              z_gzopen_w
 | 
				
			||||||
 | 
					#    endif
 | 
				
			||||||
 | 
					#    define gzprintf              z_gzprintf
 | 
				
			||||||
 | 
					#    define gzputc                z_gzputc
 | 
				
			||||||
 | 
					#    define gzputs                z_gzputs
 | 
				
			||||||
 | 
					#    define gzread                z_gzread
 | 
				
			||||||
 | 
					#    define gzrewind              z_gzrewind
 | 
				
			||||||
 | 
					#    define gzseek                z_gzseek
 | 
				
			||||||
 | 
					#    define gzseek64              z_gzseek64
 | 
				
			||||||
 | 
					#    define gzsetparams           z_gzsetparams
 | 
				
			||||||
 | 
					#    define gztell                z_gztell
 | 
				
			||||||
 | 
					#    define gztell64              z_gztell64
 | 
				
			||||||
 | 
					#    define gzungetc              z_gzungetc
 | 
				
			||||||
 | 
					#    define gzvprintf             z_gzvprintf
 | 
				
			||||||
 | 
					#    define gzwrite               z_gzwrite
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#  define inflate               z_inflate
 | 
				
			||||||
 | 
					#  define inflateBack           z_inflateBack
 | 
				
			||||||
 | 
					#  define inflateBackEnd        z_inflateBackEnd
 | 
				
			||||||
 | 
					#  define inflateBackInit       z_inflateBackInit
 | 
				
			||||||
 | 
					#  define inflateBackInit_      z_inflateBackInit_
 | 
				
			||||||
 | 
					#  define inflateCodesUsed      z_inflateCodesUsed
 | 
				
			||||||
 | 
					#  define inflateCopy           z_inflateCopy
 | 
				
			||||||
 | 
					#  define inflateEnd            z_inflateEnd
 | 
				
			||||||
 | 
					#  define inflateGetDictionary  z_inflateGetDictionary
 | 
				
			||||||
 | 
					#  define inflateGetHeader      z_inflateGetHeader
 | 
				
			||||||
 | 
					#  define inflateInit           z_inflateInit
 | 
				
			||||||
 | 
					#  define inflateInit2          z_inflateInit2
 | 
				
			||||||
 | 
					#  define inflateInit2_         z_inflateInit2_
 | 
				
			||||||
 | 
					#  define inflateInit_          z_inflateInit_
 | 
				
			||||||
 | 
					#  define inflateMark           z_inflateMark
 | 
				
			||||||
 | 
					#  define inflatePrime          z_inflatePrime
 | 
				
			||||||
 | 
					#  define inflateReset          z_inflateReset
 | 
				
			||||||
 | 
					#  define inflateReset2         z_inflateReset2
 | 
				
			||||||
 | 
					#  define inflateResetKeep      z_inflateResetKeep
 | 
				
			||||||
 | 
					#  define inflateSetDictionary  z_inflateSetDictionary
 | 
				
			||||||
 | 
					#  define inflateSync           z_inflateSync
 | 
				
			||||||
 | 
					#  define inflateSyncPoint      z_inflateSyncPoint
 | 
				
			||||||
 | 
					#  define inflateUndermine      z_inflateUndermine
 | 
				
			||||||
 | 
					#  define inflateValidate       z_inflateValidate
 | 
				
			||||||
 | 
					#  define inflate_copyright     z_inflate_copyright
 | 
				
			||||||
 | 
					#  define inflate_fast          z_inflate_fast
 | 
				
			||||||
 | 
					#  define inflate_table         z_inflate_table
 | 
				
			||||||
 | 
					#  ifndef Z_SOLO
 | 
				
			||||||
 | 
					#    define uncompress            z_uncompress
 | 
				
			||||||
 | 
					#    define uncompress2           z_uncompress2
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#  define zError                z_zError
 | 
				
			||||||
 | 
					#  ifndef Z_SOLO
 | 
				
			||||||
 | 
					#    define zcalloc               z_zcalloc
 | 
				
			||||||
 | 
					#    define zcfree                z_zcfree
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#  define zlibCompileFlags      z_zlibCompileFlags
 | 
				
			||||||
 | 
					#  define zlibVersion           z_zlibVersion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* all zlib typedefs in zlib.h and zconf.h */
 | 
				
			||||||
 | 
					#  define Byte                  z_Byte
 | 
				
			||||||
 | 
					#  define Bytef                 z_Bytef
 | 
				
			||||||
 | 
					#  define alloc_func            z_alloc_func
 | 
				
			||||||
 | 
					#  define charf                 z_charf
 | 
				
			||||||
 | 
					#  define free_func             z_free_func
 | 
				
			||||||
 | 
					#  ifndef Z_SOLO
 | 
				
			||||||
 | 
					#    define gzFile                z_gzFile
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#  define gz_header             z_gz_header
 | 
				
			||||||
 | 
					#  define gz_headerp            z_gz_headerp
 | 
				
			||||||
 | 
					#  define in_func               z_in_func
 | 
				
			||||||
 | 
					#  define intf                  z_intf
 | 
				
			||||||
 | 
					#  define out_func              z_out_func
 | 
				
			||||||
 | 
					#  define uInt                  z_uInt
 | 
				
			||||||
 | 
					#  define uIntf                 z_uIntf
 | 
				
			||||||
 | 
					#  define uLong                 z_uLong
 | 
				
			||||||
 | 
					#  define uLongf                z_uLongf
 | 
				
			||||||
 | 
					#  define voidp                 z_voidp
 | 
				
			||||||
 | 
					#  define voidpc                z_voidpc
 | 
				
			||||||
 | 
					#  define voidpf                z_voidpf
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* all zlib structs in zlib.h and zconf.h */
 | 
				
			||||||
 | 
					#  define gz_header_s           z_gz_header_s
 | 
				
			||||||
 | 
					#  define internal_state        z_internal_state
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(__MSDOS__) && !defined(MSDOS)
 | 
				
			||||||
 | 
					#  define MSDOS
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
 | 
				
			||||||
 | 
					#  define OS2
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#if defined(_WINDOWS) && !defined(WINDOWS)
 | 
				
			||||||
 | 
					#  define WINDOWS
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
 | 
				
			||||||
 | 
					#  ifndef WIN32
 | 
				
			||||||
 | 
					#    define WIN32
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
 | 
				
			||||||
 | 
					#  if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
 | 
				
			||||||
 | 
					#    ifndef SYS16BIT
 | 
				
			||||||
 | 
					#      define SYS16BIT
 | 
				
			||||||
 | 
					#    endif
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
 | 
				
			||||||
 | 
					 * than 64k bytes at a time (needed on systems with 16-bit int).
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#ifdef SYS16BIT
 | 
				
			||||||
 | 
					#  define MAXSEG_64K
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef MSDOS
 | 
				
			||||||
 | 
					#  define UNALIGNED_OK
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __STDC_VERSION__
 | 
				
			||||||
 | 
					#  ifndef STDC
 | 
				
			||||||
 | 
					#    define STDC
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#  if __STDC_VERSION__ >= 199901L
 | 
				
			||||||
 | 
					#    ifndef STDC99
 | 
				
			||||||
 | 
					#      define STDC99
 | 
				
			||||||
 | 
					#    endif
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
 | 
				
			||||||
 | 
					#  define STDC
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
 | 
				
			||||||
 | 
					#  define STDC
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
 | 
				
			||||||
 | 
					#  define STDC
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
 | 
				
			||||||
 | 
					#  define STDC
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(__OS400__) && !defined(STDC)    /* iSeries (formerly AS/400). */
 | 
				
			||||||
 | 
					#  define STDC
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef STDC
 | 
				
			||||||
 | 
					#  ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
 | 
				
			||||||
 | 
					#    define const       /* note: need a more gentle solution here */
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(ZLIB_CONST) && !defined(z_const)
 | 
				
			||||||
 | 
					#  define z_const const
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#  define z_const
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef Z_SOLO
 | 
				
			||||||
 | 
					   typedef unsigned long z_size_t;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#  define z_longlong long long
 | 
				
			||||||
 | 
					#  if defined(NO_SIZE_T)
 | 
				
			||||||
 | 
					     typedef unsigned NO_SIZE_T z_size_t;
 | 
				
			||||||
 | 
					#  elif defined(STDC)
 | 
				
			||||||
 | 
					#    include <stddef.h>
 | 
				
			||||||
 | 
					     typedef size_t z_size_t;
 | 
				
			||||||
 | 
					#  else
 | 
				
			||||||
 | 
					     typedef unsigned long z_size_t;
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#  undef z_longlong
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Maximum value for memLevel in deflateInit2 */
 | 
				
			||||||
 | 
					#ifndef MAX_MEM_LEVEL
 | 
				
			||||||
 | 
					#  ifdef MAXSEG_64K
 | 
				
			||||||
 | 
					#    define MAX_MEM_LEVEL 8
 | 
				
			||||||
 | 
					#  else
 | 
				
			||||||
 | 
					#    define MAX_MEM_LEVEL 9
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Maximum value for windowBits in deflateInit2 and inflateInit2.
 | 
				
			||||||
 | 
					 * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
 | 
				
			||||||
 | 
					 * created by gzip. (Files created by minigzip can still be extracted by
 | 
				
			||||||
 | 
					 * gzip.)
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#ifndef MAX_WBITS
 | 
				
			||||||
 | 
					#  define MAX_WBITS   15 /* 32K LZ77 window */
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* The memory requirements for deflate are (in bytes):
 | 
				
			||||||
 | 
					            (1 << (windowBits+2)) +  (1 << (memLevel+9))
 | 
				
			||||||
 | 
					 that is: 128K for windowBits=15  +  128K for memLevel = 8  (default values)
 | 
				
			||||||
 | 
					 plus a few kilobytes for small objects. For example, if you want to reduce
 | 
				
			||||||
 | 
					 the default memory requirements from 256K to 128K, compile with
 | 
				
			||||||
 | 
					     make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
 | 
				
			||||||
 | 
					 Of course this will generally degrade compression (there's no free lunch).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   The memory requirements for inflate are (in bytes) 1 << windowBits
 | 
				
			||||||
 | 
					 that is, 32K for windowBits=15 (default value) plus about 7 kilobytes
 | 
				
			||||||
 | 
					 for small objects.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        /* Type declarations */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef OF /* function prototypes */
 | 
				
			||||||
 | 
					#  ifdef STDC
 | 
				
			||||||
 | 
					#    define OF(args)  args
 | 
				
			||||||
 | 
					#  else
 | 
				
			||||||
 | 
					#    define OF(args)  ()
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef Z_ARG /* function prototypes for stdarg */
 | 
				
			||||||
 | 
					#  if defined(STDC) || defined(Z_HAVE_STDARG_H)
 | 
				
			||||||
 | 
					#    define Z_ARG(args)  args
 | 
				
			||||||
 | 
					#  else
 | 
				
			||||||
 | 
					#    define Z_ARG(args)  ()
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* The following definitions for FAR are needed only for MSDOS mixed
 | 
				
			||||||
 | 
					 * model programming (small or medium model with some far allocations).
 | 
				
			||||||
 | 
					 * This was tested only with MSC; for other MSDOS compilers you may have
 | 
				
			||||||
 | 
					 * to define NO_MEMCPY in zutil.h.  If you don't need the mixed model,
 | 
				
			||||||
 | 
					 * just define FAR to be empty.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#ifdef SYS16BIT
 | 
				
			||||||
 | 
					#  if defined(M_I86SM) || defined(M_I86MM)
 | 
				
			||||||
 | 
					     /* MSC small or medium model */
 | 
				
			||||||
 | 
					#    define SMALL_MEDIUM
 | 
				
			||||||
 | 
					#    ifdef _MSC_VER
 | 
				
			||||||
 | 
					#      define FAR _far
 | 
				
			||||||
 | 
					#    else
 | 
				
			||||||
 | 
					#      define FAR far
 | 
				
			||||||
 | 
					#    endif
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#  if (defined(__SMALL__) || defined(__MEDIUM__))
 | 
				
			||||||
 | 
					     /* Turbo C small or medium model */
 | 
				
			||||||
 | 
					#    define SMALL_MEDIUM
 | 
				
			||||||
 | 
					#    ifdef __BORLANDC__
 | 
				
			||||||
 | 
					#      define FAR _far
 | 
				
			||||||
 | 
					#    else
 | 
				
			||||||
 | 
					#      define FAR far
 | 
				
			||||||
 | 
					#    endif
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(WINDOWS) || defined(WIN32)
 | 
				
			||||||
 | 
					   /* If building or using zlib as a DLL, define ZLIB_DLL.
 | 
				
			||||||
 | 
					    * This is not mandatory, but it offers a little performance increase.
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					#  ifdef ZLIB_DLL
 | 
				
			||||||
 | 
					#    if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
 | 
				
			||||||
 | 
					#      ifdef ZLIB_INTERNAL
 | 
				
			||||||
 | 
					#        define ZEXTERN extern __declspec(dllexport)
 | 
				
			||||||
 | 
					#      else
 | 
				
			||||||
 | 
					#        define ZEXTERN extern __declspec(dllimport)
 | 
				
			||||||
 | 
					#      endif
 | 
				
			||||||
 | 
					#    endif
 | 
				
			||||||
 | 
					#  endif  /* ZLIB_DLL */
 | 
				
			||||||
 | 
					   /* If building or using zlib with the WINAPI/WINAPIV calling convention,
 | 
				
			||||||
 | 
					    * define ZLIB_WINAPI.
 | 
				
			||||||
 | 
					    * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					#  ifdef ZLIB_WINAPI
 | 
				
			||||||
 | 
					#    ifdef FAR
 | 
				
			||||||
 | 
					#      undef FAR
 | 
				
			||||||
 | 
					#    endif
 | 
				
			||||||
 | 
					#    include <windows.h>
 | 
				
			||||||
 | 
					     /* No need for _export, use ZLIB.DEF instead. */
 | 
				
			||||||
 | 
					     /* For complete Windows compatibility, use WINAPI, not __stdcall. */
 | 
				
			||||||
 | 
					#    define ZEXPORT WINAPI
 | 
				
			||||||
 | 
					#    ifdef WIN32
 | 
				
			||||||
 | 
					#      define ZEXPORTVA WINAPIV
 | 
				
			||||||
 | 
					#    else
 | 
				
			||||||
 | 
					#      define ZEXPORTVA FAR CDECL
 | 
				
			||||||
 | 
					#    endif
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined (__BEOS__)
 | 
				
			||||||
 | 
					#  ifdef ZLIB_DLL
 | 
				
			||||||
 | 
					#    ifdef ZLIB_INTERNAL
 | 
				
			||||||
 | 
					#      define ZEXPORT   __declspec(dllexport)
 | 
				
			||||||
 | 
					#      define ZEXPORTVA __declspec(dllexport)
 | 
				
			||||||
 | 
					#    else
 | 
				
			||||||
 | 
					#      define ZEXPORT   __declspec(dllimport)
 | 
				
			||||||
 | 
					#      define ZEXPORTVA __declspec(dllimport)
 | 
				
			||||||
 | 
					#    endif
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef ZEXTERN
 | 
				
			||||||
 | 
					#  define ZEXTERN extern
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifndef ZEXPORT
 | 
				
			||||||
 | 
					#  define ZEXPORT
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifndef ZEXPORTVA
 | 
				
			||||||
 | 
					#  define ZEXPORTVA
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef FAR
 | 
				
			||||||
 | 
					#  define FAR
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if !defined(__MACTYPES__)
 | 
				
			||||||
 | 
					typedef unsigned char  Byte;  /* 8 bits */
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					typedef unsigned int   uInt;  /* 16 bits or more */
 | 
				
			||||||
 | 
					typedef unsigned long  uLong; /* 32 bits or more */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef SMALL_MEDIUM
 | 
				
			||||||
 | 
					   /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
 | 
				
			||||||
 | 
					#  define Bytef Byte FAR
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					   typedef Byte  FAR Bytef;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					typedef char  FAR charf;
 | 
				
			||||||
 | 
					typedef int   FAR intf;
 | 
				
			||||||
 | 
					typedef uInt  FAR uIntf;
 | 
				
			||||||
 | 
					typedef uLong FAR uLongf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef STDC
 | 
				
			||||||
 | 
					   typedef void const *voidpc;
 | 
				
			||||||
 | 
					   typedef void FAR   *voidpf;
 | 
				
			||||||
 | 
					   typedef void       *voidp;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					   typedef Byte const *voidpc;
 | 
				
			||||||
 | 
					   typedef Byte FAR   *voidpf;
 | 
				
			||||||
 | 
					   typedef Byte       *voidp;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC)
 | 
				
			||||||
 | 
					#  include <limits.h>
 | 
				
			||||||
 | 
					#  if (UINT_MAX == 0xffffffffUL)
 | 
				
			||||||
 | 
					#    define Z_U4 unsigned
 | 
				
			||||||
 | 
					#  elif (ULONG_MAX == 0xffffffffUL)
 | 
				
			||||||
 | 
					#    define Z_U4 unsigned long
 | 
				
			||||||
 | 
					#  elif (USHRT_MAX == 0xffffffffUL)
 | 
				
			||||||
 | 
					#    define Z_U4 unsigned short
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef Z_U4
 | 
				
			||||||
 | 
					   typedef Z_U4 z_crc_t;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					   typedef unsigned long z_crc_t;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef HAVE_UNISTD_H    /* may be set to #if 1 by ./configure */
 | 
				
			||||||
 | 
					#  define Z_HAVE_UNISTD_H
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef HAVE_STDARG_H    /* may be set to #if 1 by ./configure */
 | 
				
			||||||
 | 
					#  define Z_HAVE_STDARG_H
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef STDC
 | 
				
			||||||
 | 
					#  ifndef Z_SOLO
 | 
				
			||||||
 | 
					#    include <sys/types.h>      /* for off_t */
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(STDC) || defined(Z_HAVE_STDARG_H)
 | 
				
			||||||
 | 
					#  ifndef Z_SOLO
 | 
				
			||||||
 | 
					#    include <stdarg.h>         /* for va_list */
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef _WIN32
 | 
				
			||||||
 | 
					#  ifndef Z_SOLO
 | 
				
			||||||
 | 
					#    include <stddef.h>         /* for wchar_t */
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and
 | 
				
			||||||
 | 
					 * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even
 | 
				
			||||||
 | 
					 * though the former does not conform to the LFS document), but considering
 | 
				
			||||||
 | 
					 * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as
 | 
				
			||||||
 | 
					 * equivalently requesting no 64-bit operations
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1
 | 
				
			||||||
 | 
					#  undef _LARGEFILE64_SOURCE
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H)
 | 
				
			||||||
 | 
					#  define Z_HAVE_UNISTD_H
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifndef Z_SOLO
 | 
				
			||||||
 | 
					#  if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE)
 | 
				
			||||||
 | 
					#    include <unistd.h>         /* for SEEK_*, off_t, and _LFS64_LARGEFILE */
 | 
				
			||||||
 | 
					#    ifdef VMS
 | 
				
			||||||
 | 
					#      include <unixio.h>       /* for off_t */
 | 
				
			||||||
 | 
					#    endif
 | 
				
			||||||
 | 
					#    ifndef z_off_t
 | 
				
			||||||
 | 
					#      define z_off_t off_t
 | 
				
			||||||
 | 
					#    endif
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0
 | 
				
			||||||
 | 
					#  define Z_LFS64
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64)
 | 
				
			||||||
 | 
					#  define Z_LARGE64
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64)
 | 
				
			||||||
 | 
					#  define Z_WANT64
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if !defined(SEEK_SET) && !defined(Z_SOLO)
 | 
				
			||||||
 | 
					#  define SEEK_SET        0       /* Seek from beginning of file.  */
 | 
				
			||||||
 | 
					#  define SEEK_CUR        1       /* Seek from current position.  */
 | 
				
			||||||
 | 
					#  define SEEK_END        2       /* Set file pointer to EOF plus "offset" */
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef z_off_t
 | 
				
			||||||
 | 
					#  define z_off_t long
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if !defined(_WIN32) && defined(Z_LARGE64)
 | 
				
			||||||
 | 
					#  define z_off64_t off64_t
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#  if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO)
 | 
				
			||||||
 | 
					#    define z_off64_t __int64
 | 
				
			||||||
 | 
					#  else
 | 
				
			||||||
 | 
					#    define z_off64_t z_off_t
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* MVS linker does not support external names larger than 8 bytes */
 | 
				
			||||||
 | 
					#if defined(__MVS__)
 | 
				
			||||||
 | 
					  #pragma map(deflateInit_,"DEIN")
 | 
				
			||||||
 | 
					  #pragma map(deflateInit2_,"DEIN2")
 | 
				
			||||||
 | 
					  #pragma map(deflateEnd,"DEEND")
 | 
				
			||||||
 | 
					  #pragma map(deflateBound,"DEBND")
 | 
				
			||||||
 | 
					  #pragma map(inflateInit_,"ININ")
 | 
				
			||||||
 | 
					  #pragma map(inflateInit2_,"ININ2")
 | 
				
			||||||
 | 
					  #pragma map(inflateEnd,"INEND")
 | 
				
			||||||
 | 
					  #pragma map(inflateSync,"INSY")
 | 
				
			||||||
 | 
					  #pragma map(inflateSetDictionary,"INSEDI")
 | 
				
			||||||
 | 
					  #pragma map(compressBound,"CMBND")
 | 
				
			||||||
 | 
					  #pragma map(inflate_table,"INTABL")
 | 
				
			||||||
 | 
					  #pragma map(inflate_fast,"INFA")
 | 
				
			||||||
 | 
					  #pragma map(inflate_copyright,"INCOPY")
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* ZCONF_H */
 | 
				
			||||||
							
								
								
									
										1913
									
								
								third_party/ZLIB-Windows/zlibwapi-1.2.11_deploy_v140/include/zlib.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1913
									
								
								third_party/ZLIB-Windows/zlibwapi-1.2.11_deploy_v140/include/zlib.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								third_party/ZLIB-Windows/zlibwapi-1.2.11_deploy_v140/release_dynamic/x64/bin/zlib.dll
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								third_party/ZLIB-Windows/zlibwapi-1.2.11_deploy_v140/release_dynamic/x64/bin/zlib.dll
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								third_party/ZLIB-Windows/zlibwapi-1.2.11_deploy_v140/release_dynamic/x64/lib/zlib.exp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								third_party/ZLIB-Windows/zlibwapi-1.2.11_deploy_v140/release_dynamic/x64/lib/zlib.exp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								third_party/ZLIB-Windows/zlibwapi-1.2.11_deploy_v140/release_dynamic/x64/lib/zlib.lib
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								third_party/ZLIB-Windows/zlibwapi-1.2.11_deploy_v140/release_dynamic/x64/lib/zlib.lib
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										3
									
								
								third_party/sanitizers-cmake/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								third_party/sanitizers-cmake/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					# out-of-source build top-level folders.
 | 
				
			||||||
 | 
					build/
 | 
				
			||||||
 | 
					_build/
 | 
				
			||||||
							
								
								
									
										51
									
								
								third_party/sanitizers-cmake/CMakeLists.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								third_party/sanitizers-cmake/CMakeLists.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,51 @@
 | 
				
			|||||||
 | 
					# This file is part of CMake-sanitizers.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# 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.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Copyright (c)
 | 
				
			||||||
 | 
					#   2013-2015 Matt Arsenault
 | 
				
			||||||
 | 
					#   2015      RWTH Aachen University, Federal Republic of Germany
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# project information
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# minimum required cmake version
 | 
				
			||||||
 | 
					cmake_minimum_required(VERSION 2.8)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# project name
 | 
				
			||||||
 | 
					project("CMake-sanitizers")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# cmake configuration
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# add tests
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					enable_testing()
 | 
				
			||||||
 | 
					add_subdirectory(tests)
 | 
				
			||||||
							
								
								
									
										22
									
								
								third_party/sanitizers-cmake/LICENSE
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								third_party/sanitizers-cmake/LICENSE
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					The MIT License (MIT)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Copyright (c)
 | 
				
			||||||
 | 
					    2013 Matthew Arsenault
 | 
				
			||||||
 | 
					    2015-2016 RWTH Aachen University, Federal Republic of Germany
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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.
 | 
				
			||||||
							
								
								
									
										73
									
								
								third_party/sanitizers-cmake/README.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								third_party/sanitizers-cmake/README.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,73 @@
 | 
				
			|||||||
 | 
					# sanitizers-cmake
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 [](https://github.com/arsenm/sanitizers-cmake/issues)
 | 
				
			||||||
 | 
					[](LICENSE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CMake module to enable sanitizers for binary targets.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Include into your project
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To use [FindSanitizers.cmake](cmake/FindSanitizers.cmake), simply add this repository as git submodule into your own repository
 | 
				
			||||||
 | 
					```Shell
 | 
				
			||||||
 | 
					mkdir externals
 | 
				
			||||||
 | 
					git submodule add git://github.com/arsenm/sanitizers-cmake.git externals/sanitizers-cmake
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					and adding ```externals/sanitizers-cmake/cmake``` to your ```CMAKE_MODULE_PATH```
 | 
				
			||||||
 | 
					```CMake
 | 
				
			||||||
 | 
					set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/externals/sanitizers-cmake/cmake" ${CMAKE_MODULE_PATH})
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If you don't use git or dislike submodules you can copy the files in [cmake directory](cmake) into your repository. *Be careful and keep updates in mind!*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Now you can simply run ```find_package``` in your CMake files:
 | 
				
			||||||
 | 
					```CMake
 | 
				
			||||||
 | 
					find_package(Sanitizers)
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Usage
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You can enable the sanitizers with ``SANITIZE_ADDRESS``, ``SANITIZE_MEMORY``, ``SANITIZE_THREAD`` or ``SANITIZE_UNDEFINED`` options in your CMake configuration. You can do this by passing e.g. ``-DSANITIZE_ADDRESS=On`` on your command line or with your graphical interface.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If sanitizers are supported by your compiler, the specified targets will be build with sanitizer support. If your compiler has no sanitizing capabilities (I asume intel compiler doesn't) you'll get a warning but CMake will continue processing and sanitizing will simply just be ignored.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### Compiler issues
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Different compilers may be using different implementations for sanitizers. If you'll try to sanitize targets with C and Fortran code but don't use gcc & gfortran but clang & gfortran, this will cause linking problems. To avoid this, such problems will be detected and sanitizing will be disabled for these targets.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Even C only targets may cause problems in certain situations. Some problems have been seen with AddressSanitizer for preloading or dynamic linking. In such cases you may try the ``SANITIZE_LINK_STATIC`` to link sanitizers for gcc static.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Build targets with sanitizer support
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To enable sanitizer support you simply have to add ``add_sanitizers(<TARGET>)`` after defining your target. To provide a sanitizer blacklist file you can use the ``sanitizer_add_blacklist_file(<FILE>)`` function:
 | 
				
			||||||
 | 
					```CMake
 | 
				
			||||||
 | 
					find_package(Sanitizers)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sanitizer_add_blacklist_file("blacklist.txt")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					add_executable(some_exe foo.c bar.c)
 | 
				
			||||||
 | 
					add_sanitizers(some_exe)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					add_library(some_lib foo.c bar.c)
 | 
				
			||||||
 | 
					add_sanitizers(some_lib)
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Run your application
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The sanitizers check your program, while it's running. In some situations (e.g. LD_PRELOAD your target) it might be required to preload the used AddressSanitizer library first. In this case you may use the ``asan-wrapper`` script defined in ``ASan_WRAPPER`` variable to execute your application with ``${ASan_WRAPPER} myexe arg1 ...``.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Contribute
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Anyone is welcome to contribute. Simply fork this repository, make your changes **in an own branch** and create a pull-request for your change. Please do only one change per pull-request.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You found a bug? Please fill out an [issue](https://github.com/arsenm/sanitizers-cmake/issues) and include any data to reproduce the bug.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### Contributors
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* [Matt Arsenault](https://github.com/arsenm)
 | 
				
			||||||
 | 
					* [Alexander Haase](https://github.com/alehaa)
 | 
				
			||||||
							
								
								
									
										59
									
								
								third_party/sanitizers-cmake/cmake/FindASan.cmake
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								third_party/sanitizers-cmake/cmake/FindASan.cmake
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,59 @@
 | 
				
			|||||||
 | 
					# The MIT License (MIT)
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Copyright (c)
 | 
				
			||||||
 | 
					#   2013 Matthew Arsenault
 | 
				
			||||||
 | 
					#   2015-2016 RWTH Aachen University, Federal Republic of Germany
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# 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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					option(SANITIZE_ADDRESS "Enable AddressSanitizer for sanitized targets." Off)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set(FLAG_CANDIDATES
 | 
				
			||||||
 | 
					    # Clang 3.2+ use this version. The no-omit-frame-pointer option is optional.
 | 
				
			||||||
 | 
					    "-g -fsanitize=address -fno-omit-frame-pointer"
 | 
				
			||||||
 | 
					    "-g -fsanitize=address"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Older deprecated flag for ASan
 | 
				
			||||||
 | 
					    "-g -faddress-sanitizer"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (SANITIZE_ADDRESS AND (SANITIZE_THREAD OR SANITIZE_MEMORY))
 | 
				
			||||||
 | 
					    message(FATAL_ERROR "AddressSanitizer is not compatible with "
 | 
				
			||||||
 | 
					        "ThreadSanitizer or MemorySanitizer.")
 | 
				
			||||||
 | 
					endif ()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include(sanitize-helpers)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (SANITIZE_ADDRESS)
 | 
				
			||||||
 | 
					    sanitizer_check_compiler_flags("${FLAG_CANDIDATES}" "AddressSanitizer"
 | 
				
			||||||
 | 
					        "ASan")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    find_program(ASan_WRAPPER "asan-wrapper" PATHS ${CMAKE_MODULE_PATH})
 | 
				
			||||||
 | 
						mark_as_advanced(ASan_WRAPPER)
 | 
				
			||||||
 | 
					endif ()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function (add_sanitize_address TARGET)
 | 
				
			||||||
 | 
					    if (NOT SANITIZE_ADDRESS)
 | 
				
			||||||
 | 
					        return()
 | 
				
			||||||
 | 
					    endif ()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sanitizer_add_flags(${TARGET} "AddressSanitizer" "ASan")
 | 
				
			||||||
 | 
					endfunction ()
 | 
				
			||||||
							
								
								
									
										57
									
								
								third_party/sanitizers-cmake/cmake/FindMSan.cmake
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								third_party/sanitizers-cmake/cmake/FindMSan.cmake
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,57 @@
 | 
				
			|||||||
 | 
					# The MIT License (MIT)
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Copyright (c)
 | 
				
			||||||
 | 
					#   2013 Matthew Arsenault
 | 
				
			||||||
 | 
					#   2015-2016 RWTH Aachen University, Federal Republic of Germany
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# 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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					option(SANITIZE_MEMORY "Enable MemorySanitizer for sanitized targets." Off)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set(FLAG_CANDIDATES
 | 
				
			||||||
 | 
					    "-g -fsanitize=memory"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include(sanitize-helpers)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (SANITIZE_MEMORY)
 | 
				
			||||||
 | 
					    if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
 | 
				
			||||||
 | 
					        message(WARNING "MemorySanitizer disabled for target ${TARGET} because "
 | 
				
			||||||
 | 
					            "MemorySanitizer is supported for Linux systems only.")
 | 
				
			||||||
 | 
					        set(SANITIZE_MEMORY Off CACHE BOOL
 | 
				
			||||||
 | 
					            "Enable MemorySanitizer for sanitized targets." FORCE)
 | 
				
			||||||
 | 
					    elseif (NOT ${CMAKE_SIZEOF_VOID_P} EQUAL 8)
 | 
				
			||||||
 | 
					        message(WARNING "MemorySanitizer disabled for target ${TARGET} because "
 | 
				
			||||||
 | 
					            "MemorySanitizer is supported for 64bit systems only.")
 | 
				
			||||||
 | 
					        set(SANITIZE_MEMORY Off CACHE BOOL
 | 
				
			||||||
 | 
					            "Enable MemorySanitizer for sanitized targets." FORCE)
 | 
				
			||||||
 | 
					    else ()
 | 
				
			||||||
 | 
					        sanitizer_check_compiler_flags("${FLAG_CANDIDATES}" "MemorySanitizer"
 | 
				
			||||||
 | 
					            "MSan")
 | 
				
			||||||
 | 
					    endif ()
 | 
				
			||||||
 | 
					endif ()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function (add_sanitize_memory TARGET)
 | 
				
			||||||
 | 
					    if (NOT SANITIZE_MEMORY)
 | 
				
			||||||
 | 
					        return()
 | 
				
			||||||
 | 
					    endif ()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sanitizer_add_flags(${TARGET} "MemorySanitizer" "MSan")
 | 
				
			||||||
 | 
					endfunction ()
 | 
				
			||||||
							
								
								
									
										87
									
								
								third_party/sanitizers-cmake/cmake/FindSanitizers.cmake
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								third_party/sanitizers-cmake/cmake/FindSanitizers.cmake
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,87 @@
 | 
				
			|||||||
 | 
					# The MIT License (MIT)
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Copyright (c)
 | 
				
			||||||
 | 
					#   2013 Matthew Arsenault
 | 
				
			||||||
 | 
					#   2015-2016 RWTH Aachen University, Federal Republic of Germany
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# 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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# If any of the used compiler is a GNU compiler, add a second option to static
 | 
				
			||||||
 | 
					# link against the sanitizers.
 | 
				
			||||||
 | 
					option(SANITIZE_LINK_STATIC "Try to link static against sanitizers." Off)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set(FIND_QUIETLY_FLAG "")
 | 
				
			||||||
 | 
					if (DEFINED Sanitizers_FIND_QUIETLY)
 | 
				
			||||||
 | 
					    set(FIND_QUIETLY_FLAG "QUIET")
 | 
				
			||||||
 | 
					endif ()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					find_package(ASan ${FIND_QUIETLY_FLAG})
 | 
				
			||||||
 | 
					find_package(TSan ${FIND_QUIETLY_FLAG})
 | 
				
			||||||
 | 
					find_package(MSan ${FIND_QUIETLY_FLAG})
 | 
				
			||||||
 | 
					find_package(UBSan ${FIND_QUIETLY_FLAG})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function(sanitizer_add_blacklist_file FILE)
 | 
				
			||||||
 | 
					    if(NOT IS_ABSOLUTE ${FILE})
 | 
				
			||||||
 | 
					        set(FILE "${CMAKE_CURRENT_SOURCE_DIR}/${FILE}")
 | 
				
			||||||
 | 
					    endif()
 | 
				
			||||||
 | 
					    get_filename_component(FILE "${FILE}" REALPATH)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sanitizer_check_compiler_flags("-fsanitize-blacklist=${FILE}"
 | 
				
			||||||
 | 
					        "SanitizerBlacklist" "SanBlist")
 | 
				
			||||||
 | 
					endfunction()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function(add_sanitizers ...)
 | 
				
			||||||
 | 
					    # If no sanitizer is enabled, return immediately.
 | 
				
			||||||
 | 
					    if (NOT (SANITIZE_ADDRESS OR SANITIZE_MEMORY OR SANITIZE_THREAD OR
 | 
				
			||||||
 | 
					        SANITIZE_UNDEFINED))
 | 
				
			||||||
 | 
					        return()
 | 
				
			||||||
 | 
					    endif ()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    foreach (TARGET ${ARGV})
 | 
				
			||||||
 | 
					        # Check if this target will be compiled by exactly one compiler. Other-
 | 
				
			||||||
 | 
					        # wise sanitizers can't be used and a warning should be printed once.
 | 
				
			||||||
 | 
					        sanitizer_target_compilers(${TARGET} TARGET_COMPILER)
 | 
				
			||||||
 | 
					        list(LENGTH TARGET_COMPILER NUM_COMPILERS)
 | 
				
			||||||
 | 
					        if (NUM_COMPILERS GREATER 1)
 | 
				
			||||||
 | 
					            message(WARNING "Can't use any sanitizers for target ${TARGET}, "
 | 
				
			||||||
 | 
					                    "because it will be compiled by incompatible compilers. "
 | 
				
			||||||
 | 
					                    "Target will be compiled without sanitizers.")
 | 
				
			||||||
 | 
					            return()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # If the target is compiled by no known compiler, ignore it.
 | 
				
			||||||
 | 
					        elseif (NUM_COMPILERS EQUAL 0)
 | 
				
			||||||
 | 
					            message(WARNING "Can't use any sanitizers for target ${TARGET}, "
 | 
				
			||||||
 | 
					                    "because it uses an unknown compiler. Target will be "
 | 
				
			||||||
 | 
					                    "compiled without sanitizers.")
 | 
				
			||||||
 | 
					            return()
 | 
				
			||||||
 | 
					        endif ()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Add sanitizers for target.
 | 
				
			||||||
 | 
					        add_sanitize_address(${TARGET})
 | 
				
			||||||
 | 
					        add_sanitize_thread(${TARGET})
 | 
				
			||||||
 | 
					        add_sanitize_memory(${TARGET})
 | 
				
			||||||
 | 
					        add_sanitize_undefined(${TARGET})
 | 
				
			||||||
 | 
						endforeach ()
 | 
				
			||||||
 | 
					endfunction(add_sanitizers)
 | 
				
			||||||
							
								
								
									
										65
									
								
								third_party/sanitizers-cmake/cmake/FindTSan.cmake
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								third_party/sanitizers-cmake/cmake/FindTSan.cmake
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,65 @@
 | 
				
			|||||||
 | 
					# The MIT License (MIT)
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Copyright (c)
 | 
				
			||||||
 | 
					#   2013 Matthew Arsenault
 | 
				
			||||||
 | 
					#   2015-2016 RWTH Aachen University, Federal Republic of Germany
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# 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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					option(SANITIZE_THREAD "Enable ThreadSanitizer for sanitized targets." Off)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set(FLAG_CANDIDATES
 | 
				
			||||||
 | 
					    "-g -fsanitize=thread"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# ThreadSanitizer is not compatible with MemorySanitizer.
 | 
				
			||||||
 | 
					if (SANITIZE_THREAD AND SANITIZE_MEMORY)
 | 
				
			||||||
 | 
					    message(FATAL_ERROR "ThreadSanitizer is not compatible with "
 | 
				
			||||||
 | 
					        "MemorySanitizer.")
 | 
				
			||||||
 | 
					endif ()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include(sanitize-helpers)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (SANITIZE_THREAD)
 | 
				
			||||||
 | 
					  if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Linux" AND
 | 
				
			||||||
 | 
					      NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
 | 
				
			||||||
 | 
					        message(WARNING "ThreadSanitizer disabled for target ${TARGET} because "
 | 
				
			||||||
 | 
					          "ThreadSanitizer is supported for Linux systems and macOS only.")
 | 
				
			||||||
 | 
					        set(SANITIZE_THREAD Off CACHE BOOL
 | 
				
			||||||
 | 
					            "Enable ThreadSanitizer for sanitized targets." FORCE)
 | 
				
			||||||
 | 
					    elseif (NOT ${CMAKE_SIZEOF_VOID_P} EQUAL 8)
 | 
				
			||||||
 | 
					        message(WARNING "ThreadSanitizer disabled for target ${TARGET} because "
 | 
				
			||||||
 | 
					            "ThreadSanitizer is supported for 64bit systems only.")
 | 
				
			||||||
 | 
					        set(SANITIZE_THREAD Off CACHE BOOL
 | 
				
			||||||
 | 
					            "Enable ThreadSanitizer for sanitized targets." FORCE)
 | 
				
			||||||
 | 
					    else ()
 | 
				
			||||||
 | 
					        sanitizer_check_compiler_flags("${FLAG_CANDIDATES}" "ThreadSanitizer"
 | 
				
			||||||
 | 
					            "TSan")
 | 
				
			||||||
 | 
					    endif ()
 | 
				
			||||||
 | 
					endif ()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function (add_sanitize_thread TARGET)
 | 
				
			||||||
 | 
					    if (NOT SANITIZE_THREAD)
 | 
				
			||||||
 | 
					        return()
 | 
				
			||||||
 | 
					    endif ()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sanitizer_add_flags(${TARGET} "ThreadSanitizer" "TSan")
 | 
				
			||||||
 | 
					endfunction ()
 | 
				
			||||||
							
								
								
									
										46
									
								
								third_party/sanitizers-cmake/cmake/FindUBSan.cmake
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								third_party/sanitizers-cmake/cmake/FindUBSan.cmake
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,46 @@
 | 
				
			|||||||
 | 
					# The MIT License (MIT)
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Copyright (c)
 | 
				
			||||||
 | 
					#   2013 Matthew Arsenault
 | 
				
			||||||
 | 
					#   2015-2016 RWTH Aachen University, Federal Republic of Germany
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# 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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					option(SANITIZE_UNDEFINED
 | 
				
			||||||
 | 
					    "Enable UndefinedBehaviorSanitizer for sanitized targets." Off)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set(FLAG_CANDIDATES
 | 
				
			||||||
 | 
					    "-g -fsanitize=undefined"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include(sanitize-helpers)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (SANITIZE_UNDEFINED)
 | 
				
			||||||
 | 
					    sanitizer_check_compiler_flags("${FLAG_CANDIDATES}"
 | 
				
			||||||
 | 
					        "UndefinedBehaviorSanitizer" "UBSan")
 | 
				
			||||||
 | 
					endif ()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function (add_sanitize_undefined TARGET)
 | 
				
			||||||
 | 
					    if (NOT SANITIZE_UNDEFINED)
 | 
				
			||||||
 | 
					        return()
 | 
				
			||||||
 | 
					    endif ()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sanitizer_add_flags(${TARGET} "UndefinedBehaviorSanitizer" "UBSan")
 | 
				
			||||||
 | 
					endfunction ()
 | 
				
			||||||
							
								
								
									
										55
									
								
								third_party/sanitizers-cmake/cmake/asan-wrapper
									
									
									
									
										vendored
									
									
										Executable file
									
								
							
							
						
						
									
										55
									
								
								third_party/sanitizers-cmake/cmake/asan-wrapper
									
									
									
									
										vendored
									
									
										Executable file
									
								
							@@ -0,0 +1,55 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# The MIT License (MIT)
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Copyright (c)
 | 
				
			||||||
 | 
					#   2013 Matthew Arsenault
 | 
				
			||||||
 | 
					#   2015-2016 RWTH Aachen University, Federal Republic of Germany
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# 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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# This script is a wrapper for AddressSanitizer. In some special cases you need
 | 
				
			||||||
 | 
					# to preload AddressSanitizer to avoid error messages - e.g. if you're
 | 
				
			||||||
 | 
					# preloading another library to your application. At the moment this script will
 | 
				
			||||||
 | 
					# only do something, if we're running on a Linux platform. OSX might not be
 | 
				
			||||||
 | 
					# affected.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Exit immediately, if platform is not Linux.
 | 
				
			||||||
 | 
					if [ "$(uname)" != "Linux" ]
 | 
				
			||||||
 | 
					then
 | 
				
			||||||
 | 
					    exec $@
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Get the used libasan of the application ($1). If a libasan was found, it will
 | 
				
			||||||
 | 
					# be prepended to LD_PRELOAD.
 | 
				
			||||||
 | 
					libasan=$(ldd $1 | grep libasan | sed "s/^[[:space:]]//" | cut -d' ' -f1)
 | 
				
			||||||
 | 
					if [ -n "$libasan" ]
 | 
				
			||||||
 | 
					then
 | 
				
			||||||
 | 
					    if [ -n "$LD_PRELOAD" ]
 | 
				
			||||||
 | 
					    then
 | 
				
			||||||
 | 
					        export LD_PRELOAD="$libasan:$LD_PRELOAD"
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        export LD_PRELOAD="$libasan"
 | 
				
			||||||
 | 
					    fi
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Execute the application.
 | 
				
			||||||
 | 
					exec $@
 | 
				
			||||||
							
								
								
									
										170
									
								
								third_party/sanitizers-cmake/cmake/sanitize-helpers.cmake
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										170
									
								
								third_party/sanitizers-cmake/cmake/sanitize-helpers.cmake
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,170 @@
 | 
				
			|||||||
 | 
					# The MIT License (MIT)
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Copyright (c)
 | 
				
			||||||
 | 
					#   2013 Matthew Arsenault
 | 
				
			||||||
 | 
					#   2015-2016 RWTH Aachen University, Federal Republic of Germany
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# 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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Helper function to get the language of a source file.
 | 
				
			||||||
 | 
					function (sanitizer_lang_of_source FILE RETURN_VAR)
 | 
				
			||||||
 | 
					    get_filename_component(FILE_EXT "${FILE}" EXT)
 | 
				
			||||||
 | 
					    string(TOLOWER "${FILE_EXT}" FILE_EXT)
 | 
				
			||||||
 | 
					    string(SUBSTRING "${FILE_EXT}" 1 -1 FILE_EXT)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    get_property(ENABLED_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES)
 | 
				
			||||||
 | 
					    foreach (LANG ${ENABLED_LANGUAGES})
 | 
				
			||||||
 | 
					        list(FIND CMAKE_${LANG}_SOURCE_FILE_EXTENSIONS "${FILE_EXT}" TEMP)
 | 
				
			||||||
 | 
					        if (NOT ${TEMP} EQUAL -1)
 | 
				
			||||||
 | 
					            set(${RETURN_VAR} "${LANG}" PARENT_SCOPE)
 | 
				
			||||||
 | 
					            return()
 | 
				
			||||||
 | 
					        endif ()
 | 
				
			||||||
 | 
					    endforeach()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    set(${RETURN_VAR} "" PARENT_SCOPE)
 | 
				
			||||||
 | 
					endfunction ()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Helper function to get compilers used by a target.
 | 
				
			||||||
 | 
					function (sanitizer_target_compilers TARGET RETURN_VAR)
 | 
				
			||||||
 | 
					    # Check if all sources for target use the same compiler. If a target uses
 | 
				
			||||||
 | 
					    # e.g. C and Fortran mixed and uses different compilers (e.g. clang and
 | 
				
			||||||
 | 
					    # gfortran) this can trigger huge problems, because different compilers may
 | 
				
			||||||
 | 
					    # use different implementations for sanitizers.
 | 
				
			||||||
 | 
					    set(BUFFER "")
 | 
				
			||||||
 | 
					    get_target_property(TSOURCES ${TARGET} SOURCES)
 | 
				
			||||||
 | 
					    foreach (FILE ${TSOURCES})
 | 
				
			||||||
 | 
					        # If expression was found, FILE is a generator-expression for an object
 | 
				
			||||||
 | 
					        # library. Object libraries will be ignored.
 | 
				
			||||||
 | 
					        string(REGEX MATCH "TARGET_OBJECTS:([^ >]+)" _file ${FILE})
 | 
				
			||||||
 | 
					        if ("${_file}" STREQUAL "")
 | 
				
			||||||
 | 
					            sanitizer_lang_of_source(${FILE} LANG)
 | 
				
			||||||
 | 
					            if (LANG)
 | 
				
			||||||
 | 
					                list(APPEND BUFFER ${CMAKE_${LANG}_COMPILER_ID})
 | 
				
			||||||
 | 
					            endif ()
 | 
				
			||||||
 | 
					        endif ()
 | 
				
			||||||
 | 
					    endforeach ()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    list(REMOVE_DUPLICATES BUFFER)
 | 
				
			||||||
 | 
					    set(${RETURN_VAR} "${BUFFER}" PARENT_SCOPE)
 | 
				
			||||||
 | 
					endfunction ()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Helper function to check compiler flags for language compiler.
 | 
				
			||||||
 | 
					function (sanitizer_check_compiler_flag FLAG LANG VARIABLE)
 | 
				
			||||||
 | 
					    if (${LANG} STREQUAL "C")
 | 
				
			||||||
 | 
					        include(CheckCCompilerFlag)
 | 
				
			||||||
 | 
					        check_c_compiler_flag("${FLAG}" ${VARIABLE})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    elseif (${LANG} STREQUAL "CXX")
 | 
				
			||||||
 | 
					        include(CheckCXXCompilerFlag)
 | 
				
			||||||
 | 
					        check_cxx_compiler_flag("${FLAG}" ${VARIABLE})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    elseif (${LANG} STREQUAL "Fortran")
 | 
				
			||||||
 | 
					        # CheckFortranCompilerFlag was introduced in CMake 3.x. To be compatible
 | 
				
			||||||
 | 
					        # with older Cmake versions, we will check if this module is present
 | 
				
			||||||
 | 
					        # before we use it. Otherwise we will define Fortran coverage support as
 | 
				
			||||||
 | 
					        # not available.
 | 
				
			||||||
 | 
					        include(CheckFortranCompilerFlag OPTIONAL RESULT_VARIABLE INCLUDED)
 | 
				
			||||||
 | 
					        if (INCLUDED)
 | 
				
			||||||
 | 
					            check_fortran_compiler_flag("${FLAG}" ${VARIABLE})
 | 
				
			||||||
 | 
					        elseif (NOT CMAKE_REQUIRED_QUIET)
 | 
				
			||||||
 | 
					            message(STATUS "Performing Test ${VARIABLE}")
 | 
				
			||||||
 | 
					            message(STATUS "Performing Test ${VARIABLE}"
 | 
				
			||||||
 | 
					                " - Failed (Check not supported)")
 | 
				
			||||||
 | 
					        endif ()
 | 
				
			||||||
 | 
					    endif()
 | 
				
			||||||
 | 
					endfunction ()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Helper function to test compiler flags.
 | 
				
			||||||
 | 
					function (sanitizer_check_compiler_flags FLAG_CANDIDATES NAME PREFIX)
 | 
				
			||||||
 | 
					    set(CMAKE_REQUIRED_QUIET ${${PREFIX}_FIND_QUIETLY})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    get_property(ENABLED_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES)
 | 
				
			||||||
 | 
					    foreach (LANG ${ENABLED_LANGUAGES})
 | 
				
			||||||
 | 
					        # Sanitizer flags are not dependend on language, but the used compiler.
 | 
				
			||||||
 | 
					        # So instead of searching flags foreach language, search flags foreach
 | 
				
			||||||
 | 
					        # compiler used.
 | 
				
			||||||
 | 
					        set(COMPILER ${CMAKE_${LANG}_COMPILER_ID})
 | 
				
			||||||
 | 
					        if (NOT DEFINED ${PREFIX}_${COMPILER}_FLAGS)
 | 
				
			||||||
 | 
					            foreach (FLAG ${FLAG_CANDIDATES})
 | 
				
			||||||
 | 
					                if(NOT CMAKE_REQUIRED_QUIET)
 | 
				
			||||||
 | 
					                    message(STATUS "Try ${COMPILER} ${NAME} flag = [${FLAG}]")
 | 
				
			||||||
 | 
					                endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                set(CMAKE_REQUIRED_FLAGS "${FLAG}")
 | 
				
			||||||
 | 
					                unset(${PREFIX}_FLAG_DETECTED CACHE)
 | 
				
			||||||
 | 
					                sanitizer_check_compiler_flag("${FLAG}" ${LANG}
 | 
				
			||||||
 | 
					                    ${PREFIX}_FLAG_DETECTED)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (${PREFIX}_FLAG_DETECTED)
 | 
				
			||||||
 | 
					                    # If compiler is a GNU compiler, search for static flag, if
 | 
				
			||||||
 | 
					                    # SANITIZE_LINK_STATIC is enabled.
 | 
				
			||||||
 | 
					                    if (SANITIZE_LINK_STATIC AND (${COMPILER} STREQUAL "GNU"))
 | 
				
			||||||
 | 
					                        string(TOLOWER ${PREFIX} PREFIX_lower)
 | 
				
			||||||
 | 
					                        sanitizer_check_compiler_flag(
 | 
				
			||||||
 | 
					                            "-static-lib${PREFIX_lower}" ${LANG}
 | 
				
			||||||
 | 
					                            ${PREFIX}_STATIC_FLAG_DETECTED)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        if (${PREFIX}_STATIC_FLAG_DETECTED)
 | 
				
			||||||
 | 
					                            set(FLAG "-static-lib${PREFIX_lower} ${FLAG}")
 | 
				
			||||||
 | 
					                        endif ()
 | 
				
			||||||
 | 
					                    endif ()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    set(${PREFIX}_${COMPILER}_FLAGS "${FLAG}" CACHE STRING
 | 
				
			||||||
 | 
					                        "${NAME} flags for ${COMPILER} compiler.")
 | 
				
			||||||
 | 
					                    mark_as_advanced(${PREFIX}_${COMPILER}_FLAGS)
 | 
				
			||||||
 | 
					                    break()
 | 
				
			||||||
 | 
					                endif ()
 | 
				
			||||||
 | 
					            endforeach ()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (NOT ${PREFIX}_FLAG_DETECTED)
 | 
				
			||||||
 | 
					                set(${PREFIX}_${COMPILER}_FLAGS "" CACHE STRING
 | 
				
			||||||
 | 
					                    "${NAME} flags for ${COMPILER} compiler.")
 | 
				
			||||||
 | 
					                mark_as_advanced(${PREFIX}_${COMPILER}_FLAGS)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                message(WARNING "${NAME} is not available for ${COMPILER} "
 | 
				
			||||||
 | 
					                        "compiler. Targets using this compiler will be "
 | 
				
			||||||
 | 
					                        "compiled without ${NAME}.")
 | 
				
			||||||
 | 
					            endif ()
 | 
				
			||||||
 | 
					        endif ()
 | 
				
			||||||
 | 
					    endforeach ()
 | 
				
			||||||
 | 
					endfunction ()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Helper to assign sanitizer flags for TARGET.
 | 
				
			||||||
 | 
					function (sanitizer_add_flags TARGET NAME PREFIX)
 | 
				
			||||||
 | 
					    # Get list of compilers used by target and check, if sanitizer is available
 | 
				
			||||||
 | 
					    # for this target. Other compiler checks like check for conflicting
 | 
				
			||||||
 | 
					    # compilers will be done in add_sanitizers function.
 | 
				
			||||||
 | 
					    sanitizer_target_compilers(${TARGET} TARGET_COMPILER)
 | 
				
			||||||
 | 
					    list(LENGTH TARGET_COMPILER NUM_COMPILERS)
 | 
				
			||||||
 | 
					    if ("${${PREFIX}_${TARGET_COMPILER}_FLAGS}" STREQUAL "")
 | 
				
			||||||
 | 
					        return()
 | 
				
			||||||
 | 
					    endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Set compile- and link-flags for target.
 | 
				
			||||||
 | 
					    set_property(TARGET ${TARGET} APPEND_STRING
 | 
				
			||||||
 | 
					        PROPERTY COMPILE_FLAGS " ${${PREFIX}_${TARGET_COMPILER}_FLAGS}")
 | 
				
			||||||
 | 
					    set_property(TARGET ${TARGET} APPEND_STRING
 | 
				
			||||||
 | 
					        PROPERTY COMPILE_FLAGS " ${SanBlist_${TARGET_COMPILER}_FLAGS}")
 | 
				
			||||||
 | 
					    set_property(TARGET ${TARGET} APPEND_STRING
 | 
				
			||||||
 | 
					        PROPERTY LINK_FLAGS " ${${PREFIX}_${TARGET_COMPILER}_FLAGS}")
 | 
				
			||||||
 | 
					endfunction ()
 | 
				
			||||||
							
								
								
									
										52
									
								
								third_party/sanitizers-cmake/tests/CMakeLists.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								third_party/sanitizers-cmake/tests/CMakeLists.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,52 @@
 | 
				
			|||||||
 | 
					# This file is part of CMake-sanitizers.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# 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.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Copyright (c)
 | 
				
			||||||
 | 
					#   2013-2015 Matt Arsenault
 | 
				
			||||||
 | 
					#   2015      RWTH Aachen University, Federal Republic of Germany
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Function to add testcases.
 | 
				
			||||||
 | 
					function(add_testcase TESTNAME SOURCEFILES)
 | 
				
			||||||
 | 
						# remove ${TESTNAME} from ${ARGV} to use ${ARGV} as ${SOURCEFILES}
 | 
				
			||||||
 | 
						list(REMOVE_AT ARGV 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						# add a new executable
 | 
				
			||||||
 | 
						add_executable(${TESTNAME} ${ARGV})
 | 
				
			||||||
 | 
						add_sanitizers(${TESTNAME})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						# add a testcase for executable
 | 
				
			||||||
 | 
						add_test(${TESTNAME} ${TESTNAME})
 | 
				
			||||||
 | 
					endfunction(add_testcase)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# search for sanitizers
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					find_package(Sanitizers)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# add testcases
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					add_testcase("asan_test_cpp" asan_test.cpp)
 | 
				
			||||||
							
								
								
									
										39
									
								
								third_party/sanitizers-cmake/tests/asan_test.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								third_party/sanitizers-cmake/tests/asan_test.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
				
			|||||||
 | 
					/* This file is part of CMake-sanitizers.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 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.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (c)
 | 
				
			||||||
 | 
					 *  2013-2015 Matt Arsenault
 | 
				
			||||||
 | 
					 *  2015      RWTH Aachen University, Federal Republic of Germany
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					main(int argc, char **argv)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						// Allocate a new array and delete it.
 | 
				
			||||||
 | 
						int *array = new int[argc];
 | 
				
			||||||
 | 
						delete[] array;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Access element of the deleted array. This will cause an memory error with
 | 
				
			||||||
 | 
						 * address sanitizer.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						return array[argc];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user