-
-
Notifications
You must be signed in to change notification settings - Fork 979
Expand file tree
/
Copy pathServiceFactory.cs
More file actions
193 lines (173 loc) · 9.03 KB
/
ServiceFactory.cs
File metadata and controls
193 lines (173 loc) · 9.03 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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Renci.SshNet.Common;
using Renci.SshNet.Messages.Transport;
using Renci.SshNet.Security;
using Renci.SshNet.Sftp;
using Renci.SshNet.Abstractions;
namespace Renci.SshNet
{
/// <summary>
/// Basic factory for creating new services.
/// </summary>
internal partial class ServiceFactory : IServiceFactory
{
/// <summary>
/// Defines the number of times an authentication attempt with any given <see cref="IAuthenticationMethod"/>
/// can result in <see cref="AuthenticationResult.PartialSuccess"/> before it is disregarded.
/// </summary>
private static int PartialSuccessLimit = 5;
/// <summary>
/// Creates a <see cref="IClientAuthentication"/>.
/// </summary>
/// <returns>
/// A <see cref="IClientAuthentication"/>.
/// </returns>
public IClientAuthentication CreateClientAuthentication()
{
return new ClientAuthentication(PartialSuccessLimit);
}
/// <summary>
/// Creates a new <see cref="ISession"/> with the specified <see cref="ConnectionInfo"/>.
/// </summary>
/// <param name="connectionInfo">The <see cref="ConnectionInfo"/> to use for creating a new session.</param>
/// <returns>
/// An <see cref="ISession"/> for the specified <see cref="ConnectionInfo"/>.
/// </returns>
/// <exception cref="ArgumentNullException"><paramref name="connectionInfo"/> is <c>null</c>.</exception>
public ISession CreateSession(ConnectionInfo connectionInfo)
{
return new Session(connectionInfo, this);
}
/// <summary>
/// Creates a new <see cref="ISftpSession"/> in a given <see cref="ISession"/> and with
/// the specified operation timeout and encoding.
/// </summary>
/// <param name="session">The <see cref="ISession"/> to create the <see cref="ISftpSession"/> in.</param>
/// <param name="operationTimeout">The number of milliseconds to wait for an operation to complete, or -1 to wait indefinitely.</param>
/// <param name="encoding">The encoding.</param>
/// <param name="sftpMessageFactory">The factory to use for creating SFTP messages.</param>
/// <param name="changeDirIsLocal">If true, the sftp client will always pass absolute paths to serve, and will locally mimmick 'changedir' operations</param>
/// <returns>
/// An <see cref="ISftpSession"/>.
/// </returns>
public ISftpSession CreateSftpSession(ISession session, int operationTimeout, Encoding encoding, ISftpResponseFactory sftpMessageFactory, bool changeDirIsLocal)
{
return new SftpSession(session, operationTimeout, encoding, sftpMessageFactory, changeDirIsLocal);
}
/// <summary>
/// Create a new <see cref="PipeStream"/>.
/// </summary>
/// <returns>
/// A <see cref="PipeStream"/>.
/// </returns>
public PipeStream CreatePipeStream()
{
return new PipeStream();
}
/// <summary>
/// Negotiates a key exchange algorithm, and creates a <see cref="IKeyExchange" /> for the negotiated
/// algorithm.
/// </summary>
/// <param name="clientAlgorithms">A <see cref="IDictionary{String, Type}"/> of the key exchange algorithms supported by the client where key is the name of the algorithm, and value is the type implementing this algorithm.</param>
/// <param name="serverAlgorithms">The names of the key exchange algorithms supported by the SSH server.</param>
/// <returns>
/// A <see cref="IKeyExchange"/> that was negotiated between client and server.
/// </returns>
/// <exception cref="ArgumentNullException"><paramref name="clientAlgorithms"/> is <c>null</c>.</exception>
/// <exception cref="ArgumentNullException"><paramref name="serverAlgorithms"/> is <c>null</c>.</exception>
/// <exception cref="SshConnectionException">No key exchange algorithms are supported by both client and server.</exception>
public IKeyExchange CreateKeyExchange(IDictionary<string, Type> clientAlgorithms, string[] serverAlgorithms)
{
if (clientAlgorithms == null)
throw new ArgumentNullException("clientAlgorithms");
if (serverAlgorithms == null)
throw new ArgumentNullException("serverAlgorithms");
// find an algorithm that is supported by both client and server
var keyExchangeAlgorithmType = (from c in clientAlgorithms
from s in serverAlgorithms
where s == c.Key
select c.Value).FirstOrDefault();
if (keyExchangeAlgorithmType == null)
{
throw new SshConnectionException("Failed to negotiate key exchange algorithm.", DisconnectReason.KeyExchangeFailed);
}
return keyExchangeAlgorithmType.CreateInstance<IKeyExchange>();
}
public ISftpFileReader CreateSftpFileReader(string fileName, ISftpSession sftpSession, uint bufferSize)
{
const int defaultMaxPendingReads = 3;
// Issue #292: Avoid overlapping SSH_FXP_OPEN and SSH_FXP_LSTAT requests for the same file as this
// causes a performance degradation on Sun SSH
var openAsyncResult = sftpSession.BeginOpen(fileName, Flags.Read, null, null);
var handle = sftpSession.EndOpen(openAsyncResult);
var statAsyncResult = sftpSession.BeginLStat(fileName, null, null);
long? fileSize;
int maxPendingReads;
var chunkSize = sftpSession.CalculateOptimalReadLength(bufferSize);
// fallback to a default maximum of pending reads when remote server does not allow us to obtain
// the attributes of the file
try
{
var fileAttributes = sftpSession.EndLStat(statAsyncResult);
fileSize = fileAttributes.Size;
maxPendingReads = Math.Min(10, (int) Math.Ceiling((double) fileAttributes.Size / chunkSize) + 1);
}
catch (SshException ex)
{
fileSize = null;
maxPendingReads = defaultMaxPendingReads;
DiagnosticAbstraction.Log(string.Format("Failed to obtain size of file. Allowing maximum {0} pending reads: {1}", maxPendingReads, ex));
}
return sftpSession.CreateFileReader(handle, sftpSession, chunkSize, maxPendingReads, fileSize);
}
public ISftpResponseFactory CreateSftpResponseFactory()
{
return new SftpResponseFactory();
}
/// <summary>
/// Creates a shell stream.
/// </summary>
/// <param name="session">The SSH session.</param>
/// <param name="terminalName">The <c>TERM</c> environment variable.</param>
/// <param name="columns">The terminal width in columns.</param>
/// <param name="rows">The terminal width in rows.</param>
/// <param name="width">The terminal height in pixels.</param>
/// <param name="height">The terminal height in pixels.</param>
/// <param name="terminalModeValues">The terminal mode values.</param>
/// <param name="bufferSize">The size of the buffer.</param>
/// <returns>
/// The created <see cref="ShellStream"/> instance.
/// </returns>
/// <exception cref="SshConnectionException">Client is not connected.</exception>
/// <remarks>
/// <para>
/// The <c>TERM</c> environment variable contains an identifier for the text window's capabilities.
/// You can get a detailed list of these cababilities by using the ‘infocmp’ command.
/// </para>
/// <para>
/// The column/row dimensions override the pixel dimensions(when non-zero). Pixel dimensions refer
/// to the drawable area of the window.
/// </para>
/// </remarks>
public ShellStream CreateShellStream(ISession session, string terminalName, uint columns, uint rows, uint width, uint height, IDictionary<TerminalModes, uint> terminalModeValues, int bufferSize)
{
return new ShellStream(session, terminalName, columns, rows, width, height, terminalModeValues, bufferSize);
}
/// <summary>
/// Creates an <see cref="IRemotePathTransformation"/> that encloses a path in double quotes, and escapes
/// any embedded double quote with a backslash.
/// </summary>
/// <returns>
/// An <see cref="IRemotePathTransformation"/> that encloses a path in double quotes, and escapes any
/// embedded double quote with a backslash.
/// with a shell.
/// </returns>
public IRemotePathTransformation CreateRemotePathDoubleQuoteTransformation()
{
return RemotePathTransformation.DoubleQuote;
}
}
}