2 #include <samchon/API.hpp> 4 #include <samchon/protocol/Communicator.hpp> 8 #include <samchon/protocol/WebSocketUtil.hpp> 45 this->is_server = is_server;
49 virtual void sendData(std::shared_ptr<Invoke> invoke)
override 51 std::unique_lock<std::mutex> uk(send_mtx);
54 const std::string &str = invoke->toXML()->toString();
55 if (is_server ==
true)
58 send_masked_data(str);
61 for (
size_t i = 0; i < invoke->size(); i++)
62 if (invoke->at(i)->getType() ==
"ByteArray")
63 if (is_server ==
true)
64 send_data(invoke->at(i)->referValue<
ByteArray>());
66 send_masked_data(invoke->at(i)->referValue<
ByteArray>());
77 virtual void listen_message()
override 79 std::shared_ptr<Invoke> binary_invoke =
nullptr;
80 std::queue<std::shared_ptr<InvokeParameter>> binary_parameters;
86 const std::pair<unsigned char, size_t> &header = listen_header();
89 if (header.first == WebSocketUtil::DISCONNECT)
93 if (header.first == WebSocketUtil::TEXT)
95 std::shared_ptr<Invoke> invoke = listen_string(header.second);
97 for (
size_t i = 0; i < invoke->size(); i++)
99 std::shared_ptr<InvokeParameter> ¶meter = invoke->at(i);
100 if (parameter->getType() !=
"ByteArray")
103 if (binary_invoke ==
nullptr)
104 binary_invoke = invoke;
105 binary_parameters.push(parameter);
109 if (binary_invoke ==
nullptr)
112 else if (header.first == WebSocketUtil::BINARY)
114 std::shared_ptr<InvokeParameter> parameter = binary_parameters.front();
115 listen_binary(header.second, parameter);
116 binary_parameters.pop();
118 if (binary_parameters.empty() ==
true)
121 std::shared_ptr<Invoke> invoke = binary_invoke;
122 binary_invoke =
nullptr;
137 auto listen_header() -> std::pair<unsigned char, size_t>
139 unsigned char mask = is_server ? WebSocketUtil::MASK : 0;
141 std::array<unsigned char, 2> header_bytes;
142 unsigned char op_code;
143 unsigned char size_header;
145 size_t content_size = 0;
148 listen_data(header_bytes);
149 op_code = header_bytes[0];
150 size_header = header_bytes[1];
153 if (is_server ==
true)
155 if (size_header < WebSocketUtil::MASK)
156 throw std::domain_error(
"masked message from server has delivered.");
160 if (size_header >= WebSocketUtil::MASK)
161 throw std::domain_error(
"masked message from server has delivered.");
165 if (op_code == WebSocketUtil::DISCONNECT)
166 return{ op_code, 0 };
170 size_header -= WebSocketUtil::MASK;
172 if (size_header == (
unsigned char)WebSocketUtil::TWO_BYTES)
175 std::array<unsigned char, 2> size_bytes;
176 listen_data(size_bytes);
178 for (
size_t c = 0; c < size_bytes.size(); c++)
179 content_size += size_bytes[c] << (8 * (size_bytes.size() - 1 - c));
181 else if (size_header == (
unsigned char)WebSocketUtil::EIGHT_BYTES)
184 std::array<unsigned char, 8> size_bytes;
185 listen_data(size_bytes);
187 for (
size_t c = 0; c < size_bytes.size(); c++)
188 content_size += size_bytes[c] << (8 * (size_bytes.size() - 1 - c));
191 content_size = (size_t)size_header;
193 return{ op_code, content_size };
196 auto listen_string(
size_t size) -> std::shared_ptr<Invoke>
199 std::string data(size, (
char)NULL);
201 listen_masked_data(data);
206 std::shared_ptr<Invoke> invoke(
new Invoke());
207 invoke->construct(std::make_shared<library::XML>(data));
212 void listen_binary(
size_t size, std::shared_ptr<InvokeParameter> parameter)
218 if (is_server ==
true)
219 listen_masked_data(data);
224 template <
class Container>
225 void listen_data(Container &data)
227 size_t completed = 0;
229 if (completed < data.size())
230 completed += socket->read_some(boost::asio::buffer((
unsigned char*)data.data() + completed, data.size() - completed));
233 template <
class Container>
234 void listen_masked_data(Container &data)
237 std::array<unsigned char, 4> mask;
238 socket->read_some(boost::asio::buffer(mask));
244 for (
size_t i = 0; i < data.size(); i++)
245 data[i] = data[i] ^ mask[i % 4];
251 template <
class Container>
252 void send_data(
const Container &data)
254 unsigned char op_code = std::is_same<std::string, Container>()
255 ? WebSocketUtil::TEXT
256 : WebSocketUtil::BINARY;
257 size_t size = data.size();
263 header.
write(op_code);
266 header.
write((
unsigned char)size);
267 else if (size < 0xFFFF)
269 header.
write((
unsigned char)(WebSocketUtil::TWO_BYTES));
274 header.
write((
unsigned char)(WebSocketUtil::EIGHT_BYTES));
278 socket->write_some(boost::asio::buffer(header));
279 socket->write_some(boost::asio::buffer(data));
282 template <
class Container>
283 void send_masked_data(
const Container &data)
285 unsigned char op_code = std::is_same<std::string, Container>()
286 ? WebSocketUtil::TEXT
287 : WebSocketUtil::BINARY;
288 size_t size = data.size();
294 header.
write(op_code);
297 header.
write((
unsigned char)(size + WebSocketUtil::MASK));
298 else if (size < 0xFFFF)
300 header.
write((
unsigned char)(WebSocketUtil::TWO_BYTES + WebSocketUtil::MASK));
305 header.
write((
unsigned char)(WebSocketUtil::EIGHT_BYTES + WebSocketUtil::MASK));
312 static std::uniform_int_distribution<unsigned short> distribution(0, 255);
313 static std::random_device device;
316 std::array<unsigned char, 4> mask;
317 for (
size_t i = 0; i < mask.size(); i++)
318 mask[i] = (
unsigned char)distribution(device);
321 std::vector<unsigned char> masked_data(data.size());
322 for (
size_t i = 0; i < masked_data.size(); i++)
323 masked_data[i] = data[i] ^ mask[i % 4];
326 socket->write_some(boost::asio::buffer(header));
327 socket->write_some(boost::asio::buffer(mask));
328 socket->write_some(boost::asio::buffer(masked_data));
virtual void replyData(std::shared_ptr< Invoke > invoke)
void writeReversely(const T &val)
Write a data.
virtual void sendData(std::shared_ptr< Invoke > invoke) override
Standard message of network I/O.
void write(const T &val)
Write a data.