WebSocket++  0.8.3-dev
C++ websocket client/server library
message.hpp
1 /*
2  * Copyright (c) 2014, Peter Thorson. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  * * Redistributions of source code must retain the above copyright
7  * notice, this list of conditions and the following disclaimer.
8  * * Redistributions in binary form must reproduce the above copyright
9  * notice, this list of conditions and the following disclaimer in the
10  * documentation and/or other materials provided with the distribution.
11  * * Neither the name of the WebSocket++ Project nor the
12  * names of its contributors may be used to endorse or promote products
13  * derived from this software without specific prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
19  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *
26  */
27 
28 #ifndef WEBSOCKETPP_MESSAGE_BUFFER_MESSAGE_HPP
29 #define WEBSOCKETPP_MESSAGE_BUFFER_MESSAGE_HPP
30 
31 #include <websocketpp/common/memory.hpp>
32 #include <websocketpp/frame.hpp>
33 
34 #include <string>
35 
36 namespace websocketpp {
37 namespace message_buffer {
38 
39 /* # message:
40  * object that stores a message while it is being sent or received. Contains
41  * the message payload itself, the message header, the extension data, and the
42  * opcode.
43  *
44  * # connection_message_manager:
45  * An object that manages all of the message_buffers associated with a given
46  * connection. Implements the get_message_buffer(size) method that returns
47  * a message buffer at least size bytes long.
48  *
49  * Message buffers are reference counted with shared ownership semantics. Once
50  * requested from the manager the requester and it's associated downstream code
51  * may keep a pointer to the message indefinitely at a cost of extra resource
52  * usage. Once the reference count drops to the point where the manager is the
53  * only reference the messages is recycled using whatever method is implemented
54  * in the manager.
55  *
56  * # endpoint_message_manager:
57  * An object that manages connection_message_managers. Implements the
58  * get_message_manager() method. This is used once by each connection to
59  * request the message manager that they are supposed to use to manage message
60  * buffers for their own use.
61  *
62  * TYPES OF CONNECTION_MESSAGE_MANAGERS
63  * - allocate a message with the exact size every time one is requested
64  * - maintain a pool of pre-allocated messages and return one when needed.
65  * Recycle previously used messages back into the pool
66  *
67  * TYPES OF ENDPOINT_MESSAGE_MANAGERS
68  * - allocate a new connection manager for each connection. Message pools
69  * become connection specific. This increases memory usage but improves
70  * concurrency.
71  * - allocate a single connection manager and share a pointer to it with all
72  * connections created by this endpoint. The message pool will be shared
73  * among all connections, improving memory usage and performance at the cost
74  * of reduced concurrency
75  */
76 
77 
78 /// Represents a buffer for a single WebSocket message.
79 /**
80  *
81  *
82  */
83 template <template<class> class con_msg_manager>
84 class message {
85 public:
86  typedef lib::shared_ptr<message> ptr;
87 
88  typedef con_msg_manager<message> con_msg_man_type;
89  typedef typename con_msg_man_type::ptr con_msg_man_ptr;
90  typedef typename con_msg_man_type::weak_ptr con_msg_man_weak_ptr;
91 
92  /// Construct an empty message
93  /**
94  * Construct an empty message
95  */
96  message(const con_msg_man_ptr manager)
97  : m_manager(manager)
98  , m_prepared(false)
99  , m_fin(true)
100  , m_terminal(false)
101  , m_compressed(false) {}
102 
103  /// Construct a message and fill in some values
104  /**
105  *
106  */
107  message(const con_msg_man_ptr manager, frame::opcode::value op, size_t size = 128)
108  : m_manager(manager)
109  , m_opcode(op)
110  , m_prepared(false)
111  , m_fin(true)
112  , m_terminal(false)
113  , m_compressed(false)
114  {
115  m_payload.reserve(size);
116  }
117 
118  /// Return whether or not the message has been prepared for sending
119  /**
120  * The prepared flag indicates that the message has been prepared by a
121  * websocket protocol processor and is ready to be written to the wire.
122  *
123  * @return whether or not the message has been prepared for sending
124  */
125  bool get_prepared() const {
126  return m_prepared;
127  }
128 
129  /// Set or clear the flag that indicates that the message has been prepared
130  /**
131  * This flag should not be set by end user code without a very good reason.
132  *
133  * @param value The value to set the prepared flag to
134  */
135  void set_prepared(bool value) {
136  m_prepared = value;
137  }
138 
139  /// Return whether or not the message is flagged as compressed
140  /**
141  * @return whether or not the message is/should be compressed
142  */
143  bool get_compressed() const {
144  return m_compressed;
145  }
146 
147  /// Set or clear the compression flag
148  /**
149  * Setting the compression flag indicates that the data in this message
150  * would benefit from compression. If both endpoints negotiate a compression
151  * extension WebSocket++ will attempt to compress messages with this flag.
152  * Setting this flag does not guarantee that the message will be compressed.
153  *
154  * @param value The value to set the compressed flag to
155  */
156  void set_compressed(bool value) {
157  m_compressed = value;
158  }
159 
160  /// Get whether or not the message is terminal
161  /**
162  * Messages can be flagged as terminal, which results in the connection
163  * being close after they are written rather than the implementation going
164  * on to the next message in the queue. This is typically used internally
165  * for close messages only.
166  *
167  * @return Whether or not this message is marked terminal
168  */
169  bool get_terminal() const {
170  return m_terminal;
171  }
172 
173  /// Set the terminal flag
174  /**
175  * This flag should not be set by end user code without a very good reason.
176  *
177  * @see get_terminal()
178  *
179  * @param value The value to set the terminal flag to.
180  */
181  void set_terminal(bool value) {
182  m_terminal = value;
183  }
184  /// Read the fin bit
185  /**
186  * A message with the fin bit set will be sent as the last message of its
187  * sequence. A message with the fin bit cleared will require subsequent
188  * frames of opcode continuation until one of them has the fin bit set.
189  *
190  * The remote end likely will not deliver any bytes until the frame with the fin
191  * bit set has been received.
192  *
193  * @return Whether or not the fin bit is set
194  */
195  bool get_fin() const {
196  return m_fin;
197  }
198 
199  /// Set the fin bit
200  /**
201  * @see get_fin for a more detailed explaination of the fin bit
202  *
203  * @param value The value to set the fin bit to.
204  */
205  void set_fin(bool value) {
206  m_fin = value;
207  }
208 
209  /// Return the message opcode
211  return m_opcode;
212  }
213 
214  /// Set the opcode
215  void set_opcode(frame::opcode::value op) {
216  m_opcode = op;
217  }
218 
219  /// Return the prepared frame header
220  /**
221  * This value is typically set by a websocket protocol processor
222  * and shouldn't be tampered with.
223  */
224  std::string const & get_header() const {
225  return m_header;
226  }
227 
228  /// Set prepared frame header
229  /**
230  * Under normal circumstances this should not be called by end users
231  *
232  * @param header A string to set the header to.
233  */
234  void set_header(std::string const & header) {
235  m_header = header;
236  }
237 
238  std::string const & get_extension_data() const {
239  return m_extension_data;
240  }
241 
242  /// Get a reference to the payload string
243  /**
244  * @return A const reference to the message's payload string
245  */
246  std::string const & get_payload() const {
247  return m_payload;
248  }
249 
250  /// Get a non-const reference to the payload string
251  /**
252  * @return A reference to the message's payload string
253  */
255  return m_payload;
256  }
257 
258  /// Set payload data
259  /**
260  * Set the message buffer's payload to the given value.
261  *
262  * @param payload A string to set the payload to.
263  */
264  void set_payload(std::string const & payload) {
265  m_payload = payload;
266  }
267 
268  /// Set payload data
269  /**
270  * Set the message buffer's payload to the given value.
271  *
272  * @param payload A pointer to a data array to set to.
273  * @param len The length of new payload in bytes.
274  */
275  void set_payload(void const * payload, size_t len) {
276  m_payload.reserve(len);
277  char const * pl = static_cast<char const *>(payload);
278  m_payload.assign(pl, pl + len);
279  }
280 
281  /// Append payload data
282  /**
283  * Append data to the message buffer's payload.
284  *
285  * @param payload A string containing the data array to append.
286  */
287  void append_payload(std::string const & payload) {
288  m_payload.append(payload);
289  }
290 
291  /// Append payload data
292  /**
293  * Append data to the message buffer's payload.
294  *
295  * @param payload A pointer to a data array to append
296  * @param len The length of payload in bytes
297  */
298  void append_payload(void const * payload, size_t len) {
299  m_payload.reserve(m_payload.size()+len);
300  m_payload.append(static_cast<char const *>(payload),len);
301  }
302 
303  /// Recycle the message
304  /**
305  * A request to recycle this message was received. Forward that request to
306  * the connection message manager for processing. Errors and exceptions
307  * from the manager's recycle member function should be passed back up the
308  * call chain. The caller to message::recycle will deal with them.
309  *
310  * Recycle must *only* be called by the message shared_ptr's destructor.
311  * Once recycled successfully, ownership of the memory has been passed to
312  * another system and must not be accessed again.
313  *
314  * @return true if the message was successfully recycled, false otherwise.
315  */
316  bool recycle() {
317  con_msg_man_ptr shared = m_manager.lock();
318 
319  if (shared) {
320  return shared->recycle(this);
321  } else {
322  return false;
323  }
324  }
325 private:
326  con_msg_man_weak_ptr m_manager;
327  std::string m_header;
328  std::string m_extension_data;
329  std::string m_payload;
330  frame::opcode::value m_opcode;
331  bool m_prepared;
332  bool m_fin;
333  bool m_terminal;
334  bool m_compressed;
335 };
336 
337 } // namespace message_buffer
338 } // namespace websocketpp
339 
340 #endif // WEBSOCKETPP_MESSAGE_BUFFER_MESSAGE_HPP
websocketpp::message_buffer::message::get_payload
std::string const & get_payload() const
Get a reference to the payload string.
Definition: message.hpp:246
websocketpp::message_buffer::message::set_terminal
void set_terminal(bool value)
Set the terminal flag.
Definition: message.hpp:181
websocketpp::message_buffer::message::set_fin
void set_fin(bool value)
Set the fin bit.
Definition: message.hpp:205
websocketpp::message_buffer::message::message
message(const con_msg_man_ptr manager)
Construct an empty message.
Definition: message.hpp:96
websocketpp::message_buffer::message::get_raw_payload
std::string & get_raw_payload()
Get a non-const reference to the payload string.
Definition: message.hpp:254
websocketpp::message_buffer::message::get_prepared
bool get_prepared() const
Return whether or not the message has been prepared for sending.
Definition: message.hpp:125
websocketpp::versions_supported
static std::vector< int > const versions_supported(helper, helper+4)
Container that stores the list of protocol versions supported.
websocketpp::message_buffer::message::set_opcode
void set_opcode(frame::opcode::value op)
Set the opcode.
Definition: message.hpp:215
websocketpp::message_buffer::message::append_payload
void append_payload(std::string const &payload)
Append payload data.
Definition: message.hpp:287
websocketpp::message_buffer::message::message
message(const con_msg_man_ptr manager, frame::opcode::value op, size_t size=128)
Construct a message and fill in some values.
Definition: message.hpp:107
websocketpp::message_buffer::message::set_compressed
void set_compressed(bool value)
Set or clear the compression flag.
Definition: message.hpp:156
websocketpp::message_buffer::message::set_header
void set_header(std::string const &header)
Set prepared frame header.
Definition: message.hpp:234
websocketpp::message_buffer::message::get_compressed
bool get_compressed() const
Return whether or not the message is flagged as compressed.
Definition: message.hpp:143
websocketpp::message_buffer::message::get_terminal
bool get_terminal() const
Get whether or not the message is terminal.
Definition: message.hpp:169
websocketpp::message_buffer::message::append_payload
void append_payload(void const *payload, size_t len)
Append payload data.
Definition: message.hpp:298
websocketpp::message_buffer::message::get_header
std::string const & get_header() const
Return the prepared frame header.
Definition: message.hpp:224
websocketpp::message_buffer::message::set_prepared
void set_prepared(bool value)
Set or clear the flag that indicates that the message has been prepared.
Definition: message.hpp:135
websocketpp::message_buffer::message::get_fin
bool get_fin() const
Read the fin bit.
Definition: message.hpp:195
websocketpp::message_buffer::message::get_opcode
frame::opcode::value get_opcode() const
Return the message opcode.
Definition: message.hpp:210
websocketpp::message_buffer::message::set_payload
void set_payload(void const *payload, size_t len)
Set payload data.
Definition: message.hpp:275
websocketpp::message_buffer::message::set_payload
void set_payload(std::string const &payload)
Set payload data.
Definition: message.hpp:264
websocketpp::message_buffer::message::recycle
bool recycle()
Recycle the message.
Definition: message.hpp:316