source: main/trunk/greenstone2/perllib/cpan/Mojo/IOLoop/Server.pm@ 32205

Last change on this file since 32205 was 32205, checked in by ak19, 6 years ago

First set of commits to do with implementing the new 'paged_html' output option of PDFPlugin that uses using xpdftools' new pdftohtml. So far tested only on Linux (64 bit), but things work there so I'm optimistically committing the changes since they work. 2. Committing the pre-built Linux binaries of XPDFtools for both 32 and 64 bit built by the XPDF group. 2. To use the correct bitness variant of xpdftools, setup.bash now exports the BITNESS env var, consulted by gsConvert.pl. 3. All the perl code changes to do with using xpdf tools' pdftohtml to generate paged_html and feed it in the desired form into GS(3): gsConvert.pl, PDFPlugin.pm and its parent ConvertBinaryPFile.pm have been modified to make it all work. xpdftools' pdftohtml generates a folder containing an html file and a screenshot for each page in a PDF (as well as an index.html linking to each page's html). However, we want a single html file that contains each individual 'page' html's content in a div, and need to do some further HTML style, attribute and structure modifications to massage the xpdftool output to what we want for GS. In order to parse and manipulate the HTML 'DOM' to do this, we're using the Mojo::DOM package that Dr Bainbridge found and which he's compiled up. Mojo::DOM is therefore also committed in this revision. Some further changes and some display fixes are required, but need to check with the others about that.

File size: 6.9 KB
Line 
1package Mojo::IOLoop::Server;
2use Mojo::Base 'Mojo::EventEmitter';
3
4use Carp 'croak';
5use IO::Socket::IP;
6use IO::Socket::UNIX;
7use Mojo::IOLoop;
8use Mojo::IOLoop::TLS;
9use Scalar::Util 'weaken';
10use Socket qw(IPPROTO_TCP TCP_NODELAY);
11
12has reactor => sub { Mojo::IOLoop->singleton->reactor };
13
14sub DESTROY {
15 my $self = shift;
16 $ENV{MOJO_REUSE} =~ s/(?:^|\,)\Q$self->{reuse}\E// if $self->{reuse};
17 $self->stop if $self->{handle} && $self->reactor;
18}
19
20sub generate_port {
21 IO::Socket::IP->new(Listen => 5, LocalAddr => '127.0.0.1')->sockport;
22}
23
24sub handle { shift->{handle} }
25
26sub is_accepting { !!shift->{active} }
27
28sub listen {
29 my ($self, $args) = (shift, ref $_[0] ? $_[0] : {@_});
30
31 # Look for reusable file descriptor
32 my $path = $args->{path};
33 my $address = $args->{address} || '0.0.0.0';
34 my $port = $args->{port};
35 $ENV{MOJO_REUSE} ||= '';
36 my $fd
37 = ($path && $ENV{MOJO_REUSE} =~ /(?:^|\,)unix:\Q$path\E:(\d+)/)
38 || ($port && $ENV{MOJO_REUSE} =~ /(?:^|\,)\Q$address:$port\E:(\d+)/)
39 ? $1
40 : undef;
41
42 # Allow file descriptor inheritance
43 local $^F = 1023;
44
45 # Reuse file descriptor
46 my $handle;
47 my $class = $path ? 'IO::Socket::UNIX' : 'IO::Socket::IP';
48 if (defined($fd //= $args->{fd})) {
49 $handle = $class->new_from_fd($fd, 'r')
50 or croak "Can't open file descriptor $fd: $!";
51 }
52
53 else {
54 my %options
55 = (Listen => $args->{backlog} // SOMAXCONN, Type => SOCK_STREAM);
56
57 # UNIX domain socket
58 my $reuse;
59 if ($path) {
60 unlink $path if -S $path;
61 $options{Local} = $path;
62 $handle = $class->new(%options) or croak "Can't create listen socket: $!";
63 $reuse = $self->{reuse} = join ':', 'unix', $path, fileno $handle;
64 }
65
66 # IP socket
67 else {
68 $options{LocalAddr} = $address;
69 $options{LocalAddr} =~ s/[\[\]]//g;
70 $options{LocalPort} = $port if $port;
71 $options{ReuseAddr} = 1;
72 $options{ReusePort} = $args->{reuse};
73 $handle = $class->new(%options) or croak "Can't create listen socket: $@";
74 $fd = fileno $handle;
75 $reuse = $self->{reuse} = join ':', $address, $handle->sockport, $fd;
76 }
77
78 $ENV{MOJO_REUSE} .= length $ENV{MOJO_REUSE} ? ",$reuse" : "$reuse";
79 }
80 $handle->blocking(0);
81 @$self{qw(args handle)} = ($args, $handle);
82
83 croak 'IO::Socket::SSL 2.009+ required for TLS support'
84 if !Mojo::IOLoop::TLS->can_tls && $args->{tls};
85}
86
87sub port { shift->{handle}->sockport }
88
89sub start {
90 my $self = shift;
91 weaken $self;
92 ++$self->{active}
93 and $self->reactor->io($self->{handle} => sub { $self->_accept });
94}
95
96sub stop { delete($_[0]{active}) and $_[0]->reactor->remove($_[0]{handle}) }
97
98sub _accept {
99 my $self = shift;
100
101 # Greedy accept
102 my $args = $self->{args};
103 my $accepted = 0;
104 while ($self->{active} && !($args->{single_accept} && $accepted++)) {
105 return unless my $handle = $self->{handle}->accept;
106 $handle->blocking(0);
107
108 # Disable Nagle's algorithm
109 setsockopt $handle, IPPROTO_TCP, TCP_NODELAY, 1;
110
111 $self->emit(accept => $handle) and next unless $args->{tls};
112
113 # Start TLS handshake
114 my $tls = Mojo::IOLoop::TLS->new($handle)->reactor($self->reactor);
115 $tls->on(upgrade => sub { $self->emit(accept => pop) });
116 $tls->on(error => sub { });
117 $tls->negotiate(%$args, server => 1);
118 }
119}
120
1211;
122
123=encoding utf8
124
125=head1 NAME
126
127Mojo::IOLoop::Server - Non-blocking TCP and UNIX domain socket server
128
129=head1 SYNOPSIS
130
131 use Mojo::IOLoop::Server;
132
133 # Create listen socket
134 my $server = Mojo::IOLoop::Server->new;
135 $server->on(accept => sub {
136 my ($server, $handle) = @_;
137 ...
138 });
139 $server->listen(port => 3000);
140
141 # Start and stop accepting connections
142 $server->start;
143 $server->stop;
144
145 # Start reactor if necessary
146 $server->reactor->start unless $server->reactor->is_running;
147
148=head1 DESCRIPTION
149
150L<Mojo::IOLoop::Server> accepts TCP/IP and UNIX domain socket connections for
151L<Mojo::IOLoop>.
152
153=head1 EVENTS
154
155L<Mojo::IOLoop::Server> inherits all events from L<Mojo::EventEmitter> and can
156emit the following new ones.
157
158=head2 accept
159
160 $server->on(accept => sub {
161 my ($server, $handle) = @_;
162 ...
163 });
164
165Emitted for each accepted connection.
166
167=head1 ATTRIBUTES
168
169L<Mojo::IOLoop::Server> implements the following attributes.
170
171=head2 reactor
172
173 my $reactor = $server->reactor;
174 $server = $server->reactor(Mojo::Reactor::Poll->new);
175
176Low-level event reactor, defaults to the C<reactor> attribute value of the
177global L<Mojo::IOLoop> singleton.
178
179=head1 METHODS
180
181L<Mojo::IOLoop::Server> inherits all methods from L<Mojo::EventEmitter> and
182implements the following new ones.
183
184=head2 generate_port
185
186 my $port = Mojo::IOLoop::Server->generate_port;
187
188Find a free TCP port, primarily used for tests.
189
190=head2 handle
191
192 my $handle = $server->handle;
193
194Get handle for server, usually an L<IO::Socket::IP> object.
195
196=head2 is_accepting
197
198 my $bool = $server->is_accepting;
199
200Check if connections are currently being accepted.
201
202=head2 listen
203
204 $server->listen(port => 3000);
205 $server->listen({port => 3000});
206
207Create a new listen socket. Note that TLS support depends on L<IO::Socket::SSL>
208(2.009+).
209
210These options are currently available:
211
212=over 2
213
214=item address
215
216 address => '127.0.0.1'
217
218Local address to listen on, defaults to C<0.0.0.0>.
219
220=item backlog
221
222 backlog => 128
223
224Maximum backlog size, defaults to C<SOMAXCONN>.
225
226=item fd
227
228 fd => 3
229
230File descriptor with an already prepared listen socket.
231
232=item path
233
234 path => '/tmp/myapp.sock'
235
236Path for UNIX domain socket to listen on.
237
238=item port
239
240 port => 80
241
242Port to listen on, defaults to a random port.
243
244=item reuse
245
246 reuse => 1
247
248Allow multiple servers to use the same port with the C<SO_REUSEPORT> socket
249option.
250
251=item single_accept
252
253 single_accept => 1
254
255Only accept one connection at a time.
256
257=item tls
258
259 tls => 1
260
261Enable TLS.
262
263=item tls_ca
264
265 tls_ca => '/etc/tls/ca.crt'
266
267Path to TLS certificate authority file.
268
269=item tls_cert
270
271 tls_cert => '/etc/tls/server.crt'
272 tls_cert => {'mojolicious.org' => '/etc/tls/mojo.crt'}
273
274Path to the TLS cert file, defaults to a built-in test certificate.
275
276=item tls_ciphers
277
278 tls_ciphers => 'AES128-GCM-SHA256:RC4:HIGH:!MD5:!aNULL:!EDH'
279
280TLS cipher specification string. For more information about the format see
281L<https://www.openssl.org/docs/manmaster/apps/ciphers.html#CIPHER-STRINGS>.
282
283=item tls_key
284
285 tls_key => '/etc/tls/server.key'
286 tls_key => {'mojolicious.org' => '/etc/tls/mojo.key'}
287
288Path to the TLS key file, defaults to a built-in test key.
289
290=item tls_protocols
291
292 tls_protocols => ['foo', 'bar']
293
294ALPN protocols to negotiate.
295
296=item tls_verify
297
298 tls_verify => 0x00
299
300TLS verification mode.
301
302=item tls_version
303
304 tls_version => 'TLSv1_2'
305
306TLS protocol version.
307
308=back
309
310=head2 port
311
312 my $port = $server->port;
313
314Get port this server is listening on.
315
316=head2 start
317
318 $server->start;
319
320Start or resume accepting connections.
321
322=head2 stop
323
324 $server->stop;
325
326Stop accepting connections.
327
328=head1 SEE ALSO
329
330L<Mojolicious>, L<Mojolicious::Guides>, L<https://mojolicious.org>.
331
332=cut
Note: See TracBrowser for help on using the repository browser.