mirror of
https://github.com/Ylianst/MeshCommander
synced 2025-12-06 06:03:20 +00:00
first commit
This commit is contained in:
175
webrelay.ashx
Normal file
175
webrelay.ashx
Normal file
@@ -0,0 +1,175 @@
|
||||
<%@ WebHandler Language="C#" Class="ManageabilityCommander.WebRelay" %>
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Web;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Collections;
|
||||
using System.Net.Sockets;
|
||||
using System.Net.Security;
|
||||
using System.Web.WebSockets;
|
||||
using System.Net.WebSockets;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Authentication;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
|
||||
namespace ManageabilityCommander
|
||||
{
|
||||
/// <summary>
|
||||
/// WebSocket to TCP/TLS bridge. This handler accepts a websocket connection and forwards the traffic to TCP/TLS.
|
||||
/// </summary>
|
||||
public class WebRelay : IHttpHandler
|
||||
{
|
||||
string host = null;
|
||||
int port = 0;
|
||||
bool tls = false;
|
||||
WebSocket websocket = null;
|
||||
TcpClient client = null;
|
||||
Stream stream = null;
|
||||
byte[] clientReadBuf = new byte[16384];
|
||||
bool closing = false;
|
||||
object mainlock = new object();
|
||||
|
||||
public bool IsReusable { get { return false; } }
|
||||
private void Log(string x) { lock (mainlock) { File.AppendAllText("C:\\temp\\tlog.txt", DateTime.Now.ToString() + " - " + x.Replace('\0', '~') + "\r\n"); } }
|
||||
|
||||
public void ProcessRequest(HttpContext context)
|
||||
{
|
||||
var queryargs = System.Web.HttpUtility.ParseQueryString(context.Request.Url.Query);
|
||||
|
||||
if (!context.IsWebSocketRequest)
|
||||
{
|
||||
context.Response.StatusCode = 200;
|
||||
context.Response.Redirect("default.htm");
|
||||
context.Response.End();
|
||||
return;
|
||||
}
|
||||
|
||||
if (queryargs["host"] == null || queryargs["port"] == null || queryargs["tls"] == null)
|
||||
{
|
||||
context.Response.StatusCode = 200;
|
||||
context.Response.ContentType = "text/plain";
|
||||
context.Response.Write("Host, Port and Tls arguments expected.");
|
||||
context.Response.End();
|
||||
return;
|
||||
}
|
||||
|
||||
host = queryargs["host"];
|
||||
int.TryParse(queryargs["port"], out port);
|
||||
tls = (queryargs["tls"] != null && string.Compare(queryargs["tls"], "1", true) == 0);
|
||||
|
||||
if (port < 1 || port > 65535)
|
||||
{
|
||||
context.Response.StatusCode = 200;
|
||||
context.Response.ContentType = "text/plain";
|
||||
context.Response.Write("Invalid port.");
|
||||
context.Response.End();
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
context.AcceptWebSocketRequest(ProcessNewWebSocket);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
context.Response.StatusCode = 202;
|
||||
context.Response.ContentType = "text/plain";
|
||||
context.Response.Write("AcceptWebSocketRequest() Error: " + ex.ToString());
|
||||
context.Response.End();
|
||||
}
|
||||
}
|
||||
|
||||
private bool CheckClientCert(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors errors)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
private async Task ProcessNewWebSocket(AspNetWebSocketContext context)
|
||||
{
|
||||
websocket = context.WebSocket;
|
||||
client = new TcpClient();
|
||||
try { await client.ConnectAsync(host, port); } catch (Exception) { client = null; }
|
||||
|
||||
if (client == null)
|
||||
{
|
||||
await websocket.CloseAsync(WebSocketCloseStatus.EndpointUnavailable, "Unable to TCP connect to target host:port", CancellationToken.None);
|
||||
websocket.Dispose();
|
||||
websocket = null;
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (tls == false)
|
||||
{
|
||||
stream = client.GetStream();
|
||||
stream.BeginRead(clientReadBuf, 0, clientReadBuf.Length, new AsyncCallback(onClientReadData), null);
|
||||
}
|
||||
else
|
||||
{
|
||||
SslStream secureClientStream = new SslStream(client.GetStream(), false, new RemoteCertificateValidationCallback(CheckClientCert), null, EncryptionPolicy.RequireEncryption);
|
||||
stream = secureClientStream;
|
||||
secureClientStream.AuthenticateAsClientAsync(host).Wait();
|
||||
stream.BeginRead(clientReadBuf, 0, clientReadBuf.Length, new AsyncCallback(onClientReadData), null);
|
||||
}
|
||||
}
|
||||
catch (Exception) { closing = true; }
|
||||
|
||||
while (closing == false)
|
||||
{
|
||||
try
|
||||
{
|
||||
ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[16384]);
|
||||
WebSocketReceiveResult result = await websocket.ReceiveAsync(buffer, CancellationToken.None);
|
||||
if (closing == true || websocket.State != WebSocketState.Open) break;
|
||||
stream.WriteAsync(buffer.Array, buffer.Offset, result.Count).Wait();
|
||||
}
|
||||
catch (Exception) { }
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
await websocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Remote TCP connection closed", CancellationToken.None);
|
||||
websocket.Dispose();
|
||||
}
|
||||
catch (Exception) { }
|
||||
|
||||
websocket = null;
|
||||
stream = null;
|
||||
|
||||
try { client.Close(); } catch (Exception) { }
|
||||
client = null;
|
||||
}
|
||||
|
||||
private void onClientReadData(IAsyncResult ar)
|
||||
{
|
||||
int r = 0;
|
||||
try { r = stream.EndRead(ar); } catch (Exception) { }
|
||||
|
||||
try
|
||||
{
|
||||
if (r == 0)
|
||||
{
|
||||
closing = true;
|
||||
try { websocket.Abort(); } catch (Exception) { }
|
||||
}
|
||||
else
|
||||
{
|
||||
websocket.SendAsync(new ArraySegment<byte>(clientReadBuf, 0, r), WebSocketMessageType.Binary, true, CancellationToken.None).Wait();
|
||||
stream.BeginRead(clientReadBuf, 0, clientReadBuf.Length, new AsyncCallback(onClientReadData), null);
|
||||
}
|
||||
}
|
||||
catch (Exception) {
|
||||
closing = true;
|
||||
try { websocket.Abort(); } catch (Exception) { }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user