-
-
Notifications
You must be signed in to change notification settings - Fork 980
Expand file tree
/
Copy pathConnectorBase.cs
More file actions
151 lines (130 loc) · 6.66 KB
/
ConnectorBase.cs
File metadata and controls
151 lines (130 loc) · 6.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Renci.SshNet.Abstractions;
using Renci.SshNet.Common;
using Renci.SshNet.Messages.Transport;
namespace Renci.SshNet.Connection
{
internal abstract class ConnectorBase : IConnector
{
private readonly ILogger _logger;
private readonly ILoggerFactory _loggerFactory;
protected ConnectorBase(ISocketFactory socketFactory, ILoggerFactory loggerFactory)
{
ThrowHelper.ThrowIfNull(socketFactory);
SocketFactory = socketFactory;
_loggerFactory = loggerFactory;
_logger = _loggerFactory.CreateLogger(GetType());
}
internal ISocketFactory SocketFactory { get; private set; }
public abstract Socket Connect(IConnectionInfo connectionInfo);
public abstract Task<Socket> ConnectAsync(IConnectionInfo connectionInfo, CancellationToken cancellationToken);
/// <summary>
/// Establishes a socket connection to the specified endpoint.
/// </summary>
/// <param name="endPoint">The <see cref="EndPoint"/> representing the server to connect to.</param>
/// <param name="timeout">The maximum time to wait for the connection to be established.</param>
/// <exception cref="SshOperationTimeoutException">The connection failed to establish within the configured <see cref="ConnectionInfo.Timeout"/>.</exception>
/// <exception cref="SocketException">An error occurred trying to establish the connection.</exception>
protected Socket SocketConnect(EndPoint endPoint, TimeSpan timeout)
{
_logger.LogInformation("Initiating connection to '{EndPoint}'.", endPoint);
var socket = SocketFactory.Create(SocketType.Stream, ProtocolType.Tcp);
try
{
SocketAbstraction.Connect(socket, endPoint, timeout);
const int socketBufferSize = 10 * Session.MaximumSshPacketSize;
socket.SendBufferSize = socketBufferSize;
socket.ReceiveBufferSize = socketBufferSize;
return socket;
}
catch (Exception)
{
socket.Dispose();
throw;
}
}
/// <summary>
/// Establishes a socket connection to the specified endpoint.
/// </summary>
/// <param name="endPoint">The <see cref="EndPoint"/> representing the server to connect to.</param>
/// <param name="cancellationToken">The cancellation token to observe.</param>
/// <exception cref="SshOperationTimeoutException">The connection failed to establish within the configured <see cref="ConnectionInfo.Timeout"/>.</exception>
/// <exception cref="SocketException">An error occurred trying to establish the connection.</exception>
protected async Task<Socket> SocketConnectAsync(EndPoint endPoint, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
_logger.LogInformation("Initiating connection to '{EndPoint}'.", endPoint);
var socket = SocketFactory.Create(SocketType.Stream, ProtocolType.Tcp);
try
{
await SocketAbstraction.ConnectAsync(socket, endPoint, cancellationToken).ConfigureAwait(false);
const int socketBufferSize = 2 * Session.MaximumSshPacketSize;
socket.SendBufferSize = socketBufferSize;
socket.ReceiveBufferSize = socketBufferSize;
return socket;
}
catch (Exception)
{
socket.Dispose();
throw;
}
}
protected static byte SocketReadByte(Socket socket)
{
var buffer = new byte[1];
_ = SocketRead(socket, buffer, 0, 1, Timeout.InfiniteTimeSpan);
return buffer[0];
}
protected static byte SocketReadByte(Socket socket, TimeSpan readTimeout)
{
var buffer = new byte[1];
_ = SocketRead(socket, buffer, 0, 1, readTimeout);
return buffer[0];
}
/// <summary>
/// Performs a blocking read on the socket until <paramref name="length"/> bytes are received.
/// </summary>
/// <param name="socket">The <see cref="Socket"/> to read from.</param>
/// <param name="buffer">An array of type <see cref="byte"/> that is the storage location for the received data.</param>
/// <param name="offset">The position in <paramref name="buffer"/> parameter to store the received data.</param>
/// <param name="length">The number of bytes to read.</param>
/// <returns>
/// The number of bytes read.
/// </returns>
/// <exception cref="SshConnectionException">The socket is closed.</exception>
/// <exception cref="SocketException">The read failed.</exception>
protected static int SocketRead(Socket socket, byte[] buffer, int offset, int length)
{
return SocketRead(socket, buffer, offset, length, Timeout.InfiniteTimeSpan);
}
/// <summary>
/// Performs a blocking read on the socket until <paramref name="length"/> bytes are received.
/// </summary>
/// <param name="socket">The <see cref="Socket"/> to read from.</param>
/// <param name="buffer">An array of type <see cref="byte"/> that is the storage location for the received data.</param>
/// <param name="offset">The position in <paramref name="buffer"/> parameter to store the received data.</param>
/// <param name="length">The number of bytes to read.</param>
/// <param name="readTimeout">The maximum time to wait until <paramref name="length"/> bytes have been received.</param>
/// <returns>
/// The number of bytes read.
/// </returns>
/// <exception cref="SshConnectionException">The socket is closed.</exception>
/// <exception cref="SshOperationTimeoutException">The read has timed-out.</exception>
/// <exception cref="SocketException">The read failed.</exception>
protected static int SocketRead(Socket socket, byte[] buffer, int offset, int length, TimeSpan readTimeout)
{
var bytesRead = SocketAbstraction.Read(socket, buffer, offset, length, readTimeout);
if (bytesRead == 0)
{
throw new SshConnectionException("An established connection was aborted by the server.",
DisconnectReason.ConnectionLost);
}
return bytesRead;
}
}
}