root/trunk/lib/Perlbal/ChunkedUploadState.pm

Revision 666, 1.7 kB (checked in by bradfitz, 3 years ago)

Merging in Jonathan's chunked-put branch:

+ -- make ClientHTTP (webserver mode) support transfer-encoding
+ "chunked" PUTs, when PUTs are already enabled. useful
+ for things like MogileFS, where writing clients may not
+ know the final length ahead of time to predeclare in the
+ Content-Length request header.

Line 
1package Perlbal::ChunkedUploadState;
2use strict;
3
4sub new {
5    my ($pkg, %args) = @_;
6    my $self = bless {
7        'buf' => '',
8        'bytes_remain' => 0,  # remaining in chunk (ignoring final 2 byte CRLF)
9    }, $pkg;
10    foreach my $k (qw(on_new_chunk on_disconnect on_zero_chunk)) {
11        $self->{$k} = (delete $args{$k}) || sub {};
12    }
13    die "bogus args" if %args;
14    return $self;
15}
16
17sub on_readable {
18    my ($self, $ds) = @_;
19    my $rbuf = $ds->read(131072);
20    unless (defined $rbuf) {
21        $self->{on_disconnect}->();
22        return;
23    }
24
25    $self->{buf} .= $$rbuf;
26
27    while ($self->drive_machine) {}
28}
29
30# returns 1 if progress was made parsing buffer
31sub drive_machine {
32    my $self = shift;
33
34    my $buflen = length($self->{buf});
35    return 0 unless $buflen;
36
37    if (my $br = $self->{bytes_remain}) {
38        my $extract = $buflen > $br ? $br : $buflen;
39        my $ch = substr($self->{buf}, 0, $extract, '');
40        $self->{bytes_remain} -= $extract;
41        die "assert" if $self->{bytes_remain} < 0;
42        $self->{on_new_chunk}->(\$ch);
43        return 1;
44    }
45
46    return 0 unless $self->{buf} =~ s/^(?:\r\n)?([0-9a-fA-F]+)(?:;.*)?\r\n//;
47    $self->{bytes_remain} = hex($1);
48
49    if ($self->{bytes_remain} == 0) {
50        # FIXME: new state machine state for trailer parsing/discarding.
51        # (before we do on_zero_chunk).  for now, though, just assume
52        # no trailers and throw away the extra post-trailer \r\n that
53        # is probably in this packet.  hacky.
54        $self->{buf} =~ s/^\r\n//;
55        $self->{hit_zero} = 1;
56        $self->{on_zero_chunk}->();
57        return 0;
58    }
59    return 1;
60}
61
62sub hit_zero_chunk { $_[0]{hit_zero} }
63
641;
Note: See TracBrowser for help on using the browser.