@@ -408,6 +408,7 @@ namespace vix::websocket
408408 if (self->closing_ )
409409 {
410410 self->writeQueue_ .clear ();
411+ self->queuedWriteBytes_ = 0 ;
411412 self->writeInProgress_ = false ;
412413 co_return ;
413414 }
@@ -420,6 +421,15 @@ namespace vix::websocket
420421
421422 msg = std::move (self->writeQueue_ .front ());
422423 self->writeQueue_ .pop_front ();
424+
425+ if (self->queuedWriteBytes_ >= msg.data .size ())
426+ {
427+ self->queuedWriteBytes_ -= msg.data .size ();
428+ }
429+ else
430+ {
431+ self->queuedWriteBytes_ = 0 ;
432+ }
423433 }
424434
425435 std::vector<std::byte> frame;
@@ -752,6 +762,9 @@ namespace vix::websocket
752762 return ;
753763 }
754764
765+ const std::size_t payloadSize = payload.size ();
766+ bool overflow = false ;
767+
755768 {
756769 std::lock_guard<std::mutex> lock (writeMutex_);
757770
@@ -760,10 +773,32 @@ namespace vix::websocket
760773 return ;
761774 }
762775
763- writeQueue_.push_back (PendingMessage{
764- isBinary,
765- std::move (payload),
766- });
776+ if (writeQueue_.size () >= MAX_PENDING_WRITE_MESSAGES ||
777+ queuedWriteBytes_ + payloadSize > MAX_PENDING_WRITE_BYTES )
778+ {
779+ overflow = true ;
780+ }
781+ else
782+ {
783+ queuedWriteBytes_ += payloadSize;
784+
785+ writeQueue_.push_back (PendingMessage{
786+ isBinary,
787+ std::move (payload),
788+ });
789+ }
790+ }
791+
792+ if (overflow)
793+ {
794+ log ().log (
795+ Logger::Level::Warn,
796+ " [ws] closing slow client reason=backpressure queue_messages={} queue_bytes={}" ,
797+ MAX_PENDING_WRITE_MESSAGES ,
798+ MAX_PENDING_WRITE_BYTES );
799+
800+ close (" backpressure" );
801+ return ;
767802 }
768803
769804 trigger_write_flush ();
@@ -921,9 +956,15 @@ namespace vix::websocket
921956 open_ = false ;
922957 closing_ = true ;
923958
959+ {
960+ std::lock_guard<std::mutex> lock (writeMutex_);
961+ writeQueue_.clear ();
962+ queuedWriteBytes_ = 0 ;
963+ writeInProgress_ = false ;
964+ }
965+
924966 cancel_idle_timer ();
925967 stop_heartbeat ();
926-
927968 readCancel_.request_cancel ();
928969 writeCancel_.request_cancel ();
929970 closeCancel_.request_cancel ();
0 commit comments