1
1
using System ;
2
2
using System . Collections . Generic ;
3
3
using System . Globalization ;
4
+ using System . Linq ;
4
5
using Renci . SshNet . Common ;
5
6
using Renci . SshNet . Messages ;
6
7
using Renci . SshNet . Messages . Authentication ;
@@ -14,9 +15,19 @@ internal class SshMessageFactory
14
15
private readonly MessageMetadata [ ] _enabledMessagesByNumber ;
15
16
private readonly bool [ ] _activatedMessagesById ;
16
17
17
- private static readonly MessageMetadata [ ] AllMessages ;
18
+ internal static readonly MessageMetadata [ ] AllMessages ;
18
19
private static readonly IDictionary < string , MessageMetadata > MessagesByName ;
19
20
21
+ /// <summary>
22
+ /// Defines the highest message number that is currently supported.
23
+ /// </summary>
24
+ internal const byte HighestMessageNumber = 100 ;
25
+
26
+ /// <summary>
27
+ /// Defines the total number of supported messages.
28
+ /// </summary>
29
+ internal const int TotalMessageCount = 31 ;
30
+
20
31
static SshMessageFactory ( )
21
32
{
22
33
AllMessages = new MessageMetadata [ ]
@@ -54,15 +65,15 @@ static SshMessageFactory()
54
65
new MessageMetadata < KeyExchangeDhGroupExchangeReply > ( 30 , "SSH_MSG_KEX_DH_GEX_REPLY" , 33 )
55
66
} ;
56
67
57
- MessagesByName = new Dictionary < string , MessageMetadata > ( 31 ) ;
68
+ MessagesByName = new Dictionary < string , MessageMetadata > ( AllMessages . Length ) ;
58
69
foreach ( var messageMetadata in AllMessages )
59
70
MessagesByName . Add ( messageMetadata . Name , messageMetadata ) ;
60
71
}
61
72
62
73
public SshMessageFactory ( )
63
74
{
64
- _activatedMessagesById = new bool [ 31 ] ;
65
- _enabledMessagesByNumber = new MessageMetadata [ 101 ] ;
75
+ _activatedMessagesById = new bool [ TotalMessageCount ] ;
76
+ _enabledMessagesByNumber = new MessageMetadata [ HighestMessageNumber + 1 ] ;
66
77
}
67
78
68
79
/// <summary>
@@ -76,14 +87,24 @@ public void Reset()
76
87
77
88
public Message Create ( byte messageNumber )
78
89
{
79
- var messageMetadata = _enabledMessagesByNumber [ messageNumber ] ;
90
+ if ( messageNumber > HighestMessageNumber )
91
+ {
92
+ throw CreateMessageTypeNotSupportedException ( messageNumber ) ;
93
+ }
80
94
81
- if ( messageMetadata == null )
95
+ var enabledMessageMetadata = _enabledMessagesByNumber [ messageNumber ] ;
96
+ if ( enabledMessageMetadata == null )
82
97
{
83
- throw new SshException ( string . Format ( CultureInfo . CurrentCulture , "Message type {0} is not valid." , messageNumber ) ) ;
98
+ var definedMessageMetadata = AllMessages . FirstOrDefault ( p => p . Number == messageNumber ) ;
99
+ if ( definedMessageMetadata == null )
100
+ {
101
+ throw CreateMessageTypeNotSupportedException ( messageNumber ) ;
102
+ }
103
+
104
+ throw new SshException ( string . Format ( CultureInfo . InvariantCulture , "Message type {0} is not valid in the current context." , messageNumber ) ) ;
84
105
}
85
106
86
- return messageMetadata . Create ( ) ;
107
+ return enabledMessageMetadata . Create ( ) ;
87
108
}
88
109
89
110
public void DisableNonKeyExchangeMessages ( )
@@ -106,58 +127,89 @@ public void EnableActivatedMessages()
106
127
if ( ! _activatedMessagesById [ messageMetadata . Id ] )
107
128
continue ;
108
129
109
- var enabledMessage = _enabledMessagesByNumber [ messageMetadata . Number ] ;
110
- if ( enabledMessage != null && enabledMessage != messageMetadata )
130
+ var enabledMessageMetadata = _enabledMessagesByNumber [ messageMetadata . Number ] ;
131
+ if ( enabledMessageMetadata != null && enabledMessageMetadata != messageMetadata )
111
132
{
112
- throw new Exception ( "Message X is already enabled for Y" ) ;
133
+ throw CreateMessageTypeAlreadyEnabledForOtherMessageException ( messageMetadata . Number ,
134
+ messageMetadata . Name ,
135
+ enabledMessageMetadata . Name ) ;
113
136
}
114
137
_enabledMessagesByNumber [ messageMetadata . Number ] = messageMetadata ;
115
138
}
116
139
}
117
140
118
141
public void EnableAndActivateMessage ( string messageName )
119
142
{
143
+ if ( messageName == null )
144
+ throw new ArgumentNullException ( "messageName" ) ;
145
+
120
146
lock ( this )
121
147
{
122
148
MessageMetadata messageMetadata ;
123
149
124
150
if ( ! MessagesByName . TryGetValue ( messageName , out messageMetadata ) )
125
151
{
126
- throw new Exception ( "TODO" ) ;
152
+ throw CreateMessageNotSupportedException ( messageName ) ;
127
153
}
128
154
129
- var enabledMessage = _enabledMessagesByNumber [ messageMetadata . Number ] ;
130
- if ( enabledMessage != null && enabledMessage != messageMetadata )
155
+ var enabledMessageMetadata = _enabledMessagesByNumber [ messageMetadata . Number ] ;
156
+ if ( enabledMessageMetadata != null && enabledMessageMetadata != messageMetadata )
131
157
{
132
- throw new Exception ( "Message X is already enabled for Y" ) ;
158
+ throw CreateMessageTypeAlreadyEnabledForOtherMessageException ( messageMetadata . Number ,
159
+ messageMetadata . Name ,
160
+ enabledMessageMetadata . Name ) ;
133
161
}
134
- _enabledMessagesByNumber [ messageMetadata . Number ] = messageMetadata ;
135
162
163
+ _enabledMessagesByNumber [ messageMetadata . Number ] = messageMetadata ;
136
164
_activatedMessagesById [ messageMetadata . Id ] = true ;
137
165
}
138
166
}
139
167
140
168
public void DisableAndDeactivateMessage ( string messageName )
141
169
{
170
+ if ( messageName == null )
171
+ throw new ArgumentNullException ( "messageName" ) ;
172
+
142
173
lock ( this )
143
174
{
144
175
MessageMetadata messageMetadata ;
145
176
146
177
if ( ! MessagesByName . TryGetValue ( messageName , out messageMetadata ) )
147
178
{
148
- throw new Exception ( "TODO" ) ;
179
+ throw CreateMessageNotSupportedException ( messageName ) ;
149
180
}
150
181
151
- _activatedMessagesById [ messageMetadata . Id ] = false ;
182
+ var enabledMessageMetadata = _enabledMessagesByNumber [ messageMetadata . Number ] ;
183
+ if ( enabledMessageMetadata != null && enabledMessageMetadata != messageMetadata )
184
+ {
185
+ throw CreateMessageTypeAlreadyEnabledForOtherMessageException ( messageMetadata . Number ,
186
+ messageMetadata . Name ,
187
+ enabledMessageMetadata . Name ) ;
188
+ }
152
189
153
- var enabledMetadata = _enabledMessagesByNumber [ messageMetadata . Number ] ;
154
- if ( enabledMetadata != null && enabledMetadata != messageMetadata )
155
- throw new Exception ( ) ;
190
+ _activatedMessagesById [ messageMetadata . Id ] = false ;
156
191
_enabledMessagesByNumber [ messageMetadata . Number ] = null ;
157
192
}
158
193
}
159
194
160
- private abstract class MessageMetadata
195
+ private SshException CreateMessageTypeNotSupportedException ( byte messageNumber )
196
+ {
197
+ throw new SshException ( string . Format ( CultureInfo . InvariantCulture , "Message type {0} is not supported." , messageNumber ) ) ;
198
+ }
199
+
200
+ private SshException CreateMessageNotSupportedException ( string messageName )
201
+ {
202
+ throw new SshException ( string . Format ( CultureInfo . InvariantCulture , "Message '{0}' is not supported." , messageName ) ) ;
203
+ }
204
+
205
+ private SshException CreateMessageTypeAlreadyEnabledForOtherMessageException ( byte messageNumber , string messageName , string currentEnabledForMessageName )
206
+ {
207
+ throw new SshException ( string . Format ( CultureInfo . InvariantCulture ,
208
+ "Cannot enable message '{0}'. Message type {1} is already enabled for '{2}'." ,
209
+ messageName , messageNumber , currentEnabledForMessageName ) ) ;
210
+ }
211
+
212
+ internal abstract class MessageMetadata
161
213
{
162
214
protected MessageMetadata ( byte id , string name , byte number )
163
215
{
@@ -175,7 +227,7 @@ protected MessageMetadata(byte id, string name, byte number)
175
227
public abstract Message Create ( ) ;
176
228
}
177
229
178
- private class MessageMetadata < T > : MessageMetadata where T : Message , new ( )
230
+ internal class MessageMetadata < T > : MessageMetadata where T : Message , new ( )
179
231
{
180
232
public MessageMetadata ( byte id , string name , byte number )
181
233
: base ( id , name , number )
0 commit comments