@@ -23,7 +23,7 @@ use self::{
2323} ;
2424use crate :: {
2525 error:: { Error , ProtocolError , Result } ,
26- extensions:: { self , DeflateContext } ,
26+ extensions:: { self , Extensions } ,
2727 util:: NonBlockingResult ,
2828} ;
2929
@@ -81,15 +81,14 @@ impl WebSocketConfig {
8181 self . compression . map ( |c| c. generate_offer ( ) )
8282 }
8383
84- // TODO Replace `DeflateContext` with something more general
85- // This can be used with `WebSocket::from_raw_socket_with_compression` for integration.
86- /// Returns negotiation response based on offers and `DeflateContext` to manage per message compression.
84+ // This can be used with `WebSocket::from_raw_socket_with_extensions` for integration.
85+ /// Returns negotiation response based on offers and `Extensions` to manage extensions.
8786 pub fn accept_offers < ' a > (
8887 & ' a self ,
8988 extensions : impl Iterator < Item = & ' a HeaderValue > ,
90- ) -> Option < ( HeaderValue , DeflateContext ) > {
89+ ) -> Option < ( HeaderValue , Extensions ) > {
9190 if let Some ( compression) = & self . compression {
92- let extensions = crate :: extensions:: iter_all ( extensions) ;
91+ let extensions = extensions:: iter_all ( extensions) ;
9392 let offers =
9493 extensions. filter_map (
9594 |( k, v) | {
@@ -100,7 +99,12 @@ impl WebSocketConfig {
10099 }
101100 } ,
102101 ) ;
103- compression. accept_offer ( offers)
102+
103+ // To support more extensions, store extension context in `Extensions` and
104+ // concatenate negotiation responses from each extension.
105+ compression
106+ . accept_offer ( offers)
107+ . map ( |( agreed, pmce) | ( agreed, Extensions { compression : Some ( pmce) } ) )
104108 } else {
105109 None
106110 }
@@ -130,14 +134,14 @@ impl<Stream> WebSocket<Stream> {
130134 }
131135
132136 /// Convert a raw socket into a WebSocket without performing a handshake.
133- pub fn from_raw_socket_with_compression (
137+ pub fn from_raw_socket_with_extensions (
134138 stream : Stream ,
135139 role : Role ,
136140 config : Option < WebSocketConfig > ,
137- pmce : Option < DeflateContext > ,
141+ extensions : Option < Extensions > ,
138142 ) -> Self {
139143 let mut context = WebSocketContext :: new ( role, config) ;
140- context. pmce = pmce ;
144+ context. extensions = extensions ;
141145 WebSocket { socket : stream, context }
142146 }
143147
@@ -158,17 +162,17 @@ impl<Stream> WebSocket<Stream> {
158162 }
159163 }
160164
161- pub ( crate ) fn from_partially_read_with_compression (
165+ pub ( crate ) fn from_partially_read_with_extensions (
162166 stream : Stream ,
163167 part : Vec < u8 > ,
164168 role : Role ,
165169 config : Option < WebSocketConfig > ,
166- pmce : Option < DeflateContext > ,
170+ extensions : Option < Extensions > ,
167171 ) -> Self {
168172 WebSocket {
169173 socket : stream,
170- context : WebSocketContext :: from_partially_read_with_compression (
171- part, role, config, pmce ,
174+ context : WebSocketContext :: from_partially_read_with_extensions (
175+ part, role, config, extensions ,
172176 ) ,
173177 }
174178 }
@@ -306,8 +310,8 @@ pub struct WebSocketContext {
306310 pong : Option < Frame > ,
307311 /// The configuration for the websocket session.
308312 config : WebSocketConfig ,
309- /// Per-Message Compression Extension. Only deflate is supported at the moment .
310- pub ( crate ) pmce : Option < extensions :: DeflateContext > ,
313+ // Container for extensions .
314+ pub ( crate ) extensions : Option < Extensions > ,
311315}
312316
313317impl WebSocketContext {
@@ -321,7 +325,7 @@ impl WebSocketContext {
321325 send_queue : VecDeque :: new ( ) ,
322326 pong : None ,
323327 config : config. unwrap_or_else ( WebSocketConfig :: default) ,
324- pmce : None ,
328+ extensions : None ,
325329 }
326330 }
327331
@@ -333,15 +337,15 @@ impl WebSocketContext {
333337 }
334338 }
335339
336- pub ( crate ) fn from_partially_read_with_compression (
340+ pub ( crate ) fn from_partially_read_with_extensions (
337341 part : Vec < u8 > ,
338342 role : Role ,
339343 config : Option < WebSocketConfig > ,
340- pmce : Option < DeflateContext > ,
344+ extensions : Option < Extensions > ,
341345 ) -> Self {
342346 WebSocketContext {
343347 frame : FrameCodec :: from_partially_read ( part) ,
344- pmce ,
348+ extensions ,
345349 ..WebSocketContext :: new ( role, config)
346350 }
347351 }
@@ -447,11 +451,12 @@ impl WebSocketContext {
447451 debug_assert ! ( matches!( opdata, OpData :: Text | OpData :: Binary ) , "Invalid data frame kind" ) ;
448452 let opcode = OpCode :: Data ( opdata) ;
449453 let is_final = true ;
450- let frame = if let Some ( pmce) = self . pmce . as_mut ( ) {
451- Frame :: compressed_message ( pmce. compress ( & data) ?, opcode, is_final)
452- } else {
453- Frame :: message ( data, opcode, is_final)
454- } ;
454+ let frame =
455+ if let Some ( pmce) = self . extensions . as_mut ( ) . and_then ( |e| e. compression . as_mut ( ) ) {
456+ Frame :: compressed_message ( pmce. compress ( & data) ?, opcode, is_final)
457+ } else {
458+ Frame :: message ( data, opcode, is_final)
459+ } ;
455460 Ok ( frame)
456461 }
457462
@@ -533,7 +538,7 @@ impl WebSocketContext {
533538 // Connection_.
534539 let is_compressed = {
535540 let hdr = frame. header ( ) ;
536- if ( hdr. rsv1 && self . pmce . is_none ( ) ) || hdr. rsv2 || hdr. rsv3 {
541+ if ( hdr. rsv1 && ! self . has_compression ( ) ) || hdr. rsv2 || hdr. rsv3 {
537542 return Err ( Error :: Protocol ( ProtocolError :: NonZeroReservedBits ) ) ;
538543 }
539544
@@ -606,8 +611,9 @@ impl WebSocketContext {
606611 if let Some ( ref mut msg) = self . incomplete {
607612 let data = if msg. compressed ( ) {
608613 // `msg.compressed` is only set when compression is enabled so it's safe to unwrap
609- self . pmce
614+ self . extensions
610615 . as_mut ( )
616+ . and_then ( |x| x. compression . as_mut ( ) )
611617 . unwrap ( )
612618 . decompress ( frame. into_data ( ) , fin) ?
613619 } else {
@@ -637,8 +643,9 @@ impl WebSocketContext {
637643 } ;
638644 let mut m = IncompleteMessage :: new ( message_type, is_compressed) ;
639645 let data = if is_compressed {
640- self . pmce
646+ self . extensions
641647 . as_mut ( )
648+ . and_then ( |x| x. compression . as_mut ( ) )
642649 . unwrap ( )
643650 . decompress ( frame. into_data ( ) , fin) ?
644651 } else {
@@ -729,6 +736,10 @@ impl WebSocketContext {
729736 trace ! ( "Sending frame: {:?}" , frame) ;
730737 self . frame . write_frame ( stream, frame) . check_connection_reset ( self . state )
731738 }
739+
740+ fn has_compression ( & self ) -> bool {
741+ self . extensions . as_ref ( ) . and_then ( |c| c. compression . as_ref ( ) ) . is_some ( )
742+ }
732743}
733744
734745/// The current connection state.
0 commit comments