File Coverage

blib/lib/Net/Gemini/Server.pm
Criterion Covered Total %
statement 42 52 80.7
branch 13 22 59.0
condition 1 2 50.0
subroutine 9 9 100.0
pod 5 5 100.0
total 70 90 77.7


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.06';
13 5     5   240420 use strict;
  5         17  
  5         144  
14 5     5   26 use warnings;
  5         15  
  5         128  
15             # the below code mostly cargo culted from example/ssl_server.pl
16 5     5   913 use IO::Socket::SSL;
  5         81400  
  5         49  
17              
18 8     8   1707 DESTROY { undef $_[0]{_context}; undef $_[0]{_socket} }
  8         3135  
19              
20             sub new {
21 9     9 1 26683 my ( $class, %param ) = @_;
22 9 50       64 $param{listen}{LocalPort} = 1965 unless defined $param{listen}{LocalPort};
23 9         22 my %obj;
24 9   50     152 my $ioclass = IO::Socket::SSL->can_ipv6 || 'IO::Socket::INET';
25             $obj{_socket} = $ioclass->new(
26             Listen => 5,
27             Reuse => 1,
28 9 100       130 %{ $param{listen} },
  9         150  
29             SSL_startHandshake => 0,
30             ) or die "server failed: $!";
31             # server default is not to perform any verification
32             $obj{_context} =
33 8 50       7129 IO::Socket::SSL::SSL_Context->new( %{ $param{context} }, SSL_server => 1, )
  8         99  
34             or die "context failed: $SSL_ERROR";
35 8         17321 $obj{_port} = $obj{_socket}->sockport;
36 8         855 bless \%obj, $class;
37             }
38              
39 1     1 1 5 sub context { $_[0]{_context} }
40 8     8 1 106 sub port { $_[0]{_port} }
41 5     5 1 7479 sub socket { $_[0]{_socket} }
42              
43             # this, as noted elsewhere, is mostly for testing the client
44             sub withforks {
45 2     2 1 3819 my ( $self, $callback, %param ) = @_;
46 2         124 my $server = $self->{_socket};
47 2         62 while (1) {
48 2 50       180 my $client = $server->accept or do {
49 0         0 warn "accept failed: $!\n";
50 0         0 next;
51             };
52 2 50       8191 if ( $param{close_on_accept} ) {
53 0         0 close $client;
54 0         0 next;
55             }
56 2         3955 my $parent = fork;
57 2 50       211 die "fork failed: $!" unless defined $parent;
58 2 50       69 if ($parent) {
59 0         0 close $client;
60 0         0 next;
61             }
62 2 50       127 unless ( $param{no_ssl} ) {
63 2 50       338 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 next;
72             }
73             }
74 2 50       42983 if ( $param{close_before_read} ) {
75 0         0 close $client;
76 0         0 exit;
77             }
78 2         69 binmode $client, ':raw';
79             # NOTE this assumes the client isn't sending bytes one by one slow
80 2         44 my $n = sysread( $client, my $buf, 1024 );
81             # does not suss out any new client edge cases
82             #if ( $param{close_after_read} ) {
83             # close $client;
84             # exit;
85             #}
86             eval {
87             # NOTE the buffer is raw bytes and may need a decode
88 2         88 $callback->( $client, $n, $buf );
89 1         2004991 1;
90 2 100       812 } or do {
91             # KLUGE random stderr from a fork can confuse TAP and get
92             # the tests out of sequence?
93             #warn "callback error: $@";
94 1         2448 close $client;
95             };
96 2         425 exit;
97             }
98             }
99              
100             1;
101             __END__