Просмотр исходного кода

Ensure Channel Close message is sent only once
PortForwarding improvments

olegkap_cp 12 лет назад
Родитель
Сommit
f1e82058e5

+ 8 - 2
Renci.SshClient/Renci.SshNet/Channels/Channel.cs

@@ -479,8 +479,14 @@ namespace Renci.SshNet.Channels
             //  Send message to close the channel on the server
             if (!_closeMessageSent)
             {
-                this.SendMessage(new ChannelCloseMessage(this.RemoteChannelNumber));
-                this._closeMessageSent = true;
+                lock (this)
+                {
+                    if (!_closeMessageSent)
+                    {
+                        this.SendMessage(new ChannelCloseMessage(this.RemoteChannelNumber));
+                        this._closeMessageSent = true;
+                    }
+                }
             }
 
             //  Wait for channel to be closed

+ 33 - 42
Renci.SshClient/Renci.SshNet/Channels/ChannelDirectTcpip.cs

@@ -71,63 +71,54 @@ namespace Renci.SshNet.Channels
                 return;
 
             //  Start reading data from the port and send to channel
-            var readerTaskCompleted = new ManualResetEvent(false);
             Exception exception = null;
 
-            this.ExecuteThread(() =>
+            try
             {
-                try
-                {
-                    var buffer = new byte[this.PacketSize - 9];
+                var buffer = new byte[this.PacketSize - 9];
 
-                    while (this._socket.Connected || this.IsConnected)
+                while (this._socket != null && this._socket.Connected && this._socket.Poll(1, SelectMode.SelectRead) && this._socket.Available > 0)
+                {
+                    try
                     {
-                        try
+                        var read = 0;
+                        this.InternalSocketReceive(buffer, ref read);
+                        if (read > 0)
                         {
-
-                            var read = 0;
-                            this.InternalSocketReceive(buffer, ref read);
-                            if (read > 0)
-                            {
-                                this.SendMessage(new ChannelDataMessage(this.RemoteChannelNumber, buffer.Take(read).ToArray()));
-                            }
-                            else
-                            {
-                                break;
-                            }
+                            this.SendMessage(new ChannelDataMessage(this.RemoteChannelNumber, buffer.Take(read).ToArray()));
                         }
-                        catch (SocketException exp)
+                        else
                         {
-                            if (exp.SocketErrorCode == SocketError.WouldBlock ||
-                                exp.SocketErrorCode == SocketError.IOPending ||
-                                exp.SocketErrorCode == SocketError.NoBufferSpaceAvailable)
-                            {
-                                // socket buffer is probably empty, wait and try again
-                                Thread.Sleep(30);
-                            }
-                            else if (exp.SocketErrorCode == SocketError.ConnectionAborted || exp.SocketErrorCode == SocketError.ConnectionReset)
-                            {
-                                break;
-                            }
-                            else
-                                throw;  // throw any other error
+                            break;
                         }
                     }
+                    catch (SocketException exp)
+                    {
+                        if (exp.SocketErrorCode == SocketError.WouldBlock ||
+                            exp.SocketErrorCode == SocketError.IOPending ||
+                            exp.SocketErrorCode == SocketError.NoBufferSpaceAvailable)
+                        {
+                            // socket buffer is probably empty, wait and try again
+                            Thread.Sleep(30);
+                        }
+                        else if (exp.SocketErrorCode == SocketError.ConnectionAborted || exp.SocketErrorCode == SocketError.ConnectionReset)
+                        {
+                            break;
+                        }
+                        else
+                            throw;  // throw any other error
+                    }
                 }
-                catch (Exception exp)
-                {
-                    exception = exp;
-                }
-                finally
-                {
-                    readerTaskCompleted.Set();
-                }
-            });
+            }
+            catch (Exception exp)
+            {
+                exception = exp;
+            }
 
             //  Channel was open and we MUST receive EOF notification, 
             //  data transfer can take longer then connection specified timeout
             //  If listener thread is finished then socket was closed
-            System.Threading.WaitHandle.WaitAny(new WaitHandle[] { this._channelEof, readerTaskCompleted });
+            System.Threading.WaitHandle.WaitAny(new WaitHandle[] { this._channelEof });
 
             //  Close socket if still open
             if (this._socket != null)

+ 2 - 2
Renci.SshClient/Renci.SshNet/Channels/ChannelForwardedTcpip.cs

@@ -71,8 +71,8 @@ namespace Renci.SshNet.Channels
             }
 
             //  Start reading data from the port and send to channel
-            while (this._socket.Connected || this.IsConnected)
-            {
+            while (this._socket != null && this._socket.Connected && this._socket.Poll(1, SelectMode.SelectRead) && this._socket.Available > 0)
+                {
                 try
                 {
                     int read = 0;

+ 2 - 5
Renci.SshClient/Renci.SshNet/ForwardedPortDynamic.NET.cs

@@ -72,17 +72,14 @@ namespace Renci.SshNet
                                     }
 
                                     channel.Bind();
-                                }
 
+                                    channel.Close();
+                                }
                             }
                             catch (Exception exp)
                             {
                                 this.RaiseExceptionEvent(exp);
                             }
-                            finally
-                            {
-                                socket.Close();
-                            }
                         });
                     }
                 }

+ 2 - 0
Renci.SshClient/Renci.SshNet/ForwardedPortLocal.NET.cs

@@ -58,6 +58,8 @@ namespace Renci.SshNet
                                 channel.Open(this.Host, this.Port, socket);
 
                                 channel.Bind();
+
+                                channel.Close();
                             }
                             catch (Exception exp)
                             {