html => { ct => 'text/html' },
js => { ct => 'application/javascript' },
json => { ct => 'application/json' },
+ map => { ct => 'application/json' },
png => { ct => 'image/png' , nocomp => 1 },
ico => { ct => 'image/x-icon', nocomp => 1},
gif => { ct => 'image/gif', nocomp => 1},
epub => { ct => 'application/epub+zip', nocomp => 1},
mp3 => { ct => 'audio/mpeg', nocomp => 1},
oga => { ct => 'audio/ogg', nocomp => 1},
+ tgz => { ct => 'application/x-compressed-tar', nocomp => 1},
};
sub send_file_start {
my $remhost;
my $remport;
- my $max_payload_size = 65536;
+ my $max_payload_size = 128*1024;
my $binary;
if ($wsproto eq 'binary') {
$reqstate->{proxyhdl} = AnyEvent::Handle->new(
fh => $fh,
- rbuf_max => 64*1024,
- wbuf_max => 64*10*1024,
+ rbuf_max => $max_payload_size,
+ wbuf_max => $max_payload_size*5,
timeout => 5,
on_eof => sub {
my ($hdl) = @_;
my ($hdl) = @_;
my $len = length($hdl->{rbuf});
- my $data = substr($hdl->{rbuf}, 0, $len, '');
+ my $data = substr($hdl->{rbuf}, 0, $len > $max_payload_size ? $max_payload_size : $len, '');
my $string;
my $payload;
my $hdlreader = sub {
my ($hdl) = @_;
- my $len = length($hdl->{rbuf});
- return if $len < 2;
+ while (my $len = length($hdl->{rbuf})) {
+ return if $len < 2;
- my $hdr = unpack('C', substr($hdl->{rbuf}, 0, 1));
- my $opcode = $hdr & 0b00001111;
- my $fin = $hdr & 0b10000000;
+ my $hdr = unpack('C', substr($hdl->{rbuf}, 0, 1));
+ my $opcode = $hdr & 0b00001111;
+ my $fin = $hdr & 0b10000000;
- die "received fragmented websocket frame\n" if !$fin;
+ die "received fragmented websocket frame\n" if !$fin;
- my $rsv = $hdr & 0b01110000;
- die "received websocket frame with RSV flags\n" if $rsv;
+ my $rsv = $hdr & 0b01110000;
+ die "received websocket frame with RSV flags\n" if $rsv;
- my $payload_len = unpack 'C', substr($hdl->{rbuf}, 1, 1);
+ my $payload_len = unpack 'C', substr($hdl->{rbuf}, 1, 1);
- my $masked = $payload_len & 0b10000000;
- die "received unmasked websocket frame from client\n" if !$masked;
+ my $masked = $payload_len & 0b10000000;
+ die "received unmasked websocket frame from client\n" if !$masked;
- my $offset = 2;
- $payload_len = $payload_len & 0b01111111;
- if ($payload_len == 126) {
- return if $len < 4;
- $payload_len = unpack('n', substr($hdl->{rbuf}, $offset, 2));
- $offset += 2;
- } elsif ($payload_len == 127) {
- return if $len < 10;
- $payload_len = unpack('Q>', substr($hdl->{rbuf}, $offset, 8));
- $offset += 8;
- }
+ my $offset = 2;
+ $payload_len = $payload_len & 0b01111111;
+ if ($payload_len == 126) {
+ return if $len < 4;
+ $payload_len = unpack('n', substr($hdl->{rbuf}, $offset, 2));
+ $offset += 2;
+ } elsif ($payload_len == 127) {
+ return if $len < 10;
+ $payload_len = unpack('Q>', substr($hdl->{rbuf}, $offset, 8));
+ $offset += 8;
+ }
- die "received too large websocket frame (len = $payload_len)\n"
- if ($payload_len > $max_payload_size) || ($payload_len < 0);
+ die "received too large websocket frame (len = $payload_len)\n"
+ if ($payload_len > $max_payload_size) || ($payload_len < 0);
- return if $len < ($offset + 4 + $payload_len);
+ return if $len < ($offset + 4 + $payload_len);
- my $data = substr($hdl->{rbuf}, 0, $len, ''); # now consume data
+ my $data = substr($hdl->{rbuf}, 0, $offset + 4 + $payload_len, ''); # now consume data
- my @mask = (unpack('C', substr($data, $offset+0, 1)),
- unpack('C', substr($data, $offset+1, 1)),
- unpack('C', substr($data, $offset+2, 1)),
- unpack('C', substr($data, $offset+3, 1)));
+ my @mask = (unpack('C', substr($data, $offset+0, 1)),
+ unpack('C', substr($data, $offset+1, 1)),
+ unpack('C', substr($data, $offset+2, 1)),
+ unpack('C', substr($data, $offset+3, 1)));
- $offset += 4;
+ $offset += 4;
- my $payload = substr($data, $offset, $payload_len);
+ my $payload = substr($data, $offset, $payload_len);
- for (my $i = 0; $i < $payload_len; $i++) {
- my $d = unpack('C', substr($payload, $i, 1));
- my $n = $d ^ $mask[$i % 4];
- substr($payload, $i, 1, pack('C', $n));
- }
+ for (my $i = 0; $i < $payload_len; $i++) {
+ my $d = unpack('C', substr($payload, $i, 1));
+ my $n = $d ^ $mask[$i % 4];
+ substr($payload, $i, 1, pack('C', $n));
+ }
- $payload = decode_base64($payload) if !$binary;
+ $payload = decode_base64($payload) if !$binary;
- if ($opcode == 1 || $opcode == 2) {
- $reqstate->{proxyhdl}->push_write($payload) if $reqstate->{proxyhdl};
- } elsif ($opcode == 8) {
- print "websocket received close\n" if $self->{debug};
+ if ($opcode == 1 || $opcode == 2) {
+ $reqstate->{proxyhdl}->push_write($payload) if $reqstate->{proxyhdl};
+ } elsif ($opcode == 8) {
+ my $statuscode = unpack ("n", $payload);
+ print "websocket received close. status code: '$statuscode'\n" if $self->{debug};
if ($reqstate->{proxyhdl}) {
- $reqstate->{proxyhdl}->push_write($payload);
- $reqstate->{proxyhdl}->push_shutdown();
+ $reqstate->{proxyhdl}->push_shutdown();
+ }
+ $hdl->push_shutdown();
+ } else {
+ die "received unhandled websocket opcode $opcode\n";
}
- $hdl->push_shutdown();
- } else {
- die "received unhandled websocket opcode $opcode\n";
}
};
Net::SSLeay::ERR_clear_error();
# always delay unauthorized calls by 3 seconds
my $delay = 3;
- if (my $formatter = PVE::APIServer::Formatter::get_login_formatter($format)) {
+
+ if (ref($err) eq "PVE::Exception") {
+
+ $err->{code} ||= HTTP_INTERNAL_SERVER_ERROR,
+ my $resp = HTTP::Response->new($err->{code}, $err->{msg});
+ $self->response($reqstate, $resp, undef, 0, $delay);
+
+ } elsif (my $formatter = PVE::APIServer::Formatter::get_login_formatter($format)) {
my ($raw, $ct, $nocomp) =
$formatter->($path, $auth, $self->{formatter_config});
my $resp;