2015-05-10 11:11:27 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
2015-05-29 21:34:57 +00:00
|
|
|
|
using System.Linq;
|
2015-05-10 11:11:27 +00:00
|
|
|
|
using System.Net;
|
|
|
|
|
using System.Net.Sockets;
|
2018-10-04 19:49:24 +00:00
|
|
|
|
using Quasar.Server.Networking;
|
2015-05-10 11:11:27 +00:00
|
|
|
|
|
2018-10-04 19:49:24 +00:00
|
|
|
|
namespace Quasar.Server.ReverseProxy
|
2015-05-10 11:11:27 +00:00
|
|
|
|
{
|
|
|
|
|
public class ReverseProxyServer
|
|
|
|
|
{
|
2015-05-10 17:02:10 +00:00
|
|
|
|
public delegate void ConnectionEstablishedCallback(ReverseProxyClient proxyClient);
|
2015-05-10 11:11:27 +00:00
|
|
|
|
|
2015-05-10 17:02:10 +00:00
|
|
|
|
public delegate void UpdateConnectionCallback(ReverseProxyClient proxyClient);
|
2015-05-10 11:11:27 +00:00
|
|
|
|
|
2015-05-10 17:02:10 +00:00
|
|
|
|
public event ConnectionEstablishedCallback OnConnectionEstablished;
|
|
|
|
|
public event UpdateConnectionCallback OnUpdateConnection;
|
|
|
|
|
|
|
|
|
|
private Socket _socket;
|
2015-05-29 21:34:57 +00:00
|
|
|
|
private readonly List<ReverseProxyClient> _clients;
|
2015-05-10 11:11:27 +00:00
|
|
|
|
|
2015-05-16 18:39:35 +00:00
|
|
|
|
public ReverseProxyClient[] ProxyClients
|
2015-05-10 11:11:27 +00:00
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
2015-05-10 13:34:49 +00:00
|
|
|
|
lock (_clients)
|
|
|
|
|
{
|
|
|
|
|
return _clients.ToArray();
|
|
|
|
|
}
|
2015-05-10 11:11:27 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-16 15:41:28 +00:00
|
|
|
|
public ReverseProxyClient[] OpenConnections
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
lock (_clients)
|
|
|
|
|
{
|
|
|
|
|
List<ReverseProxyClient> temp = new List<ReverseProxyClient>();
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < _clients.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
if (_clients[i].ProxySuccessful)
|
|
|
|
|
{
|
|
|
|
|
temp.Add(_clients[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return temp.ToArray();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2015-05-16 18:39:35 +00:00
|
|
|
|
public Client[] Clients { get; private set; }
|
|
|
|
|
|
|
|
|
|
//We can also use the Random class but not sure if that will evenly spread the connections
|
|
|
|
|
//The Random class might even fail to make use of all the clients
|
2015-05-29 21:34:57 +00:00
|
|
|
|
private uint _clientIndex;
|
2015-05-10 11:11:27 +00:00
|
|
|
|
|
|
|
|
|
public ReverseProxyServer()
|
|
|
|
|
{
|
|
|
|
|
_clients = new List<ReverseProxyClient>();
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-27 15:14:21 +00:00
|
|
|
|
public void StartServer(Client[] clients, string ipAddress, ushort port)
|
2015-05-10 11:11:27 +00:00
|
|
|
|
{
|
|
|
|
|
Stop();
|
|
|
|
|
|
2015-05-16 18:39:35 +00:00
|
|
|
|
this.Clients = clients;
|
2015-05-10 17:02:10 +00:00
|
|
|
|
this._socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
|
|
|
|
this._socket.Bind(new IPEndPoint(IPAddress.Parse(ipAddress), port));
|
|
|
|
|
this._socket.Listen(100);
|
2015-08-30 13:04:46 +00:00
|
|
|
|
this._socket.BeginAccept(AsyncAccept, null);
|
2015-05-10 11:11:27 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-08-30 13:04:46 +00:00
|
|
|
|
private void AsyncAccept(IAsyncResult ar)
|
2015-05-10 11:11:27 +00:00
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
lock (_clients)
|
|
|
|
|
{
|
2015-05-29 21:34:57 +00:00
|
|
|
|
_clients.Add(new ReverseProxyClient(Clients[_clientIndex % Clients.Length], this._socket.EndAccept(ar), this));
|
|
|
|
|
_clientIndex++;
|
2015-05-10 11:11:27 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2015-05-10 17:02:10 +00:00
|
|
|
|
catch
|
|
|
|
|
{
|
|
|
|
|
}
|
2015-05-10 11:11:27 +00:00
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
2015-08-30 13:04:46 +00:00
|
|
|
|
this._socket.BeginAccept(AsyncAccept, null);
|
2015-05-10 17:02:10 +00:00
|
|
|
|
}
|
|
|
|
|
catch
|
|
|
|
|
{
|
|
|
|
|
/* Server stopped listening */
|
2015-05-10 11:11:27 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Stop()
|
|
|
|
|
{
|
2015-05-10 17:02:10 +00:00
|
|
|
|
if (_socket != null)
|
2015-09-08 22:19:48 +00:00
|
|
|
|
{
|
2015-05-10 17:02:10 +00:00
|
|
|
|
_socket.Close();
|
2015-09-08 22:19:48 +00:00
|
|
|
|
_socket = null;
|
|
|
|
|
}
|
2015-05-10 11:11:27 +00:00
|
|
|
|
|
|
|
|
|
lock (_clients)
|
|
|
|
|
{
|
2015-05-10 16:14:07 +00:00
|
|
|
|
foreach (ReverseProxyClient client in new List<ReverseProxyClient>(_clients))
|
2015-05-10 11:11:27 +00:00
|
|
|
|
client.Disconnect();
|
2015-05-10 13:34:49 +00:00
|
|
|
|
_clients.Clear();
|
2015-05-10 11:11:27 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-10 17:02:10 +00:00
|
|
|
|
public ReverseProxyClient GetClientByConnectionId(int connectionId)
|
2015-05-10 11:11:27 +00:00
|
|
|
|
{
|
|
|
|
|
lock (_clients)
|
|
|
|
|
{
|
2015-05-29 21:34:57 +00:00
|
|
|
|
return _clients.FirstOrDefault(t => t.ConnectionId == connectionId);
|
2015-05-10 11:11:27 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-10 17:02:10 +00:00
|
|
|
|
internal void CallonConnectionEstablished(ReverseProxyClient proxyClient)
|
2015-05-10 11:11:27 +00:00
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
2015-05-10 17:02:10 +00:00
|
|
|
|
if (OnConnectionEstablished != null)
|
|
|
|
|
OnConnectionEstablished(proxyClient);
|
|
|
|
|
}
|
|
|
|
|
catch
|
|
|
|
|
{
|
2015-05-10 11:11:27 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2015-05-10 17:02:10 +00:00
|
|
|
|
|
|
|
|
|
internal void CallonUpdateConnection(ReverseProxyClient proxyClient)
|
2015-05-10 11:11:27 +00:00
|
|
|
|
{
|
2015-05-10 13:34:49 +00:00
|
|
|
|
//remove a client that has been disconnected
|
|
|
|
|
try
|
|
|
|
|
{
|
2015-05-10 17:02:10 +00:00
|
|
|
|
if (!proxyClient.IsConnected)
|
2015-05-10 13:34:49 +00:00
|
|
|
|
{
|
|
|
|
|
lock (_clients)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < _clients.Count; i++)
|
|
|
|
|
{
|
2015-05-10 17:02:10 +00:00
|
|
|
|
if (_clients[i].ConnectionId == proxyClient.ConnectionId)
|
2015-05-10 13:34:49 +00:00
|
|
|
|
{
|
|
|
|
|
_clients.RemoveAt(i);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-05-10 17:02:10 +00:00
|
|
|
|
catch
|
|
|
|
|
{
|
|
|
|
|
}
|
2015-05-10 13:34:49 +00:00
|
|
|
|
|
2015-05-10 11:11:27 +00:00
|
|
|
|
try
|
|
|
|
|
{
|
2015-05-10 17:02:10 +00:00
|
|
|
|
if (OnUpdateConnection != null)
|
|
|
|
|
OnUpdateConnection(proxyClient);
|
|
|
|
|
}
|
|
|
|
|
catch
|
|
|
|
|
{
|
2015-05-10 11:11:27 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-05-10 17:02:10 +00:00
|
|
|
|
}
|