Skip to content

Commit ee3f679

Browse files
committed
Separate creating, enabling/disabling, activating/deactivating of messages into SshMessageFactory.
Huge performance improvement in micro-benchmark. Work in progress.
1 parent a66b32d commit ee3f679

File tree

13 files changed

+854
-153
lines changed

13 files changed

+854
-153
lines changed

src/Renci.SshNet.NET35/Renci.SshNet.NET35.csproj

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -918,6 +918,9 @@
918918
<Compile Include="..\Renci.SshNet\SshCommand.cs">
919919
<Link>SshCommand.cs</Link>
920920
</Compile>
921+
<Compile Include="..\Renci.SshNet\SshMessageFactory.cs">
922+
<Link>SshMessageFactory.cs</Link>
923+
</Compile>
921924
<Compile Include="..\Renci.SshNet\SubsystemSession.cs">
922925
<Link>SubsystemSession.cs</Link>
923926
</Compile>
@@ -937,7 +940,7 @@
937940
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
938941
<ProjectExtensions>
939942
<VisualStudio>
940-
<UserProperties ProjectLinkReference="2f5f8c90-0bd1-424f-997c-7bc6280919d1" ProjectLinkerExcludeFilter="\\?desktop(\\.*)?$;\\?silverlight(\\.*)?$;\.desktop;\.silverlight;\.xaml;^service references(\\.*)?$;\.clientconfig;^web references(\\.*)?$" />
943+
<UserProperties ProjectLinkerExcludeFilter="\\?desktop(\\.*)?$;\\?silverlight(\\.*)?$;\.desktop;\.silverlight;\.xaml;^service references(\\.*)?$;\.clientconfig;^web references(\\.*)?$" ProjectLinkReference="2f5f8c90-0bd1-424f-997c-7bc6280919d1" />
941944
</VisualStudio>
942945
</ProjectExtensions>
943946
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.

src/Renci.SshNet.NET35/Session.NET35.cs

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -58,29 +58,5 @@ partial void HandleMessageCore(Message message)
5858
HandleMessage(message);
5959
}
6060
}
61-
62-
partial void InternalRegisterMessage(string messageName)
63-
{
64-
lock (_messagesMetadata)
65-
{
66-
foreach (var m in from m in _messagesMetadata where m.Name == messageName select m)
67-
{
68-
m.Enabled = true;
69-
m.Activated = true;
70-
}
71-
}
72-
}
73-
74-
partial void InternalUnRegisterMessage(string messageName)
75-
{
76-
lock (_messagesMetadata)
77-
{
78-
foreach (var m in from m in _messagesMetadata where m.Name == messageName select m)
79-
{
80-
m.Enabled = false;
81-
m.Activated = false;
82-
}
83-
}
84-
}
8561
}
8662
}

src/Renci.SshNet.Silverlight/Session.SilverlightShared.cs

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -12,29 +12,5 @@ partial void IsSocketConnected(ref bool isConnected)
1212
{
1313
isConnected = (_socket != null && _socket.Connected);
1414
}
15-
16-
partial void InternalRegisterMessage(string messageName)
17-
{
18-
lock (_messagesMetadata)
19-
{
20-
foreach (var item in from m in _messagesMetadata where m.Name == messageName select m)
21-
{
22-
item.Enabled = true;
23-
item.Activated = true;
24-
}
25-
}
26-
}
27-
28-
partial void InternalUnRegisterMessage(string messageName)
29-
{
30-
lock (_messagesMetadata)
31-
{
32-
foreach (var item in from m in _messagesMetadata where m.Name == messageName select m)
33-
{
34-
item.Enabled = false;
35-
item.Activated = false;
36-
}
37-
}
38-
}
3915
}
4016
}

src/Renci.SshNet.Silverlight5/Renci.SshNet.Silverlight5.csproj

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -892,6 +892,9 @@
892892
<Compile Include="..\Renci.SshNet\SshCommand.cs">
893893
<Link>SshCommand.cs</Link>
894894
</Compile>
895+
<Compile Include="..\Renci.SshNet\SshMessageFactory.cs">
896+
<Link>SshMessageFactory.cs</Link>
897+
</Compile>
895898
<Compile Include="..\Renci.SshNet\SubsystemSession.cs">
896899
<Link>SubsystemSession.cs</Link>
897900
</Compile>
@@ -912,7 +915,7 @@
912915
<FlavorProperties GUID="{A1591282-1198-4647-A2B1-27E5FF5F6F3B}">
913916
<SilverlightProjectProperties />
914917
</FlavorProperties>
915-
<UserProperties ProjectLinkReference="2f5f8c90-0bd1-424f-997c-7bc6280919d1" ProjectLinkerExcludeFilter="\\?desktop(\\.*)?$;\\?silverlight(\\.*)?$;\.desktop;\.silverlight;\.xaml;^service references(\\.*)?$;\.clientconfig;^web references(\\.*)?$" />
918+
<UserProperties ProjectLinkerExcludeFilter="\\?desktop(\\.*)?$;\\?silverlight(\\.*)?$;\.desktop;\.silverlight;\.xaml;^service references(\\.*)?$;\.clientconfig;^web references(\\.*)?$" ProjectLinkReference="2f5f8c90-0bd1-424f-997c-7bc6280919d1" />
916919
</VisualStudio>
917920
</ProjectExtensions>
918921
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.

src/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@
7070
<Compile Include="..\..\test\Renci.SshNet.Shared.Tests\Abstractions\ThreadAbstraction_ExecuteThread.cs">
7171
<Link>Classes\Abstractions\ThreadAbstraction_ExecuteThread.cs</Link>
7272
</Compile>
73+
<Compile Include="..\..\test\Renci.SshNet.Shared.Tests\SshMessageFactoryTest.cs">
74+
<Link>Classes\SshMessageFactoryTest.cs</Link>
75+
</Compile>
7376
<Compile Include="Classes\BaseClientTest_Connected_KeepAlivesNotSentConcurrently.cs" />
7477
<Compile Include="Classes\Channels\ChannelDirectTcpipTest.cs" />
7578
<Compile Include="Classes\Channels\ChannelDirectTcpipTest_Close_SessionIsConnectedAndChannelIsOpen.cs" />

src/Renci.SshNet.UAP10/Renci.SshNet.UAP10.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -960,6 +960,9 @@
960960
<Compile Include="..\Renci.SshNet\SshCommand.cs">
961961
<Link>SshCommand.cs</Link>
962962
</Compile>
963+
<Compile Include="..\Renci.SshNet\SshMessageFactory.cs">
964+
<Link>SshMessageFactory.cs</Link>
965+
</Compile>
963966
<Compile Include="..\Renci.SshNet\SubsystemSession.cs">
964967
<Link>SubsystemSession.cs</Link>
965968
</Compile>

src/Renci.SshNet.WindowsPhone8/Renci.SshNet.WindowsPhone8.csproj

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -910,6 +910,9 @@
910910
<Compile Include="..\Renci.SshNet\SshCommand.cs">
911911
<Link>SshCommand.cs</Link>
912912
</Compile>
913+
<Compile Include="..\Renci.SshNet\SshMessageFactory.cs">
914+
<Link>SshMessageFactory.cs</Link>
915+
</Compile>
913916
<Compile Include="..\Renci.SshNet\SubsystemSession.cs">
914917
<Link>SubsystemSession.cs</Link>
915918
</Compile>
@@ -932,7 +935,7 @@
932935
<Import Project="$(MSBuildExtensionsPath)\Microsoft\$(TargetFrameworkIdentifier)\$(TargetFrameworkVersion)\Microsoft.$(TargetFrameworkIdentifier).CSharp.targets" />
933936
<ProjectExtensions>
934937
<VisualStudio>
935-
<UserProperties ProjectLinkReference="2f5f8c90-0bd1-424f-997c-7bc6280919d1" ProjectLinkerExcludeFilter="\\?desktop(\\.*)?$;\\?silverlight(\\.*)?$;\.desktop;\.silverlight;\.xaml;^service references(\\.*)?$;\.clientconfig;^web references(\\.*)?$" />
938+
<UserProperties ProjectLinkerExcludeFilter="\\?desktop(\\.*)?$;\\?silverlight(\\.*)?$;\.desktop;\.silverlight;\.xaml;^service references(\\.*)?$;\.clientconfig;^web references(\\.*)?$" ProjectLinkReference="2f5f8c90-0bd1-424f-997c-7bc6280919d1" />
936939
</VisualStudio>
937940
</ProjectExtensions>
938941
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.

src/Renci.SshNet/Renci.SshNet.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,7 @@
452452
</Compile>
453453
<Compile Include="SshClient.cs" />
454454
<Compile Include="SshCommand.cs" />
455+
<Compile Include="SshMessageFactory.cs" />
455456
<Compile Include="SubsystemSession.cs" />
456457
</ItemGroup>
457458
<ItemGroup>

src/Renci.SshNet/Session.NET40.cs

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -13,25 +13,5 @@ partial void HandleMessageCore(Message message)
1313
{
1414
HandleMessage((dynamic)message);
1515
}
16-
17-
partial void InternalRegisterMessage(string messageName)
18-
{
19-
lock (_messagesMetadata)
20-
{
21-
Parallel.ForEach(
22-
from m in _messagesMetadata where m.Name == messageName select m,
23-
item => { item.Enabled = true; item.Activated = true; });
24-
}
25-
}
26-
27-
partial void InternalUnRegisterMessage(string messageName)
28-
{
29-
lock (_messagesMetadata)
30-
{
31-
Parallel.ForEach(
32-
from m in _messagesMetadata where m.Name == messageName select m,
33-
item => { item.Enabled = false; item.Activated = false; });
34-
}
35-
}
3616
}
3717
}

src/Renci.SshNet/Session.cs

Lines changed: 11 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ public partial class Session : ISession
8484
/// <summary>
8585
/// Holds metada about session messages
8686
/// </summary>
87-
private IEnumerable<MessageMetadata> _messagesMetadata;
87+
private SshMessageFactory _sshMessageFactory;
8888

8989
/// <summary>
9090
/// Holds connection socket.
@@ -523,7 +523,7 @@ public void Connect()
523523
Reset();
524524

525525
// Build list of available messages while connecting
526-
_messagesMetadata = GetMessagesMetadata();
526+
_sshMessageFactory = new SshMessageFactory();
527527

528528
switch (ConnectionInfo.ProxyType)
529529
{
@@ -621,6 +621,8 @@ public void Connect()
621621
ConnectionInfo.Authenticate(this, _serviceFactory);
622622
_isAuthenticated = true;
623623

624+
Thread.Sleep(2000);
625+
624626
// Register Connection messages
625627
RegisterMessage("SSH_MSG_GLOBAL_REQUEST");
626628
RegisterMessage("SSH_MSG_REQUEST_SUCCESS");
@@ -864,49 +866,6 @@ private bool TrySendMessage(Message message)
864866
}
865867
}
866868

867-
private static IEnumerable<MessageMetadata> GetMessagesMetadata()
868-
{
869-
return new []
870-
{
871-
new MessageMetadata { Name = "SSH_MSG_NEWKEYS", Number = 21, Type = typeof(NewKeysMessage) },
872-
new MessageMetadata { Name = "SSH_MSG_REQUEST_FAILURE", Number = 82, Type = typeof(RequestFailureMessage) },
873-
new MessageMetadata { Name = "SSH_MSG_KEXINIT", Number = 20, Type = typeof(KeyExchangeInitMessage) },
874-
new MessageMetadata { Name = "SSH_MSG_CHANNEL_OPEN_FAILURE", Number = 92, Type = typeof(ChannelOpenFailureMessage) },
875-
new MessageMetadata { Name = "SSH_MSG_CHANNEL_FAILURE", Number = 100, Type = typeof(ChannelFailureMessage) },
876-
new MessageMetadata { Name = "SSH_MSG_CHANNEL_EXTENDED_DATA", Number = 95, Type = typeof(ChannelExtendedDataMessage) },
877-
new MessageMetadata { Name = "SSH_MSG_CHANNEL_DATA", Number = 94, Type = typeof(ChannelDataMessage) },
878-
new MessageMetadata { Name = "SSH_MSG_USERAUTH_REQUEST", Number = 50, Type = typeof(RequestMessage) },
879-
new MessageMetadata { Name = "SSH_MSG_CHANNEL_REQUEST", Number = 98, Type = typeof(ChannelRequestMessage) },
880-
new MessageMetadata { Name = "SSH_MSG_USERAUTH_BANNER", Number = 53, Type = typeof(BannerMessage) },
881-
new MessageMetadata { Name = "SSH_MSG_USERAUTH_INFO_RESPONSE", Number = 61, Type = typeof(InformationResponseMessage) },
882-
new MessageMetadata { Name = "SSH_MSG_USERAUTH_FAILURE", Number = 51, Type = typeof(FailureMessage) },
883-
new MessageMetadata { Name = "SSH_MSG_DEBUG", Number = 4, Type = typeof(DebugMessage), },
884-
new MessageMetadata { Name = "SSH_MSG_KEXDH_INIT", Number = 30, Type = typeof(KeyExchangeDhInitMessage) },
885-
new MessageMetadata { Name = "SSH_MSG_GLOBAL_REQUEST", Number = 80, Type = typeof(GlobalRequestMessage) },
886-
new MessageMetadata { Name = "SSH_MSG_CHANNEL_OPEN", Number = 90, Type = typeof(ChannelOpenMessage) },
887-
new MessageMetadata { Name = "SSH_MSG_CHANNEL_OPEN_CONFIRMATION", Number = 91, Type = typeof(ChannelOpenConfirmationMessage) },
888-
new MessageMetadata { Name = "SSH_MSG_USERAUTH_INFO_REQUEST", Number = 60, Type = typeof(InformationRequestMessage) },
889-
new MessageMetadata { Name = "SSH_MSG_UNIMPLEMENTED", Number = 3, Type = typeof(UnimplementedMessage) },
890-
new MessageMetadata { Name = "SSH_MSG_REQUEST_SUCCESS", Number = 81, Type = typeof(RequestSuccessMessage) },
891-
new MessageMetadata { Name = "SSH_MSG_CHANNEL_SUCCESS", Number = 99, Type = typeof(ChannelSuccessMessage) },
892-
new MessageMetadata { Name = "SSH_MSG_USERAUTH_PASSWD_CHANGEREQ", Number = 60, Type = typeof(PasswordChangeRequiredMessage) },
893-
new MessageMetadata { Name = "SSH_MSG_DISCONNECT", Number = 1, Type = typeof(DisconnectMessage) },
894-
new MessageMetadata { Name = "SSH_MSG_SERVICE_REQUEST", Number = 5, Type = typeof(ServiceRequestMessage) },
895-
new MessageMetadata { Name = "SSH_MSG_KEX_DH_GEX_REQUEST", Number = 34, Type = typeof(KeyExchangeDhGroupExchangeRequest) },
896-
new MessageMetadata { Name = "SSH_MSG_KEX_DH_GEX_GROUP", Number = 31, Type = typeof(KeyExchangeDhGroupExchangeGroup) },
897-
new MessageMetadata { Name = "SSH_MSG_USERAUTH_SUCCESS", Number = 52, Type = typeof(SuccessMessage) },
898-
new MessageMetadata { Name = "SSH_MSG_USERAUTH_PK_OK", Number = 60, Type = typeof(PublicKeyMessage) },
899-
new MessageMetadata { Name = "SSH_MSG_IGNORE", Number = 2, Type = typeof(IgnoreMessage) },
900-
new MessageMetadata { Name = "SSH_MSG_CHANNEL_WINDOW_ADJUST", Number = 93, Type = typeof(ChannelWindowAdjustMessage) },
901-
new MessageMetadata { Name = "SSH_MSG_CHANNEL_EOF", Number = 96, Type = typeof(ChannelEofMessage) },
902-
new MessageMetadata { Name = "SSH_MSG_CHANNEL_CLOSE", Number = 97, Type = typeof(ChannelCloseMessage) },
903-
new MessageMetadata { Name = "SSH_MSG_SERVICE_ACCEPT", Number = 6, Type = typeof(ServiceAcceptMessage) },
904-
new MessageMetadata { Name = "SSH_MSG_KEXDH_REPLY", Number = 31, Type = typeof(KeyExchangeDhReplyMessage) },
905-
new MessageMetadata { Name = "SSH_MSG_KEX_DH_GEX_INIT", Number = 32, Type = typeof(KeyExchangeDhGroupExchangeInit) },
906-
new MessageMetadata { Name = "SSH_MSG_KEX_DH_GEX_REPLY", Number = 33, Type = typeof(KeyExchangeDhGroupExchangeReply) }
907-
};
908-
}
909-
910869
/// <summary>
911870
/// Receives the message from the server.
912871
/// </summary>
@@ -1332,12 +1291,8 @@ protected virtual void OnKeyExchangeInitReceived(KeyExchangeInitMessage message)
13321291

13331292
_keyExchangeCompletedWaitHandle.Reset();
13341293

1335-
// Disable all registered messages except key exchange related
1336-
foreach (var messageMetadata in _messagesMetadata)
1337-
{
1338-
if (messageMetadata.Activated && messageMetadata.Number > 2 && (messageMetadata.Number < 20 || messageMetadata.Number > 30))
1339-
messageMetadata.Enabled = false;
1340-
}
1294+
// Disable messages that are not key exchange related
1295+
_sshMessageFactory.DisableNonKeyExchangeMessages();
13411296

13421297
_keyExchange = _serviceFactory.CreateKeyExchange(ConnectionInfo.KeyExchangeAlgorithms,
13431298
message.KeyExchangeAlgorithms);
@@ -1395,12 +1350,8 @@ protected virtual void OnNewKeysReceived(NewKeysMessage message)
13951350
_keyExchange = null;
13961351
}
13971352

1398-
// Enable all active registered messages
1399-
foreach (var messageMetadata in _messagesMetadata)
1400-
{
1401-
if (messageMetadata.Activated)
1402-
messageMetadata.Enabled = true;
1403-
}
1353+
// Enable activated messages that are not key exchange related
1354+
_sshMessageFactory.EnableActivatedMessages();
14041355

14051356
var newKeysReceived = NewKeysReceived;
14061357
if (newKeysReceived != null)
@@ -1662,7 +1613,7 @@ private byte[] Read(int length)
16621613
/// <param name="messageName">The name of the message to register with the session.</param>
16631614
public void RegisterMessage(string messageName)
16641615
{
1665-
InternalRegisterMessage(messageName);
1616+
_sshMessageFactory.EnableAndActivateMessage(messageName);
16661617
}
16671618

16681619
/// <summary>
@@ -1671,7 +1622,7 @@ public void RegisterMessage(string messageName)
16711622
/// <param name="messageName">The name of the message to unregister with the session.</param>
16721623
public void UnRegisterMessage(string messageName)
16731624
{
1674-
InternalUnRegisterMessage(messageName);
1625+
_sshMessageFactory.DisableAndDeactivateMessage(messageName);
16751626
}
16761627

16771628
/// <summary>
@@ -1686,23 +1637,14 @@ public void UnRegisterMessage(string messageName)
16861637
private Message LoadMessage(byte[] data, int offset)
16871638
{
16881639
var messageType = data[offset];
1689-
var messageMetadata = (from m in _messagesMetadata where m.Number == messageType && m.Enabled && m.Activated select m).FirstOrDefault();
1690-
if (messageMetadata == null)
1691-
throw new SshException(string.Format(CultureInfo.CurrentCulture, "Message type {0} is not valid.", messageType));
1692-
1693-
var message = messageMetadata.Type.CreateInstance<Message>();
1694-
1640+
var message = _sshMessageFactory.Create(messageType);
16951641
message.Load(data, offset);
16961642

16971643
DiagnosticAbstraction.Log(string.Format("ReceiveMessage from server: '{0}': '{1}'.", message.GetType().Name, message));
16981644

16991645
return message;
17001646
}
17011647

1702-
partial void InternalRegisterMessage(string messageName);
1703-
1704-
partial void InternalUnRegisterMessage(string messageName);
1705-
17061648
#endregion
17071649

17081650
/// <summary>
@@ -2402,18 +2344,5 @@ bool ISession.TrySendMessage(Message message)
24022344
}
24032345

24042346
#endregion ISession implementation
2405-
2406-
private class MessageMetadata
2407-
{
2408-
public string Name { get; set; }
2409-
2410-
public byte Number { get; set; }
2411-
2412-
public bool Enabled { get; set; }
2413-
2414-
public bool Activated { get; set; }
2415-
2416-
public Type Type { get; set; }
2417-
}
24182347
}
24192348
}

0 commit comments

Comments
 (0)