App-HTTP_Proxy_IMP
view release on metacpan or search on metacpan
lib/App/HTTP_Proxy_IMP/IMP.pm view on Meta::CPAN
sub _response_body_imp {
my ($self,$data,$changed,$args) = @_;
my ($callback,@cb_args) = @$args;
my $eof = _check_eof($self,1);
$callback->(@cb_args,$data,$eof) if $data ne '' || $eof;
}
sub _check_eof {
my ($self,$dir) = @_;
$DEBUG && $self->{request}->xdebug(
"check eof[%d] - eof=%d - %s - (pre)pass=%d/%d",
$dir,$self->{eof}[$dir], _show_buf($self,$dir),
$self->{prepass}[$dir],
$self->{pass}[$dir]
);
return $self->{eof}[$dir] # received eof
&& ! defined $self->{ibuf}[$dir][0][2] # no more data in buf
&& ( # (pre)pass til end ok
$self->{prepass}[$dir] == IMP_MAXOFFSET
|| $self->{pass}[$dir] == IMP_MAXOFFSET
);
}
sub _show_buf {
my ($self,$dir) = @_;
return join('|',
map { ($_->[2]||'none')."($_->[0],+".length($_->[1]).")" }
@{ $self->{ibuf}[$dir] }
);
}
############################################################################
# Websockets, TLS upgrades etc
# if not IMP the forwarding will be done inside this function, otherwise it
# will be done in _in_data_imp, which gets called by IMP callback
############################################################################
sub data {
my ($self,$dir,$data,@callback) = @_;
# forward to IMP analyzer
$self->{eof}[$dir] = 1 if $data eq '';
_imp_data($self,$dir,$data,0,IMP_DATA_HTTPRQ_CONTENT,
\&_data_imp,[$dir,@callback]);
}
sub _data_imp {
my ($self,$data,$changed,$args) = @_;
my ($dir,$callback,@cb_args) = @$args;
my $eof = $self->{eof}[$dir] && # got eof from server
! defined $self->{ibuf}[$dir][0][2]; # no more data in ibuf[server]
$callback->(@cb_args,$dir,$data,$eof) if $data ne '' || $eof;
}
############################################################################
# callback from IMP
# process return types and trigger type specific callbacks on (pre)pass/replace
############################################################################
sub _imp_callback {
my $self = shift;
my %fwd; # forwarded data, per dir
for my $rv (@_) {
# if the request got closed in between just return
my $request = $self->{request} or return;
my $rtype = shift(@$rv);
# deny further data
if ( $rtype == IMP_DENY ) {
my ($impdir,$msg) = @$rv;
$DEBUG && $request->xdebug("got deny($impdir) $msg");
return $request->deny($msg // 'closed by imp');
}
# log some data
if ( $rtype == IMP_LOG ) {
my ($impdir,$offset,$len,$level,$msg) = @$rv;
$DEBUG && $request->xdebug("got log($impdir,$level) $msg");
if ( my $sub = $self->{logsub} ) {
$sub->($level,$msg,$impdir,$offset,$len)
}
next;
}
# set accounting field
if ( $rtype == IMP_ACCTFIELD ) {
my ($key,$value) = @$rv;
$DEBUG && $request->xdebug("got acct $key => $value");
$request->{acct}{$key} = $value;
next;
}
# (pre)pass data up to offset
if ( $rtype ~~ [ IMP_PASS, IMP_PREPASS ]) {
my ($dir,$offset) = @$rv;
$DEBUG && $request->xdebug("got $rtype($dir) off=$offset "._show_buf($self,$dir));
if ( $rtype == IMP_PASS ) {
# ignore pass if it's not better than a previous pass
if ( $self->{pass}[$dir] == IMP_MAXOFFSET ) {
# there is no better thing than IMP_MAXOFFSET
next;
} elsif ( $offset == IMP_MAXOFFSET
or $offset > $self->{ibuf}[$dir][0][0] ) {
# we can pass new data
$self->{pass}[$dir] = $offset;
} else {
# offset is no better than previous pass
next;
}
} else { # IMP_PREPASS
# ignore prepass if it's not better than a previous pass
# and a previous prepaself->{ibuf}[1][0]
if ( $self->{pass}[$dir] == IMP_MAXOFFSET
( run in 2.195 seconds using v1.01-cache-2.11-cpan-d7f47b0818f )