From 72997ae496930498ad87f89ee24f6d6ecc662fa3 Mon Sep 17 00:00:00 2001 From: "Julio C. Rocha" Date: Wed, 8 May 2019 20:28:15 -0700 Subject: [PATCH 01/30] package.json newline. --- vnext/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vnext/package.json b/vnext/package.json index 829cc21a3d1..e7591d25142 100644 --- a/vnext/package.json +++ b/vnext/package.json @@ -65,4 +65,4 @@ "react": "16.6.3", "react-native": "0.58.6-microsoft.34 || https://github.com/Microsoft/react-native/archive/v0.58.6-microsoft.34.tar.gz" } -} \ No newline at end of file +} From 4dc899fe68e13570f4b5f8ca140cde8c887ad0f6 Mon Sep 17 00:00:00 2001 From: "Julio C. Rocha" Date: Thu, 9 May 2019 00:07:02 -0700 Subject: [PATCH 02/30] Declare WebSocketServer. --- ...t.Windows.Desktop.IntegrationTests.vcxproj | 2 + ...s.Desktop.IntegrationTests.vcxproj.filters | 6 +++ .../WebSocketServer.cpp | 46 +++++++++++++++++++ .../WebSocketServer.h | 31 +++++++++++++ 4 files changed, 85 insertions(+) create mode 100644 vnext/Desktop.IntegrationTests/WebSocketServer.cpp create mode 100644 vnext/Desktop.IntegrationTests/WebSocketServer.h diff --git a/vnext/Desktop.IntegrationTests/React.Windows.Desktop.IntegrationTests.vcxproj b/vnext/Desktop.IntegrationTests/React.Windows.Desktop.IntegrationTests.vcxproj index abdaec014fd..4d1dfbaaf11 100644 --- a/vnext/Desktop.IntegrationTests/React.Windows.Desktop.IntegrationTests.vcxproj +++ b/vnext/Desktop.IntegrationTests/React.Windows.Desktop.IntegrationTests.vcxproj @@ -101,6 +101,7 @@ + @@ -128,6 +129,7 @@ + diff --git a/vnext/Desktop.IntegrationTests/React.Windows.Desktop.IntegrationTests.vcxproj.filters b/vnext/Desktop.IntegrationTests/React.Windows.Desktop.IntegrationTests.vcxproj.filters index a18d347868a..3191d8efa0f 100644 --- a/vnext/Desktop.IntegrationTests/React.Windows.Desktop.IntegrationTests.vcxproj.filters +++ b/vnext/Desktop.IntegrationTests/React.Windows.Desktop.IntegrationTests.vcxproj.filters @@ -45,6 +45,9 @@ Integration Tests + + Source Files + @@ -53,5 +56,8 @@ Header Files + + Header Files + \ No newline at end of file diff --git a/vnext/Desktop.IntegrationTests/WebSocketServer.cpp b/vnext/Desktop.IntegrationTests/WebSocketServer.cpp new file mode 100644 index 00000000000..bd4b2b59a68 --- /dev/null +++ b/vnext/Desktop.IntegrationTests/WebSocketServer.cpp @@ -0,0 +1,46 @@ +#include "WebSocketServer.h" + +using boost::asio::ip::tcp; +using boost::system::error_code; + +namespace Microsoft { +namespace React { +namespace Test { + +#pragma region WebSocketServer + +WebSocketServer::WebSocketServer(uint16_t port) + : m_acceptor{ m_context } + , m_socket{ m_context } +{ + tcp::endpoint ep{boost::asio::ip::make_address("0.0.0.0"), port }; + error_code ec; + + m_acceptor.open(ep.protocol(), ec); + if (ec) + { + return; // + } + + m_acceptor.set_option(boost::asio::socket_base::reuse_address(true), ec); + if (ec) + { + return; // + } + + m_acceptor.bind(ep, ec); + if (ec) + { + return; // + } + + m_acceptor.listen(boost::asio::socket_base::max_listen_connections, ec); + if (ec) + { + return; // + } +} + +#pragma endregion // WebSocketServer + +} } } // Microsoft::React::Test diff --git a/vnext/Desktop.IntegrationTests/WebSocketServer.h b/vnext/Desktop.IntegrationTests/WebSocketServer.h new file mode 100644 index 00000000000..ba13ee76e61 --- /dev/null +++ b/vnext/Desktop.IntegrationTests/WebSocketServer.h @@ -0,0 +1,31 @@ +#pragma once + +#include +#include + +namespace Microsoft { +namespace React { +namespace Test { + +class WebSocketSession : std::enable_shared_from_this +{ + boost::asio::io_context& m_context; + +public: + WebSocketSession(boost::asio::io_context& context); +}; + +class WebSocketServer : public std::enable_shared_from_this +{ + std::thread m_contextThread; + boost::asio::io_context m_context; + boost::asio::ip::tcp::acceptor m_acceptor; + boost::asio::ip::tcp::socket m_socket; + +public: + WebSocketServer(std::uint16_t port); + + void Start(); +}; + +} } } // Microsoft::React::Test From 218ac7132219750e9c3e483b8e3d1f56d1dc293a Mon Sep 17 00:00:00 2001 From: "Julio C. Rocha" Date: Thu, 9 May 2019 19:10:58 -0700 Subject: [PATCH 03/30] Implement server and session read/write cycle. --- .../WebSocketServer.cpp | 107 +++++++++++++++++- .../WebSocketServer.h | 26 ++++- 2 files changed, 128 insertions(+), 5 deletions(-) diff --git a/vnext/Desktop.IntegrationTests/WebSocketServer.cpp b/vnext/Desktop.IntegrationTests/WebSocketServer.cpp index bd4b2b59a68..a60ad8c5b10 100644 --- a/vnext/Desktop.IntegrationTests/WebSocketServer.cpp +++ b/vnext/Desktop.IntegrationTests/WebSocketServer.cpp @@ -1,19 +1,90 @@ #include "WebSocketServer.h" -using boost::asio::ip::tcp; +#include + +using namespace boost::asio; + using boost::system::error_code; namespace Microsoft { namespace React { namespace Test { +#pragma region WebSocketSession + +WebSocketSession::WebSocketSession(io_context& context) + : m_context{ context } + , m_stream{ context } + , m_strand{ m_stream.get_executor() } +{ +} + +WebSocketSession::WebSocketSession(io_context& context, ip::tcp::socket socket) + : m_context{ context } + , m_stream{ std::move(socket) } + , m_strand{ m_stream.get_executor() } +{ +} + +void WebSocketSession::Start() +{ + m_stream.async_accept(bind_executor(m_strand, std::bind(&WebSocketSession::OnAccept, shared_from_this(), std::placeholders::_1))); +} + +void WebSocketSession::OnAccept(error_code ec) +{ + if (ec) + return;//TODO: fail + + Read(); +} + +void WebSocketSession::Read() +{ + m_stream.async_read(m_buffer, bind_executor(m_strand, std::bind( + &WebSocketSession::OnRead, + shared_from_this(), + std::placeholders::_1, + std::placeholders::_2 + ))); +} + +void WebSocketSession::OnRead(error_code ec, size_t /*transferred*/) +{ + if (boost::beast::websocket::error::closed == ec) + return; + + if (ec) + ;//TODO: fail + + m_stream.text(m_stream.got_text()); + m_stream.async_write(m_buffer.data(), bind_executor(m_strand, std::bind( + &WebSocketSession::OnWrite, + shared_from_this(), + std::placeholders::_1, + std::placeholders::_2 + ))); +} + +void WebSocketSession::OnWrite(error_code ec, size_t /*transferred*/) +{ + if (ec) + return; //TODO: fail + + m_buffer.consume(m_buffer.size()); + + Read(); +} + +#pragma endregion // WebSocketSession + #pragma region WebSocketServer WebSocketServer::WebSocketServer(uint16_t port) : m_acceptor{ m_context } , m_socket{ m_context } { - tcp::endpoint ep{boost::asio::ip::make_address("0.0.0.0"), port }; + ip::tcp::endpoint ep{ip::make_address("0.0.0.0"), port }; error_code ec; m_acceptor.open(ep.protocol(), ec); @@ -22,7 +93,7 @@ WebSocketServer::WebSocketServer(uint16_t port) return; // } - m_acceptor.set_option(boost::asio::socket_base::reuse_address(true), ec); + m_acceptor.set_option(socket_base::reuse_address(true), ec); if (ec) { return; // @@ -34,11 +105,39 @@ WebSocketServer::WebSocketServer(uint16_t port) return; // } - m_acceptor.listen(boost::asio::socket_base::max_listen_connections, ec); + m_acceptor.listen(socket_base::max_listen_connections, ec); if (ec) { return; // } +} // constructor(uint16_t) + +void WebSocketServer::Start() +{ + if (!m_acceptor.is_open()) + return; + + Accept(); +} + +void WebSocketServer::Accept() +{ + m_acceptor.async_accept(m_socket, std::bind(&WebSocketServer::OnAccept, shared_from_this(), std::placeholders::_1)); +} + +void WebSocketServer::OnAccept(error_code ec) +{ + if (ec) + { + //TODO: fail + } + else + { + std::make_shared(m_context, std::move(m_socket))->Start(); + } + + //TODO: Accept again. + //Accept(); } #pragma endregion // WebSocketServer diff --git a/vnext/Desktop.IntegrationTests/WebSocketServer.h b/vnext/Desktop.IntegrationTests/WebSocketServer.h index ba13ee76e61..6a75557180a 100644 --- a/vnext/Desktop.IntegrationTests/WebSocketServer.h +++ b/vnext/Desktop.IntegrationTests/WebSocketServer.h @@ -1,6 +1,8 @@ #pragma once +#include #include +#include #include namespace Microsoft { @@ -10,9 +12,27 @@ namespace Test { class WebSocketSession : std::enable_shared_from_this { boost::asio::io_context& m_context; + boost::beast::websocket::stream m_stream; + boost::asio::strand m_strand; + boost::beast::multi_buffer m_buffer; + + std::function m_connectHandler; + std::function m_pingHandler; + std::function m_writeHandler; + std::function m_readHandler; + std::function m_closeHandler; + std::function m_errorHandler; public: - WebSocketSession(boost::asio::io_context& context); + WebSocketSession(boost::asio::io_context& context);//TODO: Remove? + WebSocketSession(boost::asio::io_context& context, boost::asio::ip::tcp::socket socket); + + void Start(); + void Read(); + + void OnAccept(boost::system::error_code ec); + void OnRead(boost::system::error_code ec, std::size_t transferred); + void OnWrite(boost::system::error_code ec, std::size_t transferred); }; class WebSocketServer : public std::enable_shared_from_this @@ -22,6 +42,10 @@ class WebSocketServer : public std::enable_shared_from_this boost::asio::ip::tcp::acceptor m_acceptor; boost::asio::ip::tcp::socket m_socket; + void Accept(); + + void OnAccept(boost::system::error_code ec); + public: WebSocketServer(std::uint16_t port); From e54b33c51453d4ee3cdf34f49c6123e34276ba74 Mon Sep 17 00:00:00 2001 From: "Julio C. Rocha" Date: Thu, 9 May 2019 19:29:48 -0700 Subject: [PATCH 04/30] Implemented WebSocketServer::Stop. --- .../WebSocketIntegrationTest.cpp | 14 ++++++++++++- .../WebSocketServer.cpp | 20 ++++++++++++++++++- .../WebSocketServer.h | 2 ++ 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/vnext/Desktop.IntegrationTests/WebSocketIntegrationTest.cpp b/vnext/Desktop.IntegrationTests/WebSocketIntegrationTest.cpp index 0b722e65d93..e93b73af1e4 100644 --- a/vnext/Desktop.IntegrationTests/WebSocketIntegrationTest.cpp +++ b/vnext/Desktop.IntegrationTests/WebSocketIntegrationTest.cpp @@ -3,17 +3,19 @@ #include #include +#include #include "UnicodeConversion.h" #include #include #include -using namespace facebook::react; +using namespace Microsoft::React; using namespace Microsoft::VisualStudio::CppUnitTestFramework; using std::chrono::milliseconds; using std::condition_variable; +using std::make_shared; using std::unique_lock; using std::lock_guard; using std::promise; @@ -21,6 +23,16 @@ using std::string; TEST_CLASS(WebSocketIntegrationTest) { + TEST_METHOD(ConnectCloseInProcServer) + { + auto server = make_shared(5556); + server->Start(); + + server->Stop(); + + Assert::IsTrue(true); + } + TEST_METHOD(ConnectClose) { auto ws = IWebSocket::Make("ws://localhost:5555/"); diff --git a/vnext/Desktop.IntegrationTests/WebSocketServer.cpp b/vnext/Desktop.IntegrationTests/WebSocketServer.cpp index a60ad8c5b10..a51686f7526 100644 --- a/vnext/Desktop.IntegrationTests/WebSocketServer.cpp +++ b/vnext/Desktop.IntegrationTests/WebSocketServer.cpp @@ -55,7 +55,7 @@ void WebSocketSession::OnRead(error_code ec, size_t /*transferred*/) return; if (ec) - ;//TODO: fail + return;//TODO: fail instead m_stream.text(m_stream.got_text()); m_stream.async_write(m_buffer.data(), bind_executor(m_strand, std::bind( @@ -112,12 +112,22 @@ WebSocketServer::WebSocketServer(uint16_t port) } } // constructor(uint16_t) +WebSocketServer::WebSocketServer(int port) + : WebSocketServer(static_cast(port)) +{ +} + void WebSocketServer::Start() { if (!m_acceptor.is_open()) return; Accept(); + + m_contextThread = std::thread([self = shared_from_this()]() + { + self->m_context.run(); + }); } void WebSocketServer::Accept() @@ -125,6 +135,14 @@ void WebSocketServer::Accept() m_acceptor.async_accept(m_socket, std::bind(&WebSocketServer::OnAccept, shared_from_this(), std::placeholders::_1)); } +void WebSocketServer::Stop() +{ + m_contextThread.join(); + + if (m_acceptor.is_open()) + m_acceptor.close(); +} + void WebSocketServer::OnAccept(error_code ec) { if (ec) diff --git a/vnext/Desktop.IntegrationTests/WebSocketServer.h b/vnext/Desktop.IntegrationTests/WebSocketServer.h index 6a75557180a..dbeb4016025 100644 --- a/vnext/Desktop.IntegrationTests/WebSocketServer.h +++ b/vnext/Desktop.IntegrationTests/WebSocketServer.h @@ -48,8 +48,10 @@ class WebSocketServer : public std::enable_shared_from_this public: WebSocketServer(std::uint16_t port); + WebSocketServer(int port); void Start(); + void Stop(); }; } } } // Microsoft::React::Test From ae287dbcca409456667ee0c4acf4e2c48d61f143 Mon Sep 17 00:00:00 2001 From: "Julio C. Rocha" Date: Fri, 10 May 2019 13:02:50 -0700 Subject: [PATCH 05/30] Join worker thread after closing acceptor. --- vnext/Desktop.IntegrationTests/WebSocketServer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vnext/Desktop.IntegrationTests/WebSocketServer.cpp b/vnext/Desktop.IntegrationTests/WebSocketServer.cpp index a51686f7526..3502d94bc6a 100644 --- a/vnext/Desktop.IntegrationTests/WebSocketServer.cpp +++ b/vnext/Desktop.IntegrationTests/WebSocketServer.cpp @@ -137,10 +137,10 @@ void WebSocketServer::Accept() void WebSocketServer::Stop() { - m_contextThread.join(); - if (m_acceptor.is_open()) m_acceptor.close(); + + m_contextThread.join(); } void WebSocketServer::OnAccept(error_code ec) From c64cafc49c0affbb78bb4403bdc2855e3d5b05a7 Mon Sep 17 00:00:00 2001 From: "Julio C. Rocha" Date: Fri, 10 May 2019 18:08:45 -0700 Subject: [PATCH 06/30] Define WebSocketServiceCallbacks. --- .../WebSocketIntegrationTest.cpp | 10 ++++- .../WebSocketServer.cpp | 40 ++++++++++++++----- .../WebSocketServer.h | 24 +++++++---- 3 files changed, 54 insertions(+), 20 deletions(-) diff --git a/vnext/Desktop.IntegrationTests/WebSocketIntegrationTest.cpp b/vnext/Desktop.IntegrationTests/WebSocketIntegrationTest.cpp index e93b73af1e4..b8c3593e646 100644 --- a/vnext/Desktop.IntegrationTests/WebSocketIntegrationTest.cpp +++ b/vnext/Desktop.IntegrationTests/WebSocketIntegrationTest.cpp @@ -25,12 +25,20 @@ TEST_CLASS(WebSocketIntegrationTest) { TEST_METHOD(ConnectCloseInProcServer) { + bool connected = false; auto server = make_shared(5556); + server->SetOnConnection([&connected]() + { + connected = true; + }); server->Start(); + auto ws = IWebSocket::Make("ws://localhost:5556"); + ws->Connect(); server->Stop(); + ws->Close(IWebSocket::CloseCode::Normal, "Closing"); - Assert::IsTrue(true); + Assert::IsTrue(connected); } TEST_METHOD(ConnectClose) diff --git a/vnext/Desktop.IntegrationTests/WebSocketServer.cpp b/vnext/Desktop.IntegrationTests/WebSocketServer.cpp index 3502d94bc6a..9a5ae69a211 100644 --- a/vnext/Desktop.IntegrationTests/WebSocketServer.cpp +++ b/vnext/Desktop.IntegrationTests/WebSocketServer.cpp @@ -5,6 +5,8 @@ using namespace boost::asio; using boost::system::error_code; +using std::function; +using std::string; namespace Microsoft { namespace React { @@ -12,17 +14,10 @@ namespace Test { #pragma region WebSocketSession -WebSocketSession::WebSocketSession(io_context& context) - : m_context{ context } - , m_stream{ context } - , m_strand{ m_stream.get_executor() } -{ -} - -WebSocketSession::WebSocketSession(io_context& context, ip::tcp::socket socket) - : m_context{ context } - , m_stream{ std::move(socket) } +WebSocketSession::WebSocketSession(ip::tcp::socket socket, WebSocketServiceCallbacks& callbacks) + : m_stream{ std::move(socket) } , m_strand{ m_stream.get_executor() } + , m_callbacks{ callbacks } { } @@ -36,6 +31,9 @@ void WebSocketSession::OnAccept(error_code ec) if (ec) return;//TODO: fail + if (m_callbacks.OnConnection) + m_callbacks.OnConnection(); + Read(); } @@ -151,13 +149,33 @@ void WebSocketServer::OnAccept(error_code ec) } else { - std::make_shared(m_context, std::move(m_socket))->Start(); + std::make_shared(std::move(m_socket), m_callbacks)->Start(); } //TODO: Accept again. //Accept(); } +void WebSocketServer::SetOnConnection(function&& func) +{ + m_callbacks.OnConnection = std::move(func); +} + +void WebSocketServer::SetOnMessage(function&& func) +{ + m_callbacks.OnMessage = std::move(func); +} + +void WebSocketServer::SetMessageFactory(function&& func) +{ + m_callbacks.MessageFactory = std::move(func); +} + +void WebSocketServer::SetOnError(function&& func) +{ + m_callbacks.OnError = std::move(func); +} + #pragma endregion // WebSocketServer } } } // Microsoft::React::Test diff --git a/vnext/Desktop.IntegrationTests/WebSocketServer.h b/vnext/Desktop.IntegrationTests/WebSocketServer.h index dbeb4016025..0a001177e40 100644 --- a/vnext/Desktop.IntegrationTests/WebSocketServer.h +++ b/vnext/Desktop.IntegrationTests/WebSocketServer.h @@ -9,23 +9,25 @@ namespace Microsoft { namespace React { namespace Test { +struct WebSocketServiceCallbacks +{ + std::function OnConnection; + std::function OnMessage; + std::function MessageFactory; + std::function OnError; +}; + class WebSocketSession : std::enable_shared_from_this { - boost::asio::io_context& m_context; boost::beast::websocket::stream m_stream; boost::asio::strand m_strand; boost::beast::multi_buffer m_buffer; + WebSocketServiceCallbacks& m_callbacks; - std::function m_connectHandler; - std::function m_pingHandler; - std::function m_writeHandler; - std::function m_readHandler; - std::function m_closeHandler; std::function m_errorHandler; public: - WebSocketSession(boost::asio::io_context& context);//TODO: Remove? - WebSocketSession(boost::asio::io_context& context, boost::asio::ip::tcp::socket socket); + WebSocketSession(boost::asio::ip::tcp::socket socket, WebSocketServiceCallbacks& callbacks); void Start(); void Read(); @@ -41,6 +43,7 @@ class WebSocketServer : public std::enable_shared_from_this boost::asio::io_context m_context; boost::asio::ip::tcp::acceptor m_acceptor; boost::asio::ip::tcp::socket m_socket; + WebSocketServiceCallbacks m_callbacks; void Accept(); @@ -52,6 +55,11 @@ class WebSocketServer : public std::enable_shared_from_this void Start(); void Stop(); + + void SetOnConnection(std::function&& func); + void SetOnMessage(std::function&& func); + void SetMessageFactory(std::function&& func); + void SetOnError(std::function&& func); }; } } } // Microsoft::React::Test From 4abcb179b18b8b68caebf76884734ac0c2beb779 Mon Sep 17 00:00:00 2001 From: "Julio C. Rocha" Date: Sat, 18 May 2019 02:06:48 -0700 Subject: [PATCH 07/30] WebSocketSession extend PUBLIC std::enable_shared... --- vnext/Desktop.IntegrationTests/WebSocketServer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vnext/Desktop.IntegrationTests/WebSocketServer.h b/vnext/Desktop.IntegrationTests/WebSocketServer.h index 0a001177e40..cfd61b8d2ea 100644 --- a/vnext/Desktop.IntegrationTests/WebSocketServer.h +++ b/vnext/Desktop.IntegrationTests/WebSocketServer.h @@ -17,7 +17,7 @@ struct WebSocketServiceCallbacks std::function OnError; }; -class WebSocketSession : std::enable_shared_from_this +class WebSocketSession : public std::enable_shared_from_this { boost::beast::websocket::stream m_stream; boost::asio::strand m_strand; From 74638138c92cf3a2ea8d72bb03a340ee2229dd10 Mon Sep 17 00:00:00 2001 From: "Julio C. Rocha" Date: Sat, 18 May 2019 02:11:59 -0700 Subject: [PATCH 08/30] Create/Connect/Stop WS client before stopping server. --- vnext/Desktop.IntegrationTests/WebSocketIntegrationTest.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vnext/Desktop.IntegrationTests/WebSocketIntegrationTest.cpp b/vnext/Desktop.IntegrationTests/WebSocketIntegrationTest.cpp index 53103c00c84..856ac644688 100644 --- a/vnext/Desktop.IntegrationTests/WebSocketIntegrationTest.cpp +++ b/vnext/Desktop.IntegrationTests/WebSocketIntegrationTest.cpp @@ -32,11 +32,12 @@ TEST_CLASS(WebSocketIntegrationTest) connected = true; }); server->Start(); + auto ws = IWebSocket::Make("ws://localhost:5556"); ws->Connect(); + ws->Close(IWebSocket::CloseCode::Normal, "Closing"); server->Stop(); - ws->Close(IWebSocket::CloseCode::Normal, "Closing"); Assert::IsTrue(connected); } From d026be07814ce188b935135905b663b9c3d4ae16 Mon Sep 17 00:00:00 2001 From: "Julio C. Rocha" Date: Wed, 29 May 2019 15:20:41 -0700 Subject: [PATCH 09/30] Don't instert newline in package.json. --- vnext/.editorconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/vnext/.editorconfig b/vnext/.editorconfig index e0bfb830ed3..3309e13016a 100644 --- a/vnext/.editorconfig +++ b/vnext/.editorconfig @@ -21,3 +21,6 @@ insert_final_newline = false [*.ps1] indent_style = tab indent_size = 4 + +[package.json] +insert_final_newline = false From ce830843ede112f00d053fd14ff39ec7c3acf379 Mon Sep 17 00:00:00 2001 From: "Julio C. Rocha" Date: Wed, 29 May 2019 15:26:59 -0700 Subject: [PATCH 10/30] Remove newline from package.json. --- vnext/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vnext/package.json b/vnext/package.json index a81cdb042da..50607505bed 100644 --- a/vnext/package.json +++ b/vnext/package.json @@ -71,4 +71,4 @@ "react": "16.6.3", "react-native": "0.58.6-microsoft.56 || https://github.com/microsoft/react-native/archive/v0.58.6-microsoft.56.tar.gz" } -} +} \ No newline at end of file From de60549734a59ead345fad17840fa353ef852ac3 Mon Sep 17 00:00:00 2001 From: "Julio C. Rocha" Date: Wed, 29 May 2019 18:22:06 -0700 Subject: [PATCH 11/30] Make MessageFactory receive string&&. --- .../WebSocketIntegrationTest.cpp | 27 +++++++++++++++++++ .../WebSocketServer.cpp | 25 +++++++++++------ .../WebSocketServer.h | 4 +-- 3 files changed, 46 insertions(+), 10 deletions(-) diff --git a/vnext/Desktop.IntegrationTests/WebSocketIntegrationTest.cpp b/vnext/Desktop.IntegrationTests/WebSocketIntegrationTest.cpp index 856ac644688..7dc870ea0af 100644 --- a/vnext/Desktop.IntegrationTests/WebSocketIntegrationTest.cpp +++ b/vnext/Desktop.IntegrationTests/WebSocketIntegrationTest.cpp @@ -42,6 +42,33 @@ TEST_CLASS(WebSocketIntegrationTest) Assert::IsTrue(connected); } + TEST_METHOD(SendReceiveInProcServer) + { + auto server = make_shared(5556); + server->SetOnMessage([](string s) + { + }); + server->SetMessageFactory([](string&& message) + { + return message + "_suffix"; + }); + server->Start(); + + string response; + auto ws = IWebSocket::Make("ws://localhost:5556"); + ws->SetOnMessage([&response](size_t, const string& message) + { + response = message; + }); + ws->Connect(); + ws->Send("prefix"); + ws->Close(IWebSocket::CloseCode::Normal, "Closing"); + + server->Stop(); + + Assert::AreEqual({ "prefix_suffix" }, response); + } + TEST_METHOD(ConnectClose) { auto ws = IWebSocket::Make("ws://localhost:5555/"); diff --git a/vnext/Desktop.IntegrationTests/WebSocketServer.cpp b/vnext/Desktop.IntegrationTests/WebSocketServer.cpp index 9a5ae69a211..20923516bff 100644 --- a/vnext/Desktop.IntegrationTests/WebSocketServer.cpp +++ b/vnext/Desktop.IntegrationTests/WebSocketServer.cpp @@ -1,11 +1,14 @@ #include "WebSocketServer.h" #include +#include using namespace boost::asio; using boost::system::error_code; using std::function; +using std::placeholders::_1; +using std::placeholders::_2; using std::string; namespace Microsoft { @@ -23,7 +26,7 @@ WebSocketSession::WebSocketSession(ip::tcp::socket socket, WebSocketServiceCallb void WebSocketSession::Start() { - m_stream.async_accept(bind_executor(m_strand, std::bind(&WebSocketSession::OnAccept, shared_from_this(), std::placeholders::_1))); + m_stream.async_accept(bind_executor(m_strand, std::bind(&WebSocketSession::OnAccept, shared_from_this(), /*ec*/ _1))); } void WebSocketSession::OnAccept(error_code ec) @@ -42,8 +45,8 @@ void WebSocketSession::Read() m_stream.async_read(m_buffer, bind_executor(m_strand, std::bind( &WebSocketSession::OnRead, shared_from_this(), - std::placeholders::_1, - std::placeholders::_2 + _1, // ec + _2 // transferred ))); } @@ -55,12 +58,18 @@ void WebSocketSession::OnRead(error_code ec, size_t /*transferred*/) if (ec) return;//TODO: fail instead + //TODO: Enable overriding output message. + //auto messageIn = buffers_to_string(m_buffer.data()); + //m_buffer.consume(m_buffer.size()); + //auto messageOut = m_callbacks.MessageFactory(std::move(messageIn)); + //string messageOut = "MESSAGEOUT"; + m_stream.text(m_stream.got_text()); - m_stream.async_write(m_buffer.data(), bind_executor(m_strand, std::bind( + m_stream.async_write(m_buffer.data()/*buffer(messageOut)*/, bind_executor(m_strand, std::bind( &WebSocketSession::OnWrite, shared_from_this(), - std::placeholders::_1, - std::placeholders::_2 + _1, // ec + _2 // transferred ))); } @@ -130,7 +139,7 @@ void WebSocketServer::Start() void WebSocketServer::Accept() { - m_acceptor.async_accept(m_socket, std::bind(&WebSocketServer::OnAccept, shared_from_this(), std::placeholders::_1)); + m_acceptor.async_accept(m_socket, std::bind(&WebSocketServer::OnAccept, shared_from_this(), /*ec*/ _1)); } void WebSocketServer::Stop() @@ -166,7 +175,7 @@ void WebSocketServer::SetOnMessage(function&& func) m_callbacks.OnMessage = std::move(func); } -void WebSocketServer::SetMessageFactory(function&& func) +void WebSocketServer::SetMessageFactory(function&& func) { m_callbacks.MessageFactory = std::move(func); } diff --git a/vnext/Desktop.IntegrationTests/WebSocketServer.h b/vnext/Desktop.IntegrationTests/WebSocketServer.h index cfd61b8d2ea..7f4e5efd413 100644 --- a/vnext/Desktop.IntegrationTests/WebSocketServer.h +++ b/vnext/Desktop.IntegrationTests/WebSocketServer.h @@ -13,7 +13,7 @@ struct WebSocketServiceCallbacks { std::function OnConnection; std::function OnMessage; - std::function MessageFactory; + std::function MessageFactory; std::function OnError; }; @@ -58,7 +58,7 @@ class WebSocketServer : public std::enable_shared_from_this void SetOnConnection(std::function&& func); void SetOnMessage(std::function&& func); - void SetMessageFactory(std::function&& func); + void SetMessageFactory(std::function&& func); void SetOnError(std::function&& func); }; From a42e66531b8ca2fbae00c9a76812845ed8e3b83b Mon Sep 17 00:00:00 2001 From: "Julio C. Rocha" Date: Wed, 29 May 2019 21:44:01 -0700 Subject: [PATCH 12/30] Store outgoing message in a member variable. --- .../WebSocketIntegrationTest.cpp | 9 +++++---- vnext/Desktop.IntegrationTests/WebSocketServer.cpp | 12 +++++------- vnext/Desktop.IntegrationTests/WebSocketServer.h | 1 + 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/vnext/Desktop.IntegrationTests/WebSocketIntegrationTest.cpp b/vnext/Desktop.IntegrationTests/WebSocketIntegrationTest.cpp index 7dc870ea0af..f54f21e0a24 100644 --- a/vnext/Desktop.IntegrationTests/WebSocketIntegrationTest.cpp +++ b/vnext/Desktop.IntegrationTests/WebSocketIntegrationTest.cpp @@ -45,23 +45,24 @@ TEST_CLASS(WebSocketIntegrationTest) TEST_METHOD(SendReceiveInProcServer) { auto server = make_shared(5556); - server->SetOnMessage([](string s) - { - }); server->SetMessageFactory([](string&& message) { return message + "_suffix"; }); server->Start(); + promise prom; string response; auto ws = IWebSocket::Make("ws://localhost:5556"); - ws->SetOnMessage([&response](size_t, const string& message) + ws->SetOnMessage([&response, &prom](size_t, const string& message) { response = message; + prom.set_value(); }); ws->Connect(); + ws->Send("prefix"); + prom.get_future().wait();//TODO: Find a way not to require this. ws->Close(IWebSocket::CloseCode::Normal, "Closing"); server->Stop(); diff --git a/vnext/Desktop.IntegrationTests/WebSocketServer.cpp b/vnext/Desktop.IntegrationTests/WebSocketServer.cpp index 20923516bff..ea3b4edbd6d 100644 --- a/vnext/Desktop.IntegrationTests/WebSocketServer.cpp +++ b/vnext/Desktop.IntegrationTests/WebSocketServer.cpp @@ -58,14 +58,11 @@ void WebSocketSession::OnRead(error_code ec, size_t /*transferred*/) if (ec) return;//TODO: fail instead - //TODO: Enable overriding output message. - //auto messageIn = buffers_to_string(m_buffer.data()); - //m_buffer.consume(m_buffer.size()); - //auto messageOut = m_callbacks.MessageFactory(std::move(messageIn)); - //string messageOut = "MESSAGEOUT"; + m_message = m_callbacks.MessageFactory(buffers_to_string(m_buffer.data())); + m_buffer.consume(m_buffer.size()); m_stream.text(m_stream.got_text()); - m_stream.async_write(m_buffer.data()/*buffer(messageOut)*/, bind_executor(m_strand, std::bind( + m_stream.async_write(buffer(m_message), bind_executor(m_strand, std::bind( &WebSocketSession::OnWrite, shared_from_this(), _1, // ec @@ -78,7 +75,8 @@ void WebSocketSession::OnWrite(error_code ec, size_t /*transferred*/) if (ec) return; //TODO: fail - m_buffer.consume(m_buffer.size()); + // Clear outgoing message contents. + m_message.clear(); Read(); } diff --git a/vnext/Desktop.IntegrationTests/WebSocketServer.h b/vnext/Desktop.IntegrationTests/WebSocketServer.h index 7f4e5efd413..427fdb24c77 100644 --- a/vnext/Desktop.IntegrationTests/WebSocketServer.h +++ b/vnext/Desktop.IntegrationTests/WebSocketServer.h @@ -22,6 +22,7 @@ class WebSocketSession : public std::enable_shared_from_this boost::beast::websocket::stream m_stream; boost::asio::strand m_strand; boost::beast::multi_buffer m_buffer; + std::string m_message; WebSocketServiceCallbacks& m_callbacks; std::function m_errorHandler; From 230431342565532d9d02bd36d500ec1221fbf7c7 Mon Sep 17 00:00:00 2001 From: "Julio C. Rocha" Date: Wed, 29 May 2019 21:59:18 -0700 Subject: [PATCH 13/30] Use std::promise in SendReceiveInProcServer. --- .../WebSocketIntegrationTest.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/vnext/Desktop.IntegrationTests/WebSocketIntegrationTest.cpp b/vnext/Desktop.IntegrationTests/WebSocketIntegrationTest.cpp index f54f21e0a24..3b85a4547e2 100644 --- a/vnext/Desktop.IntegrationTests/WebSocketIntegrationTest.cpp +++ b/vnext/Desktop.IntegrationTests/WebSocketIntegrationTest.cpp @@ -51,23 +51,22 @@ TEST_CLASS(WebSocketIntegrationTest) }); server->Start(); - promise prom; - string response; + promise response; + auto result = response.get_future(); auto ws = IWebSocket::Make("ws://localhost:5556"); - ws->SetOnMessage([&response, &prom](size_t, const string& message) + ws->SetOnMessage([&response](size_t, const string& message) { - response = message; - prom.set_value(); + response.set_value(message); }); - ws->Connect(); + ws->Connect(); ws->Send("prefix"); - prom.get_future().wait();//TODO: Find a way not to require this. + result.wait(); ws->Close(IWebSocket::CloseCode::Normal, "Closing"); server->Stop(); - Assert::AreEqual({ "prefix_suffix" }, response); + Assert::AreEqual({ "prefix_suffix" }, result.get()); } TEST_METHOD(ConnectClose) From 4ec9d2fb42839fe572000fa5ef6b61255e7598c9 Mon Sep 17 00:00:00 2001 From: "Julio C. Rocha" Date: Thu, 30 May 2019 16:03:00 -0700 Subject: [PATCH 14/30] Store sessions in member vector. --- vnext/Desktop.IntegrationTests/WebSocketServer.cpp | 9 ++++++++- vnext/Desktop.IntegrationTests/WebSocketServer.h | 2 ++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/vnext/Desktop.IntegrationTests/WebSocketServer.cpp b/vnext/Desktop.IntegrationTests/WebSocketServer.cpp index ea3b4edbd6d..42859546a29 100644 --- a/vnext/Desktop.IntegrationTests/WebSocketServer.cpp +++ b/vnext/Desktop.IntegrationTests/WebSocketServer.cpp @@ -24,6 +24,10 @@ WebSocketSession::WebSocketSession(ip::tcp::socket socket, WebSocketServiceCallb { } +WebSocketSession::~WebSocketSession() +{ +} + void WebSocketSession::Start() { m_stream.async_accept(bind_executor(m_strand, std::bind(&WebSocketSession::OnAccept, shared_from_this(), /*ec*/ _1))); @@ -88,6 +92,7 @@ void WebSocketSession::OnWrite(error_code ec, size_t /*transferred*/) WebSocketServer::WebSocketServer(uint16_t port) : m_acceptor{ m_context } , m_socket{ m_context } + , m_sessions{} { ip::tcp::endpoint ep{ip::make_address("0.0.0.0"), port }; error_code ec; @@ -156,7 +161,9 @@ void WebSocketServer::OnAccept(error_code ec) } else { - std::make_shared(std::move(m_socket), m_callbacks)->Start(); + auto session = std::make_shared(std::move(m_socket), m_callbacks); + m_sessions.push_back(session); + session->Start(); } //TODO: Accept again. diff --git a/vnext/Desktop.IntegrationTests/WebSocketServer.h b/vnext/Desktop.IntegrationTests/WebSocketServer.h index 427fdb24c77..e474ab61f62 100644 --- a/vnext/Desktop.IntegrationTests/WebSocketServer.h +++ b/vnext/Desktop.IntegrationTests/WebSocketServer.h @@ -29,6 +29,7 @@ class WebSocketSession : public std::enable_shared_from_this public: WebSocketSession(boost::asio::ip::tcp::socket socket, WebSocketServiceCallbacks& callbacks); + ~WebSocketSession(); void Start(); void Read(); @@ -45,6 +46,7 @@ class WebSocketServer : public std::enable_shared_from_this boost::asio::ip::tcp::acceptor m_acceptor; boost::asio::ip::tcp::socket m_socket; WebSocketServiceCallbacks m_callbacks; + std::vector> m_sessions; void Accept(); From 20fe4b494ea568875df08ea02a5bcc7c650378de Mon Sep 17 00:00:00 2001 From: "Julio C. Rocha" Date: Thu, 30 May 2019 18:39:05 -0700 Subject: [PATCH 15/30] Define WebSocketSession::Stop(). --- .../WebSocketIntegrationTest.cpp | 135 ++++++++---------- .../WebSocketServer.cpp | 33 +++++ .../WebSocketServer.h | 22 ++- 3 files changed, 111 insertions(+), 79 deletions(-) diff --git a/vnext/Desktop.IntegrationTests/WebSocketIntegrationTest.cpp b/vnext/Desktop.IntegrationTests/WebSocketIntegrationTest.cpp index 3b85a4547e2..7f7d876832b 100644 --- a/vnext/Desktop.IntegrationTests/WebSocketIntegrationTest.cpp +++ b/vnext/Desktop.IntegrationTests/WebSocketIntegrationTest.cpp @@ -21,57 +21,14 @@ using std::lock_guard; using std::promise; using std::string; +using CloseCode = IWebSocket::CloseCode; + TEST_CLASS(WebSocketIntegrationTest) { - TEST_METHOD(ConnectCloseInProcServer) - { - bool connected = false; - auto server = make_shared(5556); - server->SetOnConnection([&connected]() - { - connected = true; - }); - server->Start(); - - auto ws = IWebSocket::Make("ws://localhost:5556"); - ws->Connect(); - ws->Close(IWebSocket::CloseCode::Normal, "Closing"); - - server->Stop(); - - Assert::IsTrue(connected); - } - - TEST_METHOD(SendReceiveInProcServer) - { - auto server = make_shared(5556); - server->SetMessageFactory([](string&& message) - { - return message + "_suffix"; - }); - server->Start(); - - promise response; - auto result = response.get_future(); - auto ws = IWebSocket::Make("ws://localhost:5556"); - ws->SetOnMessage([&response](size_t, const string& message) - { - response.set_value(message); - }); - - ws->Connect(); - ws->Send("prefix"); - result.wait(); - ws->Close(IWebSocket::CloseCode::Normal, "Closing"); - - server->Stop(); - - Assert::AreEqual({ "prefix_suffix" }, result.get()); - } - TEST_METHOD(ConnectClose) { - auto ws = IWebSocket::Make("ws://localhost:5555/"); + auto server = make_shared(5556); + auto ws = IWebSocket::Make("ws://localhost:5556/"); Assert::IsFalse(nullptr == ws); bool connected = false; string message; @@ -80,8 +37,10 @@ TEST_CLASS(WebSocketIntegrationTest) connected = true; }); + server->Start(); ws->Connect(); ws->Close(IWebSocket::CloseCode::Normal, "Closing"); + server->Stop(); Assert::IsTrue(connected); } @@ -89,10 +48,12 @@ TEST_CLASS(WebSocketIntegrationTest) TEST_METHOD(ConnectNoClose) { bool connected = false; + auto server = make_shared(5556); + server->Start(); // IWebSocket scope. Ensures object is closed implicitly by destructor. { - auto ws = IWebSocket::Make("ws://localhost:5555/"); + auto ws = IWebSocket::Make("ws://localhost:5556/"); ws->SetOnConnect([&connected]() { connected = true; @@ -101,12 +62,17 @@ TEST_CLASS(WebSocketIntegrationTest) ws->Connect(); } + server->Stop(); + Assert::IsTrue(connected); } TEST_METHOD(PingClose) { - auto ws = IWebSocket::Make("ws://localhost:5555"); + auto server = make_shared(5556); + server->Start(); + + auto ws = IWebSocket::Make("ws://localhost:5556"); promise pingPromise; ws->SetOnPing([&pingPromise]() { @@ -123,23 +89,28 @@ TEST_CLASS(WebSocketIntegrationTest) auto pingFuture = pingPromise.get_future(); pingFuture.wait(); bool pinged = pingFuture.get(); - ws->Close(IWebSocket::CloseCode::Normal, "Closing after reading"); + server->Stop(); + Assert::IsTrue(pinged); Assert::AreEqual({}, errorString); } + //TODO: Remove this test. TEST_METHOD(SendReceiveNoClose) { - auto ws = IWebSocket::Make("ws://localhost:5555/"); + auto server = make_shared(5556); + server->SetMessageFactory([](string&& message) + { + return message + "_response"; + }); + server->Start(); + + auto ws = IWebSocket::Make("ws://localhost:5556/"); promise response; ws->SetOnMessage([&response](size_t size, const string& message) { - // Ignore greeting message. - if (message == "hello") - return; - response.set_value(message); }); string errorMessage; @@ -156,8 +127,12 @@ TEST_CLASS(WebSocketIntegrationTest) future.wait(); string result = future.get(); + ws->Close(CloseCode::Normal, "Closing"); + + server->Stop(); + Assert::AreEqual({}, errorMessage); - Assert::AreEqual(string("suffixme_response"), result); + Assert::AreEqual({ "suffixme_response" }, result); } // Emulate promise/future functionality. @@ -205,7 +180,12 @@ TEST_CLASS(WebSocketIntegrationTest) TEST_METHOD(SendReceiveClose) { - auto ws = IWebSocket::Make("ws://localhost:5555/"); + auto server = make_shared(5556); + server->SetMessageFactory([](string&& message) + { + return message + "_response"; + }); + auto ws = IWebSocket::Make("ws://localhost:5556/"); promise sentSizePromise; ws->SetOnSend([&sentSizePromise](size_t size) { @@ -214,10 +194,6 @@ TEST_CLASS(WebSocketIntegrationTest) promise receivedPromise; ws->SetOnMessage([&receivedPromise](size_t size, const string& message) { - // Ignore greeting message - if (message == "hello") - return; - receivedPromise.set_value(message); }); string errorMessage; @@ -226,7 +202,8 @@ TEST_CLASS(WebSocketIntegrationTest) errorMessage = err.Message; }); - string sent = "suffixme"; + server->Start(); + string sent = "prefix"; ws->Connect(); ws->Send(sent); @@ -240,22 +217,24 @@ TEST_CLASS(WebSocketIntegrationTest) Assert::AreEqual({}, errorMessage); ws->Close(IWebSocket::CloseCode::Normal, "Closing after reading"); + server->Stop(); Assert::AreEqual({}, errorMessage); Assert::AreEqual(sent.length(), sentSize); - Assert::AreEqual(string("suffixme_response"), received); + Assert::AreEqual({ "prefix_response" }, received); } TEST_METHOD(SendReceiveLargeMessage) { - auto ws = IWebSocket::Make("ws://localhost:5555/"); + auto server = make_shared(5556); + server->SetMessageFactory([](string&& message) + { + return message + "_response"; + }); + auto ws = IWebSocket::Make("ws://localhost:5556/"); promise response; ws->SetOnMessage([&response](size_t size, const string& message) { - // Ignore greeting message - if (message == "hello") - return; - response.set_value(message); }); ws->SetOnError([](IWebSocket::Error err) @@ -264,6 +243,7 @@ TEST_CLASS(WebSocketIntegrationTest) Assert::Fail(message.c_str()); }); + server->Start(); ws->Connect(); char digits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; @@ -283,6 +263,7 @@ TEST_CLASS(WebSocketIntegrationTest) string result = future.get(); ws->Close(IWebSocket::CloseCode::Normal, "Closing after reading"); + server->Stop(); Assert::AreEqual(static_cast(LEN + string("_response").length()), result.length()); } @@ -380,6 +361,7 @@ httpsServer.listen(443); Assert::AreEqual(string("hello"), message); } + //TODO: Use Test::WebSocketServer!!! BEGIN_TEST_METHOD_ATTRIBUTE(SendBinary) //TEST_IGNORE() END_TEST_METHOD_ATTRIBUTE() @@ -441,16 +423,17 @@ httpsServer.listen(443); TEST_METHOD(SendConsecutive) { - auto ws = IWebSocket::Make("ws://localhost:5555/"); + auto server = make_shared(5556); + server->SetMessageFactory([](string&& message) + { + return message + "_response"; + }); + auto ws = IWebSocket::Make("ws://localhost:5556/"); promise response; const int writes = 10; int count = 0; ws->SetOnMessage([&response, &count, writes](size_t size, const string& message) { - // Ignore greeting message. - if (message == "hello") - return; - if (++count < writes) return; @@ -462,6 +445,7 @@ httpsServer.listen(443); errorMessage = err.Message; }); + server->Start(); ws->Connect(); // Consecutive immediate writes should be enqueued. @@ -475,7 +459,10 @@ httpsServer.listen(443); string result = future.get(); ws->Close(IWebSocket::CloseCode::Normal, "Closing"); + server->Stop(); + Assert::AreEqual({}, errorMessage); - Assert::AreEqual(string("suffixme_response"), result); + Assert::AreEqual(writes, count); + Assert::AreEqual({ "suffixme_response" }, result); } }; diff --git a/vnext/Desktop.IntegrationTests/WebSocketServer.cpp b/vnext/Desktop.IntegrationTests/WebSocketServer.cpp index 42859546a29..5fe6d44eb10 100644 --- a/vnext/Desktop.IntegrationTests/WebSocketServer.cpp +++ b/vnext/Desktop.IntegrationTests/WebSocketServer.cpp @@ -21,6 +21,8 @@ WebSocketSession::WebSocketSession(ip::tcp::socket socket, WebSocketServiceCallb : m_stream{ std::move(socket) } , m_strand{ m_stream.get_executor() } , m_callbacks{ callbacks } + , m_state{ State::Stopped } + , m_reading{ false } { } @@ -33,11 +35,32 @@ void WebSocketSession::Start() m_stream.async_accept(bind_executor(m_strand, std::bind(&WebSocketSession::OnAccept, shared_from_this(), /*ec*/ _1))); } +void WebSocketSession::Stop() +{ + m_state = State::Stopped; + + //TODO: Re-enable or discard. + //if (m_reading) + // m_stream.async_close(boost::beast::websocket::close_code::normal, bind_executor(m_strand, std::bind( + // &WebSocketSession::OnClose, + // shared_from_this(), + // _1 // ec + // ))); +} + +void WebSocketSession::OnClose(error_code ec) +{ + if (ec) + return;//TODO: Error +} + void WebSocketSession::OnAccept(error_code ec) { if (ec) return;//TODO: fail + m_state = State::Started; + if (m_callbacks.OnConnection) m_callbacks.OnConnection(); @@ -46,6 +69,11 @@ void WebSocketSession::OnAccept(error_code ec) void WebSocketSession::Read() { + if (State::Stopped == m_state) + return; + + m_reading = true; + m_stream.async_read(m_buffer, bind_executor(m_strand, std::bind( &WebSocketSession::OnRead, shared_from_this(), @@ -56,6 +84,8 @@ void WebSocketSession::Read() void WebSocketSession::OnRead(error_code ec, size_t /*transferred*/) { + m_reading = false; + if (boost::beast::websocket::error::closed == ec) return; @@ -150,6 +180,9 @@ void WebSocketServer::Stop() if (m_acceptor.is_open()) m_acceptor.close(); + for (auto session : m_sessions) + session->Stop(); + m_contextThread.join(); } diff --git a/vnext/Desktop.IntegrationTests/WebSocketServer.h b/vnext/Desktop.IntegrationTests/WebSocketServer.h index e474ab61f62..f195f5aa5df 100644 --- a/vnext/Desktop.IntegrationTests/WebSocketServer.h +++ b/vnext/Desktop.IntegrationTests/WebSocketServer.h @@ -19,24 +19,36 @@ struct WebSocketServiceCallbacks class WebSocketSession : public std::enable_shared_from_this { + //TODO: Used at all? + enum class State : std::size_t + { + Started, + Stopped + }; + boost::beast::websocket::stream m_stream; boost::asio::strand m_strand; boost::beast::multi_buffer m_buffer; std::string m_message; WebSocketServiceCallbacks& m_callbacks; + State m_state;//TODO: Used at all? + std::atomic_bool m_reading;//TODO: Remove? std::function m_errorHandler; -public: - WebSocketSession(boost::asio::ip::tcp::socket socket, WebSocketServiceCallbacks& callbacks); - ~WebSocketSession(); - - void Start(); void Read(); void OnAccept(boost::system::error_code ec); void OnRead(boost::system::error_code ec, std::size_t transferred); void OnWrite(boost::system::error_code ec, std::size_t transferred); + void OnClose(boost::system::error_code ec); + +public: + WebSocketSession(boost::asio::ip::tcp::socket socket, WebSocketServiceCallbacks& callbacks); + ~WebSocketSession(); + + void Start(); + void Stop(); }; class WebSocketServer : public std::enable_shared_from_this From 95af449028be6e467add466dd513bb67fd3707b0 Mon Sep 17 00:00:00 2001 From: "Julio C. Rocha" Date: Fri, 31 May 2019 03:08:56 -0700 Subject: [PATCH 16/30] Implement WebSocketServer::SetOnHandshake. --- .../WebSocketIntegrationTest.cpp | 22 ++++-- .../WebSocketServer.cpp | 76 +++++++++++++++---- .../WebSocketServer.h | 3 + 3 files changed, 80 insertions(+), 21 deletions(-) diff --git a/vnext/Desktop.IntegrationTests/WebSocketIntegrationTest.cpp b/vnext/Desktop.IntegrationTests/WebSocketIntegrationTest.cpp index 7f7d876832b..003585deb1e 100644 --- a/vnext/Desktop.IntegrationTests/WebSocketIntegrationTest.cpp +++ b/vnext/Desktop.IntegrationTests/WebSocketIntegrationTest.cpp @@ -286,27 +286,39 @@ TEST_CLASS(WebSocketIntegrationTest) Test passes, otherwise. */ BEGIN_TEST_METHOD_ATTRIBUTE(AdditionalHeaders) - TEST_IGNORE() + //TEST_IGNORE() END_TEST_METHOD_ATTRIBUTE() TEST_METHOD(AdditionalHeaders) { - auto ws = IWebSocket::Make("ws://localhost:5555/"); + string cookie; + auto server = make_shared(5556); + server->SetOnHandshake([server](boost::beast::websocket::response_type& response) + { + auto cookie = response[boost::beast::http::field::cookie].to_string(); + server->SetMessageFactory([cookie](string&&) + { + return cookie; + }); + }); + auto ws = IWebSocket::Make("ws://localhost:5556/"); promise response; ws->SetOnMessage([&response](size_t size, const string& message) { response.set_value(message); }); - ws->Connect({}, {{ L"Cookie", "JSESSIONID=AD9A320CC4034641997FF903F1D10906" }}); + server->Start(); + ws->Connect({}, {{ L"Cookie", "JSESSIONID=AD9A320CC4034641997FF903F1D10906" }});//TODO: rename back to Cookie. ws->Send(""); auto future = response.get_future(); future.wait(); string result = future.get(); - Assert::AreEqual(string("JSESSIONID=AD9A320CC4034641997FF903F1D10906"), result); + Assert::AreEqual({ "JSESSIONID=AD9A320CC4034641997FF903F1D10906" }, result); ws->Close(IWebSocket::CloseCode::Normal, "No reason"); + server->Stop(); } /// @@ -363,7 +375,7 @@ httpsServer.listen(443); //TODO: Use Test::WebSocketServer!!! BEGIN_TEST_METHOD_ATTRIBUTE(SendBinary) - //TEST_IGNORE() + TEST_IGNORE() END_TEST_METHOD_ATTRIBUTE() TEST_METHOD(SendBinary) { diff --git a/vnext/Desktop.IntegrationTests/WebSocketServer.cpp b/vnext/Desktop.IntegrationTests/WebSocketServer.cpp index 5fe6d44eb10..1985057fd55 100644 --- a/vnext/Desktop.IntegrationTests/WebSocketServer.cpp +++ b/vnext/Desktop.IntegrationTests/WebSocketServer.cpp @@ -32,26 +32,39 @@ WebSocketSession::~WebSocketSession() void WebSocketSession::Start() { - m_stream.async_accept(bind_executor(m_strand, std::bind(&WebSocketSession::OnAccept, shared_from_this(), /*ec*/ _1))); +/* +ws.accept_ex( + [](response_type& m) + { + m.insert(http::field::server, "MyServer"); + }); +*/ + + //m_stream.async_accept(bind_executor(m_strand, std::bind(&WebSocketSession::OnAccept, shared_from_this(), /*ec*/ _1))); + + m_stream.async_accept_ex( + bind_executor(m_strand, std::bind( + &WebSocketSession::OnHandshake, + shared_from_this(), + _1 // response + )), + bind_executor(m_strand, std::bind( + &WebSocketSession::OnAccept, + shared_from_this(), + _1 // ec + )) + ); } -void WebSocketSession::Stop() +void WebSocketSession::OnHandshake(boost::beast::websocket::response_type& response) { - m_state = State::Stopped; - - //TODO: Re-enable or discard. - //if (m_reading) - // m_stream.async_close(boost::beast::websocket::close_code::normal, bind_executor(m_strand, std::bind( - // &WebSocketSession::OnClose, - // shared_from_this(), - // _1 // ec - // ))); -} + for (const auto& x : response) + { + int xx = 99;//TODO:Remove! + } -void WebSocketSession::OnClose(error_code ec) -{ - if (ec) - return;//TODO: Error + if (m_callbacks.OnHandshake) + m_callbacks.OnHandshake(response); } void WebSocketSession::OnAccept(error_code ec) @@ -92,6 +105,12 @@ void WebSocketSession::OnRead(error_code ec, size_t /*transferred*/) if (ec) return;//TODO: fail instead + if (!m_callbacks.MessageFactory) + { + m_buffer.consume(m_buffer.size()); + return Read(); + } + m_message = m_callbacks.MessageFactory(buffers_to_string(m_buffer.data())); m_buffer.consume(m_buffer.size()); @@ -115,6 +134,26 @@ void WebSocketSession::OnWrite(error_code ec, size_t /*transferred*/) Read(); } +void WebSocketSession::Stop() +{ + m_state = State::Stopped; + + //TODO: Re-enable or discard. + //if (m_reading) + // m_stream.async_close(boost::beast::websocket::close_code::normal, bind_executor(m_strand, std::bind( + // &WebSocketSession::OnClose, + // shared_from_this(), + // _1 // ec + // ))); +} + +//TODO: Re-enable or discard. +//void WebSocketSession::OnClose(error_code ec) +//{ +// if (ec) +// return;//TODO: Error +//} + #pragma endregion // WebSocketSession #pragma region WebSocketServer @@ -208,6 +247,11 @@ void WebSocketServer::SetOnConnection(function&& func) m_callbacks.OnConnection = std::move(func); } +void WebSocketServer::SetOnHandshake(function&& func) +{ + m_callbacks.OnHandshake = std::move(func); +} + void WebSocketServer::SetOnMessage(function&& func) { m_callbacks.OnMessage = std::move(func); diff --git a/vnext/Desktop.IntegrationTests/WebSocketServer.h b/vnext/Desktop.IntegrationTests/WebSocketServer.h index f195f5aa5df..9827cc0ed20 100644 --- a/vnext/Desktop.IntegrationTests/WebSocketServer.h +++ b/vnext/Desktop.IntegrationTests/WebSocketServer.h @@ -12,6 +12,7 @@ namespace Test { struct WebSocketServiceCallbacks { std::function OnConnection; + std::function OnHandshake; std::function OnMessage; std::function MessageFactory; std::function OnError; @@ -39,6 +40,7 @@ class WebSocketSession : public std::enable_shared_from_this void Read(); void OnAccept(boost::system::error_code ec); + void OnHandshake(boost::beast::websocket::response_type& response); void OnRead(boost::system::error_code ec, std::size_t transferred); void OnWrite(boost::system::error_code ec, std::size_t transferred); void OnClose(boost::system::error_code ec); @@ -72,6 +74,7 @@ class WebSocketServer : public std::enable_shared_from_this void Stop(); void SetOnConnection(std::function&& func); + void SetOnHandshake(std::function&& func); void SetOnMessage(std::function&& func); void SetMessageFactory(std::function&& func); void SetOnError(std::function&& func); From c7a97c0d44f29df80820f26d1b59611808d8864f Mon Sep 17 00:00:00 2001 From: "Julio C. Rocha" Date: Fri, 31 May 2019 16:26:59 -0700 Subject: [PATCH 17/30] Clean up integration tests. --- .../WebSocketIntegrationTest.cpp | 58 ++++--------------- .../WebSocketServer.cpp | 40 +------------ .../WebSocketServer.h | 2 - 3 files changed, 11 insertions(+), 89 deletions(-) diff --git a/vnext/Desktop.IntegrationTests/WebSocketIntegrationTest.cpp b/vnext/Desktop.IntegrationTests/WebSocketIntegrationTest.cpp index 003585deb1e..b1fdcbb285a 100644 --- a/vnext/Desktop.IntegrationTests/WebSocketIntegrationTest.cpp +++ b/vnext/Desktop.IntegrationTests/WebSocketIntegrationTest.cpp @@ -39,7 +39,7 @@ TEST_CLASS(WebSocketIntegrationTest) server->Start(); ws->Connect(); - ws->Close(IWebSocket::CloseCode::Normal, "Closing"); + ws->Close(CloseCode::Normal, "Closing"); server->Stop(); Assert::IsTrue(connected); @@ -89,7 +89,7 @@ TEST_CLASS(WebSocketIntegrationTest) auto pingFuture = pingPromise.get_future(); pingFuture.wait(); bool pinged = pingFuture.get(); - ws->Close(IWebSocket::CloseCode::Normal, "Closing after reading"); + ws->Close(CloseCode::Normal, "Closing after reading"); server->Stop(); @@ -97,44 +97,6 @@ TEST_CLASS(WebSocketIntegrationTest) Assert::AreEqual({}, errorString); } - //TODO: Remove this test. - TEST_METHOD(SendReceiveNoClose) - { - auto server = make_shared(5556); - server->SetMessageFactory([](string&& message) - { - return message + "_response"; - }); - server->Start(); - - auto ws = IWebSocket::Make("ws://localhost:5556/"); - promise response; - ws->SetOnMessage([&response](size_t size, const string& message) - { - response.set_value(message); - }); - string errorMessage; - ws->SetOnError([&errorMessage](IWebSocket::Error err) - { - errorMessage = err.Message; - }); - - ws->Connect(); - ws->Send("suffixme"); - - // Block until respone is received. Fail in case of a remote endpoint failure. - auto future = response.get_future(); - future.wait(); - string result = future.get(); - - ws->Close(CloseCode::Normal, "Closing"); - - server->Stop(); - - Assert::AreEqual({}, errorMessage); - Assert::AreEqual({ "suffixme_response" }, result); - } - // Emulate promise/future functionality. // Fails when connecting to stock package bundler. BEGIN_TEST_METHOD_ATTRIBUTE(WaitForBundlerResponseNoClose) @@ -216,7 +178,7 @@ TEST_CLASS(WebSocketIntegrationTest) string received = receivedFuture.get(); Assert::AreEqual({}, errorMessage); - ws->Close(IWebSocket::CloseCode::Normal, "Closing after reading"); + ws->Close(CloseCode::Normal, "Closing after reading"); server->Stop(); Assert::AreEqual({}, errorMessage); @@ -262,7 +224,7 @@ TEST_CLASS(WebSocketIntegrationTest) future.wait(); string result = future.get(); - ws->Close(IWebSocket::CloseCode::Normal, "Closing after reading"); + ws->Close(CloseCode::Normal, "Closing after reading"); server->Stop(); Assert::AreEqual(static_cast(LEN + string("_response").length()), result.length()); @@ -286,7 +248,7 @@ TEST_CLASS(WebSocketIntegrationTest) Test passes, otherwise. */ BEGIN_TEST_METHOD_ATTRIBUTE(AdditionalHeaders) - //TEST_IGNORE() + TEST_IGNORE() END_TEST_METHOD_ATTRIBUTE() TEST_METHOD(AdditionalHeaders) { @@ -308,7 +270,7 @@ TEST_CLASS(WebSocketIntegrationTest) }); server->Start(); - ws->Connect({}, {{ L"Cookie", "JSESSIONID=AD9A320CC4034641997FF903F1D10906" }});//TODO: rename back to Cookie. + ws->Connect({}, {{ L"Cookie", "JSESSIONID=AD9A320CC4034641997FF903F1D10906" }}); ws->Send(""); auto future = response.get_future(); @@ -317,7 +279,7 @@ TEST_CLASS(WebSocketIntegrationTest) Assert::AreEqual({ "JSESSIONID=AD9A320CC4034641997FF903F1D10906" }, result); - ws->Close(IWebSocket::CloseCode::Normal, "No reason"); + ws->Close(CloseCode::Normal, "No reason"); server->Stop(); } @@ -368,7 +330,7 @@ httpsServer.listen(443); ws->Connect(); ws->Send("suffixme"); - ws->Close(IWebSocket::CloseCode::Normal, "Closing after reading"); + ws->Close(CloseCode::Normal, "Closing after reading"); Assert::AreEqual(string("hello"), message); } @@ -428,7 +390,7 @@ httpsServer.listen(443); Assert::AreEqual(messages[i], response); } - ws->Close(IWebSocket::CloseCode::Normal, "Closing after reading"); + ws->Close(CloseCode::Normal, "Closing after reading"); Assert::AreEqual({}, errorMessage); } @@ -470,7 +432,7 @@ httpsServer.listen(443); future.wait(); string result = future.get(); - ws->Close(IWebSocket::CloseCode::Normal, "Closing"); + ws->Close(CloseCode::Normal, "Closing"); server->Stop(); Assert::AreEqual({}, errorMessage); diff --git a/vnext/Desktop.IntegrationTests/WebSocketServer.cpp b/vnext/Desktop.IntegrationTests/WebSocketServer.cpp index 1985057fd55..4718f91ebce 100644 --- a/vnext/Desktop.IntegrationTests/WebSocketServer.cpp +++ b/vnext/Desktop.IntegrationTests/WebSocketServer.cpp @@ -32,16 +32,6 @@ WebSocketSession::~WebSocketSession() void WebSocketSession::Start() { -/* -ws.accept_ex( - [](response_type& m) - { - m.insert(http::field::server, "MyServer"); - }); -*/ - - //m_stream.async_accept(bind_executor(m_strand, std::bind(&WebSocketSession::OnAccept, shared_from_this(), /*ec*/ _1))); - m_stream.async_accept_ex( bind_executor(m_strand, std::bind( &WebSocketSession::OnHandshake, @@ -58,11 +48,6 @@ ws.accept_ex( void WebSocketSession::OnHandshake(boost::beast::websocket::response_type& response) { - for (const auto& x : response) - { - int xx = 99;//TODO:Remove! - } - if (m_callbacks.OnHandshake) m_callbacks.OnHandshake(response); } @@ -134,26 +119,6 @@ void WebSocketSession::OnWrite(error_code ec, size_t /*transferred*/) Read(); } -void WebSocketSession::Stop() -{ - m_state = State::Stopped; - - //TODO: Re-enable or discard. - //if (m_reading) - // m_stream.async_close(boost::beast::websocket::close_code::normal, bind_executor(m_strand, std::bind( - // &WebSocketSession::OnClose, - // shared_from_this(), - // _1 // ec - // ))); -} - -//TODO: Re-enable or discard. -//void WebSocketSession::OnClose(error_code ec) -//{ -// if (ec) -// return;//TODO: Error -//} - #pragma endregion // WebSocketSession #pragma region WebSocketServer @@ -189,7 +154,7 @@ WebSocketServer::WebSocketServer(uint16_t port) { return; // } -} // constructor(uint16_t) +} WebSocketServer::WebSocketServer(int port) : WebSocketServer(static_cast(port)) @@ -219,9 +184,6 @@ void WebSocketServer::Stop() if (m_acceptor.is_open()) m_acceptor.close(); - for (auto session : m_sessions) - session->Stop(); - m_contextThread.join(); } diff --git a/vnext/Desktop.IntegrationTests/WebSocketServer.h b/vnext/Desktop.IntegrationTests/WebSocketServer.h index 9827cc0ed20..f462ab05ac9 100644 --- a/vnext/Desktop.IntegrationTests/WebSocketServer.h +++ b/vnext/Desktop.IntegrationTests/WebSocketServer.h @@ -43,14 +43,12 @@ class WebSocketSession : public std::enable_shared_from_this void OnHandshake(boost::beast::websocket::response_type& response); void OnRead(boost::system::error_code ec, std::size_t transferred); void OnWrite(boost::system::error_code ec, std::size_t transferred); - void OnClose(boost::system::error_code ec); public: WebSocketSession(boost::asio::ip::tcp::socket socket, WebSocketServiceCallbacks& callbacks); ~WebSocketSession(); void Start(); - void Stop(); }; class WebSocketServer : public std::enable_shared_from_this From 3f06fe66d2a98d842d01782acc31ead871c65b29 Mon Sep 17 00:00:00 2001 From: "Julio C. Rocha" Date: Fri, 31 May 2019 16:57:35 -0700 Subject: [PATCH 18/30] Remove m_reading. --- vnext/Desktop.IntegrationTests/WebSocketServer.cpp | 5 ----- vnext/Desktop.IntegrationTests/WebSocketServer.h | 1 - 2 files changed, 6 deletions(-) diff --git a/vnext/Desktop.IntegrationTests/WebSocketServer.cpp b/vnext/Desktop.IntegrationTests/WebSocketServer.cpp index 4718f91ebce..1e9f5710c7f 100644 --- a/vnext/Desktop.IntegrationTests/WebSocketServer.cpp +++ b/vnext/Desktop.IntegrationTests/WebSocketServer.cpp @@ -22,7 +22,6 @@ WebSocketSession::WebSocketSession(ip::tcp::socket socket, WebSocketServiceCallb , m_strand{ m_stream.get_executor() } , m_callbacks{ callbacks } , m_state{ State::Stopped } - , m_reading{ false } { } @@ -70,8 +69,6 @@ void WebSocketSession::Read() if (State::Stopped == m_state) return; - m_reading = true; - m_stream.async_read(m_buffer, bind_executor(m_strand, std::bind( &WebSocketSession::OnRead, shared_from_this(), @@ -82,8 +79,6 @@ void WebSocketSession::Read() void WebSocketSession::OnRead(error_code ec, size_t /*transferred*/) { - m_reading = false; - if (boost::beast::websocket::error::closed == ec) return; diff --git a/vnext/Desktop.IntegrationTests/WebSocketServer.h b/vnext/Desktop.IntegrationTests/WebSocketServer.h index f462ab05ac9..dbf87c87561 100644 --- a/vnext/Desktop.IntegrationTests/WebSocketServer.h +++ b/vnext/Desktop.IntegrationTests/WebSocketServer.h @@ -33,7 +33,6 @@ class WebSocketSession : public std::enable_shared_from_this std::string m_message; WebSocketServiceCallbacks& m_callbacks; State m_state;//TODO: Used at all? - std::atomic_bool m_reading;//TODO: Remove? std::function m_errorHandler; From 269da912c07cafbfc93bec99e871aef22295af79 Mon Sep 17 00:00:00 2001 From: "Julio C. Rocha" Date: Sat, 1 Jun 2019 00:31:21 -0700 Subject: [PATCH 19/30] Refactor as BaseWebSocketSession. --- ...t.Windows.Desktop.IntegrationTests.vcxproj | 1 + .../WebSocketServer.cpp | 120 +++++++++++++----- .../WebSocketServer.h | 46 ++++++- 3 files changed, 133 insertions(+), 34 deletions(-) diff --git a/vnext/Desktop.IntegrationTests/React.Windows.Desktop.IntegrationTests.vcxproj b/vnext/Desktop.IntegrationTests/React.Windows.Desktop.IntegrationTests.vcxproj index 7580c21843a..892aea5be9e 100644 --- a/vnext/Desktop.IntegrationTests/React.Windows.Desktop.IntegrationTests.vcxproj +++ b/vnext/Desktop.IntegrationTests/React.Windows.Desktop.IntegrationTests.vcxproj @@ -57,6 +57,7 @@ true BOOST_ASIO_HAS_IOCP;_WIN32_WINNT=_WIN32_WINNT_WIN7;WIN32;_WINDOWS;REACTNATIVEWIN32_EXPORTS;FOLLY_NO_CONFIG;WIN32_LEAN_AND_MEAN;NOMINMAX;GLOG_NO_ABBREVIATED_SEVERITIES;_HAS_AUTO_PTR_ETC;CHAKRACORE;RN_PLATFORM=windesktop;RN_EXPORT=;JSI_EXPORT=;NOJSC;%(PreprocessorDefinitions) + %(AdditionalOptions) /bigobj $(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) ProgramDatabase true diff --git a/vnext/Desktop.IntegrationTests/WebSocketServer.cpp b/vnext/Desktop.IntegrationTests/WebSocketServer.cpp index 1e9f5710c7f..4f1c792896a 100644 --- a/vnext/Desktop.IntegrationTests/WebSocketServer.cpp +++ b/vnext/Desktop.IntegrationTests/WebSocketServer.cpp @@ -11,47 +11,58 @@ using std::placeholders::_1; using std::placeholders::_2; using std::string; +namespace websocket = boost::beast::websocket; + namespace Microsoft { namespace React { namespace Test { -#pragma region WebSocketSession +#pragma region BaseWebSocketSession -WebSocketSession::WebSocketSession(ip::tcp::socket socket, WebSocketServiceCallbacks& callbacks) - : m_stream{ std::move(socket) } - , m_strand{ m_stream.get_executor() } - , m_callbacks{ callbacks } +template +BaseWebSocketSession::BaseWebSocketSession(WebSocketServiceCallbacks& callbacks) + : m_callbacks{ callbacks } , m_state{ State::Stopped } { } -WebSocketSession::~WebSocketSession() +template +BaseWebSocketSession::~BaseWebSocketSession() +{ +} + +template +void BaseWebSocketSession::Start() { + Accept(); } -void WebSocketSession::Start() +template +void BaseWebSocketSession::Accept() { - m_stream.async_accept_ex( - bind_executor(m_strand, std::bind( - &WebSocketSession::OnHandshake, - shared_from_this(), + m_stream->async_accept_ex( + bind_executor(*m_strand, std::bind( + &BaseWebSocketSession::OnHandshake, + this->shared_from_this(), _1 // response )), - bind_executor(m_strand, std::bind( - &WebSocketSession::OnAccept, - shared_from_this(), + bind_executor(*m_strand, std::bind( + &BaseWebSocketSession::OnAccept, + this->shared_from_this(), _1 // ec )) ); } -void WebSocketSession::OnHandshake(boost::beast::websocket::response_type& response) +template +void BaseWebSocketSession::OnHandshake(websocket::response_type& response) { if (m_callbacks.OnHandshake) m_callbacks.OnHandshake(response); } -void WebSocketSession::OnAccept(error_code ec) +template +void BaseWebSocketSession::OnAccept(error_code ec) { if (ec) return;//TODO: fail @@ -64,22 +75,24 @@ void WebSocketSession::OnAccept(error_code ec) Read(); } -void WebSocketSession::Read() +template +void BaseWebSocketSession::Read() { if (State::Stopped == m_state) return; - m_stream.async_read(m_buffer, bind_executor(m_strand, std::bind( - &WebSocketSession::OnRead, - shared_from_this(), + m_stream->async_read(m_buffer, bind_executor(*m_strand, std::bind( + &BaseWebSocketSession::OnRead, + this->shared_from_this(), _1, // ec _2 // transferred ))); } -void WebSocketSession::OnRead(error_code ec, size_t /*transferred*/) +template +void BaseWebSocketSession::OnRead(error_code ec, size_t /*transferred*/) { - if (boost::beast::websocket::error::closed == ec) + if (websocket::error::closed == ec) return; if (ec) @@ -94,16 +107,17 @@ void WebSocketSession::OnRead(error_code ec, size_t /*transferred*/) m_message = m_callbacks.MessageFactory(buffers_to_string(m_buffer.data())); m_buffer.consume(m_buffer.size()); - m_stream.text(m_stream.got_text()); - m_stream.async_write(buffer(m_message), bind_executor(m_strand, std::bind( - &WebSocketSession::OnWrite, - shared_from_this(), + m_stream->text(m_stream->got_text()); + m_stream->async_write(buffer(m_message), bind_executor(*m_strand, std::bind( + &BaseWebSocketSession::OnWrite, + this->shared_from_this(), _1, // ec _2 // transferred ))); } -void WebSocketSession::OnWrite(error_code ec, size_t /*transferred*/) +template +void BaseWebSocketSession::OnWrite(error_code ec, size_t /*transferred*/) { if (ec) return; //TODO: fail @@ -114,8 +128,56 @@ void WebSocketSession::OnWrite(error_code ec, size_t /*transferred*/) Read(); } +#pragma endregion // BaseWebSocketSession + +#pragma region WebSocketSession + +WebSocketSession::WebSocketSession(ip::tcp::socket socket, WebSocketServiceCallbacks& callbacks) + : BaseWebSocketSession(callbacks) +{ + m_stream = std::make_shared>(std::move(socket)); + m_strand = std::make_shared>(m_stream->get_executor()); +} + +WebSocketSession::~WebSocketSession() {} + #pragma endregion // WebSocketSession +#pragma region SecureWebSocketSession + +SecureWebSocketSession::SecureWebSocketSession(ip::tcp::socket socket, WebSocketServiceCallbacks& callbacks) + : BaseWebSocketSession(callbacks) +{ + auto context = ssl::context(ssl::context::sslv23_client); + m_stream = std::make_shared>>(std::move(socket), context); + m_strand = std::make_shared>(m_stream->get_executor()); +} + +SecureWebSocketSession::~SecureWebSocketSession() {} + +#pragma region IWebSocketSession + +void SecureWebSocketSession::Start() /*override*/ +{ + //m_stream->next_layer().async_handshake(ssl::stream_base::server, bind_executor(*m_strand, std::bind( + // &SecureWebSocketSession::OnSslHandshake, + // this->shared_from_this(), + // _1 // ec + //))); +} + +void SecureWebSocketSession::OnSslHandshake(error_code ec) +{ + if (ec) + return;//TODO: Handle error + + Accept(); +} + +#pragma endregion // IWebSocketSession + +#pragma endregion // SecureWebSocketSession + #pragma region WebSocketServer WebSocketServer::WebSocketServer(uint16_t port) @@ -190,7 +252,7 @@ void WebSocketServer::OnAccept(error_code ec) } else { - auto session = std::make_shared(std::move(m_socket), m_callbacks); + auto session = std::shared_ptr(new WebSocketSession(std::move(m_socket), m_callbacks)); m_sessions.push_back(session); session->Start(); } @@ -204,7 +266,7 @@ void WebSocketServer::SetOnConnection(function&& func) m_callbacks.OnConnection = std::move(func); } -void WebSocketServer::SetOnHandshake(function&& func) +void WebSocketServer::SetOnHandshake(function&& func) { m_callbacks.OnHandshake = std::move(func); } diff --git a/vnext/Desktop.IntegrationTests/WebSocketServer.h b/vnext/Desktop.IntegrationTests/WebSocketServer.h index dbf87c87561..4e5e95cc7e1 100644 --- a/vnext/Desktop.IntegrationTests/WebSocketServer.h +++ b/vnext/Desktop.IntegrationTests/WebSocketServer.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include #include @@ -18,7 +19,15 @@ struct WebSocketServiceCallbacks std::function OnError; }; -class WebSocketSession : public std::enable_shared_from_this +struct IWebSocketSession +{ + virtual ~IWebSocketSession() {} + + virtual void Start() = 0; +}; + +template +class BaseWebSocketSession : public std::enable_shared_from_this>, public IWebSocketSession { //TODO: Used at all? enum class State : std::size_t @@ -27,8 +36,6 @@ class WebSocketSession : public std::enable_shared_from_this Stopped }; - boost::beast::websocket::stream m_stream; - boost::asio::strand m_strand; boost::beast::multi_buffer m_buffer; std::string m_message; WebSocketServiceCallbacks& m_callbacks; @@ -43,11 +50,40 @@ class WebSocketSession : public std::enable_shared_from_this void OnRead(boost::system::error_code ec, std::size_t transferred); void OnWrite(boost::system::error_code ec, std::size_t transferred); +protected: + std::shared_ptr> m_stream; + std::shared_ptr> m_strand; + + void Accept(); + +public: + BaseWebSocketSession(WebSocketServiceCallbacks& callbacks); + ~BaseWebSocketSession(); + + virtual void Start() override; +}; + +class WebSocketSession + : public BaseWebSocketSession<> +{ public: WebSocketSession(boost::asio::ip::tcp::socket socket, WebSocketServiceCallbacks& callbacks); ~WebSocketSession(); +}; - void Start(); +class SecureWebSocketSession + : public BaseWebSocketSession> +{ + SecureWebSocketSession(boost::asio::ip::tcp::socket socket, WebSocketServiceCallbacks& callbacks); + ~SecureWebSocketSession(); + + void OnSslHandshake(boost::system::error_code ec); + + #pragma region IWebSocketSession + + void Start() override; + + #pragma endregion //IWebSocketSession }; class WebSocketServer : public std::enable_shared_from_this @@ -57,7 +93,7 @@ class WebSocketServer : public std::enable_shared_from_this boost::asio::ip::tcp::acceptor m_acceptor; boost::asio::ip::tcp::socket m_socket; WebSocketServiceCallbacks m_callbacks; - std::vector> m_sessions; + std::vector> m_sessions; void Accept(); From a1811b1e1a3f98fb8991ef6bee9705b96e1674fa Mon Sep 17 00:00:00 2001 From: "Julio C. Rocha" Date: Sat, 1 Jun 2019 03:12:18 -0700 Subject: [PATCH 20/30] Implemented SecureWebSocketSession and client test --- .../WebSocketIntegrationTest.cpp | 59 ++---- .../WebSocketServer.cpp | 181 ++++++++++++++---- .../WebSocketServer.h | 27 ++- 3 files changed, 175 insertions(+), 92 deletions(-) diff --git a/vnext/Desktop.IntegrationTests/WebSocketIntegrationTest.cpp b/vnext/Desktop.IntegrationTests/WebSocketIntegrationTest.cpp index b1fdcbb285a..03bb5f6c6a5 100644 --- a/vnext/Desktop.IntegrationTests/WebSocketIntegrationTest.cpp +++ b/vnext/Desktop.IntegrationTests/WebSocketIntegrationTest.cpp @@ -283,56 +283,31 @@ TEST_CLASS(WebSocketIntegrationTest) server->Stop(); } - /// - // Run this test against a valid WebSocket server runing on SSL. - // See sample below. - /// - /* -const WebSocket = require('ws'); -const fs = require('fs'); -const https = require('https'); - -const httpsServer = https.createServer({ - key: fs.readFileSync('key.pem'), - cert: fs.readFileSync('cert.pem') -}); -const server = new WebSocket.Server({ - server:httpsServer -}); - -server.on('connection', (ws) => { - ws.on('message', (message) => { - console.log('Received message:', message); - if (message === 'exit') { - console.log('WebSocket integration test server exit'); - process.exit(0); - } - console.log('Cookie:', ws.upgradeReq.headers.cookie); - ws.send(message + '_response'); - }); - - ws.send('hello'); -}); - -httpsServer.listen(443); - */ - BEGIN_TEST_METHOD_ATTRIBUTE(SendAndReceiveSsl) - TEST_IGNORE() - END_TEST_METHOD_ATTRIBUTE() - TEST_METHOD(SendAndReceiveSsl) + TEST_METHOD(SendReceiveSsl) { - auto ws = IWebSocket::Make("wss://localhost/"); - string message; - ws->SetOnMessage([&message](size_t size, const string& messageIn) + auto server = make_shared(5556, /*isSecure*/ true); + server->SetMessageFactory([](string&& message) { - message = messageIn; + return message + "_response"; + }); + auto ws = IWebSocket::Make("wss://localhost:5556"); + promise response; + ws->SetOnMessage([&response](size_t size, const string& messageIn) + { + response.set_value(messageIn); }); + server->Start(); ws->Connect(); ws->Send("suffixme"); + + auto result = response.get_future(); + result.wait(); + ws->Close(CloseCode::Normal, "Closing after reading"); + server->Stop(); - Assert::AreEqual(string("hello"), message); + Assert::AreEqual({ "suffixme_response" }, result.get()); } //TODO: Use Test::WebSocketServer!!! diff --git a/vnext/Desktop.IntegrationTests/WebSocketServer.cpp b/vnext/Desktop.IntegrationTests/WebSocketServer.cpp index 4f1c792896a..db5efc24ae7 100644 --- a/vnext/Desktop.IntegrationTests/WebSocketServer.cpp +++ b/vnext/Desktop.IntegrationTests/WebSocketServer.cpp @@ -19,50 +19,50 @@ namespace Test { #pragma region BaseWebSocketSession -template -BaseWebSocketSession::BaseWebSocketSession(WebSocketServiceCallbacks& callbacks) +template +BaseWebSocketSession::BaseWebSocketSession(WebSocketServiceCallbacks& callbacks) : m_callbacks{ callbacks } , m_state{ State::Stopped } { } -template -BaseWebSocketSession::~BaseWebSocketSession() +template +BaseWebSocketSession::~BaseWebSocketSession() { } -template -void BaseWebSocketSession::Start() +template +void BaseWebSocketSession::Start() { Accept(); } -template -void BaseWebSocketSession::Accept() +template +void BaseWebSocketSession::Accept() { m_stream->async_accept_ex( bind_executor(*m_strand, std::bind( - &BaseWebSocketSession::OnHandshake, - this->shared_from_this(), + &BaseWebSocketSession::OnHandshake, + this->SharedFromThis(), _1 // response )), bind_executor(*m_strand, std::bind( - &BaseWebSocketSession::OnAccept, - this->shared_from_this(), + &BaseWebSocketSession::OnAccept, + this->SharedFromThis(), _1 // ec )) ); } -template -void BaseWebSocketSession::OnHandshake(websocket::response_type& response) +template +void BaseWebSocketSession::OnHandshake(websocket::response_type& response) { if (m_callbacks.OnHandshake) m_callbacks.OnHandshake(response); } -template -void BaseWebSocketSession::OnAccept(error_code ec) +template +void BaseWebSocketSession::OnAccept(error_code ec) { if (ec) return;//TODO: fail @@ -75,22 +75,22 @@ void BaseWebSocketSession::OnAccept(error_code ec) Read(); } -template -void BaseWebSocketSession::Read() +template +void BaseWebSocketSession::Read() { if (State::Stopped == m_state) return; m_stream->async_read(m_buffer, bind_executor(*m_strand, std::bind( - &BaseWebSocketSession::OnRead, - this->shared_from_this(), + &BaseWebSocketSession::OnRead, + this->SharedFromThis(), _1, // ec _2 // transferred ))); } -template -void BaseWebSocketSession::OnRead(error_code ec, size_t /*transferred*/) +template +void BaseWebSocketSession::OnRead(error_code ec, size_t /*transferred*/) { if (websocket::error::closed == ec) return; @@ -109,15 +109,15 @@ void BaseWebSocketSession::OnRead(error_code ec, size_t /*transferred m_stream->text(m_stream->got_text()); m_stream->async_write(buffer(m_message), bind_executor(*m_strand, std::bind( - &BaseWebSocketSession::OnWrite, - this->shared_from_this(), + &BaseWebSocketSession::OnWrite, + this->SharedFromThis(), _1, // ec _2 // transferred ))); } -template -void BaseWebSocketSession::OnWrite(error_code ec, size_t /*transferred*/) +template +void BaseWebSocketSession::OnWrite(error_code ec, size_t /*transferred*/) { if (ec) return; //TODO: fail @@ -141,6 +141,15 @@ WebSocketSession::WebSocketSession(ip::tcp::socket socket, WebSocketServiceCallb WebSocketSession::~WebSocketSession() {} +#pragma region BaseWebSocketSession + +std::shared_ptr> WebSocketSession::SharedFromThis() /*override*/ +{ + return this->shared_from_this(); +} + +#pragma endregion // BaseWebSocketSession + #pragma endregion // WebSocketSession #pragma region SecureWebSocketSession @@ -148,28 +157,112 @@ WebSocketSession::~WebSocketSession() {} SecureWebSocketSession::SecureWebSocketSession(ip::tcp::socket socket, WebSocketServiceCallbacks& callbacks) : BaseWebSocketSession(callbacks) { - auto context = ssl::context(ssl::context::sslv23_client); + // Initialize SSL context. + string const cert = + "-----BEGIN CERTIFICATE-----\n" + "MIIDhjCCAm6gAwIBAgIJAPh+egUebaStMA0GCSqGSIb3DQEBCwUAMFgxCzAJBgNV\n" + "BAYTAlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdSZWRtb25kMRIw\n" + "EAYDVQQKDAlNaWNyb3NvZnQxDjAMBgNVBAsMBVJlYWN0MB4XDTE5MDYwMTA4MDcx\n" + "M1oXDTI5MDUyOTA4MDcxM1owWDELMAkGA1UEBhMCVVMxEzARBgNVBAgMCldhc2hp\n" + "bmd0b24xEDAOBgNVBAcMB1JlZG1vbmQxEjAQBgNVBAoMCU1pY3Jvc29mdDEOMAwG\n" + "A1UECwwFUmVhY3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCgHKC9\n" + "XC+1FjDg2Xdmbpf3ILiJQtGFiD3WFb+duNXThOA0LY6gytVBY6LitAzB7Jm7spvx\n" + "BbA46kw8Dsmv02hI0diVzFKCB5bTTs0N8bgAsem6qvDpo/mvp2TtDU2J8o4RhMQ3\n" + "BQvdZUGgtH4VR2W4vIHufNjVUvN9hTL2eOBz0EYElsMSogG8f97N+m/7L6JeyjPo\n" + "kFwXYTFMjv3ihJmev/cBNkxuchLUT7NAc7bMCtmv5lzsKMKe6g0lUxDSBYxXztqU\n" + "l3huo2g990VbvTWH/lhz3bgdnon/AUKWBmS2eRmK9hH/rGlm1NeMCjexMZrYC3m8\n" + "vvfIR25plGmNjyQJAgMBAAGjUzBRMB0GA1UdDgQWBBTNLE3Nl0s3O40wDEXf9t/7\n" + "r6Y1QjAfBgNVHSMEGDAWgBTNLE3Nl0s3O40wDEXf9t/7r6Y1QjAPBgNVHRMBAf8E\n" + "BTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAbRL+69uZLW3Q6JIQ9qg3CPjm6574o\n" + "cOiyJ9DX49i23AyYNsCYulvLApHgrmltMJHrC4U7EasQCTtwpAMyLJDLIDdujSSs\n" + "ynSe5PcNeElLmEkH4PxyAFsb/2oWI2PSJh0vseuugUpeKTHJv5MPkLUm7WMLHYj5\n" + "uOQzYDwJ+IuveVzX5TRXtkY8jF9ErL4iF8eYTyp0ANeY11vJOAbd2FcAy5baYjB3\n" + "JVczHy7eegwfOQJFM9mIZE7+Ac0SaknC0Jun9486cJ0mvbdrMSd+vgF85OrpWwYU\n" + "ISfux0NDVN1gjvSgdkEB+CWnV1rNKsVKlg4psDkpq33AJEwnx3qNxtKG\n" + "-----END CERTIFICATE-----\n"; + + string const key = + "-----BEGIN RSA PRIVATE KEY-----\n" + "MIIEowIBAAKCAQEAoBygvVwvtRYw4Nl3Zm6X9yC4iULRhYg91hW/nbjV04TgNC2O\n" + "oMrVQWOi4rQMweyZu7Kb8QWwOOpMPA7Jr9NoSNHYlcxSggeW007NDfG4ALHpuqrw\n" + "6aP5r6dk7Q1NifKOEYTENwUL3WVBoLR+FUdluLyB7nzY1VLzfYUy9njgc9BGBJbD\n" + "EqIBvH/ezfpv+y+iXsoz6JBcF2ExTI794oSZnr/3ATZMbnIS1E+zQHO2zArZr+Zc\n" + "7CjCnuoNJVMQ0gWMV87alJd4bqNoPfdFW701h/5Yc924HZ6J/wFClgZktnkZivYR\n" + "/6xpZtTXjAo3sTGa2At5vL73yEduaZRpjY8kCQIDAQABAoIBAA/bpgP7THJYF1E9\n" + "2LiZfY2pfP2DU7MxEkbQ8qCRfQQtJfOlC3pbfJG0Z56ijJzsbTGM+CsAEDsi4ZgV\n" + "Mt6qRqrntdboXMeqLsMRC/g0l6/h7y9g3OmXJxTBtJpR9fsSvgV4K+LzKgCslbpw\n" + "BgjfgHCyov/W97bxN1KYTbrhsAFoWFwyTglDIkTYo/92suwsyYt14pxnK54QyNrM\n" + "tWKS0K9rZmSMjaVYW+nnSLelFVAOAzW4SOt8CE1V0usjIkmD5smdadjT14exWnxV\n" + "zVMhsbrfUFi3oBfW8X+TuWQjBnVfX0akZALY6vmnmOEWLz4pXJBLmazSGpXyM5o2\n" + "JpxSUS0CgYEAywE9MhWqKhZXpOwGWbNe1Nibh4l8vt+pTDs2TpFdHXNT8UfuUk03\n" + "ycCxGKrDPUAUPdVGygvmqdKHpXLbWalPGdFR6Xcn5YjVxM7L37jGl28oQOdNLI5u\n" + "Lw7hJ5L84M0LZqMI5589jA63WrgkLNQ9eKnuFn9N/3n9r/uZqtGVjLsCgYEAyejc\n" + "I/St33V0CNDtfEZ8dBDztXhx1WjDzv+JgNiy7pLUB+8yW0/iU2Y8ptpmfQ0nRDDv\n" + "sGK5myuBv85PRgWQnPskL3V5+L+DK40hyYnrL4bKhxT8az2CQdWI23sS4Nq5b59A\n" + "ylUyGIUXv3P62nUgMq3kM7L6mMgz/cCxeVeQyAsCgYAlZAIIgpMIE3trJgn5ZZ9W\n" + "5tqmuT0fzwRYxSM4j2+uJ/rTGyObRxu6bmJwH6u8UVwpE2ppdo2yw9M2NxSNzDCE\n" + "mdhTfx37Ghv9lvVYLKlvZQruAWxmg4lp43y3FEy9fybVbbwLJXppnKBK9lW7aBA2\n" + "dF4lCKeuIaMHUfk4zEeWVwKBgF81HXEa9E4VfUSW+BUMy6yTPcgJZmwCParDFlya\n" + "Ui1rMO4Y3X7vOUKoR9tJyuAWrrhZ9vwOYYUIy+Lc7saO4zUSu2phk8U20SxdHVyC\n" + "W1MK1T9DJw+ObniKr0EHVMyQdrZqusttxvSG9b7Cerw+VJNxKdUzBTW72cBC96zH\n" + "HK8nAoGBAMGKiSm4a1O5SpSiiZ6kNZHw9wB98Jtic7ozoUrlVEPSeRrXq/BzsyyH\n" + "md/sN/1v/Qq4SPlUtnzRakcPa2sntDb4SEt/Lrr97ouX1C/qfWljh69jRDLPBBez\n" + "cAlHdEzualsWQsACr7I71UebXvha+v0XXAKiIRqAKRrFLmPPCFrP\n" + "-----END RSA PRIVATE KEY-----\n"; + + string dh = + "-----BEGIN DH PARAMETERS-----\n" + "MIIBCAKCAQEA5VbTCtf4s2qPpqTtk2pXsYcqo7cLF0LVQaXMhOZNmif0TKDyclSV\n" + "NQANJcl0K9C5cGfh/1oEZs30A+Ww1zCtjkwJFvQdUAhCy/1U/qhRO2swXtz+CGZL\n" + "7PL0yu0Xht3EqGRS4z98LPCALVYvuqbNKTnFHUZl8oYJT0Xx0lzzZ+r5uFYYghQU\n" + "nCohXf/O0VLCPJMnd/oLY70CcPEL9V1KDb80oTzlYzrVPAHidcOXkiZpmOHgdiA/\n" + "LLG0h495hZhL5OqqDrLM7IWxHNmzgwhQ04PdGa6zPP4fnt7L4Ia5/lYOolvdmNkx\n" + "XgdewtScX7P5ltOMhhcWS4Og+qZn18a3kwIBAg==\n" + "-----END DH PARAMETERS-----\n"; + + auto context = ssl::context(ssl::context::sslv23); + + //TODO: Remove if not used. + context.set_password_callback([](size_t, ssl::context_base::password_purpose) + { + return "test"; + }); + + context.set_options(ssl::context::default_workarounds | ssl::context::no_sslv2 | ssl::context::single_dh_use); + context.use_certificate_chain(buffer(cert.data(), cert.size())); + context.use_private_key(buffer(key.data(), key.size()), ssl::context::file_format::pem); + context.use_tmp_dh(buffer(dh.data(), dh.size())); + m_stream = std::make_shared>>(std::move(socket), context); m_strand = std::make_shared>(m_stream->get_executor()); } SecureWebSocketSession::~SecureWebSocketSession() {} +#pragma region BaseWebSocketSession + +std::shared_ptr>> SecureWebSocketSession::SharedFromThis() /*override*/ +{ + return this->shared_from_this(); +} + +#pragma endregion // BaseWebSocketSession + #pragma region IWebSocketSession void SecureWebSocketSession::Start() /*override*/ { - //m_stream->next_layer().async_handshake(ssl::stream_base::server, bind_executor(*m_strand, std::bind( - // &SecureWebSocketSession::OnSslHandshake, - // this->shared_from_this(), - // _1 // ec - //))); + m_stream->next_layer().async_handshake(ssl::stream_base::server, bind_executor(*m_strand, std::bind( + &SecureWebSocketSession::OnSslHandshake, + this->shared_from_this(), + _1 // ec + ))); } void SecureWebSocketSession::OnSslHandshake(error_code ec) { if (ec) - return;//TODO: Handle error + return; Accept(); } @@ -180,10 +273,11 @@ void SecureWebSocketSession::OnSslHandshake(error_code ec) #pragma region WebSocketServer -WebSocketServer::WebSocketServer(uint16_t port) +WebSocketServer::WebSocketServer(uint16_t port, bool isSecure) : m_acceptor{ m_context } , m_socket{ m_context } , m_sessions{} + , m_isSecure{ isSecure } { ip::tcp::endpoint ep{ip::make_address("0.0.0.0"), port }; error_code ec; @@ -191,30 +285,30 @@ WebSocketServer::WebSocketServer(uint16_t port) m_acceptor.open(ep.protocol(), ec); if (ec) { - return; // + return; //TODO: handle } m_acceptor.set_option(socket_base::reuse_address(true), ec); if (ec) { - return; // + return; //TODO: handle } m_acceptor.bind(ep, ec); if (ec) { - return; // + return; //TODO: handle } m_acceptor.listen(socket_base::max_listen_connections, ec); if (ec) { - return; // + return; //TODO: handle } } -WebSocketServer::WebSocketServer(int port) - : WebSocketServer(static_cast(port)) +WebSocketServer::WebSocketServer(int port, bool isSecure) + : WebSocketServer(static_cast(port), isSecure) { } @@ -252,7 +346,12 @@ void WebSocketServer::OnAccept(error_code ec) } else { - auto session = std::shared_ptr(new WebSocketSession(std::move(m_socket), m_callbacks)); + std::shared_ptr session; + if (m_isSecure) + session = std::shared_ptr(new SecureWebSocketSession(std::move(m_socket), m_callbacks)); + else + session = std::shared_ptr(new WebSocketSession(std::move(m_socket), m_callbacks)); + m_sessions.push_back(session); session->Start(); } diff --git a/vnext/Desktop.IntegrationTests/WebSocketServer.h b/vnext/Desktop.IntegrationTests/WebSocketServer.h index 4e5e95cc7e1..ce7ff5dc650 100644 --- a/vnext/Desktop.IntegrationTests/WebSocketServer.h +++ b/vnext/Desktop.IntegrationTests/WebSocketServer.h @@ -26,10 +26,9 @@ struct IWebSocketSession virtual void Start() = 0; }; -template -class BaseWebSocketSession : public std::enable_shared_from_this>, public IWebSocketSession +template +class BaseWebSocketSession : public IWebSocketSession { - //TODO: Used at all? enum class State : std::size_t { Started, @@ -39,7 +38,7 @@ class BaseWebSocketSession : public std::enable_shared_from_this m_errorHandler; @@ -51,11 +50,13 @@ class BaseWebSocketSession : public std::enable_shared_from_this> m_stream; + std::shared_ptr> m_stream; std::shared_ptr> m_strand; void Accept(); + virtual std::shared_ptr> SharedFromThis() = 0; + public: BaseWebSocketSession(WebSocketServiceCallbacks& callbacks); ~BaseWebSocketSession(); @@ -64,16 +65,23 @@ class BaseWebSocketSession : public std::enable_shared_from_this + : public std::enable_shared_from_this + , public BaseWebSocketSession { + std::shared_ptr> SharedFromThis() override; + public: WebSocketSession(boost::asio::ip::tcp::socket socket, WebSocketServiceCallbacks& callbacks); ~WebSocketSession(); }; class SecureWebSocketSession - : public BaseWebSocketSession> + : public std::enable_shared_from_this + , public BaseWebSocketSession> { + std::shared_ptr>> SharedFromThis() override; + +public: SecureWebSocketSession(boost::asio::ip::tcp::socket socket, WebSocketServiceCallbacks& callbacks); ~SecureWebSocketSession(); @@ -94,14 +102,15 @@ class WebSocketServer : public std::enable_shared_from_this boost::asio::ip::tcp::socket m_socket; WebSocketServiceCallbacks m_callbacks; std::vector> m_sessions; + bool m_isSecure; void Accept(); void OnAccept(boost::system::error_code ec); public: - WebSocketServer(std::uint16_t port); - WebSocketServer(int port); + WebSocketServer(std::uint16_t port, bool isSecure); + WebSocketServer(int port, bool isSecure = false); void Start(); void Stop(); From 8c6b5dc4b29744551f0c42582db51d7b8d08d731 Mon Sep 17 00:00:00 2001 From: "Julio C. Rocha" Date: Thu, 6 Jun 2019 17:32:34 -0700 Subject: [PATCH 21/30] Temporarily disable x86 in favor of Win32. --- vnext/Desktop.DLL/React.Windows.Desktop.DLL.vcxproj | 8 ++++---- vnext/Desktop.DLL/packages.config | 2 +- .../React.Windows.Desktop.IntegrationTests.vcxproj | 8 ++++---- vnext/Desktop.IntegrationTests/packages.config | 2 +- .../React.Windows.Desktop.UnitTests.vcxproj | 8 ++++---- vnext/Desktop.UnitTests/packages.config | 2 +- vnext/Desktop/React.Windows.Desktop.vcxproj | 8 ++++---- vnext/Desktop/packages.config | 2 +- vnext/Directory.Build.props | 2 +- vnext/Directory.Build.targets | 2 +- .../React.Windows.IntegrationTests.vcxproj | 8 ++++---- 11 files changed, 26 insertions(+), 26 deletions(-) diff --git a/vnext/Desktop.DLL/React.Windows.Desktop.DLL.vcxproj b/vnext/Desktop.DLL/React.Windows.Desktop.DLL.vcxproj index 0450e9fa76c..a24bede4cb2 100644 --- a/vnext/Desktop.DLL/React.Windows.Desktop.DLL.vcxproj +++ b/vnext/Desktop.DLL/React.Windows.Desktop.DLL.vcxproj @@ -1,14 +1,14 @@ - + Debug x64 @@ -143,20 +143,20 @@ - + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + \ No newline at end of file diff --git a/vnext/Desktop.DLL/packages.config b/vnext/Desktop.DLL/packages.config index 45e6ddc4b1e..e5570eb747c 100644 --- a/vnext/Desktop.DLL/packages.config +++ b/vnext/Desktop.DLL/packages.config @@ -2,7 +2,7 @@ + - \ No newline at end of file diff --git a/vnext/Desktop.IntegrationTests/React.Windows.Desktop.IntegrationTests.vcxproj b/vnext/Desktop.IntegrationTests/React.Windows.Desktop.IntegrationTests.vcxproj index bac80063ab5..772addbd70e 100644 --- a/vnext/Desktop.IntegrationTests/React.Windows.Desktop.IntegrationTests.vcxproj +++ b/vnext/Desktop.IntegrationTests/React.Windows.Desktop.IntegrationTests.vcxproj @@ -1,14 +1,14 @@ - + Debug x64 @@ -136,21 +136,21 @@ - + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + diff --git a/vnext/Desktop.IntegrationTests/packages.config b/vnext/Desktop.IntegrationTests/packages.config index 45e6ddc4b1e..e5570eb747c 100644 --- a/vnext/Desktop.IntegrationTests/packages.config +++ b/vnext/Desktop.IntegrationTests/packages.config @@ -2,7 +2,7 @@ + - \ No newline at end of file diff --git a/vnext/Desktop.UnitTests/React.Windows.Desktop.UnitTests.vcxproj b/vnext/Desktop.UnitTests/React.Windows.Desktop.UnitTests.vcxproj index f3e1c03d2b8..2e23e496388 100644 --- a/vnext/Desktop.UnitTests/React.Windows.Desktop.UnitTests.vcxproj +++ b/vnext/Desktop.UnitTests/React.Windows.Desktop.UnitTests.vcxproj @@ -1,14 +1,14 @@ - + Debug x64 @@ -103,8 +103,8 @@ - + @@ -112,8 +112,8 @@ - + diff --git a/vnext/Desktop.UnitTests/packages.config b/vnext/Desktop.UnitTests/packages.config index 897ea128c47..1516830fa04 100644 --- a/vnext/Desktop.UnitTests/packages.config +++ b/vnext/Desktop.UnitTests/packages.config @@ -2,6 +2,6 @@ + - \ No newline at end of file diff --git a/vnext/Desktop/React.Windows.Desktop.vcxproj b/vnext/Desktop/React.Windows.Desktop.vcxproj index e7020b82b49..c1d050e0bce 100644 --- a/vnext/Desktop/React.Windows.Desktop.vcxproj +++ b/vnext/Desktop/React.Windows.Desktop.vcxproj @@ -1,14 +1,14 @@ - + Debug x64 @@ -159,20 +159,20 @@ - + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + \ No newline at end of file diff --git a/vnext/Desktop/packages.config b/vnext/Desktop/packages.config index 45e6ddc4b1e..e5570eb747c 100644 --- a/vnext/Desktop/packages.config +++ b/vnext/Desktop/packages.config @@ -2,7 +2,7 @@ + - \ No newline at end of file diff --git a/vnext/Directory.Build.props b/vnext/Directory.Build.props index c9a843f8bf4..44c50076839 100644 --- a/vnext/Directory.Build.props +++ b/vnext/Directory.Build.props @@ -16,7 +16,7 @@ - x86 + $(ReactNativeWindowsDir)build\$(Platform)\$(Configuration) $(ReactNativeWindowsDir)target\$(Platform)\$(Configuration) diff --git a/vnext/Directory.Build.targets b/vnext/Directory.Build.targets index 23efe85aff1..0a71a22011b 100644 --- a/vnext/Directory.Build.targets +++ b/vnext/Directory.Build.targets @@ -3,7 +3,7 @@ - x86 + diff --git a/vnext/IntegrationTests/React.Windows.IntegrationTests.vcxproj b/vnext/IntegrationTests/React.Windows.IntegrationTests.vcxproj index e844b58589d..a17c04f0a6a 100644 --- a/vnext/IntegrationTests/React.Windows.IntegrationTests.vcxproj +++ b/vnext/IntegrationTests/React.Windows.IntegrationTests.vcxproj @@ -5,10 +5,10 @@ Debug ARM - + Debug x64 @@ -17,10 +17,10 @@ Release ARM - + Release x64 From f860d548adcea759c4bdd07abc88de35aaf883d4 Mon Sep 17 00:00:00 2001 From: "Julio C. Rocha" Date: Mon, 10 Jun 2019 21:46:46 -0700 Subject: [PATCH 22/30] Make IWebSocket::Make __cdecl. --- .../React.Windows.Desktop.DLL.vcxproj | 4 ++-- vnext/Desktop.DLL/packages.config | 2 +- vnext/Desktop.DLL/react-native-win32.x86.def | 4 ++-- ...t.Windows.Desktop.IntegrationTests.vcxproj | 12 ++++++---- .../WebSocketIntegrationTest.cpp | 8 +++---- .../Desktop.IntegrationTests/packages.config | 2 +- .../React.Windows.Desktop.UnitTests.vcxproj | 12 ++++++---- vnext/Desktop.UnitTests/packages.config | 2 +- vnext/Desktop/LegacyWebSocket.cpp | 4 +--- vnext/Desktop/React.Windows.Desktop.vcxproj | 14 +++++++---- vnext/Desktop/WebSocket.cpp | 4 +--- vnext/Desktop/packages.config | 2 +- vnext/ReactWindowsCore/IWebSocket.h | 4 ++-- vnext/ReactWindowsCore/unicode.cpp | 24 +++++++++---------- vnext/include/ReactWindowsCore/unicode.h | 24 +++++++++---------- 15 files changed, 66 insertions(+), 56 deletions(-) diff --git a/vnext/Desktop.DLL/React.Windows.Desktop.DLL.vcxproj b/vnext/Desktop.DLL/React.Windows.Desktop.DLL.vcxproj index a24bede4cb2..094a5f44a00 100644 --- a/vnext/Desktop.DLL/React.Windows.Desktop.DLL.vcxproj +++ b/vnext/Desktop.DLL/React.Windows.Desktop.DLL.vcxproj @@ -147,7 +147,7 @@ - + @@ -157,6 +157,6 @@ - + \ No newline at end of file diff --git a/vnext/Desktop.DLL/packages.config b/vnext/Desktop.DLL/packages.config index e5570eb747c..1d5582e3b95 100644 --- a/vnext/Desktop.DLL/packages.config +++ b/vnext/Desktop.DLL/packages.config @@ -2,7 +2,7 @@ - + \ No newline at end of file diff --git a/vnext/Desktop.DLL/react-native-win32.x86.def b/vnext/Desktop.DLL/react-native-win32.x86.def index 0b4df2812ce..1295ef20ae7 100644 --- a/vnext/Desktop.DLL/react-native-win32.x86.def +++ b/vnext/Desktop.DLL/react-native-win32.x86.def @@ -47,10 +47,10 @@ EXPORTS ?utf16ToUtf8@unicode@react@facebook@@YG?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@ABV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@5@@Z ?utf8ToUtf16@unicode@react@facebook@@YG?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@5@@Z ?Make@IHttpResource@react@facebook@@SG?AV?$unique_ptr@UIHttpResource@react@facebook@@U?$default_delete@UIHttpResource@react@facebook@@@std@@@std@@XZ -?Make@IWebSocket@React@Microsoft@@SG?AV?$unique_ptr@UIWebSocket@React@Microsoft@@U?$default_delete@UIWebSocket@React@Microsoft@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@5@@Z +?Make@IWebSocket@React@Microsoft@@SA?AV?$unique_ptr@UIWebSocket@React@Microsoft@@U?$default_delete@UIWebSocket@React@Microsoft@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@5@@Z ?Make@JSBigAbiString@react@facebook@@SG?AV?$unique_ptr@$$CBUJSBigAbiString@react@facebook@@U?$default_delete@$$CBUJSBigAbiString@react@facebook@@@std@@@std@@$$QAV?$unique_ptr@U?$IAbiArray@D@AbiSafe@@UAbiObjectDeleter@2@@5@@Z ?Make@JSBigStringResourceDll@react@facebook@@SG?AV?$unique_ptr@$$CBVJSBigStringResourceDll@react@facebook@@U?$default_delete@$$CBVJSBigStringResourceDll@react@facebook@@@std@@@std@@PAUHINSTANCE__@@PAUHRSRC__@@@Z -?MakeLegacy@IWebSocket@React@Microsoft@@SG?AV?$unique_ptr@UIWebSocket@React@Microsoft@@U?$default_delete@UIWebSocket@React@Microsoft@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@5@@Z +?MakeLegacy@IWebSocket@React@Microsoft@@SA?AV?$unique_ptr@UIWebSocket@React@Microsoft@@U?$default_delete@UIWebSocket@React@Microsoft@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@5@@Z ?asFunction@Object@jsi@facebook@@QHAE?AVFunction@23@AAVRuntime@23@@Z ??1Value@jsi@facebook@@QAE@XZ ??1Buffer@jsi@facebook@@UAE@XZ diff --git a/vnext/Desktop.IntegrationTests/React.Windows.Desktop.IntegrationTests.vcxproj b/vnext/Desktop.IntegrationTests/React.Windows.Desktop.IntegrationTests.vcxproj index 772addbd70e..b538b8ace6b 100644 --- a/vnext/Desktop.IntegrationTests/React.Windows.Desktop.IntegrationTests.vcxproj +++ b/vnext/Desktop.IntegrationTests/React.Windows.Desktop.IntegrationTests.vcxproj @@ -99,11 +99,15 @@ - + + Cdecl + - + + Cdecl + @@ -140,7 +144,7 @@ - + @@ -150,7 +154,7 @@ - + diff --git a/vnext/Desktop.IntegrationTests/WebSocketIntegrationTest.cpp b/vnext/Desktop.IntegrationTests/WebSocketIntegrationTest.cpp index 03bb5f6c6a5..19ce87d4828 100644 --- a/vnext/Desktop.IntegrationTests/WebSocketIntegrationTest.cpp +++ b/vnext/Desktop.IntegrationTests/WebSocketIntegrationTest.cpp @@ -4,7 +4,6 @@ #include #include #include -#include "unicode.h" #include #include @@ -199,10 +198,10 @@ TEST_CLASS(WebSocketIntegrationTest) { response.set_value(message); }); - ws->SetOnError([](IWebSocket::Error err) + string errorMessage; + ws->SetOnError([&errorMessage](IWebSocket::Error err) { - auto message = facebook::react::unicode::utf8ToUtf16(err.Message); - Assert::Fail(message.c_str()); + errorMessage = err.Message; }); server->Start(); @@ -227,6 +226,7 @@ TEST_CLASS(WebSocketIntegrationTest) ws->Close(CloseCode::Normal, "Closing after reading"); server->Stop(); + Assert::AreEqual({}, errorMessage); Assert::AreEqual(static_cast(LEN + string("_response").length()), result.length()); } diff --git a/vnext/Desktop.IntegrationTests/packages.config b/vnext/Desktop.IntegrationTests/packages.config index e5570eb747c..1d5582e3b95 100644 --- a/vnext/Desktop.IntegrationTests/packages.config +++ b/vnext/Desktop.IntegrationTests/packages.config @@ -2,7 +2,7 @@ - + \ No newline at end of file diff --git a/vnext/Desktop.UnitTests/React.Windows.Desktop.UnitTests.vcxproj b/vnext/Desktop.UnitTests/React.Windows.Desktop.UnitTests.vcxproj index 2e23e496388..fd9424a09b8 100644 --- a/vnext/Desktop.UnitTests/React.Windows.Desktop.UnitTests.vcxproj +++ b/vnext/Desktop.UnitTests/React.Windows.Desktop.UnitTests.vcxproj @@ -71,7 +71,9 @@ - + + Cdecl + @@ -82,7 +84,9 @@ - + + Cdecl + @@ -104,7 +108,7 @@ - + @@ -113,7 +117,7 @@ - + diff --git a/vnext/Desktop.UnitTests/packages.config b/vnext/Desktop.UnitTests/packages.config index 1516830fa04..e5a55045374 100644 --- a/vnext/Desktop.UnitTests/packages.config +++ b/vnext/Desktop.UnitTests/packages.config @@ -2,6 +2,6 @@ - + \ No newline at end of file diff --git a/vnext/Desktop/LegacyWebSocket.cpp b/vnext/Desktop/LegacyWebSocket.cpp index eab28858364..a2cd1de3435 100644 --- a/vnext/Desktop/LegacyWebSocket.cpp +++ b/vnext/Desktop/LegacyWebSocket.cpp @@ -1,8 +1,6 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -#include "pch.h" - #pragma warning( push ) #pragma warning( disable : 4996 ) // std::copy::_Unchecked_iterators::_Deprecate @@ -445,7 +443,7 @@ template class LegacySecureWebSocket>; #pragma region IWebSocket static members -/*static*/ std::unique_ptr IWebSocket::MakeLegacy(const string& urlString) +/*static*/ std::unique_ptr __cdecl IWebSocket::MakeLegacy(const string& urlString) { Url url(urlString); diff --git a/vnext/Desktop/React.Windows.Desktop.vcxproj b/vnext/Desktop/React.Windows.Desktop.vcxproj index c1d050e0bce..194b73e38f3 100644 --- a/vnext/Desktop/React.Windows.Desktop.vcxproj +++ b/vnext/Desktop/React.Windows.Desktop.vcxproj @@ -105,7 +105,10 @@ - + + + Cdecl + @@ -117,7 +120,10 @@ - + + + Cdecl + @@ -163,7 +169,7 @@ - + @@ -173,6 +179,6 @@ - + \ No newline at end of file diff --git a/vnext/Desktop/WebSocket.cpp b/vnext/Desktop/WebSocket.cpp index 0d192c1a816..b853c3b9ea8 100644 --- a/vnext/Desktop/WebSocket.cpp +++ b/vnext/Desktop/WebSocket.cpp @@ -1,8 +1,6 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -#include "pch.h" - #pragma warning( push ) #pragma warning( disable : 4996 ) // std::copy::_Unchecked_iterators::_Deprecate @@ -483,7 +481,7 @@ void SecureWebSocket::Handshake(const IWebSocket::Options& options) #pragma region IWebSocket static members -/*static*/ unique_ptr IWebSocket::Make(const string& urlString) +/*static*/ unique_ptr __cdecl IWebSocket::Make(const string& urlString) { Url url(urlString); diff --git a/vnext/Desktop/packages.config b/vnext/Desktop/packages.config index e5570eb747c..1d5582e3b95 100644 --- a/vnext/Desktop/packages.config +++ b/vnext/Desktop/packages.config @@ -2,7 +2,7 @@ - + \ No newline at end of file diff --git a/vnext/ReactWindowsCore/IWebSocket.h b/vnext/ReactWindowsCore/IWebSocket.h index 1aa8e4251e3..dadb418b8e5 100644 --- a/vnext/ReactWindowsCore/IWebSocket.h +++ b/vnext/ReactWindowsCore/IWebSocket.h @@ -73,10 +73,10 @@ struct IWebSocket #pragma endregion // Inner types - static std::unique_ptr Make(const std::string& url); + static std::unique_ptr __cdecl Make(const std::string& url); // Only use if a legacy implementation is required as fallback. - static std::unique_ptr MakeLegacy(const std::string& url); + static std::unique_ptr __cdecl MakeLegacy(const std::string& url); virtual ~IWebSocket() {} diff --git a/vnext/ReactWindowsCore/unicode.cpp b/vnext/ReactWindowsCore/unicode.cpp index 9a5615bb6bd..e073f2962a7 100644 --- a/vnext/ReactWindowsCore/unicode.cpp +++ b/vnext/ReactWindowsCore/unicode.cpp @@ -19,7 +19,7 @@ namespace unicode { // The implementations of the following functions heavily reference the MSDN // article at https://msdn.microsoft.com/en-us/magazine/mt763237.aspx. -std::wstring utf8ToUtf16(const char* utf8, size_t utf8Len) +std::wstring __stdcall utf8ToUtf16(const char* utf8, size_t utf8Len) { std::wstring utf16{}; @@ -91,24 +91,24 @@ std::wstring utf8ToUtf16(const char* utf8, size_t utf8Len) return utf16; } -std::wstring utf8ToUtf16(const char* utf8) +std::wstring __stdcall utf8ToUtf16(const char* utf8) { return utf8ToUtf16(utf8, strlen(utf8)); } -std::wstring utf8ToUtf16(const std::string& utf8) +std::wstring __stdcall utf8ToUtf16(const std::string& utf8) { return utf8ToUtf16(utf8.c_str(), utf8.length()); } #if _HAS_CXX17 -std::wstring utf8ToUtf16(const std::string_view& utf8) +std::wstring __stdcall utf8ToUtf16(const std::string_view& utf8) { return utf8ToUtf16(utf8.data(), utf8.length()); } #endif -std::string utf16ToUtf8(const wchar_t* utf16, size_t utf16Len) +std::string __stdcall utf16ToUtf8(const wchar_t* utf16, size_t utf16Len) { std::string utf8{}; @@ -184,28 +184,28 @@ std::string utf16ToUtf8(const wchar_t* utf16, size_t utf16Len) return utf8; } -std::string utf16ToUtf8(const char16_t* utf16, size_t utf16Len) +std::string __stdcall utf16ToUtf8(const char16_t* utf16, size_t utf16Len) { return utf16ToUtf8( utilities::checkedReinterpretCast(utf16), utf16Len); } -std::string utf16ToUtf8(const wchar_t* utf16) +std::string __stdcall utf16ToUtf8(const wchar_t* utf16) { return utf16ToUtf8(utf16, wcslen(utf16)); } -std::string utf16ToUtf8(const char16_t* utf16) +std::string __stdcall utf16ToUtf8(const char16_t* utf16) { return utf16ToUtf8(utf16, std::char_traits::length(utf16)); } -std::string utf16ToUtf8(const std::wstring& utf16) +std::string __stdcall utf16ToUtf8(const std::wstring& utf16) { return utf16ToUtf8(utf16.c_str(), utf16.length()); } -std::string utf16ToUtf8(const std::u16string& utf16) +std::string __stdcall utf16ToUtf8(const std::u16string& utf16) { return utf16ToUtf8( utilities::checkedReinterpretCast(utf16.c_str()), @@ -213,12 +213,12 @@ std::string utf16ToUtf8(const std::u16string& utf16) } #if _HAS_CXX17 -std::string utf16ToUtf8(const std::wstring_view& utf16) +std::string __stdcall utf16ToUtf8(const std::wstring_view& utf16) { return utf16ToUtf8(utf16.data(), utf16.length()); } -std::string utf16ToUtf8(const std::u16string_view& utf16) +std::string __stdcall utf16ToUtf8(const std::u16string_view& utf16) { return utf16ToUtf8( utilities::checkedReinterpretCast(utf16.data()), diff --git a/vnext/include/ReactWindowsCore/unicode.h b/vnext/include/ReactWindowsCore/unicode.h index c666b6ce519..506464e1cf4 100644 --- a/vnext/include/ReactWindowsCore/unicode.h +++ b/vnext/include/ReactWindowsCore/unicode.h @@ -54,11 +54,11 @@ class UnicodeConversionException : public std::runtime_error // // For (2), utf8 must be null terminated. The behavior is undefined otherwise. // -/* (1) */ std::wstring utf8ToUtf16(const char* utf8, size_t utf8Len); -/* (2) */ std::wstring utf8ToUtf16(const char* utf8); -/* (3) */ std::wstring utf8ToUtf16(const std::string& utf8); +/* (1) */ std::wstring __stdcall utf8ToUtf16(const char* utf8, size_t utf8Len); +/* (2) */ std::wstring __stdcall utf8ToUtf16(const char* utf8); +/* (3) */ std::wstring __stdcall utf8ToUtf16(const std::string& utf8); #if _HAS_CXX17 -/* (4) */ std::wstring utf8ToUtf16(const std::string_view& utf8); +/* (4) */ std::wstring __stdcall utf8ToUtf16(const std::string_view& utf8); #endif // The following functions convert UTF-16BE strings to UTF-8 strings. Their @@ -71,15 +71,15 @@ class UnicodeConversionException : public std::runtime_error // For (3) and (4), utf16 must be null terminated. The behavior is undefined // otherwise. // -/* (1) */ std::string utf16ToUtf8(const wchar_t* utf16, size_t utf16Len); -/* (2) */ std::string utf16ToUtf8(const char16_t* utf16, size_t utf16Len); -/* (3) */ std::string utf16ToUtf8(const wchar_t* utf16); -/* (4) */ std::string utf16ToUtf8(const char16_t* utf16); -/* (5) */ std::string utf16ToUtf8(const std::wstring& utf16); -/* (6) */ std::string utf16ToUtf8(const std::u16string& utf16); +/* (1) */ std::string __stdcall utf16ToUtf8(const wchar_t* utf16, size_t utf16Len); +/* (2) */ std::string __stdcall utf16ToUtf8(const char16_t* utf16, size_t utf16Len); +/* (3) */ std::string __stdcall utf16ToUtf8(const wchar_t* utf16); +/* (4) */ std::string __stdcall utf16ToUtf8(const char16_t* utf16); +/* (5) */ std::string __stdcall utf16ToUtf8(const std::wstring& utf16); +/* (6) */ std::string __stdcall utf16ToUtf8(const std::u16string& utf16); #if _HAS_CXX17 -/* (7) */ std::string utf16ToUtf8(const std::wstring_view& utf16); -/* (8) */ std::string utf16ToUtf8(const std::u16string_view& utf16); +/* (7) */ std::string __stdcall utf16ToUtf8(const std::wstring_view& utf16); +/* (8) */ std::string __stdcall utf16ToUtf8(const std::u16string_view& utf16); #endif } // namespace utilities From 002eb0a342f5fdf922f5add2c527ab6dbba9b20d Mon Sep 17 00:00:00 2001 From: "Julio C. Rocha" Date: Mon, 10 Jun 2019 22:47:51 -0700 Subject: [PATCH 23/30] Reverted back to using OpenSSL.Windows-1.0.2n. --- .../Desktop.DLL/React.Windows.Desktop.DLL.vcxproj | 8 ++++---- vnext/Desktop.DLL/packages.config | 2 +- .../React.Windows.Desktop.IntegrationTests.vcxproj | 8 ++++---- vnext/Desktop.IntegrationTests/packages.config | 2 +- .../React.Windows.Desktop.UnitTests.vcxproj | 8 ++++---- vnext/Desktop.UnitTests/packages.config | 2 +- vnext/Desktop/React.Windows.Desktop.vcxproj | 14 ++++++++------ vnext/Desktop/packages.config | 2 +- vnext/Directory.Build.props | 2 +- vnext/Directory.Build.targets | 2 +- 10 files changed, 26 insertions(+), 24 deletions(-) diff --git a/vnext/Desktop.DLL/React.Windows.Desktop.DLL.vcxproj b/vnext/Desktop.DLL/React.Windows.Desktop.DLL.vcxproj index 094a5f44a00..e4a497e1b29 100644 --- a/vnext/Desktop.DLL/React.Windows.Desktop.DLL.vcxproj +++ b/vnext/Desktop.DLL/React.Windows.Desktop.DLL.vcxproj @@ -1,14 +1,14 @@ - + Debug x64 @@ -147,7 +147,7 @@ - + @@ -157,6 +157,6 @@ - + \ No newline at end of file diff --git a/vnext/Desktop.DLL/packages.config b/vnext/Desktop.DLL/packages.config index 1d5582e3b95..45e6ddc4b1e 100644 --- a/vnext/Desktop.DLL/packages.config +++ b/vnext/Desktop.DLL/packages.config @@ -2,7 +2,7 @@ - + \ No newline at end of file diff --git a/vnext/Desktop.IntegrationTests/React.Windows.Desktop.IntegrationTests.vcxproj b/vnext/Desktop.IntegrationTests/React.Windows.Desktop.IntegrationTests.vcxproj index b538b8ace6b..b9f641bc3d4 100644 --- a/vnext/Desktop.IntegrationTests/React.Windows.Desktop.IntegrationTests.vcxproj +++ b/vnext/Desktop.IntegrationTests/React.Windows.Desktop.IntegrationTests.vcxproj @@ -1,14 +1,14 @@ - + Debug x64 @@ -144,7 +144,7 @@ - + @@ -154,7 +154,7 @@ - + diff --git a/vnext/Desktop.IntegrationTests/packages.config b/vnext/Desktop.IntegrationTests/packages.config index 1d5582e3b95..45e6ddc4b1e 100644 --- a/vnext/Desktop.IntegrationTests/packages.config +++ b/vnext/Desktop.IntegrationTests/packages.config @@ -2,7 +2,7 @@ - + \ No newline at end of file diff --git a/vnext/Desktop.UnitTests/React.Windows.Desktop.UnitTests.vcxproj b/vnext/Desktop.UnitTests/React.Windows.Desktop.UnitTests.vcxproj index fd9424a09b8..cccf8257d82 100644 --- a/vnext/Desktop.UnitTests/React.Windows.Desktop.UnitTests.vcxproj +++ b/vnext/Desktop.UnitTests/React.Windows.Desktop.UnitTests.vcxproj @@ -1,14 +1,14 @@ - + Debug x64 @@ -108,7 +108,7 @@ - + @@ -117,7 +117,7 @@ - + diff --git a/vnext/Desktop.UnitTests/packages.config b/vnext/Desktop.UnitTests/packages.config index e5a55045374..897ea128c47 100644 --- a/vnext/Desktop.UnitTests/packages.config +++ b/vnext/Desktop.UnitTests/packages.config @@ -2,6 +2,6 @@ - + \ No newline at end of file diff --git a/vnext/Desktop/React.Windows.Desktop.vcxproj b/vnext/Desktop/React.Windows.Desktop.vcxproj index 194b73e38f3..d48ac065f3a 100644 --- a/vnext/Desktop/React.Windows.Desktop.vcxproj +++ b/vnext/Desktop/React.Windows.Desktop.vcxproj @@ -1,14 +1,14 @@ - + Debug x64 @@ -106,7 +106,8 @@ - + + Cdecl @@ -121,7 +122,8 @@ - + + Cdecl @@ -169,7 +171,7 @@ - + @@ -179,6 +181,6 @@ - + \ No newline at end of file diff --git a/vnext/Desktop/packages.config b/vnext/Desktop/packages.config index 1d5582e3b95..45e6ddc4b1e 100644 --- a/vnext/Desktop/packages.config +++ b/vnext/Desktop/packages.config @@ -2,7 +2,7 @@ - + \ No newline at end of file diff --git a/vnext/Directory.Build.props b/vnext/Directory.Build.props index 44c50076839..c9a843f8bf4 100644 --- a/vnext/Directory.Build.props +++ b/vnext/Directory.Build.props @@ -16,7 +16,7 @@ - + x86 $(ReactNativeWindowsDir)build\$(Platform)\$(Configuration) $(ReactNativeWindowsDir)target\$(Platform)\$(Configuration) diff --git a/vnext/Directory.Build.targets b/vnext/Directory.Build.targets index 0a71a22011b..23efe85aff1 100644 --- a/vnext/Directory.Build.targets +++ b/vnext/Directory.Build.targets @@ -3,7 +3,7 @@ - + x86 From 7824a717ba73f3bef65348bb70b52532eb5a0348 Mon Sep 17 00:00:00 2001 From: "Julio C. Rocha" Date: Mon, 10 Jun 2019 23:26:48 -0700 Subject: [PATCH 24/30] Re-introduced x86 as platform for IntegrationTests common. --- .../React.Windows.IntegrationTests.vcxproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/vnext/IntegrationTests/React.Windows.IntegrationTests.vcxproj b/vnext/IntegrationTests/React.Windows.IntegrationTests.vcxproj index a17c04f0a6a..e844b58589d 100644 --- a/vnext/IntegrationTests/React.Windows.IntegrationTests.vcxproj +++ b/vnext/IntegrationTests/React.Windows.IntegrationTests.vcxproj @@ -5,10 +5,10 @@ Debug ARM - + Debug x64 @@ -17,10 +17,10 @@ Release ARM - + Release x64 From d8dcbf1234048b6e3c021f41dd285ad4bcd21990 Mon Sep 17 00:00:00 2001 From: "Julio C. Rocha" Date: Tue, 11 Jun 2019 18:58:44 -0700 Subject: [PATCH 25/30] Use OpenSSL.Windows-1.0.2n 0.0.3. --- .../React.Windows.Desktop.DLL.vcxproj | 4 ++-- vnext/Desktop.DLL/packages.config | 4 ++-- vnext/Desktop.DLL/react-native-win32.x86.def | 4 ++-- ...act.Windows.Desktop.IntegrationTests.vcxproj | 12 ++++-------- vnext/Desktop.IntegrationTests/packages.config | 4 ++-- .../React.Windows.Desktop.UnitTests.vcxproj | 4 ++-- vnext/Desktop.UnitTests/packages.config | 4 ++-- vnext/Desktop/LegacyWebSocket.cpp | 4 +++- vnext/Desktop/React.Windows.Desktop.vcxproj | 17 +++++------------ .../React.Windows.Desktop.vcxproj.filters | 1 + vnext/Desktop/Stubs.cpp | 7 +++++++ vnext/Desktop/WebSocket.cpp | 4 +++- vnext/Desktop/packages.config | 4 ++-- vnext/ReactWindowsCore/IWebSocket.h | 4 ++-- 14 files changed, 39 insertions(+), 38 deletions(-) create mode 100644 vnext/Desktop/Stubs.cpp diff --git a/vnext/Desktop.DLL/React.Windows.Desktop.DLL.vcxproj b/vnext/Desktop.DLL/React.Windows.Desktop.DLL.vcxproj index 572293cdfdf..1127bbd6670 100644 --- a/vnext/Desktop.DLL/React.Windows.Desktop.DLL.vcxproj +++ b/vnext/Desktop.DLL/React.Windows.Desktop.DLL.vcxproj @@ -150,7 +150,7 @@ - + @@ -160,6 +160,6 @@ - + \ No newline at end of file diff --git a/vnext/Desktop.DLL/packages.config b/vnext/Desktop.DLL/packages.config index 108f4b4577d..5fa79e4ee41 100644 --- a/vnext/Desktop.DLL/packages.config +++ b/vnext/Desktop.DLL/packages.config @@ -4,5 +4,5 @@ - - \ No newline at end of file + + diff --git a/vnext/Desktop.DLL/react-native-win32.x86.def b/vnext/Desktop.DLL/react-native-win32.x86.def index 1295ef20ae7..0b4df2812ce 100644 --- a/vnext/Desktop.DLL/react-native-win32.x86.def +++ b/vnext/Desktop.DLL/react-native-win32.x86.def @@ -47,10 +47,10 @@ EXPORTS ?utf16ToUtf8@unicode@react@facebook@@YG?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@ABV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@5@@Z ?utf8ToUtf16@unicode@react@facebook@@YG?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@5@@Z ?Make@IHttpResource@react@facebook@@SG?AV?$unique_ptr@UIHttpResource@react@facebook@@U?$default_delete@UIHttpResource@react@facebook@@@std@@@std@@XZ -?Make@IWebSocket@React@Microsoft@@SA?AV?$unique_ptr@UIWebSocket@React@Microsoft@@U?$default_delete@UIWebSocket@React@Microsoft@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@5@@Z +?Make@IWebSocket@React@Microsoft@@SG?AV?$unique_ptr@UIWebSocket@React@Microsoft@@U?$default_delete@UIWebSocket@React@Microsoft@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@5@@Z ?Make@JSBigAbiString@react@facebook@@SG?AV?$unique_ptr@$$CBUJSBigAbiString@react@facebook@@U?$default_delete@$$CBUJSBigAbiString@react@facebook@@@std@@@std@@$$QAV?$unique_ptr@U?$IAbiArray@D@AbiSafe@@UAbiObjectDeleter@2@@5@@Z ?Make@JSBigStringResourceDll@react@facebook@@SG?AV?$unique_ptr@$$CBVJSBigStringResourceDll@react@facebook@@U?$default_delete@$$CBVJSBigStringResourceDll@react@facebook@@@std@@@std@@PAUHINSTANCE__@@PAUHRSRC__@@@Z -?MakeLegacy@IWebSocket@React@Microsoft@@SA?AV?$unique_ptr@UIWebSocket@React@Microsoft@@U?$default_delete@UIWebSocket@React@Microsoft@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@5@@Z +?MakeLegacy@IWebSocket@React@Microsoft@@SG?AV?$unique_ptr@UIWebSocket@React@Microsoft@@U?$default_delete@UIWebSocket@React@Microsoft@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@5@@Z ?asFunction@Object@jsi@facebook@@QHAE?AVFunction@23@AAVRuntime@23@@Z ??1Value@jsi@facebook@@QAE@XZ ??1Buffer@jsi@facebook@@UAE@XZ diff --git a/vnext/Desktop.IntegrationTests/React.Windows.Desktop.IntegrationTests.vcxproj b/vnext/Desktop.IntegrationTests/React.Windows.Desktop.IntegrationTests.vcxproj index b9f641bc3d4..d23170c15de 100644 --- a/vnext/Desktop.IntegrationTests/React.Windows.Desktop.IntegrationTests.vcxproj +++ b/vnext/Desktop.IntegrationTests/React.Windows.Desktop.IntegrationTests.vcxproj @@ -99,15 +99,11 @@ - - Cdecl - + - - Cdecl - + @@ -144,7 +140,7 @@ - + @@ -154,7 +150,7 @@ - + diff --git a/vnext/Desktop.IntegrationTests/packages.config b/vnext/Desktop.IntegrationTests/packages.config index 108f4b4577d..5fa79e4ee41 100644 --- a/vnext/Desktop.IntegrationTests/packages.config +++ b/vnext/Desktop.IntegrationTests/packages.config @@ -4,5 +4,5 @@ - - \ No newline at end of file + + diff --git a/vnext/Desktop.UnitTests/React.Windows.Desktop.UnitTests.vcxproj b/vnext/Desktop.UnitTests/React.Windows.Desktop.UnitTests.vcxproj index cccf8257d82..00c0c3366af 100644 --- a/vnext/Desktop.UnitTests/React.Windows.Desktop.UnitTests.vcxproj +++ b/vnext/Desktop.UnitTests/React.Windows.Desktop.UnitTests.vcxproj @@ -108,7 +108,7 @@ - + @@ -117,7 +117,7 @@ - + diff --git a/vnext/Desktop.UnitTests/packages.config b/vnext/Desktop.UnitTests/packages.config index 897ea128c47..0416526c667 100644 --- a/vnext/Desktop.UnitTests/packages.config +++ b/vnext/Desktop.UnitTests/packages.config @@ -3,5 +3,5 @@ - - \ No newline at end of file + + diff --git a/vnext/Desktop/LegacyWebSocket.cpp b/vnext/Desktop/LegacyWebSocket.cpp index a2cd1de3435..eab28858364 100644 --- a/vnext/Desktop/LegacyWebSocket.cpp +++ b/vnext/Desktop/LegacyWebSocket.cpp @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +#include "pch.h" + #pragma warning( push ) #pragma warning( disable : 4996 ) // std::copy::_Unchecked_iterators::_Deprecate @@ -443,7 +445,7 @@ template class LegacySecureWebSocket>; #pragma region IWebSocket static members -/*static*/ std::unique_ptr __cdecl IWebSocket::MakeLegacy(const string& urlString) +/*static*/ std::unique_ptr IWebSocket::MakeLegacy(const string& urlString) { Url url(urlString); diff --git a/vnext/Desktop/React.Windows.Desktop.vcxproj b/vnext/Desktop/React.Windows.Desktop.vcxproj index d48ac065f3a..98cbcc11cf1 100644 --- a/vnext/Desktop/React.Windows.Desktop.vcxproj +++ b/vnext/Desktop/React.Windows.Desktop.vcxproj @@ -105,11 +105,7 @@ - - - - Cdecl - + @@ -120,12 +116,9 @@ + - - - - Cdecl - + @@ -171,7 +164,7 @@ - + @@ -181,6 +174,6 @@ - + \ No newline at end of file diff --git a/vnext/Desktop/React.Windows.Desktop.vcxproj.filters b/vnext/Desktop/React.Windows.Desktop.vcxproj.filters index 4810ee8251e..790f54ddd37 100644 --- a/vnext/Desktop/React.Windows.Desktop.vcxproj.filters +++ b/vnext/Desktop/React.Windows.Desktop.vcxproj.filters @@ -38,6 +38,7 @@ Modules + Executors diff --git a/vnext/Desktop/Stubs.cpp b/vnext/Desktop/Stubs.cpp new file mode 100644 index 00000000000..781ebba8452 --- /dev/null +++ b/vnext/Desktop/Stubs.cpp @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "pch.h" + +// Required by Linker. +extern "C" void __cdecl All_office_binaries_must_use_OLIBC(void) { }; diff --git a/vnext/Desktop/WebSocket.cpp b/vnext/Desktop/WebSocket.cpp index b853c3b9ea8..0d192c1a816 100644 --- a/vnext/Desktop/WebSocket.cpp +++ b/vnext/Desktop/WebSocket.cpp @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +#include "pch.h" + #pragma warning( push ) #pragma warning( disable : 4996 ) // std::copy::_Unchecked_iterators::_Deprecate @@ -481,7 +483,7 @@ void SecureWebSocket::Handshake(const IWebSocket::Options& options) #pragma region IWebSocket static members -/*static*/ unique_ptr __cdecl IWebSocket::Make(const string& urlString) +/*static*/ unique_ptr IWebSocket::Make(const string& urlString) { Url url(urlString); diff --git a/vnext/Desktop/packages.config b/vnext/Desktop/packages.config index 108f4b4577d..5fa79e4ee41 100644 --- a/vnext/Desktop/packages.config +++ b/vnext/Desktop/packages.config @@ -4,5 +4,5 @@ - - \ No newline at end of file + + diff --git a/vnext/ReactWindowsCore/IWebSocket.h b/vnext/ReactWindowsCore/IWebSocket.h index dadb418b8e5..1aa8e4251e3 100644 --- a/vnext/ReactWindowsCore/IWebSocket.h +++ b/vnext/ReactWindowsCore/IWebSocket.h @@ -73,10 +73,10 @@ struct IWebSocket #pragma endregion // Inner types - static std::unique_ptr __cdecl Make(const std::string& url); + static std::unique_ptr Make(const std::string& url); // Only use if a legacy implementation is required as fallback. - static std::unique_ptr __cdecl MakeLegacy(const std::string& url); + static std::unique_ptr MakeLegacy(const std::string& url); virtual ~IWebSocket() {} From 971616130331de159a91e09428444a6167d6fae9 Mon Sep 17 00:00:00 2001 From: "Julio C. Rocha" Date: Wed, 19 Jun 2019 15:27:15 -0700 Subject: [PATCH 26/30] Removed Stubs.cpp. --- vnext/Desktop/React.Windows.Desktop.vcxproj | 1 - vnext/Desktop/React.Windows.Desktop.vcxproj.filters | 1 - vnext/Desktop/Stubs.cpp | 7 ------- 3 files changed, 9 deletions(-) delete mode 100644 vnext/Desktop/Stubs.cpp diff --git a/vnext/Desktop/React.Windows.Desktop.vcxproj b/vnext/Desktop/React.Windows.Desktop.vcxproj index 98c876a21a0..8b4eacce776 100644 --- a/vnext/Desktop/React.Windows.Desktop.vcxproj +++ b/vnext/Desktop/React.Windows.Desktop.vcxproj @@ -116,7 +116,6 @@ - diff --git a/vnext/Desktop/React.Windows.Desktop.vcxproj.filters b/vnext/Desktop/React.Windows.Desktop.vcxproj.filters index 790f54ddd37..4810ee8251e 100644 --- a/vnext/Desktop/React.Windows.Desktop.vcxproj.filters +++ b/vnext/Desktop/React.Windows.Desktop.vcxproj.filters @@ -38,7 +38,6 @@ Modules - Executors diff --git a/vnext/Desktop/Stubs.cpp b/vnext/Desktop/Stubs.cpp deleted file mode 100644 index 781ebba8452..00000000000 --- a/vnext/Desktop/Stubs.cpp +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#include "pch.h" - -// Required by Linker. -extern "C" void __cdecl All_office_binaries_must_use_OLIBC(void) { }; From 619832567af977a37df8928b76ca60309f40d2d1 Mon Sep 17 00:00:00 2001 From: "Julio C. Rocha" Date: Wed, 19 Jun 2019 16:08:28 -0700 Subject: [PATCH 27/30] Updated ChakraCore.Debugger. --- vnext/Desktop.DLL/React.Windows.Desktop.DLL.vcxproj | 4 ++-- .../React.Windows.Desktop.IntegrationTests.vcxproj | 4 ++-- vnext/Desktop/React.Windows.Desktop.vcxproj | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/vnext/Desktop.DLL/React.Windows.Desktop.DLL.vcxproj b/vnext/Desktop.DLL/React.Windows.Desktop.DLL.vcxproj index 5d054d5cc15..0db8e980fdc 100644 --- a/vnext/Desktop.DLL/React.Windows.Desktop.DLL.vcxproj +++ b/vnext/Desktop.DLL/React.Windows.Desktop.DLL.vcxproj @@ -150,7 +150,7 @@ - + @@ -160,6 +160,6 @@ - + \ No newline at end of file diff --git a/vnext/Desktop.IntegrationTests/React.Windows.Desktop.IntegrationTests.vcxproj b/vnext/Desktop.IntegrationTests/React.Windows.Desktop.IntegrationTests.vcxproj index b19c1b9852f..387351c4006 100644 --- a/vnext/Desktop.IntegrationTests/React.Windows.Desktop.IntegrationTests.vcxproj +++ b/vnext/Desktop.IntegrationTests/React.Windows.Desktop.IntegrationTests.vcxproj @@ -140,7 +140,7 @@ - + @@ -150,7 +150,7 @@ - + diff --git a/vnext/Desktop/React.Windows.Desktop.vcxproj b/vnext/Desktop/React.Windows.Desktop.vcxproj index 8b4eacce776..c1be21445de 100644 --- a/vnext/Desktop/React.Windows.Desktop.vcxproj +++ b/vnext/Desktop/React.Windows.Desktop.vcxproj @@ -163,7 +163,7 @@ - + @@ -173,6 +173,6 @@ - + \ No newline at end of file From c455e70db025fed39c4a1424e10158a7006b709b Mon Sep 17 00:00:00 2001 From: "Julio C. Rocha" Date: Wed, 19 Jun 2019 16:17:03 -0700 Subject: [PATCH 28/30] Remove unneeded __stdcall annotations. --- vnext/ReactWindowsCore/unicode.cpp | 36 +++++++++++------------- vnext/include/ReactWindowsCore/unicode.h | 24 ++++++++-------- 2 files changed, 29 insertions(+), 31 deletions(-) diff --git a/vnext/ReactWindowsCore/unicode.cpp b/vnext/ReactWindowsCore/unicode.cpp index 146aa715964..9a5615bb6bd 100644 --- a/vnext/ReactWindowsCore/unicode.cpp +++ b/vnext/ReactWindowsCore/unicode.cpp @@ -19,7 +19,7 @@ namespace unicode { // The implementations of the following functions heavily reference the MSDN // article at https://msdn.microsoft.com/en-us/magazine/mt763237.aspx. -std::wstring __stdcall utf8ToUtf16(const char* utf8, size_t utf8Len) +std::wstring utf8ToUtf16(const char* utf8, size_t utf8Len) { std::wstring utf16{}; @@ -39,9 +39,8 @@ std::wstring __stdcall utf8ToUtf16(const char* utf8, size_t utf8Len) const int utf8Length = static_cast(utf8Len); - // We do not specify MB_ERR_INVALID_CHARS here, which means that invalid UTF-8 - // characters are replaced with U+FFFD. - constexpr DWORD flags = 0; + // Fail if an invalid UTF-8 character is encountered in the input string. + constexpr DWORD flags = MB_ERR_INVALID_CHARS; const int utf16Length = ::MultiByteToWideChar( CP_UTF8, // Source string is in UTF-8. @@ -92,24 +91,24 @@ std::wstring __stdcall utf8ToUtf16(const char* utf8, size_t utf8Len) return utf16; } -std::wstring __stdcall utf8ToUtf16(const char* utf8) +std::wstring utf8ToUtf16(const char* utf8) { return utf8ToUtf16(utf8, strlen(utf8)); } -std::wstring __stdcall utf8ToUtf16(const std::string& utf8) +std::wstring utf8ToUtf16(const std::string& utf8) { return utf8ToUtf16(utf8.c_str(), utf8.length()); } #if _HAS_CXX17 -std::wstring __stdcall utf8ToUtf16(const std::string_view& utf8) +std::wstring utf8ToUtf16(const std::string_view& utf8) { return utf8ToUtf16(utf8.data(), utf8.length()); } #endif -std::string __stdcall utf16ToUtf8(const wchar_t* utf16, size_t utf16Len) +std::string utf16ToUtf8(const wchar_t* utf16, size_t utf16Len) { std::string utf8{}; @@ -129,9 +128,8 @@ std::string __stdcall utf16ToUtf8(const wchar_t* utf16, size_t utf16Len) const int utf16Length = static_cast(utf16Len); - // We do not specify WC_ERR_INVALID_CHARS here, which means that invalid - // UTF-16 characters are replaced with U+FFFD. - constexpr DWORD flags = 0; + // Fail if an invalid UTF-16 character is encountered in the input string. + constexpr DWORD flags = WC_ERR_INVALID_CHARS; const int utf8Length = ::WideCharToMultiByte( CP_UTF8, // Destination string is in UTF-8. @@ -186,28 +184,28 @@ std::string __stdcall utf16ToUtf8(const wchar_t* utf16, size_t utf16Len) return utf8; } -std::string __stdcall utf16ToUtf8(const char16_t* utf16, size_t utf16Len) +std::string utf16ToUtf8(const char16_t* utf16, size_t utf16Len) { return utf16ToUtf8( utilities::checkedReinterpretCast(utf16), utf16Len); } -std::string __stdcall utf16ToUtf8(const wchar_t* utf16) +std::string utf16ToUtf8(const wchar_t* utf16) { return utf16ToUtf8(utf16, wcslen(utf16)); } -std::string __stdcall utf16ToUtf8(const char16_t* utf16) +std::string utf16ToUtf8(const char16_t* utf16) { return utf16ToUtf8(utf16, std::char_traits::length(utf16)); } -std::string __stdcall utf16ToUtf8(const std::wstring& utf16) +std::string utf16ToUtf8(const std::wstring& utf16) { return utf16ToUtf8(utf16.c_str(), utf16.length()); } -std::string __stdcall utf16ToUtf8(const std::u16string& utf16) +std::string utf16ToUtf8(const std::u16string& utf16) { return utf16ToUtf8( utilities::checkedReinterpretCast(utf16.c_str()), @@ -215,12 +213,12 @@ std::string __stdcall utf16ToUtf8(const std::u16string& utf16) } #if _HAS_CXX17 -std::string __stdcall utf16ToUtf8(const std::wstring_view& utf16) +std::string utf16ToUtf8(const std::wstring_view& utf16) { return utf16ToUtf8(utf16.data(), utf16.length()); } -std::string __stdcall utf16ToUtf8(const std::u16string_view& utf16) +std::string utf16ToUtf8(const std::u16string_view& utf16) { return utf16ToUtf8( utilities::checkedReinterpretCast(utf16.data()), @@ -228,6 +226,6 @@ std::string __stdcall utf16ToUtf8(const std::u16string_view& utf16) } #endif -} // namespace unicode +} // namespace utilities } // namespace react } // namespace facebook diff --git a/vnext/include/ReactWindowsCore/unicode.h b/vnext/include/ReactWindowsCore/unicode.h index 506464e1cf4..c666b6ce519 100644 --- a/vnext/include/ReactWindowsCore/unicode.h +++ b/vnext/include/ReactWindowsCore/unicode.h @@ -54,11 +54,11 @@ class UnicodeConversionException : public std::runtime_error // // For (2), utf8 must be null terminated. The behavior is undefined otherwise. // -/* (1) */ std::wstring __stdcall utf8ToUtf16(const char* utf8, size_t utf8Len); -/* (2) */ std::wstring __stdcall utf8ToUtf16(const char* utf8); -/* (3) */ std::wstring __stdcall utf8ToUtf16(const std::string& utf8); +/* (1) */ std::wstring utf8ToUtf16(const char* utf8, size_t utf8Len); +/* (2) */ std::wstring utf8ToUtf16(const char* utf8); +/* (3) */ std::wstring utf8ToUtf16(const std::string& utf8); #if _HAS_CXX17 -/* (4) */ std::wstring __stdcall utf8ToUtf16(const std::string_view& utf8); +/* (4) */ std::wstring utf8ToUtf16(const std::string_view& utf8); #endif // The following functions convert UTF-16BE strings to UTF-8 strings. Their @@ -71,15 +71,15 @@ class UnicodeConversionException : public std::runtime_error // For (3) and (4), utf16 must be null terminated. The behavior is undefined // otherwise. // -/* (1) */ std::string __stdcall utf16ToUtf8(const wchar_t* utf16, size_t utf16Len); -/* (2) */ std::string __stdcall utf16ToUtf8(const char16_t* utf16, size_t utf16Len); -/* (3) */ std::string __stdcall utf16ToUtf8(const wchar_t* utf16); -/* (4) */ std::string __stdcall utf16ToUtf8(const char16_t* utf16); -/* (5) */ std::string __stdcall utf16ToUtf8(const std::wstring& utf16); -/* (6) */ std::string __stdcall utf16ToUtf8(const std::u16string& utf16); +/* (1) */ std::string utf16ToUtf8(const wchar_t* utf16, size_t utf16Len); +/* (2) */ std::string utf16ToUtf8(const char16_t* utf16, size_t utf16Len); +/* (3) */ std::string utf16ToUtf8(const wchar_t* utf16); +/* (4) */ std::string utf16ToUtf8(const char16_t* utf16); +/* (5) */ std::string utf16ToUtf8(const std::wstring& utf16); +/* (6) */ std::string utf16ToUtf8(const std::u16string& utf16); #if _HAS_CXX17 -/* (7) */ std::string __stdcall utf16ToUtf8(const std::wstring_view& utf16); -/* (8) */ std::string __stdcall utf16ToUtf8(const std::u16string_view& utf16); +/* (7) */ std::string utf16ToUtf8(const std::wstring_view& utf16); +/* (8) */ std::string utf16ToUtf8(const std::u16string_view& utf16); #endif } // namespace utilities From 7a12f2fc01f5097c2e0ba280f7374d54f26148e5 Mon Sep 17 00:00:00 2001 From: "Julio C. Rocha" Date: Wed, 19 Jun 2019 16:20:46 -0700 Subject: [PATCH 29/30] Removed unused Cdecls. --- .../React.Windows.Desktop.UnitTests.vcxproj | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/vnext/Desktop.UnitTests/React.Windows.Desktop.UnitTests.vcxproj b/vnext/Desktop.UnitTests/React.Windows.Desktop.UnitTests.vcxproj index b9338aba04d..a1a0ba62f50 100644 --- a/vnext/Desktop.UnitTests/React.Windows.Desktop.UnitTests.vcxproj +++ b/vnext/Desktop.UnitTests/React.Windows.Desktop.UnitTests.vcxproj @@ -71,9 +71,7 @@ - - Cdecl - + @@ -84,9 +82,7 @@ - - Cdecl - + From 9a146fa4dc0541d3d8d44e776651b30102147958 Mon Sep 17 00:00:00 2001 From: "Julio C. Rocha" Date: Thu, 20 Jun 2019 16:28:07 -0700 Subject: [PATCH 30/30] Reverted unicode.cpp changes. --- vnext/ReactWindowsCore/unicode.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/vnext/ReactWindowsCore/unicode.cpp b/vnext/ReactWindowsCore/unicode.cpp index 9a5615bb6bd..b748358e144 100644 --- a/vnext/ReactWindowsCore/unicode.cpp +++ b/vnext/ReactWindowsCore/unicode.cpp @@ -39,8 +39,9 @@ std::wstring utf8ToUtf16(const char* utf8, size_t utf8Len) const int utf8Length = static_cast(utf8Len); - // Fail if an invalid UTF-8 character is encountered in the input string. - constexpr DWORD flags = MB_ERR_INVALID_CHARS; + // We do not specify MB_ERR_INVALID_CHARS here, which means that invalid UTF-8 + // characters are replaced with U+FFFD. + constexpr DWORD flags = 0; const int utf16Length = ::MultiByteToWideChar( CP_UTF8, // Source string is in UTF-8. @@ -128,8 +129,9 @@ std::string utf16ToUtf8(const wchar_t* utf16, size_t utf16Len) const int utf16Length = static_cast(utf16Len); - // Fail if an invalid UTF-16 character is encountered in the input string. - constexpr DWORD flags = WC_ERR_INVALID_CHARS; + // We do not specify WC_ERR_INVALID_CHARS here, which means that invalid + // UTF-16 characters are replaced with U+FFFD. + constexpr DWORD flags = 0; const int utf8Length = ::WideCharToMultiByte( CP_UTF8, // Destination string is in UTF-8. @@ -226,6 +228,6 @@ std::string utf16ToUtf8(const std::u16string_view& utf16) } #endif -} // namespace utilities +} // namespace unicode } // namespace react } // namespace facebook