1use std::{
6 collections::VecDeque,
7 io::{self, IoSlice},
8 mem::{replace, take},
9 pin::Pin,
10 task::{Context, Poll, Waker, ready},
11};
12
13use bytes::{Buf, BytesMut};
14use futures_core::Stream;
15use futures_sink::Sink;
16use tokio::io::{AsyncRead, AsyncWrite};
17use tokio_util::{codec::FramedRead, io::poll_write_buf};
18
19#[cfg(any(feature = "client", feature = "server"))]
20use super::types::Role;
21use super::{
22 Config, Limits,
23 codec::WebSocketProtocol,
24 types::{Frame, Message, OpCode, Payload, StreamState},
25};
26use crate::{CloseCode, Error};
27
28#[derive(Debug)]
30struct EncodedFrame {
31 header: [u8; 14],
33 payload: Payload,
35}
36
37impl EncodedFrame {
38 #[inline]
40 fn is_masked(&self) -> bool {
41 self.header[1] >> 7 != 0
42 }
43
44 #[inline]
46 fn header_len(&self) -> usize {
47 let mask_bytes = if self.is_masked() { 4 } else { 0 };
48 match self.header[1] & 127 {
49 127 => 10 + mask_bytes,
50 126 => 4 + mask_bytes,
51 _ => 2 + mask_bytes,
52 }
53 }
54
55 fn len(&self) -> usize {
57 self.header_len() + self.payload.len()
58 }
59}
60
61#[derive(Debug)]
63struct FrameQueue {
64 queue: VecDeque<EncodedFrame>,
67 bytes_written: usize,
69 pending_bytes: usize,
71}
72
73impl FrameQueue {
74 #[cfg(any(feature = "client", feature = "server"))]
76 fn new() -> Self {
77 Self {
78 queue: VecDeque::with_capacity(1),
79 bytes_written: 0,
80 pending_bytes: 0,
81 }
82 }
83
84 fn push(&mut self, item: EncodedFrame) {
86 self.pending_bytes += item.len();
87 self.queue.push_back(item);
88 }
89}
90
91impl Buf for FrameQueue {
92 fn remaining(&self) -> usize {
93 self.pending_bytes
94 }
95
96 fn chunk(&self) -> &[u8] {
97 if let Some(frame) = self.queue.front() {
98 if self.bytes_written >= frame.header_len() {
99 unsafe {
100 frame
101 .payload
102 .get_unchecked(self.bytes_written - frame.header_len()..)
103 }
104 } else {
105 &frame.header[self.bytes_written..frame.header_len()]
106 }
107 } else {
108 &[]
109 }
110 }
111
112 fn advance(&mut self, mut cnt: usize) {
113 self.pending_bytes -= cnt;
114 cnt += self.bytes_written;
115
116 while cnt > 0 {
117 let item = self
118 .queue
119 .front()
120 .expect("advance called with too long count");
121 let item_len = item.len();
122
123 if cnt >= item_len {
124 self.queue.pop_front();
125 self.bytes_written = 0;
126 cnt -= item_len;
127 } else {
128 self.bytes_written = cnt;
129 return;
130 }
131 }
132 }
133
134 fn chunks_vectored<'a>(&'a self, dst: &mut [io::IoSlice<'a>]) -> usize {
135 let mut n = 0;
136 for (idx, frame) in self.queue.iter().enumerate() {
137 if n >= dst.len() {
138 break;
139 }
140
141 if idx == 0 {
142 if frame.header_len() > self.bytes_written {
143 dst[n] = IoSlice::new(&frame.header[self.bytes_written..frame.header_len()]);
144 n += 1;
145 }
146
147 if !frame.payload.is_empty() && n < dst.len() {
148 dst[n] = IoSlice::new(unsafe {
149 frame
150 .payload
151 .get_unchecked(self.bytes_written.saturating_sub(frame.header_len())..)
152 });
153 n += 1;
154 }
155 } else {
156 dst[n] = IoSlice::new(&frame.header[..frame.header_len()]);
157 n += 1;
158 if !frame.payload.is_empty() && n < dst.len() {
159 dst[n] = IoSlice::new(&frame.payload);
160 n += 1;
161 }
162 }
163 }
164
165 n
166 }
167}
168
169#[allow(clippy::module_name_repetitions)]
182#[derive(Debug)]
183pub struct WebSocketStream<T> {
184 inner: FramedRead<T, WebSocketProtocol>,
187
188 config: Config,
190
191 state: StreamState,
193
194 partial_payload: BytesMut,
196 partial_opcode: OpCode,
198
199 header_buf: [u8; 14],
201
202 frame_queue: FrameQueue,
204
205 flushing_waker: Option<Waker>,
208}
209
210impl<T> WebSocketStream<T>
211where
212 T: AsyncRead + AsyncWrite + Unpin,
213{
214 #[cfg(any(feature = "client", feature = "server"))]
216 pub(crate) fn from_raw_stream(stream: T, role: Role, config: Config, limits: Limits) -> Self {
217 Self {
218 inner: FramedRead::new(stream, WebSocketProtocol::new(role, limits)),
219 config,
220 state: StreamState::Active,
221 partial_payload: BytesMut::new(),
222 partial_opcode: OpCode::Continuation,
223 header_buf: [0; 14],
224 frame_queue: FrameQueue::new(),
225 flushing_waker: None,
226 }
227 }
228
229 #[cfg(any(feature = "client", feature = "server"))]
232 pub(crate) fn from_framed<U>(
233 framed: FramedRead<T, U>,
234 role: Role,
235 config: Config,
236 limits: Limits,
237 ) -> Self {
238 Self {
239 inner: framed.map_decoder(|_| WebSocketProtocol::new(role, limits)),
240 config,
241 state: StreamState::Active,
242 partial_payload: BytesMut::new(),
243 partial_opcode: OpCode::Continuation,
244 header_buf: [0; 14],
245 frame_queue: FrameQueue::new(),
246 flushing_waker: None,
247 }
248 }
249
250 pub fn get_ref(&self) -> &T {
255 self.inner.get_ref()
256 }
257
258 pub fn get_mut(&mut self) -> &mut T {
264 self.inner.get_mut()
265 }
266
267 pub fn limits(&self) -> &Limits {
269 &self.inner.decoder().limits
270 }
271
272 pub fn limits_mut(&mut self) -> &mut Limits {
274 &mut self.inner.decoder_mut().limits
275 }
276
277 pub fn into_inner(self) -> T {
279 self.inner.into_inner()
280 }
281
282 fn poll_next_frame(
290 mut self: Pin<&mut Self>,
291 cx: &mut Context<'_>,
292 ) -> Poll<Option<Result<Frame, Error>>> {
293 if self.state == StreamState::CloseAcknowledged {
297 return Poll::Ready(None);
298 } else if self.state == StreamState::ClosedByPeer {
299 ready!(self.as_mut().poll_flush(cx))?;
300 self.state = StreamState::CloseAcknowledged;
301 return Poll::Ready(None);
302 }
303
304 if self.frame_queue.has_remaining() {
311 let waker = self.flushing_waker.clone();
312 _ = self.as_mut().poll_flush(&mut Context::from_waker(
313 waker.as_ref().unwrap_or(cx.waker()),
314 ))?;
315 }
316
317 let frame = match ready!(Pin::new(&mut self.inner).poll_next(cx)) {
318 Some(Ok(frame)) => frame,
319 Some(Err(e)) => {
320 if matches!(e, Error::Io(_)) || self.state == StreamState::ClosedByUs {
321 self.state = StreamState::CloseAcknowledged;
322 } else {
323 self.state = StreamState::ClosedByPeer;
324
325 match &e {
326 Error::Protocol(e) => self.queue_frame(Frame::from(e)),
327 Error::PayloadTooLong { max_len, .. } => self.queue_frame(
328 Message::close(
329 Some(CloseCode::MESSAGE_TOO_BIG),
330 &format!("max length: {max_len}"),
331 )
332 .into(),
333 ),
334 _ => {}
335 }
336 }
337 return Poll::Ready(Some(Err(e)));
338 }
339 None => return Poll::Ready(None),
340 };
341
342 match frame.opcode {
343 OpCode::Close => match self.state {
344 StreamState::Active => {
345 self.state = StreamState::ClosedByPeer;
346
347 let mut frame = frame.clone();
348 frame.payload.truncate(2);
349
350 self.queue_frame(frame);
351 }
352 StreamState::ClosedByPeer | StreamState::CloseAcknowledged => {
353 debug_assert!(false, "unexpected StreamState");
354 }
355 StreamState::ClosedByUs => {
356 self.state = StreamState::CloseAcknowledged;
357 }
358 },
359 OpCode::Ping if self.state == StreamState::Active => {
360 let mut frame = frame.clone();
361 frame.opcode = OpCode::Pong;
362
363 self.queue_frame(frame);
364 }
365 _ => {}
366 }
367
368 Poll::Ready(Some(Ok(frame)))
369 }
370
371 fn queue_frame(
373 &mut self,
374 #[cfg_attr(not(feature = "client"), allow(unused_mut))] mut frame: Frame,
375 ) {
376 if frame.opcode == OpCode::Close && self.state != StreamState::ClosedByPeer {
377 self.state = StreamState::ClosedByUs;
378 }
379
380 #[cfg_attr(not(feature = "client"), allow(unused_variables))]
381 let mask = frame.encode(&mut self.header_buf);
382
383 #[cfg(feature = "client")]
384 {
385 if self.inner.decoder().role == Role::Client {
386 let mut payload = BytesMut::from(frame.payload);
387 crate::rand::get_mask(mask);
388 let mut mask_copy = *mask;
393 crate::mask::frame(&mut mask_copy, &mut payload);
394 frame.payload = Payload::from(payload);
395 self.header_buf[1] |= 1 << 7;
396 }
397 }
398
399 let item = EncodedFrame {
400 header: self.header_buf,
401 payload: frame.payload,
402 };
403 self.frame_queue.push(item);
404 }
405
406 fn set_flushing_waker(&mut self, waker: &Waker) {
409 if !self
410 .flushing_waker
411 .as_ref()
412 .is_some_and(|w| w.will_wake(waker))
413 {
414 self.flushing_waker = Some(waker.clone());
415 }
416 }
417}
418
419impl<T> Stream for WebSocketStream<T>
420where
421 T: AsyncRead + AsyncWrite + Unpin,
422{
423 type Item = Result<Message, Error>;
424
425 fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
426 let max_len = self.inner.decoder().limits.max_payload_len;
427
428 loop {
429 let (opcode, payload, fin) = match ready!(self.as_mut().poll_next_frame(cx)?) {
430 Some(frame) => (frame.opcode, frame.payload, frame.is_final),
431 None => return Poll::Ready(None),
432 };
433 let len = self.partial_payload.len() + payload.len();
434
435 if opcode != OpCode::Continuation {
436 if fin {
437 return Poll::Ready(Some(Ok(Message { opcode, payload })));
438 }
439 self.partial_opcode = opcode;
440 self.partial_payload = BytesMut::from(payload);
441 } else if len > max_len {
442 return Poll::Ready(Some(Err(Error::PayloadTooLong { len, max_len })));
443 } else {
444 self.partial_payload.extend_from_slice(&payload);
445 }
446
447 if fin {
448 break;
449 }
450 }
451
452 let opcode = replace(&mut self.partial_opcode, OpCode::Continuation);
453 let mut payload = Payload::from(take(&mut self.partial_payload));
454 payload.set_utf8_validated(opcode == OpCode::Text);
455
456 Poll::Ready(Some(Ok(Message { opcode, payload })))
457 }
458}
459
460impl<T> Sink<Message> for WebSocketStream<T>
466where
467 T: AsyncRead + AsyncWrite + Unpin,
468{
469 type Error = Error;
470
471 fn poll_ready(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
472 if self.frame_queue.remaining() >= self.config.flush_threshold {
475 self.as_mut().poll_flush(cx)
476 } else {
477 Poll::Ready(Ok(()))
478 }
479 }
480
481 fn start_send(mut self: Pin<&mut Self>, item: Message) -> Result<(), Self::Error> {
482 if self.state != StreamState::Active {
483 return Err(Error::AlreadyClosed);
484 }
485
486 if item.opcode.is_control() || item.payload.len() <= self.config.frame_size {
487 let frame: Frame = item.into();
488 self.queue_frame(frame);
489 } else {
490 for frame in item.into_frames(self.config.frame_size) {
492 self.queue_frame(frame);
493 }
494 }
495
496 Ok(())
497 }
498
499 fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
500 let this = self.get_mut();
503 let frame_queue = &mut this.frame_queue;
504 let io = this.inner.get_mut();
505 let flushing_waker = &mut this.flushing_waker;
506
507 while frame_queue.has_remaining() {
508 let n = match poll_write_buf(Pin::new(io), cx, frame_queue) {
509 Poll::Ready(Ok(n)) => n,
510 Poll::Ready(Err(e)) => {
511 *flushing_waker = None;
512 this.state = StreamState::CloseAcknowledged;
513 return Poll::Ready(Err(Error::Io(e)));
514 }
515 Poll::Pending => {
516 this.set_flushing_waker(cx.waker());
517 return Poll::Pending;
518 }
519 };
520
521 if n == 0 {
522 *flushing_waker = None;
523 this.state = StreamState::CloseAcknowledged;
524 return Poll::Ready(Err(Error::Io(io::ErrorKind::WriteZero.into())));
525 }
526 }
527
528 match Pin::new(io).poll_flush(cx) {
529 Poll::Ready(Ok(())) => {
530 *flushing_waker = None;
531 Poll::Ready(Ok(()))
532 }
533 Poll::Ready(Err(e)) => {
534 *flushing_waker = None;
535 this.state = StreamState::CloseAcknowledged;
536 Poll::Ready(Err(Error::Io(e)))
537 }
538 Poll::Pending => {
539 this.set_flushing_waker(cx.waker());
540 Poll::Pending
541 }
542 }
543 }
544
545 fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
546 if self.state == StreamState::Active {
547 self.queue_frame(Frame::DEFAULT_CLOSE);
548 }
549 while ready!(self.as_mut().poll_next(cx)).is_some() {}
550
551 ready!(self.as_mut().poll_flush(cx))?;
552 Pin::new(self.inner.get_mut())
553 .poll_shutdown(cx)
554 .map_err(Error::Io)
555 }
556}