1package HTTP::Proxy::Engine;
2$HTTP::Proxy::Engine::VERSION = '0.304';
3use strict;
4use Carp;
5
6my %engines = (
7    MSWin32 => 'NoFork',
8    default => 'Legacy',
9);
10
11# required accessors
12__PACKAGE__->make_accessors( qw( max_clients ));
13
14sub new {
15    my $class  = shift;
16    my %params = @_;
17
18    # the front-end
19    if ( $class eq 'HTTP::Proxy::Engine' ) {
20        my $engine = delete $params{engine};
21        $engine = $engines{$^O} || $engines{default}
22          unless defined $engine;
23
24        $class = "HTTP::Proxy::Engine::$engine";
25        eval "require $class";
26        croak $@ if $@;
27    }
28
29    # some error checking
30    croak "No proxy defined"
31      unless exists $params{proxy};
32    croak "$params{proxy} is not a HTTP::Proxy object"
33      unless UNIVERSAL::isa( $params{proxy}, 'HTTP::Proxy' );
34
35    # so we are an actual engine
36    no strict 'refs';
37    return bless {
38        %{"$class\::defaults"},
39        %params
40    }, $class;
41}
42
43# run() should be defined in subclasses
44sub run {
45    my $self = shift;
46    my $class = ref $self;
47    croak "$class doesn't define a run() method";
48}
49
50sub proxy { $_[0]{proxy} }
51
52# class method
53sub make_accessors {
54    my $class = shift;
55
56    for my $attr (@_) {
57        no strict 'refs';
58        *{"$class\::$attr"} = sub {
59            $_[0]{$attr} = $_[1] if defined $_[1];
60            $_[0]{$attr};
61        };
62    }
63}
64
651;
66
67__END__
68
69=head1 NAME
70
71HTTP::Proxy::Engine - Generic child process manager engine for HTTP::Proxy
72
73=head1 SYNOPSIS
74
75    use HTTP::Proxy;
76
77    # use the default engine for your system
78    my $proxy = HTTP::Proxy->new();
79
80    # choose one
81    my $proxy = HTTP::Proxy->new( engine => 'Old' );
82
83=head1 DESCRIPTION
84
85The L<HTTP::Proxy::Engine> class is a front-end to actual proxy
86engine classes.
87
88The role of an engine is to implement the main fork+serve loop
89with all the required bookkeeping. This is also a good way to
90test various implementation and/or try out new algorithms
91without too much difficulties.
92
93=head1 METHODS
94
95=over 4
96
97=item new()
98
99Create a new engine. The parameter C<engine> is used to decide which
100kind of engine will be created. Other parameters are passed to the
101underlying engine.
102
103This method also implement the subclasses constructor (they obviously
104do not need the C<engine> parameter).
105
106=back
107
108=head1 CREATING YOUR OWN ENGINE
109
110It is possible to create one's own engine, by creating
111a simple subclass of L<HTTP::Proxy::Engine> with the following
112methods:
113
114=over 4
115
116=item start()
117
118This method should handle any initialisation required when the
119engine starts.
120
121=item run()
122
123This method is the main loop of the master process.
124It defines how child processes are forked, checked and killed.
125
126The engine MUST have a run() method, and it will be called again
127and again until the proxy exits.
128
129C<< $self->proxy->daemon >> returns the listening socket that can C<accept()>
130connections. The child must call C<< $self->proxy->serve_connections() >>
131on the returned socket to handle actual TCP connections.
132
133=item stop()
134
135This optional method should handle any cleanup procedures when the
136engine stops (typically when the main proxy process is killed).
137
138=back
139
140A subclass may also define a C<%defaults> hash (with C<our>) that
141contains the default values for the fields used internaly.
142
143=head1 METHODS PROVIDED TO SUBCLASSES
144
145L<HTTP::Proxy::Engine> provides the following methods to its
146subclasses:
147
148=over 4
149
150=item proxy()
151
152Return the L<HTTP::Proxy> object that runs the engine.
153
154=item max_clients()
155
156Get or set the maximum number of TCP clients, that is to say
157the maximum number of forked child process.
158
159Some engines may understand a value of C<0> as I<do not fork at all>.
160This is what L<HTTP::Proxy::Engine::Legacy> does.
161
162=item make_accessors( @names )
163
164Create accessors named after C<@names> in the subclass package.
165All accessors are read/write. This is a utility method.
166
167B<This is a class method.>
168
169=back
170
171=head1 AUTHOR
172
173Philippe "BooK" Bruhat, C<< <book@cpan.org> >>.
174
175=head1 COPYRIGHT
176
177Copyright 2005-2015, Philippe Bruhat.
178
179=head1 LICENSE
180
181This module is free software; you can redistribute it or modify it under
182the same terms as Perl itself.
183
184=cut
185
186