File Coverage

blib/lib/Net/Gemini/Server.pm
Criterion Covered Total %
statement 44 53 83.0
branch 14 22 63.6
condition 1 2 50.0
subroutine 9 9 100.0
pod 5 5 100.0
total 73 91 80.2


line stmt bran cond sub pod time code
1             # -*- Perl -*-
2             #
3             # a Gemini protocol server, mostly to test the Net::Gemini client with
4             #
5             # "They are great warriors: their greatness is like the empty desert
6             # wastes. They are both the lords of the River, the River of the
7             # Ordeal which clears the just man. They weigh upon the evil man like
8             # a neck-stock. In Kisiga, their very anciently founded city, the
9             # trustworthy does not get caught, but the evil cannot pass through."
10              
11             package Net::Gemini::Server;
12             our $VERSION = '0.07';
13 21     21   261313 use strict;
  21         106  
  21         669  
14 21     21   105 use warnings;
  21         46  
  21         551  
15             # the below code mostly cargo culted from example/ssl_server.pl
16 21     21   999 use IO::Socket::SSL;
  21         83055  
  21         193  
17              
18 73     73   13369 DESTROY { undef $_[0]{_context}; undef $_[0]{_socket} }
  73         35547  
19              
20             sub new {
21 74     74 1 204336 my ( $class, %param ) = @_;
22 74 50       548 $param{listen}{LocalPort} = 1965 unless defined $param{listen}{LocalPort};
23 74         170 my %obj;
24 74   50     2328 my $ioclass = IO::Socket::SSL->can_ipv6 || 'IO::Socket::INET';
25             $obj{_socket} = $ioclass->new(
26             Listen => 5,
27             Reuse => 1,
28 74 100       1331 %{ $param{listen} },
  74         1147  
29             SSL_startHandshake => 0,
30             ) or die "server failed: $!";
31             # server default is not to perform any verification
32             $obj{_context} =
33 73 50       64014 IO::Socket::SSL::SSL_Context->new( %{ $param{context} }, SSL_server => 1, )
  73         1091  
34             or die "context failed: $SSL_ERROR";
35 73         136874 $obj{_port} = $obj{_socket}->sockport;
36 73         8880 bless \%obj, $class;
37             }
38              
39 1     1 1 5 sub context { $_[0]{_context} }
40 73     73 1 999 sub port { $_[0]{_port} }
41 54     54 1 107941 sub socket { $_[0]{_socket} }
42              
43             # this, as noted elsewhere, is mostly for testing the client
44             sub withforks {
45 18     18 1 25952 my ( $self, $callback, %param ) = @_;
46 18         439 my $server = $self->{_socket};
47 18         331 while (1) {
48 138 50       8385 my $client = $server->accept or do {
49 0         0 warn "accept failed: $!\n";
50 0         0 next;
51             };
52 138 50       51531560 if ( $param{close_on_accept} ) {
53 0         0 close $client;
54 0         0 next;
55             }
56 138         301983 my $parent = fork;
57 138 50       7016 die "fork failed: $!" unless defined $parent;
58 138 100       3611 if ($parent) {
59 120         7690 close $client;
60 120         11828 next;
61             }
62 18 50       1732 unless ( $param{no_ssl} ) {
63 18 50       2769 unless (
64             IO::Socket::SSL->start_SSL(
65             $client,
66             SSL_server => 1,
67             SSL_reuse_ctx => $self->{_context}
68             )
69             ) {
70 0         0 warn "ssl handshake failed: $SSL_ERROR\n";
71 0         0 close $client;
72 0         0 exit;
73             }
74             }
75 18 50       376621 if ( $param{close_before_read} ) {
76 0         0 close $client;
77 0         0 exit;
78             }
79 18         645 binmode $client, ':raw';
80             # NOTE this assumes the client isn't sending bytes one by one slow
81 18         347 my $n = sysread( $client, my $buf, 1024 );
82             # does not suss out any new client edge cases
83             #if ( $param{close_after_read} ) {
84             # close $client;
85             # exit;
86             #}
87             eval {
88             # NOTE the buffer is raw bytes and may need a decode
89 18         672 $callback->( $client, $n, $buf );
90 17         2048701 1;
91 18 100       3641 } or do {
92             # KLUGE random stderr from a fork can confuse TAP and get
93             # the tests out of sequence?
94             #warn "callback error: $@";
95 1         2480 close $client;
96             };
97 18         1120 exit;
98             }
99             }
100              
101             1;
102             __END__