浏览代码

Add KeepAliveRequestInfo class
Add EndOfWriteRequestInfo class
Refactor channel request messages to allow custom channel reuqest support

olegkap_cp 14 年之前
父节点
当前提交
033218647f

+ 16 - 1
Renci.SshClient/Renci.SshNet/Channels/Channel.cs

@@ -3,6 +3,7 @@ using System.Threading;
 using Renci.SshNet.Common;
 using Renci.SshNet.Messages;
 using Renci.SshNet.Messages.Connection;
+using System.Globalization;
 
 namespace Renci.SshNet.Channels
 {
@@ -540,7 +541,21 @@ namespace Renci.SshNet.Channels
         {
             if (e.Message.LocalChannelNumber == this.LocalChannelNumber)
             {
-                this.OnRequest(e.Message.Info);
+                if (this._session.ConnectionInfo.ChannelRequests.ContainsKey(e.Message.RequestName))
+                {
+                    //  Get request specific class
+                    RequestInfo requestInfo = this._session.ConnectionInfo.ChannelRequests[e.Message.RequestName];
+
+                    //  Load request specific data
+                    requestInfo.Load(e.Message.RequestData);
+
+                    //  Raise request specific event
+                    this.OnRequest(requestInfo);
+                }
+                else
+                {
+                    throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "Request '{0}' is not supported.", e.Message.RequestName));
+                }
             }
         }
 

+ 32 - 1
Renci.SshClient/Renci.SshNet/Channels/ChannelSession.cs

@@ -7,7 +7,7 @@ using System.Globalization;
 namespace Renci.SshNet.Channels
 {
     /// <summary>
-    /// Implements "forwarded-tcpip" SSH channel.
+    /// Implements Session SSH channel.
     /// </summary>
     internal class ChannelSession : Channel
     {
@@ -271,6 +271,37 @@ namespace Renci.SshNet.Channels
             return true;
         }
 
+        /// <summary>
+        /// Sends eow@openssh.com request.
+        /// </summary>
+        /// <returns>true if request was successful; otherwise false.</returns>
+        public bool SendEndOfWriteRequest()
+        {
+            this._channelRequestResponse.Reset();
+
+            this.SendMessage(new ChannelRequestMessage(this.RemoteChannelNumber, new EndOfWriteRequestInfo()));
+
+            this._channelRequestResponse.WaitOne();
+
+            return this._channelRequestSucces;
+        }
+
+        /// <summary>
+        /// Sends keepalive@openssh.com request.
+        /// </summary>
+        /// <returns>true if request was successful; otherwise false.</returns>
+        public bool SendKeepAliveRequest()
+        {
+            this._channelRequestResponse.Reset();
+
+            this.SendMessage(new ChannelRequestMessage(this.RemoteChannelNumber, new KeepAliveRequestInfo()));
+
+            this._channelRequestResponse.WaitOne();
+
+            return this._channelRequestSucces;
+        }
+
+
         /// <summary>
         /// Called when channel request was successful
         /// </summary>

+ 22 - 0
Renci.SshClient/Renci.SshNet/ConnectionInfo.cs

@@ -8,6 +8,7 @@ using Renci.SshNet.Messages.Authentication;
 using Renci.SshNet.Common;
 using System.Threading;
 using System.Net;
+using Renci.SshNet.Messages.Connection;
 namespace Renci.SshNet
 {
     /// <summary>
@@ -68,6 +69,11 @@ namespace Renci.SshNet
         /// </summary>
         public IDictionary<string, Type> CompressionAlgorithms { get; private set; }
 
+        /// <summary>
+        /// Gets supported channel requests for this connection.
+        /// </summary>
+        public IDictionary<string, RequestInfo> ChannelRequests { get; private set; }
+
         /// <summary>
         /// Gets connection host.
         /// </summary>
@@ -194,6 +200,22 @@ namespace Renci.SshNet
                 {"zlib@openssh.com", typeof(ZlibOpenSsh)}, 
             };
 
+            this.ChannelRequests = new Dictionary<string, RequestInfo>()
+            {
+                {EnvironmentVariableRequestInfo.NAME, new EnvironmentVariableRequestInfo()}, 
+                {ExecRequestInfo.NAME, new ExecRequestInfo()}, 
+                {ExitSignalRequestInfo.NAME, new ExitSignalRequestInfo()}, 
+                {ExitStatusRequestInfo.NAME, new ExitStatusRequestInfo()}, 
+                {PseudoTerminalRequestInfo.NAME, new PseudoTerminalRequestInfo()}, 
+                {ShellRequestInfo.NAME, new ShellRequestInfo()}, 
+                {SignalRequestInfo.NAME, new SignalRequestInfo()}, 
+                {SubsystemRequestInfo.NAME, new SubsystemRequestInfo()}, 
+                {WindowChangeRequestInfo.NAME, new WindowChangeRequestInfo()}, 
+                {X11ForwardingRequestInfo.NAME, new X11ForwardingRequestInfo()}, 
+                {XonXoffRequestInfo.NAME, new XonXoffRequestInfo()}, 
+                {EndOfWriteRequestInfo.NAME, new EndOfWriteRequestInfo()}, 
+                {KeepAliveRequestInfo.NAME, new KeepAliveRequestInfo()}, 
+            };
         }
 
         /// <summary>

+ 8 - 78
Renci.SshClient/Renci.SshNet/Messages/Connection/ChannelRequest/ChannelRequestMessage.cs

@@ -15,32 +15,12 @@ namespace Renci.SshNet.Messages.Connection
         /// <value>
         /// The name of the request.
         /// </value>
-        public string RequestName
-        {
-            get
-            {
-                return this.Info.RequestName;
-            }
-        }
+        public string RequestName { get; private set; }
 
         /// <summary>
-        /// Gets a value indicating whether the reply is needed.
+        /// Gets channel request data.
         /// </summary>
-        /// <value>
-        ///   <c>true</c> if reply is needed; otherwise, <c>false</c>.
-        /// </value>
-        public bool WantReply
-        {
-            get
-            {
-                return this.Info.WantReply;
-            }
-        }
-
-        /// <summary>
-        /// Gets channel request information.
-        /// </summary>
-        public RequestInfo Info { get; private set; }
+        public byte[] RequestData { get; private set; }
 
         /// <summary>
         /// Initializes a new instance of the <see cref="ChannelRequestMessage"/> class.
@@ -58,7 +38,8 @@ namespace Renci.SshNet.Messages.Connection
         public ChannelRequestMessage(uint localChannelName, RequestInfo info)
         {
             this.LocalChannelNumber = localChannelName;
-            this.Info = info;
+            this.RequestName = info.RequestName;
+            this.RequestData = info.GetBytes();
         }
 
         /// <summary>
@@ -68,59 +49,8 @@ namespace Renci.SshNet.Messages.Connection
         {
             base.LoadData();
 
-            var requestName = this.ReadString();
-            var bytes = this.ReadBytes();
-
-            if (requestName == EnvironmentVariableRequestInfo.NAME)
-            {
-                this.Info = new EnvironmentVariableRequestInfo();
-            }
-            else if (requestName == ExecRequestInfo.NAME)
-            {
-                this.Info = new ExecRequestInfo();
-            }
-            else if (requestName == ExitSignalRequestInfo.NAME)
-            {
-                this.Info = new ExitSignalRequestInfo();
-            }
-            else if (requestName == ExitStatusRequestInfo.NAME)
-            {
-                this.Info = new ExitStatusRequestInfo();
-            }
-            else if (requestName == PseudoTerminalRequestInfo.NAME)
-            {
-                this.Info = new PseudoTerminalRequestInfo();
-            }
-            else if (requestName == ShellRequestInfo.NAME)
-            {
-                this.Info = new ShellRequestInfo();
-            }
-            else if (requestName == SignalRequestInfo.NAME)
-            {
-                this.Info = new SignalRequestInfo();
-            }
-            else if (requestName == SubsystemRequestInfo.NAME)
-            {
-                this.Info = new SubsystemRequestInfo();
-            }
-            else if (requestName == WindowChangeRequestInfo.NAME)
-            {
-                this.Info = new WindowChangeRequestInfo();
-            }
-            else if (requestName == X11ForwardingRequestInfo.NAME)
-            {
-                this.Info = new X11ForwardingRequestInfo();
-            }
-            else if (requestName == XonXoffRequestInfo.NAME)
-            {
-                this.Info = new XonXoffRequestInfo();
-            }
-            else
-            {
-                throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "Request '{0}' is not supported.", requestName));
-            }
-
-            this.Info.Load(bytes);
+            this.RequestName = this.ReadString();
+            this.RequestData = this.ReadBytes();
         }
 
         /// <summary>
@@ -131,7 +61,7 @@ namespace Renci.SshNet.Messages.Connection
             base.SaveData();
 
             this.Write(this.RequestName);
-            this.Write(this.Info.GetBytes());
+            this.Write(this.RequestData);
         }
     }
 }

+ 34 - 0
Renci.SshClient/Renci.SshNet/Messages/Connection/ChannelRequest/EndOfWriteRequestInfo.cs

@@ -0,0 +1,34 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Renci.SshNet.Messages.Connection
+{
+    public class EndOfWriteRequestInfo : RequestInfo
+    {
+        /// <summary>
+        /// Channel request name
+        /// </summary>
+        public const string NAME = "eow@openssh.com";
+
+        /// <summary>
+        /// Gets the name of the request.
+        /// </summary>
+        /// <value>
+        /// The name of the request.
+        /// </value>
+        public override string RequestName
+        {
+            get { return EndOfWriteRequestInfo.NAME; }
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="EndOfWriteRequestInfo"/> class.
+        /// </summary>
+        public EndOfWriteRequestInfo()
+        {
+            this.WantReply = false;
+        }
+    }
+}

+ 34 - 0
Renci.SshClient/Renci.SshNet/Messages/Connection/ChannelRequest/KeepAliveRequestInfo.cs

@@ -0,0 +1,34 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Renci.SshNet.Messages.Connection
+{
+    public class KeepAliveRequestInfo : RequestInfo
+    {
+        /// <summary>
+        /// Channel request name
+        /// </summary>
+        public const string NAME = "keepalive@openssh.com";
+
+        /// <summary>
+        /// Gets the name of the request.
+        /// </summary>
+        /// <value>
+        /// The name of the request.
+        /// </value>
+        public override string RequestName
+        {
+            get { return KeepAliveRequestInfo.NAME; }
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="EndOfWriteRequestInfo"/> class.
+        /// </summary>
+        public KeepAliveRequestInfo()
+        {
+            this.WantReply = false;
+        }
+    }
+}

+ 2 - 0
Renci.SshClient/Renci.SshNet/Renci.SshNet.csproj

@@ -103,6 +103,8 @@
     <Compile Include="ForwardedPortLocal.cs">
       <SubType>Code</SubType>
     </Compile>
+    <Compile Include="Messages\Connection\ChannelRequest\EndOfWriteRequestInfo.cs" />
+    <Compile Include="Messages\Connection\ChannelRequest\KeepAliveRequestInfo.cs" />
     <Compile Include="Security\Algorithm.cs">
       <SubType>Code</SubType>
     </Compile>