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

Add IPAddress Span-based APIs #22918

Closed
3 tasks
stephentoub opened this issue Jul 25, 2017 · 8 comments · Fixed by dotnet/corefx#23224
Closed
3 tasks

Add IPAddress Span-based APIs #22918

stephentoub opened this issue Jul 25, 2017 · 8 comments · Fixed by dotnet/corefx#23224
Assignees
Labels
api-approved API was approved in API review, it can be implemented area-System.Net help wanted [up-for-grabs] Good issue for external contributors tenet-performance Performance related issue
Milestone

Comments

@stephentoub
Copy link
Member

Separated out of https://github.com/dotnet/corefx/issues/21281 for tracking purposes.

  • Implement in System.Net.Primitives in corefx
  • Expose from System.Net.Primitives contract in corefx
  • Add tests to System.Net.Primitives tests in corefx
namespace System.Net
{
    public class IPAddress
    {
        public IPAddress(ReadOnlySpan<byte> address);
        public IPAddress(ReadOnlySpan<byte> address, long scopeid);

        public bool TryWriteBytes(Span<byte> destination, out int bytesWritten);

        public static IPAddress Parse(ReadOnlySpan<char> ipChars);
        public static bool TryParse(ReadOnlySpan<char> ipChars, out IPAddress address);
        public static bool TryFormat(Span<char> destination, out int charsWritten);}
}
@Paxxi
Copy link
Contributor

Paxxi commented Aug 2, 2017

I'm interested in this one.

I'm curious, what is TryWriteBytes supposed to do here?

@stephentoub
Copy link
Member Author

I'm interested in this one.

Great

what is TryWriteBytes supposed to do here?

The same thing as GetAddressBytes, except instead of allocating an array and writing the bytes to that, it writes the bytes to the supplied span and stores the number of bytes written into the out int. If there's enough room to store the bytes, it returns true. If the span is too small, nothing is written, the out int is set to 0, and it returns false.

@Paxxi
Copy link
Contributor

Paxxi commented Aug 4, 2017

Thank you. I was looking for a similarly named method and completely missed GetAddressBytes.

Now I ran into an issue getting it to build after adding a reference to System.Memory for the Span. I guess I've missed adding the reference somewhere but haven't been able to figure out where.

current test changes Paxxi/corefx@2f91bef

error I get when building

  Microsoft.Private.CoreFx.NETCoreApp -> C:\code\corefx\bin/packages/Debug/specs/runtime.win-x64.Microsoft.Private.CoreFx.NETCoreApp.nuspec
  Verifying closure of runtime.win-x64.Microsoft.Private.CoreFx.NETCoreApp runtime assemblies
C:\code\corefx\pkg\frameworkPackage.targets(124,5): error : Assembly 'System.Net.Primitives' is missing dependency 'System.Memory' [C:\code\corefx\pkg\Microsoft.Private.CoreFx.NETCoreApp\Microsoft.Private.CoreFx.NETCoreApp.pkgproj]

C:\code\corefx\pkg\frameworkPackage.targets(124,5): error : Assembly 'System.Net.Primitives' is missing dependency 'System.Memory' [C:\code\corefx\pkg\Microsoft.Private.CoreFx.NETCoreApp\Microsoft.Private.CoreFx.NETCoreApp.pkgproj]
Command execution failed with exit code 1.

@stephentoub
Copy link
Member Author

You don't need/want to add a System.Memory reference; Span is now exposed from System.Runtime in corefx master, so the System.Net.Primitives src/ref projects already have access to it. For the test project, it's currently building against netstandard, so you'll want to add a netcoreapp build of the tests in order to test the new API that's being added only to .NET Core. You can see an example of doing that in dotnet/corefx#22689:

@Paxxi
Copy link
Contributor

Paxxi commented Aug 7, 2017

Thank you for the pointers, that got me going. Not sure about the etiquette since it's a large repo so I didn't want to post just a thank you.

Now I have a new issue which I've been fighting with over the weekend.
The simple act of changing the signature of IPv6AddressHelper::Parse(string address, ushort* numbers, int start, ref string scopeId) to IPv6AddressHelper::Parse(ref ReadOnlySpan<char> address, ushort* numbers, int start, ref string scopeId) results in tests crashing with

System.TypeInitializationException : The type initializer for 'System.Net.Primitives.Functional.Tests.IPEndPointTest' threw an exception.\r\n---- System.InvalidProgramException : Common Language Runtime detected an invalid program.
at System.Net.Primitives.Functional.Tests.IPEndPointTest.Port_Set_Invalid() in C:\code\corefx\src\System.Net.Primitives\tests\FunctionalTests\IPEndPointTest.cs:line 62
----- Inner Stack Trace -----
   at System.IPv6AddressHelper.Parse(ReadOnlySpan`1 address, UInt16* numbers, Int32 start, String& scopeId)
   at System.Net.IPAddressParser.Ipv6StringToAddress(String ipString, UInt16* numbers, Int32 numbersLength, UInt32& scope) in C:\code\corefx\src\System.Net.Primitives\src\System\Net\IPAddressParser.cs:line 166
   at System.Net.IPAddressParser.Parse(String ipString, Boolean tryParse) in C:\code\corefx\src\System.Net.Primitives\src\System\Net\IPAddressParser.cs:line 36
   at System.Net.IPAddress.Parse(String ipString) in C:\code\corefx\src\System.Net.Primitives\src\System\Net\IPAddress.cs:line 289
   at System.Net.Primitives.Functional.Tests.IPEndPointTest..cctor() in C:\code\corefx\src\System.Net.Primitives\tests\FunctionalTests\IPEndPointTest.cs:line 15

The working code can be found at Paxxi/corefx@0b98780 and the invalid at Paxxi/corefx@553fe6b pay no attention to the weird conversions back and forth from string, it's just there trying to narrow down the issue.

Here's a gist with the generated IL for the valid and invalid versions https://gist.github.com/Paxxi/3b3561ae3d1020898fb904db40b51ef2

@stephentoub
Copy link
Member Author

ToString on a span doesn't do what you want it to (just as it doesn't on a char[]) and is likely the cause of the error.

Paxxi referenced this issue in Paxxi/corefx Aug 14, 2017
See issue #22607
This adds
public IPAddress(ReadOnlySpan<byte> address)
public IPAddress(ReadOnlySpan<byte> address, long scopeid)
public bool TryWriteBytes(Span<byte> destination, out int bytesWritten)
public static IPAddress Parse(ReadOnlySpan<char> ipSpan)
public static bool TryParse(ReadOnlySpan<char> ipSpan, out IPAddress address)
public static bool TryFormat(Span<char> destination, out int bytesWritten)
@karelz
Copy link
Member

karelz commented Aug 17, 2017

@Paxxi I sent you collaborator invite, so that we can assign the issue to you (let me know when you accept).
BTW: I recommend to disable all CoreFX repo notifications (you will be subscribed to all once you accept the invite), otherwise you will be DoS'd.

Thanks for your contribution!

@karelz karelz self-assigned this Aug 17, 2017
@Paxxi
Copy link
Contributor

Paxxi commented Aug 18, 2017

I have accepted the invitation now.

@karelz karelz assigned Paxxi and unassigned karelz Aug 18, 2017
stephentoub referenced this issue in Paxxi/corefx Aug 21, 2017
See issue #22607
This adds
public IPAddress(ReadOnlySpan<byte> address)
public IPAddress(ReadOnlySpan<byte> address, long scopeid)
public bool TryWriteBytes(Span<byte> destination, out int bytesWritten)
public static IPAddress Parse(ReadOnlySpan<char> ipSpan)
public static bool TryParse(ReadOnlySpan<char> ipSpan, out IPAddress address)
public static bool TryFormat(Span<char> destination, out int bytesWritten)
@msftgits msftgits transferred this issue from dotnet/corefx Jan 31, 2020
@msftgits msftgits added this to the 2.1.0 milestone Jan 31, 2020
@ghost ghost locked as resolved and limited conversation to collaborators Dec 21, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
api-approved API was approved in API review, it can be implemented area-System.Net help wanted [up-for-grabs] Good issue for external contributors tenet-performance Performance related issue
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants