I'm not gonna give you a full proxy, but here's a demonstration on how you might set up a basic proxy to listen on some ports, accept connectionson those ports, and handle events on those accepted connections. This uses a single thread for all connections.
Code:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
namespace CoProxyExample
{
class CoProxy
{
private TcpListener m_authlistener;
private TcpListener m_gamelistener;
private ArrayList m_read_sock_set;
private List<CoConnection> m_Connections;
public CoProxy()
{
IPAddress localhost = IPAddress.Parse("127.0.0.1");
m_authlistener = new TcpListener(localhost, 9958);
m_gamelistener = new TcpListener(localhost, 5816);
m_authlistener.Start();
m_gamelistener.Start();
m_read_sock_set = new ArrayList();
m_read_sock_set.Add(m_authlistener.Server);
m_read_sock_set.Add(m_gamelistener.Server);
m_Connections = new List<CoConnection>();
}
public void RunProxy()
{
bool stopproxy = false;
IPAddress loginserverIP = IPAddress.Parse("69.59.142.13");
ArrayList tmp_sock_set = new ArrayList();
while (true)
{
tmp_sock_set.Clear();
tmp_sock_set = (ArrayList)m_read_sock_set.Clone();
Socket.Select(tmp_sock_set, null, null, 1000);
for (int i=0;i<tmp_sock_set.Count;i++)
{
if (tmp_sock_set[i] == m_authlistener.Server)
{
Socket s1 = m_authlistener.AcceptSocket();
m_Connections.Add(new AuthConnection(s1));
m_Connections[m_Connections.Count - 1].ConnectToServer(loginserverIP, 9958);
m_read_sock_set.Add(s1);
m_read_sock_set.Add(m_Connections[m_Connections.Count-1].serversocket);
}
else if (tmp_sock_set[i] == m_gamelistener.Server)
{
Socket s2 = m_gamelistener.AcceptSocket();
m_read_sock_set.Add(s2);
m_Connections.Add(new GameConnection(s2));
m_read_sock_set.Add(m_Connections[m_Connections.Count - 1].serversocket);
}
else
{
FindConnection((Socket)tmp_sock_set[i]);
}
}
if (stopproxy)
{
break;
}
}
m_authlistener.Stop();
m_maplistener.Stop();
}
private void FindConnection(Socket s)
{
for(int i=0;i<m_Connections.Count;i++)
{
if (m_Connections[i].IsPending(s)) break;
if (m_Connections[i].IsDisconnected())
{
m_read_sock_set.Remove(m_Connections[i].clientsocket);
m_read_sock_set.Remove(m_Connections[i].serversocket);
m_Connections.Remove(m_Connections[i]);
break;
}
}
}
}
}
The CoConnection is an abstract class which would contain the socket descriptor for the connection to the client and to the server, and would have the basic send/receive methods and IsPending() etc. You'd derive from this to contain the information specific to AuthConnection or GameConnection such as encryptions.
Code:
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using CoProxyExample.Packets;
namespace CoProxyExample
{
abstract class CoConnection
{
private Socket m_clientConnection;
private Socket m_serverConnection;
private bool hasconnected;
public CoConnection(Socket s)
{
m_clientConnection = s;
m_serverConnection = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
hasconnected = false;
}
public Socket clientsocket
{
get { return m_clientConnection; }
}
public Socket serversocket
{
get { return m_serverConnection; }
}
public void ConnectToServer(IPAddress serverip, int port)
{
m_serverConnection.Connect(serverip, port);
hasconnected = true;
}
public bool IsPending(Socket s)
{
if (m_clientConnection == s)
{
ReceiveFromClient();
return true;
}
else if(m_serverConnection == s)
{
ReceiveFromServer();
return true;
}
return false;
}
public bool IsDisconnected()
{
if (!hasconnected) return false;
if (!m_clientConnection.Connected)
{
m_serverConnection.Disconnect(false);
return true;
}
if (!m_serverConnection.Connected)
{
m_clientConnection.Disconnect(false);
return true;
}
return false;
}
private void ReceiveFromClient()
{
Packet packet = new Packet(2048);
int bsize = 0;
bsize = m_clientConnection.Receive(packet.Buffer);
if (bsize == 0)
{
m_clientConnection.Disconnect(false);
return;
}
HandlePacketFromClient(packet);
}
private void ReceiveFromServer()
{
Packet packet = new Packet(2048);
int bsize = 0;
bsize = m_serverConnection.Receive(packet.Buffer);
if (bsize == 0)
{
m_serverConnection.Disconnect(false);
return;
}
HandlePacketFromServer(packet);
}
private void SendToServer(Packet packet)
{
m_serverConnection.Send(packet.Buffer, packet.Size, SocketFlags.None);
}
private void SendToClient(Packet packet)
{
m_clientConnection.Send(packet.Buffer, packet.Size, SocketFlags.None);
}
}
}