ws_encoder.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: MPL-2.0 */
2 
3 #include "precompiled.hpp"
4 #include "ws_protocol.hpp"
5 #include "ws_encoder.hpp"
6 #include "msg.hpp"
7 #include "likely.hpp"
8 #include "wire.hpp"
9 #include "random.hpp"
10 
11 #include <limits.h>
12 
13 zmq::ws_encoder_t::ws_encoder_t (size_t bufsize_, bool must_mask_) :
14  encoder_base_t<ws_encoder_t> (bufsize_), _must_mask (must_mask_)
15 {
16  // Write 0 bytes to the batch and go to message_ready state.
17  next_step (NULL, 0, &ws_encoder_t::message_ready, true);
18  _masked_msg.init ();
19 }
20 
21 zmq::ws_encoder_t::~ws_encoder_t ()
22 {
23  _masked_msg.close ();
24 }
25 
26 void zmq::ws_encoder_t::message_ready ()
27 {
28  int offset = 0;
29 
30  _is_binary = false;
31 
32  if (in_progress ()->is_ping ())
33  _tmp_buf[offset++] = 0x80 | zmq::ws_protocol_t::opcode_ping;
34  else if (in_progress ()->is_pong ())
35  _tmp_buf[offset++] = 0x80 | zmq::ws_protocol_t::opcode_pong;
36  else if (in_progress ()->is_close_cmd ())
37  _tmp_buf[offset++] = 0x80 | zmq::ws_protocol_t::opcode_close;
38  else {
39  _tmp_buf[offset++] = 0x82; // Final | binary
40  _is_binary = true;
41  }
42 
43  _tmp_buf[offset] = _must_mask ? 0x80 : 0x00;
44 
45  size_t size = in_progress ()->size ();
46  if (_is_binary)
47  size++;
48  // TODO: create an opcode for subscribe/cancel
49  if (in_progress ()->is_subscribe () || in_progress ()->is_cancel ())
50  size++;
51 
52  if (size <= 125)
53  _tmp_buf[offset++] |= static_cast<unsigned char> (size & 127);
54  else if (size <= 0xFFFF) {
55  _tmp_buf[offset++] |= 126;
56  _tmp_buf[offset++] = static_cast<unsigned char> ((size >> 8) & 0xFF);
57  _tmp_buf[offset++] = static_cast<unsigned char> (size & 0xFF);
58  } else {
59  _tmp_buf[offset++] |= 127;
60  put_uint64 (_tmp_buf + offset, size);
61  offset += 8;
62  }
63 
64  if (_must_mask) {
65  const uint32_t random = generate_random ();
66  put_uint32 (_tmp_buf + offset, random);
67  put_uint32 (_mask, random);
68  offset += 4;
69  }
70 
71  int mask_index = 0;
72  if (_is_binary) {
73  // Encode flags.
74  unsigned char protocol_flags = 0;
75  if (in_progress ()->flags () & msg_t::more)
76  protocol_flags |= ws_protocol_t::more_flag;
77  if (in_progress ()->flags () & msg_t::command)
78  protocol_flags |= ws_protocol_t::command_flag;
79 
80  _tmp_buf[offset++] =
81  _must_mask ? protocol_flags ^ _mask[mask_index++] : protocol_flags;
82  }
83 
84  // Encode the subscribe/cancel byte.
85  // TODO: remove once there is an opcode for subscribe/cancel
86  if (in_progress ()->is_subscribe ())
87  _tmp_buf[offset++] = _must_mask ? 1 ^ _mask[mask_index++] : 1;
88  else if (in_progress ()->is_cancel ())
89  _tmp_buf[offset++] = _must_mask ? 0 ^ _mask[mask_index++] : 0;
90 
91  next_step (_tmp_buf, offset, &ws_encoder_t::size_ready, false);
92 }
93 
94 void zmq::ws_encoder_t::size_ready ()
95 {
96  if (_must_mask) {
97  assert (in_progress () != &_masked_msg);
98  const size_t size = in_progress ()->size ();
99 
100  unsigned char *src =
101  static_cast<unsigned char *> (in_progress ()->data ());
102  unsigned char *dest = src;
103 
104  // If msg is shared or data is constant we cannot mask in-place, allocate a new msg for it
105  if (in_progress ()->flags () & msg_t::shared
106  || in_progress ()->is_cmsg ()) {
107  _masked_msg.close ();
108  _masked_msg.init_size (size);
109  dest = static_cast<unsigned char *> (_masked_msg.data ());
110  }
111 
112  int mask_index = 0;
113  if (_is_binary)
114  ++mask_index;
115  // TODO: remove once there is an opcode for subscribe/cancel
116  if (in_progress ()->is_subscribe () || in_progress ()->is_cancel ())
117  ++mask_index;
118  for (size_t i = 0; i < size; ++i, mask_index++)
119  dest[i] = src[i] ^ _mask[mask_index % 4];
120 
121  next_step (dest, size, &ws_encoder_t::message_ready, true);
122  } else {
123  next_step (in_progress ()->data (), in_progress ()->size (),
124  &ws_encoder_t::message_ready, true);
125  }
126 }
zmq::msg_t::command
@ command
Definition: msg.hpp:56
NULL
NULL
Definition: test_security_zap.cpp:405
src
GLenum src
Definition: glcorearb.h:3364
zmq::put_uint32
void put_uint32(unsigned char *buffer_, uint32_t value_)
Definition: wire.hpp:35
precompiled.hpp
random.hpp
zmq::ws_protocol_t::opcode_close
@ opcode_close
Definition: ws_protocol.hpp:18
flags
GLbitfield flags
Definition: glcorearb.h:3585
wire.hpp
offset
GLintptr offset
Definition: glcorearb.h:2944
zmq::msg_t::shared
@ shared
Definition: msg.hpp:66
size
#define size
Definition: glcorearb.h:2944
ws_encoder.hpp
zmq::msg_t::init
int init()
Definition: msg.cpp:50
i
int i
Definition: gmock-matchers_test.cc:764
msg.hpp
zmq::put_uint64
void put_uint64(unsigned char *buffer_, uint64_t value_)
Definition: wire.hpp:51
zmq::msg_t::more
@ more
Definition: msg.hpp:55
zmq::ws_protocol_t::opcode_pong
@ opcode_pong
Definition: ws_protocol.hpp:20
zmq::ws_protocol_t::more_flag
@ more_flag
Definition: ws_protocol.hpp:25
benchmarks.python.py_benchmark.dest
dest
Definition: py_benchmark.py:13
size
GLsizeiptr size
Definition: glcorearb.h:2943
zmq::ws_protocol_t::opcode_ping
@ opcode_ping
Definition: ws_protocol.hpp:19
zmq::generate_random
uint32_t generate_random()
Definition: random.cpp:30
likely.hpp
data
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: glcorearb.h:2879
zmq::ZMQ_FINAL::_masked_msg
msg_t _masked_msg
Definition: ws_encoder.hpp:25
ws_protocol.hpp
zmq::ws_protocol_t::command_flag
@ command_flag
Definition: ws_protocol.hpp:26


libaditof
Author(s):
autogenerated on Wed May 21 2025 02:07:02