Reputation: 654
I am using a SignalR persistent connection in website A (localhost:6599
). When rendering A/index.html and connecting to /goose (my connection name!), groups are respected over SSE. When copying the code over to website B (localhost:58660
) and changing the $.connection to an absolute URL (http://localhost:6599/goose
), the signalR client from website B does not receive messages sent to the same group.
At the same time, website B can send messages, and the website A client will receive them on the group. Changing from a Group message to a Broadcast and the messages arrive at both website A and B clients.
My code on Website A:
<div id="data"></div>
<script>
$(document).ready(function() {
var connection = $.connection('/goose', "group=123", true);
connection.start().done(function() {
connection.received(function(data) {
console.log(data);
$("#data").html(data);
});
connection.send("123:hooo");
}
);
});
</script>
On the Server Side:
public class GooseConnection : PersistentConnection
{
protected override Task OnConnected(IRequest request, string connectionId)
{
var group = request.QueryString["group"];
return Groups.Add(connectionId, group);
}
protected override Task OnReceived(IRequest request, string connectionId, string data)
{
// Messages are sent with the following format
// group:message
string[] decoded = data.Split(':');
string groupName = decoded[0];
string message = decoded[1];
// Send a message to the specified
return Groups.Send(groupName, message);
}
protected override Task OnDisconnected(IRequest request, string connectionId)
{
return Groups.Remove(connectionId, request.QueryString["group"]);
}
}
My code on Website B:
var connection = null;
$(document).ready(function () {
connection = $.connection('http://localhost:6599/goose', "group=123", true);
connection.start({ jsonp: true }).done(function () {
connection.received(function (data) {
console.log(data);
alert('oooyeah');
$("#data").html(data);
});
connection.send("123:hooo");
}
);
});
function tryagain() {
connection.send("123:hooo");
}
Trace from Website A (sorry about the formatting):
[21:31:58 GMT+0000 (GMT Standard Time)] SignalR: Negotiating with
'/goose/negotiate'. jquery.signalR-1.0.0-rc2.min.js:10 [21:31:58 GMT+0000 (GMT Standard Time)] SignalR: Attempting to connect to SSE endpoint 'http://localhost:6599/goose/connect?transport=serverSentEvents&connectionId=93b07a1b-779f-44e9-87f3-3eb201a97fdd&group=123&tid=0' jquery.signalR-1.0.0-rc2.min.js:10 [21:31:59 GMT+0000 (GMT Standard Time)] SignalR: EventSource connected jquery.signalR-1.0.0-rc2.min.js:10 [21:31:59 GMT+0000 (GMT Standard Time)] SignalR: Now monitoring keep alive with a warning timeout of 40000 and a connection lost timeout of 60000 jquery.signalR-1.0.0-rc2.min.js:10 hooo localhost:18 [21:44:30 GMT+0000 (GMT Standard Time)] SignalR: EventSource readyState: 0 jquery.signalR-1.0.0-rc2.min.js:10 [21:44:30 GMT+0000 (GMT Standard Time)] SignalR: EventSource reconnecting due to the server connection ending jquery.signalR-1.0.0-rc2.min.js:10 [21:44:32 GMT+0000 (GMT Standard Time)] SignalR: EventSource calling close() jquery.signalR-1.0.0-rc2.min.js:10 [21:44:32 GMT+0000 (GMT Standard Time)] SignalR: EventSource reconnecting
Trace from Website B:
[21:30:33 GMT+0000 (GMT Standard Time)] SignalR: Auto detected cross domain url. jquery.signalR-1.0.0-rc2.min.js:10 [21:30:33 GMT+0000 (GMT Standard Time)] SignalR: Negotiating with 'http://localhost:6599/goose/negotiate'. jquery.signalR-1.0.0-rc2.min.js:10 [21:30:33 GMT+0000 (GMT Standard Time)] SignalR: SignalR: Initializing long polling connection with server. jquery.signalR-1.0.0-rc2.min.js:10 [21:30:33 GMT+0000 (GMT Standard Time)] SignalR: Attempting to connect to 'http://localhost:6599/goose/connect?transport=longPolling&connectionId=d01cebe3-28f6-4150-a606-b9d64224edd7&group=123&tid=3' using longPolling. jquery.signalR-1.0.0-rc2.min.js:10 [21:30:33 GMT+0000 (GMT Standard Time)] SignalR: Longpolling connected jquery.signalR-1.0.0-rc2.min.js:10 [21:30:33 GMT+0000 (GMT Standard Time)] SignalR: Attempting to connect to 'http://localhost:6599/goose?transport=longPolling&connectionId=d01cebe3-28f…cloud.Spotify.Goose.Connections.GooseConnection.123%22%5D&group=123&tid=10' using longPolling. jquery.signalR-1.0.0-rc2.min.js:10 [21:32:29 GMT+0000 (GMT Standard Time)] SignalR: Attempting to connect to 'http://localhost:6599/goose?transport=longPolling&connectionId=d01cebe3-28f…acloud.Spotify.Goose.Connections.GooseConnection.123%22%5D&group=123&tid=2' using longPolling. jquery.signalR-1.0.0-rc2.min.js:10
Things I've tried:
Any further debugging advice would be greatly appreciated. Andy
Upvotes: 0
Views: 902
Reputation: 33379
EnableAutoRejoiningGroups
is a feature of the Hubs API and, since you're working at the lower PersistentConnection
API layer, it won't help you. As @halter73 said, OnRejoiningGroups
is the way to do it at the PersistentConnection
layer.
Upvotes: 0
Reputation: 15234
Your issue with groups is likely do to the fact that groups aren't automatically rejoined when a client reconnects. This isn't an issue when running on the same domain because your clients are likely using the forever-frame or server-sent-events transport which won't reconnect unless there is some issue with the underlying connection.
However, cross-origin access to SignalR requires either the WebSocket or long-polling transport. The latter is likely being used in your case considering the issue you are having with groups. (NOTE: Your SignalR server needs to be running .NET 4.5 on Windows 8 or 2012 to support WebSockets). The long-polling transport has to reconnect to the SignalR server every time it receives messages.
To fix this issue, add the following:
public class GooseConnection : PersistentConnection
{
protected override IEnumerable<string> OnRejoiningGroups(IRequest request, IEnumerable<string> groups, string connectionId)
{
return groups;
}
}
By overriding OnRejoiningGroups
to return the groups
parameter instead of an empty collection, you are allowing clients to rejoin all the groups they were previously in when they reconnect. However, SignalR, as of RC2, doesn't verify the reconnecting clients were really previously in those groups they are trying to rejoin. The groups
parameter is simply pulled from the query string of the reconnect request. Of course, a well-behaving client will only try to rejoin groups it was previously in, but enabling automatic group rejoining on RC2 allows attackers to add themselves to any group. This is not an issue for many applications, but that's why group rejoining isn't enabled by default.
In the RTM version of SignalR, automatic group rejoining will be enabled by default. The list of groups the client tries to rejoin with will also be signed by the server making it much more secure.
Upvotes: 1