-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement experimental websocket client #2552
base: master
Are you sure you want to change the base?
Conversation
Websocket protocol handshake uses HTTP, thus it makes sense to reuse at least some of the abstractions and API style.
This will allow to implement Websocket client that reuses existing code.
Current implementation of websocket connection is specific to the server. Rename to more appropriate name.
Websocket connection handling is mostly not specific to the server and thus can be reused on the client easily.
Previous name was useful when it's used locally in translation unit. The new name is exposed in a header and should be more unique.
https://datatracker.ietf.org/doc/html/rfc6455#section-5.3 requires that the masking key must be unpredictable and derived from a strong source of entropy. This requirement arose due to usage of WebSocket protocol in the browsers, where both server and client payload generation code may be malicious and the only trusted piece is the browser itself. Consequently there was a need to make the bytes on the wire unpredictable for the client code, so that it cannot run attacks against intermediate proxies that do not understand WebSocket. In the case of Seastar there is no security boundary between payload generator and payload serializer in this class, accordingly in terms of security impact it is sufficient to simply use predictable masking key. Zero is chosen because it does not change the payload.
#include <seastar/core/when_all.hh> | ||
#include <seastar/websocket/common.hh> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So far only the parser is in there, so it makes sense to name it parser.hh
include/seastar/websocket/common.hh
Outdated
/*! | ||
* \param fd established socket used for communication | ||
*/ | ||
connection(connected_socket&& fd) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't it be protected as well?
@@ -243,16 +243,19 @@ protected: | |||
|
|||
sstring _subprotocol; | |||
handler_t _handler; | |||
bool _is_client; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems that std::optional<uint32_t> _masking_key
would fit better here. Constructor and send_key() would need to be updated accordingly
@@ -168,6 +172,26 @@ future<> connection::send_data(opcodes opcode, temporary_buffer<char>&& buff) { | |||
header[1] = uint8_t(buff.size()); | |||
} | |||
|
|||
temporary_buffer<char> write_buf; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unused in this patch. Maybe it's used later, but then it should as well be added "later"
@@ -87,7 +87,7 @@ struct frame_header { | |||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Patch is missing descriptive comment
@@ -313,10 +313,10 @@ struct request { | |||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What for? Should be in the patch comment
@@ -777,6 +777,7 @@ add_library (seastar | |||
src/util/read_first_line.cc |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Patch comment is missing
* | ||
* \param addr -- host address to connect to | ||
* \param creds -- credentials | ||
* \param host -- optional host name |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
optional local host name ?
@@ -777,6 +777,7 @@ add_library (seastar | |||
src/util/read_first_line.cc | |||
src/util/tmp_file.cc | |||
src/util/short_streams.cc | |||
src/websocket/client.cc |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Test is missing as well
*/ | ||
future<> send_message(temporary_buffer<char> buf, bool flush); | ||
|
||
protected: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why no private? Are there plans to implement more specific connections inherited from this class?
|
||
auto con = seastar::make_shared<client_connection>(*this, std::move(cs), ws_key, handler); | ||
|
||
auto sub = as ? as->subscribe([con] () noexcept { con->shutdown_input(); }) : std::nullopt; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This sub
dies immediately after con->perform_handshake()
returns, even if its future doesn't resolve immediately (likely it doesn't)
This PR consists of 2 parts:
It probably makes sense to land the general refactorings in smaller PRs once Websocket client is approved in principle.
One way that the websocket client differs from what is prescribed by RFC 6455 is that the client masking key is not random. The practical reason for that is to avoid needing to pull randomization infrastructure into the Websocket client. This would need additional APIs to control, as it makes sense to turn off randomization in unit tests.
Below is an excerpt from commit description on why this is reasonable solution