Click here to Skip to main content
15,893,722 members
Articles / Programming Languages / C#

Internet Magic (Proxy Server) Windows Application

Rate me:
Please Sign up or sign in to vote.
3.00/5 (8 votes)
10 Apr 2010CPOL3 min read 68.7K   8.8K   38  
Windows application which creates a proxy server to share Internet over any TCP/IP network
using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
using internet_magic;

namespace internet_magic.Ftp {

///<summary>Relays FTP data between a remote host and a local client.</summary>
internal sealed class FtpDataConnection : Client {
	///<summary>Initializes a new instance of the FtpDataConnection class.</summary>
	public FtpDataConnection() : base() {}
	///<summary>Initializes a new instance of the FtpDataConnection class.</summary>
	///<param name="RemoteAddress">The address on the local FTP client to connect to.</param>
	///<returns>The PORT command string to send to the FTP server.</returns>
	public string ProcessPort(IPEndPoint RemoteAddress) {
		try {
			ListenSocket = new Socket(IPAddress.Any.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
			ListenSocket.Bind(new IPEndPoint(IPAddress.Any, 0));
			ListenSocket.Listen(1);
			ListenSocket.BeginAccept(new AsyncCallback(this.OnPortAccept), ListenSocket);
			ClientSocket = new Socket(RemoteAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
			ClientSocket.BeginConnect(RemoteAddress, new AsyncCallback(this.OnPortConnected), ClientSocket);
            return "PORT " + Listener.GetLocalExternalIP().ToString().Replace('.', ',') + "," + Math.Floor((double)((IPEndPoint)ListenSocket.LocalEndPoint).Port / 256).ToString() + "," + (((IPEndPoint)ListenSocket.LocalEndPoint).Port % 256).ToString() + "\r\n";
		} catch {
			Dispose();
			return "PORT 0,0,0,0,0,0\r\n";
		}
	}
	///<summary>Called when we're connected to the data port on the local FTP client.</summary>
	///<param name="ar">The result of the asynchronous operation.</param>
	private void OnPortConnected(IAsyncResult ar) {
		try {
			ClientSocket.EndConnect(ar);
			StartHandshake();
		} catch {
			Dispose();
		}
	}
	///<summary>Called when there's a connection from the remote FTP server waiting to be accepted.</summary>
	///<param name="ar">The result of the asynchronous operation.</param>
	private void OnPortAccept(IAsyncResult ar) {
		try {
			DestinationSocket = ListenSocket.EndAccept(ar);
			ListenSocket.Close();
			ListenSocket = null;
			StartHandshake();
		} catch {
			Dispose();
		}
	}
	///<summary>Starts relaying data between the remote FTP server and the local FTP client.</summary>
	public override void StartHandshake() {
		if (DestinationSocket != null && ClientSocket != null && DestinationSocket.Connected && ClientSocket.Connected)
			StartRelay();
	}
	///<summary>Gets or sets the Socket that's used to listen for incoming connections.</summary>
	///<value>A Socket that's used to listen for incoming connections.</value>
	private Socket ListenSocket {
		get {
			return m_ListenSocket;
		}
		set {
			if (m_ListenSocket != null)
				m_ListenSocket.Close();
			m_ListenSocket = value;
		}
	}
	///<summary>Gets or sets the parent of this FtpDataConnection.</summary>
	///<value>The FtpClient object that's the parent of this FtpDataConnection object.</value>
	private FtpClient Parent {
		get {
			return m_Parent;
		}
		set {
			m_Parent = value;
		}
	}
	///<summary>Gets or sets a string that stores the reply that has been sent from the remote FTP server.</summary>
	///<value>A string that stores the reply that has been sent from the remote FTP server.</value>
	private string FtpReply {
		get {
			return m_FtpReply;
		}
		set {
			m_FtpReply = value;
		}
	}
	///<summary>Gets or sets a boolean value that indicates whether the FtpDataConnection expects a reply from the remote FTP server or not.</summary>
	///<value>A boolean value that indicates whether the FtpDataConnection expects a reply from the remote FTP server or not.</value>
	internal bool ExpectsReply {
		get {
			return m_ExpectsReply;
		}
		set {
			m_ExpectsReply = value;
		}
	}
	///<summary>Called when the proxy server processes a PASV command.</summary>
	///<param name="Parent">The parent FtpClient object.</param>
	public void ProcessPasv(FtpClient Parent) {
		this.Parent = Parent;
		ExpectsReply = true;
	}
	///<summary>Called when the FtpClient receives a reply on the PASV command from the server.</summary>
	///<param name="Input">The received reply.</param>
	///<returns>True if the input has been processed successfully, false otherwise.</returns>
	internal bool ProcessPasvReplyRecv(string Input) {
		FtpReply += Input;
		if (FtpClient.IsValidReply(FtpReply)) {
			ExpectsReply = false;
			ProcessPasvReply(FtpReply);
			FtpReply = "";
			return true;
		}
		return false;
	}
	///<summary>Processes a PASV reply from the server.</summary>
	///<param name="Reply">The reply to process.</param>
	private void ProcessPasvReply(string Reply) {
		try {
			IPEndPoint ConnectTo = ParsePasvIP(Reply);
			DestinationSocket = new Socket(ConnectTo.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
			DestinationSocket.BeginConnect(ConnectTo, new AsyncCallback(this.OnPasvConnected), DestinationSocket);
		} catch {
			Dispose();
		}
	}
	///<summary>Parses a PASV reply into an instance of the IPEndPoint class.</summary>
	///<param name="Reply">The reply to parse into an IPEndPoint.</param>
	///<returns>An instance of the IPEndPoint class when successful, null otherwise.</returns>
	private IPEndPoint ParsePasvIP(string Reply) {
		int StartIndex, StopIndex;
		string IPString;
		StartIndex = Reply.IndexOf("(");
		if (StartIndex == -1) {
			return null;
		} else {
			StopIndex = Reply.IndexOf(")", StartIndex);
			if (StopIndex == -1)
				return null;
			else
				IPString = Reply.Substring(StartIndex + 1, StopIndex - StartIndex - 1);
		}
		string [] Parts = IPString.Split(',');
		if (Parts.Length == 6)
			return new IPEndPoint(IPAddress.Parse(String.Join(".", Parts, 0, 4)), int.Parse(Parts[4]) * 256 + int.Parse(Parts[5]));
		else
			return null;
	}
	///<summary>Called when we're connected to the data port of the remote FTP server.</summary>
	///<param name="ar">The result of the asynchronous operation.</param>
	private void OnPasvConnected(IAsyncResult ar) {
		try {
			DestinationSocket.EndConnect(ar);
			ListenSocket = new Socket(IPAddress.Any.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
			ListenSocket.Bind(new IPEndPoint(IPAddress.Any, 0));
			ListenSocket.Listen(1);
			ListenSocket.BeginAccept(new AsyncCallback(this.OnPasvAccept), ListenSocket);
            Parent.SendCommand("227 Entering Passive Mode (" + Listener.GetLocalInternalIP().ToString().Replace('.', ',') + "," + Math.Floor((double)((IPEndPoint)ListenSocket.LocalEndPoint).Port / 256).ToString() + "," + (((IPEndPoint)ListenSocket.LocalEndPoint).Port % 256).ToString() + ").\r\n");
		} catch {
			Dispose();
		}
	}
	///<summary>Called when there's a connection from the local FTP client waiting to be accepted.</summary>
	///<param name="ar">The result of the asynchronous operation.</param>
	private void OnPasvAccept(IAsyncResult ar) {
		try {
			ClientSocket = ListenSocket.EndAccept(ar);
			StartHandshake();
		} catch {
			Dispose();
		}
	}
	// private variables
	/// <summary>Holds the value of the ListenSocket property.</summary>
	private Socket m_ListenSocket;
	/// <summary>Holds the value of the Parent property.</summary>
	private FtpClient m_Parent;
	/// <summary>Holds the value of the FtpReply property.</summary>
	private string m_FtpReply = "";
	/// <summary>Holds the value of the ExpectsReply property.</summary>
	private bool m_ExpectsReply = false;
}

}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
India India
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions