mirror of
https://github.com/Ylianst/MeshCentralRouter
synced 2025-12-14 15:23:35 +00:00
Windows native websocket fixes.
This commit is contained in:
@@ -50,32 +50,6 @@ namespace MeshCentralRouter
|
|||||||
public delegate void onStateMsgChangedHandler(string statemsg);
|
public delegate void onStateMsgChangedHandler(string statemsg);
|
||||||
public event onStateMsgChangedHandler onStateMsgChanged;
|
public event onStateMsgChangedHandler onStateMsgChanged;
|
||||||
|
|
||||||
public static string GetProxyForUrlUsingPac(string DestinationUrl, string PacUri)
|
|
||||||
{
|
|
||||||
IntPtr WinHttpSession = Win32Api.WinHttpOpen("User", Win32Api.WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, IntPtr.Zero, IntPtr.Zero, 0);
|
|
||||||
|
|
||||||
Win32Api.WINHTTP_AUTOPROXY_OPTIONS ProxyOptions = new Win32Api.WINHTTP_AUTOPROXY_OPTIONS();
|
|
||||||
Win32Api.WINHTTP_PROXY_INFO ProxyInfo = new Win32Api.WINHTTP_PROXY_INFO();
|
|
||||||
|
|
||||||
ProxyOptions.dwFlags = Win32Api.WINHTTP_AUTOPROXY_CONFIG_URL;
|
|
||||||
ProxyOptions.dwAutoDetectFlags = (Win32Api.WINHTTP_AUTO_DETECT_TYPE_DHCP | Win32Api.WINHTTP_AUTO_DETECT_TYPE_DNS_A);
|
|
||||||
ProxyOptions.lpszAutoConfigUrl = PacUri;
|
|
||||||
|
|
||||||
// Get Proxy
|
|
||||||
bool IsSuccess = Win32Api.WinHttpGetProxyForUrl(WinHttpSession, DestinationUrl, ref ProxyOptions, ref ProxyInfo);
|
|
||||||
Win32Api.WinHttpCloseHandle(WinHttpSession);
|
|
||||||
|
|
||||||
if (IsSuccess)
|
|
||||||
{
|
|
||||||
return ProxyInfo.lpszProxy;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Console.WriteLine("Error: {0}", Win32Api.GetLastError());
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Starts the routing server, called when the start button is pressed
|
// Starts the routing server, called when the start button is pressed
|
||||||
public void start(MeshCentralServer parent, int protocol, int localPort, string url, int remotePort, string remoteIP)
|
public void start(MeshCentralServer parent, int protocol, int localPort, string url, int remotePort, string remoteIP)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ namespace MeshCentralRouter
|
|||||||
public TLSCertificateCheck TLSCertCheck = TLSCertificateCheck.Verify;
|
public TLSCertificateCheck TLSCertCheck = TLSCertificateCheck.Verify;
|
||||||
public X509Certificate2 failedTlsCert = null;
|
public X509Certificate2 failedTlsCert = null;
|
||||||
static public bool nativeWebSocketFirst = true;
|
static public bool nativeWebSocketFirst = true;
|
||||||
|
private SemaphoreSlim receiveLock = new SemaphoreSlim(1, 1);
|
||||||
|
|
||||||
// Outside variables
|
// Outside variables
|
||||||
public object tag = null;
|
public object tag = null;
|
||||||
@@ -704,7 +704,17 @@ namespace MeshCentralRouter
|
|||||||
return SendFragment(null, 0, 0, 138);
|
return SendFragment(null, 0, 0, 138);
|
||||||
}
|
}
|
||||||
|
|
||||||
Task pendingSend = null;
|
// This controls the flow of fragments being sent, queuing send operations if needed
|
||||||
|
private Task pendingSend = null;
|
||||||
|
private List<pendingSendClass> pendingSends = new List<pendingSendClass>();
|
||||||
|
private class pendingSendClass
|
||||||
|
{
|
||||||
|
public pendingSendClass(byte[] data, int offset, int len, byte op) { this.data = data; this.offset = offset; this.len = len; this.op = op; }
|
||||||
|
public byte[] data;
|
||||||
|
public int offset;
|
||||||
|
public int len;
|
||||||
|
public byte op;
|
||||||
|
}
|
||||||
|
|
||||||
// Fragment op code (129 = text, 130 = binary)
|
// Fragment op code (129 = text, 130 = binary)
|
||||||
public int SendFragment(byte[] data, int offset, int len, byte op)
|
public int SendFragment(byte[] data, int offset, int len, byte op)
|
||||||
@@ -713,12 +723,21 @@ namespace MeshCentralRouter
|
|||||||
if (ws != null)
|
if (ws != null)
|
||||||
{
|
{
|
||||||
// Using native websocket
|
// Using native websocket
|
||||||
lock (this)
|
lock (pendingSends)
|
||||||
{
|
{
|
||||||
if ((pendingSend != null) && (pendingSend.IsCompleted == false)) { pendingSend.Wait(); }
|
if (pendingSend != null)
|
||||||
|
{
|
||||||
|
// A send operating is already being processes, queue this send.
|
||||||
|
pendingSends.Add(new pendingSendClass(data, offset, len, op));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// No send operations being performed now, send this fragment now.
|
||||||
ArraySegment<byte> arr = new ArraySegment<byte>(data, offset, len);
|
ArraySegment<byte> arr = new ArraySegment<byte>(data, offset, len);
|
||||||
WebSocketMessageType msgType = ((op == 129) ? WebSocketMessageType.Text : WebSocketMessageType.Binary);
|
WebSocketMessageType msgType = ((op == 129) ? WebSocketMessageType.Text : WebSocketMessageType.Binary);
|
||||||
pendingSend = ws.SendAsync(arr, msgType, true, CTS.Token);
|
pendingSend = ws.SendAsync(arr, msgType, true, CTS.Token);
|
||||||
|
pendingSend.ContinueWith(antecedent => SendFragmentDone());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
@@ -804,6 +823,29 @@ namespace MeshCentralRouter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Called when a fragment is done sending. We look to send the next one or signal that we can accept more data
|
||||||
|
private void SendFragmentDone()
|
||||||
|
{
|
||||||
|
bool q = false;
|
||||||
|
lock (pendingSends)
|
||||||
|
{
|
||||||
|
pendingSend = null;
|
||||||
|
if (pendingSends.Count > 0)
|
||||||
|
{
|
||||||
|
// There is more send operation pending, send the next one now.
|
||||||
|
pendingSendClass p = pendingSends[0];
|
||||||
|
pendingSends.RemoveAt(0);
|
||||||
|
ArraySegment<byte> arr = new ArraySegment<byte>(p.data, p.offset, p.len);
|
||||||
|
WebSocketMessageType msgType = ((p.op == 129) ? WebSocketMessageType.Text : WebSocketMessageType.Binary);
|
||||||
|
pendingSend = ws.SendAsync(arr, msgType, true, CTS.Token);
|
||||||
|
pendingSend.ContinueWith(antecedent => SendFragmentDone());
|
||||||
|
}
|
||||||
|
else { q = true; } // No pending send operations, signal ok to send more.
|
||||||
|
}
|
||||||
|
if ((q == true) && (onSendOk != null)) { onSendOk(this); }
|
||||||
|
}
|
||||||
|
|
||||||
private void SendData(byte[] buf) { SendData(buf, 0, buf.Length); }
|
private void SendData(byte[] buf) { SendData(buf, 0, buf.Length); }
|
||||||
|
|
||||||
private void SendData(byte[] buf, int off, int len)
|
private void SendData(byte[] buf, int off, int len)
|
||||||
@@ -847,7 +889,9 @@ namespace MeshCentralRouter
|
|||||||
{
|
{
|
||||||
lock (mainLock)
|
lock (mainLock)
|
||||||
{
|
{
|
||||||
|
if (readPaused == true) return;
|
||||||
readPaused = true;
|
readPaused = true;
|
||||||
|
if (ws != null) { receiveLock.Wait(); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -857,6 +901,12 @@ namespace MeshCentralRouter
|
|||||||
{
|
{
|
||||||
if (readPaused == false) return;
|
if (readPaused == false) return;
|
||||||
readPaused = false;
|
readPaused = false;
|
||||||
|
if (ws != null)
|
||||||
|
{
|
||||||
|
receiveLock.Release();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
if (shouldRead == true)
|
if (shouldRead == true)
|
||||||
{
|
{
|
||||||
shouldRead = false;
|
shouldRead = false;
|
||||||
@@ -864,6 +914,7 @@ namespace MeshCentralRouter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async Task ReceiveLoop()
|
private async Task ReceiveLoop()
|
||||||
{
|
{
|
||||||
@@ -887,6 +938,10 @@ namespace MeshCentralRouter
|
|||||||
while (!receiveResult.EndOfMessage);
|
while (!receiveResult.EndOfMessage);
|
||||||
if (receiveResult.MessageType == WebSocketMessageType.Close) break;
|
if (receiveResult.MessageType == WebSocketMessageType.Close) break;
|
||||||
outputStream.Position = 0;
|
outputStream.Position = 0;
|
||||||
|
|
||||||
|
receiveLock.Wait(); // Pause reading if needed
|
||||||
|
receiveLock.Release();
|
||||||
|
|
||||||
if (receiveResult.MessageType == WebSocketMessageType.Text)
|
if (receiveResult.MessageType == WebSocketMessageType.Text)
|
||||||
{
|
{
|
||||||
Log("Websocket got string data, len = " + (int)outputStream.Length);
|
Log("Websocket got string data, len = " + (int)outputStream.Length);
|
||||||
|
|||||||
Reference in New Issue
Block a user