Skip to content

SignalR Negotiate protocol versioning #13389

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Sep 4, 2019

Conversation

mikaelm12
Copy link
Contributor

This includes the changes for the server and the .NET client. Still polishing but ready for some review
Spec: https://github.com/aspnet/specs/pull/325

Copy link
Member

@BrennanConroy BrennanConroy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quick first pass

@Pilchie Pilchie added the area-signalr Includes: SignalR clients and servers label Aug 26, 2019
@mikaelm12 mikaelm12 marked this pull request as ready for review August 27, 2019 16:50
@@ -428,8 +429,10 @@ private async Task<NegotiationResponse> NegotiateAsync(Uri url, HttpClient httpC
urlBuilder.Path += "/";
}
urlBuilder.Path += "negotiate";
//urlBuilder.Query = $"version={_protocolVersionNumber}";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

Suggested change
//urlBuilder.Query = $"version={_protocolVersionNumber}";

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
//urlBuilder.Query = $"version={_protocolVersionNumber}";

It looks like a follow up commit overwrote this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, idk what happened here

Version = options.MinimumProtocolVersion
};

if (context.Request.Query.TryGetValue("version", out var queryStringVersion))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the client doesn't pass a version and a minimum protocol version is specified via options, shouldn't that connection also be rejected?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

options, shouldn't that connection also be rejected?

No version from the client implies V1 so if the minimum specified through options on the server is greater than that (it should be greater than V1 it it's explicitly set) we should reject the connection.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't look like there is a check for that though

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added

/// Gets or sets the minimum protocol verison supported by the server.
/// The default value is 0, the lowest possible protocol version.
/// </summary>
public int MinimumProtocolVersion { get; set; } = 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if this is set to a non-default value and a client tries to connection without negotiating?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this was an open question in the design doc. I think your suggestion there of having an option to reject clients that skip negotiation seems reasonable. Otherwise you're left in a weird position where the client and server are unaware of each other's capabilities.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 We can always revisit if the default MinimumProtocolVersion ever goes above 0.

Version = options.MinimumProtocolVersion
};

if (context.Request.Query.TryGetValue("version", out var queryStringVersion))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't look like there is a check for that though

@mikaelm12 mikaelm12 force-pushed the mikaelm12/NegotiateProtocolVersioning branch from 1716fae to 24417fa Compare August 28, 2019 21:48
{
response.Version = clientProtocolVersion;
}
} else if (options.MinimumProtocolVersion > 0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
} else if (options.MinimumProtocolVersion > 0)
}
else if (options.MinimumProtocolVersion > 0)

var clientProtocolVersion = int.Parse(queryStringVersion.ToString());
if (clientProtocolVersion < options.MinimumProtocolVersion)
{
response.Error = $"The client requested version '{clientProtocolVersion}', but the server does not support this version.";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this message should include what the server-configure min protocol version is.

@halter73
Copy link
Member

It might be nice to rename the "version" query string parameter and negotiate property to "protocolVersion" or similar so customers don't think this is supposed to match the SiganlR package version.

@mikaelm12
Copy link
Contributor Author

It might be nice to rename the "version" query string parameter and negotiate property to "protocolVersion"

ProtocolVersion is taken
https://github.com/aspnet/AspNetCore/blob/bcdc9b08dfbb79ca6b8780e9ef5f9cabba67f71d/src/SignalR/common/Http.Connections.Common/src/NegotiateProtocol.cs#L160-L163

We can use NegotiateVersion if no one hates it too much

var clientProtocolVersion = int.Parse(queryStringVersion.ToString());
if (clientProtocolVersion < options.MinimumProtocolVersion)
{
response.Error = $"The client requested version '{clientProtocolVersion}', but the server does not support this version.";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might want to log on the server here and the one below?

response.AvailableTransports = new List<AvailableTransport>();
var response = new NegotiationResponse
{
ConnectionId = connectionId,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should delay setting this until we know the client is compatible, and perhaps we should invalidate the ID too if there is an error. Or maybe we can delay even creating the connectionId and do the version checking earlier?

@mikaelm12
Copy link
Contributor Author

Note to self to add a test for client sending an invalid version in the query string

@halter73
Copy link
Member

I think NegotiateVersion is fine.

Copy link
Member

@BrennanConroy BrennanConroy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to update the transport spec document too!

return;
}

if (response.Version > 0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per the spec, the server should send back the version even for clients that don't support versions yet.

This could be useful for bug reports where we see people with "version" in the negotiate but are using <=3.0 clients.

@mikaelm12
Copy link
Contributor Author

@aspnet-hello
Copy link

This comment was made automatically. If there is a problem contact [email protected].

I've triaged the above build. I've created/commented on the following issue(s)
https://github.com/aspnet/AspNetCore-Internal/issues/3057

@mikaelm12
Copy link
Contributor Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-signalr Includes: SignalR clients and servers
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants