package Net::WebSocket::PMCE::deflate::Data::Streamer; use strict; use warnings; =encoding utf-8 =head1 NAME Net::WebSocket::PMCE::deflate::Data::Streamer =head1 SYNOPSIS my $streamer = $deflate_data->create_streamer( $frame_class ); #These frames form a single compressed message in three #fragments whose content is “onetwothree”. my @frames = ( $streamer->create_chunk('one'), $streamer->create_chunk('two'), $streamer->create_final('three'), ); =head1 DESCRIPTION This class implements fragmentation for the permessage-deflate WebSocket extension. It allows you to send a single message in arbitrarily many parts. The class is not instantiated directly, but instances are returned as the result of L’s C method. Strictly speaking, this is a base class; the C<::Client> and C<::Server> subclasses implement a bit of logic specific to either endpoint type. The C and C methods follow the same pattern as L. =cut use Module::Runtime (); use Net::WebSocket::Frame::continuation (); =head1 METHODS =cut sub new { my ($class, $data_obj, $frame_class) = @_; Module::Runtime::require_module($frame_class) if !$frame_class->can('new'); my $self = { _data_obj => $data_obj, _frame_class => $frame_class, }; return bless $self, $class; } my ($_COMPRESS_FUNC, $_FIN); =head2 I->create_chunk( OCTET_STRING ) Compresses OCTET_STRING. The compressor doesn’t necessarily produce output from this, however. If the compressor does produce output, then this method returns a frame object (an instance of either the streamer’s assigned frame class or L); otherwise, undef is returned. =cut sub create_chunk { $_COMPRESS_FUNC = '_compress_non_final_fragment'; $_FIN = 0; goto &_create; } =head2 I->create_final( OCTET_STRING ) Compresses OCTET_STRING and flushes the compressor. The output matches that of C except that the output is always a frame object. The output of this method will complete the message. =cut sub create_final { $_COMPRESS_FUNC = $_[0]->{'_data_obj'}{'final_frame_compress_func'}; $_FIN = 1; goto &_create; } sub _create { my ($self) = @_; my $data_obj = $self->{'_data_obj'}; my $payload_sr = \($data_obj->$_COMPRESS_FUNC( $_[1] )); return undef if !length $$payload_sr; my $class = $self->{'_frames_count'} ? 'Net::WebSocket::Frame::continuation' : $self->{'_frame_class'}; my $rsv = $self->{'_frames_count'} ? 0 : $data_obj->INITIAL_FRAME_RSV(); $self->{'_frames_count'}++; return $class->new( payload => $payload_sr, rsv => $rsv, $data_obj->FRAME_MASK_ARGS(), ); } 1;