Framework_YooAsset_HybridCLR/Assets/Plugins/TouchSocket/TouchSocket.Http/Components/HttpSocketClient.cs

187 lines
7.0 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

//------------------------------------------------------------------------------
// 此代码版权除特别声明或在XREF结尾的命名空间的代码归作者本人若汝棋茗所有
// 源代码使用协议遵循本仓库的开源协议及附加协议若本仓库没有设置则按MIT开源协议授权
// CSDN博客https://blog.csdn.net/qq_40374647
// 哔哩哔哩视频https://space.bilibili.com/94253567
// Gitee源代码仓库https://gitee.com/RRQM_Home
// Github源代码仓库https://github.com/RRQM
// API首页https://touchsocket.net/
// 交流QQ群234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
using System.Threading.Tasks;
using TouchSocket.Core;
using TouchSocket.Http.WebSockets;
using TouchSocket.Sockets;
namespace TouchSocket.Http
{
/// <summary>
/// http辅助类
/// </summary>
public class HttpSocketClient : SocketClient, IHttpSocketClient
{
private HttpContext m_httpContext;
private InternalWebSocket m_webSocket;
/// <summary>
/// 构造函数
/// </summary>
public HttpSocketClient()
{
this.Protocol = Protocol.Http;
}
/// <inheritdoc/>
public IWebSocket WebSocket { get => this.m_webSocket; }
/// <inheritdoc/>
public async Task<bool> SwitchProtocolToWebSocket(HttpContext httpContext)
{
if (this.m_webSocket is not null)
{
return true;
}
if (this.Protocol == Protocol.Http)
{
if (WSTools.TryGetResponse(httpContext.Request, httpContext.Response))
{
var args = new HttpContextEventArgs(this.m_httpContext)
{
IsPermitOperation = true
};
var webSocket = new InternalWebSocket(this);
await this.PluginManager.RaiseAsync(nameof(IWebSocketHandshakingPlugin.OnWebSocketHandshaking), webSocket, args).ConfigureAwait(false);
if (this.m_httpContext.Response.Responsed)
{
return false;
}
if (args.IsPermitOperation)
{
this.InitWebSocket(webSocket);
using (var byteBlock = new ByteBlock())
{
this.m_httpContext.Response.Build(byteBlock);
await this.DefaultSendAsync(byteBlock).ConfigureAwait(false);
}
_ = this.PluginManager.RaiseAsync(nameof(IWebSocketHandshakedPlugin.OnWebSocketHandshaked), webSocket, new HttpContextEventArgs(httpContext))
.ConfigureAwait(false);
return true;
}
else
{
this.m_httpContext.Response.SetStatus(403, "Forbidden");
using (var byteBlock = new ByteBlock())
{
this.m_httpContext.Response.Build(byteBlock);
await this.DefaultSendAsync(byteBlock).ConfigureAwait(false);
}
this.Close("主动拒绝WebSocket连接");
}
}
else
{
this.Close("WebSocket连接协议不正确");
}
}
return false;
}
/// <inheritdoc/>
protected override async Task OnConnecting(ConnectingEventArgs e)
{
this.SetAdapter(new HttpServerDataHandlingAdapter());
await base.OnConnecting(e).ConfigureFalseAwait();
}
/// <inheritdoc/>
protected override async Task OnDisconnected(DisconnectEventArgs e)
{
if (this.m_webSocket != null)
{
this.m_webSocket.IsHandshaked = false;
_ = this.m_webSocket.TryInputReceiveAsync(null);
}
await base.OnDisconnected(e);
}
/// <summary>
/// 当收到到Http请求时。覆盖父类方法将不会触发插件。
/// </summary>
protected virtual async Task OnReceivedHttpRequest(HttpRequest request)
{
if (this.PluginManager.GetPluginCount(nameof(IHttpPlugin.OnHttpRequest)) > 0)
{
var e = new HttpContextEventArgs(this.m_httpContext);
await this.PluginManager.RaiseAsync(nameof(IHttpPlugin.OnHttpRequest), this, e).ConfigureFalseAwait();
}
}
/// <inheritdoc/>
protected override async Task ReceivedData(ReceivedDataEventArgs e)
{
if (e.RequestInfo is HttpRequest request)
{
this.m_httpContext ??= new HttpContext(request);
await this.OnReceivedHttpRequest(request).ConfigureFalseAwait();
this.m_httpContext.Response.Reset();
}
else if (this.m_webSocket != null && e.RequestInfo is WSDataFrame dataFrame)
{
e.Handled = true;
await this.OnHandleWSDataFrame(dataFrame);
return;
}
await base.ReceivedData(e).ConfigureFalseAwait();
}
private void InitWebSocket(InternalWebSocket webSocket)
{
this.SetAdapter(new WebSocketDataHandlingAdapter());
this.Protocol = Protocol.WebSocket;
this.m_webSocket = webSocket;
}
private async Task OnHandleWSDataFrame(WSDataFrame dataFrame)
{
if (dataFrame.IsClose && this.GetValue(WebSocketFeature.AutoCloseProperty))
{
var msg = dataFrame.PayloadData?.ToString();
await this.PluginManager.RaiseAsync(nameof(IWebSocketClosingPlugin.OnWebSocketClosing), this.m_webSocket, new MsgPermitEventArgs() { Message = msg });
this.m_webSocket.Close(msg);
return;
}
if (dataFrame.IsPing && this.GetValue(WebSocketFeature.AutoPongProperty))
{
this.m_webSocket.Pong();
return;
}
if (this.m_webSocket.AllowAsyncRead)
{
if (await this.m_webSocket.TryInputReceiveAsync(dataFrame))
{
return;
}
}
await this.PluginManager.RaiseAsync(nameof(IWebSocketReceivedPlugin.OnWebSocketReceived), this.m_webSocket, new WSDataFrameEventArgs(dataFrame));
}
/// <inheritdoc/>
protected override void Dispose(bool disposing)
{
if (disposing)
{
this.m_httpContext?.Request.SafeDispose();
this.m_httpContext?.Response.SafeDispose();
this.m_webSocket.SafeDispose();
}
base.Dispose(disposing);
}
}
}