Compare commits
	
		
			14 Commits
		
	
	
		
			feature/no
			...
			feature/wi
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | a6199f1009 | ||
|  | 69093953da | ||
|  | 64e88d617b | ||
|  | 5b4ca7f9df | ||
|  | 71bac1ea7d | ||
|  | 9c9e7f3206 | ||
|  | e691ac3704 | ||
|  | 6fcecb84eb | ||
|  | e26cd1faba | ||
|  | 1f659c34bd | ||
|  | 93f16018f7 | ||
|  | a3cfd6810b | ||
|  | f7b87be65b | ||
|  | 739a43988c | 
| @@ -29,6 +29,9 @@ if (USE_TLS) | ||||
|     if (APPLE) | ||||
|         list( APPEND IXWEBSOCKET_HEADERS ixwebsocket/IXSocketAppleSSL.h) | ||||
|         list( APPEND IXWEBSOCKET_SOURCES ixwebsocket/IXSocketAppleSSL.cpp) | ||||
|     elseif (WIN32) | ||||
|         list( APPEND IXWEBSOCKET_HEADERS ixwebsocket/IXSocketSChannel.h) | ||||
|         list( APPEND IXWEBSOCKET_SOURCES ixwebsocket/IXSocketSChannel.cpp) | ||||
|     else() | ||||
|         list( APPEND IXWEBSOCKET_HEADERS ixwebsocket/IXSocketOpenSSL.h) | ||||
|         list( APPEND IXWEBSOCKET_SOURCES ixwebsocket/IXSocketOpenSSL.cpp) | ||||
|   | ||||
| @@ -19,5 +19,10 @@ if (APPLE AND USE_TLS) | ||||
|     target_link_libraries(cmd_websocket_chat "-framework foundation" "-framework security") | ||||
| endif() | ||||
|  | ||||
| if (WIN32) | ||||
|     target_link_libraries(cmd_websocket_chat wsock32 ws2_32) | ||||
|     add_definitions(-D_CRT_SECURE_NO_WARNINGS) | ||||
| endif() | ||||
|  | ||||
| target_link_libraries(cmd_websocket_chat ixwebsocket) | ||||
| install(TARGETS cmd_websocket_chat DESTINATION bin) | ||||
|   | ||||
							
								
								
									
										1
									
								
								examples/ping_pong/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								examples/ping_pong/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| venv | ||||
							
								
								
									
										27
									
								
								examples/ping_pong/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								examples/ping_pong/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| # | ||||
| # Author: Benjamin Sergeant | ||||
| # Copyright (c) 2018 Machine Zone, Inc. All rights reserved. | ||||
| # | ||||
|  | ||||
| cmake_minimum_required (VERSION 3.4.1) | ||||
| project (ping_pong) | ||||
|  | ||||
| set (CMAKE_CXX_STANDARD 11) | ||||
|  | ||||
| option(USE_TLS "Add TLS support" ON) | ||||
|  | ||||
| add_subdirectory(${PROJECT_SOURCE_DIR}/../.. ixwebsocket) | ||||
|  | ||||
| add_executable(ping_pong ping_pong.cpp) | ||||
|  | ||||
| if (APPLE AND USE_TLS) | ||||
|     target_link_libraries(ping_pong "-framework foundation" "-framework security") | ||||
| endif() | ||||
|  | ||||
| if (WIN32) | ||||
|     target_link_libraries(ping_pong wsock32 ws2_32) | ||||
|     add_definitions(-D_CRT_SECURE_NO_WARNINGS) | ||||
| endif() | ||||
|  | ||||
| target_link_libraries(ping_pong ixwebsocket) | ||||
| install(TARGETS ping_pong DESTINATION bin) | ||||
							
								
								
									
										17
									
								
								examples/ping_pong/client.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								examples/ping_pong/client.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| #!/usr/bin/env python | ||||
|  | ||||
| import asyncio | ||||
| import websockets | ||||
|  | ||||
| async def hello(uri): | ||||
|     async with websockets.connect(uri) as websocket: | ||||
|         await websocket.send("Hello world!") | ||||
|         response = await websocket.recv() | ||||
|         print(response) | ||||
|  | ||||
|         pong_waiter = await websocket.ping('coucou') | ||||
|         ret = await pong_waiter   # only if you want to wait for the pong | ||||
|         print(ret) | ||||
|  | ||||
| asyncio.get_event_loop().run_until_complete( | ||||
|     hello('ws://localhost:5678')) | ||||
							
								
								
									
										145
									
								
								examples/ping_pong/ping_pong.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										145
									
								
								examples/ping_pong/ping_pong.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,145 @@ | ||||
| /* | ||||
|  *  ws_connect.cpp | ||||
|  *  Author: Benjamin Sergeant | ||||
|  *  Copyright (c) 2017-2018 Machine Zone, Inc. All rights reserved. | ||||
|  */ | ||||
|  | ||||
| #include <iostream> | ||||
| #include <sstream> | ||||
| #include <ixwebsocket/IXWebSocket.h> | ||||
| #include <ixwebsocket/IXSocket.h> | ||||
|  | ||||
| using namespace ix; | ||||
|  | ||||
| namespace | ||||
| { | ||||
|     void log(const std::string& msg) | ||||
|     { | ||||
|         std::cout << msg << std::endl; | ||||
|     } | ||||
|  | ||||
|     class WebSocketPingPong | ||||
|     { | ||||
|         public: | ||||
|             WebSocketPingPong(const std::string& _url); | ||||
|  | ||||
|             void subscribe(const std::string& channel); | ||||
|             void start(); | ||||
|             void stop(); | ||||
|  | ||||
|             void ping(const std::string& text); | ||||
|  | ||||
|         private: | ||||
|             std::string _url; | ||||
|             ix::WebSocket _webSocket; | ||||
|     }; | ||||
|  | ||||
|     WebSocketPingPong::WebSocketPingPong(const std::string& url) : | ||||
|         _url(url) | ||||
|     { | ||||
|         ; | ||||
|     } | ||||
|  | ||||
|     void WebSocketPingPong::stop() | ||||
|     { | ||||
|         _webSocket.stop(); | ||||
|     } | ||||
|  | ||||
|     void WebSocketPingPong::start() | ||||
|     { | ||||
|         _webSocket.configure(_url); | ||||
|  | ||||
|         std::stringstream ss; | ||||
|         log(std::string("Connecting to url: ") + _url); | ||||
|  | ||||
|         _webSocket.setOnMessageCallback( | ||||
|             [this](ix::WebSocketMessageType messageType, const std::string& str, ix::WebSocketErrorInfo error) | ||||
|             { | ||||
|                 std::stringstream ss; | ||||
|                 if (messageType == ix::WebSocket_MessageType_Open) | ||||
|                 { | ||||
|                     log("ws_connect: connected"); | ||||
|                 } | ||||
|                 else if (messageType == ix::WebSocket_MessageType_Close) | ||||
|                 { | ||||
|                     log("ws_connect: disconnected"); | ||||
|                 } | ||||
|                 else if (messageType == ix::WebSocket_MessageType_Message) | ||||
|                 { | ||||
|                     ss << "ws_connect: received message: " | ||||
|                        << str; | ||||
|                     log(ss.str()); | ||||
|                 } | ||||
|                 else if (messageType == ix::WebSocket_MessageType_Ping) | ||||
|                 { | ||||
|                     ss << "ws_connect: received ping message: " | ||||
|                        << str; | ||||
|                     log(ss.str()); | ||||
|                 } | ||||
|                 else if (messageType == ix::WebSocket_MessageType_Pong) | ||||
|                 { | ||||
|                     ss << "ws_connect: received pong message: " | ||||
|                        << str; | ||||
|                     log(ss.str()); | ||||
|                 } | ||||
|                 else if (messageType == ix::WebSocket_MessageType_Error) | ||||
|                 { | ||||
|                     ss << "Connection error: " << error.reason      << std::endl; | ||||
|                     ss << "#retries: "         << error.retries     << std::endl; | ||||
|                     ss << "Wait time(ms): "    << error.wait_time   << std::endl; | ||||
|                     ss << "HTTP Status: "      << error.http_status << std::endl; | ||||
|                     log(ss.str()); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     ss << "Invalid ix::WebSocketMessageType"; | ||||
|                     log(ss.str()); | ||||
|                 } | ||||
|             }); | ||||
|  | ||||
|         _webSocket.start(); | ||||
|     } | ||||
|  | ||||
|     void WebSocketPingPong::ping(const std::string& text) | ||||
|     { | ||||
|         _webSocket.ping(text); | ||||
|     } | ||||
|  | ||||
|     void interactiveMain(const std::string& url) | ||||
|     { | ||||
|         std::cout << "Type Ctrl-D to exit prompt..." << std::endl; | ||||
|         WebSocketPingPong webSocketPingPong(url); | ||||
|         webSocketPingPong.start(); | ||||
|  | ||||
|         while (true) | ||||
|         { | ||||
|             std::string text; | ||||
|             std::cout << "> " << std::flush; | ||||
|             std::getline(std::cin, text); | ||||
|  | ||||
|             if (!std::cin) | ||||
|             { | ||||
|                 break; | ||||
|             } | ||||
|  | ||||
|             webSocketPingPong.ping(text); | ||||
|         } | ||||
|  | ||||
|         std::cout << std::endl; | ||||
|         webSocketPingPong.stop(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| int main(int argc, char** argv) | ||||
| { | ||||
|     if (argc != 2) | ||||
|     { | ||||
|         std::cerr << "Usage: ping_pong <url>" << std::endl; | ||||
|         return 1; | ||||
|     } | ||||
|     std::string url = argv[1]; | ||||
|  | ||||
|     Socket::init(); | ||||
|     interactiveMain(url); | ||||
|     return 0; | ||||
| } | ||||
							
								
								
									
										13
									
								
								examples/ping_pong/server.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								examples/ping_pong/server.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| #!/usr/bin/env python | ||||
|  | ||||
| import asyncio | ||||
| import websockets | ||||
|  | ||||
| async def echo(websocket, path): | ||||
|     async for message in websocket: | ||||
|         print(message) | ||||
|         await websocket.send(message) | ||||
|  | ||||
| asyncio.get_event_loop().run_until_complete( | ||||
|     websockets.serve(echo, 'localhost', 5678)) | ||||
| asyncio.get_event_loop().run_forever() | ||||
							
								
								
									
										9
									
								
								examples/ping_pong/test.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								examples/ping_pong/test.sh
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| #!/bin/sh | ||||
|  | ||||
| test -d build || { | ||||
|     mkdir -p build | ||||
|     cd build | ||||
|     cmake .. | ||||
| } | ||||
| (cd build ; make) | ||||
| ./build/ping_pong ws://localhost:5678 | ||||
							
								
								
									
										27
									
								
								examples/ws_connect/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								examples/ws_connect/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| # | ||||
| # Author: Benjamin Sergeant | ||||
| # Copyright (c) 2018 Machine Zone, Inc. All rights reserved. | ||||
| # | ||||
|  | ||||
| cmake_minimum_required (VERSION 3.4.1) | ||||
| project (ws_connect) | ||||
|  | ||||
| set (CMAKE_CXX_STANDARD 11) | ||||
|  | ||||
| option(USE_TLS "Add TLS support" ON) | ||||
|  | ||||
| add_subdirectory(${PROJECT_SOURCE_DIR}/../.. ixwebsocket) | ||||
|  | ||||
| add_executable(ws_connect ws_connect.cpp) | ||||
|  | ||||
| if (APPLE AND USE_TLS) | ||||
|     target_link_libraries(ws_connect "-framework foundation" "-framework security") | ||||
| endif() | ||||
|  | ||||
| if (WIN32) | ||||
|     target_link_libraries(ws_connect wsock32 ws2_32) | ||||
|     add_definitions(-D_CRT_SECURE_NO_WARNINGS) | ||||
| endif() | ||||
|  | ||||
| target_link_libraries(ws_connect ixwebsocket) | ||||
| install(TARGETS ws_connect DESTINATION bin) | ||||
							
								
								
									
										11
									
								
								examples/ws_connect/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								examples/ws_connect/README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| # Building | ||||
|  | ||||
| 1. mkdir build | ||||
| 2. cd build | ||||
| 3. cmake .. | ||||
| 4. make | ||||
|  | ||||
| ## Disable TLS | ||||
|  | ||||
| * Enable: `cmake -DUSE_TLS=OFF ..` | ||||
| * Disable: `cmake -DUSE_TLS=ON ..` | ||||
							
								
								
									
										133
									
								
								examples/ws_connect/ws_connect.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								examples/ws_connect/ws_connect.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,133 @@ | ||||
| /* | ||||
|  *  ws_connect.cpp | ||||
|  *  Author: Benjamin Sergeant | ||||
|  *  Copyright (c) 2017-2018 Machine Zone, Inc. All rights reserved. | ||||
|  */ | ||||
|  | ||||
| #include <iostream> | ||||
| #include <sstream> | ||||
| #include <ixwebsocket/IXWebSocket.h> | ||||
| #include <ixwebsocket/IXSocket.h> | ||||
|  | ||||
| using namespace ix; | ||||
|  | ||||
| namespace | ||||
| { | ||||
|     void log(const std::string& msg) | ||||
|     { | ||||
|         std::cout << msg << std::endl; | ||||
|     } | ||||
|  | ||||
|     class WebSocketConnect | ||||
|     { | ||||
|         public: | ||||
|             WebSocketConnect(const std::string& _url); | ||||
|  | ||||
|             void subscribe(const std::string& channel); | ||||
|             void start(); | ||||
|             void stop(); | ||||
|  | ||||
|             void sendMessage(const std::string& text); | ||||
|  | ||||
|         private: | ||||
|             std::string _url; | ||||
|             ix::WebSocket _webSocket; | ||||
|     }; | ||||
|  | ||||
|     WebSocketConnect::WebSocketConnect(const std::string& url) : | ||||
|         _url(url) | ||||
|     { | ||||
|         ; | ||||
|     } | ||||
|  | ||||
|     void WebSocketConnect::stop() | ||||
|     { | ||||
|         _webSocket.stop(); | ||||
|     } | ||||
|  | ||||
|     void WebSocketConnect::start() | ||||
|     { | ||||
|         _webSocket.configure(_url); | ||||
|  | ||||
|         std::stringstream ss; | ||||
|         log(std::string("Connecting to url: ") + _url); | ||||
|  | ||||
|         _webSocket.setOnMessageCallback( | ||||
|             [this](ix::WebSocketMessageType messageType, const std::string& str, ix::WebSocketErrorInfo error) | ||||
|             { | ||||
|                 std::stringstream ss; | ||||
|                 if (messageType == ix::WebSocket_MessageType_Open) | ||||
|                 { | ||||
|                     log("ws_connect: connected"); | ||||
|                 } | ||||
|                 else if (messageType == ix::WebSocket_MessageType_Close) | ||||
|                 { | ||||
|                     log("ws_connect: disconnected"); | ||||
|                 } | ||||
|                 else if (messageType == ix::WebSocket_MessageType_Message) | ||||
|                 { | ||||
|                     ss << "ws_connect: received message: " | ||||
|                        << str; | ||||
|                     log(ss.str()); | ||||
|                 } | ||||
|                 else if (messageType == ix::WebSocket_MessageType_Error) | ||||
|                 { | ||||
|                     ss << "Connection error: " << error.reason      << std::endl; | ||||
|                     ss << "#retries: "         << error.retries     << std::endl; | ||||
|                     ss << "Wait time(ms): "    << error.wait_time   << std::endl; | ||||
|                     ss << "HTTP Status: "      << error.http_status << std::endl; | ||||
|                     log(ss.str()); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     ss << "Invalid ix::WebSocketMessageType"; | ||||
|                     log(ss.str()); | ||||
|                 } | ||||
|             }); | ||||
|  | ||||
|         _webSocket.start(); | ||||
|     } | ||||
|  | ||||
|     void WebSocketConnect::sendMessage(const std::string& text) | ||||
|     { | ||||
|         _webSocket.send(text); | ||||
|     } | ||||
|  | ||||
|     void interactiveMain(const std::string& url) | ||||
|     { | ||||
|         std::cout << "Type Ctrl-D to exit prompt..." << std::endl; | ||||
|         WebSocketConnect webSocketChat(url); | ||||
|         webSocketChat.start(); | ||||
|  | ||||
|         while (true) | ||||
|         { | ||||
|             std::string text; | ||||
|             std::cout << "> " << std::flush; | ||||
|             std::getline(std::cin, text); | ||||
|  | ||||
|             if (!std::cin) | ||||
|             { | ||||
|                 break; | ||||
|             } | ||||
|  | ||||
|             webSocketChat.sendMessage(text); | ||||
|         } | ||||
|  | ||||
|         std::cout << std::endl; | ||||
|         webSocketChat.stop(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| int main(int argc, char** argv) | ||||
| { | ||||
|     if (argc != 2) | ||||
|     { | ||||
|         std::cerr << "Usage: ws_connect <url>" << std::endl; | ||||
|         return 1; | ||||
|     } | ||||
|     std::string url = argv[1]; | ||||
|  | ||||
|     Socket::init(); | ||||
|     interactiveMain(url); | ||||
|     return 0; | ||||
| } | ||||
| @@ -301,4 +301,9 @@ namespace ix | ||||
|         WSACleanup(); | ||||
| #endif | ||||
|     } | ||||
|  | ||||
|     void Socket::secureSocket() | ||||
|     { | ||||
|         ; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -40,6 +40,8 @@ namespace ix | ||||
|         virtual int send(const std::string& buffer); | ||||
|         virtual int recv(void* buffer, size_t length); | ||||
|  | ||||
|         virtual void secureSocket(); // Windows | ||||
|  | ||||
|         int getErrno() const; | ||||
|         static bool init(); // Required on Windows to initialize WinSocket | ||||
|         static void cleanup(); // Required on Windows to cleanup WinSocket | ||||
|   | ||||
							
								
								
									
										108
									
								
								ixwebsocket/IXSocketSChannel.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								ixwebsocket/IXSocketSChannel.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,108 @@ | ||||
| /* | ||||
|  *  IXSocketSChannel.cpp | ||||
|  *  Author: Benjamin Sergeant | ||||
|  *  Copyright (c) 2018 Machine Zone, Inc. All rights reserved. | ||||
|  * | ||||
|  *  See https://docs.microsoft.com/en-us/windows/desktop/WinSock/using-secure-socket-extensions | ||||
|  * | ||||
|  *  https://github.com/pauldotknopf/WindowsSDK7-Samples/blob/master/netds/winsock/securesocket/stcpclient/tcpclient.c | ||||
|  * | ||||
|  *  This is the right example to look at: | ||||
|  *  https://www.codeproject.com/Articles/1000189/A-Working-TCP-Client-and-Server-With-SSL | ||||
|  */ | ||||
| #include "IXSocketSChannel.h" | ||||
|  | ||||
| #ifdef _WIN32 | ||||
| # include <basetsd.h> | ||||
| # include <WinSock2.h> | ||||
| # include <ws2def.h> | ||||
| # include <WS2tcpip.h> | ||||
| # include <schannel.h> | ||||
| # include <sslsock.h> | ||||
| # include <io.h> | ||||
|  | ||||
| #define WIN32_LEAN_AND_MEAN | ||||
|  | ||||
| #ifndef UNICODE | ||||
| #define UNICODE | ||||
| #endif | ||||
|  | ||||
| #include <windows.h> | ||||
| #include <winsock2.h> | ||||
| #include <mstcpip.h> | ||||
| #include <ws2tcpip.h> | ||||
| #include <rpc.h> | ||||
| #include <ntdsapi.h> | ||||
| #include <stdio.h> | ||||
| #include <tchar.h> | ||||
|  | ||||
| #define RECV_DATA_BUF_SIZE 256 | ||||
|  | ||||
| // Link with ws2_32.lib | ||||
| #pragma comment(lib, "Ws2_32.lib") | ||||
|  | ||||
| // link with fwpuclnt.lib for Winsock secure socket extensions | ||||
| #pragma comment(lib, "fwpuclnt.lib") | ||||
|  | ||||
| // link with ntdsapi.lib for DsMakeSpn function | ||||
| #pragma comment(lib, "ntdsapi.lib") | ||||
|  | ||||
| // The following function assumes that Winsock  | ||||
| // has already been initialized | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| #else | ||||
| # error("This file should only be built on Windows") | ||||
| #endif | ||||
|  | ||||
| namespace ix  | ||||
| { | ||||
|     SocketSChannel::SocketSChannel() | ||||
|     { | ||||
|         ; | ||||
|     } | ||||
|  | ||||
|     SocketSChannel::~SocketSChannel() | ||||
|     { | ||||
|          | ||||
|     } | ||||
|  | ||||
|     bool SocketSChannel::connect(const std::string& host, | ||||
|                                  int port, | ||||
|                                  std::string& errMsg) | ||||
|     { | ||||
|         return Socket::connect(host, port, errMsg); | ||||
|     } | ||||
|  | ||||
|      | ||||
|     void SocketSChannel::secureSocket() | ||||
|     { | ||||
|         // there will be a lot to do here ... | ||||
|         // FIXME do something with sockerror | ||||
|     } | ||||
|  | ||||
|     void SocketSChannel::close() | ||||
|     { | ||||
|         Socket::close(); | ||||
|     } | ||||
|  | ||||
|     int SocketSChannel::send(char* buf, size_t nbyte) | ||||
|     { | ||||
|         return Socket::send(buf, nbyte); | ||||
|     } | ||||
|  | ||||
|     int SocketSChannel::send(const std::string& buffer) | ||||
|     { | ||||
|         return Socket::send(buffer); | ||||
|     } | ||||
|  | ||||
|     int SocketSChannel::recv(void* buf, size_t nbyte) | ||||
|     { | ||||
|         return Socket::recv(buf, nbyte); | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										34
									
								
								ixwebsocket/IXSocketSChannel.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								ixwebsocket/IXSocketSChannel.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| /* | ||||
|  *  IXSocketSChannel.h | ||||
|  *  Author: Benjamin Sergeant | ||||
|  *  Copyright (c) 2017-2018 Machine Zone, Inc. All rights reserved. | ||||
|  */ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "IXSocket.h" | ||||
|  | ||||
| namespace ix  | ||||
| { | ||||
|     class SocketSChannel : public Socket  | ||||
|     { | ||||
|     public: | ||||
|         SocketSChannel(); | ||||
|         ~SocketSChannel(); | ||||
|  | ||||
|         virtual bool connect(const std::string& host,  | ||||
|                              int port, | ||||
|                              std::string& errMsg) final; | ||||
|         virtual void close() final; | ||||
|  | ||||
|         // The important override | ||||
|         virtual void secureSocket() final; | ||||
|  | ||||
|         virtual int send(char* buffer, size_t length) final; | ||||
|         virtual int send(const std::string& buffer) final; | ||||
|         virtual int recv(void* buffer, size_t length) final; | ||||
|  | ||||
|     private: | ||||
|     }; | ||||
|  | ||||
| } | ||||
| @@ -177,9 +177,29 @@ namespace ix { | ||||
|  | ||||
|             // 3. Dispatch the incoming messages | ||||
|             _ws.dispatch( | ||||
|                 [this](const std::string& msg) | ||||
|                 [this](const std::string& msg, | ||||
|                        WebSocketTransport::MessageKind messageKind) | ||||
|                 { | ||||
|                     _onMessageCallback(WebSocket_MessageType_Message, msg, WebSocketErrorInfo()); | ||||
|                     WebSocketMessageType webSocketMessageType; | ||||
|                     switch (messageKind) | ||||
|                     { | ||||
|                         case WebSocketTransport::MSG: | ||||
|                         { | ||||
|                             webSocketMessageType = WebSocket_MessageType_Message; | ||||
|                         } break; | ||||
|  | ||||
|                         case WebSocketTransport::PING: | ||||
|                         { | ||||
|                             webSocketMessageType = WebSocket_MessageType_Ping; | ||||
|                         } break; | ||||
|  | ||||
|                         case WebSocketTransport::PONG: | ||||
|                         { | ||||
|                             webSocketMessageType = WebSocket_MessageType_Pong; | ||||
|                         } break; | ||||
|                     } | ||||
|  | ||||
|                     _onMessageCallback(webSocketMessageType, msg, WebSocketErrorInfo()); | ||||
|  | ||||
|                     WebSocket::invokeTrafficTrackerCallback(msg.size(), true); | ||||
|                 }); | ||||
| @@ -210,6 +230,20 @@ namespace ix { | ||||
|     } | ||||
|  | ||||
|     bool WebSocket::send(const std::string& text) | ||||
|     { | ||||
|         return sendMessage(text, false); | ||||
|     } | ||||
|  | ||||
|     bool WebSocket::ping(const std::string& text) | ||||
|     { | ||||
|         // Standard limit ping message size | ||||
|         constexpr size_t pingMaxPayloadSize = 125; | ||||
|         if (text.size() > pingMaxPayloadSize) return false; | ||||
|  | ||||
|         return sendMessage(text, true); | ||||
|     } | ||||
|  | ||||
|     bool WebSocket::sendMessage(const std::string& text, bool ping) | ||||
|     { | ||||
|         if (!isConnected()) return false; | ||||
|  | ||||
| @@ -223,7 +257,15 @@ namespace ix { | ||||
|         // incoming messages are arriving / there's data to be received. | ||||
|         // | ||||
|         std::lock_guard<std::mutex> lock(_writeMutex); | ||||
|         _ws.sendBinary(text); | ||||
|  | ||||
|         if (ping) | ||||
|         { | ||||
|             _ws.sendPing(text); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             _ws.sendBinary(text); | ||||
|         } | ||||
|  | ||||
|         WebSocket::invokeTrafficTrackerCallback(text.size(), false); | ||||
|  | ||||
|   | ||||
| @@ -32,7 +32,9 @@ namespace ix | ||||
|         WebSocket_MessageType_Message = 0, | ||||
|         WebSocket_MessageType_Open = 1, | ||||
|         WebSocket_MessageType_Close = 2, | ||||
|         WebSocket_MessageType_Error = 3 | ||||
|         WebSocket_MessageType_Error = 3, | ||||
|         WebSocket_MessageType_Ping = 4, | ||||
|         WebSocket_MessageType_Pong = 5 | ||||
|     }; | ||||
|  | ||||
|     struct WebSocketErrorInfo | ||||
| @@ -56,6 +58,7 @@ namespace ix | ||||
|         void start(); | ||||
|         void stop(); | ||||
|         bool send(const std::string& text); | ||||
|         bool ping(const std::string& text); | ||||
|         void close(); | ||||
|  | ||||
|         void setOnMessageCallback(const OnMessageCallback& callback); | ||||
| @@ -70,6 +73,8 @@ namespace ix | ||||
|     private: | ||||
|         void run(); | ||||
|  | ||||
|         bool sendMessage(const std::string& text, bool ping); | ||||
|  | ||||
|         WebSocketInitResult connect(); | ||||
|         bool isConnected() const; | ||||
|         bool isClosing() const; | ||||
|   | ||||
| @@ -14,12 +14,13 @@ | ||||
| #ifdef IXWEBSOCKET_USE_TLS | ||||
| # ifdef __APPLE__ | ||||
| #  include "IXSocketAppleSSL.h" | ||||
| # else | ||||
| # elif defined(__linux__) | ||||
| #  include "IXSocketOpenSSL.h" | ||||
| # elif defined(_WIN32) | ||||
| #  include "IXSocketSChannel.h" | ||||
| # endif | ||||
| #endif | ||||
|  | ||||
| // #include <unistd.h> | ||||
| #include <string.h> | ||||
| #include <stdlib.h> | ||||
|  | ||||
| @@ -145,8 +146,10 @@ namespace ix { | ||||
| #ifdef IXWEBSOCKET_USE_TLS | ||||
| # ifdef __APPLE__ | ||||
|              _socket = std::make_shared<SocketAppleSSL>(); | ||||
| # else | ||||
| # elif defined(__linux__) | ||||
|              _socket = std::make_shared<SocketOpenSSL>(); | ||||
| # elif defined(_WIN32) | ||||
|              _socket = std::make_shared<SocketSChannel>(); | ||||
| # endif | ||||
| #else | ||||
|             return WebSocketInitResult(false, 0, "TLS is not supported."); | ||||
| @@ -449,7 +452,7 @@ namespace ix { | ||||
|                     // fire callback with a string message | ||||
|                     std::string stringMessage(_receivedData.begin(), | ||||
|                                               _receivedData.end()); | ||||
|                     onMessageCallback(stringMessage); | ||||
|                     onMessageCallback(stringMessage, MSG); | ||||
|  | ||||
|                     _receivedData.clear(); | ||||
|                 } | ||||
| @@ -467,10 +470,27 @@ namespace ix { | ||||
|                 std::string pingData(_rxbuf.begin()+ws.header_size, | ||||
|                                      _rxbuf.begin()+ws.header_size + (size_t) ws.N); | ||||
|  | ||||
|                 // Reply back right away | ||||
|                 sendData(wsheader_type::PONG, pingData.size(), | ||||
|                          pingData.begin(), pingData.end()); | ||||
|  | ||||
|                 onMessageCallback(pingData, PING); | ||||
|             } | ||||
|             else if (ws.opcode == wsheader_type::PONG) | ||||
|             { | ||||
|                 if (ws.mask) | ||||
|                 { | ||||
|                     for (size_t j = 0; j != ws.N; ++j) | ||||
|                     { | ||||
|                         _rxbuf[j+ws.header_size] ^= ws.masking_key[j&0x3]; | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 std::string pongData(_rxbuf.begin()+ws.header_size, | ||||
|                                      _rxbuf.begin()+ws.header_size + (size_t) ws.N); | ||||
|  | ||||
|                 onMessageCallback(pongData, PONG); | ||||
|             } | ||||
|             else if (ws.opcode == wsheader_type::PONG) { } | ||||
|             else if (ws.opcode == wsheader_type::CLOSE) { close(); } | ||||
|             else { close(); } | ||||
|  | ||||
| @@ -556,10 +576,9 @@ namespace ix { | ||||
|         sendOnSocket(); | ||||
|     } | ||||
|  | ||||
|     void WebSocketTransport::sendPing() | ||||
|     void WebSocketTransport::sendPing(const std::string& message) | ||||
|     { | ||||
|         std::string empty; | ||||
|         sendData(wsheader_type::PING, empty.size(), empty.begin(), empty.end()); | ||||
|         sendData(wsheader_type::PING, message.size(), message.begin(), message.end()); | ||||
|     } | ||||
|  | ||||
|     void WebSocketTransport::sendBinary(const std::string& message)  | ||||
|   | ||||
| @@ -54,7 +54,15 @@ namespace ix | ||||
|             OPEN | ||||
|         }; | ||||
|  | ||||
|         using OnMessageCallback = std::function<void(const std::string&)>; | ||||
|         enum MessageKind | ||||
|         { | ||||
|             MSG, | ||||
|             PING, | ||||
|             PONG | ||||
|         }; | ||||
|  | ||||
|         using OnMessageCallback = std::function<void(const std::string&, | ||||
|                                                      MessageKind)>; | ||||
|         using OnStateChangeCallback = std::function<void(ReadyStateValues)>; | ||||
|  | ||||
|         WebSocketTransport(); | ||||
| @@ -67,7 +75,7 @@ namespace ix | ||||
|         void send(const std::string& message); | ||||
|         void sendBinary(const std::string& message); | ||||
|         void sendBinary(const std::vector<uint8_t>& message); | ||||
|         void sendPing(); | ||||
|         void sendPing(const std::string& message); | ||||
|         void close(); | ||||
|         ReadyStateValues getReadyState() const; | ||||
|         void setReadyState(ReadyStateValues readyStateValue); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user