mirror of
https://github.com/sshnet/SSH.NET.git
synced 2026-09-10 09:15:47 +00:00
Separate creating, enabling/disabling, activating/deactivating of messages into SshMessageFactory.
Huge performance improvement in micro-benchmark. Work in progress.
This commit is contained in:
@@ -918,6 +918,9 @@
|
||||
<Compile Include="..\Renci.SshNet\SshCommand.cs">
|
||||
<Link>SshCommand.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Renci.SshNet\SshMessageFactory.cs">
|
||||
<Link>SshMessageFactory.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Renci.SshNet\SubsystemSession.cs">
|
||||
<Link>SubsystemSession.cs</Link>
|
||||
</Compile>
|
||||
@@ -937,7 +940,7 @@
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<ProjectExtensions>
|
||||
<VisualStudio>
|
||||
<UserProperties ProjectLinkReference="2f5f8c90-0bd1-424f-997c-7bc6280919d1" ProjectLinkerExcludeFilter="\\?desktop(\\.*)?$;\\?silverlight(\\.*)?$;\.desktop;\.silverlight;\.xaml;^service references(\\.*)?$;\.clientconfig;^web references(\\.*)?$" />
|
||||
<UserProperties ProjectLinkerExcludeFilter="\\?desktop(\\.*)?$;\\?silverlight(\\.*)?$;\.desktop;\.silverlight;\.xaml;^service references(\\.*)?$;\.clientconfig;^web references(\\.*)?$" ProjectLinkReference="2f5f8c90-0bd1-424f-997c-7bc6280919d1" />
|
||||
</VisualStudio>
|
||||
</ProjectExtensions>
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
|
||||
@@ -58,29 +58,5 @@ namespace Renci.SshNet
|
||||
HandleMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
partial void InternalRegisterMessage(string messageName)
|
||||
{
|
||||
lock (_messagesMetadata)
|
||||
{
|
||||
foreach (var m in from m in _messagesMetadata where m.Name == messageName select m)
|
||||
{
|
||||
m.Enabled = true;
|
||||
m.Activated = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
partial void InternalUnRegisterMessage(string messageName)
|
||||
{
|
||||
lock (_messagesMetadata)
|
||||
{
|
||||
foreach (var m in from m in _messagesMetadata where m.Name == messageName select m)
|
||||
{
|
||||
m.Enabled = false;
|
||||
m.Activated = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,29 +12,5 @@ namespace Renci.SshNet
|
||||
{
|
||||
isConnected = (_socket != null && _socket.Connected);
|
||||
}
|
||||
|
||||
partial void InternalRegisterMessage(string messageName)
|
||||
{
|
||||
lock (_messagesMetadata)
|
||||
{
|
||||
foreach (var item in from m in _messagesMetadata where m.Name == messageName select m)
|
||||
{
|
||||
item.Enabled = true;
|
||||
item.Activated = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
partial void InternalUnRegisterMessage(string messageName)
|
||||
{
|
||||
lock (_messagesMetadata)
|
||||
{
|
||||
foreach (var item in from m in _messagesMetadata where m.Name == messageName select m)
|
||||
{
|
||||
item.Enabled = false;
|
||||
item.Activated = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -892,6 +892,9 @@
|
||||
<Compile Include="..\Renci.SshNet\SshCommand.cs">
|
||||
<Link>SshCommand.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Renci.SshNet\SshMessageFactory.cs">
|
||||
<Link>SshMessageFactory.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Renci.SshNet\SubsystemSession.cs">
|
||||
<Link>SubsystemSession.cs</Link>
|
||||
</Compile>
|
||||
@@ -912,7 +915,7 @@
|
||||
<FlavorProperties GUID="{A1591282-1198-4647-A2B1-27E5FF5F6F3B}">
|
||||
<SilverlightProjectProperties />
|
||||
</FlavorProperties>
|
||||
<UserProperties ProjectLinkReference="2f5f8c90-0bd1-424f-997c-7bc6280919d1" ProjectLinkerExcludeFilter="\\?desktop(\\.*)?$;\\?silverlight(\\.*)?$;\.desktop;\.silverlight;\.xaml;^service references(\\.*)?$;\.clientconfig;^web references(\\.*)?$" />
|
||||
<UserProperties ProjectLinkerExcludeFilter="\\?desktop(\\.*)?$;\\?silverlight(\\.*)?$;\.desktop;\.silverlight;\.xaml;^service references(\\.*)?$;\.clientconfig;^web references(\\.*)?$" ProjectLinkReference="2f5f8c90-0bd1-424f-997c-7bc6280919d1" />
|
||||
</VisualStudio>
|
||||
</ProjectExtensions>
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
|
||||
@@ -70,6 +70,9 @@
|
||||
<Compile Include="..\..\test\Renci.SshNet.Shared.Tests\Abstractions\ThreadAbstraction_ExecuteThread.cs">
|
||||
<Link>Classes\Abstractions\ThreadAbstraction_ExecuteThread.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\..\test\Renci.SshNet.Shared.Tests\SshMessageFactoryTest.cs">
|
||||
<Link>Classes\SshMessageFactoryTest.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="Classes\BaseClientTest_Connected_KeepAlivesNotSentConcurrently.cs" />
|
||||
<Compile Include="Classes\Channels\ChannelDirectTcpipTest.cs" />
|
||||
<Compile Include="Classes\Channels\ChannelDirectTcpipTest_Close_SessionIsConnectedAndChannelIsOpen.cs" />
|
||||
|
||||
@@ -960,6 +960,9 @@
|
||||
<Compile Include="..\Renci.SshNet\SshCommand.cs">
|
||||
<Link>SshCommand.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Renci.SshNet\SshMessageFactory.cs">
|
||||
<Link>SshMessageFactory.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Renci.SshNet\SubsystemSession.cs">
|
||||
<Link>SubsystemSession.cs</Link>
|
||||
</Compile>
|
||||
|
||||
@@ -910,6 +910,9 @@
|
||||
<Compile Include="..\Renci.SshNet\SshCommand.cs">
|
||||
<Link>SshCommand.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Renci.SshNet\SshMessageFactory.cs">
|
||||
<Link>SshMessageFactory.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Renci.SshNet\SubsystemSession.cs">
|
||||
<Link>SubsystemSession.cs</Link>
|
||||
</Compile>
|
||||
@@ -932,7 +935,7 @@
|
||||
<Import Project="$(MSBuildExtensionsPath)\Microsoft\$(TargetFrameworkIdentifier)\$(TargetFrameworkVersion)\Microsoft.$(TargetFrameworkIdentifier).CSharp.targets" />
|
||||
<ProjectExtensions>
|
||||
<VisualStudio>
|
||||
<UserProperties ProjectLinkReference="2f5f8c90-0bd1-424f-997c-7bc6280919d1" ProjectLinkerExcludeFilter="\\?desktop(\\.*)?$;\\?silverlight(\\.*)?$;\.desktop;\.silverlight;\.xaml;^service references(\\.*)?$;\.clientconfig;^web references(\\.*)?$" />
|
||||
<UserProperties ProjectLinkerExcludeFilter="\\?desktop(\\.*)?$;\\?silverlight(\\.*)?$;\.desktop;\.silverlight;\.xaml;^service references(\\.*)?$;\.clientconfig;^web references(\\.*)?$" ProjectLinkReference="2f5f8c90-0bd1-424f-997c-7bc6280919d1" />
|
||||
</VisualStudio>
|
||||
</ProjectExtensions>
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
|
||||
@@ -452,6 +452,7 @@
|
||||
</Compile>
|
||||
<Compile Include="SshClient.cs" />
|
||||
<Compile Include="SshCommand.cs" />
|
||||
<Compile Include="SshMessageFactory.cs" />
|
||||
<Compile Include="SubsystemSession.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -13,25 +13,5 @@ namespace Renci.SshNet
|
||||
{
|
||||
HandleMessage((dynamic)message);
|
||||
}
|
||||
|
||||
partial void InternalRegisterMessage(string messageName)
|
||||
{
|
||||
lock (_messagesMetadata)
|
||||
{
|
||||
Parallel.ForEach(
|
||||
from m in _messagesMetadata where m.Name == messageName select m,
|
||||
item => { item.Enabled = true; item.Activated = true; });
|
||||
}
|
||||
}
|
||||
|
||||
partial void InternalUnRegisterMessage(string messageName)
|
||||
{
|
||||
lock (_messagesMetadata)
|
||||
{
|
||||
Parallel.ForEach(
|
||||
from m in _messagesMetadata where m.Name == messageName select m,
|
||||
item => { item.Enabled = false; item.Activated = false; });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+11
-82
@@ -84,7 +84,7 @@ namespace Renci.SshNet
|
||||
/// <summary>
|
||||
/// Holds metada about session messages
|
||||
/// </summary>
|
||||
private IEnumerable<MessageMetadata> _messagesMetadata;
|
||||
private SshMessageFactory _sshMessageFactory;
|
||||
|
||||
/// <summary>
|
||||
/// Holds connection socket.
|
||||
@@ -523,7 +523,7 @@ namespace Renci.SshNet
|
||||
Reset();
|
||||
|
||||
// Build list of available messages while connecting
|
||||
_messagesMetadata = GetMessagesMetadata();
|
||||
_sshMessageFactory = new SshMessageFactory();
|
||||
|
||||
switch (ConnectionInfo.ProxyType)
|
||||
{
|
||||
@@ -621,6 +621,8 @@ namespace Renci.SshNet
|
||||
ConnectionInfo.Authenticate(this, _serviceFactory);
|
||||
_isAuthenticated = true;
|
||||
|
||||
Thread.Sleep(2000);
|
||||
|
||||
// Register Connection messages
|
||||
RegisterMessage("SSH_MSG_GLOBAL_REQUEST");
|
||||
RegisterMessage("SSH_MSG_REQUEST_SUCCESS");
|
||||
@@ -864,49 +866,6 @@ namespace Renci.SshNet
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<MessageMetadata> GetMessagesMetadata()
|
||||
{
|
||||
return new []
|
||||
{
|
||||
new MessageMetadata { Name = "SSH_MSG_NEWKEYS", Number = 21, Type = typeof(NewKeysMessage) },
|
||||
new MessageMetadata { Name = "SSH_MSG_REQUEST_FAILURE", Number = 82, Type = typeof(RequestFailureMessage) },
|
||||
new MessageMetadata { Name = "SSH_MSG_KEXINIT", Number = 20, Type = typeof(KeyExchangeInitMessage) },
|
||||
new MessageMetadata { Name = "SSH_MSG_CHANNEL_OPEN_FAILURE", Number = 92, Type = typeof(ChannelOpenFailureMessage) },
|
||||
new MessageMetadata { Name = "SSH_MSG_CHANNEL_FAILURE", Number = 100, Type = typeof(ChannelFailureMessage) },
|
||||
new MessageMetadata { Name = "SSH_MSG_CHANNEL_EXTENDED_DATA", Number = 95, Type = typeof(ChannelExtendedDataMessage) },
|
||||
new MessageMetadata { Name = "SSH_MSG_CHANNEL_DATA", Number = 94, Type = typeof(ChannelDataMessage) },
|
||||
new MessageMetadata { Name = "SSH_MSG_USERAUTH_REQUEST", Number = 50, Type = typeof(RequestMessage) },
|
||||
new MessageMetadata { Name = "SSH_MSG_CHANNEL_REQUEST", Number = 98, Type = typeof(ChannelRequestMessage) },
|
||||
new MessageMetadata { Name = "SSH_MSG_USERAUTH_BANNER", Number = 53, Type = typeof(BannerMessage) },
|
||||
new MessageMetadata { Name = "SSH_MSG_USERAUTH_INFO_RESPONSE", Number = 61, Type = typeof(InformationResponseMessage) },
|
||||
new MessageMetadata { Name = "SSH_MSG_USERAUTH_FAILURE", Number = 51, Type = typeof(FailureMessage) },
|
||||
new MessageMetadata { Name = "SSH_MSG_DEBUG", Number = 4, Type = typeof(DebugMessage), },
|
||||
new MessageMetadata { Name = "SSH_MSG_KEXDH_INIT", Number = 30, Type = typeof(KeyExchangeDhInitMessage) },
|
||||
new MessageMetadata { Name = "SSH_MSG_GLOBAL_REQUEST", Number = 80, Type = typeof(GlobalRequestMessage) },
|
||||
new MessageMetadata { Name = "SSH_MSG_CHANNEL_OPEN", Number = 90, Type = typeof(ChannelOpenMessage) },
|
||||
new MessageMetadata { Name = "SSH_MSG_CHANNEL_OPEN_CONFIRMATION", Number = 91, Type = typeof(ChannelOpenConfirmationMessage) },
|
||||
new MessageMetadata { Name = "SSH_MSG_USERAUTH_INFO_REQUEST", Number = 60, Type = typeof(InformationRequestMessage) },
|
||||
new MessageMetadata { Name = "SSH_MSG_UNIMPLEMENTED", Number = 3, Type = typeof(UnimplementedMessage) },
|
||||
new MessageMetadata { Name = "SSH_MSG_REQUEST_SUCCESS", Number = 81, Type = typeof(RequestSuccessMessage) },
|
||||
new MessageMetadata { Name = "SSH_MSG_CHANNEL_SUCCESS", Number = 99, Type = typeof(ChannelSuccessMessage) },
|
||||
new MessageMetadata { Name = "SSH_MSG_USERAUTH_PASSWD_CHANGEREQ", Number = 60, Type = typeof(PasswordChangeRequiredMessage) },
|
||||
new MessageMetadata { Name = "SSH_MSG_DISCONNECT", Number = 1, Type = typeof(DisconnectMessage) },
|
||||
new MessageMetadata { Name = "SSH_MSG_SERVICE_REQUEST", Number = 5, Type = typeof(ServiceRequestMessage) },
|
||||
new MessageMetadata { Name = "SSH_MSG_KEX_DH_GEX_REQUEST", Number = 34, Type = typeof(KeyExchangeDhGroupExchangeRequest) },
|
||||
new MessageMetadata { Name = "SSH_MSG_KEX_DH_GEX_GROUP", Number = 31, Type = typeof(KeyExchangeDhGroupExchangeGroup) },
|
||||
new MessageMetadata { Name = "SSH_MSG_USERAUTH_SUCCESS", Number = 52, Type = typeof(SuccessMessage) },
|
||||
new MessageMetadata { Name = "SSH_MSG_USERAUTH_PK_OK", Number = 60, Type = typeof(PublicKeyMessage) },
|
||||
new MessageMetadata { Name = "SSH_MSG_IGNORE", Number = 2, Type = typeof(IgnoreMessage) },
|
||||
new MessageMetadata { Name = "SSH_MSG_CHANNEL_WINDOW_ADJUST", Number = 93, Type = typeof(ChannelWindowAdjustMessage) },
|
||||
new MessageMetadata { Name = "SSH_MSG_CHANNEL_EOF", Number = 96, Type = typeof(ChannelEofMessage) },
|
||||
new MessageMetadata { Name = "SSH_MSG_CHANNEL_CLOSE", Number = 97, Type = typeof(ChannelCloseMessage) },
|
||||
new MessageMetadata { Name = "SSH_MSG_SERVICE_ACCEPT", Number = 6, Type = typeof(ServiceAcceptMessage) },
|
||||
new MessageMetadata { Name = "SSH_MSG_KEXDH_REPLY", Number = 31, Type = typeof(KeyExchangeDhReplyMessage) },
|
||||
new MessageMetadata { Name = "SSH_MSG_KEX_DH_GEX_INIT", Number = 32, Type = typeof(KeyExchangeDhGroupExchangeInit) },
|
||||
new MessageMetadata { Name = "SSH_MSG_KEX_DH_GEX_REPLY", Number = 33, Type = typeof(KeyExchangeDhGroupExchangeReply) }
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Receives the message from the server.
|
||||
/// </summary>
|
||||
@@ -1332,12 +1291,8 @@ namespace Renci.SshNet
|
||||
|
||||
_keyExchangeCompletedWaitHandle.Reset();
|
||||
|
||||
// Disable all registered messages except key exchange related
|
||||
foreach (var messageMetadata in _messagesMetadata)
|
||||
{
|
||||
if (messageMetadata.Activated && messageMetadata.Number > 2 && (messageMetadata.Number < 20 || messageMetadata.Number > 30))
|
||||
messageMetadata.Enabled = false;
|
||||
}
|
||||
// Disable messages that are not key exchange related
|
||||
_sshMessageFactory.DisableNonKeyExchangeMessages();
|
||||
|
||||
_keyExchange = _serviceFactory.CreateKeyExchange(ConnectionInfo.KeyExchangeAlgorithms,
|
||||
message.KeyExchangeAlgorithms);
|
||||
@@ -1395,12 +1350,8 @@ namespace Renci.SshNet
|
||||
_keyExchange = null;
|
||||
}
|
||||
|
||||
// Enable all active registered messages
|
||||
foreach (var messageMetadata in _messagesMetadata)
|
||||
{
|
||||
if (messageMetadata.Activated)
|
||||
messageMetadata.Enabled = true;
|
||||
}
|
||||
// Enable activated messages that are not key exchange related
|
||||
_sshMessageFactory.EnableActivatedMessages();
|
||||
|
||||
var newKeysReceived = NewKeysReceived;
|
||||
if (newKeysReceived != null)
|
||||
@@ -1662,7 +1613,7 @@ namespace Renci.SshNet
|
||||
/// <param name="messageName">The name of the message to register with the session.</param>
|
||||
public void RegisterMessage(string messageName)
|
||||
{
|
||||
InternalRegisterMessage(messageName);
|
||||
_sshMessageFactory.EnableAndActivateMessage(messageName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1671,7 +1622,7 @@ namespace Renci.SshNet
|
||||
/// <param name="messageName">The name of the message to unregister with the session.</param>
|
||||
public void UnRegisterMessage(string messageName)
|
||||
{
|
||||
InternalUnRegisterMessage(messageName);
|
||||
_sshMessageFactory.DisableAndDeactivateMessage(messageName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1686,12 +1637,7 @@ namespace Renci.SshNet
|
||||
private Message LoadMessage(byte[] data, int offset)
|
||||
{
|
||||
var messageType = data[offset];
|
||||
var messageMetadata = (from m in _messagesMetadata where m.Number == messageType && m.Enabled && m.Activated select m).FirstOrDefault();
|
||||
if (messageMetadata == null)
|
||||
throw new SshException(string.Format(CultureInfo.CurrentCulture, "Message type {0} is not valid.", messageType));
|
||||
|
||||
var message = messageMetadata.Type.CreateInstance<Message>();
|
||||
|
||||
var message = _sshMessageFactory.Create(messageType);
|
||||
message.Load(data, offset);
|
||||
|
||||
DiagnosticAbstraction.Log(string.Format("ReceiveMessage from server: '{0}': '{1}'.", message.GetType().Name, message));
|
||||
@@ -1699,10 +1645,6 @@ namespace Renci.SshNet
|
||||
return message;
|
||||
}
|
||||
|
||||
partial void InternalRegisterMessage(string messageName);
|
||||
|
||||
partial void InternalUnRegisterMessage(string messageName);
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
@@ -2402,18 +2344,5 @@ namespace Renci.SshNet
|
||||
}
|
||||
|
||||
#endregion ISession implementation
|
||||
|
||||
private class MessageMetadata
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public byte Number { get; set; }
|
||||
|
||||
public bool Enabled { get; set; }
|
||||
|
||||
public bool Activated { get; set; }
|
||||
|
||||
public Type Type { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using Renci.SshNet.Common;
|
||||
using Renci.SshNet.Messages;
|
||||
using Renci.SshNet.Messages.Authentication;
|
||||
using Renci.SshNet.Messages.Connection;
|
||||
using Renci.SshNet.Messages.Transport;
|
||||
|
||||
namespace Renci.SshNet
|
||||
{
|
||||
internal class SshMessageFactory
|
||||
{
|
||||
private readonly MessageMetadata[] _enabledMessagesByNumber;
|
||||
private readonly bool[] _activatedMessagesById;
|
||||
|
||||
private static readonly MessageMetadata[] AllMessages;
|
||||
private static readonly IDictionary<string, MessageMetadata> MessagesByName;
|
||||
|
||||
static SshMessageFactory()
|
||||
{
|
||||
AllMessages = new MessageMetadata[]
|
||||
{
|
||||
new MessageMetadata<KeyExchangeInitMessage>(0, "SSH_MSG_KEXINIT", 20),
|
||||
new MessageMetadata<NewKeysMessage> (1, "SSH_MSG_NEWKEYS", 21),
|
||||
new MessageMetadata<RequestFailureMessage> (2, "SSH_MSG_REQUEST_FAILURE", 82),
|
||||
new MessageMetadata<ChannelOpenFailureMessage> (3, "SSH_MSG_CHANNEL_OPEN_FAILURE", 92),
|
||||
new MessageMetadata<ChannelFailureMessage> (4, "SSH_MSG_CHANNEL_FAILURE", 100),
|
||||
new MessageMetadata<ChannelExtendedDataMessage> (5, "SSH_MSG_CHANNEL_EXTENDED_DATA", 95),
|
||||
new MessageMetadata<ChannelDataMessage> (6, "SSH_MSG_CHANNEL_DATA", 94),
|
||||
new MessageMetadata<ChannelRequestMessage> (7, "SSH_MSG_CHANNEL_REQUEST", 98),
|
||||
new MessageMetadata<BannerMessage> (8, "SSH_MSG_USERAUTH_BANNER", 53),
|
||||
new MessageMetadata<InformationResponseMessage> (9, "SSH_MSG_USERAUTH_INFO_RESPONSE", 61),
|
||||
new MessageMetadata<FailureMessage> (10, "SSH_MSG_USERAUTH_FAILURE", 51),
|
||||
new MessageMetadata<DebugMessage> (11, "SSH_MSG_DEBUG", 4),
|
||||
new MessageMetadata<GlobalRequestMessage> (12, "SSH_MSG_GLOBAL_REQUEST", 80),
|
||||
new MessageMetadata<ChannelOpenMessage> (13, "SSH_MSG_CHANNEL_OPEN", 90),
|
||||
new MessageMetadata<ChannelOpenConfirmationMessage> (14, "SSH_MSG_CHANNEL_OPEN_CONFIRMATION", 91),
|
||||
new MessageMetadata<InformationRequestMessage> (15, "SSH_MSG_USERAUTH_INFO_REQUEST", 60),
|
||||
new MessageMetadata<UnimplementedMessage> (16, "SSH_MSG_UNIMPLEMENTED", 3),
|
||||
new MessageMetadata<RequestSuccessMessage> (17, "SSH_MSG_REQUEST_SUCCESS", 81),
|
||||
new MessageMetadata<ChannelSuccessMessage> (18, "SSH_MSG_CHANNEL_SUCCESS", 99),
|
||||
new MessageMetadata<PasswordChangeRequiredMessage> (19, "SSH_MSG_USERAUTH_PASSWD_CHANGEREQ", 60),
|
||||
new MessageMetadata<DisconnectMessage> (20, "SSH_MSG_DISCONNECT", 1),
|
||||
new MessageMetadata<SuccessMessage> (21, "SSH_MSG_USERAUTH_SUCCESS", 52),
|
||||
new MessageMetadata<PublicKeyMessage> (22, "SSH_MSG_USERAUTH_PK_OK", 60),
|
||||
new MessageMetadata<IgnoreMessage> (23, "SSH_MSG_IGNORE", 2),
|
||||
new MessageMetadata<ChannelWindowAdjustMessage> (24, "SSH_MSG_CHANNEL_WINDOW_ADJUST", 93),
|
||||
new MessageMetadata<ChannelEofMessage> (25, "SSH_MSG_CHANNEL_EOF", 96),
|
||||
new MessageMetadata<ChannelCloseMessage> (26, "SSH_MSG_CHANNEL_CLOSE", 97),
|
||||
new MessageMetadata<ServiceAcceptMessage> (27, "SSH_MSG_SERVICE_ACCEPT", 6),
|
||||
new MessageMetadata<KeyExchangeDhGroupExchangeGroup> (28, "SSH_MSG_KEX_DH_GEX_GROUP", 31),
|
||||
new MessageMetadata<KeyExchangeDhReplyMessage> (29, "SSH_MSG_KEXDH_REPLY", 31),
|
||||
new MessageMetadata<KeyExchangeDhGroupExchangeReply> (30, "SSH_MSG_KEX_DH_GEX_REPLY", 33)
|
||||
};
|
||||
|
||||
MessagesByName = new Dictionary<string, MessageMetadata>(31);
|
||||
foreach (var messageMetadata in AllMessages)
|
||||
MessagesByName.Add(messageMetadata.Name, messageMetadata);
|
||||
}
|
||||
|
||||
public SshMessageFactory()
|
||||
{
|
||||
_activatedMessagesById = new bool[31];
|
||||
_enabledMessagesByNumber = new MessageMetadata[101];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disables and deactivate all messages.
|
||||
/// </summary>
|
||||
public void Reset()
|
||||
{
|
||||
Array.Clear(_activatedMessagesById, 0, _activatedMessagesById.Length);
|
||||
Array.Clear(_enabledMessagesByNumber, 0, _enabledMessagesByNumber.Length);
|
||||
}
|
||||
|
||||
public Message Create(byte messageNumber)
|
||||
{
|
||||
var messageMetadata = _enabledMessagesByNumber[messageNumber];
|
||||
|
||||
if (messageMetadata == null)
|
||||
{
|
||||
throw new SshException(string.Format(CultureInfo.CurrentCulture, "Message type {0} is not valid.", messageNumber));
|
||||
}
|
||||
|
||||
return messageMetadata.Create();
|
||||
}
|
||||
|
||||
public void DisableNonKeyExchangeMessages()
|
||||
{
|
||||
foreach (var messageMetadata in AllMessages)
|
||||
{
|
||||
var messageNumber = messageMetadata.Number;
|
||||
if ((messageNumber > 2 && messageNumber < 20) || messageNumber > 30)
|
||||
{
|
||||
//Console.WriteLine("Disabling " + messageMetadata.Name + "...");
|
||||
_enabledMessagesByNumber[messageNumber] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void EnableActivatedMessages()
|
||||
{
|
||||
foreach (var messageMetadata in AllMessages)
|
||||
{
|
||||
if (!_activatedMessagesById[messageMetadata.Id])
|
||||
continue;
|
||||
|
||||
var enabledMessage = _enabledMessagesByNumber[messageMetadata.Number];
|
||||
if (enabledMessage != null && enabledMessage != messageMetadata)
|
||||
{
|
||||
throw new Exception("Message X is already enabled for Y");
|
||||
}
|
||||
_enabledMessagesByNumber[messageMetadata.Number] = messageMetadata;
|
||||
}
|
||||
}
|
||||
|
||||
public void EnableAndActivateMessage(string messageName)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
MessageMetadata messageMetadata;
|
||||
|
||||
if (!MessagesByName.TryGetValue(messageName, out messageMetadata))
|
||||
{
|
||||
throw new Exception("TODO");
|
||||
}
|
||||
|
||||
var enabledMessage = _enabledMessagesByNumber[messageMetadata.Number];
|
||||
if (enabledMessage != null && enabledMessage != messageMetadata)
|
||||
{
|
||||
throw new Exception("Message X is already enabled for Y");
|
||||
}
|
||||
_enabledMessagesByNumber[messageMetadata.Number] = messageMetadata;
|
||||
|
||||
_activatedMessagesById[messageMetadata.Id] = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void DisableAndDeactivateMessage(string messageName)
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
MessageMetadata messageMetadata;
|
||||
|
||||
if (!MessagesByName.TryGetValue(messageName, out messageMetadata))
|
||||
{
|
||||
throw new Exception("TODO");
|
||||
}
|
||||
|
||||
_activatedMessagesById[messageMetadata.Id] = false;
|
||||
|
||||
var enabledMetadata = _enabledMessagesByNumber[messageMetadata.Number];
|
||||
if (enabledMetadata != null && enabledMetadata != messageMetadata)
|
||||
throw new Exception();
|
||||
_enabledMessagesByNumber[messageMetadata.Number] = null;
|
||||
}
|
||||
}
|
||||
|
||||
private abstract class MessageMetadata
|
||||
{
|
||||
protected MessageMetadata(byte id, string name, byte number)
|
||||
{
|
||||
Id = id;
|
||||
Name = name;
|
||||
Number = number;
|
||||
}
|
||||
|
||||
public readonly byte Id;
|
||||
|
||||
public readonly string Name;
|
||||
|
||||
public readonly byte Number;
|
||||
|
||||
public abstract Message Create();
|
||||
}
|
||||
|
||||
private class MessageMetadata<T> : MessageMetadata where T : Message, new()
|
||||
{
|
||||
public MessageMetadata(byte id, string name, byte number)
|
||||
: base(id, name, number)
|
||||
{
|
||||
}
|
||||
|
||||
public override Message Create()
|
||||
{
|
||||
return new T();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,5 +12,6 @@
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Abstractions\CryptoAbstraction_GenerateRandom.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Abstractions\DnsAbstraction_GetHostAddresses.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Abstractions\ThreadAbstraction_ExecuteThread.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)SshMessageFactoryTest.cs" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,632 @@
|
||||
#if SILVERLIGHT
|
||||
using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;
|
||||
#else
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Renci.SshNet.Common;
|
||||
using Renci.SshNet.Messages;
|
||||
using Renci.SshNet.Messages.Authentication;
|
||||
using Renci.SshNet.Messages.Connection;
|
||||
using Renci.SshNet.Messages.Transport;
|
||||
|
||||
#endif
|
||||
|
||||
namespace Renci.SshNet.Tests
|
||||
{
|
||||
[TestClass]
|
||||
public class SshMessageFactoryTest
|
||||
{
|
||||
private SshMessageFactory _sshMessageFactory;
|
||||
private SshMessageFactoryOriginal _sshMessageFactoryOriginal;
|
||||
|
||||
[TestInitialize]
|
||||
public void SetUp()
|
||||
{
|
||||
_sshMessageFactory = new SshMessageFactory();
|
||||
_sshMessageFactoryOriginal = new SshMessageFactoryOriginal();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void EnableInformationRequestMessage()
|
||||
{
|
||||
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_USERAUTH_INFO_REQUEST");
|
||||
var message = _sshMessageFactory.Create(60);
|
||||
Assert.AreEqual(typeof(InformationRequestMessage), message.GetType());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void EnablePasswordChangeRequiredMessage()
|
||||
{
|
||||
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
|
||||
var message = _sshMessageFactory.Create(60);
|
||||
Assert.AreEqual(typeof(PasswordChangeRequiredMessage), message.GetType());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Di()
|
||||
{
|
||||
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
|
||||
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_SERVICE_ACCEPT");
|
||||
|
||||
_sshMessageFactory.DisableNonKeyExchangeMessages();
|
||||
|
||||
try
|
||||
{
|
||||
_sshMessageFactory.Create(6); // SSH_MSG_SERVICE_ACCEPT
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshException)
|
||||
{
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_sshMessageFactory.Create(60);
|
||||
// SSH_MSG_USERAUTH_PASSWD_CHANGEREQ or SSH_MSG_USERAUTH_INFO_REQUEST or SSH_MSG_USERAUTH_PK_OK
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshException)
|
||||
{
|
||||
}
|
||||
|
||||
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_USERAUTH_INFO_REQUEST");
|
||||
var message = _sshMessageFactory.Create(60);
|
||||
Assert.AreEqual(typeof(InformationRequestMessage), message.GetType());
|
||||
|
||||
_sshMessageFactory.EnableActivatedMessages();
|
||||
|
||||
var message2 = _sshMessageFactory.Create(60);
|
||||
Assert.AreEqual(typeof(InformationRequestMessage), message2.GetType());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Performance_Ctor()
|
||||
{
|
||||
const int runCount = 100000;
|
||||
|
||||
// warm-up
|
||||
for (var i = 0; i < 3; i++)
|
||||
{
|
||||
var sshMessageFactory = new SshMessageFactory();
|
||||
var sshMessageFactoryOriginal = new SshMessageFactoryOriginal();
|
||||
}
|
||||
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
GC.Collect();
|
||||
|
||||
var stopwatch = new Stopwatch();
|
||||
stopwatch.Start();
|
||||
|
||||
for (var i = 0; i < runCount; i++)
|
||||
{
|
||||
var sshMessageFactory = new SshMessageFactory();
|
||||
}
|
||||
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
GC.Collect();
|
||||
|
||||
stopwatch.Stop();
|
||||
|
||||
Console.WriteLine(stopwatch.ElapsedMilliseconds);
|
||||
|
||||
stopwatch.Reset();
|
||||
stopwatch.Start();
|
||||
|
||||
for (var i = 0; i < runCount; i++)
|
||||
{
|
||||
var sshMessageFactory = new SshMessageFactoryOriginal();
|
||||
}
|
||||
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
GC.Collect();
|
||||
|
||||
stopwatch.Stop();
|
||||
|
||||
Console.WriteLine(stopwatch.ElapsedMilliseconds);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Performance_Create()
|
||||
{
|
||||
const int runCount = 10000000;
|
||||
const string messageName = "SSH_MSG_CHANNEL_CLOSE";
|
||||
|
||||
_sshMessageFactory.EnableAndActivateMessage(messageName);
|
||||
_sshMessageFactoryOriginal.EnableAndActivateMessage(messageName);
|
||||
|
||||
// warm-up
|
||||
for (var i = 0; i < 3; i++)
|
||||
{
|
||||
_sshMessageFactory.Create(97);
|
||||
_sshMessageFactoryOriginal.Create(97);
|
||||
}
|
||||
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
GC.Collect();
|
||||
|
||||
var stopwatch = new Stopwatch();
|
||||
stopwatch.Start();
|
||||
|
||||
for (var i = 0; i < runCount; i++)
|
||||
{
|
||||
var msg = _sshMessageFactory.Create(97);
|
||||
if (msg == null)
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
GC.Collect();
|
||||
|
||||
stopwatch.Stop();
|
||||
|
||||
Console.WriteLine(stopwatch.ElapsedMilliseconds);
|
||||
|
||||
stopwatch.Reset();
|
||||
stopwatch.Start();
|
||||
|
||||
for (var i = 0; i < runCount; i++)
|
||||
{
|
||||
var msg = _sshMessageFactoryOriginal.Create(97);
|
||||
if (msg == null)
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
GC.Collect();
|
||||
|
||||
stopwatch.Stop();
|
||||
|
||||
Console.WriteLine(stopwatch.ElapsedMilliseconds);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Performance_EnableAndActivateMessage()
|
||||
{
|
||||
const int runCount = 1000000;
|
||||
const string messageName = "SSH_MSG_CHANNEL_CLOSE";
|
||||
|
||||
// warm-up
|
||||
for (var i = 0; i < 3; i++)
|
||||
{
|
||||
_sshMessageFactory.EnableAndActivateMessage(messageName);
|
||||
_sshMessageFactoryOriginal.EnableAndActivateMessage(messageName);
|
||||
}
|
||||
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
GC.Collect();
|
||||
|
||||
var stopwatch = new Stopwatch();
|
||||
stopwatch.Start();
|
||||
|
||||
for (var i = 0; i < runCount; i++)
|
||||
_sshMessageFactory.EnableAndActivateMessage(messageName);
|
||||
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
GC.Collect();
|
||||
|
||||
stopwatch.Stop();
|
||||
|
||||
Console.WriteLine(stopwatch.ElapsedMilliseconds);
|
||||
|
||||
stopwatch.Reset();
|
||||
stopwatch.Start();
|
||||
|
||||
for (var i = 0; i < runCount; i++)
|
||||
_sshMessageFactoryOriginal.EnableAndActivateMessage(messageName);
|
||||
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
GC.Collect();
|
||||
|
||||
stopwatch.Stop();
|
||||
|
||||
Console.WriteLine(stopwatch.ElapsedMilliseconds);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Performance_DisableAndDeactivateMessage()
|
||||
{
|
||||
const int runCount = 1000000;
|
||||
const string messageName = "SSH_MSG_CHANNEL_CLOSE";
|
||||
|
||||
// warm-up
|
||||
for (var i = 0; i < 3; i++)
|
||||
{
|
||||
_sshMessageFactory.DisableAndDeactivateMessage(messageName);
|
||||
_sshMessageFactoryOriginal.DisableAndDeactivateMessage(messageName);
|
||||
}
|
||||
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
GC.Collect();
|
||||
|
||||
var stopwatch = new Stopwatch();
|
||||
stopwatch.Start();
|
||||
|
||||
for (var i = 0; i < runCount; i++)
|
||||
_sshMessageFactory.DisableAndDeactivateMessage(messageName);
|
||||
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
GC.Collect();
|
||||
|
||||
stopwatch.Stop();
|
||||
|
||||
Console.WriteLine(stopwatch.ElapsedMilliseconds);
|
||||
|
||||
stopwatch.Reset();
|
||||
stopwatch.Start();
|
||||
|
||||
for (var i = 0; i < runCount; i++)
|
||||
_sshMessageFactoryOriginal.DisableAndDeactivateMessage(messageName);
|
||||
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
GC.Collect();
|
||||
|
||||
stopwatch.Stop();
|
||||
|
||||
Console.WriteLine(stopwatch.ElapsedMilliseconds);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Performance_DisableNonKeyExchangeMessages()
|
||||
{
|
||||
const int runCount = 1000000;
|
||||
|
||||
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_USERAUTH_BANNER");
|
||||
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_DEBUG");
|
||||
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_UNIMPLEMENTED");
|
||||
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_SERVICE_ACCEPT");
|
||||
|
||||
_sshMessageFactoryOriginal.EnableAndActivateMessage("SSH_MSG_USERAUTH_BANNER");
|
||||
_sshMessageFactoryOriginal.EnableAndActivateMessage("SSH_MSG_DEBUG");
|
||||
_sshMessageFactoryOriginal.EnableAndActivateMessage("SSH_MSG_UNIMPLEMENTED");
|
||||
_sshMessageFactoryOriginal.EnableAndActivateMessage("SSH_MSG_SERVICE_ACCEPT");
|
||||
|
||||
// warm-up
|
||||
for (var i = 0; i < 3; i++)
|
||||
{
|
||||
_sshMessageFactory.DisableNonKeyExchangeMessages();
|
||||
_sshMessageFactory.EnableActivatedMessages();
|
||||
|
||||
_sshMessageFactoryOriginal.DisableNonKeyExchangeMessages();
|
||||
_sshMessageFactoryOriginal.EnableActivatedMessages();
|
||||
}
|
||||
|
||||
//Console.WriteLine("Starting test");
|
||||
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
GC.Collect();
|
||||
|
||||
var stopwatch = new Stopwatch();
|
||||
stopwatch.Start();
|
||||
|
||||
for (var i = 0; i < runCount; i++)
|
||||
{
|
||||
_sshMessageFactory.DisableNonKeyExchangeMessages();
|
||||
_sshMessageFactory.EnableActivatedMessages();
|
||||
}
|
||||
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
GC.Collect();
|
||||
|
||||
stopwatch.Stop();
|
||||
|
||||
Console.WriteLine(stopwatch.ElapsedMilliseconds);
|
||||
|
||||
stopwatch.Reset();
|
||||
stopwatch.Start();
|
||||
|
||||
for (var i = 0; i < runCount; i++)
|
||||
{
|
||||
_sshMessageFactoryOriginal.DisableNonKeyExchangeMessages();
|
||||
_sshMessageFactoryOriginal.EnableActivatedMessages();
|
||||
}
|
||||
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
GC.Collect();
|
||||
|
||||
stopwatch.Stop();
|
||||
|
||||
Console.WriteLine(stopwatch.ElapsedMilliseconds);
|
||||
}
|
||||
|
||||
internal class SshMessageFactoryOriginal
|
||||
{
|
||||
private readonly IEnumerable<MessageMetadata> _messagesMetadata;
|
||||
|
||||
public SshMessageFactoryOriginal()
|
||||
{
|
||||
_messagesMetadata = new[]
|
||||
{
|
||||
new MessageMetadata {Name = "SSH_MSG_NEWKEYS", Number = 21, Type = typeof(NewKeysMessage)},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_REQUEST_FAILURE",
|
||||
Number = 82,
|
||||
Type = typeof(RequestFailureMessage)
|
||||
},
|
||||
new MessageMetadata {Name = "SSH_MSG_KEXINIT", Number = 20, Type = typeof(KeyExchangeInitMessage)},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_CHANNEL_OPEN_FAILURE",
|
||||
Number = 92,
|
||||
Type = typeof(ChannelOpenFailureMessage)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_CHANNEL_FAILURE",
|
||||
Number = 100,
|
||||
Type = typeof(ChannelFailureMessage)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_CHANNEL_EXTENDED_DATA",
|
||||
Number = 95,
|
||||
Type = typeof(ChannelExtendedDataMessage)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_CHANNEL_DATA",
|
||||
Number = 94,
|
||||
Type = typeof(ChannelDataMessage)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_USERAUTH_REQUEST",
|
||||
Number = 50,
|
||||
Type = typeof(RequestMessage)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_CHANNEL_REQUEST",
|
||||
Number = 98,
|
||||
Type = typeof(ChannelRequestMessage)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_USERAUTH_BANNER",
|
||||
Number = 53,
|
||||
Type = typeof(BannerMessage)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_USERAUTH_INFO_RESPONSE",
|
||||
Number = 61,
|
||||
Type = typeof(InformationResponseMessage)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_USERAUTH_FAILURE",
|
||||
Number = 51,
|
||||
Type = typeof(FailureMessage)
|
||||
},
|
||||
new MessageMetadata {Name = "SSH_MSG_DEBUG", Number = 4, Type = typeof(DebugMessage),},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_KEXDH_INIT",
|
||||
Number = 30,
|
||||
Type = typeof(KeyExchangeDhInitMessage)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_GLOBAL_REQUEST",
|
||||
Number = 80,
|
||||
Type = typeof(GlobalRequestMessage)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_CHANNEL_OPEN",
|
||||
Number = 90,
|
||||
Type = typeof(ChannelOpenMessage)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_CHANNEL_OPEN_CONFIRMATION",
|
||||
Number = 91,
|
||||
Type = typeof(ChannelOpenConfirmationMessage)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_USERAUTH_INFO_REQUEST",
|
||||
Number = 60,
|
||||
Type = typeof(InformationRequestMessage)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_UNIMPLEMENTED",
|
||||
Number = 3,
|
||||
Type = typeof(UnimplementedMessage)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_REQUEST_SUCCESS",
|
||||
Number = 81,
|
||||
Type = typeof(RequestSuccessMessage)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_CHANNEL_SUCCESS",
|
||||
Number = 99,
|
||||
Type = typeof(ChannelSuccessMessage)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_USERAUTH_PASSWD_CHANGEREQ",
|
||||
Number = 60,
|
||||
Type = typeof(PasswordChangeRequiredMessage)
|
||||
},
|
||||
new MessageMetadata {Name = "SSH_MSG_DISCONNECT", Number = 1, Type = typeof(DisconnectMessage)},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_SERVICE_REQUEST",
|
||||
Number = 5,
|
||||
Type = typeof(ServiceRequestMessage)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_KEX_DH_GEX_REQUEST",
|
||||
Number = 34,
|
||||
Type = typeof(KeyExchangeDhGroupExchangeRequest)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_KEX_DH_GEX_GROUP",
|
||||
Number = 31,
|
||||
Type = typeof(KeyExchangeDhGroupExchangeGroup)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_USERAUTH_SUCCESS",
|
||||
Number = 52,
|
||||
Type = typeof(SuccessMessage)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_USERAUTH_PK_OK",
|
||||
Number = 60,
|
||||
Type = typeof(PublicKeyMessage)
|
||||
},
|
||||
new MessageMetadata {Name = "SSH_MSG_IGNORE", Number = 2, Type = typeof(IgnoreMessage)},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_CHANNEL_WINDOW_ADJUST",
|
||||
Number = 93,
|
||||
Type = typeof(ChannelWindowAdjustMessage)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_CHANNEL_EOF",
|
||||
Number = 96,
|
||||
Type = typeof(ChannelEofMessage)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_CHANNEL_CLOSE",
|
||||
Number = 97,
|
||||
Type = typeof(ChannelCloseMessage)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_SERVICE_ACCEPT",
|
||||
Number = 6,
|
||||
Type = typeof(ServiceAcceptMessage)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_KEXDH_REPLY",
|
||||
Number = 31,
|
||||
Type = typeof(KeyExchangeDhReplyMessage)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_KEX_DH_GEX_INIT",
|
||||
Number = 32,
|
||||
Type = typeof(KeyExchangeDhGroupExchangeInit)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_KEX_DH_GEX_REPLY",
|
||||
Number = 33,
|
||||
Type = typeof(KeyExchangeDhGroupExchangeReply)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disables and deactivate all messages.
|
||||
/// </summary>
|
||||
public void Reset()
|
||||
{
|
||||
foreach (var messageMetadata in _messagesMetadata)
|
||||
{
|
||||
messageMetadata.Activated = messageMetadata.Enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void EnableActivatedMessages()
|
||||
{
|
||||
foreach (var messageMetadata in _messagesMetadata)
|
||||
{
|
||||
if (messageMetadata.Activated)
|
||||
messageMetadata.Enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
public Message Create(byte messageNumber)
|
||||
{
|
||||
var messageMetadata =
|
||||
(from m in _messagesMetadata where m.Number == messageNumber && m.Enabled && m.Activated select m)
|
||||
.FirstOrDefault();
|
||||
if (messageMetadata == null)
|
||||
throw new SshException(string.Format(CultureInfo.CurrentCulture, "Message type {0} is not valid.",
|
||||
messageNumber));
|
||||
|
||||
return messageMetadata.Type.CreateInstance<Message>();
|
||||
}
|
||||
|
||||
public void DisableNonKeyExchangeMessages()
|
||||
{
|
||||
foreach (var messageMetadata in _messagesMetadata)
|
||||
{
|
||||
if (messageMetadata.Activated && messageMetadata.Number > 2 &&
|
||||
(messageMetadata.Number < 20 || messageMetadata.Number > 30))
|
||||
{
|
||||
//Console.WriteLine("Disabling " + messageMetadata.Name + "...");
|
||||
|
||||
messageMetadata.Enabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void EnableAndActivateMessage(string messageName)
|
||||
{
|
||||
lock (_messagesMetadata)
|
||||
{
|
||||
var messagesMetadata = _messagesMetadata.Where(m => m.Name == messageName);
|
||||
foreach (var messageMetadata in messagesMetadata)
|
||||
messageMetadata.Enabled = messageMetadata.Activated = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void DisableAndDeactivateMessage(string messageName)
|
||||
{
|
||||
lock (_messagesMetadata)
|
||||
{
|
||||
var messagesMetadata = _messagesMetadata.Where(m => m.Name == messageName);
|
||||
foreach (var messageMetadata in messagesMetadata)
|
||||
messageMetadata.Enabled = messageMetadata.Activated = false;
|
||||
}
|
||||
}
|
||||
|
||||
private class MessageMetadata
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public byte Number { get; set; }
|
||||
|
||||
public bool Enabled { get; set; }
|
||||
|
||||
public bool Activated { get; set; }
|
||||
|
||||
public Type Type { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user