private void Session_ChannelOpening(object sender, MessageEventArgs<ChannelOpenMessage> e)
{
var channelOpenMessage = e.Message;
var info = channelOpenMessage.Info as ForwardedTcpipChannelInfo;
if (info != null)
{
// Ensure this is the corresponding request
if (info.ConnectedAddress == BoundHost && info.ConnectedPort == BoundPort)
{
if (!IsStarted)
{
Session.SendMessage(new ChannelOpenFailureMessage(channelOpenMessage.LocalChannelNumber, "", ChannelOpenFailureMessage.AdministrativelyProhibited));
return;
}
ThreadAbstraction.ExecuteThread(() =>
{
// capture the countdown event that we're adding a count to, as we need to make sure that we'll be signaling
// that same instance; the instance field for the countdown event is re-initialize when the port is restarted
// and that time there may still be pending requests
var pendingChannelCountdown = _pendingChannelCountdown;
pendingChannelCountdown.AddCount();
try
{
RaiseRequestReceived(info.OriginatorAddress, info.OriginatorPort);
using (
var channel =
Session.CreateChannelForwardedTcpip(channelOpenMessage.LocalChannelNumber,
channelOpenMessage.InitialWindowSize, channelOpenMessage.MaximumPacketSize))
{
channel.Exception += Channel_Exception;
channel.Bind(new IPEndPoint(HostAddress, (int) Port), this);
}
}
catch (Exception exp)
{
RaiseExceptionEvent(exp);
}
finally
{
// take into account that CountdownEvent has since been disposed; when stopping the port we
// wait for a given time for the channels to close, but once that timeout period has elapsed
// the CountdownEvent will be disposed
try
{
pendingChannelCountdown.Signal();
}
catch (ObjectDisposedException)
{
}
}
});
}
}
}