using System;
using System.Net.Sockets;
using System.Net.Security;
using System.Security.Authentication;
namespace Ant.Service.Utilities
{
///
/// Performs the connect to a Pop3 server and returns a Pop3
/// response indicating the attempt to connect results and the
/// network stream to use for all subsequent Pop3 Commands.
///
internal sealed class ConnectCommand : Pop3Command
{
private TcpClient _client;
private string _hostname;
private int _port;
private bool _useSsl;
///
/// Initializes a new instance of the class.
///
///
/// Even though a network stream is provided to the base constructor the stream
/// does not already exist so we have to send in a dummy stream until the actual
/// connect has taken place. Then we'll reset network stream to the
/// stream made available by the TcpClient.GetStream() to read the data returned
/// after a connect.
///
/// The client.
/// The hostname.
/// The port.
/// if set to true [use SSL].
public ConnectCommand(TcpClient client, string hostname, int port, bool useSsl)
: base(new System.IO.MemoryStream(), false, Pop3State.Unknown)
{
if (client == null)
{
throw new ArgumentNullException("client");
}
if (string.IsNullOrEmpty(hostname))
{
throw new ArgumentNullException("hostname");
}
if (port < 1)
{
throw new ArgumentOutOfRangeException("port");
}
_client = client;
_hostname = hostname;
_port = port;
_useSsl = useSsl;
}
///
/// Creates the connect request message.
///
/// A byte[] containing connect request message.
protected override byte[] CreateRequestMessage()
{
return null;
}
///
/// Executes this instance.
///
///
internal override ConnectResponse Execute(Pop3State currentState)
{
EnsurePop3State(currentState);
try
{
_client.Connect(_hostname, _port);
SetClientStream();
}
catch (SocketException e)
{
throw new Pop3Exception(string.Format("Unable to connect to {0}:{1}.", _hostname, _port), e);
}
return base.Execute(currentState);
}
///
/// Sets the client stream.
///
private void SetClientStream()
{
if (_useSsl)
{
try
{
NetworkStream = new SslStream(_client.GetStream(), true); //make sure the inner stream stays available for the Pop3Client to make use of.
((SslStream)NetworkStream).AuthenticateAsClient(_hostname);
}
catch (ArgumentException e)
{
throw new Pop3Exception("Unable to create Ssl Stream for hostname: " + _hostname, e);
}
catch (AuthenticationException e)
{
throw new Pop3Exception("Unable to authenticate ssl stream for hostname: " + _hostname, e);
}
catch (InvalidOperationException e)
{
throw new Pop3Exception("There was a problem attempting to authenticate this SSL stream for hostname: " + _hostname, e);
}
} //wrap NetworkStream in an SSL stream
else
{
NetworkStream = _client.GetStream();
}
}
///
/// Creates the response.
///
/// The buffer.
///
/// The Pop3Response containing the results of the
/// Pop3 command execution.
///
protected override ConnectResponse CreateResponse(byte[] buffer)
{
Pop3Response response = Pop3Response.CreateResponse(buffer);
return new ConnectResponse(response, NetworkStream);
}
}
}