#!/usr/bin/perl
use strict;
use warnings;
use Test::More;
use Socket;
use File::Spec;
use Symbol qw(gensym);
use Net::SSLeay;
use Config;
BEGIN {
plan skip_all => "openssl 1.0.1 required" unless Net::SSLeay::SSLeay >= 0x10001000;
plan skip_all => "libressl removed support for NPN" if Net::SSLeay::constant("LIBRESSL_VERSION_NUMBER");
plan skip_all => "fork() not supported on $^O" unless $Config{d_fork};
}
plan tests => 7;
my $sock;
my $pid;
my $port = 40000+int(rand(9999));
my $ip = "\x7F\0\0\x01";
my $serv_params = sockaddr_in($port, $ip);
my $msg = 'ssleay-npn-test';
my $cert_pem = File::Spec->catfile('t', 'data', 'testcert_wildcard.crt.pem');
my $key_pem = File::Spec->catfile('t', 'data', 'testcert_key_2048.pem');
my @results;
Net::SSLeay::initialize();
{
# SSL server
$sock = gensym();
socket($sock, AF_INET, SOCK_STREAM, 0) or BAIL_OUT("failed to open socket: $!");
bind($sock, $serv_params) or BAIL_OUT("failed to bind socket: $!");
listen($sock, 3) or BAIL_OUT("failed to listen on socket: $!");
$pid = fork();
BAIL_OUT("failed to fork: $!") unless defined $pid;
if ($pid == 0) {
my $ns = gensym();
my $addr = accept($ns, $sock);
my $old_out = select($ns);
$| = 1;
select($old_out);
my $ctx = Net::SSLeay::CTX_tlsv1_new();
Net::SSLeay::set_cert_and_key($ctx, $cert_pem, $key_pem);
my $rv = Net::SSLeay::CTX_set_next_protos_advertised_cb($ctx, ['spdy/2','http1.1']);
is($rv, 1, 'CTX_set_next_protos_advertised_cb');
my $ssl = Net::SSLeay::new($ctx);
Net::SSLeay::set_fd($ssl, fileno($ns));
Net::SSLeay::accept($ssl);
is('spdy/2' , Net::SSLeay::P_next_proto_negotiated($ssl), 'P_next_proto_negotiated/server');
my $got = Net::SSLeay::ssl_read_all($ssl);
is($got, $msg, 'ssl_read_all compare');
Net::SSLeay::ssl_write_all($ssl, uc($got));
Net::SSLeay::free($ssl);
Net::SSLeay::CTX_free($ctx);
close $ns;
close $sock;
exit;
}
}
{
# SSL client
my $s1 = gensym();
socket($s1, AF_INET, SOCK_STREAM, 0) or BAIL_OUT("failed to open socket: $!");
connect($s1, $serv_params) or BAIL_OUT("failed to connect: $!");
my $old_out = select($s1);
$| = 1;
select($old_out);
my $ctx1 = Net::SSLeay::CTX_tlsv1_new();
my $rv = Net::SSLeay::CTX_set_next_proto_select_cb($ctx1, ['http1.1','spdy/2']);
push @results, [ $rv==1, 'CTX_set_next_proto_select_cb'];
Net::SSLeay::CTX_set_options($ctx1, &Net::SSLeay::OP_ALL);
my $ssl1 = Net::SSLeay::new($ctx1);
Net::SSLeay::set_fd($ssl1, $s1);
Net::SSLeay::connect($ssl1);
Net::SSLeay::ssl_write_all($ssl1, $msg);
push @results, [ 'spdy/2' eq Net::SSLeay::P_next_proto_negotiated($ssl1), 'P_next_proto_negotiated/client'];
push @results, [ 1 == Net::SSLeay::P_next_proto_last_status($ssl1), 'P_next_proto_last_status/client'];
Net::SSLeay::free($ssl1);
Net::SSLeay::CTX_free($ctx1);
close $s1;
}
waitpid $pid, 0;
push @results, [$? == 0, 'server exited with 0'];
END {
Test::More->builder->current_test(3);
ok( $_->[0], $_->[1] ) for (@results);
}