Mercurial > hg > nginx-tests
comparison lib/Test/Nginx/HTTP2.pm @ 1622:5b3d33b5556c
Tests: converted HTTP2 raw_read() and raw_write() to class methods.
author | Sergey Kandaurov <pluknet@nginx.com> |
---|---|
date | Tue, 24 Nov 2020 01:23:00 +0000 |
parents | 4e48bf51714f |
children | 3fe652bc9dae |
comparison
equal
deleted
inserted
replaced
1621:fd440d324700 | 1622:5b3d33b5556c |
---|---|
37 | 37 |
38 my $s = $extra{socket} || new_socket($port, %extra); | 38 my $s = $extra{socket} || new_socket($port, %extra); |
39 my $preface = defined $extra{preface} ? $extra{preface} | 39 my $preface = defined $extra{preface} ? $extra{preface} |
40 : 'PRI * HTTP/2.0' . CRLF . CRLF . 'SM' . CRLF . CRLF; | 40 : 'PRI * HTTP/2.0' . CRLF . CRLF . 'SM' . CRLF . CRLF; |
41 | 41 |
42 if ($extra{proxy}) { | |
43 raw_write($s, $extra{proxy}); | |
44 } | |
45 | |
46 # preface | |
47 | |
48 raw_write($s, $preface); | |
49 | |
50 my $self = bless { | 42 my $self = bless { |
51 socket => $s, last_stream => -1, | 43 socket => $s, last_stream => -1, |
52 dynamic_encode => [ static_table() ], | 44 dynamic_encode => [ static_table() ], |
53 dynamic_decode => [ static_table() ], | 45 dynamic_decode => [ static_table() ], |
54 static_table_size => scalar @{[static_table()]}, | 46 static_table_size => scalar @{[static_table()]}, |
55 iws => 65535, conn_window => 65535, streams => {} | 47 iws => 65535, conn_window => 65535, streams => {} |
56 }, $class; | 48 }, $class; |
57 | 49 |
50 if ($extra{proxy}) { | |
51 $self->raw_write($extra{proxy}); | |
52 } | |
53 | |
54 # preface | |
55 | |
56 $self->raw_write($preface); | |
57 | |
58 return $self if $extra{pure}; | 58 return $self if $extra{pure}; |
59 | 59 |
60 # update windows, if any | 60 # update windows, if any |
61 | 61 |
62 my $frames = $self->read(all => [ | 62 my $frames = $self->read(all => [ |
74 } | 74 } |
75 | 75 |
76 sub h2_ping { | 76 sub h2_ping { |
77 my ($self, $payload) = @_; | 77 my ($self, $payload) = @_; |
78 | 78 |
79 raw_write($self->{socket}, pack("x2C2x5a8", 8, 0x6, $payload)); | 79 $self->raw_write(pack("x2C2x5a8", 8, 0x6, $payload)); |
80 } | 80 } |
81 | 81 |
82 sub h2_rst { | 82 sub h2_rst { |
83 my ($self, $stream, $error) = @_; | 83 my ($self, $stream, $error) = @_; |
84 | 84 |
85 raw_write($self->{socket}, pack("x2C2xNN", 4, 0x3, $stream, $error)); | 85 $self->raw_write(pack("x2C2xNN", 4, 0x3, $stream, $error)); |
86 } | 86 } |
87 | 87 |
88 sub h2_goaway { | 88 sub h2_goaway { |
89 my ($self, $stream, $lstream, $err, $debug, %extra) = @_; | 89 my ($self, $stream, $lstream, $err, $debug, %extra) = @_; |
90 $debug = '' unless defined $debug; | 90 $debug = '' unless defined $debug; |
91 my $len = defined $extra{len} ? $extra{len} : 8 + length($debug); | 91 my $len = defined $extra{len} ? $extra{len} : 8 + length($debug); |
92 my $buf = pack("x2C2xN3A*", $len, 0x7, $stream, $lstream, $err, $debug); | 92 my $buf = pack("x2C2xN3A*", $len, 0x7, $stream, $lstream, $err, $debug); |
93 | 93 |
94 my @bufs = map { | 94 my @bufs = map { |
95 raw_write($self->{socket}, substr $buf, 0, $_, ""); | 95 $self->raw_write(substr $buf, 0, $_, ""); |
96 select undef, undef, undef, 0.2; | 96 select undef, undef, undef, 0.2; |
97 } @{$extra{split}}; | 97 } @{$extra{split}}; |
98 | 98 |
99 raw_write($self->{socket}, $buf); | 99 $self->raw_write($buf); |
100 } | 100 } |
101 | 101 |
102 sub h2_priority { | 102 sub h2_priority { |
103 my ($self, $w, $stream, $dep, %extra) = @_; | 103 my ($self, $w, $stream, $dep, %extra) = @_; |
104 | 104 |
105 $stream = 0 unless defined $stream; | 105 $stream = 0 unless defined $stream; |
106 $dep = 0 unless defined $dep; | 106 $dep = 0 unless defined $dep; |
107 $dep |= $extra{excl} << 31 if exists $extra{excl}; | 107 $dep |= $extra{excl} << 31 if exists $extra{excl}; |
108 raw_write($self->{socket}, pack("x2C2xNNC", 5, 0x2, $stream, $dep, $w)); | 108 $self->raw_write(pack("x2C2xNNC", 5, 0x2, $stream, $dep, $w)); |
109 } | 109 } |
110 | 110 |
111 sub h2_window { | 111 sub h2_window { |
112 my ($self, $win, $stream) = @_; | 112 my ($self, $win, $stream) = @_; |
113 | 113 |
114 $stream = 0 unless defined $stream; | 114 $stream = 0 unless defined $stream; |
115 raw_write($self->{socket}, pack("x2C2xNN", 4, 0x8, $stream, $win)); | 115 $self->raw_write(pack("x2C2xNN", 4, 0x8, $stream, $win)); |
116 } | 116 } |
117 | 117 |
118 sub h2_settings { | 118 sub h2_settings { |
119 my ($self, $ack, @pairs) = @_; | 119 my ($self, $ack, @pairs) = @_; |
120 | 120 |
121 my $len = 6 * @pairs / 2; | 121 my $len = 6 * @pairs / 2; |
122 my $buf = pack_length($len) . pack "CCx4", 0x4, $ack ? 0x1 : 0x0; | 122 my $buf = pack_length($len) . pack "CCx4", 0x4, $ack ? 0x1 : 0x0; |
123 $buf .= pack "nN", splice @pairs, 0, 2 while @pairs; | 123 $buf .= pack "nN", splice @pairs, 0, 2 while @pairs; |
124 raw_write($self->{socket}, $buf); | 124 $self->raw_write($buf); |
125 } | 125 } |
126 | 126 |
127 sub h2_unknown { | 127 sub h2_unknown { |
128 my ($self, $payload) = @_; | 128 my ($self, $payload) = @_; |
129 | 129 |
130 my $buf = pack_length(length($payload)) . pack("Cx5a*", 0xa, $payload); | 130 my $buf = pack_length(length($payload)) . pack("Cx5a*", 0xa, $payload); |
131 raw_write($self->{socket}, $buf); | 131 $self->raw_write($buf); |
132 } | 132 } |
133 | 133 |
134 sub h2_continue { | 134 sub h2_continue { |
135 my ($ctx, $stream, $uri) = @_; | 135 my ($ctx, $stream, $uri) = @_; |
136 | 136 |
165 | 165 |
166 $buf .= pack_body($self, $body, 0x1, $extra) if defined $body; | 166 $buf .= pack_body($self, $body, 0x1, $extra) if defined $body; |
167 | 167 |
168 $split = ref $extra->{split} && $extra->{split} || []; | 168 $split = ref $extra->{split} && $extra->{split} || []; |
169 for (@$split) { | 169 for (@$split) { |
170 raw_write($self->{socket}, substr($buf, 0, $_, "")); | 170 $self->raw_write(substr($buf, 0, $_, "")); |
171 return if $extra->{abort}; | 171 return if $extra->{abort}; |
172 select undef, undef, undef, ($extra->{split_delay} || 0.2); | 172 select undef, undef, undef, ($extra->{split_delay} || 0.2); |
173 } | 173 } |
174 | 174 |
175 raw_write($self->{socket}, $buf); | 175 $self->raw_write($buf); |
176 } | 176 } |
177 | 177 |
178 sub new_stream { | 178 sub new_stream { |
179 my ($self, $uri, $stream) = @_; | 179 my ($self, $uri, $stream) = @_; |
180 my ($input, $buf); | 180 my ($input, $buf); |
266 | 266 |
267 $buf .= pack_body($self, $body, 0x1, $uri) if defined $body; | 267 $buf .= pack_body($self, $body, 0x1, $uri) if defined $body; |
268 | 268 |
269 $split = ref $uri->{split} && $uri->{split} || []; | 269 $split = ref $uri->{split} && $uri->{split} || []; |
270 for (@$split) { | 270 for (@$split) { |
271 raw_write($self->{socket}, substr($buf, 0, $_, "")); | 271 $self->raw_write(substr($buf, 0, $_, "")); |
272 goto done if $uri->{abort}; | 272 goto done if $uri->{abort}; |
273 select undef, undef, undef, ($uri->{split_delay} || 0.2); | 273 select undef, undef, undef, ($uri->{split_delay} || 0.2); |
274 } | 274 } |
275 | 275 |
276 raw_write($self->{socket}, $buf); | 276 $self->raw_write($buf); |
277 done: | 277 done: |
278 return $self->{last_stream}; | 278 return $self->{last_stream}; |
279 } | 279 } |
280 | 280 |
281 sub read { | 281 sub read { |
286 my $wait = $extra{wait}; | 286 my $wait = $extra{wait}; |
287 | 287 |
288 local $Data::Dumper::Terse = 1; | 288 local $Data::Dumper::Terse = 1; |
289 | 289 |
290 while (1) { | 290 while (1) { |
291 $buf = raw_read($s, $buf, 9, $wait); | 291 $buf = $self->raw_read($buf, 9, $wait); |
292 last if length $buf < 9; | 292 last if length $buf < 9; |
293 | 293 |
294 my $length = unpack_length($buf); | 294 my $length = unpack_length($buf); |
295 my $type = unpack('x3C', $buf); | 295 my $type = unpack('x3C', $buf); |
296 my $flags = unpack('x4C', $buf); | 296 my $flags = unpack('x4C', $buf); |
297 | 297 |
298 my $stream = unpack "x5 B32", $buf; | 298 my $stream = unpack "x5 B32", $buf; |
299 substr($stream, 0, 1) = 0; | 299 substr($stream, 0, 1) = 0; |
300 $stream = unpack("N", pack("B32", $stream)); | 300 $stream = unpack("N", pack("B32", $stream)); |
301 | 301 |
302 $buf = raw_read($s, $buf, $length + 9, $wait); | 302 $buf = $self->raw_read($buf, $length + 9, $wait); |
303 last if length($buf) < $length + 9; | 303 last if length($buf) < $length + 9; |
304 | 304 |
305 $buf = substr($buf, 9); | 305 $buf = substr($buf, 9); |
306 | 306 |
307 my $frame = $cframe{$type}{value}($self, $buf, $length, $flags, | 307 my $frame = $cframe{$type}{value}($self, $buf, $length, $flags, |
317 $buf = substr($buf, $length); | 317 $buf = substr($buf, $length); |
318 | 318 |
319 last unless $extra{all} && test_fin($got[-1], $extra{all}); | 319 last unless $extra{all} && test_fin($got[-1], $extra{all}); |
320 }; | 320 }; |
321 return \@got; | 321 return \@got; |
322 } | |
323 | |
324 sub raw_read { | |
325 my ($self, $buf, $len, $timo) = @_; | |
326 $timo = 8 unless $timo; | |
327 my $got = ''; | |
328 my $s = $self->{socket}; | |
329 | |
330 while (length($buf) < $len && IO::Select->new($s)->can_read($timo)) { | |
331 $s->sysread($got, 16384) or last; | |
332 log_in($got); | |
333 $buf .= $got; | |
334 } | |
335 return $buf; | |
336 } | |
337 | |
338 sub raw_write { | |
339 my ($self, $message) = @_; | |
340 my $s = $self->{socket}; | |
341 | |
342 local $SIG{PIPE} = 'IGNORE'; | |
343 | |
344 while (IO::Select->new($s)->can_write(0.4)) { | |
345 log_out($message); | |
346 my $n = $s->syswrite($message); | |
347 last unless $n; | |
348 $message = substr($message, $n); | |
349 last unless length $message; | |
350 } | |
322 } | 351 } |
323 | 352 |
324 ############################################################################### | 353 ############################################################################### |
325 | 354 |
326 sub pack_body { | 355 sub pack_body { |
459 pack 'c3', unpack 'xc3', pack 'N', $_[0]; | 488 pack 'c3', unpack 'xc3', pack 'N', $_[0]; |
460 } | 489 } |
461 | 490 |
462 sub unpack_length { | 491 sub unpack_length { |
463 unpack 'N', pack 'xc3', unpack 'c3', $_[0]; | 492 unpack 'N', pack 'xc3', unpack 'c3', $_[0]; |
464 } | |
465 | |
466 sub raw_read { | |
467 my ($s, $buf, $len, $timo) = @_; | |
468 $timo = 8 unless $timo; | |
469 my $got = ''; | |
470 | |
471 while (length($buf) < $len && IO::Select->new($s)->can_read($timo)) { | |
472 $s->sysread($got, 16384) or last; | |
473 log_in($got); | |
474 $buf .= $got; | |
475 } | |
476 return $buf; | |
477 } | |
478 | |
479 sub raw_write { | |
480 my ($s, $message) = @_; | |
481 | |
482 local $SIG{PIPE} = 'IGNORE'; | |
483 | |
484 while (IO::Select->new($s)->can_write(0.4)) { | |
485 log_out($message); | |
486 my $n = $s->syswrite($message); | |
487 last unless $n; | |
488 $message = substr($message, $n); | |
489 last unless length $message; | |
490 } | |
491 } | 493 } |
492 | 494 |
493 sub new_socket { | 495 sub new_socket { |
494 my ($port, %extra) = @_; | 496 my ($port, %extra) = @_; |
495 my $npn = $extra{'npn'}; | 497 my $npn = $extra{'npn'}; |