ChannelForwardedTcpip
Implements "forwarded-tcpip" SSH channel.
using Renci.SshNet.Abstractions;
using Renci.SshNet.Common;
using Renci.SshNet.Messages.Connection;
using System;
using System.Net;
using System.Net.Sockets;
namespace Renci.SshNet.Channels
{
internal class ChannelForwardedTcpip : ServerChannel, IChannelForwardedTcpip, IDisposable
{
private readonly object _socketShutdownAndCloseLock = new object();
private Socket _socket;
private IForwardedPort _forwardedPort;
public override ChannelTypes ChannelType => ChannelTypes.ForwardedTcpip;
internal ChannelForwardedTcpip(ISession session, uint localChannelNumber, uint localWindowSize, uint localPacketSize, uint remoteChannelNumber, uint remoteWindowSize, uint remotePacketSize)
: base(session, localChannelNumber, localWindowSize, localPacketSize, remoteChannelNumber, remoteWindowSize, remotePacketSize)
{
}
public void Bind(IPEndPoint remoteEndpoint, IForwardedPort forwardedPort)
{
if (!base.IsConnected)
throw new SshException("Session is not connected.");
_forwardedPort = forwardedPort;
_forwardedPort.Closing += ForwardedPort_Closing;
try {
_socket = SocketAbstraction.Connect(remoteEndpoint, base.ConnectionInfo.Timeout);
SendMessage(new ChannelOpenConfirmationMessage(base.RemoteChannelNumber, base.LocalWindowSize, base.LocalPacketSize, base.LocalChannelNumber));
} catch (Exception ex) {
SendMessage(new ChannelOpenFailureMessage(base.RemoteChannelNumber, ex.ToString(), 2, "en"));
throw;
}
byte[] array = new byte[base.RemotePacketSize];
SocketAbstraction.ReadContinuous(_socket, array, 0, array.Length, SendData);
}
protected override void OnErrorOccured(Exception exp)
{
base.OnErrorOccured(exp);
ShutdownSocket(SocketShutdown.Send);
}
private void ForwardedPort_Closing(object sender, EventArgs eventArgs)
{
ShutdownSocket(SocketShutdown.Send);
}
private void ShutdownSocket(SocketShutdown how)
{
if (_socket != null) {
lock (_socketShutdownAndCloseLock) {
Socket socket = _socket;
if (socket.IsConnected())
try {
socket.Shutdown(how);
} catch (SocketException) {
}
}
}
}
private void CloseSocket()
{
if (_socket != null) {
lock (_socketShutdownAndCloseLock) {
Socket socket = _socket;
if (socket != null) {
_socket = null;
socket.Dispose();
}
}
}
}
protected override void Close()
{
IForwardedPort forwardedPort = _forwardedPort;
if (forwardedPort != null) {
forwardedPort.Closing -= ForwardedPort_Closing;
_forwardedPort = null;
}
ShutdownSocket(SocketShutdown.Send);
base.Close();
CloseSocket();
}
protected override void OnData(byte[] data)
{
base.OnData(data);
Socket socket = _socket;
if (socket.IsConnected())
SocketAbstraction.Send(socket, data, 0, data.Length);
}
}
}