Skip to content

Commit 50bb5fd

Browse files
committed
WIP
1 parent 9c2175d commit 50bb5fd

29 files changed

+464
-40
lines changed

src/DotNetty.NetUV/Handles/Pipe.cs

+4-4
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ internal Pipe(LoopContext loop, bool ipc = false)
3030

3131
public int GetSendBufferSize()
3232
{
33-
if (Platform.IsWindows)
33+
if (PlatformApi.IsWindows)
3434
{
3535
ThrowHelper.ThrowPlatformNotSupportedException_handle_type_send_buffer_size_setting_not_supported_on_Windows(HandleType);
3636
}
@@ -42,7 +42,7 @@ public int SetSendBufferSize(int value)
4242
{
4343
if ((uint)value > SharedConstants.TooBigOrNegative) { ThrowHelper.ThrowArgumentException_PositiveOrZero(value, ExceptionArgument.value); }
4444

45-
if (Platform.IsWindows)
45+
if (PlatformApi.IsWindows)
4646
{
4747
ThrowHelper.ThrowPlatformNotSupportedException_handle_type_send_buffer_size_setting_not_supported_on_Windows(HandleType);
4848
}
@@ -52,7 +52,7 @@ public int SetSendBufferSize(int value)
5252

5353
public int GetReceiveBufferSize()
5454
{
55-
if (Platform.IsWindows)
55+
if (PlatformApi.IsWindows)
5656
{
5757
ThrowHelper.ThrowPlatformNotSupportedException_handle_type_send_buffer_size_setting_not_supported_on_Windows(HandleType);
5858
}
@@ -64,7 +64,7 @@ public int SetReceiveBufferSize(int value)
6464
{
6565
if ((uint)value > SharedConstants.TooBigOrNegative) { ThrowHelper.ThrowArgumentException_PositiveOrZero(value, ExceptionArgument.value); }
6666

67-
if (Platform.IsWindows)
67+
if (PlatformApi.IsWindows)
6868
{
6969
ThrowHelper.ThrowPlatformNotSupportedException_handle_type_send_buffer_size_setting_not_supported_on_Windows(HandleType);
7070
}

src/DotNetty.NetUV/Handles/Tty.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ public override void OnRead(Action<Tty, IStreamReadCompletion> onRead)
8282

8383
public Tty Mode(TtyMode mode)
8484
{
85-
if (mode == TtyMode.IO && !Platform.IsUnix)
85+
if (mode == TtyMode.IO && !PlatformApi.IsUnix)
8686
{
8787
ThrowHelper.ThrowArgumentException_TtyMode_is_Unix_only(mode);
8888
}

src/DotNetty.NetUV/Internal/ThrowHelper.Libuv.cs

+37
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@
2222

2323
using System;
2424
using System.Net;
25+
using System.Net.Sockets;
2526
using System.Runtime.CompilerServices;
27+
using System.Runtime.InteropServices;
2628
using DotNetty.NetUV.Handles;
2729
using DotNetty.NetUV.Native;
2830
using DotNetty.NetUV.Channels;
@@ -50,5 +52,40 @@ InvalidOperationException GetInvalidOperationException()
5052
return new InvalidOperationException($"Invalid {nameof(LoopExecutor)} state {executionState}");
5153
}
5254
}
55+
56+
[MethodImpl(MethodImplOptions.NoInlining)]
57+
internal static void ThrowInvalidOperationException_Dispatch()
58+
{
59+
throw GetInvalidOperationException();
60+
61+
static InvalidOperationException GetInvalidOperationException()
62+
{
63+
return new InvalidOperationException("No pipe connections to dispatch handles.");
64+
}
65+
}
66+
67+
[MethodImpl(MethodImplOptions.NoInlining)]
68+
internal static uint ThrowInvalidOperationException_Dispatch(AddressFamily addressFamily)
69+
{
70+
throw GetInvalidOperationException();
71+
InvalidOperationException GetInvalidOperationException()
72+
{
73+
return new InvalidOperationException($"Address family : {addressFamily} platform : {RuntimeInformation.OSDescription} not supported");
74+
}
75+
}
76+
77+
#region -- SocketException --
78+
79+
[MethodImpl(MethodImplOptions.NoInlining)]
80+
internal static void ThrowSocketException(int errorCode)
81+
{
82+
throw GetSocketException();
83+
SocketException GetSocketException()
84+
{
85+
return new SocketException(errorCode);
86+
}
87+
}
88+
89+
#endregion
5390
}
5491
}

src/DotNetty.NetUV/Native/NativeHandles.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ internal unsafe IPEndPoint GetIPEndPoint()
153153
var port = ((int)(_field0 & 0x00FF0000) >> 8) | (int)((_field0 & 0xFF000000) >> 24);
154154

155155
int family = (int)_field0;
156-
if (Platform.IsDarwin)
156+
if (PlatformApi.IsDarwin)
157157
{
158158
// see explaination in example 4
159159
family >>= 8;

src/DotNetty.NetUV/Native/NativeRequests.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ internal struct uv_getaddrinfo_t
116116
[StructLayout(LayoutKind.Sequential)]
117117
internal struct addrinfo
118118
{
119-
private static readonly bool s_isWindows = Platform.IsWindows;
119+
private static readonly bool s_isWindows = PlatformApi.IsWindows;
120120

121121
public readonly int ai_flags;
122122
public readonly int ai_family; // AF_INET or AF_INET6

src/DotNetty.NetUV/Native/NativeStreams.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ namespace DotNetty.NetUV.Native
2525
[StructLayout(LayoutKind.Sequential)]
2626
internal struct uv_buf_t
2727
{
28-
private static readonly bool IsWindows = Platform.IsWindows;
28+
private static readonly bool IsWindows = PlatformApi.IsWindows;
2929
private static readonly int Size = IntPtr.Size;
3030

3131
/*
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/*
2+
* Copyright 2012 The Netty Project
3+
*
4+
* The Netty Project licenses this file to you under the Apache License,
5+
* version 2.0 (the "License"); you may not use this file except in compliance
6+
* with the License. You may obtain a copy of the License at:
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations
14+
* under the License.
15+
*
16+
* Copyright (c) The DotNetty Project (Microsoft). All rights reserved.
17+
*
18+
* https://github.com/azure/dotnetty
19+
*
20+
* Licensed under the MIT license. See LICENSE file in the project root for full license information.
21+
*
22+
* Copyright (c) 2020 The Dotnetty-Span-Fork Project ([email protected]) All rights reserved.
23+
*
24+
* https://github.com/cuteant/dotnetty-span-fork
25+
*
26+
* Licensed under the MIT license. See LICENSE file in the project root for full license information.
27+
*/
28+
29+
namespace DotNetty.NetUV.Native
30+
{
31+
using System;
32+
using System.Net.Sockets;
33+
using DotNetty.NetUV.Handles;
34+
35+
static partial class PlatformApi
36+
{
37+
const int AF_INET6_LINUX = 10;
38+
const int AF_INET6_OSX = 30;
39+
40+
internal static uint GetAddressFamily(AddressFamily addressFamily)
41+
{
42+
// AF_INET 2
43+
if (addressFamily == AddressFamily.InterNetwork || IsWindows)
44+
{
45+
return (uint)addressFamily;
46+
}
47+
48+
if (IsLinux)
49+
{
50+
return AF_INET6_LINUX;
51+
}
52+
53+
if (IsDarwin)
54+
{
55+
return AF_INET6_OSX;
56+
}
57+
58+
return ThrowHelper.ThrowInvalidOperationException_Dispatch(addressFamily);
59+
}
60+
61+
internal static bool GetReuseAddress(IInternalScheduleHandle handle)
62+
{
63+
IntPtr socketHandle = GetSocketHandle(handle);
64+
65+
if (IsWindows)
66+
{
67+
return WindowsApi.GetReuseAddress(socketHandle);
68+
}
69+
return UnixApi.GetReuseAddress(socketHandle);
70+
}
71+
72+
internal static void SetReuseAddress(IInternalScheduleHandle handle, int value)
73+
{
74+
IntPtr socketHandle = GetSocketHandle(handle);
75+
if (IsWindows)
76+
{
77+
WindowsApi.SetReuseAddress(socketHandle, value);
78+
}
79+
else
80+
{
81+
UnixApi.SetReuseAddress(socketHandle, value);
82+
}
83+
}
84+
85+
internal static bool GetReusePort(IInternalScheduleHandle handle)
86+
{
87+
if (IsWindows) { return GetReuseAddress(handle); }
88+
89+
IntPtr socketHandle = GetSocketHandle(handle);
90+
return UnixApi.GetReusePort(socketHandle);
91+
}
92+
93+
internal static void SetReusePort(IInternalScheduleHandle handle, int value)
94+
{
95+
IntPtr socketHandle = GetSocketHandle(handle);
96+
// Ignore SO_REUSEPORT on Windows because it is controlled
97+
// by SO_REUSEADDR
98+
if (IsWindows) { return; }
99+
100+
UnixApi.SetReusePort(socketHandle, value);
101+
}
102+
103+
static IntPtr GetSocketHandle(IInternalScheduleHandle handle)
104+
{
105+
IntPtr socket = IntPtr.Zero;
106+
NativeMethods.GetFileDescriptor(handle.InternalHandle, ref socket);
107+
return socket;
108+
}
109+
}
110+
}

src/DotNetty.NetUV/Native/Platform.cs src/DotNetty.NetUV/Native/PlatformApi.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ namespace DotNetty.NetUV.Native
1717
using System.Net.Sockets;
1818
using System.Runtime.InteropServices;
1919

20-
internal static class Platform
20+
internal static partial class PlatformApi
2121
{
22-
static Platform()
22+
static PlatformApi()
2323
{
2424
IsWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
2525
IsLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux);

src/DotNetty.NetUV/Native/UnixApi.cs

+128
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
/*
2+
* Copyright 2012 The Netty Project
3+
*
4+
* The Netty Project licenses this file to you under the Apache License,
5+
* version 2.0 (the "License"); you may not use this file except in compliance
6+
* with the License. You may obtain a copy of the License at:
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations
14+
* under the License.
15+
*
16+
* Copyright (c) The DotNetty Project (Microsoft). All rights reserved.
17+
*
18+
* https://github.com/azure/dotnetty
19+
*
20+
* Licensed under the MIT license. See LICENSE file in the project root for full license information.
21+
*
22+
* Copyright (c) 2020 The Dotnetty-Span-Fork Project ([email protected]) All rights reserved.
23+
*
24+
* https://github.com/cuteant/dotnetty-span-fork
25+
*
26+
* Licensed under the MIT license. See LICENSE file in the project root for full license information.
27+
*/
28+
29+
namespace DotNetty.NetUV.Native
30+
{
31+
using System;
32+
using System.Net.Sockets;
33+
using System.Runtime.InteropServices;
34+
35+
static class UnixApi
36+
{
37+
#pragma warning disable IDE1006 // 命名样式
38+
[DllImport("libc", SetLastError = true)]
39+
static extern int setsockopt(int socket, int level, int option_name, IntPtr option_value, uint option_len);
40+
41+
[DllImport("libc", SetLastError = true)]
42+
static extern unsafe int getsockopt(int socket, int level, int option_name, byte* optionValue, int* optionLen);
43+
#pragma warning restore IDE1006 // 命名样式
44+
45+
const int SOL_SOCKET_LINUX = 0x0001;
46+
const int SO_REUSEADDR_LINUX = 0x0002;
47+
const int SO_REUSEPORT_LINUX = 0x000f;
48+
49+
const int SOL_SOCKET_OSX = 0xffff;
50+
const int SO_REUSEADDR_OSX = 0x0004;
51+
const int SO_REUSEPORT_OSX = 0x0200;
52+
53+
internal static unsafe bool GetReuseAddress(IntPtr socket)
54+
{
55+
int value = 0;
56+
int status = 0;
57+
int optLen = sizeof(int);
58+
if (PlatformApi.IsLinux)
59+
{
60+
status = getsockopt(socket.ToInt32(), SOL_SOCKET_LINUX, SO_REUSEADDR_LINUX, (byte*)&value, &optLen);
61+
}
62+
else if (PlatformApi.IsDarwin)
63+
{
64+
status = getsockopt(socket.ToInt32(), SOL_SOCKET_OSX, SO_REUSEADDR_OSX, (byte*)&value, &optLen);
65+
}
66+
if (status != 0)
67+
{
68+
ThrowHelper.ThrowSocketException(Marshal.GetLastWin32Error());
69+
}
70+
71+
return value != 0;
72+
}
73+
74+
internal static unsafe void SetReuseAddress(IntPtr socket, int value)
75+
{
76+
int status = 0;
77+
if (PlatformApi.IsLinux)
78+
{
79+
status = setsockopt(socket.ToInt32(), SOL_SOCKET_LINUX, SO_REUSEADDR_LINUX, (IntPtr)(&value), sizeof(int));
80+
}
81+
else if (PlatformApi.IsDarwin)
82+
{
83+
status = setsockopt(socket.ToInt32(), SOL_SOCKET_OSX, SO_REUSEADDR_OSX, (IntPtr)(&value), sizeof(int));
84+
}
85+
if (status != 0)
86+
{
87+
ThrowHelper.ThrowSocketException(Marshal.GetLastWin32Error());
88+
}
89+
}
90+
91+
internal static unsafe bool GetReusePort(IntPtr socket)
92+
{
93+
int value = 0;
94+
int status = 0;
95+
int optLen = sizeof(int);
96+
if (PlatformApi.IsLinux)
97+
{
98+
status = getsockopt(socket.ToInt32(), SOL_SOCKET_LINUX, SO_REUSEPORT_LINUX, (byte*)&value, &optLen);
99+
}
100+
else if (PlatformApi.IsDarwin)
101+
{
102+
status = getsockopt(socket.ToInt32(), SOL_SOCKET_OSX, SO_REUSEPORT_OSX, (byte*)&value, &optLen);
103+
}
104+
if (status != 0)
105+
{
106+
ThrowHelper.ThrowSocketException(Marshal.GetLastWin32Error());
107+
}
108+
return value != 0;
109+
}
110+
111+
internal static unsafe void SetReusePort(IntPtr socket, int value)
112+
{
113+
int status = 0;
114+
if (PlatformApi.IsLinux)
115+
{
116+
status = setsockopt(socket.ToInt32(), SOL_SOCKET_LINUX, SO_REUSEPORT_LINUX, (IntPtr)(&value), sizeof(int));
117+
}
118+
else if (PlatformApi.IsDarwin)
119+
{
120+
status = setsockopt(socket.ToInt32(), SOL_SOCKET_OSX, SO_REUSEPORT_OSX, (IntPtr)(&value), sizeof(int));
121+
}
122+
if (status != 0)
123+
{
124+
ThrowHelper.ThrowSocketException(Marshal.GetLastWin32Error());
125+
}
126+
}
127+
}
128+
}

0 commit comments

Comments
 (0)