Skip to content

Commit 40b1939

Browse files
committed
Breaking change: SendStream renamed to OutMessage, and Message renamed to InMessage. Also added convencience functions for Connection::send that takes strings as arguments."
1 parent 611f17c commit 40b1939

File tree

7 files changed

+254
-245
lines changed

7 files changed

+254
-245
lines changed

client_ws.hpp

Lines changed: 100 additions & 92 deletions
Large diffs are not rendered by default.

server_ws.hpp

Lines changed: 59 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ namespace SimpleWeb {
5353
template <class socket_type>
5454
class SocketServerBase {
5555
public:
56-
class Message : public std::istream {
56+
class InMessage : public std::istream {
5757
friend class SocketServerBase<socket_type>;
5858

5959
public:
@@ -77,21 +77,21 @@ namespace SimpleWeb {
7777
}
7878

7979
private:
80-
Message() noexcept : std::istream(&streambuf), length(0) {}
81-
Message(unsigned char fin_rsv_opcode, std::size_t length) noexcept : std::istream(&streambuf), fin_rsv_opcode(fin_rsv_opcode), length(length) {}
80+
InMessage() noexcept : std::istream(&streambuf), length(0) {}
81+
InMessage(unsigned char fin_rsv_opcode, std::size_t length) noexcept : std::istream(&streambuf), fin_rsv_opcode(fin_rsv_opcode), length(length) {}
8282
std::size_t length;
8383
asio::streambuf streambuf;
8484
};
8585

8686
/// The buffer is not consumed during send operations.
8787
/// Do not alter while sending.
88-
class SendStream : public std::ostream {
88+
class OutMessage : public std::ostream {
8989
friend class SocketServerBase<socket_type>;
9090

9191
asio::streambuf streambuf;
9292

9393
public:
94-
SendStream() noexcept : std::ostream(&streambuf) {}
94+
OutMessage() noexcept : std::ostream(&streambuf) {}
9595

9696
/// Returns the size of the buffer
9797
std::size_t size() const noexcept {
@@ -138,7 +138,7 @@ namespace SimpleWeb {
138138
std::mutex socket_close_mutex;
139139

140140
asio::streambuf read_buffer;
141-
std::shared_ptr<Message> fragmented_message;
141+
std::shared_ptr<InMessage> fragmented_in_message;
142142

143143
long timeout_idle;
144144
std::unique_ptr<asio::steady_timer> timer;
@@ -209,27 +209,27 @@ namespace SimpleWeb {
209209

210210
asio::io_service::strand strand;
211211

212-
class SendData {
212+
class OutData {
213213
public:
214-
SendData(std::shared_ptr<SendStream> header_stream_, std::shared_ptr<SendStream> message_stream_,
215-
std::function<void(const error_code)> &&callback_) noexcept
216-
: header_stream(std::move(header_stream_)), message_stream(std::move(message_stream_)), callback(std::move(callback_)) {}
217-
std::shared_ptr<SendStream> header_stream;
218-
std::shared_ptr<SendStream> message_stream;
214+
OutData(std::shared_ptr<OutMessage> out_header_, std::shared_ptr<OutMessage> out_message_,
215+
std::function<void(const error_code)> &&callback_) noexcept
216+
: out_header(std::move(out_header_)), out_message(std::move(out_message_)), callback(std::move(callback_)) {}
217+
std::shared_ptr<OutMessage> out_header;
218+
std::shared_ptr<OutMessage> out_message;
219219
std::function<void(const error_code)> callback;
220220
};
221221

222-
std::list<SendData> send_queue;
222+
std::list<OutData> send_queue;
223223

224224
void send_from_queue() {
225225
auto self = this->shared_from_this();
226226
strand.post([self]() {
227-
asio::async_write(*self->socket, self->send_queue.begin()->header_stream->streambuf, self->strand.wrap([self](const error_code &ec, std::size_t /*bytes_transferred*/) {
227+
asio::async_write(*self->socket, self->send_queue.begin()->out_header->streambuf, self->strand.wrap([self](const error_code &ec, std::size_t /*bytes_transferred*/) {
228228
auto lock = self->handler_runner->continue_lock();
229229
if(!lock)
230230
return;
231231
if(!ec) {
232-
asio::async_write(*self->socket, self->send_queue.begin()->message_stream->streambuf.data(), self->strand.wrap([self](const error_code &ec, std::size_t /*bytes_transferred*/) {
232+
asio::async_write(*self->socket, self->send_queue.begin()->out_message->streambuf.data(), self->strand.wrap([self](const error_code &ec, std::size_t /*bytes_transferred*/) {
233233
auto lock = self->handler_runner->continue_lock();
234234
if(!lock)
235235
return;
@@ -243,19 +243,19 @@ namespace SimpleWeb {
243243
}
244244
else {
245245
// All handlers in the queue is called with ec:
246-
for(auto &send_data : self->send_queue) {
247-
if(send_data.callback)
248-
send_data.callback(ec);
246+
for(auto &out_data : self->send_queue) {
247+
if(out_data.callback)
248+
out_data.callback(ec);
249249
}
250250
self->send_queue.clear();
251251
}
252252
}));
253253
}
254254
else {
255255
// All handlers in the queue is called with ec:
256-
for(auto &send_data : self->send_queue) {
257-
if(send_data.callback)
258-
send_data.callback(ec);
256+
for(auto &out_data : self->send_queue) {
257+
if(out_data.callback)
258+
out_data.callback(ec);
259259
}
260260
self->send_queue.clear();
261261
}
@@ -275,50 +275,58 @@ namespace SimpleWeb {
275275

276276
public:
277277
/// fin_rsv_opcode: 129=one fragment, text, 130=one fragment, binary, 136=close connection.
278-
/// See http://tools.ietf.org/html/rfc6455#section-5.2 for more information
279-
void send(const std::shared_ptr<SendStream> &send_stream, const std::function<void(const error_code &)> &callback = nullptr,
280-
unsigned char fin_rsv_opcode = 129) {
278+
/// See http://tools.ietf.org/html/rfc6455#section-5.2 for more information.
279+
void send(const std::shared_ptr<OutMessage> &out_message, const std::function<void(const error_code &)> &callback = nullptr, unsigned char fin_rsv_opcode = 129) {
281280
cancel_timeout();
282281
set_timeout();
283282

284-
auto header_stream = std::make_shared<SendStream>();
283+
auto out_header = std::make_shared<OutMessage>();
285284

286-
std::size_t length = send_stream->size();
285+
std::size_t length = out_message->size();
287286

288-
header_stream->put(static_cast<char>(fin_rsv_opcode));
287+
out_header->put(static_cast<char>(fin_rsv_opcode));
289288
// Unmasked (first length byte<128)
290289
if(length >= 126) {
291290
std::size_t num_bytes;
292291
if(length > 0xffff) {
293292
num_bytes = 8;
294-
header_stream->put(127);
293+
out_header->put(127);
295294
}
296295
else {
297296
num_bytes = 2;
298-
header_stream->put(126);
297+
out_header->put(126);
299298
}
300299

301300
for(std::size_t c = num_bytes - 1; c != static_cast<std::size_t>(-1); c--)
302-
header_stream->put((static_cast<unsigned long long>(length) >> (8 * c)) % 256);
301+
out_header->put((static_cast<unsigned long long>(length) >> (8 * c)) % 256);
303302
}
304303
else
305-
header_stream->put(static_cast<char>(length));
304+
out_header->put(static_cast<char>(length));
306305

307306
auto self = this->shared_from_this();
308-
strand.post([self, header_stream, send_stream, callback]() {
309-
self->send_queue.emplace_back(header_stream, send_stream, callback);
307+
strand.post([self, out_header, out_message, callback]() {
308+
self->send_queue.emplace_back(out_header, out_message, callback);
310309
if(self->send_queue.size() == 1)
311310
self->send_from_queue();
312311
});
313312
}
314313

314+
/// Convenience function for sending a string.
315+
/// fin_rsv_opcode: 129=one fragment, text, 130=one fragment, binary, 136=close connection.
316+
/// See http://tools.ietf.org/html/rfc6455#section-5.2 for more information.
317+
void send(string_view out_message_str, const std::function<void(const error_code &)> &callback = nullptr, unsigned char fin_rsv_opcode = 129) {
318+
auto out_message = std::make_shared<OutMessage>();
319+
out_message->write(out_message_str.data(), static_cast<std::streamsize>(out_message_str.size()));
320+
send(out_message, callback, fin_rsv_opcode);
321+
}
322+
315323
void send_close(int status, const std::string &reason = "", const std::function<void(const error_code &)> &callback = nullptr) {
316324
// Send close only once (in case close is initiated by server)
317325
if(closed)
318326
return;
319327
closed = true;
320328

321-
auto send_stream = std::make_shared<SendStream>();
329+
auto send_stream = std::make_shared<OutMessage>();
322330

323331
send_stream->put(status >> 8);
324332
send_stream->put(status % 256);
@@ -339,7 +347,7 @@ namespace SimpleWeb {
339347

340348
public:
341349
std::function<void(std::shared_ptr<Connection>)> on_open;
342-
std::function<void(std::shared_ptr<Connection>, std::shared_ptr<Message>)> on_message;
350+
std::function<void(std::shared_ptr<Connection>, std::shared_ptr<InMessage>)> on_message;
343351
std::function<void(std::shared_ptr<Connection>, int, const std::string &)> on_close;
344352
std::function<void(std::shared_ptr<Connection>, const error_code &)> on_error;
345353
std::function<void(std::shared_ptr<Connection>)> on_ping;
@@ -660,7 +668,7 @@ namespace SimpleWeb {
660668
}
661669

662670
void read_message_content(const std::shared_ptr<Connection> &connection, std::size_t length, Endpoint &endpoint, unsigned char fin_rsv_opcode) const {
663-
if(length + (connection->fragmented_message ? connection->fragmented_message->length : 0) > config.max_message_size) {
671+
if(length + (connection->fragmented_in_message ? connection->fragmented_in_message->length : 0) > config.max_message_size) {
664672
connection_error(connection, endpoint, make_error_code::make_error_code(errc::message_size));
665673
const int status = 1009;
666674
const std::string reason = "message too big";
@@ -679,21 +687,21 @@ namespace SimpleWeb {
679687
std::array<unsigned char, 4> mask;
680688
istream.read((char *)&mask[0], 4);
681689

682-
std::shared_ptr<Message> message;
690+
std::shared_ptr<InMessage> in_message;
683691

684692
// If fragmented message
685693
if((fin_rsv_opcode & 0x80) == 0 || (fin_rsv_opcode & 0x0f) == 0) {
686-
if(!connection->fragmented_message) {
687-
connection->fragmented_message = std::shared_ptr<Message>(new Message(fin_rsv_opcode, length));
688-
connection->fragmented_message->fin_rsv_opcode |= 0x80;
694+
if(!connection->fragmented_in_message) {
695+
connection->fragmented_in_message = std::shared_ptr<InMessage>(new InMessage(fin_rsv_opcode, length));
696+
connection->fragmented_in_message->fin_rsv_opcode |= 0x80;
689697
}
690698
else
691-
connection->fragmented_message->length += length;
692-
message = connection->fragmented_message;
699+
connection->fragmented_in_message->length += length;
700+
in_message = connection->fragmented_in_message;
693701
}
694702
else
695-
message = std::shared_ptr<Message>(new Message(fin_rsv_opcode, length));
696-
std::ostream ostream(&message->streambuf);
703+
in_message = std::shared_ptr<InMessage>(new InMessage(fin_rsv_opcode, length));
704+
std::ostream ostream(&in_message->streambuf);
697705
for(std::size_t c = 0; c < length; c++)
698706
ostream.put(istream.get() ^ mask[c % 4]);
699707

@@ -704,12 +712,12 @@ namespace SimpleWeb {
704712

705713
int status = 0;
706714
if(length >= 2) {
707-
unsigned char byte1 = message->get();
708-
unsigned char byte2 = message->get();
715+
unsigned char byte1 = in_message->get();
716+
unsigned char byte2 = in_message->get();
709717
status = (static_cast<int>(byte1) << 8) + byte2;
710718
}
711719

712-
auto reason = message->string();
720+
auto reason = in_message->string();
713721
connection->send_close(status, reason);
714722
this->connection_close(connection, endpoint, status, reason);
715723
}
@@ -719,7 +727,7 @@ namespace SimpleWeb {
719727
connection->set_timeout();
720728

721729
// Send pong
722-
auto empty_send_stream = std::make_shared<SendStream>();
730+
auto empty_send_stream = std::make_shared<OutMessage>();
723731
connection->send(empty_send_stream, nullptr, fin_rsv_opcode + 1);
724732

725733
if(endpoint.on_ping)
@@ -749,11 +757,11 @@ namespace SimpleWeb {
749757
connection->set_timeout();
750758

751759
if(endpoint.on_message)
752-
endpoint.on_message(connection, message);
760+
endpoint.on_message(connection, in_message);
753761

754762
// Next message
755-
// Only reset fragmented_message for non-control frames (control frames can be in between a fragmented message)
756-
connection->fragmented_message = nullptr;
763+
// Only reset fragmented_in_message for non-control frames (control frames can be in between a fragmented message)
764+
connection->fragmented_in_message = nullptr;
757765
this->read_message(connection, endpoint);
758766
}
759767
}

0 commit comments

Comments
 (0)