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