char/avril
(wip) why'd you have to go and make things so complicaaaaated?
git clone https://git.t4t.associates/char/avril
f4a0f5b
main
1use fastwebsockets::{ OpCode , WebSocketError }; 2use tokio:: io::{ AsyncRead , AsyncReadExt }; 3 4use super :: Received ; 5 6const MAX_MESSAGE_SIZE : usize =16 * 1024 * 1024 ; 7 8pub ( super ) struct Reader < R > { 9pub ( super ) stream : R , 10message : Option < Received >, 11validated : usize , 12masked : bool , 13} 14 15impl < R : AsyncRead +Unpin > Reader < R > { 16pub ( super ) fn new ( stream : R , masked : bool ) ->Self { 17Self { 18 stream, 19message : None , 20validated : 0 , 21 masked, 22} 23} 24 25pub ( super ) async fn read ( & mut self ) ->Result < Received , WebSocketError > { 26loop { 27let mut header =[ 0 ; 2 ]; 28self . stream . read_exact ( & mut header). await ?; 29if header[ 0 ] & 0x70 !=0 { 30return Err ( WebSocketError :: ReservedBitsNotZero ); 31} 32if ( header[ 1 ] & 0x80 !=0 ) !=self . masked { 33return Err ( WebSocketError :: InvalidValue ); 34} 35let fin = header[ 0 ] & 0x80 !=0 ; 36let opcode =OpCode :: try_from ( header[ 0 ] & 0x0f ) ?; 37let control =matches! ( opcode, OpCode :: Close |OpCode :: Ping |OpCode :: Pong ); 38let length_code = header[ 1 ] & 0x7f ; 39if control{ 40if !fin{ 41return Err ( WebSocketError :: ControlFrameFragmented ); 42} 43if length_code >125 { 44return Err ( WebSocketError :: InvalidValue ); 45} 46} 47let length =match length_code{ 48126 =>{ 49let length = u64:: from ( self . stream . read_u16 (). await ?); 50if length <126 { 51return Err ( WebSocketError :: InvalidValue ); 52} 53 length 54} 55127 =>{ 56let length =self . stream . read_u64 (). await ?; 57if !( 65536 ..=i64:: MAX as u64 ). contains ( & length) { 58return Err ( WebSocketError :: InvalidValue ); 59} 60 length 61} 62 length => u64:: from ( length), 63}; 64let mut mask =[ 0 ; 4 ]; 65if self . masked { 66self . stream . read_exact ( & mut mask). await ?; 67} 68if control{ 69let mut payload =vec! [ 0 ; lengthas usize ]; 70self . stream . read_exact ( & mut payload). await ?; 71if self . masked { 72for ( index, byte) in payload. iter_mut (). enumerate () { 73* byte ^= mask[ index %4 ]; 74} 75} 76return Ok ( Received { opcode, payload}); 77} 78match opcode{ 79OpCode :: Text |OpCode :: Binary =>{ 80if self . message . is_some () { 81return Err ( WebSocketError :: InvalidFragment ); 82} 83self . message =Some ( Received { opcode, payload : Vec :: new () }); 84self . validated =0 ; 85} 86OpCode :: Continuation if self . message . is_none () =>{ 87return Err ( WebSocketError :: InvalidContinuationFrame ); 88} 89 _ =>{} 90} 91let message =self . message . as_mut (). unwrap (); 92let start = message. payload . len (); 93// Check the aggregate before allocating or waiting for the payload. 94if length >( MAX_MESSAGE_SIZE - start) as u64 { 95return Err ( WebSocketError :: FrameTooLarge ); 96} 97let read =( & mut self . stream ) 98. take ( length) 99. read_to_end ( & mut message. payload ) 100. await ?; 101if readas u64 != length{ 102return Err ( std:: io:: Error :: from ( std:: io:: ErrorKind :: UnexpectedEof ). into ()); 103} 104if self . masked { 105for ( index, byte) in message. payload [ start..]. iter_mut (). enumerate () { 106* byte ^= mask[ index %4 ]; 107} 108} 109if message. opcode ==OpCode :: Text { 110match std:: str:: from_utf8 ( & message. payload [ self . validated ..]) { 111Ok ( _) =>self . validated = message. payload . len (), 112Err ( error) if !fin && error. error_len (). is_none () =>{ 113// Recheck only the incomplete suffix when the next fragment arrives. 114self . validated += error. valid_up_to (); 115} 116Err ( _) =>return Err ( WebSocketError :: InvalidUTF8 ), 117} 118} 119if fin{ 120return Ok ( self . message . take (). unwrap ()); 121} 122} 123} 124} 125 126# [ cfg ( test )] 127mod tests{ 128use super :: * ; 129 130# [ tokio :: test ] 131async fn truncated_large_frame_is_unexpected_eof () { 132let mut frame =vec! [ 0x82 , 0xff ]; 133 frame. extend_from_slice ( & ( MAX_MESSAGE_SIZE as u64 ). to_be_bytes ()); 134 frame. extend_from_slice ( & [ 1 , 2 , 3 , 4 ]); 135 frame. extend_from_slice ( & [ 5 , 6 , 7 ]); 136let mut reader =Reader :: new ( frame. as_slice (), true ); 137assert! ( matches! ( 138 reader. read (). await , 139Err ( WebSocketError :: IoError ( error)) if error. kind () == std:: io:: ErrorKind :: UnexpectedEof 140)); 141} 142}