using System;
using System.Net.Sockets;
using System.Text;

namespace Org.Mentalis.Network.ProxySocket.Authentication
{
	internal sealed class AuthUserPass : AuthMethod
	{
		private string m_Username;

		private string m_Password;

		private string Username
		{
			get
			{
				return this.m_Username;
			}
			set
			{
				if (value == null)
				{
					throw new ArgumentNullException();
				}
				this.m_Username = value;
			}
		}

		private string Password
		{
			get
			{
				return this.m_Password;
			}
			set
			{
				if (value == null)
				{
					throw new ArgumentNullException();
				}
				this.m_Password = value;
			}
		}

		public AuthUserPass(Socket server, string user, string pass) : base(server)
		{
			this.Username = user;
			this.Password = pass;
		}

		private byte[] GetAuthenticationBytes()
		{
			byte[] array = new byte[3 + this.Username.Length + this.Password.Length];
			array[0] = 1;
			array[1] = (byte)this.Username.Length;
			Array.Copy(Encoding.ASCII.GetBytes(this.Username), 0, array, 2, this.Username.Length);
			array[this.Username.Length + 2] = (byte)this.Password.Length;
			Array.Copy(Encoding.ASCII.GetBytes(this.Password), 0, array, this.Username.Length + 3, this.Password.Length);
			return array;
		}

		public override void Authenticate()
		{
			base.Server.Send(this.GetAuthenticationBytes());
			byte[] array = new byte[2];
			for (int num = 0; num != 2; num += base.Server.Receive(array, num, 2 - num, SocketFlags.None))
			{
			}
			if (array[1] != 0)
			{
				base.Server.Close();
				throw new ProxyException("Username/password combination rejected.");
			}
		}

		public override void BeginAuthenticate(HandShakeComplete callback)
		{
			this.CallBack = callback;
			base.Server.BeginSend(this.GetAuthenticationBytes(), 0, 3 + this.Username.Length + this.Password.Length, SocketFlags.None, new AsyncCallback(this.OnSent), base.Server);
		}

		private void OnSent(IAsyncResult ar)
		{
			try
			{
				base.Server.EndSend(ar);
				base.Buffer = new byte[2];
				base.Server.BeginReceive(base.Buffer, 0, 2, SocketFlags.None, new AsyncCallback(this.OnReceive), base.Server);
			}
			catch (Exception error)
			{
				this.CallBack(error);
			}
		}

		private void OnReceive(IAsyncResult ar)
		{
			try
			{
				base.Received += base.Server.EndReceive(ar);
				if (base.Received == base.Buffer.Length)
				{
					if (base.Buffer[1] != 0)
					{
						throw new ProxyException("Username/password combination not accepted.");
					}
					this.CallBack(null);
				}
				else
				{
					base.Server.BeginReceive(base.Buffer, base.Received, base.Buffer.Length - base.Received, SocketFlags.None, new AsyncCallback(this.OnReceive), base.Server);
				}
			}
			catch (Exception error)
			{
				this.CallBack(error);
			}
		}
	}
}
