1 #!/usr/local/bin/perl -w
13 my $opts_ok = GetOptions(
22 usage() unless $opts_ok ;
23 usage() if $opts{help} ;
27 'reverse' => $opts{reverse_port} || 8888,
28 'upper' => $opts{upper_port} || 8889,
31 # this controls the order of requests to the backends.
33 my @backend_ids = sort keys %backend_ports ;
35 my $listen = init_server( $opts{server_port} || 8887 ) ;
37 Stem::Event::start_loop() ;
41 # create the listen socket for the server side of the middle layer.
47 # create the middle layer listen socket
49 my $listen = Stem::Socket->new(
52 method => 'client_connected',
57 die "can't listen on $port: $listen" unless ref $listen ;
62 # this is called when the server has accepted a socket connection
64 sub client_connected {
66 my( $obj, $socket ) = @_ ;
68 # create the session object
70 my $self = bless {}, __PACKAGE__ ;
72 # create and save the async io object for the client
74 my $async = Stem::AsyncIO->new(
77 read_method => 'client_read_data',
78 send_data_on_close => 1,
80 ref $async or die "can't create Async: $async" ;
81 $self->{client_async} = $async ;
83 # create and save the gather object
85 my $gather = Stem::Gather->new(
87 keys => \@backend_ids,
90 ref $gather or die "can't create Gather: $gather" ;
91 $self->{gather} = $gather ;
94 # this is called when all the data from client has been read.
96 sub client_read_data {
98 my( $self, $data ) = @_ ;
100 print "Client read [${$data}]\n" if $opts{verbose} ;
102 # store the client data (a ref is passed in)
104 $self->{'client_data'} = ${$data} ;
106 # connect to all of the backend servers
108 $self->connect_to_backends() ;
111 # this connects the session to all of the backends
113 sub connect_to_backends {
117 # loop over all the backends
119 foreach my $id ( @backend_ids ) {
121 # connect to the backend with this id and its port and save the
124 my $connect = Stem::Socket->new(
127 port => $backend_ports{ $id },
128 method => 'backend_connected',
131 ref $connect or die "can't create Socket: $connect" ;
132 $self->{connect}{$id} = $connect ;
136 # this is called when a backend end connection succeeds
138 sub backend_connected {
140 my( $self, $socket, $id ) = @_ ;
142 # delete and shutdown the connect object as we no longer need it
144 my $connect = delete $self->{connect}{$id} ;
145 $connect->shut_down() ;
147 # create and save an async i/o object for this backend
149 my $async = Stem::AsyncIO->new(
153 read_method => 'backend_read_data',
154 send_data_on_close => 1,
156 ref $async or die "can't create Async: $async" ;
157 $self->{async}{$id} = $async ;
159 # write the client data to the back end. no more data will follow.
161 $async->final_write( \$self->{client_data} ) ;
164 # this is called when we have read all the data from the backend
166 sub backend_read_data {
168 my( $self, $data, $id ) = @_ ;
170 print "Backend $id READ [${$data}]\n" if $opts{verbose} ;
172 # save the backend data (we are passed a ref)
174 $self->{backend_data}{$id} = ${$data} ;
176 # delete and shutdown the async i/o for the backend since we don't
179 my $async = delete $self->{async}{$id} ;
180 $async->shut_down() ;
182 # mark that this backend is done
184 $self->{'gather'}->gathered( $id ) ;
187 # this is called when all the backends are done.
193 my $gather = delete $self->{gather} ;
194 $gather->shut_down() ;
196 # no more backends so we return the joined backend data to the client.
198 # we don't need the gather object around anymore
199 # allow for self cleanup when it is done with the final write to the
202 my $async = delete $self->{client_async} ;
204 join( '', @{$self->{backend_data}}{ @backend_ids } )
217 usage: $0 [--help|h] [--upper_port <port>] [--reverse_port <port>]
218 [--server_port <port>] [--v|--verbose]
220 upper_port <port> Set the port for the middleware server
222 upper_port <port> Set the port for the upper case server
224 reverse_port <port> Set the port for the string reverse server
226 verbose Set verbose mode
227 help | h Print this help text
232 # this destroy can be uncommented to see the actual destruction of the
233 # various obects in this script.
237 # print "DEST [$self]\n" ;