File manager - Edit - /usr/local/cpanel/3rdparty/perl/542/cpanel-lib/Net/WebSocket/PMCE/deflate/Data.pm
Back
package Net::WebSocket::PMCE::deflate::Data; use strict; use warnings; use parent qw( Net::WebSocket::PMCE::Data ); use Net::WebSocket::FrameTypeName (); use Net::WebSocket::Message (); use Net::WebSocket::PMCE::deflate::Constants (); use constant { _ZLIB_SYNC_TAIL => "\0\0\xff\xff", _DEBUG => 0, }; =encoding utf-8 =head2 I<CLASS>->new( %OPTS ) %OPTS is: =over =item C<deflate_max_window_bits> - optional; the number of window bits to use for compressing messages. This should correspond with the local endpoint’s behavior; i.e., for a server, this should match the C<server_max_window_bits> extension parameter in the WebSocket handshake. =item C<inflate_max_window_bits> - optional; the number of window bits to use for decompressing messages. This should correspond with the remote peer’s behavior; i.e., for a server, this should match the C<client_max_window_bits> extension parameter in the WebSocket handshake. =item C<deflate_no_context_takeover> - corresponds to either the C<client_no_context_takeover> or C<server_no_context_takeover> parameter, to match the local endpoint’s role. When this flag is set, the object will do a full flush at the end of each C<compress()> call. =back =cut sub new { my ($class, %opts) = @_; #Validate deflate_max_window_bits/inflate_max_window_bits? my $compress_func = '_compress_'; $compress_func .= $opts{'deflate_no_context_takeover'} ? 'full' : 'sync'; $compress_func .= '_flush_chomp'; $opts{'final_frame_compress_func'} = $compress_func; return bless \%opts, $class; } #---------------------------------------------------------------------- =head2 $msg = I<OBJ>->create_message( FRAME_TYPE, PAYLOAD ) Creates an unfragmented, compressed message. The message will be an instance of L<Net::WebSocket::Message>. FRAME_TYPE can be either C<text> or C<binary> (for Net::WebSocket’s default frame classes) or full package names (e.g., to use a custom frame class). This method cannot be called while a streamer object has yet to create its final frame. B<NOTE:> This function alters PAYLOAD. =cut sub create_message { my ($self, $frame_type) = @_; #$_[2] = payload die "A streamer is active!" if $self->{'_streamer_mode'}; my $compress_func = $self->{'final_frame_compress_func'}; my $payload_sr = \($self->$compress_func( $_[2] )); my $frame_class = Net::WebSocket::FrameTypeName::get_module($frame_type); return Net::WebSocket::Message->new( $frame_class->new( payload => $payload_sr, rsv => $self->INITIAL_FRAME_RSV(), $self->FRAME_MASK_ARGS(), ), ); } #---------------------------------------------------------------------- =head2 $msg = I<OBJ>->create_streamer( FRAME_TYPE ) FRAME_TYPE can be either C<text> or C<binary> (for Net::WebSocket’s default frame classes) or full package names (e.g., to use a custom frame class). Returns an instance of L<Net::WebSocket::PMCE::deflate::Data::Streamer> based on this object. =cut sub create_streamer { my ($self, $frame_type) = @_; $self->{'_streamer_mode'} = 1; require Net::WebSocket::PMCE::deflate::Data::Streamer; my $frame_class = Net::WebSocket::FrameTypeName::get_module($frame_type); return Net::WebSocket::PMCE::deflate::Data::Streamer->new($self, $frame_class); } #---------------------------------------------------------------------- =head2 $decompressed = I<OBJ>->decompress( COMPRESSED_PAYLOAD ) Decompresses the given string and returns the result. B<NOTE:> This function alters COMPRESSED_PAYLOAD, such that it’s probably not useful afterward. =cut #cf. RFC 7692, 7.2.2 sub decompress { my ($self) = @_; #$_[1] = payload $self->{'i'} ||= $self->_create_inflate_obj(); _DEBUG && _debug(sprintf "inflating: %v.02x\n", $_[1]); $_[1] .= _ZLIB_SYNC_TAIL; my $status = $self->{'i'}->inflate($_[1], my $v); die $status if $status != Compress::Raw::Zlib::Z_OK(); _DEBUG && _debug(sprintf "inflate output: [%v.02x]\n", $v); return $v; } #---------------------------------------------------------------------- my $_payload_sr; #cf. RFC 7692, 7.2.1 #Use for non-final fragments. sub _compress_non_final_fragment { $_[0]->{'d'} ||= $_[0]->_create_deflate_obj(); return $_[0]->_compress( $_[1] ); } #Preserves sliding window to the next message. #Use for final fragments when deflate_no_context_takeover is OFF sub _compress_sync_flush_chomp { $_[0]->{'d'} ||= $_[0]->_create_deflate_obj(); return _chomp_0000ffff_or_die( $_[0]->_compress( $_[1], Compress::Raw::Zlib::Z_SYNC_FLUSH() ) ); } #Flushes the sliding window. #Use for final fragments when deflate_no_context_takeover is ON sub _compress_full_flush_chomp { $_[0]->{'d'} ||= $_[0]->_create_deflate_obj(); return _chomp_0000ffff_or_die( $_[0]->_compress( $_[1], Compress::Raw::Zlib::Z_FULL_FLUSH() ) ); } sub _chomp_0000ffff_or_die { if ( rindex( $_[0], _ZLIB_SYNC_TAIL ) == length($_[0]) - 4 ) { substr($_[0], -4) = q<>; } else { die sprintf('deflate/flush didn’t end with expected SYNC tail (00.00.ff.ff): %v.02x', $_[0]); } return $_[0]; } sub _compress { my ($self) = @_; # $_[1] = payload; $_[2] = flush method $_payload_sr = \$_[1]; _DEBUG && _debug(sprintf "to deflate: [%v.02x]", $$_payload_sr); my $out; my $dstatus = $self->{'d'}->deflate( $$_payload_sr, $out ); die "deflate: $dstatus" if $dstatus != Compress::Raw::Zlib::Z_OK(); _DEBUG && _debug(sprintf "post-deflate output: [%v.02x]", $out); if ($_[2]) { $dstatus = $self->{'d'}->flush($out, $_[2]); die "deflate flush: $dstatus" if $dstatus != Compress::Raw::Zlib::Z_OK(); undef $self->{'_streamer_mode'}; _DEBUG && _debug(sprintf "post-flush output: [%v.02x]", $out); } #NB: The RFC directs at this point that: # #If the resulting data does not end with an empty DEFLATE block #with no compression (the "BTYPE" bits are set to 00), append an #empty DEFLATE block with no compression to the tail end. # #… but I don’t know the protocol well enough to detect that?? # #NB: #> perl -MCompress::Raw::Zlib -e' my $deflate = Compress::Raw::Zlib::Deflate->new( -WindowBits => -8, -AppendOutput => 1, -Level => Compress::Raw::Zlib::Z_NO_COMPRESSION ); $deflate->deflate( "", my $out ); $deflate->flush( $out, Compress::Raw::Zlib::Z_SYNC_FLUSH()); print $out' | xxd #00000000: 0000 00ff ff ..... # if ( $_[2] == Compress::Raw::Zlib::Z_FULL_FLUSH() ) { # if ( substr($out, -4) eq _ZLIB_SYNC_TAIL ) { # substr($out, -4) = q<>; # } # else { # die sprintf('deflate/flush didn’t end with expected SYNC tail (00.00.ff.ff): %v.02x', $out); # } # } return $out; } #---------------------------------------------------------------------- sub _create_inflate_obj { my ($self) = @_; my $window_bits = $self->{'inflate_max_window_bits'} || ( Net::WebSocket::PMCE::deflate::Constants::VALID_MAX_WINDOW_BITS() )[-1]; require Compress::Raw::Zlib; my ($inflate, $istatus) = Compress::Raw::Zlib::Inflate->new( -WindowBits => -$window_bits, -AppendOutput => 1, ); die "Inflate: $istatus" if $istatus != Compress::Raw::Zlib::Z_OK(); return $inflate; } sub _create_deflate_obj { my ($self) = @_; my $window_bits = $self->{'deflate_max_window_bits'} || ( Net::WebSocket::PMCE::deflate::Constants::VALID_MAX_WINDOW_BITS() )[-1]; require Compress::Raw::Zlib; my ($deflate, $dstatus) = Compress::Raw::Zlib::Deflate->new( -WindowBits => -$window_bits, -AppendOutput => 1, ); die "Deflate: $dstatus" if $dstatus != Compress::Raw::Zlib::Z_OK(); return $deflate; } sub _debug { print STDERR "$_[0]$/"; } 1;
| ver. 1.4 |
Github
|
.
| PHP 8.1.34 | Generation time: 0.04 |
proxy
|
phpinfo
|
Settings