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