3
3
using System . Net ;
4
4
using System . Net . Sockets ;
5
5
using System . Threading ;
6
+ #if NET6_0_OR_GREATER == false
6
7
using System . Threading . Tasks ;
8
+ #endif
7
9
8
10
using Renci . SshNet . Common ;
9
11
10
12
namespace Renci . SshNet . Abstractions
11
13
{
12
14
internal static partial class SocketAbstraction
13
15
{
14
- public static bool CanRead ( Socket socket )
15
- {
16
- if ( socket . Connected )
17
- {
18
- return socket . Poll ( - 1 , SelectMode . SelectRead ) && socket . Available > 0 ;
19
- }
20
-
21
- return false ;
22
- }
23
-
24
- /// <summary>
25
- /// Returns a value indicating whether the specified <see cref="Socket"/> can be used
26
- /// to send data.
27
- /// </summary>
28
- /// <param name="socket">The <see cref="Socket"/> to check.</param>
29
- /// <returns>
30
- /// <see langword="true"/> if <paramref name="socket"/> can be written to; otherwise, <see langword="false"/>.
31
- /// </returns>
32
- public static bool CanWrite ( Socket socket )
33
- {
34
- if ( socket != null && socket . Connected )
35
- {
36
- return socket . Poll ( - 1 , SelectMode . SelectWrite ) ;
37
- }
38
-
39
- return false ;
40
- }
41
-
42
- public static Socket Connect ( IPEndPoint remoteEndpoint , TimeSpan connectTimeout )
43
- {
44
- var socket = new Socket ( remoteEndpoint . AddressFamily , SocketType . Stream , ProtocolType . Tcp ) { NoDelay = true } ;
45
- ConnectCore ( socket , remoteEndpoint , connectTimeout , ownsSocket : true ) ;
46
- return socket ;
47
- }
48
-
49
16
public static void Connect ( Socket socket , IPEndPoint remoteEndpoint , TimeSpan connectTimeout )
50
17
{
51
- ConnectCore ( socket , remoteEndpoint , connectTimeout , ownsSocket : false ) ;
52
- }
53
-
54
- public static async Task ConnectAsync ( Socket socket , IPEndPoint remoteEndpoint , CancellationToken cancellationToken )
55
- {
56
- await socket . ConnectAsync ( remoteEndpoint , cancellationToken ) . ConfigureAwait ( false ) ;
57
- }
58
-
59
- private static void ConnectCore ( Socket socket , IPEndPoint remoteEndpoint , TimeSpan connectTimeout , bool ownsSocket )
60
- {
61
- var connectCompleted = new ManualResetEvent ( initialState : false ) ;
62
- var args = new SocketAsyncEventArgs
63
- {
64
- UserToken = connectCompleted ,
65
- RemoteEndPoint = remoteEndpoint
66
- } ;
67
- args . Completed += ConnectCompleted ;
18
+ using var connectCompleted = new ManualResetEventSlim ( initialState : false ) ;
19
+ using var args = new SocketAsyncEventArgs
20
+ {
21
+ RemoteEndPoint = remoteEndpoint
22
+ } ;
23
+ args . Completed += ( _ , _ ) => connectCompleted . Set ( ) ;
68
24
69
25
if ( socket . ConnectAsync ( args ) )
70
26
{
71
- if ( ! connectCompleted . WaitOne ( connectTimeout ) )
27
+ if ( ! connectCompleted . Wait ( connectTimeout ) )
72
28
{
73
- // avoid ObjectDisposedException in ConnectCompleted
74
- args . Completed -= ConnectCompleted ;
75
- if ( ownsSocket )
76
- {
77
- // dispose Socket
78
- socket . Dispose ( ) ;
79
- }
80
-
81
- // dispose ManualResetEvent
82
- connectCompleted . Dispose ( ) ;
83
-
84
- // dispose SocketAsyncEventArgs
85
- args . Dispose ( ) ;
29
+ socket . Dispose ( ) ;
86
30
87
31
throw new SshOperationTimeoutException ( string . Format ( CultureInfo . InvariantCulture ,
88
32
"Connection failed to establish within {0:F0} milliseconds." ,
89
33
connectTimeout . TotalMilliseconds ) ) ;
90
34
}
91
35
}
92
36
93
- // dispose ManualResetEvent
94
- connectCompleted . Dispose ( ) ;
95
-
96
37
if ( args . SocketError != SocketError . Success )
97
38
{
98
39
var socketError = ( int ) args . SocketError ;
99
40
100
- if ( ownsSocket )
101
- {
102
- // dispose Socket
103
- socket . Dispose ( ) ;
104
- }
105
-
106
- // dispose SocketAsyncEventArgs
107
- args . Dispose ( ) ;
108
-
109
41
throw new SocketException ( socketError ) ;
110
42
}
111
-
112
- // dispose SocketAsyncEventArgs
113
- args . Dispose ( ) ;
114
- }
115
-
116
- public static void ClearReadBuffer ( Socket socket )
117
- {
118
- var timeout = TimeSpan . FromMilliseconds ( 500 ) ;
119
- var buffer = new byte [ 256 ] ;
120
- int bytesReceived ;
121
-
122
- do
123
- {
124
- bytesReceived = ReadPartial ( socket , buffer , 0 , buffer . Length , timeout ) ;
125
- }
126
- while ( bytesReceived > 0 ) ;
127
- }
128
-
129
- public static int ReadPartial ( Socket socket , byte [ ] buffer , int offset , int size , TimeSpan timeout )
130
- {
131
- socket . ReceiveTimeout = timeout . AsTimeout ( nameof ( timeout ) ) ;
132
-
133
- try
134
- {
135
- return socket . Receive ( buffer , offset , size , SocketFlags . None ) ;
136
- }
137
- catch ( SocketException ex )
138
- {
139
- if ( ex . SocketErrorCode == SocketError . TimedOut )
140
- {
141
- throw new SshOperationTimeoutException ( string . Format ( CultureInfo . InvariantCulture ,
142
- "Socket read operation has timed out after {0:F0} milliseconds." ,
143
- timeout . TotalMilliseconds ) ) ;
144
- }
145
-
146
- throw ;
147
- }
148
43
}
149
44
150
45
public static void ReadContinuous ( Socket socket , byte [ ] buffer , int offset , int size , Action < byte [ ] , int , int > processReceivedBytesAction )
@@ -206,41 +101,6 @@ public static int ReadByte(Socket socket, TimeSpan timeout)
206
101
return buffer [ 0 ] ;
207
102
}
208
103
209
- /// <summary>
210
- /// Sends a byte using the specified <see cref="Socket"/>.
211
- /// </summary>
212
- /// <param name="socket">The <see cref="Socket"/> to write to.</param>
213
- /// <param name="value">The value to send.</param>
214
- /// <exception cref="SocketException">The write failed.</exception>
215
- public static void SendByte ( Socket socket , byte value )
216
- {
217
- var buffer = new [ ] { value } ;
218
- _ = socket . Send ( buffer ) ;
219
- }
220
-
221
- /// <summary>
222
- /// Receives data from a bound <see cref="Socket"/>.
223
- /// </summary>
224
- /// <param name="socket">The <see cref="Socket"/> to read from.</param>
225
- /// <param name="size">The number of bytes to receive.</param>
226
- /// <param name="timeout">Specifies the amount of time after which the call will time out.</param>
227
- /// <returns>
228
- /// The bytes received.
229
- /// </returns>
230
- /// <remarks>
231
- /// If no data is available for reading, the <see cref="Read(Socket, int, TimeSpan)"/> method will
232
- /// block until data is available or the time-out value is exceeded. If the time-out value is exceeded, the
233
- /// <see cref="Read(Socket, int, TimeSpan)"/> call will throw a <see cref="SshOperationTimeoutException"/>.
234
- /// If you are in non-blocking mode, and there is no data available in the in the protocol stack buffer, the
235
- /// <see cref="Read(Socket, int, TimeSpan)"/> method will complete immediately and throw a <see cref="SocketException"/>.
236
- /// </remarks>
237
- public static byte [ ] Read ( Socket socket , int size , TimeSpan timeout )
238
- {
239
- var buffer = new byte [ size ] ;
240
- _ = Read ( socket , buffer , 0 , size , timeout ) ;
241
- return buffer ;
242
- }
243
-
244
104
/// <summary>
245
105
/// Receives data from a bound <see cref="Socket"/> into a receive buffer.
246
106
/// </summary>
@@ -258,10 +118,6 @@ public static byte[] Read(Socket socket, int size, TimeSpan timeout)
258
118
/// block until data is available or the time-out value is exceeded. If the time-out value is exceeded, the
259
119
/// <see cref="Read(Socket, byte[], int, int, TimeSpan)"/> call will throw a <see cref="SshOperationTimeoutException"/>.
260
120
/// </para>
261
- /// <para>
262
- /// If you are in non-blocking mode, and there is no data available in the in the protocol stack buffer, the
263
- /// <see cref="Read(Socket, byte[], int, int, TimeSpan)"/> method will complete immediately and throw a <see cref="SocketException"/>.
264
- /// </para>
265
121
/// </remarks>
266
122
public static int Read ( Socket socket , byte [ ] buffer , int offset , int size , TimeSpan readTimeout )
267
123
{
@@ -301,10 +157,5 @@ public static ValueTask<int> ReadAsync(Socket socket, byte[] buffer, Cancellatio
301
157
return socket . ReceiveAsync ( new ArraySegment < byte > ( buffer , 0 , buffer . Length ) , SocketFlags . None , cancellationToken ) ;
302
158
}
303
159
#endif
304
- private static void ConnectCompleted ( object sender , SocketAsyncEventArgs e )
305
- {
306
- var eventWaitHandle = ( ManualResetEvent ) e . UserToken ;
307
- _ = eventWaitHandle ? . Set ( ) ;
308
- }
309
160
}
310
161
}
0 commit comments