userver: userver/websocket/connection.hpp Source File
Loading...
Searching...
No Matches
connection.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/websocket/connection.hpp
4/// @brief @copybrief websocket::WebSocketConnection
5
6#include <memory>
7
8#include <userver/engine/io/socket.hpp>
9#include <userver/server/http/http_request.hpp>
10#include <userver/tracing/span.hpp>
11#include <userver/utils/span.hpp>
12#include <userver/utils/statistics/rate_counter.hpp>
13#include <userver/websocket/message.hpp>
14#include <userver/yaml_config/fwd.hpp>
15
16USERVER_NAMESPACE_BEGIN
17
18namespace websocket {
19
20class WebSocketConnectionImpl;
21
22struct Config final {
23 unsigned max_remote_payload = 65536;
24 unsigned fragment_size = 65536; // 0 - do not fragment
25};
26
27Config Parse(const yaml_config::YamlConfig&, formats::parse::To<Config>);
28
29struct Statistics final {
30 utils::statistics::RateCounter msg_sent{};
31 utils::statistics::RateCounter msg_recv{};
32 utils::statistics::RateCounter bytes_sent{};
33 utils::statistics::RateCounter bytes_recv{};
34};
35
36/// @brief Main class for Websocket connection
38public:
39 WebSocketConnection();
40
41 WebSocketConnection(WebSocketConnection&&) = delete;
42 WebSocketConnection(const WebSocketConnection&) = delete;
43
44 WebSocketConnection& operator=(WebSocketConnection&&) = delete;
45 WebSocketConnection& operator=(const WebSocketConnection&) = delete;
46
47 /// Closes the connection by closing the underlying OS socket.
49
50 /// @brief Read a message from websocket, handling pings under the hood.
51 /// @param message input message
52 /// @throws engine::io::IoException in case of socket errors
53 /// @note Recv() is **not** thread-safe by itself (you may not call Recv() from
54 /// multiple coroutines at once). It is **not** safe to call Recv() and Send() from different coroutines
55 /// at once if TLS is used. Consider using Send()+TryRecv() from the same coroutine instead.
56 virtual void Recv(Message& message) = 0;
57
58 /// @brief Behaves in the same way as Recv(), but in case of first bytes of
59 /// message are not yet ready to receive gives the control up to a client.
60 /// @returns false in case of messages absence, otherwise true and behaves
61 /// like Recv()
62 virtual bool TryRecv(Message& message) = 0;
63
64 /// @brief Send a message to websocket.
65 /// @param message message to send
66 /// @throws engine::io::IoException in case of socket errors
67 /// @note Send() is not thread-safe by itself (you may not call Send() from
68 /// multiple coroutines at once). It is **not** safe to call Recv() and Send() from different coroutines
69 /// at once if TLS is used. Consider using Send()+TryRecv() from the same coroutine instead.
70 virtual void Send(const Message& message) = 0;
71
72 /// @copydoc Send
73 virtual void SendText(std::string_view message) = 0;
74
75 /// @brief Send a ping message to websocket.
76 /// @throws engine::io::IoException in case of socket errors
77 virtual void SendPing() = 0;
78
79 /// @brief Get the number of not answered sequential pings;
80 /// calls to SendPing() increment this value, Recv and TryRecv
81 /// reset this value if some 'pong' is received.
82 /// @returns the number of not answered sequential pings
83 virtual std::size_t NotAnsweredSequentialPingsCount() = 0;
84
85 /// @brief Sends binary data from container @b message.
86 template <typename ContiguousContainer>
87 void SendBinary(const ContiguousContainer& message) {
88 static_assert(
89 sizeof(typename ContiguousContainer::value_type) == 1,
90 "SendBinary() should send either std::bytes or chars"
91 );
92 DoSendBinary(utils::span(
93 reinterpret_cast<const std::byte*>(message.data()),
94 reinterpret_cast<const std::byte*>(message.data() + message.size())
95 ));
96 }
97
98 /// @brief Closes the connection with specified @b status_code.
99 virtual void Close(CloseStatus status_code) = 0;
100
101 virtual const engine::io::Sockaddr& RemoteAddr() const = 0;
102
103 virtual void AddFinalTags(tracing::Span& span) const = 0;
104 virtual void AddStatistics(Statistics& stats) const = 0;
105
106 virtual engine::io::ReadAwaiter& ReadAwaiter() = 0;
107 virtual engine::io::WriteAwaiter& WriteAwaiter() = 0;
108
109protected:
110 virtual void DoSendBinary(utils::span<const std::byte> message) = 0;
111};
112
113std::shared_ptr<WebSocketConnection> MakeServerWebSocketConnection(
114 std::unique_ptr<engine::io::RwBase>&& socket,
115 engine::io::Sockaddr&& peer_name,
116 const Config& config
117);
118
119std::shared_ptr<WebSocketConnection> MakeClientWebSocketConnection(
120 std::unique_ptr<engine::io::RwBase>&& socket,
121 engine::io::Sockaddr&& peer_name,
122 const Config& config
123);
124
125} // namespace websocket
126
127USERVER_NAMESPACE_END