websocket_message.cpp
Go to the documentation of this file.
2 
3 namespace async_web_server_cpp
4 {
5 
7 {
8  switch (message.type)
9  {
11  header.opcode = WebsocketFrame::Header::opcode_text;
12  break;
14  header.opcode = WebsocketFrame::Header::opcode_binary;
15  break;
17  header.opcode = WebsocketFrame::Header::opcode_close;
18  break;
20  header.opcode = WebsocketFrame::Header::opcode_ping;
21  break;
23  header.opcode = WebsocketFrame::Header::opcode_pong;
24  break;
25  default:
26  return false;
27  }
28  header.fin = true;
29  header.rsv1 = false;
30  header.rsv2 = false;
31  header.rsv3 = false;
32  content = message.content;
33  length = message.content.size();
34  return true;
35 }
36 
37 bool WebsocketFrame::serialize(std::vector<unsigned char>& buffer)
38 {
39  int header_size = 2; // first two bytes of header
40  if (length < 126)
41  {
42  header.len = length;
43  }
44  else if (length <= std::numeric_limits<uint16_t>::max())
45  {
46  header.len = 126;
47  header_size += 2;
48  }
49  else if (length <= std::numeric_limits<uint64_t>::max())
50  {
51  header.len = 127;
52  header_size += 8;
53  }
54  else
55  return false; // Message too big
56  header.mask = false; // sending from server
57 
58  buffer.resize(header_size + content.size());
59  buffer[0] = header_bytes[0];
60  buffer[1] = header_bytes[1];
61 
62  if (length < 126)
63  {
64  // already copied in header bytes
65  }
66  else if (length <= std::numeric_limits<uint16_t>::max())
67  {
68  buffer[2] = (length >> 8) & 0xFF;
69  buffer[3] = (length >> 0) & 0xFF;
70  }
71  else if (length <= std::numeric_limits<uint64_t>::max())
72  {
73  buffer[2] = (length >> 56) & 0xFF;
74  buffer[3] = (length >> 48) & 0xFF;
75  buffer[4] = (length >> 40) & 0xFF;
76  buffer[5] = (length >> 32) & 0xFF;
77  buffer[6] = (length >> 24) & 0xFF;
78  buffer[7] = (length >> 16) & 0xFF;
79  buffer[8] = (length >> 8) & 0xFF;
80  buffer[9] = (length >> 0) & 0xFF;
81  }
82  content.copy((char*)&buffer[header_size], content.size());
83  return true;
84 }
85 
87 {
88  reset();
89 }
90 
92 {
93  state_ = header_byte1;
94 }
95 
96 boost::tribool WebsocketFrameParser::consume(WebsocketFrame& frame, char input)
97 {
98  switch (state_)
99  {
100  case header_byte1:
101  frame.header_bytes[0] = input;
102  state_ = header_byte2;
103  return boost::indeterminate;
104  case header_byte2:
105  frame.header_bytes[1] = input;
106  if (frame.header.len < 126)
107  {
108  frame.length = frame.header.len;
109  frame.content.reserve(frame.length);
110  frame.content.resize(0);
111  if (frame.header.mask)
112  state_ = mask_byte1;
113  else if (frame.length > 0)
114  state_ = body;
115  else
116  return true;
117  }
118  else if (frame.header.len == 126)
119  {
120  frame.length = 0;
121  state_ = length_2bytes_left;
122  }
123  else
124  {
125  frame.length = 0;
126  state_ = length_8bytes_left;
127  }
128  return boost::indeterminate;
129 
130  case length_8bytes_left:
131  frame.length |= ((uint64_t)(input & 0xFF) << 56);
132  state_ = length_7bytes_left;
133  return boost::indeterminate;
134  case length_7bytes_left:
135  frame.length |= ((uint64_t)(input & 0xFF) << 48);
136  state_ = length_6bytes_left;
137  return boost::indeterminate;
138  case length_6bytes_left:
139  frame.length |= ((uint64_t)(input & 0xFF) << 40);
140  state_ = length_5bytes_left;
141  return boost::indeterminate;
142  case length_5bytes_left:
143  frame.length |= ((uint64_t)(input & 0xFF) << 32);
144  state_ = length_4bytes_left;
145  return boost::indeterminate;
146  case length_4bytes_left:
147  frame.length |= ((uint64_t)(input & 0xFF) << 24);
148  state_ = length_3bytes_left;
149  return boost::indeterminate;
150  case length_3bytes_left:
151  frame.length |= ((uint64_t)(input & 0xFF) << 16);
152  state_ = length_2bytes_left;
153  return boost::indeterminate;
154  case length_2bytes_left:
155  frame.length |= ((uint64_t)(input & 0xFF) << 8);
156  state_ = length_1bytes_left;
157  return boost::indeterminate;
158  case length_1bytes_left:
159  frame.length |= ((uint64_t)(input & 0xFF) << 0);
160  frame.content.reserve(frame.length);
161  frame.content.resize(0);
162  if (frame.header.mask)
163  state_ = mask_byte1;
164  else
165  state_ = body;
166  return boost::indeterminate;
167 
168  case mask_byte1:
169  frame.mask[0] = input;
170  state_ = mask_byte2;
171  return boost::indeterminate;
172  case mask_byte2:
173  frame.mask[1] = input;
174  state_ = mask_byte3;
175  return boost::indeterminate;
176  case mask_byte3:
177  frame.mask[2] = input;
178  state_ = mask_byte4;
179  return boost::indeterminate;
180  case mask_byte4:
181  frame.mask[3] = input;
182  if (frame.length > 0)
183  state_ = body;
184  else
185  return true;
186  return boost::indeterminate;
187 
188  case body:
189  frame.content += input;
190  if (frame.content.size() < frame.length)
191  return boost::indeterminate;
192  // unmask the frame
193  if (frame.header.mask)
194  {
195  for (uint64_t i = 0; i < frame.length; ++i)
196  {
197  frame.content[i] = frame.content[i] ^ frame.mask[i % 4];
198  }
199  }
200  return true;
201  default:
202  return false;
203  }
204 }
205 
207 
209  WebsocketFrame& frame)
210 {
211  if (frame.header.opcode == WebsocketFrame::Header::opcode_continuation)
212  {
213  if (message.type == WebsocketMessage::type_unknown)
214  return false;
215  else
216  message.content.append(frame.content);
217  }
218  else
219  {
220  switch (frame.header.opcode)
221  {
222  case WebsocketFrame::Header::opcode_text:
224  break;
225  case WebsocketFrame::Header::opcode_binary:
227  break;
228  case WebsocketFrame::Header::opcode_close:
230  break;
231  case WebsocketFrame::Header::opcode_ping:
233  break;
234  case WebsocketFrame::Header::opcode_pong:
236  break;
237  default:
239  return false;
240  }
241  message.content = frame.content;
242  }
243  if (frame.header.fin)
244  return true;
245  else
246  return boost::indeterminate;
247 }
248 
249 } // namespace async_web_server_cpp
boost::tribool consume(WebsocketFrame &frame, char input)
bool fromMessage(const WebsocketMessage &message)
boost::tribool consume(WebsocketMessage &message, WebsocketFrame &frame)
bool serialize(std::vector< unsigned char > &buffer)


async_web_server_cpp
Author(s): Mitchell Wills , Russel Toris
autogenerated on Mon Feb 28 2022 21:54:08