Unverified Commit 6bbcebf8 authored by Raphael's avatar Raphael Committed by GitHub

Merge pull request #1403

Fix flow setup for WebSocket servers
parents 73c3ad38 a928b44b
...@@ -3,6 +3,16 @@ ...@@ -3,6 +3,16 @@
All notable changes to this project will be documented in this file. The format All notable changes to this project will be documented in this file. The format
is based on [Keep a Changelog](https://keepachangelog.com). is based on [Keep a Changelog](https://keepachangelog.com).
## [Unreleased]
### Fixed
- Fix flow setup for servers that use `web_socket::with`. This bug caused
servers to immediately abort incoming connection (#1402).
- Make sure that a protocol stack ships pending data before closing a socket.
This bug prevented clients from receiving error messages from servers if the
server shuts down immediately after writing the message.
## [0.19.0] - 2023-04-17 ## [0.19.0] - 2023-04-17
### Added ### Added
......
...@@ -93,6 +93,13 @@ int caf_main(caf::actor_system& sys, const config& cfg) { ...@@ -93,6 +93,13 @@ int caf_main(caf::actor_system& sys, const config& cfg) {
// ... that simply pushes data back to the sender. // ... that simply pushes data back to the sender.
auto [pull, push] = ev.data(); auto [pull, push] = ev.data();
pull.observe_on(self) pull.observe_on(self)
.do_on_error([](const caf::error& what) { //
std::cout << "*** connection closed: " << to_string(what)
<< "\n";
})
.do_on_complete([] { //
std::cout << "*** connection closed\n";
})
.do_on_next([](const ws::frame& x) { .do_on_next([](const ws::frame& x) {
if (x.is_binary()) { if (x.is_binary()) {
std::cout std::cout
...@@ -115,7 +122,7 @@ int caf_main(caf::actor_system& sys, const config& cfg) { ...@@ -115,7 +122,7 @@ int caf_main(caf::actor_system& sys, const config& cfg) {
return EXIT_FAILURE; return EXIT_FAILURE;
} }
// Note: the actor system will keep the application running for as long as the // Note: the actor system will keep the application running for as long as the
// workers are still alive. // worker from .start() is still alive.
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
// --(rst-main-end)-- // --(rst-main-end)--
......
...@@ -78,6 +78,7 @@ public: ...@@ -78,6 +78,7 @@ public:
(*on_request_)(acc); (*on_request_)(acc);
if (acc.accepted()) { if (acc.accepted()) {
app_event = std::move(acc.app_event); app_event = std::move(acc.app_event);
ws_resources = std::move(acc.ws_resources);
return {}; return {};
} }
return std::move(acc) // return std::move(acc) //
......
...@@ -214,16 +214,16 @@ void transport::handle_buffered_data() { ...@@ -214,16 +214,16 @@ void transport::handle_buffered_data() {
auto delta = bytes.subspan(delta_offset_); auto delta = bytes.subspan(delta_offset_);
auto consumed = up_->consume(bytes, delta); auto consumed = up_->consume(bytes, delta);
if (consumed < 0) { if (consumed < 0) {
// Negative values indicate that the application encountered an // Negative values indicate that the application wants to close the
// unrecoverable error. // socket. We still make sure to send any pending data before closing.
up_->abort(make_error(caf::sec::runtime_error, "consumed < 0")); up_->abort(make_error(caf::sec::runtime_error, "consumed < 0"));
parent_->deregister(); parent_->deregister_reading();
return; return;
} else if (static_cast<size_t>(consumed) > n) { } else if (static_cast<size_t>(consumed) > n) {
// Must not happen. An application cannot handle more data then we pass // Must not happen. An application cannot handle more data then we pass
// to it. // to it.
up_->abort(make_error(sec::logic_error, "consumed > buffer.size")); up_->abort(make_error(sec::logic_error, "consumed > buffer.size"));
parent_->deregister(); parent_->deregister_reading();
return; return;
} else if (consumed == 0) { } else if (consumed == 0) {
if (next_) { if (next_) {
......
...@@ -17,3 +17,12 @@ add_test( ...@@ -17,3 +17,12 @@ add_test(
--variable BINARY_PATH:$<TARGET_FILE:quote-server> --variable BINARY_PATH:$<TARGET_FILE:quote-server>
--variable SSL_PATH:${CMAKE_CURRENT_SOURCE_DIR} --variable SSL_PATH:${CMAKE_CURRENT_SOURCE_DIR}
"${CMAKE_CURRENT_SOURCE_DIR}/web_socket/quote-server.robot") "${CMAKE_CURRENT_SOURCE_DIR}/web_socket/quote-server.robot")
add_test(
NAME "robot-web-socket-echo"
COMMAND
${Python_EXECUTABLE}
-m robot
--variable BINARY_PATH:$<TARGET_FILE:echo>
--variable SSL_PATH:${CMAKE_CURRENT_SOURCE_DIR}
"${CMAKE_CURRENT_SOURCE_DIR}/web_socket/echo.robot")
*** Settings ***
Documentation A test suite for examples/web_socket/echo-server
Library Collections
Library Process
Library RequestsLibrary
Library WebSocketClient
Suite Setup Start Servers
Suite Teardown Stop Servers
*** Variables ***
${HTTP_URL} http://localhost:55501
${HTTPS_URL} https://localhost:55502
${WS_URL} ws://localhost:55501
${WSS_URL} wss://localhost:55502
${FRAME_COUNT} ${10}
${BINARY_PATH} /path/to/the/server
${SSL_PATH} /path/to/the/pem/files
*** Test Cases ***
Test WebSocket Server
[Tags] WebSocket
${fd}= WebSocketClient.Connect ${WS_URL}
WebSocketClient.Send ${fd} Hello
${result}= WebSocketClient.Recv ${fd}
WebSocketClient.Close ${fd}
Should Be Equal ${result} Hello
Test WebSocket Over SSL Server
[Tags] WebSocket
${ssl_arg}= Evaluate {"cert_reqs": ssl.CERT_NONE}
${fd}= WebSocketClient.Connect ${WSS_URL} sslopt=${ssl_arg}
WebSocketClient.Send ${fd} Hello
${result}= WebSocketClient.Recv ${fd}
WebSocketClient.Close ${fd}
Should Be Equal ${result} Hello
*** Keywords ***
Start Servers
${res1}= Start Process ${BINARY_PATH} -p 55501
Set Suite Variable ${ws_server_process} ${res1}
${res2}= Start Process ${BINARY_PATH} -p 55502 -k ${SSL_PATH}/key.pem -c ${SSL_PATH}/cert.pem
Set Suite Variable ${wss_server_process} ${res2}
Wait Until Keyword Succeeds 5s 125ms Check If HTTP Server Is Reachable
Wait Until Keyword Succeeds 5s 125ms Check If HTTPS Server Is Reachable
Stop Servers
Terminate Process ${ws_server_process}
Terminate Process ${wss_server_process}
Check If HTTP Server Is Reachable
# The server sends a "400 Bad Request" if we try HTTP on the WebSocket port.
# This is because the server is configured to only accept WebSocket
# connections. However, we can still use this behavior to check if the
# server is up and running.
Log Try reaching ${HTTP_URL}.
${resp}= GET ${HTTP_URL} expected_status=400
Check If HTTPS Server Is Reachable
Log Try reaching ${HTTPS_URL}.
${resp}= GET ${HTTPS_URL} expected_status=400 verify=${False}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment