Skip to content
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

Enable websocket polling for netcore #431

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
</ItemGroup>

<PropertyGroup Condition=" '$(TargetFramework)' == 'net48' ">
<DefineConstants>$(DefineConstants);SUPPORTS_WEB_SOCKET_CLIENT;DOES_NOT_SUPPORT_CANCELLATION_ON_SOCKETS</DefineConstants>
<DefineConstants>$(DefineConstants);DOES_NOT_SUPPORT_CANCELLATION_ON_SOCKETS</DefineConstants>
</PropertyGroup>

<ItemGroup>
Expand Down
2 changes: 0 additions & 2 deletions source/Halibut.Tests.DotMemory/MemoryFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,8 @@ public void TcpClientsAreDisposedCorrectly()
RunPollingClient(server, Certificates.TentaclePolling, Certificates.TentaclePollingPublicThumbprint);
}

#if SUPPORTS_WEB_SOCKET_CLIENT
for (var i = 0; i < NumberOfClients; i++)
RunWebSocketPollingClient(server, Certificates.TentaclePolling, Certificates.TentaclePollingPublicThumbprint, Certificates.OctopusPublicThumbprint);
#endif

//https://dotnettools-support.jetbrains.com/hc/en-us/community/posts/360000088690-How-reproduce-DotMemory-s-Force-GC-button-s-behaviour-on-code-with-c-?page=1#community_comment_360000072750
for (var i = 0; i < 4; i++)
Expand Down
2 changes: 0 additions & 2 deletions source/Halibut.Tests/BindCertificatesForAllTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@ public class TestsSetupClass
[OneTimeSetUp]
public void GlobalSetup()
{
#if SUPPORTS_WEB_SOCKET_CLIENT
WebSocketSslCertificateHelper.AddSslCertToLocalStore();
#endif
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion source/Halibut.Tests/Halibut.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
</ItemGroup>

<PropertyGroup Condition=" '$(TargetFramework)' == 'net48' ">
<DefineConstants>$(DefineConstants);SUPPORTS_WEB_SOCKET_CLIENT;DOES_NOT_SUPPORT_CANCELLATION_ON_SOCKETS</DefineConstants>
<DefineConstants>$(DefineConstants);DOES_NOT_SUPPORT_CANCELLATION_ON_SOCKETS</DefineConstants>
</PropertyGroup>

<ItemGroup>
Expand Down
10 changes: 4 additions & 6 deletions source/Halibut.Tests/Support/ServiceConnectionType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,10 @@ public enum ServiceConnectionType
public static class ServiceConnectionTypes
{
public static ServiceConnectionType[] All => new[]
{
ServiceConnectionType.Listening,
ServiceConnectionType.Polling,
#if SUPPORTS_WEB_SOCKET_CLIENT
ServiceConnectionType.PollingOverWebSocket
#endif
{
ServiceConnectionType.Listening,
ServiceConnectionType.Polling,
ServiceConnectionType.PollingOverWebSocket
};

public static ServiceConnectionType[] AllExceptWebSockets => new[]
Expand Down
2 changes: 1 addition & 1 deletion source/Halibut/Halibut.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
</PropertyGroup>

<PropertyGroup Condition=" '$(TargetFramework)' == 'net48' ">
<DefineConstants>$(DefineConstants);HAS_REAL_PROXY;SUPPORTS_WEB_SOCKET_CLIENT</DefineConstants>
<DefineConstants>$(DefineConstants);HAS_REAL_PROXY</DefineConstants>
</PropertyGroup>

<ItemGroup>
Expand Down
4 changes: 0 additions & 4 deletions source/Halibut/HalibutRuntime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -186,11 +186,7 @@ public void Poll(Uri subscription, ServiceEndPoint endPoint, CancellationToken c
var log = logs.ForEndpoint(endPoint.BaseUri);
if (endPoint.IsWebSocketEndpoint)
{
#if SUPPORTS_WEB_SOCKET_CLIENT
client = new SecureWebSocketClient(ExchangeProtocolBuilder(), endPoint, serverCertificate, TimeoutsAndLimits, log, connectionManager);
#else
throw new NotSupportedException("The netstandard build of this library cannot act as the client in a WebSocket polling setup");
#endif
}
else
{
Expand Down
2 changes: 0 additions & 2 deletions source/Halibut/Transport/SecureWebSocketClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
// See https://github.com/dotnet/corefx/issues/12038

using Halibut.Util;
#if SUPPORTS_WEB_SOCKET_CLIENT
using System;
using System.Diagnostics;
using System.Net.Sockets;
Expand Down Expand Up @@ -255,4 +254,3 @@ void HandleError(Exception lastError, bool retryAllowed)
}
}
}
#endif
4 changes: 1 addition & 3 deletions source/Halibut/Transport/ServerCertificateInterceptor.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#if SUPPORTS_WEB_SOCKET_CLIENT
using System;
using System.Collections.Generic;
using System.Net;
Expand Down Expand Up @@ -68,5 +67,4 @@ public static void Validate(string connectionId, ServiceEndPoint endPoint)
throw new UnexpectedCertificateException(providedCertificate, endPoint);
}
}
}
#endif
}
38 changes: 33 additions & 5 deletions source/Halibut/Transport/WebSocketConnectionFactory.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#if SUPPORTS_WEB_SOCKET_CLIENT
using System;
using System.Net;
using System.Net.Security;
using System.Net.WebSockets;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
Expand Down Expand Up @@ -72,19 +72,30 @@ ClientWebSocket CreateConnectedClient(ServiceEndPoint serviceEndpoint, Cancellat
client.Options.ClientCertificates = new X509Certificate2Collection(new X509Certificate2Collection(clientCertificate));
client.Options.AddSubProtocol("Octopus");
client.Options.SetRequestHeader(ServerCertificateInterceptor.Header, connectionId);
#if NETCOREAPP
client.Options.RemoteCertificateValidationCallback = (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
=> ValidateRemoteCert(serviceEndpoint, certificate, sslPolicyErrors);
#endif


if (serviceEndpoint.Proxy != null)
client.Options.Proxy = new WebSocketProxy(serviceEndpoint.Proxy);

try
{
#if !NETCOREAPP
ServerCertificateInterceptor.Expect(connectionId);
#endif
using (var cts = new CancellationTokenSource(serviceEndpoint.TcpClientConnectTimeout))
{
using (cancellationToken.Register(() => cts?.Cancel()))
client.ConnectAsync(serviceEndpoint.BaseUri, cts.Token)
.ConfigureAwait(false).GetAwaiter().GetResult();
}

#if !NETCOREAPP
ServerCertificateInterceptor.Validate(connectionId, serviceEndpoint);
#endif
}
catch
{
Expand All @@ -96,14 +107,16 @@ ClientWebSocket CreateConnectedClient(ServiceEndPoint serviceEndpoint, Cancellat
client.Dispose();
throw;
}
#if !NETCOREAPP
finally
{
ServerCertificateInterceptor.Remove(connectionId);
}
#endif

return client;
}

async Task<ClientWebSocket> CreateConnectedClientAsync(ServiceEndPoint serviceEndpoint, CancellationToken cancellationToken)
{
if (!serviceEndpoint.IsWebSocketEndpoint)
Expand All @@ -117,18 +130,26 @@ async Task<ClientWebSocket> CreateConnectedClientAsync(ServiceEndPoint serviceEn
client.Options.SetRequestHeader(ServerCertificateInterceptor.Header, connectionId);
if (serviceEndpoint.Proxy != null)
client.Options.Proxy = new WebSocketProxy(serviceEndpoint.Proxy);
#if NETCOREAPP
client.Options.RemoteCertificateValidationCallback = (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
=> ValidateRemoteCert(serviceEndpoint, certificate, sslPolicyErrors);
#endif

try
{
#if !NETCOREAPP
ServerCertificateInterceptor.Expect(connectionId);
#endif
using (var cts = new CancellationTokenSource(serviceEndpoint.TcpClientConnectTimeout))
{
using (cancellationToken.Register(() => cts?.Cancel()))
{
await client.ConnectAsync(serviceEndpoint.BaseUri, cts.Token);
}
}
#if !NETCOREAPP
ServerCertificateInterceptor.Validate(connectionId, serviceEndpoint);
#endif
}
catch
{
Expand All @@ -140,13 +161,21 @@ async Task<ClientWebSocket> CreateConnectedClientAsync(ServiceEndPoint serviceEn
client.Dispose();
throw;
}
#if !NETCOREAPP
finally
{
ServerCertificateInterceptor.Remove(connectionId);
}

#endif
return client;
}

private static bool ValidateRemoteCert(ServiceEndPoint serviceEndPoint, X509Certificate certificate, SslPolicyErrors sslPolicyErrors)
{
if (certificate == null) return false;

return new X509Certificate2(certificate).Thumbprint == serviceEndPoint.RemoteThumbprint;
}
}

class WebSocketProxy : IWebProxy
Expand All @@ -172,5 +201,4 @@ public WebSocketProxy(ProxyDetails proxy)

public ICredentials Credentials { get; set; }
}
}
#endif
}