Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
1 change: 1 addition & 0 deletions AspNetCore.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -890,6 +890,7 @@
</Folder>
<Folder Name="/src/Servers/HttpSys/samples/">
<Project Path="src/Servers/HttpSys/samples/HotAddSample/HotAddSample.csproj" />
<Project Path="src/Servers/HttpSys/samples/MinimalSample/MinimalSample.csproj" />
<Project Path="src/Servers/HttpSys/samples/QueueSharing/QueueSharing.csproj" />
<Project Path="src/Servers/HttpSys/samples/SelfHostServer/SelfHostServer.csproj" />
<Project Path="src/Servers/HttpSys/samples/TestClient/TestClient.csproj" />
Expand Down
1 change: 1 addition & 0 deletions src/Servers/HttpSys/HttpSysServer.slnf
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"src\\Servers\\Connections.Abstractions\\src\\Microsoft.AspNetCore.Connections.Abstractions.csproj",
"src\\Servers\\HttpSys\\perf\\Microbenchmarks\\Microsoft.AspNetCore.Server.HttpSys.Microbenchmarks.csproj",
"src\\Servers\\HttpSys\\samples\\HotAddSample\\HotAddSample.csproj",
"src\\Servers\\HttpSys\\samples\\MinimalSample\\MinimalSample.csproj",
"src\\Servers\\HttpSys\\samples\\QueueSharing\\QueueSharing.csproj",
"src\\Servers\\HttpSys\\samples\\SelfHostServer\\SelfHostServer.csproj",
"src\\Servers\\HttpSys\\samples\\TestClient\\TestClient.csproj",
Expand Down
14 changes: 14 additions & 0 deletions src/Servers/HttpSys/samples/MinimalSample/MinimalSample.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
<OutputType>Exe</OutputType>
</PropertyGroup>

<ItemGroup>
<Reference Include="Microsoft.AspNetCore" />
<Reference Include="Microsoft.AspNetCore.Server.HttpSys" />
<Reference Include="Microsoft.Extensions.Hosting" />
<Reference Include="Microsoft.Extensions.Logging.Console" />
</ItemGroup>
</Project>
43 changes: 43 additions & 0 deletions src/Servers/HttpSys/samples/MinimalSample/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Buffers;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.InteropServices;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;

Check failure on line 11 in src/Servers/HttpSys/samples/MinimalSample/Program.cs

View check run for this annotation

Azure Pipelines / aspnetcore-quarantined-pr (Tests: macOS)

src/Servers/HttpSys/samples/MinimalSample/Program.cs#L11

src/Servers/HttpSys/samples/MinimalSample/Program.cs(11,33): error CS0234: (NETCORE_ENGINEERING_TELEMETRY=Build) The type or namespace name 'Features' does not exist in the namespace 'Microsoft.AspNetCore.Http' (are you missing an assembly reference?)

Check failure on line 11 in src/Servers/HttpSys/samples/MinimalSample/Program.cs

View check run for this annotation

Azure Pipelines / aspnetcore-quarantined-pr

src/Servers/HttpSys/samples/MinimalSample/Program.cs#L11

src/Servers/HttpSys/samples/MinimalSample/Program.cs(11,33): error CS0234: (NETCORE_ENGINEERING_TELEMETRY=Build) The type or namespace name 'Features' does not exist in the namespace 'Microsoft.AspNetCore.Http' (are you missing an assembly reference?)
using Microsoft.AspNetCore.Server.HttpSys;
using Microsoft.Extensions.Hosting;

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.UseHttpSys(options =>
{
options.UrlPrefixes.Add("http://*:42000");

options.Authentication.Schemes = AuthenticationSchemes.None;
options.Authentication.AllowAnonymous = true;
});

var app = builder.Build();

app.Use(async (context, next) =>
{
var connectionFeature = context.Features.GetRequiredFeature<IHttpConnectionFeature>();

var response = $"""
ConnectionInfo:
- HttpContext.Connection.LocalPort : {context.Connection.LocalPort}
- HttpContext.Connection.RemotePort : {context.Connection.RemotePort}
- IHttpConnectionFeature.LocalPort : {connectionFeature.LocalPort}
- IHttpConnectionFeature.RemotePort : {connectionFeature.RemotePort}
""";

await context.Response.WriteAsync(response);
await next(context);
});

app.Run();
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"profiles": {
"MinimalSample": {
"commandName": "Project",
"launchBrowser": true,
"applicationUrl": "http://localhost:42000",
"nativeDebugging": true
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Net;
using Microsoft.AspNetCore.HttpSys.Internal;
using Windows.Win32.Networking.WinSock;
using Xunit;
using static Microsoft.AspNetCore.HttpSys.Internal.SocketAddress;
using SocketAddress = Microsoft.AspNetCore.HttpSys.Internal.SocketAddress;

namespace Microsoft.AspNetCore.Server.HttpSys.Tests.NativeInterop;

public class SocketAddressTests
{
[Theory]
[InlineData(80)]
[InlineData(443)]
[InlineData(8080)]
[InlineData(32767)] // max signed short
[InlineData(32768)] // min value that causes negative when cast to short
[InlineData(42000)]
[InlineData(65535)] // Max port number
public void IPv6_GetPort_ReturnsCorrectPort_ForAllValidPorts(ushort expectedPort)
{
var nativeIpV6Address = new SOCKADDR_IN6
{
sin6_family = ADDRESS_FAMILY.AF_INET6,
sin6_port = (ushort)IPAddress.HostToNetworkOrder((short)expectedPort)
};

var socketAddress = new SocketAddressIPv6(nativeIpV6Address);
var actualPort = socketAddress.GetPort();

Assert.Equal(expectedPort, actualPort);
Assert.True(actualPort >= 0, "Port should never be negative");
Assert.True(actualPort <= 65535, "Port should not exceed maximum valid port");
}

[Theory]
[InlineData(80)]
[InlineData(443)]
[InlineData(8080)]
[InlineData(42000)]
[InlineData(32767)]
[InlineData(32768)]
[InlineData(65535)]
public void IPv4_GetPort_ReturnsCorrectPort_ForAllValidPorts(ushort expectedPort)
{
var nativeIpV4Address = new SOCKADDR_IN
{
sin_family = ADDRESS_FAMILY.AF_INET,
sin_port = (ushort)IPAddress.HostToNetworkOrder((short)expectedPort)
};

var socketAddress = new SocketAddressIPv4(nativeIpV4Address);
var actualPort = socketAddress.GetPort();

Assert.Equal(expectedPort, actualPort);
Assert.True(actualPort >= 0, "Port should never be negative");
Assert.True(actualPort <= 65535, "Port should not exceed maximum valid port");
}
}
17 changes: 11 additions & 6 deletions src/Shared/HttpSys/NativeInterop/SocketAddress.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Buffers.Binary;
using System.Net;
using Windows.Win32.Networking.WinSock;

Expand All @@ -25,7 +26,8 @@ internal abstract class SocketAddress
};
}

private sealed class SocketAddressIPv4 : SocketAddress
// internal for testing
internal sealed class SocketAddressIPv4 : SocketAddress
{
private readonly SOCKADDR_IN _sockaddr;

Expand All @@ -36,8 +38,9 @@ internal SocketAddressIPv4(in SOCKADDR_IN sockaddr)

internal override int GetPort()
{
// sin_port is network byte order
return IPAddress.NetworkToHostOrder((short)_sockaddr.sin_port);
// _sockaddr.sin_port has network byte order.
// cast to ushort is important to avoid negative values for the TCP port
return (ushort)IPAddress.NetworkToHostOrder((short)_sockaddr.sin_port);
}

internal override IPAddress? GetIPAddress()
Expand All @@ -47,7 +50,8 @@ internal override int GetPort()
}
}

private sealed class SocketAddressIPv6 : SocketAddress
// internal for testing
internal sealed class SocketAddressIPv6 : SocketAddress
{
private readonly SOCKADDR_IN6 _sockaddr;

Expand All @@ -58,8 +62,9 @@ internal SocketAddressIPv6(in SOCKADDR_IN6 sockaddr)

internal override int GetPort()
{
// sin6_port is network byte order
return IPAddress.NetworkToHostOrder((short)_sockaddr.sin6_port);
// _sockaddr.sin6_port has network byte order.
// cast to ushort is important to avoid negative values for the TCP port
return (ushort)IPAddress.NetworkToHostOrder((short)_sockaddr.sin6_port);
}

internal override IPAddress? GetIPAddress()
Expand Down
Loading