Permalink
Browse files

!!! This change breaks backward compatibility on a relatively unused

!!! feature.  You are affected if you use ARG0 or ARG1 in a
!!! POE::Component::Server::TCP ClientConnected callback.

ClientArgs promised more than it could deliver, and people finally
noticed.  This change backs off supplying the socket in $_[ARG0], and
it expands ClientArgs' arrayref into @_[ARG0..$#_].  Thanks to Michael
Fowler for rt.cpan.org #47855 (which this resolves), and POE's mailing
list for advice on which way this change should go.
  • Loading branch information...
1 parent 3be6db4 commit a5d37656384b80116af22045ebca09aa9a62ce56 @rcaputo committed Jul 29, 2009
Showing with 48 additions and 27 deletions.
  1. +43 −22 poe/lib/POE/Component/Server/TCP.pm
  2. +5 −5 poe/t/90_regression/somni-poco-server-tcp.t
View
65 poe/lib/POE/Component/Server/TCP.pm
@@ -115,7 +115,7 @@ sub new {
}
}
- my $client_args = delete($param{ClientArgs}) || delete($param{Args});
+ my $client_args = delete($param{ClientArgs}) || delete($param{Args});
# Defaults.
@@ -144,7 +144,7 @@ sub new {
$client_connected = sub {} unless defined $client_connected;
$client_disconnected = sub {} unless defined $client_disconnected;
$client_flushed = sub {} unless defined $client_flushed;
- $client_args = [] unless defined $client_args;
+ $client_args = [] unless defined $client_args;
# Extra states.
@@ -276,7 +276,7 @@ sub new {
$heap->{remote_port} = $remote_port;
$heap->{client} = POE::Wheel::ReadWrite->new(
- Handle => splice(@_, ARG0, 1),
+ Handle => $_[ARG0],
Driver => POE::Driver::SysRW->new(),
_get_filters(
$client_filter,
@@ -299,6 +299,10 @@ sub new {
),
);
+ # Expand the Args constructor array, and place a copy
+ # into @_[ARG0..]. There are only 2 parameters.
+ splice(@_, ARG0, 2, @{$_[ARG1]});
+
$client_connected->(@_);
},
tcp_server_got_high => $high_event,
@@ -377,6 +381,8 @@ sub new {
package_states => $package_states,
object_states => $object_states,
+ # XXX - If you change the number of args here, also change
+ # the splice elsewhere.
args => [ $socket, $client_args ],
);
};
@@ -670,12 +676,27 @@ POE::Wheel::SocketFactory's C<SuccessEvent>.
Otherwise, the default C<Acceptor> callback will start a new session
to handle each connection. These child sessions do not have their own
aliases, but their C<ClientConnected> and C<ClientDisconnected>
-callbacks may register and unregister the sessions with a shared
-namespace of their own.
+callbacks may be used to register and unregister the sessions with a
+shared namespace, such as a hash keyed on session IDs, or an object
+that manages such a hash.
+
+ my %client_namespace;
+
+ sub handle_client_connected {
+ my $client_session_id = $_[SESSION]->ID;
+ $client_namespace{$client_session_id} = \%anything;
+ }
+
+ sub handle_client_disconnected {
+ my $client_session_id = $_[SESSION]->ID;
+ $client_namespace{$client_session_id} = \%anything;
+ }
The component's C<Started> callback is invoked at the end of the
-master session's startup routine. This callback's parameters are
-the usual ones for C<_start>.
+master session's startup routine. The @_[ARG0..$#_] parameters are
+set to a copy of the values in the server's C<ListenerArgs>
+constructor parameter. The other parameters are standard for
+POE::Session's _start handlers.
The component's C<Error> callback is invoked when the server has a
problem listening for connections. C<Error> may also be called if the
@@ -704,12 +725,17 @@ The component's C<ClientInput> callback defines how child sessions
will handle input from their clients. Its parameters are that of
POE::Wheel::ReadWrite's C<InputEvent>.
+As mentioned
C<ClientConnected> is called at the end of the child session's
-C<_start> routine. In addition to the usual C<_start> parameters, it
-includes the socket in $_[ARG0] and the contents of the component's
-C<Args> constructor parameter in $_[ARG1].
-
-TODO - Should C<Args> be flattened into C<ARG1..$%_>?
+C<_start> routine. The C<ClientConneted> callback receives the same
+parameters as the client session's _start does. The arrayref passed
+to the constructor's C<Args> parameter is flattened and included in
+C<ClientConnected>'s parameters as @_[ARG0..$#_].
+
+ sub handle_client_connected {
+ my @constructor_args = @_[ARG0..$#_];
+ ...
+ }
C<ClientDisconnected> is called when the client has disconnected,
either because the remote socket endpoint has closed or the local
@@ -982,9 +1008,8 @@ interact with established connections.
=head4 ClientArgs
C<ClientArgs> is optional. When specified, it holds an ARRAYREF that
-will be passed to the C<ClientConnected> callback in $_[ARG1].
-(ClientConnected's $_[ARG0] contains the newly accepted client
-socket.)
+will be expanded one level and passed to the C<ClientConnected>
+callback in @_[ARG0..$#_].
=head4 ClientConnected
@@ -993,9 +1018,9 @@ C<ClientConnected> is a callback that notifies the application when a
client's session is started and ready for operation. Banners are
often sent to the remote client from this callback.
-C<ClientConnected> callbacks receive the usual POE parameters plus:
-The newly accepted client socket in $_[ARG0] and the ARRAYREF
-specified in C<ClientArgs> in $_[ARG1].
+The @_[ARG0..$#_] parameters to C<ClientConnected> are a copy of the
+values in the C<ClientArgs> constructor parameter's array referece.
+The other @_ members are standard for a POE::Session _start handler.
C<ClientConnected> is called once per session startup. It will never
be called twice for the same connection.
@@ -1005,8 +1030,6 @@ be called twice for the same connection.
# Other client initialization here.
},
-TODO - Show Args and client socket introspection.
-
=head4 ClientDisconnected
C<ClientDisconnected> is a callback that will be invoked when the
@@ -1331,8 +1354,6 @@ Some use cases require different session classes for the listener and
the connection handlers. This isn't currently supported. Please send
patches. :)
-TODO - Rename C<Args> into C<ClientArgs>.
-
TODO - Document that Reuse is set implicitly.
=head1 AUTHORS & COPYRIGHTS
View
10 poe/t/90_regression/somni-poco-server-tcp.t
@@ -27,7 +27,7 @@ use Test::More tests => 43;
ok_state_top(\@state, 'server started');
ok_state_top(\@state, 'client started');
- ok_state_top(\@state, 'client connected to server: ARRAY');
+ ok_state_top(\@state, 'client connected to server');
ok_state_top(\@state, 'client connected');
ok_state_top(\@state, 'client flushed');
ok_state_any(\@state, 'received from server: I will be serving you today!');
@@ -41,7 +41,7 @@ use Test::More tests => 43;
ok_state_top(\@state, 'server started');
ok_state_top(\@state, 'client started');
- ok_state_top(\@state, 'client connected to server: ARRAY');
+ ok_state_top(\@state, 'client connected to server');
ok_state_top(\@state, 'client connected');
ok_state_top(\@state, 'client flushed');
ok_state_any(\@state, 'received from server: I will be serving you today!');
@@ -52,13 +52,13 @@ use Test::More tests => 43;
}
{
my @state = run(
- ClientArgs => [ {} ],
+ ClientArgs => [ '', \"", {}, [] ],
ListenerArgs => [ [], {}, \"", '' ],
);
ok_state_top(\@state, 'server started: ARRAY HASH SCALAR none');
ok_state_top(\@state, 'client started');
- ok_state_top(\@state, 'client connected to server: ARRAY');
+ ok_state_top(\@state, 'client connected to server: none SCALAR HASH ARRAY');
ok_state_top(\@state, 'client connected');
ok_state_top(\@state, 'client flushed');
ok_state_any(\@state, 'received from server: I will be serving you today!');
@@ -80,7 +80,7 @@ use Test::More tests => 43;
ok_state_top(\@state, 'server started');
ok_state_top(\@state, 'client started');
- ok_state_top(\@state, 'client connected to server: ARRAY');
+ ok_state_top(\@state, 'client connected to server');
ok_state_top(\@state, 'client connected');
ok_state_top(\@state, 'InlineStates test: from server_client_connected');
ok_state_top(\@state, 'ObjectStates test: from server_client_connected');

0 comments on commit a5d3765

Please sign in to comment.