if ($index > $max_iter) {
debug "$max_iter iteration reached...going to next task",$sck;
last;
}
$byte_read = sysread $sck, $buffer, $max_buffering;
if (defined $byte_read) {
if ($byte_read == 0) {
# Server just closed the connection. This may be the result of 2 options:
# 1. Message has been transmitted fully, or
# 2. Some part of the message has been transmitted.
# For now, let's assume that the server transmission is reliable (option 1)
debug "Server closed the connection (end of response message)",$sck;
last;
}
debug "Server->Proxy ($byte_read bytes)",$sck;
$st{$st{$sck}{ch}}{resp} .= $buffer;
$st{$st{$sck}{ch}}{resp_len} += $byte_read;
}
elsif ($! == EAGAIN()) { #socket buffer empty
debug "Server is too slow, skipping... (non-blocking)",$sck;
last;
}
else { # if anything else, cleanup server connection, tell client about it, and cleanup client too
debug "Server connection error",$sck;
quickresp 502,"Connection to server broke when reading", $sck;
serverclose $sck;
next READ_FHS;
}
}
$st{$sck}{mark} ||= 1;
if ($st{$sck}{mark} == 1) {
debug "Parsing header...", $sck;
while (1) { # skip crlf before start-line
unless ($st{$st{$sck}{ch}}{resp} =~ s/^([^\r]*\r\n)//) {
clientclose $sck if $byte_read == 0;
next READ_FHS;
}
$buffer = $1;
last if $buffer ne "\r\n";
}
$st{$st{$sck}{ch}}{resp_line} = $buffer;
$st{$sck}{mark} = 2;
}
if ($st{$sck}{mark} == 2) {
debug "Parsing header...", $sck;
while (1) { # loop for picking each field-line
unless ($st{$st{$sck}{ch}}{resp} =~ s/^([^\r]*\r\n)//) {
clientclose $sck if $byte_read == 0;
next READ_FHS;
}
$buffer = $1;
last if $buffer eq "\r\n";
next if $buffer =~ /^Connection:/im; # Remove connection field
# chunked to normal rule
if ($buffer =~ /^Transfer-Encoding:\s*chunked/im and
$st{$st{$sck}{ch}}{versi} ne "HTTP/1.1") {
$st{$sck}{chunked} = "";
next;
}
$st{$st{$sck}{ch}}{resp_fields} .= $buffer;
}
# add new response fields
$st{$st{$sck}{ch}}{resp_fields} .= "Via: $viastring\r\n";
$st{$st{$sck}{ch}}{resp_fields} .= "Connection: close\r\n"
if ($st{$st{$sck}{ch}}{persist} == 0);
if (!defined $st{$sck}{chunked}) {
$st{$st{$sck}{ch}}{resp} = join "", $st{$st{$sck}{ch}}{resp_line},
$st{$st{$sck}{ch}}{resp_fields}, "\r\n", $st{$st{$sck}{ch}}{resp};
$st{$st{$sck}{ch}}{resp_len} = length $st{$st{$sck}{ch}}{resp};
}
else {
debug "Response body is chunked, disabling fast-passing....decoding... ", $sck;
}
$st{$sck}{mark} = 3;
}
if ($st{$sck}{mark} == 3) { # fase 3 is action after parsing the header
if (defined $st{$sck}{chunked}) { #chunked to body rule
unless (defined($byte_read) and $byte_read == 0) { # FORCE GETTING ALL DATA FIRST
debug "Partial body detected...getting more to select",$sck;
next READ_FHS;
}
if ($st{$st{$sck}{ch}}{resp} =~ s/^\W*(\w*)\W*\r\n//) {
$st{$sck}{chunked} = hex $1;
}
else { #something wrong with the chunked body
debug "Error decoding chunked...closing connection",$sck;
quickresp 502,"Error decoding chunked body", $sck;
serverclose $sck;
next READ_FHS;
}
while ($st{$sck}{chunked} > 0) {
$st{$sck}{chunked_buff} .= substr( $st{$st{$sck}{ch}}{resp}, 0, $st{$sck}{chunked});
$st{$st{$sck}{ch}}{resp} = substr( $st{$st{$sck}{ch}}{resp}, $st{$sck}{chunked}+2);
if ($st{$st{$sck}{ch}}{resp} =~ s/^\W*(\w*)\W*\r\n//) {
$st{$sck}{chunked} = hex $1;
}
else { #something wrong with the chunked body
debug "Error decoding chunked",$sck;
=4= |