3
3
4
4
using System ;
5
5
using System . Buffers ;
6
- using System . Diagnostics ;
7
6
using System . IO . Pipelines ;
8
7
using System . Net ;
9
8
using System . Net . Sockets ;
@@ -23,6 +22,7 @@ internal sealed class SocketConnectionListener : IConnectionListener
23
22
private Socket _listenSocket ;
24
23
private int _schedulerIndex ;
25
24
private readonly SocketTransportOptions _options ;
25
+ private SafeSocketHandle _socketHandle ;
26
26
27
27
public EndPoint EndPoint { get ; private set ; }
28
28
@@ -62,33 +62,44 @@ internal void Bind()
62
62
throw new InvalidOperationException ( SocketsStrings . TransportAlreadyBound ) ;
63
63
}
64
64
65
- // Check if EndPoint is a FileHandleEndpoint before attempting to access EndPoint.AddressFamily
66
- // since that will throw an NotImplementedException.
67
- if ( EndPoint is FileHandleEndPoint )
68
- {
69
- throw new NotSupportedException ( SocketsStrings . FileHandleEndPointNotSupported ) ;
70
- }
71
-
72
65
Socket listenSocket ;
73
66
74
- // Unix domain sockets are unspecified
75
- var protocolType = EndPoint is UnixDomainSocketEndPoint ? ProtocolType . Unspecified : ProtocolType . Tcp ;
76
-
77
- listenSocket = new Socket ( EndPoint . AddressFamily , SocketType . Stream , protocolType ) ;
78
-
79
- // Kestrel expects IPv6Any to bind to both IPv6 and IPv4
80
- if ( EndPoint is IPEndPoint ip && ip . Address == IPAddress . IPv6Any )
67
+ switch ( EndPoint )
81
68
{
82
- listenSocket . DualMode = true ;
69
+ case FileHandleEndPoint fileHandle :
70
+ _socketHandle = new SafeSocketHandle ( ( IntPtr ) fileHandle . FileHandle , ownsHandle : true ) ;
71
+ listenSocket = new Socket ( _socketHandle ) ;
72
+ break ;
73
+ case UnixDomainSocketEndPoint unix :
74
+ listenSocket = new Socket ( unix . AddressFamily , SocketType . Stream , ProtocolType . Unspecified ) ;
75
+ BindSocket ( ) ;
76
+ break ;
77
+ case IPEndPoint ip :
78
+ listenSocket = new Socket ( ip . AddressFamily , SocketType . Stream , ProtocolType . Tcp ) ;
79
+
80
+ // Kestrel expects IPv6Any to bind to both IPv6 and IPv4
81
+ if ( ip . Address == IPAddress . IPv6Any )
82
+ {
83
+ listenSocket . DualMode = true ;
84
+ }
85
+ BindSocket ( ) ;
86
+ break ;
87
+ default :
88
+ listenSocket = new Socket ( EndPoint . AddressFamily , SocketType . Stream , ProtocolType . Tcp ) ;
89
+ BindSocket ( ) ;
90
+ break ;
83
91
}
84
92
85
- try
86
- {
87
- listenSocket . Bind ( EndPoint ) ;
88
- }
89
- catch ( SocketException e ) when ( e . SocketErrorCode == SocketError . AddressAlreadyInUse )
93
+ void BindSocket ( )
90
94
{
91
- throw new AddressInUseException ( e . Message , e ) ;
95
+ try
96
+ {
97
+ listenSocket . Bind ( EndPoint ) ;
98
+ }
99
+ catch ( SocketException e ) when ( e . SocketErrorCode == SocketError . AddressAlreadyInUse )
100
+ {
101
+ throw new AddressInUseException ( e . Message , e ) ;
102
+ }
92
103
}
93
104
94
105
EndPoint = listenSocket . LocalEndPoint ;
@@ -142,12 +153,17 @@ public async ValueTask<ConnectionContext> AcceptAsync(CancellationToken cancella
142
153
public ValueTask UnbindAsync ( CancellationToken cancellationToken = default )
143
154
{
144
155
_listenSocket ? . Dispose ( ) ;
156
+
157
+ _socketHandle ? . Dispose ( ) ;
145
158
return default ;
146
159
}
147
160
148
161
public ValueTask DisposeAsync ( )
149
162
{
150
163
_listenSocket ? . Dispose ( ) ;
164
+
165
+ _socketHandle ? . Dispose ( ) ;
166
+
151
167
// Dispose the memory pool
152
168
_memoryPool . Dispose ( ) ;
153
169
return default ;
0 commit comments