Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit bd0c788

Browse files
committed
Merge pull request #2595 from pgavlin/SNPrimitivesXP
Implement System.Net.Primitives for *nix.
2 parents 4c423dc + 0c9f431 commit bd0c788

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+3966
-355
lines changed
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using System;
5+
6+
internal static partial class Interop
7+
{
8+
public static unsafe void CheckBounds(byte* buffer, int bufferSize, byte* offset, int accessSize)
9+
{
10+
var start = checked((int)(IntPtr)(offset - buffer));
11+
var end = checked(start + accessSize);
12+
if (start < 0 || end > bufferSize)
13+
{
14+
throw new IndexOutOfRangeException();
15+
}
16+
}
17+
18+
public static unsafe void CheckBounds(byte* buffer, int bufferSize, byte* offset)
19+
{
20+
CheckBounds(buffer, bufferSize, offset, sizeof(byte));
21+
}
22+
23+
public static unsafe void CheckBounds(byte* buffer, int bufferSize, ushort* offset)
24+
{
25+
CheckBounds(buffer, bufferSize, (byte*)offset, sizeof(ushort));
26+
}
27+
28+
public static unsafe void CheckBounds(byte* buffer, int bufferSize, uint* offset)
29+
{
30+
CheckBounds(buffer, bufferSize, (byte*)offset, sizeof(uint));
31+
}
32+
33+
public static unsafe byte CheckedRead(byte* buffer, int bufferSize, byte* offset)
34+
{
35+
CheckBounds(buffer, bufferSize, offset);
36+
return *offset;
37+
}
38+
39+
public static unsafe ushort CheckedRead(byte* buffer, int bufferSize, ushort* offset)
40+
{
41+
CheckBounds(buffer, bufferSize, offset);
42+
return *offset;
43+
}
44+
45+
public static unsafe uint CheckedRead(byte* buffer, int bufferSize, uint* offset)
46+
{
47+
CheckBounds(buffer, bufferSize, offset);
48+
return *offset;
49+
}
50+
51+
public static unsafe void CheckedWrite(byte* buffer, int bufferSize, byte* offset, byte value)
52+
{
53+
CheckBounds(buffer, bufferSize, offset);
54+
*offset = value;
55+
}
56+
57+
public static unsafe void CheckedWrite(byte* buffer, int bufferSize, ushort* offset, ushort value)
58+
{
59+
CheckBounds(buffer, bufferSize, offset);
60+
*offset = value;
61+
}
62+
63+
public static unsafe void CheckedWrite(byte* buffer, int bufferSize, uint* offset, uint value)
64+
{
65+
CheckBounds(buffer, bufferSize, offset);
66+
*offset = value;
67+
}
68+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using System;
5+
using System.Runtime.InteropServices;
6+
using System.Text;
7+
8+
using socklen_t = System.UInt32;
9+
10+
internal static partial class Interop
11+
{
12+
internal static partial class libc
13+
{
14+
public const int AI_NUMERICHOST = 0x0004; // Don't use name resolution.
15+
public const int AI_NUMERICSERV = 0x1000; // Don't use name resolution.
16+
17+
public const int NI_NUMERICHOST = 2; // Don't try to look up hostname.
18+
19+
public const int EAI_BADFLAGS = 3; // Invalid value for `ai_flags' field.
20+
public const int EAI_NONAME = 8; // NAME or SERVICE is unknown.
21+
22+
public unsafe struct addrinfo
23+
{
24+
public int ai_flags;
25+
public int ai_family;
26+
public int ai_socktype;
27+
public int ai_protocol;
28+
public socklen_t ai_addrlen;
29+
public byte* ai_canonname;
30+
public sockaddr* ai_addr;
31+
public addrinfo* ai_next;
32+
}
33+
}
34+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using System;
5+
using System.Runtime.InteropServices;
6+
using System.Text;
7+
8+
using in_port_t = System.UInt16;
9+
using sa_family_t = System.Byte;
10+
11+
internal static partial class Interop
12+
{
13+
internal static partial class libc
14+
{
15+
public const sa_family_t AF_UNSPEC = 0; // Unspecified.
16+
public const sa_family_t AF_UNIX = 1; // Local to host.
17+
public const sa_family_t AF_INET = 2; // IP protocol family.
18+
public const sa_family_t AF_INET6 = 30; // IP version 6.
19+
20+
// NOTE: this type is incomplete, and its values should never be used directly.
21+
// Specific sockaddr types (e.g. sockaddr_in or sockaddr_in6) should be used instead.
22+
public unsafe struct sockaddr
23+
{
24+
// Disable CS0649: Field 'Interop.libc.sockaddr.sa_family' is never assigned to,
25+
// and will always have its default value 0
26+
#pragma warning disable 649
27+
public byte sa_len;
28+
public sa_family_t sa_family;
29+
#pragma warning restore 649
30+
}
31+
32+
public struct in_addr
33+
{
34+
public uint s_addr; // Address in network byte order.
35+
}
36+
37+
public struct sockaddr_in
38+
{
39+
public const int Size = 16;
40+
41+
public byte sin_len; // sizeof(sockaddr_in)
42+
public sa_family_t sin_family; // Address family: AF_INET
43+
public in_port_t sin_port; // Port in network byte order
44+
public in_addr sin_addr; // Internet address
45+
private ulong padding; // 8 bytes of padding
46+
}
47+
48+
public unsafe struct in6_addr
49+
{
50+
public fixed byte s6_addr[16]; // IPv6 address
51+
}
52+
53+
public struct sockaddr_in6
54+
{
55+
public const int Size = 28;
56+
57+
public byte sin6_len; // sizeof(sockaddr_in6)
58+
public sa_family_t sin6_family; // AF_INET6
59+
public in_port_t sin6_port; // Port number
60+
public uint sin6_flowinfo; // IPv6 flow information
61+
public in6_addr sin6_addr; // IPv6 address
62+
public uint sin6_scope_id; // Scope ID
63+
}
64+
}
65+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using System;
5+
using System.Runtime.InteropServices;
6+
using System.Text;
7+
8+
using socklen_t = System.UInt32;
9+
10+
internal static partial class Interop
11+
{
12+
internal static partial class libc
13+
{
14+
public const int AI_NUMERICHOST = 0x0004; // Don't use name resolution.
15+
public const int AI_NUMERICSERV = 0x0400; // Don't use name resolution.
16+
17+
public const int NI_NUMERICHOST = 1; // Don't try to look up hostname.
18+
19+
public const int EAI_BADFLAGS = -1; // Invalid value for `ai_flags' field.
20+
public const int EAI_NONAME = -2; // NAME or SERVICE is unknown.
21+
22+
public unsafe struct addrinfo
23+
{
24+
public int ai_flags;
25+
public int ai_family;
26+
public int ai_socktype;
27+
public int ai_protocol;
28+
public socklen_t ai_addrlen;
29+
public sockaddr* ai_addr;
30+
public byte* ai_canonname;
31+
public addrinfo* ai_next;
32+
}
33+
}
34+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using System;
5+
using System.Runtime.InteropServices;
6+
using System.Text;
7+
8+
internal static partial class Interop
9+
{
10+
internal static partial class libc
11+
{
12+
[DllImport(Libraries.Libc)]
13+
public static extern unsafe void freeaddrinfo(addrinfo* res);
14+
}
15+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using System;
5+
using System.Runtime.InteropServices;
6+
using System.Text;
7+
8+
internal static partial class Interop
9+
{
10+
internal static partial class libc
11+
{
12+
[DllImport(Libraries.Libc, CharSet = CharSet.Ansi, SetLastError = true)]
13+
public static extern unsafe int getaddrinfo(string node, string service, addrinfo* hints, addrinfo** res);
14+
}
15+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using System;
5+
using System.Diagnostics;
6+
using System.Runtime.InteropServices;
7+
using System.Text;
8+
9+
internal static partial class Interop
10+
{
11+
internal static partial class libc
12+
{
13+
[DllImport(Libraries.Libc, SetLastError = true)]
14+
private static extern unsafe int getdomainname(byte* name, int len);
15+
16+
internal static unsafe string getdomainname()
17+
{
18+
const int HOST_NAME_MAX = 255; // man getdomainname
19+
const int ArrLength = HOST_NAME_MAX + 1;
20+
21+
byte* name = stackalloc byte[ArrLength];
22+
int err = getdomainname(name, ArrLength);
23+
if (err != 0)
24+
{
25+
// This should never happen. According to the man page,
26+
// the only possible errno for getdomainname is ENAMETOOLONG,
27+
// which should only happen if the buffer we supply isn't big
28+
// enough, and we're using a buffer size that the man page
29+
// says is the max for POSIX (and larger than the max for Linux).
30+
Debug.Fail("getdomainname failed");
31+
throw new InvalidOperationException(string.Format("getdomainname returned {0}", err));
32+
}
33+
34+
// Marshal.PtrToStringAnsi uses UTF8 on Unix.
35+
return Marshal.PtrToStringAnsi((IntPtr)name);
36+
}
37+
}
38+
}

src/Common/src/Interop/Unix/libc/Interop.gethostname.cs

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
33

44
using System;
5+
using System.Diagnostics;
56
using System.Runtime.InteropServices;
67
using System.Text;
78

@@ -18,20 +19,20 @@ internal static unsafe string gethostname()
1819
const int ArrLength = HOST_NAME_MAX + 1;
1920

2021
byte* name = stackalloc byte[ArrLength];
21-
int errno = gethostname(name, ArrLength);
22-
if (errno == 0)
22+
int err = gethostname(name, ArrLength);
23+
if (err != 0)
2324
{
24-
int nullPos = 0;
25-
for (; nullPos < ArrLength && name[nullPos] != '\0'; nullPos++) ;
26-
return Encoding.UTF8.GetString(name, nullPos);
25+
// This should never happen. According to the man page,
26+
// the only possible errno for gethostname is ENAMETOOLONG,
27+
// which should only happen if the buffer we supply isn't big
28+
// enough, and we're using a buffer size that the man page
29+
// says is the max for POSIX (and larger than the max for Linux).
30+
Debug.Fail("gethostname failed");
31+
throw new InvalidOperationException(string.Format("gethostname returned {0}", err));
2732
}
2833

29-
// This should never happen. According to the man page,
30-
// the only possible errno for gethostname is ENAMETOOLONG,
31-
// which should only happen if the buffer we supply isn't big
32-
// enough, and we're using a buffer size that the man page
33-
// says is the max for POSIX (and larger than the max for Linux).
34-
throw new InvalidOperationException();
34+
// Marshal.PtrToStringAnsi uses UTF8 on Unix.
35+
return Marshal.PtrToStringAnsi((IntPtr)name);
3536
}
3637
}
3738
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using System;
5+
using System.Runtime.InteropServices;
6+
using System.Text;
7+
8+
using socklen_t = System.UInt32;
9+
10+
internal static partial class Interop
11+
{
12+
internal static partial class libc
13+
{
14+
[DllImport(Libraries.Libc, CharSet = CharSet.Ansi, SetLastError = true)]
15+
public static extern unsafe int getnameinfo(sockaddr* sa, socklen_t salen, StringBuilder host, socklen_t hostlen, StringBuilder serv, socklen_t servlen, int flags);
16+
}
17+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using System;
5+
using System.Runtime.InteropServices;
6+
using System.Text;
7+
8+
using in_port_t = System.UInt16;
9+
using sa_family_t = System.UInt16;
10+
11+
internal static partial class Interop
12+
{
13+
internal static partial class libc
14+
{
15+
public const sa_family_t AF_UNSPEC = 0; // Unspecified.
16+
public const sa_family_t AF_UNIX = 1; // Local to host.
17+
public const sa_family_t AF_INET = 2; // IP protocol family.
18+
public const sa_family_t AF_INET6 = 10; // IP version 6.
19+
20+
// NOTE: this type is incomplete, and its values should never be used directly.
21+
// Specific sockaddr types (e.g. sockaddr_in or sockaddr_in6) should be used instead.
22+
public unsafe struct sockaddr
23+
{
24+
// Disable CS0649: Field 'Interop.libc.sockaddr.sa_family' is never assigned to,
25+
// and will always have its default value 0
26+
#pragma warning disable 649
27+
public sa_family_t sa_family;
28+
#pragma warning restore 649
29+
}
30+
31+
public struct in_addr
32+
{
33+
public uint s_addr; // Address in network byte order.
34+
}
35+
36+
public struct sockaddr_in
37+
{
38+
public const int Size = 16;
39+
40+
public sa_family_t sin_family; // Address family: AF_INET
41+
public in_port_t sin_port; // Port in network byte order
42+
public in_addr sin_addr; // Internet address
43+
private ulong padding; // 8 bytes of padding
44+
}
45+
46+
public unsafe struct in6_addr
47+
{
48+
public fixed byte s6_addr[16]; // IPv6 address
49+
}
50+
51+
public struct sockaddr_in6
52+
{
53+
public const int Size = 28;
54+
55+
public sa_family_t sin6_family; // AF_INET6
56+
public in_port_t sin6_port; // Port number
57+
public uint sin6_flowinfo; // IPv6 flow information
58+
public in6_addr sin6_addr; // IPv6 address
59+
public uint sin6_scope_id; // Scope ID
60+
}
61+
}
62+
}

0 commit comments

Comments
 (0)