@@ -255,6 +255,29 @@ impl<Stream: Read + Write> WebSocket<Stream> {
255255 self . context . read ( & mut self . socket )
256256 }
257257
258+ /// Read a message from stream, if possible.
259+ ///
260+ /// This will also queue responses to ping and close messages. These responses
261+ /// will be written and flushed on the next call to [`read`](Self::read),
262+ /// [`write`](Self::write) or [`flush`](Self::flush).
263+ ///
264+ /// # Closing the connection
265+ /// When the remote endpoint decides to close the connection this will return
266+ /// the close message with an optional close frame.
267+ ///
268+ /// You should continue calling [`read`](Self::read), [`write`](Self::write) or
269+ /// [`flush`](Self::flush) to drive the reply to the close frame until [`Error::ConnectionClosed`]
270+ /// is returned. Once that happens it is safe to drop the underlying connection.
271+ ///
272+ /// # Safety
273+ ///
274+ /// This function uses `FrameCodec::read_in_unsound` which can be unsound.
275+ /// It is up to the caller of this function to ensure that the underlying `Read` implementation does not
276+ /// attempt to read the uninitialized buffer and only writes to it.
277+ pub unsafe fn read_unsound ( & mut self ) -> Result < Message > {
278+ unsafe { self . context . read_unsound ( & mut self . socket ) }
279+ }
280+
258281 /// Writes and immediately flushes a message.
259282 /// Equivalent to calling [`write`](Self::write) then [`flush`](Self::flush).
260283 pub fn send ( & mut self , message : Message ) -> Result < ( ) > {
@@ -441,9 +464,44 @@ impl WebSocketContext {
441464 ///
442465 /// This function sends pong and close responses automatically.
443466 /// However, it never blocks on write.
467+ #[ inline]
444468 pub fn read < Stream > ( & mut self , stream : & mut Stream ) -> Result < Message >
445469 where
446470 Stream : Read + Write ,
471+ {
472+ self . read_inner ( stream, & FrameCodec :: read_in)
473+ }
474+
475+ /// Read a message from the provided stream, if possible.
476+ ///
477+ /// This function sends pong and close responses automatically.
478+ /// However, it never blocks on write.
479+ ///
480+ /// # Safety
481+ ///
482+ /// This function uses `FrameCodec::read_in_unsound` which can be unsound.
483+ /// It is up to the caller of this function to ensure that the underlying `Read` implementation does not
484+ /// attempt to read the uninitialized buffer and only writes to it.
485+ #[ inline]
486+ pub unsafe fn read_unsound < Stream > ( & mut self , stream : & mut Stream ) -> Result < Message >
487+ where
488+ Stream : Read + Write ,
489+ {
490+ self . read_inner ( stream, & |fc, s| unsafe { fc. read_in_unsound ( s) } )
491+ }
492+
493+ /// Read a message from the provided stream, if possible.
494+ ///
495+ /// This function sends pong and close responses automatically.
496+ /// However, it never blocks on write.
497+ fn read_inner < Stream , Reader > (
498+ & mut self ,
499+ stream : & mut Stream ,
500+ reader : & Reader ,
501+ ) -> Result < Message >
502+ where
503+ Stream : Read + Write ,
504+ Reader : Fn ( & mut FrameCodec , & mut Stream ) -> io:: Result < usize > ,
447505 {
448506 // Do not read from already closed connections.
449507 self . state . check_not_terminated ( ) ?;
@@ -466,7 +524,7 @@ impl WebSocketContext {
466524
467525 // If we get here, either write blocks or we have nothing to write.
468526 // Thus if read blocks, just let it return WouldBlock.
469- if let Some ( message) = self . read_message_frame ( stream) ? {
527+ if let Some ( message) = self . read_message_frame ( stream, reader ) ? {
470528 trace ! ( "Received message {message}" ) ;
471529 return Ok ( message) ;
472530 }
@@ -598,14 +656,23 @@ impl WebSocketContext {
598656 }
599657
600658 /// Try to decode one message frame. May return None.
601- fn read_message_frame ( & mut self , stream : & mut impl Read ) -> Result < Option < Message > > {
659+ fn read_message_frame < Stream , Reader > (
660+ & mut self ,
661+ stream : & mut Stream ,
662+ reader : & Reader ,
663+ ) -> Result < Option < Message > >
664+ where
665+ Stream : Read ,
666+ Reader : Fn ( & mut FrameCodec , & mut Stream ) -> io:: Result < usize > ,
667+ {
602668 if let Some ( frame) = self
603669 . frame
604670 . read_frame (
605671 stream,
606672 self . config . max_frame_size ,
607673 matches ! ( self . role, Role :: Server ) ,
608674 self . config . accept_unmasked_frames ,
675+ reader,
609676 )
610677 . check_connection_reset ( self . state ) ?
611678 {
0 commit comments