You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Gateway/Mime/HttpWebSocket.cs

191 lines
5.9 KiB
C#

2 years ago
using System;
1 year ago
using System.Buffers;
2 years ago
using System.IO;
1 year ago
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
2 years ago
using System.Text;
1 year ago
using System.Threading;
using System.Threading.Tasks;
using System.Threading.Tasks.Sources;
2 years ago
using UMC.Net;
namespace UMC.Host
{
1 year ago
abstract class WebSocket : UMC.Net.MimeRequest, IDisposable
2 years ago
{
1 year ago
public override bool IsWebSocket => true;
public abstract void Dispose();
2 years ago
internal static string GetSecWebSocketAcceptString(string secWebSocketKey)
{
string s = secWebSocketKey + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
byte[] bytes = Encoding.UTF8.GetBytes(s);
byte[] inArray = System.Security.Cryptography.SHA1.HashData(bytes);
return Convert.ToBase64String(inArray);
}
internal static bool ProcessWebSocketProtocolHeader(string clientSecWebSocketProtocol, out string acceptProtocol)
{
acceptProtocol = string.Empty;
if (string.IsNullOrEmpty(clientSecWebSocketProtocol))
{
return false;
}
string[] array = clientSecWebSocketProtocol.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
if (array.Length > 0)
{
acceptProtocol = array[0];
}
return true;
}
internal static bool ValidateWebSocketHeaders(NetContext context)
{
string text = context.Headers["Sec-WebSocket-Version"];
if (string.IsNullOrEmpty(text))
{
return false;
}
if (!string.Equals(text, "13", StringComparison.OrdinalIgnoreCase))
{
return false;
}
string text2 = context.Headers["Sec-WebSocket-Key"];
if (!string.IsNullOrWhiteSpace(text2))
{
try
{
return Convert.FromBase64String(text2).Length == 16;
}
catch
{
return false;
}
}
return false;
}
internal static void AcceptWebSocketAsyncCore(NetContext context, Stream stream)
{
if (context.Url.AbsolutePath == "/UMC.WS")
{
var Device = context.Cookies["device"] ?? context.QueryString.Get("device");
if (String.IsNullOrEmpty(Device) == false)
{
if (ValidateWebSocketHeaders(context) && false)
{
string secWebSocketKey = context.Headers["Sec-WebSocket-Key"];
string secWebSocketAcceptString = GetSecWebSocketAcceptString(secWebSocketKey);
var writer = new Net.TextWriter(stream.Write);
writer.Write($"HTTP/1.1 101 {HttpStatusDescription.Get(101)}\r\n");
writer.Write("Connection: Upgrade\r\n");
writer.Write("Upgrade: websocket\r\n");
writer.Write($"Sec-WebSocket-Accept: {secWebSocketAcceptString}\r\n");
writer.Write($"Sec-WebSocket-Protocol: mqtt\r\n");
1 year ago
writer.Write("Server: Apiumc\r\n\r\n");
2 years ago
writer.Flush();
writer.Dispose();
var DeviceId = UMC.Data.Utility.Guid(Device, true).Value;
//16384,
1 year ago
// context.Tag = WebSocket.CreateFromStream(stream, isServer: true, "mqtt", WebSocket.DefaultKeepAliveInterval);
2 years ago
return;
}
}
}
context.Error(new ArgumentException("WebSocket"));
}
}
1 year ago
class HttpWebSocket : WebSocket
{
public byte[] buffer = System.Buffers.ArrayPool<byte>.Shared.Rent(0x600);
Socket socket;
public HttpWebSocket(HttpMime mime, Socket stream)
{
this.mime = mime;
this.socket = stream;
SocketAsyncEventArgs eventArgs = new SocketAsyncEventArgs();
eventArgs.SetBuffer(buffer);
eventArgs.Completed += Http;
if (!this.socket.ReceiveAsync(eventArgs))
{
ProcessReceive(eventArgs);
}
}
HttpMime mime;
private void Http(object sender, SocketAsyncEventArgs e)
{
switch (e.LastOperation)
{
case SocketAsyncOperation.Receive:
ProcessReceive(e);
break;
}
}
private void ProcessReceive(SocketAsyncEventArgs e)
{
if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success)
{
try
{
this.mime.Write(buffer, e.Offset, e.BytesTransferred);
if (!socket.ReceiveAsync(e))
{
ProcessReceive(e);
}
}
catch
{
this.Dispose();
}
}
else
{
this.Dispose();
}
}
public override void Receive(byte[] buffer, int offset, int size)
{
socket.Send(buffer, offset, size, SocketFlags.None);
}
protected override void Header(byte[] data, int offset, int size)
{
}
public override void Dispose()
{
this.Dispose();
try
{
socket.Shutdown(SocketShutdown.Both);
}
catch
{
}
socket.Close();
System.Buffers.ArrayPool<byte>.Shared.Return(buffer);
buffer = null;
}
}
2 years ago
}