I am writing proxy server on asynchronous sockets for educational purposes and stuck at the point, that my browser treat some web-sites' response different way if i don't use the proxy, for some of them i don't see response at all, though i see in console, that request was sent and response was received.
Here is the code of server.
Quote:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
namespace AsyncTcpServer
{
internal class AsyncTcpServer
{
private bool syncmode;
private Socket listenSocket;
private const int port_ = 9999;
private const int bufferSendSize = 8192;
private const int bufferSize = 65536;
private LingerOption lo;
private AutoResetEvent autoEvent;
private static void Main(string[] args)
{
var server = new AsyncTcpServer();
ThreadPool.SetMinThreads(100, 100);
ThreadPool.SetMaxThreads(3000, 3000);
server.StartServer();
Console.WriteLine("Press smth to stop server");
Console.Read();
}
private void StartServer()
{
autoEvent = new AutoResetEvent(true);
var addressList = Dns.GetHostEntry(Environment.MachineName).AddressList;
foreach (var ipAddress in addressList)
{
Console.WriteLine(ipAddress);
}
int choice;
Console.WriteLine("Choose ip");
int.TryParse(Console.ReadLine(), out choice);
Console.WriteLine("Choose sync mode or not");
bool.TryParse(Console.ReadLine(), out syncmode);
var localEndPoint = new IPEndPoint(addressList[choice], port_);
listenSocket = new Socket(localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
lo = new LingerOption(false, 0);
listenSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, lo);
if (localEndPoint.AddressFamily == AddressFamily.InterNetworkV6)
{
listenSocket.SetSocketOption(SocketOptionLevel.IPv6, (SocketOptionName)27, false);
listenSocket.Bind(new IPEndPoint(IPAddress.IPv6Any, localEndPoint.Port));
}
else
{
Console.WriteLine(localEndPoint);
listenSocket.Bind(localEndPoint);
}
listenSocket.Listen(500);
if (syncmode)
{
listenSocket.BeginAccept(EndAccept, listenSocket);
}
else
{
for (int i = 0; i < 200; i++)
{
listenSocket.BeginAccept(EndAccept, listenSocket);
}
}
}
private void EndAccept(IAsyncResult result)
{
if (syncmode)
{
autoEvent.WaitOne();
}
Console.WriteLine("ExecuteRequest");
var server = result.AsyncState as Socket;
if (server != null)
{
try
{
var myClient = server.EndAccept(result);
myClient.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, lo);
var token = new Token(myClient, bufferSendSize);
myClient.BeginReceive(token.Buffer, 0, token.Buffer.Length, SocketFlags.None, EndReceive, token);
}
catch (SocketException e)
{
Console.WriteLine(e.Message);
autoEvent.Set();
listenSocket.BeginAccept(EndAccept, listenSocket);
}
}
else
{
StartServer();
}
}
private void EndReceive(IAsyncResult result)
{
var token = result.AsyncState as Token;
if (token == null) return;
var myClient = token.Connection;
var length = myClient.EndReceive(result);
Console.WriteLine("Process request from {0}", myClient.RemoteEndPoint as IPEndPoint);
byte[] httpRequest = new byte[length];
Array.Copy(token.Buffer, httpRequest, length);
token.Buffer = httpRequest;
var endPoint = ProcessReceive(token);
if (endPoint == null)
{
return;
}
var rerouting = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
{
SendBufferSize = bufferSendSize,
ReceiveBufferSize = bufferSize
};
rerouting.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, lo);
token.RemoteConnection = rerouting;
rerouting.BeginConnect(endPoint, EndConnect, token);
}
private IPEndPoint ProcessReceive(Token token)
{
var client = token.Connection;
var regex = new Regex(@"Host: (((?<host>.+?):(?<port>\d+?))|(?<host>.+?))\s+", RegexOptions.Multiline | RegexOptions.IgnoreCase);
var match = regex.Match(System.Text.Encoding.UTF8.GetString(token.Buffer));
string host = match.Groups["host"].Value;
var endPoint = client.RemoteEndPoint as IPEndPoint;
if (host.Equals(string.Empty))
{
listenSocket.BeginAccept(EndAccept, listenSocket);
return null;
}
Console.WriteLine("requesting {0} from {1}", host, endPoint);
int port = 0;
if (!int.TryParse(match.Groups["port"].Value, out port))
{
port = 80;
}
const string ipPattern = @"^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$";
bool isIp = Regex.IsMatch(host, ipPattern);
IPAddress ip;
if (isIp)
{
ip = IPAddress.Parse(host);
}
else
{
IPHostEntry hostEntry = Dns.GetHostEntry(host);
ip = hostEntry.AddressList[hostEntry.AddressList.Count() - 1];
}
return new IPEndPoint(ip, port);
}
private void EndConnect(IAsyncResult result)
{
var token = result.AsyncState as Token;
if (token == null) return;
try
{
var rerouting = token.RemoteConnection;
rerouting.EndConnect(result);
Console.WriteLine("Connected to {0}", token.RemoteConnection.RemoteEndPoint as IPEndPoint);
rerouting.BeginSend(token.Buffer, 0, token.Buffer.Length, SocketFlags.None, EndSend, token);
}
catch (SocketException e)
{
token.Dispose();
Console.WriteLine(e.Message);
autoEvent.Set();
listenSocket.BeginAccept(EndAccept, listenSocket);
}
}
private void EndSend(IAsyncResult result)
{
var token = result.AsyncState as Token;
if (token == null) return;
try
{
var length = token.RemoteConnection.EndSend(result);
Console.WriteLine("Sent{1} bytes to {0}", token.RemoteConnection.RemoteEndPoint as IPEndPoint, length);
var newtoken = new Token(token, bufferSize);
token.RemoteConnection.BeginReceive(newtoken.Buffer, 0, newtoken.Buffer.Length, SocketFlags.None, EndReceiveRemote, newtoken);
}
catch (SocketException e)
{
token.Dispose();
Console.WriteLine(e.Message);
autoEvent.Set();
listenSocket.BeginAccept(EndAccept, listenSocket);
}
}
private void EndReceiveRemote(IAsyncResult result)
{
var token = result.AsyncState as Token;
if (token == null) return;
try
{
var length = token.RemoteConnection.EndReceive(result);
Console.WriteLine("Received {1} bytes from {0}", token.RemoteConnection.RemoteEndPoint as IPEndPoint, length);
var httpResponse = token.Buffer;
if (httpResponse == null || httpResponse.Length <= 0) return;
if (!syncmode)
{
autoEvent.WaitOne();
}
token.Connection.BeginSend(token.Buffer, 0, length, SocketFlags.None, EndSendToClient, token);
}
catch (SocketException e)
{
token.Dispose();
autoEvent.Set();
Console.WriteLine(e.Message);
listenSocket.BeginAccept(EndAccept, listenSocket);
}
}
private void EndSendToClient(IAsyncResult result)
{
var token = result.AsyncState as Token;
if (token == null) return;
var length = token.Connection.EndSend(result);
Console.WriteLine("Sent{1} bytes to {0}", token.Connection.RemoteEndPoint as IPEndPoint, length);
token.Dispose();
autoEvent.Set();
listenSocket.BeginAccept(EndAccept, listenSocket);
}
}
}