forked from sshnet/SSH.NET
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathConnectorBase.cs
More file actions
155 lines (134 loc) · 6.9 KB
/
ConnectorBase.cs
File metadata and controls
155 lines (134 loc) · 6.9 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
152
153
154
155
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
using Renci.SshNet.Abstractions;
using Renci.SshNet.Common;
using Renci.SshNet.Messages.Transport;
namespace Renci.SshNet.Connection
{
internal abstract class ConnectorBase : IConnector
{
protected ConnectorBase(ISocketFactory socketFactory)
{
if (socketFactory is null)
{
throw new ArgumentNullException(nameof(socketFactory));
}
SocketFactory = socketFactory;
}
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 host and port.
/// </summary>
/// <param name="host">The host name of the server to connect to.</param>
/// <param name="port">The port 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(string host, int port, TimeSpan timeout)
{
var ipAddress = DnsAbstraction.GetHostAddresses(host)[0];
var ep = new IPEndPoint(ipAddress, port);
DiagnosticAbstraction.Log(string.Format("Initiating connection to '{0}:{1}'.", host, port));
var socket = SocketFactory.Create(ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
try
{
SocketAbstraction.Connect(socket, ep, 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 host and port.
/// </summary>
/// <param name="host">The host name of the server to connect to.</param>
/// <param name="port">The port 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(string host, int port, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
var ipAddress = (await DnsAbstraction.GetHostAddressesAsync(host).ConfigureAwait(false))[0];
var ep = new IPEndPoint(ipAddress, port);
DiagnosticAbstraction.Log(string.Format("Initiating connection to '{0}:{1}'.", host, port));
var socket = SocketFactory.Create(ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
try
{
await SocketAbstraction.ConnectAsync(socket, ep, 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, Session.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, Session.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;
}
}
}