# HG changeset patch # User Andrey Zelenkov # Date 1436194042 -10800 # Node ID 0016fe31be131b3f1d13c587ab92a96b9608792d # Parent 1dd0e909fe94b6b11813c837a5701eb54d9d2339 Tests: fixed connection handling in stream_proxy_protocol_ipv6.t. Inapplicable http proxying was replaced with stream proxying. Backend connection close is postponed until all client data is read. diff --git a/stream_proxy_protocol_ipv6.t b/stream_proxy_protocol_ipv6.t --- a/stream_proxy_protocol_ipv6.t +++ b/stream_proxy_protocol_ipv6.t @@ -12,6 +12,9 @@ use strict; use Test::More; +use IO::Select; +use Socket qw/ $CRLF /; + BEGIN { use FindBin; chdir($FindBin::Bin); } use lib 'lib'; @@ -22,7 +25,7 @@ use Test::Nginx; select STDERR; $| = 1; select STDOUT; $| = 1; -my $t = Test::Nginx->new()->has(qw/http proxy stream ipv6/) +my $t = Test::Nginx->new()->has(qw/stream ipv6/) ->write_file_expand('nginx.conf', <<'EOF'); %%TEST_GLOBALS%% @@ -32,35 +35,26 @@ daemon off; events { } -http { - %%TEST_GLOBALS_HTTP%% - +stream { server { listen 127.0.0.1:8080; - server_name localhost; - - location /on { - proxy_pass http://[::1]:8080; - } + proxy_pass [::1]:8080; + } - location /off { - proxy_pass http://[::1]:8081; - } + server { + listen 127.0.0.1:8081; + proxy_pass [::1]:8081; } -} - -stream { - proxy_protocol on; server { listen [::1]:8080; proxy_pass 127.0.0.1:8082; + proxy_protocol on; } server { listen [::1]:8081; proxy_pass 127.0.0.1:8082; - proxy_protocol off; } } @@ -72,13 +66,70 @@ EOF ############################################################################### -like(http_get('/on'), qr/PROXY TCP6 ::1 ::1 [0-9]+ 8080/, 'protocol on'); -unlike(http_get('/off'), qr/PROXY/, 'protocol off'); +like(stream_get('close'), qr/PROXY TCP6 ::1 ::1 \d+ 8080$CRLF/, 'protocol on'); +unlike(stream_get('close', '127.0.0.1:8081'), qr/PROXY/, 'protocol off'); + +############################################################################### + +sub stream_get { + my ($data, $peer) = @_; + + my $s = stream_connect($peer); + stream_write($s, $data); + + $data = ''; + while (my $buf = stream_read($s)) { + $data .= $buf; + } + + return $data; +} + +sub stream_connect { + my $peer = shift; + my $s = IO::Socket::INET->new( + Proto => 'tcp', + PeerAddr => $peer || '127.0.0.1:8080' + ) + or die "Can't connect to nginx: $!\n"; + + return $s; +} + +sub stream_write { + my ($s, $message) = @_; + + local $SIG{PIPE} = 'IGNORE'; + + $s->blocking(0); + while (IO::Select->new($s)->can_write(1.5)) { + my $n = $s->syswrite($message); + last unless $n; + $message = substr($message, $n); + last unless length $message; + } + + if (length $message) { + $s->close(); + } +} + +sub stream_read { + my ($s) = @_; + my ($buf); + + $s->blocking(0); + if (IO::Select->new($s)->can_read(3)) { + $s->sysread($buf, 1024); + }; + + log_in($buf); + return $buf; +} ############################################################################### sub stream_daemon { - my $d = shift; my $server = IO::Socket::INET->new( Proto => 'tcp', LocalHost => '127.0.0.1:8082', @@ -87,26 +138,39 @@ sub stream_daemon { ) or die "Can't create listening socket: $!\n"; + my $sel = IO::Select->new($server); + local $SIG{PIPE} = 'IGNORE'; - while (my $client = $server->accept()) { - $client->autoflush(1); + while (my @ready = $sel->can_read) { + foreach my $fh (@ready) { + if ($server == $fh) { + my $new = $fh->accept; + $new->autoflush(1); + $sel->add($new); - log2c("(new connection $client)"); - - $client->sysread(my $buffer, 65536) or next; - - log2i("$client $buffer"); + } elsif (stream_handle_client($fh)) { + $sel->remove($fh); + $fh->close; + } + } + } +} - $buffer =~ /(.*?)\x0d\x0a?/ms; - $buffer = $1; +sub stream_handle_client { + my ($client) = @_; - log2o("$client $buffer"); + log2c("(new connection $client)"); + + $client->sysread(my $buffer, 65536) or return 1; - $client->syswrite($buffer); + log2i("$client $buffer"); + + log2o("$client $buffer"); - close $client; - } + $client->syswrite($buffer); + + return $buffer =~ /close/; } sub log2i { Test::Nginx::log_core('|| <<', @_); }