93 std::function<
bool(
const crow::request&,
void**)> accept_handler):
94 adaptor_(std::move(adaptor)),
96 max_payload_bytes_(max_payload),
97 open_handler_(std::move(open_handler)),
98 message_handler_(std::move(message_handler)),
99 close_handler_(std::move(close_handler)),
100 error_handler_(std::move(error_handler)),
101 accept_handler_(std::move(accept_handler))
103 if (!utility::string_equals(req.get_header_value(
"upgrade"),
"websocket"))
106 handler_->remove_websocket(
this);
114 if (!accept_handler_(req, &ud))
117 handler_->remove_websocket(
this);
126 std::string magic = req.get_header_value(
"Sec-WebSocket-Key") +
"258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
128 s.processBytes(magic.data(), magic.size());
130 s.getDigestBytes(digest);
132 start(crow::utility::base64encode((
unsigned char*)digest, 20));
298 if (has_sent_close_ && has_recv_close_)
300 close_connection_ =
true;
301 adaptor_.shutdown_readwrite();
310 case WebSocketReadState::MiniHeader:
314 adaptor_.socket().async_read_some(
315 asio::buffer(&mini_header_, 2),
316 [
this](
const error_code& ec, std::size_t
317#ifdef CROW_ENABLE_DEBUG
324 mini_header_ = ntohs(mini_header_);
325#ifdef CROW_ENABLE_DEBUG
327 if (!ec && bytes_transferred != 2)
329 throw std::runtime_error(
"WebSocket:MiniHeader:async_read fail:asio bug?");
335 if ((mini_header_ & 0x80) == 0x80)
339#ifndef CROW_ENFORCE_WS_SPEC
342 close_connection_ =
true;
343 adaptor_.shutdown_readwrite();
346 error_handler_(*
this,
"Client connection not masked.");
351 if ((mini_header_ & 0x7f) == 127)
353 state_ = WebSocketReadState::Len64;
355 else if ((mini_header_ & 0x7f) == 126)
357 state_ = WebSocketReadState::Len16;
361 remaining_length_ = mini_header_ & 0x7f;
362 state_ = WebSocketReadState::Mask;
368 close_connection_ =
true;
369 adaptor_.shutdown_readwrite();
372 error_handler_(*
this, ec.message());
378 case WebSocketReadState::Len16:
380 remaining_length_ = 0;
381 remaining_length16_ = 0;
383 adaptor_.socket(), asio::buffer(&remaining_length16_, 2),
384 [
this](
const error_code& ec, std::size_t
385#ifdef CROW_ENABLE_DEBUG
390 remaining_length16_ = ntohs(remaining_length16_);
391 remaining_length_ = remaining_length16_;
392#ifdef CROW_ENABLE_DEBUG
393 if (!ec && bytes_transferred != 2)
395 throw std::runtime_error(
"WebSocket:Len16:async_read fail:asio bug?");
401 state_ = WebSocketReadState::Mask;
406 close_connection_ =
true;
407 adaptor_.shutdown_readwrite();
410 error_handler_(*
this, ec.message());
416 case WebSocketReadState::Len64:
419 adaptor_.socket(), asio::buffer(&remaining_length_, 8),
420 [
this](
const error_code& ec, std::size_t
421#ifdef CROW_ENABLE_DEBUG
426 remaining_length_ = ((1 == ntohl(1)) ? (remaining_length_) : (static_cast<uint64_t>(ntohl((remaining_length_)&0xFFFFFFFF)) << 32) | ntohl((remaining_length_) >> 32));
427#ifdef CROW_ENABLE_DEBUG
428 if (!ec && bytes_transferred != 8)
430 throw std::runtime_error(
"WebSocket:Len16:async_read fail:asio bug?");
436 state_ = WebSocketReadState::Mask;
441 close_connection_ =
true;
442 adaptor_.shutdown_readwrite();
445 error_handler_(*
this, ec.message());
451 case WebSocketReadState::Mask:
452 if (remaining_length_ > max_payload_bytes_)
454 close_connection_ =
true;
457 error_handler_(*
this,
"Message length exceeds maximum payload.");
463 adaptor_.socket(), asio::buffer((
char*)&mask_, 4),
464 [
this](
const error_code& ec, std::size_t
465#ifdef CROW_ENABLE_DEBUG
470#ifdef CROW_ENABLE_DEBUG
471 if (!ec && bytes_transferred != 4)
473 throw std::runtime_error(
"WebSocket:Mask:async_read fail:asio bug?");
479 state_ = WebSocketReadState::Payload;
484 close_connection_ =
true;
486 error_handler_(*
this, ec.message());
487 adaptor_.shutdown_readwrite();
495 state_ = WebSocketReadState::Payload;
499 case WebSocketReadState::Payload:
501 auto to_read =
static_cast<std::uint64_t
>(buffer_.size());
502 if (remaining_length_ < to_read)
503 to_read = remaining_length_;
504 adaptor_.socket().async_read_some(
505 asio::buffer(buffer_,
static_cast<std::size_t
>(to_read)),
506 [
this](
const error_code& ec, std::size_t bytes_transferred) {
511 fragment_.insert(fragment_.end(), buffer_.begin(), buffer_.begin() + bytes_transferred);
512 remaining_length_ -= bytes_transferred;
513 if (remaining_length_ == 0)
515 if (handle_fragment())
517 state_ = WebSocketReadState::MiniHeader;
526 close_connection_ =
true;
528 error_handler_(*
this, ec.message());
529 adaptor_.shutdown_readwrite();
646 if (sending_buffers_.empty())
648 sending_buffers_.swap(write_buffers_);
649 std::vector<asio::const_buffer> buffers;
650 buffers.reserve(sending_buffers_.size());
651 for (
auto& s : sending_buffers_)
653 buffers.emplace_back(asio::buffer(s));
655 auto watch = std::weak_ptr<void>{anchor_};
657 adaptor_.socket(), buffers,
658 [&, watch](
const error_code& ec, std::size_t ) {
659 if (!ec && !close_connection_)
661 sending_buffers_.clear();
662 if (!write_buffers_.empty())
665 close_connection_ = true;
669 auto anchor = watch.lock();
670 if (anchor == nullptr) { return; }
672 sending_buffers_.clear();
673 close_connection_ =
true;