-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathMessage.hpp
146 lines (128 loc) · 3.72 KB
/
Message.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#pragma once
#include <ostream>
#include <string>
#include <string_view>
#include <cstddef>
#include <span>
#include "ws_client/Frame.hpp"
namespace ws_client
{
using std::string;
using std::string_view;
using std::byte;
using std::span;
enum class MessageType : uint8_t
{
text = static_cast<uint8_t>(opcode::text),
binary = static_cast<uint8_t>(opcode::binary)
};
static constexpr string_view to_string(MessageType v)
{
switch (v)
{
case MessageType::text:
return "text";
case MessageType::binary:
return "binary";
default:
return "unknown";
}
}
struct MessageReadState
{
bool is_compressed = false;
bool is_first = true;
opcode op_code = opcode::not_set;
void reset() noexcept
{
is_compressed = false;
is_first = true;
op_code = opcode::not_set;
}
};
/**
* Data container for Web Socket messages.
* Buffer `data` may be modified in-place, but MUST NOT be deleted.
* The buffer is owned by the caller of the constructor.
* The buffer MUST remain valid for the lifetime of this `Message` instance.
*/
struct Message
{
MessageType type;
span<byte> data;
/**
* Creates a Message from a buffer, without copying the data.
* The passed buffer MUST remain valid for the lifetime of this `Message` instance.
*/
explicit Message(MessageType type, span<byte> data) noexcept //
: type(type), data(data)
{
}
/**
* Creates a Message from a buffer, without copying the data.
* The passed buffer MUST remain valid for the lifetime of this `Message` instance.
*/
explicit Message(MessageType type, span<const byte> data) noexcept //
: type(type), data(const_cast<byte*>(data.data()), data.size())
{
}
/**
* Creates a Message from a `string_view`, without copying the data.
* The string underlying the passed `string_view` MUST remain valid
* for the lifetime of this `Message` instance.
*/
explicit Message(MessageType type, string_view data) noexcept
: type(type),
data(span<byte>(reinterpret_cast<byte*>(const_cast<char*>(data.data())), data.size()))
{
}
/**
* Returns a `string_view` of the message payload.
* The returned `string_view` is valid as long as the underlying
* `Message` buffer is valid.
*/
[[nodiscard]] inline string_view to_string_view() const noexcept
{
return string_view(reinterpret_cast<const char*>(data.data()), data.size());
}
/**
* Returns a `string` copy of the message payload.
*/
[[nodiscard]] inline string to_string() const noexcept
{
return string(reinterpret_cast<const char*>(data.data()), data.size());
}
};
// iostream operator for Message
inline std::ostream& operator<<(std::ostream& os, const Message& msg)
{
os << "Message(type=" << to_string(msg.type) << ", data=" << msg.to_string_view() << ")";
return os;
}
struct SendOptions
{
/**
* Whether to compress the message payload.
* Only applicable if permessage-deflate compression
* was negotiated during the WebSocket handshake,
* otherwise this option is ignored.
*
* Default: `true`
*/
bool compress{true};
/**
* Timeout for sending the message, in milliseconds.
* If the message cannot be sent within this time,
* the send operation will fail with a timeout error.
*
* Default: 30 seconds.
*/
std::chrono::milliseconds timeout{std::chrono::seconds(30)};
};
// iostream operator for SendOptions
inline std::ostream& operator<<(std::ostream& os, const SendOptions& opts)
{
os << "SendOptions(compress=" << opts.compress << ")";
return os;
}
} // namespace ws_client