[Slim-Checkins] r33928 - in /7.8/trunk/server/Slim: Control/Queries.pm Web/Cometd.pm
[email protected] Wed, 04 Apr 2012 15:34:41 -0000
| Newsgroups | gmane.music.equipment.slimdevices.cvs |
|---|---|
| Message-ID | <[email protected]> |
Author: ayoung
Date: Wed Apr 4 08:34:41 2012
New Revision: 33928
URL: http://svn.slimdevices.com/slim?rev=33928&view=rev
Log:
Resolve a couple of problems player-status subscription reliability.
Need to extract clientId from /slim/unsubscribe Comet requests. This was one of the causes of SP clients not always reconnecting "completely". If the first request in a packet was an unsubscribe then the whole packey would be dropped.
Do not remove the repeating subscription from a (player)status query when the client has gone as otherwise a Comet subscription can be dropped.
Do not give up processing requests from a Comet packet upon any error, other than conditions that explicitly do this.
Stop processing requests from a Comet packet after getting a subscription request that results in an errorNeedClient condition.
Remove duplicate checking for valid clientId.
Modified:
7.8/trunk/server/Slim/Control/Queries.pm
7.8/trunk/server/Slim/Web/Cometd.pm
Modified: 7.8/trunk/server/Slim/Control/Queries.pm
URL: http://svn.slimdevices.com/slim/7.8/trunk/server/Slim/Control/Queries.pm?rev=33928&r1=33927&r2=33928&view=diff
==============================================================================
--- 7.8/trunk/server/Slim/Control/Queries.pm (original)
+++ 7.8/trunk/server/Slim/Control/Queries.pm Wed Apr 4 08:34:41 2012
@@ -3004,9 +3004,10 @@
# accomodate the fact we can be called automatically when the client is gone
if (!defined($client)) {
$request->addResult('error', "invalid player");
- $request->registerAutoExecute('-');
- $request->setStatusDone();
- return;
+ # Still need to (re)register the autoexec if this is a subscription so
+ # that the subscription does not dissappear while a Comet client thinks
+ # that it is still valid.
+ goto do_it_again;
}
my $connected = $client->connected() || 0;
@@ -3404,7 +3405,7 @@
}
}
-
+do_it_again:
# manage the subscription
if (defined(my $timeout = $request->getParam('subscribe'))) {
main::DEBUGLOG && $isDebug && $log->debug("statusQuery(): setting up subscription");
Modified: 7.8/trunk/server/Slim/Web/Cometd.pm
URL: http://svn.slimdevices.com/slim/7.8/trunk/server/Slim/Web/Cometd.pm?rev=33928&r1=33927&r2=33928&view=diff
==============================================================================
--- 7.8/trunk/server/Slim/Web/Cometd.pm (original)
+++ 7.8/trunk/server/Slim/Web/Cometd.pm Wed Apr 4 08:34:41 2012
@@ -176,6 +176,10 @@
# Pull clientId out of response channel
($clid) = $obj->{data}->{response} =~ m{/([0-9a-f]{8})/};
}
+ elsif ( $obj->{channel} =~ m{^/slim/unsubscribe} && $obj->{data} ) {
+ # Pull clientId out of unsubscribe
+ ($clid) = $obj->{data}->{unsubscribe} =~ m{/([0-9a-f]{8})/};
+ }
# Register client with HTTP connection
if ( $clid ) {
@@ -189,10 +193,14 @@
error => 'No clientId found',
id => $obj->{id},
};
- }
- }
-
- last if @errors;
+
+ # No point in trying to process requests without a clientId
+ # Given that we are not sending advice to the client, the pending
+ # requests may just get dropped but what can we do?
+ $log->error('Invalid request without clientId - discarding remaining requests in packet');
+ last;
+ }
+ }
# Detect the language Jive wants content returned in
my ($lang, $ua);
@@ -325,76 +333,42 @@
}
elsif ( $obj->{channel} eq '/meta/subscribe' ) {
- if ( !$manager->is_valid_clid( $clid ) ) {
- # Invalid clientId, send advice to re-handshake
-
+ my $subscriptions = $obj->{subscription};
+
+ # a channel name or a channel pattern or an array of channel names and channel patterns.
+ if ( !ref $subscriptions ) {
+ $subscriptions = [ $subscriptions ];
+ }
+
+ $manager->add_channels( $clid, $subscriptions );
+
+ for my $sub ( @{$subscriptions} ) {
push @{$events}, {
- channel => '/meta/subscribe',
- clientId => undef,
- successful => JSON::XS::false,
- timestamp => time2str( time() ),
- error => 'invalid clientId',
- advice => {
- reconnect => 'handshake',
- interval => 0,
- }
+ channel => '/meta/subscribe',
+ clientId => $clid,
+ successful => JSON::XS::true,
+ subscription => $sub,
};
}
- else {
- my $subscriptions = $obj->{subscription};
-
- # a channel name or a channel pattern or an array of channel names and channel patterns.
- if ( !ref $subscriptions ) {
- $subscriptions = [ $subscriptions ];
- }
-
- $manager->add_channels( $clid, $subscriptions );
-
- for my $sub ( @{$subscriptions} ) {
- push @{$events}, {
- channel => '/meta/subscribe',
- clientId => $clid,
- successful => JSON::XS::true,
- subscription => $sub,
- };
- }
- }
}
elsif ( $obj->{channel} eq '/meta/unsubscribe' ) {
- if ( !$manager->is_valid_clid( $clid ) ) {
- # Invalid clientId, send advice to re-handshake
-
+ my $subscriptions = $obj->{subscription};
+
+ # a channel name or a channel pattern or an array of channel names and channel patterns.
+ if ( !ref $subscriptions ) {
+ $subscriptions = [ $subscriptions ];
+ }
+
+ $manager->remove_channels( $clid, $subscriptions );
+
+ for my $sub ( @{$subscriptions} ) {
push @{$events}, {
- channel => '/meta/unsubscribe',
- clientId => undef,
- successful => JSON::XS::false,
- timestamp => time2str( time() ),
- error => 'invalid clientId',
- advice => {
- reconnect => 'handshake',
- interval => 0,
- }
+ channel => '/meta/unsubscribe',
+ clientId => $clid,
+ subscription => $sub,
+ successful => JSON::XS::true,
};
- }
- else {
- my $subscriptions = $obj->{subscription};
-
- # a channel name or a channel pattern or an array of channel names and channel patterns.
- if ( !ref $subscriptions ) {
- $subscriptions = [ $subscriptions ];
- }
-
- $manager->remove_channels( $clid, $subscriptions );
-
- for my $sub ( @{$subscriptions} ) {
- push @{$events}, {
- channel => '/meta/unsubscribe',
- clientId => $clid,
- subscription => $sub,
- successful => JSON::XS::true,
- };
- }
}
}
elsif ( $obj->{channel} eq '/slim/subscribe' ) {
@@ -441,7 +415,10 @@
id => $id,
};
+ push @errors, \%error;
+
if ($result->{'errorNeedClient'}) {
+ $log->error('errorNeedsClient: ', join(', ', $request->[0], @{$request->[1]}));
# Force reconnect because client not connected.
# We should not need to force a new handshake, just a reconect.
# Any successful subscribes will have the acknowledgements in the $events queue
@@ -450,9 +427,12 @@
$error{'advice'} = {
reconnect => 'retry',
};
+
+ # The client will stop processing responses after this error with reconnect advice
+ # so stop processing further requests.
+ last;
}
- push @errors, \%error;
}
else {
push @{$events}, {
@@ -930,7 +910,7 @@
sub requestCallback {
my $request = shift;
- my ($channel, $id, $priority, $clid) = split /\|/, $request->source, 4;
+ my ($channel, $id, $priority, $clid) = split (/\|/, $request->source, 4);
main::DEBUGLOG && $log->debug( "requestCallback got results for $channel / $id" );