// DataSocket.cs
//
//  Copyright (C) 2008-2009 Christian Eide
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

using System;
using System.Net.Sockets;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;

namespace bareFTP.Protocol.Ftp
{
	public class DataSocket
	{
		private FTPMode mode;
		TcpClient tcpClient = null;
		TcpListener tcpListener = null;
		bool SSL = false;
		string protection_level = string.Empty;
		bareFTP.Preferences.Config config;
		string host;
		
		public DataSocket(string host, int port, FTPMode ftpMode, bool ssl, string prot_level, bareFTP.Preferences.Config config)
		{
			this.config = config;
			mode = ftpMode;
			SSL = ssl;
			protection_level = prot_level;
			this.host = host;
			
			if(mode == FTPMode.Passive)
			{
				tcpClient = new TcpClient();
				tcpClient.Connect(host, port);
			}
			else if(mode == FTPMode.Active)
			{
				tcpListener = new TcpListener(System.Net.IPAddress.Any, port);
				tcpListener.Start();
			}
		}
		
		public System.IO.Stream GetStream()
		{
			if(mode == FTPMode.Active)
				tcpClient = tcpListener.AcceptTcpClient();
			
			tcpClient.ReceiveTimeout = config.NetworkTimeout;
			//tcpClient.ReceiveTimeout = 2000;
			tcpClient.SendTimeout = config.NetworkTimeout;
			//tcpClient.ReceiveBufferSize = 1;
			
			if(SSL && protection_level == "P")
			{
				SslStream stream = new SslStream(tcpClient.GetStream() , false, CertificateValidation);
				stream.AuthenticateAsClient(host);
				return stream;
			}
			else
			{
				return tcpClient.GetStream();
			}
		}
		
		public bool DataAvailable()
		{
			int count = 0;
			bool result = false;
			
			while(count < 50)
			{
				if(mode == FTPMode.Passive)
				{
					if(tcpClient.Available > 0)
					{
						return true;
					}
				}
				else
				{
					if(tcpListener.Pending())
						return true;
				}
				System.Threading.Thread.Sleep(10);
				count++;
			}
			
			return result;
		}
		
		public void Close()
		{
			tcpClient.Close();
			if(mode == FTPMode.Active)
				tcpListener.Stop();			
		}
		
		private bool CertificateValidation (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
        {
			return true; // I don't care about the certificate, so it will always return true
        }
		
		
	}
	
}
