File Coverage

blib/lib/Net/Gemini/Server.pm
Criterion Covered Total %
statement 49 55 89.0
branch 15 22 68.1
condition n/a
subroutine 10 10 100.0
pod 5 5 100.0
total 79 92 85.8


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.08';
13 33     33   7318798 use strict;
  33         151  
  33         938  
14 33     33   185 use warnings;
  33         66  
  33         793  
15             # the below code mostly cargo culted from example/ssl_server.pl
16 33     33   8169 use IO::Socket::IP;
  33         382134  
  33         286  
17 33     33   31462 use IO::Socket::SSL;
  33         636027  
  33         354  
18              
19 85     85   15114 DESTROY { undef $_[0]{_context}; undef $_[0]{_socket} }
  85         36188  
20              
21             sub new {
22 86     86 1 4594114 my ( $class, %param ) = @_;
23             $param{listen}{LocalPort} = 1965
24 86 50       819 unless defined $param{listen}{LocalPort};
25 86         365 my %obj;
26             $obj{_socket} = IO::Socket::IP->new(
27             Listen => 5,
28             Reuse => 1,
29 86 100       351 %{ $param{listen} },
  86         1564  
30             ) or die "server failed: $!";
31             # server default is not to perform any verification
32             $obj{_context} =
33 85 50       77527 IO::Socket::SSL::SSL_Context->new( %{ $param{context} },
  85         2396  
34             SSL_server => 1, )
35             or die "context failed: $SSL_ERROR";
36 85         194700 $obj{_port} = $obj{_socket}->sockport;
37 85         8702 bless \%obj, $class;
38             }
39              
40 1     1 1 5 sub context { $_[0]{_context} }
41 85     85 1 1353 sub port { $_[0]{_port} }
42 55     55 1 104429 sub socket { $_[0]{_socket} }
43              
44             # this, as noted elsewhere, is mostly for testing the client
45             sub withforks {
46 29     29 1 62661 my ( $self, $callback, %param ) = @_;
47 29         645 my $server = $self->{_socket};
48 29         678 while (1) {
49 204 50       11406 my $client = $server->accept or do {
50 0         0 warn "accept failed: $!\n";
51 0         0 next;
52             };
53 204 50       85256427 if ( $param{close_on_accept} ) {
54 0         0 close $client;
55 0         0 next;
56             }
57 204         411907 my $parent = fork;
58 204 50       9559 die "fork failed: $!" unless defined $parent;
59 204 100       7650 if ($parent) {
60 175         10695 close $client;
61 175         18824 next;
62             }
63 29 50       3093 unless ( $param{no_ssl} ) {
64 29 100       4808 unless (
65             IO::Socket::SSL->start_SSL(
66             $client,
67             SSL_server => 1,
68             SSL_reuse_ctx => $self->{_context}
69             )
70             ) {
71 1         18875 warn "ssl handshake failed: $SSL_ERROR\n";
72 1         122 close $client;
73 1         91 exit;
74             }
75             }
76 28 50       576524 if ( $param{close_before_read} ) {
77 0         0 close $client;
78 0         0 exit;
79             }
80 28         1793 binmode $client, ':raw';
81             # NOTE this assumes the client isn't sending bytes one by one slow
82 28         826 my $n = sysread( $client, my $buf, 1024 );
83             # does not suss out any new client edge cases
84             #if ( $param{close_after_read} ) {
85             # close $client;
86             # exit;
87             #}
88             eval {
89             # NOTE the buffer is raw bytes and may need a decode
90 28         1261 $callback->( $client, $n, $buf );
91 27         2075985 1;
92 28 100       5841 } or do {
93             # KLUGE random stderr from a fork can confuse TAP and get
94             # the tests out of sequence?
95             #warn "callback error: $@";
96 1         2510 close $client;
97             };
98 28         1567 exit;
99             }
100             }
101              
102             1;
103             __END__