Open czmirek opened 1 year ago
Is this code resulting in a HTTP/2 request? https://github.com/czmirek/maui_droid_linuxazapp_grpc_bug/blob/83816204207fe245837ae22396601acf7a87ba31/MauiTest/MainPage.xaml.cs#L34-L43
It's probably HTTP/1.1. You can check by looking at HttpResponseMessage.Version
.
Edit: On further thought, it might be HTTP/2. Note that the gRPC channel uses SocketsHttpHandler
internally, and it might have different behavior than the default HTTP handler. HttpClient client = new HttpClient(new SocketsHttpHandler())
would be more equivalent with gRPC.
@steveisok Do you know if there are certain versions of Android where HTTP/2 is supported with SocketsHttpHandler
? If not, could you recommend someone who would know?
@JamesNK I will look into this issue next week. It's possible we already fixed this problem with some recent improvements in .NET 8.
I looked into the issue and I have a few notes:
HttpClient
uses the native AndroidMessageHandler
from Xamarin under the hood by default and it can't do HTTP/2 requests.Simplified repro:
var handler = new SocketsHttpHandler();
var client = new HttpClient(handler)
{
DefaultRequestVersion = new Version(2, 0),
DefaultVersionPolicy = HttpVersionPolicy.RequestVersionExact
};
var response = await client.GetAsync("https://www.github.com/"); // -- throws on Android 9
Console.WriteLine(response);
I haven't been able to narrow down what exactly is going on with Android 9 (and older) yet.
@JamesNK When do you expect this issue to be fixed? Or are there any alternative ways to avoid this?
Any updates on this? Been looking for a workaround / solution for multiple days now. We are stuck at the moment.
After allot of digging through the dotnet runtime it eventually comes down to this function
This function is defined from api level 29
which is called here in the dotnet framework:
with further definitions in:
https://github.com/dotnet/runtime/blob/main/src/native/libs/System.Security.Cryptography.Native.Android/pal_ssl.c#L55 and https://github.com/dotnet/runtime/blob/main/src/native/libs/System.Security.Cryptography.Native.Android/pal_jni.c#L83
When this function is not present (below api 29), ALPN does not work. http/2 is not set in the handshake.
@Sevenish thanks for the detailed investigation and explanation. I looked through Android API docs and I can't find any alternative APIs that could be used on older versions. I wonder if we might use some private java APIs that would allow us to implement ALPN on older Android versions.
OkHttp uses BoringSLL
If you look through their issues history they where struggling the the native jave SSL and support for ALPN and http/2 in the past. They opted for using BoringSSL on android and support ALPN http/2 from android 5 and up
https://square.github.io/okhttp/security/security_providers/
OkHttp also mentions Conscrypt which uses BoringSSL https://source.android.com/docs/core/ota/modular-system/conscrypt
It seems android made a switch to using conscrypt under the hood in android 10 (api 29) https://source.android.com/docs/core/ota/modular-system/conscrypt
Conscrypt works from api level 9 and up https://github.com/google/conscrypt
conscrypt is where the actual implementation of the missing function is located: https://github.com/google/conscrypt/blob/master/common/src/main/java/org/conscrypt/SSLParametersImpl.java
I did read that conscrypt used to be installed on older android versions with google play services with a feature called 'Google Play Services Dynamic Security Provider'
What version of gRPC and what language are you using?
C# .NET 7 proto3 Visual Studio Version 17.5.5 Grpc.Net.Client 2.53.0 Grpc.Tools 2.54.0 Google.Protobuf 3.23.0
What operating system (Linux, Windows,...) and version?
Server = Azure WebApp running on linux Failing clients = Android 9 and older Successful Clients = Android 10 and newer
What runtime / compiler are you using (e.g. .NET Core SDK version
dotnet --info
).NET SDK: Version: 7.0.203 Commit: 5b005c19f5
Runtime Environment: OS Name: Windows OS Version: 10.0.22621 OS Platform: Windows RID: win10-x64 Base Path: C:\Program Files\dotnet\sdk\7.0.203\
Host: Version: 7.0.5 Architecture: x64 Commit: 8042d61b17
.NET SDKs installed: 6.0.311 [C:\Program Files\dotnet\sdk] 6.0.400-preview.22330.6 [C:\Program Files\dotnet\sdk] 7.0.100 [C:\Program Files\dotnet\sdk] 7.0.203 [C:\Program Files\dotnet\sdk]
.NET runtimes installed: Microsoft.AspNetCore.App 6.0.6 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 6.0.10 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 6.0.16 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 7.0.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.NETCore.App 6.0.6 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 6.0.10 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 6.0.12 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 6.0.15 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 6.0.16 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 7.0.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.WindowsDesktop.App 6.0.6 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 6.0.10 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 6.0.15 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 6.0.16 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 7.0.5 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Other architectures found: x86 [C:\Program Files (x86)\dotnet] registered at [HKLM\SOFTWARE\dotnet\Setup\InstalledVersions\x86\InstallLocation]
Environment variables: Not set
global.json file: Not found
Learn more: https://aka.ms/dotnet/info
Download .NET: https://aka.ms/dotnet/download
What did you do?
I have prepared a repository with a Visual Studio for you to test here: https://github.com/czmirek/maui_droid_linuxazapp_grpc_bug
MainPage.xaml.cs
const string testUrl = "https://YOURAPP.azurewebsites.net";
Error starting gRPC call. HttpRequestException: Requesting HTTP version 2.0 with version policy RequestVersionOrHigher while unable to estabilish HTTP/2 connection.
What did you expect to see?
For Android 9 or lower:
What did you see instead?
Exception is thrown.
Error starting gRPC call. HttpRequestException: Requesting HTTP version 2.0 with version policy RequestVersionOrHigher while unable to estabilish HTTP/2 connection.
Anything else we should know about your project / environment?