userver: userver/server/websocket/server.hpp Source File
⚠️ This is the documentation for an old userver version. Click here to switch to the latest version.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
server.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/server/websocket/server.hpp
4/// @brief @copybrief websocket::WebSocketConnection
5
6#include <memory>
7#include <optional>
8
9#include <userver/engine/io/socket.hpp>
10#include <userver/server/http/http_request.hpp>
11#include <userver/tracing/span.hpp>
12#include <userver/utils/impl/span.hpp>
13#include <userver/yaml_config/fwd.hpp>
14
15USERVER_NAMESPACE_BEGIN
16
17namespace server::websocket {
18
19using CloseStatusInt = int16_t;
20
21/// @brief Close statuses
23 kNone = 0,
24
25 kNormal = 1000,
26 kGoingAway = 1001,
27 kProtocolError = 1002,
28 kUnsupportedData = 1003,
29 kFrameTooLarge = 1004,
30 kNoStatusRcvd = 1005,
31 kAbnormalClosure = 1006,
32 kBadMessageData = 1007,
33 kPolicyViolation = 1008,
34 kTooBigData = 1009,
35 kExtensionMismatch = 1010,
36 kServerError = 1011
37};
38
39/// @brief WebSocket message
40struct Message {
41 std::string data; ///< payload
42 std::optional<CloseStatus> close_status = {}; ///< close status
43 bool is_text = false; ///< is it text or binary?
44};
45
46class WebSocketConnectionImpl;
47
48struct Config final {
49 unsigned max_remote_payload = 65536;
50 unsigned fragment_size = 65536; // 0 - do not fragment
51};
52
53Config Parse(const yaml_config::YamlConfig&, formats::parse::To<Config>);
54
55struct Statistics final {
56 std::atomic<int64_t> msg_sent{0};
57 std::atomic<int64_t> msg_recv{0};
58 std::atomic<int64_t> bytes_sent{0};
59 std::atomic<int64_t> bytes_recv{0};
60};
61
62/// @brief Main class for Websocket connection
64 public:
65 WebSocketConnection();
66
67 WebSocketConnection(WebSocketConnection&&) = delete;
68 WebSocketConnection(const WebSocketConnection&) = delete;
69
70 WebSocketConnection& operator=(WebSocketConnection&&) = delete;
71 WebSocketConnection& operator=(const WebSocketConnection&) = delete;
72
73 virtual ~WebSocketConnection();
74
75 /// @brief Read a message from websocket, handling pings under the hood.
76 /// @param message input message
77 /// @throws engine::io::IoException in case of socket errors
78 /// @note Recv() is not thread-safe by itself (you may not call Recv() from
79 /// multiple coroutines at once), but it is safe to call Recv() and Send()
80 /// from different coroutines at once thus implementing full-duplex socket
81 /// connection.
82 virtual void Recv(Message& message) = 0;
83
84 /// @brief Send a message to websocket.
85 /// @param message message to send
86 /// @throws engine::io::IoException in case of socket errors
87 /// @note Send() is not thread-safe by itself (you may not call Send() from
88 /// multiple coroutines at once), but it is safe to call Recv() and Send()
89 /// from different coroutines at once thus implementing full-duplex socket
90 /// connection.
91 virtual void Send(const Message& message) = 0;
92 virtual void SendText(std::string_view message) = 0;
93
94 template <typename ContiguousContainer>
95 void SendBinary(const ContiguousContainer& message) {
96 static_assert(sizeof(typename ContiguousContainer::value_type) == 1,
97 "SendBinary() should send either std::bytes or chars");
98 DoSendBinary(utils::impl::Span(
99 reinterpret_cast<const std::byte*>(message.data()),
100 reinterpret_cast<const std::byte*>(message.data() + message.size())));
101 }
102
103 virtual void Close(CloseStatus status_code) = 0;
104
105 virtual const engine::io::Sockaddr& RemoteAddr() const = 0;
106
107 virtual void AddFinalTags(tracing::Span& span) const = 0;
108 virtual void AddStatistics(Statistics& stats) const = 0;
109
110 protected:
111 virtual void DoSendBinary(utils::impl::Span<const std::byte> message) = 0;
112};
113
114std::shared_ptr<WebSocketConnection> MakeWebSocket(
115 std::unique_ptr<engine::io::RwBase>&& socket,
116 engine::io::Sockaddr&& peer_name, const Config& config);
117
118} // namespace server::websocket
119
120USERVER_NAMESPACE_END